2018-07-25 08:16:41 -04:00
|
|
|
// Copyright 2013 Miek Gieben. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package pkcs11
|
|
|
|
|
|
|
|
/*
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "pkcs11go.h"
|
2019-02-26 06:45:19 -05:00
|
|
|
|
|
|
|
static inline void putOAEPParams(CK_RSA_PKCS_OAEP_PARAMS_PTR params, CK_VOID_PTR pSourceData, CK_ULONG ulSourceDataLen)
|
|
|
|
{
|
|
|
|
params->pSourceData = pSourceData;
|
|
|
|
params->ulSourceDataLen = ulSourceDataLen;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void putECDH1SharedParams(CK_ECDH1_DERIVE_PARAMS_PTR params, CK_VOID_PTR pSharedData, CK_ULONG ulSharedDataLen)
|
|
|
|
{
|
|
|
|
params->pSharedData = pSharedData;
|
|
|
|
params->ulSharedDataLen = ulSharedDataLen;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void putECDH1PublicParams(CK_ECDH1_DERIVE_PARAMS_PTR params, CK_VOID_PTR pPublicData, CK_ULONG ulPublicDataLen)
|
|
|
|
{
|
|
|
|
params->pPublicData = pPublicData;
|
|
|
|
params->ulPublicDataLen = ulPublicDataLen;
|
|
|
|
}
|
2018-07-25 08:16:41 -04:00
|
|
|
*/
|
|
|
|
import "C"
|
|
|
|
import "unsafe"
|
|
|
|
|
|
|
|
// GCMParams represents the parameters for the AES-GCM mechanism.
|
|
|
|
type GCMParams struct {
|
|
|
|
arena
|
|
|
|
params *C.CK_GCM_PARAMS
|
|
|
|
iv []byte
|
|
|
|
aad []byte
|
|
|
|
tagSize int
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:45:19 -05:00
|
|
|
// NewGCMParams returns a pointer to AES-GCM parameters that can be used with the CKM_AES_GCM mechanism.
|
|
|
|
// The Free() method must be called after the operation is complete.
|
2018-07-25 08:16:41 -04:00
|
|
|
//
|
|
|
|
// *NOTE*
|
|
|
|
// Some HSMs, like CloudHSM, will ignore the IV you pass in and write their
|
|
|
|
// own. As a result, to support all libraries, memory is not freed
|
|
|
|
// automatically, so that after the EncryptInit/Encrypt operation the HSM's IV
|
|
|
|
// can be read back out. It is up to the caller to ensure that Free() is called
|
|
|
|
// on the GCMParams object at an appropriate time, which is after
|
|
|
|
// Encrypt/Decrypt. As an example:
|
|
|
|
//
|
|
|
|
// gcmParams := pkcs11.NewGCMParams(make([]byte, 12), nil, 128)
|
|
|
|
// p.ctx.EncryptInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_AES_GCM, gcmParams)}, aesObjHandle)
|
|
|
|
// ct, _ := p.ctx.Encrypt(session, pt)
|
|
|
|
// iv := gcmParams.IV()
|
|
|
|
// gcmParams.Free()
|
|
|
|
func NewGCMParams(iv, aad []byte, tagSize int) *GCMParams {
|
|
|
|
return &GCMParams{
|
|
|
|
iv: iv,
|
|
|
|
aad: aad,
|
|
|
|
tagSize: tagSize,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func cGCMParams(p *GCMParams) []byte {
|
|
|
|
params := C.CK_GCM_PARAMS{
|
|
|
|
ulTagBits: C.CK_ULONG(p.tagSize),
|
|
|
|
}
|
|
|
|
var arena arena
|
|
|
|
if len(p.iv) > 0 {
|
|
|
|
iv, ivLen := arena.Allocate(p.iv)
|
|
|
|
params.pIv = C.CK_BYTE_PTR(iv)
|
|
|
|
params.ulIvLen = ivLen
|
2019-02-26 06:45:19 -05:00
|
|
|
params.ulIvBits = ivLen * 8
|
2018-07-25 08:16:41 -04:00
|
|
|
}
|
|
|
|
if len(p.aad) > 0 {
|
|
|
|
aad, aadLen := arena.Allocate(p.aad)
|
|
|
|
params.pAAD = C.CK_BYTE_PTR(aad)
|
|
|
|
params.ulAADLen = aadLen
|
|
|
|
}
|
2019-02-26 06:45:19 -05:00
|
|
|
p.Free()
|
2018-07-25 08:16:41 -04:00
|
|
|
p.arena = arena
|
|
|
|
p.params = ¶ms
|
|
|
|
return C.GoBytes(unsafe.Pointer(¶ms), C.int(unsafe.Sizeof(params)))
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:45:19 -05:00
|
|
|
// IV returns a copy of the actual IV used for the operation.
|
|
|
|
//
|
|
|
|
// Some HSMs may ignore the user-specified IV and write their own at the end of
|
|
|
|
// the encryption operation; this method allows you to retrieve it.
|
2018-07-25 08:16:41 -04:00
|
|
|
func (p *GCMParams) IV() []byte {
|
|
|
|
if p == nil || p.params == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
newIv := C.GoBytes(unsafe.Pointer(p.params.pIv), C.int(p.params.ulIvLen))
|
|
|
|
iv := make([]byte, len(newIv))
|
|
|
|
copy(iv, newIv)
|
|
|
|
return iv
|
|
|
|
}
|
|
|
|
|
2019-02-26 06:45:19 -05:00
|
|
|
// Free deallocates the memory reserved for the HSM to write back the actual IV.
|
|
|
|
//
|
|
|
|
// This must be called after the entire operation is complete, i.e. after
|
|
|
|
// Encrypt or EncryptFinal. It is safe to call Free multiple times.
|
2018-07-25 08:16:41 -04:00
|
|
|
func (p *GCMParams) Free() {
|
|
|
|
if p == nil || p.arena == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
p.arena.Free()
|
|
|
|
p.params = nil
|
|
|
|
p.arena = nil
|
|
|
|
}
|
2019-02-26 06:45:19 -05:00
|
|
|
|
|
|
|
// NewPSSParams creates a CK_RSA_PKCS_PSS_PARAMS structure and returns it as a byte array for use with the CKM_RSA_PKCS_PSS mechanism
|
|
|
|
func NewPSSParams(hashAlg, mgf, saltLength uint) []byte {
|
|
|
|
p := C.CK_RSA_PKCS_PSS_PARAMS{
|
|
|
|
hashAlg: C.CK_MECHANISM_TYPE(hashAlg),
|
|
|
|
mgf: C.CK_RSA_PKCS_MGF_TYPE(mgf),
|
|
|
|
sLen: C.CK_ULONG(saltLength),
|
|
|
|
}
|
|
|
|
return C.GoBytes(unsafe.Pointer(&p), C.int(unsafe.Sizeof(p)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// OAEPParams can be passed to NewMechanism to implement CKM_RSA_PKCS_OAEP
|
|
|
|
type OAEPParams struct {
|
|
|
|
HashAlg uint
|
|
|
|
MGF uint
|
|
|
|
SourceType uint
|
|
|
|
SourceData []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewOAEPParams creates a CK_RSA_PKCS_OAEP_PARAMS structure suitable for use with the CKM_RSA_PKCS_OAEP mechanism
|
|
|
|
func NewOAEPParams(hashAlg, mgf, sourceType uint, sourceData []byte) *OAEPParams {
|
|
|
|
return &OAEPParams{
|
|
|
|
HashAlg: hashAlg,
|
|
|
|
MGF: mgf,
|
|
|
|
SourceType: sourceType,
|
|
|
|
SourceData: sourceData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func cOAEPParams(p *OAEPParams, arena arena) ([]byte, arena) {
|
|
|
|
params := C.CK_RSA_PKCS_OAEP_PARAMS{
|
|
|
|
hashAlg: C.CK_MECHANISM_TYPE(p.HashAlg),
|
|
|
|
mgf: C.CK_RSA_PKCS_MGF_TYPE(p.MGF),
|
|
|
|
source: C.CK_RSA_PKCS_OAEP_SOURCE_TYPE(p.SourceType),
|
|
|
|
}
|
|
|
|
if len(p.SourceData) != 0 {
|
|
|
|
buf, len := arena.Allocate(p.SourceData)
|
|
|
|
// field is unaligned on windows so this has to call into C
|
|
|
|
C.putOAEPParams(¶ms, buf, len)
|
|
|
|
}
|
|
|
|
return C.GoBytes(unsafe.Pointer(¶ms), C.int(unsafe.Sizeof(params))), arena
|
|
|
|
}
|
|
|
|
|
|
|
|
// ECDH1DeriveParams can be passed to NewMechanism to implement CK_ECDH1_DERIVE_PARAMS
|
|
|
|
type ECDH1DeriveParams struct {
|
|
|
|
KDF uint
|
|
|
|
SharedData []byte
|
|
|
|
PublicKeyData []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewECDH1DeriveParams creates a CK_ECDH1_DERIVE_PARAMS structure suitable for use with the CKM_ECDH1_DERIVE mechanism
|
|
|
|
func NewECDH1DeriveParams(kdf uint, sharedData []byte, publicKeyData []byte) *ECDH1DeriveParams {
|
|
|
|
return &ECDH1DeriveParams{
|
|
|
|
KDF: kdf,
|
|
|
|
SharedData: sharedData,
|
|
|
|
PublicKeyData: publicKeyData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func cECDH1DeriveParams(p *ECDH1DeriveParams, arena arena) ([]byte, arena) {
|
|
|
|
params := C.CK_ECDH1_DERIVE_PARAMS{
|
|
|
|
kdf: C.CK_EC_KDF_TYPE(p.KDF),
|
|
|
|
}
|
|
|
|
|
|
|
|
// SharedData MUST be null if key derivation function (KDF) is CKD_NULL
|
|
|
|
if len(p.SharedData) != 0 {
|
|
|
|
sharedData, sharedDataLen := arena.Allocate(p.SharedData)
|
|
|
|
C.putECDH1SharedParams(¶ms, sharedData, sharedDataLen)
|
|
|
|
}
|
|
|
|
|
|
|
|
publicKeyData, publicKeyDataLen := arena.Allocate(p.PublicKeyData)
|
|
|
|
C.putECDH1PublicParams(¶ms, publicKeyData, publicKeyDataLen)
|
|
|
|
|
|
|
|
return C.GoBytes(unsafe.Pointer(¶ms), C.int(unsafe.Sizeof(params))), arena
|
|
|
|
}
|