1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
8 "crypto/elliptic/internal/nistec"
13 // p224Curve is a Curve implementation based on nistec.P224Point.
15 // It's a wrapper that exposes the big.Int-based Curve interface and encodes the
16 // legacy idiosyncrasies it requires, such as invalid and infinity point
19 // To interact with the nistec package, points are encoded into and decoded from
20 // properly formatted byte slices. All big.Int use is limited to this package.
21 // Encoding and decoding is 1/1000th of the runtime of a scalar multiplication,
22 // so the overhead is acceptable.
23 type p224Curve
struct {
31 p224
.params
= &CurveParams
{
34 // FIPS 186-4, section D.1.2.2
35 P
: bigFromDecimal("26959946667150639794667015087019630673557916260026308143510066298881"),
36 N
: bigFromDecimal("26959946667150639794667015087019625940457807714424391721682722368061"),
37 B
: bigFromHex("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"),
38 Gx
: bigFromHex("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"),
39 Gy
: bigFromHex("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"),
43 func (curve p224Curve
) Params() *CurveParams
{
47 func (curve p224Curve
) IsOnCurve(x
, y
*big
.Int
) bool {
48 // IsOnCurve is documented to reject (0, 0), the conventional point at
49 // infinity, which however is accepted by p224PointFromAffine.
50 if x
.Sign() == 0 && y
.Sign() == 0 {
53 _
, ok
:= p224PointFromAffine(x
, y
)
57 func p224PointFromAffine(x
, y
*big
.Int
) (p
*nistec
.P224Point
, ok
bool) {
58 // (0, 0) is by convention the point at infinity, which can't be represented
59 // in affine coordinates. Marshal incorrectly encodes it as an uncompressed
60 // point, which SetBytes would correctly reject. See Issue 37294.
61 if x
.Sign() == 0 && y
.Sign() == 0 {
62 return nistec
.NewP224Point(), true
64 if x
.Sign() < 0 || y
.Sign() < 0 {
67 if x
.BitLen() > 224 || y
.BitLen() > 224 {
70 p
, err
:= nistec
.NewP224Point().SetBytes(Marshal(P224(), x
, y
))
77 func p224PointToAffine(p
*nistec
.P224Point
) (x
, y
*big
.Int
) {
79 if len(out
) == 1 && out
[0] == 0 {
80 // This is the correct encoding of the point at infinity, which
81 // Unmarshal does not support. See Issue 37294.
82 return new(big
.Int
), new(big
.Int
)
84 x
, y
= Unmarshal(P224(), out
)
86 panic("crypto/elliptic: internal error: Unmarshal rejected a valid point encoding")
91 // p224RandomPoint returns a random point on the curve. It's used when Add,
92 // Double, or ScalarMult are fed a point not on the curve, which is undefined
93 // behavior. Originally, we used to do the math on it anyway (which allows
94 // invalid curve attacks) and relied on the caller and Unmarshal to avoid this
95 // happening in the first place. Now, we just can't construct a nistec.P224Point
96 // for an invalid pair of coordinates, because that API is safer. If we panic,
97 // we risk introducing a DoS. If we return nil, we risk a panic. If we return
98 // the input, ecdsa.Verify might fail open. The safest course seems to be to
99 // return a valid, random point, which hopefully won't help the attacker.
100 func p224RandomPoint() (x
, y
*big
.Int
) {
101 _
, x
, y
, err
:= GenerateKey(P224(), rand
.Reader
)
103 panic("crypto/elliptic: failed to generate random point")
108 func (p224Curve
) Add(x1
, y1
, x2
, y2
*big
.Int
) (*big
.Int
, *big
.Int
) {
109 p1
, ok
:= p224PointFromAffine(x1
, y1
)
111 return p224RandomPoint()
113 p2
, ok
:= p224PointFromAffine(x2
, y2
)
115 return p224RandomPoint()
117 return p224PointToAffine(p1
.Add(p1
, p2
))
120 func (p224Curve
) Double(x1
, y1
*big
.Int
) (*big
.Int
, *big
.Int
) {
121 p
, ok
:= p224PointFromAffine(x1
, y1
)
123 return p224RandomPoint()
125 return p224PointToAffine(p
.Double(p
))
128 func (p224Curve
) ScalarMult(Bx
, By
*big
.Int
, scalar
[]byte) (*big
.Int
, *big
.Int
) {
129 p
, ok
:= p224PointFromAffine(Bx
, By
)
131 return p224RandomPoint()
133 return p224PointToAffine(p
.ScalarMult(p
, scalar
))
136 func (p224Curve
) ScalarBaseMult(scalar
[]byte) (*big
.Int
, *big
.Int
) {
137 p
:= nistec
.NewP224Generator()
138 return p224PointToAffine(p
.ScalarMult(p
, scalar
))