~vcs-imports/putty/master

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
#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 *wc);
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);

/* ----------------------------------------------------------------------
 * 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 *ec);
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 */