ScalarBaseMult(k []byte) (x, y *big.Int)
}
+func matchesSpecificCurve(params *CurveParams, available ...Curve) (Curve, bool) {
+ for _, c := range available {
+ if params == c.Params() {
+ return c, true
+ }
+ }
+ return nil, false
+}
+
// CurveParams contains the parameters of an elliptic curve and also provides
// a generic, non-constant time implementation of Curve.
type CurveParams struct {
}
func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
+ // If there is a dedicated constant-time implementation for this curve operation,
+ // use that instead of the generic one.
+ if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+ return specific.IsOnCurve(x, y)
+ }
+
// y² = x³ - 3x + b
y2 := new(big.Int).Mul(y, y)
y2.Mod(y2, curve.P)
}
func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+ // If there is a dedicated constant-time implementation for this curve operation,
+ // use that instead of the generic one.
+ if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+ return specific.Add(x1, y1, x2, y2)
+ }
+
z1 := zForAffine(x1, y1)
z2 := zForAffine(x2, y2)
return curve.affineFromJacobian(curve.addJacobian(x1, y1, z1, x2, y2, z2))
}
func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+ // If there is a dedicated constant-time implementation for this curve operation,
+ // use that instead of the generic one.
+ if specific, ok := matchesSpecificCurve(curve, p224, p521); ok {
+ return specific.Double(x1, y1)
+ }
+
z1 := zForAffine(x1, y1)
return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1))
}
}
func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
+ // If there is a dedicated constant-time implementation for this curve operation,
+ // use that instead of the generic one.
+ if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok {
+ return specific.ScalarMult(Bx, By, k)
+ }
+
Bz := new(big.Int).SetInt64(1)
x, y, z := new(big.Int), new(big.Int), new(big.Int)
}
func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
+ // If there is a dedicated constant-time implementation for this curve operation,
+ // use that instead of the generic one.
+ if specific, ok := matchesSpecificCurve(curve, p224, p256, p521); ok {
+ return specific.ScalarBaseMult(k)
+ }
+
return curve.ScalarMult(curve.Gx, curve.Gy, k)
}
"testing"
)
+// genericParamsForCurve returns the dereferenced CurveParams for
+// the specified curve. This is used to avoid the logic for
+// upgrading a curve to it's specific implementation, forcing
+// usage of the generic implementation. This is only relevant
+// for the P224, P256, and P521 curves.
+func genericParamsForCurve(c Curve) *CurveParams {
+ d := *(c.Params())
+ return &d
+}
+
func testAllCurves(t *testing.T, f func(*testing.T, Curve)) {
tests := []struct {
name string
curve Curve
}{
{"P256", P256()},
- {"P256/Params", P256().Params()},
+ {"P256/Params", genericParamsForCurve(P256())},
{"P224", P224()},
- {"P224/Params", P224().Params()},
+ {"P224/Params", genericParamsForCurve(P224())},
{"P384", P384()},
- {"P384/Params", P384().Params()},
+ {"P384/Params", genericParamsForCurve(P384())},
{"P521", P521()},
- {"P521/Params", P521().Params()},
+ {"P521/Params", genericParamsForCurve(P521())},
}
if testing.Short() {
tests = tests[:1]