1
2
3
4
5 package nistec
6
7 import (
8 "crypto/elliptic/internal/fiat"
9 "crypto/subtle"
10 "errors"
11 )
12
13 var p224B, _ = new(fiat.P224Element).SetBytes([]byte{0xb4, 0x05, 0x0a, 0x85,
14 0x0c, 0x04, 0xb3, 0xab, 0xf5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7,
15 0xd7, 0xbf, 0xd8, 0xba, 0x27, 0x0b, 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4})
16
17 var p224G, _ = NewP224Point().SetBytes([]byte{0x04,
18 0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9,
19 0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6,
20 0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb,
21 0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64,
22 0x44, 0xd5, 0x81, 0x99, 0x85, 0x0, 0x7e, 0x34})
23
24 const p224ElementLength = 28
25
26
27 type P224Point struct {
28
29
30 x, y, z *fiat.P224Element
31 }
32
33
34 func NewP224Point() *P224Point {
35 return &P224Point{
36 x: new(fiat.P224Element),
37 y: new(fiat.P224Element).One(),
38 z: new(fiat.P224Element),
39 }
40 }
41
42
43 func NewP224Generator() *P224Point {
44 return (&P224Point{
45 x: new(fiat.P224Element),
46 y: new(fiat.P224Element),
47 z: new(fiat.P224Element),
48 }).Set(p224G)
49 }
50
51
52 func (p *P224Point) Set(q *P224Point) *P224Point {
53 p.x.Set(q.x)
54 p.y.Set(q.y)
55 p.z.Set(q.z)
56 return p
57 }
58
59
60
61
62
63 func (p *P224Point) SetBytes(b []byte) (*P224Point, error) {
64 switch {
65
66 case len(b) == 1 && b[0] == 0:
67 return p.Set(NewP224Point()), nil
68
69
70 case len(b) == 1+2*p224ElementLength && b[0] == 4:
71 x, err := new(fiat.P224Element).SetBytes(b[1 : 1+p224ElementLength])
72 if err != nil {
73 return nil, err
74 }
75 y, err := new(fiat.P224Element).SetBytes(b[1+p224ElementLength:])
76 if err != nil {
77 return nil, err
78 }
79 if err := p224CheckOnCurve(x, y); err != nil {
80 return nil, err
81 }
82 p.x.Set(x)
83 p.y.Set(y)
84 p.z.One()
85 return p, nil
86
87
88 case len(b) == 1+p224ElementLength && b[0] == 0:
89 return nil, errors.New("unimplemented")
90
91 default:
92 return nil, errors.New("invalid P224 point encoding")
93 }
94 }
95
96 func p224CheckOnCurve(x, y *fiat.P224Element) error {
97
98 x3 := new(fiat.P224Element).Square(x)
99 x3.Mul(x3, x)
100
101 threeX := new(fiat.P224Element).Add(x, x)
102 threeX.Add(threeX, x)
103
104 x3.Sub(x3, threeX)
105 x3.Add(x3, p224B)
106
107
108 y2 := new(fiat.P224Element).Square(y)
109
110 if x3.Equal(y2) != 1 {
111 return errors.New("P224 point not on curve")
112 }
113 return nil
114 }
115
116
117
118
119 func (p *P224Point) Bytes() []byte {
120
121
122 var out [133]byte
123 return p.bytes(&out)
124 }
125
126 func (p *P224Point) bytes(out *[133]byte) []byte {
127 if p.z.IsZero() == 1 {
128 return append(out[:0], 0)
129 }
130
131 zinv := new(fiat.P224Element).Invert(p.z)
132 xx := new(fiat.P224Element).Mul(p.x, zinv)
133 yy := new(fiat.P224Element).Mul(p.y, zinv)
134
135 buf := append(out[:0], 4)
136 buf = append(buf, xx.Bytes()...)
137 buf = append(buf, yy.Bytes()...)
138 return buf
139 }
140
141
142 func (q *P224Point) Add(p1, p2 *P224Point) *P224Point {
143
144
145
146 t0 := new(fiat.P224Element).Mul(p1.x, p2.x)
147 t1 := new(fiat.P224Element).Mul(p1.y, p2.y)
148 t2 := new(fiat.P224Element).Mul(p1.z, p2.z)
149 t3 := new(fiat.P224Element).Add(p1.x, p1.y)
150 t4 := new(fiat.P224Element).Add(p2.x, p2.y)
151 t3.Mul(t3, t4)
152 t4.Add(t0, t1)
153 t3.Sub(t3, t4)
154 t4.Add(p1.y, p1.z)
155 x3 := new(fiat.P224Element).Add(p2.y, p2.z)
156 t4.Mul(t4, x3)
157 x3.Add(t1, t2)
158 t4.Sub(t4, x3)
159 x3.Add(p1.x, p1.z)
160 y3 := new(fiat.P224Element).Add(p2.x, p2.z)
161 x3.Mul(x3, y3)
162 y3.Add(t0, t2)
163 y3.Sub(x3, y3)
164 z3 := new(fiat.P224Element).Mul(p224B, t2)
165 x3.Sub(y3, z3)
166 z3.Add(x3, x3)
167 x3.Add(x3, z3)
168 z3.Sub(t1, x3)
169 x3.Add(t1, x3)
170 y3.Mul(p224B, y3)
171 t1.Add(t2, t2)
172 t2.Add(t1, t2)
173 y3.Sub(y3, t2)
174 y3.Sub(y3, t0)
175 t1.Add(y3, y3)
176 y3.Add(t1, y3)
177 t1.Add(t0, t0)
178 t0.Add(t1, t0)
179 t0.Sub(t0, t2)
180 t1.Mul(t4, y3)
181 t2.Mul(t0, y3)
182 y3.Mul(x3, z3)
183 y3.Add(y3, t2)
184 x3.Mul(t3, x3)
185 x3.Sub(x3, t1)
186 z3.Mul(t4, z3)
187 t1.Mul(t3, t0)
188 z3.Add(z3, t1)
189
190 q.x.Set(x3)
191 q.y.Set(y3)
192 q.z.Set(z3)
193 return q
194 }
195
196
197 func (q *P224Point) Double(p *P224Point) *P224Point {
198
199
200
201 t0 := new(fiat.P224Element).Square(p.x)
202 t1 := new(fiat.P224Element).Square(p.y)
203 t2 := new(fiat.P224Element).Square(p.z)
204 t3 := new(fiat.P224Element).Mul(p.x, p.y)
205 t3.Add(t3, t3)
206 z3 := new(fiat.P224Element).Mul(p.x, p.z)
207 z3.Add(z3, z3)
208 y3 := new(fiat.P224Element).Mul(p224B, t2)
209 y3.Sub(y3, z3)
210 x3 := new(fiat.P224Element).Add(y3, y3)
211 y3.Add(x3, y3)
212 x3.Sub(t1, y3)
213 y3.Add(t1, y3)
214 y3.Mul(x3, y3)
215 x3.Mul(x3, t3)
216 t3.Add(t2, t2)
217 t2.Add(t2, t3)
218 z3.Mul(p224B, z3)
219 z3.Sub(z3, t2)
220 z3.Sub(z3, t0)
221 t3.Add(z3, z3)
222 z3.Add(z3, t3)
223 t3.Add(t0, t0)
224 t0.Add(t3, t0)
225 t0.Sub(t0, t2)
226 t0.Mul(t0, z3)
227 y3.Add(y3, t0)
228 t0.Mul(p.y, p.z)
229 t0.Add(t0, t0)
230 z3.Mul(t0, z3)
231 x3.Sub(x3, z3)
232 z3.Mul(t0, t1)
233 z3.Add(z3, z3)
234 z3.Add(z3, z3)
235
236 q.x.Set(x3)
237 q.y.Set(y3)
238 q.z.Set(z3)
239 return q
240 }
241
242
243 func (q *P224Point) Select(p1, p2 *P224Point, cond int) *P224Point {
244 q.x.Select(p1.x, p2.x, cond)
245 q.y.Select(p1.y, p2.y, cond)
246 q.z.Select(p1.z, p2.z, cond)
247 return q
248 }
249
250
251 func (p *P224Point) ScalarMult(q *P224Point, scalar []byte) *P224Point {
252
253
254 var table = [16]*P224Point{
255 NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
256 NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
257 NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
258 NewP224Point(), NewP224Point(), NewP224Point(), NewP224Point(),
259 }
260 for i := 1; i < 16; i++ {
261 table[i].Add(table[i-1], q)
262 }
263
264
265
266 t := NewP224Point()
267 p.Set(NewP224Point())
268 for _, byte := range scalar {
269 p.Double(p)
270 p.Double(p)
271 p.Double(p)
272 p.Double(p)
273
274 for i := uint8(0); i < 16; i++ {
275 cond := subtle.ConstantTimeByteEq(byte>>4, i)
276 t.Select(table[i], t, cond)
277 }
278 p.Add(p, t)
279
280 p.Double(p)
281 p.Double(p)
282 p.Double(p)
283 p.Double(p)
284
285 for i := uint8(0); i < 16; i++ {
286 cond := subtle.ConstantTimeByteEq(byte&0b1111, i)
287 t.Select(table[i], t, cond)
288 }
289 p.Add(p, t)
290 }
291
292 return p
293 }
294
View as plain text