1
2
3
4
5
6
7 package boring
8
9
10 import "C"
11 import (
12 "bytes"
13 "crypto"
14 "hash"
15 "runtime"
16 "unsafe"
17 )
18
19
20
21 func hashToMD(h hash.Hash) *C.GO_EVP_MD {
22 switch h.(type) {
23 case *sha1Hash:
24 return C._goboringcrypto_EVP_sha1()
25 case *sha224Hash:
26 return C._goboringcrypto_EVP_sha224()
27 case *sha256Hash:
28 return C._goboringcrypto_EVP_sha256()
29 case *sha384Hash:
30 return C._goboringcrypto_EVP_sha384()
31 case *sha512Hash:
32 return C._goboringcrypto_EVP_sha512()
33 }
34 return nil
35 }
36
37
38
39 func cryptoHashToMD(ch crypto.Hash) *C.GO_EVP_MD {
40 switch ch {
41 case crypto.MD5:
42 return C._goboringcrypto_EVP_md5()
43 case crypto.MD5SHA1:
44 return C._goboringcrypto_EVP_md5_sha1()
45 case crypto.SHA1:
46 return C._goboringcrypto_EVP_sha1()
47 case crypto.SHA224:
48 return C._goboringcrypto_EVP_sha224()
49 case crypto.SHA256:
50 return C._goboringcrypto_EVP_sha256()
51 case crypto.SHA384:
52 return C._goboringcrypto_EVP_sha384()
53 case crypto.SHA512:
54 return C._goboringcrypto_EVP_sha512()
55 }
56 return nil
57 }
58
59
60
61
62
63 func NewHMAC(h func() hash.Hash, key []byte) hash.Hash {
64 ch := h()
65 md := hashToMD(ch)
66 if md == nil {
67 return nil
68 }
69
70
71 hkey := bytes.Clone(key)
72 hmac := &boringHMAC{
73 md: md,
74 size: ch.Size(),
75 blockSize: ch.BlockSize(),
76 key: hkey,
77 }
78 hmac.Reset()
79 return hmac
80 }
81
82 type boringHMAC struct {
83 md *C.GO_EVP_MD
84 ctx C.GO_HMAC_CTX
85 ctx2 C.GO_HMAC_CTX
86 size int
87 blockSize int
88 key []byte
89 sum []byte
90 needCleanup bool
91 }
92
93 func (h *boringHMAC) Reset() {
94 if h.needCleanup {
95 C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx)
96 } else {
97 h.needCleanup = true
98
99
100
101
102 runtime.SetFinalizer(h, (*boringHMAC).finalize)
103 }
104 C._goboringcrypto_HMAC_CTX_init(&h.ctx)
105
106 if C._goboringcrypto_HMAC_Init(&h.ctx, unsafe.Pointer(base(h.key)), C.int(len(h.key)), h.md) == 0 {
107 panic("boringcrypto: HMAC_Init failed")
108 }
109 if int(C._goboringcrypto_HMAC_size(&h.ctx)) != h.size {
110 println("boringcrypto: HMAC size:", C._goboringcrypto_HMAC_size(&h.ctx), "!=", h.size)
111 panic("boringcrypto: HMAC size mismatch")
112 }
113 runtime.KeepAlive(h)
114 h.sum = nil
115 }
116
117 func (h *boringHMAC) finalize() {
118 C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx)
119 }
120
121 func (h *boringHMAC) Write(p []byte) (int, error) {
122 if len(p) > 0 {
123 C._goboringcrypto_HMAC_Update(&h.ctx, (*C.uint8_t)(unsafe.Pointer(&p[0])), C.size_t(len(p)))
124 }
125 runtime.KeepAlive(h)
126 return len(p), nil
127 }
128
129 func (h *boringHMAC) Size() int {
130 return h.size
131 }
132
133 func (h *boringHMAC) BlockSize() int {
134 return h.blockSize
135 }
136
137 func (h *boringHMAC) Sum(in []byte) []byte {
138 if h.sum == nil {
139 size := h.Size()
140 h.sum = make([]byte, size)
141 }
142
143
144
145
146 C._goboringcrypto_HMAC_CTX_init(&h.ctx2)
147 if C._goboringcrypto_HMAC_CTX_copy_ex(&h.ctx2, &h.ctx) == 0 {
148 panic("boringcrypto: HMAC_CTX_copy_ex failed")
149 }
150 C._goboringcrypto_HMAC_Final(&h.ctx2, (*C.uint8_t)(unsafe.Pointer(&h.sum[0])), nil)
151 C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx2)
152 return append(in, h.sum...)
153 }
154
View as plain text