mirror of https://github.com/docker/docs.git
updating miekg/pkcs11 for go 1.6
Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
parent
332fc35dc5
commit
9db2ae3ed6
|
@ -171,6 +171,10 @@
|
|||
"ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil",
|
||||
"Rev": "d0c3fe89de86839aecf2e0579c40ba3bb336a453"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/miekg/pkcs11",
|
||||
"Rev": "df8ae6ca730422dba20c768ff38ef7d79077a59f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/mitchellh/go-homedir",
|
||||
"Rev": "df55a15e5ce646808815381b3db47a8c66ea62f4"
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
# PKCS#11
|
||||
# PKCS#11 [](https://travis-ci.org/miekg/pkcs11)
|
||||
|
||||
This is a Go implementation of the PKCS#11 API. It wraps the library closely, but uses Go idiom
|
||||
were it makes sense. It has been tested with SoftHSM.
|
||||
|
||||
## SoftHSM
|
||||
|
||||
* Make it use a custom configuration file
|
||||
|
||||
export SOFTHSM_CONF=$PWD/softhsm.conf
|
||||
* Make it use a custom configuration file `export SOFTHSM_CONF=$PWD/softhsm.conf`
|
||||
|
||||
* Then use `softhsm` to init it
|
||||
|
||||
|
@ -22,16 +20,37 @@ were it makes sense. It has been tested with SoftHSM.
|
|||
A skeleton program would look somewhat like this (yes, pkcs#11 is verbose):
|
||||
|
||||
p := pkcs11.New("/usr/lib/softhsm/libsofthsm.so")
|
||||
p.Initialize()
|
||||
err := p.Initialize()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
defer p.Destroy()
|
||||
defer p.Finalize()
|
||||
slots, _ := p.GetSlotList(true)
|
||||
session, _ := p.OpenSession(slots[0], pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
|
||||
|
||||
slots, err := p.GetSlotList(true)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
session, err := p.OpenSession(slots[0], pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer p.CloseSession(session)
|
||||
p.Login(session, pkcs11.CKU_USER, "1234")
|
||||
|
||||
err = p.Login(session, pkcs11.CKU_USER, "1234")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer p.Logout(session)
|
||||
|
||||
p.DigestInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_SHA_1, nil)})
|
||||
hash, err := p.Digest(session, []byte("this is a string"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, d := range hash {
|
||||
fmt.Printf("%x", d)
|
||||
}
|
||||
|
@ -41,8 +60,5 @@ Further examples are included in the tests.
|
|||
|
||||
# TODO
|
||||
|
||||
* Fix/double check endian stuff, see types.go NewAttribute();
|
||||
* Kill C.Sizeof in that same function.
|
||||
* Look at the memory copying in fast functions (sign, hash etc).
|
||||
* Fix inconsistencies in naming?
|
||||
* Add tests -- there are way too few
|
||||
* Fix/double check endian stuff, see types.go NewAttribute()
|
||||
* Look at the memory copying in fast functions (sign, hash etc)
|
||||
|
|
|
@ -23,9 +23,9 @@ const (
|
|||
CKO_VENDOR_DEFINED uint = 0x80000000
|
||||
)
|
||||
|
||||
// Generated with: awk '/#define CK[AFKMR]/{ print $2 "=" $3 }' pkcs11t.h
|
||||
// Generated with: awk '/#define CK[AFKMRC]/{ print $2 "=" $3 }' pkcs11t.h
|
||||
|
||||
// All the flag (CKF_), attribute (CKA_), error code (CKR_), key type (CKK_) and
|
||||
// All the flag (CKF_), attribute (CKA_), error code (CKR_), key type (CKK_), certificate type (CKC_) and
|
||||
// mechanism (CKM_) constants as defined in PKCS#11.
|
||||
const (
|
||||
CKF_TOKEN_PRESENT = 0x00000001
|
||||
|
@ -83,6 +83,10 @@ const (
|
|||
CKK_CAMELLIA = 0x00000025
|
||||
CKK_ARIA = 0x00000026
|
||||
CKK_VENDOR_DEFINED = 0x80000000
|
||||
CKC_X_509 = 0x00000000
|
||||
CKC_X_509_ATTR_CERT = 0x00000001
|
||||
CKC_WTLS = 0x00000002
|
||||
CKC_VENDOR_DEFINED = 0x80000000
|
||||
CKF_ARRAY_ATTRIBUTE = 0x40000000
|
||||
CKA_CLASS = 0x00000000
|
||||
CKA_TOKEN = 0x00000001
|
||||
|
@ -117,11 +121,11 @@ const (
|
|||
CKA_VERIFY = 0x0000010A
|
||||
CKA_VERIFY_RECOVER = 0x0000010B
|
||||
CKA_DERIVE = 0x0000010C
|
||||
CKA_START_DATE = 0x00000110 // Use time.Time as a value.
|
||||
CKA_END_DATE = 0x00000111 // Use time.Time as a value.
|
||||
CKA_START_DATE = 0x00000110
|
||||
CKA_END_DATE = 0x00000111
|
||||
CKA_MODULUS = 0x00000120
|
||||
CKA_MODULUS_BITS = 0x00000121
|
||||
CKA_PUBLIC_EXPONENT = 0x00000122 // Use []byte slice as a value.
|
||||
CKA_PUBLIC_EXPONENT = 0x00000122
|
||||
CKA_PRIVATE_EXPONENT = 0x00000123
|
||||
CKA_PRIME_1 = 0x00000124
|
||||
CKA_PRIME_2 = 0x00000125
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
package pkcs11
|
||||
|
||||
// A test of using several pkcs11 sessions in parallel for signing across
|
||||
// multiple goroutines. Access to the PKCS11 module is thread-safe because of
|
||||
// the C.CKF_OS_LOCKING_OK param and nil mutex functions that the pkcs11
|
||||
// package passes to C.Initialize, which indicate that the module should use OS
|
||||
// locking primitives on its own.
|
||||
//
|
||||
// Note that while access to the module is thread-safe, sessions are not thread
|
||||
// safe, and each session must be protected from simultaneous use by some
|
||||
// synchronization mechanism. In this case we use a cache of sessions (as
|
||||
// embodied by the `signer` struct), protected by a condition variable. So long
|
||||
// as there is an available signer in the cache, it is popped off and used. If
|
||||
// there are no signers available, the caller blocks until there is one
|
||||
// available.
|
||||
//
|
||||
// Please set the appropiate env variables. See the init function.
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
module = "/usr/lib/softhsm/libsofthsm.so"
|
||||
tokenLabel = "softhsm token"
|
||||
privateKeyLabel = "my key"
|
||||
pin = "1234"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if x := os.Getenv("SOFTHSM_LIB"); x != "" {
|
||||
module = x
|
||||
}
|
||||
if x := os.Getenv("SOFTHSM_TOKENLABEL"); x != "" {
|
||||
tokenLabel = x
|
||||
}
|
||||
if x := os.Getenv("SOFTHSM_PRIVKEYLABEL"); x != "" {
|
||||
privateKeyLabel = x
|
||||
}
|
||||
if x := os.Getenv("SOFTHSM_PIN"); x != "" {
|
||||
pin = x
|
||||
}
|
||||
wd, _ := os.Getwd()
|
||||
os.Setenv("SOFTHSM_CONF", wd+"/softhsm.conf")
|
||||
}
|
||||
|
||||
func initPKCS11Context(modulePath string) (*Ctx, error) {
|
||||
context := New(modulePath)
|
||||
|
||||
if context == nil {
|
||||
return nil, fmt.Errorf("unable to load PKCS#11 module")
|
||||
}
|
||||
|
||||
err := context.Initialize()
|
||||
return context, err
|
||||
}
|
||||
|
||||
func getSlot(p *Ctx, label string) (uint, error) {
|
||||
slots, err := p.GetSlotList(true)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
for _, slot := range slots {
|
||||
_, err := p.GetSlotInfo(slot)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
tokenInfo, err := p.GetTokenInfo(slot)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if tokenInfo.Label == label {
|
||||
return slot, nil
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("Slot not found: %s", label)
|
||||
}
|
||||
|
||||
func getPrivateKey(context *Ctx, session SessionHandle, label string) (ObjectHandle, error) {
|
||||
var noKey ObjectHandle
|
||||
template := []*Attribute{
|
||||
NewAttribute(CKA_CLASS, CKO_PRIVATE_KEY),
|
||||
NewAttribute(CKA_LABEL, label),
|
||||
}
|
||||
if err := context.FindObjectsInit(session, template); err != nil {
|
||||
return noKey, err
|
||||
}
|
||||
objs, _, err := context.FindObjects(session, 2)
|
||||
if err != nil {
|
||||
return noKey, err
|
||||
}
|
||||
if err = context.FindObjectsFinal(session); err != nil {
|
||||
return noKey, err
|
||||
}
|
||||
|
||||
if len(objs) == 0 {
|
||||
err = fmt.Errorf("private key not found")
|
||||
return noKey, err
|
||||
}
|
||||
return objs[0], nil
|
||||
}
|
||||
|
||||
type signer struct {
|
||||
context *Ctx
|
||||
session SessionHandle
|
||||
privateKey ObjectHandle
|
||||
}
|
||||
|
||||
func makeSigner(context *Ctx) (*signer, error) {
|
||||
slot, err := getSlot(context, tokenLabel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
session, err := context.OpenSession(slot, CKF_SERIAL_SESSION)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = context.Login(session, CKU_USER, pin); err != nil {
|
||||
context.CloseSession(session)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
privateKey, err := getPrivateKey(context, session, privateKeyLabel)
|
||||
if err != nil {
|
||||
context.CloseSession(session)
|
||||
return nil, err
|
||||
}
|
||||
return &signer{context, session, privateKey}, nil
|
||||
}
|
||||
|
||||
func (s *signer) sign(input []byte) ([]byte, error) {
|
||||
mechanism := []*Mechanism{NewMechanism(CKM_RSA_PKCS, nil)}
|
||||
if err := s.context.SignInit(s.session, mechanism, s.privateKey); err != nil {
|
||||
log.Fatalf("SignInit: %s", err)
|
||||
}
|
||||
|
||||
signed, err := s.context.Sign(s.session, input)
|
||||
if err != nil {
|
||||
log.Fatalf("Sign: %s", err)
|
||||
}
|
||||
return signed, nil
|
||||
}
|
||||
|
||||
type cache struct {
|
||||
signers []*signer
|
||||
// this variable signals the condition that there are signers available to be
|
||||
// used.
|
||||
cond *sync.Cond
|
||||
}
|
||||
|
||||
func newCache(signers []*signer) cache {
|
||||
var mutex sync.Mutex
|
||||
return cache{
|
||||
signers: signers,
|
||||
cond: sync.NewCond(&mutex),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cache) get() *signer {
|
||||
c.cond.L.Lock()
|
||||
for len(c.signers) == 0 {
|
||||
c.cond.Wait()
|
||||
}
|
||||
|
||||
instance := c.signers[len(c.signers)-1]
|
||||
c.signers = c.signers[:len(c.signers)-1]
|
||||
c.cond.L.Unlock()
|
||||
return instance
|
||||
}
|
||||
|
||||
func (c *cache) put(instance *signer) {
|
||||
c.cond.L.Lock()
|
||||
c.signers = append(c.signers, instance)
|
||||
c.cond.Signal()
|
||||
c.cond.L.Unlock()
|
||||
}
|
||||
|
||||
func (c *cache) sign(input []byte) ([]byte, error) {
|
||||
instance := c.get()
|
||||
defer c.put(instance)
|
||||
return instance.sign(input)
|
||||
}
|
||||
|
||||
// TODO(miek): disabled for now. Fill out the correct values in hsm.db so we can use it.
|
||||
func testParallel(t *testing.T) {
|
||||
if module == "" || tokenLabel == "" || pin == "" || privateKeyLabel == "" {
|
||||
t.Fatal("Must pass all flags: module, tokenLabel, pin, and privateKeyLabel")
|
||||
return
|
||||
}
|
||||
|
||||
context, err := initPKCS11Context(module)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
context.Finalize()
|
||||
context.Destroy()
|
||||
}()
|
||||
|
||||
const nSigners = 100
|
||||
const nSignatures = 1000
|
||||
signers := make([]*signer, nSigners)
|
||||
for i := 0; i < nSigners; i++ {
|
||||
signers[i], err = makeSigner(context)
|
||||
if err != nil {
|
||||
t.Fatalf("Problem making signer: %s", err)
|
||||
}
|
||||
}
|
||||
pool := newCache(signers)
|
||||
|
||||
output := make(chan []byte, nSignatures)
|
||||
for i := 0; i < nSignatures; i++ {
|
||||
go func() {
|
||||
result, err := pool.sign([]byte("hi"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
output <- result
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < nSignatures; i++ {
|
||||
// Consume the output of the signers, but do nothing with it.
|
||||
<-output
|
||||
}
|
||||
|
||||
for i := 0; i < nSigners; i++ {
|
||||
// Note: It is not necessary to call context.Logout. Closing the last
|
||||
// session will automatically log out, per PKCS#11 API.
|
||||
context.CloseSession(signers[i].session)
|
||||
}
|
||||
}
|
|
@ -207,6 +207,9 @@ CK_RV SetOperationState(struct ctx * c, CK_SESSION_HANDLE session,
|
|||
CK_RV Login(struct ctx *c, CK_SESSION_HANDLE session, CK_USER_TYPE userType,
|
||||
char *pin, CK_ULONG pinLen)
|
||||
{
|
||||
if (pinLen == 0) {
|
||||
pin = NULL;
|
||||
}
|
||||
CK_RV e =
|
||||
c->sym->C_Login(session, userType, (CK_UTF8CHAR_PTR) pin, pinLen);
|
||||
return e;
|
||||
|
@ -997,7 +1000,8 @@ func (c *Ctx) Logout(sh SessionHandle) error {
|
|||
/* CreateObject creates a new object. */
|
||||
func (c *Ctx) CreateObject(sh SessionHandle, temp []*Attribute) (ObjectHandle, error) {
|
||||
var obj C.CK_OBJECT_HANDLE
|
||||
t, tcount := cAttributeList(temp)
|
||||
arena, t, tcount := cAttributeList(temp)
|
||||
defer arena.Free()
|
||||
e := C.CreateObject(c.ctx, C.CK_SESSION_HANDLE(sh), t, tcount, C.CK_OBJECT_HANDLE_PTR(&obj))
|
||||
e1 := toError(e)
|
||||
if e1 == nil {
|
||||
|
@ -1009,7 +1013,8 @@ func (c *Ctx) CreateObject(sh SessionHandle, temp []*Attribute) (ObjectHandle, e
|
|||
/* CopyObject copies an object, creating a new object for the copy. */
|
||||
func (c *Ctx) CopyObject(sh SessionHandle, o ObjectHandle, temp []*Attribute) (ObjectHandle, error) {
|
||||
var obj C.CK_OBJECT_HANDLE
|
||||
t, tcount := cAttributeList(temp)
|
||||
arena, t, tcount := cAttributeList(temp)
|
||||
defer arena.Free()
|
||||
|
||||
e := C.CopyObject(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(o), t, tcount, C.CK_OBJECT_HANDLE_PTR(&obj))
|
||||
e1 := toError(e)
|
||||
|
@ -1059,7 +1064,8 @@ func (c *Ctx) GetAttributeValue(sh SessionHandle, o ObjectHandle, a []*Attribute
|
|||
|
||||
/* SetAttributeValue modifies the value of one or more object attributes */
|
||||
func (c *Ctx) SetAttributeValue(sh SessionHandle, o ObjectHandle, a []*Attribute) error {
|
||||
pa, palen := cAttributeList(a)
|
||||
arena, pa, palen := cAttributeList(a)
|
||||
defer arena.Free()
|
||||
e := C.SetAttributeValue(c.ctx, C.CK_SESSION_HANDLE(sh), C.CK_OBJECT_HANDLE(o), pa, palen)
|
||||
return toError(e)
|
||||
}
|
||||
|
@ -1067,7 +1073,8 @@ func (c *Ctx) SetAttributeValue(sh SessionHandle, o ObjectHandle, a []*Attribute
|
|||
// FindObjectsInit initializes a search for token and session
|
||||
// objects that match a template.
|
||||
func (c *Ctx) FindObjectsInit(sh SessionHandle, temp []*Attribute) error {
|
||||
t, tcount := cAttributeList(temp)
|
||||
arena, t, tcount := cAttributeList(temp)
|
||||
defer arena.Free()
|
||||
e := C.FindObjectsInit(c.ctx, C.CK_SESSION_HANDLE(sh), t, tcount)
|
||||
return toError(e)
|
||||
}
|
||||
|
@ -1103,7 +1110,8 @@ func (c *Ctx) FindObjectsFinal(sh SessionHandle) error {
|
|||
|
||||
/* EncryptInit initializes an encryption operation. */
|
||||
func (c *Ctx) EncryptInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
|
||||
mech, _ := cMechanismList(m)
|
||||
arena, mech, _ := cMechanismList(m)
|
||||
defer arena.Free()
|
||||
e := C.EncryptInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
|
||||
return toError(e)
|
||||
}
|
||||
|
@ -1155,7 +1163,8 @@ func (c *Ctx) EncryptFinal(sh SessionHandle) ([]byte, error) {
|
|||
|
||||
/* DecryptInit initializes a decryption operation. */
|
||||
func (c *Ctx) DecryptInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
|
||||
mech, _ := cMechanismList(m)
|
||||
arena, mech, _ := cMechanismList(m)
|
||||
defer arena.Free()
|
||||
e := C.DecryptInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
|
||||
return toError(e)
|
||||
}
|
||||
|
@ -1207,7 +1216,8 @@ func (c *Ctx) DecryptFinal(sh SessionHandle) ([]byte, error) {
|
|||
|
||||
/* DigestInit initializes a message-digesting operation. */
|
||||
func (c *Ctx) DigestInit(sh SessionHandle, m []*Mechanism) error {
|
||||
mech, _ := cMechanismList(m)
|
||||
arena, mech, _ := cMechanismList(m)
|
||||
defer arena.Free()
|
||||
e := C.DigestInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech)
|
||||
return toError(e)
|
||||
}
|
||||
|
@ -1267,7 +1277,8 @@ func (c *Ctx) DigestFinal(sh SessionHandle) ([]byte, error) {
|
|||
// the data, and plaintext cannot be recovered from the
|
||||
// signature.
|
||||
func (c *Ctx) SignInit(sh SessionHandle, m []*Mechanism, o ObjectHandle) error {
|
||||
mech, _ := cMechanismList(m) // Only the first is used, but still use a list.
|
||||
arena, mech, _ := cMechanismList(m) // Only the first is used, but still use a list.
|
||||
defer arena.Free()
|
||||
e := C.SignInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(o))
|
||||
return toError(e)
|
||||
}
|
||||
|
@ -1314,7 +1325,8 @@ func (c *Ctx) SignFinal(sh SessionHandle) ([]byte, error) {
|
|||
// SignRecoverInit initializes a signature operation, where
|
||||
// the data can be recovered from the signature.
|
||||
func (c *Ctx) SignRecoverInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
|
||||
mech, _ := cMechanismList(m)
|
||||
arena, mech, _ := cMechanismList(m)
|
||||
defer arena.Free()
|
||||
e := C.SignRecoverInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
|
||||
return toError(e)
|
||||
}
|
||||
|
@ -1339,7 +1351,8 @@ func (c *Ctx) SignRecover(sh SessionHandle, data []byte) ([]byte, error) {
|
|||
// signature is an appendix to the data, and plaintext cannot
|
||||
// be recovered from the signature (e.g. DSA).
|
||||
func (c *Ctx) VerifyInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
|
||||
mech, _ := cMechanismList(m) // only use one here
|
||||
arena, mech, _ := cMechanismList(m) // only use one here
|
||||
defer arena.Free()
|
||||
e := C.VerifyInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
|
||||
return toError(e)
|
||||
}
|
||||
|
@ -1370,7 +1383,8 @@ func (c *Ctx) VerifyFinal(sh SessionHandle, signature []byte) error {
|
|||
// VerifyRecoverInit initializes a signature verification
|
||||
// operation, where the data is recovered from the signature.
|
||||
func (c *Ctx) VerifyRecoverInit(sh SessionHandle, m []*Mechanism, key ObjectHandle) error {
|
||||
mech, _ := cMechanismList(m)
|
||||
arena, mech, _ := cMechanismList(m)
|
||||
defer arena.Free()
|
||||
e := C.VerifyRecoverInit(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(key))
|
||||
return toError(e)
|
||||
}
|
||||
|
@ -1455,8 +1469,10 @@ func (c *Ctx) DecryptVerifyUpdate(sh SessionHandle, cipher []byte) ([]byte, erro
|
|||
/* GenerateKey generates a secret key, creating a new key object. */
|
||||
func (c *Ctx) GenerateKey(sh SessionHandle, m []*Mechanism, temp []*Attribute) (ObjectHandle, error) {
|
||||
var key C.CK_OBJECT_HANDLE
|
||||
t, tcount := cAttributeList(temp)
|
||||
mech, _ := cMechanismList(m)
|
||||
attrarena, t, tcount := cAttributeList(temp)
|
||||
defer attrarena.Free()
|
||||
mecharena, mech, _ := cMechanismList(m)
|
||||
defer mecharena.Free()
|
||||
e := C.GenerateKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, t, tcount, C.CK_OBJECT_HANDLE_PTR(&key))
|
||||
e1 := toError(e)
|
||||
if e1 == nil {
|
||||
|
@ -1471,9 +1487,12 @@ func (c *Ctx) GenerateKeyPair(sh SessionHandle, m []*Mechanism, public, private
|
|||
pubkey C.CK_OBJECT_HANDLE
|
||||
privkey C.CK_OBJECT_HANDLE
|
||||
)
|
||||
pub, pubcount := cAttributeList(public)
|
||||
priv, privcount := cAttributeList(private)
|
||||
mech, _ := cMechanismList(m)
|
||||
pubarena, pub, pubcount := cAttributeList(public)
|
||||
defer pubarena.Free()
|
||||
privarena, priv, privcount := cAttributeList(private)
|
||||
defer privarena.Free()
|
||||
mecharena, mech, _ := cMechanismList(m)
|
||||
defer mecharena.Free()
|
||||
e := C.GenerateKeyPair(c.ctx, C.CK_SESSION_HANDLE(sh), mech, pub, pubcount, priv, privcount, C.CK_OBJECT_HANDLE_PTR(&pubkey), C.CK_OBJECT_HANDLE_PTR(&privkey))
|
||||
e1 := toError(e)
|
||||
if e1 == nil {
|
||||
|
@ -1488,7 +1507,8 @@ func (c *Ctx) WrapKey(sh SessionHandle, m []*Mechanism, wrappingkey, key ObjectH
|
|||
wrappedkey C.CK_BYTE_PTR
|
||||
wrappedkeylen C.CK_ULONG
|
||||
)
|
||||
mech, _ := cMechanismList(m)
|
||||
arena, mech, _ := cMechanismList(m)
|
||||
defer arena.Free()
|
||||
e := C.WrapKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(wrappingkey), C.CK_OBJECT_HANDLE(key), &wrappedkey, &wrappedkeylen)
|
||||
if toError(e) != nil {
|
||||
return nil, toError(e)
|
||||
|
@ -1501,8 +1521,10 @@ func (c *Ctx) WrapKey(sh SessionHandle, m []*Mechanism, wrappingkey, key ObjectH
|
|||
/* UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
|
||||
func (c *Ctx) UnwrapKey(sh SessionHandle, m []*Mechanism, unwrappingkey ObjectHandle, wrappedkey []byte, a []*Attribute) (ObjectHandle, error) {
|
||||
var key C.CK_OBJECT_HANDLE
|
||||
ac, aclen := cAttributeList(a)
|
||||
mech, _ := cMechanismList(m)
|
||||
attrarena, ac, aclen := cAttributeList(a)
|
||||
defer attrarena.Free()
|
||||
mecharena, mech, _ := cMechanismList(m)
|
||||
defer mecharena.Free()
|
||||
e := C.UnwrapKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(unwrappingkey), C.CK_BYTE_PTR(unsafe.Pointer(&wrappedkey[0])), C.CK_ULONG(len(wrappedkey)), ac, aclen, &key)
|
||||
return ObjectHandle(key), toError(e)
|
||||
}
|
||||
|
@ -1510,8 +1532,10 @@ func (c *Ctx) UnwrapKey(sh SessionHandle, m []*Mechanism, unwrappingkey ObjectHa
|
|||
// DeriveKey derives a key from a base key, creating a new key object. */
|
||||
func (c *Ctx) DeriveKey(sh SessionHandle, m []*Mechanism, basekey ObjectHandle, a []*Attribute) (ObjectHandle, error) {
|
||||
var key C.CK_OBJECT_HANDLE
|
||||
ac, aclen := cAttributeList(a)
|
||||
mech, _ := cMechanismList(m)
|
||||
attrarena, ac, aclen := cAttributeList(a)
|
||||
defer attrarena.Free()
|
||||
mecharena, mech, _ := cMechanismList(m)
|
||||
defer mecharena.Free()
|
||||
e := C.DeriveKey(c.ctx, C.CK_SESSION_HANDLE(sh), mech, C.CK_OBJECT_HANDLE(basekey), ac, aclen, &key)
|
||||
return ObjectHandle(key), toError(e)
|
||||
}
|
||||
|
|
|
@ -9,49 +9,91 @@ package pkcs11
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
/*
|
||||
This test supports the following environment variables:
|
||||
|
||||
* SOFTHSM_LIB: complete path to libsofthsm.so
|
||||
* SOFTHSM_TOKENLABEL
|
||||
* SOFTHSM_PRIVKEYLABEL
|
||||
* SOFTHSM_PIN
|
||||
*/
|
||||
|
||||
func setenv(t *testing.T) *Ctx {
|
||||
wd, _ := os.Getwd()
|
||||
os.Setenv("SOFTHSM_CONF", wd+"/softhsm.conf")
|
||||
p := New("/usr/lib/softhsm/libsofthsm.so") //p := New("/home/miek/libsofthsm.so")
|
||||
lib := "/usr/lib/softhsm/libsofthsm.so"
|
||||
if x := os.Getenv("SOFTHSM_LIB"); x != "" {
|
||||
lib = x
|
||||
}
|
||||
t.Logf("loading %s", lib)
|
||||
p := New(lib)
|
||||
if p == nil {
|
||||
t.Fatal("Failed to init lib")
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func TestSetenv(t *testing.T) {
|
||||
wd, _ := os.Getwd()
|
||||
os.Setenv("SOFTHSM_CONF", wd+"/softhsm.conf")
|
||||
|
||||
lib := "/usr/lib/softhsm/libsofthsm.so"
|
||||
if x := os.Getenv("SOFTHSM_LIB"); x != "" {
|
||||
lib = x
|
||||
}
|
||||
p := New(lib)
|
||||
if p == nil {
|
||||
t.Fatal("Failed to init pkcs11")
|
||||
}
|
||||
p.Destroy()
|
||||
return
|
||||
}
|
||||
|
||||
func getSession(p *Ctx, t *testing.T) SessionHandle {
|
||||
if e := p.Initialize(); e != nil {
|
||||
t.Fatalf("init error %s\n", e.Error())
|
||||
t.Fatalf("init error %s\n", e)
|
||||
}
|
||||
slots, e := p.GetSlotList(true)
|
||||
if e != nil {
|
||||
t.Fatalf("slots %s\n", e.Error())
|
||||
t.Fatalf("slots %s\n", e)
|
||||
}
|
||||
session, e := p.OpenSession(slots[0], CKF_SERIAL_SESSION)
|
||||
if e != nil {
|
||||
t.Fatalf("session %s\n", e.Error())
|
||||
t.Fatalf("session %s\n", e)
|
||||
}
|
||||
if e := p.Login(session, CKU_USER, "1234"); e != nil {
|
||||
t.Fatal("user pin %s\n", e.Error())
|
||||
if e := p.Login(session, CKU_USER, pin); e != nil {
|
||||
t.Fatalf("user pin %s\n", e)
|
||||
}
|
||||
return session
|
||||
}
|
||||
|
||||
func TestInitialize(t *testing.T) {
|
||||
p := setenv(t)
|
||||
if e := p.Initialize(); e != nil {
|
||||
t.Fatalf("init error %s\n", e)
|
||||
}
|
||||
p.Finalize()
|
||||
p.Destroy()
|
||||
}
|
||||
|
||||
func finishSession(p *Ctx, session SessionHandle) {
|
||||
p.Logout(session)
|
||||
p.CloseSession(session)
|
||||
p.Finalize()
|
||||
p.Destroy()
|
||||
}
|
||||
|
||||
func TestGetInfo(t *testing.T) {
|
||||
p := setenv(t)
|
||||
session := getSession(p, t)
|
||||
defer p.Logout(session)
|
||||
defer p.CloseSession(session)
|
||||
defer p.Finalize()
|
||||
defer p.Destroy()
|
||||
defer finishSession(p, session)
|
||||
info, err := p.GetInfo()
|
||||
if err != nil {
|
||||
t.Fatalf("Non zero error %s\n", err.Error())
|
||||
t.Fatalf("non zero error %s\n", err)
|
||||
}
|
||||
if info.ManufacturerID != "SoftHSM" {
|
||||
t.Fatal("ID should be SoftHSM")
|
||||
|
@ -62,21 +104,18 @@ func TestGetInfo(t *testing.T) {
|
|||
func TestFindObject(t *testing.T) {
|
||||
p := setenv(t)
|
||||
session := getSession(p, t)
|
||||
defer p.Logout(session)
|
||||
defer p.CloseSession(session)
|
||||
defer p.Finalize()
|
||||
defer p.Destroy()
|
||||
defer finishSession(p, session)
|
||||
// There are 2 keys in the db with this tag
|
||||
template := []*Attribute{NewAttribute(CKA_LABEL, "MyFirstKey")}
|
||||
if e := p.FindObjectsInit(session, template); e != nil {
|
||||
t.Fatalf("Failed to init: %s\n", e.Error())
|
||||
t.Fatalf("failed to init: %s\n", e)
|
||||
}
|
||||
obj, b, e := p.FindObjects(session, 2)
|
||||
if e != nil {
|
||||
t.Fatalf("Failed to find: %s %v\n", e.Error(), b)
|
||||
t.Fatalf("failed to find: %s %v\n", e, b)
|
||||
}
|
||||
if e := p.FindObjectsFinal(session); e != nil {
|
||||
t.Fatalf("Failed to finalize: %s\n", e.Error())
|
||||
t.Fatalf("failed to finalize: %s\n", e)
|
||||
}
|
||||
if len(obj) != 2 {
|
||||
t.Fatal("should have found two objects")
|
||||
|
@ -86,10 +125,7 @@ func TestFindObject(t *testing.T) {
|
|||
func TestGetAttributeValue(t *testing.T) {
|
||||
p := setenv(t)
|
||||
session := getSession(p, t)
|
||||
defer p.Logout(session)
|
||||
defer p.Destroy()
|
||||
defer p.Finalize()
|
||||
defer p.CloseSession(session)
|
||||
defer finishSession(p, session)
|
||||
// There are at least two RSA keys in the hsm.db, objecthandle 1 and 2.
|
||||
template := []*Attribute{
|
||||
NewAttribute(CKA_PUBLIC_EXPONENT, nil),
|
||||
|
@ -100,14 +136,14 @@ func TestGetAttributeValue(t *testing.T) {
|
|||
// ObjectHandle two is the public key
|
||||
attr, err := p.GetAttributeValue(session, ObjectHandle(2), template)
|
||||
if err != nil {
|
||||
t.Fatalf("err %s\n", err.Error())
|
||||
t.Fatalf("err %s\n", err)
|
||||
}
|
||||
for i, a := range attr {
|
||||
t.Logf("Attr %d, type %d, valuelen %d", i, a.Type, len(a.Value))
|
||||
t.Logf("attr %d, type %d, valuelen %d", i, a.Type, len(a.Value))
|
||||
if a.Type == CKA_MODULUS {
|
||||
mod := big.NewInt(0)
|
||||
mod.SetBytes(a.Value)
|
||||
t.Logf("Modulus %s\n", mod.String())
|
||||
t.Logf("modulus %s\n", mod.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -115,18 +151,15 @@ func TestGetAttributeValue(t *testing.T) {
|
|||
func TestDigest(t *testing.T) {
|
||||
p := setenv(t)
|
||||
session := getSession(p, t)
|
||||
defer p.Logout(session)
|
||||
defer p.CloseSession(session)
|
||||
defer p.Finalize()
|
||||
defer p.Destroy()
|
||||
defer finishSession(p, session)
|
||||
e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)})
|
||||
if e != nil {
|
||||
t.Fatalf("DigestInit: %s\n", e.Error())
|
||||
t.Fatalf("DigestInit: %s\n", e)
|
||||
}
|
||||
|
||||
hash, e := p.Digest(session, []byte("this is a string"))
|
||||
if e != nil {
|
||||
t.Fatalf("Digest: %s\n", e.Error())
|
||||
t.Fatalf("digest: %s\n", e)
|
||||
}
|
||||
hex := ""
|
||||
for _, d := range hash {
|
||||
|
@ -141,22 +174,19 @@ func TestDigest(t *testing.T) {
|
|||
func TestDigestUpdate(t *testing.T) {
|
||||
p := setenv(t)
|
||||
session := getSession(p, t)
|
||||
defer p.Logout(session)
|
||||
defer p.CloseSession(session)
|
||||
defer p.Finalize()
|
||||
defer p.Destroy()
|
||||
defer finishSession(p, session)
|
||||
if e := p.DigestInit(session, []*Mechanism{NewMechanism(CKM_SHA_1, nil)}); e != nil {
|
||||
t.Fatalf("DigestInit: %s\n", e.Error())
|
||||
t.Fatalf("DigestInit: %s\n", e)
|
||||
}
|
||||
if e := p.DigestUpdate(session, []byte("this is ")); e != nil {
|
||||
t.Fatalf("DigestUpdate: %s\n", e.Error())
|
||||
t.Fatalf("DigestUpdate: %s\n", e)
|
||||
}
|
||||
if e := p.DigestUpdate(session, []byte("a string")); e != nil {
|
||||
t.Fatalf("DigestUpdate: %s\n", e.Error())
|
||||
t.Fatalf("DigestUpdate: %s\n", e)
|
||||
}
|
||||
hash, e := p.DigestFinal(session)
|
||||
if e != nil {
|
||||
t.Fatalf("DigestFinal: %s\n", e.Error())
|
||||
t.Fatalf("DigestFinal: %s\n", e)
|
||||
}
|
||||
hex := ""
|
||||
for _, d := range hash {
|
||||
|
@ -166,47 +196,95 @@ func TestDigestUpdate(t *testing.T) {
|
|||
if hex != "517592df8fec3ad146a79a9af153db2a4d784ec5" {
|
||||
t.Fatalf("wrong digest: %s", hex)
|
||||
}
|
||||
}
|
||||
|
||||
func generateRSAKeyPair(t *testing.T, p *Ctx, session SessionHandle) (ObjectHandle, ObjectHandle) {
|
||||
publicKeyTemplate := []*Attribute{
|
||||
NewAttribute(CKA_KEY_TYPE, CKO_PUBLIC_KEY),
|
||||
NewAttribute(CKA_TOKEN, false),
|
||||
NewAttribute(CKA_VERIFY, true),
|
||||
NewAttribute(CKA_PUBLIC_EXPONENT, []byte{1, 0, 1}),
|
||||
NewAttribute(CKA_MODULUS_BITS, 2048),
|
||||
NewAttribute(CKA_LABEL, "TestPbk"),
|
||||
}
|
||||
privateKeyTemplate := []*Attribute{
|
||||
NewAttribute(CKA_TOKEN, false),
|
||||
NewAttribute(CKA_SIGN, true),
|
||||
NewAttribute(CKA_LABEL, "TestPvk"),
|
||||
NewAttribute(CKA_SENSITIVE, true),
|
||||
NewAttribute(CKA_EXTRACTABLE, true),
|
||||
}
|
||||
pbk, pvk, e := p.GenerateKeyPair(session,
|
||||
[]*Mechanism{NewMechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, nil)},
|
||||
publicKeyTemplate, privateKeyTemplate)
|
||||
if e != nil {
|
||||
t.Fatalf("failed to generate keypair: %s\n", e)
|
||||
}
|
||||
|
||||
return pbk, pvk
|
||||
}
|
||||
|
||||
func TestGenerateKeyPair(t *testing.T) {
|
||||
p := setenv(t)
|
||||
session := getSession(p, t)
|
||||
defer finishSession(p, session)
|
||||
generateRSAKeyPair(t, p, session)
|
||||
}
|
||||
|
||||
func TestSign(t *testing.T) {
|
||||
p := setenv(t)
|
||||
session := getSession(p, t)
|
||||
defer finishSession(p, session)
|
||||
_, pvk := generateRSAKeyPair(t, p, session)
|
||||
|
||||
p.SignInit(session, []*Mechanism{NewMechanism(CKM_SHA1_RSA_PKCS, nil)}, pvk)
|
||||
_, e := p.Sign(session, []byte("Sign me!"))
|
||||
if e != nil {
|
||||
t.Fatalf("failed to sign: %s\n", e)
|
||||
}
|
||||
}
|
||||
|
||||
func testDestroyObject(t *testing.T) {
|
||||
p := setenv(t)
|
||||
session := getSession(p, t)
|
||||
defer p.Logout(session)
|
||||
defer p.CloseSession(session)
|
||||
defer p.Finalize()
|
||||
defer p.Destroy()
|
||||
defer finishSession(p, session)
|
||||
|
||||
p.Logout(session) // log out the normal user
|
||||
if e := p.Login(session, CKU_SO, "1234"); e != nil {
|
||||
t.Fatal("security officer pin %s\n", e.Error())
|
||||
t.Fatalf("security officer pin %s\n", e)
|
||||
}
|
||||
|
||||
// Looking the int values is tricky because they are stored in 64 bits in hsm.db,
|
||||
// this means looking up stuff on 32 bits will not found them.
|
||||
template := []*Attribute{
|
||||
NewAttribute(CKA_LABEL, "MyFirstKey")}
|
||||
|
||||
if e := p.FindObjectsInit(session, template); e != nil {
|
||||
t.Fatalf("Failed to init: %s\n", e.Error())
|
||||
t.Fatalf("failed to init: %s\n", e)
|
||||
}
|
||||
obj, _, e := p.FindObjects(session, 1)
|
||||
if e != nil || len(obj) == 0 {
|
||||
t.Fatalf("Failed to find objects\n")
|
||||
t.Fatalf("failed to find objects\n")
|
||||
}
|
||||
if e := p.FindObjectsFinal(session); e != nil {
|
||||
t.Fatalf("Failed to finalize: %s\n", e.Error())
|
||||
t.Fatalf("failed to finalize: %s\n", e)
|
||||
}
|
||||
|
||||
if err := p.DestroyObject(session, obj[0]); err != nil {
|
||||
t.Fatal("DestroyObject failed" + err.Error())
|
||||
if e := p.DestroyObject(session, obj[0]); e != nil {
|
||||
t.Fatal("DestroyObject failed: %s\n", e)
|
||||
}
|
||||
}
|
||||
|
||||
// ExampleSign show how to sign some data with a private key.
|
||||
// Note: error correction is not implemented in this function.
|
||||
// ExampleSign shows how to sign some data with a private key.
|
||||
// Note: error correction is not implemented in this example.
|
||||
func ExampleSign() {
|
||||
p := setenv(nil)
|
||||
lib := "/usr/lib/softhsm/libsofthsm.so"
|
||||
if x := os.Getenv("SOFTHSM_LIB"); x != "" {
|
||||
lib = x
|
||||
}
|
||||
p := New(lib)
|
||||
if p == nil {
|
||||
log.Fatal("Failed to init lib")
|
||||
}
|
||||
|
||||
p.Initialize()
|
||||
defer p.Destroy()
|
||||
defer p.Finalize()
|
||||
|
@ -217,7 +295,7 @@ func ExampleSign() {
|
|||
defer p.Logout(session)
|
||||
publicKeyTemplate := []*Attribute{
|
||||
NewAttribute(CKA_KEY_TYPE, CKO_PUBLIC_KEY),
|
||||
NewAttribute(CKA_TOKEN, true),
|
||||
NewAttribute(CKA_TOKEN, false),
|
||||
NewAttribute(CKA_ENCRYPT, true),
|
||||
NewAttribute(CKA_PUBLIC_EXPONENT, []byte{3}),
|
||||
NewAttribute(CKA_MODULUS_BITS, 1024),
|
||||
|
@ -225,18 +303,26 @@ func ExampleSign() {
|
|||
}
|
||||
privateKeyTemplate := []*Attribute{
|
||||
NewAttribute(CKA_KEY_TYPE, CKO_PRIVATE_KEY),
|
||||
NewAttribute(CKA_TOKEN, true),
|
||||
NewAttribute(CKA_TOKEN, false),
|
||||
NewAttribute(CKA_PRIVATE, true),
|
||||
NewAttribute(CKA_SIGN, true),
|
||||
NewAttribute(CKA_LABEL, "MyFirstKey"),
|
||||
}
|
||||
pub, priv, _ := p.GenerateKeyPair(session,
|
||||
_, priv, err := p.GenerateKeyPair(session,
|
||||
[]*Mechanism{NewMechanism(CKM_RSA_PKCS_KEY_PAIR_GEN, nil)},
|
||||
publicKeyTemplate, privateKeyTemplate)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
p.SignInit(session, []*Mechanism{NewMechanism(CKM_SHA1_RSA_PKCS, nil)}, priv)
|
||||
// Sign something with the private key.
|
||||
data := []byte("Lets sign this data")
|
||||
|
||||
sig, _ := p.Sign(session, data)
|
||||
fmt.Printf("%v validate with %v\n", sig, pub)
|
||||
_, err = p.Sign(session, data)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Printf("It works!")
|
||||
// Output: It works!
|
||||
}
|
||||
|
|
|
@ -15,17 +15,13 @@ package pkcs11
|
|||
#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pkcs11.h"
|
||||
|
||||
CK_ULONG Index(CK_ULONG_PTR array, CK_ULONG i)
|
||||
{
|
||||
return array[i];
|
||||
}
|
||||
|
||||
CK_ULONG Sizeof()
|
||||
{
|
||||
return sizeof(CK_ULONG);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
|
@ -35,6 +31,21 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
type arena []unsafe.Pointer
|
||||
|
||||
func (a *arena) Allocate(obj []byte) (C.CK_VOID_PTR, C.CK_ULONG) {
|
||||
cobj := C.calloc(C.size_t(len(obj)), 1)
|
||||
*a = append(*a, cobj)
|
||||
C.memmove(cobj, unsafe.Pointer(&obj[0]), C.size_t(len(obj)))
|
||||
return C.CK_VOID_PTR(cobj), C.CK_ULONG(len(obj))
|
||||
}
|
||||
|
||||
func (a arena) Free() {
|
||||
for _, p := range a {
|
||||
C.free(p)
|
||||
}
|
||||
}
|
||||
|
||||
// toList converts from a C style array to a []uint.
|
||||
func toList(clist C.CK_ULONG_PTR, size C.CK_ULONG) []uint {
|
||||
l := make([]uint, int(size))
|
||||
|
@ -53,6 +64,11 @@ func cBBool(x bool) C.CK_BBOOL {
|
|||
return C.CK_BBOOL(C.CK_FALSE)
|
||||
}
|
||||
|
||||
func uintToBytes(x uint64) []byte {
|
||||
ul := C.CK_ULONG(x)
|
||||
return C.GoBytes(unsafe.Pointer(&ul), C.int(unsafe.Sizeof(ul)))
|
||||
}
|
||||
|
||||
// Error represents an PKCS#11 error.
|
||||
type Error uint
|
||||
|
||||
|
@ -156,46 +172,23 @@ func NewAttribute(typ uint, x interface{}) *Attribute {
|
|||
if x == nil {
|
||||
return a
|
||||
}
|
||||
switch x.(type) {
|
||||
case bool: // create bbool
|
||||
if x.(bool) {
|
||||
switch v := x.(type) {
|
||||
case bool:
|
||||
if v {
|
||||
a.Value = []byte{1}
|
||||
break
|
||||
}
|
||||
} else {
|
||||
a.Value = []byte{0}
|
||||
case uint, int:
|
||||
var y uint
|
||||
if _, ok := x.(int); ok {
|
||||
y = uint(x.(int))
|
||||
}
|
||||
if _, ok := x.(uint); ok {
|
||||
y = x.(uint)
|
||||
}
|
||||
// TODO(miek): ugly!
|
||||
switch int(C.Sizeof()) {
|
||||
case 4:
|
||||
a.Value = make([]byte, 4)
|
||||
a.Value[0] = byte(y)
|
||||
a.Value[1] = byte(y >> 8)
|
||||
a.Value[2] = byte(y >> 16)
|
||||
a.Value[3] = byte(y >> 24)
|
||||
case 8:
|
||||
a.Value = make([]byte, 8)
|
||||
a.Value[0] = byte(y)
|
||||
a.Value[1] = byte(y >> 8)
|
||||
a.Value[2] = byte(y >> 16)
|
||||
a.Value[3] = byte(y >> 24)
|
||||
a.Value[4] = byte(y >> 32)
|
||||
a.Value[5] = byte(y >> 40)
|
||||
a.Value[6] = byte(y >> 48)
|
||||
a.Value[7] = byte(y >> 56)
|
||||
}
|
||||
case int:
|
||||
a.Value = uintToBytes(uint64(v))
|
||||
case uint:
|
||||
a.Value = uintToBytes(uint64(v))
|
||||
case string:
|
||||
a.Value = []byte(x.(string))
|
||||
case []byte: // just copy
|
||||
a.Value = x.([]byte)
|
||||
a.Value = []byte(v)
|
||||
case []byte:
|
||||
a.Value = v
|
||||
case time.Time: // for CKA_DATE
|
||||
a.Value = cDate(x.(time.Time))
|
||||
a.Value = cDate(v)
|
||||
default:
|
||||
panic("pkcs11: unhandled attribute type")
|
||||
}
|
||||
|
@ -203,9 +196,10 @@ func NewAttribute(typ uint, x interface{}) *Attribute {
|
|||
}
|
||||
|
||||
// cAttribute returns the start address and the length of an attribute list.
|
||||
func cAttributeList(a []*Attribute) (C.CK_ATTRIBUTE_PTR, C.CK_ULONG) {
|
||||
func cAttributeList(a []*Attribute) (arena, C.CK_ATTRIBUTE_PTR, C.CK_ULONG) {
|
||||
var arena arena
|
||||
if len(a) == 0 {
|
||||
return nil, 0
|
||||
return nil, nil, 0
|
||||
}
|
||||
pa := make([]C.CK_ATTRIBUTE, len(a))
|
||||
for i := 0; i < len(a); i++ {
|
||||
|
@ -213,10 +207,9 @@ func cAttributeList(a []*Attribute) (C.CK_ATTRIBUTE_PTR, C.CK_ULONG) {
|
|||
if a[i].Value == nil {
|
||||
continue
|
||||
}
|
||||
pa[i].pValue = C.CK_VOID_PTR((&a[i].Value[0]))
|
||||
pa[i].ulValueLen = C.CK_ULONG(len(a[i].Value))
|
||||
pa[i].pValue, pa[i].ulValueLen = arena.Allocate(a[i].Value)
|
||||
}
|
||||
return C.CK_ATTRIBUTE_PTR(&pa[0]), C.CK_ULONG(len(a))
|
||||
return arena, C.CK_ATTRIBUTE_PTR(&pa[0]), C.CK_ULONG(len(a))
|
||||
}
|
||||
|
||||
func cDate(t time.Time) []byte {
|
||||
|
@ -250,9 +243,10 @@ func NewMechanism(mech uint, x interface{}) *Mechanism {
|
|||
return m
|
||||
}
|
||||
|
||||
func cMechanismList(m []*Mechanism) (C.CK_MECHANISM_PTR, C.CK_ULONG) {
|
||||
func cMechanismList(m []*Mechanism) (arena, C.CK_MECHANISM_PTR, C.CK_ULONG) {
|
||||
var arena arena
|
||||
if len(m) == 0 {
|
||||
return nil, 0
|
||||
return nil, nil, 0
|
||||
}
|
||||
pm := make([]C.CK_MECHANISM, len(m))
|
||||
for i := 0; i < len(m); i++ {
|
||||
|
@ -260,10 +254,9 @@ func cMechanismList(m []*Mechanism) (C.CK_MECHANISM_PTR, C.CK_ULONG) {
|
|||
if m[i].Parameter == nil {
|
||||
continue
|
||||
}
|
||||
pm[i].pParameter = C.CK_VOID_PTR(&(m[i].Parameter[0]))
|
||||
pm[i].ulParameterLen = C.CK_ULONG(len(m[i].Parameter))
|
||||
pm[i].pParameter, pm[i].ulParameterLen = arena.Allocate(m[i].Parameter)
|
||||
}
|
||||
return C.CK_MECHANISM_PTR(&pm[0]), C.CK_ULONG(len(m))
|
||||
return arena, C.CK_MECHANISM_PTR(&pm[0]), C.CK_ULONG(len(m))
|
||||
}
|
||||
|
||||
// MechanismInfo provides information about a particular mechanism.
|
||||
|
|
Loading…
Reference in New Issue