1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package nistec
16
17 import (
18 _ "embed"
19 "errors"
20 "internal/byteorder"
21 "math/bits"
22 "runtime"
23 "unsafe"
24 )
25
26
27
28 type p256Element [4]uint64
29
30
31 var p256One = p256Element{0x0000000000000001, 0xffffffff00000000,
32 0xffffffffffffffff, 0x00000000fffffffe}
33
34 var p256Zero = p256Element{}
35
36
37 var p256P = p256Element{0xffffffffffffffff, 0x00000000ffffffff,
38 0x0000000000000000, 0xffffffff00000001}
39
40
41
42 type P256Point struct {
43
44
45 x, y, z p256Element
46 }
47
48
49 func NewP256Point() *P256Point {
50 return &P256Point{
51 x: p256One, y: p256One, z: p256Zero,
52 }
53 }
54
55
56 func (p *P256Point) SetGenerator() *P256Point {
57 p.x = p256Element{0x79e730d418a9143c, 0x75ba95fc5fedb601,
58 0x79fb732b77622510, 0x18905f76a53755c6}
59 p.y = p256Element{0xddf25357ce95560a, 0x8b4ab8e4ba19e45c,
60 0xd2e88688dd21f325, 0x8571ff1825885d85}
61 p.z = p256One
62 return p
63 }
64
65
66 func (p *P256Point) Set(q *P256Point) *P256Point {
67 p.x, p.y, p.z = q.x, q.y, q.z
68 return p
69 }
70
71 const p256ElementLength = 32
72 const p256UncompressedLength = 1 + 2*p256ElementLength
73 const p256CompressedLength = 1 + p256ElementLength
74
75
76
77
78
79 func (p *P256Point) SetBytes(b []byte) (*P256Point, error) {
80
81
82
83 rr := p256Element{0x0000000000000003, 0xfffffffbffffffff,
84 0xfffffffffffffffe, 0x00000004fffffffd}
85
86 switch {
87
88 case len(b) == 1 && b[0] == 0:
89 return p.Set(NewP256Point()), nil
90
91
92 case len(b) == p256UncompressedLength && b[0] == 4:
93 var r P256Point
94 p256BigToLittle(&r.x, (*[32]byte)(b[1:33]))
95 p256BigToLittle(&r.y, (*[32]byte)(b[33:65]))
96 if p256LessThanP(&r.x) == 0 || p256LessThanP(&r.y) == 0 {
97 return nil, errors.New("invalid P256 element encoding")
98 }
99 p256Mul(&r.x, &r.x, &rr)
100 p256Mul(&r.y, &r.y, &rr)
101 if err := p256CheckOnCurve(&r.x, &r.y); err != nil {
102 return nil, err
103 }
104 r.z = p256One
105 return p.Set(&r), nil
106
107
108 case len(b) == p256CompressedLength && (b[0] == 2 || b[0] == 3):
109 var r P256Point
110 p256BigToLittle(&r.x, (*[32]byte)(b[1:33]))
111 if p256LessThanP(&r.x) == 0 {
112 return nil, errors.New("invalid P256 element encoding")
113 }
114 p256Mul(&r.x, &r.x, &rr)
115
116
117 p256Polynomial(&r.y, &r.x)
118 if !p256Sqrt(&r.y, &r.y) {
119 return nil, errors.New("invalid P256 compressed point encoding")
120 }
121
122
123
124 yy := new(p256Element)
125 p256FromMont(yy, &r.y)
126 cond := int(yy[0]&1) ^ int(b[0]&1)
127 p256NegCond(&r.y, cond)
128
129 r.z = p256One
130 return p.Set(&r), nil
131
132 default:
133 return nil, errors.New("invalid P256 point encoding")
134 }
135 }
136
137
138 func p256Polynomial(y2, x *p256Element) *p256Element {
139 x3 := new(p256Element)
140 p256Sqr(x3, x, 1)
141 p256Mul(x3, x3, x)
142
143 threeX := new(p256Element)
144 p256Add(threeX, x, x)
145 p256Add(threeX, threeX, x)
146 p256NegCond(threeX, 1)
147
148 p256B := &p256Element{0xd89cdf6229c4bddf, 0xacf005cd78843090,
149 0xe5a220abf7212ed6, 0xdc30061d04874834}
150
151 p256Add(x3, x3, threeX)
152 p256Add(x3, x3, p256B)
153
154 *y2 = *x3
155 return y2
156 }
157
158 func p256CheckOnCurve(x, y *p256Element) error {
159
160 rhs := p256Polynomial(new(p256Element), x)
161 lhs := new(p256Element)
162 p256Sqr(lhs, y, 1)
163 if p256Equal(lhs, rhs) != 1 {
164 return errors.New("P256 point not on curve")
165 }
166 return nil
167 }
168
169
170
171
172 func p256LessThanP(x *p256Element) int {
173 var b uint64
174 _, b = bits.Sub64(x[0], p256P[0], b)
175 _, b = bits.Sub64(x[1], p256P[1], b)
176 _, b = bits.Sub64(x[2], p256P[2], b)
177 _, b = bits.Sub64(x[3], p256P[3], b)
178 return int(b)
179 }
180
181
182 func p256Add(res, x, y *p256Element) {
183 var c, b uint64
184 t1 := make([]uint64, 4)
185 t1[0], c = bits.Add64(x[0], y[0], 0)
186 t1[1], c = bits.Add64(x[1], y[1], c)
187 t1[2], c = bits.Add64(x[2], y[2], c)
188 t1[3], c = bits.Add64(x[3], y[3], c)
189 t2 := make([]uint64, 4)
190 t2[0], b = bits.Sub64(t1[0], p256P[0], 0)
191 t2[1], b = bits.Sub64(t1[1], p256P[1], b)
192 t2[2], b = bits.Sub64(t1[2], p256P[2], b)
193 t2[3], b = bits.Sub64(t1[3], p256P[3], b)
194
195
196
197
198
199
200
201 t2Mask := (c ^ b) - 1
202 res[0] = (t1[0] & ^t2Mask) | (t2[0] & t2Mask)
203 res[1] = (t1[1] & ^t2Mask) | (t2[1] & t2Mask)
204 res[2] = (t1[2] & ^t2Mask) | (t2[2] & t2Mask)
205 res[3] = (t1[3] & ^t2Mask) | (t2[3] & t2Mask)
206 }
207
208
209
210 func p256Sqrt(e, x *p256Element) (isSquare bool) {
211 t0, t1 := new(p256Element), new(p256Element)
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228 p256Sqr(t0, x, 1)
229 p256Mul(t0, x, t0)
230 p256Sqr(t1, t0, 2)
231 p256Mul(t0, t0, t1)
232 p256Sqr(t1, t0, 4)
233 p256Mul(t0, t0, t1)
234 p256Sqr(t1, t0, 8)
235 p256Mul(t0, t0, t1)
236 p256Sqr(t1, t0, 16)
237 p256Mul(t0, t0, t1)
238 p256Sqr(t0, t0, 32)
239 p256Mul(t0, x, t0)
240 p256Sqr(t0, t0, 96)
241 p256Mul(t0, x, t0)
242 p256Sqr(t0, t0, 94)
243
244 p256Sqr(t1, t0, 1)
245 if p256Equal(t1, x) != 1 {
246 return false
247 }
248 *e = *t0
249 return true
250 }
251
252
253
254
255
256
257 func p256Mul(res, in1, in2 *p256Element)
258
259
260
261
262 func p256Sqr(res, in *p256Element, n int)
263
264
265
266
267
268 func p256FromMont(res, in *p256Element)
269
270
271
272
273 func p256NegCond(val *p256Element, cond int)
274
275
276
277
278 func p256MovCond(res, a, b *P256Point, cond int)
279
280
281 func p256BigToLittle(res *p256Element, in *[32]byte)
282
283
284 func p256LittleToBig(res *[32]byte, in *p256Element)
285
286
287 func p256OrdBigToLittle(res *p256OrdElement, in *[32]byte)
288
289
290 func p256OrdLittleToBig(res *[32]byte, in *p256OrdElement)
291
292
293
294
295 type p256Table [16]P256Point
296
297
298
299
300
301 func p256Select(res *P256Point, table *p256Table, idx int)
302
303
304
305 type p256AffinePoint struct {
306 x, y p256Element
307 }
308
309
310
311 type p256AffineTable [32]p256AffinePoint
312
313
314
315
316
317
318
319
320 var p256Precomputed *[43]p256AffineTable
321
322
323 var p256PrecomputedEmbed string
324
325 func init() {
326 p256PrecomputedPtr := (*unsafe.Pointer)(unsafe.Pointer(&p256PrecomputedEmbed))
327 if runtime.GOARCH == "s390x" {
328 var newTable [43 * 32 * 2 * 4]uint64
329 for i, x := range (*[43 * 32 * 2 * 4][8]byte)(*p256PrecomputedPtr) {
330 newTable[i] = byteorder.LeUint64(x[:])
331 }
332 newTablePtr := unsafe.Pointer(&newTable)
333 p256PrecomputedPtr = &newTablePtr
334 }
335 p256Precomputed = (*[43]p256AffineTable)(*p256PrecomputedPtr)
336 }
337
338
339
340
341
342 func p256SelectAffine(res *p256AffinePoint, table *p256AffineTable, idx int)
343
344
345
346
347
348
349 func p256PointAddAffineAsm(res, in1 *P256Point, in2 *p256AffinePoint, sign, sel, zero int)
350
351
352
353
354
355
356 func p256PointAddAsm(res, in1, in2 *P256Point) int
357
358
359
360
361 func p256PointDoubleAsm(res, in *P256Point)
362
363
364
365 type p256OrdElement [4]uint64
366
367
368 func p256OrdReduce(s *p256OrdElement) {
369
370
371 t0, b := bits.Sub64(s[0], 0xf3b9cac2fc632551, 0)
372 t1, b := bits.Sub64(s[1], 0xbce6faada7179e84, b)
373 t2, b := bits.Sub64(s[2], 0xffffffffffffffff, b)
374 t3, b := bits.Sub64(s[3], 0xffffffff00000000, b)
375 tMask := b - 1
376 s[0] ^= (t0 ^ s[0]) & tMask
377 s[1] ^= (t1 ^ s[1]) & tMask
378 s[2] ^= (t2 ^ s[2]) & tMask
379 s[3] ^= (t3 ^ s[3]) & tMask
380 }
381
382
383 func (q *P256Point) Add(r1, r2 *P256Point) *P256Point {
384 var sum, double P256Point
385 r1IsInfinity := r1.isInfinity()
386 r2IsInfinity := r2.isInfinity()
387 pointsEqual := p256PointAddAsm(&sum, r1, r2)
388 p256PointDoubleAsm(&double, r1)
389 p256MovCond(&sum, &double, &sum, pointsEqual)
390 p256MovCond(&sum, r1, &sum, r2IsInfinity)
391 p256MovCond(&sum, r2, &sum, r1IsInfinity)
392 return q.Set(&sum)
393 }
394
395
396 func (q *P256Point) Double(p *P256Point) *P256Point {
397 var double P256Point
398 p256PointDoubleAsm(&double, p)
399 return q.Set(&double)
400 }
401
402
403
404
405 func (r *P256Point) ScalarBaseMult(scalar []byte) (*P256Point, error) {
406 if len(scalar) != 32 {
407 return nil, errors.New("invalid scalar length")
408 }
409 scalarReversed := new(p256OrdElement)
410 p256OrdBigToLittle(scalarReversed, (*[32]byte)(scalar))
411 p256OrdReduce(scalarReversed)
412
413 r.p256BaseMult(scalarReversed)
414 return r, nil
415 }
416
417
418
419
420 func (r *P256Point) ScalarMult(q *P256Point, scalar []byte) (*P256Point, error) {
421 if len(scalar) != 32 {
422 return nil, errors.New("invalid scalar length")
423 }
424 scalarReversed := new(p256OrdElement)
425 p256OrdBigToLittle(scalarReversed, (*[32]byte)(scalar))
426 p256OrdReduce(scalarReversed)
427
428 r.Set(q).p256ScalarMult(scalarReversed)
429 return r, nil
430 }
431
432
433 func uint64IsZero(x uint64) int {
434 x = ^x
435 x &= x >> 32
436 x &= x >> 16
437 x &= x >> 8
438 x &= x >> 4
439 x &= x >> 2
440 x &= x >> 1
441 return int(x & 1)
442 }
443
444
445 func p256Equal(a, b *p256Element) int {
446 var acc uint64
447 for i := range a {
448 acc |= a[i] ^ b[i]
449 }
450 return uint64IsZero(acc)
451 }
452
453
454 func (p *P256Point) isInfinity() int {
455 return p256Equal(&p.z, &p256Zero)
456 }
457
458
459
460
461 func (p *P256Point) Bytes() []byte {
462
463
464 var out [p256UncompressedLength]byte
465 return p.bytes(&out)
466 }
467
468 func (p *P256Point) bytes(out *[p256UncompressedLength]byte) []byte {
469
470 if p.isInfinity() == 1 {
471 return append(out[:0], 0)
472 }
473
474 x, y := new(p256Element), new(p256Element)
475 p.affineFromMont(x, y)
476
477 out[0] = 4
478 p256LittleToBig((*[32]byte)(out[1:33]), x)
479 p256LittleToBig((*[32]byte)(out[33:65]), y)
480
481 return out[:]
482 }
483
484
485
486 func (p *P256Point) affineFromMont(x, y *p256Element) {
487 p256Inverse(y, &p.z)
488 p256Sqr(x, y, 1)
489 p256Mul(y, y, x)
490
491 p256Mul(x, &p.x, x)
492 p256Mul(y, &p.y, y)
493
494 p256FromMont(x, x)
495 p256FromMont(y, y)
496 }
497
498
499
500 func (p *P256Point) BytesX() ([]byte, error) {
501
502
503 var out [p256ElementLength]byte
504 return p.bytesX(&out)
505 }
506
507 func (p *P256Point) bytesX(out *[p256ElementLength]byte) ([]byte, error) {
508 if p.isInfinity() == 1 {
509 return nil, errors.New("P256 point is the point at infinity")
510 }
511
512 x := new(p256Element)
513 p256Inverse(x, &p.z)
514 p256Sqr(x, x, 1)
515 p256Mul(x, &p.x, x)
516 p256FromMont(x, x)
517 p256LittleToBig((*[32]byte)(out[:]), x)
518
519 return out[:], nil
520 }
521
522
523
524
525 func (p *P256Point) BytesCompressed() []byte {
526
527
528 var out [p256CompressedLength]byte
529 return p.bytesCompressed(&out)
530 }
531
532 func (p *P256Point) bytesCompressed(out *[p256CompressedLength]byte) []byte {
533 if p.isInfinity() == 1 {
534 return append(out[:0], 0)
535 }
536
537 x, y := new(p256Element), new(p256Element)
538 p.affineFromMont(x, y)
539
540 out[0] = 2 | byte(y[0]&1)
541 p256LittleToBig((*[32]byte)(out[1:33]), x)
542
543 return out[:]
544 }
545
546
547 func (q *P256Point) Select(p1, p2 *P256Point, cond int) *P256Point {
548 p256MovCond(q, p1, p2, cond)
549 return q
550 }
551
552
553 func p256Inverse(out, in *p256Element) {
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576 var z = new(p256Element)
577 var t0 = new(p256Element)
578 var t1 = new(p256Element)
579
580 p256Sqr(z, in, 1)
581 p256Mul(z, in, z)
582 p256Sqr(z, z, 1)
583 p256Mul(z, in, z)
584 p256Sqr(t0, z, 3)
585 p256Mul(t0, z, t0)
586 p256Sqr(t1, t0, 6)
587 p256Mul(t0, t0, t1)
588 p256Sqr(t0, t0, 3)
589 p256Mul(z, z, t0)
590 p256Sqr(t0, z, 1)
591 p256Mul(t0, in, t0)
592 p256Sqr(t1, t0, 16)
593 p256Mul(t0, t0, t1)
594 p256Sqr(t0, t0, 15)
595 p256Mul(z, z, t0)
596 p256Sqr(t0, t0, 17)
597 p256Mul(t0, in, t0)
598 p256Sqr(t0, t0, 143)
599 p256Mul(t0, z, t0)
600 p256Sqr(t0, t0, 47)
601 p256Mul(z, z, t0)
602 p256Sqr(z, z, 2)
603 p256Mul(out, in, z)
604 }
605
606 func boothW5(in uint) (int, int) {
607 var s uint = ^((in >> 5) - 1)
608 var d uint = (1 << 6) - in - 1
609 d = (d & s) | (in & (^s))
610 d = (d >> 1) + (d & 1)
611 return int(d), int(s & 1)
612 }
613
614 func boothW6(in uint) (int, int) {
615 var s uint = ^((in >> 6) - 1)
616 var d uint = (1 << 7) - in - 1
617 d = (d & s) | (in & (^s))
618 d = (d >> 1) + (d & 1)
619 return int(d), int(s & 1)
620 }
621
622 func (p *P256Point) p256BaseMult(scalar *p256OrdElement) {
623 var t0 p256AffinePoint
624
625 wvalue := (scalar[0] << 1) & 0x7f
626 sel, sign := boothW6(uint(wvalue))
627 p256SelectAffine(&t0, &p256Precomputed[0], sel)
628 p.x, p.y, p.z = t0.x, t0.y, p256One
629 p256NegCond(&p.y, sign)
630
631 index := uint(5)
632 zero := sel
633
634 for i := 1; i < 43; i++ {
635 if index < 192 {
636 wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0x7f
637 } else {
638 wvalue = (scalar[index/64] >> (index % 64)) & 0x7f
639 }
640 index += 6
641 sel, sign = boothW6(uint(wvalue))
642 p256SelectAffine(&t0, &p256Precomputed[i], sel)
643 p256PointAddAffineAsm(p, p, &t0, sign, sel, zero)
644 zero |= sel
645 }
646
647
648 p256MovCond(p, p, NewP256Point(), zero)
649 }
650
651 func (p *P256Point) p256ScalarMult(scalar *p256OrdElement) {
652
653
654 var precomp p256Table
655 var t0, t1, t2, t3 P256Point
656
657
658 precomp[0] = *p
659
660 p256PointDoubleAsm(&t0, p)
661 p256PointDoubleAsm(&t1, &t0)
662 p256PointDoubleAsm(&t2, &t1)
663 p256PointDoubleAsm(&t3, &t2)
664 precomp[1] = t0
665 precomp[3] = t1
666 precomp[7] = t2
667 precomp[15] = t3
668
669 p256PointAddAsm(&t0, &t0, p)
670 p256PointAddAsm(&t1, &t1, p)
671 p256PointAddAsm(&t2, &t2, p)
672 precomp[2] = t0
673 precomp[4] = t1
674 precomp[8] = t2
675
676 p256PointDoubleAsm(&t0, &t0)
677 p256PointDoubleAsm(&t1, &t1)
678 precomp[5] = t0
679 precomp[9] = t1
680
681 p256PointAddAsm(&t2, &t0, p)
682 p256PointAddAsm(&t1, &t1, p)
683 precomp[6] = t2
684 precomp[10] = t1
685
686 p256PointDoubleAsm(&t0, &t0)
687 p256PointDoubleAsm(&t2, &t2)
688 precomp[11] = t0
689 precomp[13] = t2
690
691 p256PointAddAsm(&t0, &t0, p)
692 p256PointAddAsm(&t2, &t2, p)
693 precomp[12] = t0
694 precomp[14] = t2
695
696
697 index := uint(254)
698 var sel, sign int
699
700 wvalue := (scalar[index/64] >> (index % 64)) & 0x3f
701 sel, _ = boothW5(uint(wvalue))
702
703 p256Select(p, &precomp, sel)
704 zero := sel
705
706 for index > 4 {
707 index -= 5
708 p256PointDoubleAsm(p, p)
709 p256PointDoubleAsm(p, p)
710 p256PointDoubleAsm(p, p)
711 p256PointDoubleAsm(p, p)
712 p256PointDoubleAsm(p, p)
713
714 if index < 192 {
715 wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0x3f
716 } else {
717 wvalue = (scalar[index/64] >> (index % 64)) & 0x3f
718 }
719
720 sel, sign = boothW5(uint(wvalue))
721
722 p256Select(&t0, &precomp, sel)
723 p256NegCond(&t0.y, sign)
724 p256PointAddAsm(&t1, p, &t0)
725 p256MovCond(&t1, &t1, p, sel)
726 p256MovCond(p, &t1, &t0, zero)
727 zero |= sel
728 }
729
730 p256PointDoubleAsm(p, p)
731 p256PointDoubleAsm(p, p)
732 p256PointDoubleAsm(p, p)
733 p256PointDoubleAsm(p, p)
734 p256PointDoubleAsm(p, p)
735
736 wvalue = (scalar[0] << 1) & 0x3f
737 sel, sign = boothW5(uint(wvalue))
738
739 p256Select(&t0, &precomp, sel)
740 p256NegCond(&t0.y, sign)
741 p256PointAddAsm(&t1, p, &t0)
742 p256MovCond(&t1, &t1, p, sel)
743 p256MovCond(p, &t1, &t0, zero)
744 }
745
View as plain text