cmac.mx raw
1 // Copyright 2024 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package gcm
6
7 import (
8 "crypto/internal/fips140"
9 "crypto/internal/fips140/aes"
10 "crypto/internal/fips140/subtle"
11 )
12
13 // CMAC implements the CMAC mode from NIST SP 800-38B.
14 //
15 // It is optimized for use in Counter KDF (SP 800-108r1) and XAES-256-GCM
16 // (https://c2sp.org/XAES-256-GCM), rather than for exposing it to applications
17 // as a stand-alone MAC.
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 // Hoist the nil check out of the loop.
43 var x [aes.BlockSize]byte
44 if len(m) == 0 {
45 // Special-cased as a single empty partial final block.
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 // Final complete block.
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 // Final incomplete block.
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 // shiftLeft sets x to x << 1, and returns MSB₁(x).
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