-
Notifications
You must be signed in to change notification settings - Fork 1
/
attribute.go
114 lines (101 loc) · 3.23 KB
/
attribute.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
package main
/*
#include <stdlib.h>
#include <string.h>
#include "pkcs11go.h"
*/
import "C"
import (
"bytes"
"unsafe"
)
// An attribute related to a crypto object.
type Attribute struct {
Type uint32 // Type of attribute
Value []byte // Value of attribute
}
// A map of attributes
type Attributes map[uint32]*Attribute
// CToAttributes transform a C pointer of attributes into a Golang Attributes structure.
func CToAttributes(pAttributes C.CK_ATTRIBUTE_PTR, ulCount C.CK_ULONG) (Attributes, error) {
if ulCount <= 0 {
return nil, NewError("CToAttributes", "cannot transform: ulcount is not greater than 0", C.CKR_BUFFER_TOO_SMALL)
}
cAttrSlice := (*[1 << 30]C.CK_ATTRIBUTE)(unsafe.Pointer(pAttributes))[:ulCount:ulCount]
attributes := make(Attributes, ulCount)
for _, cAttr := range cAttrSlice {
attr := CToAttribute(cAttr)
attributes[attr.Type] = attr
}
return attributes, nil
}
// Equals returns true if the maps of attributes are equal.
func (attributes Attributes) Equals(attributes2 Attributes) bool {
if len(attributes) != len(attributes2) {
return false
}
for attrType, attribute := range attributes {
attribute2, ok := attributes2[attrType]
if !ok {
return false
}
if !attribute.Equals(attribute2) {
return false
}
}
return true
}
// SetIfUndefined adds an attribute only if it doesn't exist
func (attributes Attributes) SetIfUndefined(attrs ...*Attribute) {
for _, attr := range attrs {
if _, ok := attributes[attr.Type]; !ok {
attributes[attr.Type] = attr
}
}
}
// Set adds an attribute or modifies it if it already exists
func (attributes Attributes) Set(attrs ...*Attribute) {
for _, attr := range attrs {
attributes[attr.Type] = attr
}
}
// CToAttribute transforms a single C attribute struct into an Attribute Golang struct.
func CToAttribute(cAttr C.CK_ATTRIBUTE) *Attribute {
attrType := cAttr._type
attrVal := C.GoBytes(unsafe.Pointer(cAttr.pValue), C.int(cAttr.ulValueLen))
return &Attribute{
Type: uint32(attrType),
Value: attrVal,
}
}
// ToC copies an attribute into a C pointer of attribute struct.
func (attribute *Attribute) ToC(cDst C.CK_ATTRIBUTE_PTR) error {
if cDst.pValue == nil {
cDst.ulValueLen = C.CK_ULONG(len(attribute.Value))
return nil
}
if cDst.ulValueLen >= C.CK_ULONG(len(attribute.Value)) {
cValue := C.CBytes(attribute.Value)
cValueLen := C.CK_ULONG(len(attribute.Value))
cDst._type = C.CK_ATTRIBUTE_TYPE(attribute.Type)
cDst.ulValueLen = cValueLen
C.memcpy(unsafe.Pointer(cDst.pValue), unsafe.Pointer(cValue), cValueLen)
C.free(unsafe.Pointer(cValue))
} else {
return NewError("Attribute.ToC", "Buffer too small", C.CKR_BUFFER_TOO_SMALL)
}
return nil
}
// Equals returns true if the attributes are equal.
func (attribute *Attribute) Equals(attribute2 *Attribute) bool {
return attribute.Type == attribute2.Type &&
bytes.Compare(attribute.Value, attribute2.Value) == 0
}
// GetAttributeByType returns an attribute of the attributes list with the type specified in the arguments.
func (attributes Attributes) GetAttributeByType(cAttr C.CK_ATTRIBUTE_TYPE) (*Attribute, error) {
attr, ok := attributes[uint32(cAttr)]
if ok {
return attr, nil
}
return nil, NewError("Attributes.GetAttributeByType", "attribute doesn't exist", C.CKR_ATTRIBUTE_VALUE_INVALID)
}