-
Notifications
You must be signed in to change notification settings - Fork 9
/
error_correction.go
135 lines (107 loc) · 3.25 KB
/
error_correction.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// error_correction.go - NewHope key exchange error correction.
//
// To the extent possible under law, Yawning Angel has waived all copyright
// and related or neighboring rights to newhope, using the Creative
// Commons "CC0" public domain dedication. See LICENSE or
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
package newhope
import "gitlab.com/yawning/chacha20.git"
func abs(v int32) int32 {
mask := v >> 31
return (v ^ mask) - mask
}
func f(v0, v1 *int32, x int32) int32 {
// The`ref` code uses uint32 for x, but none of the values ever get large
// enough for that, and that would be cast-tastic due to Go being Go.
// Next 6 lines compute t = x/PARAM_Q
b := x * 2730
t := b >> 25
b = x - t*paramQ
b = (paramQ - 1) - b
b >>= 31
t -= b
r := t & 1
xit := t >> 1
*v0 = xit + r // v0 = round(x/(2*PARAM_Q))
t--
r = t & 1
*v1 = (t >> 1) + r
return abs(x - ((*v0) * 2 * paramQ))
}
func g(x int32) int32 {
// Next 6 lines compute t = x/(4 *PARAMQ)
b := x * 2730
t := b >> 27
b = x - t*(paramQ*4)
b = (paramQ * 4) - b
b >>= 31
t -= b
c := t & 1
t = (t >> 1) + c // t = round(x/(8*PARAM_Q))
t *= 8 * paramQ
return abs(t - x)
}
func llDecode(xi0, xi1, xi2, xi3 int32) int16 {
t := g(xi0)
t += g(xi1)
t += g(xi2)
t += g(xi3)
t -= 8 * paramQ
t >>= 31
return int16(t & 1)
}
func (c *poly) helpRec(v *poly, seed *[SeedBytes]byte, nonce byte) {
var v0, v1, vTmp [4]int32
var k int32
var rand [32]byte
var n [8]byte
n[7] = nonce
stream, err := chacha20.New(seed[:], n[:])
if err != nil {
panic(err)
}
stream.KeyStream(rand[:])
stream.Reset()
defer memwipe(rand[:])
for i := uint(0); i < 256; i++ {
rBit := int32((rand[i>>3] >> (i & 7)) & 1)
vTmp[0], vTmp[1], vTmp[2], vTmp[3] = int32(v.coeffs[i]), int32(v.coeffs[256+i]), int32(v.coeffs[512+i]), int32(v.coeffs[768+i])
// newhope-20151209 - New version of the reconciliation.
k = f(&v0[0], &v1[0], 8*vTmp[0]+4*rBit)
k += f(&v0[1], &v1[1], 8*vTmp[1]+4*rBit)
k += f(&v0[2], &v1[2], 8*vTmp[2]+4*rBit)
k += f(&v0[3], &v1[3], 8*vTmp[3]+4*rBit)
k = (2*paramQ - 1 - k) >> 31
vTmp[0] = ((^k) & v0[0]) ^ (k & v1[0])
vTmp[1] = ((^k) & v0[1]) ^ (k & v1[1])
vTmp[2] = ((^k) & v0[2]) ^ (k & v1[2])
vTmp[3] = ((^k) & v0[3]) ^ (k & v1[3])
c.coeffs[0+i] = uint16((vTmp[0] - vTmp[3]) & 3)
c.coeffs[256+i] = uint16((vTmp[1] - vTmp[3]) & 3)
c.coeffs[512+i] = uint16((vTmp[2] - vTmp[3]) & 3)
c.coeffs[768+i] = uint16((-k + 2*vTmp[3]) & 3)
}
for i := range vTmp {
vTmp[i] = 0
}
}
func rec(key *[32]byte, v, c *poly) {
var tmp, vTmp, cTmp [4]int32
for i := range key {
key[i] = 0
}
for i := uint(0); i < 256; i++ {
vTmp[0], vTmp[1], vTmp[2], vTmp[3] = int32(v.coeffs[i]), int32(v.coeffs[256+i]), int32(v.coeffs[512+i]), int32(v.coeffs[768+i])
cTmp[0], cTmp[1], cTmp[2], cTmp[3] = int32(c.coeffs[i]), int32(c.coeffs[256+i]), int32(c.coeffs[512+i]), int32(c.coeffs[768+i])
tmp[0] = 16*paramQ + 8*vTmp[0] - paramQ*(2*cTmp[0]+cTmp[3])
tmp[1] = 16*paramQ + 8*vTmp[1] - paramQ*(2*cTmp[1]+cTmp[3])
tmp[2] = 16*paramQ + 8*vTmp[2] - paramQ*(2*cTmp[2]+cTmp[3])
tmp[3] = 16*paramQ + 8*vTmp[3] - paramQ*(cTmp[3])
key[i>>3] |= byte(llDecode(tmp[0], tmp[1], tmp[2], tmp[3]) << (i & 7))
}
for i := 0; i < 4; i++ {
tmp[i] = 0
vTmp[i] = 0
cTmp[i] = 0
}
}