forked from miekg/pkcs11
-
Notifications
You must be signed in to change notification settings - Fork 0
/
params.go
143 lines (131 loc) · 4.24 KB
/
params.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// 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"
static inline void putOAEPParams(CK_RSA_PKCS_OAEP_PARAMS_PTR params, CK_VOID_PTR pSourceData, CK_ULONG ulSourceDataLen)
{
params->pSourceData = pSourceData;
params->ulSourceDataLen = ulSourceDataLen;
}
*/
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
}
// 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.
//
// *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
params.ulIvBits = ivLen * 8
}
if len(p.aad) > 0 {
aad, aadLen := arena.Allocate(p.aad)
params.pAAD = C.CK_BYTE_PTR(aad)
params.ulAADLen = aadLen
}
p.Free()
p.arena = arena
p.params = ¶ms
return C.GoBytes(unsafe.Pointer(¶ms), C.int(unsafe.Sizeof(params)))
}
// 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.
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
}
// 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.
func (p *GCMParams) Free() {
if p == nil || p.arena == nil {
return
}
p.arena.Free()
p.params = nil
p.arena = nil
}
// 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
}