Skip to content

Commit

Permalink
Support conventions for functions returning output in a variable-leng…
Browse files Browse the repository at this point in the history
…th buffer
  • Loading branch information
bernard-wagner committed Sep 3, 2020
1 parent 5e777eb commit c8e6cef
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 19 deletions.
96 changes: 77 additions & 19 deletions pkcs11.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,11 +357,13 @@ CK_RV Encrypt(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
if (rv != CKR_OK) {
return rv;
}
*enc = calloc(*enclen, sizeof(CK_BYTE));
if (*enc == NULL) {
return CKR_HOST_MEMORY;
if (enc != NULL) {
*enc = calloc(*enclen, sizeof(CK_BYTE));
if (*enc == NULL) {
return CKR_HOST_MEMORY;
}
rv = c->sym->C_Encrypt(session, message, mlen, *enc, enclen);
}
rv = c->sym->C_Encrypt(session, message, mlen, *enc, enclen);
return rv;
}
Expand Down Expand Up @@ -411,11 +413,13 @@ CK_RV Decrypt(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR cipher,
if (e != CKR_OK) {
return e;
}
*plain = calloc(*plainlen, sizeof(CK_BYTE));
if (*plain == NULL) {
return CKR_HOST_MEMORY;
if (plain != NULL) {
*plain = calloc(*plainlen, sizeof(CK_BYTE));
if (*plain == NULL) {
return CKR_HOST_MEMORY;
}
e = c->sym->C_Decrypt(session, cipher, clen, *plain, plainlen);
}
e = c->sym->C_Decrypt(session, cipher, clen, *plain, plainlen);
return e;
}
Expand Down Expand Up @@ -465,11 +469,13 @@ CK_RV Digest(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
if (rv != CKR_OK) {
return rv;
}
*hash = calloc(*hashlen, sizeof(CK_BYTE));
if (*hash == NULL) {
return CKR_HOST_MEMORY;
if (hash != NULL) {
*hash = calloc(*hashlen, sizeof(CK_BYTE));
if (*hash == NULL) {
return CKR_HOST_MEMORY;
}
rv = c->sym->C_Digest(session, message, mlen, *hash, hashlen);
}
rv = c->sym->C_Digest(session, message, mlen, *hash, hashlen);
return rv;
}
Expand Down Expand Up @@ -514,11 +520,13 @@ CK_RV Sign(struct ctx * c, CK_SESSION_HANDLE session, CK_BYTE_PTR message,
if (rv != CKR_OK) {
return rv;
}
*sig = calloc(*siglen, sizeof(CK_BYTE));
if (*sig == NULL) {
return CKR_HOST_MEMORY;
if (sig != NULL) {
*sig = calloc(*siglen, sizeof(CK_BYTE));
if (*sig == NULL) {
return CKR_HOST_MEMORY;
}
rv = c->sym->C_Sign(session, message, mlen, *sig, siglen);
}
rv = c->sym->C_Sign(session, message, mlen, *sig, siglen);
return rv;
}
Expand Down Expand Up @@ -770,9 +778,10 @@ static inline CK_VOID_PTR getAttributePval(CK_ATTRIBUTE_PTR a)
*/
import "C"
import "strings"

import "unsafe"
import (
"strings"
"unsafe"
)

// Ctx contains the current pkcs11 context.
type Ctx struct {
Expand Down Expand Up @@ -1166,6 +1175,18 @@ func (c *Ctx) Encrypt(sh SessionHandle, message []byte) ([]byte, error) {
return s, nil
}

// EncryptNull encrypts single-part data.
func (c *Ctx) EncryptNull(sh SessionHandle, message []byte) (int, error) {
var (
enclen C.CK_ULONG
)
e := C.Encrypt(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)), nil, &enclen)
if toError(e) != nil {
return 0, toError(e)
}
return int(enclen), nil
}

// EncryptUpdate continues a multiple-part encryption operation.
func (c *Ctx) EncryptUpdate(sh SessionHandle, plain []byte) ([]byte, error) {
var (
Expand Down Expand Up @@ -1219,6 +1240,18 @@ func (c *Ctx) Decrypt(sh SessionHandle, cipher []byte) ([]byte, error) {
return s, nil
}

// DecryptNull decrypts encrypted data in a single part.
func (c *Ctx) DecryptNull(sh SessionHandle, cipher []byte) (int, error) {
var (
plainlen C.CK_ULONG
)
e := C.Decrypt(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(cipher), C.CK_ULONG(len(cipher)), nil, &plainlen)
if toError(e) != nil {
return 0, toError(e)
}
return int(plainlen), nil
}

// DecryptUpdate continues a multiple-part decryption operation.
func (c *Ctx) DecryptUpdate(sh SessionHandle, cipher []byte) ([]byte, error) {
var (
Expand Down Expand Up @@ -1272,6 +1305,18 @@ func (c *Ctx) Digest(sh SessionHandle, message []byte) ([]byte, error) {
return h, nil
}

// DigestNull digests message in a single part.
func (c *Ctx) DigestNull(sh SessionHandle, message []byte) (int, error) {
var (
hashlen C.CK_ULONG
)
e := C.Digest(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)), nil, &hashlen)
if toError(e) != nil {
return 0, toError(e)
}
return int(hashlen), nil
}

// DigestUpdate continues a multiple-part message-digesting operation.
func (c *Ctx) DigestUpdate(sh SessionHandle, message []byte) error {
e := C.DigestUpdate(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)))
Expand Down Expand Up @@ -1333,6 +1378,19 @@ func (c *Ctx) Sign(sh SessionHandle, message []byte) ([]byte, error) {
return s, nil
}

// Sign signs (encrypts with private key) data in a single part, where the signature
// is (will be) an appendix to the data, and plaintext cannot be recovered from the signature.
func (c *Ctx) SignNull(sh SessionHandle, message []byte) (int, error) {
var (
siglen C.CK_ULONG
)
e := C.Sign(c.ctx, C.CK_SESSION_HANDLE(sh), cMessage(message), C.CK_ULONG(len(message)), nil, &siglen)
if toError(e) != nil {
return 0, toError(e)
}
return int(siglen), nil
}

// SignUpdate continues a multiple-part signature operation,
// where the signature is (will be) an appendix to the data,
// and plaintext cannot be recovered from the signature.
Expand Down
57 changes: 57 additions & 0 deletions pkcs11_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -530,4 +530,61 @@ func ExampleCtx_Sign() {
// Output: It works!
}

// ExampleSign shows how to sign some data with a private key.
// Note: error correction is not implemented in this example.
func ExampleCtx_SignNull() {
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()
slots, _ := p.GetSlotList(true)
session, _ := p.OpenSession(slots[0], CKF_SERIAL_SESSION|CKF_RW_SESSION)
defer p.CloseSession(session)
p.Login(session, CKU_USER, "1234")
defer p.Logout(session)
publicKeyTemplate := []*Attribute{
NewAttribute(CKA_CLASS, CKO_PUBLIC_KEY),
NewAttribute(CKA_KEY_TYPE, CKK_RSA),
NewAttribute(CKA_TOKEN, false),
NewAttribute(CKA_ENCRYPT, true),
NewAttribute(CKA_PUBLIC_EXPONENT, []byte{3}),
NewAttribute(CKA_MODULUS_BITS, 1024),
NewAttribute(CKA_LABEL, "ExampleSign"),
}
privateKeyTemplate := []*Attribute{
NewAttribute(CKA_CLASS, CKO_PRIVATE_KEY),
NewAttribute(CKA_KEY_TYPE, CKK_RSA),
NewAttribute(CKA_TOKEN, false),
NewAttribute(CKA_PRIVATE, true),
NewAttribute(CKA_SIGN, true),
NewAttribute(CKA_LABEL, "ExampleSign"),
}
_, 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)

size, err := p.SignNull(session, nil)
if err != nil {
log.Fatal(err)
}

if size == 0 {
log.Fatalf("Failed %v", size)
}
fmt.Printf("It works!")
// Output: It works!
}

// Copyright 2013 Miek Gieben. All rights reserved.
Binary file not shown.

0 comments on commit c8e6cef

Please sign in to comment.