mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-22 10:16:18 +08:00
sm2: refactoring to reduce duplicated code
This commit is contained in:
parent
4a21345e72
commit
8948bdd931
@ -75,7 +75,7 @@ TEXT ·p256BigToLittle(SB),NOSPLIT,$0
|
||||
|
||||
RET
|
||||
/* ---------------------------------------*/
|
||||
// func p256MovCond(res, a, b *P256Point, cond int)
|
||||
// func p256MovCond(res, a, b *SM2P256Point, cond int)
|
||||
TEXT ·p256MovCond(SB),NOSPLIT,$0
|
||||
MOVQ res+0(FP), res_ptr
|
||||
MOVQ a+8(FP), x_ptr
|
||||
@ -671,7 +671,7 @@ TEXT ·p256FromMont(SB),NOSPLIT,$0
|
||||
|
||||
RET
|
||||
/* ---------------------------------------*/
|
||||
// func p256Select(res *P256Point, table *p256Table, idx int)
|
||||
// func p256Select(res *SM2P256Point, table *p256Table, idx int)
|
||||
TEXT ·p256Select(SB),NOSPLIT,$0
|
||||
MOVQ idx+16(FP),AX
|
||||
MOVQ table+8(FP),DI
|
||||
@ -1797,7 +1797,7 @@ TEXT sm2P256SqrInternal(SB),NOSPLIT,$8
|
||||
#define sel_save (32*15 + 8)(SP)
|
||||
#define zero_save (32*15 + 8 + 4)(SP)
|
||||
|
||||
// func p256PointAddAffineAsm(res, in1 *P256Point, in2 *p256AffinePoint, sign, sel, zero int)
|
||||
// func p256PointAddAffineAsm(res, in1 *SM2P256Point, in2 *p256AffinePoint, sign, sel, zero int)
|
||||
TEXT ·p256PointAddAffineAsm(SB),0,$512-48
|
||||
// Move input to stack in order to free registers
|
||||
MOVQ res+0(FP), AX
|
||||
@ -2110,7 +2110,7 @@ TEXT sm2P256IsZero(SB),NOSPLIT,$0
|
||||
#define rptr (32*20)(SP)
|
||||
#define points_eq (32*20+8)(SP)
|
||||
|
||||
//func p256PointAddAsm(res, in1, in2 *P256Point) int
|
||||
//func p256PointAddAsm(res, in1, in2 *SM2P256Point) int
|
||||
TEXT ·p256PointAddAsm(SB),0,$680-32
|
||||
// See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
|
||||
// Move input to stack in order to free registers
|
||||
@ -2290,7 +2290,7 @@ TEXT ·p256PointAddAsm(SB),0,$680-32
|
||||
#define tmp(off) (32*6 + off)(SP)
|
||||
#define rptr (32*7)(SP)
|
||||
|
||||
//func p256PointDoubleAsm(res, in *P256Point)
|
||||
//func p256PointDoubleAsm(res, in *SM2P256Point)
|
||||
TEXT ·p256PointDoubleAsm(SB),NOSPLIT,$256-16
|
||||
// Move input to stack in order to free registers
|
||||
MOVQ res+0(FP), AX
|
||||
|
@ -92,7 +92,7 @@ TEXT ·p256BigToLittle(SB),NOSPLIT,$0
|
||||
STP (acc1, acc0), 1*16(res_ptr)
|
||||
RET
|
||||
/* ---------------------------------------*/
|
||||
// func p256MovCond(res, a, b *P256Point, cond int)
|
||||
// func p256MovCond(res, a, b *SM2P256Point, cond int)
|
||||
// If cond == 0 res=b, else res=a
|
||||
TEXT ·p256MovCond(SB),NOSPLIT,$0
|
||||
MOVD res+0(FP), res_ptr
|
||||
@ -291,7 +291,7 @@ TEXT ·p256FromMont(SB),NOSPLIT,$0
|
||||
|
||||
RET
|
||||
/* ---------------------------------------*/
|
||||
// func p256Select(res *P256Point, table *p256Table, idx int)
|
||||
// func p256Select(res *SM2P256Point, table *p256Table, idx int)
|
||||
TEXT ·p256Select(SB),NOSPLIT,$0
|
||||
MOVD idx+16(FP), const0
|
||||
MOVD table+8(FP), b_ptr
|
||||
@ -1159,7 +1159,7 @@ TEXT sm2P256MulInternal<>(SB),NOSPLIT,$0
|
||||
#define u1(off) (32*10 + 8 + off)(RSP)
|
||||
#define u2(off) (32*11 + 8 + off)(RSP)
|
||||
|
||||
// func p256PointAddAffineAsm(res, in1 *P256Point, in2 *p256AffinePoint, sign, sel, zero int)
|
||||
// func p256PointAddAffineAsm(res, in1 *SM2P256Point, in2 *p256AffinePoint, sign, sel, zero int)
|
||||
TEXT ·p256PointAddAffineAsm(SB),0,$264-48
|
||||
MOVD in1+8(FP), a_ptr
|
||||
MOVD in2+16(FP), b_ptr
|
||||
@ -1355,7 +1355,7 @@ TEXT ·p256PointAddAffineAsm(SB),0,$264-48
|
||||
#define zsqr(off) (32*2 + 8 + off)(RSP)
|
||||
#define tmp(off) (32*3 + 8 + off)(RSP)
|
||||
|
||||
//func p256PointDoubleAsm(res, in *P256Point)
|
||||
//func p256PointDoubleAsm(res, in *SM2P256Point)
|
||||
TEXT ·p256PointDoubleAsm(SB),NOSPLIT,$136-16
|
||||
MOVD res+0(FP), res_ptr
|
||||
MOVD in+8(FP), a_ptr
|
||||
@ -1455,7 +1455,7 @@ TEXT ·p256PointDoubleAsm(SB),NOSPLIT,$136-16
|
||||
#define x3out(off) (off)(b_ptr)
|
||||
#define y3out(off) (off + 32)(b_ptr)
|
||||
#define z3out(off) (off + 64)(b_ptr)
|
||||
// func p256PointAddAsm(res, in1, in2 *P256Point) int
|
||||
// func p256PointAddAsm(res, in1, in2 *SM2P256Point) int
|
||||
TEXT ·p256PointAddAsm(SB),0,$392-32
|
||||
// See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
|
||||
// Move input to stack in order to free registers
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
func TestP256PrecomputedTable(t *testing.T) {
|
||||
base := NewP256Point().SetGenerator()
|
||||
base := NewSM2P256Point().SetGenerator()
|
||||
|
||||
for i := 0; i < 43; i++ {
|
||||
t.Run(fmt.Sprintf("table[%d]", i), func(t *testing.T) {
|
||||
@ -22,8 +22,8 @@ func TestP256PrecomputedTable(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func testP256AffineTable(t *testing.T, base *P256Point, table *p256AffineTable) {
|
||||
p := NewP256Point()
|
||||
func testP256AffineTable(t *testing.T, base *SM2P256Point, table *p256AffineTable) {
|
||||
p := NewSM2P256Point()
|
||||
zInv := new(p256Element)
|
||||
zInvSq := new(p256Element)
|
||||
|
||||
|
@ -34,21 +34,21 @@ var p256P = p256Element{0xffffffffffffffff, 0xffffffff00000000,
|
||||
|
||||
// P256Point is a P-256 point. The zero value should not be assumed to be valid
|
||||
// (although it is in this implementation).
|
||||
type P256Point struct {
|
||||
type SM2P256Point struct {
|
||||
// (X:Y:Z) are Jacobian coordinates where x = X/Z² and y = Y/Z³. The point
|
||||
// at infinity can be represented by any set of coordinates with Z = 0.
|
||||
x, y, z p256Element
|
||||
}
|
||||
|
||||
// NewP256Point returns a new P256Point representing the point at infinity.
|
||||
func NewP256Point() *P256Point {
|
||||
return &P256Point{
|
||||
// NewSM2P256Point returns a new SM2P256Point representing the point at infinity.
|
||||
func NewSM2P256Point() *SM2P256Point {
|
||||
return &SM2P256Point{
|
||||
x: p256One, y: p256One, z: p256Zero,
|
||||
}
|
||||
}
|
||||
|
||||
// SetGenerator sets p to the canonical generator and returns p.
|
||||
func (p *P256Point) SetGenerator() *P256Point {
|
||||
func (p *SM2P256Point) SetGenerator() *SM2P256Point {
|
||||
p.x = p256Element{0x61328990f418029e, 0x3e7981eddca6c050,
|
||||
0xd6a1ed99ac24c3c3, 0x91167a5ee1c13b05}
|
||||
p.y = p256Element{0xc1354e593c2d0ddd, 0xc1f5e5788d3295fa,
|
||||
@ -58,7 +58,7 @@ func (p *P256Point) SetGenerator() *P256Point {
|
||||
}
|
||||
|
||||
// Set sets p = q and returns p.
|
||||
func (p *P256Point) Set(q *P256Point) *P256Point {
|
||||
func (p *SM2P256Point) Set(q *SM2P256Point) *SM2P256Point {
|
||||
p.x, p.y, p.z = q.x, q.y, q.z
|
||||
return p
|
||||
}
|
||||
@ -79,7 +79,7 @@ func toElementArray(b []byte) *[32]byte {
|
||||
// b, as specified in SEC 1, Version 2.0, Section 2.3.4. If the point is not on
|
||||
// the curve, it returns nil and an error, and the receiver is unchanged.
|
||||
// Otherwise, it returns p.
|
||||
func (p *P256Point) SetBytes(b []byte) (*P256Point, error) {
|
||||
func (p *SM2P256Point) SetBytes(b []byte) (*SM2P256Point, error) {
|
||||
// p256Mul operates in the Montgomery domain with R = 2²⁵⁶ mod p. Thus rr
|
||||
// here is R in the Montgomery domain, or R×R mod p. See comment in
|
||||
// P256OrdInverse about how this is used.
|
||||
@ -89,11 +89,11 @@ func (p *P256Point) SetBytes(b []byte) (*P256Point, error) {
|
||||
switch {
|
||||
// Point at infinity.
|
||||
case len(b) == 1 && b[0] == 0:
|
||||
return p.Set(NewP256Point()), nil
|
||||
return p.Set(NewSM2P256Point()), nil
|
||||
|
||||
// Uncompressed form.
|
||||
case len(b) == p256UncompressedLength && b[0] == 4:
|
||||
var r P256Point
|
||||
var r SM2P256Point
|
||||
p256BigToLittle(&r.x, toElementArray(b[1:33]))
|
||||
p256BigToLittle(&r.y, toElementArray(b[33:65]))
|
||||
if p256LessThanP(&r.x) == 0 || p256LessThanP(&r.y) == 0 {
|
||||
@ -109,7 +109,7 @@ func (p *P256Point) SetBytes(b []byte) (*P256Point, error) {
|
||||
|
||||
// Compressed form.
|
||||
case len(b) == p256CompressedLength && (b[0] == 2 || b[0] == 3):
|
||||
var r P256Point
|
||||
var r SM2P256Point
|
||||
p256BigToLittle(&r.x, toElementArray(b[1:33]))
|
||||
if p256LessThanP(&r.x) == 0 {
|
||||
return nil, errors.New("invalid P256 element encoding")
|
||||
@ -334,7 +334,7 @@ func p256NegCond(val *p256Element, cond int)
|
||||
// If cond is 0, sets res = b, otherwise sets res = a.
|
||||
//
|
||||
//go:noescape
|
||||
func p256MovCond(res, a, b *P256Point, cond int)
|
||||
func p256MovCond(res, a, b *SM2P256Point, cond int)
|
||||
|
||||
//go:noescape
|
||||
func p256BigToLittle(res *p256Element, in *[32]byte)
|
||||
@ -351,13 +351,13 @@ func p256OrdLittleToBig(res *[32]byte, in *p256OrdElement)
|
||||
// p256Table is a table of the first 16 multiples of a point. Points are stored
|
||||
// at an index offset of -1 so [8]P is at index 7, P is at 0, and [16]P is at 15.
|
||||
// [0]P is the point at infinity and it's not stored.
|
||||
type p256Table [16]P256Point
|
||||
type p256Table [16]SM2P256Point
|
||||
|
||||
// p256Select sets res to the point at index idx in the table.
|
||||
// idx must be in [0, 15]. It executes in constant time.
|
||||
//
|
||||
//go:noescape
|
||||
func p256Select(res *P256Point, table *p256Table, idx int)
|
||||
func p256Select(res *SM2P256Point, table *p256Table, idx int)
|
||||
|
||||
// p256AffinePoint is a point in affine coordinates (x, y). x and y are still
|
||||
// Montgomery domain elements. The point can't be the point at infinity.
|
||||
@ -397,27 +397,27 @@ func p256SelectAffine(res *p256AffinePoint, table *p256AffineTable, idx int)
|
||||
// If sign is not 0, sets res = in1 + -in2. Otherwise, sets res = in1 + in2
|
||||
//
|
||||
//go:noescape
|
||||
func p256PointAddAffineAsm(res, in1 *P256Point, in2 *p256AffinePoint, sign, sel, zero int)
|
||||
func p256PointAddAffineAsm(res, in1 *SM2P256Point, in2 *p256AffinePoint, sign, sel, zero int)
|
||||
|
||||
// Point addition. Sets res = in1 + in2. Returns one if the two input points
|
||||
// were equal and zero otherwise. If in1 or in2 are the point at infinity, res
|
||||
// and the return value are undefined.
|
||||
//
|
||||
//go:noescape
|
||||
func p256PointAddAsm(res, in1, in2 *P256Point) int
|
||||
func p256PointAddAsm(res, in1, in2 *SM2P256Point) int
|
||||
|
||||
// Point doubling. Sets res = in + in. in can be the point at infinity.
|
||||
//
|
||||
//go:noescape
|
||||
func p256PointDoubleAsm(res, in *P256Point)
|
||||
func p256PointDoubleAsm(res, in *SM2P256Point)
|
||||
|
||||
// p256OrdElement is a P-256 scalar field element in [0, ord(G)-1] in the
|
||||
// Montgomery domain (with R 2²⁵⁶) as four uint64 limbs in little-endian order.
|
||||
type p256OrdElement [4]uint64
|
||||
|
||||
// Add sets q = p1 + p2, and returns q. The points may overlap.
|
||||
func (q *P256Point) Add(r1, r2 *P256Point) *P256Point {
|
||||
var sum, double P256Point
|
||||
func (q *SM2P256Point) Add(r1, r2 *SM2P256Point) *SM2P256Point {
|
||||
var sum, double SM2P256Point
|
||||
r1IsInfinity := r1.isInfinity()
|
||||
r2IsInfinity := r2.isInfinity()
|
||||
pointsEqual := p256PointAddAsm(&sum, r1, r2)
|
||||
@ -429,8 +429,8 @@ func (q *P256Point) Add(r1, r2 *P256Point) *P256Point {
|
||||
}
|
||||
|
||||
// Double sets q = p + p, and returns q. The points may overlap.
|
||||
func (q *P256Point) Double(p *P256Point) *P256Point {
|
||||
var double P256Point
|
||||
func (q *SM2P256Point) Double(p *SM2P256Point) *SM2P256Point {
|
||||
var double SM2P256Point
|
||||
p256PointDoubleAsm(&double, p)
|
||||
return q.Set(&double)
|
||||
}
|
||||
@ -438,7 +438,7 @@ func (q *P256Point) Double(p *P256Point) *P256Point {
|
||||
// ScalarBaseMult sets r = scalar * generator, where scalar is a 32-byte big
|
||||
// endian value, and returns r. If scalar is not 32 bytes long, ScalarBaseMult
|
||||
// returns an error and the receiver is unchanged.
|
||||
func (r *P256Point) ScalarBaseMult(scalar []byte) (*P256Point, error) {
|
||||
func (r *SM2P256Point) ScalarBaseMult(scalar []byte) (*SM2P256Point, error) {
|
||||
if len(scalar) != 32 {
|
||||
return nil, errors.New("invalid scalar length")
|
||||
}
|
||||
@ -452,7 +452,7 @@ func (r *P256Point) ScalarBaseMult(scalar []byte) (*P256Point, error) {
|
||||
// ScalarMult sets r = scalar * q, where scalar is a 32-byte big endian value,
|
||||
// and returns r. If scalar is not 32 bytes long, ScalarBaseMult returns an
|
||||
// error and the receiver is unchanged.
|
||||
func (r *P256Point) ScalarMult(q *P256Point, scalar []byte) (*P256Point, error) {
|
||||
func (r *SM2P256Point) ScalarMult(q *SM2P256Point, scalar []byte) (*SM2P256Point, error) {
|
||||
if len(scalar) != 32 {
|
||||
return nil, errors.New("invalid scalar length")
|
||||
}
|
||||
@ -485,21 +485,21 @@ func p256Equal(a, b *p256Element) int {
|
||||
}
|
||||
|
||||
// isInfinity returns 1 if p is the point at infinity and 0 otherwise.
|
||||
func (p *P256Point) isInfinity() int {
|
||||
func (p *SM2P256Point) isInfinity() int {
|
||||
return p256Equal(&p.z, &p256Zero)
|
||||
}
|
||||
|
||||
// Bytes returns the uncompressed or infinity encoding of p, as specified in
|
||||
// SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the point at
|
||||
// infinity is shorter than all other encodings.
|
||||
func (p *P256Point) Bytes() []byte {
|
||||
func (p *SM2P256Point) Bytes() []byte {
|
||||
// This function is outlined to make the allocations inline in the caller
|
||||
// rather than happen on the heap.
|
||||
var out [p256UncompressedLength]byte
|
||||
return p.bytes(&out)
|
||||
}
|
||||
|
||||
func (p *P256Point) bytes(out *[p256UncompressedLength]byte) []byte {
|
||||
func (p *SM2P256Point) bytes(out *[p256UncompressedLength]byte) []byte {
|
||||
// The proper representation of the point at infinity is a single zero byte.
|
||||
if p.isInfinity() == 1 {
|
||||
return append(out[:0], 0)
|
||||
@ -517,7 +517,7 @@ func (p *P256Point) bytes(out *[p256UncompressedLength]byte) []byte {
|
||||
|
||||
// affineFromMont sets (x, y) to the affine coordinates of p, converted out of the
|
||||
// Montgomery domain.
|
||||
func (p *P256Point) affineFromMont(x, y *p256Element) {
|
||||
func (p *SM2P256Point) affineFromMont(x, y *p256Element) {
|
||||
p256Inverse(y, &p.z)
|
||||
p256Sqr(x, y, 1)
|
||||
p256Mul(y, y, x)
|
||||
@ -529,17 +529,41 @@ func (p *P256Point) affineFromMont(x, y *p256Element) {
|
||||
p256FromMont(y, y)
|
||||
}
|
||||
|
||||
// BytesX returns the encoding of the x-coordinate of p, as specified in SEC 1,
|
||||
// Version 2.0, Section 2.3.5, or an error if p is the point at infinity.
|
||||
func (p *SM2P256Point) BytesX() ([]byte, error) {
|
||||
// This function is outlined to make the allocations inline in the caller
|
||||
// rather than happen on the heap.
|
||||
var out [p256ElementLength]byte
|
||||
return p.bytesX(&out)
|
||||
}
|
||||
|
||||
func (p *SM2P256Point) bytesX(out *[p256ElementLength]byte) ([]byte, error) {
|
||||
if p.isInfinity() == 1 {
|
||||
return nil, errors.New("SM2 point is the point at infinity")
|
||||
}
|
||||
|
||||
x := new(p256Element)
|
||||
p256Inverse(x, &p.z)
|
||||
p256Sqr(x, x, 1)
|
||||
p256Mul(x, &p.x, x)
|
||||
p256FromMont(x, x)
|
||||
p256LittleToBig(toElementArray(out[:]), x)
|
||||
|
||||
return out[:], nil
|
||||
}
|
||||
|
||||
// BytesCompressed returns the compressed or infinity encoding of p, as
|
||||
// specified in SEC 1, Version 2.0, Section 2.3.3. Note that the encoding of the
|
||||
// point at infinity is shorter than all other encodings.
|
||||
func (p *P256Point) BytesCompressed() []byte {
|
||||
func (p *SM2P256Point) BytesCompressed() []byte {
|
||||
// This function is outlined to make the allocations inline in the caller
|
||||
// rather than happen on the heap.
|
||||
var out [p256CompressedLength]byte
|
||||
return p.bytesCompressed(&out)
|
||||
}
|
||||
|
||||
func (p *P256Point) bytesCompressed(out *[p256CompressedLength]byte) []byte {
|
||||
func (p *SM2P256Point) bytesCompressed(out *[p256CompressedLength]byte) []byte {
|
||||
if p.isInfinity() == 1 {
|
||||
return append(out[:0], 0)
|
||||
}
|
||||
@ -554,7 +578,7 @@ func (p *P256Point) bytesCompressed(out *[p256CompressedLength]byte) []byte {
|
||||
}
|
||||
|
||||
// Select sets q to p1 if cond == 1, and to p2 if cond == 0.
|
||||
func (q *P256Point) Select(p1, p2 *P256Point, cond int) *P256Point {
|
||||
func (q *SM2P256Point) Select(p1, p2 *SM2P256Point, cond int) *SM2P256Point {
|
||||
p256MovCond(q, p1, p2, cond)
|
||||
return q
|
||||
}
|
||||
@ -757,7 +781,7 @@ func boothW6(in uint) (int, int) {
|
||||
return int(d), int(s & 1)
|
||||
}
|
||||
|
||||
func (p *P256Point) p256BaseMult(scalar *p256OrdElement) {
|
||||
func (p *SM2P256Point) p256BaseMult(scalar *p256OrdElement) {
|
||||
var t0 p256AffinePoint
|
||||
|
||||
wvalue := (scalar[0] << 1) & 0x7f
|
||||
@ -783,14 +807,14 @@ func (p *P256Point) p256BaseMult(scalar *p256OrdElement) {
|
||||
}
|
||||
|
||||
// If the whole scalar was zero, set to the point at infinity.
|
||||
p256MovCond(p, p, NewP256Point(), zero)
|
||||
p256MovCond(p, p, NewSM2P256Point(), zero)
|
||||
}
|
||||
|
||||
func (p *P256Point) p256ScalarMult(scalar *p256OrdElement) {
|
||||
func (p *SM2P256Point) p256ScalarMult(scalar *p256OrdElement) {
|
||||
// precomp is a table of precomputed points that stores powers of p
|
||||
// from p^1 to p^16.
|
||||
var precomp p256Table
|
||||
var t0, t1, t2, t3 P256Point
|
||||
var t0, t1, t2, t3 SM2P256Point
|
||||
|
||||
// Prepare the table
|
||||
precomp[0] = *p // 1
|
||||
|
@ -1,6 +1,3 @@
|
||||
//go:build (amd64 && !generic) || (arm64 && !generic)
|
||||
// +build amd64,!generic arm64,!generic
|
||||
|
||||
package sm2ec
|
||||
|
||||
import (
|
||||
@ -13,11 +10,11 @@ import (
|
||||
|
||||
// TODO: will merge it with sm2p256_generic.go from golang 1.18 with generic support.
|
||||
type sm2Curve struct {
|
||||
newPoint func() *_sm2ec.P256Point
|
||||
newPoint func() *_sm2ec.SM2P256Point
|
||||
params *elliptic.CurveParams
|
||||
}
|
||||
|
||||
var sm2p256 = &sm2Curve{newPoint: _sm2ec.NewP256Point}
|
||||
var sm2p256 = &sm2Curve{newPoint: _sm2ec.NewSM2P256Point}
|
||||
|
||||
func initSM2P256() {
|
||||
sm2p256.params = sm2Params
|
||||
@ -37,7 +34,7 @@ func (curve *sm2Curve) IsOnCurve(x, y *big.Int) bool {
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) pointFromAffine(x, y *big.Int) (p *_sm2ec.P256Point, err error) {
|
||||
func (curve *sm2Curve) pointFromAffine(x, y *big.Int) (p *_sm2ec.SM2P256Point, err error) {
|
||||
p = curve.newPoint()
|
||||
// (0, 0) is by convention the point at infinity, which can't be represented
|
||||
// in affine coordinates. See Issue 37294.
|
||||
@ -60,7 +57,7 @@ func (curve *sm2Curve) pointFromAffine(x, y *big.Int) (p *_sm2ec.P256Point, err
|
||||
return p.SetBytes(buf)
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) pointToAffine(p *_sm2ec.P256Point) (x, y *big.Int) {
|
||||
func (curve *sm2Curve) pointToAffine(p *_sm2ec.SM2P256Point) (x, y *big.Int) {
|
||||
out := p.Bytes()
|
||||
if len(out) == 1 && out[0] == 0 {
|
||||
// This is the encoding of the point at infinity, which the affine
|
@ -1,180 +0,0 @@
|
||||
//go:build !amd64 && !arm64 || generic
|
||||
// +build !amd64,!arm64 generic
|
||||
|
||||
package sm2ec
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
_sm2ec "github.com/emmansun/gmsm/internal/sm2ec"
|
||||
)
|
||||
|
||||
// TODO: will merge it with sm2p256_asm_ec.go from golang 1.18 with generic support.
|
||||
type sm2Curve struct {
|
||||
newPoint func() *_sm2ec.SM2P256Point
|
||||
params *elliptic.CurveParams
|
||||
}
|
||||
|
||||
var sm2p256 = &sm2Curve{newPoint: _sm2ec.NewSM2P256Point}
|
||||
|
||||
func initSM2P256() {
|
||||
sm2p256.params = sm2Params
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) Params() *elliptic.CurveParams {
|
||||
return curve.params
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) IsOnCurve(x, y *big.Int) bool {
|
||||
// IsOnCurve is documented to reject (0, 0), the conventional point at
|
||||
// infinity, which however is accepted by pointFromAffine.
|
||||
if x.Sign() == 0 && y.Sign() == 0 {
|
||||
return false
|
||||
}
|
||||
_, err := curve.pointFromAffine(x, y)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) pointFromAffine(x, y *big.Int) (p *_sm2ec.SM2P256Point, err error) {
|
||||
p = curve.newPoint()
|
||||
// (0, 0) is by convention the point at infinity, which can't be represented
|
||||
// in affine coordinates. See Issue 37294.
|
||||
if x.Sign() == 0 && y.Sign() == 0 {
|
||||
return p, nil
|
||||
}
|
||||
// Reject values that would not get correctly encoded.
|
||||
if x.Sign() < 0 || y.Sign() < 0 {
|
||||
return p, errors.New("negative coordinate")
|
||||
}
|
||||
if x.BitLen() > curve.params.BitSize || y.BitLen() > curve.params.BitSize {
|
||||
return p, errors.New("overflowing coordinate")
|
||||
}
|
||||
// Encode the coordinates and let SetBytes reject invalid points.
|
||||
byteLen := (curve.params.BitSize + 7) / 8
|
||||
buf := make([]byte, 1+2*byteLen)
|
||||
buf[0] = 4 // uncompressed point
|
||||
x.FillBytes(buf[1 : 1+byteLen])
|
||||
y.FillBytes(buf[1+byteLen : 1+2*byteLen])
|
||||
return p.SetBytes(buf)
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) pointToAffine(p *_sm2ec.SM2P256Point) (x, y *big.Int) {
|
||||
out := p.Bytes()
|
||||
if len(out) == 1 && out[0] == 0 {
|
||||
// This is the encoding of the point at infinity, which the affine
|
||||
// coordinates API represents as (0, 0) by convention.
|
||||
return new(big.Int), new(big.Int)
|
||||
}
|
||||
byteLen := (curve.params.BitSize + 7) / 8
|
||||
x = new(big.Int).SetBytes(out[1 : 1+byteLen])
|
||||
y = new(big.Int).SetBytes(out[1+byteLen:])
|
||||
return x, y
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
|
||||
p1, err := curve.pointFromAffine(x1, y1)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: Add was called on an invalid point")
|
||||
}
|
||||
p2, err := curve.pointFromAffine(x2, y2)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: Add was called on an invalid point")
|
||||
}
|
||||
return curve.pointToAffine(p1.Add(p1, p2))
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
|
||||
p, err := curve.pointFromAffine(x1, y1)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: Double was called on an invalid point")
|
||||
}
|
||||
return curve.pointToAffine(p.Double(p))
|
||||
}
|
||||
|
||||
// normalizeScalar brings the scalar within the byte size of the order of the
|
||||
// curve, as expected by the nistec scalar multiplication functions.
|
||||
func (curve *sm2Curve) normalizeScalar(scalar []byte) []byte {
|
||||
byteSize := (curve.params.N.BitLen() + 7) / 8
|
||||
if len(scalar) == byteSize {
|
||||
return scalar
|
||||
}
|
||||
s := new(big.Int).SetBytes(scalar)
|
||||
if len(scalar) > byteSize {
|
||||
s.Mod(s, curve.params.N)
|
||||
}
|
||||
out := make([]byte, byteSize)
|
||||
return s.FillBytes(out)
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
|
||||
p, err := curve.pointFromAffine(Bx, By)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: ScalarMult was called on an invalid point")
|
||||
}
|
||||
scalar = curve.normalizeScalar(scalar)
|
||||
p, err = p.ScalarMult(p, scalar)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: sm2 rejected normalized scalar")
|
||||
}
|
||||
return curve.pointToAffine(p)
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) ScalarBaseMult(scalar []byte) (*big.Int, *big.Int) {
|
||||
scalar = curve.normalizeScalar(scalar)
|
||||
p, err := curve.newPoint().ScalarBaseMult(scalar)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: sm2 rejected normalized scalar")
|
||||
}
|
||||
return curve.pointToAffine(p)
|
||||
}
|
||||
|
||||
// CombinedMult returns [s1]G + [s2]P where G is the generator. It's used
|
||||
// through an interface upgrade in crypto/ecdsa.
|
||||
func (curve *sm2Curve) CombinedMult(Px, Py *big.Int, s1, s2 []byte) (x, y *big.Int) {
|
||||
s1 = curve.normalizeScalar(s1)
|
||||
q, err := curve.newPoint().ScalarBaseMult(s1)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: sm2 rejected normalized scalar")
|
||||
}
|
||||
p, err := curve.pointFromAffine(Px, Py)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: CombinedMult was called on an invalid point")
|
||||
}
|
||||
s2 = curve.normalizeScalar(s2)
|
||||
p, err = p.ScalarMult(p, s2)
|
||||
if err != nil {
|
||||
panic("sm2/elliptic: sm2 rejected normalized scalar")
|
||||
}
|
||||
return curve.pointToAffine(p.Add(p, q))
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) Unmarshal(data []byte) (x, y *big.Int) {
|
||||
if len(data) == 0 || data[0] != 4 {
|
||||
return nil, nil
|
||||
}
|
||||
// Use SetBytes to check that data encodes a valid point.
|
||||
_, err := curve.newPoint().SetBytes(data)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
// We don't use pointToAffine because it involves an expensive field
|
||||
// inversion to convert from Jacobian to affine coordinates, which we
|
||||
// already have.
|
||||
byteLen := (curve.params.BitSize + 7) / 8
|
||||
x = new(big.Int).SetBytes(data[1 : 1+byteLen])
|
||||
y = new(big.Int).SetBytes(data[1+byteLen:])
|
||||
return x, y
|
||||
}
|
||||
|
||||
func (curve *sm2Curve) UnmarshalCompressed(data []byte) (x, y *big.Int) {
|
||||
if len(data) == 0 || (data[0] != 2 && data[0] != 3) {
|
||||
return nil, nil
|
||||
}
|
||||
p, err := curve.newPoint().SetBytes(data)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
return curve.pointToAffine(p)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user