1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package crypto11
23
24 import (
25 "errors"
26 "hash"
27
28 "github.com/miekg/pkcs11"
29 )
30
31 const (
32
33 NFCK_VENDOR_NCIPHER = 0xde436972
34
35
36 CKM_NCIPHER = (pkcs11.CKM_VENDOR_DEFINED | NFCK_VENDOR_NCIPHER)
37
38
39 CKM_NC_MD5_HMAC_KEY_GEN = (CKM_NCIPHER + 0x6)
40
41
42 CKM_NC_SHA_1_HMAC_KEY_GEN = (CKM_NCIPHER + 0x3)
43
44
45 CKM_NC_SHA224_HMAC_KEY_GEN = (CKM_NCIPHER + 0x24)
46
47
48 CKM_NC_SHA256_HMAC_KEY_GEN = (CKM_NCIPHER + 0x25)
49
50
51 CKM_NC_SHA384_HMAC_KEY_GEN = (CKM_NCIPHER + 0x26)
52
53
54 CKM_NC_SHA512_HMAC_KEY_GEN = (CKM_NCIPHER + 0x27)
55 )
56
57 type hmacImplementation struct {
58
59 session *pkcs11Session
60
61
62 key *SecretKey
63
64
65 size int
66
67
68 blockSize int
69
70
71 mechDescription []*pkcs11.Mechanism
72
73
74 cleanup func()
75
76
77 updates uint64
78
79
80 result []byte
81 }
82
83 type hmacInfo struct {
84 size int
85 blockSize int
86 general bool
87 }
88
89 var hmacInfos = map[int]*hmacInfo{
90 pkcs11.CKM_MD5_HMAC: {20, 64, false},
91 pkcs11.CKM_MD5_HMAC_GENERAL: {20, 64, true},
92 pkcs11.CKM_SHA_1_HMAC: {20, 64, false},
93 pkcs11.CKM_SHA_1_HMAC_GENERAL: {20, 64, true},
94 pkcs11.CKM_SHA224_HMAC: {28, 64, false},
95 pkcs11.CKM_SHA224_HMAC_GENERAL: {28, 64, true},
96 pkcs11.CKM_SHA256_HMAC: {32, 64, false},
97 pkcs11.CKM_SHA256_HMAC_GENERAL: {32, 64, true},
98 pkcs11.CKM_SHA384_HMAC: {48, 64, false},
99 pkcs11.CKM_SHA384_HMAC_GENERAL: {48, 64, true},
100 pkcs11.CKM_SHA512_HMAC: {64, 128, false},
101 pkcs11.CKM_SHA512_HMAC_GENERAL: {64, 128, true},
102 pkcs11.CKM_SHA512_224_HMAC: {28, 128, false},
103 pkcs11.CKM_SHA512_224_HMAC_GENERAL: {28, 128, true},
104 pkcs11.CKM_SHA512_256_HMAC: {32, 128, false},
105 pkcs11.CKM_SHA512_256_HMAC_GENERAL: {32, 128, true},
106 pkcs11.CKM_RIPEMD160_HMAC: {20, 64, false},
107 pkcs11.CKM_RIPEMD160_HMAC_GENERAL: {20, 64, true},
108 }
109
110
111 var errHmacClosed = errors.New("already called Sum()")
112
113
114
115
116
117
118
119
120
121
122
123 func (key *SecretKey) NewHMAC(mech int, length int) (hash.Hash, error) {
124 hi := hmacImplementation{
125 key: key,
126 }
127 var params []byte
128 if info, ok := hmacInfos[mech]; ok {
129 hi.blockSize = info.blockSize
130 if info.general {
131 hi.size = length
132 params = ulongToBytes(uint(length))
133 } else {
134 hi.size = info.size
135 }
136 } else {
137 hi.size = length
138 }
139 hi.mechDescription = []*pkcs11.Mechanism{pkcs11.NewMechanism(uint(mech), params)}
140 if err := hi.initialize(); err != nil {
141 return nil, err
142 }
143 return &hi, nil
144 }
145
146 func (hi *hmacImplementation) initialize() (err error) {
147 session, err := hi.key.context.getSession()
148 if err != nil {
149 return err
150 }
151
152 hi.session = session
153 hi.cleanup = func() {
154 hi.key.context.pool.Put(session)
155 hi.session = nil
156 }
157 if err = hi.session.ctx.SignInit(hi.session.handle, hi.mechDescription, hi.key.handle); err != nil {
158 hi.cleanup()
159 return
160 }
161 hi.updates = 0
162 hi.result = nil
163 return
164 }
165
166 func (hi *hmacImplementation) Write(p []byte) (n int, err error) {
167 if hi.result != nil {
168 if len(p) > 0 {
169 err = errHmacClosed
170 }
171 return
172 }
173 if err = hi.session.ctx.SignUpdate(hi.session.handle, p); err != nil {
174 return
175 }
176 hi.updates++
177 n = len(p)
178 return
179 }
180
181 func (hi *hmacImplementation) Sum(b []byte) []byte {
182 if hi.result == nil {
183 var err error
184 if hi.updates == 0 {
185
186
187 if err = hi.session.ctx.SignUpdate(hi.session.handle, []byte{}); err != nil {
188 panic(err)
189 }
190 }
191 hi.result, err = hi.session.ctx.SignFinal(hi.session.handle)
192 hi.cleanup()
193 if err != nil {
194 panic(err)
195 }
196 }
197 return append(b, hi.result...)
198 }
199
200 func (hi *hmacImplementation) Reset() {
201 hi.Sum(nil)
202
203
204
205
206 _ = hi.initialize()
207 }
208
209 func (hi *hmacImplementation) Size() int {
210 return hi.size
211 }
212
213 func (hi *hmacImplementation) BlockSize() int {
214 return hi.blockSize
215 }
216
View as plain text