1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
|
#ifndef PUTTY_ECC_H
#define PUTTY_ECC_H
/*
* Arithmetic functions for the various kinds of elliptic curves used
* by PuTTY's public-key cryptography.
*
* All of these elliptic curves are over the finite field whose order
* is a large prime p. (Elliptic curves over a field of order 2^n are
* also known, but PuTTY currently has no need of them.)
*/
/* ----------------------------------------------------------------------
* Weierstrass curves (or rather, 'short form' Weierstrass curves).
*
* A curve in this form is defined by two parameters a,b, and the
* non-identity points on the curve are represented by (x,y) (the
* 'affine coordinates') such that y^2 = x^3 + ax + b.
*
* The identity element of the curve's group is an additional 'point
* at infinity', which is considered to be the third point on the
* intersection of the curve with any vertical line. Hence, the
* inverse of the point (x,y) is (x,-y).
*/
/*
* Create and destroy Weierstrass curve data structures. The mandatory
* parameters to the constructor are the prime modulus p, and the
* curve parameters a,b.
*
* 'nonsquare_mod_p' is an optional extra parameter, only needed by
* ecc_edwards_point_new_from_y which has to take a modular square
* root. You can pass it as NULL if you don't need that function.
*/
WeierstrassCurve *ecc_weierstrass_curve(
mp_int *p, mp_int *a, mp_int *b, mp_int *nonsquare_mod_p);
void ecc_weierstrass_curve_free(WeierstrassCurve *);
/*
* Create points on a Weierstrass curve, given the curve.
*
* point_new_identity returns the special identity point.
* point_new(x,y) returns the non-identity point with the given affine
* coordinates.
*
* point_new_from_x constructs a non-identity point given only the
* x-coordinate, by using the curve equation to work out what y has to
* be. Of course the equation only tells you y^2, so it only
* determines y up to sign; the parameter desired_y_parity controls
* which of the two values of y you get, by saying whether you'd like
* its minimal non-negative residue mod p to be even or odd. (Of
* course, since p itself is odd, exactly one of y and p-y is odd.)
* This function has to take a modular square root, so it will only
* work if you passed in a non-square mod p when constructing the
* curve.
*/
WeierstrassPoint *ecc_weierstrass_point_new_identity(WeierstrassCurve *curve);
WeierstrassPoint *ecc_weierstrass_point_new(
WeierstrassCurve *curve, mp_int *x, mp_int *y);
WeierstrassPoint *ecc_weierstrass_point_new_from_x(
WeierstrassCurve *curve, mp_int *x, unsigned desired_y_parity);
/* Memory management: copy and free points. */
void ecc_weierstrass_point_copy_into(
WeierstrassPoint *dest, WeierstrassPoint *src);
WeierstrassPoint *ecc_weierstrass_point_copy(WeierstrassPoint *orig);
void ecc_weierstrass_point_free(WeierstrassPoint *point);
/* Check whether a point is actually on the curve. */
unsigned ecc_weierstrass_point_valid(WeierstrassPoint *);
/*
* Add two points and return their sum. This function is fully
* general: it should do the right thing if the two inputs are the
* same, or if either (or both) of the input points is the identity,
* or if the two input points are inverses so the output is the
* identity. However, it pays for that generality by being slower than
* the special-purpose functions below..
*/
WeierstrassPoint *ecc_weierstrass_add_general(
WeierstrassPoint *, WeierstrassPoint *);
/*
* Fast but less general arithmetic functions: add two points on the
* condition that they are not equal and neither is the identity, and
* add a point to itself.
*/
WeierstrassPoint *ecc_weierstrass_add(WeierstrassPoint *, WeierstrassPoint *);
WeierstrassPoint *ecc_weierstrass_double(WeierstrassPoint *);
/*
* Compute an integer multiple of a point. Not guaranteed to work
* unless the integer argument is less than the order of the point in
* the group (because it won't cope if an identity element shows up in
* any intermediate product).
*/
WeierstrassPoint *ecc_weierstrass_multiply(WeierstrassPoint *, mp_int *);
/*
* Query functions to get the value of a point back out. is_identity
* tells you whether the point is the identity; if it isn't, then
* get_affine will retrieve one or both of its affine coordinates.
* (You can pass NULL as either output pointer, if you don't need that
* coordinate as output.)
*/
unsigned ecc_weierstrass_is_identity(WeierstrassPoint *wp);
void ecc_weierstrass_get_affine(WeierstrassPoint *wp, mp_int **x, mp_int **y);
/* ----------------------------------------------------------------------
* Montgomery curves.
*
* A curve in this form is defined by two parameters a,b, and the
* curve equation is by^2 = x^3 + ax^2 + x.
*
* As with Weierstrass curves, there's an additional point at infinity
* that is the identity element, and the inverse of (x,y) is (x,-y).
*
* However, we don't actually work with full (x,y) pairs. We just
* store the x-coordinate (so what we're really representing is not a
* specific point on the curve but a two-point set {P,-P}). This means
* you can't quite do point addition, because if you're given {P,-P}
* and {Q,-Q} as input, you can work out a pair of x-coordinates that
* are those of P-Q and P+Q, but you don't know which is which.
*
* Instead, the basic operation is 'differential addition', in which
* you are given three parameters P, Q and P-Q and you return P+Q. (As
* well as disambiguating which of the possible answers you want, that
* extra input also enables a fast formulae for computing it. This
* fast formula is more or less why Montgomery curves are useful in
* the first place.)
*
* Doubling a point is still possible to do unambiguously, so you can
* still compute an integer multiple of P if you start by making 2P
* and then doing a series of differential additions.
*/
/*
* Create and destroy Montgomery curve data structures.
*/
MontgomeryCurve *ecc_montgomery_curve(mp_int *p, mp_int *a, mp_int *b);
void ecc_montgomery_curve_free(MontgomeryCurve *);
/*
* Create, copy and free points on the curve. We don't need to
* explicitly represent the identity for this application.
*/
MontgomeryPoint *ecc_montgomery_point_new(MontgomeryCurve *mc, mp_int *x);
void ecc_montgomery_point_copy_into(
MontgomeryPoint *dest, MontgomeryPoint *src);
MontgomeryPoint *ecc_montgomery_point_copy(MontgomeryPoint *orig);
void ecc_montgomery_point_free(MontgomeryPoint *mp);
/*
* Basic arithmetic routines: differential addition and point-
* doubling. Each of these assumes that no special cases come up - no
* input or output point should be the identity, and in diff_add, P
* and Q shouldn't be the same.
*/
MontgomeryPoint *ecc_montgomery_diff_add(
MontgomeryPoint *P, MontgomeryPoint *Q, MontgomeryPoint *PminusQ);
MontgomeryPoint *ecc_montgomery_double(MontgomeryPoint *P);
/*
* Compute an integer multiple of a point.
*/
MontgomeryPoint *ecc_montgomery_multiply(MontgomeryPoint *, mp_int *);
/*
* Return the affine x-coordinate of a point.
*/
void ecc_montgomery_get_affine(MontgomeryPoint *mp, mp_int **x);
/*
* Test whether a point is the curve identity.
*/
unsigned ecc_montgomery_is_identity(MontgomeryPoint *mp);
/* ----------------------------------------------------------------------
* Twisted Edwards curves.
*
* A curve in this form is defined by two parameters d,a, and the
* curve equation is a x^2 + y^2 = 1 + d x^2 y^2.
*
* Apparently if you ask a proper algebraic geometer they'll tell you
* that this is technically not an actual elliptic curve. Certainly it
* doesn't work quite the same way as the other kinds: in this form,
* there is no need for a point at infinity, because the identity
* element is represented by the affine coordinates (0,1). And you
* invert a point by negating its x rather than y coordinate: the
* inverse of (x,y) is (-x,y).
*
* The usefulness of this representation is that the addition formula
* is 'strongly unified', meaning that the same formula works for any
* input and output points, without needing special cases for the
* identity or for doubling.
*/
/*
* Create and destroy Edwards curve data structures.
*
* Similarly to ecc_weierstrass_curve, you don't have to provide
* nonsquare_mod_p if you don't need ecc_edwards_point_new_from_y.
*/
EdwardsCurve *ecc_edwards_curve(
mp_int *p, mp_int *d, mp_int *a, mp_int *nonsquare_mod_p);
void ecc_edwards_curve_free(EdwardsCurve *);
/*
* Create points.
*
* There's no need to have a separate function to create the identity
* point, because you can just pass x=0 and y=1 to the usual function.
*
* Similarly to the Weierstrass curve, ecc_edwards_point_new_from_y
* creates a point given only its y-coordinate and the desired parity
* of its x-coordinate, and you can only call it if you provided the
* optional nonsquare_mod_p argument when creating the curve.
*/
EdwardsPoint *ecc_edwards_point_new(
EdwardsCurve *curve, mp_int *x, mp_int *y);
EdwardsPoint *ecc_edwards_point_new_from_y(
EdwardsCurve *curve, mp_int *y, unsigned desired_x_parity);
/* Copy and free points. */
void ecc_edwards_point_copy_into(EdwardsPoint *dest, EdwardsPoint *src);
EdwardsPoint *ecc_edwards_point_copy(EdwardsPoint *orig);
void ecc_edwards_point_free(EdwardsPoint *point);
/*
* Arithmetic: add two points, and calculate an integer multiple of a
* point.
*/
EdwardsPoint *ecc_edwards_add(EdwardsPoint *, EdwardsPoint *);
EdwardsPoint *ecc_edwards_multiply(EdwardsPoint *, mp_int *);
/*
* Query functions: compare two points for equality, and return the
* affine coordinates of a point.
*/
unsigned ecc_edwards_eq(EdwardsPoint *, EdwardsPoint *);
void ecc_edwards_get_affine(EdwardsPoint *wp, mp_int **x, mp_int **y);
#endif /* PUTTY_ECC_H */
|