1 // GoGOST -- Pure Go GOST cryptographic functions library
2 // Copyright (C) 2015-2021 Sergey Matveev <stargrave@stargrave.org>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, version 3 of the License.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 0, 1, 2, 3, 4, 5, 6, 7,
25 0, 1, 2, 3, 4, 5, 6, 7,
39 // Create MAC with given tag size and initial initialization vector.
40 // Size is in bytes and must be between 1 and 8. To be RFC conformant,
41 // iv must be the first block of the authenticated data, second and
42 // following ones are fed to Write function.
43 func (c *Cipher) NewMAC(size int, iv []byte) (*MAC, error) {
44 if size == 0 || size > 8 {
45 return nil, errors.New("gogost/gost28147: invalid tag size")
47 if len(iv) != BlockSize {
48 return nil, errors.New("gogost/gost28147: len(iv) != 8")
50 m := MAC{c: c, size: size, iv: iv}
51 n2, n1 := block2nvs(iv)
52 m.iv = make([]byte, BlockSize)
53 nvs2block(n1, n2, m.iv)
54 m.prev = make([]byte, BlockSize)
59 func (m *MAC) Reset() {
64 func (m *MAC) BlockSize() int {
68 func (m *MAC) Size() int {
72 func (m *MAC) Write(b []byte) (int, error) {
73 m.buf = append(m.buf, b...)
74 for len(m.buf) >= BlockSize {
75 for i := 0; i < BlockSize; i++ {
78 m.n1, m.n2 = block2nvs(m.prev)
79 m.n1, m.n2 = m.c.xcrypt(SeqMAC, m.n1, m.n2)
80 nvs2block(m.n2, m.n1, m.prev)
86 func (m *MAC) Sum(b []byte) []byte {
88 return append(b, m.prev[0:m.size]...)
92 for i = 0; i < BlockSize-len(m.buf); i++ {
93 buf = append(buf, byte(0))
95 for i = 0; i < BlockSize; i++ {
98 m.n1, m.n2 = block2nvs(buf)
99 m.n1, m.n2 = m.c.xcrypt(SeqMAC, m.n1, m.n2)
100 nvs2block(m.n2, m.n1, buf)
101 return append(b, buf[0:m.size]...)