1
2
3
4
5 package pkcs11
6
7
27 import "C"
28
29 import (
30 "fmt"
31 "time"
32 "unsafe"
33 )
34
35 type arena []unsafe.Pointer
36
37 func (a *arena) Allocate(obj []byte) (C.CK_VOID_PTR, C.CK_ULONG) {
38 cobj := C.calloc(C.size_t(len(obj)), 1)
39 *a = append(*a, cobj)
40 C.memmove(cobj, unsafe.Pointer(&obj[0]), C.size_t(len(obj)))
41 return C.CK_VOID_PTR(cobj), C.CK_ULONG(len(obj))
42 }
43
44 func (a arena) Free() {
45 for _, p := range a {
46 C.free(p)
47 }
48 }
49
50
51 func toList(clist C.CK_ULONG_PTR, size C.CK_ULONG) []uint {
52 l := make([]uint, int(size))
53 for i := 0; i < len(l); i++ {
54 l[i] = uint(C.Index(clist, C.CK_ULONG(i)))
55 }
56 defer C.free(unsafe.Pointer(clist))
57 return l
58 }
59
60
61 func cBBool(x bool) C.CK_BBOOL {
62 if x {
63 return C.CK_BBOOL(C.CK_TRUE)
64 }
65 return C.CK_BBOOL(C.CK_FALSE)
66 }
67
68 func uintToBytes(x uint64) []byte {
69 ul := C.CK_ULONG(x)
70 return C.GoBytes(unsafe.Pointer(&ul), C.int(unsafe.Sizeof(ul)))
71 }
72
73
74 type Error uint
75
76 func (e Error) Error() string {
77 return fmt.Sprintf("pkcs11: 0x%X: %s", uint(e), strerror[uint(e)])
78 }
79
80 func toError(e C.CK_RV) error {
81 if e == C.CKR_OK {
82 return nil
83 }
84 return Error(e)
85 }
86
87
88 type SessionHandle uint
89
90
91 type ObjectHandle uint
92
93
94 type Version struct {
95 Major byte
96 Minor byte
97 }
98
99 func toVersion(version C.CK_VERSION) Version {
100 return Version{byte(version.major), byte(version.minor)}
101 }
102
103
104
105 type SlotEvent struct {
106 SlotID uint
107 }
108
109
110 type Info struct {
111 CryptokiVersion Version
112 ManufacturerID string
113 Flags uint
114 LibraryDescription string
115 LibraryVersion Version
116 }
117
118
119 type SlotInfo struct {
120 SlotDescription string
121 ManufacturerID string
122 Flags uint
123 HardwareVersion Version
124 FirmwareVersion Version
125 }
126
127
128 type TokenInfo struct {
129 Label string
130 ManufacturerID string
131 Model string
132 SerialNumber string
133 Flags uint
134 MaxSessionCount uint
135 SessionCount uint
136 MaxRwSessionCount uint
137 RwSessionCount uint
138 MaxPinLen uint
139 MinPinLen uint
140 TotalPublicMemory uint
141 FreePublicMemory uint
142 TotalPrivateMemory uint
143 FreePrivateMemory uint
144 HardwareVersion Version
145 FirmwareVersion Version
146 UTCTime string
147 }
148
149
150 type SessionInfo struct {
151 SlotID uint
152 State uint
153 Flags uint
154 DeviceError uint
155 }
156
157
158 type Attribute struct {
159 Type uint
160 Value []byte
161 }
162
163
164
165
166
167 func NewAttribute(typ uint, x interface{}) *Attribute {
168
169
170
171 a := new(Attribute)
172 a.Type = typ
173 if x == nil {
174 return a
175 }
176 switch v := x.(type) {
177 case bool:
178 if v {
179 a.Value = []byte{1}
180 } else {
181 a.Value = []byte{0}
182 }
183 case int:
184 a.Value = uintToBytes(uint64(v))
185 case int16:
186 a.Value = uintToBytes(uint64(v))
187 case int32:
188 a.Value = uintToBytes(uint64(v))
189 case int64:
190 a.Value = uintToBytes(uint64(v))
191 case uint:
192 a.Value = uintToBytes(uint64(v))
193 case uint16:
194 a.Value = uintToBytes(uint64(v))
195 case uint32:
196 a.Value = uintToBytes(uint64(v))
197 case uint64:
198 a.Value = uintToBytes(uint64(v))
199 case string:
200 a.Value = []byte(v)
201 case []byte:
202 a.Value = v
203 case time.Time:
204 a.Value = cDate(v)
205 default:
206 panic("pkcs11: unhandled attribute type")
207 }
208 return a
209 }
210
211
212 func cAttributeList(a []*Attribute) (arena, C.CK_ATTRIBUTE_PTR, C.CK_ULONG) {
213 var arena arena
214 if len(a) == 0 {
215 return nil, nil, 0
216 }
217 pa := make([]C.CK_ATTRIBUTE, len(a))
218 for i, attr := range a {
219 pa[i]._type = C.CK_ATTRIBUTE_TYPE(attr.Type)
220 if len(attr.Value) != 0 {
221 buf, len := arena.Allocate(attr.Value)
222
223 C.putAttributePval(&pa[i], buf)
224 pa[i].ulValueLen = len
225 }
226 }
227 return arena, &pa[0], C.CK_ULONG(len(a))
228 }
229
230 func cDate(t time.Time) []byte {
231 b := make([]byte, 8)
232 year, month, day := t.Date()
233 y := fmt.Sprintf("%4d", year)
234 m := fmt.Sprintf("%02d", month)
235 d1 := fmt.Sprintf("%02d", day)
236 b[0], b[1], b[2], b[3] = y[0], y[1], y[2], y[3]
237 b[4], b[5] = m[0], m[1]
238 b[6], b[7] = d1[0], d1[1]
239 return b
240 }
241
242
243 type Mechanism struct {
244 Mechanism uint
245 Parameter []byte
246 generator interface{}
247 }
248
249
250 func NewMechanism(mech uint, x interface{}) *Mechanism {
251 m := new(Mechanism)
252 m.Mechanism = mech
253 if x == nil {
254 return m
255 }
256
257 switch p := x.(type) {
258 case *GCMParams, *OAEPParams, *ECDH1DeriveParams:
259
260 m.generator = p
261 case []byte:
262 m.Parameter = p
263 default:
264 panic("parameter must be one of type: []byte, *GCMParams, *OAEPParams, *ECDH1DeriveParams")
265 }
266
267 return m
268 }
269
270 func cMechanism(mechList []*Mechanism) (arena, *C.CK_MECHANISM) {
271 if len(mechList) != 1 {
272 panic("expected exactly one mechanism")
273 }
274 mech := mechList[0]
275 cmech := &C.CK_MECHANISM{mechanism: C.CK_MECHANISM_TYPE(mech.Mechanism)}
276
277 param := mech.Parameter
278 var arena arena
279 switch p := mech.generator.(type) {
280 case *GCMParams:
281
282 param = cGCMParams(p)
283 case *OAEPParams:
284 param, arena = cOAEPParams(p, arena)
285 case *ECDH1DeriveParams:
286 param, arena = cECDH1DeriveParams(p, arena)
287 }
288 if len(param) != 0 {
289 buf, len := arena.Allocate(param)
290
291 C.putMechanismParam(cmech, buf)
292 cmech.ulParameterLen = len
293 }
294 return arena, cmech
295 }
296
297
298 type MechanismInfo struct {
299 MinKeySize uint
300 MaxKeySize uint
301 Flags uint
302 }
303
304
305 var stubData = []byte{0}
306
307
308 func cMessage(data []byte) (dataPtr C.CK_BYTE_PTR) {
309 l := len(data)
310 if l == 0 {
311
312 data = stubData
313 }
314 return C.CK_BYTE_PTR(unsafe.Pointer(&data[0]))
315 }
316
View as plain text