github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/integration/pkcs11/pkcs11_test.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package pkcs11
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/elliptic"
    12  	"crypto/rand"
    13  	"crypto/sha256"
    14  	"crypto/x509"
    15  	"crypto/x509/pkix"
    16  	"encoding/asn1"
    17  	"encoding/hex"
    18  	"encoding/pem"
    19  	"fmt"
    20  	"io/ioutil"
    21  	"math/big"
    22  	"os"
    23  	"path/filepath"
    24  	"syscall"
    25  	"time"
    26  
    27  	bpkcs11 "github.com/hechain20/hechain/bccsp/pkcs11"
    28  	"github.com/hechain20/hechain/integration/nwo"
    29  	"github.com/hechain20/hechain/integration/nwo/fabricconfig"
    30  	"github.com/miekg/pkcs11"
    31  	. "github.com/onsi/ginkgo"
    32  	. "github.com/onsi/gomega"
    33  	"github.com/tedsuo/ifrit"
    34  )
    35  
    36  var _ = Describe("PKCS11 enabled network", func() {
    37  	var (
    38  		tempDir   string
    39  		network   *nwo.Network
    40  		chaincode nwo.Chaincode
    41  		process   ifrit.Process
    42  	)
    43  
    44  	BeforeEach(func() {
    45  		var err error
    46  		tempDir, err = ioutil.TempDir("", "p11")
    47  		Expect(err).NotTo(HaveOccurred())
    48  
    49  		network = nwo.New(nwo.BasicSolo(), tempDir, nil, StartPort(), components)
    50  		network.GenerateConfigTree()
    51  		network.Bootstrap()
    52  
    53  		chaincode = nwo.Chaincode{
    54  			Name:            "mycc",
    55  			Version:         "0.0",
    56  			Path:            components.Build("github.com/hechain20/hechain/integration/chaincode/simple/cmd"),
    57  			Lang:            "binary",
    58  			PackageFile:     filepath.Join(tempDir, "simplecc.tar.gz"),
    59  			Ctor:            `{"Args":["init","a","100","b","200"]}`,
    60  			SignaturePolicy: `AND ('Org1MSP.member','Org2MSP.member')`,
    61  			Sequence:        "1",
    62  			InitRequired:    true,
    63  			Label:           "my_prebuilt_chaincode",
    64  		}
    65  	})
    66  
    67  	AfterEach(func() {
    68  		if process != nil {
    69  			process.Signal(syscall.SIGTERM)
    70  			Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive())
    71  		}
    72  		network.Cleanup()
    73  		os.RemoveAll(tempDir)
    74  	})
    75  
    76  	Describe("without mapping", func() {
    77  		BeforeEach(func() {
    78  			By("configuring PKCS11 artifacts")
    79  			setupPKCS11(network, noMapping)
    80  
    81  			By("starting fabric processes")
    82  			networkRunner := network.NetworkGroupRunner()
    83  			process = ifrit.Invoke(networkRunner)
    84  			Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
    85  		})
    86  
    87  		It("executes transactions against a basic solo network", func() {
    88  			orderer := network.Orderer("orderer")
    89  			network.CreateAndJoinChannels(orderer)
    90  
    91  			nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.PeersWithChannel("testchannel")...)
    92  			nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
    93  			runQueryInvokeQuery(network, orderer, network.Peer("Org1", "peer0"), "testchannel")
    94  		})
    95  	})
    96  
    97  	Describe("mapping everything", func() {
    98  		BeforeEach(func() {
    99  			By("configuring PKCS11 artifacts")
   100  			setupPKCS11(network, mapAll)
   101  
   102  			By("starting fabric processes")
   103  			networkRunner := network.NetworkGroupRunner()
   104  			process = ifrit.Invoke(networkRunner)
   105  			Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed())
   106  		})
   107  
   108  		It("executes transactions against a basic solo network", func() {
   109  			orderer := network.Orderer("orderer")
   110  			network.CreateAndJoinChannels(orderer)
   111  
   112  			nwo.EnableCapabilities(network, "testchannel", "Application", "V2_0", orderer, network.PeersWithChannel("testchannel")...)
   113  			nwo.DeployChaincode(network, "testchannel", orderer, chaincode)
   114  			runQueryInvokeQuery(network, orderer, network.Peer("Org1", "peer0"), "testchannel")
   115  		})
   116  	})
   117  })
   118  
   119  type model uint8
   120  
   121  const (
   122  	noMapping = model(iota)
   123  	mapAll
   124  )
   125  
   126  func setupPKCS11(network *nwo.Network, model model) {
   127  	lib, pin, label := bpkcs11.FindPKCS11Lib()
   128  
   129  	By("establishing a PKCS11 session")
   130  	ctx, sess := setupPKCS11Ctx(lib, label, pin)
   131  	defer ctx.Destroy()
   132  	defer ctx.CloseSession(sess)
   133  
   134  	serialNumbers := map[string]*big.Int{}
   135  	configurePeerPKCS11(ctx, sess, network, serialNumbers)
   136  	configureOrdererPKCS11(ctx, sess, network, serialNumbers)
   137  
   138  	var keyConfig []fabricconfig.KeyIDMapping
   139  	switch model {
   140  	case noMapping:
   141  	case mapAll:
   142  		updateKeyIdentifiers(ctx, sess, serialNumbers)
   143  		for ski, serial := range serialNumbers {
   144  			keyConfig = append(keyConfig, fabricconfig.KeyIDMapping{
   145  				SKI: ski,
   146  				ID:  serial.String(),
   147  			})
   148  		}
   149  	}
   150  
   151  	bccspConfig := &fabricconfig.BCCSP{
   152  		Default: "PKCS11",
   153  		PKCS11: &fabricconfig.PKCS11{
   154  			Security: 256,
   155  			Hash:     "SHA2",
   156  			Pin:      pin,
   157  			Label:    label,
   158  			Library:  lib,
   159  			KeyIDs:   keyConfig,
   160  		},
   161  	}
   162  
   163  	By("updating bccsp peer config")
   164  	for _, peer := range network.Peers {
   165  		peerConfig := network.ReadPeerConfig(peer)
   166  		peerConfig.Peer.BCCSP = bccspConfig
   167  		network.WritePeerConfig(peer, peerConfig)
   168  	}
   169  
   170  	By("updating bccsp orderer config")
   171  	orderer := network.Orderer("orderer")
   172  	ordererConfig := network.ReadOrdererConfig(orderer)
   173  	ordererConfig.General.BCCSP = bccspConfig
   174  	network.WriteOrdererConfig(orderer, ordererConfig)
   175  }
   176  
   177  func configurePeerPKCS11(ctx *pkcs11.Ctx, sess pkcs11.SessionHandle, network *nwo.Network, serialNumbers map[string]*big.Int) {
   178  	for _, peer := range network.Peers {
   179  		orgName := peer.Organization
   180  
   181  		peerPubKey, peerCSR, peerSerial := createCSR(ctx, sess, orgName, "peer")
   182  		adminPubKey, adminCSR, adminSerial := createCSR(ctx, sess, orgName, "admin")
   183  		userPubKey, userCSR, userSerial := createCSR(ctx, sess, orgName, "client")
   184  
   185  		domain := network.Organization(orgName).Domain
   186  
   187  		// Retrieves org CA cert
   188  		orgCAPath := network.PeerOrgCADir(network.Organization(orgName))
   189  		caBytes, err := ioutil.ReadFile(filepath.Join(orgCAPath, fmt.Sprintf("ca.%s-cert.pem", domain)))
   190  		Expect(err).NotTo(HaveOccurred())
   191  
   192  		By("Updating the peer signcerts")
   193  		newOrdererPemCert := buildCert(caBytes, orgCAPath, peerCSR, peerSerial, peerPubKey)
   194  		updateMSPFolder(network.PeerLocalMSPDir(peer), fmt.Sprintf("peer.%s-cert.pem", domain), newOrdererPemCert)
   195  		serialNumbers[hex.EncodeToString(skiForKey(peerPubKey))] = peerSerial
   196  
   197  		By("Updating the peer admin user signcerts")
   198  		newAdminPemCert := buildCert(caBytes, orgCAPath, adminCSR, adminSerial, adminPubKey)
   199  		orgAdminMSPPath := network.PeerUserMSPDir(peer, "Admin")
   200  		updateMSPFolder(orgAdminMSPPath, fmt.Sprintf("Admin@%s-cert.pem", domain), newAdminPemCert)
   201  		serialNumbers[hex.EncodeToString(skiForKey(adminPubKey))] = adminSerial
   202  
   203  		By("Updating the peer user1 signcerts")
   204  		newUserPemCert := buildCert(caBytes, orgCAPath, userCSR, userSerial, userPubKey)
   205  		orgUserMSPPath := network.PeerUserMSPDir(peer, "User1")
   206  		updateMSPFolder(orgUserMSPPath, fmt.Sprintf("User1@%s-cert.pem", domain), newUserPemCert)
   207  		serialNumbers[hex.EncodeToString(skiForKey(userPubKey))] = userSerial
   208  	}
   209  }
   210  
   211  func configureOrdererPKCS11(ctx *pkcs11.Ctx, sess pkcs11.SessionHandle, network *nwo.Network, serialNumbers map[string]*big.Int) {
   212  	orderer := network.Orderer("orderer")
   213  	orgName := orderer.Organization
   214  	domain := network.Organization(orgName).Domain
   215  
   216  	ordererPubKey, ordererCSR, ordererSerial := createCSR(ctx, sess, orgName, "orderer")
   217  	adminPubKey, adminCSR, adminSerial := createCSR(ctx, sess, orgName, "admin")
   218  
   219  	// Retrieves org CA cert
   220  	orgCAPath := network.OrdererOrgCADir(network.Organization(orgName))
   221  	caBytes, err := ioutil.ReadFile(filepath.Join(orgCAPath, fmt.Sprintf("ca.%s-cert.pem", domain)))
   222  	Expect(err).NotTo(HaveOccurred())
   223  
   224  	By("Updating the orderer signcerts")
   225  	newOrdererPemCert := buildCert(caBytes, orgCAPath, ordererCSR, ordererSerial, ordererPubKey)
   226  	updateMSPFolder(network.OrdererLocalMSPDir(orderer), fmt.Sprintf("orderer.%s-cert.pem", domain), newOrdererPemCert)
   227  	serialNumbers[hex.EncodeToString(skiForKey(ordererPubKey))] = ordererSerial
   228  
   229  	By("Updating the orderer admin user signcerts")
   230  	newAdminPemCert := buildCert(caBytes, orgCAPath, adminCSR, adminSerial, adminPubKey)
   231  	orgAdminMSPPath := network.OrdererUserMSPDir(orderer, "Admin")
   232  	updateMSPFolder(orgAdminMSPPath, fmt.Sprintf("Admin@%s-cert.pem", domain), newAdminPemCert)
   233  	serialNumbers[hex.EncodeToString(skiForKey(adminPubKey))] = adminSerial
   234  }
   235  
   236  // Creates pkcs11 context and session
   237  func setupPKCS11Ctx(lib, label, pin string) (*pkcs11.Ctx, pkcs11.SessionHandle) {
   238  	ctx := pkcs11.New(lib)
   239  
   240  	if err := ctx.Initialize(); err != nil {
   241  		Expect(err).To(Equal(pkcs11.Error(pkcs11.CKR_CRYPTOKI_ALREADY_INITIALIZED)))
   242  	} else {
   243  		Expect(err).NotTo(HaveOccurred())
   244  	}
   245  
   246  	slot := findPKCS11Slot(ctx, label)
   247  	Expect(slot).Should(BeNumerically(">", 0), "Could not find slot with label %s", label)
   248  
   249  	sess, err := ctx.OpenSession(slot, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
   250  	Expect(err).NotTo(HaveOccurred())
   251  
   252  	// Login
   253  	err = ctx.Login(sess, pkcs11.CKU_USER, pin)
   254  	Expect(err).NotTo(HaveOccurred())
   255  
   256  	return ctx, sess
   257  }
   258  
   259  // Identifies pkcs11 slot using specified label
   260  func findPKCS11Slot(ctx *pkcs11.Ctx, label string) uint {
   261  	slots, err := ctx.GetSlotList(true)
   262  	Expect(err).NotTo(HaveOccurred())
   263  
   264  	for _, s := range slots {
   265  		tokInfo, err := ctx.GetTokenInfo(s)
   266  		Expect(err).NotTo(HaveOccurred())
   267  
   268  		if tokInfo.Label == label {
   269  			return s
   270  		}
   271  	}
   272  
   273  	return 0
   274  }
   275  
   276  // Creates CSR for provided organization and organizational unit
   277  func createCSR(ctx *pkcs11.Ctx, sess pkcs11.SessionHandle, org, ou string) (*ecdsa.PublicKey, *x509.CertificateRequest, *big.Int) {
   278  	pubKey, pkcs11Key := generateKeyPair(ctx, sess)
   279  
   280  	csrTemplate := x509.CertificateRequest{
   281  		Subject: pkix.Name{
   282  			Country:            []string{"US"},
   283  			Province:           []string{"California"},
   284  			Locality:           []string{"San Francisco"},
   285  			Organization:       []string{fmt.Sprintf("%s.example.com", org)},
   286  			OrganizationalUnit: []string{ou},
   287  			CommonName:         fmt.Sprintf("peer.%s.example.com", org),
   288  		},
   289  		SignatureAlgorithm: x509.ECDSAWithSHA256,
   290  	}
   291  
   292  	csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, pkcs11Key)
   293  	Expect(err).NotTo(HaveOccurred())
   294  
   295  	csr, err := x509.ParseCertificateRequest(csrBytes)
   296  	Expect(err).NotTo(HaveOccurred())
   297  	err = csr.CheckSignature()
   298  	Expect(err).NotTo(HaveOccurred())
   299  
   300  	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
   301  	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
   302  	Expect(err).NotTo(HaveOccurred())
   303  
   304  	return pubKey, csr, serialNumber
   305  }
   306  
   307  func buildCert(caBytes []byte, org1CAPath string, csr *x509.CertificateRequest, serialNumber *big.Int, pubKey *ecdsa.PublicKey) []byte {
   308  	pemBlock, _ := pem.Decode(caBytes)
   309  	Expect(pemBlock).NotTo(BeNil())
   310  
   311  	caCert, err := x509.ParseCertificate(pemBlock.Bytes)
   312  	Expect(err).NotTo(HaveOccurred())
   313  
   314  	keyBytes, err := ioutil.ReadFile(filepath.Join(org1CAPath, "priv_sk"))
   315  	Expect(err).NotTo(HaveOccurred())
   316  
   317  	pemBlock, _ = pem.Decode(keyBytes)
   318  	Expect(pemBlock).NotTo(BeNil())
   319  	key, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes)
   320  	Expect(err).NotTo(HaveOccurred())
   321  	caKey := key.(*ecdsa.PrivateKey)
   322  
   323  	certTemplate := &x509.Certificate{
   324  		Signature:          csr.Signature,
   325  		SignatureAlgorithm: csr.SignatureAlgorithm,
   326  		PublicKey:          csr.PublicKey,
   327  		PublicKeyAlgorithm: csr.PublicKeyAlgorithm,
   328  
   329  		SerialNumber:          serialNumber,
   330  		NotBefore:             time.Now().Add(-1 * time.Minute).UTC(),
   331  		NotAfter:              time.Now().Add(365 * 24 * time.Hour).UTC(),
   332  		BasicConstraintsValid: true,
   333  
   334  		Subject:     csr.Subject,
   335  		KeyUsage:    x509.KeyUsageDigitalSignature,
   336  		ExtKeyUsage: []x509.ExtKeyUsage{},
   337  	}
   338  
   339  	// Use root CA to create and sign cert
   340  	signedCert, err := x509.CreateCertificate(rand.Reader, certTemplate, caCert, pubKey, caKey)
   341  	Expect(err).NotTo(HaveOccurred())
   342  
   343  	return pem.EncodeToMemory(&pem.Block{Bytes: signedCert, Type: "CERTIFICATE"})
   344  }
   345  
   346  // Overwrites existing cert and removes private key from keystore folder
   347  func updateMSPFolder(path, certName string, cert []byte) {
   348  	// Overwrite existing certificate with new certificate
   349  	err := ioutil.WriteFile(filepath.Join(path, "signcerts", certName), cert, 0o644)
   350  	Expect(err).NotTo(HaveOccurred())
   351  
   352  	// delete the existing private key - this is stored in the hsm
   353  	adminKSCert := filepath.Join(path, "keystore", "priv_sk")
   354  	err = os.Remove(adminKSCert)
   355  	Expect(err).NotTo(HaveOccurred())
   356  }
   357  
   358  // Generating key pair in HSM, convert, and return keys
   359  func generateKeyPair(ctx *pkcs11.Ctx, sess pkcs11.SessionHandle) (*ecdsa.PublicKey, *P11ECDSAKey) {
   360  	publabel, privlabel := "BCPUB7", "BCPRV7"
   361  
   362  	curve := asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} // secp256r1 Curve
   363  
   364  	marshaledOID, err := asn1.Marshal(curve)
   365  	Expect(err).NotTo(HaveOccurred())
   366  
   367  	pubAttrs := []*pkcs11.Attribute{
   368  		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC),
   369  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
   370  		pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
   371  		pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true),
   372  		pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, marshaledOID),
   373  
   374  		pkcs11.NewAttribute(pkcs11.CKA_ID, publabel),
   375  		pkcs11.NewAttribute(pkcs11.CKA_LABEL, publabel),
   376  	}
   377  
   378  	privAttrs := []*pkcs11.Attribute{
   379  		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC),
   380  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
   381  		pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
   382  		pkcs11.NewAttribute(pkcs11.CKA_SIGN, true),
   383  
   384  		pkcs11.NewAttribute(pkcs11.CKA_ID, privlabel),
   385  		pkcs11.NewAttribute(pkcs11.CKA_LABEL, privlabel),
   386  
   387  		pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, false),
   388  		pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
   389  	}
   390  
   391  	pubK, privK, err := ctx.GenerateKeyPair(
   392  		sess,
   393  		[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_EC_KEY_PAIR_GEN, nil)},
   394  		pubAttrs,
   395  		privAttrs,
   396  	)
   397  	Expect(err).NotTo(HaveOccurred())
   398  
   399  	ecpt := ecPoint(ctx, sess, pubK)
   400  	Expect(ecpt).NotTo(BeEmpty(), "CKA_EC_POINT not found")
   401  
   402  	hash := sha256.Sum256(ecpt)
   403  	ski := hash[:]
   404  
   405  	setskiT := []*pkcs11.Attribute{
   406  		pkcs11.NewAttribute(pkcs11.CKA_ID, ski),
   407  		pkcs11.NewAttribute(pkcs11.CKA_LABEL, hex.EncodeToString(ski)),
   408  	}
   409  
   410  	err = ctx.SetAttributeValue(sess, pubK, setskiT)
   411  	Expect(err).NotTo(HaveOccurred())
   412  
   413  	err = ctx.SetAttributeValue(sess, privK, setskiT)
   414  	Expect(err).NotTo(HaveOccurred())
   415  
   416  	// convert pub key to ansi types
   417  	nistCurve := elliptic.P256()
   418  	x, y := elliptic.Unmarshal(nistCurve, ecpt)
   419  	if x == nil {
   420  		Expect(x).NotTo(BeNil(), "Failed Unmarshalling Public Key")
   421  	}
   422  
   423  	pubKey := &ecdsa.PublicKey{Curve: nistCurve, X: x, Y: y}
   424  
   425  	pkcs11Key := &P11ECDSAKey{
   426  		ctx:              ctx,
   427  		session:          sess,
   428  		publicKey:        pubKey,
   429  		privateKeyHandle: privK,
   430  	}
   431  
   432  	return pubKey, pkcs11Key
   433  }
   434  
   435  // SoftHSM reports extra two bytes before the uncompressed point
   436  // see /bccsp/pkcs11/pkcs11.go::ecPoint() for additional details
   437  func ecPoint(pkcs11lib *pkcs11.Ctx, session pkcs11.SessionHandle, key pkcs11.ObjectHandle) (ecpt []byte) {
   438  	template := []*pkcs11.Attribute{
   439  		pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil),
   440  		pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, nil),
   441  	}
   442  
   443  	attr, err := pkcs11lib.GetAttributeValue(session, key, template)
   444  	if err != nil {
   445  		Expect(err).NotTo(HaveOccurred(), "PKCS11: get(EC point)")
   446  	}
   447  
   448  	for _, a := range attr {
   449  		if a.Type != pkcs11.CKA_EC_POINT {
   450  			continue
   451  		}
   452  
   453  		switch {
   454  		case ((len(a.Value) % 2) == 0) && (byte(0x04) == a.Value[0]) && (byte(0x04) == a.Value[len(a.Value)-1]):
   455  			ecpt = a.Value[0 : len(a.Value)-1] // Trim trailing 0x04
   456  		case byte(0x04) == a.Value[0] && byte(0x04) == a.Value[2]:
   457  			ecpt = a.Value[2:len(a.Value)]
   458  		default:
   459  			ecpt = a.Value
   460  		}
   461  	}
   462  
   463  	return ecpt
   464  }
   465  
   466  func skiForKey(pk *ecdsa.PublicKey) []byte {
   467  	ski := sha256.Sum256(elliptic.Marshal(pk.Curve, pk.X, pk.Y))
   468  	return ski[:]
   469  }
   470  
   471  func updateKeyIdentifiers(pctx *pkcs11.Ctx, sess pkcs11.SessionHandle, serialNumbers map[string]*big.Int) {
   472  	for ks, serial := range serialNumbers {
   473  		ski, err := hex.DecodeString(ks)
   474  		Expect(err).NotTo(HaveOccurred())
   475  
   476  		updateKeyIdentifier(pctx, sess, pkcs11.CKO_PUBLIC_KEY, ski, []byte(serial.String()))
   477  		updateKeyIdentifier(pctx, sess, pkcs11.CKO_PRIVATE_KEY, ski, []byte(serial.String()))
   478  	}
   479  }
   480  
   481  func updateKeyIdentifier(pctx *pkcs11.Ctx, sess pkcs11.SessionHandle, class uint, currentID, newID []byte) {
   482  	pkt := []*pkcs11.Attribute{
   483  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, class),
   484  		pkcs11.NewAttribute(pkcs11.CKA_ID, currentID),
   485  	}
   486  	err := pctx.FindObjectsInit(sess, pkt)
   487  	Expect(err).NotTo(HaveOccurred())
   488  
   489  	objs, _, err := pctx.FindObjects(sess, 1)
   490  	Expect(err).NotTo(HaveOccurred())
   491  	Expect(objs).To(HaveLen(1))
   492  
   493  	err = pctx.FindObjectsFinal(sess)
   494  	Expect(err).NotTo(HaveOccurred())
   495  
   496  	err = pctx.SetAttributeValue(sess, objs[0], []*pkcs11.Attribute{
   497  		pkcs11.NewAttribute(pkcs11.CKA_ID, newID),
   498  	})
   499  	Expect(err).NotTo(HaveOccurred())
   500  }