1  
     2  
     3  
     4  
     5  
     6  
     7  
     8  
     9  
    10  
    11  
    12  
    13  
    14  
    15  package nistec
    16  
    17  import (
    18  	_ "embed"
    19  	"encoding/binary"
    20  	"errors"
    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] = binary.LittleEndian.Uint64(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