Skip to content

Commit 3b8a031

Browse files
committed
crypto/elliptic: fix incomplete addition used in CombinedMult on s390x
This applies the amd64-specific changes from CL 42611 to the s390x P256 implementation. The s390x implementation was disabled in CL 62292 and this CL re-enables it. Adam Langley's commit message from CL 42611: The optimised P-256 includes a CombinedMult function, which doesn't do dual-scalar multiplication, but does avoid an affine conversion for ECDSA verification. However, it currently uses an assembly point addition function that doesn't handle exceptional cases. Fixes #20215. Change-Id: I2f6b532f495e85b8903475b4f64cc32a3b2f6769 Reviewed-on: https://go-review.googlesource.com/64290 Run-TryBot: Michael Munday <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent d24a36c commit 3b8a031

File tree

2 files changed

+63
-12
lines changed

2 files changed

+63
-12
lines changed

src/crypto/elliptic/p256_asm_s390x.s

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,10 +1944,12 @@ TEXT ·p256PointDoubleAsm(SB), NOSPLIT, $0
19441944
#undef CAR2
19451945

19461946
// p256PointAddAsm(P3, P1, P2 *p256Point)
1947-
#define P3ptr R1
1948-
#define P1ptr R2
1949-
#define P2ptr R3
1950-
#define CPOOL R4
1947+
#define P3ptr R1
1948+
#define P1ptr R2
1949+
#define P2ptr R3
1950+
#define CPOOL R4
1951+
#define ISZERO R5
1952+
#define TRUE R6
19511953

19521954
// Temporaries in REGs
19531955
#define T1L V16
@@ -2102,6 +2104,21 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $0
21022104
// SUB(H<H-T) // H = H-U1
21032105
p256SubInternal(HH,HL,HH,HL,T1,T0)
21042106

2107+
// if H == 0 or H^P == 0 then ret=1 else ret=0
2108+
// clobbers T1H and T1L
2109+
MOVD $0, ISZERO
2110+
MOVD $1, TRUE
2111+
VZERO ZER
2112+
VO HL, HH, T1H
2113+
VCEQGS ZER, T1H, T1H
2114+
MOVDEQ TRUE, ISZERO
2115+
VX HL, PL, T1L
2116+
VX HH, PH, T1H
2117+
VO T1L, T1H, T1H
2118+
VCEQGS ZER, T1H, T1H
2119+
MOVDEQ TRUE, ISZERO
2120+
MOVD ISZERO, ret+24(FP)
2121+
21052122
// X=Z1; Y=Z2; MUL; T- // Z3 = Z1*Z2
21062123
VL 64(P1ptr), X1 // Z1H
21072124
VL 80(P1ptr), X0 // Z1L
@@ -2137,6 +2154,22 @@ TEXT ·p256PointAddAsm(SB), NOSPLIT, $0
21372154
// SUB(R<T-S1) // R = T-S1
21382155
p256SubInternal(RH,RL,T1,T0,S1H,S1L)
21392156

2157+
// if R == 0 or R^P == 0 then ret=ret else ret=0
2158+
// clobbers T1H and T1L
2159+
MOVD $0, ISZERO
2160+
MOVD $1, TRUE
2161+
VZERO ZER
2162+
VO RL, RH, T1H
2163+
VCEQGS ZER, T1H, T1H
2164+
MOVDEQ TRUE, ISZERO
2165+
VX RL, PL, T1L
2166+
VX RH, PH, T1H
2167+
VO T1L, T1H, T1H
2168+
VCEQGS ZER, T1H, T1H
2169+
MOVDEQ TRUE, ISZERO
2170+
AND ret+24(FP), ISZERO
2171+
MOVD ISZERO, ret+24(FP)
2172+
21402173
// X=H ; Y=H ; MUL; T- // T1 = H*H
21412174
VLR HL, X0
21422175
VLR HH, X1

src/crypto/elliptic/p256_s390x.go

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package elliptic
88

99
import (
10+
"crypto/subtle"
1011
"math/big"
1112
)
1213

@@ -32,10 +33,7 @@ func hasVectorFacility() bool
3233
var hasVX = hasVectorFacility()
3334

3435
func initP256Arch() {
35-
// Assembly implementation is temporarily disabled until issue
36-
// #20215 is fixed.
37-
// if hasVX {
38-
if false {
36+
if hasVX {
3937
p256 = p256CurveFast{p256Params}
4038
initTable()
4139
return
@@ -90,7 +88,7 @@ func p256OrdSqr(res, in []byte, n int) {
9088
func p256PointAddAffineAsm(P3, P1, P2 *p256Point, sign, sel, zero int)
9189

9290
// Point add
93-
func p256PointAddAsm(P3, P1, P2 *p256Point)
91+
func p256PointAddAsm(P3, P1, P2 *p256Point) int
9492
func p256PointDoubleAsm(P3, P1 *p256Point)
9593

9694
func (curve p256CurveFast) Inverse(k *big.Int) *big.Int {
@@ -205,17 +203,27 @@ func maybeReduceModP(in *big.Int) *big.Int {
205203

206204
func (curve p256CurveFast) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) {
207205
var r1, r2 p256Point
208-
r1.p256BaseMult(p256GetMultiplier(baseScalar))
206+
scalarReduced := p256GetMultiplier(baseScalar)
207+
r1IsInfinity := scalarIsZero(scalarReduced)
208+
r1.p256BaseMult(scalarReduced)
209209

210210
copy(r2.x[:], fromBig(maybeReduceModP(bigX)))
211211
copy(r2.y[:], fromBig(maybeReduceModP(bigY)))
212212
copy(r2.z[:], one)
213213
p256MulAsm(r2.x[:], r2.x[:], rr[:])
214214
p256MulAsm(r2.y[:], r2.y[:], rr[:])
215215

216+
scalarReduced = p256GetMultiplier(scalar)
217+
r2IsInfinity := scalarIsZero(scalarReduced)
216218
r2.p256ScalarMult(p256GetMultiplier(scalar))
217-
p256PointAddAsm(&r1, &r1, &r2)
218-
return r1.p256PointToAffine()
219+
220+
var sum, double p256Point
221+
pointsEqual := p256PointAddAsm(&sum, &r1, &r2)
222+
p256PointDoubleAsm(&double, &r1)
223+
p256MovCond(&sum, &double, &sum, pointsEqual)
224+
p256MovCond(&sum, &r1, &sum, r2IsInfinity)
225+
p256MovCond(&sum, &r2, &sum, r1IsInfinity)
226+
return sum.p256PointToAffine()
219227
}
220228

221229
func (curve p256CurveFast) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
@@ -235,6 +243,16 @@ func (curve p256CurveFast) ScalarMult(bigX, bigY *big.Int, scalar []byte) (x, y
235243
return r.p256PointToAffine()
236244
}
237245

246+
// scalarIsZero returns 1 if scalar represents the zero value, and zero
247+
// otherwise.
248+
func scalarIsZero(scalar []byte) int {
249+
b := byte(0)
250+
for _, s := range scalar {
251+
b |= s
252+
}
253+
return subtle.ConstantTimeByteEq(b, 0)
254+
}
255+
238256
func (p *p256Point) p256PointToAffine() (x, y *big.Int) {
239257
zInv := make([]byte, 32)
240258
zInvSq := make([]byte, 32)

0 commit comments

Comments
 (0)