507 lines
16 KiB
Go
507 lines
16 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package pkcs11
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/asn1"
|
|
"encoding/hex"
|
|
"encoding/pem"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"math/big"
|
|
"os"
|
|
"path/filepath"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/hyperledger/fabric/integration/channelparticipation"
|
|
ginkgomon "github.com/tedsuo/ifrit/ginkgomon_v2"
|
|
|
|
bpkcs11 "github.com/hyperledger/fabric/bccsp/pkcs11"
|
|
"github.com/hyperledger/fabric/integration/nwo"
|
|
"github.com/hyperledger/fabric/integration/nwo/fabricconfig"
|
|
"github.com/miekg/pkcs11"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"github.com/tedsuo/ifrit"
|
|
)
|
|
|
|
var _ = Describe("PKCS11 enabled network", func() {
|
|
var (
|
|
tempDir string
|
|
network *nwo.Network
|
|
chaincode nwo.Chaincode
|
|
ordererRunner *ginkgomon.Runner
|
|
ordererProcess, peerProcess ifrit.Process
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
var err error
|
|
tempDir, err = ioutil.TempDir("", "p11")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
network = nwo.New(nwo.BasicEtcdRaft(), tempDir, nil, StartPort(), components)
|
|
network.GenerateConfigTree()
|
|
network.Bootstrap()
|
|
|
|
chaincode = nwo.Chaincode{
|
|
Name: "mycc",
|
|
Version: "0.0",
|
|
Path: components.Build("github.com/hyperledger/fabric/integration/chaincode/simple/cmd"),
|
|
Lang: "binary",
|
|
PackageFile: filepath.Join(tempDir, "simplecc.tar.gz"),
|
|
Ctor: `{"Args":["init","a","100","b","200"]}`,
|
|
SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`,
|
|
Sequence: "1",
|
|
InitRequired: true,
|
|
Label: "my_prebuilt_chaincode",
|
|
}
|
|
})
|
|
|
|
AfterEach(func() {
|
|
if ordererProcess != nil {
|
|
ordererProcess.Signal(syscall.SIGTERM)
|
|
Eventually(ordererProcess.Wait(), network.EventuallyTimeout).Should(Receive())
|
|
}
|
|
|
|
if peerProcess != nil {
|
|
peerProcess.Signal(syscall.SIGTERM)
|
|
Eventually(peerProcess.Wait(), network.EventuallyTimeout).Should(Receive())
|
|
}
|
|
|
|
network.Cleanup()
|
|
os.RemoveAll(tempDir)
|
|
})
|
|
|
|
Describe("without mapping", func() {
|
|
BeforeEach(func() {
|
|
By("configuring PKCS11 artifacts")
|
|
setupPKCS11(network, noMapping)
|
|
|
|
By("starting fabric processes")
|
|
ordererRunner, ordererProcess, peerProcess = network.StartSingleOrdererNetwork("orderer")
|
|
})
|
|
|
|
It("executes transactions against a basic etcdraft network", func() {
|
|
orderer := network.Orderer("orderer")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", orderer, ordererRunner)
|
|
|
|
nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.PeersWithChannel("testchannel")...)
|
|
nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
|
|
runQueryInvokeQuery(network, orderer, network.Peer("Org1", "peer0"), "testchannel")
|
|
})
|
|
})
|
|
|
|
Describe("mapping everything", func() {
|
|
BeforeEach(func() {
|
|
By("configuring PKCS11 artifacts")
|
|
setupPKCS11(network, mapAll)
|
|
|
|
By("starting fabric processes")
|
|
ordererRunner, ordererProcess, peerProcess = network.StartSingleOrdererNetwork("orderer")
|
|
})
|
|
|
|
It("executes transactions against a basic etcdraft network", func() {
|
|
orderer := network.Orderer("orderer")
|
|
channelparticipation.JoinOrdererJoinPeersAppChannel(network, "testchannel", orderer, ordererRunner)
|
|
|
|
nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.PeersWithChannel("testchannel")...)
|
|
nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
|
|
runQueryInvokeQuery(network, orderer, network.Peer("Org1", "peer0"), "testchannel")
|
|
})
|
|
})
|
|
})
|
|
|
|
type model uint8
|
|
|
|
const (
|
|
noMapping = model(iota)
|
|
mapAll
|
|
)
|
|
|
|
func setupPKCS11(network *nwo.Network, model model) {
|
|
lib, pin, label := bpkcs11.FindPKCS11Lib()
|
|
|
|
By("establishing a PKCS11 session")
|
|
ctx, sess := setupPKCS11Ctx(lib, label, pin)
|
|
defer ctx.Destroy()
|
|
defer ctx.CloseSession(sess)
|
|
|
|
serialNumbers := map[string]*big.Int{}
|
|
configurePeerPKCS11(ctx, sess, network, serialNumbers)
|
|
configureOrdererPKCS11(ctx, sess, network, serialNumbers)
|
|
|
|
var keyConfig []fabricconfig.KeyIDMapping
|
|
switch model {
|
|
case noMapping:
|
|
case mapAll:
|
|
updateKeyIdentifiers(ctx, sess, serialNumbers)
|
|
for ski, serial := range serialNumbers {
|
|
keyConfig = append(keyConfig, fabricconfig.KeyIDMapping{
|
|
SKI: ski,
|
|
ID: serial.String(),
|
|
})
|
|
}
|
|
}
|
|
|
|
bccspConfig := &fabricconfig.BCCSP{
|
|
Default: "PKCS11",
|
|
PKCS11: &fabricconfig.PKCS11{
|
|
Security: 256,
|
|
Hash: "SHA2",
|
|
Pin: pin,
|
|
Label: label,
|
|
Library: lib,
|
|
KeyIDs: keyConfig,
|
|
},
|
|
}
|
|
|
|
By("updating bccsp peer config")
|
|
for _, peer := range network.Peers {
|
|
peerConfig := network.ReadPeerConfig(peer)
|
|
peerConfig.Peer.BCCSP = bccspConfig
|
|
network.WritePeerConfig(peer, peerConfig)
|
|
}
|
|
|
|
By("updating bccsp orderer config")
|
|
orderer := network.Orderer("orderer")
|
|
ordererConfig := network.ReadOrdererConfig(orderer)
|
|
ordererConfig.General.BCCSP = bccspConfig
|
|
network.WriteOrdererConfig(orderer, ordererConfig)
|
|
}
|
|
|
|
func configurePeerPKCS11(ctx *pkcs11.Ctx, sess pkcs11.SessionHandle, network *nwo.Network, serialNumbers map[string]*big.Int) {
|
|
for _, peer := range network.Peers {
|
|
orgName := peer.Organization
|
|
|
|
peerPubKey, peerCSR, peerSerial := createCSR(ctx, sess, orgName, "peer")
|
|
adminPubKey, adminCSR, adminSerial := createCSR(ctx, sess, orgName, "admin")
|
|
userPubKey, userCSR, userSerial := createCSR(ctx, sess, orgName, "client")
|
|
|
|
domain := network.Organization(orgName).Domain
|
|
|
|
// Retrieves org CA cert
|
|
orgCAPath := network.PeerOrgCADir(network.Organization(orgName))
|
|
caBytes, err := ioutil.ReadFile(filepath.Join(orgCAPath, fmt.Sprintf("ca.%s-cert.pem", domain)))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
By("Updating the peer signcerts")
|
|
newOrdererPemCert := buildCert(caBytes, orgCAPath, peerCSR, peerSerial, peerPubKey)
|
|
updateMSPFolder(network.PeerLocalMSPDir(peer), fmt.Sprintf("peer.%s-cert.pem", domain), newOrdererPemCert)
|
|
serialNumbers[hex.EncodeToString(skiForKey(peerPubKey))] = peerSerial
|
|
|
|
By("Updating the peer admin user signcerts")
|
|
newAdminPemCert := buildCert(caBytes, orgCAPath, adminCSR, adminSerial, adminPubKey)
|
|
orgAdminMSPPath := network.PeerUserMSPDir(peer, "Admin")
|
|
updateMSPFolder(orgAdminMSPPath, fmt.Sprintf("Admin@%s-cert.pem", domain), newAdminPemCert)
|
|
serialNumbers[hex.EncodeToString(skiForKey(adminPubKey))] = adminSerial
|
|
|
|
By("Updating the peer user1 signcerts")
|
|
newUserPemCert := buildCert(caBytes, orgCAPath, userCSR, userSerial, userPubKey)
|
|
orgUserMSPPath := network.PeerUserMSPDir(peer, "User1")
|
|
updateMSPFolder(orgUserMSPPath, fmt.Sprintf("User1@%s-cert.pem", domain), newUserPemCert)
|
|
serialNumbers[hex.EncodeToString(skiForKey(userPubKey))] = userSerial
|
|
}
|
|
}
|
|
|
|
func configureOrdererPKCS11(ctx *pkcs11.Ctx, sess pkcs11.SessionHandle, network *nwo.Network, serialNumbers map[string]*big.Int) {
|
|
orderer := network.Orderer("orderer")
|
|
orgName := orderer.Organization
|
|
domain := network.Organization(orgName).Domain
|
|
|
|
ordererPubKey, ordererCSR, ordererSerial := createCSR(ctx, sess, orgName, "orderer")
|
|
adminPubKey, adminCSR, adminSerial := createCSR(ctx, sess, orgName, "admin")
|
|
|
|
// Retrieves org CA cert
|
|
orgCAPath := network.OrdererOrgCADir(network.Organization(orgName))
|
|
caBytes, err := ioutil.ReadFile(filepath.Join(orgCAPath, fmt.Sprintf("ca.%s-cert.pem", domain)))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
By("Updating the orderer signcerts")
|
|
newOrdererPemCert := buildCert(caBytes, orgCAPath, ordererCSR, ordererSerial, ordererPubKey)
|
|
updateMSPFolder(network.OrdererLocalMSPDir(orderer), fmt.Sprintf("orderer.%s-cert.pem", domain), newOrdererPemCert)
|
|
serialNumbers[hex.EncodeToString(skiForKey(ordererPubKey))] = ordererSerial
|
|
|
|
By("Updating the orderer admin user signcerts")
|
|
newAdminPemCert := buildCert(caBytes, orgCAPath, adminCSR, adminSerial, adminPubKey)
|
|
orgAdminMSPPath := network.OrdererUserMSPDir(orderer, "Admin")
|
|
updateMSPFolder(orgAdminMSPPath, fmt.Sprintf("Admin@%s-cert.pem", domain), newAdminPemCert)
|
|
serialNumbers[hex.EncodeToString(skiForKey(adminPubKey))] = adminSerial
|
|
}
|
|
|
|
// Creates pkcs11 context and session
|
|
func setupPKCS11Ctx(lib, label, pin string) (*pkcs11.Ctx, pkcs11.SessionHandle) {
|
|
ctx := pkcs11.New(lib)
|
|
|
|
if err := ctx.Initialize(); err != nil {
|
|
Expect(err).To(Equal(pkcs11.Error(pkcs11.CKR_CRYPTOKI_ALREADY_INITIALIZED)))
|
|
} else {
|
|
Expect(err).NotTo(HaveOccurred())
|
|
}
|
|
|
|
slot := findPKCS11Slot(ctx, label)
|
|
Expect(slot).Should(BeNumerically(">", 0), "Could not find slot with label %s", label)
|
|
|
|
sess, err := ctx.OpenSession(slot, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
// Login
|
|
err = ctx.Login(sess, pkcs11.CKU_USER, pin)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
return ctx, sess
|
|
}
|
|
|
|
// Identifies pkcs11 slot using specified label
|
|
func findPKCS11Slot(ctx *pkcs11.Ctx, label string) uint {
|
|
slots, err := ctx.GetSlotList(true)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
for _, s := range slots {
|
|
tokInfo, err := ctx.GetTokenInfo(s)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
if tokInfo.Label == label {
|
|
return s
|
|
}
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
// Creates CSR for provided organization and organizational unit
|
|
func createCSR(ctx *pkcs11.Ctx, sess pkcs11.SessionHandle, org, ou string) (*ecdsa.PublicKey, *x509.CertificateRequest, *big.Int) {
|
|
pubKey, pkcs11Key := generateKeyPair(ctx, sess)
|
|
|
|
csrTemplate := x509.CertificateRequest{
|
|
Subject: pkix.Name{
|
|
Country: []string{"US"},
|
|
Province: []string{"California"},
|
|
Locality: []string{"San Francisco"},
|
|
Organization: []string{fmt.Sprintf("%s.example.com", org)},
|
|
OrganizationalUnit: []string{ou},
|
|
CommonName: fmt.Sprintf("peer.%s.example.com", org),
|
|
},
|
|
SignatureAlgorithm: x509.ECDSAWithSHA256,
|
|
}
|
|
|
|
csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, pkcs11Key)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
csr, err := x509.ParseCertificateRequest(csrBytes)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
err = csr.CheckSignature()
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
return pubKey, csr, serialNumber
|
|
}
|
|
|
|
func buildCert(caBytes []byte, org1CAPath string, csr *x509.CertificateRequest, serialNumber *big.Int, pubKey *ecdsa.PublicKey) []byte {
|
|
pemBlock, _ := pem.Decode(caBytes)
|
|
Expect(pemBlock).NotTo(BeNil())
|
|
|
|
caCert, err := x509.ParseCertificate(pemBlock.Bytes)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
keyBytes, err := ioutil.ReadFile(filepath.Join(org1CAPath, "priv_sk"))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
pemBlock, _ = pem.Decode(keyBytes)
|
|
Expect(pemBlock).NotTo(BeNil())
|
|
key, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
caKey := key.(*ecdsa.PrivateKey)
|
|
|
|
certTemplate := &x509.Certificate{
|
|
Signature: csr.Signature,
|
|
SignatureAlgorithm: csr.SignatureAlgorithm,
|
|
PublicKey: csr.PublicKey,
|
|
PublicKeyAlgorithm: csr.PublicKeyAlgorithm,
|
|
|
|
SerialNumber: serialNumber,
|
|
NotBefore: time.Now().Add(-1 * time.Minute).UTC(),
|
|
NotAfter: time.Now().Add(365 * 24 * time.Hour).UTC(),
|
|
BasicConstraintsValid: true,
|
|
|
|
Subject: csr.Subject,
|
|
KeyUsage: x509.KeyUsageDigitalSignature,
|
|
ExtKeyUsage: []x509.ExtKeyUsage{},
|
|
}
|
|
|
|
// Use root CA to create and sign cert
|
|
signedCert, err := x509.CreateCertificate(rand.Reader, certTemplate, caCert, pubKey, caKey)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
return pem.EncodeToMemory(&pem.Block{Bytes: signedCert, Type: "CERTIFICATE"})
|
|
}
|
|
|
|
// Overwrites existing cert and removes private key from keystore folder
|
|
func updateMSPFolder(path, certName string, cert []byte) {
|
|
// Overwrite existing certificate with new certificate
|
|
err := ioutil.WriteFile(filepath.Join(path, "signcerts", certName), cert, 0o644)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
// delete the existing private key - this is stored in the hsm
|
|
adminKSCert := filepath.Join(path, "keystore", "priv_sk")
|
|
err = os.Remove(adminKSCert)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
}
|
|
|
|
// Generating key pair in HSM, convert, and return keys
|
|
func generateKeyPair(ctx *pkcs11.Ctx, sess pkcs11.SessionHandle) (*ecdsa.PublicKey, *P11ECDSAKey) {
|
|
publabel, privlabel := "BCPUB7", "BCPRV7"
|
|
|
|
curve := asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} // secp256r1 Curve
|
|
|
|
marshaledOID, err := asn1.Marshal(curve)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
pubAttrs := []*pkcs11.Attribute{
|
|
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC),
|
|
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
|
|
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
|
|
pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true),
|
|
pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, marshaledOID),
|
|
|
|
pkcs11.NewAttribute(pkcs11.CKA_ID, publabel),
|
|
pkcs11.NewAttribute(pkcs11.CKA_LABEL, publabel),
|
|
}
|
|
|
|
privAttrs := []*pkcs11.Attribute{
|
|
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC),
|
|
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
|
|
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
|
|
pkcs11.NewAttribute(pkcs11.CKA_SIGN, true),
|
|
|
|
pkcs11.NewAttribute(pkcs11.CKA_ID, privlabel),
|
|
pkcs11.NewAttribute(pkcs11.CKA_LABEL, privlabel),
|
|
|
|
pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, false),
|
|
pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
|
|
}
|
|
|
|
pubK, privK, err := ctx.GenerateKeyPair(
|
|
sess,
|
|
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_EC_KEY_PAIR_GEN, nil)},
|
|
pubAttrs,
|
|
privAttrs,
|
|
)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
ecpt := ecPoint(ctx, sess, pubK)
|
|
Expect(ecpt).NotTo(BeEmpty(), "CKA_EC_POINT not found")
|
|
|
|
hash := sha256.Sum256(ecpt)
|
|
ski := hash[:]
|
|
|
|
setskiT := []*pkcs11.Attribute{
|
|
pkcs11.NewAttribute(pkcs11.CKA_ID, ski),
|
|
pkcs11.NewAttribute(pkcs11.CKA_LABEL, hex.EncodeToString(ski)),
|
|
}
|
|
|
|
err = ctx.SetAttributeValue(sess, pubK, setskiT)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = ctx.SetAttributeValue(sess, privK, setskiT)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
// convert pub key to ansi types
|
|
nistCurve := elliptic.P256()
|
|
x, y := elliptic.Unmarshal(nistCurve, ecpt)
|
|
if x == nil {
|
|
Expect(x).NotTo(BeNil(), "Failed Unmarshalling Public Key")
|
|
}
|
|
|
|
pubKey := &ecdsa.PublicKey{Curve: nistCurve, X: x, Y: y}
|
|
|
|
pkcs11Key := &P11ECDSAKey{
|
|
ctx: ctx,
|
|
session: sess,
|
|
publicKey: pubKey,
|
|
privateKeyHandle: privK,
|
|
}
|
|
|
|
return pubKey, pkcs11Key
|
|
}
|
|
|
|
// SoftHSM reports extra two bytes before the uncompressed point
|
|
// see /bccsp/pkcs11/pkcs11.go::ecPoint() for additional details
|
|
func ecPoint(pkcs11lib *pkcs11.Ctx, session pkcs11.SessionHandle, key pkcs11.ObjectHandle) (ecpt []byte) {
|
|
template := []*pkcs11.Attribute{
|
|
pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil),
|
|
pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, nil),
|
|
}
|
|
|
|
attr, err := pkcs11lib.GetAttributeValue(session, key, template)
|
|
if err != nil {
|
|
Expect(err).NotTo(HaveOccurred(), "PKCS11: get(EC point)")
|
|
}
|
|
|
|
for _, a := range attr {
|
|
if a.Type != pkcs11.CKA_EC_POINT {
|
|
continue
|
|
}
|
|
|
|
switch {
|
|
case ((len(a.Value) % 2) == 0) && (byte(0x04) == a.Value[0]) && (byte(0x04) == a.Value[len(a.Value)-1]):
|
|
ecpt = a.Value[0 : len(a.Value)-1] // Trim trailing 0x04
|
|
case byte(0x04) == a.Value[0] && byte(0x04) == a.Value[2]:
|
|
ecpt = a.Value[2:len(a.Value)]
|
|
default:
|
|
ecpt = a.Value
|
|
}
|
|
}
|
|
|
|
return ecpt
|
|
}
|
|
|
|
func skiForKey(pk *ecdsa.PublicKey) []byte {
|
|
ski := sha256.Sum256(elliptic.Marshal(pk.Curve, pk.X, pk.Y))
|
|
return ski[:]
|
|
}
|
|
|
|
func updateKeyIdentifiers(pctx *pkcs11.Ctx, sess pkcs11.SessionHandle, serialNumbers map[string]*big.Int) {
|
|
for ks, serial := range serialNumbers {
|
|
ski, err := hex.DecodeString(ks)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
updateKeyIdentifier(pctx, sess, pkcs11.CKO_PUBLIC_KEY, ski, []byte(serial.String()))
|
|
updateKeyIdentifier(pctx, sess, pkcs11.CKO_PRIVATE_KEY, ski, []byte(serial.String()))
|
|
}
|
|
}
|
|
|
|
func updateKeyIdentifier(pctx *pkcs11.Ctx, sess pkcs11.SessionHandle, class uint, currentID, newID []byte) {
|
|
pkt := []*pkcs11.Attribute{
|
|
pkcs11.NewAttribute(pkcs11.CKA_CLASS, class),
|
|
pkcs11.NewAttribute(pkcs11.CKA_ID, currentID),
|
|
}
|
|
err := pctx.FindObjectsInit(sess, pkt)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
objs, _, err := pctx.FindObjects(sess, 1)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(objs).To(HaveLen(1))
|
|
|
|
err = pctx.FindObjectsFinal(sess)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = pctx.SetAttributeValue(sess, objs[0], []*pkcs11.Attribute{
|
|
pkcs11.NewAttribute(pkcs11.CKA_ID, newID),
|
|
})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
}
|