From 8b1d31080a7692e075c4681cb2458454a1fe0706 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Tue, 1 May 2018 13:57:54 -0400 Subject: [PATCH] =?UTF-8?q?bn256:=20explicitly=20fix=20MakeAffine=20for=20?= =?UTF-8?q?=E2=88=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When c = ∞, z = 0 and 0 does not have a modular inverse, triggering undefined behavior (recently changed to returning nil) in ModInverse. Unclear how this used to work anyway. Looks like ModInverse was leaving the receiver untouched, making zInv = 0 when pool = nil. Fixes golang/go#25199 Change-Id: Ib39abf59f0e71cf43cdb5836142ebdd3b206fb3f Reviewed-on: https://go-review.googlesource.com/110695 Run-TryBot: Filippo Valsorda TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda Reviewed-by: Adam Langley --- bn256/bn256.go | 18 ++++++++++++++---- bn256/curve.go | 9 +++++++++ bn256/twist.go | 9 +++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/bn256/bn256.go b/bn256/bn256.go index f88f3fc..479e731 100644 --- a/bn256/bn256.go +++ b/bn256/bn256.go @@ -97,13 +97,18 @@ func (e *G1) Neg(a *G1) *G1 { // Marshal converts n to a byte slice. func (e *G1) Marshal() []byte { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + if e.p.IsInfinity() { + return make([]byte, numBytes*2) + } + e.p.MakeAffine(nil) xBytes := new(big.Int).Mod(e.p.x, p).Bytes() yBytes := new(big.Int).Mod(e.p.y, p).Bytes() - // Each value is a 256-bit number. - const numBytes = 256 / 8 ret := make([]byte, numBytes*2) copy(ret[1*numBytes-len(xBytes):], xBytes) @@ -205,6 +210,13 @@ func (e *G2) Add(a, b *G2) *G2 { // Marshal converts n into a byte slice. func (n *G2) Marshal() []byte { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + if n.p.IsInfinity() { + return make([]byte, numBytes*4) + } + n.p.MakeAffine(nil) xxBytes := new(big.Int).Mod(n.p.x.x, p).Bytes() @@ -212,8 +224,6 @@ func (n *G2) Marshal() []byte { yxBytes := new(big.Int).Mod(n.p.y.x, p).Bytes() yyBytes := new(big.Int).Mod(n.p.y.y, p).Bytes() - // Each value is a 256-bit number. - const numBytes = 256 / 8 ret := make([]byte, numBytes*4) copy(ret[1*numBytes-len(xxBytes):], xxBytes) diff --git a/bn256/curve.go b/bn256/curve.go index 55b7063..63c052b 100644 --- a/bn256/curve.go +++ b/bn256/curve.go @@ -245,10 +245,19 @@ func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoi return c } +// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets +// c to 0 : 1 : 0. func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint { if words := c.z.Bits(); len(words) == 1 && words[0] == 1 { return c } + if c.IsInfinity() { + c.x.SetInt64(0) + c.y.SetInt64(1) + c.z.SetInt64(0) + c.t.SetInt64(0) + return c + } zInv := pool.Get().ModInverse(c.z, p) t := pool.Get().Mul(c.y, zInv) diff --git a/bn256/twist.go b/bn256/twist.go index 4f8b3fe..056d80f 100644 --- a/bn256/twist.go +++ b/bn256/twist.go @@ -219,10 +219,19 @@ func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoi return c } +// MakeAffine converts c to affine form and returns c. If c is ∞, then it sets +// c to 0 : 1 : 0. func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint { if c.z.IsOne() { return c } + if c.IsInfinity() { + c.x.SetZero() + c.y.SetOne() + c.z.SetZero() + c.t.SetZero() + return c + } zInv := newGFp2(pool).Invert(c.z, pool) t := newGFp2(pool).Mul(c.y, zInv, pool)