1
2
3
4
5 package gcm
6
7 import (
8 "crypto/internal/fips140"
9 "crypto/internal/fips140/aes"
10 "crypto/internal/fips140/subtle"
11 )
12
13
14
15
16
17
18 type CMAC struct {
19 b aes.Block
20 k1 [aes.BlockSize]byte
21 k2 [aes.BlockSize]byte
22 }
23
24 func NewCMAC(b *aes.Block) *CMAC {
25 c := &CMAC{b: *b}
26 c.deriveSubkeys()
27 return c
28 }
29
30 func (c *CMAC) deriveSubkeys() {
31 aes.EncryptBlockInternal(&c.b, c.k1[:], c.k1[:])
32 msb := shiftLeft(&c.k1)
33 c.k1[len(c.k1)-1] ^= msb * 0b10000111
34
35 c.k2 = c.k1
36 msb = shiftLeft(&c.k2)
37 c.k2[len(c.k2)-1] ^= msb * 0b10000111
38 }
39
40 func (c *CMAC) MAC(m []byte) [aes.BlockSize]byte {
41 fips140.RecordApproved()
42 _ = c.b
43 var x [aes.BlockSize]byte
44 if len(m) == 0 {
45
46 x = c.k2
47 x[len(m)] ^= 0b10000000
48 aes.EncryptBlockInternal(&c.b, x[:], x[:])
49 return x
50 }
51 for len(m) >= aes.BlockSize {
52 subtle.XORBytes(x[:], m[:aes.BlockSize], x[:])
53 if len(m) == aes.BlockSize {
54
55 subtle.XORBytes(x[:], c.k1[:], x[:])
56 }
57 aes.EncryptBlockInternal(&c.b, x[:], x[:])
58 m = m[aes.BlockSize:]
59 }
60 if len(m) > 0 {
61
62 subtle.XORBytes(x[:], m, x[:])
63 subtle.XORBytes(x[:], c.k2[:], x[:])
64 x[len(m)] ^= 0b10000000
65 aes.EncryptBlockInternal(&c.b, x[:], x[:])
66 }
67 return x
68 }
69
70
71 func shiftLeft(x *[aes.BlockSize]byte) byte {
72 var msb byte
73 for i := len(x) - 1; i >= 0; i-- {
74 msb, x[i] = x[i]>>7, x[i]<<1|msb
75 }
76 return msb
77 }
78
View as plain text