package main
import (
"bytes"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/binary"
"fmt"
"log"
"github.com/miekg/pkcs11"
)
const (
pin = "87654321"
)
var ()
func main() {
// Init PKCS11
p := pkcs11.New("/opt/utimaco/lib/libcs_pkcs11_R3.so")
err := p.Initialize()
if err != nil {
panic(err)
}
defer p.Destroy()
defer p.Finalize()
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)
err = p.Login(session, pkcs11.CKU_USER, pin)
if err != nil {
panic(err)
}
defer p.Logout(session)
info, err := p.GetInfo()
if err != nil {
panic(err)
}
fmt.Printf("CryptokiVersion.Major %v", info.CryptokiVersion.Major)
fmt.Println()
// Create AES key
buf := new(bytes.Buffer)
var num uint16 = 1
err = binary.Write(buf, binary.LittleEndian, num)
if err != nil {
fmt.Println("binary.Write failed:", err)
}
id := buf.Bytes()
aesKeyTemplate := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_SECRET_KEY),
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_AES),
pkcs11.NewAttribute(pkcs11.CKA_ENCRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_DECRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, true), // we don't
need to extract this..
pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
pkcs11.NewAttribute(pkcs11.CKA_VALUE_LEN, 32), /* KeyLength */
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "AESKey"), /*
Name of Key */
}
aesKey, err := p.GenerateKey(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_KEY_GEN
, nil)},
aesKeyTemplate)
if err != nil {
panic(fmt.Sprintf("GenerateKey() failed %s\n", err))
}
log.Printf("Created AES Key: %v", aesKey)
ktemplate := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_SECRET_KEY),
pkcs11.NewAttribute(pkcs11.CKA_ID, id),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "AESKey"),
}
aesKeyTemplate2 := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_SECRET_KEY),
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_AES),
pkcs11.NewAttribute(pkcs11.CKA_ENCRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_DECRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_DECRYPT, true),
pkcs11.NewAttribute(pkcs11.CKA_WRAP, true),
pkcs11.NewAttribute(pkcs11.CKA_UNWRAP, true),
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, true), // we don't
need to extract this..
pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
pkcs11.NewAttribute(pkcs11.CKA_VALUE_LEN, 32), /* KeyLength */
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "AESKeyToWrap"), /*
Name of Key */
}
aesKey2, err := p.GenerateKey(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_KEY_GEN
, nil)},
aesKeyTemplate2)
if err != nil {
panic(fmt.Sprintf("GenerateKey() failed %s\n", err))
}
log.Printf("Created AES Key: %v", aesKey2)
if err := p.FindObjectsInit(session, ktemplate); err != nil {
panic(err)
}
if err != nil {
panic(err)
}
if err = p.FindObjectsFinal(session); err != nil {
panic(err)
}
iv := make([]byte, 16)
_, err = rand.Read(iv)
if err != nil {
panic(err)
}
// Encryption
err = p.EncryptInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_CBC_PAD, iv)}, aesKey)
if err != nil {
panic(fmt.Sprintf("EncryptInit() failed %s\n", err))
}
ct, err := p.Encrypt(session, []byte("foo"))
if err != nil {
panic(fmt.Sprintf("Encrypt() failed %s\n", err))
}
// append the IV to the ciphertext
cdWithIV := append(iv, ct...)
log.Printf("Encrypted IV+Ciphertext %s",
base64.RawStdEncoding.EncodeToString(cdWithIV))
// Decryption
err = p.DecryptInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_CBC_PAD,
cdWithIV[0:16])}, aesKey)
if err != nil {
panic(fmt.Sprintf("EncryptInit() failed %s\n", err))
}
pt, err := p.Decrypt(session, ct[:16])
if err != nil {
panic(fmt.Sprintf("Encrypt() failed %s\n", err))
}
log.Printf("Decrypt %s", string(pt))
// Signing
msg := []byte("foo")
digest := sha256.Sum256(msg)
log.Printf("Decrypt %s", string(pt))
err = p.SignInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_CBC, nil)}, aesKey)
sig, err := p.Sign(session, msg)
// Verification
err = p.VerifyInit(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_CBC, nil)}, aesKey)
err = p.Verify(session, digest[:], sig)
// Wrapping
wrappedPrivBytes, err := p.WrapKey(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_KEY_WRAP, nil)},
aesKey, aesKey2)
if err != nil {
log.Fatalf("failed to wrap privatekey : %s\n", err)
}
buf = new(bytes.Buffer)
num = 6
err = binary.Write(buf, binary.LittleEndian, num)
if err != nil {
log.Fatalf("binary.Write failed: %v", err)
}
importedPrivID := buf.Bytes()
aesKeyTemplate2 = []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_SECRET_KEY),
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_AES),
pkcs11.NewAttribute(pkcs11.CKA_TOKEN, true),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, "UnwrappedAESKey"), /*
Name of Key */
pkcs11.NewAttribute(pkcs11.CKA_ID, importedPrivID),
}
// Unwrapping
ik, err := p.UnwrapKey(session,
[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_KEY_WRAP, nil)},
aesKey, wrappedPrivBytes, aesKeyTemplate2)
_ = ik
if err != nil {
log.Fatalf("Unwrap Failed: %v", err)
}
}