1 // Copyright 2012 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.
5 // +build !amd64,!arm gccgo appengine nacl
9 import "encoding/binary"
11 // Sum generates an authenticator for msg using a one-time key and puts the
12 // 16-byte result into out. Authenticating two different messages with the same
13 // key allows an attacker to forge messages at will.
14 func Sum(out
*[TagSize
]byte, msg
[]byte, key
*[32]byte) {
16 h0
, h1
, h2
, h3
, h4
uint32 // the hash accumulators
17 r0
, r1
, r2
, r3
, r4
uint64 // the r part of the key
20 r0
= uint64(binary
.LittleEndian
.Uint32(key
[0:]) & 0x3ffffff)
21 r1
= uint64((binary
.LittleEndian
.Uint32(key
[3:]) >> 2) & 0x3ffff03)
22 r2
= uint64((binary
.LittleEndian
.Uint32(key
[6:]) >> 4) & 0x3ffc0ff)
23 r3
= uint64((binary
.LittleEndian
.Uint32(key
[9:]) >> 6) & 0x3f03fff)
24 r4
= uint64((binary
.LittleEndian
.Uint32(key
[12:]) >> 8) & 0x00fffff)
26 R1
, R2
, R3
, R4
:= r1
*5, r2
*5, r3
*5, r4
*5
28 for len(msg
) >= TagSize
{
30 h0
+= binary
.LittleEndian
.Uint32(msg
[0:]) & 0x3ffffff
31 h1
+= (binary
.LittleEndian
.Uint32(msg
[3:]) >> 2) & 0x3ffffff
32 h2
+= (binary
.LittleEndian
.Uint32(msg
[6:]) >> 4) & 0x3ffffff
33 h3
+= (binary
.LittleEndian
.Uint32(msg
[9:]) >> 6) & 0x3ffffff
34 h4
+= (binary
.LittleEndian
.Uint32(msg
[12:]) >> 8) |
(1 << 24)
37 d0
:= (uint64(h0
) * r0
) + (uint64(h1
) * R4
) + (uint64(h2
) * R3
) + (uint64(h3
) * R2
) + (uint64(h4
) * R1
)
38 d1
:= (d0
>> 26) + (uint64(h0
) * r1
) + (uint64(h1
) * r0
) + (uint64(h2
) * R4
) + (uint64(h3
) * R3
) + (uint64(h4
) * R2
)
39 d2
:= (d1
>> 26) + (uint64(h0
) * r2
) + (uint64(h1
) * r1
) + (uint64(h2
) * r0
) + (uint64(h3
) * R4
) + (uint64(h4
) * R3
)
40 d3
:= (d2
>> 26) + (uint64(h0
) * r3
) + (uint64(h1
) * r2
) + (uint64(h2
) * r1
) + (uint64(h3
) * r0
) + (uint64(h4
) * R4
)
41 d4
:= (d3
>> 26) + (uint64(h0
) * r4
) + (uint64(h1
) * r3
) + (uint64(h2
) * r2
) + (uint64(h3
) * r1
) + (uint64(h4
) * r0
)
44 h0
= uint32(d0
) & 0x3ffffff
45 h1
= uint32(d1
) & 0x3ffffff
46 h2
= uint32(d2
) & 0x3ffffff
47 h3
= uint32(d3
) & 0x3ffffff
48 h4
= uint32(d4
) & 0x3ffffff
50 h0
+= uint32(d4
>>26) * 5
58 var block
[TagSize
]byte
59 off
:= copy(block
[:], msg
)
63 h0
+= binary
.LittleEndian
.Uint32(block
[0:]) & 0x3ffffff
64 h1
+= (binary
.LittleEndian
.Uint32(block
[3:]) >> 2) & 0x3ffffff
65 h2
+= (binary
.LittleEndian
.Uint32(block
[6:]) >> 4) & 0x3ffffff
66 h3
+= (binary
.LittleEndian
.Uint32(block
[9:]) >> 6) & 0x3ffffff
67 h4
+= (binary
.LittleEndian
.Uint32(block
[12:]) >> 8)
70 d0
:= (uint64(h0
) * r0
) + (uint64(h1
) * R4
) + (uint64(h2
) * R3
) + (uint64(h3
) * R2
) + (uint64(h4
) * R1
)
71 d1
:= (d0
>> 26) + (uint64(h0
) * r1
) + (uint64(h1
) * r0
) + (uint64(h2
) * R4
) + (uint64(h3
) * R3
) + (uint64(h4
) * R2
)
72 d2
:= (d1
>> 26) + (uint64(h0
) * r2
) + (uint64(h1
) * r1
) + (uint64(h2
) * r0
) + (uint64(h3
) * R4
) + (uint64(h4
) * R3
)
73 d3
:= (d2
>> 26) + (uint64(h0
) * r3
) + (uint64(h1
) * r2
) + (uint64(h2
) * r1
) + (uint64(h3
) * r0
) + (uint64(h4
) * R4
)
74 d4
:= (d3
>> 26) + (uint64(h0
) * r4
) + (uint64(h1
) * r3
) + (uint64(h2
) * r2
) + (uint64(h3
) * r1
) + (uint64(h4
) * r0
)
77 h0
= uint32(d0
) & 0x3ffffff
78 h1
= uint32(d1
) & 0x3ffffff
79 h2
= uint32(d2
) & 0x3ffffff
80 h3
= uint32(d3
) & 0x3ffffff
81 h4
= uint32(d4
) & 0x3ffffff
83 h0
+= uint32(d4
>>26) * 5
102 t1
:= h1
+ (t0
>> 26)
103 t2
:= h2
+ (t1
>> 26)
104 t3
:= h3
+ (t2
>> 26)
105 t4
:= h4
+ (t3
>> 26) - (1 << 26)
111 // select h if h < p else h - p
112 t_mask
:= (t4
>> 31) - 1
114 h0
= (h0
& h_mask
) |
(t0
& t_mask
)
115 h1
= (h1
& h_mask
) |
(t1
& t_mask
)
116 h2
= (h2
& h_mask
) |
(t2
& t_mask
)
117 h3
= (h3
& h_mask
) |
(t3
& t_mask
)
118 h4
= (h4
& h_mask
) |
(t4
& t_mask
)
122 h1
= ((h1
>> 6) |
(h2
<< 20))
123 h2
= ((h2
>> 12) |
(h3
<< 14))
124 h3
= ((h3
>> 18) |
(h4
<< 8))
126 // s: the s part of the key
127 // tag = (h + s) % (2^128)
128 t
:= uint64(h0
) + uint64(binary
.LittleEndian
.Uint32(key
[16:]))
130 t
= uint64(h1
) + uint64(binary
.LittleEndian
.Uint32(key
[20:])) + (t
>> 32)
132 t
= uint64(h2
) + uint64(binary
.LittleEndian
.Uint32(key
[24:])) + (t
>> 32)
134 t
= uint64(h3
) + uint64(binary
.LittleEndian
.Uint32(key
[28:])) + (t
>> 32)
137 binary
.LittleEndian
.PutUint32(out
[0:], h0
)
138 binary
.LittleEndian
.PutUint32(out
[4:], h1
)
139 binary
.LittleEndian
.PutUint32(out
[8:], h2
)
140 binary
.LittleEndian
.PutUint32(out
[12:], h3
)