summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/ec')
-rw-r--r--src/lib/libcrypto/ec/ec.h1100
-rw-r--r--src/lib/libcrypto/ec/ec2_mult.c390
-rw-r--r--src/lib/libcrypto/ec/ec2_oct.c407
-rw-r--r--src/lib/libcrypto/ec/ec2_smpl.c1042
-rw-r--r--src/lib/libcrypto/ec/ec_ameth.c660
-rw-r--r--src/lib/libcrypto/ec/ec_asn1.c1443
-rw-r--r--src/lib/libcrypto/ec/ec_check.c (renamed from src/lib/libcrypto/ec/ec2_smpt.c)83
-rw-r--r--src/lib/libcrypto/ec/ec_curve.c2100
-rw-r--r--src/lib/libcrypto/ec/ec_cvt.c (renamed from src/lib/libcrypto/ec/ecp_recp.c)157
-rw-r--r--src/lib/libcrypto/ec/ec_err.c258
-rw-r--r--src/lib/libcrypto/ec/ec_key.c563
-rw-r--r--src/lib/libcrypto/ec/ec_lcl.h393
-rw-r--r--src/lib/libcrypto/ec/ec_lib.c1164
-rw-r--r--src/lib/libcrypto/ec/ec_mult.c940
-rw-r--r--src/lib/libcrypto/ec/ec_oct.c199
-rw-r--r--src/lib/libcrypto/ec/ec_pmeth.c341
-rw-r--r--src/lib/libcrypto/ec/ec_print.c195
-rw-r--r--src/lib/libcrypto/ec/eck_prn.c392
-rw-r--r--src/lib/libcrypto/ec/ecp_mont.c315
-rw-r--r--src/lib/libcrypto/ec/ecp_nist.c210
-rw-r--r--src/lib/libcrypto/ec/ecp_nistp224.c1658
-rw-r--r--src/lib/libcrypto/ec/ecp_nistp256.c2171
-rw-r--r--src/lib/libcrypto/ec/ecp_nistp521.c2025
-rw-r--r--src/lib/libcrypto/ec/ecp_nistputil.c197
-rw-r--r--src/lib/libcrypto/ec/ecp_oct.c433
-rw-r--r--src/lib/libcrypto/ec/ecp_smpl.c1719
-rw-r--r--src/lib/libcrypto/ec/ectest.c341
27 files changed, 20558 insertions, 338 deletions
diff --git a/src/lib/libcrypto/ec/ec.h b/src/lib/libcrypto/ec/ec.h
new file mode 100644
index 0000000000..ee7078130c
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec.h
@@ -0,0 +1,1100 @@
1/* crypto/ec/ec.h */
2/*
3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */
5/**
6 * \file crypto/ec/ec.h Include file for the OpenSSL EC functions
7 * \author Originally written by Bodo Moeller for the OpenSSL project
8 */
9/* ====================================================================
10 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in
21 * the documentation and/or other materials provided with the
22 * distribution.
23 *
24 * 3. All advertising materials mentioning features or use of this
25 * software must display the following acknowledgment:
26 * "This product includes software developed by the OpenSSL Project
27 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
28 *
29 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
30 * endorse or promote products derived from this software without
31 * prior written permission. For written permission, please contact
32 * openssl-core@openssl.org.
33 *
34 * 5. Products derived from this software may not be called "OpenSSL"
35 * nor may "OpenSSL" appear in their names without prior written
36 * permission of the OpenSSL Project.
37 *
38 * 6. Redistributions of any form whatsoever must retain the following
39 * acknowledgment:
40 * "This product includes software developed by the OpenSSL Project
41 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
44 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
46 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
47 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
49 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
50 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
52 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
54 * OF THE POSSIBILITY OF SUCH DAMAGE.
55 * ====================================================================
56 *
57 * This product includes cryptographic software written by Eric Young
58 * (eay@cryptsoft.com). This product includes software written by Tim
59 * Hudson (tjh@cryptsoft.com).
60 *
61 */
62/* ====================================================================
63 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
64 *
65 * Portions of the attached software ("Contribution") are developed by
66 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
67 *
68 * The Contribution is licensed pursuant to the OpenSSL open source
69 * license provided above.
70 *
71 * The elliptic curve binary polynomial software is originally written by
72 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
73 *
74 */
75
76#ifndef HEADER_EC_H
77#define HEADER_EC_H
78
79#include <openssl/opensslconf.h>
80
81#ifdef OPENSSL_NO_EC
82#error EC is disabled.
83#endif
84
85#include <openssl/asn1.h>
86#include <openssl/symhacks.h>
87#ifndef OPENSSL_NO_DEPRECATED
88#include <openssl/bn.h>
89#endif
90
91#ifdef __cplusplus
92extern "C" {
93#elif defined(__SUNPRO_C)
94# if __SUNPRO_C >= 0x520
95# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
96# endif
97#endif
98
99
100#ifndef OPENSSL_ECC_MAX_FIELD_BITS
101# define OPENSSL_ECC_MAX_FIELD_BITS 661
102#endif
103
104/** Enum for the point conversion form as defined in X9.62 (ECDSA)
105 * for the encoding of a elliptic curve point (x,y) */
106typedef enum {
107 /** the point is encoded as z||x, where the octet z specifies
108 * which solution of the quadratic equation y is */
109 POINT_CONVERSION_COMPRESSED = 2,
110 /** the point is encoded as z||x||y, where z is the octet 0x02 */
111 POINT_CONVERSION_UNCOMPRESSED = 4,
112 /** the point is encoded as z||x||y, where the octet z specifies
113 * which solution of the quadratic equation y is */
114 POINT_CONVERSION_HYBRID = 6
115} point_conversion_form_t;
116
117
118typedef struct ec_method_st EC_METHOD;
119
120typedef struct ec_group_st
121 /*
122 EC_METHOD *meth;
123 -- field definition
124 -- curve coefficients
125 -- optional generator with associated information (order, cofactor)
126 -- optional extra data (precomputed table for fast computation of multiples of generator)
127 -- ASN1 stuff
128 */
129 EC_GROUP;
130
131typedef struct ec_point_st EC_POINT;
132
133
134/********************************************************************/
135/* EC_METHODs for curves over GF(p) */
136/********************************************************************/
137
138/** Returns the basic GFp ec methods which provides the basis for the
139 * optimized methods.
140 * \return EC_METHOD object
141 */
142const EC_METHOD *EC_GFp_simple_method(void);
143
144/** Returns GFp methods using montgomery multiplication.
145 * \return EC_METHOD object
146 */
147const EC_METHOD *EC_GFp_mont_method(void);
148
149/** Returns GFp methods using optimized methods for NIST recommended curves
150 * \return EC_METHOD object
151 */
152const EC_METHOD *EC_GFp_nist_method(void);
153
154
155/********************************************************************/
156/* EC_METHOD for curves over GF(2^m) */
157/********************************************************************/
158
159/** Returns the basic GF2m ec method
160 * \return EC_METHOD object
161 */
162const EC_METHOD *EC_GF2m_simple_method(void);
163
164
165/********************************************************************/
166/* EC_GROUP functions */
167/********************************************************************/
168
169/** Creates a new EC_GROUP object
170 * \param meth EC_METHOD to use
171 * \return newly created EC_GROUP object or NULL in case of an error.
172 */
173EC_GROUP *EC_GROUP_new(const EC_METHOD *meth);
174
175/** Frees a EC_GROUP object
176 * \param group EC_GROUP object to be freed.
177 */
178void EC_GROUP_free(EC_GROUP *group);
179
180/** Clears and frees a EC_GROUP object
181 * \param group EC_GROUP object to be cleared and freed.
182 */
183void EC_GROUP_clear_free(EC_GROUP *group);
184
185/** Copies EC_GROUP objects. Note: both EC_GROUPs must use the same EC_METHOD.
186 * \param dst destination EC_GROUP object
187 * \param src source EC_GROUP object
188 * \return 1 on success and 0 if an error occurred.
189 */
190int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src);
191
192/** Creates a new EC_GROUP object and copies the copies the content
193 * form src to the newly created EC_KEY object
194 * \param src source EC_GROUP object
195 * \return newly created EC_GROUP object or NULL in case of an error.
196 */
197EC_GROUP *EC_GROUP_dup(const EC_GROUP *src);
198
199/** Returns the EC_METHOD of the EC_GROUP object.
200 * \param group EC_GROUP object
201 * \return EC_METHOD used in this EC_GROUP object.
202 */
203const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group);
204
205/** Returns the field type of the EC_METHOD.
206 * \param meth EC_METHOD object
207 * \return NID of the underlying field type OID.
208 */
209int EC_METHOD_get_field_type(const EC_METHOD *meth);
210
211/** Sets the generator and it's order/cofactor of a EC_GROUP object.
212 * \param group EC_GROUP object
213 * \param generator EC_POINT object with the generator.
214 * \param order the order of the group generated by the generator.
215 * \param cofactor the index of the sub-group generated by the generator
216 * in the group of all points on the elliptic curve.
217 * \return 1 on success and 0 if an error occured
218 */
219int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor);
220
221/** Returns the generator of a EC_GROUP object.
222 * \param group EC_GROUP object
223 * \return the currently used generator (possibly NULL).
224 */
225const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group);
226
227/** Gets the order of a EC_GROUP
228 * \param group EC_GROUP object
229 * \param order BIGNUM to which the order is copied
230 * \param ctx BN_CTX object (optional)
231 * \return 1 on success and 0 if an error occured
232 */
233int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx);
234
235/** Gets the cofactor of a EC_GROUP
236 * \param group EC_GROUP object
237 * \param cofactor BIGNUM to which the cofactor is copied
238 * \param ctx BN_CTX object (optional)
239 * \return 1 on success and 0 if an error occured
240 */
241int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx);
242
243/** Sets the name of a EC_GROUP object
244 * \param group EC_GROUP object
245 * \param nid NID of the curve name OID
246 */
247void EC_GROUP_set_curve_name(EC_GROUP *group, int nid);
248
249/** Returns the curve name of a EC_GROUP object
250 * \param group EC_GROUP object
251 * \return NID of the curve name OID or 0 if not set.
252 */
253int EC_GROUP_get_curve_name(const EC_GROUP *group);
254
255void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag);
256int EC_GROUP_get_asn1_flag(const EC_GROUP *group);
257
258void EC_GROUP_set_point_conversion_form(EC_GROUP *, point_conversion_form_t);
259point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *);
260
261unsigned char *EC_GROUP_get0_seed(const EC_GROUP *);
262size_t EC_GROUP_get_seed_len(const EC_GROUP *);
263size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len);
264
265/** Sets the parameter of a ec over GFp defined by y^2 = x^3 + a*x + b
266 * \param group EC_GROUP object
267 * \param p BIGNUM with the prime number
268 * \param a BIGNUM with parameter a of the equation
269 * \param b BIGNUM with parameter b of the equation
270 * \param ctx BN_CTX object (optional)
271 * \return 1 on success and 0 if an error occured
272 */
273int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
274
275/** Gets the parameter of the ec over GFp defined by y^2 = x^3 + a*x + b
276 * \param group EC_GROUP object
277 * \param p BIGNUM for the prime number
278 * \param a BIGNUM for parameter a of the equation
279 * \param b BIGNUM for parameter b of the equation
280 * \param ctx BN_CTX object (optional)
281 * \return 1 on success and 0 if an error occured
282 */
283int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
284
285/** Sets the parameter of a ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b
286 * \param group EC_GROUP object
287 * \param p BIGNUM with the polynomial defining the underlying field
288 * \param a BIGNUM with parameter a of the equation
289 * \param b BIGNUM with parameter b of the equation
290 * \param ctx BN_CTX object (optional)
291 * \return 1 on success and 0 if an error occured
292 */
293int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
294
295/** Gets the parameter of the ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b
296 * \param group EC_GROUP object
297 * \param p BIGNUM for the polynomial defining the underlying field
298 * \param a BIGNUM for parameter a of the equation
299 * \param b BIGNUM for parameter b of the equation
300 * \param ctx BN_CTX object (optional)
301 * \return 1 on success and 0 if an error occured
302 */
303int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
304
305/** Returns the number of bits needed to represent a field element
306 * \param group EC_GROUP object
307 * \return number of bits needed to represent a field element
308 */
309int EC_GROUP_get_degree(const EC_GROUP *group);
310
311/** Checks whether the parameter in the EC_GROUP define a valid ec group
312 * \param group EC_GROUP object
313 * \param ctx BN_CTX object (optional)
314 * \return 1 if group is a valid ec group and 0 otherwise
315 */
316int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);
317
318/** Checks whether the discriminant of the elliptic curve is zero or not
319 * \param group EC_GROUP object
320 * \param ctx BN_CTX object (optional)
321 * \return 1 if the discriminant is not zero and 0 otherwise
322 */
323int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx);
324
325/** Compares two EC_GROUP objects
326 * \param a first EC_GROUP object
327 * \param b second EC_GROUP object
328 * \param ctx BN_CTX object (optional)
329 * \return 0 if both groups are equal and 1 otherwise
330 */
331int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx);
332
333/* EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*()
334 * after choosing an appropriate EC_METHOD */
335
336/** Creates a new EC_GROUP object with the specified parameters defined
337 * over GFp (defined by the equation y^2 = x^3 + a*x + b)
338 * \param p BIGNUM with the prime number
339 * \param a BIGNUM with the parameter a of the equation
340 * \param b BIGNUM with the parameter b of the equation
341 * \param ctx BN_CTX object (optional)
342 * \return newly created EC_GROUP object with the specified parameters
343 */
344EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
345
346/** Creates a new EC_GROUP object with the specified parameters defined
347 * over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b)
348 * \param p BIGNUM with the polynomial defining the underlying field
349 * \param a BIGNUM with the parameter a of the equation
350 * \param b BIGNUM with the parameter b of the equation
351 * \param ctx BN_CTX object (optional)
352 * \return newly created EC_GROUP object with the specified parameters
353 */
354EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
355
356/** Creates a EC_GROUP object with a curve specified by a NID
357 * \param nid NID of the OID of the curve name
358 * \return newly created EC_GROUP object with specified curve or NULL
359 * if an error occurred
360 */
361EC_GROUP *EC_GROUP_new_by_curve_name(int nid);
362
363
364/********************************************************************/
365/* handling of internal curves */
366/********************************************************************/
367
368typedef struct {
369 int nid;
370 const char *comment;
371 } EC_builtin_curve;
372
373/* EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number
374 * of all available curves or zero if a error occurred.
375 * In case r ist not zero nitems EC_builtin_curve structures
376 * are filled with the data of the first nitems internal groups */
377size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
378
379
380/********************************************************************/
381/* EC_POINT functions */
382/********************************************************************/
383
384/** Creates a new EC_POINT object for the specified EC_GROUP
385 * \param group EC_GROUP the underlying EC_GROUP object
386 * \return newly created EC_POINT object or NULL if an error occurred
387 */
388EC_POINT *EC_POINT_new(const EC_GROUP *group);
389
390/** Frees a EC_POINT object
391 * \param point EC_POINT object to be freed
392 */
393void EC_POINT_free(EC_POINT *point);
394
395/** Clears and frees a EC_POINT object
396 * \param point EC_POINT object to be cleared and freed
397 */
398void EC_POINT_clear_free(EC_POINT *point);
399
400/** Copies EC_POINT object
401 * \param dst destination EC_POINT object
402 * \param src source EC_POINT object
403 * \return 1 on success and 0 if an error occured
404 */
405int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src);
406
407/** Creates a new EC_POINT object and copies the content of the supplied
408 * EC_POINT
409 * \param src source EC_POINT object
410 * \param group underlying the EC_GROUP object
411 * \return newly created EC_POINT object or NULL if an error occurred
412 */
413EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group);
414
415/** Returns the EC_METHOD used in EC_POINT object
416 * \param point EC_POINT object
417 * \return the EC_METHOD used
418 */
419const EC_METHOD *EC_POINT_method_of(const EC_POINT *point);
420
421/** Sets a point to infinity (neutral element)
422 * \param group underlying EC_GROUP object
423 * \param point EC_POINT to set to infinity
424 * \return 1 on success and 0 if an error occured
425 */
426int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point);
427
428/** Sets the jacobian projective coordinates of a EC_POINT over GFp
429 * \param group underlying EC_GROUP object
430 * \param p EC_POINT object
431 * \param x BIGNUM with the x-coordinate
432 * \param y BIGNUM with the y-coordinate
433 * \param z BIGNUM with the z-coordinate
434 * \param ctx BN_CTX object (optional)
435 * \return 1 on success and 0 if an error occured
436 */
437int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,
438 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx);
439
440/** Gets the jacobian projective coordinates of a EC_POINT over GFp
441 * \param group underlying EC_GROUP object
442 * \param p EC_POINT object
443 * \param x BIGNUM for the x-coordinate
444 * \param y BIGNUM for the y-coordinate
445 * \param z BIGNUM for the z-coordinate
446 * \param ctx BN_CTX object (optional)
447 * \return 1 on success and 0 if an error occured
448 */
449int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
450 const EC_POINT *p, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx);
451
452/** Sets the affine coordinates of a EC_POINT over GFp
453 * \param group underlying EC_GROUP object
454 * \param p EC_POINT object
455 * \param x BIGNUM with the x-coordinate
456 * \param y BIGNUM with the y-coordinate
457 * \param ctx BN_CTX object (optional)
458 * \return 1 on success and 0 if an error occured
459 */
460int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,
461 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx);
462
463/** Gets the affine coordinates of a EC_POINT over GFp
464 * \param group underlying EC_GROUP object
465 * \param p EC_POINT object
466 * \param x BIGNUM for the x-coordinate
467 * \param y BIGNUM for the y-coordinate
468 * \param ctx BN_CTX object (optional)
469 * \return 1 on success and 0 if an error occured
470 */
471int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
472 const EC_POINT *p, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
473
474/** Sets the x9.62 compressed coordinates of a EC_POINT over GFp
475 * \param group underlying EC_GROUP object
476 * \param p EC_POINT object
477 * \param x BIGNUM with x-coordinate
478 * \param y_bit integer with the y-Bit (either 0 or 1)
479 * \param ctx BN_CTX object (optional)
480 * \return 1 on success and 0 if an error occured
481 */
482int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,
483 const BIGNUM *x, int y_bit, BN_CTX *ctx);
484
485/** Sets the affine coordinates of a EC_POINT over GF2m
486 * \param group underlying EC_GROUP object
487 * \param p EC_POINT object
488 * \param x BIGNUM with the x-coordinate
489 * \param y BIGNUM with the y-coordinate
490 * \param ctx BN_CTX object (optional)
491 * \return 1 on success and 0 if an error occured
492 */
493int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p,
494 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx);
495
496/** Gets the affine coordinates of a EC_POINT over GF2m
497 * \param group underlying EC_GROUP object
498 * \param p EC_POINT object
499 * \param x BIGNUM for the x-coordinate
500 * \param y BIGNUM for the y-coordinate
501 * \param ctx BN_CTX object (optional)
502 * \return 1 on success and 0 if an error occured
503 */
504int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
505 const EC_POINT *p, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
506
507/** Sets the x9.62 compressed coordinates of a EC_POINT over GF2m
508 * \param group underlying EC_GROUP object
509 * \param p EC_POINT object
510 * \param x BIGNUM with x-coordinate
511 * \param y_bit integer with the y-Bit (either 0 or 1)
512 * \param ctx BN_CTX object (optional)
513 * \return 1 on success and 0 if an error occured
514 */
515int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p,
516 const BIGNUM *x, int y_bit, BN_CTX *ctx);
517
518/** Encodes a EC_POINT object to a octet string
519 * \param group underlying EC_GROUP object
520 * \param p EC_POINT object
521 * \param form point conversion form
522 * \param buf memory buffer for the result. If NULL the function returns
523 * required buffer size.
524 * \param len length of the memory buffer
525 * \param ctx BN_CTX object (optional)
526 * \return the length of the encoded octet string or 0 if an error occurred
527 */
528size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p,
529 point_conversion_form_t form,
530 unsigned char *buf, size_t len, BN_CTX *ctx);
531
532/** Decodes a EC_POINT from a octet string
533 * \param group underlying EC_GROUP object
534 * \param p EC_POINT object
535 * \param buf memory buffer with the encoded ec point
536 * \param len length of the encoded ec point
537 * \param ctx BN_CTX object (optional)
538 * \return 1 on success and 0 if an error occured
539 */
540int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p,
541 const unsigned char *buf, size_t len, BN_CTX *ctx);
542
543/* other interfaces to point2oct/oct2point: */
544BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *,
545 point_conversion_form_t form, BIGNUM *, BN_CTX *);
546EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *,
547 EC_POINT *, BN_CTX *);
548char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *,
549 point_conversion_form_t form, BN_CTX *);
550EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *,
551 EC_POINT *, BN_CTX *);
552
553
554/********************************************************************/
555/* functions for doing EC_POINT arithmetic */
556/********************************************************************/
557
558/** Computes the sum of two EC_POINT
559 * \param group underlying EC_GROUP object
560 * \param r EC_POINT object for the result (r = a + b)
561 * \param a EC_POINT object with the first summand
562 * \param b EC_POINT object with the second summand
563 * \param ctx BN_CTX object (optional)
564 * \return 1 on success and 0 if an error occured
565 */
566int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx);
567
568/** Computes the double of a EC_POINT
569 * \param group underlying EC_GROUP object
570 * \param r EC_POINT object for the result (r = 2 * a)
571 * \param a EC_POINT object
572 * \param ctx BN_CTX object (optional)
573 * \return 1 on success and 0 if an error occured
574 */
575int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx);
576
577/** Computes the inverse of a EC_POINT
578 * \param group underlying EC_GROUP object
579 * \param a EC_POINT object to be inverted (it's used for the result as well)
580 * \param ctx BN_CTX object (optional)
581 * \return 1 on success and 0 if an error occured
582 */
583int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx);
584
585/** Checks whether the point is the neutral element of the group
586 * \param group the underlying EC_GROUP object
587 * \param p EC_POINT object
588 * \return 1 if the point is the neutral element and 0 otherwise
589 */
590int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *p);
591
592/** Checks whether the point is on the curve
593 * \param group underlying EC_GROUP object
594 * \param point EC_POINT object to check
595 * \param ctx BN_CTX object (optional)
596 * \return 1 if point if on the curve and 0 otherwise
597 */
598int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx);
599
600/** Compares two EC_POINTs
601 * \param group underlying EC_GROUP object
602 * \param a first EC_POINT object
603 * \param b second EC_POINT object
604 * \param ctx BN_CTX object (optional)
605 * \return 0 if both points are equal and a value != 0 otherwise
606 */
607int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx);
608
609int EC_POINT_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
610int EC_POINTs_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
611
612/** Computes r = generator * n sum_{i=0}^num p[i] * m[i]
613 * \param group underlying EC_GROUP object
614 * \param r EC_POINT object for the result
615 * \param n BIGNUM with the multiplier for the group generator (optional)
616 * \param num number futher summands
617 * \param p array of size num of EC_POINT objects
618 * \param m array of size num of BIGNUM objects
619 * \param ctx BN_CTX object (optional)
620 * \return 1 on success and 0 if an error occured
621 */
622int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, size_t num, const EC_POINT *p[], const BIGNUM *m[], BN_CTX *ctx);
623
624/** Computes r = generator * n + q * m
625 * \param group underlying EC_GROUP object
626 * \param r EC_POINT object for the result
627 * \param n BIGNUM with the multiplier for the group generator (optional)
628 * \param q EC_POINT object with the first factor of the second summand
629 * \param m BIGNUM with the second factor of the second summand
630 * \param ctx BN_CTX object (optional)
631 * \return 1 on success and 0 if an error occured
632 */
633int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);
634
635/** Stores multiples of generator for faster point multiplication
636 * \param group EC_GROUP object
637 * \param ctx BN_CTX object (optional)
638 * \return 1 on success and 0 if an error occured
639 */
640int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
641
642/** Reports whether a precomputation has been done
643 * \param group EC_GROUP object
644 * \return 1 if a pre-computation has been done and 0 otherwise
645 */
646int EC_GROUP_have_precompute_mult(const EC_GROUP *group);
647
648
649/********************************************************************/
650/* ASN1 stuff */
651/********************************************************************/
652
653/* EC_GROUP_get_basis_type() returns the NID of the basis type
654 * used to represent the field elements */
655int EC_GROUP_get_basis_type(const EC_GROUP *);
656int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
657int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,
658 unsigned int *k2, unsigned int *k3);
659
660#define OPENSSL_EC_NAMED_CURVE 0x001
661
662typedef struct ecpk_parameters_st ECPKPARAMETERS;
663
664EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len);
665int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out);
666
667#define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x)
668#define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x)
669#define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \
670 (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x))
671#define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \
672 (unsigned char *)(x))
673
674#ifndef OPENSSL_NO_BIO
675int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);
676#endif
677#ifndef OPENSSL_NO_FP_API
678int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
679#endif
680
681
682/********************************************************************/
683/* EC_KEY functions */
684/********************************************************************/
685
686typedef struct ec_key_st EC_KEY;
687
688/* some values for the encoding_flag */
689#define EC_PKEY_NO_PARAMETERS 0x001
690#define EC_PKEY_NO_PUBKEY 0x002
691
692/** Creates a new EC_KEY object.
693 * \return EC_KEY object or NULL if an error occurred.
694 */
695EC_KEY *EC_KEY_new(void);
696
697/** Creates a new EC_KEY object using a named curve as underlying
698 * EC_GROUP object.
699 * \param nid NID of the named curve.
700 * \return EC_KEY object or NULL if an error occurred.
701 */
702EC_KEY *EC_KEY_new_by_curve_name(int nid);
703
704/** Frees a EC_KEY object.
705 * \param key EC_KEY object to be freed.
706 */
707void EC_KEY_free(EC_KEY *key);
708
709/** Copies a EC_KEY object.
710 * \param dst destination EC_KEY object
711 * \param src src EC_KEY object
712 * \return dst or NULL if an error occurred.
713 */
714EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src);
715
716/** Creates a new EC_KEY object and copies the content from src to it.
717 * \param src the source EC_KEY object
718 * \return newly created EC_KEY object or NULL if an error occurred.
719 */
720EC_KEY *EC_KEY_dup(const EC_KEY *src);
721
722/** Increases the internal reference count of a EC_KEY object.
723 * \param key EC_KEY object
724 * \return 1 on success and 0 if an error occurred.
725 */
726int EC_KEY_up_ref(EC_KEY *key);
727
728/** Returns the EC_GROUP object of a EC_KEY object
729 * \param key EC_KEY object
730 * \return the EC_GROUP object (possibly NULL).
731 */
732const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key);
733
734/** Sets the EC_GROUP of a EC_KEY object.
735 * \param key EC_KEY object
736 * \param group EC_GROUP to use in the EC_KEY object (note: the EC_KEY
737 * object will use an own copy of the EC_GROUP).
738 * \return 1 on success and 0 if an error occurred.
739 */
740int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group);
741
742/** Returns the private key of a EC_KEY object.
743 * \param key EC_KEY object
744 * \return a BIGNUM with the private key (possibly NULL).
745 */
746const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key);
747
748/** Sets the private key of a EC_KEY object.
749 * \param key EC_KEY object
750 * \param prv BIGNUM with the private key (note: the EC_KEY object
751 * will use an own copy of the BIGNUM).
752 * \return 1 on success and 0 if an error occurred.
753 */
754int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv);
755
756/** Returns the public key of a EC_KEY object.
757 * \param key the EC_KEY object
758 * \return a EC_POINT object with the public key (possibly NULL)
759 */
760const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key);
761
762/** Sets the public key of a EC_KEY object.
763 * \param key EC_KEY object
764 * \param pub EC_POINT object with the public key (note: the EC_KEY object
765 * will use an own copy of the EC_POINT object).
766 * \return 1 on success and 0 if an error occurred.
767 */
768int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub);
769
770unsigned EC_KEY_get_enc_flags(const EC_KEY *key);
771void EC_KEY_set_enc_flags(EC_KEY *, unsigned int);
772point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *);
773void EC_KEY_set_conv_form(EC_KEY *, point_conversion_form_t);
774/* functions to set/get method specific data */
775void *EC_KEY_get_key_method_data(EC_KEY *,
776 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
777void EC_KEY_insert_key_method_data(EC_KEY *, void *data,
778 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
779/* wrapper functions for the underlying EC_GROUP object */
780void EC_KEY_set_asn1_flag(EC_KEY *, int);
781
782/** Creates a table of pre-computed multiples of the generator to
783 * accelerate further EC_KEY operations.
784 * \param key EC_KEY object
785 * \param ctx BN_CTX object (optional)
786 * \return 1 on success and 0 if an error occurred.
787 */
788int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx);
789
790/** Creates a new ec private (and optional a new public) key.
791 * \param key EC_KEY object
792 * \return 1 on success and 0 if an error occurred.
793 */
794int EC_KEY_generate_key(EC_KEY *key);
795
796/** Verifies that a private and/or public key is valid.
797 * \param key the EC_KEY object
798 * \return 1 on success and 0 otherwise.
799 */
800int EC_KEY_check_key(const EC_KEY *key);
801
802
803/********************************************************************/
804/* de- and encoding functions for SEC1 ECPrivateKey */
805/********************************************************************/
806
807/** Decodes a private key from a memory buffer.
808 * \param key a pointer to a EC_KEY object which should be used (or NULL)
809 * \param in pointer to memory with the DER encoded private key
810 * \param len length of the DER encoded private key
811 * \return the decoded private key or NULL if an error occurred.
812 */
813EC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len);
814
815/** Encodes a private key object and stores the result in a buffer.
816 * \param key the EC_KEY object to encode
817 * \param out the buffer for the result (if NULL the function returns number
818 * of bytes needed).
819 * \return 1 on success and 0 if an error occurred.
820 */
821int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out);
822
823
824/********************************************************************/
825/* de- and encoding functions for EC parameters */
826/********************************************************************/
827
828/** Decodes ec parameter from a memory buffer.
829 * \param key a pointer to a EC_KEY object which should be used (or NULL)
830 * \param in pointer to memory with the DER encoded ec parameters
831 * \param len length of the DER encoded ec parameters
832 * \return a EC_KEY object with the decoded parameters or NULL if an error
833 * occurred.
834 */
835EC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len);
836
837/** Encodes ec parameter and stores the result in a buffer.
838 * \param key the EC_KEY object with ec paramters to encode
839 * \param out the buffer for the result (if NULL the function returns number
840 * of bytes needed).
841 * \return 1 on success and 0 if an error occurred.
842 */
843int i2d_ECParameters(EC_KEY *key, unsigned char **out);
844
845
846/********************************************************************/
847/* de- and encoding functions for EC public key */
848/* (octet string, not DER -- hence 'o2i' and 'i2o') */
849/********************************************************************/
850
851/** Decodes a ec public key from a octet string.
852 * \param key a pointer to a EC_KEY object which should be used
853 * \param in memory buffer with the encoded public key
854 * \param len length of the encoded public key
855 * \return EC_KEY object with decoded public key or NULL if an error
856 * occurred.
857 */
858EC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len);
859
860/** Encodes a ec public key in an octet string.
861 * \param key the EC_KEY object with the public key
862 * \param out the buffer for the result (if NULL the function returns number
863 * of bytes needed).
864 * \return 1 on success and 0 if an error occurred
865 */
866int i2o_ECPublicKey(EC_KEY *key, unsigned char **out);
867
868#ifndef OPENSSL_NO_BIO
869/** Prints out the ec parameters on human readable form.
870 * \param bp BIO object to which the information is printed
871 * \param key EC_KEY object
872 * \return 1 on success and 0 if an error occurred
873 */
874int ECParameters_print(BIO *bp, const EC_KEY *key);
875
876/** Prints out the contents of a EC_KEY object
877 * \param bp BIO object to which the information is printed
878 * \param key EC_KEY object
879 * \param off line offset
880 * \return 1 on success and 0 if an error occurred
881 */
882int EC_KEY_print(BIO *bp, const EC_KEY *key, int off);
883
884#endif
885#ifndef OPENSSL_NO_FP_API
886/** Prints out the ec parameters on human readable form.
887 * \param fp file descriptor to which the information is printed
888 * \param key EC_KEY object
889 * \return 1 on success and 0 if an error occurred
890 */
891int ECParameters_print_fp(FILE *fp, const EC_KEY *key);
892
893/** Prints out the contents of a EC_KEY object
894 * \param fp file descriptor to which the information is printed
895 * \param key EC_KEY object
896 * \param off line offset
897 * \return 1 on success and 0 if an error occurred
898 */
899int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off);
900
901#endif
902
903#define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x)
904
905#ifndef __cplusplus
906#if defined(__SUNPRO_C)
907# if __SUNPRO_C >= 0x520
908# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
909# endif
910# endif
911#endif
912
913#define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \
914 EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_PARAMGEN, \
915 EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL)
916
917
918#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1)
919
920/* BEGIN ERROR CODES */
921/* The following lines are auto generated by the script mkerr.pl. Any changes
922 * made after this point may be overwritten when the script is next run.
923 */
924void ERR_load_EC_strings(void);
925
926/* Error codes for the EC functions. */
927
928/* Function codes. */
929#define EC_F_COMPUTE_WNAF 143
930#define EC_F_D2I_ECPARAMETERS 144
931#define EC_F_D2I_ECPKPARAMETERS 145
932#define EC_F_D2I_ECPRIVATEKEY 146
933#define EC_F_DO_EC_KEY_PRINT 221
934#define EC_F_ECKEY_PARAM2TYPE 223
935#define EC_F_ECKEY_PARAM_DECODE 212
936#define EC_F_ECKEY_PRIV_DECODE 213
937#define EC_F_ECKEY_PRIV_ENCODE 214
938#define EC_F_ECKEY_PUB_DECODE 215
939#define EC_F_ECKEY_PUB_ENCODE 216
940#define EC_F_ECKEY_TYPE2PARAM 220
941#define EC_F_ECPARAMETERS_PRINT 147
942#define EC_F_ECPARAMETERS_PRINT_FP 148
943#define EC_F_ECPKPARAMETERS_PRINT 149
944#define EC_F_ECPKPARAMETERS_PRINT_FP 150
945#define EC_F_ECP_NIST_MOD_192 203
946#define EC_F_ECP_NIST_MOD_224 204
947#define EC_F_ECP_NIST_MOD_256 205
948#define EC_F_ECP_NIST_MOD_521 206
949#define EC_F_EC_ASN1_GROUP2CURVE 153
950#define EC_F_EC_ASN1_GROUP2FIELDID 154
951#define EC_F_EC_ASN1_GROUP2PARAMETERS 155
952#define EC_F_EC_ASN1_GROUP2PKPARAMETERS 156
953#define EC_F_EC_ASN1_PARAMETERS2GROUP 157
954#define EC_F_EC_ASN1_PKPARAMETERS2GROUP 158
955#define EC_F_EC_EX_DATA_SET_DATA 211
956#define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208
957#define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159
958#define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195
959#define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160
960#define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161
961#define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162
962#define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163
963#define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164
964#define EC_F_EC_GFP_MONT_FIELD_DECODE 133
965#define EC_F_EC_GFP_MONT_FIELD_ENCODE 134
966#define EC_F_EC_GFP_MONT_FIELD_MUL 131
967#define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 209
968#define EC_F_EC_GFP_MONT_FIELD_SQR 132
969#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189
970#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135
971#define EC_F_EC_GFP_NIST_FIELD_MUL 200
972#define EC_F_EC_GFP_NIST_FIELD_SQR 201
973#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202
974#define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 165
975#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 166
976#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP 100
977#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 101
978#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102
979#define EC_F_EC_GFP_SIMPLE_OCT2POINT 103
980#define EC_F_EC_GFP_SIMPLE_POINT2OCT 104
981#define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137
982#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 167
983#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105
984#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 168
985#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128
986#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 169
987#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129
988#define EC_F_EC_GROUP_CHECK 170
989#define EC_F_EC_GROUP_CHECK_DISCRIMINANT 171
990#define EC_F_EC_GROUP_COPY 106
991#define EC_F_EC_GROUP_GET0_GENERATOR 139
992#define EC_F_EC_GROUP_GET_COFACTOR 140
993#define EC_F_EC_GROUP_GET_CURVE_GF2M 172
994#define EC_F_EC_GROUP_GET_CURVE_GFP 130
995#define EC_F_EC_GROUP_GET_DEGREE 173
996#define EC_F_EC_GROUP_GET_ORDER 141
997#define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 193
998#define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 194
999#define EC_F_EC_GROUP_NEW 108
1000#define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 174
1001#define EC_F_EC_GROUP_NEW_FROM_DATA 175
1002#define EC_F_EC_GROUP_PRECOMPUTE_MULT 142
1003#define EC_F_EC_GROUP_SET_CURVE_GF2M 176
1004#define EC_F_EC_GROUP_SET_CURVE_GFP 109
1005#define EC_F_EC_GROUP_SET_EXTRA_DATA 110
1006#define EC_F_EC_GROUP_SET_GENERATOR 111
1007#define EC_F_EC_KEY_CHECK_KEY 177
1008#define EC_F_EC_KEY_COPY 178
1009#define EC_F_EC_KEY_GENERATE_KEY 179
1010#define EC_F_EC_KEY_NEW 182
1011#define EC_F_EC_KEY_PRINT 180
1012#define EC_F_EC_KEY_PRINT_FP 181
1013#define EC_F_EC_POINTS_MAKE_AFFINE 136
1014#define EC_F_EC_POINT_ADD 112
1015#define EC_F_EC_POINT_CMP 113
1016#define EC_F_EC_POINT_COPY 114
1017#define EC_F_EC_POINT_DBL 115
1018#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 183
1019#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116
1020#define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117
1021#define EC_F_EC_POINT_INVERT 210
1022#define EC_F_EC_POINT_IS_AT_INFINITY 118
1023#define EC_F_EC_POINT_IS_ON_CURVE 119
1024#define EC_F_EC_POINT_MAKE_AFFINE 120
1025#define EC_F_EC_POINT_MUL 184
1026#define EC_F_EC_POINT_NEW 121
1027#define EC_F_EC_POINT_OCT2POINT 122
1028#define EC_F_EC_POINT_POINT2OCT 123
1029#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 185
1030#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124
1031#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 186
1032#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125
1033#define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126
1034#define EC_F_EC_POINT_SET_TO_INFINITY 127
1035#define EC_F_EC_PRE_COMP_DUP 207
1036#define EC_F_EC_PRE_COMP_NEW 196
1037#define EC_F_EC_WNAF_MUL 187
1038#define EC_F_EC_WNAF_PRECOMPUTE_MULT 188
1039#define EC_F_I2D_ECPARAMETERS 190
1040#define EC_F_I2D_ECPKPARAMETERS 191
1041#define EC_F_I2D_ECPRIVATEKEY 192
1042#define EC_F_I2O_ECPUBLICKEY 151
1043#define EC_F_O2I_ECPUBLICKEY 152
1044#define EC_F_OLD_EC_PRIV_DECODE 222
1045#define EC_F_PKEY_EC_CTRL 197
1046#define EC_F_PKEY_EC_CTRL_STR 198
1047#define EC_F_PKEY_EC_DERIVE 217
1048#define EC_F_PKEY_EC_KEYGEN 199
1049#define EC_F_PKEY_EC_PARAMGEN 219
1050#define EC_F_PKEY_EC_SIGN 218
1051
1052/* Reason codes. */
1053#define EC_R_ASN1_ERROR 115
1054#define EC_R_ASN1_UNKNOWN_FIELD 116
1055#define EC_R_BUFFER_TOO_SMALL 100
1056#define EC_R_D2I_ECPKPARAMETERS_FAILURE 117
1057#define EC_R_DECODE_ERROR 142
1058#define EC_R_DISCRIMINANT_IS_ZERO 118
1059#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119
1060#define EC_R_FIELD_TOO_LARGE 143
1061#define EC_R_GROUP2PKPARAMETERS_FAILURE 120
1062#define EC_R_I2D_ECPKPARAMETERS_FAILURE 121
1063#define EC_R_INCOMPATIBLE_OBJECTS 101
1064#define EC_R_INVALID_ARGUMENT 112
1065#define EC_R_INVALID_COMPRESSED_POINT 110
1066#define EC_R_INVALID_COMPRESSION_BIT 109
1067#define EC_R_INVALID_CURVE 141
1068#define EC_R_INVALID_DIGEST_TYPE 138
1069#define EC_R_INVALID_ENCODING 102
1070#define EC_R_INVALID_FIELD 103
1071#define EC_R_INVALID_FORM 104
1072#define EC_R_INVALID_GROUP_ORDER 122
1073#define EC_R_INVALID_PENTANOMIAL_BASIS 132
1074#define EC_R_INVALID_PRIVATE_KEY 123
1075#define EC_R_INVALID_TRINOMIAL_BASIS 137
1076#define EC_R_KEYS_NOT_SET 140
1077#define EC_R_MISSING_PARAMETERS 124
1078#define EC_R_MISSING_PRIVATE_KEY 125
1079#define EC_R_NOT_A_NIST_PRIME 135
1080#define EC_R_NOT_A_SUPPORTED_NIST_PRIME 136
1081#define EC_R_NOT_IMPLEMENTED 126
1082#define EC_R_NOT_INITIALIZED 111
1083#define EC_R_NO_FIELD_MOD 133
1084#define EC_R_NO_PARAMETERS_SET 139
1085#define EC_R_PASSED_NULL_PARAMETER 134
1086#define EC_R_PKPARAMETERS2GROUP_FAILURE 127
1087#define EC_R_POINT_AT_INFINITY 106
1088#define EC_R_POINT_IS_NOT_ON_CURVE 107
1089#define EC_R_SLOT_FULL 108
1090#define EC_R_UNDEFINED_GENERATOR 113
1091#define EC_R_UNDEFINED_ORDER 128
1092#define EC_R_UNKNOWN_GROUP 129
1093#define EC_R_UNKNOWN_ORDER 114
1094#define EC_R_UNSUPPORTED_FIELD 131
1095#define EC_R_WRONG_ORDER 130
1096
1097#ifdef __cplusplus
1098}
1099#endif
1100#endif
diff --git a/src/lib/libcrypto/ec/ec2_mult.c b/src/lib/libcrypto/ec/ec2_mult.c
new file mode 100644
index 0000000000..26f4a783fc
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec2_mult.c
@@ -0,0 +1,390 @@
1/* crypto/ec/ec2_mult.c */
2/* ====================================================================
3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4 *
5 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7 * to the OpenSSL project.
8 *
9 * The ECC Code is licensed pursuant to the OpenSSL open source
10 * license provided below.
11 *
12 * The software is originally written by Sheueling Chang Shantz and
13 * Douglas Stebila of Sun Microsystems Laboratories.
14 *
15 */
16/* ====================================================================
17 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 *
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 *
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in
28 * the documentation and/or other materials provided with the
29 * distribution.
30 *
31 * 3. All advertising materials mentioning features or use of this
32 * software must display the following acknowledgment:
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35 *
36 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37 * endorse or promote products derived from this software without
38 * prior written permission. For written permission, please contact
39 * openssl-core@openssl.org.
40 *
41 * 5. Products derived from this software may not be called "OpenSSL"
42 * nor may "OpenSSL" appear in their names without prior written
43 * permission of the OpenSSL Project.
44 *
45 * 6. Redistributions of any form whatsoever must retain the following
46 * acknowledgment:
47 * "This product includes software developed by the OpenSSL Project
48 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
54 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61 * OF THE POSSIBILITY OF SUCH DAMAGE.
62 * ====================================================================
63 *
64 * This product includes cryptographic software written by Eric Young
65 * (eay@cryptsoft.com). This product includes software written by Tim
66 * Hudson (tjh@cryptsoft.com).
67 *
68 */
69
70#include <openssl/err.h>
71
72#include "ec_lcl.h"
73
74#ifndef OPENSSL_NO_EC2M
75
76
77/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective
78 * coordinates.
79 * Uses algorithm Mdouble in appendix of
80 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
81 * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
82 * modified to not require precomputation of c=b^{2^{m-1}}.
83 */
84static int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z, BN_CTX *ctx)
85 {
86 BIGNUM *t1;
87 int ret = 0;
88
89 /* Since Mdouble is static we can guarantee that ctx != NULL. */
90 BN_CTX_start(ctx);
91 t1 = BN_CTX_get(ctx);
92 if (t1 == NULL) goto err;
93
94 if (!group->meth->field_sqr(group, x, x, ctx)) goto err;
95 if (!group->meth->field_sqr(group, t1, z, ctx)) goto err;
96 if (!group->meth->field_mul(group, z, x, t1, ctx)) goto err;
97 if (!group->meth->field_sqr(group, x, x, ctx)) goto err;
98 if (!group->meth->field_sqr(group, t1, t1, ctx)) goto err;
99 if (!group->meth->field_mul(group, t1, &group->b, t1, ctx)) goto err;
100 if (!BN_GF2m_add(x, x, t1)) goto err;
101
102 ret = 1;
103
104 err:
105 BN_CTX_end(ctx);
106 return ret;
107 }
108
109/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery
110 * projective coordinates.
111 * Uses algorithm Madd in appendix of
112 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
113 * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
114 */
115static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1, BIGNUM *z1,
116 const BIGNUM *x2, const BIGNUM *z2, BN_CTX *ctx)
117 {
118 BIGNUM *t1, *t2;
119 int ret = 0;
120
121 /* Since Madd is static we can guarantee that ctx != NULL. */
122 BN_CTX_start(ctx);
123 t1 = BN_CTX_get(ctx);
124 t2 = BN_CTX_get(ctx);
125 if (t2 == NULL) goto err;
126
127 if (!BN_copy(t1, x)) goto err;
128 if (!group->meth->field_mul(group, x1, x1, z2, ctx)) goto err;
129 if (!group->meth->field_mul(group, z1, z1, x2, ctx)) goto err;
130 if (!group->meth->field_mul(group, t2, x1, z1, ctx)) goto err;
131 if (!BN_GF2m_add(z1, z1, x1)) goto err;
132 if (!group->meth->field_sqr(group, z1, z1, ctx)) goto err;
133 if (!group->meth->field_mul(group, x1, z1, t1, ctx)) goto err;
134 if (!BN_GF2m_add(x1, x1, t2)) goto err;
135
136 ret = 1;
137
138 err:
139 BN_CTX_end(ctx);
140 return ret;
141 }
142
143/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
144 * using Montgomery point multiplication algorithm Mxy() in appendix of
145 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
146 * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
147 * Returns:
148 * 0 on error
149 * 1 if return value should be the point at infinity
150 * 2 otherwise
151 */
152static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIGNUM *x1,
153 BIGNUM *z1, BIGNUM *x2, BIGNUM *z2, BN_CTX *ctx)
154 {
155 BIGNUM *t3, *t4, *t5;
156 int ret = 0;
157
158 if (BN_is_zero(z1))
159 {
160 BN_zero(x2);
161 BN_zero(z2);
162 return 1;
163 }
164
165 if (BN_is_zero(z2))
166 {
167 if (!BN_copy(x2, x)) return 0;
168 if (!BN_GF2m_add(z2, x, y)) return 0;
169 return 2;
170 }
171
172 /* Since Mxy is static we can guarantee that ctx != NULL. */
173 BN_CTX_start(ctx);
174 t3 = BN_CTX_get(ctx);
175 t4 = BN_CTX_get(ctx);
176 t5 = BN_CTX_get(ctx);
177 if (t5 == NULL) goto err;
178
179 if (!BN_one(t5)) goto err;
180
181 if (!group->meth->field_mul(group, t3, z1, z2, ctx)) goto err;
182
183 if (!group->meth->field_mul(group, z1, z1, x, ctx)) goto err;
184 if (!BN_GF2m_add(z1, z1, x1)) goto err;
185 if (!group->meth->field_mul(group, z2, z2, x, ctx)) goto err;
186 if (!group->meth->field_mul(group, x1, z2, x1, ctx)) goto err;
187 if (!BN_GF2m_add(z2, z2, x2)) goto err;
188
189 if (!group->meth->field_mul(group, z2, z2, z1, ctx)) goto err;
190 if (!group->meth->field_sqr(group, t4, x, ctx)) goto err;
191 if (!BN_GF2m_add(t4, t4, y)) goto err;
192 if (!group->meth->field_mul(group, t4, t4, t3, ctx)) goto err;
193 if (!BN_GF2m_add(t4, t4, z2)) goto err;
194
195 if (!group->meth->field_mul(group, t3, t3, x, ctx)) goto err;
196 if (!group->meth->field_div(group, t3, t5, t3, ctx)) goto err;
197 if (!group->meth->field_mul(group, t4, t3, t4, ctx)) goto err;
198 if (!group->meth->field_mul(group, x2, x1, t3, ctx)) goto err;
199 if (!BN_GF2m_add(z2, x2, x)) goto err;
200
201 if (!group->meth->field_mul(group, z2, z2, t4, ctx)) goto err;
202 if (!BN_GF2m_add(z2, z2, y)) goto err;
203
204 ret = 2;
205
206 err:
207 BN_CTX_end(ctx);
208 return ret;
209 }
210
211/* Computes scalar*point and stores the result in r.
212 * point can not equal r.
213 * Uses algorithm 2P of
214 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
215 * GF(2^m) without precomputation" (CHES '99, LNCS 1717).
216 */
217static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
218 const EC_POINT *point, BN_CTX *ctx)
219 {
220 BIGNUM *x1, *x2, *z1, *z2;
221 int ret = 0, i;
222 BN_ULONG mask,word;
223
224 if (r == point)
225 {
226 ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT);
227 return 0;
228 }
229
230 /* if result should be point at infinity */
231 if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) ||
232 EC_POINT_is_at_infinity(group, point))
233 {
234 return EC_POINT_set_to_infinity(group, r);
235 }
236
237 /* only support affine coordinates */
238 if (!point->Z_is_one) return 0;
239
240 /* Since point_multiply is static we can guarantee that ctx != NULL. */
241 BN_CTX_start(ctx);
242 x1 = BN_CTX_get(ctx);
243 z1 = BN_CTX_get(ctx);
244 if (z1 == NULL) goto err;
245
246 x2 = &r->X;
247 z2 = &r->Y;
248
249 if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */
250 if (!BN_one(z1)) goto err; /* z1 = 1 */
251 if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */
252 if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err;
253 if (!BN_GF2m_add(x2, x2, &group->b)) goto err; /* x2 = x^4 + b */
254
255 /* find top most bit and go one past it */
256 i = scalar->top - 1;
257 mask = BN_TBIT;
258 word = scalar->d[i];
259 while (!(word & mask)) mask >>= 1;
260 mask >>= 1;
261 /* if top most bit was at word break, go to next word */
262 if (!mask)
263 {
264 i--;
265 mask = BN_TBIT;
266 }
267
268 for (; i >= 0; i--)
269 {
270 word = scalar->d[i];
271 while (mask)
272 {
273 if (word & mask)
274 {
275 if (!gf2m_Madd(group, &point->X, x1, z1, x2, z2, ctx)) goto err;
276 if (!gf2m_Mdouble(group, x2, z2, ctx)) goto err;
277 }
278 else
279 {
280 if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err;
281 if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err;
282 }
283 mask >>= 1;
284 }
285 mask = BN_TBIT;
286 }
287
288 /* convert out of "projective" coordinates */
289 i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx);
290 if (i == 0) goto err;
291 else if (i == 1)
292 {
293 if (!EC_POINT_set_to_infinity(group, r)) goto err;
294 }
295 else
296 {
297 if (!BN_one(&r->Z)) goto err;
298 r->Z_is_one = 1;
299 }
300
301 /* GF(2^m) field elements should always have BIGNUM::neg = 0 */
302 BN_set_negative(&r->X, 0);
303 BN_set_negative(&r->Y, 0);
304
305 ret = 1;
306
307 err:
308 BN_CTX_end(ctx);
309 return ret;
310 }
311
312
313/* Computes the sum
314 * scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1]
315 * gracefully ignoring NULL scalar values.
316 */
317int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
318 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
319 {
320 BN_CTX *new_ctx = NULL;
321 int ret = 0;
322 size_t i;
323 EC_POINT *p=NULL;
324 EC_POINT *acc = NULL;
325
326 if (ctx == NULL)
327 {
328 ctx = new_ctx = BN_CTX_new();
329 if (ctx == NULL)
330 return 0;
331 }
332
333 /* This implementation is more efficient than the wNAF implementation for 2
334 * or fewer points. Use the ec_wNAF_mul implementation for 3 or more points,
335 * or if we can perform a fast multiplication based on precomputation.
336 */
337 if ((scalar && (num > 1)) || (num > 2) || (num == 0 && EC_GROUP_have_precompute_mult(group)))
338 {
339 ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
340 goto err;
341 }
342
343 if ((p = EC_POINT_new(group)) == NULL) goto err;
344 if ((acc = EC_POINT_new(group)) == NULL) goto err;
345
346 if (!EC_POINT_set_to_infinity(group, acc)) goto err;
347
348 if (scalar)
349 {
350 if (!ec_GF2m_montgomery_point_multiply(group, p, scalar, group->generator, ctx)) goto err;
351 if (BN_is_negative(scalar))
352 if (!group->meth->invert(group, p, ctx)) goto err;
353 if (!group->meth->add(group, acc, acc, p, ctx)) goto err;
354 }
355
356 for (i = 0; i < num; i++)
357 {
358 if (!ec_GF2m_montgomery_point_multiply(group, p, scalars[i], points[i], ctx)) goto err;
359 if (BN_is_negative(scalars[i]))
360 if (!group->meth->invert(group, p, ctx)) goto err;
361 if (!group->meth->add(group, acc, acc, p, ctx)) goto err;
362 }
363
364 if (!EC_POINT_copy(r, acc)) goto err;
365
366 ret = 1;
367
368 err:
369 if (p) EC_POINT_free(p);
370 if (acc) EC_POINT_free(acc);
371 if (new_ctx != NULL)
372 BN_CTX_free(new_ctx);
373 return ret;
374 }
375
376
377/* Precomputation for point multiplication: fall back to wNAF methods
378 * because ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate */
379
380int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
381 {
382 return ec_wNAF_precompute_mult(group, ctx);
383 }
384
385int ec_GF2m_have_precompute_mult(const EC_GROUP *group)
386 {
387 return ec_wNAF_have_precompute_mult(group);
388 }
389
390#endif
diff --git a/src/lib/libcrypto/ec/ec2_oct.c b/src/lib/libcrypto/ec/ec2_oct.c
new file mode 100644
index 0000000000..f1d75e5ddf
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec2_oct.c
@@ -0,0 +1,407 @@
1/* crypto/ec/ec2_oct.c */
2/* ====================================================================
3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4 *
5 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7 * to the OpenSSL project.
8 *
9 * The ECC Code is licensed pursuant to the OpenSSL open source
10 * license provided below.
11 *
12 * The software is originally written by Sheueling Chang Shantz and
13 * Douglas Stebila of Sun Microsystems Laboratories.
14 *
15 */
16/* ====================================================================
17 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 *
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 *
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in
28 * the documentation and/or other materials provided with the
29 * distribution.
30 *
31 * 3. All advertising materials mentioning features or use of this
32 * software must display the following acknowledgment:
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35 *
36 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37 * endorse or promote products derived from this software without
38 * prior written permission. For written permission, please contact
39 * openssl-core@openssl.org.
40 *
41 * 5. Products derived from this software may not be called "OpenSSL"
42 * nor may "OpenSSL" appear in their names without prior written
43 * permission of the OpenSSL Project.
44 *
45 * 6. Redistributions of any form whatsoever must retain the following
46 * acknowledgment:
47 * "This product includes software developed by the OpenSSL Project
48 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
54 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61 * OF THE POSSIBILITY OF SUCH DAMAGE.
62 * ====================================================================
63 *
64 * This product includes cryptographic software written by Eric Young
65 * (eay@cryptsoft.com). This product includes software written by Tim
66 * Hudson (tjh@cryptsoft.com).
67 *
68 */
69
70#include <openssl/err.h>
71
72#include "ec_lcl.h"
73
74#ifndef OPENSSL_NO_EC2M
75
76/* Calculates and sets the affine coordinates of an EC_POINT from the given
77 * compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
78 * Note that the simple implementation only uses affine coordinates.
79 *
80 * The method is from the following publication:
81 *
82 * Harper, Menezes, Vanstone:
83 * "Public-Key Cryptosystems with Very Small Key Lengths",
84 * EUROCRYPT '92, Springer-Verlag LNCS 658,
85 * published February 1993
86 *
87 * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
88 * the same method, but claim no priority date earlier than July 29, 1994
89 * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
90 */
91int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
92 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
93 {
94 BN_CTX *new_ctx = NULL;
95 BIGNUM *tmp, *x, *y, *z;
96 int ret = 0, z0;
97
98 /* clear error queue */
99 ERR_clear_error();
100
101 if (ctx == NULL)
102 {
103 ctx = new_ctx = BN_CTX_new();
104 if (ctx == NULL)
105 return 0;
106 }
107
108 y_bit = (y_bit != 0) ? 1 : 0;
109
110 BN_CTX_start(ctx);
111 tmp = BN_CTX_get(ctx);
112 x = BN_CTX_get(ctx);
113 y = BN_CTX_get(ctx);
114 z = BN_CTX_get(ctx);
115 if (z == NULL) goto err;
116
117 if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
118 if (BN_is_zero(x))
119 {
120 if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
121 }
122 else
123 {
124 if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
125 if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
126 if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
127 if (!BN_GF2m_add(tmp, x, tmp)) goto err;
128 if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
129 {
130 unsigned long err = ERR_peek_last_error();
131
132 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
133 {
134 ERR_clear_error();
135 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
136 }
137 else
138 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
139 goto err;
140 }
141 z0 = (BN_is_odd(z)) ? 1 : 0;
142 if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
143 if (z0 != y_bit)
144 {
145 if (!BN_GF2m_add(y, y, x)) goto err;
146 }
147 }
148
149 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
150
151 ret = 1;
152
153 err:
154 BN_CTX_end(ctx);
155 if (new_ctx != NULL)
156 BN_CTX_free(new_ctx);
157 return ret;
158 }
159
160
161/* Converts an EC_POINT to an octet string.
162 * If buf is NULL, the encoded length will be returned.
163 * If the length len of buf is smaller than required an error will be returned.
164 */
165size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
166 unsigned char *buf, size_t len, BN_CTX *ctx)
167 {
168 size_t ret;
169 BN_CTX *new_ctx = NULL;
170 int used_ctx = 0;
171 BIGNUM *x, *y, *yxi;
172 size_t field_len, i, skip;
173
174 if ((form != POINT_CONVERSION_COMPRESSED)
175 && (form != POINT_CONVERSION_UNCOMPRESSED)
176 && (form != POINT_CONVERSION_HYBRID))
177 {
178 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
179 goto err;
180 }
181
182 if (EC_POINT_is_at_infinity(group, point))
183 {
184 /* encodes to a single 0 octet */
185 if (buf != NULL)
186 {
187 if (len < 1)
188 {
189 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
190 return 0;
191 }
192 buf[0] = 0;
193 }
194 return 1;
195 }
196
197
198 /* ret := required output buffer length */
199 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
200 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
201
202 /* if 'buf' is NULL, just return required length */
203 if (buf != NULL)
204 {
205 if (len < ret)
206 {
207 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
208 goto err;
209 }
210
211 if (ctx == NULL)
212 {
213 ctx = new_ctx = BN_CTX_new();
214 if (ctx == NULL)
215 return 0;
216 }
217
218 BN_CTX_start(ctx);
219 used_ctx = 1;
220 x = BN_CTX_get(ctx);
221 y = BN_CTX_get(ctx);
222 yxi = BN_CTX_get(ctx);
223 if (yxi == NULL) goto err;
224
225 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
226
227 buf[0] = form;
228 if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
229 {
230 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
231 if (BN_is_odd(yxi)) buf[0]++;
232 }
233
234 i = 1;
235
236 skip = field_len - BN_num_bytes(x);
237 if (skip > field_len)
238 {
239 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
240 goto err;
241 }
242 while (skip > 0)
243 {
244 buf[i++] = 0;
245 skip--;
246 }
247 skip = BN_bn2bin(x, buf + i);
248 i += skip;
249 if (i != 1 + field_len)
250 {
251 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
252 goto err;
253 }
254
255 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
256 {
257 skip = field_len - BN_num_bytes(y);
258 if (skip > field_len)
259 {
260 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
261 goto err;
262 }
263 while (skip > 0)
264 {
265 buf[i++] = 0;
266 skip--;
267 }
268 skip = BN_bn2bin(y, buf + i);
269 i += skip;
270 }
271
272 if (i != ret)
273 {
274 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
275 goto err;
276 }
277 }
278
279 if (used_ctx)
280 BN_CTX_end(ctx);
281 if (new_ctx != NULL)
282 BN_CTX_free(new_ctx);
283 return ret;
284
285 err:
286 if (used_ctx)
287 BN_CTX_end(ctx);
288 if (new_ctx != NULL)
289 BN_CTX_free(new_ctx);
290 return 0;
291 }
292
293
294/* Converts an octet string representation to an EC_POINT.
295 * Note that the simple implementation only uses affine coordinates.
296 */
297int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
298 const unsigned char *buf, size_t len, BN_CTX *ctx)
299 {
300 point_conversion_form_t form;
301 int y_bit;
302 BN_CTX *new_ctx = NULL;
303 BIGNUM *x, *y, *yxi;
304 size_t field_len, enc_len;
305 int ret = 0;
306
307 if (len == 0)
308 {
309 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
310 return 0;
311 }
312 form = buf[0];
313 y_bit = form & 1;
314 form = form & ~1U;
315 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
316 && (form != POINT_CONVERSION_UNCOMPRESSED)
317 && (form != POINT_CONVERSION_HYBRID))
318 {
319 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
320 return 0;
321 }
322 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
323 {
324 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
325 return 0;
326 }
327
328 if (form == 0)
329 {
330 if (len != 1)
331 {
332 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
333 return 0;
334 }
335
336 return EC_POINT_set_to_infinity(group, point);
337 }
338
339 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
340 enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
341
342 if (len != enc_len)
343 {
344 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
345 return 0;
346 }
347
348 if (ctx == NULL)
349 {
350 ctx = new_ctx = BN_CTX_new();
351 if (ctx == NULL)
352 return 0;
353 }
354
355 BN_CTX_start(ctx);
356 x = BN_CTX_get(ctx);
357 y = BN_CTX_get(ctx);
358 yxi = BN_CTX_get(ctx);
359 if (yxi == NULL) goto err;
360
361 if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
362 if (BN_ucmp(x, &group->field) >= 0)
363 {
364 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
365 goto err;
366 }
367
368 if (form == POINT_CONVERSION_COMPRESSED)
369 {
370 if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
371 }
372 else
373 {
374 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
375 if (BN_ucmp(y, &group->field) >= 0)
376 {
377 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
378 goto err;
379 }
380 if (form == POINT_CONVERSION_HYBRID)
381 {
382 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
383 if (y_bit != BN_is_odd(yxi))
384 {
385 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
386 goto err;
387 }
388 }
389
390 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
391 }
392
393 if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
394 {
395 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
396 goto err;
397 }
398
399 ret = 1;
400
401 err:
402 BN_CTX_end(ctx);
403 if (new_ctx != NULL)
404 BN_CTX_free(new_ctx);
405 return ret;
406 }
407#endif
diff --git a/src/lib/libcrypto/ec/ec2_smpl.c b/src/lib/libcrypto/ec/ec2_smpl.c
new file mode 100644
index 0000000000..03deae6674
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec2_smpl.c
@@ -0,0 +1,1042 @@
1/* crypto/ec/ec2_smpl.c */
2/* ====================================================================
3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4 *
5 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7 * to the OpenSSL project.
8 *
9 * The ECC Code is licensed pursuant to the OpenSSL open source
10 * license provided below.
11 *
12 * The software is originally written by Sheueling Chang Shantz and
13 * Douglas Stebila of Sun Microsystems Laboratories.
14 *
15 */
16/* ====================================================================
17 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 *
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 *
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in
28 * the documentation and/or other materials provided with the
29 * distribution.
30 *
31 * 3. All advertising materials mentioning features or use of this
32 * software must display the following acknowledgment:
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35 *
36 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37 * endorse or promote products derived from this software without
38 * prior written permission. For written permission, please contact
39 * openssl-core@openssl.org.
40 *
41 * 5. Products derived from this software may not be called "OpenSSL"
42 * nor may "OpenSSL" appear in their names without prior written
43 * permission of the OpenSSL Project.
44 *
45 * 6. Redistributions of any form whatsoever must retain the following
46 * acknowledgment:
47 * "This product includes software developed by the OpenSSL Project
48 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
54 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61 * OF THE POSSIBILITY OF SUCH DAMAGE.
62 * ====================================================================
63 *
64 * This product includes cryptographic software written by Eric Young
65 * (eay@cryptsoft.com). This product includes software written by Tim
66 * Hudson (tjh@cryptsoft.com).
67 *
68 */
69
70#include <openssl/err.h>
71
72#include "ec_lcl.h"
73
74
75const EC_METHOD *EC_GF2m_simple_method(void)
76 {
77 static const EC_METHOD ret = {
78 NID_X9_62_characteristic_two_field,
79 ec_GF2m_simple_group_init,
80 ec_GF2m_simple_group_finish,
81 ec_GF2m_simple_group_clear_finish,
82 ec_GF2m_simple_group_copy,
83 ec_GF2m_simple_group_set_curve,
84 ec_GF2m_simple_group_get_curve,
85 ec_GF2m_simple_group_get_degree,
86 ec_GF2m_simple_group_check_discriminant,
87 ec_GF2m_simple_point_init,
88 ec_GF2m_simple_point_finish,
89 ec_GF2m_simple_point_clear_finish,
90 ec_GF2m_simple_point_copy,
91 ec_GF2m_simple_point_set_to_infinity,
92 0 /* set_Jprojective_coordinates_GFp */,
93 0 /* get_Jprojective_coordinates_GFp */,
94 ec_GF2m_simple_point_set_affine_coordinates,
95 ec_GF2m_simple_point_get_affine_coordinates,
96 ec_GF2m_simple_set_compressed_coordinates,
97 ec_GF2m_simple_point2oct,
98 ec_GF2m_simple_oct2point,
99 ec_GF2m_simple_add,
100 ec_GF2m_simple_dbl,
101 ec_GF2m_simple_invert,
102 ec_GF2m_simple_is_at_infinity,
103 ec_GF2m_simple_is_on_curve,
104 ec_GF2m_simple_cmp,
105 ec_GF2m_simple_make_affine,
106 ec_GF2m_simple_points_make_affine,
107
108 /* the following three method functions are defined in ec2_mult.c */
109 ec_GF2m_simple_mul,
110 ec_GF2m_precompute_mult,
111 ec_GF2m_have_precompute_mult,
112
113 ec_GF2m_simple_field_mul,
114 ec_GF2m_simple_field_sqr,
115 ec_GF2m_simple_field_div,
116 0 /* field_encode */,
117 0 /* field_decode */,
118 0 /* field_set_to_one */ };
119
120 return &ret;
121 }
122
123
124/* Initialize a GF(2^m)-based EC_GROUP structure.
125 * Note that all other members are handled by EC_GROUP_new.
126 */
127int ec_GF2m_simple_group_init(EC_GROUP *group)
128 {
129 BN_init(&group->field);
130 BN_init(&group->a);
131 BN_init(&group->b);
132 return 1;
133 }
134
135
136/* Free a GF(2^m)-based EC_GROUP structure.
137 * Note that all other members are handled by EC_GROUP_free.
138 */
139void ec_GF2m_simple_group_finish(EC_GROUP *group)
140 {
141 BN_free(&group->field);
142 BN_free(&group->a);
143 BN_free(&group->b);
144 }
145
146
147/* Clear and free a GF(2^m)-based EC_GROUP structure.
148 * Note that all other members are handled by EC_GROUP_clear_free.
149 */
150void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
151 {
152 BN_clear_free(&group->field);
153 BN_clear_free(&group->a);
154 BN_clear_free(&group->b);
155 group->poly[0] = 0;
156 group->poly[1] = 0;
157 group->poly[2] = 0;
158 group->poly[3] = 0;
159 group->poly[4] = 0;
160 group->poly[5] = -1;
161 }
162
163
164/* Copy a GF(2^m)-based EC_GROUP structure.
165 * Note that all other members are handled by EC_GROUP_copy.
166 */
167int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
168 {
169 int i;
170 if (!BN_copy(&dest->field, &src->field)) return 0;
171 if (!BN_copy(&dest->a, &src->a)) return 0;
172 if (!BN_copy(&dest->b, &src->b)) return 0;
173 dest->poly[0] = src->poly[0];
174 dest->poly[1] = src->poly[1];
175 dest->poly[2] = src->poly[2];
176 dest->poly[3] = src->poly[3];
177 dest->poly[4] = src->poly[4];
178 dest->poly[5] = src->poly[5];
179 if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0;
180 if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) return 0;
181 for (i = dest->a.top; i < dest->a.dmax; i++) dest->a.d[i] = 0;
182 for (i = dest->b.top; i < dest->b.dmax; i++) dest->b.d[i] = 0;
183 return 1;
184 }
185
186
187/* Set the curve parameters of an EC_GROUP structure. */
188int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
189 const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
190 {
191 int ret = 0, i;
192
193 /* group->field */
194 if (!BN_copy(&group->field, p)) goto err;
195 i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1;
196 if ((i != 5) && (i != 3))
197 {
198 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
199 goto err;
200 }
201
202 /* group->a */
203 if (!BN_GF2m_mod_arr(&group->a, a, group->poly)) goto err;
204 if(bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
205 for (i = group->a.top; i < group->a.dmax; i++) group->a.d[i] = 0;
206
207 /* group->b */
208 if (!BN_GF2m_mod_arr(&group->b, b, group->poly)) goto err;
209 if(bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2) == NULL) goto err;
210 for (i = group->b.top; i < group->b.dmax; i++) group->b.d[i] = 0;
211
212 ret = 1;
213 err:
214 return ret;
215 }
216
217
218/* Get the curve parameters of an EC_GROUP structure.
219 * If p, a, or b are NULL then there values will not be set but the method will return with success.
220 */
221int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
222 {
223 int ret = 0;
224
225 if (p != NULL)
226 {
227 if (!BN_copy(p, &group->field)) return 0;
228 }
229
230 if (a != NULL)
231 {
232 if (!BN_copy(a, &group->a)) goto err;
233 }
234
235 if (b != NULL)
236 {
237 if (!BN_copy(b, &group->b)) goto err;
238 }
239
240 ret = 1;
241
242 err:
243 return ret;
244 }
245
246
247/* Gets the degree of the field. For a curve over GF(2^m) this is the value m. */
248int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
249 {
250 return BN_num_bits(&group->field)-1;
251 }
252
253
254/* Checks the discriminant of the curve.
255 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p)
256 */
257int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
258 {
259 int ret = 0;
260 BIGNUM *b;
261 BN_CTX *new_ctx = NULL;
262
263 if (ctx == NULL)
264 {
265 ctx = new_ctx = BN_CTX_new();
266 if (ctx == NULL)
267 {
268 ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
269 goto err;
270 }
271 }
272 BN_CTX_start(ctx);
273 b = BN_CTX_get(ctx);
274 if (b == NULL) goto err;
275
276 if (!BN_GF2m_mod_arr(b, &group->b, group->poly)) goto err;
277
278 /* check the discriminant:
279 * y^2 + x*y = x^3 + a*x^2 + b is an elliptic curve <=> b != 0 (mod p)
280 */
281 if (BN_is_zero(b)) goto err;
282
283 ret = 1;
284
285err:
286 if (ctx != NULL)
287 BN_CTX_end(ctx);
288 if (new_ctx != NULL)
289 BN_CTX_free(new_ctx);
290 return ret;
291 }
292
293
294/* Initializes an EC_POINT. */
295int ec_GF2m_simple_point_init(EC_POINT *point)
296 {
297 BN_init(&point->X);
298 BN_init(&point->Y);
299 BN_init(&point->Z);
300 return 1;
301 }
302
303
304/* Frees an EC_POINT. */
305void ec_GF2m_simple_point_finish(EC_POINT *point)
306 {
307 BN_free(&point->X);
308 BN_free(&point->Y);
309 BN_free(&point->Z);
310 }
311
312
313/* Clears and frees an EC_POINT. */
314void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
315 {
316 BN_clear_free(&point->X);
317 BN_clear_free(&point->Y);
318 BN_clear_free(&point->Z);
319 point->Z_is_one = 0;
320 }
321
322
323/* Copy the contents of one EC_POINT into another. Assumes dest is initialized. */
324int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
325 {
326 if (!BN_copy(&dest->X, &src->X)) return 0;
327 if (!BN_copy(&dest->Y, &src->Y)) return 0;
328 if (!BN_copy(&dest->Z, &src->Z)) return 0;
329 dest->Z_is_one = src->Z_is_one;
330
331 return 1;
332 }
333
334
335/* Set an EC_POINT to the point at infinity.
336 * A point at infinity is represented by having Z=0.
337 */
338int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
339 {
340 point->Z_is_one = 0;
341 BN_zero(&point->Z);
342 return 1;
343 }
344
345
346/* Set the coordinates of an EC_POINT using affine coordinates.
347 * Note that the simple implementation only uses affine coordinates.
348 */
349int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
350 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
351 {
352 int ret = 0;
353 if (x == NULL || y == NULL)
354 {
355 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
356 return 0;
357 }
358
359 if (!BN_copy(&point->X, x)) goto err;
360 BN_set_negative(&point->X, 0);
361 if (!BN_copy(&point->Y, y)) goto err;
362 BN_set_negative(&point->Y, 0);
363 if (!BN_copy(&point->Z, BN_value_one())) goto err;
364 BN_set_negative(&point->Z, 0);
365 point->Z_is_one = 1;
366 ret = 1;
367
368 err:
369 return ret;
370 }
371
372
373/* Gets the affine coordinates of an EC_POINT.
374 * Note that the simple implementation only uses affine coordinates.
375 */
376int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
377 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
378 {
379 int ret = 0;
380
381 if (EC_POINT_is_at_infinity(group, point))
382 {
383 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
384 return 0;
385 }
386
387 if (BN_cmp(&point->Z, BN_value_one()))
388 {
389 ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
390 return 0;
391 }
392 if (x != NULL)
393 {
394 if (!BN_copy(x, &point->X)) goto err;
395 BN_set_negative(x, 0);
396 }
397 if (y != NULL)
398 {
399 if (!BN_copy(y, &point->Y)) goto err;
400 BN_set_negative(y, 0);
401 }
402 ret = 1;
403
404 err:
405 return ret;
406 }
407
408
409/* Calculates and sets the affine coordinates of an EC_POINT from the given
410 * compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
411 * Note that the simple implementation only uses affine coordinates.
412 *
413 * The method is from the following publication:
414 *
415 * Harper, Menezes, Vanstone:
416 * "Public-Key Cryptosystems with Very Small Key Lengths",
417 * EUROCRYPT '92, Springer-Verlag LNCS 658,
418 * published February 1993
419 *
420 * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
421 * the same method, but claim no priority date earlier than July 29, 1994
422 * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
423 */
424int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
425 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
426 {
427 BN_CTX *new_ctx = NULL;
428 BIGNUM *tmp, *x, *y, *z;
429 int ret = 0, z0;
430
431 /* clear error queue */
432 ERR_clear_error();
433
434 if (ctx == NULL)
435 {
436 ctx = new_ctx = BN_CTX_new();
437 if (ctx == NULL)
438 return 0;
439 }
440
441 y_bit = (y_bit != 0) ? 1 : 0;
442
443 BN_CTX_start(ctx);
444 tmp = BN_CTX_get(ctx);
445 x = BN_CTX_get(ctx);
446 y = BN_CTX_get(ctx);
447 z = BN_CTX_get(ctx);
448 if (z == NULL) goto err;
449
450 if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
451 if (BN_is_zero(x))
452 {
453 if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
454 }
455 else
456 {
457 if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
458 if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
459 if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
460 if (!BN_GF2m_add(tmp, x, tmp)) goto err;
461 if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
462 {
463 unsigned long err = ERR_peek_last_error();
464
465 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
466 {
467 ERR_clear_error();
468 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
469 }
470 else
471 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
472 goto err;
473 }
474 z0 = (BN_is_odd(z)) ? 1 : 0;
475 if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
476 if (z0 != y_bit)
477 {
478 if (!BN_GF2m_add(y, y, x)) goto err;
479 }
480 }
481
482 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
483
484 ret = 1;
485
486 err:
487 BN_CTX_end(ctx);
488 if (new_ctx != NULL)
489 BN_CTX_free(new_ctx);
490 return ret;
491 }
492
493
494/* Converts an EC_POINT to an octet string.
495 * If buf is NULL, the encoded length will be returned.
496 * If the length len of buf is smaller than required an error will be returned.
497 */
498size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
499 unsigned char *buf, size_t len, BN_CTX *ctx)
500 {
501 size_t ret;
502 BN_CTX *new_ctx = NULL;
503 int used_ctx = 0;
504 BIGNUM *x, *y, *yxi;
505 size_t field_len, i, skip;
506
507 if ((form != POINT_CONVERSION_COMPRESSED)
508 && (form != POINT_CONVERSION_UNCOMPRESSED)
509 && (form != POINT_CONVERSION_HYBRID))
510 {
511 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
512 goto err;
513 }
514
515 if (EC_POINT_is_at_infinity(group, point))
516 {
517 /* encodes to a single 0 octet */
518 if (buf != NULL)
519 {
520 if (len < 1)
521 {
522 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
523 return 0;
524 }
525 buf[0] = 0;
526 }
527 return 1;
528 }
529
530
531 /* ret := required output buffer length */
532 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
533 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
534
535 /* if 'buf' is NULL, just return required length */
536 if (buf != NULL)
537 {
538 if (len < ret)
539 {
540 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
541 goto err;
542 }
543
544 if (ctx == NULL)
545 {
546 ctx = new_ctx = BN_CTX_new();
547 if (ctx == NULL)
548 return 0;
549 }
550
551 BN_CTX_start(ctx);
552 used_ctx = 1;
553 x = BN_CTX_get(ctx);
554 y = BN_CTX_get(ctx);
555 yxi = BN_CTX_get(ctx);
556 if (yxi == NULL) goto err;
557
558 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
559
560 buf[0] = form;
561 if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
562 {
563 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
564 if (BN_is_odd(yxi)) buf[0]++;
565 }
566
567 i = 1;
568
569 skip = field_len - BN_num_bytes(x);
570 if (skip > field_len)
571 {
572 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
573 goto err;
574 }
575 while (skip > 0)
576 {
577 buf[i++] = 0;
578 skip--;
579 }
580 skip = BN_bn2bin(x, buf + i);
581 i += skip;
582 if (i != 1 + field_len)
583 {
584 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
585 goto err;
586 }
587
588 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
589 {
590 skip = field_len - BN_num_bytes(y);
591 if (skip > field_len)
592 {
593 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
594 goto err;
595 }
596 while (skip > 0)
597 {
598 buf[i++] = 0;
599 skip--;
600 }
601 skip = BN_bn2bin(y, buf + i);
602 i += skip;
603 }
604
605 if (i != ret)
606 {
607 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
608 goto err;
609 }
610 }
611
612 if (used_ctx)
613 BN_CTX_end(ctx);
614 if (new_ctx != NULL)
615 BN_CTX_free(new_ctx);
616 return ret;
617
618 err:
619 if (used_ctx)
620 BN_CTX_end(ctx);
621 if (new_ctx != NULL)
622 BN_CTX_free(new_ctx);
623 return 0;
624 }
625
626
627/* Converts an octet string representation to an EC_POINT.
628 * Note that the simple implementation only uses affine coordinates.
629 */
630int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
631 const unsigned char *buf, size_t len, BN_CTX *ctx)
632 {
633 point_conversion_form_t form;
634 int y_bit;
635 BN_CTX *new_ctx = NULL;
636 BIGNUM *x, *y, *yxi;
637 size_t field_len, enc_len;
638 int ret = 0;
639
640 if (len == 0)
641 {
642 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
643 return 0;
644 }
645 form = buf[0];
646 y_bit = form & 1;
647 form = form & ~1U;
648 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
649 && (form != POINT_CONVERSION_UNCOMPRESSED)
650 && (form != POINT_CONVERSION_HYBRID))
651 {
652 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
653 return 0;
654 }
655 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
656 {
657 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
658 return 0;
659 }
660
661 if (form == 0)
662 {
663 if (len != 1)
664 {
665 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
666 return 0;
667 }
668
669 return EC_POINT_set_to_infinity(group, point);
670 }
671
672 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
673 enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
674
675 if (len != enc_len)
676 {
677 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
678 return 0;
679 }
680
681 if (ctx == NULL)
682 {
683 ctx = new_ctx = BN_CTX_new();
684 if (ctx == NULL)
685 return 0;
686 }
687
688 BN_CTX_start(ctx);
689 x = BN_CTX_get(ctx);
690 y = BN_CTX_get(ctx);
691 yxi = BN_CTX_get(ctx);
692 if (yxi == NULL) goto err;
693
694 if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
695 if (BN_ucmp(x, &group->field) >= 0)
696 {
697 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
698 goto err;
699 }
700
701 if (form == POINT_CONVERSION_COMPRESSED)
702 {
703 if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
704 }
705 else
706 {
707 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
708 if (BN_ucmp(y, &group->field) >= 0)
709 {
710 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
711 goto err;
712 }
713 if (form == POINT_CONVERSION_HYBRID)
714 {
715 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
716 if (y_bit != BN_is_odd(yxi))
717 {
718 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
719 goto err;
720 }
721 }
722
723 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
724 }
725
726 if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
727 {
728 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
729 goto err;
730 }
731
732 ret = 1;
733
734 err:
735 BN_CTX_end(ctx);
736 if (new_ctx != NULL)
737 BN_CTX_free(new_ctx);
738 return ret;
739 }
740
741
742/* Computes a + b and stores the result in r. r could be a or b, a could be b.
743 * Uses algorithm A.10.2 of IEEE P1363.
744 */
745int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
746 {
747 BN_CTX *new_ctx = NULL;
748 BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
749 int ret = 0;
750
751 if (EC_POINT_is_at_infinity(group, a))
752 {
753 if (!EC_POINT_copy(r, b)) return 0;
754 return 1;
755 }
756
757 if (EC_POINT_is_at_infinity(group, b))
758 {
759 if (!EC_POINT_copy(r, a)) return 0;
760 return 1;
761 }
762
763 if (ctx == NULL)
764 {
765 ctx = new_ctx = BN_CTX_new();
766 if (ctx == NULL)
767 return 0;
768 }
769
770 BN_CTX_start(ctx);
771 x0 = BN_CTX_get(ctx);
772 y0 = BN_CTX_get(ctx);
773 x1 = BN_CTX_get(ctx);
774 y1 = BN_CTX_get(ctx);
775 x2 = BN_CTX_get(ctx);
776 y2 = BN_CTX_get(ctx);
777 s = BN_CTX_get(ctx);
778 t = BN_CTX_get(ctx);
779 if (t == NULL) goto err;
780
781 if (a->Z_is_one)
782 {
783 if (!BN_copy(x0, &a->X)) goto err;
784 if (!BN_copy(y0, &a->Y)) goto err;
785 }
786 else
787 {
788 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx)) goto err;
789 }
790 if (b->Z_is_one)
791 {
792 if (!BN_copy(x1, &b->X)) goto err;
793 if (!BN_copy(y1, &b->Y)) goto err;
794 }
795 else
796 {
797 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx)) goto err;
798 }
799
800
801 if (BN_GF2m_cmp(x0, x1))
802 {
803 if (!BN_GF2m_add(t, x0, x1)) goto err;
804 if (!BN_GF2m_add(s, y0, y1)) goto err;
805 if (!group->meth->field_div(group, s, s, t, ctx)) goto err;
806 if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
807 if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
808 if (!BN_GF2m_add(x2, x2, s)) goto err;
809 if (!BN_GF2m_add(x2, x2, t)) goto err;
810 }
811 else
812 {
813 if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1))
814 {
815 if (!EC_POINT_set_to_infinity(group, r)) goto err;
816 ret = 1;
817 goto err;
818 }
819 if (!group->meth->field_div(group, s, y1, x1, ctx)) goto err;
820 if (!BN_GF2m_add(s, s, x1)) goto err;
821
822 if (!group->meth->field_sqr(group, x2, s, ctx)) goto err;
823 if (!BN_GF2m_add(x2, x2, s)) goto err;
824 if (!BN_GF2m_add(x2, x2, &group->a)) goto err;
825 }
826
827 if (!BN_GF2m_add(y2, x1, x2)) goto err;
828 if (!group->meth->field_mul(group, y2, y2, s, ctx)) goto err;
829 if (!BN_GF2m_add(y2, y2, x2)) goto err;
830 if (!BN_GF2m_add(y2, y2, y1)) goto err;
831
832 if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx)) goto err;
833
834 ret = 1;
835
836 err:
837 BN_CTX_end(ctx);
838 if (new_ctx != NULL)
839 BN_CTX_free(new_ctx);
840 return ret;
841 }
842
843
844/* Computes 2 * a and stores the result in r. r could be a.
845 * Uses algorithm A.10.2 of IEEE P1363.
846 */
847int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
848 {
849 return ec_GF2m_simple_add(group, r, a, a, ctx);
850 }
851
852
853int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
854 {
855 if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
856 /* point is its own inverse */
857 return 1;
858
859 if (!EC_POINT_make_affine(group, point, ctx)) return 0;
860 return BN_GF2m_add(&point->Y, &point->X, &point->Y);
861 }
862
863
864/* Indicates whether the given point is the point at infinity. */
865int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
866 {
867 return BN_is_zero(&point->Z);
868 }
869
870
871/* Determines whether the given EC_POINT is an actual point on the curve defined
872 * in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation:
873 * y^2 + x*y = x^3 + a*x^2 + b.
874 */
875int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
876 {
877 int ret = -1;
878 BN_CTX *new_ctx = NULL;
879 BIGNUM *lh, *y2;
880 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
881 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
882
883 if (EC_POINT_is_at_infinity(group, point))
884 return 1;
885
886 field_mul = group->meth->field_mul;
887 field_sqr = group->meth->field_sqr;
888
889 /* only support affine coordinates */
890 if (!point->Z_is_one) return -1;
891
892 if (ctx == NULL)
893 {
894 ctx = new_ctx = BN_CTX_new();
895 if (ctx == NULL)
896 return -1;
897 }
898
899 BN_CTX_start(ctx);
900 y2 = BN_CTX_get(ctx);
901 lh = BN_CTX_get(ctx);
902 if (lh == NULL) goto err;
903
904 /* We have a curve defined by a Weierstrass equation
905 * y^2 + x*y = x^3 + a*x^2 + b.
906 * <=> x^3 + a*x^2 + x*y + b + y^2 = 0
907 * <=> ((x + a) * x + y ) * x + b + y^2 = 0
908 */
909 if (!BN_GF2m_add(lh, &point->X, &group->a)) goto err;
910 if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
911 if (!BN_GF2m_add(lh, lh, &point->Y)) goto err;
912 if (!field_mul(group, lh, lh, &point->X, ctx)) goto err;
913 if (!BN_GF2m_add(lh, lh, &group->b)) goto err;
914 if (!field_sqr(group, y2, &point->Y, ctx)) goto err;
915 if (!BN_GF2m_add(lh, lh, y2)) goto err;
916 ret = BN_is_zero(lh);
917 err:
918 if (ctx) BN_CTX_end(ctx);
919 if (new_ctx) BN_CTX_free(new_ctx);
920 return ret;
921 }
922
923
924/* Indicates whether two points are equal.
925 * Return values:
926 * -1 error
927 * 0 equal (in affine coordinates)
928 * 1 not equal
929 */
930int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
931 {
932 BIGNUM *aX, *aY, *bX, *bY;
933 BN_CTX *new_ctx = NULL;
934 int ret = -1;
935
936 if (EC_POINT_is_at_infinity(group, a))
937 {
938 return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
939 }
940
941 if (EC_POINT_is_at_infinity(group, b))
942 return 1;
943
944 if (a->Z_is_one && b->Z_is_one)
945 {
946 return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
947 }
948
949 if (ctx == NULL)
950 {
951 ctx = new_ctx = BN_CTX_new();
952 if (ctx == NULL)
953 return -1;
954 }
955
956 BN_CTX_start(ctx);
957 aX = BN_CTX_get(ctx);
958 aY = BN_CTX_get(ctx);
959 bX = BN_CTX_get(ctx);
960 bY = BN_CTX_get(ctx);
961 if (bY == NULL) goto err;
962
963 if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx)) goto err;
964 if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx)) goto err;
965 ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
966
967 err:
968 if (ctx) BN_CTX_end(ctx);
969 if (new_ctx) BN_CTX_free(new_ctx);
970 return ret;
971 }
972
973
974/* Forces the given EC_POINT to internally use affine coordinates. */
975int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
976 {
977 BN_CTX *new_ctx = NULL;
978 BIGNUM *x, *y;
979 int ret = 0;
980
981 if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
982 return 1;
983
984 if (ctx == NULL)
985 {
986 ctx = new_ctx = BN_CTX_new();
987 if (ctx == NULL)
988 return 0;
989 }
990
991 BN_CTX_start(ctx);
992 x = BN_CTX_get(ctx);
993 y = BN_CTX_get(ctx);
994 if (y == NULL) goto err;
995
996 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
997 if (!BN_copy(&point->X, x)) goto err;
998 if (!BN_copy(&point->Y, y)) goto err;
999 if (!BN_one(&point->Z)) goto err;
1000
1001 ret = 1;
1002
1003 err:
1004 if (ctx) BN_CTX_end(ctx);
1005 if (new_ctx) BN_CTX_free(new_ctx);
1006 return ret;
1007 }
1008
1009
1010/* Forces each of the EC_POINTs in the given array to use affine coordinates. */
1011int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1012 {
1013 size_t i;
1014
1015 for (i = 0; i < num; i++)
1016 {
1017 if (!group->meth->make_affine(group, points[i], ctx)) return 0;
1018 }
1019
1020 return 1;
1021 }
1022
1023
1024/* Wrapper to simple binary polynomial field multiplication implementation. */
1025int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1026 {
1027 return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
1028 }
1029
1030
1031/* Wrapper to simple binary polynomial field squaring implementation. */
1032int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
1033 {
1034 return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
1035 }
1036
1037
1038/* Wrapper to simple binary polynomial field division implementation. */
1039int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1040 {
1041 return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
1042 }
diff --git a/src/lib/libcrypto/ec/ec_ameth.c b/src/lib/libcrypto/ec/ec_ameth.c
new file mode 100644
index 0000000000..83909c1853
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_ameth.c
@@ -0,0 +1,660 @@
1/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2 * project 2006.
3 */
4/* ====================================================================
5 * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 * software must display the following acknowledgment:
21 * "This product includes software developed by the OpenSSL Project
22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 * endorse or promote products derived from this software without
26 * prior written permission. For written permission, please contact
27 * licensing@OpenSSL.org.
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 * nor may "OpenSSL" appear in their names without prior written
31 * permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 * acknowledgment:
35 * "This product includes software developed by the OpenSSL Project
36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com). This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com).
55 *
56 */
57
58#include <stdio.h>
59#include "cryptlib.h"
60#include <openssl/x509.h>
61#include <openssl/ec.h>
62#include <openssl/bn.h>
63#ifndef OPENSSL_NO_CMS
64#include <openssl/cms.h>
65#endif
66#include "asn1_locl.h"
67
68static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
69 {
70 const EC_GROUP *group;
71 int nid;
72 if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL)
73 {
74 ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
75 return 0;
76 }
77 if (EC_GROUP_get_asn1_flag(group)
78 && (nid = EC_GROUP_get_curve_name(group)))
79 /* we have a 'named curve' => just set the OID */
80 {
81 *ppval = OBJ_nid2obj(nid);
82 *pptype = V_ASN1_OBJECT;
83 }
84 else /* explicit parameters */
85 {
86 ASN1_STRING *pstr = NULL;
87 pstr = ASN1_STRING_new();
88 if (!pstr)
89 return 0;
90 pstr->length = i2d_ECParameters(ec_key, &pstr->data);
91 if (pstr->length < 0)
92 {
93 ASN1_STRING_free(pstr);
94 ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB);
95 return 0;
96 }
97 *ppval = pstr;
98 *pptype = V_ASN1_SEQUENCE;
99 }
100 return 1;
101 }
102
103static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
104 {
105 EC_KEY *ec_key = pkey->pkey.ec;
106 void *pval = NULL;
107 int ptype;
108 unsigned char *penc = NULL, *p;
109 int penclen;
110
111 if (!eckey_param2type(&ptype, &pval, ec_key))
112 {
113 ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB);
114 return 0;
115 }
116 penclen = i2o_ECPublicKey(ec_key, NULL);
117 if (penclen <= 0)
118 goto err;
119 penc = OPENSSL_malloc(penclen);
120 if (!penc)
121 goto err;
122 p = penc;
123 penclen = i2o_ECPublicKey(ec_key, &p);
124 if (penclen <= 0)
125 goto err;
126 if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC),
127 ptype, pval, penc, penclen))
128 return 1;
129 err:
130 if (ptype == V_ASN1_OBJECT)
131 ASN1_OBJECT_free(pval);
132 else
133 ASN1_STRING_free(pval);
134 if (penc)
135 OPENSSL_free(penc);
136 return 0;
137 }
138
139static EC_KEY *eckey_type2param(int ptype, void *pval)
140 {
141 EC_KEY *eckey = NULL;
142 if (ptype == V_ASN1_SEQUENCE)
143 {
144 ASN1_STRING *pstr = pval;
145 const unsigned char *pm = NULL;
146 int pmlen;
147 pm = pstr->data;
148 pmlen = pstr->length;
149 if (!(eckey = d2i_ECParameters(NULL, &pm, pmlen)))
150 {
151 ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
152 goto ecerr;
153 }
154 }
155 else if (ptype == V_ASN1_OBJECT)
156 {
157 ASN1_OBJECT *poid = pval;
158 EC_GROUP *group;
159
160 /* type == V_ASN1_OBJECT => the parameters are given
161 * by an asn1 OID
162 */
163 if ((eckey = EC_KEY_new()) == NULL)
164 {
165 ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE);
166 goto ecerr;
167 }
168 group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
169 if (group == NULL)
170 goto ecerr;
171 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
172 if (EC_KEY_set_group(eckey, group) == 0)
173 goto ecerr;
174 EC_GROUP_free(group);
175 }
176 else
177 {
178 ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
179 goto ecerr;
180 }
181
182 return eckey;
183
184 ecerr:
185 if (eckey)
186 EC_KEY_free(eckey);
187 return NULL;
188 }
189
190static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
191 {
192 const unsigned char *p = NULL;
193 void *pval;
194 int ptype, pklen;
195 EC_KEY *eckey = NULL;
196 X509_ALGOR *palg;
197
198 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
199 return 0;
200 X509_ALGOR_get0(NULL, &ptype, &pval, palg);
201
202 eckey = eckey_type2param(ptype, pval);
203
204 if (!eckey)
205 {
206 ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
207 return 0;
208 }
209
210 /* We have parameters now set public key */
211 if (!o2i_ECPublicKey(&eckey, &p, pklen))
212 {
213 ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR);
214 goto ecerr;
215 }
216
217 EVP_PKEY_assign_EC_KEY(pkey, eckey);
218 return 1;
219
220 ecerr:
221 if (eckey)
222 EC_KEY_free(eckey);
223 return 0;
224 }
225
226static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
227 {
228 int r;
229 const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
230 const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
231 *pb = EC_KEY_get0_public_key(b->pkey.ec);
232 r = EC_POINT_cmp(group, pa, pb, NULL);
233 if (r == 0)
234 return 1;
235 if (r == 1)
236 return 0;
237 return -2;
238 }
239
240static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
241 {
242 const unsigned char *p = NULL;
243 void *pval;
244 int ptype, pklen;
245 EC_KEY *eckey = NULL;
246 X509_ALGOR *palg;
247
248 if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
249 return 0;
250 X509_ALGOR_get0(NULL, &ptype, &pval, palg);
251
252 eckey = eckey_type2param(ptype, pval);
253
254 if (!eckey)
255 goto ecliberr;
256
257 /* We have parameters now set private key */
258 if (!d2i_ECPrivateKey(&eckey, &p, pklen))
259 {
260 ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
261 goto ecerr;
262 }
263
264 /* calculate public key (if necessary) */
265 if (EC_KEY_get0_public_key(eckey) == NULL)
266 {
267 const BIGNUM *priv_key;
268 const EC_GROUP *group;
269 EC_POINT *pub_key;
270 /* the public key was not included in the SEC1 private
271 * key => calculate the public key */
272 group = EC_KEY_get0_group(eckey);
273 pub_key = EC_POINT_new(group);
274 if (pub_key == NULL)
275 {
276 ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
277 goto ecliberr;
278 }
279 if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group)))
280 {
281 EC_POINT_free(pub_key);
282 ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
283 goto ecliberr;
284 }
285 priv_key = EC_KEY_get0_private_key(eckey);
286 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL))
287 {
288 EC_POINT_free(pub_key);
289 ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
290 goto ecliberr;
291 }
292 if (EC_KEY_set_public_key(eckey, pub_key) == 0)
293 {
294 EC_POINT_free(pub_key);
295 ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
296 goto ecliberr;
297 }
298 EC_POINT_free(pub_key);
299 }
300
301 EVP_PKEY_assign_EC_KEY(pkey, eckey);
302 return 1;
303
304 ecliberr:
305 ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
306 ecerr:
307 if (eckey)
308 EC_KEY_free(eckey);
309 return 0;
310 }
311
312static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
313{
314 EC_KEY *ec_key;
315 unsigned char *ep, *p;
316 int eplen, ptype;
317 void *pval;
318 unsigned int tmp_flags, old_flags;
319
320 ec_key = pkey->pkey.ec;
321
322 if (!eckey_param2type(&ptype, &pval, ec_key))
323 {
324 ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR);
325 return 0;
326 }
327
328 /* set the private key */
329
330 /* do not include the parameters in the SEC1 private key
331 * see PKCS#11 12.11 */
332 old_flags = EC_KEY_get_enc_flags(ec_key);
333 tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
334 EC_KEY_set_enc_flags(ec_key, tmp_flags);
335 eplen = i2d_ECPrivateKey(ec_key, NULL);
336 if (!eplen)
337 {
338 EC_KEY_set_enc_flags(ec_key, old_flags);
339 ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
340 return 0;
341 }
342 ep = (unsigned char *) OPENSSL_malloc(eplen);
343 if (!ep)
344 {
345 EC_KEY_set_enc_flags(ec_key, old_flags);
346 ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
347 return 0;
348 }
349 p = ep;
350 if (!i2d_ECPrivateKey(ec_key, &p))
351 {
352 EC_KEY_set_enc_flags(ec_key, old_flags);
353 OPENSSL_free(ep);
354 ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
355 }
356 /* restore old encoding flags */
357 EC_KEY_set_enc_flags(ec_key, old_flags);
358
359 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
360 ptype, pval, ep, eplen))
361 return 0;
362
363 return 1;
364}
365
366static int int_ec_size(const EVP_PKEY *pkey)
367 {
368 return ECDSA_size(pkey->pkey.ec);
369 }
370
371static int ec_bits(const EVP_PKEY *pkey)
372 {
373 BIGNUM *order = BN_new();
374 const EC_GROUP *group;
375 int ret;
376
377 if (!order)
378 {
379 ERR_clear_error();
380 return 0;
381 }
382 group = EC_KEY_get0_group(pkey->pkey.ec);
383 if (!EC_GROUP_get_order(group, order, NULL))
384 {
385 ERR_clear_error();
386 return 0;
387 }
388
389 ret = BN_num_bits(order);
390 BN_free(order);
391 return ret;
392 }
393
394static int ec_missing_parameters(const EVP_PKEY *pkey)
395 {
396 if (EC_KEY_get0_group(pkey->pkey.ec) == NULL)
397 return 1;
398 return 0;
399 }
400
401static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
402 {
403 EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
404 if (group == NULL)
405 return 0;
406 if (EC_KEY_set_group(to->pkey.ec, group) == 0)
407 return 0;
408 EC_GROUP_free(group);
409 return 1;
410 }
411
412static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
413 {
414 const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
415 *group_b = EC_KEY_get0_group(b->pkey.ec);
416 if (EC_GROUP_cmp(group_a, group_b, NULL))
417 return 0;
418 else
419 return 1;
420 }
421
422static void int_ec_free(EVP_PKEY *pkey)
423 {
424 EC_KEY_free(pkey->pkey.ec);
425 }
426
427static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
428 {
429 unsigned char *buffer=NULL;
430 const char *ecstr;
431 size_t buf_len=0, i;
432 int ret=0, reason=ERR_R_BIO_LIB;
433 BIGNUM *pub_key=NULL, *order=NULL;
434 BN_CTX *ctx=NULL;
435 const EC_GROUP *group;
436 const EC_POINT *public_key;
437 const BIGNUM *priv_key;
438
439 if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL)
440 {
441 reason = ERR_R_PASSED_NULL_PARAMETER;
442 goto err;
443 }
444
445 ctx = BN_CTX_new();
446 if (ctx == NULL)
447 {
448 reason = ERR_R_MALLOC_FAILURE;
449 goto err;
450 }
451
452 if (ktype > 0)
453 {
454 public_key = EC_KEY_get0_public_key(x);
455 if ((pub_key = EC_POINT_point2bn(group, public_key,
456 EC_KEY_get_conv_form(x), NULL, ctx)) == NULL)
457 {
458 reason = ERR_R_EC_LIB;
459 goto err;
460 }
461 if (pub_key)
462 buf_len = (size_t)BN_num_bytes(pub_key);
463 }
464
465 if (ktype == 2)
466 {
467 priv_key = EC_KEY_get0_private_key(x);
468 if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len)
469 buf_len = i;
470 }
471 else
472 priv_key = NULL;
473
474 if (ktype > 0)
475 {
476 buf_len += 10;
477 if ((buffer = OPENSSL_malloc(buf_len)) == NULL)
478 {
479 reason = ERR_R_MALLOC_FAILURE;
480 goto err;
481 }
482 }
483 if (ktype == 2)
484 ecstr = "Private-Key";
485 else if (ktype == 1)
486 ecstr = "Public-Key";
487 else
488 ecstr = "ECDSA-Parameters";
489
490 if (!BIO_indent(bp, off, 128))
491 goto err;
492 if ((order = BN_new()) == NULL)
493 goto err;
494 if (!EC_GROUP_get_order(group, order, NULL))
495 goto err;
496 if (BIO_printf(bp, "%s: (%d bit)\n", ecstr,
497 BN_num_bits(order)) <= 0) goto err;
498
499 if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key,
500 buffer, off))
501 goto err;
502 if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key,
503 buffer, off))
504 goto err;
505 if (!ECPKParameters_print(bp, group, off))
506 goto err;
507 ret=1;
508err:
509 if (!ret)
510 ECerr(EC_F_DO_EC_KEY_PRINT, reason);
511 if (pub_key)
512 BN_free(pub_key);
513 if (order)
514 BN_free(order);
515 if (ctx)
516 BN_CTX_free(ctx);
517 if (buffer != NULL)
518 OPENSSL_free(buffer);
519 return(ret);
520 }
521
522static int eckey_param_decode(EVP_PKEY *pkey,
523 const unsigned char **pder, int derlen)
524 {
525 EC_KEY *eckey;
526 if (!(eckey = d2i_ECParameters(NULL, pder, derlen)))
527 {
528 ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB);
529 return 0;
530 }
531 EVP_PKEY_assign_EC_KEY(pkey, eckey);
532 return 1;
533 }
534
535static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
536 {
537 return i2d_ECParameters(pkey->pkey.ec, pder);
538 }
539
540static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
541 ASN1_PCTX *ctx)
542 {
543 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
544 }
545
546static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
547 ASN1_PCTX *ctx)
548 {
549 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
550 }
551
552
553static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
554 ASN1_PCTX *ctx)
555 {
556 return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
557 }
558
559static int old_ec_priv_decode(EVP_PKEY *pkey,
560 const unsigned char **pder, int derlen)
561 {
562 EC_KEY *ec;
563 if (!(ec = d2i_ECPrivateKey (NULL, pder, derlen)))
564 {
565 ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR);
566 return 0;
567 }
568 EVP_PKEY_assign_EC_KEY(pkey, ec);
569 return 1;
570 }
571
572static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
573 {
574 return i2d_ECPrivateKey(pkey->pkey.ec, pder);
575 }
576
577static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
578 {
579 switch (op)
580 {
581 case ASN1_PKEY_CTRL_PKCS7_SIGN:
582 if (arg1 == 0)
583 {
584 int snid, hnid;
585 X509_ALGOR *alg1, *alg2;
586 PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
587 if (alg1 == NULL || alg1->algorithm == NULL)
588 return -1;
589 hnid = OBJ_obj2nid(alg1->algorithm);
590 if (hnid == NID_undef)
591 return -1;
592 if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
593 return -1;
594 X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
595 }
596 return 1;
597#ifndef OPENSSL_NO_CMS
598 case ASN1_PKEY_CTRL_CMS_SIGN:
599 if (arg1 == 0)
600 {
601 int snid, hnid;
602 X509_ALGOR *alg1, *alg2;
603 CMS_SignerInfo_get0_algs(arg2, NULL, NULL,
604 &alg1, &alg2);
605 if (alg1 == NULL || alg1->algorithm == NULL)
606 return -1;
607 hnid = OBJ_obj2nid(alg1->algorithm);
608 if (hnid == NID_undef)
609 return -1;
610 if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
611 return -1;
612 X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
613 }
614 return 1;
615#endif
616
617 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
618 *(int *)arg2 = NID_sha1;
619 return 2;
620
621 default:
622 return -2;
623
624 }
625
626 }
627
628const EVP_PKEY_ASN1_METHOD eckey_asn1_meth =
629 {
630 EVP_PKEY_EC,
631 EVP_PKEY_EC,
632 0,
633 "EC",
634 "OpenSSL EC algorithm",
635
636 eckey_pub_decode,
637 eckey_pub_encode,
638 eckey_pub_cmp,
639 eckey_pub_print,
640
641 eckey_priv_decode,
642 eckey_priv_encode,
643 eckey_priv_print,
644
645 int_ec_size,
646 ec_bits,
647
648 eckey_param_decode,
649 eckey_param_encode,
650 ec_missing_parameters,
651 ec_copy_parameters,
652 ec_cmp_parameters,
653 eckey_param_print,
654 0,
655
656 int_ec_free,
657 ec_pkey_ctrl,
658 old_ec_priv_decode,
659 old_ec_priv_encode
660 };
diff --git a/src/lib/libcrypto/ec/ec_asn1.c b/src/lib/libcrypto/ec/ec_asn1.c
new file mode 100644
index 0000000000..175eec5342
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_asn1.c
@@ -0,0 +1,1443 @@
1/* crypto/ec/ec_asn1.c */
2/*
3 * Written by Nils Larsch for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 2000-2003 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <string.h>
60#include "ec_lcl.h"
61#include <openssl/err.h>
62#include <openssl/asn1t.h>
63#include <openssl/objects.h>
64
65
66int EC_GROUP_get_basis_type(const EC_GROUP *group)
67 {
68 int i=0;
69
70 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
71 NID_X9_62_characteristic_two_field)
72 /* everything else is currently not supported */
73 return 0;
74
75 while (group->poly[i] != 0)
76 i++;
77
78 if (i == 4)
79 return NID_X9_62_ppBasis;
80 else if (i == 2)
81 return NID_X9_62_tpBasis;
82 else
83 /* everything else is currently not supported */
84 return 0;
85 }
86#ifndef OPENSSL_NO_EC2M
87int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
88 {
89 if (group == NULL)
90 return 0;
91
92 if (EC_GROUP_method_of(group)->group_set_curve != ec_GF2m_simple_group_set_curve
93 || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] == 0)))
94 {
95 ECerr(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
96 return 0;
97 }
98
99 if (k)
100 *k = group->poly[1];
101
102 return 1;
103 }
104int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
105 unsigned int *k2, unsigned int *k3)
106 {
107 if (group == NULL)
108 return 0;
109
110 if (EC_GROUP_method_of(group)->group_set_curve != ec_GF2m_simple_group_set_curve
111 || !((group->poly[0] != 0) && (group->poly[1] != 0) && (group->poly[2] != 0) && (group->poly[3] != 0) && (group->poly[4] == 0)))
112 {
113 ECerr(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
114 return 0;
115 }
116
117 if (k1)
118 *k1 = group->poly[3];
119 if (k2)
120 *k2 = group->poly[2];
121 if (k3)
122 *k3 = group->poly[1];
123
124 return 1;
125 }
126#endif
127
128
129/* some structures needed for the asn1 encoding */
130typedef struct x9_62_pentanomial_st {
131 long k1;
132 long k2;
133 long k3;
134 } X9_62_PENTANOMIAL;
135
136typedef struct x9_62_characteristic_two_st {
137 long m;
138 ASN1_OBJECT *type;
139 union {
140 char *ptr;
141 /* NID_X9_62_onBasis */
142 ASN1_NULL *onBasis;
143 /* NID_X9_62_tpBasis */
144 ASN1_INTEGER *tpBasis;
145 /* NID_X9_62_ppBasis */
146 X9_62_PENTANOMIAL *ppBasis;
147 /* anything else */
148 ASN1_TYPE *other;
149 } p;
150 } X9_62_CHARACTERISTIC_TWO;
151
152typedef struct x9_62_fieldid_st {
153 ASN1_OBJECT *fieldType;
154 union {
155 char *ptr;
156 /* NID_X9_62_prime_field */
157 ASN1_INTEGER *prime;
158 /* NID_X9_62_characteristic_two_field */
159 X9_62_CHARACTERISTIC_TWO *char_two;
160 /* anything else */
161 ASN1_TYPE *other;
162 } p;
163 } X9_62_FIELDID;
164
165typedef struct x9_62_curve_st {
166 ASN1_OCTET_STRING *a;
167 ASN1_OCTET_STRING *b;
168 ASN1_BIT_STRING *seed;
169 } X9_62_CURVE;
170
171typedef struct ec_parameters_st {
172 long version;
173 X9_62_FIELDID *fieldID;
174 X9_62_CURVE *curve;
175 ASN1_OCTET_STRING *base;
176 ASN1_INTEGER *order;
177 ASN1_INTEGER *cofactor;
178 } ECPARAMETERS;
179
180struct ecpk_parameters_st {
181 int type;
182 union {
183 ASN1_OBJECT *named_curve;
184 ECPARAMETERS *parameters;
185 ASN1_NULL *implicitlyCA;
186 } value;
187 }/* ECPKPARAMETERS */;
188
189/* SEC1 ECPrivateKey */
190typedef struct ec_privatekey_st {
191 long version;
192 ASN1_OCTET_STRING *privateKey;
193 ECPKPARAMETERS *parameters;
194 ASN1_BIT_STRING *publicKey;
195 } EC_PRIVATEKEY;
196
197/* the OpenSSL ASN.1 definitions */
198ASN1_SEQUENCE(X9_62_PENTANOMIAL) = {
199 ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG),
200 ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG),
201 ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG)
202} ASN1_SEQUENCE_END(X9_62_PENTANOMIAL)
203
204DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
205IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
206
207ASN1_ADB_TEMPLATE(char_two_def) = ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.other, ASN1_ANY);
208
209ASN1_ADB(X9_62_CHARACTERISTIC_TWO) = {
210 ADB_ENTRY(NID_X9_62_onBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.onBasis, ASN1_NULL)),
211 ADB_ENTRY(NID_X9_62_tpBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.tpBasis, ASN1_INTEGER)),
212 ADB_ENTRY(NID_X9_62_ppBasis, ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, p.ppBasis, X9_62_PENTANOMIAL))
213} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL);
214
215ASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = {
216 ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG),
217 ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT),
218 ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO)
219} ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO)
220
221DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
222IMPLEMENT_ASN1_ALLOC_FUNCTIONS(X9_62_CHARACTERISTIC_TWO)
223
224ASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY);
225
226ASN1_ADB(X9_62_FIELDID) = {
227 ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
228 ADB_ENTRY(NID_X9_62_characteristic_two_field, ASN1_SIMPLE(X9_62_FIELDID, p.char_two, X9_62_CHARACTERISTIC_TWO))
229} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL);
230
231ASN1_SEQUENCE(X9_62_FIELDID) = {
232 ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
233 ASN1_ADB_OBJECT(X9_62_FIELDID)
234} ASN1_SEQUENCE_END(X9_62_FIELDID)
235
236ASN1_SEQUENCE(X9_62_CURVE) = {
237 ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
238 ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
239 ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
240} ASN1_SEQUENCE_END(X9_62_CURVE)
241
242ASN1_SEQUENCE(ECPARAMETERS) = {
243 ASN1_SIMPLE(ECPARAMETERS, version, LONG),
244 ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
245 ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
246 ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
247 ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
248 ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER)
249} ASN1_SEQUENCE_END(ECPARAMETERS)
250
251DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
252IMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS)
253
254ASN1_CHOICE(ECPKPARAMETERS) = {
255 ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
256 ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
257 ASN1_SIMPLE(ECPKPARAMETERS, value.implicitlyCA, ASN1_NULL)
258} ASN1_CHOICE_END(ECPKPARAMETERS)
259
260DECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
261DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS)
262IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
263
264ASN1_SEQUENCE(EC_PRIVATEKEY) = {
265 ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
266 ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
267 ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
268 ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1)
269} ASN1_SEQUENCE_END(EC_PRIVATEKEY)
270
271DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
272DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY)
273IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY)
274
275/* some declarations of internal function */
276
277/* ec_asn1_group2field() sets the values in a X9_62_FIELDID object */
278static int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *);
279/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */
280static int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *);
281/* ec_asn1_parameters2group() creates a EC_GROUP object from a
282 * ECPARAMETERS object */
283static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *);
284/* ec_asn1_group2parameters() creates a ECPARAMETERS object from a
285 * EC_GROUP object */
286static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *,ECPARAMETERS *);
287/* ec_asn1_pkparameters2group() creates a EC_GROUP object from a
288 * ECPKPARAMETERS object */
289static EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *);
290/* ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a
291 * EC_GROUP object */
292static ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *,
293 ECPKPARAMETERS *);
294
295
296/* the function definitions */
297
298static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
299 {
300 int ok=0, nid;
301 BIGNUM *tmp = NULL;
302
303 if (group == NULL || field == NULL)
304 return 0;
305
306 /* clear the old values (if necessary) */
307 if (field->fieldType != NULL)
308 ASN1_OBJECT_free(field->fieldType);
309 if (field->p.other != NULL)
310 ASN1_TYPE_free(field->p.other);
311
312 nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
313 /* set OID for the field */
314 if ((field->fieldType = OBJ_nid2obj(nid)) == NULL)
315 {
316 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
317 goto err;
318 }
319
320 if (nid == NID_X9_62_prime_field)
321 {
322 if ((tmp = BN_new()) == NULL)
323 {
324 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
325 goto err;
326 }
327 /* the parameters are specified by the prime number p */
328 if (!EC_GROUP_get_curve_GFp(group, tmp, NULL, NULL, NULL))
329 {
330 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
331 goto err;
332 }
333 /* set the prime number */
334 field->p.prime = BN_to_ASN1_INTEGER(tmp,NULL);
335 if (field->p.prime == NULL)
336 {
337 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_ASN1_LIB);
338 goto err;
339 }
340 }
341 else /* nid == NID_X9_62_characteristic_two_field */
342#ifdef OPENSSL_NO_EC2M
343 {
344 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED);
345 goto err;
346 }
347#else
348 {
349 int field_type;
350 X9_62_CHARACTERISTIC_TWO *char_two;
351
352 field->p.char_two = X9_62_CHARACTERISTIC_TWO_new();
353 char_two = field->p.char_two;
354
355 if (char_two == NULL)
356 {
357 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
358 goto err;
359 }
360
361 char_two->m = (long)EC_GROUP_get_degree(group);
362
363 field_type = EC_GROUP_get_basis_type(group);
364
365 if (field_type == 0)
366 {
367 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_EC_LIB);
368 goto err;
369 }
370 /* set base type OID */
371 if ((char_two->type = OBJ_nid2obj(field_type)) == NULL)
372 {
373 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_OBJ_LIB);
374 goto err;
375 }
376
377 if (field_type == NID_X9_62_tpBasis)
378 {
379 unsigned int k;
380
381 if (!EC_GROUP_get_trinomial_basis(group, &k))
382 goto err;
383
384 char_two->p.tpBasis = ASN1_INTEGER_new();
385 if (!char_two->p.tpBasis)
386 {
387 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
388 goto err;
389 }
390 if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k))
391 {
392 ECerr(EC_F_EC_ASN1_GROUP2FIELDID,
393 ERR_R_ASN1_LIB);
394 goto err;
395 }
396 }
397 else if (field_type == NID_X9_62_ppBasis)
398 {
399 unsigned int k1, k2, k3;
400
401 if (!EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3))
402 goto err;
403
404 char_two->p.ppBasis = X9_62_PENTANOMIAL_new();
405 if (!char_two->p.ppBasis)
406 {
407 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
408 goto err;
409 }
410
411 /* set k? values */
412 char_two->p.ppBasis->k1 = (long)k1;
413 char_two->p.ppBasis->k2 = (long)k2;
414 char_two->p.ppBasis->k3 = (long)k3;
415 }
416 else /* field_type == NID_X9_62_onBasis */
417 {
418 /* for ONB the parameters are (asn1) NULL */
419 char_two->p.onBasis = ASN1_NULL_new();
420 if (!char_two->p.onBasis)
421 {
422 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, ERR_R_MALLOC_FAILURE);
423 goto err;
424 }
425 }
426 }
427#endif
428
429 ok = 1;
430
431err : if (tmp)
432 BN_free(tmp);
433 return(ok);
434}
435
436static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
437 {
438 int ok=0, nid;
439 BIGNUM *tmp_1=NULL, *tmp_2=NULL;
440 unsigned char *buffer_1=NULL, *buffer_2=NULL,
441 *a_buf=NULL, *b_buf=NULL;
442 size_t len_1, len_2;
443 unsigned char char_zero = 0;
444
445 if (!group || !curve || !curve->a || !curve->b)
446 return 0;
447
448 if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL)
449 {
450 ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
451 goto err;
452 }
453
454 nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
455
456 /* get a and b */
457 if (nid == NID_X9_62_prime_field)
458 {
459 if (!EC_GROUP_get_curve_GFp(group, NULL, tmp_1, tmp_2, NULL))
460 {
461 ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
462 goto err;
463 }
464 }
465#ifndef OPENSSL_NO_EC2M
466 else /* nid == NID_X9_62_characteristic_two_field */
467 {
468 if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL))
469 {
470 ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_EC_LIB);
471 goto err;
472 }
473 }
474#endif
475 len_1 = (size_t)BN_num_bytes(tmp_1);
476 len_2 = (size_t)BN_num_bytes(tmp_2);
477
478 if (len_1 == 0)
479 {
480 /* len_1 == 0 => a == 0 */
481 a_buf = &char_zero;
482 len_1 = 1;
483 }
484 else
485 {
486 if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL)
487 {
488 ECerr(EC_F_EC_ASN1_GROUP2CURVE,
489 ERR_R_MALLOC_FAILURE);
490 goto err;
491 }
492 if ( (len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0)
493 {
494 ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
495 goto err;
496 }
497 a_buf = buffer_1;
498 }
499
500 if (len_2 == 0)
501 {
502 /* len_2 == 0 => b == 0 */
503 b_buf = &char_zero;
504 len_2 = 1;
505 }
506 else
507 {
508 if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL)
509 {
510 ECerr(EC_F_EC_ASN1_GROUP2CURVE,
511 ERR_R_MALLOC_FAILURE);
512 goto err;
513 }
514 if ( (len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0)
515 {
516 ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
517 goto err;
518 }
519 b_buf = buffer_2;
520 }
521
522 /* set a and b */
523 if (!M_ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) ||
524 !M_ASN1_OCTET_STRING_set(curve->b, b_buf, len_2))
525 {
526 ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
527 goto err;
528 }
529
530 /* set the seed (optional) */
531 if (group->seed)
532 {
533 if (!curve->seed)
534 if ((curve->seed = ASN1_BIT_STRING_new()) == NULL)
535 {
536 ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
537 goto err;
538 }
539 curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
540 curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT;
541 if (!ASN1_BIT_STRING_set(curve->seed, group->seed,
542 (int)group->seed_len))
543 {
544 ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
545 goto err;
546 }
547 }
548 else
549 {
550 if (curve->seed)
551 {
552 ASN1_BIT_STRING_free(curve->seed);
553 curve->seed = NULL;
554 }
555 }
556
557 ok = 1;
558
559err: if (buffer_1)
560 OPENSSL_free(buffer_1);
561 if (buffer_2)
562 OPENSSL_free(buffer_2);
563 if (tmp_1)
564 BN_free(tmp_1);
565 if (tmp_2)
566 BN_free(tmp_2);
567 return(ok);
568 }
569
570static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *group,
571 ECPARAMETERS *param)
572 {
573 int ok=0;
574 size_t len=0;
575 ECPARAMETERS *ret=NULL;
576 BIGNUM *tmp=NULL;
577 unsigned char *buffer=NULL;
578 const EC_POINT *point=NULL;
579 point_conversion_form_t form;
580
581 if ((tmp = BN_new()) == NULL)
582 {
583 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
584 goto err;
585 }
586
587 if (param == NULL)
588 {
589 if ((ret = ECPARAMETERS_new()) == NULL)
590 {
591 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS,
592 ERR_R_MALLOC_FAILURE);
593 goto err;
594 }
595 }
596 else
597 ret = param;
598
599 /* set the version (always one) */
600 ret->version = (long)0x1;
601
602 /* set the fieldID */
603 if (!ec_asn1_group2fieldid(group, ret->fieldID))
604 {
605 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
606 goto err;
607 }
608
609 /* set the curve */
610 if (!ec_asn1_group2curve(group, ret->curve))
611 {
612 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
613 goto err;
614 }
615
616 /* set the base point */
617 if ((point = EC_GROUP_get0_generator(group)) == NULL)
618 {
619 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, EC_R_UNDEFINED_GENERATOR);
620 goto err;
621 }
622
623 form = EC_GROUP_get_point_conversion_form(group);
624
625 len = EC_POINT_point2oct(group, point, form, NULL, len, NULL);
626 if (len == 0)
627 {
628 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
629 goto err;
630 }
631 if ((buffer = OPENSSL_malloc(len)) == NULL)
632 {
633 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
634 goto err;
635 }
636 if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL))
637 {
638 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
639 goto err;
640 }
641 if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL)
642 {
643 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_MALLOC_FAILURE);
644 goto err;
645 }
646 if (!ASN1_OCTET_STRING_set(ret->base, buffer, len))
647 {
648 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
649 goto err;
650 }
651
652 /* set the order */
653 if (!EC_GROUP_get_order(group, tmp, NULL))
654 {
655 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_EC_LIB);
656 goto err;
657 }
658 ret->order = BN_to_ASN1_INTEGER(tmp, ret->order);
659 if (ret->order == NULL)
660 {
661 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
662 goto err;
663 }
664
665 /* set the cofactor (optional) */
666 if (EC_GROUP_get_cofactor(group, tmp, NULL))
667 {
668 ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor);
669 if (ret->cofactor == NULL)
670 {
671 ECerr(EC_F_EC_ASN1_GROUP2PARAMETERS, ERR_R_ASN1_LIB);
672 goto err;
673 }
674 }
675
676 ok = 1;
677
678err : if(!ok)
679 {
680 if (ret && !param)
681 ECPARAMETERS_free(ret);
682 ret = NULL;
683 }
684 if (tmp)
685 BN_free(tmp);
686 if (buffer)
687 OPENSSL_free(buffer);
688 return(ret);
689 }
690
691ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
692 ECPKPARAMETERS *params)
693 {
694 int ok = 1, tmp;
695 ECPKPARAMETERS *ret = params;
696
697 if (ret == NULL)
698 {
699 if ((ret = ECPKPARAMETERS_new()) == NULL)
700 {
701 ECerr(EC_F_EC_ASN1_GROUP2PKPARAMETERS,
702 ERR_R_MALLOC_FAILURE);
703 return NULL;
704 }
705 }
706 else
707 {
708 if (ret->type == 0 && ret->value.named_curve)
709 ASN1_OBJECT_free(ret->value.named_curve);
710 else if (ret->type == 1 && ret->value.parameters)
711 ECPARAMETERS_free(ret->value.parameters);
712 }
713
714 if (EC_GROUP_get_asn1_flag(group))
715 {
716 /* use the asn1 OID to describe the
717 * the elliptic curve parameters
718 */
719 tmp = EC_GROUP_get_curve_name(group);
720 if (tmp)
721 {
722 ret->type = 0;
723 if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL)
724 ok = 0;
725 }
726 else
727 /* we don't kmow the nid => ERROR */
728 ok = 0;
729 }
730 else
731 {
732 /* use the ECPARAMETERS structure */
733 ret->type = 1;
734 if ((ret->value.parameters = ec_asn1_group2parameters(
735 group, NULL)) == NULL)
736 ok = 0;
737 }
738
739 if (!ok)
740 {
741 ECPKPARAMETERS_free(ret);
742 return NULL;
743 }
744 return ret;
745 }
746
747static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
748 {
749 int ok = 0, tmp;
750 EC_GROUP *ret = NULL;
751 BIGNUM *p = NULL, *a = NULL, *b = NULL;
752 EC_POINT *point=NULL;
753 long field_bits;
754
755 if (!params->fieldID || !params->fieldID->fieldType ||
756 !params->fieldID->p.ptr)
757 {
758 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
759 goto err;
760 }
761
762 /* now extract the curve parameters a and b */
763 if (!params->curve || !params->curve->a ||
764 !params->curve->a->data || !params->curve->b ||
765 !params->curve->b->data)
766 {
767 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
768 goto err;
769 }
770 a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL);
771 if (a == NULL)
772 {
773 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
774 goto err;
775 }
776 b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL);
777 if (b == NULL)
778 {
779 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_BN_LIB);
780 goto err;
781 }
782
783 /* get the field parameters */
784 tmp = OBJ_obj2nid(params->fieldID->fieldType);
785 if (tmp == NID_X9_62_characteristic_two_field)
786#ifdef OPENSSL_NO_EC2M
787 {
788 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_GF2M_NOT_SUPPORTED);
789 goto err;
790 }
791#else
792 {
793 X9_62_CHARACTERISTIC_TWO *char_two;
794
795 char_two = params->fieldID->p.char_two;
796
797 field_bits = char_two->m;
798 if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS)
799 {
800 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
801 goto err;
802 }
803
804 if ((p = BN_new()) == NULL)
805 {
806 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_MALLOC_FAILURE);
807 goto err;
808 }
809
810 /* get the base type */
811 tmp = OBJ_obj2nid(char_two->type);
812
813 if (tmp == NID_X9_62_tpBasis)
814 {
815 long tmp_long;
816
817 if (!char_two->p.tpBasis)
818 {
819 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
820 goto err;
821 }
822
823 tmp_long = ASN1_INTEGER_get(char_two->p.tpBasis);
824
825 if (!(char_two->m > tmp_long && tmp_long > 0))
826 {
827 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_TRINOMIAL_BASIS);
828 goto err;
829 }
830
831 /* create the polynomial */
832 if (!BN_set_bit(p, (int)char_two->m))
833 goto err;
834 if (!BN_set_bit(p, (int)tmp_long))
835 goto err;
836 if (!BN_set_bit(p, 0))
837 goto err;
838 }
839 else if (tmp == NID_X9_62_ppBasis)
840 {
841 X9_62_PENTANOMIAL *penta;
842
843 penta = char_two->p.ppBasis;
844 if (!penta)
845 {
846 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
847 goto err;
848 }
849
850 if (!(char_two->m > penta->k3 && penta->k3 > penta->k2 && penta->k2 > penta->k1 && penta->k1 > 0))
851 {
852 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_PENTANOMIAL_BASIS);
853 goto err;
854 }
855
856 /* create the polynomial */
857 if (!BN_set_bit(p, (int)char_two->m)) goto err;
858 if (!BN_set_bit(p, (int)penta->k1)) goto err;
859 if (!BN_set_bit(p, (int)penta->k2)) goto err;
860 if (!BN_set_bit(p, (int)penta->k3)) goto err;
861 if (!BN_set_bit(p, 0)) goto err;
862 }
863 else if (tmp == NID_X9_62_onBasis)
864 {
865 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_NOT_IMPLEMENTED);
866 goto err;
867 }
868 else /* error */
869 {
870 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
871 goto err;
872 }
873
874 /* create the EC_GROUP structure */
875 ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
876 }
877#endif
878 else if (tmp == NID_X9_62_prime_field)
879 {
880 /* we have a curve over a prime field */
881 /* extract the prime number */
882 if (!params->fieldID->p.prime)
883 {
884 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
885 goto err;
886 }
887 p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL);
888 if (p == NULL)
889 {
890 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
891 goto err;
892 }
893
894 if (BN_is_negative(p) || BN_is_zero(p))
895 {
896 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
897 goto err;
898 }
899
900 field_bits = BN_num_bits(p);
901 if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS)
902 {
903 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_FIELD_TOO_LARGE);
904 goto err;
905 }
906
907 /* create the EC_GROUP structure */
908 ret = EC_GROUP_new_curve_GFp(p, a, b, NULL);
909 }
910 else
911 {
912 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_FIELD);
913 goto err;
914 }
915
916 if (ret == NULL)
917 {
918 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
919 goto err;
920 }
921
922 /* extract seed (optional) */
923 if (params->curve->seed != NULL)
924 {
925 if (ret->seed != NULL)
926 OPENSSL_free(ret->seed);
927 if (!(ret->seed = OPENSSL_malloc(params->curve->seed->length)))
928 {
929 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP,
930 ERR_R_MALLOC_FAILURE);
931 goto err;
932 }
933 memcpy(ret->seed, params->curve->seed->data,
934 params->curve->seed->length);
935 ret->seed_len = params->curve->seed->length;
936 }
937
938 if (!params->order || !params->base || !params->base->data)
939 {
940 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_ASN1_ERROR);
941 goto err;
942 }
943
944 if ((point = EC_POINT_new(ret)) == NULL) goto err;
945
946 /* set the point conversion form */
947 EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t)
948 (params->base->data[0] & ~0x01));
949
950 /* extract the ec point */
951 if (!EC_POINT_oct2point(ret, point, params->base->data,
952 params->base->length, NULL))
953 {
954 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
955 goto err;
956 }
957
958 /* extract the order */
959 if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL)
960 {
961 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
962 goto err;
963 }
964 if (BN_is_negative(a) || BN_is_zero(a))
965 {
966 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
967 goto err;
968 }
969 if (BN_num_bits(a) > (int)field_bits + 1) /* Hasse bound */
970 {
971 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_INVALID_GROUP_ORDER);
972 goto err;
973 }
974
975 /* extract the cofactor (optional) */
976 if (params->cofactor == NULL)
977 {
978 if (b)
979 {
980 BN_free(b);
981 b = NULL;
982 }
983 }
984 else
985 if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL)
986 {
987 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_ASN1_LIB);
988 goto err;
989 }
990 /* set the generator, order and cofactor (if present) */
991 if (!EC_GROUP_set_generator(ret, point, a, b))
992 {
993 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, ERR_R_EC_LIB);
994 goto err;
995 }
996
997 ok = 1;
998
999err: if (!ok)
1000 {
1001 if (ret)
1002 EC_GROUP_clear_free(ret);
1003 ret = NULL;
1004 }
1005
1006 if (p)
1007 BN_free(p);
1008 if (a)
1009 BN_free(a);
1010 if (b)
1011 BN_free(b);
1012 if (point)
1013 EC_POINT_free(point);
1014 return(ret);
1015}
1016
1017EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params)
1018 {
1019 EC_GROUP *ret=NULL;
1020 int tmp=0;
1021
1022 if (params == NULL)
1023 {
1024 ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP,
1025 EC_R_MISSING_PARAMETERS);
1026 return NULL;
1027 }
1028
1029 if (params->type == 0)
1030 { /* the curve is given by an OID */
1031 tmp = OBJ_obj2nid(params->value.named_curve);
1032 if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL)
1033 {
1034 ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP,
1035 EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
1036 return NULL;
1037 }
1038 EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE);
1039 }
1040 else if (params->type == 1)
1041 { /* the parameters are given by a ECPARAMETERS
1042 * structure */
1043 ret = ec_asn1_parameters2group(params->value.parameters);
1044 if (!ret)
1045 {
1046 ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, ERR_R_EC_LIB);
1047 return NULL;
1048 }
1049 EC_GROUP_set_asn1_flag(ret, 0x0);
1050 }
1051 else if (params->type == 2)
1052 { /* implicitlyCA */
1053 return NULL;
1054 }
1055 else
1056 {
1057 ECerr(EC_F_EC_ASN1_PKPARAMETERS2GROUP, EC_R_ASN1_ERROR);
1058 return NULL;
1059 }
1060
1061 return ret;
1062 }
1063
1064/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */
1065
1066EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
1067 {
1068 EC_GROUP *group = NULL;
1069 ECPKPARAMETERS *params = NULL;
1070
1071 if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL)
1072 {
1073 ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_D2I_ECPKPARAMETERS_FAILURE);
1074 ECPKPARAMETERS_free(params);
1075 return NULL;
1076 }
1077
1078 if ((group = ec_asn1_pkparameters2group(params)) == NULL)
1079 {
1080 ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE);
1081 ECPKPARAMETERS_free(params);
1082 return NULL;
1083 }
1084
1085
1086 if (a && *a)
1087 EC_GROUP_clear_free(*a);
1088 if (a)
1089 *a = group;
1090
1091 ECPKPARAMETERS_free(params);
1092 return(group);
1093 }
1094
1095int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
1096 {
1097 int ret=0;
1098 ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL);
1099 if (tmp == NULL)
1100 {
1101 ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_GROUP2PKPARAMETERS_FAILURE);
1102 return 0;
1103 }
1104 if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0)
1105 {
1106 ECerr(EC_F_I2D_ECPKPARAMETERS, EC_R_I2D_ECPKPARAMETERS_FAILURE);
1107 ECPKPARAMETERS_free(tmp);
1108 return 0;
1109 }
1110 ECPKPARAMETERS_free(tmp);
1111 return(ret);
1112 }
1113
1114/* some EC_KEY functions */
1115
1116EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
1117 {
1118 int ok=0;
1119 EC_KEY *ret=NULL;
1120 EC_PRIVATEKEY *priv_key=NULL;
1121
1122 if ((priv_key = EC_PRIVATEKEY_new()) == NULL)
1123 {
1124 ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1125 return NULL;
1126 }
1127
1128 if ((priv_key = d2i_EC_PRIVATEKEY(&priv_key, in, len)) == NULL)
1129 {
1130 ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1131 EC_PRIVATEKEY_free(priv_key);
1132 return NULL;
1133 }
1134
1135 if (a == NULL || *a == NULL)
1136 {
1137 if ((ret = EC_KEY_new()) == NULL)
1138 {
1139 ECerr(EC_F_D2I_ECPRIVATEKEY,
1140 ERR_R_MALLOC_FAILURE);
1141 goto err;
1142 }
1143 if (a)
1144 *a = ret;
1145 }
1146 else
1147 ret = *a;
1148
1149 if (priv_key->parameters)
1150 {
1151 if (ret->group)
1152 EC_GROUP_clear_free(ret->group);
1153 ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
1154 }
1155
1156 if (ret->group == NULL)
1157 {
1158 ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1159 goto err;
1160 }
1161
1162 ret->version = priv_key->version;
1163
1164 if (priv_key->privateKey)
1165 {
1166 ret->priv_key = BN_bin2bn(
1167 M_ASN1_STRING_data(priv_key->privateKey),
1168 M_ASN1_STRING_length(priv_key->privateKey),
1169 ret->priv_key);
1170 if (ret->priv_key == NULL)
1171 {
1172 ECerr(EC_F_D2I_ECPRIVATEKEY,
1173 ERR_R_BN_LIB);
1174 goto err;
1175 }
1176 }
1177 else
1178 {
1179 ECerr(EC_F_D2I_ECPRIVATEKEY,
1180 EC_R_MISSING_PRIVATE_KEY);
1181 goto err;
1182 }
1183
1184 if (priv_key->publicKey)
1185 {
1186 const unsigned char *pub_oct;
1187 size_t pub_oct_len;
1188
1189 if (ret->pub_key)
1190 EC_POINT_clear_free(ret->pub_key);
1191 ret->pub_key = EC_POINT_new(ret->group);
1192 if (ret->pub_key == NULL)
1193 {
1194 ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1195 goto err;
1196 }
1197 pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
1198 pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
1199 /* save the point conversion form */
1200 ret->conv_form = (point_conversion_form_t)(pub_oct[0] & ~0x01);
1201 if (!EC_POINT_oct2point(ret->group, ret->pub_key,
1202 pub_oct, pub_oct_len, NULL))
1203 {
1204 ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
1205 goto err;
1206 }
1207 }
1208
1209 ok = 1;
1210err:
1211 if (!ok)
1212 {
1213 if (ret)
1214 EC_KEY_free(ret);
1215 ret = NULL;
1216 }
1217
1218 if (priv_key)
1219 EC_PRIVATEKEY_free(priv_key);
1220
1221 return(ret);
1222 }
1223
1224int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
1225 {
1226 int ret=0, ok=0;
1227 unsigned char *buffer=NULL;
1228 size_t buf_len=0, tmp_len;
1229 EC_PRIVATEKEY *priv_key=NULL;
1230
1231 if (a == NULL || a->group == NULL || a->priv_key == NULL)
1232 {
1233 ECerr(EC_F_I2D_ECPRIVATEKEY,
1234 ERR_R_PASSED_NULL_PARAMETER);
1235 goto err;
1236 }
1237
1238 if ((priv_key = EC_PRIVATEKEY_new()) == NULL)
1239 {
1240 ECerr(EC_F_I2D_ECPRIVATEKEY,
1241 ERR_R_MALLOC_FAILURE);
1242 goto err;
1243 }
1244
1245 priv_key->version = a->version;
1246
1247 buf_len = (size_t)BN_num_bytes(a->priv_key);
1248 buffer = OPENSSL_malloc(buf_len);
1249 if (buffer == NULL)
1250 {
1251 ECerr(EC_F_I2D_ECPRIVATEKEY,
1252 ERR_R_MALLOC_FAILURE);
1253 goto err;
1254 }
1255
1256 if (!BN_bn2bin(a->priv_key, buffer))
1257 {
1258 ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB);
1259 goto err;
1260 }
1261
1262 if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len))
1263 {
1264 ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1265 goto err;
1266 }
1267
1268 if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS))
1269 {
1270 if ((priv_key->parameters = ec_asn1_group2pkparameters(
1271 a->group, priv_key->parameters)) == NULL)
1272 {
1273 ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1274 goto err;
1275 }
1276 }
1277
1278 if (!(a->enc_flag & EC_PKEY_NO_PUBKEY))
1279 {
1280 priv_key->publicKey = M_ASN1_BIT_STRING_new();
1281 if (priv_key->publicKey == NULL)
1282 {
1283 ECerr(EC_F_I2D_ECPRIVATEKEY,
1284 ERR_R_MALLOC_FAILURE);
1285 goto err;
1286 }
1287
1288 tmp_len = EC_POINT_point2oct(a->group, a->pub_key,
1289 a->conv_form, NULL, 0, NULL);
1290
1291 if (tmp_len > buf_len)
1292 {
1293 unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
1294 if (!tmp_buffer)
1295 {
1296 ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
1297 goto err;
1298 }
1299 buffer = tmp_buffer;
1300 buf_len = tmp_len;
1301 }
1302
1303 if (!EC_POINT_point2oct(a->group, a->pub_key,
1304 a->conv_form, buffer, buf_len, NULL))
1305 {
1306 ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1307 goto err;
1308 }
1309
1310 priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
1311 priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
1312 if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer,
1313 buf_len))
1314 {
1315 ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
1316 goto err;
1317 }
1318 }
1319
1320 if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0)
1321 {
1322 ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
1323 goto err;
1324 }
1325 ok=1;
1326err:
1327 if (buffer)
1328 OPENSSL_free(buffer);
1329 if (priv_key)
1330 EC_PRIVATEKEY_free(priv_key);
1331 return(ok?ret:0);
1332 }
1333
1334int i2d_ECParameters(EC_KEY *a, unsigned char **out)
1335 {
1336 if (a == NULL)
1337 {
1338 ECerr(EC_F_I2D_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1339 return 0;
1340 }
1341 return i2d_ECPKParameters(a->group, out);
1342 }
1343
1344EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
1345 {
1346 EC_KEY *ret;
1347
1348 if (in == NULL || *in == NULL)
1349 {
1350 ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_PASSED_NULL_PARAMETER);
1351 return NULL;
1352 }
1353
1354 if (a == NULL || *a == NULL)
1355 {
1356 if ((ret = EC_KEY_new()) == NULL)
1357 {
1358 ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
1359 return NULL;
1360 }
1361 if (a)
1362 *a = ret;
1363 }
1364 else
1365 ret = *a;
1366
1367 if (!d2i_ECPKParameters(&ret->group, in, len))
1368 {
1369 ECerr(EC_F_D2I_ECPARAMETERS, ERR_R_EC_LIB);
1370 return NULL;
1371 }
1372
1373 return ret;
1374 }
1375
1376EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)
1377 {
1378 EC_KEY *ret=NULL;
1379
1380 if (a == NULL || (*a) == NULL || (*a)->group == NULL)
1381 {
1382 /* sorry, but a EC_GROUP-structur is necessary
1383 * to set the public key */
1384 ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1385 return 0;
1386 }
1387 ret = *a;
1388 if (ret->pub_key == NULL &&
1389 (ret->pub_key = EC_POINT_new(ret->group)) == NULL)
1390 {
1391 ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1392 return 0;
1393 }
1394 if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL))
1395 {
1396 ECerr(EC_F_O2I_ECPUBLICKEY, ERR_R_EC_LIB);
1397 return 0;
1398 }
1399 /* save the point conversion form */
1400 ret->conv_form = (point_conversion_form_t)(*in[0] & ~0x01);
1401 *in += len;
1402 return ret;
1403 }
1404
1405int i2o_ECPublicKey(EC_KEY *a, unsigned char **out)
1406 {
1407 size_t buf_len=0;
1408 int new_buffer = 0;
1409
1410 if (a == NULL)
1411 {
1412 ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_PASSED_NULL_PARAMETER);
1413 return 0;
1414 }
1415
1416 buf_len = EC_POINT_point2oct(a->group, a->pub_key,
1417 a->conv_form, NULL, 0, NULL);
1418
1419 if (out == NULL || buf_len == 0)
1420 /* out == NULL => just return the length of the octet string */
1421 return buf_len;
1422
1423 if (*out == NULL)
1424 {
1425 if ((*out = OPENSSL_malloc(buf_len)) == NULL)
1426 {
1427 ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_MALLOC_FAILURE);
1428 return 0;
1429 }
1430 new_buffer = 1;
1431 }
1432 if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form,
1433 *out, buf_len, NULL))
1434 {
1435 ECerr(EC_F_I2O_ECPUBLICKEY, ERR_R_EC_LIB);
1436 OPENSSL_free(*out);
1437 *out = NULL;
1438 return 0;
1439 }
1440 if (!new_buffer)
1441 *out += buf_len;
1442 return buf_len;
1443 }
diff --git a/src/lib/libcrypto/ec/ec2_smpt.c b/src/lib/libcrypto/ec/ec_check.c
index 59d52bf663..0e316b4b3f 100644
--- a/src/lib/libcrypto/ec/ec2_smpt.c
+++ b/src/lib/libcrypto/ec/ec_check.c
@@ -1,7 +1,4 @@
1/* crypto/ec/ec2_smpt.c */ 1/* crypto/ec/ec_check.c */
2/* This code was originally written by Douglas Stebila
3 * <dstebila@student.math.uwaterloo.ca> for the OpenSSL project.
4 */
5/* ==================================================================== 2/* ====================================================================
6 * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
7 * 4 *
@@ -56,19 +53,71 @@
56 * 53 *
57 */ 54 */
58 55
56#include "ec_lcl.h"
57#include <openssl/err.h>
59 58
60/* Calaculates and sets the affine coordinates of an EC_POINT from the given 59int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
61 * compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
62 * Note that the simple implementation only uses affine coordinates.
63 *
64 * This algorithm is patented by Certicom Corp. under US Patent 6,141,420
65 * (for licensing information, contact licensing@certicom.com).
66 * This function is disabled by default and can be enabled by defining the
67 * preprocessor macro OPENSSL_EC_BIN_PT_COMP at Configure-time.
68 */
69int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
70 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
71 { 60 {
72 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_DISABLED); 61 int ret = 0;
73 return 0; 62 BIGNUM *order;
63 BN_CTX *new_ctx = NULL;
64 EC_POINT *point = NULL;
65
66 if (ctx == NULL)
67 {
68 ctx = new_ctx = BN_CTX_new();
69 if (ctx == NULL)
70 {
71 ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE);
72 goto err;
73 }
74 }
75 BN_CTX_start(ctx);
76 if ((order = BN_CTX_get(ctx)) == NULL) goto err;
77
78 /* check the discriminant */
79 if (!EC_GROUP_check_discriminant(group, ctx))
80 {
81 ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
82 goto err;
83 }
84
85 /* check the generator */
86 if (group->generator == NULL)
87 {
88 ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
89 goto err;
90 }
91 if (!EC_POINT_is_on_curve(group, group->generator, ctx))
92 {
93 ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);
94 goto err;
95 }
96
97 /* check the order of the generator */
98 if ((point = EC_POINT_new(group)) == NULL) goto err;
99 if (!EC_GROUP_get_order(group, order, ctx)) goto err;
100 if (BN_is_zero(order))
101 {
102 ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER);
103 goto err;
104 }
105
106 if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx)) goto err;
107 if (!EC_POINT_is_at_infinity(group, point))
108 {
109 ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);
110 goto err;
111 }
112
113 ret = 1;
114
115err:
116 if (ctx != NULL)
117 BN_CTX_end(ctx);
118 if (new_ctx != NULL)
119 BN_CTX_free(new_ctx);
120 if (point)
121 EC_POINT_free(point);
122 return ret;
74 } 123 }
diff --git a/src/lib/libcrypto/ec/ec_curve.c b/src/lib/libcrypto/ec/ec_curve.c
new file mode 100644
index 0000000000..c72fb2697c
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_curve.c
@@ -0,0 +1,2100 @@
1/* crypto/ec/ec_curve.c */
2/*
3 * Written by Nils Larsch for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2010 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 *
61 * Portions of the attached software ("Contribution") are developed by
62 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
63 *
64 * The Contribution is licensed pursuant to the OpenSSL open source
65 * license provided above.
66 *
67 * The elliptic curve binary polynomial software is originally written by
68 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
69 *
70 */
71
72#include "ec_lcl.h"
73#include <openssl/err.h>
74#include <openssl/obj_mac.h>
75#include <openssl/opensslconf.h>
76
77typedef struct {
78 int field_type, /* either NID_X9_62_prime_field or
79 * NID_X9_62_characteristic_two_field */
80 seed_len,
81 param_len;
82 unsigned int cofactor; /* promoted to BN_ULONG */
83} EC_CURVE_DATA;
84
85/* the nist prime curves */
86static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
87 _EC_NIST_PRIME_192 = {
88 { NID_X9_62_prime_field,20,24,1 },
89 { 0x30,0x45,0xAE,0x6F,0xC8,0x42,0x2F,0x64,0xED,0x57, /* seed */
90 0x95,0x28,0xD3,0x81,0x20,0xEA,0xE1,0x21,0x96,0xD5,
91
92 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
93 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
94 0xFF,0xFF,0xFF,0xFF,
95 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
96 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
97 0xFF,0xFF,0xFF,0xFC,
98 0x64,0x21,0x05,0x19,0xE5,0x9C,0x80,0xE7,0x0F,0xA7, /* b */
99 0xE9,0xAB,0x72,0x24,0x30,0x49,0xFE,0xB8,0xDE,0xEC,
100 0xC1,0x46,0xB9,0xB1,
101 0x18,0x8D,0xA8,0x0E,0xB0,0x30,0x90,0xF6,0x7C,0xBF, /* x */
102 0x20,0xEB,0x43,0xA1,0x88,0x00,0xF4,0xFF,0x0A,0xFD,
103 0x82,0xFF,0x10,0x12,
104 0x07,0x19,0x2b,0x95,0xff,0xc8,0xda,0x78,0x63,0x10, /* y */
105 0x11,0xed,0x6b,0x24,0xcd,0xd5,0x73,0xf9,0x77,0xa1,
106 0x1e,0x79,0x48,0x11,
107 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
108 0xFF,0xFF,0x99,0xDE,0xF8,0x36,0x14,0x6B,0xC9,0xB1,
109 0xB4,0xD2,0x28,0x31 }
110 };
111
112static const struct { EC_CURVE_DATA h; unsigned char data[20+28*6]; }
113 _EC_NIST_PRIME_224 = {
114 { NID_X9_62_prime_field,20,28,1 },
115 { 0xBD,0x71,0x34,0x47,0x99,0xD5,0xC7,0xFC,0xDC,0x45, /* seed */
116 0xB5,0x9F,0xA3,0xB9,0xAB,0x8F,0x6A,0x94,0x8B,0xC5,
117
118 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
119 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
120 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
121 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
122 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
123 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
124 0xB4,0x05,0x0A,0x85,0x0C,0x04,0xB3,0xAB,0xF5,0x41, /* b */
125 0x32,0x56,0x50,0x44,0xB0,0xB7,0xD7,0xBF,0xD8,0xBA,
126 0x27,0x0B,0x39,0x43,0x23,0x55,0xFF,0xB4,
127 0xB7,0x0E,0x0C,0xBD,0x6B,0xB4,0xBF,0x7F,0x32,0x13, /* x */
128 0x90,0xB9,0x4A,0x03,0xC1,0xD3,0x56,0xC2,0x11,0x22,
129 0x34,0x32,0x80,0xD6,0x11,0x5C,0x1D,0x21,
130 0xbd,0x37,0x63,0x88,0xb5,0xf7,0x23,0xfb,0x4c,0x22, /* y */
131 0xdf,0xe6,0xcd,0x43,0x75,0xa0,0x5a,0x07,0x47,0x64,
132 0x44,0xd5,0x81,0x99,0x85,0x00,0x7e,0x34,
133 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
134 0xFF,0xFF,0xFF,0xFF,0x16,0xA2,0xE0,0xB8,0xF0,0x3E,
135 0x13,0xDD,0x29,0x45,0x5C,0x5C,0x2A,0x3D }
136 };
137
138static const struct { EC_CURVE_DATA h; unsigned char data[20+48*6]; }
139 _EC_NIST_PRIME_384 = {
140 { NID_X9_62_prime_field,20,48,1 },
141 { 0xA3,0x35,0x92,0x6A,0xA3,0x19,0xA2,0x7A,0x1D,0x00, /* seed */
142 0x89,0x6A,0x67,0x73,0xA4,0x82,0x7A,0xCD,0xAC,0x73,
143
144 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
145 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
146 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
147 0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
148 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,
149 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
150 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
151 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
152 0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
153 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFC,
154 0xB3,0x31,0x2F,0xA7,0xE2,0x3E,0xE7,0xE4,0x98,0x8E, /* b */
155 0x05,0x6B,0xE3,0xF8,0x2D,0x19,0x18,0x1D,0x9C,0x6E,
156 0xFE,0x81,0x41,0x12,0x03,0x14,0x08,0x8F,0x50,0x13,
157 0x87,0x5A,0xC6,0x56,0x39,0x8D,0x8A,0x2E,0xD1,0x9D,
158 0x2A,0x85,0xC8,0xED,0xD3,0xEC,0x2A,0xEF,
159 0xAA,0x87,0xCA,0x22,0xBE,0x8B,0x05,0x37,0x8E,0xB1, /* x */
160 0xC7,0x1E,0xF3,0x20,0xAD,0x74,0x6E,0x1D,0x3B,0x62,
161 0x8B,0xA7,0x9B,0x98,0x59,0xF7,0x41,0xE0,0x82,0x54,
162 0x2A,0x38,0x55,0x02,0xF2,0x5D,0xBF,0x55,0x29,0x6C,
163 0x3A,0x54,0x5E,0x38,0x72,0x76,0x0A,0xB7,
164 0x36,0x17,0xde,0x4a,0x96,0x26,0x2c,0x6f,0x5d,0x9e, /* y */
165 0x98,0xbf,0x92,0x92,0xdc,0x29,0xf8,0xf4,0x1d,0xbd,
166 0x28,0x9a,0x14,0x7c,0xe9,0xda,0x31,0x13,0xb5,0xf0,
167 0xb8,0xc0,0x0a,0x60,0xb1,0xce,0x1d,0x7e,0x81,0x9d,
168 0x7a,0x43,0x1d,0x7c,0x90,0xea,0x0e,0x5f,
169 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
170 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
171 0xFF,0xFF,0xFF,0xFF,0xC7,0x63,0x4D,0x81,0xF4,0x37,
172 0x2D,0xDF,0x58,0x1A,0x0D,0xB2,0x48,0xB0,0xA7,0x7A,
173 0xEC,0xEC,0x19,0x6A,0xCC,0xC5,0x29,0x73 }
174 };
175
176static const struct { EC_CURVE_DATA h; unsigned char data[20+66*6]; }
177 _EC_NIST_PRIME_521 = {
178 { NID_X9_62_prime_field,20,66,1 },
179 { 0xD0,0x9E,0x88,0x00,0x29,0x1C,0xB8,0x53,0x96,0xCC, /* seed */
180 0x67,0x17,0x39,0x32,0x84,0xAA,0xA0,0xDA,0x64,0xBA,
181
182 0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
183 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
184 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
185 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
186 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
187 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
188 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
189 0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
190 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
191 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
192 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
193 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
194 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
195 0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,
196 0x00,0x51,0x95,0x3E,0xB9,0x61,0x8E,0x1C,0x9A,0x1F, /* b */
197 0x92,0x9A,0x21,0xA0,0xB6,0x85,0x40,0xEE,0xA2,0xDA,
198 0x72,0x5B,0x99,0xB3,0x15,0xF3,0xB8,0xB4,0x89,0x91,
199 0x8E,0xF1,0x09,0xE1,0x56,0x19,0x39,0x51,0xEC,0x7E,
200 0x93,0x7B,0x16,0x52,0xC0,0xBD,0x3B,0xB1,0xBF,0x07,
201 0x35,0x73,0xDF,0x88,0x3D,0x2C,0x34,0xF1,0xEF,0x45,
202 0x1F,0xD4,0x6B,0x50,0x3F,0x00,
203 0x00,0xC6,0x85,0x8E,0x06,0xB7,0x04,0x04,0xE9,0xCD, /* x */
204 0x9E,0x3E,0xCB,0x66,0x23,0x95,0xB4,0x42,0x9C,0x64,
205 0x81,0x39,0x05,0x3F,0xB5,0x21,0xF8,0x28,0xAF,0x60,
206 0x6B,0x4D,0x3D,0xBA,0xA1,0x4B,0x5E,0x77,0xEF,0xE7,
207 0x59,0x28,0xFE,0x1D,0xC1,0x27,0xA2,0xFF,0xA8,0xDE,
208 0x33,0x48,0xB3,0xC1,0x85,0x6A,0x42,0x9B,0xF9,0x7E,
209 0x7E,0x31,0xC2,0xE5,0xBD,0x66,
210 0x01,0x18,0x39,0x29,0x6a,0x78,0x9a,0x3b,0xc0,0x04, /* y */
211 0x5c,0x8a,0x5f,0xb4,0x2c,0x7d,0x1b,0xd9,0x98,0xf5,
212 0x44,0x49,0x57,0x9b,0x44,0x68,0x17,0xaf,0xbd,0x17,
213 0x27,0x3e,0x66,0x2c,0x97,0xee,0x72,0x99,0x5e,0xf4,
214 0x26,0x40,0xc5,0x50,0xb9,0x01,0x3f,0xad,0x07,0x61,
215 0x35,0x3c,0x70,0x86,0xa2,0x72,0xc2,0x40,0x88,0xbe,
216 0x94,0x76,0x9f,0xd1,0x66,0x50,
217 0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
218 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
219 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
220 0xFF,0xFF,0xFF,0xFA,0x51,0x86,0x87,0x83,0xBF,0x2F,
221 0x96,0x6B,0x7F,0xCC,0x01,0x48,0xF7,0x09,0xA5,0xD0,
222 0x3B,0xB5,0xC9,0xB8,0x89,0x9C,0x47,0xAE,0xBB,0x6F,
223 0xB7,0x1E,0x91,0x38,0x64,0x09 }
224 };
225
226/* the x9.62 prime curves (minus the nist prime curves) */
227static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
228 _EC_X9_62_PRIME_192V2 = {
229 { NID_X9_62_prime_field,20,24,1 },
230 { 0x31,0xA9,0x2E,0xE2,0x02,0x9F,0xD1,0x0D,0x90,0x1B, /* seed */
231 0x11,0x3E,0x99,0x07,0x10,0xF0,0xD2,0x1A,0xC6,0xB6,
232
233 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
234 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
235 0xFF,0xFF,0xFF,0xFF,
236 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
237 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
238 0xFF,0xFF,0xFF,0xFC,
239 0xCC,0x22,0xD6,0xDF,0xB9,0x5C,0x6B,0x25,0xE4,0x9C, /* b */
240 0x0D,0x63,0x64,0xA4,0xE5,0x98,0x0C,0x39,0x3A,0xA2,
241 0x16,0x68,0xD9,0x53,
242 0xEE,0xA2,0xBA,0xE7,0xE1,0x49,0x78,0x42,0xF2,0xDE, /* x */
243 0x77,0x69,0xCF,0xE9,0xC9,0x89,0xC0,0x72,0xAD,0x69,
244 0x6F,0x48,0x03,0x4A,
245 0x65,0x74,0xd1,0x1d,0x69,0xb6,0xec,0x7a,0x67,0x2b, /* y */
246 0xb8,0x2a,0x08,0x3d,0xf2,0xf2,0xb0,0x84,0x7d,0xe9,
247 0x70,0xb2,0xde,0x15,
248 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
249 0xFF,0xFE,0x5F,0xB1,0xA7,0x24,0xDC,0x80,0x41,0x86,
250 0x48,0xD8,0xDD,0x31 }
251 };
252
253static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
254 _EC_X9_62_PRIME_192V3 = {
255 { NID_X9_62_prime_field,20,24,1 },
256 { 0xC4,0x69,0x68,0x44,0x35,0xDE,0xB3,0x78,0xC4,0xB6, /* seed */
257 0x5C,0xA9,0x59,0x1E,0x2A,0x57,0x63,0x05,0x9A,0x2E,
258
259 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
260 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
261 0xFF,0xFF,0xFF,0xFF,
262 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
263 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
264 0xFF,0xFF,0xFF,0xFC,
265 0x22,0x12,0x3D,0xC2,0x39,0x5A,0x05,0xCA,0xA7,0x42, /* b */
266 0x3D,0xAE,0xCC,0xC9,0x47,0x60,0xA7,0xD4,0x62,0x25,
267 0x6B,0xD5,0x69,0x16,
268 0x7D,0x29,0x77,0x81,0x00,0xC6,0x5A,0x1D,0xA1,0x78, /* x */
269 0x37,0x16,0x58,0x8D,0xCE,0x2B,0x8B,0x4A,0xEE,0x8E,
270 0x22,0x8F,0x18,0x96,
271 0x38,0xa9,0x0f,0x22,0x63,0x73,0x37,0x33,0x4b,0x49, /* y */
272 0xdc,0xb6,0x6a,0x6d,0xc8,0xf9,0x97,0x8a,0xca,0x76,
273 0x48,0xa9,0x43,0xb0,
274 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
275 0xFF,0xFF,0x7A,0x62,0xD0,0x31,0xC8,0x3F,0x42,0x94,
276 0xF6,0x40,0xEC,0x13 }
277 };
278
279static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
280 _EC_X9_62_PRIME_239V1 = {
281 { NID_X9_62_prime_field,20,30,1 },
282 { 0xE4,0x3B,0xB4,0x60,0xF0,0xB8,0x0C,0xC0,0xC0,0xB0, /* seed */
283 0x75,0x79,0x8E,0x94,0x80,0x60,0xF8,0x32,0x1B,0x7D,
284
285 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
286 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
287 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,
288
289 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
290 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
291 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFC,
292
293 0x6B,0x01,0x6C,0x3B,0xDC,0xF1,0x89,0x41,0xD0,0xD6, /* b */
294 0x54,0x92,0x14,0x75,0xCA,0x71,0xA9,0xDB,0x2F,0xB2,
295 0x7D,0x1D,0x37,0x79,0x61,0x85,0xC2,0x94,0x2C,0x0A,
296
297 0x0F,0xFA,0x96,0x3C,0xDC,0xA8,0x81,0x6C,0xCC,0x33, /* x */
298 0xB8,0x64,0x2B,0xED,0xF9,0x05,0xC3,0xD3,0x58,0x57,
299 0x3D,0x3F,0x27,0xFB,0xBD,0x3B,0x3C,0xB9,0xAA,0xAF,
300
301 0x7d,0xeb,0xe8,0xe4,0xe9,0x0a,0x5d,0xae,0x6e,0x40, /* y */
302 0x54,0xca,0x53,0x0b,0xa0,0x46,0x54,0xb3,0x68,0x18,
303 0xce,0x22,0x6b,0x39,0xfc,0xcb,0x7b,0x02,0xf1,0xae,
304
305 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
306 0xFF,0xFF,0x7F,0xFF,0xFF,0x9E,0x5E,0x9A,0x9F,0x5D,
307 0x90,0x71,0xFB,0xD1,0x52,0x26,0x88,0x90,0x9D,0x0B }
308 };
309
310static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
311 _EC_X9_62_PRIME_239V2 = {
312 { NID_X9_62_prime_field,20,30,1 },
313 { 0xE8,0xB4,0x01,0x16,0x04,0x09,0x53,0x03,0xCA,0x3B, /* seed */
314 0x80,0x99,0x98,0x2B,0xE0,0x9F,0xCB,0x9A,0xE6,0x16,
315
316 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
317 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
318 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,
319
320 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
321 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
322 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFC,
323
324 0x61,0x7F,0xAB,0x68,0x32,0x57,0x6C,0xBB,0xFE,0xD5, /* b */
325 0x0D,0x99,0xF0,0x24,0x9C,0x3F,0xEE,0x58,0xB9,0x4B,
326 0xA0,0x03,0x8C,0x7A,0xE8,0x4C,0x8C,0x83,0x2F,0x2C,
327
328 0x38,0xAF,0x09,0xD9,0x87,0x27,0x70,0x51,0x20,0xC9, /* x */
329 0x21,0xBB,0x5E,0x9E,0x26,0x29,0x6A,0x3C,0xDC,0xF2,
330 0xF3,0x57,0x57,0xA0,0xEA,0xFD,0x87,0xB8,0x30,0xE7,
331
332 0x5b,0x01,0x25,0xe4,0xdb,0xea,0x0e,0xc7,0x20,0x6d, /* y */
333 0xa0,0xfc,0x01,0xd9,0xb0,0x81,0x32,0x9f,0xb5,0x55,
334 0xde,0x6e,0xf4,0x60,0x23,0x7d,0xff,0x8b,0xe4,0xba,
335
336 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
337 0xFF,0xFF,0x80,0x00,0x00,0xCF,0xA7,0xE8,0x59,0x43,
338 0x77,0xD4,0x14,0xC0,0x38,0x21,0xBC,0x58,0x20,0x63 }
339 };
340
341static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
342 _EC_X9_62_PRIME_239V3 = {
343 { NID_X9_62_prime_field,20,30,1 },
344 { 0x7D,0x73,0x74,0x16,0x8F,0xFE,0x34,0x71,0xB6,0x0A, /* seed */
345 0x85,0x76,0x86,0xA1,0x94,0x75,0xD3,0xBF,0xA2,0xFF,
346
347 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
348 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
349 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,
350
351 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
352 0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,
353 0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFC,
354
355 0x25,0x57,0x05,0xFA,0x2A,0x30,0x66,0x54,0xB1,0xF4, /* b */
356 0xCB,0x03,0xD6,0xA7,0x50,0xA3,0x0C,0x25,0x01,0x02,
357 0xD4,0x98,0x87,0x17,0xD9,0xBA,0x15,0xAB,0x6D,0x3E,
358
359 0x67,0x68,0xAE,0x8E,0x18,0xBB,0x92,0xCF,0xCF,0x00, /* x */
360 0x5C,0x94,0x9A,0xA2,0xC6,0xD9,0x48,0x53,0xD0,0xE6,
361 0x60,0xBB,0xF8,0x54,0xB1,0xC9,0x50,0x5F,0xE9,0x5A,
362
363 0x16,0x07,0xe6,0x89,0x8f,0x39,0x0c,0x06,0xbc,0x1d, /* y */
364 0x55,0x2b,0xad,0x22,0x6f,0x3b,0x6f,0xcf,0xe4,0x8b,
365 0x6e,0x81,0x84,0x99,0xaf,0x18,0xe3,0xed,0x6c,0xf3,
366
367 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
368 0xFF,0xFF,0x7F,0xFF,0xFF,0x97,0x5D,0xEB,0x41,0xB3,
369 0xA6,0x05,0x7C,0x3C,0x43,0x21,0x46,0x52,0x65,0x51 }
370 };
371
372
373static const struct { EC_CURVE_DATA h; unsigned char data[20+32*6]; }
374 _EC_X9_62_PRIME_256V1 = {
375 { NID_X9_62_prime_field,20,32,1 },
376 { 0xC4,0x9D,0x36,0x08,0x86,0xE7,0x04,0x93,0x6A,0x66, /* seed */
377 0x78,0xE1,0x13,0x9D,0x26,0xB7,0x81,0x9F,0x7E,0x90,
378
379 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x00,0x00, /* p */
380 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
381 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
382 0xFF,0xFF,
383 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0x00,0x00, /* a */
384 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
385 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
386 0xFF,0xFC,
387 0x5A,0xC6,0x35,0xD8,0xAA,0x3A,0x93,0xE7,0xB3,0xEB, /* b */
388 0xBD,0x55,0x76,0x98,0x86,0xBC,0x65,0x1D,0x06,0xB0,
389 0xCC,0x53,0xB0,0xF6,0x3B,0xCE,0x3C,0x3E,0x27,0xD2,
390 0x60,0x4B,
391 0x6B,0x17,0xD1,0xF2,0xE1,0x2C,0x42,0x47,0xF8,0xBC, /* x */
392 0xE6,0xE5,0x63,0xA4,0x40,0xF2,0x77,0x03,0x7D,0x81,
393 0x2D,0xEB,0x33,0xA0,0xF4,0xA1,0x39,0x45,0xD8,0x98,
394 0xC2,0x96,
395 0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,0x8e,0xe7, /* y */
396 0xeb,0x4a,0x7c,0x0f,0x9e,0x16,0x2b,0xce,0x33,0x57,
397 0x6b,0x31,0x5e,0xce,0xcb,0xb6,0x40,0x68,0x37,0xbf,
398 0x51,0xf5,
399 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF, /* order */
400 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBC,0xE6,0xFA,0xAD,
401 0xA7,0x17,0x9E,0x84,0xF3,0xB9,0xCA,0xC2,0xFC,0x63,
402 0x25,0x51 }
403 };
404
405/* the secg prime curves (minus the nist and x9.62 prime curves) */
406static const struct { EC_CURVE_DATA h; unsigned char data[20+14*6]; }
407 _EC_SECG_PRIME_112R1 = {
408 { NID_X9_62_prime_field,20,14,1 },
409 { 0x00,0xF5,0x0B,0x02,0x8E,0x4D,0x69,0x6E,0x67,0x68, /* seed */
410 0x75,0x61,0x51,0x75,0x29,0x04,0x72,0x78,0x3F,0xB1,
411
412 0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x66,0x80,0x76, /* p */
413 0xBE,0xAD,0x20,0x8B,
414 0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x66,0x80,0x76, /* a */
415 0xBE,0xAD,0x20,0x88,
416 0x65,0x9E,0xF8,0xBA,0x04,0x39,0x16,0xEE,0xDE,0x89, /* b */
417 0x11,0x70,0x2B,0x22,
418 0x09,0x48,0x72,0x39,0x99,0x5A,0x5E,0xE7,0x6B,0x55, /* x */
419 0xF9,0xC2,0xF0,0x98,
420 0xa8,0x9c,0xe5,0xaf,0x87,0x24,0xc0,0xa2,0x3e,0x0e, /* y */
421 0x0f,0xf7,0x75,0x00,
422 0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x76,0x28,0xDF, /* order */
423 0xAC,0x65,0x61,0xC5 }
424 };
425
426static const struct { EC_CURVE_DATA h; unsigned char data[20+14*6]; }
427 _EC_SECG_PRIME_112R2 = {
428 { NID_X9_62_prime_field,20,14,4 },
429 { 0x00,0x27,0x57,0xA1,0x11,0x4D,0x69,0x6E,0x67,0x68, /* seed */
430 0x75,0x61,0x51,0x75,0x53,0x16,0xC0,0x5E,0x0B,0xD4,
431
432 0xDB,0x7C,0x2A,0xBF,0x62,0xE3,0x5E,0x66,0x80,0x76, /* p */
433 0xBE,0xAD,0x20,0x8B,
434 0x61,0x27,0xC2,0x4C,0x05,0xF3,0x8A,0x0A,0xAA,0xF6, /* a */
435 0x5C,0x0E,0xF0,0x2C,
436 0x51,0xDE,0xF1,0x81,0x5D,0xB5,0xED,0x74,0xFC,0xC3, /* b */
437 0x4C,0x85,0xD7,0x09,
438 0x4B,0xA3,0x0A,0xB5,0xE8,0x92,0xB4,0xE1,0x64,0x9D, /* x */
439 0xD0,0x92,0x86,0x43,
440 0xad,0xcd,0x46,0xf5,0x88,0x2e,0x37,0x47,0xde,0xf3, /* y */
441 0x6e,0x95,0x6e,0x97,
442 0x36,0xDF,0x0A,0xAF,0xD8,0xB8,0xD7,0x59,0x7C,0xA1, /* order */
443 0x05,0x20,0xD0,0x4B }
444 };
445
446static const struct { EC_CURVE_DATA h; unsigned char data[20+16*6]; }
447 _EC_SECG_PRIME_128R1 = {
448 { NID_X9_62_prime_field,20,16,1 },
449 { 0x00,0x0E,0x0D,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61, /* seed */
450 0x51,0x75,0x0C,0xC0,0x3A,0x44,0x73,0xD0,0x36,0x79,
451
452 0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
453 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
454 0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
455 0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,
456 0xE8,0x75,0x79,0xC1,0x10,0x79,0xF4,0x3D,0xD8,0x24, /* b */
457 0x99,0x3C,0x2C,0xEE,0x5E,0xD3,
458 0x16,0x1F,0xF7,0x52,0x8B,0x89,0x9B,0x2D,0x0C,0x28, /* x */
459 0x60,0x7C,0xA5,0x2C,0x5B,0x86,
460 0xcf,0x5a,0xc8,0x39,0x5b,0xaf,0xeb,0x13,0xc0,0x2d, /* y */
461 0xa2,0x92,0xdd,0xed,0x7a,0x83,
462 0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x75,0xA3, /* order */
463 0x0D,0x1B,0x90,0x38,0xA1,0x15 }
464 };
465
466static const struct { EC_CURVE_DATA h; unsigned char data[20+16*6]; }
467 _EC_SECG_PRIME_128R2 = {
468 { NID_X9_62_prime_field,20,16,4 },
469 { 0x00,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61,0x51,0x75, /* seed */
470 0x12,0xD8,0xF0,0x34,0x31,0xFC,0xE6,0x3B,0x88,0xF4,
471
472 0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
473 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
474 0xD6,0x03,0x19,0x98,0xD1,0xB3,0xBB,0xFE,0xBF,0x59, /* a */
475 0xCC,0x9B,0xBF,0xF9,0xAE,0xE1,
476 0x5E,0xEE,0xFC,0xA3,0x80,0xD0,0x29,0x19,0xDC,0x2C, /* b */
477 0x65,0x58,0xBB,0x6D,0x8A,0x5D,
478 0x7B,0x6A,0xA5,0xD8,0x5E,0x57,0x29,0x83,0xE6,0xFB, /* x */
479 0x32,0xA7,0xCD,0xEB,0xC1,0x40,
480 0x27,0xb6,0x91,0x6a,0x89,0x4d,0x3a,0xee,0x71,0x06, /* y */
481 0xfe,0x80,0x5f,0xc3,0x4b,0x44,
482 0x3F,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xBE,0x00, /* order */
483 0x24,0x72,0x06,0x13,0xB5,0xA3 }
484 };
485
486static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; }
487 _EC_SECG_PRIME_160K1 = {
488 { NID_X9_62_prime_field,0,21,1 },
489 { /* no seed */
490 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
491 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xAC,
492 0x73,
493 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
494 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
495 0x00,
496 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
497 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
498 0x07,
499 0x00,0x3B,0x4C,0x38,0x2C,0xE3,0x7A,0xA1,0x92,0xA4, /* x */
500 0x01,0x9E,0x76,0x30,0x36,0xF4,0xF5,0xDD,0x4D,0x7E,
501 0xBB,
502 0x00,0x93,0x8c,0xf9,0x35,0x31,0x8f,0xdc,0xed,0x6b, /* y */
503 0xc2,0x82,0x86,0x53,0x17,0x33,0xc3,0xf0,0x3c,0x4f,
504 0xee,
505 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
506 0x01,0xB8,0xFA,0x16,0xDF,0xAB,0x9A,0xCA,0x16,0xB6,
507 0xB3 }
508 };
509
510static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; }
511 _EC_SECG_PRIME_160R1 = {
512 { NID_X9_62_prime_field,20,21,1 },
513 { 0x10,0x53,0xCD,0xE4,0x2C,0x14,0xD6,0x96,0xE6,0x76, /* seed */
514 0x87,0x56,0x15,0x17,0x53,0x3B,0xF3,0xF8,0x33,0x45,
515
516 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
517 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,
518 0xFF,
519 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
520 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,
521 0xFC,
522 0x00,0x1C,0x97,0xBE,0xFC,0x54,0xBD,0x7A,0x8B,0x65, /* b */
523 0xAC,0xF8,0x9F,0x81,0xD4,0xD4,0xAD,0xC5,0x65,0xFA,
524 0x45,
525 0x00,0x4A,0x96,0xB5,0x68,0x8E,0xF5,0x73,0x28,0x46, /* x */
526 0x64,0x69,0x89,0x68,0xC3,0x8B,0xB9,0x13,0xCB,0xFC,
527 0x82,
528 0x00,0x23,0xa6,0x28,0x55,0x31,0x68,0x94,0x7d,0x59, /* y */
529 0xdc,0xc9,0x12,0x04,0x23,0x51,0x37,0x7a,0xc5,0xfb,
530 0x32,
531 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
532 0x01,0xF4,0xC8,0xF9,0x27,0xAE,0xD3,0xCA,0x75,0x22,
533 0x57 }
534 };
535
536static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; }
537 _EC_SECG_PRIME_160R2 = {
538 { NID_X9_62_prime_field,20,21,1 },
539 { 0xB9,0x9B,0x99,0xB0,0x99,0xB3,0x23,0xE0,0x27,0x09, /* seed */
540 0xA4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15,0x17,0x51,
541
542 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
543 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xAC,
544 0x73,
545 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
546 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xAC,
547 0x70,
548 0x00,0xB4,0xE1,0x34,0xD3,0xFB,0x59,0xEB,0x8B,0xAB, /* b */
549 0x57,0x27,0x49,0x04,0x66,0x4D,0x5A,0xF5,0x03,0x88,
550 0xBA,
551 0x00,0x52,0xDC,0xB0,0x34,0x29,0x3A,0x11,0x7E,0x1F, /* x */
552 0x4F,0xF1,0x1B,0x30,0xF7,0x19,0x9D,0x31,0x44,0xCE,
553 0x6D,
554 0x00,0xfe,0xaf,0xfe,0xf2,0xe3,0x31,0xf2,0x96,0xe0, /* y */
555 0x71,0xfa,0x0d,0xf9,0x98,0x2c,0xfe,0xa7,0xd4,0x3f,
556 0x2e,
557 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
558 0x00,0x35,0x1E,0xE7,0x86,0xA8,0x18,0xF3,0xA1,0xA1,
559 0x6B }
560 };
561
562static const struct { EC_CURVE_DATA h; unsigned char data[0+24*6]; }
563 _EC_SECG_PRIME_192K1 = {
564 { NID_X9_62_prime_field,0,24,1 },
565 { /* no seed */
566 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
567 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
568 0xFF,0xFF,0xEE,0x37,
569 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
570 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
571 0x00,0x00,0x00,0x00,
572 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
573 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
574 0x00,0x00,0x00,0x03,
575 0xDB,0x4F,0xF1,0x0E,0xC0,0x57,0xE9,0xAE,0x26,0xB0, /* x */
576 0x7D,0x02,0x80,0xB7,0xF4,0x34,0x1D,0xA5,0xD1,0xB1,
577 0xEA,0xE0,0x6C,0x7D,
578 0x9b,0x2f,0x2f,0x6d,0x9c,0x56,0x28,0xa7,0x84,0x41, /* y */
579 0x63,0xd0,0x15,0xbe,0x86,0x34,0x40,0x82,0xaa,0x88,
580 0xd9,0x5e,0x2f,0x9d,
581 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
582 0xFF,0xFE,0x26,0xF2,0xFC,0x17,0x0F,0x69,0x46,0x6A,
583 0x74,0xDE,0xFD,0x8D }
584 };
585
586static const struct { EC_CURVE_DATA h; unsigned char data[0+29*6]; }
587 _EC_SECG_PRIME_224K1 = {
588 { NID_X9_62_prime_field,0,29,1 },
589 { /* no seed */
590 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
591 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
592 0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xE5,0x6D,
593 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
594 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
595 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
596 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
597 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
598 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,
599 0x00,0xA1,0x45,0x5B,0x33,0x4D,0xF0,0x99,0xDF,0x30, /* x */
600 0xFC,0x28,0xA1,0x69,0xA4,0x67,0xE9,0xE4,0x70,0x75,
601 0xA9,0x0F,0x7E,0x65,0x0E,0xB6,0xB7,0xA4,0x5C,
602 0x00,0x7e,0x08,0x9f,0xed,0x7f,0xba,0x34,0x42,0x82, /* y */
603 0xca,0xfb,0xd6,0xf7,0xe3,0x19,0xf7,0xc0,0xb0,0xbd,
604 0x59,0xe2,0xca,0x4b,0xdb,0x55,0x6d,0x61,0xa5,
605 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
606 0x00,0x00,0x00,0x00,0x01,0xDC,0xE8,0xD2,0xEC,0x61,
607 0x84,0xCA,0xF0,0xA9,0x71,0x76,0x9F,0xB1,0xF7 }
608 };
609
610static const struct { EC_CURVE_DATA h; unsigned char data[0+32*6]; }
611 _EC_SECG_PRIME_256K1 = {
612 { NID_X9_62_prime_field,0,32,1 },
613 { /* no seed */
614 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
615 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
616 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,
617 0xFC,0x2F,
618 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
619 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
620 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
621 0x00,0x00,
622 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
623 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
624 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
625 0x00,0x07,
626 0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0, /* x */
627 0x62,0x95,0xCE,0x87,0x0B,0x07,0x02,0x9B,0xFC,0xDB,
628 0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
629 0x17,0x98,
630 0x48,0x3a,0xda,0x77,0x26,0xa3,0xc4,0x65,0x5d,0xa4, /* y */
631 0xfb,0xfc,0x0e,0x11,0x08,0xa8,0xfd,0x17,0xb4,0x48,
632 0xa6,0x85,0x54,0x19,0x9c,0x47,0xd0,0x8f,0xfb,0x10,
633 0xd4,0xb8,
634 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
635 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,
636 0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,0x8C,0xD0,0x36,
637 0x41,0x41 }
638 };
639
640/* some wap/wtls curves */
641static const struct { EC_CURVE_DATA h; unsigned char data[0+15*6]; }
642 _EC_WTLS_8 = {
643 { NID_X9_62_prime_field,0,15,1 },
644 { /* no seed */
645 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
646 0xFF,0xFF,0xFF,0xFD,0xE7,
647 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
648 0x00,0x00,0x00,0x00,0x00,
649 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
650 0x00,0x00,0x00,0x00,0x03,
651 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x */
652 0x00,0x00,0x00,0x00,0x01,
653 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y */
654 0x00,0x00,0x00,0x00,0x02,
655 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xEC,0xEA, /* order */
656 0x55,0x1A,0xD8,0x37,0xE9 }
657 };
658
659static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; }
660 _EC_WTLS_9 = {
661 { NID_X9_62_prime_field,0,21,1 },
662 { /* no seed */
663 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
664 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x80,
665 0x8F,
666 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
667 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
668 0x00,
669 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
670 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
671 0x03,
672 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x */
673 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
674 0x01,
675 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y */
676 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
677 0x02,
678 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
679 0x01,0xCD,0xC9,0x8A,0xE0,0xE2,0xDE,0x57,0x4A,0xBF,
680 0x33 }
681 };
682
683static const struct { EC_CURVE_DATA h; unsigned char data[0+28*6]; }
684 _EC_WTLS_12 = {
685 { NID_X9_62_prime_field,0,28,1 },
686 { /* no seed */
687 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
688 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
689 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
690 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
691 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
692 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
693 0xB4,0x05,0x0A,0x85,0x0C,0x04,0xB3,0xAB,0xF5,0x41, /* b */
694 0x32,0x56,0x50,0x44,0xB0,0xB7,0xD7,0xBF,0xD8,0xBA,
695 0x27,0x0B,0x39,0x43,0x23,0x55,0xFF,0xB4,
696 0xB7,0x0E,0x0C,0xBD,0x6B,0xB4,0xBF,0x7F,0x32,0x13, /* x */
697 0x90,0xB9,0x4A,0x03,0xC1,0xD3,0x56,0xC2,0x11,0x22,
698 0x34,0x32,0x80,0xD6,0x11,0x5C,0x1D,0x21,
699 0xbd,0x37,0x63,0x88,0xb5,0xf7,0x23,0xfb,0x4c,0x22, /* y */
700 0xdf,0xe6,0xcd,0x43,0x75,0xa0,0x5a,0x07,0x47,0x64,
701 0x44,0xd5,0x81,0x99,0x85,0x00,0x7e,0x34,
702 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
703 0xFF,0xFF,0xFF,0xFF,0x16,0xA2,0xE0,0xB8,0xF0,0x3E,
704 0x13,0xDD,0x29,0x45,0x5C,0x5C,0x2A,0x3D }
705 };
706
707#ifndef OPENSSL_NO_EC2M
708
709/* characteristic two curves */
710static const struct { EC_CURVE_DATA h; unsigned char data[20+15*6]; }
711 _EC_SECG_CHAR2_113R1 = {
712 { NID_X9_62_characteristic_two_field,20,15,2 },
713 { 0x10,0xE7,0x23,0xAB,0x14,0xD6,0x96,0xE6,0x76,0x87, /* seed */
714 0x56,0x15,0x17,0x56,0xFE,0xBF,0x8F,0xCB,0x49,0xA9,
715
716 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
717 0x00,0x00,0x00,0x02,0x01,
718 0x00,0x30,0x88,0x25,0x0C,0xA6,0xE7,0xC7,0xFE,0x64, /* a */
719 0x9C,0xE8,0x58,0x20,0xF7,
720 0x00,0xE8,0xBE,0xE4,0xD3,0xE2,0x26,0x07,0x44,0x18, /* b */
721 0x8B,0xE0,0xE9,0xC7,0x23,
722 0x00,0x9D,0x73,0x61,0x6F,0x35,0xF4,0xAB,0x14,0x07, /* x */
723 0xD7,0x35,0x62,0xC1,0x0F,
724 0x00,0xA5,0x28,0x30,0x27,0x79,0x58,0xEE,0x84,0xD1, /* y */
725 0x31,0x5E,0xD3,0x18,0x86,
726 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD9,0xCC, /* order */
727 0xEC,0x8A,0x39,0xE5,0x6F }
728 };
729
730static const struct { EC_CURVE_DATA h; unsigned char data[20+15*6]; }
731 _EC_SECG_CHAR2_113R2 = {
732 { NID_X9_62_characteristic_two_field,20,15,2 },
733 { 0x10,0xC0,0xFB,0x15,0x76,0x08,0x60,0xDE,0xF1,0xEE, /* seed */
734 0xF4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15,0x17,0x5D,
735
736 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
737 0x00,0x00,0x00,0x02,0x01,
738 0x00,0x68,0x99,0x18,0xDB,0xEC,0x7E,0x5A,0x0D,0xD6, /* a */
739 0xDF,0xC0,0xAA,0x55,0xC7,
740 0x00,0x95,0xE9,0xA9,0xEC,0x9B,0x29,0x7B,0xD4,0xBF, /* b */
741 0x36,0xE0,0x59,0x18,0x4F,
742 0x01,0xA5,0x7A,0x6A,0x7B,0x26,0xCA,0x5E,0xF5,0x2F, /* x */
743 0xCD,0xB8,0x16,0x47,0x97,
744 0x00,0xB3,0xAD,0xC9,0x4E,0xD1,0xFE,0x67,0x4C,0x06, /* y */
745 0xE6,0x95,0xBA,0xBA,0x1D,
746 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x08,0x78, /* order */
747 0x9B,0x24,0x96,0xAF,0x93 }
748 };
749
750static const struct { EC_CURVE_DATA h; unsigned char data[20+17*6]; }
751 _EC_SECG_CHAR2_131R1 = {
752 { NID_X9_62_characteristic_two_field,20,17,2 },
753 { 0x4D,0x69,0x6E,0x67,0x68,0x75,0x61,0x51,0x75,0x98, /* seed */
754 0x5B,0xD3,0xAD,0xBA,0xDA,0x21,0xB4,0x3A,0x97,0xE2,
755
756 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
757 0x00,0x00,0x00,0x00,0x00,0x01,0x0D,
758 0x07,0xA1,0x1B,0x09,0xA7,0x6B,0x56,0x21,0x44,0x41, /* a */
759 0x8F,0xF3,0xFF,0x8C,0x25,0x70,0xB8,
760 0x02,0x17,0xC0,0x56,0x10,0x88,0x4B,0x63,0xB9,0xC6, /* b */
761 0xC7,0x29,0x16,0x78,0xF9,0xD3,0x41,
762 0x00,0x81,0xBA,0xF9,0x1F,0xDF,0x98,0x33,0xC4,0x0F, /* x */
763 0x9C,0x18,0x13,0x43,0x63,0x83,0x99,
764 0x07,0x8C,0x6E,0x7E,0xA3,0x8C,0x00,0x1F,0x73,0xC8, /* y */
765 0x13,0x4B,0x1B,0x4E,0xF9,0xE1,0x50,
766 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x31, /* order */
767 0x23,0x95,0x3A,0x94,0x64,0xB5,0x4D }
768 };
769
770static const struct { EC_CURVE_DATA h; unsigned char data[20+17*6]; }
771 _EC_SECG_CHAR2_131R2 = {
772 { NID_X9_62_characteristic_two_field,20,17,2 },
773 { 0x98,0x5B,0xD3,0xAD,0xBA,0xD4,0xD6,0x96,0xE6,0x76, /* seed */
774 0x87,0x56,0x15,0x17,0x5A,0x21,0xB4,0x3A,0x97,0xE3,
775
776 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
777 0x00,0x00,0x00,0x00,0x00,0x01,0x0D,
778 0x03,0xE5,0xA8,0x89,0x19,0xD7,0xCA,0xFC,0xBF,0x41, /* a */
779 0x5F,0x07,0xC2,0x17,0x65,0x73,0xB2,
780 0x04,0xB8,0x26,0x6A,0x46,0xC5,0x56,0x57,0xAC,0x73, /* b */
781 0x4C,0xE3,0x8F,0x01,0x8F,0x21,0x92,
782 0x03,0x56,0xDC,0xD8,0xF2,0xF9,0x50,0x31,0xAD,0x65, /* x */
783 0x2D,0x23,0x95,0x1B,0xB3,0x66,0xA8,
784 0x06,0x48,0xF0,0x6D,0x86,0x79,0x40,0xA5,0x36,0x6D, /* y */
785 0x9E,0x26,0x5D,0xE9,0xEB,0x24,0x0F,
786 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x69, /* order */
787 0x54,0xA2,0x33,0x04,0x9B,0xA9,0x8F }
788 };
789
790static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; }
791 _EC_NIST_CHAR2_163K = {
792 { NID_X9_62_characteristic_two_field,0,21,2 },
793 { /* no seed */
794 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
795 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
796 0xC9,
797 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
798 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
799 0x01,
800 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
801 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
802 0x01,
803 0x02,0xFE,0x13,0xC0,0x53,0x7B,0xBC,0x11,0xAC,0xAA, /* x */
804 0x07,0xD7,0x93,0xDE,0x4E,0x6D,0x5E,0x5C,0x94,0xEE,
805 0xE8,
806 0x02,0x89,0x07,0x0F,0xB0,0x5D,0x38,0xFF,0x58,0x32, /* y */
807 0x1F,0x2E,0x80,0x05,0x36,0xD5,0x38,0xCC,0xDA,0xA3,
808 0xD9,
809 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
810 0x02,0x01,0x08,0xA2,0xE0,0xCC,0x0D,0x99,0xF8,0xA5,
811 0xEF }
812 };
813
814static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; }
815 _EC_SECG_CHAR2_163R1 = {
816 { NID_X9_62_characteristic_two_field,0,21,2 },
817 { /* no seed */
818#if 0
819/* The algorithm used to derive the curve parameters from
820 * the seed used here is slightly different than the
821 * algorithm described in X9.62 . */
822 0x24,0xB7,0xB1,0x37,0xC8,0xA1,0x4D,0x69,0x6E,0x67,
823 0x68,0x75,0x61,0x51,0x75,0x6F,0xD0,0xDA,0x2E,0x5C,
824#endif
825 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
826 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
827 0xC9,
828 0x07,0xB6,0x88,0x2C,0xAA,0xEF,0xA8,0x4F,0x95,0x54, /* a */
829 0xFF,0x84,0x28,0xBD,0x88,0xE2,0x46,0xD2,0x78,0x2A,
830 0xE2,
831 0x07,0x13,0x61,0x2D,0xCD,0xDC,0xB4,0x0A,0xAB,0x94, /* b */
832 0x6B,0xDA,0x29,0xCA,0x91,0xF7,0x3A,0xF9,0x58,0xAF,
833 0xD9,
834 0x03,0x69,0x97,0x96,0x97,0xAB,0x43,0x89,0x77,0x89, /* x */
835 0x56,0x67,0x89,0x56,0x7F,0x78,0x7A,0x78,0x76,0xA6,
836 0x54,
837 0x00,0x43,0x5E,0xDB,0x42,0xEF,0xAF,0xB2,0x98,0x9D, /* y */
838 0x51,0xFE,0xFC,0xE3,0xC8,0x09,0x88,0xF4,0x1F,0xF8,
839 0x83,
840 0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
841 0xFF,0x48,0xAA,0xB6,0x89,0xC2,0x9C,0xA7,0x10,0x27,
842 0x9B }
843 };
844
845static const struct { EC_CURVE_DATA h; unsigned char data[0+21*6]; }
846 _EC_NIST_CHAR2_163B = {
847 { NID_X9_62_characteristic_two_field,0,21,2 },
848 { /* no seed */
849#if 0
850/* The seed here was used to created the curve parameters in normal
851 * basis representation (and not the polynomial representation used here) */
852 0x85,0xE2,0x5B,0xFE,0x5C,0x86,0x22,0x6C,0xDB,0x12,
853 0x01,0x6F,0x75,0x53,0xF9,0xD0,0xE6,0x93,0xA2,0x68,
854#endif
855 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
856 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
857 0xC9,
858 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
859 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
860 0x01,
861 0x02,0x0A,0x60,0x19,0x07,0xB8,0xC9,0x53,0xCA,0x14, /* b */
862 0x81,0xEB,0x10,0x51,0x2F,0x78,0x74,0x4A,0x32,0x05,
863 0xFD,
864 0x03,0xF0,0xEB,0xA1,0x62,0x86,0xA2,0xD5,0x7E,0xA0, /* x */
865 0x99,0x11,0x68,0xD4,0x99,0x46,0x37,0xE8,0x34,0x3E,
866 0x36,
867 0x00,0xD5,0x1F,0xBC,0x6C,0x71,0xA0,0x09,0x4F,0xA2, /* y */
868 0xCD,0xD5,0x45,0xB1,0x1C,0x5C,0x0C,0x79,0x73,0x24,
869 0xF1,
870 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
871 0x02,0x92,0xFE,0x77,0xE7,0x0C,0x12,0xA4,0x23,0x4C,
872 0x33 }
873 };
874
875static const struct { EC_CURVE_DATA h; unsigned char data[20+25*6]; }
876 _EC_SECG_CHAR2_193R1 = {
877 { NID_X9_62_characteristic_two_field,20,25,2 },
878 { 0x10,0x3F,0xAE,0xC7,0x4D,0x69,0x6E,0x67,0x68,0x75, /* seed */
879 0x61,0x51,0x75,0x77,0x7F,0xC5,0xB1,0x91,0xEF,0x30,
880
881 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
882 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
883 0x00,0x00,0x00,0x80,0x01,
884 0x00,0x17,0x85,0x8F,0xEB,0x7A,0x98,0x97,0x51,0x69, /* a */
885 0xE1,0x71,0xF7,0x7B,0x40,0x87,0xDE,0x09,0x8A,0xC8,
886 0xA9,0x11,0xDF,0x7B,0x01,
887 0x00,0xFD,0xFB,0x49,0xBF,0xE6,0xC3,0xA8,0x9F,0xAC, /* b */
888 0xAD,0xAA,0x7A,0x1E,0x5B,0xBC,0x7C,0xC1,0xC2,0xE5,
889 0xD8,0x31,0x47,0x88,0x14,
890 0x01,0xF4,0x81,0xBC,0x5F,0x0F,0xF8,0x4A,0x74,0xAD, /* x */
891 0x6C,0xDF,0x6F,0xDE,0xF4,0xBF,0x61,0x79,0x62,0x53,
892 0x72,0xD8,0xC0,0xC5,0xE1,
893 0x00,0x25,0xE3,0x99,0xF2,0x90,0x37,0x12,0xCC,0xF3, /* y */
894 0xEA,0x9E,0x3A,0x1A,0xD1,0x7F,0xB0,0xB3,0x20,0x1B,
895 0x6A,0xF7,0xCE,0x1B,0x05,
896 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
897 0x00,0x00,0x00,0xC7,0xF3,0x4A,0x77,0x8F,0x44,0x3A,
898 0xCC,0x92,0x0E,0xBA,0x49 }
899 };
900
901static const struct { EC_CURVE_DATA h; unsigned char data[20+25*6]; }
902 _EC_SECG_CHAR2_193R2 = {
903 { NID_X9_62_characteristic_two_field,20,25,2 },
904 { 0x10,0xB7,0xB4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15, /* seed */
905 0x17,0x51,0x37,0xC8,0xA1,0x6F,0xD0,0xDA,0x22,0x11,
906
907 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
908 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
909 0x00,0x00,0x00,0x80,0x01,
910 0x01,0x63,0xF3,0x5A,0x51,0x37,0xC2,0xCE,0x3E,0xA6, /* a */
911 0xED,0x86,0x67,0x19,0x0B,0x0B,0xC4,0x3E,0xCD,0x69,
912 0x97,0x77,0x02,0x70,0x9B,
913 0x00,0xC9,0xBB,0x9E,0x89,0x27,0xD4,0xD6,0x4C,0x37, /* b */
914 0x7E,0x2A,0xB2,0x85,0x6A,0x5B,0x16,0xE3,0xEF,0xB7,
915 0xF6,0x1D,0x43,0x16,0xAE,
916 0x00,0xD9,0xB6,0x7D,0x19,0x2E,0x03,0x67,0xC8,0x03, /* x */
917 0xF3,0x9E,0x1A,0x7E,0x82,0xCA,0x14,0xA6,0x51,0x35,
918 0x0A,0xAE,0x61,0x7E,0x8F,
919 0x01,0xCE,0x94,0x33,0x56,0x07,0xC3,0x04,0xAC,0x29, /* y */
920 0xE7,0xDE,0xFB,0xD9,0xCA,0x01,0xF5,0x96,0xF9,0x27,
921 0x22,0x4C,0xDE,0xCF,0x6C,
922 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
923 0x00,0x00,0x01,0x5A,0xAB,0x56,0x1B,0x00,0x54,0x13,
924 0xCC,0xD4,0xEE,0x99,0xD5 }
925 };
926
927static const struct { EC_CURVE_DATA h; unsigned char data[0+30*6]; }
928 _EC_NIST_CHAR2_233K = {
929 { NID_X9_62_characteristic_two_field,0,30,4 },
930 { /* no seed */
931 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
932 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
933 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
934
935 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
936 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
937 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
938
939 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
940 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
941 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
942
943 0x01,0x72,0x32,0xBA,0x85,0x3A,0x7E,0x73,0x1A,0xF1, /* x */
944 0x29,0xF2,0x2F,0xF4,0x14,0x95,0x63,0xA4,0x19,0xC2,
945 0x6B,0xF5,0x0A,0x4C,0x9D,0x6E,0xEF,0xAD,0x61,0x26,
946
947 0x01,0xDB,0x53,0x7D,0xEC,0xE8,0x19,0xB7,0xF7,0x0F, /* y */
948 0x55,0x5A,0x67,0xC4,0x27,0xA8,0xCD,0x9B,0xF1,0x8A,
949 0xEB,0x9B,0x56,0xE0,0xC1,0x10,0x56,0xFA,0xE6,0xA3,
950
951 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
952 0x00,0x00,0x00,0x00,0x00,0x06,0x9D,0x5B,0xB9,0x15,
953 0xBC,0xD4,0x6E,0xFB,0x1A,0xD5,0xF1,0x73,0xAB,0xDF }
954 };
955
956static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
957 _EC_NIST_CHAR2_233B = {
958 { NID_X9_62_characteristic_two_field,20,30,2 },
959 { 0x74,0xD5,0x9F,0xF0,0x7F,0x6B,0x41,0x3D,0x0E,0xA1, /* seed */
960 0x4B,0x34,0x4B,0x20,0xA2,0xDB,0x04,0x9B,0x50,0xC3,
961
962 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
963 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
964 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
965
966 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
967 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
968 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
969
970 0x00,0x66,0x64,0x7E,0xDE,0x6C,0x33,0x2C,0x7F,0x8C, /* b */
971 0x09,0x23,0xBB,0x58,0x21,0x3B,0x33,0x3B,0x20,0xE9,
972 0xCE,0x42,0x81,0xFE,0x11,0x5F,0x7D,0x8F,0x90,0xAD,
973
974 0x00,0xFA,0xC9,0xDF,0xCB,0xAC,0x83,0x13,0xBB,0x21, /* x */
975 0x39,0xF1,0xBB,0x75,0x5F,0xEF,0x65,0xBC,0x39,0x1F,
976 0x8B,0x36,0xF8,0xF8,0xEB,0x73,0x71,0xFD,0x55,0x8B,
977
978 0x01,0x00,0x6A,0x08,0xA4,0x19,0x03,0x35,0x06,0x78, /* y */
979 0xE5,0x85,0x28,0xBE,0xBF,0x8A,0x0B,0xEF,0xF8,0x67,
980 0xA7,0xCA,0x36,0x71,0x6F,0x7E,0x01,0xF8,0x10,0x52,
981
982 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
983 0x00,0x00,0x00,0x00,0x00,0x13,0xE9,0x74,0xE7,0x2F,
984 0x8A,0x69,0x22,0x03,0x1D,0x26,0x03,0xCF,0xE0,0xD7 }
985 };
986
987static const struct { EC_CURVE_DATA h; unsigned char data[0+30*6]; }
988 _EC_SECG_CHAR2_239K1 = {
989 { NID_X9_62_characteristic_two_field,0,30,4 },
990 { /* no seed */
991 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
992 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
993 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
994
995 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
996 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
997 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
998
999 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
1000 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1001 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
1002
1003 0x29,0xA0,0xB6,0xA8,0x87,0xA9,0x83,0xE9,0x73,0x09, /* x */
1004 0x88,0xA6,0x87,0x27,0xA8,0xB2,0xD1,0x26,0xC4,0x4C,
1005 0xC2,0xCC,0x7B,0x2A,0x65,0x55,0x19,0x30,0x35,0xDC,
1006
1007 0x76,0x31,0x08,0x04,0xF1,0x2E,0x54,0x9B,0xDB,0x01, /* y */
1008 0x1C,0x10,0x30,0x89,0xE7,0x35,0x10,0xAC,0xB2,0x75,
1009 0xFC,0x31,0x2A,0x5D,0xC6,0xB7,0x65,0x53,0xF0,0xCA,
1010
1011 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
1012 0x00,0x00,0x00,0x00,0x00,0x5A,0x79,0xFE,0xC6,0x7C,
1013 0xB6,0xE9,0x1F,0x1C,0x1D,0xA8,0x00,0xE4,0x78,0xA5 }
1014 };
1015
1016static const struct { EC_CURVE_DATA h; unsigned char data[0+36*6]; }
1017 _EC_NIST_CHAR2_283K = {
1018 { NID_X9_62_characteristic_two_field,0,36,4 },
1019 { /* no seed */
1020 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1021 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1022 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1023 0x00,0x00,0x00,0x00,0x10,0xA1,
1024 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
1025 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1026 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1027 0x00,0x00,0x00,0x00,0x00,0x00,
1028 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
1029 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1030 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1031 0x00,0x00,0x00,0x00,0x00,0x01,
1032 0x05,0x03,0x21,0x3F,0x78,0xCA,0x44,0x88,0x3F,0x1A, /* x */
1033 0x3B,0x81,0x62,0xF1,0x88,0xE5,0x53,0xCD,0x26,0x5F,
1034 0x23,0xC1,0x56,0x7A,0x16,0x87,0x69,0x13,0xB0,0xC2,
1035 0xAC,0x24,0x58,0x49,0x28,0x36,
1036 0x01,0xCC,0xDA,0x38,0x0F,0x1C,0x9E,0x31,0x8D,0x90, /* y */
1037 0xF9,0x5D,0x07,0xE5,0x42,0x6F,0xE8,0x7E,0x45,0xC0,
1038 0xE8,0x18,0x46,0x98,0xE4,0x59,0x62,0x36,0x4E,0x34,
1039 0x11,0x61,0x77,0xDD,0x22,0x59,
1040 0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
1041 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE9,0xAE,
1042 0x2E,0xD0,0x75,0x77,0x26,0x5D,0xFF,0x7F,0x94,0x45,
1043 0x1E,0x06,0x1E,0x16,0x3C,0x61 }
1044 };
1045
1046static const struct { EC_CURVE_DATA h; unsigned char data[20+36*6]; }
1047 _EC_NIST_CHAR2_283B = {
1048 { NID_X9_62_characteristic_two_field,20,36,2 },
1049 { 0x77,0xE2,0xB0,0x73,0x70,0xEB,0x0F,0x83,0x2A,0x6D, /* no seed */
1050 0xD5,0xB6,0x2D,0xFC,0x88,0xCD,0x06,0xBB,0x84,0xBE,
1051
1052 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1053 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1054 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1055 0x00,0x00,0x00,0x00,0x10,0xA1,
1056 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
1057 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1058 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1059 0x00,0x00,0x00,0x00,0x00,0x01,
1060 0x02,0x7B,0x68,0x0A,0xC8,0xB8,0x59,0x6D,0xA5,0xA4, /* b */
1061 0xAF,0x8A,0x19,0xA0,0x30,0x3F,0xCA,0x97,0xFD,0x76,
1062 0x45,0x30,0x9F,0xA2,0xA5,0x81,0x48,0x5A,0xF6,0x26,
1063 0x3E,0x31,0x3B,0x79,0xA2,0xF5,
1064 0x05,0xF9,0x39,0x25,0x8D,0xB7,0xDD,0x90,0xE1,0x93, /* x */
1065 0x4F,0x8C,0x70,0xB0,0xDF,0xEC,0x2E,0xED,0x25,0xB8,
1066 0x55,0x7E,0xAC,0x9C,0x80,0xE2,0xE1,0x98,0xF8,0xCD,
1067 0xBE,0xCD,0x86,0xB1,0x20,0x53,
1068 0x03,0x67,0x68,0x54,0xFE,0x24,0x14,0x1C,0xB9,0x8F, /* y */
1069 0xE6,0xD4,0xB2,0x0D,0x02,0xB4,0x51,0x6F,0xF7,0x02,
1070 0x35,0x0E,0xDD,0xB0,0x82,0x67,0x79,0xC8,0x13,0xF0,
1071 0xDF,0x45,0xBE,0x81,0x12,0xF4,
1072 0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
1073 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x90,
1074 0x39,0x96,0x60,0xFC,0x93,0x8A,0x90,0x16,0x5B,0x04,
1075 0x2A,0x7C,0xEF,0xAD,0xB3,0x07 }
1076 };
1077
1078static const struct { EC_CURVE_DATA h; unsigned char data[0+52*6]; }
1079 _EC_NIST_CHAR2_409K = {
1080 { NID_X9_62_characteristic_two_field,0,52,4 },
1081 { /* no seed */
1082 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1083 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1084 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1085 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1086 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1087 0x00,0x01,
1088 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
1089 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1090 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1091 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1092 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1093 0x00,0x00,
1094 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
1095 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1096 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1097 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1098 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1099 0x00,0x01,
1100 0x00,0x60,0xF0,0x5F,0x65,0x8F,0x49,0xC1,0xAD,0x3A, /* x */
1101 0xB1,0x89,0x0F,0x71,0x84,0x21,0x0E,0xFD,0x09,0x87,
1102 0xE3,0x07,0xC8,0x4C,0x27,0xAC,0xCF,0xB8,0xF9,0xF6,
1103 0x7C,0xC2,0xC4,0x60,0x18,0x9E,0xB5,0xAA,0xAA,0x62,
1104 0xEE,0x22,0x2E,0xB1,0xB3,0x55,0x40,0xCF,0xE9,0x02,
1105 0x37,0x46,
1106 0x01,0xE3,0x69,0x05,0x0B,0x7C,0x4E,0x42,0xAC,0xBA, /* y */
1107 0x1D,0xAC,0xBF,0x04,0x29,0x9C,0x34,0x60,0x78,0x2F,
1108 0x91,0x8E,0xA4,0x27,0xE6,0x32,0x51,0x65,0xE9,0xEA,
1109 0x10,0xE3,0xDA,0x5F,0x6C,0x42,0xE9,0xC5,0x52,0x15,
1110 0xAA,0x9C,0xA2,0x7A,0x58,0x63,0xEC,0x48,0xD8,0xE0,
1111 0x28,0x6B,
1112 0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
1113 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1114 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x5F,0x83,0xB2,
1115 0xD4,0xEA,0x20,0x40,0x0E,0xC4,0x55,0x7D,0x5E,0xD3,
1116 0xE3,0xE7,0xCA,0x5B,0x4B,0x5C,0x83,0xB8,0xE0,0x1E,
1117 0x5F,0xCF }
1118 };
1119
1120static const struct { EC_CURVE_DATA h; unsigned char data[20+52*6]; }
1121 _EC_NIST_CHAR2_409B = {
1122 { NID_X9_62_characteristic_two_field,20,52,2 },
1123 { 0x40,0x99,0xB5,0xA4,0x57,0xF9,0xD6,0x9F,0x79,0x21, /* seed */
1124 0x3D,0x09,0x4C,0x4B,0xCD,0x4D,0x42,0x62,0x21,0x0B,
1125
1126 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1127 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1128 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1129 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1130 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1131 0x00,0x01,
1132 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
1133 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1134 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1135 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1136 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1137 0x00,0x01,
1138 0x00,0x21,0xA5,0xC2,0xC8,0xEE,0x9F,0xEB,0x5C,0x4B, /* b */
1139 0x9A,0x75,0x3B,0x7B,0x47,0x6B,0x7F,0xD6,0x42,0x2E,
1140 0xF1,0xF3,0xDD,0x67,0x47,0x61,0xFA,0x99,0xD6,0xAC,
1141 0x27,0xC8,0xA9,0xA1,0x97,0xB2,0x72,0x82,0x2F,0x6C,
1142 0xD5,0x7A,0x55,0xAA,0x4F,0x50,0xAE,0x31,0x7B,0x13,
1143 0x54,0x5F,
1144 0x01,0x5D,0x48,0x60,0xD0,0x88,0xDD,0xB3,0x49,0x6B, /* x */
1145 0x0C,0x60,0x64,0x75,0x62,0x60,0x44,0x1C,0xDE,0x4A,
1146 0xF1,0x77,0x1D,0x4D,0xB0,0x1F,0xFE,0x5B,0x34,0xE5,
1147 0x97,0x03,0xDC,0x25,0x5A,0x86,0x8A,0x11,0x80,0x51,
1148 0x56,0x03,0xAE,0xAB,0x60,0x79,0x4E,0x54,0xBB,0x79,
1149 0x96,0xA7,
1150 0x00,0x61,0xB1,0xCF,0xAB,0x6B,0xE5,0xF3,0x2B,0xBF, /* y */
1151 0xA7,0x83,0x24,0xED,0x10,0x6A,0x76,0x36,0xB9,0xC5,
1152 0xA7,0xBD,0x19,0x8D,0x01,0x58,0xAA,0x4F,0x54,0x88,
1153 0xD0,0x8F,0x38,0x51,0x4F,0x1F,0xDF,0x4B,0x4F,0x40,
1154 0xD2,0x18,0x1B,0x36,0x81,0xC3,0x64,0xBA,0x02,0x73,
1155 0xC7,0x06,
1156 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
1157 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1158 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xE2,0xAA,0xD6,
1159 0xA6,0x12,0xF3,0x33,0x07,0xBE,0x5F,0xA4,0x7C,0x3C,
1160 0x9E,0x05,0x2F,0x83,0x81,0x64,0xCD,0x37,0xD9,0xA2,
1161 0x11,0x73 }
1162 };
1163
1164static const struct { EC_CURVE_DATA h; unsigned char data[0+72*6]; }
1165 _EC_NIST_CHAR2_571K = {
1166 { NID_X9_62_characteristic_two_field,0,72,4 },
1167 { /* no seed */
1168 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1169 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1170 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1171 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1172 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1173 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1174 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1175 0x04,0x25,
1176 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
1177 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1178 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1179 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1180 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1181 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1182 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1183 0x00,0x00,
1184 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
1185 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1186 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1187 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1188 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1189 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1190 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1191 0x00,0x01,
1192 0x02,0x6E,0xB7,0xA8,0x59,0x92,0x3F,0xBC,0x82,0x18, /* x */
1193 0x96,0x31,0xF8,0x10,0x3F,0xE4,0xAC,0x9C,0xA2,0x97,
1194 0x00,0x12,0xD5,0xD4,0x60,0x24,0x80,0x48,0x01,0x84,
1195 0x1C,0xA4,0x43,0x70,0x95,0x84,0x93,0xB2,0x05,0xE6,
1196 0x47,0xDA,0x30,0x4D,0xB4,0xCE,0xB0,0x8C,0xBB,0xD1,
1197 0xBA,0x39,0x49,0x47,0x76,0xFB,0x98,0x8B,0x47,0x17,
1198 0x4D,0xCA,0x88,0xC7,0xE2,0x94,0x52,0x83,0xA0,0x1C,
1199 0x89,0x72,
1200 0x03,0x49,0xDC,0x80,0x7F,0x4F,0xBF,0x37,0x4F,0x4A, /* y */
1201 0xEA,0xDE,0x3B,0xCA,0x95,0x31,0x4D,0xD5,0x8C,0xEC,
1202 0x9F,0x30,0x7A,0x54,0xFF,0xC6,0x1E,0xFC,0x00,0x6D,
1203 0x8A,0x2C,0x9D,0x49,0x79,0xC0,0xAC,0x44,0xAE,0xA7,
1204 0x4F,0xBE,0xBB,0xB9,0xF7,0x72,0xAE,0xDC,0xB6,0x20,
1205 0xB0,0x1A,0x7B,0xA7,0xAF,0x1B,0x32,0x04,0x30,0xC8,
1206 0x59,0x19,0x84,0xF6,0x01,0xCD,0x4C,0x14,0x3E,0xF1,
1207 0xC7,0xA3,
1208 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
1209 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1210 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1211 0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x18,0x50,0xE1,
1212 0xF1,0x9A,0x63,0xE4,0xB3,0x91,0xA8,0xDB,0x91,0x7F,
1213 0x41,0x38,0xB6,0x30,0xD8,0x4B,0xE5,0xD6,0x39,0x38,
1214 0x1E,0x91,0xDE,0xB4,0x5C,0xFE,0x77,0x8F,0x63,0x7C,
1215 0x10,0x01 }
1216 };
1217
1218static const struct { EC_CURVE_DATA h; unsigned char data[20+72*6]; }
1219 _EC_NIST_CHAR2_571B = {
1220 { NID_X9_62_characteristic_two_field,20,72,2 },
1221 { 0x2A,0xA0,0x58,0xF7,0x3A,0x0E,0x33,0xAB,0x48,0x6B, /* seed */
1222 0x0F,0x61,0x04,0x10,0xC5,0x3A,0x7F,0x13,0x23,0x10,
1223
1224 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1225 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1226 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1227 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1228 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1229 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1230 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1231 0x04,0x25,
1232 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
1233 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1234 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1235 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1236 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1237 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1238 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1239 0x00,0x01,
1240 0x02,0xF4,0x0E,0x7E,0x22,0x21,0xF2,0x95,0xDE,0x29, /* b */
1241 0x71,0x17,0xB7,0xF3,0xD6,0x2F,0x5C,0x6A,0x97,0xFF,
1242 0xCB,0x8C,0xEF,0xF1,0xCD,0x6B,0xA8,0xCE,0x4A,0x9A,
1243 0x18,0xAD,0x84,0xFF,0xAB,0xBD,0x8E,0xFA,0x59,0x33,
1244 0x2B,0xE7,0xAD,0x67,0x56,0xA6,0x6E,0x29,0x4A,0xFD,
1245 0x18,0x5A,0x78,0xFF,0x12,0xAA,0x52,0x0E,0x4D,0xE7,
1246 0x39,0xBA,0xCA,0x0C,0x7F,0xFE,0xFF,0x7F,0x29,0x55,
1247 0x72,0x7A,
1248 0x03,0x03,0x00,0x1D,0x34,0xB8,0x56,0x29,0x6C,0x16, /* x */
1249 0xC0,0xD4,0x0D,0x3C,0xD7,0x75,0x0A,0x93,0xD1,0xD2,
1250 0x95,0x5F,0xA8,0x0A,0xA5,0xF4,0x0F,0xC8,0xDB,0x7B,
1251 0x2A,0xBD,0xBD,0xE5,0x39,0x50,0xF4,0xC0,0xD2,0x93,
1252 0xCD,0xD7,0x11,0xA3,0x5B,0x67,0xFB,0x14,0x99,0xAE,
1253 0x60,0x03,0x86,0x14,0xF1,0x39,0x4A,0xBF,0xA3,0xB4,
1254 0xC8,0x50,0xD9,0x27,0xE1,0xE7,0x76,0x9C,0x8E,0xEC,
1255 0x2D,0x19,
1256 0x03,0x7B,0xF2,0x73,0x42,0xDA,0x63,0x9B,0x6D,0xCC, /* y */
1257 0xFF,0xFE,0xB7,0x3D,0x69,0xD7,0x8C,0x6C,0x27,0xA6,
1258 0x00,0x9C,0xBB,0xCA,0x19,0x80,0xF8,0x53,0x39,0x21,
1259 0xE8,0xA6,0x84,0x42,0x3E,0x43,0xBA,0xB0,0x8A,0x57,
1260 0x62,0x91,0xAF,0x8F,0x46,0x1B,0xB2,0xA8,0xB3,0x53,
1261 0x1D,0x2F,0x04,0x85,0xC1,0x9B,0x16,0xE2,0xF1,0x51,
1262 0x6E,0x23,0xDD,0x3C,0x1A,0x48,0x27,0xAF,0x1B,0x8A,
1263 0xC1,0x5B,
1264 0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
1265 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1266 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
1267 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x61,0xCE,0x18,
1268 0xFF,0x55,0x98,0x73,0x08,0x05,0x9B,0x18,0x68,0x23,
1269 0x85,0x1E,0xC7,0xDD,0x9C,0xA1,0x16,0x1D,0xE9,0x3D,
1270 0x51,0x74,0xD6,0x6E,0x83,0x82,0xE9,0xBB,0x2F,0xE8,
1271 0x4E,0x47 }
1272 };
1273
1274static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; }
1275 _EC_X9_62_CHAR2_163V1 = {
1276 { NID_X9_62_characteristic_two_field,20,21,2 },
1277 { 0xD2,0xC0,0xFB,0x15,0x76,0x08,0x60,0xDE,0xF1,0xEE,
1278 0xF4,0xD6,0x96,0xE6,0x76,0x87,0x56,0x15,0x17,0x54, /* seed */
1279
1280 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1281 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
1282 0x07,
1283 0x07,0x25,0x46,0xB5,0x43,0x52,0x34,0xA4,0x22,0xE0, /* a */
1284 0x78,0x96,0x75,0xF4,0x32,0xC8,0x94,0x35,0xDE,0x52,
1285 0x42,
1286 0x00,0xC9,0x51,0x7D,0x06,0xD5,0x24,0x0D,0x3C,0xFF, /* b */
1287 0x38,0xC7,0x4B,0x20,0xB6,0xCD,0x4D,0x6F,0x9D,0xD4,
1288 0xD9,
1289 0x07,0xAF,0x69,0x98,0x95,0x46,0x10,0x3D,0x79,0x32, /* x */
1290 0x9F,0xCC,0x3D,0x74,0x88,0x0F,0x33,0xBB,0xE8,0x03,
1291 0xCB,
1292 0x01,0xEC,0x23,0x21,0x1B,0x59,0x66,0xAD,0xEA,0x1D, /* y */
1293 0x3F,0x87,0xF7,0xEA,0x58,0x48,0xAE,0xF0,0xB7,0xCA,
1294 0x9F,
1295 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
1296 0x01,0xE6,0x0F,0xC8,0x82,0x1C,0xC7,0x4D,0xAE,0xAF,
1297 0xC1 }
1298 };
1299
1300static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; }
1301 _EC_X9_62_CHAR2_163V2 = {
1302 { NID_X9_62_characteristic_two_field,20,21,2 },
1303 { 0x53,0x81,0x4C,0x05,0x0D,0x44,0xD6,0x96,0xE6,0x76, /* seed */
1304 0x87,0x56,0x15,0x17,0x58,0x0C,0xA4,0xE2,0x9F,0xFD,
1305
1306 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1307 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
1308 0x07,
1309 0x01,0x08,0xB3,0x9E,0x77,0xC4,0xB1,0x08,0xBE,0xD9, /* a */
1310 0x81,0xED,0x0E,0x89,0x0E,0x11,0x7C,0x51,0x1C,0xF0,
1311 0x72,
1312 0x06,0x67,0xAC,0xEB,0x38,0xAF,0x4E,0x48,0x8C,0x40, /* b */
1313 0x74,0x33,0xFF,0xAE,0x4F,0x1C,0x81,0x16,0x38,0xDF,
1314 0x20,
1315 0x00,0x24,0x26,0x6E,0x4E,0xB5,0x10,0x6D,0x0A,0x96, /* x */
1316 0x4D,0x92,0xC4,0x86,0x0E,0x26,0x71,0xDB,0x9B,0x6C,
1317 0xC5,
1318 0x07,0x9F,0x68,0x4D,0xDF,0x66,0x84,0xC5,0xCD,0x25, /* y */
1319 0x8B,0x38,0x90,0x02,0x1B,0x23,0x86,0xDF,0xD1,0x9F,
1320 0xC5,
1321 0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
1322 0xFD,0xF6,0x4D,0xE1,0x15,0x1A,0xDB,0xB7,0x8F,0x10,
1323 0xA7 }
1324 };
1325
1326static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; }
1327 _EC_X9_62_CHAR2_163V3 = {
1328 { NID_X9_62_characteristic_two_field,20,21,2 },
1329 { 0x50,0xCB,0xF1,0xD9,0x5C,0xA9,0x4D,0x69,0x6E,0x67, /* seed */
1330 0x68,0x75,0x61,0x51,0x75,0xF1,0x6A,0x36,0xA3,0xB8,
1331
1332 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1333 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
1334 0x07,
1335 0x07,0xA5,0x26,0xC6,0x3D,0x3E,0x25,0xA2,0x56,0xA0, /* a */
1336 0x07,0x69,0x9F,0x54,0x47,0xE3,0x2A,0xE4,0x56,0xB5,
1337 0x0E,
1338 0x03,0xF7,0x06,0x17,0x98,0xEB,0x99,0xE2,0x38,0xFD, /* b */
1339 0x6F,0x1B,0xF9,0x5B,0x48,0xFE,0xEB,0x48,0x54,0x25,
1340 0x2B,
1341 0x02,0xF9,0xF8,0x7B,0x7C,0x57,0x4D,0x0B,0xDE,0xCF, /* x */
1342 0x8A,0x22,0xE6,0x52,0x47,0x75,0xF9,0x8C,0xDE,0xBD,
1343 0xCB,
1344 0x05,0xB9,0x35,0x59,0x0C,0x15,0x5E,0x17,0xEA,0x48, /* y */
1345 0xEB,0x3F,0xF3,0x71,0x8B,0x89,0x3D,0xF5,0x9A,0x05,
1346 0xD0,
1347 0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
1348 0xFE,0x1A,0xEE,0x14,0x0F,0x11,0x0A,0xFF,0x96,0x13,
1349 0x09 }
1350 };
1351
1352static const struct { EC_CURVE_DATA h; unsigned char data[0+23*6]; }
1353 _EC_X9_62_CHAR2_176V1 = {
1354 { NID_X9_62_characteristic_two_field,0,23,0xFF6E },
1355 { /* no seed */
1356 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1357 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,
1358 0x00,0x00,0x07,
1359 0x00,0xE4,0xE6,0xDB,0x29,0x95,0x06,0x5C,0x40,0x7D, /* a */
1360 0x9D,0x39,0xB8,0xD0,0x96,0x7B,0x96,0x70,0x4B,0xA8,
1361 0xE9,0xC9,0x0B,
1362 0x00,0x5D,0xDA,0x47,0x0A,0xBE,0x64,0x14,0xDE,0x8E, /* b */
1363 0xC1,0x33,0xAE,0x28,0xE9,0xBB,0xD7,0xFC,0xEC,0x0A,
1364 0xE0,0xFF,0xF2,
1365 0x00,0x8D,0x16,0xC2,0x86,0x67,0x98,0xB6,0x00,0xF9, /* x */
1366 0xF0,0x8B,0xB4,0xA8,0xE8,0x60,0xF3,0x29,0x8C,0xE0,
1367 0x4A,0x57,0x98,
1368 0x00,0x6F,0xA4,0x53,0x9C,0x2D,0xAD,0xDD,0xD6,0xBA, /* y */
1369 0xB5,0x16,0x7D,0x61,0xB4,0x36,0xE1,0xD9,0x2B,0xB1,
1370 0x6A,0x56,0x2C,
1371 0x00,0x00,0x01,0x00,0x92,0x53,0x73,0x97,0xEC,0xA4, /* order */
1372 0xF6,0x14,0x57,0x99,0xD6,0x2B,0x0A,0x19,0xCE,0x06,
1373 0xFE,0x26,0xAD }
1374 };
1375
1376static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
1377 _EC_X9_62_CHAR2_191V1 = {
1378 { NID_X9_62_characteristic_two_field,20,24,2 },
1379 { 0x4E,0x13,0xCA,0x54,0x27,0x44,0xD6,0x96,0xE6,0x76, /* seed */
1380 0x87,0x56,0x15,0x17,0x55,0x2F,0x27,0x9A,0x8C,0x84,
1381
1382 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1383 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1384 0x00,0x00,0x02,0x01,
1385 0x28,0x66,0x53,0x7B,0x67,0x67,0x52,0x63,0x6A,0x68, /* a */
1386 0xF5,0x65,0x54,0xE1,0x26,0x40,0x27,0x6B,0x64,0x9E,
1387 0xF7,0x52,0x62,0x67,
1388 0x2E,0x45,0xEF,0x57,0x1F,0x00,0x78,0x6F,0x67,0xB0, /* b */
1389 0x08,0x1B,0x94,0x95,0xA3,0xD9,0x54,0x62,0xF5,0xDE,
1390 0x0A,0xA1,0x85,0xEC,
1391 0x36,0xB3,0xDA,0xF8,0xA2,0x32,0x06,0xF9,0xC4,0xF2, /* x */
1392 0x99,0xD7,0xB2,0x1A,0x9C,0x36,0x91,0x37,0xF2,0xC8,
1393 0x4A,0xE1,0xAA,0x0D,
1394 0x76,0x5B,0xE7,0x34,0x33,0xB3,0xF9,0x5E,0x33,0x29, /* y */
1395 0x32,0xE7,0x0E,0xA2,0x45,0xCA,0x24,0x18,0xEA,0x0E,
1396 0xF9,0x80,0x18,0xFB,
1397 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
1398 0x00,0x00,0x04,0xA2,0x0E,0x90,0xC3,0x90,0x67,0xC8,
1399 0x93,0xBB,0xB9,0xA5 }
1400 };
1401
1402static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
1403 _EC_X9_62_CHAR2_191V2 = {
1404 { NID_X9_62_characteristic_two_field,20,24,4 },
1405 { 0x08,0x71,0xEF,0x2F,0xEF,0x24,0xD6,0x96,0xE6,0x76, /* seed */
1406 0x87,0x56,0x15,0x17,0x58,0xBE,0xE0,0xD9,0x5C,0x15,
1407
1408 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1409 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1410 0x00,0x00,0x02,0x01,
1411 0x40,0x10,0x28,0x77,0x4D,0x77,0x77,0xC7,0xB7,0x66, /* a */
1412 0x6D,0x13,0x66,0xEA,0x43,0x20,0x71,0x27,0x4F,0x89,
1413 0xFF,0x01,0xE7,0x18,
1414 0x06,0x20,0x04,0x8D,0x28,0xBC,0xBD,0x03,0xB6,0x24, /* b */
1415 0x9C,0x99,0x18,0x2B,0x7C,0x8C,0xD1,0x97,0x00,0xC3,
1416 0x62,0xC4,0x6A,0x01,
1417 0x38,0x09,0xB2,0xB7,0xCC,0x1B,0x28,0xCC,0x5A,0x87, /* x */
1418 0x92,0x6A,0xAD,0x83,0xFD,0x28,0x78,0x9E,0x81,0xE2,
1419 0xC9,0xE3,0xBF,0x10,
1420 0x17,0x43,0x43,0x86,0x62,0x6D,0x14,0xF3,0xDB,0xF0, /* y */
1421 0x17,0x60,0xD9,0x21,0x3A,0x3E,0x1C,0xF3,0x7A,0xEC,
1422 0x43,0x7D,0x66,0x8A,
1423 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
1424 0x00,0x00,0x50,0x50,0x8C,0xB8,0x9F,0x65,0x28,0x24,
1425 0xE0,0x6B,0x81,0x73 }
1426 };
1427
1428static const struct { EC_CURVE_DATA h; unsigned char data[20+24*6]; }
1429 _EC_X9_62_CHAR2_191V3 = {
1430 { NID_X9_62_characteristic_two_field,20,24,6 },
1431 { 0xE0,0x53,0x51,0x2D,0xC6,0x84,0xD6,0x96,0xE6,0x76, /* seed */
1432 0x87,0x56,0x15,0x17,0x50,0x67,0xAE,0x78,0x6D,0x1F,
1433
1434 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1435 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1436 0x00,0x00,0x02,0x01,
1437 0x6C,0x01,0x07,0x47,0x56,0x09,0x91,0x22,0x22,0x10, /* a */
1438 0x56,0x91,0x1C,0x77,0xD7,0x7E,0x77,0xA7,0x77,0xE7,
1439 0xE7,0xE7,0x7F,0xCB,
1440 0x71,0xFE,0x1A,0xF9,0x26,0xCF,0x84,0x79,0x89,0xEF, /* b */
1441 0xEF,0x8D,0xB4,0x59,0xF6,0x63,0x94,0xD9,0x0F,0x32,
1442 0xAD,0x3F,0x15,0xE8,
1443 0x37,0x5D,0x4C,0xE2,0x4F,0xDE,0x43,0x44,0x89,0xDE, /* x */
1444 0x87,0x46,0xE7,0x17,0x86,0x01,0x50,0x09,0xE6,0x6E,
1445 0x38,0xA9,0x26,0xDD,
1446 0x54,0x5A,0x39,0x17,0x61,0x96,0x57,0x5D,0x98,0x59, /* y */
1447 0x99,0x36,0x6E,0x6A,0xD3,0x4C,0xE0,0xA7,0x7C,0xD7,
1448 0x12,0x7B,0x06,0xBE,
1449 0x15,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, /* order */
1450 0x55,0x55,0x61,0x0C,0x0B,0x19,0x68,0x12,0xBF,0xB6,
1451 0x28,0x8A,0x3E,0xA3 }
1452 };
1453
1454static const struct { EC_CURVE_DATA h; unsigned char data[0+27*6]; }
1455 _EC_X9_62_CHAR2_208W1 = {
1456 { NID_X9_62_characteristic_two_field,0,27,0xFE48 },
1457 { /* no seed */
1458 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1459 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
1460 0x00,0x00,0x00,0x00,0x00,0x00,0x07,
1461 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
1462 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1463 0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1464 0x00,0xC8,0x61,0x9E,0xD4,0x5A,0x62,0xE6,0x21,0x2E, /* b */
1465 0x11,0x60,0x34,0x9E,0x2B,0xFA,0x84,0x44,0x39,0xFA,
1466 0xFC,0x2A,0x3F,0xD1,0x63,0x8F,0x9E,
1467 0x00,0x89,0xFD,0xFB,0xE4,0xAB,0xE1,0x93,0xDF,0x95, /* x */
1468 0x59,0xEC,0xF0,0x7A,0xC0,0xCE,0x78,0x55,0x4E,0x27,
1469 0x84,0xEB,0x8C,0x1E,0xD1,0xA5,0x7A,
1470 0x00,0x0F,0x55,0xB5,0x1A,0x06,0xE7,0x8E,0x9A,0xC3, /* y */
1471 0x8A,0x03,0x5F,0xF5,0x20,0xD8,0xB0,0x17,0x81,0xBE,
1472 0xB1,0xA6,0xBB,0x08,0x61,0x7D,0xE3,
1473 0x00,0x00,0x01,0x01,0xBA,0xF9,0x5C,0x97,0x23,0xC5, /* order */
1474 0x7B,0x6C,0x21,0xDA,0x2E,0xFF,0x2D,0x5E,0xD5,0x88,
1475 0xBD,0xD5,0x71,0x7E,0x21,0x2F,0x9D }
1476 };
1477
1478static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
1479 _EC_X9_62_CHAR2_239V1 = {
1480 { NID_X9_62_characteristic_two_field,20,30,4 },
1481 { 0xD3,0x4B,0x9A,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61, /* seed */
1482 0x51,0x75,0xCA,0x71,0xB9,0x20,0xBF,0xEF,0xB0,0x5D,
1483
1484 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1485 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1486 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,
1487
1488 0x32,0x01,0x08,0x57,0x07,0x7C,0x54,0x31,0x12,0x3A, /* a */
1489 0x46,0xB8,0x08,0x90,0x67,0x56,0xF5,0x43,0x42,0x3E,
1490 0x8D,0x27,0x87,0x75,0x78,0x12,0x57,0x78,0xAC,0x76,
1491
1492 0x79,0x04,0x08,0xF2,0xEE,0xDA,0xF3,0x92,0xB0,0x12, /* b */
1493 0xED,0xEF,0xB3,0x39,0x2F,0x30,0xF4,0x32,0x7C,0x0C,
1494 0xA3,0xF3,0x1F,0xC3,0x83,0xC4,0x22,0xAA,0x8C,0x16,
1495
1496 0x57,0x92,0x70,0x98,0xFA,0x93,0x2E,0x7C,0x0A,0x96, /* x */
1497 0xD3,0xFD,0x5B,0x70,0x6E,0xF7,0xE5,0xF5,0xC1,0x56,
1498 0xE1,0x6B,0x7E,0x7C,0x86,0x03,0x85,0x52,0xE9,0x1D,
1499
1500 0x61,0xD8,0xEE,0x50,0x77,0xC3,0x3F,0xEC,0xF6,0xF1, /* y */
1501 0xA1,0x6B,0x26,0x8D,0xE4,0x69,0xC3,0xC7,0x74,0x4E,
1502 0xA9,0xA9,0x71,0x64,0x9F,0xC7,0xA9,0x61,0x63,0x05,
1503
1504 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* order */
1505 0x00,0x00,0x00,0x00,0x00,0x0F,0x4D,0x42,0xFF,0xE1,
1506 0x49,0x2A,0x49,0x93,0xF1,0xCA,0xD6,0x66,0xE4,0x47 }
1507 };
1508
1509static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
1510 _EC_X9_62_CHAR2_239V2 = {
1511 { NID_X9_62_characteristic_two_field,20,30,6 },
1512 { 0x2A,0xA6,0x98,0x2F,0xDF,0xA4,0xD6,0x96,0xE6,0x76, /* seed */
1513 0x87,0x56,0x15,0x17,0x5D,0x26,0x67,0x27,0x27,0x7D,
1514
1515 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1516 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1517 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,
1518
1519 0x42,0x30,0x01,0x77,0x57,0xA7,0x67,0xFA,0xE4,0x23, /* a */
1520 0x98,0x56,0x9B,0x74,0x63,0x25,0xD4,0x53,0x13,0xAF,
1521 0x07,0x66,0x26,0x64,0x79,0xB7,0x56,0x54,0xE6,0x5F,
1522
1523 0x50,0x37,0xEA,0x65,0x41,0x96,0xCF,0xF0,0xCD,0x82, /* b */
1524 0xB2,0xC1,0x4A,0x2F,0xCF,0x2E,0x3F,0xF8,0x77,0x52,
1525 0x85,0xB5,0x45,0x72,0x2F,0x03,0xEA,0xCD,0xB7,0x4B,
1526
1527 0x28,0xF9,0xD0,0x4E,0x90,0x00,0x69,0xC8,0xDC,0x47, /* x */
1528 0xA0,0x85,0x34,0xFE,0x76,0xD2,0xB9,0x00,0xB7,0xD7,
1529 0xEF,0x31,0xF5,0x70,0x9F,0x20,0x0C,0x4C,0xA2,0x05,
1530
1531 0x56,0x67,0x33,0x4C,0x45,0xAF,0xF3,0xB5,0xA0,0x3B, /* y */
1532 0xAD,0x9D,0xD7,0x5E,0x2C,0x71,0xA9,0x93,0x62,0x56,
1533 0x7D,0x54,0x53,0xF7,0xFA,0x6E,0x22,0x7E,0xC8,0x33,
1534
1535 0x15,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, /* order */
1536 0x55,0x55,0x55,0x55,0x55,0x3C,0x6F,0x28,0x85,0x25,
1537 0x9C,0x31,0xE3,0xFC,0xDF,0x15,0x46,0x24,0x52,0x2D }
1538 };
1539
1540static const struct { EC_CURVE_DATA h; unsigned char data[20+30*6]; }
1541 _EC_X9_62_CHAR2_239V3 = {
1542 { NID_X9_62_characteristic_two_field,20,30,0xA },
1543 { 0x9E,0x07,0x6F,0x4D,0x69,0x6E,0x67,0x68,0x75,0x61, /* seed */
1544 0x51,0x75,0xE1,0x1E,0x9F,0xDD,0x77,0xF9,0x20,0x41,
1545
1546 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1547 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1548 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,
1549
1550 0x01,0x23,0x87,0x74,0x66,0x6A,0x67,0x76,0x6D,0x66, /* a */
1551 0x76,0xF7,0x78,0xE6,0x76,0xB6,0x69,0x99,0x17,0x66,
1552 0x66,0xE6,0x87,0x66,0x6D,0x87,0x66,0xC6,0x6A,0x9F,
1553
1554 0x6A,0x94,0x19,0x77,0xBA,0x9F,0x6A,0x43,0x51,0x99, /* b */
1555 0xAC,0xFC,0x51,0x06,0x7E,0xD5,0x87,0xF5,0x19,0xC5,
1556 0xEC,0xB5,0x41,0xB8,0xE4,0x41,0x11,0xDE,0x1D,0x40,
1557
1558 0x70,0xF6,0xE9,0xD0,0x4D,0x28,0x9C,0x4E,0x89,0x91, /* x */
1559 0x3C,0xE3,0x53,0x0B,0xFD,0xE9,0x03,0x97,0x7D,0x42,
1560 0xB1,0x46,0xD5,0x39,0xBF,0x1B,0xDE,0x4E,0x9C,0x92,
1561
1562 0x2E,0x5A,0x0E,0xAF,0x6E,0x5E,0x13,0x05,0xB9,0x00, /* y */
1563 0x4D,0xCE,0x5C,0x0E,0xD7,0xFE,0x59,0xA3,0x56,0x08,
1564 0xF3,0x38,0x37,0xC8,0x16,0xD8,0x0B,0x79,0xF4,0x61,
1565
1566 0x0C,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC, /* order */
1567 0xCC,0xCC,0xCC,0xCC,0xCC,0xAC,0x49,0x12,0xD2,0xD9,
1568 0xDF,0x90,0x3E,0xF9,0x88,0x8B,0x8A,0x0E,0x4C,0xFF }
1569 };
1570
1571static const struct { EC_CURVE_DATA h; unsigned char data[0+35*6]; }
1572 _EC_X9_62_CHAR2_272W1 = {
1573 { NID_X9_62_characteristic_two_field,0,35,0xFF06 },
1574 { /* no seed */
1575 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1576 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1577 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
1578 0x00,0x00,0x00,0x00,0x0B,
1579 0x00,0x91,0xA0,0x91,0xF0,0x3B,0x5F,0xBA,0x4A,0xB2, /* a */
1580 0xCC,0xF4,0x9C,0x4E,0xDD,0x22,0x0F,0xB0,0x28,0x71,
1581 0x2D,0x42,0xBE,0x75,0x2B,0x2C,0x40,0x09,0x4D,0xBA,
1582 0xCD,0xB5,0x86,0xFB,0x20,
1583 0x00,0x71,0x67,0xEF,0xC9,0x2B,0xB2,0xE3,0xCE,0x7C, /* b */
1584 0x8A,0xAA,0xFF,0x34,0xE1,0x2A,0x9C,0x55,0x70,0x03,
1585 0xD7,0xC7,0x3A,0x6F,0xAF,0x00,0x3F,0x99,0xF6,0xCC,
1586 0x84,0x82,0xE5,0x40,0xF7,
1587 0x00,0x61,0x08,0xBA,0xBB,0x2C,0xEE,0xBC,0xF7,0x87, /* x */
1588 0x05,0x8A,0x05,0x6C,0xBE,0x0C,0xFE,0x62,0x2D,0x77,
1589 0x23,0xA2,0x89,0xE0,0x8A,0x07,0xAE,0x13,0xEF,0x0D,
1590 0x10,0xD1,0x71,0xDD,0x8D,
1591 0x00,0x10,0xC7,0x69,0x57,0x16,0x85,0x1E,0xEF,0x6B, /* y */
1592 0xA7,0xF6,0x87,0x2E,0x61,0x42,0xFB,0xD2,0x41,0xB8,
1593 0x30,0xFF,0x5E,0xFC,0xAC,0xEC,0xCA,0xB0,0x5E,0x02,
1594 0x00,0x5D,0xDE,0x9D,0x23,
1595 0x00,0x00,0x01,0x00,0xFA,0xF5,0x13,0x54,0xE0,0xE3, /* order */
1596 0x9E,0x48,0x92,0xDF,0x6E,0x31,0x9C,0x72,0xC8,0x16,
1597 0x16,0x03,0xFA,0x45,0xAA,0x7B,0x99,0x8A,0x16,0x7B,
1598 0x8F,0x1E,0x62,0x95,0x21 }
1599 };
1600
1601static const struct { EC_CURVE_DATA h; unsigned char data[0+39*6]; }
1602 _EC_X9_62_CHAR2_304W1 = {
1603 { NID_X9_62_characteristic_two_field,0,39,0xFE2E },
1604 { /* no seed */
1605 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1606 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1607 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1608 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x07,
1609 0x00,0xFD,0x0D,0x69,0x31,0x49,0xA1,0x18,0xF6,0x51, /* a */
1610 0xE6,0xDC,0xE6,0x80,0x20,0x85,0x37,0x7E,0x5F,0x88,
1611 0x2D,0x1B,0x51,0x0B,0x44,0x16,0x00,0x74,0xC1,0x28,
1612 0x80,0x78,0x36,0x5A,0x03,0x96,0xC8,0xE6,0x81,
1613 0x00,0xBD,0xDB,0x97,0xE5,0x55,0xA5,0x0A,0x90,0x8E, /* b */
1614 0x43,0xB0,0x1C,0x79,0x8E,0xA5,0xDA,0xA6,0x78,0x8F,
1615 0x1E,0xA2,0x79,0x4E,0xFC,0xF5,0x71,0x66,0xB8,0xC1,
1616 0x40,0x39,0x60,0x1E,0x55,0x82,0x73,0x40,0xBE,
1617 0x00,0x19,0x7B,0x07,0x84,0x5E,0x9B,0xE2,0xD9,0x6A, /* x */
1618 0xDB,0x0F,0x5F,0x3C,0x7F,0x2C,0xFF,0xBD,0x7A,0x3E,
1619 0xB8,0xB6,0xFE,0xC3,0x5C,0x7F,0xD6,0x7F,0x26,0xDD,
1620 0xF6,0x28,0x5A,0x64,0x4F,0x74,0x0A,0x26,0x14,
1621 0x00,0xE1,0x9F,0xBE,0xB7,0x6E,0x0D,0xA1,0x71,0x51, /* y */
1622 0x7E,0xCF,0x40,0x1B,0x50,0x28,0x9B,0xF0,0x14,0x10,
1623 0x32,0x88,0x52,0x7A,0x9B,0x41,0x6A,0x10,0x5E,0x80,
1624 0x26,0x0B,0x54,0x9F,0xDC,0x1B,0x92,0xC0,0x3B,
1625 0x00,0x00,0x01,0x01,0xD5,0x56,0x57,0x2A,0xAB,0xAC, /* order */
1626 0x80,0x01,0x01,0xD5,0x56,0x57,0x2A,0xAB,0xAC,0x80,
1627 0x01,0x02,0x2D,0x5C,0x91,0xDD,0x17,0x3F,0x8F,0xB5,
1628 0x61,0xDA,0x68,0x99,0x16,0x44,0x43,0x05,0x1D }
1629 };
1630
1631static const struct { EC_CURVE_DATA h; unsigned char data[20+45*6]; }
1632 _EC_X9_62_CHAR2_359V1 = {
1633 { NID_X9_62_characteristic_two_field,20,45,0x4C },
1634 { 0x2B,0x35,0x49,0x20,0xB7,0x24,0xD6,0x96,0xE6,0x76, /* seed */
1635 0x87,0x56,0x15,0x17,0x58,0x5B,0xA1,0x33,0x2D,0xC6,
1636
1637 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1638 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1639 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1640 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
1641 0x00,0x00,0x00,0x00,0x01,
1642 0x56,0x67,0x67,0x6A,0x65,0x4B,0x20,0x75,0x4F,0x35, /* a */
1643 0x6E,0xA9,0x20,0x17,0xD9,0x46,0x56,0x7C,0x46,0x67,
1644 0x55,0x56,0xF1,0x95,0x56,0xA0,0x46,0x16,0xB5,0x67,
1645 0xD2,0x23,0xA5,0xE0,0x56,0x56,0xFB,0x54,0x90,0x16,
1646 0xA9,0x66,0x56,0xA5,0x57,
1647 0x24,0x72,0xE2,0xD0,0x19,0x7C,0x49,0x36,0x3F,0x1F, /* b */
1648 0xE7,0xF5,0xB6,0xDB,0x07,0x5D,0x52,0xB6,0x94,0x7D,
1649 0x13,0x5D,0x8C,0xA4,0x45,0x80,0x5D,0x39,0xBC,0x34,
1650 0x56,0x26,0x08,0x96,0x87,0x74,0x2B,0x63,0x29,0xE7,
1651 0x06,0x80,0x23,0x19,0x88,
1652 0x3C,0x25,0x8E,0xF3,0x04,0x77,0x67,0xE7,0xED,0xE0, /* x */
1653 0xF1,0xFD,0xAA,0x79,0xDA,0xEE,0x38,0x41,0x36,0x6A,
1654 0x13,0x2E,0x16,0x3A,0xCE,0xD4,0xED,0x24,0x01,0xDF,
1655 0x9C,0x6B,0xDC,0xDE,0x98,0xE8,0xE7,0x07,0xC0,0x7A,
1656 0x22,0x39,0xB1,0xB0,0x97,
1657 0x53,0xD7,0xE0,0x85,0x29,0x54,0x70,0x48,0x12,0x1E, /* y */
1658 0x9C,0x95,0xF3,0x79,0x1D,0xD8,0x04,0x96,0x39,0x48,
1659 0xF3,0x4F,0xAE,0x7B,0xF4,0x4E,0xA8,0x23,0x65,0xDC,
1660 0x78,0x68,0xFE,0x57,0xE4,0xAE,0x2D,0xE2,0x11,0x30,
1661 0x5A,0x40,0x71,0x04,0xBD,
1662 0x01,0xAF,0x28,0x6B,0xCA,0x1A,0xF2,0x86,0xBC,0xA1, /* order */
1663 0xAF,0x28,0x6B,0xCA,0x1A,0xF2,0x86,0xBC,0xA1,0xAF,
1664 0x28,0x6B,0xC9,0xFB,0x8F,0x6B,0x85,0xC5,0x56,0x89,
1665 0x2C,0x20,0xA7,0xEB,0x96,0x4F,0xE7,0x71,0x9E,0x74,
1666 0xF4,0x90,0x75,0x8D,0x3B }
1667 };
1668
1669static const struct { EC_CURVE_DATA h; unsigned char data[0+47*6]; }
1670 _EC_X9_62_CHAR2_368W1 = {
1671 { NID_X9_62_characteristic_two_field,0,47,0xFF70 },
1672 { /* no seed */
1673 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1674 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1675 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1676 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
1677 0x00,0x00,0x00,0x00,0x00,0x00,0x07,
1678 0x00,0xE0,0xD2,0xEE,0x25,0x09,0x52,0x06,0xF5,0xE2, /* a */
1679 0xA4,0xF9,0xED,0x22,0x9F,0x1F,0x25,0x6E,0x79,0xA0,
1680 0xE2,0xB4,0x55,0x97,0x0D,0x8D,0x0D,0x86,0x5B,0xD9,
1681 0x47,0x78,0xC5,0x76,0xD6,0x2F,0x0A,0xB7,0x51,0x9C,
1682 0xCD,0x2A,0x1A,0x90,0x6A,0xE3,0x0D,
1683 0x00,0xFC,0x12,0x17,0xD4,0x32,0x0A,0x90,0x45,0x2C, /* b */
1684 0x76,0x0A,0x58,0xED,0xCD,0x30,0xC8,0xDD,0x06,0x9B,
1685 0x3C,0x34,0x45,0x38,0x37,0xA3,0x4E,0xD5,0x0C,0xB5,
1686 0x49,0x17,0xE1,0xC2,0x11,0x2D,0x84,0xD1,0x64,0xF4,
1687 0x44,0xF8,0xF7,0x47,0x86,0x04,0x6A,
1688 0x00,0x10,0x85,0xE2,0x75,0x53,0x81,0xDC,0xCC,0xE3, /* x */
1689 0xC1,0x55,0x7A,0xFA,0x10,0xC2,0xF0,0xC0,0xC2,0x82,
1690 0x56,0x46,0xC5,0xB3,0x4A,0x39,0x4C,0xBC,0xFA,0x8B,
1691 0xC1,0x6B,0x22,0xE7,0xE7,0x89,0xE9,0x27,0xBE,0x21,
1692 0x6F,0x02,0xE1,0xFB,0x13,0x6A,0x5F,
1693 0x00,0x7B,0x3E,0xB1,0xBD,0xDC,0xBA,0x62,0xD5,0xD8, /* y */
1694 0xB2,0x05,0x9B,0x52,0x57,0x97,0xFC,0x73,0x82,0x2C,
1695 0x59,0x05,0x9C,0x62,0x3A,0x45,0xFF,0x38,0x43,0xCE,
1696 0xE8,0xF8,0x7C,0xD1,0x85,0x5A,0xDA,0xA8,0x1E,0x2A,
1697 0x07,0x50,0xB8,0x0F,0xDA,0x23,0x10,
1698 0x00,0x00,0x01,0x00,0x90,0x51,0x2D,0xA9,0xAF,0x72, /* order */
1699 0xB0,0x83,0x49,0xD9,0x8A,0x5D,0xD4,0xC7,0xB0,0x53,
1700 0x2E,0xCA,0x51,0xCE,0x03,0xE2,0xD1,0x0F,0x3B,0x7A,
1701 0xC5,0x79,0xBD,0x87,0xE9,0x09,0xAE,0x40,0xA6,0xF1,
1702 0x31,0xE9,0xCF,0xCE,0x5B,0xD9,0x67 }
1703 };
1704
1705static const struct { EC_CURVE_DATA h; unsigned char data[0+54*6]; }
1706 _EC_X9_62_CHAR2_431R1 = {
1707 { NID_X9_62_characteristic_two_field,0,54,0x2760 },
1708 { /* no seed */
1709 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1710 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1711 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1712 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
1713 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1714 0x00,0x00,0x00,0x01,
1715 0x1A,0x82,0x7E,0xF0,0x0D,0xD6,0xFC,0x0E,0x23,0x4C, /* a */
1716 0xAF,0x04,0x6C,0x6A,0x5D,0x8A,0x85,0x39,0x5B,0x23,
1717 0x6C,0xC4,0xAD,0x2C,0xF3,0x2A,0x0C,0xAD,0xBD,0xC9,
1718 0xDD,0xF6,0x20,0xB0,0xEB,0x99,0x06,0xD0,0x95,0x7F,
1719 0x6C,0x6F,0xEA,0xCD,0x61,0x54,0x68,0xDF,0x10,0x4D,
1720 0xE2,0x96,0xCD,0x8F,
1721 0x10,0xD9,0xB4,0xA3,0xD9,0x04,0x7D,0x8B,0x15,0x43, /* b */
1722 0x59,0xAB,0xFB,0x1B,0x7F,0x54,0x85,0xB0,0x4C,0xEB,
1723 0x86,0x82,0x37,0xDD,0xC9,0xDE,0xDA,0x98,0x2A,0x67,
1724 0x9A,0x5A,0x91,0x9B,0x62,0x6D,0x4E,0x50,0xA8,0xDD,
1725 0x73,0x1B,0x10,0x7A,0x99,0x62,0x38,0x1F,0xB5,0xD8,
1726 0x07,0xBF,0x26,0x18,
1727 0x12,0x0F,0xC0,0x5D,0x3C,0x67,0xA9,0x9D,0xE1,0x61, /* x */
1728 0xD2,0xF4,0x09,0x26,0x22,0xFE,0xCA,0x70,0x1B,0xE4,
1729 0xF5,0x0F,0x47,0x58,0x71,0x4E,0x8A,0x87,0xBB,0xF2,
1730 0xA6,0x58,0xEF,0x8C,0x21,0xE7,0xC5,0xEF,0xE9,0x65,
1731 0x36,0x1F,0x6C,0x29,0x99,0xC0,0xC2,0x47,0xB0,0xDB,
1732 0xD7,0x0C,0xE6,0xB7,
1733 0x20,0xD0,0xAF,0x89,0x03,0xA9,0x6F,0x8D,0x5F,0xA2, /* y */
1734 0xC2,0x55,0x74,0x5D,0x3C,0x45,0x1B,0x30,0x2C,0x93,
1735 0x46,0xD9,0xB7,0xE4,0x85,0xE7,0xBC,0xE4,0x1F,0x6B,
1736 0x59,0x1F,0x3E,0x8F,0x6A,0xDD,0xCB,0xB0,0xBC,0x4C,
1737 0x2F,0x94,0x7A,0x7D,0xE1,0xA8,0x9B,0x62,0x5D,0x6A,
1738 0x59,0x8B,0x37,0x60,
1739 0x00,0x03,0x40,0x34,0x03,0x40,0x34,0x03,0x40,0x34, /* order */
1740 0x03,0x40,0x34,0x03,0x40,0x34,0x03,0x40,0x34,0x03,
1741 0x40,0x34,0x03,0x40,0x34,0x03,0x40,0x34,0x03,0x23,
1742 0xC3,0x13,0xFA,0xB5,0x05,0x89,0x70,0x3B,0x5E,0xC6,
1743 0x8D,0x35,0x87,0xFE,0xC6,0x0D,0x16,0x1C,0xC1,0x49,
1744 0xC1,0xAD,0x4A,0x91 }
1745 };
1746
1747static const struct { EC_CURVE_DATA h; unsigned char data[0+15*6]; }
1748 _EC_WTLS_1 = {
1749 { NID_X9_62_characteristic_two_field,0,15,2 },
1750 { /* no seed */
1751 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1752 0x00,0x00,0x00,0x02,0x01,
1753 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
1754 0x00,0x00,0x00,0x00,0x01,
1755 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
1756 0x00,0x00,0x00,0x00,0x01,
1757 0x01,0x66,0x79,0x79,0xA4,0x0B,0xA4,0x97,0xE5,0xD5, /* x */
1758 0xC2,0x70,0x78,0x06,0x17,
1759 0x00,0xF4,0x4B,0x4A,0xF1,0xEC,0xC2,0x63,0x0E,0x08, /* y */
1760 0x78,0x5C,0xEB,0xCC,0x15,
1761 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xBF, /* order */
1762 0x91,0xAF,0x6D,0xEA,0x73 }
1763 };
1764
1765/* IPSec curves */
1766/* NOTE: The of curves over a extension field of non prime degree
1767 * is not recommended (Weil-descent).
1768 * As the group order is not a prime this curve is not suitable
1769 * for ECDSA.
1770 */
1771static const struct { EC_CURVE_DATA h; unsigned char data[0+20*6]; }
1772 _EC_IPSEC_155_ID3 = {
1773 { NID_X9_62_characteristic_two_field,0,20,3 },
1774 { /* no seed */
1775 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1776 0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
1777
1778 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
1779 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1780
1781 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
1782 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x33,0x8f,
1783
1784 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x */
1785 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7b,
1786
1787 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y */
1788 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xc8,
1789
1790 0x02,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, /* order */
1791 0xC7,0xF3,0xC7,0x88,0x1B,0xD0,0x86,0x8F,0xA8,0x6C }
1792 };
1793
1794/* NOTE: The of curves over a extension field of non prime degree
1795 * is not recommended (Weil-descent).
1796 * As the group order is not a prime this curve is not suitable
1797 * for ECDSA.
1798 */
1799static const struct { EC_CURVE_DATA h; unsigned char data[0+24*6]; }
1800 _EC_IPSEC_185_ID4 = {
1801 { NID_X9_62_characteristic_two_field,0,24,2 },
1802 { /* no seed */
1803 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1804 0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,
1805 0x00,0x00,0x00,0x01,
1806 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a */
1807 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1808 0x00,0x00,0x00,0x00,
1809 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b */
1810 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1811 0x00,0x00,0x1e,0xe9,
1812 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* x */
1813 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1814 0x00,0x00,0x00,0x18,
1815 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* y */
1816 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1817 0x00,0x00,0x00,0x0d,
1818 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* order */
1819 0xFF,0xFF,0xED,0xF9,0x7C,0x44,0xDB,0x9F,0x24,0x20,
1820 0xBA,0xFC,0xA7,0x5E }
1821 };
1822
1823#endif
1824
1825typedef struct _ec_list_element_st {
1826 int nid;
1827 const EC_CURVE_DATA *data;
1828 const EC_METHOD *(*meth)(void);
1829 const char *comment;
1830 } ec_list_element;
1831
1832static const ec_list_element curve_list[] = {
1833 /* prime field curves */
1834 /* secg curves */
1835 { NID_secp112r1, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field" },
1836 { NID_secp112r2, &_EC_SECG_PRIME_112R2.h, 0, "SECG curve over a 112 bit prime field" },
1837 { NID_secp128r1, &_EC_SECG_PRIME_128R1.h, 0, "SECG curve over a 128 bit prime field" },
1838 { NID_secp128r2, &_EC_SECG_PRIME_128R2.h, 0, "SECG curve over a 128 bit prime field" },
1839 { NID_secp160k1, &_EC_SECG_PRIME_160K1.h, 0, "SECG curve over a 160 bit prime field" },
1840 { NID_secp160r1, &_EC_SECG_PRIME_160R1.h, 0, "SECG curve over a 160 bit prime field" },
1841 { NID_secp160r2, &_EC_SECG_PRIME_160R2.h, 0, "SECG/WTLS curve over a 160 bit prime field" },
1842 /* SECG secp192r1 is the same as X9.62 prime192v1 and hence omitted */
1843 { NID_secp192k1, &_EC_SECG_PRIME_192K1.h, 0, "SECG curve over a 192 bit prime field" },
1844 { NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0, "SECG curve over a 224 bit prime field" },
1845#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1846 { NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, "NIST/SECG curve over a 224 bit prime field" },
1847#else
1848 { NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, "NIST/SECG curve over a 224 bit prime field" },
1849#endif
1850 { NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0, "SECG curve over a 256 bit prime field" },
1851 /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
1852 { NID_secp384r1, &_EC_NIST_PRIME_384.h, 0, "NIST/SECG curve over a 384 bit prime field" },
1853#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1854 { NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method, "NIST/SECG curve over a 521 bit prime field" },
1855#else
1856 { NID_secp521r1, &_EC_NIST_PRIME_521.h, 0, "NIST/SECG curve over a 521 bit prime field" },
1857#endif
1858 /* X9.62 curves */
1859 { NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, "NIST/X9.62/SECG curve over a 192 bit prime field" },
1860 { NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0, "X9.62 curve over a 192 bit prime field" },
1861 { NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, 0, "X9.62 curve over a 192 bit prime field" },
1862 { NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, 0, "X9.62 curve over a 239 bit prime field" },
1863 { NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0, "X9.62 curve over a 239 bit prime field" },
1864 { NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0, "X9.62 curve over a 239 bit prime field" },
1865#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1866 { NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, EC_GFp_nistp256_method, "X9.62/SECG curve over a 256 bit prime field" },
1867#else
1868 { NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, 0, "X9.62/SECG curve over a 256 bit prime field" },
1869#endif
1870#ifndef OPENSSL_NO_EC2M
1871 /* characteristic two field curves */
1872 /* NIST/SECG curves */
1873 { NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field" },
1874 { NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, 0, "SECG curve over a 113 bit binary field" },
1875 { NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, 0, "SECG/WTLS curve over a 131 bit binary field" },
1876 { NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, 0, "SECG curve over a 131 bit binary field" },
1877 { NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field" },
1878 { NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, 0, "SECG curve over a 163 bit binary field" },
1879 { NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0, "NIST/SECG curve over a 163 bit binary field" },
1880 { NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, 0, "SECG curve over a 193 bit binary field" },
1881 { NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, 0, "SECG curve over a 193 bit binary field" },
1882 { NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
1883 { NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
1884 { NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, 0, "SECG curve over a 239 bit binary field" },
1885 { NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0, "NIST/SECG curve over a 283 bit binary field" },
1886 { NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0, "NIST/SECG curve over a 283 bit binary field" },
1887 { NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0, "NIST/SECG curve over a 409 bit binary field" },
1888 { NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0, "NIST/SECG curve over a 409 bit binary field" },
1889 { NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0, "NIST/SECG curve over a 571 bit binary field" },
1890 { NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0, "NIST/SECG curve over a 571 bit binary field" },
1891 /* X9.62 curves */
1892 { NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field" },
1893 { NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, 0, "X9.62 curve over a 163 bit binary field" },
1894 { NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, 0, "X9.62 curve over a 163 bit binary field" },
1895 { NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, 0, "X9.62 curve over a 176 bit binary field" },
1896 { NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, 0, "X9.62 curve over a 191 bit binary field" },
1897 { NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, 0, "X9.62 curve over a 191 bit binary field" },
1898 { NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, 0, "X9.62 curve over a 191 bit binary field" },
1899 { NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, 0, "X9.62 curve over a 208 bit binary field" },
1900 { NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, 0, "X9.62 curve over a 239 bit binary field" },
1901 { NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, 0, "X9.62 curve over a 239 bit binary field" },
1902 { NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, 0, "X9.62 curve over a 239 bit binary field" },
1903 { NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, 0, "X9.62 curve over a 272 bit binary field" },
1904 { NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, 0, "X9.62 curve over a 304 bit binary field" },
1905 { NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, 0, "X9.62 curve over a 359 bit binary field" },
1906 { NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, 0, "X9.62 curve over a 368 bit binary field" },
1907 { NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, 0, "X9.62 curve over a 431 bit binary field" },
1908 /* the WAP/WTLS curves
1909 * [unlike SECG, spec has its own OIDs for curves from X9.62] */
1910 { NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, 0, "WTLS curve over a 113 bit binary field" },
1911 { NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field" },
1912 { NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field" },
1913 { NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field" },
1914#endif
1915 { NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field" },
1916 { NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0, "SECG/WTLS curve over a 160 bit prime field" },
1917 { NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0, "WTLS curve over a 112 bit prime field" },
1918 { NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0, "WTLS curve over a 160 bit prime field" },
1919#ifndef OPENSSL_NO_EC2M
1920 { NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
1921 { NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
1922#endif
1923 { NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0, "WTLS curvs over a 224 bit prime field" },
1924#ifndef OPENSSL_NO_EC2M
1925 /* IPSec curves */
1926 { NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0, "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n"
1927 "\tNot suitable for ECDSA.\n\tQuestionable extension field!" },
1928 { NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0, "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n"
1929 "\tNot suitable for ECDSA.\n\tQuestionable extension field!" },
1930#endif
1931};
1932
1933#define curve_list_length (sizeof(curve_list)/sizeof(ec_list_element))
1934
1935static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
1936 {
1937 EC_GROUP *group=NULL;
1938 EC_POINT *P=NULL;
1939 BN_CTX *ctx=NULL;
1940 BIGNUM *p=NULL, *a=NULL, *b=NULL, *x=NULL, *y=NULL, *order=NULL;
1941 int ok=0;
1942 int seed_len,param_len;
1943 const EC_METHOD *meth;
1944 const EC_CURVE_DATA *data;
1945 const unsigned char *params;
1946
1947 if ((ctx = BN_CTX_new()) == NULL)
1948 {
1949 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE);
1950 goto err;
1951 }
1952
1953 data = curve.data;
1954 seed_len = data->seed_len;
1955 param_len = data->param_len;
1956 params = (const unsigned char *)(data+1); /* skip header */
1957 params += seed_len; /* skip seed */
1958
1959 if (!(p = BN_bin2bn(params+0*param_len, param_len, NULL))
1960 || !(a = BN_bin2bn(params+1*param_len, param_len, NULL))
1961 || !(b = BN_bin2bn(params+2*param_len, param_len, NULL)))
1962 {
1963 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
1964 goto err;
1965 }
1966
1967 if (curve.meth != 0)
1968 {
1969 meth = curve.meth();
1970 if (((group = EC_GROUP_new(meth)) == NULL) ||
1971 (!(group->meth->group_set_curve(group, p, a, b, ctx))))
1972 {
1973 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
1974 goto err;
1975 }
1976 }
1977 else if (data->field_type == NID_X9_62_prime_field)
1978 {
1979 if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL)
1980 {
1981 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
1982 goto err;
1983 }
1984 }
1985#ifndef OPENSSL_NO_EC2M
1986 else /* field_type == NID_X9_62_characteristic_two_field */
1987 {
1988 if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL)
1989 {
1990 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
1991 goto err;
1992 }
1993 }
1994#endif
1995
1996 if ((P = EC_POINT_new(group)) == NULL)
1997 {
1998 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
1999 goto err;
2000 }
2001
2002 if (!(x = BN_bin2bn(params+3*param_len, param_len, NULL))
2003 || !(y = BN_bin2bn(params+4*param_len, param_len, NULL)))
2004 {
2005 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
2006 goto err;
2007 }
2008 if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx))
2009 {
2010 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
2011 goto err;
2012 }
2013 if (!(order = BN_bin2bn(params+5*param_len, param_len, NULL))
2014 || !BN_set_word(x, (BN_ULONG)data->cofactor))
2015 {
2016 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
2017 goto err;
2018 }
2019 if (!EC_GROUP_set_generator(group, P, order, x))
2020 {
2021 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
2022 goto err;
2023 }
2024 if (seed_len)
2025 {
2026 if (!EC_GROUP_set_seed(group, params-seed_len, seed_len))
2027 {
2028 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
2029 goto err;
2030 }
2031 }
2032 ok=1;
2033err:
2034 if (!ok)
2035 {
2036 EC_GROUP_free(group);
2037 group = NULL;
2038 }
2039 if (P)
2040 EC_POINT_free(P);
2041 if (ctx)
2042 BN_CTX_free(ctx);
2043 if (p)
2044 BN_free(p);
2045 if (a)
2046 BN_free(a);
2047 if (b)
2048 BN_free(b);
2049 if (order)
2050 BN_free(order);
2051 if (x)
2052 BN_free(x);
2053 if (y)
2054 BN_free(y);
2055 return group;
2056 }
2057
2058EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
2059 {
2060 size_t i;
2061 EC_GROUP *ret = NULL;
2062
2063 if (nid <= 0)
2064 return NULL;
2065
2066 for (i=0; i<curve_list_length; i++)
2067 if (curve_list[i].nid == nid)
2068 {
2069 ret = ec_group_new_from_data(curve_list[i]);
2070 break;
2071 }
2072
2073 if (ret == NULL)
2074 {
2075 ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP);
2076 return NULL;
2077 }
2078
2079 EC_GROUP_set_curve_name(ret, nid);
2080
2081 return ret;
2082 }
2083
2084size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems)
2085 {
2086 size_t i, min;
2087
2088 if (r == NULL || nitems == 0)
2089 return curve_list_length;
2090
2091 min = nitems < curve_list_length ? nitems : curve_list_length;
2092
2093 for (i = 0; i < min; i++)
2094 {
2095 r[i].nid = curve_list[i].nid;
2096 r[i].comment = curve_list[i].comment;
2097 }
2098
2099 return curve_list_length;
2100 }
diff --git a/src/lib/libcrypto/ec/ecp_recp.c b/src/lib/libcrypto/ec/ec_cvt.c
index fec843b5c8..d45640bab9 100644
--- a/src/lib/libcrypto/ec/ecp_recp.c
+++ b/src/lib/libcrypto/ec/ec_cvt.c
@@ -1,6 +1,9 @@
1/* crypto/ec/ecp_recp.c */ 1/* crypto/ec/ec_cvt.c */
2/*
3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */
2/* ==================================================================== 5/* ====================================================================
3 * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 6 * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
4 * 7 *
5 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
@@ -52,82 +55,90 @@
52 * Hudson (tjh@cryptsoft.com). 55 * Hudson (tjh@cryptsoft.com).
53 * 56 *
54 */ 57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 *
61 * Portions of the attached software ("Contribution") are developed by
62 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
63 *
64 * The Contribution is licensed pursuant to the OpenSSL open source
65 * license provided above.
66 *
67 * The elliptic curve binary polynomial software is originally written by
68 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
69 *
70 */
55 71
72#include <openssl/err.h>
56#include "ec_lcl.h" 73#include "ec_lcl.h"
57 74
58#if 0
59const EC_METHOD *EC_GFp_recp_method(void)
60 {
61 static const EC_METHOD ret = {
62 ec_GFp_recp_group_init,
63 ec_GFp_recp_group_finish,
64 ec_GFp_recp_group_clear_finish,
65 ec_GFp_recp_group_copy,
66 ec_GFp_recp_group_set_curve_GFp,
67 ec_GFp_simple_group_get_curve_GFp,
68 ec_GFp_simple_group_set_generator,
69 ec_GFp_simple_group_get0_generator,
70 ec_GFp_simple_group_get_order,
71 ec_GFp_simple_group_get_cofactor,
72 ec_GFp_simple_point_init,
73 ec_GFp_simple_point_finish,
74 ec_GFp_simple_point_clear_finish,
75 ec_GFp_simple_point_copy,
76 ec_GFp_simple_point_set_to_infinity,
77 ec_GFp_simple_set_Jprojective_coordinates_GFp,
78 ec_GFp_simple_get_Jprojective_coordinates_GFp,
79 ec_GFp_simple_point_set_affine_coordinates_GFp,
80 ec_GFp_simple_point_get_affine_coordinates_GFp,
81 ec_GFp_simple_set_compressed_coordinates_GFp,
82 ec_GFp_simple_point2oct,
83 ec_GFp_simple_oct2point,
84 ec_GFp_simple_add,
85 ec_GFp_simple_dbl,
86 ec_GFp_simple_invert,
87 ec_GFp_simple_is_at_infinity,
88 ec_GFp_simple_is_on_curve,
89 ec_GFp_simple_cmp,
90 ec_GFp_simple_make_affine,
91 ec_GFp_simple_points_make_affine,
92 ec_GFp_recp_field_mul,
93 ec_GFp_recp_field_sqr,
94 0 /* field_encode */,
95 0 /* field_decode */,
96 0 /* field_set_to_one */ };
97
98 return &ret;
99 }
100#endif
101 75
102int ec_GFp_recp_group_init(EC_GROUP *group) 76EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
103 { 77 {
104 int ok; 78 const EC_METHOD *meth;
105 79 EC_GROUP *ret;
106 ok = ec_GFp_simple_group_init(group); 80
107 group->field_data1 = NULL; 81 meth = EC_GFp_nist_method();
108 return ok; 82
83 ret = EC_GROUP_new(meth);
84 if (ret == NULL)
85 return NULL;
86
87 if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx))
88 {
89 unsigned long err;
90
91 err = ERR_peek_last_error();
92
93 if (!(ERR_GET_LIB(err) == ERR_LIB_EC &&
94 ((ERR_GET_REASON(err) == EC_R_NOT_A_NIST_PRIME) ||
95 (ERR_GET_REASON(err) == EC_R_NOT_A_SUPPORTED_NIST_PRIME))))
96 {
97 /* real error */
98
99 EC_GROUP_clear_free(ret);
100 return NULL;
101 }
102
103
104 /* not an actual error, we just cannot use EC_GFp_nist_method */
105
106 ERR_clear_error();
107
108 EC_GROUP_clear_free(ret);
109 meth = EC_GFp_mont_method();
110
111 ret = EC_GROUP_new(meth);
112 if (ret == NULL)
113 return NULL;
114
115 if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx))
116 {
117 EC_GROUP_clear_free(ret);
118 return NULL;
119 }
120 }
121
122 return ret;
109 } 123 }
110 124
111 125
112int ec_GFp_recp_group_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); 126EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
113/* TODO */ 127 {
114 128 const EC_METHOD *meth;
115 129 EC_GROUP *ret;
116void ec_GFp_recp_group_finish(EC_GROUP *group); 130
117/* TODO */ 131 meth = EC_GF2m_simple_method();
118 132
119 133 ret = EC_GROUP_new(meth);
120void ec_GFp_recp_group_clear_finish(EC_GROUP *group); 134 if (ret == NULL)
121/* TODO */ 135 return NULL;
122 136
123 137 if (!EC_GROUP_set_curve_GF2m(ret, p, a, b, ctx))
124int ec_GFp_recp_group_copy(EC_GROUP *dest, const EC_GROUP *src); 138 {
125/* TODO */ 139 EC_GROUP_clear_free(ret);
126 140 return NULL;
127 141 }
128int ec_GFp_recp_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); 142
129/* TODO */ 143 return ret;
130 144 }
131
132int ec_GFp_recp_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx);
133/* TODO */
diff --git a/src/lib/libcrypto/ec/ec_err.c b/src/lib/libcrypto/ec/ec_err.c
new file mode 100644
index 0000000000..84b4833371
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_err.c
@@ -0,0 +1,258 @@
1/* crypto/ec/ec_err.c */
2/* ====================================================================
3 * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * 3. All advertising materials mentioning features or use of this
18 * software must display the following acknowledgment:
19 * "This product includes software developed by the OpenSSL Project
20 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21 *
22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23 * endorse or promote products derived from this software without
24 * prior written permission. For written permission, please contact
25 * openssl-core@OpenSSL.org.
26 *
27 * 5. Products derived from this software may not be called "OpenSSL"
28 * nor may "OpenSSL" appear in their names without prior written
29 * permission of the OpenSSL Project.
30 *
31 * 6. Redistributions of any form whatsoever must retain the following
32 * acknowledgment:
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 * OF THE POSSIBILITY OF SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This product includes cryptographic software written by Eric Young
51 * (eay@cryptsoft.com). This product includes software written by Tim
52 * Hudson (tjh@cryptsoft.com).
53 *
54 */
55
56/* NOTE: this file was auto generated by the mkerr.pl script: any changes
57 * made to it will be overwritten when the script next updates this file,
58 * only reason strings will be preserved.
59 */
60
61#include <stdio.h>
62#include <openssl/err.h>
63#include <openssl/ec.h>
64
65/* BEGIN ERROR CODES */
66#ifndef OPENSSL_NO_ERR
67
68#define ERR_FUNC(func) ERR_PACK(ERR_LIB_EC,func,0)
69#define ERR_REASON(reason) ERR_PACK(ERR_LIB_EC,0,reason)
70
71static ERR_STRING_DATA EC_str_functs[]=
72 {
73{ERR_FUNC(EC_F_COMPUTE_WNAF), "COMPUTE_WNAF"},
74{ERR_FUNC(EC_F_D2I_ECPARAMETERS), "d2i_ECParameters"},
75{ERR_FUNC(EC_F_D2I_ECPKPARAMETERS), "d2i_ECPKParameters"},
76{ERR_FUNC(EC_F_D2I_ECPRIVATEKEY), "d2i_ECPrivateKey"},
77{ERR_FUNC(EC_F_DO_EC_KEY_PRINT), "DO_EC_KEY_PRINT"},
78{ERR_FUNC(EC_F_ECKEY_PARAM2TYPE), "ECKEY_PARAM2TYPE"},
79{ERR_FUNC(EC_F_ECKEY_PARAM_DECODE), "ECKEY_PARAM_DECODE"},
80{ERR_FUNC(EC_F_ECKEY_PRIV_DECODE), "ECKEY_PRIV_DECODE"},
81{ERR_FUNC(EC_F_ECKEY_PRIV_ENCODE), "ECKEY_PRIV_ENCODE"},
82{ERR_FUNC(EC_F_ECKEY_PUB_DECODE), "ECKEY_PUB_DECODE"},
83{ERR_FUNC(EC_F_ECKEY_PUB_ENCODE), "ECKEY_PUB_ENCODE"},
84{ERR_FUNC(EC_F_ECKEY_TYPE2PARAM), "ECKEY_TYPE2PARAM"},
85{ERR_FUNC(EC_F_ECPARAMETERS_PRINT), "ECParameters_print"},
86{ERR_FUNC(EC_F_ECPARAMETERS_PRINT_FP), "ECParameters_print_fp"},
87{ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT), "ECPKParameters_print"},
88{ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT_FP), "ECPKParameters_print_fp"},
89{ERR_FUNC(EC_F_ECP_NIST_MOD_192), "ECP_NIST_MOD_192"},
90{ERR_FUNC(EC_F_ECP_NIST_MOD_224), "ECP_NIST_MOD_224"},
91{ERR_FUNC(EC_F_ECP_NIST_MOD_256), "ECP_NIST_MOD_256"},
92{ERR_FUNC(EC_F_ECP_NIST_MOD_521), "ECP_NIST_MOD_521"},
93{ERR_FUNC(EC_F_EC_ASN1_GROUP2CURVE), "EC_ASN1_GROUP2CURVE"},
94{ERR_FUNC(EC_F_EC_ASN1_GROUP2FIELDID), "EC_ASN1_GROUP2FIELDID"},
95{ERR_FUNC(EC_F_EC_ASN1_GROUP2PARAMETERS), "EC_ASN1_GROUP2PARAMETERS"},
96{ERR_FUNC(EC_F_EC_ASN1_GROUP2PKPARAMETERS), "EC_ASN1_GROUP2PKPARAMETERS"},
97{ERR_FUNC(EC_F_EC_ASN1_PARAMETERS2GROUP), "EC_ASN1_PARAMETERS2GROUP"},
98{ERR_FUNC(EC_F_EC_ASN1_PKPARAMETERS2GROUP), "EC_ASN1_PKPARAMETERS2GROUP"},
99{ERR_FUNC(EC_F_EC_EX_DATA_SET_DATA), "EC_EX_DATA_set_data"},
100{ERR_FUNC(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY), "EC_GF2M_MONTGOMERY_POINT_MULTIPLY"},
101{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT), "ec_GF2m_simple_group_check_discriminant"},
102{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE), "ec_GF2m_simple_group_set_curve"},
103{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_OCT2POINT), "ec_GF2m_simple_oct2point"},
104{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT2OCT), "ec_GF2m_simple_point2oct"},
105{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES), "ec_GF2m_simple_point_get_affine_coordinates"},
106{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES), "ec_GF2m_simple_point_set_affine_coordinates"},
107{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES), "ec_GF2m_simple_set_compressed_coordinates"},
108{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_DECODE), "ec_GFp_mont_field_decode"},
109{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_ENCODE), "ec_GFp_mont_field_encode"},
110{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_MUL), "ec_GFp_mont_field_mul"},
111{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE), "ec_GFp_mont_field_set_to_one"},
112{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"},
113{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE), "ec_GFp_mont_group_set_curve"},
114{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP), "EC_GFP_MONT_GROUP_SET_CURVE_GFP"},
115{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL), "ec_GFp_nist_field_mul"},
116{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"},
117{ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE), "ec_GFp_nist_group_set_curve"},
118{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT), "ec_GFp_simple_group_check_discriminant"},
119{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE), "ec_GFp_simple_group_set_curve"},
120{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP), "EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP"},
121{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR), "EC_GFP_SIMPLE_GROUP_SET_GENERATOR"},
122{ERR_FUNC(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE), "ec_GFp_simple_make_affine"},
123{ERR_FUNC(EC_F_EC_GFP_SIMPLE_OCT2POINT), "ec_GFp_simple_oct2point"},
124{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT2OCT), "ec_GFp_simple_point2oct"},
125{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE), "ec_GFp_simple_points_make_affine"},
126{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES), "ec_GFp_simple_point_get_affine_coordinates"},
127{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP), "EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP"},
128{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES), "ec_GFp_simple_point_set_affine_coordinates"},
129{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP), "EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP"},
130{ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES), "ec_GFp_simple_set_compressed_coordinates"},
131{ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP), "EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP"},
132{ERR_FUNC(EC_F_EC_GROUP_CHECK), "EC_GROUP_check"},
133{ERR_FUNC(EC_F_EC_GROUP_CHECK_DISCRIMINANT), "EC_GROUP_check_discriminant"},
134{ERR_FUNC(EC_F_EC_GROUP_COPY), "EC_GROUP_copy"},
135{ERR_FUNC(EC_F_EC_GROUP_GET0_GENERATOR), "EC_GROUP_get0_generator"},
136{ERR_FUNC(EC_F_EC_GROUP_GET_COFACTOR), "EC_GROUP_get_cofactor"},
137{ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GF2M), "EC_GROUP_get_curve_GF2m"},
138{ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GFP), "EC_GROUP_get_curve_GFp"},
139{ERR_FUNC(EC_F_EC_GROUP_GET_DEGREE), "EC_GROUP_get_degree"},
140{ERR_FUNC(EC_F_EC_GROUP_GET_ORDER), "EC_GROUP_get_order"},
141{ERR_FUNC(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS), "EC_GROUP_get_pentanomial_basis"},
142{ERR_FUNC(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS), "EC_GROUP_get_trinomial_basis"},
143{ERR_FUNC(EC_F_EC_GROUP_NEW), "EC_GROUP_new"},
144{ERR_FUNC(EC_F_EC_GROUP_NEW_BY_CURVE_NAME), "EC_GROUP_new_by_curve_name"},
145{ERR_FUNC(EC_F_EC_GROUP_NEW_FROM_DATA), "EC_GROUP_NEW_FROM_DATA"},
146{ERR_FUNC(EC_F_EC_GROUP_PRECOMPUTE_MULT), "EC_GROUP_precompute_mult"},
147{ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GF2M), "EC_GROUP_set_curve_GF2m"},
148{ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GFP), "EC_GROUP_set_curve_GFp"},
149{ERR_FUNC(EC_F_EC_GROUP_SET_EXTRA_DATA), "EC_GROUP_SET_EXTRA_DATA"},
150{ERR_FUNC(EC_F_EC_GROUP_SET_GENERATOR), "EC_GROUP_set_generator"},
151{ERR_FUNC(EC_F_EC_KEY_CHECK_KEY), "EC_KEY_check_key"},
152{ERR_FUNC(EC_F_EC_KEY_COPY), "EC_KEY_copy"},
153{ERR_FUNC(EC_F_EC_KEY_GENERATE_KEY), "EC_KEY_generate_key"},
154{ERR_FUNC(EC_F_EC_KEY_NEW), "EC_KEY_new"},
155{ERR_FUNC(EC_F_EC_KEY_PRINT), "EC_KEY_print"},
156{ERR_FUNC(EC_F_EC_KEY_PRINT_FP), "EC_KEY_print_fp"},
157{ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"},
158{ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"},
159{ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"},
160{ERR_FUNC(EC_F_EC_POINT_COPY), "EC_POINT_copy"},
161{ERR_FUNC(EC_F_EC_POINT_DBL), "EC_POINT_dbl"},
162{ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M), "EC_POINT_get_affine_coordinates_GF2m"},
163{ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP), "EC_POINT_get_affine_coordinates_GFp"},
164{ERR_FUNC(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP), "EC_POINT_get_Jprojective_coordinates_GFp"},
165{ERR_FUNC(EC_F_EC_POINT_INVERT), "EC_POINT_invert"},
166{ERR_FUNC(EC_F_EC_POINT_IS_AT_INFINITY), "EC_POINT_is_at_infinity"},
167{ERR_FUNC(EC_F_EC_POINT_IS_ON_CURVE), "EC_POINT_is_on_curve"},
168{ERR_FUNC(EC_F_EC_POINT_MAKE_AFFINE), "EC_POINT_make_affine"},
169{ERR_FUNC(EC_F_EC_POINT_MUL), "EC_POINT_mul"},
170{ERR_FUNC(EC_F_EC_POINT_NEW), "EC_POINT_new"},
171{ERR_FUNC(EC_F_EC_POINT_OCT2POINT), "EC_POINT_oct2point"},
172{ERR_FUNC(EC_F_EC_POINT_POINT2OCT), "EC_POINT_point2oct"},
173{ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M), "EC_POINT_set_affine_coordinates_GF2m"},
174{ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP), "EC_POINT_set_affine_coordinates_GFp"},
175{ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M), "EC_POINT_set_compressed_coordinates_GF2m"},
176{ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP), "EC_POINT_set_compressed_coordinates_GFp"},
177{ERR_FUNC(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP), "EC_POINT_set_Jprojective_coordinates_GFp"},
178{ERR_FUNC(EC_F_EC_POINT_SET_TO_INFINITY), "EC_POINT_set_to_infinity"},
179{ERR_FUNC(EC_F_EC_PRE_COMP_DUP), "EC_PRE_COMP_DUP"},
180{ERR_FUNC(EC_F_EC_PRE_COMP_NEW), "EC_PRE_COMP_NEW"},
181{ERR_FUNC(EC_F_EC_WNAF_MUL), "ec_wNAF_mul"},
182{ERR_FUNC(EC_F_EC_WNAF_PRECOMPUTE_MULT), "ec_wNAF_precompute_mult"},
183{ERR_FUNC(EC_F_I2D_ECPARAMETERS), "i2d_ECParameters"},
184{ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"},
185{ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"},
186{ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"},
187{ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"},
188{ERR_FUNC(EC_F_OLD_EC_PRIV_DECODE), "OLD_EC_PRIV_DECODE"},
189{ERR_FUNC(EC_F_PKEY_EC_CTRL), "PKEY_EC_CTRL"},
190{ERR_FUNC(EC_F_PKEY_EC_CTRL_STR), "PKEY_EC_CTRL_STR"},
191{ERR_FUNC(EC_F_PKEY_EC_DERIVE), "PKEY_EC_DERIVE"},
192{ERR_FUNC(EC_F_PKEY_EC_KEYGEN), "PKEY_EC_KEYGEN"},
193{ERR_FUNC(EC_F_PKEY_EC_PARAMGEN), "PKEY_EC_PARAMGEN"},
194{ERR_FUNC(EC_F_PKEY_EC_SIGN), "PKEY_EC_SIGN"},
195{0,NULL}
196 };
197
198static ERR_STRING_DATA EC_str_reasons[]=
199 {
200{ERR_REASON(EC_R_ASN1_ERROR) ,"asn1 error"},
201{ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD) ,"asn1 unknown field"},
202{ERR_REASON(EC_R_BUFFER_TOO_SMALL) ,"buffer too small"},
203{ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE),"d2i ecpkparameters failure"},
204{ERR_REASON(EC_R_DECODE_ERROR) ,"decode error"},
205{ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO) ,"discriminant is zero"},
206{ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),"ec group new by name failure"},
207{ERR_REASON(EC_R_FIELD_TOO_LARGE) ,"field too large"},
208{ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE),"group2pkparameters failure"},
209{ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE),"i2d ecpkparameters failure"},
210{ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS) ,"incompatible objects"},
211{ERR_REASON(EC_R_INVALID_ARGUMENT) ,"invalid argument"},
212{ERR_REASON(EC_R_INVALID_COMPRESSED_POINT),"invalid compressed point"},
213{ERR_REASON(EC_R_INVALID_COMPRESSION_BIT),"invalid compression bit"},
214{ERR_REASON(EC_R_INVALID_CURVE) ,"invalid curve"},
215{ERR_REASON(EC_R_INVALID_DIGEST_TYPE) ,"invalid digest type"},
216{ERR_REASON(EC_R_INVALID_ENCODING) ,"invalid encoding"},
217{ERR_REASON(EC_R_INVALID_FIELD) ,"invalid field"},
218{ERR_REASON(EC_R_INVALID_FORM) ,"invalid form"},
219{ERR_REASON(EC_R_INVALID_GROUP_ORDER) ,"invalid group order"},
220{ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS),"invalid pentanomial basis"},
221{ERR_REASON(EC_R_INVALID_PRIVATE_KEY) ,"invalid private key"},
222{ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS),"invalid trinomial basis"},
223{ERR_REASON(EC_R_KEYS_NOT_SET) ,"keys not set"},
224{ERR_REASON(EC_R_MISSING_PARAMETERS) ,"missing parameters"},
225{ERR_REASON(EC_R_MISSING_PRIVATE_KEY) ,"missing private key"},
226{ERR_REASON(EC_R_NOT_A_NIST_PRIME) ,"not a NIST prime"},
227{ERR_REASON(EC_R_NOT_A_SUPPORTED_NIST_PRIME),"not a supported NIST prime"},
228{ERR_REASON(EC_R_NOT_IMPLEMENTED) ,"not implemented"},
229{ERR_REASON(EC_R_NOT_INITIALIZED) ,"not initialized"},
230{ERR_REASON(EC_R_NO_FIELD_MOD) ,"no field mod"},
231{ERR_REASON(EC_R_NO_PARAMETERS_SET) ,"no parameters set"},
232{ERR_REASON(EC_R_PASSED_NULL_PARAMETER) ,"passed null parameter"},
233{ERR_REASON(EC_R_PKPARAMETERS2GROUP_FAILURE),"pkparameters2group failure"},
234{ERR_REASON(EC_R_POINT_AT_INFINITY) ,"point at infinity"},
235{ERR_REASON(EC_R_POINT_IS_NOT_ON_CURVE) ,"point is not on curve"},
236{ERR_REASON(EC_R_SLOT_FULL) ,"slot full"},
237{ERR_REASON(EC_R_UNDEFINED_GENERATOR) ,"undefined generator"},
238{ERR_REASON(EC_R_UNDEFINED_ORDER) ,"undefined order"},
239{ERR_REASON(EC_R_UNKNOWN_GROUP) ,"unknown group"},
240{ERR_REASON(EC_R_UNKNOWN_ORDER) ,"unknown order"},
241{ERR_REASON(EC_R_UNSUPPORTED_FIELD) ,"unsupported field"},
242{ERR_REASON(EC_R_WRONG_ORDER) ,"wrong order"},
243{0,NULL}
244 };
245
246#endif
247
248void ERR_load_EC_strings(void)
249 {
250#ifndef OPENSSL_NO_ERR
251
252 if (ERR_func_error_string(EC_str_functs[0].error) == NULL)
253 {
254 ERR_load_strings(0,EC_str_functs);
255 ERR_load_strings(0,EC_str_reasons);
256 }
257#endif
258 }
diff --git a/src/lib/libcrypto/ec/ec_key.c b/src/lib/libcrypto/ec/ec_key.c
new file mode 100644
index 0000000000..bf9fd2dc2c
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_key.c
@@ -0,0 +1,563 @@
1/* crypto/ec/ec_key.c */
2/*
3 * Written by Nils Larsch for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Portions originally developed by SUN MICROSYSTEMS, INC., and
61 * contributed to the OpenSSL project.
62 */
63
64#include <string.h>
65#include "ec_lcl.h"
66#include <openssl/err.h>
67#ifdef OPENSSL_FIPS
68#include <openssl/fips.h>
69#endif
70
71EC_KEY *EC_KEY_new(void)
72 {
73 EC_KEY *ret;
74
75 ret=(EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY));
76 if (ret == NULL)
77 {
78 ECerr(EC_F_EC_KEY_NEW, ERR_R_MALLOC_FAILURE);
79 return(NULL);
80 }
81
82 ret->version = 1;
83 ret->flags = 0;
84 ret->group = NULL;
85 ret->pub_key = NULL;
86 ret->priv_key= NULL;
87 ret->enc_flag= 0;
88 ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
89 ret->references= 1;
90 ret->method_data = NULL;
91 return(ret);
92 }
93
94EC_KEY *EC_KEY_new_by_curve_name(int nid)
95 {
96 EC_KEY *ret = EC_KEY_new();
97 if (ret == NULL)
98 return NULL;
99 ret->group = EC_GROUP_new_by_curve_name(nid);
100 if (ret->group == NULL)
101 {
102 EC_KEY_free(ret);
103 return NULL;
104 }
105 return ret;
106 }
107
108void EC_KEY_free(EC_KEY *r)
109 {
110 int i;
111
112 if (r == NULL) return;
113
114 i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_EC);
115#ifdef REF_PRINT
116 REF_PRINT("EC_KEY",r);
117#endif
118 if (i > 0) return;
119#ifdef REF_CHECK
120 if (i < 0)
121 {
122 fprintf(stderr,"EC_KEY_free, bad reference count\n");
123 abort();
124 }
125#endif
126
127 if (r->group != NULL)
128 EC_GROUP_free(r->group);
129 if (r->pub_key != NULL)
130 EC_POINT_free(r->pub_key);
131 if (r->priv_key != NULL)
132 BN_clear_free(r->priv_key);
133
134 EC_EX_DATA_free_all_data(&r->method_data);
135
136 OPENSSL_cleanse((void *)r, sizeof(EC_KEY));
137
138 OPENSSL_free(r);
139 }
140
141EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
142 {
143 EC_EXTRA_DATA *d;
144
145 if (dest == NULL || src == NULL)
146 {
147 ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
148 return NULL;
149 }
150 /* copy the parameters */
151 if (src->group)
152 {
153 const EC_METHOD *meth = EC_GROUP_method_of(src->group);
154 /* clear the old group */
155 if (dest->group)
156 EC_GROUP_free(dest->group);
157 dest->group = EC_GROUP_new(meth);
158 if (dest->group == NULL)
159 return NULL;
160 if (!EC_GROUP_copy(dest->group, src->group))
161 return NULL;
162 }
163 /* copy the public key */
164 if (src->pub_key && src->group)
165 {
166 if (dest->pub_key)
167 EC_POINT_free(dest->pub_key);
168 dest->pub_key = EC_POINT_new(src->group);
169 if (dest->pub_key == NULL)
170 return NULL;
171 if (!EC_POINT_copy(dest->pub_key, src->pub_key))
172 return NULL;
173 }
174 /* copy the private key */
175 if (src->priv_key)
176 {
177 if (dest->priv_key == NULL)
178 {
179 dest->priv_key = BN_new();
180 if (dest->priv_key == NULL)
181 return NULL;
182 }
183 if (!BN_copy(dest->priv_key, src->priv_key))
184 return NULL;
185 }
186 /* copy method/extra data */
187 EC_EX_DATA_free_all_data(&dest->method_data);
188
189 for (d = src->method_data; d != NULL; d = d->next)
190 {
191 void *t = d->dup_func(d->data);
192
193 if (t == NULL)
194 return 0;
195 if (!EC_EX_DATA_set_data(&dest->method_data, t, d->dup_func, d->free_func, d->clear_free_func))
196 return 0;
197 }
198
199 /* copy the rest */
200 dest->enc_flag = src->enc_flag;
201 dest->conv_form = src->conv_form;
202 dest->version = src->version;
203 dest->flags = src->flags;
204
205 return dest;
206 }
207
208EC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
209 {
210 EC_KEY *ret = EC_KEY_new();
211 if (ret == NULL)
212 return NULL;
213 if (EC_KEY_copy(ret, ec_key) == NULL)
214 {
215 EC_KEY_free(ret);
216 return NULL;
217 }
218 return ret;
219 }
220
221int EC_KEY_up_ref(EC_KEY *r)
222 {
223 int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC);
224#ifdef REF_PRINT
225 REF_PRINT("EC_KEY",r);
226#endif
227#ifdef REF_CHECK
228 if (i < 2)
229 {
230 fprintf(stderr, "EC_KEY_up, bad reference count\n");
231 abort();
232 }
233#endif
234 return ((i > 1) ? 1 : 0);
235 }
236
237int EC_KEY_generate_key(EC_KEY *eckey)
238 {
239 int ok = 0;
240 BN_CTX *ctx = NULL;
241 BIGNUM *priv_key = NULL, *order = NULL;
242 EC_POINT *pub_key = NULL;
243
244#ifdef OPENSSL_FIPS
245 if (FIPS_mode())
246 return FIPS_ec_key_generate_key(eckey);
247#endif
248
249 if (!eckey || !eckey->group)
250 {
251 ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
252 return 0;
253 }
254
255 if ((order = BN_new()) == NULL) goto err;
256 if ((ctx = BN_CTX_new()) == NULL) goto err;
257
258 if (eckey->priv_key == NULL)
259 {
260 priv_key = BN_new();
261 if (priv_key == NULL)
262 goto err;
263 }
264 else
265 priv_key = eckey->priv_key;
266
267 if (!EC_GROUP_get_order(eckey->group, order, ctx))
268 goto err;
269
270 do
271 if (!BN_rand_range(priv_key, order))
272 goto err;
273 while (BN_is_zero(priv_key));
274
275 if (eckey->pub_key == NULL)
276 {
277 pub_key = EC_POINT_new(eckey->group);
278 if (pub_key == NULL)
279 goto err;
280 }
281 else
282 pub_key = eckey->pub_key;
283
284 if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx))
285 goto err;
286
287 eckey->priv_key = priv_key;
288 eckey->pub_key = pub_key;
289
290 ok=1;
291
292err:
293 if (order)
294 BN_free(order);
295 if (pub_key != NULL && eckey->pub_key == NULL)
296 EC_POINT_free(pub_key);
297 if (priv_key != NULL && eckey->priv_key == NULL)
298 BN_free(priv_key);
299 if (ctx != NULL)
300 BN_CTX_free(ctx);
301 return(ok);
302 }
303
304int EC_KEY_check_key(const EC_KEY *eckey)
305 {
306 int ok = 0;
307 BN_CTX *ctx = NULL;
308 const BIGNUM *order = NULL;
309 EC_POINT *point = NULL;
310
311 if (!eckey || !eckey->group || !eckey->pub_key)
312 {
313 ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
314 return 0;
315 }
316
317 if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key))
318 {
319 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY);
320 goto err;
321 }
322
323 if ((ctx = BN_CTX_new()) == NULL)
324 goto err;
325 if ((point = EC_POINT_new(eckey->group)) == NULL)
326 goto err;
327
328 /* testing whether the pub_key is on the elliptic curve */
329 if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx))
330 {
331 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
332 goto err;
333 }
334 /* testing whether pub_key * order is the point at infinity */
335 order = &eckey->group->order;
336 if (BN_is_zero(order))
337 {
338 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
339 goto err;
340 }
341 if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx))
342 {
343 ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
344 goto err;
345 }
346 if (!EC_POINT_is_at_infinity(eckey->group, point))
347 {
348 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
349 goto err;
350 }
351 /* in case the priv_key is present :
352 * check if generator * priv_key == pub_key
353 */
354 if (eckey->priv_key)
355 {
356 if (BN_cmp(eckey->priv_key, order) >= 0)
357 {
358 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
359 goto err;
360 }
361 if (!EC_POINT_mul(eckey->group, point, eckey->priv_key,
362 NULL, NULL, ctx))
363 {
364 ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
365 goto err;
366 }
367 if (EC_POINT_cmp(eckey->group, point, eckey->pub_key,
368 ctx) != 0)
369 {
370 ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
371 goto err;
372 }
373 }
374 ok = 1;
375err:
376 if (ctx != NULL)
377 BN_CTX_free(ctx);
378 if (point != NULL)
379 EC_POINT_free(point);
380 return(ok);
381 }
382
383int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y)
384 {
385 BN_CTX *ctx = NULL;
386 BIGNUM *tx, *ty;
387 EC_POINT *point = NULL;
388 int ok = 0, tmp_nid, is_char_two = 0;
389
390 if (!key || !key->group || !x || !y)
391 {
392 ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
393 ERR_R_PASSED_NULL_PARAMETER);
394 return 0;
395 }
396 ctx = BN_CTX_new();
397 if (!ctx)
398 goto err;
399
400 point = EC_POINT_new(key->group);
401
402 if (!point)
403 goto err;
404
405 tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));
406
407 if (tmp_nid == NID_X9_62_characteristic_two_field)
408 is_char_two = 1;
409
410 tx = BN_CTX_get(ctx);
411 ty = BN_CTX_get(ctx);
412#ifndef OPENSSL_NO_EC2M
413 if (is_char_two)
414 {
415 if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point,
416 x, y, ctx))
417 goto err;
418 if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point,
419 tx, ty, ctx))
420 goto err;
421 }
422 else
423#endif
424 {
425 if (!EC_POINT_set_affine_coordinates_GFp(key->group, point,
426 x, y, ctx))
427 goto err;
428 if (!EC_POINT_get_affine_coordinates_GFp(key->group, point,
429 tx, ty, ctx))
430 goto err;
431 }
432 /* Check if retrieved coordinates match originals: if not values
433 * are out of range.
434 */
435 if (BN_cmp(x, tx) || BN_cmp(y, ty))
436 {
437 ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
438 EC_R_COORDINATES_OUT_OF_RANGE);
439 goto err;
440 }
441
442 if (!EC_KEY_set_public_key(key, point))
443 goto err;
444
445 if (EC_KEY_check_key(key) == 0)
446 goto err;
447
448 ok = 1;
449
450 err:
451 if (ctx)
452 BN_CTX_free(ctx);
453 if (point)
454 EC_POINT_free(point);
455 return ok;
456
457 }
458
459const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
460 {
461 return key->group;
462 }
463
464int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
465 {
466 if (key->group != NULL)
467 EC_GROUP_free(key->group);
468 key->group = EC_GROUP_dup(group);
469 return (key->group == NULL) ? 0 : 1;
470 }
471
472const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key)
473 {
474 return key->priv_key;
475 }
476
477int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
478 {
479 if (key->priv_key)
480 BN_clear_free(key->priv_key);
481 key->priv_key = BN_dup(priv_key);
482 return (key->priv_key == NULL) ? 0 : 1;
483 }
484
485const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key)
486 {
487 return key->pub_key;
488 }
489
490int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
491 {
492 if (key->pub_key != NULL)
493 EC_POINT_free(key->pub_key);
494 key->pub_key = EC_POINT_dup(pub_key, key->group);
495 return (key->pub_key == NULL) ? 0 : 1;
496 }
497
498unsigned int EC_KEY_get_enc_flags(const EC_KEY *key)
499 {
500 return key->enc_flag;
501 }
502
503void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
504 {
505 key->enc_flag = flags;
506 }
507
508point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key)
509 {
510 return key->conv_form;
511 }
512
513void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
514 {
515 key->conv_form = cform;
516 if (key->group != NULL)
517 EC_GROUP_set_point_conversion_form(key->group, cform);
518 }
519
520void *EC_KEY_get_key_method_data(EC_KEY *key,
521 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
522 {
523 return EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
524 }
525
526void EC_KEY_insert_key_method_data(EC_KEY *key, void *data,
527 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
528 {
529 EC_EXTRA_DATA *ex_data;
530 CRYPTO_w_lock(CRYPTO_LOCK_EC);
531 ex_data = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
532 if (ex_data == NULL)
533 EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, clear_free_func);
534 CRYPTO_w_unlock(CRYPTO_LOCK_EC);
535 }
536
537void EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
538 {
539 if (key->group != NULL)
540 EC_GROUP_set_asn1_flag(key->group, flag);
541 }
542
543int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
544 {
545 if (key->group == NULL)
546 return 0;
547 return EC_GROUP_precompute_mult(key->group, ctx);
548 }
549
550int EC_KEY_get_flags(const EC_KEY *key)
551 {
552 return key->flags;
553 }
554
555void EC_KEY_set_flags(EC_KEY *key, int flags)
556 {
557 key->flags |= flags;
558 }
559
560void EC_KEY_clear_flags(EC_KEY *key, int flags)
561 {
562 key->flags &= ~flags;
563 }
diff --git a/src/lib/libcrypto/ec/ec_lcl.h b/src/lib/libcrypto/ec/ec_lcl.h
new file mode 100644
index 0000000000..3e2c34b0bc
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_lcl.h
@@ -0,0 +1,393 @@
1/* crypto/ec/ec_lcl.h */
2/*
3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 *
61 * Portions of the attached software ("Contribution") are developed by
62 * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
63 *
64 * The Contribution is licensed pursuant to the OpenSSL open source
65 * license provided above.
66 *
67 * The elliptic curve binary polynomial software is originally written by
68 * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
69 *
70 */
71
72
73#include <stdlib.h>
74
75#include <openssl/obj_mac.h>
76#include <openssl/ec.h>
77#include <openssl/bn.h>
78
79#if defined(__SUNPRO_C)
80# if __SUNPRO_C >= 0x520
81# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
82# endif
83#endif
84
85/* Structure details are not part of the exported interface,
86 * so all this may change in future versions. */
87
88struct ec_method_st {
89 /* used by EC_METHOD_get_field_type: */
90 int field_type; /* a NID */
91
92 /* used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, EC_GROUP_copy: */
93 int (*group_init)(EC_GROUP *);
94 void (*group_finish)(EC_GROUP *);
95 void (*group_clear_finish)(EC_GROUP *);
96 int (*group_copy)(EC_GROUP *, const EC_GROUP *);
97
98 /* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */
99 /* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */
100 int (*group_set_curve)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
101 int (*group_get_curve)(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
102
103 /* used by EC_GROUP_get_degree: */
104 int (*group_get_degree)(const EC_GROUP *);
105
106 /* used by EC_GROUP_check: */
107 int (*group_check_discriminant)(const EC_GROUP *, BN_CTX *);
108
109 /* used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_free, EC_POINT_copy: */
110 int (*point_init)(EC_POINT *);
111 void (*point_finish)(EC_POINT *);
112 void (*point_clear_finish)(EC_POINT *);
113 int (*point_copy)(EC_POINT *, const EC_POINT *);
114
115 /* used by EC_POINT_set_to_infinity,
116 * EC_POINT_set_Jprojective_coordinates_GFp,
117 * EC_POINT_get_Jprojective_coordinates_GFp,
118 * EC_POINT_set_affine_coordinates_GFp, ..._GF2m,
119 * EC_POINT_get_affine_coordinates_GFp, ..._GF2m,
120 * EC_POINT_set_compressed_coordinates_GFp, ..._GF2m:
121 */
122 int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *);
123 int (*point_set_Jprojective_coordinates_GFp)(const EC_GROUP *, EC_POINT *,
124 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
125 int (*point_get_Jprojective_coordinates_GFp)(const EC_GROUP *, const EC_POINT *,
126 BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *);
127 int (*point_set_affine_coordinates)(const EC_GROUP *, EC_POINT *,
128 const BIGNUM *x, const BIGNUM *y, BN_CTX *);
129 int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_POINT *,
130 BIGNUM *x, BIGNUM *y, BN_CTX *);
131 int (*point_set_compressed_coordinates)(const EC_GROUP *, EC_POINT *,
132 const BIGNUM *x, int y_bit, BN_CTX *);
133
134 /* used by EC_POINT_point2oct, EC_POINT_oct2point: */
135 size_t (*point2oct)(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
136 unsigned char *buf, size_t len, BN_CTX *);
137 int (*oct2point)(const EC_GROUP *, EC_POINT *,
138 const unsigned char *buf, size_t len, BN_CTX *);
139
140 /* used by EC_POINT_add, EC_POINT_dbl, ECP_POINT_invert: */
141 int (*add)(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
142 int (*dbl)(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
143 int (*invert)(const EC_GROUP *, EC_POINT *, BN_CTX *);
144
145 /* used by EC_POINT_is_at_infinity, EC_POINT_is_on_curve, EC_POINT_cmp: */
146 int (*is_at_infinity)(const EC_GROUP *, const EC_POINT *);
147 int (*is_on_curve)(const EC_GROUP *, const EC_POINT *, BN_CTX *);
148 int (*point_cmp)(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
149
150 /* used by EC_POINT_make_affine, EC_POINTs_make_affine: */
151 int (*make_affine)(const EC_GROUP *, EC_POINT *, BN_CTX *);
152 int (*points_make_affine)(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
153
154 /* used by EC_POINTs_mul, EC_POINT_mul, EC_POINT_precompute_mult, EC_POINT_have_precompute_mult
155 * (default implementations are used if the 'mul' pointer is 0): */
156 int (*mul)(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
157 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
158 int (*precompute_mult)(EC_GROUP *group, BN_CTX *);
159 int (*have_precompute_mult)(const EC_GROUP *group);
160
161
162 /* internal functions */
163
164 /* 'field_mul', 'field_sqr', and 'field_div' can be used by 'add' and 'dbl' so that
165 * the same implementations of point operations can be used with different
166 * optimized implementations of expensive field operations: */
167 int (*field_mul)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
168 int (*field_sqr)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
169 int (*field_div)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
170
171 int (*field_encode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. to Montgomery */
172 int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. from Montgomery */
173 int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *);
174} /* EC_METHOD */;
175
176typedef struct ec_extra_data_st {
177 struct ec_extra_data_st *next;
178 void *data;
179 void *(*dup_func)(void *);
180 void (*free_func)(void *);
181 void (*clear_free_func)(void *);
182} EC_EXTRA_DATA; /* used in EC_GROUP */
183
184struct ec_group_st {
185 const EC_METHOD *meth;
186
187 EC_POINT *generator; /* optional */
188 BIGNUM order, cofactor;
189
190 int curve_name;/* optional NID for named curve */
191 int asn1_flag; /* flag to control the asn1 encoding */
192 point_conversion_form_t asn1_form;
193
194 unsigned char *seed; /* optional seed for parameters (appears in ASN1) */
195 size_t seed_len;
196
197 EC_EXTRA_DATA *extra_data; /* linked list */
198
199 /* The following members are handled by the method functions,
200 * even if they appear generic */
201
202 BIGNUM field; /* Field specification.
203 * For curves over GF(p), this is the modulus;
204 * for curves over GF(2^m), this is the
205 * irreducible polynomial defining the field.
206 */
207
208 int poly[6]; /* Field specification for curves over GF(2^m).
209 * The irreducible f(t) is then of the form:
210 * t^poly[0] + t^poly[1] + ... + t^poly[k]
211 * where m = poly[0] > poly[1] > ... > poly[k] = 0.
212 * The array is terminated with poly[k+1]=-1.
213 * All elliptic curve irreducibles have at most 5
214 * non-zero terms.
215 */
216
217 BIGNUM a, b; /* Curve coefficients.
218 * (Here the assumption is that BIGNUMs can be used
219 * or abused for all kinds of fields, not just GF(p).)
220 * For characteristic > 3, the curve is defined
221 * by a Weierstrass equation of the form
222 * y^2 = x^3 + a*x + b.
223 * For characteristic 2, the curve is defined by
224 * an equation of the form
225 * y^2 + x*y = x^3 + a*x^2 + b.
226 */
227
228 int a_is_minus3; /* enable optimized point arithmetics for special case */
229
230 void *field_data1; /* method-specific (e.g., Montgomery structure) */
231 void *field_data2; /* method-specific */
232 int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); /* method-specific */
233} /* EC_GROUP */;
234
235struct ec_key_st {
236 int version;
237
238 EC_GROUP *group;
239
240 EC_POINT *pub_key;
241 BIGNUM *priv_key;
242
243 unsigned int enc_flag;
244 point_conversion_form_t conv_form;
245
246 int references;
247
248 EC_EXTRA_DATA *method_data;
249} /* EC_KEY */;
250
251/* Basically a 'mixin' for extra data, but available for EC_GROUPs/EC_KEYs only
252 * (with visibility limited to 'package' level for now).
253 * We use the function pointers as index for retrieval; this obviates
254 * global ex_data-style index tables.
255 */
256int EC_EX_DATA_set_data(EC_EXTRA_DATA **, void *data,
257 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
258void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *,
259 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
260void EC_EX_DATA_free_data(EC_EXTRA_DATA **,
261 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
262void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **,
263 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
264void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **);
265void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **);
266
267
268
269struct ec_point_st {
270 const EC_METHOD *meth;
271
272 /* All members except 'meth' are handled by the method functions,
273 * even if they appear generic */
274
275 BIGNUM X;
276 BIGNUM Y;
277 BIGNUM Z; /* Jacobian projective coordinates:
278 * (X, Y, Z) represents (X/Z^2, Y/Z^3) if Z != 0 */
279 int Z_is_one; /* enable optimized point arithmetics for special case */
280} /* EC_POINT */;
281
282
283
284/* method functions in ec_mult.c
285 * (ec_lib.c uses these as defaults if group->method->mul is 0) */
286int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
287 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
288int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *);
289int ec_wNAF_have_precompute_mult(const EC_GROUP *group);
290
291
292/* method functions in ecp_smpl.c */
293int ec_GFp_simple_group_init(EC_GROUP *);
294void ec_GFp_simple_group_finish(EC_GROUP *);
295void ec_GFp_simple_group_clear_finish(EC_GROUP *);
296int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);
297int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
298int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
299int ec_GFp_simple_group_get_degree(const EC_GROUP *);
300int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
301int ec_GFp_simple_point_init(EC_POINT *);
302void ec_GFp_simple_point_finish(EC_POINT *);
303void ec_GFp_simple_point_clear_finish(EC_POINT *);
304int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *);
305int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
306int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *,
307 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
308int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
309 BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *);
310int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
311 const BIGNUM *x, const BIGNUM *y, BN_CTX *);
312int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *, const EC_POINT *,
313 BIGNUM *x, BIGNUM *y, BN_CTX *);
314int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
315 const BIGNUM *x, int y_bit, BN_CTX *);
316size_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
317 unsigned char *buf, size_t len, BN_CTX *);
318int ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *,
319 const unsigned char *buf, size_t len, BN_CTX *);
320int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
321int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
322int ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
323int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);
324int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
325int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
326int ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
327int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
328int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
329int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
330
331
332/* method functions in ecp_mont.c */
333int ec_GFp_mont_group_init(EC_GROUP *);
334int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
335void ec_GFp_mont_group_finish(EC_GROUP *);
336void ec_GFp_mont_group_clear_finish(EC_GROUP *);
337int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);
338int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
339int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
340int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
341int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
342int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *);
343
344
345/* method functions in ecp_nist.c */
346int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src);
347int ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
348int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
349int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
350
351
352/* method functions in ec2_smpl.c */
353int ec_GF2m_simple_group_init(EC_GROUP *);
354void ec_GF2m_simple_group_finish(EC_GROUP *);
355void ec_GF2m_simple_group_clear_finish(EC_GROUP *);
356int ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *);
357int ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
358int ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
359int ec_GF2m_simple_group_get_degree(const EC_GROUP *);
360int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
361int ec_GF2m_simple_point_init(EC_POINT *);
362void ec_GF2m_simple_point_finish(EC_POINT *);
363void ec_GF2m_simple_point_clear_finish(EC_POINT *);
364int ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *);
365int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
366int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
367 const BIGNUM *x, const BIGNUM *y, BN_CTX *);
368int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *, const EC_POINT *,
369 BIGNUM *x, BIGNUM *y, BN_CTX *);
370int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
371 const BIGNUM *x, int y_bit, BN_CTX *);
372size_t ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
373 unsigned char *buf, size_t len, BN_CTX *);
374int ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *,
375 const unsigned char *buf, size_t len, BN_CTX *);
376int ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
377int ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
378int ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
379int ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);
380int ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
381int ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
382int ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
383int ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
384int ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
385int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
386int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
387
388
389/* method functions in ec2_mult.c */
390int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
391 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
392int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
393int ec_GF2m_have_precompute_mult(const EC_GROUP *group);
diff --git a/src/lib/libcrypto/ec/ec_lib.c b/src/lib/libcrypto/ec/ec_lib.c
new file mode 100644
index 0000000000..dd7da0fcf9
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_lib.c
@@ -0,0 +1,1164 @@
1/* crypto/ec/ec_lib.c */
2/*
3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Binary polynomial ECC support in OpenSSL originally developed by
61 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
62 */
63
64#include <string.h>
65
66#include <openssl/err.h>
67#include <openssl/opensslv.h>
68
69#include "ec_lcl.h"
70
71static const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
72
73
74/* functions for EC_GROUP objects */
75
76EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
77 {
78 EC_GROUP *ret;
79
80 if (meth == NULL)
81 {
82 ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
83 return NULL;
84 }
85 if (meth->group_init == 0)
86 {
87 ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
88 return NULL;
89 }
90
91 ret = OPENSSL_malloc(sizeof *ret);
92 if (ret == NULL)
93 {
94 ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
95 return NULL;
96 }
97
98 ret->meth = meth;
99
100 ret->extra_data = NULL;
101
102 ret->generator = NULL;
103 BN_init(&ret->order);
104 BN_init(&ret->cofactor);
105
106 ret->curve_name = 0;
107 ret->asn1_flag = 0;
108 ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
109
110 ret->seed = NULL;
111 ret->seed_len = 0;
112
113 if (!meth->group_init(ret))
114 {
115 OPENSSL_free(ret);
116 return NULL;
117 }
118
119 return ret;
120 }
121
122
123void EC_GROUP_free(EC_GROUP *group)
124 {
125 if (!group) return;
126
127 if (group->meth->group_finish != 0)
128 group->meth->group_finish(group);
129
130 EC_EX_DATA_free_all_data(&group->extra_data);
131
132 if (group->generator != NULL)
133 EC_POINT_free(group->generator);
134 BN_free(&group->order);
135 BN_free(&group->cofactor);
136
137 if (group->seed)
138 OPENSSL_free(group->seed);
139
140 OPENSSL_free(group);
141 }
142
143
144void EC_GROUP_clear_free(EC_GROUP *group)
145 {
146 if (!group) return;
147
148 if (group->meth->group_clear_finish != 0)
149 group->meth->group_clear_finish(group);
150 else if (group->meth->group_finish != 0)
151 group->meth->group_finish(group);
152
153 EC_EX_DATA_clear_free_all_data(&group->extra_data);
154
155 if (group->generator != NULL)
156 EC_POINT_clear_free(group->generator);
157 BN_clear_free(&group->order);
158 BN_clear_free(&group->cofactor);
159
160 if (group->seed)
161 {
162 OPENSSL_cleanse(group->seed, group->seed_len);
163 OPENSSL_free(group->seed);
164 }
165
166 OPENSSL_cleanse(group, sizeof *group);
167 OPENSSL_free(group);
168 }
169
170
171int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
172 {
173 EC_EXTRA_DATA *d;
174
175 if (dest->meth->group_copy == 0)
176 {
177 ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
178 return 0;
179 }
180 if (dest->meth != src->meth)
181 {
182 ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
183 return 0;
184 }
185 if (dest == src)
186 return 1;
187
188 EC_EX_DATA_free_all_data(&dest->extra_data);
189
190 for (d = src->extra_data; d != NULL; d = d->next)
191 {
192 void *t = d->dup_func(d->data);
193
194 if (t == NULL)
195 return 0;
196 if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func))
197 return 0;
198 }
199
200 if (src->generator != NULL)
201 {
202 if (dest->generator == NULL)
203 {
204 dest->generator = EC_POINT_new(dest);
205 if (dest->generator == NULL) return 0;
206 }
207 if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
208 }
209 else
210 {
211 /* src->generator == NULL */
212 if (dest->generator != NULL)
213 {
214 EC_POINT_clear_free(dest->generator);
215 dest->generator = NULL;
216 }
217 }
218
219 if (!BN_copy(&dest->order, &src->order)) return 0;
220 if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
221
222 dest->curve_name = src->curve_name;
223 dest->asn1_flag = src->asn1_flag;
224 dest->asn1_form = src->asn1_form;
225
226 if (src->seed)
227 {
228 if (dest->seed)
229 OPENSSL_free(dest->seed);
230 dest->seed = OPENSSL_malloc(src->seed_len);
231 if (dest->seed == NULL)
232 return 0;
233 if (!memcpy(dest->seed, src->seed, src->seed_len))
234 return 0;
235 dest->seed_len = src->seed_len;
236 }
237 else
238 {
239 if (dest->seed)
240 OPENSSL_free(dest->seed);
241 dest->seed = NULL;
242 dest->seed_len = 0;
243 }
244
245
246 return dest->meth->group_copy(dest, src);
247 }
248
249
250EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
251 {
252 EC_GROUP *t = NULL;
253 int ok = 0;
254
255 if (a == NULL) return NULL;
256
257 if ((t = EC_GROUP_new(a->meth)) == NULL) return(NULL);
258 if (!EC_GROUP_copy(t, a)) goto err;
259
260 ok = 1;
261
262 err:
263 if (!ok)
264 {
265 if (t) EC_GROUP_free(t);
266 return NULL;
267 }
268 else return t;
269 }
270
271
272const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
273 {
274 return group->meth;
275 }
276
277
278int EC_METHOD_get_field_type(const EC_METHOD *meth)
279 {
280 return meth->field_type;
281 }
282
283
284int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
285 {
286 if (generator == NULL)
287 {
288 ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
289 return 0 ;
290 }
291
292 if (group->generator == NULL)
293 {
294 group->generator = EC_POINT_new(group);
295 if (group->generator == NULL) return 0;
296 }
297 if (!EC_POINT_copy(group->generator, generator)) return 0;
298
299 if (order != NULL)
300 { if (!BN_copy(&group->order, order)) return 0; }
301 else
302 BN_zero(&group->order);
303
304 if (cofactor != NULL)
305 { if (!BN_copy(&group->cofactor, cofactor)) return 0; }
306 else
307 BN_zero(&group->cofactor);
308
309 return 1;
310 }
311
312
313const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
314 {
315 return group->generator;
316 }
317
318
319int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
320 {
321 if (!BN_copy(order, &group->order))
322 return 0;
323
324 return !BN_is_zero(order);
325 }
326
327
328int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
329 {
330 if (!BN_copy(cofactor, &group->cofactor))
331 return 0;
332
333 return !BN_is_zero(&group->cofactor);
334 }
335
336
337void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
338 {
339 group->curve_name = nid;
340 }
341
342
343int EC_GROUP_get_curve_name(const EC_GROUP *group)
344 {
345 return group->curve_name;
346 }
347
348
349void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
350 {
351 group->asn1_flag = flag;
352 }
353
354
355int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
356 {
357 return group->asn1_flag;
358 }
359
360
361void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
362 point_conversion_form_t form)
363 {
364 group->asn1_form = form;
365 }
366
367
368point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
369 {
370 return group->asn1_form;
371 }
372
373
374size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
375 {
376 if (group->seed)
377 {
378 OPENSSL_free(group->seed);
379 group->seed = NULL;
380 group->seed_len = 0;
381 }
382
383 if (!len || !p)
384 return 1;
385
386 if ((group->seed = OPENSSL_malloc(len)) == NULL)
387 return 0;
388 memcpy(group->seed, p, len);
389 group->seed_len = len;
390
391 return len;
392 }
393
394
395unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
396 {
397 return group->seed;
398 }
399
400
401size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
402 {
403 return group->seed_len;
404 }
405
406
407int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
408 {
409 if (group->meth->group_set_curve == 0)
410 {
411 ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
412 return 0;
413 }
414 return group->meth->group_set_curve(group, p, a, b, ctx);
415 }
416
417
418int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
419 {
420 if (group->meth->group_get_curve == 0)
421 {
422 ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
423 return 0;
424 }
425 return group->meth->group_get_curve(group, p, a, b, ctx);
426 }
427
428
429int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
430 {
431 if (group->meth->group_set_curve == 0)
432 {
433 ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
434 return 0;
435 }
436 return group->meth->group_set_curve(group, p, a, b, ctx);
437 }
438
439
440int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
441 {
442 if (group->meth->group_get_curve == 0)
443 {
444 ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
445 return 0;
446 }
447 return group->meth->group_get_curve(group, p, a, b, ctx);
448 }
449
450
451int EC_GROUP_get_degree(const EC_GROUP *group)
452 {
453 if (group->meth->group_get_degree == 0)
454 {
455 ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
456 return 0;
457 }
458 return group->meth->group_get_degree(group);
459 }
460
461
462int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
463 {
464 if (group->meth->group_check_discriminant == 0)
465 {
466 ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
467 return 0;
468 }
469 return group->meth->group_check_discriminant(group, ctx);
470 }
471
472
473int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
474 {
475 int r = 0;
476 BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
477 BN_CTX *ctx_new = NULL;
478
479 /* compare the field types*/
480 if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
481 EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
482 return 1;
483 /* compare the curve name (if present) */
484 if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
485 EC_GROUP_get_curve_name(a) == EC_GROUP_get_curve_name(b))
486 return 0;
487
488 if (!ctx)
489 ctx_new = ctx = BN_CTX_new();
490 if (!ctx)
491 return -1;
492
493 BN_CTX_start(ctx);
494 a1 = BN_CTX_get(ctx);
495 a2 = BN_CTX_get(ctx);
496 a3 = BN_CTX_get(ctx);
497 b1 = BN_CTX_get(ctx);
498 b2 = BN_CTX_get(ctx);
499 b3 = BN_CTX_get(ctx);
500 if (!b3)
501 {
502 BN_CTX_end(ctx);
503 if (ctx_new)
504 BN_CTX_free(ctx);
505 return -1;
506 }
507
508 /* XXX This approach assumes that the external representation
509 * of curves over the same field type is the same.
510 */
511 if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
512 !b->meth->group_get_curve(b, b1, b2, b3, ctx))
513 r = 1;
514
515 if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
516 r = 1;
517
518 /* XXX EC_POINT_cmp() assumes that the methods are equal */
519 if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
520 EC_GROUP_get0_generator(b), ctx))
521 r = 1;
522
523 if (!r)
524 {
525 /* compare the order and cofactor */
526 if (!EC_GROUP_get_order(a, a1, ctx) ||
527 !EC_GROUP_get_order(b, b1, ctx) ||
528 !EC_GROUP_get_cofactor(a, a2, ctx) ||
529 !EC_GROUP_get_cofactor(b, b2, ctx))
530 {
531 BN_CTX_end(ctx);
532 if (ctx_new)
533 BN_CTX_free(ctx);
534 return -1;
535 }
536 if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
537 r = 1;
538 }
539
540 BN_CTX_end(ctx);
541 if (ctx_new)
542 BN_CTX_free(ctx);
543
544 return r;
545 }
546
547
548/* this has 'package' visibility */
549int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
550 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
551 {
552 EC_EXTRA_DATA *d;
553
554 if (ex_data == NULL)
555 return 0;
556
557 for (d = *ex_data; d != NULL; d = d->next)
558 {
559 if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
560 {
561 ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
562 return 0;
563 }
564 }
565
566 if (data == NULL)
567 /* no explicit entry needed */
568 return 1;
569
570 d = OPENSSL_malloc(sizeof *d);
571 if (d == NULL)
572 return 0;
573
574 d->data = data;
575 d->dup_func = dup_func;
576 d->free_func = free_func;
577 d->clear_free_func = clear_free_func;
578
579 d->next = *ex_data;
580 *ex_data = d;
581
582 return 1;
583 }
584
585/* this has 'package' visibility */
586void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
587 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
588 {
589 const EC_EXTRA_DATA *d;
590
591 for (d = ex_data; d != NULL; d = d->next)
592 {
593 if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
594 return d->data;
595 }
596
597 return NULL;
598 }
599
600/* this has 'package' visibility */
601void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
602 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
603 {
604 EC_EXTRA_DATA **p;
605
606 if (ex_data == NULL)
607 return;
608
609 for (p = ex_data; *p != NULL; p = &((*p)->next))
610 {
611 if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
612 {
613 EC_EXTRA_DATA *next = (*p)->next;
614
615 (*p)->free_func((*p)->data);
616 OPENSSL_free(*p);
617
618 *p = next;
619 return;
620 }
621 }
622 }
623
624/* this has 'package' visibility */
625void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
626 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
627 {
628 EC_EXTRA_DATA **p;
629
630 if (ex_data == NULL)
631 return;
632
633 for (p = ex_data; *p != NULL; p = &((*p)->next))
634 {
635 if ((*p)->dup_func == dup_func && (*p)->free_func == free_func && (*p)->clear_free_func == clear_free_func)
636 {
637 EC_EXTRA_DATA *next = (*p)->next;
638
639 (*p)->clear_free_func((*p)->data);
640 OPENSSL_free(*p);
641
642 *p = next;
643 return;
644 }
645 }
646 }
647
648/* this has 'package' visibility */
649void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
650 {
651 EC_EXTRA_DATA *d;
652
653 if (ex_data == NULL)
654 return;
655
656 d = *ex_data;
657 while (d)
658 {
659 EC_EXTRA_DATA *next = d->next;
660
661 d->free_func(d->data);
662 OPENSSL_free(d);
663
664 d = next;
665 }
666 *ex_data = NULL;
667 }
668
669/* this has 'package' visibility */
670void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
671 {
672 EC_EXTRA_DATA *d;
673
674 if (ex_data == NULL)
675 return;
676
677 d = *ex_data;
678 while (d)
679 {
680 EC_EXTRA_DATA *next = d->next;
681
682 d->clear_free_func(d->data);
683 OPENSSL_free(d);
684
685 d = next;
686 }
687 *ex_data = NULL;
688 }
689
690
691/* functions for EC_POINT objects */
692
693EC_POINT *EC_POINT_new(const EC_GROUP *group)
694 {
695 EC_POINT *ret;
696
697 if (group == NULL)
698 {
699 ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
700 return NULL;
701 }
702 if (group->meth->point_init == 0)
703 {
704 ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
705 return NULL;
706 }
707
708 ret = OPENSSL_malloc(sizeof *ret);
709 if (ret == NULL)
710 {
711 ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
712 return NULL;
713 }
714
715 ret->meth = group->meth;
716
717 if (!ret->meth->point_init(ret))
718 {
719 OPENSSL_free(ret);
720 return NULL;
721 }
722
723 return ret;
724 }
725
726
727void EC_POINT_free(EC_POINT *point)
728 {
729 if (!point) return;
730
731 if (point->meth->point_finish != 0)
732 point->meth->point_finish(point);
733 OPENSSL_free(point);
734 }
735
736
737void EC_POINT_clear_free(EC_POINT *point)
738 {
739 if (!point) return;
740
741 if (point->meth->point_clear_finish != 0)
742 point->meth->point_clear_finish(point);
743 else if (point->meth->point_finish != 0)
744 point->meth->point_finish(point);
745 OPENSSL_cleanse(point, sizeof *point);
746 OPENSSL_free(point);
747 }
748
749
750int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
751 {
752 if (dest->meth->point_copy == 0)
753 {
754 ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
755 return 0;
756 }
757 if (dest->meth != src->meth)
758 {
759 ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
760 return 0;
761 }
762 if (dest == src)
763 return 1;
764 return dest->meth->point_copy(dest, src);
765 }
766
767
768EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
769 {
770 EC_POINT *t;
771 int r;
772
773 if (a == NULL) return NULL;
774
775 t = EC_POINT_new(group);
776 if (t == NULL) return(NULL);
777 r = EC_POINT_copy(t, a);
778 if (!r)
779 {
780 EC_POINT_free(t);
781 return NULL;
782 }
783 else return t;
784 }
785
786
787const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
788 {
789 return point->meth;
790 }
791
792
793int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
794 {
795 if (group->meth->point_set_to_infinity == 0)
796 {
797 ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
798 return 0;
799 }
800 if (group->meth != point->meth)
801 {
802 ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
803 return 0;
804 }
805 return group->meth->point_set_to_infinity(group, point);
806 }
807
808
809int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
810 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
811 {
812 if (group->meth->point_set_Jprojective_coordinates_GFp == 0)
813 {
814 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
815 return 0;
816 }
817 if (group->meth != point->meth)
818 {
819 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
820 return 0;
821 }
822 return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
823 }
824
825
826int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
827 BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
828 {
829 if (group->meth->point_get_Jprojective_coordinates_GFp == 0)
830 {
831 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
832 return 0;
833 }
834 if (group->meth != point->meth)
835 {
836 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
837 return 0;
838 }
839 return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
840 }
841
842
843int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
844 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
845 {
846 if (group->meth->point_set_affine_coordinates == 0)
847 {
848 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
849 return 0;
850 }
851 if (group->meth != point->meth)
852 {
853 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
854 return 0;
855 }
856 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
857 }
858
859
860int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
861 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
862 {
863 if (group->meth->point_set_affine_coordinates == 0)
864 {
865 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
866 return 0;
867 }
868 if (group->meth != point->meth)
869 {
870 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
871 return 0;
872 }
873 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
874 }
875
876
877int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
878 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
879 {
880 if (group->meth->point_get_affine_coordinates == 0)
881 {
882 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
883 return 0;
884 }
885 if (group->meth != point->meth)
886 {
887 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
888 return 0;
889 }
890 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
891 }
892
893
894int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
895 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
896 {
897 if (group->meth->point_get_affine_coordinates == 0)
898 {
899 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
900 return 0;
901 }
902 if (group->meth != point->meth)
903 {
904 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
905 return 0;
906 }
907 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
908 }
909
910
911int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
912 const BIGNUM *x, int y_bit, BN_CTX *ctx)
913 {
914 if (group->meth->point_set_compressed_coordinates == 0)
915 {
916 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
917 return 0;
918 }
919 if (group->meth != point->meth)
920 {
921 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
922 return 0;
923 }
924 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
925 }
926
927
928int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
929 const BIGNUM *x, int y_bit, BN_CTX *ctx)
930 {
931 if (group->meth->point_set_compressed_coordinates == 0)
932 {
933 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
934 return 0;
935 }
936 if (group->meth != point->meth)
937 {
938 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
939 return 0;
940 }
941 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
942 }
943
944
945size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
946 unsigned char *buf, size_t len, BN_CTX *ctx)
947 {
948 if (group->meth->point2oct == 0)
949 {
950 ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
951 return 0;
952 }
953 if (group->meth != point->meth)
954 {
955 ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
956 return 0;
957 }
958 return group->meth->point2oct(group, point, form, buf, len, ctx);
959 }
960
961
962int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
963 const unsigned char *buf, size_t len, BN_CTX *ctx)
964 {
965 if (group->meth->oct2point == 0)
966 {
967 ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
968 return 0;
969 }
970 if (group->meth != point->meth)
971 {
972 ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
973 return 0;
974 }
975 return group->meth->oct2point(group, point, buf, len, ctx);
976 }
977
978
979int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
980 {
981 if (group->meth->add == 0)
982 {
983 ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
984 return 0;
985 }
986 if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth))
987 {
988 ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
989 return 0;
990 }
991 return group->meth->add(group, r, a, b, ctx);
992 }
993
994
995int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
996 {
997 if (group->meth->dbl == 0)
998 {
999 ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1000 return 0;
1001 }
1002 if ((group->meth != r->meth) || (r->meth != a->meth))
1003 {
1004 ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
1005 return 0;
1006 }
1007 return group->meth->dbl(group, r, a, ctx);
1008 }
1009
1010
1011int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
1012 {
1013 if (group->meth->dbl == 0)
1014 {
1015 ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1016 return 0;
1017 }
1018 if (group->meth != a->meth)
1019 {
1020 ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
1021 return 0;
1022 }
1023 return group->meth->invert(group, a, ctx);
1024 }
1025
1026
1027int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
1028 {
1029 if (group->meth->is_at_infinity == 0)
1030 {
1031 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1032 return 0;
1033 }
1034 if (group->meth != point->meth)
1035 {
1036 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
1037 return 0;
1038 }
1039 return group->meth->is_at_infinity(group, point);
1040 }
1041
1042
1043int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
1044 {
1045 if (group->meth->is_on_curve == 0)
1046 {
1047 ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1048 return 0;
1049 }
1050 if (group->meth != point->meth)
1051 {
1052 ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
1053 return 0;
1054 }
1055 return group->meth->is_on_curve(group, point, ctx);
1056 }
1057
1058
1059int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
1060 {
1061 if (group->meth->point_cmp == 0)
1062 {
1063 ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1064 return 0;
1065 }
1066 if ((group->meth != a->meth) || (a->meth != b->meth))
1067 {
1068 ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
1069 return 0;
1070 }
1071 return group->meth->point_cmp(group, a, b, ctx);
1072 }
1073
1074
1075int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1076 {
1077 if (group->meth->make_affine == 0)
1078 {
1079 ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1080 return 0;
1081 }
1082 if (group->meth != point->meth)
1083 {
1084 ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1085 return 0;
1086 }
1087 return group->meth->make_affine(group, point, ctx);
1088 }
1089
1090
1091int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1092 {
1093 size_t i;
1094
1095 if (group->meth->points_make_affine == 0)
1096 {
1097 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1098 return 0;
1099 }
1100 for (i = 0; i < num; i++)
1101 {
1102 if (group->meth != points[i]->meth)
1103 {
1104 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1105 return 0;
1106 }
1107 }
1108 return group->meth->points_make_affine(group, num, points, ctx);
1109 }
1110
1111
1112/* Functions for point multiplication.
1113 *
1114 * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c;
1115 * otherwise we dispatch through methods.
1116 */
1117
1118int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1119 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
1120 {
1121 if (group->meth->mul == 0)
1122 /* use default */
1123 return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
1124
1125 return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
1126 }
1127
1128int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1129 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1130 {
1131 /* just a convenient interface to EC_POINTs_mul() */
1132
1133 const EC_POINT *points[1];
1134 const BIGNUM *scalars[1];
1135
1136 points[0] = point;
1137 scalars[0] = p_scalar;
1138
1139 return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx);
1140 }
1141
1142int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1143 {
1144 if (group->meth->mul == 0)
1145 /* use default */
1146 return ec_wNAF_precompute_mult(group, ctx);
1147
1148 if (group->meth->precompute_mult != 0)
1149 return group->meth->precompute_mult(group, ctx);
1150 else
1151 return 1; /* nothing to do, so report success */
1152 }
1153
1154int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1155 {
1156 if (group->meth->mul == 0)
1157 /* use default */
1158 return ec_wNAF_have_precompute_mult(group);
1159
1160 if (group->meth->have_precompute_mult != 0)
1161 return group->meth->have_precompute_mult(group);
1162 else
1163 return 0; /* cannot tell whether precomputation has been performed */
1164 }
diff --git a/src/lib/libcrypto/ec/ec_mult.c b/src/lib/libcrypto/ec/ec_mult.c
new file mode 100644
index 0000000000..19f21675fb
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_mult.c
@@ -0,0 +1,940 @@
1/* crypto/ec/ec_mult.c */
2/*
3 * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
61 * and contributed to the OpenSSL project.
62 */
63
64#include <string.h>
65
66#include <openssl/err.h>
67
68#include "ec_lcl.h"
69
70
71/*
72 * This file implements the wNAF-based interleaving multi-exponentation method
73 * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>);
74 * for multiplication with precomputation, we use wNAF splitting
75 * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp>).
76 */
77
78
79
80
81/* structure for precomputed multiples of the generator */
82typedef struct ec_pre_comp_st {
83 const EC_GROUP *group; /* parent EC_GROUP object */
84 size_t blocksize; /* block size for wNAF splitting */
85 size_t numblocks; /* max. number of blocks for which we have precomputation */
86 size_t w; /* window size */
87 EC_POINT **points; /* array with pre-calculated multiples of generator:
88 * 'num' pointers to EC_POINT objects followed by a NULL */
89 size_t num; /* numblocks * 2^(w-1) */
90 int references;
91} EC_PRE_COMP;
92
93/* functions to manage EC_PRE_COMP within the EC_GROUP extra_data framework */
94static void *ec_pre_comp_dup(void *);
95static void ec_pre_comp_free(void *);
96static void ec_pre_comp_clear_free(void *);
97
98static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group)
99 {
100 EC_PRE_COMP *ret = NULL;
101
102 if (!group)
103 return NULL;
104
105 ret = (EC_PRE_COMP *)OPENSSL_malloc(sizeof(EC_PRE_COMP));
106 if (!ret)
107 {
108 ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
109 return ret;
110 }
111 ret->group = group;
112 ret->blocksize = 8; /* default */
113 ret->numblocks = 0;
114 ret->w = 4; /* default */
115 ret->points = NULL;
116 ret->num = 0;
117 ret->references = 1;
118 return ret;
119 }
120
121static void *ec_pre_comp_dup(void *src_)
122 {
123 EC_PRE_COMP *src = src_;
124
125 /* no need to actually copy, these objects never change! */
126
127 CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
128
129 return src_;
130 }
131
132static void ec_pre_comp_free(void *pre_)
133 {
134 int i;
135 EC_PRE_COMP *pre = pre_;
136
137 if (!pre)
138 return;
139
140 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
141 if (i > 0)
142 return;
143
144 if (pre->points)
145 {
146 EC_POINT **p;
147
148 for (p = pre->points; *p != NULL; p++)
149 EC_POINT_free(*p);
150 OPENSSL_free(pre->points);
151 }
152 OPENSSL_free(pre);
153 }
154
155static void ec_pre_comp_clear_free(void *pre_)
156 {
157 int i;
158 EC_PRE_COMP *pre = pre_;
159
160 if (!pre)
161 return;
162
163 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
164 if (i > 0)
165 return;
166
167 if (pre->points)
168 {
169 EC_POINT **p;
170
171 for (p = pre->points; *p != NULL; p++)
172 {
173 EC_POINT_clear_free(*p);
174 OPENSSL_cleanse(p, sizeof *p);
175 }
176 OPENSSL_free(pre->points);
177 }
178 OPENSSL_cleanse(pre, sizeof *pre);
179 OPENSSL_free(pre);
180 }
181
182
183
184
185/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'.
186 * This is an array r[] of values that are either zero or odd with an
187 * absolute value less than 2^w satisfying
188 * scalar = \sum_j r[j]*2^j
189 * where at most one of any w+1 consecutive digits is non-zero
190 * with the exception that the most significant digit may be only
191 * w-1 zeros away from that next non-zero digit.
192 */
193static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
194 {
195 int window_val;
196 int ok = 0;
197 signed char *r = NULL;
198 int sign = 1;
199 int bit, next_bit, mask;
200 size_t len = 0, j;
201
202 if (BN_is_zero(scalar))
203 {
204 r = OPENSSL_malloc(1);
205 if (!r)
206 {
207 ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
208 goto err;
209 }
210 r[0] = 0;
211 *ret_len = 1;
212 return r;
213 }
214
215 if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute values less than 2^7 */
216 {
217 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
218 goto err;
219 }
220 bit = 1 << w; /* at most 128 */
221 next_bit = bit << 1; /* at most 256 */
222 mask = next_bit - 1; /* at most 255 */
223
224 if (BN_is_negative(scalar))
225 {
226 sign = -1;
227 }
228
229 if (scalar->d == NULL || scalar->top == 0)
230 {
231 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
232 goto err;
233 }
234
235 len = BN_num_bits(scalar);
236 r = OPENSSL_malloc(len + 1); /* modified wNAF may be one digit longer than binary representation
237 * (*ret_len will be set to the actual length, i.e. at most
238 * BN_num_bits(scalar) + 1) */
239 if (r == NULL)
240 {
241 ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
242 goto err;
243 }
244 window_val = scalar->d[0] & mask;
245 j = 0;
246 while ((window_val != 0) || (j + w + 1 < len)) /* if j+w+1 >= len, window_val will not increase */
247 {
248 int digit = 0;
249
250 /* 0 <= window_val <= 2^(w+1) */
251
252 if (window_val & 1)
253 {
254 /* 0 < window_val < 2^(w+1) */
255
256 if (window_val & bit)
257 {
258 digit = window_val - next_bit; /* -2^w < digit < 0 */
259
260#if 1 /* modified wNAF */
261 if (j + w + 1 >= len)
262 {
263 /* special case for generating modified wNAFs:
264 * no new bits will be added into window_val,
265 * so using a positive digit here will decrease
266 * the total length of the representation */
267
268 digit = window_val & (mask >> 1); /* 0 < digit < 2^w */
269 }
270#endif
271 }
272 else
273 {
274 digit = window_val; /* 0 < digit < 2^w */
275 }
276
277 if (digit <= -bit || digit >= bit || !(digit & 1))
278 {
279 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
280 goto err;
281 }
282
283 window_val -= digit;
284
285 /* now window_val is 0 or 2^(w+1) in standard wNAF generation;
286 * for modified window NAFs, it may also be 2^w
287 */
288 if (window_val != 0 && window_val != next_bit && window_val != bit)
289 {
290 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
291 goto err;
292 }
293 }
294
295 r[j++] = sign * digit;
296
297 window_val >>= 1;
298 window_val += bit * BN_is_bit_set(scalar, j + w);
299
300 if (window_val > next_bit)
301 {
302 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
303 goto err;
304 }
305 }
306
307 if (j > len + 1)
308 {
309 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
310 goto err;
311 }
312 len = j;
313 ok = 1;
314
315 err:
316 if (!ok)
317 {
318 OPENSSL_free(r);
319 r = NULL;
320 }
321 if (ok)
322 *ret_len = len;
323 return r;
324 }
325
326
327/* TODO: table should be optimised for the wNAF-based implementation,
328 * sometimes smaller windows will give better performance
329 * (thus the boundaries should be increased)
330 */
331#define EC_window_bits_for_scalar_size(b) \
332 ((size_t) \
333 ((b) >= 2000 ? 6 : \
334 (b) >= 800 ? 5 : \
335 (b) >= 300 ? 4 : \
336 (b) >= 70 ? 3 : \
337 (b) >= 20 ? 2 : \
338 1))
339
340/* Compute
341 * \sum scalars[i]*points[i],
342 * also including
343 * scalar*generator
344 * in the addition if scalar != NULL
345 */
346int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
347 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
348 {
349 BN_CTX *new_ctx = NULL;
350 const EC_POINT *generator = NULL;
351 EC_POINT *tmp = NULL;
352 size_t totalnum;
353 size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */
354 size_t pre_points_per_block = 0;
355 size_t i, j;
356 int k;
357 int r_is_inverted = 0;
358 int r_is_at_infinity = 1;
359 size_t *wsize = NULL; /* individual window sizes */
360 signed char **wNAF = NULL; /* individual wNAFs */
361 size_t *wNAF_len = NULL;
362 size_t max_len = 0;
363 size_t num_val;
364 EC_POINT **val = NULL; /* precomputation */
365 EC_POINT **v;
366 EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or 'pre_comp->points' */
367 const EC_PRE_COMP *pre_comp = NULL;
368 int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be treated like other scalars,
369 * i.e. precomputation is not available */
370 int ret = 0;
371
372 if (group->meth != r->meth)
373 {
374 ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
375 return 0;
376 }
377
378 if ((scalar == NULL) && (num == 0))
379 {
380 return EC_POINT_set_to_infinity(group, r);
381 }
382
383 for (i = 0; i < num; i++)
384 {
385 if (group->meth != points[i]->meth)
386 {
387 ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
388 return 0;
389 }
390 }
391
392 if (ctx == NULL)
393 {
394 ctx = new_ctx = BN_CTX_new();
395 if (ctx == NULL)
396 goto err;
397 }
398
399 if (scalar != NULL)
400 {
401 generator = EC_GROUP_get0_generator(group);
402 if (generator == NULL)
403 {
404 ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR);
405 goto err;
406 }
407
408 /* look if we can use precomputed multiples of generator */
409
410 pre_comp = EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free);
411
412 if (pre_comp && pre_comp->numblocks && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) == 0))
413 {
414 blocksize = pre_comp->blocksize;
415
416 /* determine maximum number of blocks that wNAF splitting may yield
417 * (NB: maximum wNAF length is bit length plus one) */
418 numblocks = (BN_num_bits(scalar) / blocksize) + 1;
419
420 /* we cannot use more blocks than we have precomputation for */
421 if (numblocks > pre_comp->numblocks)
422 numblocks = pre_comp->numblocks;
423
424 pre_points_per_block = (size_t)1 << (pre_comp->w - 1);
425
426 /* check that pre_comp looks sane */
427 if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block))
428 {
429 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
430 goto err;
431 }
432 }
433 else
434 {
435 /* can't use precomputation */
436 pre_comp = NULL;
437 numblocks = 1;
438 num_scalar = 1; /* treat 'scalar' like 'num'-th element of 'scalars' */
439 }
440 }
441
442 totalnum = num + numblocks;
443
444 wsize = OPENSSL_malloc(totalnum * sizeof wsize[0]);
445 wNAF_len = OPENSSL_malloc(totalnum * sizeof wNAF_len[0]);
446 wNAF = OPENSSL_malloc((totalnum + 1) * sizeof wNAF[0]); /* includes space for pivot */
447 val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]);
448
449 if (!wsize || !wNAF_len || !wNAF || !val_sub)
450 {
451 ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
452 goto err;
453 }
454
455 wNAF[0] = NULL; /* preliminary pivot */
456
457 /* num_val will be the total number of temporarily precomputed points */
458 num_val = 0;
459
460 for (i = 0; i < num + num_scalar; i++)
461 {
462 size_t bits;
463
464 bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);
465 wsize[i] = EC_window_bits_for_scalar_size(bits);
466 num_val += (size_t)1 << (wsize[i] - 1);
467 wNAF[i + 1] = NULL; /* make sure we always have a pivot */
468 wNAF[i] = compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], &wNAF_len[i]);
469 if (wNAF[i] == NULL)
470 goto err;
471 if (wNAF_len[i] > max_len)
472 max_len = wNAF_len[i];
473 }
474
475 if (numblocks)
476 {
477 /* we go here iff scalar != NULL */
478
479 if (pre_comp == NULL)
480 {
481 if (num_scalar != 1)
482 {
483 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
484 goto err;
485 }
486 /* we have already generated a wNAF for 'scalar' */
487 }
488 else
489 {
490 signed char *tmp_wNAF = NULL;
491 size_t tmp_len = 0;
492
493 if (num_scalar != 0)
494 {
495 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
496 goto err;
497 }
498
499 /* use the window size for which we have precomputation */
500 wsize[num] = pre_comp->w;
501 tmp_wNAF = compute_wNAF(scalar, wsize[num], &tmp_len);
502 if (!tmp_wNAF)
503 goto err;
504
505 if (tmp_len <= max_len)
506 {
507 /* One of the other wNAFs is at least as long
508 * as the wNAF belonging to the generator,
509 * so wNAF splitting will not buy us anything. */
510
511 numblocks = 1;
512 totalnum = num + 1; /* don't use wNAF splitting */
513 wNAF[num] = tmp_wNAF;
514 wNAF[num + 1] = NULL;
515 wNAF_len[num] = tmp_len;
516 if (tmp_len > max_len)
517 max_len = tmp_len;
518 /* pre_comp->points starts with the points that we need here: */
519 val_sub[num] = pre_comp->points;
520 }
521 else
522 {
523 /* don't include tmp_wNAF directly into wNAF array
524 * - use wNAF splitting and include the blocks */
525
526 signed char *pp;
527 EC_POINT **tmp_points;
528
529 if (tmp_len < numblocks * blocksize)
530 {
531 /* possibly we can do with fewer blocks than estimated */
532 numblocks = (tmp_len + blocksize - 1) / blocksize;
533 if (numblocks > pre_comp->numblocks)
534 {
535 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
536 goto err;
537 }
538 totalnum = num + numblocks;
539 }
540
541 /* split wNAF in 'numblocks' parts */
542 pp = tmp_wNAF;
543 tmp_points = pre_comp->points;
544
545 for (i = num; i < totalnum; i++)
546 {
547 if (i < totalnum - 1)
548 {
549 wNAF_len[i] = blocksize;
550 if (tmp_len < blocksize)
551 {
552 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
553 goto err;
554 }
555 tmp_len -= blocksize;
556 }
557 else
558 /* last block gets whatever is left
559 * (this could be more or less than 'blocksize'!) */
560 wNAF_len[i] = tmp_len;
561
562 wNAF[i + 1] = NULL;
563 wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
564 if (wNAF[i] == NULL)
565 {
566 ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
567 OPENSSL_free(tmp_wNAF);
568 goto err;
569 }
570 memcpy(wNAF[i], pp, wNAF_len[i]);
571 if (wNAF_len[i] > max_len)
572 max_len = wNAF_len[i];
573
574 if (*tmp_points == NULL)
575 {
576 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
577 OPENSSL_free(tmp_wNAF);
578 goto err;
579 }
580 val_sub[i] = tmp_points;
581 tmp_points += pre_points_per_block;
582 pp += blocksize;
583 }
584 OPENSSL_free(tmp_wNAF);
585 }
586 }
587 }
588
589 /* All points we precompute now go into a single array 'val'.
590 * 'val_sub[i]' is a pointer to the subarray for the i-th point,
591 * or to a subarray of 'pre_comp->points' if we already have precomputation. */
592 val = OPENSSL_malloc((num_val + 1) * sizeof val[0]);
593 if (val == NULL)
594 {
595 ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
596 goto err;
597 }
598 val[num_val] = NULL; /* pivot element */
599
600 /* allocate points for precomputation */
601 v = val;
602 for (i = 0; i < num + num_scalar; i++)
603 {
604 val_sub[i] = v;
605 for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++)
606 {
607 *v = EC_POINT_new(group);
608 if (*v == NULL) goto err;
609 v++;
610 }
611 }
612 if (!(v == val + num_val))
613 {
614 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
615 goto err;
616 }
617
618 if (!(tmp = EC_POINT_new(group)))
619 goto err;
620
621 /* prepare precomputed values:
622 * val_sub[i][0] := points[i]
623 * val_sub[i][1] := 3 * points[i]
624 * val_sub[i][2] := 5 * points[i]
625 * ...
626 */
627 for (i = 0; i < num + num_scalar; i++)
628 {
629 if (i < num)
630 {
631 if (!EC_POINT_copy(val_sub[i][0], points[i])) goto err;
632 }
633 else
634 {
635 if (!EC_POINT_copy(val_sub[i][0], generator)) goto err;
636 }
637
638 if (wsize[i] > 1)
639 {
640 if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx)) goto err;
641 for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++)
642 {
643 if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) goto err;
644 }
645 }
646 }
647
648#if 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */
649 if (!EC_POINTs_make_affine(group, num_val, val, ctx))
650 goto err;
651#endif
652
653 r_is_at_infinity = 1;
654
655 for (k = max_len - 1; k >= 0; k--)
656 {
657 if (!r_is_at_infinity)
658 {
659 if (!EC_POINT_dbl(group, r, r, ctx)) goto err;
660 }
661
662 for (i = 0; i < totalnum; i++)
663 {
664 if (wNAF_len[i] > (size_t)k)
665 {
666 int digit = wNAF[i][k];
667 int is_neg;
668
669 if (digit)
670 {
671 is_neg = digit < 0;
672
673 if (is_neg)
674 digit = -digit;
675
676 if (is_neg != r_is_inverted)
677 {
678 if (!r_is_at_infinity)
679 {
680 if (!EC_POINT_invert(group, r, ctx)) goto err;
681 }
682 r_is_inverted = !r_is_inverted;
683 }
684
685 /* digit > 0 */
686
687 if (r_is_at_infinity)
688 {
689 if (!EC_POINT_copy(r, val_sub[i][digit >> 1])) goto err;
690 r_is_at_infinity = 0;
691 }
692 else
693 {
694 if (!EC_POINT_add(group, r, r, val_sub[i][digit >> 1], ctx)) goto err;
695 }
696 }
697 }
698 }
699 }
700
701 if (r_is_at_infinity)
702 {
703 if (!EC_POINT_set_to_infinity(group, r)) goto err;
704 }
705 else
706 {
707 if (r_is_inverted)
708 if (!EC_POINT_invert(group, r, ctx)) goto err;
709 }
710
711 ret = 1;
712
713 err:
714 if (new_ctx != NULL)
715 BN_CTX_free(new_ctx);
716 if (tmp != NULL)
717 EC_POINT_free(tmp);
718 if (wsize != NULL)
719 OPENSSL_free(wsize);
720 if (wNAF_len != NULL)
721 OPENSSL_free(wNAF_len);
722 if (wNAF != NULL)
723 {
724 signed char **w;
725
726 for (w = wNAF; *w != NULL; w++)
727 OPENSSL_free(*w);
728
729 OPENSSL_free(wNAF);
730 }
731 if (val != NULL)
732 {
733 for (v = val; *v != NULL; v++)
734 EC_POINT_clear_free(*v);
735
736 OPENSSL_free(val);
737 }
738 if (val_sub != NULL)
739 {
740 OPENSSL_free(val_sub);
741 }
742 return ret;
743 }
744
745
746/* ec_wNAF_precompute_mult()
747 * creates an EC_PRE_COMP object with preprecomputed multiples of the generator
748 * for use with wNAF splitting as implemented in ec_wNAF_mul().
749 *
750 * 'pre_comp->points' is an array of multiples of the generator
751 * of the following form:
752 * points[0] = generator;
753 * points[1] = 3 * generator;
754 * ...
755 * points[2^(w-1)-1] = (2^(w-1)-1) * generator;
756 * points[2^(w-1)] = 2^blocksize * generator;
757 * points[2^(w-1)+1] = 3 * 2^blocksize * generator;
758 * ...
759 * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) * 2^(blocksize*(numblocks-2)) * generator
760 * points[2^(w-1)*(numblocks-1)] = 2^(blocksize*(numblocks-1)) * generator
761 * ...
762 * points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) * generator
763 * points[2^(w-1)*numblocks] = NULL
764 */
765int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
766 {
767 const EC_POINT *generator;
768 EC_POINT *tmp_point = NULL, *base = NULL, **var;
769 BN_CTX *new_ctx = NULL;
770 BIGNUM *order;
771 size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;
772 EC_POINT **points = NULL;
773 EC_PRE_COMP *pre_comp;
774 int ret = 0;
775
776 /* if there is an old EC_PRE_COMP object, throw it away */
777 EC_EX_DATA_free_data(&group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free);
778
779 if ((pre_comp = ec_pre_comp_new(group)) == NULL)
780 return 0;
781
782 generator = EC_GROUP_get0_generator(group);
783 if (generator == NULL)
784 {
785 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR);
786 goto err;
787 }
788
789 if (ctx == NULL)
790 {
791 ctx = new_ctx = BN_CTX_new();
792 if (ctx == NULL)
793 goto err;
794 }
795
796 BN_CTX_start(ctx);
797 order = BN_CTX_get(ctx);
798 if (order == NULL) goto err;
799
800 if (!EC_GROUP_get_order(group, order, ctx)) goto err;
801 if (BN_is_zero(order))
802 {
803 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER);
804 goto err;
805 }
806
807 bits = BN_num_bits(order);
808 /* The following parameters mean we precompute (approximately)
809 * one point per bit.
810 *
811 * TBD: The combination 8, 4 is perfect for 160 bits; for other
812 * bit lengths, other parameter combinations might provide better
813 * efficiency.
814 */
815 blocksize = 8;
816 w = 4;
817 if (EC_window_bits_for_scalar_size(bits) > w)
818 {
819 /* let's not make the window too small ... */
820 w = EC_window_bits_for_scalar_size(bits);
821 }
822
823 numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks to use for wNAF splitting */
824
825 pre_points_per_block = (size_t)1 << (w - 1);
826 num = pre_points_per_block * numblocks; /* number of points to compute and store */
827
828 points = OPENSSL_malloc(sizeof (EC_POINT*)*(num + 1));
829 if (!points)
830 {
831 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
832 goto err;
833 }
834
835 var = points;
836 var[num] = NULL; /* pivot */
837 for (i = 0; i < num; i++)
838 {
839 if ((var[i] = EC_POINT_new(group)) == NULL)
840 {
841 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
842 goto err;
843 }
844 }
845
846 if (!(tmp_point = EC_POINT_new(group)) || !(base = EC_POINT_new(group)))
847 {
848 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
849 goto err;
850 }
851
852 if (!EC_POINT_copy(base, generator))
853 goto err;
854
855 /* do the precomputation */
856 for (i = 0; i < numblocks; i++)
857 {
858 size_t j;
859
860 if (!EC_POINT_dbl(group, tmp_point, base, ctx))
861 goto err;
862
863 if (!EC_POINT_copy(*var++, base))
864 goto err;
865
866 for (j = 1; j < pre_points_per_block; j++, var++)
867 {
868 /* calculate odd multiples of the current base point */
869 if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx))
870 goto err;
871 }
872
873 if (i < numblocks - 1)
874 {
875 /* get the next base (multiply current one by 2^blocksize) */
876 size_t k;
877
878 if (blocksize <= 2)
879 {
880 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR);
881 goto err;
882 }
883
884 if (!EC_POINT_dbl(group, base, tmp_point, ctx))
885 goto err;
886 for (k = 2; k < blocksize; k++)
887 {
888 if (!EC_POINT_dbl(group,base,base,ctx))
889 goto err;
890 }
891 }
892 }
893
894 if (!EC_POINTs_make_affine(group, num, points, ctx))
895 goto err;
896
897 pre_comp->group = group;
898 pre_comp->blocksize = blocksize;
899 pre_comp->numblocks = numblocks;
900 pre_comp->w = w;
901 pre_comp->points = points;
902 points = NULL;
903 pre_comp->num = num;
904
905 if (!EC_EX_DATA_set_data(&group->extra_data, pre_comp,
906 ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free))
907 goto err;
908 pre_comp = NULL;
909
910 ret = 1;
911 err:
912 if (ctx != NULL)
913 BN_CTX_end(ctx);
914 if (new_ctx != NULL)
915 BN_CTX_free(new_ctx);
916 if (pre_comp)
917 ec_pre_comp_free(pre_comp);
918 if (points)
919 {
920 EC_POINT **p;
921
922 for (p = points; *p != NULL; p++)
923 EC_POINT_free(*p);
924 OPENSSL_free(points);
925 }
926 if (tmp_point)
927 EC_POINT_free(tmp_point);
928 if (base)
929 EC_POINT_free(base);
930 return ret;
931 }
932
933
934int ec_wNAF_have_precompute_mult(const EC_GROUP *group)
935 {
936 if (EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free) != NULL)
937 return 1;
938 else
939 return 0;
940 }
diff --git a/src/lib/libcrypto/ec/ec_oct.c b/src/lib/libcrypto/ec/ec_oct.c
new file mode 100644
index 0000000000..fd9db0798d
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_oct.c
@@ -0,0 +1,199 @@
1/* crypto/ec/ec_lib.c */
2/*
3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Binary polynomial ECC support in OpenSSL originally developed by
61 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
62 */
63
64#include <string.h>
65
66#include <openssl/err.h>
67#include <openssl/opensslv.h>
68
69#include "ec_lcl.h"
70
71int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
72 const BIGNUM *x, int y_bit, BN_CTX *ctx)
73 {
74 if (group->meth->point_set_compressed_coordinates == 0
75 && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
76 {
77 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
78 return 0;
79 }
80 if (group->meth != point->meth)
81 {
82 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
83 return 0;
84 }
85 if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
86 {
87 if (group->meth->field_type == NID_X9_62_prime_field)
88 return ec_GFp_simple_set_compressed_coordinates(
89 group, point, x, y_bit, ctx);
90 else
91#ifdef OPENSSL_NO_EC2M
92 {
93 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_GF2M_NOT_SUPPORTED);
94 return 0;
95 }
96#else
97 return ec_GF2m_simple_set_compressed_coordinates(
98 group, point, x, y_bit, ctx);
99#endif
100 }
101 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
102 }
103
104#ifndef OPENSSL_NO_EC2M
105int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
106 const BIGNUM *x, int y_bit, BN_CTX *ctx)
107 {
108 if (group->meth->point_set_compressed_coordinates == 0
109 && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
110 {
111 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
112 return 0;
113 }
114 if (group->meth != point->meth)
115 {
116 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
117 return 0;
118 }
119 if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
120 {
121 if (group->meth->field_type == NID_X9_62_prime_field)
122 return ec_GFp_simple_set_compressed_coordinates(
123 group, point, x, y_bit, ctx);
124 else
125 return ec_GF2m_simple_set_compressed_coordinates(
126 group, point, x, y_bit, ctx);
127 }
128 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
129 }
130#endif
131
132size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
133 unsigned char *buf, size_t len, BN_CTX *ctx)
134 {
135 if (group->meth->point2oct == 0
136 && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
137 {
138 ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
139 return 0;
140 }
141 if (group->meth != point->meth)
142 {
143 ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
144 return 0;
145 }
146 if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
147 {
148 if (group->meth->field_type == NID_X9_62_prime_field)
149 return ec_GFp_simple_point2oct(group, point,
150 form, buf, len, ctx);
151 else
152#ifdef OPENSSL_NO_EC2M
153 {
154 ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_GF2M_NOT_SUPPORTED);
155 return 0;
156 }
157#else
158 return ec_GF2m_simple_point2oct(group, point,
159 form, buf, len, ctx);
160#endif
161 }
162
163 return group->meth->point2oct(group, point, form, buf, len, ctx);
164 }
165
166
167int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
168 const unsigned char *buf, size_t len, BN_CTX *ctx)
169 {
170 if (group->meth->oct2point == 0
171 && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
172 {
173 ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
174 return 0;
175 }
176 if (group->meth != point->meth)
177 {
178 ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
179 return 0;
180 }
181 if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
182 {
183 if (group->meth->field_type == NID_X9_62_prime_field)
184 return ec_GFp_simple_oct2point(group, point,
185 buf, len, ctx);
186 else
187#ifdef OPENSSL_NO_EC2M
188 {
189 ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_GF2M_NOT_SUPPORTED);
190 return 0;
191 }
192#else
193 return ec_GF2m_simple_oct2point(group, point,
194 buf, len, ctx);
195#endif
196 }
197 return group->meth->oct2point(group, point, buf, len, ctx);
198 }
199
diff --git a/src/lib/libcrypto/ec/ec_pmeth.c b/src/lib/libcrypto/ec/ec_pmeth.c
new file mode 100644
index 0000000000..d1ed66c37e
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_pmeth.c
@@ -0,0 +1,341 @@
1/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2 * project 2006.
3 */
4/* ====================================================================
5 * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 * software must display the following acknowledgment:
21 * "This product includes software developed by the OpenSSL Project
22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 * endorse or promote products derived from this software without
26 * prior written permission. For written permission, please contact
27 * licensing@OpenSSL.org.
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 * nor may "OpenSSL" appear in their names without prior written
31 * permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 * acknowledgment:
35 * "This product includes software developed by the OpenSSL Project
36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com). This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com).
55 *
56 */
57
58#include <stdio.h>
59#include "cryptlib.h"
60#include <openssl/asn1t.h>
61#include <openssl/x509.h>
62#include <openssl/ec.h>
63#include <openssl/ecdsa.h>
64#include <openssl/evp.h>
65#include "evp_locl.h"
66
67/* EC pkey context structure */
68
69typedef struct
70 {
71 /* Key and paramgen group */
72 EC_GROUP *gen_group;
73 /* message digest */
74 const EVP_MD *md;
75 } EC_PKEY_CTX;
76
77static int pkey_ec_init(EVP_PKEY_CTX *ctx)
78 {
79 EC_PKEY_CTX *dctx;
80 dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX));
81 if (!dctx)
82 return 0;
83 dctx->gen_group = NULL;
84 dctx->md = NULL;
85
86 ctx->data = dctx;
87
88 return 1;
89 }
90
91static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
92 {
93 EC_PKEY_CTX *dctx, *sctx;
94 if (!pkey_ec_init(dst))
95 return 0;
96 sctx = src->data;
97 dctx = dst->data;
98 if (sctx->gen_group)
99 {
100 dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
101 if (!dctx->gen_group)
102 return 0;
103 }
104 dctx->md = sctx->md;
105 return 1;
106 }
107
108static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
109 {
110 EC_PKEY_CTX *dctx = ctx->data;
111 if (dctx)
112 {
113 if (dctx->gen_group)
114 EC_GROUP_free(dctx->gen_group);
115 OPENSSL_free(dctx);
116 }
117 }
118
119static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
120 const unsigned char *tbs, size_t tbslen)
121 {
122 int ret, type;
123 unsigned int sltmp;
124 EC_PKEY_CTX *dctx = ctx->data;
125 EC_KEY *ec = ctx->pkey->pkey.ec;
126
127 if (!sig)
128 {
129 *siglen = ECDSA_size(ec);
130 return 1;
131 }
132 else if(*siglen < (size_t)ECDSA_size(ec))
133 {
134 ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL);
135 return 0;
136 }
137
138 if (dctx->md)
139 type = EVP_MD_type(dctx->md);
140 else
141 type = NID_sha1;
142
143
144 ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
145
146 if (ret <= 0)
147 return ret;
148 *siglen = (size_t)sltmp;
149 return 1;
150 }
151
152static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
153 const unsigned char *sig, size_t siglen,
154 const unsigned char *tbs, size_t tbslen)
155 {
156 int ret, type;
157 EC_PKEY_CTX *dctx = ctx->data;
158 EC_KEY *ec = ctx->pkey->pkey.ec;
159
160 if (dctx->md)
161 type = EVP_MD_type(dctx->md);
162 else
163 type = NID_sha1;
164
165 ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
166
167 return ret;
168 }
169
170static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
171 {
172 int ret;
173 size_t outlen;
174 const EC_POINT *pubkey = NULL;
175 if (!ctx->pkey || !ctx->peerkey)
176 {
177 ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET);
178 return 0;
179 }
180
181 if (!key)
182 {
183 const EC_GROUP *group;
184 group = EC_KEY_get0_group(ctx->pkey->pkey.ec);
185 *keylen = (EC_GROUP_get_degree(group) + 7)/8;
186 return 1;
187 }
188
189 pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
190
191 /* NB: unlike PKS#3 DH, if *outlen is less than maximum size this is
192 * not an error, the result is truncated.
193 */
194
195 outlen = *keylen;
196
197 ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0);
198 if (ret < 0)
199 return ret;
200 *keylen = ret;
201 return 1;
202 }
203
204static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
205 {
206 EC_PKEY_CTX *dctx = ctx->data;
207 EC_GROUP *group;
208 switch (type)
209 {
210 case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
211 group = EC_GROUP_new_by_curve_name(p1);
212 if (group == NULL)
213 {
214 ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE);
215 return 0;
216 }
217 if (dctx->gen_group)
218 EC_GROUP_free(dctx->gen_group);
219 dctx->gen_group = group;
220 return 1;
221
222 case EVP_PKEY_CTRL_MD:
223 if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
224 EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
225 EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
226 EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
227 EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
228 EVP_MD_type((const EVP_MD *)p2) != NID_sha512)
229 {
230 ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
231 return 0;
232 }
233 dctx->md = p2;
234 return 1;
235
236 case EVP_PKEY_CTRL_PEER_KEY:
237 /* Default behaviour is OK */
238 case EVP_PKEY_CTRL_DIGESTINIT:
239 case EVP_PKEY_CTRL_PKCS7_SIGN:
240 case EVP_PKEY_CTRL_CMS_SIGN:
241 return 1;
242
243 default:
244 return -2;
245
246 }
247 }
248
249static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
250 const char *type, const char *value)
251 {
252 if (!strcmp(type, "ec_paramgen_curve"))
253 {
254 int nid;
255 nid = OBJ_sn2nid(value);
256 if (nid == NID_undef)
257 nid = OBJ_ln2nid(value);
258 if (nid == NID_undef)
259 {
260 ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE);
261 return 0;
262 }
263 return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
264 }
265 return -2;
266 }
267
268static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
269 {
270 EC_KEY *ec = NULL;
271 EC_PKEY_CTX *dctx = ctx->data;
272 int ret = 0;
273 if (dctx->gen_group == NULL)
274 {
275 ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
276 return 0;
277 }
278 ec = EC_KEY_new();
279 if (!ec)
280 return 0;
281 ret = EC_KEY_set_group(ec, dctx->gen_group);
282 if (ret)
283 EVP_PKEY_assign_EC_KEY(pkey, ec);
284 else
285 EC_KEY_free(ec);
286 return ret;
287 }
288
289static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
290 {
291 EC_KEY *ec = NULL;
292 if (ctx->pkey == NULL)
293 {
294 ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
295 return 0;
296 }
297 ec = EC_KEY_new();
298 if (!ec)
299 return 0;
300 EVP_PKEY_assign_EC_KEY(pkey, ec);
301 /* Note: if error return, pkey is freed by parent routine */
302 if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
303 return 0;
304 return EC_KEY_generate_key(pkey->pkey.ec);
305 }
306
307const EVP_PKEY_METHOD ec_pkey_meth =
308 {
309 EVP_PKEY_EC,
310 0,
311 pkey_ec_init,
312 pkey_ec_copy,
313 pkey_ec_cleanup,
314
315 0,
316 pkey_ec_paramgen,
317
318 0,
319 pkey_ec_keygen,
320
321 0,
322 pkey_ec_sign,
323
324 0,
325 pkey_ec_verify,
326
327 0,0,
328
329 0,0,0,0,
330
331 0,0,
332
333 0,0,
334
335 0,
336 pkey_ec_derive,
337
338 pkey_ec_ctrl,
339 pkey_ec_ctrl_str
340
341 };
diff --git a/src/lib/libcrypto/ec/ec_print.c b/src/lib/libcrypto/ec/ec_print.c
new file mode 100644
index 0000000000..f7c8a303ac
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_print.c
@@ -0,0 +1,195 @@
1/* crypto/ec/ec_print.c */
2/* ====================================================================
3 * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * 3. All advertising materials mentioning features or use of this
18 * software must display the following acknowledgment:
19 * "This product includes software developed by the OpenSSL Project
20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21 *
22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23 * endorse or promote products derived from this software without
24 * prior written permission. For written permission, please contact
25 * openssl-core@openssl.org.
26 *
27 * 5. Products derived from this software may not be called "OpenSSL"
28 * nor may "OpenSSL" appear in their names without prior written
29 * permission of the OpenSSL Project.
30 *
31 * 6. Redistributions of any form whatsoever must retain the following
32 * acknowledgment:
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 * OF THE POSSIBILITY OF SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This product includes cryptographic software written by Eric Young
51 * (eay@cryptsoft.com). This product includes software written by Tim
52 * Hudson (tjh@cryptsoft.com).
53 *
54 */
55
56#include <openssl/crypto.h>
57#include "ec_lcl.h"
58
59BIGNUM *EC_POINT_point2bn(const EC_GROUP *group,
60 const EC_POINT *point,
61 point_conversion_form_t form,
62 BIGNUM *ret,
63 BN_CTX *ctx)
64 {
65 size_t buf_len=0;
66 unsigned char *buf;
67
68 buf_len = EC_POINT_point2oct(group, point, form,
69 NULL, 0, ctx);
70 if (buf_len == 0)
71 return NULL;
72
73 if ((buf = OPENSSL_malloc(buf_len)) == NULL)
74 return NULL;
75
76 if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx))
77 {
78 OPENSSL_free(buf);
79 return NULL;
80 }
81
82 ret = BN_bin2bn(buf, buf_len, ret);
83
84 OPENSSL_free(buf);
85
86 return ret;
87}
88
89EC_POINT *EC_POINT_bn2point(const EC_GROUP *group,
90 const BIGNUM *bn,
91 EC_POINT *point,
92 BN_CTX *ctx)
93 {
94 size_t buf_len=0;
95 unsigned char *buf;
96 EC_POINT *ret;
97
98 if ((buf_len = BN_num_bytes(bn)) == 0) return NULL;
99 buf = OPENSSL_malloc(buf_len);
100 if (buf == NULL)
101 return NULL;
102
103 if (!BN_bn2bin(bn, buf))
104 {
105 OPENSSL_free(buf);
106 return NULL;
107 }
108
109 if (point == NULL)
110 {
111 if ((ret = EC_POINT_new(group)) == NULL)
112 {
113 OPENSSL_free(buf);
114 return NULL;
115 }
116 }
117 else
118 ret = point;
119
120 if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx))
121 {
122 if (point == NULL)
123 EC_POINT_clear_free(ret);
124 OPENSSL_free(buf);
125 return NULL;
126 }
127
128 OPENSSL_free(buf);
129 return ret;
130 }
131
132static const char *HEX_DIGITS = "0123456789ABCDEF";
133
134/* the return value must be freed (using OPENSSL_free()) */
135char *EC_POINT_point2hex(const EC_GROUP *group,
136 const EC_POINT *point,
137 point_conversion_form_t form,
138 BN_CTX *ctx)
139 {
140 char *ret, *p;
141 size_t buf_len=0,i;
142 unsigned char *buf, *pbuf;
143
144 buf_len = EC_POINT_point2oct(group, point, form,
145 NULL, 0, ctx);
146 if (buf_len == 0)
147 return NULL;
148
149 if ((buf = OPENSSL_malloc(buf_len)) == NULL)
150 return NULL;
151
152 if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx))
153 {
154 OPENSSL_free(buf);
155 return NULL;
156 }
157
158 ret = (char *)OPENSSL_malloc(buf_len*2+2);
159 if (ret == NULL)
160 {
161 OPENSSL_free(buf);
162 return NULL;
163 }
164 p = ret;
165 pbuf = buf;
166 for (i=buf_len; i > 0; i--)
167 {
168 int v = (int) *(pbuf++);
169 *(p++)=HEX_DIGITS[v>>4];
170 *(p++)=HEX_DIGITS[v&0x0F];
171 }
172 *p='\0';
173
174 OPENSSL_free(buf);
175
176 return ret;
177 }
178
179EC_POINT *EC_POINT_hex2point(const EC_GROUP *group,
180 const char *buf,
181 EC_POINT *point,
182 BN_CTX *ctx)
183 {
184 EC_POINT *ret=NULL;
185 BIGNUM *tmp_bn=NULL;
186
187 if (!BN_hex2bn(&tmp_bn, buf))
188 return NULL;
189
190 ret = EC_POINT_bn2point(group, tmp_bn, point, ctx);
191
192 BN_clear_free(tmp_bn);
193
194 return ret;
195 }
diff --git a/src/lib/libcrypto/ec/eck_prn.c b/src/lib/libcrypto/ec/eck_prn.c
new file mode 100644
index 0000000000..06de8f3959
--- /dev/null
+++ b/src/lib/libcrypto/ec/eck_prn.c
@@ -0,0 +1,392 @@
1/* crypto/ec/eck_prn.c */
2/*
3 * Written by Nils Larsch for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Portions originally developed by SUN MICROSYSTEMS, INC., and
61 * contributed to the OpenSSL project.
62 */
63
64#include <stdio.h>
65#include "cryptlib.h"
66#include <openssl/evp.h>
67#include <openssl/ec.h>
68#include <openssl/bn.h>
69
70#ifndef OPENSSL_NO_FP_API
71int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off)
72 {
73 BIO *b;
74 int ret;
75
76 if ((b=BIO_new(BIO_s_file())) == NULL)
77 {
78 ECerr(EC_F_ECPKPARAMETERS_PRINT_FP,ERR_R_BUF_LIB);
79 return(0);
80 }
81 BIO_set_fp(b, fp, BIO_NOCLOSE);
82 ret = ECPKParameters_print(b, x, off);
83 BIO_free(b);
84 return(ret);
85 }
86
87int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off)
88 {
89 BIO *b;
90 int ret;
91
92 if ((b=BIO_new(BIO_s_file())) == NULL)
93 {
94 ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB);
95 return(0);
96 }
97 BIO_set_fp(b, fp, BIO_NOCLOSE);
98 ret = EC_KEY_print(b, x, off);
99 BIO_free(b);
100 return(ret);
101 }
102
103int ECParameters_print_fp(FILE *fp, const EC_KEY *x)
104 {
105 BIO *b;
106 int ret;
107
108 if ((b=BIO_new(BIO_s_file())) == NULL)
109 {
110 ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB);
111 return(0);
112 }
113 BIO_set_fp(b, fp, BIO_NOCLOSE);
114 ret = ECParameters_print(b, x);
115 BIO_free(b);
116 return(ret);
117 }
118#endif
119
120int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
121 {
122 EVP_PKEY *pk;
123 int ret;
124 pk = EVP_PKEY_new();
125 if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x))
126 return 0;
127 ret = EVP_PKEY_print_private(bp, pk, off, NULL);
128 EVP_PKEY_free(pk);
129 return ret;
130 }
131
132int ECParameters_print(BIO *bp, const EC_KEY *x)
133 {
134 EVP_PKEY *pk;
135 int ret;
136 pk = EVP_PKEY_new();
137 if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x))
138 return 0;
139 ret = EVP_PKEY_print_params(bp, pk, 4, NULL);
140 EVP_PKEY_free(pk);
141 return ret;
142 }
143
144static int print_bin(BIO *fp, const char *str, const unsigned char *num,
145 size_t len, int off);
146
147int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
148 {
149 unsigned char *buffer=NULL;
150 size_t buf_len=0, i;
151 int ret=0, reason=ERR_R_BIO_LIB;
152 BN_CTX *ctx=NULL;
153 const EC_POINT *point=NULL;
154 BIGNUM *p=NULL, *a=NULL, *b=NULL, *gen=NULL,
155 *order=NULL, *cofactor=NULL;
156 const unsigned char *seed;
157 size_t seed_len=0;
158
159 static const char *gen_compressed = "Generator (compressed):";
160 static const char *gen_uncompressed = "Generator (uncompressed):";
161 static const char *gen_hybrid = "Generator (hybrid):";
162
163 if (!x)
164 {
165 reason = ERR_R_PASSED_NULL_PARAMETER;
166 goto err;
167 }
168
169 ctx = BN_CTX_new();
170 if (ctx == NULL)
171 {
172 reason = ERR_R_MALLOC_FAILURE;
173 goto err;
174 }
175
176 if (EC_GROUP_get_asn1_flag(x))
177 {
178 /* the curve parameter are given by an asn1 OID */
179 int nid;
180
181 if (!BIO_indent(bp, off, 128))
182 goto err;
183
184 nid = EC_GROUP_get_curve_name(x);
185 if (nid == 0)
186 goto err;
187
188 if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0)
189 goto err;
190 if (BIO_printf(bp, "\n") <= 0)
191 goto err;
192 }
193 else
194 {
195 /* explicit parameters */
196 int is_char_two = 0;
197 point_conversion_form_t form;
198 int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x));
199
200 if (tmp_nid == NID_X9_62_characteristic_two_field)
201 is_char_two = 1;
202
203 if ((p = BN_new()) == NULL || (a = BN_new()) == NULL ||
204 (b = BN_new()) == NULL || (order = BN_new()) == NULL ||
205 (cofactor = BN_new()) == NULL)
206 {
207 reason = ERR_R_MALLOC_FAILURE;
208 goto err;
209 }
210#ifndef OPENSSL_NO_EC2M
211 if (is_char_two)
212 {
213 if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx))
214 {
215 reason = ERR_R_EC_LIB;
216 goto err;
217 }
218 }
219 else /* prime field */
220#endif
221 {
222 if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx))
223 {
224 reason = ERR_R_EC_LIB;
225 goto err;
226 }
227 }
228
229 if ((point = EC_GROUP_get0_generator(x)) == NULL)
230 {
231 reason = ERR_R_EC_LIB;
232 goto err;
233 }
234 if (!EC_GROUP_get_order(x, order, NULL) ||
235 !EC_GROUP_get_cofactor(x, cofactor, NULL))
236 {
237 reason = ERR_R_EC_LIB;
238 goto err;
239 }
240
241 form = EC_GROUP_get_point_conversion_form(x);
242
243 if ((gen = EC_POINT_point2bn(x, point,
244 form, NULL, ctx)) == NULL)
245 {
246 reason = ERR_R_EC_LIB;
247 goto err;
248 }
249
250 buf_len = (size_t)BN_num_bytes(p);
251 if (buf_len < (i = (size_t)BN_num_bytes(a)))
252 buf_len = i;
253 if (buf_len < (i = (size_t)BN_num_bytes(b)))
254 buf_len = i;
255 if (buf_len < (i = (size_t)BN_num_bytes(gen)))
256 buf_len = i;
257 if (buf_len < (i = (size_t)BN_num_bytes(order)))
258 buf_len = i;
259 if (buf_len < (i = (size_t)BN_num_bytes(cofactor)))
260 buf_len = i;
261
262 if ((seed = EC_GROUP_get0_seed(x)) != NULL)
263 seed_len = EC_GROUP_get_seed_len(x);
264
265 buf_len += 10;
266 if ((buffer = OPENSSL_malloc(buf_len)) == NULL)
267 {
268 reason = ERR_R_MALLOC_FAILURE;
269 goto err;
270 }
271
272 if (!BIO_indent(bp, off, 128))
273 goto err;
274
275 /* print the 'short name' of the field type */
276 if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid))
277 <= 0)
278 goto err;
279
280 if (is_char_two)
281 {
282 /* print the 'short name' of the base type OID */
283 int basis_type = EC_GROUP_get_basis_type(x);
284 if (basis_type == 0)
285 goto err;
286
287 if (!BIO_indent(bp, off, 128))
288 goto err;
289
290 if (BIO_printf(bp, "Basis Type: %s\n",
291 OBJ_nid2sn(basis_type)) <= 0)
292 goto err;
293
294 /* print the polynomial */
295 if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer,
296 off))
297 goto err;
298 }
299 else
300 {
301 if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer,off))
302 goto err;
303 }
304 if ((a != NULL) && !ASN1_bn_print(bp, "A: ", a, buffer, off))
305 goto err;
306 if ((b != NULL) && !ASN1_bn_print(bp, "B: ", b, buffer, off))
307 goto err;
308 if (form == POINT_CONVERSION_COMPRESSED)
309 {
310 if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen,
311 buffer, off))
312 goto err;
313 }
314 else if (form == POINT_CONVERSION_UNCOMPRESSED)
315 {
316 if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen,
317 buffer, off))
318 goto err;
319 }
320 else /* form == POINT_CONVERSION_HYBRID */
321 {
322 if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen,
323 buffer, off))
324 goto err;
325 }
326 if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order,
327 buffer, off)) goto err;
328 if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor,
329 buffer, off)) goto err;
330 if (seed && !print_bin(bp, "Seed:", seed, seed_len, off))
331 goto err;
332 }
333 ret=1;
334err:
335 if (!ret)
336 ECerr(EC_F_ECPKPARAMETERS_PRINT, reason);
337 if (p)
338 BN_free(p);
339 if (a)
340 BN_free(a);
341 if (b)
342 BN_free(b);
343 if (gen)
344 BN_free(gen);
345 if (order)
346 BN_free(order);
347 if (cofactor)
348 BN_free(cofactor);
349 if (ctx)
350 BN_CTX_free(ctx);
351 if (buffer != NULL)
352 OPENSSL_free(buffer);
353 return(ret);
354 }
355
356static int print_bin(BIO *fp, const char *name, const unsigned char *buf,
357 size_t len, int off)
358 {
359 size_t i;
360 char str[128];
361
362 if (buf == NULL)
363 return 1;
364 if (off)
365 {
366 if (off > 128)
367 off=128;
368 memset(str,' ',off);
369 if (BIO_write(fp, str, off) <= 0)
370 return 0;
371 }
372
373 if (BIO_printf(fp,"%s", name) <= 0)
374 return 0;
375
376 for (i=0; i<len; i++)
377 {
378 if ((i%15) == 0)
379 {
380 str[0]='\n';
381 memset(&(str[1]),' ',off+4);
382 if (BIO_write(fp, str, off+1+4) <= 0)
383 return 0;
384 }
385 if (BIO_printf(fp,"%02x%s",buf[i],((i+1) == len)?"":":") <= 0)
386 return 0;
387 }
388 if (BIO_write(fp,"\n",1) <= 0)
389 return 0;
390
391 return 1;
392 }
diff --git a/src/lib/libcrypto/ec/ecp_mont.c b/src/lib/libcrypto/ec/ecp_mont.c
new file mode 100644
index 0000000000..9fc4a466a5
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_mont.c
@@ -0,0 +1,315 @@
1/* crypto/ec/ecp_mont.c */
2/*
3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
61 * and contributed to the OpenSSL project.
62 */
63
64#include <openssl/err.h>
65
66#include "ec_lcl.h"
67
68
69const EC_METHOD *EC_GFp_mont_method(void)
70 {
71 static const EC_METHOD ret = {
72 NID_X9_62_prime_field,
73 ec_GFp_mont_group_init,
74 ec_GFp_mont_group_finish,
75 ec_GFp_mont_group_clear_finish,
76 ec_GFp_mont_group_copy,
77 ec_GFp_mont_group_set_curve,
78 ec_GFp_simple_group_get_curve,
79 ec_GFp_simple_group_get_degree,
80 ec_GFp_simple_group_check_discriminant,
81 ec_GFp_simple_point_init,
82 ec_GFp_simple_point_finish,
83 ec_GFp_simple_point_clear_finish,
84 ec_GFp_simple_point_copy,
85 ec_GFp_simple_point_set_to_infinity,
86 ec_GFp_simple_set_Jprojective_coordinates_GFp,
87 ec_GFp_simple_get_Jprojective_coordinates_GFp,
88 ec_GFp_simple_point_set_affine_coordinates,
89 ec_GFp_simple_point_get_affine_coordinates,
90 ec_GFp_simple_set_compressed_coordinates,
91 ec_GFp_simple_point2oct,
92 ec_GFp_simple_oct2point,
93 ec_GFp_simple_add,
94 ec_GFp_simple_dbl,
95 ec_GFp_simple_invert,
96 ec_GFp_simple_is_at_infinity,
97 ec_GFp_simple_is_on_curve,
98 ec_GFp_simple_cmp,
99 ec_GFp_simple_make_affine,
100 ec_GFp_simple_points_make_affine,
101 0 /* mul */,
102 0 /* precompute_mult */,
103 0 /* have_precompute_mult */,
104 ec_GFp_mont_field_mul,
105 ec_GFp_mont_field_sqr,
106 0 /* field_div */,
107 ec_GFp_mont_field_encode,
108 ec_GFp_mont_field_decode,
109 ec_GFp_mont_field_set_to_one };
110
111 return &ret;
112 }
113
114
115int ec_GFp_mont_group_init(EC_GROUP *group)
116 {
117 int ok;
118
119 ok = ec_GFp_simple_group_init(group);
120 group->field_data1 = NULL;
121 group->field_data2 = NULL;
122 return ok;
123 }
124
125
126void ec_GFp_mont_group_finish(EC_GROUP *group)
127 {
128 if (group->field_data1 != NULL)
129 {
130 BN_MONT_CTX_free(group->field_data1);
131 group->field_data1 = NULL;
132 }
133 if (group->field_data2 != NULL)
134 {
135 BN_free(group->field_data2);
136 group->field_data2 = NULL;
137 }
138 ec_GFp_simple_group_finish(group);
139 }
140
141
142void ec_GFp_mont_group_clear_finish(EC_GROUP *group)
143 {
144 if (group->field_data1 != NULL)
145 {
146 BN_MONT_CTX_free(group->field_data1);
147 group->field_data1 = NULL;
148 }
149 if (group->field_data2 != NULL)
150 {
151 BN_clear_free(group->field_data2);
152 group->field_data2 = NULL;
153 }
154 ec_GFp_simple_group_clear_finish(group);
155 }
156
157
158int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src)
159 {
160 if (dest->field_data1 != NULL)
161 {
162 BN_MONT_CTX_free(dest->field_data1);
163 dest->field_data1 = NULL;
164 }
165 if (dest->field_data2 != NULL)
166 {
167 BN_clear_free(dest->field_data2);
168 dest->field_data2 = NULL;
169 }
170
171 if (!ec_GFp_simple_group_copy(dest, src)) return 0;
172
173 if (src->field_data1 != NULL)
174 {
175 dest->field_data1 = BN_MONT_CTX_new();
176 if (dest->field_data1 == NULL) return 0;
177 if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1)) goto err;
178 }
179 if (src->field_data2 != NULL)
180 {
181 dest->field_data2 = BN_dup(src->field_data2);
182 if (dest->field_data2 == NULL) goto err;
183 }
184
185 return 1;
186
187 err:
188 if (dest->field_data1 != NULL)
189 {
190 BN_MONT_CTX_free(dest->field_data1);
191 dest->field_data1 = NULL;
192 }
193 return 0;
194 }
195
196
197int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
198 {
199 BN_CTX *new_ctx = NULL;
200 BN_MONT_CTX *mont = NULL;
201 BIGNUM *one = NULL;
202 int ret = 0;
203
204 if (group->field_data1 != NULL)
205 {
206 BN_MONT_CTX_free(group->field_data1);
207 group->field_data1 = NULL;
208 }
209 if (group->field_data2 != NULL)
210 {
211 BN_free(group->field_data2);
212 group->field_data2 = NULL;
213 }
214
215 if (ctx == NULL)
216 {
217 ctx = new_ctx = BN_CTX_new();
218 if (ctx == NULL)
219 return 0;
220 }
221
222 mont = BN_MONT_CTX_new();
223 if (mont == NULL) goto err;
224 if (!BN_MONT_CTX_set(mont, p, ctx))
225 {
226 ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB);
227 goto err;
228 }
229 one = BN_new();
230 if (one == NULL) goto err;
231 if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) goto err;
232
233 group->field_data1 = mont;
234 mont = NULL;
235 group->field_data2 = one;
236 one = NULL;
237
238 ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
239
240 if (!ret)
241 {
242 BN_MONT_CTX_free(group->field_data1);
243 group->field_data1 = NULL;
244 BN_free(group->field_data2);
245 group->field_data2 = NULL;
246 }
247
248 err:
249 if (new_ctx != NULL)
250 BN_CTX_free(new_ctx);
251 if (mont != NULL)
252 BN_MONT_CTX_free(mont);
253 return ret;
254 }
255
256
257int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
258 {
259 if (group->field_data1 == NULL)
260 {
261 ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED);
262 return 0;
263 }
264
265 return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx);
266 }
267
268
269int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
270 {
271 if (group->field_data1 == NULL)
272 {
273 ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED);
274 return 0;
275 }
276
277 return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx);
278 }
279
280
281int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
282 {
283 if (group->field_data1 == NULL)
284 {
285 ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED);
286 return 0;
287 }
288
289 return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx);
290 }
291
292
293int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
294 {
295 if (group->field_data1 == NULL)
296 {
297 ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED);
298 return 0;
299 }
300
301 return BN_from_montgomery(r, a, group->field_data1, ctx);
302 }
303
304
305int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, BN_CTX *ctx)
306 {
307 if (group->field_data2 == NULL)
308 {
309 ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED);
310 return 0;
311 }
312
313 if (!BN_copy(r, group->field_data2)) return 0;
314 return 1;
315 }
diff --git a/src/lib/libcrypto/ec/ecp_nist.c b/src/lib/libcrypto/ec/ecp_nist.c
new file mode 100644
index 0000000000..2a5682ea41
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_nist.c
@@ -0,0 +1,210 @@
1/* crypto/ec/ecp_nist.c */
2/*
3 * Written by Nils Larsch for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
61 * and contributed to the OpenSSL project.
62 */
63
64#include <limits.h>
65
66#include <openssl/err.h>
67#include <openssl/obj_mac.h>
68#include "ec_lcl.h"
69
70const EC_METHOD *EC_GFp_nist_method(void)
71 {
72 static const EC_METHOD ret = {
73 NID_X9_62_prime_field,
74 ec_GFp_simple_group_init,
75 ec_GFp_simple_group_finish,
76 ec_GFp_simple_group_clear_finish,
77 ec_GFp_nist_group_copy,
78 ec_GFp_nist_group_set_curve,
79 ec_GFp_simple_group_get_curve,
80 ec_GFp_simple_group_get_degree,
81 ec_GFp_simple_group_check_discriminant,
82 ec_GFp_simple_point_init,
83 ec_GFp_simple_point_finish,
84 ec_GFp_simple_point_clear_finish,
85 ec_GFp_simple_point_copy,
86 ec_GFp_simple_point_set_to_infinity,
87 ec_GFp_simple_set_Jprojective_coordinates_GFp,
88 ec_GFp_simple_get_Jprojective_coordinates_GFp,
89 ec_GFp_simple_point_set_affine_coordinates,
90 ec_GFp_simple_point_get_affine_coordinates,
91 ec_GFp_simple_set_compressed_coordinates,
92 ec_GFp_simple_point2oct,
93 ec_GFp_simple_oct2point,
94 ec_GFp_simple_add,
95 ec_GFp_simple_dbl,
96 ec_GFp_simple_invert,
97 ec_GFp_simple_is_at_infinity,
98 ec_GFp_simple_is_on_curve,
99 ec_GFp_simple_cmp,
100 ec_GFp_simple_make_affine,
101 ec_GFp_simple_points_make_affine,
102 0 /* mul */,
103 0 /* precompute_mult */,
104 0 /* have_precompute_mult */,
105 ec_GFp_nist_field_mul,
106 ec_GFp_nist_field_sqr,
107 0 /* field_div */,
108 0 /* field_encode */,
109 0 /* field_decode */,
110 0 /* field_set_to_one */ };
111
112 return &ret;
113 }
114
115int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src)
116 {
117 dest->field_mod_func = src->field_mod_func;
118
119 return ec_GFp_simple_group_copy(dest, src);
120 }
121
122int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p,
123 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
124 {
125 int ret = 0;
126 BN_CTX *new_ctx = NULL;
127 BIGNUM *tmp_bn;
128
129 if (ctx == NULL)
130 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
131
132 BN_CTX_start(ctx);
133 if ((tmp_bn = BN_CTX_get(ctx)) == NULL) goto err;
134
135 if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0)
136 group->field_mod_func = BN_nist_mod_192;
137 else if (BN_ucmp(BN_get0_nist_prime_224(), p) == 0)
138 group->field_mod_func = BN_nist_mod_224;
139 else if (BN_ucmp(BN_get0_nist_prime_256(), p) == 0)
140 group->field_mod_func = BN_nist_mod_256;
141 else if (BN_ucmp(BN_get0_nist_prime_384(), p) == 0)
142 group->field_mod_func = BN_nist_mod_384;
143 else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0)
144 group->field_mod_func = BN_nist_mod_521;
145 else
146 {
147 ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_NIST_PRIME);
148 goto err;
149 }
150
151 ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
152
153 err:
154 BN_CTX_end(ctx);
155 if (new_ctx != NULL)
156 BN_CTX_free(new_ctx);
157 return ret;
158 }
159
160
161int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
162 const BIGNUM *b, BN_CTX *ctx)
163 {
164 int ret=0;
165 BN_CTX *ctx_new=NULL;
166
167 if (!group || !r || !a || !b)
168 {
169 ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_R_PASSED_NULL_PARAMETER);
170 goto err;
171 }
172 if (!ctx)
173 if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err;
174
175 if (!BN_mul(r, a, b, ctx)) goto err;
176 if (!group->field_mod_func(r, r, &group->field, ctx))
177 goto err;
178
179 ret=1;
180err:
181 if (ctx_new)
182 BN_CTX_free(ctx_new);
183 return ret;
184 }
185
186
187int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
188 BN_CTX *ctx)
189 {
190 int ret=0;
191 BN_CTX *ctx_new=NULL;
192
193 if (!group || !r || !a)
194 {
195 ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER);
196 goto err;
197 }
198 if (!ctx)
199 if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err;
200
201 if (!BN_sqr(r, a, ctx)) goto err;
202 if (!group->field_mod_func(r, r, &group->field, ctx))
203 goto err;
204
205 ret=1;
206err:
207 if (ctx_new)
208 BN_CTX_free(ctx_new);
209 return ret;
210 }
diff --git a/src/lib/libcrypto/ec/ecp_nistp224.c b/src/lib/libcrypto/ec/ecp_nistp224.c
new file mode 100644
index 0000000000..b5ff56c252
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_nistp224.c
@@ -0,0 +1,1658 @@
1/* crypto/ec/ecp_nistp224.c */
2/*
3 * Written by Emilia Kasper (Google) for the OpenSSL project.
4 */
5/* Copyright 2011 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 *
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21/*
22 * A 64-bit implementation of the NIST P-224 elliptic curve point multiplication
23 *
24 * Inspired by Daniel J. Bernstein's public domain nistp224 implementation
25 * and Adam Langley's public domain 64-bit C implementation of curve25519
26 */
27
28#include <openssl/opensslconf.h>
29#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
30
31#ifndef OPENSSL_SYS_VMS
32#include <stdint.h>
33#else
34#include <inttypes.h>
35#endif
36
37#include <string.h>
38#include <openssl/err.h>
39#include "ec_lcl.h"
40
41#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
42 /* even with gcc, the typedef won't work for 32-bit platforms */
43 typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit platforms */
44#else
45 #error "Need GCC 3.1 or later to define type uint128_t"
46#endif
47
48typedef uint8_t u8;
49typedef uint64_t u64;
50typedef int64_t s64;
51
52
53/******************************************************************************/
54/* INTERNAL REPRESENTATION OF FIELD ELEMENTS
55 *
56 * Field elements are represented as a_0 + 2^56*a_1 + 2^112*a_2 + 2^168*a_3
57 * using 64-bit coefficients called 'limbs',
58 * and sometimes (for multiplication results) as
59 * b_0 + 2^56*b_1 + 2^112*b_2 + 2^168*b_3 + 2^224*b_4 + 2^280*b_5 + 2^336*b_6
60 * using 128-bit coefficients called 'widelimbs'.
61 * A 4-limb representation is an 'felem';
62 * a 7-widelimb representation is a 'widefelem'.
63 * Even within felems, bits of adjacent limbs overlap, and we don't always
64 * reduce the representations: we ensure that inputs to each felem
65 * multiplication satisfy a_i < 2^60, so outputs satisfy b_i < 4*2^60*2^60,
66 * and fit into a 128-bit word without overflow. The coefficients are then
67 * again partially reduced to obtain an felem satisfying a_i < 2^57.
68 * We only reduce to the unique minimal representation at the end of the
69 * computation.
70 */
71
72typedef uint64_t limb;
73typedef uint128_t widelimb;
74
75typedef limb felem[4];
76typedef widelimb widefelem[7];
77
78/* Field element represented as a byte arrary.
79 * 28*8 = 224 bits is also the group order size for the elliptic curve,
80 * and we also use this type for scalars for point multiplication.
81 */
82typedef u8 felem_bytearray[28];
83
84static const felem_bytearray nistp224_curve_params[5] = {
85 {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
86 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
87 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
88 {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
89 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
90 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE},
91 {0xB4,0x05,0x0A,0x85,0x0C,0x04,0xB3,0xAB,0xF5,0x41, /* b */
92 0x32,0x56,0x50,0x44,0xB0,0xB7,0xD7,0xBF,0xD8,0xBA,
93 0x27,0x0B,0x39,0x43,0x23,0x55,0xFF,0xB4},
94 {0xB7,0x0E,0x0C,0xBD,0x6B,0xB4,0xBF,0x7F,0x32,0x13, /* x */
95 0x90,0xB9,0x4A,0x03,0xC1,0xD3,0x56,0xC2,0x11,0x22,
96 0x34,0x32,0x80,0xD6,0x11,0x5C,0x1D,0x21},
97 {0xbd,0x37,0x63,0x88,0xb5,0xf7,0x23,0xfb,0x4c,0x22, /* y */
98 0xdf,0xe6,0xcd,0x43,0x75,0xa0,0x5a,0x07,0x47,0x64,
99 0x44,0xd5,0x81,0x99,0x85,0x00,0x7e,0x34}
100};
101
102/* Precomputed multiples of the standard generator
103 * Points are given in coordinates (X, Y, Z) where Z normally is 1
104 * (0 for the point at infinity).
105 * For each field element, slice a_0 is word 0, etc.
106 *
107 * The table has 2 * 16 elements, starting with the following:
108 * index | bits | point
109 * ------+---------+------------------------------
110 * 0 | 0 0 0 0 | 0G
111 * 1 | 0 0 0 1 | 1G
112 * 2 | 0 0 1 0 | 2^56G
113 * 3 | 0 0 1 1 | (2^56 + 1)G
114 * 4 | 0 1 0 0 | 2^112G
115 * 5 | 0 1 0 1 | (2^112 + 1)G
116 * 6 | 0 1 1 0 | (2^112 + 2^56)G
117 * 7 | 0 1 1 1 | (2^112 + 2^56 + 1)G
118 * 8 | 1 0 0 0 | 2^168G
119 * 9 | 1 0 0 1 | (2^168 + 1)G
120 * 10 | 1 0 1 0 | (2^168 + 2^56)G
121 * 11 | 1 0 1 1 | (2^168 + 2^56 + 1)G
122 * 12 | 1 1 0 0 | (2^168 + 2^112)G
123 * 13 | 1 1 0 1 | (2^168 + 2^112 + 1)G
124 * 14 | 1 1 1 0 | (2^168 + 2^112 + 2^56)G
125 * 15 | 1 1 1 1 | (2^168 + 2^112 + 2^56 + 1)G
126 * followed by a copy of this with each element multiplied by 2^28.
127 *
128 * The reason for this is so that we can clock bits into four different
129 * locations when doing simple scalar multiplies against the base point,
130 * and then another four locations using the second 16 elements.
131 */
132static const felem gmul[2][16][3] =
133{{{{0, 0, 0, 0},
134 {0, 0, 0, 0},
135 {0, 0, 0, 0}},
136 {{0x3280d6115c1d21, 0xc1d356c2112234, 0x7f321390b94a03, 0xb70e0cbd6bb4bf},
137 {0xd5819985007e34, 0x75a05a07476444, 0xfb4c22dfe6cd43, 0xbd376388b5f723},
138 {1, 0, 0, 0}},
139 {{0xfd9675666ebbe9, 0xbca7664d40ce5e, 0x2242df8d8a2a43, 0x1f49bbb0f99bc5},
140 {0x29e0b892dc9c43, 0xece8608436e662, 0xdc858f185310d0, 0x9812dd4eb8d321},
141 {1, 0, 0, 0}},
142 {{0x6d3e678d5d8eb8, 0x559eed1cb362f1, 0x16e9a3bbce8a3f, 0xeedcccd8c2a748},
143 {0xf19f90ed50266d, 0xabf2b4bf65f9df, 0x313865468fafec, 0x5cb379ba910a17},
144 {1, 0, 0, 0}},
145 {{0x0641966cab26e3, 0x91fb2991fab0a0, 0xefec27a4e13a0b, 0x0499aa8a5f8ebe},
146 {0x7510407766af5d, 0x84d929610d5450, 0x81d77aae82f706, 0x6916f6d4338c5b},
147 {1, 0, 0, 0}},
148 {{0xea95ac3b1f15c6, 0x086000905e82d4, 0xdd323ae4d1c8b1, 0x932b56be7685a3},
149 {0x9ef93dea25dbbf, 0x41665960f390f0, 0xfdec76dbe2a8a7, 0x523e80f019062a},
150 {1, 0, 0, 0}},
151 {{0x822fdd26732c73, 0xa01c83531b5d0f, 0x363f37347c1ba4, 0xc391b45c84725c},
152 {0xbbd5e1b2d6ad24, 0xddfbcde19dfaec, 0xc393da7e222a7f, 0x1efb7890ede244},
153 {1, 0, 0, 0}},
154 {{0x4c9e90ca217da1, 0xd11beca79159bb, 0xff8d33c2c98b7c, 0x2610b39409f849},
155 {0x44d1352ac64da0, 0xcdbb7b2c46b4fb, 0x966c079b753c89, 0xfe67e4e820b112},
156 {1, 0, 0, 0}},
157 {{0xe28cae2df5312d, 0xc71b61d16f5c6e, 0x79b7619a3e7c4c, 0x05c73240899b47},
158 {0x9f7f6382c73e3a, 0x18615165c56bda, 0x641fab2116fd56, 0x72855882b08394},
159 {1, 0, 0, 0}},
160 {{0x0469182f161c09, 0x74a98ca8d00fb5, 0xb89da93489a3e0, 0x41c98768fb0c1d},
161 {0xe5ea05fb32da81, 0x3dce9ffbca6855, 0x1cfe2d3fbf59e6, 0x0e5e03408738a7},
162 {1, 0, 0, 0}},
163 {{0xdab22b2333e87f, 0x4430137a5dd2f6, 0xe03ab9f738beb8, 0xcb0c5d0dc34f24},
164 {0x764a7df0c8fda5, 0x185ba5c3fa2044, 0x9281d688bcbe50, 0xc40331df893881},
165 {1, 0, 0, 0}},
166 {{0xb89530796f0f60, 0xade92bd26909a3, 0x1a0c83fb4884da, 0x1765bf22a5a984},
167 {0x772a9ee75db09e, 0x23bc6c67cec16f, 0x4c1edba8b14e2f, 0xe2a215d9611369},
168 {1, 0, 0, 0}},
169 {{0x571e509fb5efb3, 0xade88696410552, 0xc8ae85fada74fe, 0x6c7e4be83bbde3},
170 {0xff9f51160f4652, 0xb47ce2495a6539, 0xa2946c53b582f4, 0x286d2db3ee9a60},
171 {1, 0, 0, 0}},
172 {{0x40bbd5081a44af, 0x0995183b13926c, 0xbcefba6f47f6d0, 0x215619e9cc0057},
173 {0x8bc94d3b0df45e, 0xf11c54a3694f6f, 0x8631b93cdfe8b5, 0xe7e3f4b0982db9},
174 {1, 0, 0, 0}},
175 {{0xb17048ab3e1c7b, 0xac38f36ff8a1d8, 0x1c29819435d2c6, 0xc813132f4c07e9},
176 {0x2891425503b11f, 0x08781030579fea, 0xf5426ba5cc9674, 0x1e28ebf18562bc},
177 {1, 0, 0, 0}},
178 {{0x9f31997cc864eb, 0x06cd91d28b5e4c, 0xff17036691a973, 0xf1aef351497c58},
179 {0xdd1f2d600564ff, 0xdead073b1402db, 0x74a684435bd693, 0xeea7471f962558},
180 {1, 0, 0, 0}}},
181 {{{0, 0, 0, 0},
182 {0, 0, 0, 0},
183 {0, 0, 0, 0}},
184 {{0x9665266dddf554, 0x9613d78b60ef2d, 0xce27a34cdba417, 0xd35ab74d6afc31},
185 {0x85ccdd22deb15e, 0x2137e5783a6aab, 0xa141cffd8c93c6, 0x355a1830e90f2d},
186 {1, 0, 0, 0}},
187 {{0x1a494eadaade65, 0xd6da4da77fe53c, 0xe7992996abec86, 0x65c3553c6090e3},
188 {0xfa610b1fb09346, 0xf1c6540b8a4aaf, 0xc51a13ccd3cbab, 0x02995b1b18c28a},
189 {1, 0, 0, 0}},
190 {{0x7874568e7295ef, 0x86b419fbe38d04, 0xdc0690a7550d9a, 0xd3966a44beac33},
191 {0x2b7280ec29132f, 0xbeaa3b6a032df3, 0xdc7dd88ae41200, 0xd25e2513e3a100},
192 {1, 0, 0, 0}},
193 {{0x924857eb2efafd, 0xac2bce41223190, 0x8edaa1445553fc, 0x825800fd3562d5},
194 {0x8d79148ea96621, 0x23a01c3dd9ed8d, 0xaf8b219f9416b5, 0xd8db0cc277daea},
195 {1, 0, 0, 0}},
196 {{0x76a9c3b1a700f0, 0xe9acd29bc7e691, 0x69212d1a6b0327, 0x6322e97fe154be},
197 {0x469fc5465d62aa, 0x8d41ed18883b05, 0x1f8eae66c52b88, 0xe4fcbe9325be51},
198 {1, 0, 0, 0}},
199 {{0x825fdf583cac16, 0x020b857c7b023a, 0x683c17744b0165, 0x14ffd0a2daf2f1},
200 {0x323b36184218f9, 0x4944ec4e3b47d4, 0xc15b3080841acf, 0x0bced4b01a28bb},
201 {1, 0, 0, 0}},
202 {{0x92ac22230df5c4, 0x52f33b4063eda8, 0xcb3f19870c0c93, 0x40064f2ba65233},
203 {0xfe16f0924f8992, 0x012da25af5b517, 0x1a57bb24f723a6, 0x06f8bc76760def},
204 {1, 0, 0, 0}},
205 {{0x4a7084f7817cb9, 0xbcab0738ee9a78, 0x3ec11e11d9c326, 0xdc0fe90e0f1aae},
206 {0xcf639ea5f98390, 0x5c350aa22ffb74, 0x9afae98a4047b7, 0x956ec2d617fc45},
207 {1, 0, 0, 0}},
208 {{0x4306d648c1be6a, 0x9247cd8bc9a462, 0xf5595e377d2f2e, 0xbd1c3caff1a52e},
209 {0x045e14472409d0, 0x29f3e17078f773, 0x745a602b2d4f7d, 0x191837685cdfbb},
210 {1, 0, 0, 0}},
211 {{0x5b6ee254a8cb79, 0x4953433f5e7026, 0xe21faeb1d1def4, 0xc4c225785c09de},
212 {0x307ce7bba1e518, 0x31b125b1036db8, 0x47e91868839e8f, 0xc765866e33b9f3},
213 {1, 0, 0, 0}},
214 {{0x3bfece24f96906, 0x4794da641e5093, 0xde5df64f95db26, 0x297ecd89714b05},
215 {0x701bd3ebb2c3aa, 0x7073b4f53cb1d5, 0x13c5665658af16, 0x9895089d66fe58},
216 {1, 0, 0, 0}},
217 {{0x0fef05f78c4790, 0x2d773633b05d2e, 0x94229c3a951c94, 0xbbbd70df4911bb},
218 {0xb2c6963d2c1168, 0x105f47a72b0d73, 0x9fdf6111614080, 0x7b7e94b39e67b0},
219 {1, 0, 0, 0}},
220 {{0xad1a7d6efbe2b3, 0xf012482c0da69d, 0x6b3bdf12438345, 0x40d7558d7aa4d9},
221 {0x8a09fffb5c6d3d, 0x9a356e5d9ffd38, 0x5973f15f4f9b1c, 0xdcd5f59f63c3ea},
222 {1, 0, 0, 0}},
223 {{0xacf39f4c5ca7ab, 0x4c8071cc5fd737, 0xc64e3602cd1184, 0x0acd4644c9abba},
224 {0x6c011a36d8bf6e, 0xfecd87ba24e32a, 0x19f6f56574fad8, 0x050b204ced9405},
225 {1, 0, 0, 0}},
226 {{0xed4f1cae7d9a96, 0x5ceef7ad94c40a, 0x778e4a3bf3ef9b, 0x7405783dc3b55e},
227 {0x32477c61b6e8c6, 0xb46a97570f018b, 0x91176d0a7e95d1, 0x3df90fbc4c7d0e},
228 {1, 0, 0, 0}}}};
229
230/* Precomputation for the group generator. */
231typedef struct {
232 felem g_pre_comp[2][16][3];
233 int references;
234} NISTP224_PRE_COMP;
235
236const EC_METHOD *EC_GFp_nistp224_method(void)
237 {
238 static const EC_METHOD ret = {
239 EC_FLAGS_DEFAULT_OCT,
240 NID_X9_62_prime_field,
241 ec_GFp_nistp224_group_init,
242 ec_GFp_simple_group_finish,
243 ec_GFp_simple_group_clear_finish,
244 ec_GFp_nist_group_copy,
245 ec_GFp_nistp224_group_set_curve,
246 ec_GFp_simple_group_get_curve,
247 ec_GFp_simple_group_get_degree,
248 ec_GFp_simple_group_check_discriminant,
249 ec_GFp_simple_point_init,
250 ec_GFp_simple_point_finish,
251 ec_GFp_simple_point_clear_finish,
252 ec_GFp_simple_point_copy,
253 ec_GFp_simple_point_set_to_infinity,
254 ec_GFp_simple_set_Jprojective_coordinates_GFp,
255 ec_GFp_simple_get_Jprojective_coordinates_GFp,
256 ec_GFp_simple_point_set_affine_coordinates,
257 ec_GFp_nistp224_point_get_affine_coordinates,
258 0 /* point_set_compressed_coordinates */,
259 0 /* point2oct */,
260 0 /* oct2point */,
261 ec_GFp_simple_add,
262 ec_GFp_simple_dbl,
263 ec_GFp_simple_invert,
264 ec_GFp_simple_is_at_infinity,
265 ec_GFp_simple_is_on_curve,
266 ec_GFp_simple_cmp,
267 ec_GFp_simple_make_affine,
268 ec_GFp_simple_points_make_affine,
269 ec_GFp_nistp224_points_mul,
270 ec_GFp_nistp224_precompute_mult,
271 ec_GFp_nistp224_have_precompute_mult,
272 ec_GFp_nist_field_mul,
273 ec_GFp_nist_field_sqr,
274 0 /* field_div */,
275 0 /* field_encode */,
276 0 /* field_decode */,
277 0 /* field_set_to_one */ };
278
279 return &ret;
280 }
281
282/* Helper functions to convert field elements to/from internal representation */
283static void bin28_to_felem(felem out, const u8 in[28])
284 {
285 out[0] = *((const uint64_t *)(in)) & 0x00ffffffffffffff;
286 out[1] = (*((const uint64_t *)(in+7))) & 0x00ffffffffffffff;
287 out[2] = (*((const uint64_t *)(in+14))) & 0x00ffffffffffffff;
288 out[3] = (*((const uint64_t *)(in+21))) & 0x00ffffffffffffff;
289 }
290
291static void felem_to_bin28(u8 out[28], const felem in)
292 {
293 unsigned i;
294 for (i = 0; i < 7; ++i)
295 {
296 out[i] = in[0]>>(8*i);
297 out[i+7] = in[1]>>(8*i);
298 out[i+14] = in[2]>>(8*i);
299 out[i+21] = in[3]>>(8*i);
300 }
301 }
302
303/* To preserve endianness when using BN_bn2bin and BN_bin2bn */
304static void flip_endian(u8 *out, const u8 *in, unsigned len)
305 {
306 unsigned i;
307 for (i = 0; i < len; ++i)
308 out[i] = in[len-1-i];
309 }
310
311/* From OpenSSL BIGNUM to internal representation */
312static int BN_to_felem(felem out, const BIGNUM *bn)
313 {
314 felem_bytearray b_in;
315 felem_bytearray b_out;
316 unsigned num_bytes;
317
318 /* BN_bn2bin eats leading zeroes */
319 memset(b_out, 0, sizeof b_out);
320 num_bytes = BN_num_bytes(bn);
321 if (num_bytes > sizeof b_out)
322 {
323 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
324 return 0;
325 }
326 if (BN_is_negative(bn))
327 {
328 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
329 return 0;
330 }
331 num_bytes = BN_bn2bin(bn, b_in);
332 flip_endian(b_out, b_in, num_bytes);
333 bin28_to_felem(out, b_out);
334 return 1;
335 }
336
337/* From internal representation to OpenSSL BIGNUM */
338static BIGNUM *felem_to_BN(BIGNUM *out, const felem in)
339 {
340 felem_bytearray b_in, b_out;
341 felem_to_bin28(b_in, in);
342 flip_endian(b_out, b_in, sizeof b_out);
343 return BN_bin2bn(b_out, sizeof b_out, out);
344 }
345
346/******************************************************************************/
347/* FIELD OPERATIONS
348 *
349 * Field operations, using the internal representation of field elements.
350 * NB! These operations are specific to our point multiplication and cannot be
351 * expected to be correct in general - e.g., multiplication with a large scalar
352 * will cause an overflow.
353 *
354 */
355
356static void felem_one(felem out)
357 {
358 out[0] = 1;
359 out[1] = 0;
360 out[2] = 0;
361 out[3] = 0;
362 }
363
364static void felem_assign(felem out, const felem in)
365 {
366 out[0] = in[0];
367 out[1] = in[1];
368 out[2] = in[2];
369 out[3] = in[3];
370 }
371
372/* Sum two field elements: out += in */
373static void felem_sum(felem out, const felem in)
374 {
375 out[0] += in[0];
376 out[1] += in[1];
377 out[2] += in[2];
378 out[3] += in[3];
379 }
380
381/* Get negative value: out = -in */
382/* Assumes in[i] < 2^57 */
383static void felem_neg(felem out, const felem in)
384 {
385 static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2);
386 static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2);
387 static const limb two58m42m2 = (((limb) 1) << 58) -
388 (((limb) 1) << 42) - (((limb) 1) << 2);
389
390 /* Set to 0 mod 2^224-2^96+1 to ensure out > in */
391 out[0] = two58p2 - in[0];
392 out[1] = two58m42m2 - in[1];
393 out[2] = two58m2 - in[2];
394 out[3] = two58m2 - in[3];
395 }
396
397/* Subtract field elements: out -= in */
398/* Assumes in[i] < 2^57 */
399static void felem_diff(felem out, const felem in)
400 {
401 static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2);
402 static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2);
403 static const limb two58m42m2 = (((limb) 1) << 58) -
404 (((limb) 1) << 42) - (((limb) 1) << 2);
405
406 /* Add 0 mod 2^224-2^96+1 to ensure out > in */
407 out[0] += two58p2;
408 out[1] += two58m42m2;
409 out[2] += two58m2;
410 out[3] += two58m2;
411
412 out[0] -= in[0];
413 out[1] -= in[1];
414 out[2] -= in[2];
415 out[3] -= in[3];
416 }
417
418/* Subtract in unreduced 128-bit mode: out -= in */
419/* Assumes in[i] < 2^119 */
420static void widefelem_diff(widefelem out, const widefelem in)
421 {
422 static const widelimb two120 = ((widelimb) 1) << 120;
423 static const widelimb two120m64 = (((widelimb) 1) << 120) -
424 (((widelimb) 1) << 64);
425 static const widelimb two120m104m64 = (((widelimb) 1) << 120) -
426 (((widelimb) 1) << 104) - (((widelimb) 1) << 64);
427
428 /* Add 0 mod 2^224-2^96+1 to ensure out > in */
429 out[0] += two120;
430 out[1] += two120m64;
431 out[2] += two120m64;
432 out[3] += two120;
433 out[4] += two120m104m64;
434 out[5] += two120m64;
435 out[6] += two120m64;
436
437 out[0] -= in[0];
438 out[1] -= in[1];
439 out[2] -= in[2];
440 out[3] -= in[3];
441 out[4] -= in[4];
442 out[5] -= in[5];
443 out[6] -= in[6];
444 }
445
446/* Subtract in mixed mode: out128 -= in64 */
447/* in[i] < 2^63 */
448static void felem_diff_128_64(widefelem out, const felem in)
449 {
450 static const widelimb two64p8 = (((widelimb) 1) << 64) +
451 (((widelimb) 1) << 8);
452 static const widelimb two64m8 = (((widelimb) 1) << 64) -
453 (((widelimb) 1) << 8);
454 static const widelimb two64m48m8 = (((widelimb) 1) << 64) -
455 (((widelimb) 1) << 48) - (((widelimb) 1) << 8);
456
457 /* Add 0 mod 2^224-2^96+1 to ensure out > in */
458 out[0] += two64p8;
459 out[1] += two64m48m8;
460 out[2] += two64m8;
461 out[3] += two64m8;
462
463 out[0] -= in[0];
464 out[1] -= in[1];
465 out[2] -= in[2];
466 out[3] -= in[3];
467 }
468
469/* Multiply a field element by a scalar: out = out * scalar
470 * The scalars we actually use are small, so results fit without overflow */
471static void felem_scalar(felem out, const limb scalar)
472 {
473 out[0] *= scalar;
474 out[1] *= scalar;
475 out[2] *= scalar;
476 out[3] *= scalar;
477 }
478
479/* Multiply an unreduced field element by a scalar: out = out * scalar
480 * The scalars we actually use are small, so results fit without overflow */
481static void widefelem_scalar(widefelem out, const widelimb scalar)
482 {
483 out[0] *= scalar;
484 out[1] *= scalar;
485 out[2] *= scalar;
486 out[3] *= scalar;
487 out[4] *= scalar;
488 out[5] *= scalar;
489 out[6] *= scalar;
490 }
491
492/* Square a field element: out = in^2 */
493static void felem_square(widefelem out, const felem in)
494 {
495 limb tmp0, tmp1, tmp2;
496 tmp0 = 2 * in[0]; tmp1 = 2 * in[1]; tmp2 = 2 * in[2];
497 out[0] = ((widelimb) in[0]) * in[0];
498 out[1] = ((widelimb) in[0]) * tmp1;
499 out[2] = ((widelimb) in[0]) * tmp2 + ((widelimb) in[1]) * in[1];
500 out[3] = ((widelimb) in[3]) * tmp0 +
501 ((widelimb) in[1]) * tmp2;
502 out[4] = ((widelimb) in[3]) * tmp1 + ((widelimb) in[2]) * in[2];
503 out[5] = ((widelimb) in[3]) * tmp2;
504 out[6] = ((widelimb) in[3]) * in[3];
505 }
506
507/* Multiply two field elements: out = in1 * in2 */
508static void felem_mul(widefelem out, const felem in1, const felem in2)
509 {
510 out[0] = ((widelimb) in1[0]) * in2[0];
511 out[1] = ((widelimb) in1[0]) * in2[1] + ((widelimb) in1[1]) * in2[0];
512 out[2] = ((widelimb) in1[0]) * in2[2] + ((widelimb) in1[1]) * in2[1] +
513 ((widelimb) in1[2]) * in2[0];
514 out[3] = ((widelimb) in1[0]) * in2[3] + ((widelimb) in1[1]) * in2[2] +
515 ((widelimb) in1[2]) * in2[1] + ((widelimb) in1[3]) * in2[0];
516 out[4] = ((widelimb) in1[1]) * in2[3] + ((widelimb) in1[2]) * in2[2] +
517 ((widelimb) in1[3]) * in2[1];
518 out[5] = ((widelimb) in1[2]) * in2[3] + ((widelimb) in1[3]) * in2[2];
519 out[6] = ((widelimb) in1[3]) * in2[3];
520 }
521
522/* Reduce seven 128-bit coefficients to four 64-bit coefficients.
523 * Requires in[i] < 2^126,
524 * ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16 */
525static void felem_reduce(felem out, const widefelem in)
526 {
527 static const widelimb two127p15 = (((widelimb) 1) << 127) +
528 (((widelimb) 1) << 15);
529 static const widelimb two127m71 = (((widelimb) 1) << 127) -
530 (((widelimb) 1) << 71);
531 static const widelimb two127m71m55 = (((widelimb) 1) << 127) -
532 (((widelimb) 1) << 71) - (((widelimb) 1) << 55);
533 widelimb output[5];
534
535 /* Add 0 mod 2^224-2^96+1 to ensure all differences are positive */
536 output[0] = in[0] + two127p15;
537 output[1] = in[1] + two127m71m55;
538 output[2] = in[2] + two127m71;
539 output[3] = in[3];
540 output[4] = in[4];
541
542 /* Eliminate in[4], in[5], in[6] */
543 output[4] += in[6] >> 16;
544 output[3] += (in[6] & 0xffff) << 40;
545 output[2] -= in[6];
546
547 output[3] += in[5] >> 16;
548 output[2] += (in[5] & 0xffff) << 40;
549 output[1] -= in[5];
550
551 output[2] += output[4] >> 16;
552 output[1] += (output[4] & 0xffff) << 40;
553 output[0] -= output[4];
554
555 /* Carry 2 -> 3 -> 4 */
556 output[3] += output[2] >> 56;
557 output[2] &= 0x00ffffffffffffff;
558
559 output[4] = output[3] >> 56;
560 output[3] &= 0x00ffffffffffffff;
561
562 /* Now output[2] < 2^56, output[3] < 2^56, output[4] < 2^72 */
563
564 /* Eliminate output[4] */
565 output[2] += output[4] >> 16;
566 /* output[2] < 2^56 + 2^56 = 2^57 */
567 output[1] += (output[4] & 0xffff) << 40;
568 output[0] -= output[4];
569
570 /* Carry 0 -> 1 -> 2 -> 3 */
571 output[1] += output[0] >> 56;
572 out[0] = output[0] & 0x00ffffffffffffff;
573
574 output[2] += output[1] >> 56;
575 /* output[2] < 2^57 + 2^72 */
576 out[1] = output[1] & 0x00ffffffffffffff;
577 output[3] += output[2] >> 56;
578 /* output[3] <= 2^56 + 2^16 */
579 out[2] = output[2] & 0x00ffffffffffffff;
580
581 /* out[0] < 2^56, out[1] < 2^56, out[2] < 2^56,
582 * out[3] <= 2^56 + 2^16 (due to final carry),
583 * so out < 2*p */
584 out[3] = output[3];
585 }
586
587static void felem_square_reduce(felem out, const felem in)
588 {
589 widefelem tmp;
590 felem_square(tmp, in);
591 felem_reduce(out, tmp);
592 }
593
594static void felem_mul_reduce(felem out, const felem in1, const felem in2)
595 {
596 widefelem tmp;
597 felem_mul(tmp, in1, in2);
598 felem_reduce(out, tmp);
599 }
600
601/* Reduce to unique minimal representation.
602 * Requires 0 <= in < 2*p (always call felem_reduce first) */
603static void felem_contract(felem out, const felem in)
604 {
605 static const int64_t two56 = ((limb) 1) << 56;
606 /* 0 <= in < 2*p, p = 2^224 - 2^96 + 1 */
607 /* if in > p , reduce in = in - 2^224 + 2^96 - 1 */
608 int64_t tmp[4], a;
609 tmp[0] = in[0];
610 tmp[1] = in[1];
611 tmp[2] = in[2];
612 tmp[3] = in[3];
613 /* Case 1: a = 1 iff in >= 2^224 */
614 a = (in[3] >> 56);
615 tmp[0] -= a;
616 tmp[1] += a << 40;
617 tmp[3] &= 0x00ffffffffffffff;
618 /* Case 2: a = 0 iff p <= in < 2^224, i.e.,
619 * the high 128 bits are all 1 and the lower part is non-zero */
620 a = ((in[3] & in[2] & (in[1] | 0x000000ffffffffff)) + 1) |
621 (((int64_t)(in[0] + (in[1] & 0x000000ffffffffff)) - 1) >> 63);
622 a &= 0x00ffffffffffffff;
623 /* turn a into an all-one mask (if a = 0) or an all-zero mask */
624 a = (a - 1) >> 63;
625 /* subtract 2^224 - 2^96 + 1 if a is all-one*/
626 tmp[3] &= a ^ 0xffffffffffffffff;
627 tmp[2] &= a ^ 0xffffffffffffffff;
628 tmp[1] &= (a ^ 0xffffffffffffffff) | 0x000000ffffffffff;
629 tmp[0] -= 1 & a;
630
631 /* eliminate negative coefficients: if tmp[0] is negative, tmp[1] must
632 * be non-zero, so we only need one step */
633 a = tmp[0] >> 63;
634 tmp[0] += two56 & a;
635 tmp[1] -= 1 & a;
636
637 /* carry 1 -> 2 -> 3 */
638 tmp[2] += tmp[1] >> 56;
639 tmp[1] &= 0x00ffffffffffffff;
640
641 tmp[3] += tmp[2] >> 56;
642 tmp[2] &= 0x00ffffffffffffff;
643
644 /* Now 0 <= out < p */
645 out[0] = tmp[0];
646 out[1] = tmp[1];
647 out[2] = tmp[2];
648 out[3] = tmp[3];
649 }
650
651/* Zero-check: returns 1 if input is 0, and 0 otherwise.
652 * We know that field elements are reduced to in < 2^225,
653 * so we only need to check three cases: 0, 2^224 - 2^96 + 1,
654 * and 2^225 - 2^97 + 2 */
655static limb felem_is_zero(const felem in)
656 {
657 limb zero, two224m96p1, two225m97p2;
658
659 zero = in[0] | in[1] | in[2] | in[3];
660 zero = (((int64_t)(zero) - 1) >> 63) & 1;
661 two224m96p1 = (in[0] ^ 1) | (in[1] ^ 0x00ffff0000000000)
662 | (in[2] ^ 0x00ffffffffffffff) | (in[3] ^ 0x00ffffffffffffff);
663 two224m96p1 = (((int64_t)(two224m96p1) - 1) >> 63) & 1;
664 two225m97p2 = (in[0] ^ 2) | (in[1] ^ 0x00fffe0000000000)
665 | (in[2] ^ 0x00ffffffffffffff) | (in[3] ^ 0x01ffffffffffffff);
666 two225m97p2 = (((int64_t)(two225m97p2) - 1) >> 63) & 1;
667 return (zero | two224m96p1 | two225m97p2);
668 }
669
670static limb felem_is_zero_int(const felem in)
671 {
672 return (int) (felem_is_zero(in) & ((limb)1));
673 }
674
675/* Invert a field element */
676/* Computation chain copied from djb's code */
677static void felem_inv(felem out, const felem in)
678 {
679 felem ftmp, ftmp2, ftmp3, ftmp4;
680 widefelem tmp;
681 unsigned i;
682
683 felem_square(tmp, in); felem_reduce(ftmp, tmp); /* 2 */
684 felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^2 - 1 */
685 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2 */
686 felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 1 */
687 felem_square(tmp, ftmp); felem_reduce(ftmp2, tmp); /* 2^4 - 2 */
688 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^5 - 4 */
689 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^6 - 8 */
690 felem_mul(tmp, ftmp2, ftmp); felem_reduce(ftmp, tmp); /* 2^6 - 1 */
691 felem_square(tmp, ftmp); felem_reduce(ftmp2, tmp); /* 2^7 - 2 */
692 for (i = 0; i < 5; ++i) /* 2^12 - 2^6 */
693 {
694 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp);
695 }
696 felem_mul(tmp, ftmp2, ftmp); felem_reduce(ftmp2, tmp); /* 2^12 - 1 */
697 felem_square(tmp, ftmp2); felem_reduce(ftmp3, tmp); /* 2^13 - 2 */
698 for (i = 0; i < 11; ++i) /* 2^24 - 2^12 */
699 {
700 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp);
701 }
702 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp2, tmp); /* 2^24 - 1 */
703 felem_square(tmp, ftmp2); felem_reduce(ftmp3, tmp); /* 2^25 - 2 */
704 for (i = 0; i < 23; ++i) /* 2^48 - 2^24 */
705 {
706 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp);
707 }
708 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^48 - 1 */
709 felem_square(tmp, ftmp3); felem_reduce(ftmp4, tmp); /* 2^49 - 2 */
710 for (i = 0; i < 47; ++i) /* 2^96 - 2^48 */
711 {
712 felem_square(tmp, ftmp4); felem_reduce(ftmp4, tmp);
713 }
714 felem_mul(tmp, ftmp3, ftmp4); felem_reduce(ftmp3, tmp); /* 2^96 - 1 */
715 felem_square(tmp, ftmp3); felem_reduce(ftmp4, tmp); /* 2^97 - 2 */
716 for (i = 0; i < 23; ++i) /* 2^120 - 2^24 */
717 {
718 felem_square(tmp, ftmp4); felem_reduce(ftmp4, tmp);
719 }
720 felem_mul(tmp, ftmp2, ftmp4); felem_reduce(ftmp2, tmp); /* 2^120 - 1 */
721 for (i = 0; i < 6; ++i) /* 2^126 - 2^6 */
722 {
723 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp);
724 }
725 felem_mul(tmp, ftmp2, ftmp); felem_reduce(ftmp, tmp); /* 2^126 - 1 */
726 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^127 - 2 */
727 felem_mul(tmp, ftmp, in); felem_reduce(ftmp, tmp); /* 2^127 - 1 */
728 for (i = 0; i < 97; ++i) /* 2^224 - 2^97 */
729 {
730 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp);
731 }
732 felem_mul(tmp, ftmp, ftmp3); felem_reduce(out, tmp); /* 2^224 - 2^96 - 1 */
733 }
734
735/* Copy in constant time:
736 * if icopy == 1, copy in to out,
737 * if icopy == 0, copy out to itself. */
738static void
739copy_conditional(felem out, const felem in, limb icopy)
740 {
741 unsigned i;
742 /* icopy is a (64-bit) 0 or 1, so copy is either all-zero or all-one */
743 const limb copy = -icopy;
744 for (i = 0; i < 4; ++i)
745 {
746 const limb tmp = copy & (in[i] ^ out[i]);
747 out[i] ^= tmp;
748 }
749 }
750
751/******************************************************************************/
752/* ELLIPTIC CURVE POINT OPERATIONS
753 *
754 * Points are represented in Jacobian projective coordinates:
755 * (X, Y, Z) corresponds to the affine point (X/Z^2, Y/Z^3),
756 * or to the point at infinity if Z == 0.
757 *
758 */
759
760/* Double an elliptic curve point:
761 * (X', Y', Z') = 2 * (X, Y, Z), where
762 * X' = (3 * (X - Z^2) * (X + Z^2))^2 - 8 * X * Y^2
763 * Y' = 3 * (X - Z^2) * (X + Z^2) * (4 * X * Y^2 - X') - 8 * Y^2
764 * Z' = (Y + Z)^2 - Y^2 - Z^2 = 2 * Y * Z
765 * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed,
766 * while x_out == y_in is not (maybe this works, but it's not tested). */
767static void
768point_double(felem x_out, felem y_out, felem z_out,
769 const felem x_in, const felem y_in, const felem z_in)
770 {
771 widefelem tmp, tmp2;
772 felem delta, gamma, beta, alpha, ftmp, ftmp2;
773
774 felem_assign(ftmp, x_in);
775 felem_assign(ftmp2, x_in);
776
777 /* delta = z^2 */
778 felem_square(tmp, z_in);
779 felem_reduce(delta, tmp);
780
781 /* gamma = y^2 */
782 felem_square(tmp, y_in);
783 felem_reduce(gamma, tmp);
784
785 /* beta = x*gamma */
786 felem_mul(tmp, x_in, gamma);
787 felem_reduce(beta, tmp);
788
789 /* alpha = 3*(x-delta)*(x+delta) */
790 felem_diff(ftmp, delta);
791 /* ftmp[i] < 2^57 + 2^58 + 2 < 2^59 */
792 felem_sum(ftmp2, delta);
793 /* ftmp2[i] < 2^57 + 2^57 = 2^58 */
794 felem_scalar(ftmp2, 3);
795 /* ftmp2[i] < 3 * 2^58 < 2^60 */
796 felem_mul(tmp, ftmp, ftmp2);
797 /* tmp[i] < 2^60 * 2^59 * 4 = 2^121 */
798 felem_reduce(alpha, tmp);
799
800 /* x' = alpha^2 - 8*beta */
801 felem_square(tmp, alpha);
802 /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */
803 felem_assign(ftmp, beta);
804 felem_scalar(ftmp, 8);
805 /* ftmp[i] < 8 * 2^57 = 2^60 */
806 felem_diff_128_64(tmp, ftmp);
807 /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */
808 felem_reduce(x_out, tmp);
809
810 /* z' = (y + z)^2 - gamma - delta */
811 felem_sum(delta, gamma);
812 /* delta[i] < 2^57 + 2^57 = 2^58 */
813 felem_assign(ftmp, y_in);
814 felem_sum(ftmp, z_in);
815 /* ftmp[i] < 2^57 + 2^57 = 2^58 */
816 felem_square(tmp, ftmp);
817 /* tmp[i] < 4 * 2^58 * 2^58 = 2^118 */
818 felem_diff_128_64(tmp, delta);
819 /* tmp[i] < 2^118 + 2^64 + 8 < 2^119 */
820 felem_reduce(z_out, tmp);
821
822 /* y' = alpha*(4*beta - x') - 8*gamma^2 */
823 felem_scalar(beta, 4);
824 /* beta[i] < 4 * 2^57 = 2^59 */
825 felem_diff(beta, x_out);
826 /* beta[i] < 2^59 + 2^58 + 2 < 2^60 */
827 felem_mul(tmp, alpha, beta);
828 /* tmp[i] < 4 * 2^57 * 2^60 = 2^119 */
829 felem_square(tmp2, gamma);
830 /* tmp2[i] < 4 * 2^57 * 2^57 = 2^116 */
831 widefelem_scalar(tmp2, 8);
832 /* tmp2[i] < 8 * 2^116 = 2^119 */
833 widefelem_diff(tmp, tmp2);
834 /* tmp[i] < 2^119 + 2^120 < 2^121 */
835 felem_reduce(y_out, tmp);
836 }
837
838/* Add two elliptic curve points:
839 * (X_1, Y_1, Z_1) + (X_2, Y_2, Z_2) = (X_3, Y_3, Z_3), where
840 * X_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1)^2 - (Z_1^2 * X_2 - Z_2^2 * X_1)^3 -
841 * 2 * Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^2
842 * Y_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1) * (Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^2 - X_3) -
843 * Z_2^3 * Y_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^3
844 * Z_3 = (Z_1^2 * X_2 - Z_2^2 * X_1) * (Z_1 * Z_2)
845 *
846 * This runs faster if 'mixed' is set, which requires Z_2 = 1 or Z_2 = 0.
847 */
848
849/* This function is not entirely constant-time:
850 * it includes a branch for checking whether the two input points are equal,
851 * (while not equal to the point at infinity).
852 * This case never happens during single point multiplication,
853 * so there is no timing leak for ECDH or ECDSA signing. */
854static void point_add(felem x3, felem y3, felem z3,
855 const felem x1, const felem y1, const felem z1,
856 const int mixed, const felem x2, const felem y2, const felem z2)
857 {
858 felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, x_out, y_out, z_out;
859 widefelem tmp, tmp2;
860 limb z1_is_zero, z2_is_zero, x_equal, y_equal;
861
862 if (!mixed)
863 {
864 /* ftmp2 = z2^2 */
865 felem_square(tmp, z2);
866 felem_reduce(ftmp2, tmp);
867
868 /* ftmp4 = z2^3 */
869 felem_mul(tmp, ftmp2, z2);
870 felem_reduce(ftmp4, tmp);
871
872 /* ftmp4 = z2^3*y1 */
873 felem_mul(tmp2, ftmp4, y1);
874 felem_reduce(ftmp4, tmp2);
875
876 /* ftmp2 = z2^2*x1 */
877 felem_mul(tmp2, ftmp2, x1);
878 felem_reduce(ftmp2, tmp2);
879 }
880 else
881 {
882 /* We'll assume z2 = 1 (special case z2 = 0 is handled later) */
883
884 /* ftmp4 = z2^3*y1 */
885 felem_assign(ftmp4, y1);
886
887 /* ftmp2 = z2^2*x1 */
888 felem_assign(ftmp2, x1);
889 }
890
891 /* ftmp = z1^2 */
892 felem_square(tmp, z1);
893 felem_reduce(ftmp, tmp);
894
895 /* ftmp3 = z1^3 */
896 felem_mul(tmp, ftmp, z1);
897 felem_reduce(ftmp3, tmp);
898
899 /* tmp = z1^3*y2 */
900 felem_mul(tmp, ftmp3, y2);
901 /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */
902
903 /* ftmp3 = z1^3*y2 - z2^3*y1 */
904 felem_diff_128_64(tmp, ftmp4);
905 /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */
906 felem_reduce(ftmp3, tmp);
907
908 /* tmp = z1^2*x2 */
909 felem_mul(tmp, ftmp, x2);
910 /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */
911
912 /* ftmp = z1^2*x2 - z2^2*x1 */
913 felem_diff_128_64(tmp, ftmp2);
914 /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */
915 felem_reduce(ftmp, tmp);
916
917 /* the formulae are incorrect if the points are equal
918 * so we check for this and do doubling if this happens */
919 x_equal = felem_is_zero(ftmp);
920 y_equal = felem_is_zero(ftmp3);
921 z1_is_zero = felem_is_zero(z1);
922 z2_is_zero = felem_is_zero(z2);
923 /* In affine coordinates, (X_1, Y_1) == (X_2, Y_2) */
924 if (x_equal && y_equal && !z1_is_zero && !z2_is_zero)
925 {
926 point_double(x3, y3, z3, x1, y1, z1);
927 return;
928 }
929
930 /* ftmp5 = z1*z2 */
931 if (!mixed)
932 {
933 felem_mul(tmp, z1, z2);
934 felem_reduce(ftmp5, tmp);
935 }
936 else
937 {
938 /* special case z2 = 0 is handled later */
939 felem_assign(ftmp5, z1);
940 }
941
942 /* z_out = (z1^2*x2 - z2^2*x1)*(z1*z2) */
943 felem_mul(tmp, ftmp, ftmp5);
944 felem_reduce(z_out, tmp);
945
946 /* ftmp = (z1^2*x2 - z2^2*x1)^2 */
947 felem_assign(ftmp5, ftmp);
948 felem_square(tmp, ftmp);
949 felem_reduce(ftmp, tmp);
950
951 /* ftmp5 = (z1^2*x2 - z2^2*x1)^3 */
952 felem_mul(tmp, ftmp, ftmp5);
953 felem_reduce(ftmp5, tmp);
954
955 /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */
956 felem_mul(tmp, ftmp2, ftmp);
957 felem_reduce(ftmp2, tmp);
958
959 /* tmp = z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */
960 felem_mul(tmp, ftmp4, ftmp5);
961 /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */
962
963 /* tmp2 = (z1^3*y2 - z2^3*y1)^2 */
964 felem_square(tmp2, ftmp3);
965 /* tmp2[i] < 4 * 2^57 * 2^57 < 2^116 */
966
967 /* tmp2 = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 */
968 felem_diff_128_64(tmp2, ftmp5);
969 /* tmp2[i] < 2^116 + 2^64 + 8 < 2^117 */
970
971 /* ftmp5 = 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */
972 felem_assign(ftmp5, ftmp2);
973 felem_scalar(ftmp5, 2);
974 /* ftmp5[i] < 2 * 2^57 = 2^58 */
975
976 /* x_out = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 -
977 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */
978 felem_diff_128_64(tmp2, ftmp5);
979 /* tmp2[i] < 2^117 + 2^64 + 8 < 2^118 */
980 felem_reduce(x_out, tmp2);
981
982 /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out */
983 felem_diff(ftmp2, x_out);
984 /* ftmp2[i] < 2^57 + 2^58 + 2 < 2^59 */
985
986 /* tmp2 = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) */
987 felem_mul(tmp2, ftmp3, ftmp2);
988 /* tmp2[i] < 4 * 2^57 * 2^59 = 2^118 */
989
990 /* y_out = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) -
991 z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */
992 widefelem_diff(tmp2, tmp);
993 /* tmp2[i] < 2^118 + 2^120 < 2^121 */
994 felem_reduce(y_out, tmp2);
995
996 /* the result (x_out, y_out, z_out) is incorrect if one of the inputs is
997 * the point at infinity, so we need to check for this separately */
998
999 /* if point 1 is at infinity, copy point 2 to output, and vice versa */
1000 copy_conditional(x_out, x2, z1_is_zero);
1001 copy_conditional(x_out, x1, z2_is_zero);
1002 copy_conditional(y_out, y2, z1_is_zero);
1003 copy_conditional(y_out, y1, z2_is_zero);
1004 copy_conditional(z_out, z2, z1_is_zero);
1005 copy_conditional(z_out, z1, z2_is_zero);
1006 felem_assign(x3, x_out);
1007 felem_assign(y3, y_out);
1008 felem_assign(z3, z_out);
1009 }
1010
1011/* select_point selects the |idx|th point from a precomputation table and
1012 * copies it to out. */
1013static void select_point(const u64 idx, unsigned int size, const felem pre_comp[/*size*/][3], felem out[3])
1014 {
1015 unsigned i, j;
1016 limb *outlimbs = &out[0][0];
1017 memset(outlimbs, 0, 3 * sizeof(felem));
1018
1019 for (i = 0; i < size; i++)
1020 {
1021 const limb *inlimbs = &pre_comp[i][0][0];
1022 u64 mask = i ^ idx;
1023 mask |= mask >> 4;
1024 mask |= mask >> 2;
1025 mask |= mask >> 1;
1026 mask &= 1;
1027 mask--;
1028 for (j = 0; j < 4 * 3; j++)
1029 outlimbs[j] |= inlimbs[j] & mask;
1030 }
1031 }
1032
1033/* get_bit returns the |i|th bit in |in| */
1034static char get_bit(const felem_bytearray in, unsigned i)
1035 {
1036 if (i >= 224)
1037 return 0;
1038 return (in[i >> 3] >> (i & 7)) & 1;
1039 }
1040
1041/* Interleaved point multiplication using precomputed point multiples:
1042 * The small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[],
1043 * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple
1044 * of the generator, using certain (large) precomputed multiples in g_pre_comp.
1045 * Output point (X, Y, Z) is stored in x_out, y_out, z_out */
1046static void batch_mul(felem x_out, felem y_out, felem z_out,
1047 const felem_bytearray scalars[], const unsigned num_points, const u8 *g_scalar,
1048 const int mixed, const felem pre_comp[][17][3], const felem g_pre_comp[2][16][3])
1049 {
1050 int i, skip;
1051 unsigned num;
1052 unsigned gen_mul = (g_scalar != NULL);
1053 felem nq[3], tmp[4];
1054 u64 bits;
1055 u8 sign, digit;
1056
1057 /* set nq to the point at infinity */
1058 memset(nq, 0, 3 * sizeof(felem));
1059
1060 /* Loop over all scalars msb-to-lsb, interleaving additions
1061 * of multiples of the generator (two in each of the last 28 rounds)
1062 * and additions of other points multiples (every 5th round).
1063 */
1064 skip = 1; /* save two point operations in the first round */
1065 for (i = (num_points ? 220 : 27); i >= 0; --i)
1066 {
1067 /* double */
1068 if (!skip)
1069 point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
1070
1071 /* add multiples of the generator */
1072 if (gen_mul && (i <= 27))
1073 {
1074 /* first, look 28 bits upwards */
1075 bits = get_bit(g_scalar, i + 196) << 3;
1076 bits |= get_bit(g_scalar, i + 140) << 2;
1077 bits |= get_bit(g_scalar, i + 84) << 1;
1078 bits |= get_bit(g_scalar, i + 28);
1079 /* select the point to add, in constant time */
1080 select_point(bits, 16, g_pre_comp[1], tmp);
1081
1082 if (!skip)
1083 {
1084 point_add(nq[0], nq[1], nq[2],
1085 nq[0], nq[1], nq[2],
1086 1 /* mixed */, tmp[0], tmp[1], tmp[2]);
1087 }
1088 else
1089 {
1090 memcpy(nq, tmp, 3 * sizeof(felem));
1091 skip = 0;
1092 }
1093
1094 /* second, look at the current position */
1095 bits = get_bit(g_scalar, i + 168) << 3;
1096 bits |= get_bit(g_scalar, i + 112) << 2;
1097 bits |= get_bit(g_scalar, i + 56) << 1;
1098 bits |= get_bit(g_scalar, i);
1099 /* select the point to add, in constant time */
1100 select_point(bits, 16, g_pre_comp[0], tmp);
1101 point_add(nq[0], nq[1], nq[2],
1102 nq[0], nq[1], nq[2],
1103 1 /* mixed */, tmp[0], tmp[1], tmp[2]);
1104 }
1105
1106 /* do other additions every 5 doublings */
1107 if (num_points && (i % 5 == 0))
1108 {
1109 /* loop over all scalars */
1110 for (num = 0; num < num_points; ++num)
1111 {
1112 bits = get_bit(scalars[num], i + 4) << 5;
1113 bits |= get_bit(scalars[num], i + 3) << 4;
1114 bits |= get_bit(scalars[num], i + 2) << 3;
1115 bits |= get_bit(scalars[num], i + 1) << 2;
1116 bits |= get_bit(scalars[num], i) << 1;
1117 bits |= get_bit(scalars[num], i - 1);
1118 ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
1119
1120 /* select the point to add or subtract */
1121 select_point(digit, 17, pre_comp[num], tmp);
1122 felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative point */
1123 copy_conditional(tmp[1], tmp[3], sign);
1124
1125 if (!skip)
1126 {
1127 point_add(nq[0], nq[1], nq[2],
1128 nq[0], nq[1], nq[2],
1129 mixed, tmp[0], tmp[1], tmp[2]);
1130 }
1131 else
1132 {
1133 memcpy(nq, tmp, 3 * sizeof(felem));
1134 skip = 0;
1135 }
1136 }
1137 }
1138 }
1139 felem_assign(x_out, nq[0]);
1140 felem_assign(y_out, nq[1]);
1141 felem_assign(z_out, nq[2]);
1142 }
1143
1144/******************************************************************************/
1145/* FUNCTIONS TO MANAGE PRECOMPUTATION
1146 */
1147
1148static NISTP224_PRE_COMP *nistp224_pre_comp_new()
1149 {
1150 NISTP224_PRE_COMP *ret = NULL;
1151 ret = (NISTP224_PRE_COMP *) OPENSSL_malloc(sizeof *ret);
1152 if (!ret)
1153 {
1154 ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
1155 return ret;
1156 }
1157 memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp));
1158 ret->references = 1;
1159 return ret;
1160 }
1161
1162static void *nistp224_pre_comp_dup(void *src_)
1163 {
1164 NISTP224_PRE_COMP *src = src_;
1165
1166 /* no need to actually copy, these objects never change! */
1167 CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
1168
1169 return src_;
1170 }
1171
1172static void nistp224_pre_comp_free(void *pre_)
1173 {
1174 int i;
1175 NISTP224_PRE_COMP *pre = pre_;
1176
1177 if (!pre)
1178 return;
1179
1180 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1181 if (i > 0)
1182 return;
1183
1184 OPENSSL_free(pre);
1185 }
1186
1187static void nistp224_pre_comp_clear_free(void *pre_)
1188 {
1189 int i;
1190 NISTP224_PRE_COMP *pre = pre_;
1191
1192 if (!pre)
1193 return;
1194
1195 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1196 if (i > 0)
1197 return;
1198
1199 OPENSSL_cleanse(pre, sizeof *pre);
1200 OPENSSL_free(pre);
1201 }
1202
1203/******************************************************************************/
1204/* OPENSSL EC_METHOD FUNCTIONS
1205 */
1206
1207int ec_GFp_nistp224_group_init(EC_GROUP *group)
1208 {
1209 int ret;
1210 ret = ec_GFp_simple_group_init(group);
1211 group->a_is_minus3 = 1;
1212 return ret;
1213 }
1214
1215int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
1216 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1217 {
1218 int ret = 0;
1219 BN_CTX *new_ctx = NULL;
1220 BIGNUM *curve_p, *curve_a, *curve_b;
1221
1222 if (ctx == NULL)
1223 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1224 BN_CTX_start(ctx);
1225 if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
1226 ((curve_a = BN_CTX_get(ctx)) == NULL) ||
1227 ((curve_b = BN_CTX_get(ctx)) == NULL)) goto err;
1228 BN_bin2bn(nistp224_curve_params[0], sizeof(felem_bytearray), curve_p);
1229 BN_bin2bn(nistp224_curve_params[1], sizeof(felem_bytearray), curve_a);
1230 BN_bin2bn(nistp224_curve_params[2], sizeof(felem_bytearray), curve_b);
1231 if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) ||
1232 (BN_cmp(curve_b, b)))
1233 {
1234 ECerr(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE,
1235 EC_R_WRONG_CURVE_PARAMETERS);
1236 goto err;
1237 }
1238 group->field_mod_func = BN_nist_mod_224;
1239 ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
1240err:
1241 BN_CTX_end(ctx);
1242 if (new_ctx != NULL)
1243 BN_CTX_free(new_ctx);
1244 return ret;
1245 }
1246
1247/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns
1248 * (X', Y') = (X/Z^2, Y/Z^3) */
1249int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
1250 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
1251 {
1252 felem z1, z2, x_in, y_in, x_out, y_out;
1253 widefelem tmp;
1254
1255 if (EC_POINT_is_at_infinity(group, point))
1256 {
1257 ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES,
1258 EC_R_POINT_AT_INFINITY);
1259 return 0;
1260 }
1261 if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) ||
1262 (!BN_to_felem(z1, &point->Z))) return 0;
1263 felem_inv(z2, z1);
1264 felem_square(tmp, z2); felem_reduce(z1, tmp);
1265 felem_mul(tmp, x_in, z1); felem_reduce(x_in, tmp);
1266 felem_contract(x_out, x_in);
1267 if (x != NULL)
1268 {
1269 if (!felem_to_BN(x, x_out)) {
1270 ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES,
1271 ERR_R_BN_LIB);
1272 return 0;
1273 }
1274 }
1275 felem_mul(tmp, z1, z2); felem_reduce(z1, tmp);
1276 felem_mul(tmp, y_in, z1); felem_reduce(y_in, tmp);
1277 felem_contract(y_out, y_in);
1278 if (y != NULL)
1279 {
1280 if (!felem_to_BN(y, y_out)) {
1281 ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES,
1282 ERR_R_BN_LIB);
1283 return 0;
1284 }
1285 }
1286 return 1;
1287 }
1288
1289static void make_points_affine(size_t num, felem points[/*num*/][3], felem tmp_felems[/*num+1*/])
1290 {
1291 /* Runs in constant time, unless an input is the point at infinity
1292 * (which normally shouldn't happen). */
1293 ec_GFp_nistp_points_make_affine_internal(
1294 num,
1295 points,
1296 sizeof(felem),
1297 tmp_felems,
1298 (void (*)(void *)) felem_one,
1299 (int (*)(const void *)) felem_is_zero_int,
1300 (void (*)(void *, const void *)) felem_assign,
1301 (void (*)(void *, const void *)) felem_square_reduce,
1302 (void (*)(void *, const void *, const void *)) felem_mul_reduce,
1303 (void (*)(void *, const void *)) felem_inv,
1304 (void (*)(void *, const void *)) felem_contract);
1305 }
1306
1307/* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL values
1308 * Result is stored in r (r can equal one of the inputs). */
1309int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
1310 const BIGNUM *scalar, size_t num, const EC_POINT *points[],
1311 const BIGNUM *scalars[], BN_CTX *ctx)
1312 {
1313 int ret = 0;
1314 int j;
1315 unsigned i;
1316 int mixed = 0;
1317 BN_CTX *new_ctx = NULL;
1318 BIGNUM *x, *y, *z, *tmp_scalar;
1319 felem_bytearray g_secret;
1320 felem_bytearray *secrets = NULL;
1321 felem (*pre_comp)[17][3] = NULL;
1322 felem *tmp_felems = NULL;
1323 felem_bytearray tmp;
1324 unsigned num_bytes;
1325 int have_pre_comp = 0;
1326 size_t num_points = num;
1327 felem x_in, y_in, z_in, x_out, y_out, z_out;
1328 NISTP224_PRE_COMP *pre = NULL;
1329 const felem (*g_pre_comp)[16][3] = NULL;
1330 EC_POINT *generator = NULL;
1331 const EC_POINT *p = NULL;
1332 const BIGNUM *p_scalar = NULL;
1333
1334 if (ctx == NULL)
1335 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1336 BN_CTX_start(ctx);
1337 if (((x = BN_CTX_get(ctx)) == NULL) ||
1338 ((y = BN_CTX_get(ctx)) == NULL) ||
1339 ((z = BN_CTX_get(ctx)) == NULL) ||
1340 ((tmp_scalar = BN_CTX_get(ctx)) == NULL))
1341 goto err;
1342
1343 if (scalar != NULL)
1344 {
1345 pre = EC_EX_DATA_get_data(group->extra_data,
1346 nistp224_pre_comp_dup, nistp224_pre_comp_free,
1347 nistp224_pre_comp_clear_free);
1348 if (pre)
1349 /* we have precomputation, try to use it */
1350 g_pre_comp = (const felem (*)[16][3]) pre->g_pre_comp;
1351 else
1352 /* try to use the standard precomputation */
1353 g_pre_comp = &gmul[0];
1354 generator = EC_POINT_new(group);
1355 if (generator == NULL)
1356 goto err;
1357 /* get the generator from precomputation */
1358 if (!felem_to_BN(x, g_pre_comp[0][1][0]) ||
1359 !felem_to_BN(y, g_pre_comp[0][1][1]) ||
1360 !felem_to_BN(z, g_pre_comp[0][1][2]))
1361 {
1362 ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
1363 goto err;
1364 }
1365 if (!EC_POINT_set_Jprojective_coordinates_GFp(group,
1366 generator, x, y, z, ctx))
1367 goto err;
1368 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
1369 /* precomputation matches generator */
1370 have_pre_comp = 1;
1371 else
1372 /* we don't have valid precomputation:
1373 * treat the generator as a random point */
1374 num_points = num_points + 1;
1375 }
1376
1377 if (num_points > 0)
1378 {
1379 if (num_points >= 3)
1380 {
1381 /* unless we precompute multiples for just one or two points,
1382 * converting those into affine form is time well spent */
1383 mixed = 1;
1384 }
1385 secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
1386 pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(felem));
1387 if (mixed)
1388 tmp_felems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem));
1389 if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_felems == NULL)))
1390 {
1391 ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_MALLOC_FAILURE);
1392 goto err;
1393 }
1394
1395 /* we treat NULL scalars as 0, and NULL points as points at infinity,
1396 * i.e., they contribute nothing to the linear combination */
1397 memset(secrets, 0, num_points * sizeof(felem_bytearray));
1398 memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem));
1399 for (i = 0; i < num_points; ++i)
1400 {
1401 if (i == num)
1402 /* the generator */
1403 {
1404 p = EC_GROUP_get0_generator(group);
1405 p_scalar = scalar;
1406 }
1407 else
1408 /* the i^th point */
1409 {
1410 p = points[i];
1411 p_scalar = scalars[i];
1412 }
1413 if ((p_scalar != NULL) && (p != NULL))
1414 {
1415 /* reduce scalar to 0 <= scalar < 2^224 */
1416 if ((BN_num_bits(p_scalar) > 224) || (BN_is_negative(p_scalar)))
1417 {
1418 /* this is an unusual input, and we don't guarantee
1419 * constant-timeness */
1420 if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx))
1421 {
1422 ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
1423 goto err;
1424 }
1425 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1426 }
1427 else
1428 num_bytes = BN_bn2bin(p_scalar, tmp);
1429 flip_endian(secrets[i], tmp, num_bytes);
1430 /* precompute multiples */
1431 if ((!BN_to_felem(x_out, &p->X)) ||
1432 (!BN_to_felem(y_out, &p->Y)) ||
1433 (!BN_to_felem(z_out, &p->Z))) goto err;
1434 felem_assign(pre_comp[i][1][0], x_out);
1435 felem_assign(pre_comp[i][1][1], y_out);
1436 felem_assign(pre_comp[i][1][2], z_out);
1437 for (j = 2; j <= 16; ++j)
1438 {
1439 if (j & 1)
1440 {
1441 point_add(
1442 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1443 pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2],
1444 0, pre_comp[i][j-1][0], pre_comp[i][j-1][1], pre_comp[i][j-1][2]);
1445 }
1446 else
1447 {
1448 point_double(
1449 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1450 pre_comp[i][j/2][0], pre_comp[i][j/2][1], pre_comp[i][j/2][2]);
1451 }
1452 }
1453 }
1454 }
1455 if (mixed)
1456 make_points_affine(num_points * 17, pre_comp[0], tmp_felems);
1457 }
1458
1459 /* the scalar for the generator */
1460 if ((scalar != NULL) && (have_pre_comp))
1461 {
1462 memset(g_secret, 0, sizeof g_secret);
1463 /* reduce scalar to 0 <= scalar < 2^224 */
1464 if ((BN_num_bits(scalar) > 224) || (BN_is_negative(scalar)))
1465 {
1466 /* this is an unusual input, and we don't guarantee
1467 * constant-timeness */
1468 if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx))
1469 {
1470 ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
1471 goto err;
1472 }
1473 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1474 }
1475 else
1476 num_bytes = BN_bn2bin(scalar, tmp);
1477 flip_endian(g_secret, tmp, num_bytes);
1478 /* do the multiplication with generator precomputation*/
1479 batch_mul(x_out, y_out, z_out,
1480 (const felem_bytearray (*)) secrets, num_points,
1481 g_secret,
1482 mixed, (const felem (*)[17][3]) pre_comp,
1483 g_pre_comp);
1484 }
1485 else
1486 /* do the multiplication without generator precomputation */
1487 batch_mul(x_out, y_out, z_out,
1488 (const felem_bytearray (*)) secrets, num_points,
1489 NULL, mixed, (const felem (*)[17][3]) pre_comp, NULL);
1490 /* reduce the output to its unique minimal representation */
1491 felem_contract(x_in, x_out);
1492 felem_contract(y_in, y_out);
1493 felem_contract(z_in, z_out);
1494 if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) ||
1495 (!felem_to_BN(z, z_in)))
1496 {
1497 ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
1498 goto err;
1499 }
1500 ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
1501
1502err:
1503 BN_CTX_end(ctx);
1504 if (generator != NULL)
1505 EC_POINT_free(generator);
1506 if (new_ctx != NULL)
1507 BN_CTX_free(new_ctx);
1508 if (secrets != NULL)
1509 OPENSSL_free(secrets);
1510 if (pre_comp != NULL)
1511 OPENSSL_free(pre_comp);
1512 if (tmp_felems != NULL)
1513 OPENSSL_free(tmp_felems);
1514 return ret;
1515 }
1516
1517int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1518 {
1519 int ret = 0;
1520 NISTP224_PRE_COMP *pre = NULL;
1521 int i, j;
1522 BN_CTX *new_ctx = NULL;
1523 BIGNUM *x, *y;
1524 EC_POINT *generator = NULL;
1525 felem tmp_felems[32];
1526
1527 /* throw away old precomputation */
1528 EC_EX_DATA_free_data(&group->extra_data, nistp224_pre_comp_dup,
1529 nistp224_pre_comp_free, nistp224_pre_comp_clear_free);
1530 if (ctx == NULL)
1531 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1532 BN_CTX_start(ctx);
1533 if (((x = BN_CTX_get(ctx)) == NULL) ||
1534 ((y = BN_CTX_get(ctx)) == NULL))
1535 goto err;
1536 /* get the generator */
1537 if (group->generator == NULL) goto err;
1538 generator = EC_POINT_new(group);
1539 if (generator == NULL)
1540 goto err;
1541 BN_bin2bn(nistp224_curve_params[3], sizeof (felem_bytearray), x);
1542 BN_bin2bn(nistp224_curve_params[4], sizeof (felem_bytearray), y);
1543 if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx))
1544 goto err;
1545 if ((pre = nistp224_pre_comp_new()) == NULL)
1546 goto err;
1547 /* if the generator is the standard one, use built-in precomputation */
1548 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
1549 {
1550 memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp));
1551 ret = 1;
1552 goto err;
1553 }
1554 if ((!BN_to_felem(pre->g_pre_comp[0][1][0], &group->generator->X)) ||
1555 (!BN_to_felem(pre->g_pre_comp[0][1][1], &group->generator->Y)) ||
1556 (!BN_to_felem(pre->g_pre_comp[0][1][2], &group->generator->Z)))
1557 goto err;
1558 /* compute 2^56*G, 2^112*G, 2^168*G for the first table,
1559 * 2^28*G, 2^84*G, 2^140*G, 2^196*G for the second one
1560 */
1561 for (i = 1; i <= 8; i <<= 1)
1562 {
1563 point_double(
1564 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2],
1565 pre->g_pre_comp[0][i][0], pre->g_pre_comp[0][i][1], pre->g_pre_comp[0][i][2]);
1566 for (j = 0; j < 27; ++j)
1567 {
1568 point_double(
1569 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2],
1570 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]);
1571 }
1572 if (i == 8)
1573 break;
1574 point_double(
1575 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2],
1576 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]);
1577 for (j = 0; j < 27; ++j)
1578 {
1579 point_double(
1580 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2],
1581 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2]);
1582 }
1583 }
1584 for (i = 0; i < 2; i++)
1585 {
1586 /* g_pre_comp[i][0] is the point at infinity */
1587 memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0]));
1588 /* the remaining multiples */
1589 /* 2^56*G + 2^112*G resp. 2^84*G + 2^140*G */
1590 point_add(
1591 pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1],
1592 pre->g_pre_comp[i][6][2], pre->g_pre_comp[i][4][0],
1593 pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2],
1594 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1],
1595 pre->g_pre_comp[i][2][2]);
1596 /* 2^56*G + 2^168*G resp. 2^84*G + 2^196*G */
1597 point_add(
1598 pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1],
1599 pre->g_pre_comp[i][10][2], pre->g_pre_comp[i][8][0],
1600 pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
1601 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1],
1602 pre->g_pre_comp[i][2][2]);
1603 /* 2^112*G + 2^168*G resp. 2^140*G + 2^196*G */
1604 point_add(
1605 pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1],
1606 pre->g_pre_comp[i][12][2], pre->g_pre_comp[i][8][0],
1607 pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
1608 0, pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1],
1609 pre->g_pre_comp[i][4][2]);
1610 /* 2^56*G + 2^112*G + 2^168*G resp. 2^84*G + 2^140*G + 2^196*G */
1611 point_add(
1612 pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1],
1613 pre->g_pre_comp[i][14][2], pre->g_pre_comp[i][12][0],
1614 pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2],
1615 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1],
1616 pre->g_pre_comp[i][2][2]);
1617 for (j = 1; j < 8; ++j)
1618 {
1619 /* odd multiples: add G resp. 2^28*G */
1620 point_add(
1621 pre->g_pre_comp[i][2*j+1][0], pre->g_pre_comp[i][2*j+1][1],
1622 pre->g_pre_comp[i][2*j+1][2], pre->g_pre_comp[i][2*j][0],
1623 pre->g_pre_comp[i][2*j][1], pre->g_pre_comp[i][2*j][2],
1624 0, pre->g_pre_comp[i][1][0], pre->g_pre_comp[i][1][1],
1625 pre->g_pre_comp[i][1][2]);
1626 }
1627 }
1628 make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_felems);
1629
1630 if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp224_pre_comp_dup,
1631 nistp224_pre_comp_free, nistp224_pre_comp_clear_free))
1632 goto err;
1633 ret = 1;
1634 pre = NULL;
1635 err:
1636 BN_CTX_end(ctx);
1637 if (generator != NULL)
1638 EC_POINT_free(generator);
1639 if (new_ctx != NULL)
1640 BN_CTX_free(new_ctx);
1641 if (pre)
1642 nistp224_pre_comp_free(pre);
1643 return ret;
1644 }
1645
1646int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group)
1647 {
1648 if (EC_EX_DATA_get_data(group->extra_data, nistp224_pre_comp_dup,
1649 nistp224_pre_comp_free, nistp224_pre_comp_clear_free)
1650 != NULL)
1651 return 1;
1652 else
1653 return 0;
1654 }
1655
1656#else
1657static void *dummy=&dummy;
1658#endif
diff --git a/src/lib/libcrypto/ec/ecp_nistp256.c b/src/lib/libcrypto/ec/ecp_nistp256.c
new file mode 100644
index 0000000000..4bc0f5dce0
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_nistp256.c
@@ -0,0 +1,2171 @@
1/* crypto/ec/ecp_nistp256.c */
2/*
3 * Written by Adam Langley (Google) for the OpenSSL project
4 */
5/* Copyright 2011 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 *
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21/*
22 * A 64-bit implementation of the NIST P-256 elliptic curve point multiplication
23 *
24 * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c.
25 * Otherwise based on Emilia's P224 work, which was inspired by my curve25519
26 * work which got its smarts from Daniel J. Bernstein's work on the same.
27 */
28
29#include <openssl/opensslconf.h>
30#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
31
32#ifndef OPENSSL_SYS_VMS
33#include <stdint.h>
34#else
35#include <inttypes.h>
36#endif
37
38#include <string.h>
39#include <openssl/err.h>
40#include "ec_lcl.h"
41
42#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
43 /* even with gcc, the typedef won't work for 32-bit platforms */
44 typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit platforms */
45 typedef __int128_t int128_t;
46#else
47 #error "Need GCC 3.1 or later to define type uint128_t"
48#endif
49
50typedef uint8_t u8;
51typedef uint32_t u32;
52typedef uint64_t u64;
53typedef int64_t s64;
54
55/* The underlying field.
56 *
57 * P256 operates over GF(2^256-2^224+2^192+2^96-1). We can serialise an element
58 * of this field into 32 bytes. We call this an felem_bytearray. */
59
60typedef u8 felem_bytearray[32];
61
62/* These are the parameters of P256, taken from FIPS 186-3, page 86. These
63 * values are big-endian. */
64static const felem_bytearray nistp256_curve_params[5] = {
65 {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* p */
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
68 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
69 {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* a = -3 */
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
72 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc}, /* b */
73 {0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7,
74 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc,
75 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6,
76 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b},
77 {0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, /* x */
78 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2,
79 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
80 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96},
81 {0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, /* y */
82 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
83 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
84 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5}
85};
86
87/* The representation of field elements.
88 * ------------------------------------
89 *
90 * We represent field elements with either four 128-bit values, eight 128-bit
91 * values, or four 64-bit values. The field element represented is:
92 * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + v[3]*2^192 (mod p)
93 * or:
94 * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + ... + v[8]*2^512 (mod p)
95 *
96 * 128-bit values are called 'limbs'. Since the limbs are spaced only 64 bits
97 * apart, but are 128-bits wide, the most significant bits of each limb overlap
98 * with the least significant bits of the next.
99 *
100 * A field element with four limbs is an 'felem'. One with eight limbs is a
101 * 'longfelem'
102 *
103 * A field element with four, 64-bit values is called a 'smallfelem'. Small
104 * values are used as intermediate values before multiplication.
105 */
106
107#define NLIMBS 4
108
109typedef uint128_t limb;
110typedef limb felem[NLIMBS];
111typedef limb longfelem[NLIMBS * 2];
112typedef u64 smallfelem[NLIMBS];
113
114/* This is the value of the prime as four 64-bit words, little-endian. */
115static const u64 kPrime[4] = { 0xfffffffffffffffful, 0xffffffff, 0, 0xffffffff00000001ul };
116static const limb bottom32bits = 0xffffffff;
117static const u64 bottom63bits = 0x7ffffffffffffffful;
118
119/* bin32_to_felem takes a little-endian byte array and converts it into felem
120 * form. This assumes that the CPU is little-endian. */
121static void bin32_to_felem(felem out, const u8 in[32])
122 {
123 out[0] = *((u64*) &in[0]);
124 out[1] = *((u64*) &in[8]);
125 out[2] = *((u64*) &in[16]);
126 out[3] = *((u64*) &in[24]);
127 }
128
129/* smallfelem_to_bin32 takes a smallfelem and serialises into a little endian,
130 * 32 byte array. This assumes that the CPU is little-endian. */
131static void smallfelem_to_bin32(u8 out[32], const smallfelem in)
132 {
133 *((u64*) &out[0]) = in[0];
134 *((u64*) &out[8]) = in[1];
135 *((u64*) &out[16]) = in[2];
136 *((u64*) &out[24]) = in[3];
137 }
138
139/* To preserve endianness when using BN_bn2bin and BN_bin2bn */
140static void flip_endian(u8 *out, const u8 *in, unsigned len)
141 {
142 unsigned i;
143 for (i = 0; i < len; ++i)
144 out[i] = in[len-1-i];
145 }
146
147/* BN_to_felem converts an OpenSSL BIGNUM into an felem */
148static int BN_to_felem(felem out, const BIGNUM *bn)
149 {
150 felem_bytearray b_in;
151 felem_bytearray b_out;
152 unsigned num_bytes;
153
154 /* BN_bn2bin eats leading zeroes */
155 memset(b_out, 0, sizeof b_out);
156 num_bytes = BN_num_bytes(bn);
157 if (num_bytes > sizeof b_out)
158 {
159 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
160 return 0;
161 }
162 if (BN_is_negative(bn))
163 {
164 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
165 return 0;
166 }
167 num_bytes = BN_bn2bin(bn, b_in);
168 flip_endian(b_out, b_in, num_bytes);
169 bin32_to_felem(out, b_out);
170 return 1;
171 }
172
173/* felem_to_BN converts an felem into an OpenSSL BIGNUM */
174static BIGNUM *smallfelem_to_BN(BIGNUM *out, const smallfelem in)
175 {
176 felem_bytearray b_in, b_out;
177 smallfelem_to_bin32(b_in, in);
178 flip_endian(b_out, b_in, sizeof b_out);
179 return BN_bin2bn(b_out, sizeof b_out, out);
180 }
181
182
183/* Field operations
184 * ---------------- */
185
186static void smallfelem_one(smallfelem out)
187 {
188 out[0] = 1;
189 out[1] = 0;
190 out[2] = 0;
191 out[3] = 0;
192 }
193
194static void smallfelem_assign(smallfelem out, const smallfelem in)
195 {
196 out[0] = in[0];
197 out[1] = in[1];
198 out[2] = in[2];
199 out[3] = in[3];
200 }
201
202static void felem_assign(felem out, const felem in)
203 {
204 out[0] = in[0];
205 out[1] = in[1];
206 out[2] = in[2];
207 out[3] = in[3];
208 }
209
210/* felem_sum sets out = out + in. */
211static void felem_sum(felem out, const felem in)
212 {
213 out[0] += in[0];
214 out[1] += in[1];
215 out[2] += in[2];
216 out[3] += in[3];
217 }
218
219/* felem_small_sum sets out = out + in. */
220static void felem_small_sum(felem out, const smallfelem in)
221 {
222 out[0] += in[0];
223 out[1] += in[1];
224 out[2] += in[2];
225 out[3] += in[3];
226 }
227
228/* felem_scalar sets out = out * scalar */
229static void felem_scalar(felem out, const u64 scalar)
230 {
231 out[0] *= scalar;
232 out[1] *= scalar;
233 out[2] *= scalar;
234 out[3] *= scalar;
235 }
236
237/* longfelem_scalar sets out = out * scalar */
238static void longfelem_scalar(longfelem out, const u64 scalar)
239 {
240 out[0] *= scalar;
241 out[1] *= scalar;
242 out[2] *= scalar;
243 out[3] *= scalar;
244 out[4] *= scalar;
245 out[5] *= scalar;
246 out[6] *= scalar;
247 out[7] *= scalar;
248 }
249
250#define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9)
251#define two105 (((limb)1) << 105)
252#define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9)
253
254/* zero105 is 0 mod p */
255static const felem zero105 = { two105m41m9, two105, two105m41p9, two105m41p9 };
256
257/* smallfelem_neg sets |out| to |-small|
258 * On exit:
259 * out[i] < out[i] + 2^105
260 */
261static void smallfelem_neg(felem out, const smallfelem small)
262 {
263 /* In order to prevent underflow, we subtract from 0 mod p. */
264 out[0] = zero105[0] - small[0];
265 out[1] = zero105[1] - small[1];
266 out[2] = zero105[2] - small[2];
267 out[3] = zero105[3] - small[3];
268 }
269
270/* felem_diff subtracts |in| from |out|
271 * On entry:
272 * in[i] < 2^104
273 * On exit:
274 * out[i] < out[i] + 2^105
275 */
276static void felem_diff(felem out, const felem in)
277 {
278 /* In order to prevent underflow, we add 0 mod p before subtracting. */
279 out[0] += zero105[0];
280 out[1] += zero105[1];
281 out[2] += zero105[2];
282 out[3] += zero105[3];
283
284 out[0] -= in[0];
285 out[1] -= in[1];
286 out[2] -= in[2];
287 out[3] -= in[3];
288 }
289
290#define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11)
291#define two107 (((limb)1) << 107)
292#define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11)
293
294/* zero107 is 0 mod p */
295static const felem zero107 = { two107m43m11, two107, two107m43p11, two107m43p11 };
296
297/* An alternative felem_diff for larger inputs |in|
298 * felem_diff_zero107 subtracts |in| from |out|
299 * On entry:
300 * in[i] < 2^106
301 * On exit:
302 * out[i] < out[i] + 2^107
303 */
304static void felem_diff_zero107(felem out, const felem in)
305 {
306 /* In order to prevent underflow, we add 0 mod p before subtracting. */
307 out[0] += zero107[0];
308 out[1] += zero107[1];
309 out[2] += zero107[2];
310 out[3] += zero107[3];
311
312 out[0] -= in[0];
313 out[1] -= in[1];
314 out[2] -= in[2];
315 out[3] -= in[3];
316 }
317
318/* longfelem_diff subtracts |in| from |out|
319 * On entry:
320 * in[i] < 7*2^67
321 * On exit:
322 * out[i] < out[i] + 2^70 + 2^40
323 */
324static void longfelem_diff(longfelem out, const longfelem in)
325 {
326 static const limb two70m8p6 = (((limb)1) << 70) - (((limb)1) << 8) + (((limb)1) << 6);
327 static const limb two70p40 = (((limb)1) << 70) + (((limb)1) << 40);
328 static const limb two70 = (((limb)1) << 70);
329 static const limb two70m40m38p6 = (((limb)1) << 70) - (((limb)1) << 40) - (((limb)1) << 38) + (((limb)1) << 6);
330 static const limb two70m6 = (((limb)1) << 70) - (((limb)1) << 6);
331
332 /* add 0 mod p to avoid underflow */
333 out[0] += two70m8p6;
334 out[1] += two70p40;
335 out[2] += two70;
336 out[3] += two70m40m38p6;
337 out[4] += two70m6;
338 out[5] += two70m6;
339 out[6] += two70m6;
340 out[7] += two70m6;
341
342 /* in[i] < 7*2^67 < 2^70 - 2^40 - 2^38 + 2^6 */
343 out[0] -= in[0];
344 out[1] -= in[1];
345 out[2] -= in[2];
346 out[3] -= in[3];
347 out[4] -= in[4];
348 out[5] -= in[5];
349 out[6] -= in[6];
350 out[7] -= in[7];
351 }
352
353#define two64m0 (((limb)1) << 64) - 1
354#define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1
355#define two64m46 (((limb)1) << 64) - (((limb)1) << 46)
356#define two64m32 (((limb)1) << 64) - (((limb)1) << 32)
357
358/* zero110 is 0 mod p */
359static const felem zero110 = { two64m0, two110p32m0, two64m46, two64m32 };
360
361/* felem_shrink converts an felem into a smallfelem. The result isn't quite
362 * minimal as the value may be greater than p.
363 *
364 * On entry:
365 * in[i] < 2^109
366 * On exit:
367 * out[i] < 2^64
368 */
369static void felem_shrink(smallfelem out, const felem in)
370 {
371 felem tmp;
372 u64 a, b, mask;
373 s64 high, low;
374 static const u64 kPrime3Test = 0x7fffffff00000001ul; /* 2^63 - 2^32 + 1 */
375
376 /* Carry 2->3 */
377 tmp[3] = zero110[3] + in[3] + ((u64) (in[2] >> 64));
378 /* tmp[3] < 2^110 */
379
380 tmp[2] = zero110[2] + (u64) in[2];
381 tmp[0] = zero110[0] + in[0];
382 tmp[1] = zero110[1] + in[1];
383 /* tmp[0] < 2**110, tmp[1] < 2^111, tmp[2] < 2**65 */
384
385 /* We perform two partial reductions where we eliminate the
386 * high-word of tmp[3]. We don't update the other words till the end.
387 */
388 a = tmp[3] >> 64; /* a < 2^46 */
389 tmp[3] = (u64) tmp[3];
390 tmp[3] -= a;
391 tmp[3] += ((limb)a) << 32;
392 /* tmp[3] < 2^79 */
393
394 b = a;
395 a = tmp[3] >> 64; /* a < 2^15 */
396 b += a; /* b < 2^46 + 2^15 < 2^47 */
397 tmp[3] = (u64) tmp[3];
398 tmp[3] -= a;
399 tmp[3] += ((limb)a) << 32;
400 /* tmp[3] < 2^64 + 2^47 */
401
402 /* This adjusts the other two words to complete the two partial
403 * reductions. */
404 tmp[0] += b;
405 tmp[1] -= (((limb)b) << 32);
406
407 /* In order to make space in tmp[3] for the carry from 2 -> 3, we
408 * conditionally subtract kPrime if tmp[3] is large enough. */
409 high = tmp[3] >> 64;
410 /* As tmp[3] < 2^65, high is either 1 or 0 */
411 high <<= 63;
412 high >>= 63;
413 /* high is:
414 * all ones if the high word of tmp[3] is 1
415 * all zeros if the high word of tmp[3] if 0 */
416 low = tmp[3];
417 mask = low >> 63;
418 /* mask is:
419 * all ones if the MSB of low is 1
420 * all zeros if the MSB of low if 0 */
421 low &= bottom63bits;
422 low -= kPrime3Test;
423 /* if low was greater than kPrime3Test then the MSB is zero */
424 low = ~low;
425 low >>= 63;
426 /* low is:
427 * all ones if low was > kPrime3Test
428 * all zeros if low was <= kPrime3Test */
429 mask = (mask & low) | high;
430 tmp[0] -= mask & kPrime[0];
431 tmp[1] -= mask & kPrime[1];
432 /* kPrime[2] is zero, so omitted */
433 tmp[3] -= mask & kPrime[3];
434 /* tmp[3] < 2**64 - 2**32 + 1 */
435
436 tmp[1] += ((u64) (tmp[0] >> 64)); tmp[0] = (u64) tmp[0];
437 tmp[2] += ((u64) (tmp[1] >> 64)); tmp[1] = (u64) tmp[1];
438 tmp[3] += ((u64) (tmp[2] >> 64)); tmp[2] = (u64) tmp[2];
439 /* tmp[i] < 2^64 */
440
441 out[0] = tmp[0];
442 out[1] = tmp[1];
443 out[2] = tmp[2];
444 out[3] = tmp[3];
445 }
446
447/* smallfelem_expand converts a smallfelem to an felem */
448static void smallfelem_expand(felem out, const smallfelem in)
449 {
450 out[0] = in[0];
451 out[1] = in[1];
452 out[2] = in[2];
453 out[3] = in[3];
454 }
455
456/* smallfelem_square sets |out| = |small|^2
457 * On entry:
458 * small[i] < 2^64
459 * On exit:
460 * out[i] < 7 * 2^64 < 2^67
461 */
462static void smallfelem_square(longfelem out, const smallfelem small)
463 {
464 limb a;
465 u64 high, low;
466
467 a = ((uint128_t) small[0]) * small[0];
468 low = a;
469 high = a >> 64;
470 out[0] = low;
471 out[1] = high;
472
473 a = ((uint128_t) small[0]) * small[1];
474 low = a;
475 high = a >> 64;
476 out[1] += low;
477 out[1] += low;
478 out[2] = high;
479
480 a = ((uint128_t) small[0]) * small[2];
481 low = a;
482 high = a >> 64;
483 out[2] += low;
484 out[2] *= 2;
485 out[3] = high;
486
487 a = ((uint128_t) small[0]) * small[3];
488 low = a;
489 high = a >> 64;
490 out[3] += low;
491 out[4] = high;
492
493 a = ((uint128_t) small[1]) * small[2];
494 low = a;
495 high = a >> 64;
496 out[3] += low;
497 out[3] *= 2;
498 out[4] += high;
499
500 a = ((uint128_t) small[1]) * small[1];
501 low = a;
502 high = a >> 64;
503 out[2] += low;
504 out[3] += high;
505
506 a = ((uint128_t) small[1]) * small[3];
507 low = a;
508 high = a >> 64;
509 out[4] += low;
510 out[4] *= 2;
511 out[5] = high;
512
513 a = ((uint128_t) small[2]) * small[3];
514 low = a;
515 high = a >> 64;
516 out[5] += low;
517 out[5] *= 2;
518 out[6] = high;
519 out[6] += high;
520
521 a = ((uint128_t) small[2]) * small[2];
522 low = a;
523 high = a >> 64;
524 out[4] += low;
525 out[5] += high;
526
527 a = ((uint128_t) small[3]) * small[3];
528 low = a;
529 high = a >> 64;
530 out[6] += low;
531 out[7] = high;
532 }
533
534/* felem_square sets |out| = |in|^2
535 * On entry:
536 * in[i] < 2^109
537 * On exit:
538 * out[i] < 7 * 2^64 < 2^67
539 */
540static void felem_square(longfelem out, const felem in)
541 {
542 u64 small[4];
543 felem_shrink(small, in);
544 smallfelem_square(out, small);
545 }
546
547/* smallfelem_mul sets |out| = |small1| * |small2|
548 * On entry:
549 * small1[i] < 2^64
550 * small2[i] < 2^64
551 * On exit:
552 * out[i] < 7 * 2^64 < 2^67
553 */
554static void smallfelem_mul(longfelem out, const smallfelem small1, const smallfelem small2)
555 {
556 limb a;
557 u64 high, low;
558
559 a = ((uint128_t) small1[0]) * small2[0];
560 low = a;
561 high = a >> 64;
562 out[0] = low;
563 out[1] = high;
564
565
566 a = ((uint128_t) small1[0]) * small2[1];
567 low = a;
568 high = a >> 64;
569 out[1] += low;
570 out[2] = high;
571
572 a = ((uint128_t) small1[1]) * small2[0];
573 low = a;
574 high = a >> 64;
575 out[1] += low;
576 out[2] += high;
577
578
579 a = ((uint128_t) small1[0]) * small2[2];
580 low = a;
581 high = a >> 64;
582 out[2] += low;
583 out[3] = high;
584
585 a = ((uint128_t) small1[1]) * small2[1];
586 low = a;
587 high = a >> 64;
588 out[2] += low;
589 out[3] += high;
590
591 a = ((uint128_t) small1[2]) * small2[0];
592 low = a;
593 high = a >> 64;
594 out[2] += low;
595 out[3] += high;
596
597
598 a = ((uint128_t) small1[0]) * small2[3];
599 low = a;
600 high = a >> 64;
601 out[3] += low;
602 out[4] = high;
603
604 a = ((uint128_t) small1[1]) * small2[2];
605 low = a;
606 high = a >> 64;
607 out[3] += low;
608 out[4] += high;
609
610 a = ((uint128_t) small1[2]) * small2[1];
611 low = a;
612 high = a >> 64;
613 out[3] += low;
614 out[4] += high;
615
616 a = ((uint128_t) small1[3]) * small2[0];
617 low = a;
618 high = a >> 64;
619 out[3] += low;
620 out[4] += high;
621
622
623 a = ((uint128_t) small1[1]) * small2[3];
624 low = a;
625 high = a >> 64;
626 out[4] += low;
627 out[5] = high;
628
629 a = ((uint128_t) small1[2]) * small2[2];
630 low = a;
631 high = a >> 64;
632 out[4] += low;
633 out[5] += high;
634
635 a = ((uint128_t) small1[3]) * small2[1];
636 low = a;
637 high = a >> 64;
638 out[4] += low;
639 out[5] += high;
640
641
642 a = ((uint128_t) small1[2]) * small2[3];
643 low = a;
644 high = a >> 64;
645 out[5] += low;
646 out[6] = high;
647
648 a = ((uint128_t) small1[3]) * small2[2];
649 low = a;
650 high = a >> 64;
651 out[5] += low;
652 out[6] += high;
653
654
655 a = ((uint128_t) small1[3]) * small2[3];
656 low = a;
657 high = a >> 64;
658 out[6] += low;
659 out[7] = high;
660 }
661
662/* felem_mul sets |out| = |in1| * |in2|
663 * On entry:
664 * in1[i] < 2^109
665 * in2[i] < 2^109
666 * On exit:
667 * out[i] < 7 * 2^64 < 2^67
668 */
669static void felem_mul(longfelem out, const felem in1, const felem in2)
670 {
671 smallfelem small1, small2;
672 felem_shrink(small1, in1);
673 felem_shrink(small2, in2);
674 smallfelem_mul(out, small1, small2);
675 }
676
677/* felem_small_mul sets |out| = |small1| * |in2|
678 * On entry:
679 * small1[i] < 2^64
680 * in2[i] < 2^109
681 * On exit:
682 * out[i] < 7 * 2^64 < 2^67
683 */
684static void felem_small_mul(longfelem out, const smallfelem small1, const felem in2)
685 {
686 smallfelem small2;
687 felem_shrink(small2, in2);
688 smallfelem_mul(out, small1, small2);
689 }
690
691#define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4)
692#define two100 (((limb)1) << 100)
693#define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4)
694/* zero100 is 0 mod p */
695static const felem zero100 = { two100m36m4, two100, two100m36p4, two100m36p4 };
696
697/* Internal function for the different flavours of felem_reduce.
698 * felem_reduce_ reduces the higher coefficients in[4]-in[7].
699 * On entry:
700 * out[0] >= in[6] + 2^32*in[6] + in[7] + 2^32*in[7]
701 * out[1] >= in[7] + 2^32*in[4]
702 * out[2] >= in[5] + 2^32*in[5]
703 * out[3] >= in[4] + 2^32*in[5] + 2^32*in[6]
704 * On exit:
705 * out[0] <= out[0] + in[4] + 2^32*in[5]
706 * out[1] <= out[1] + in[5] + 2^33*in[6]
707 * out[2] <= out[2] + in[7] + 2*in[6] + 2^33*in[7]
708 * out[3] <= out[3] + 2^32*in[4] + 3*in[7]
709 */
710static void felem_reduce_(felem out, const longfelem in)
711 {
712 int128_t c;
713 /* combine common terms from below */
714 c = in[4] + (in[5] << 32);
715 out[0] += c;
716 out[3] -= c;
717
718 c = in[5] - in[7];
719 out[1] += c;
720 out[2] -= c;
721
722 /* the remaining terms */
723 /* 256: [(0,1),(96,-1),(192,-1),(224,1)] */
724 out[1] -= (in[4] << 32);
725 out[3] += (in[4] << 32);
726
727 /* 320: [(32,1),(64,1),(128,-1),(160,-1),(224,-1)] */
728 out[2] -= (in[5] << 32);
729
730 /* 384: [(0,-1),(32,-1),(96,2),(128,2),(224,-1)] */
731 out[0] -= in[6];
732 out[0] -= (in[6] << 32);
733 out[1] += (in[6] << 33);
734 out[2] += (in[6] * 2);
735 out[3] -= (in[6] << 32);
736
737 /* 448: [(0,-1),(32,-1),(64,-1),(128,1),(160,2),(192,3)] */
738 out[0] -= in[7];
739 out[0] -= (in[7] << 32);
740 out[2] += (in[7] << 33);
741 out[3] += (in[7] * 3);
742 }
743
744/* felem_reduce converts a longfelem into an felem.
745 * To be called directly after felem_square or felem_mul.
746 * On entry:
747 * in[0] < 2^64, in[1] < 3*2^64, in[2] < 5*2^64, in[3] < 7*2^64
748 * in[4] < 7*2^64, in[5] < 5*2^64, in[6] < 3*2^64, in[7] < 2*64
749 * On exit:
750 * out[i] < 2^101
751 */
752static void felem_reduce(felem out, const longfelem in)
753 {
754 out[0] = zero100[0] + in[0];
755 out[1] = zero100[1] + in[1];
756 out[2] = zero100[2] + in[2];
757 out[3] = zero100[3] + in[3];
758
759 felem_reduce_(out, in);
760
761 /* out[0] > 2^100 - 2^36 - 2^4 - 3*2^64 - 3*2^96 - 2^64 - 2^96 > 0
762 * out[1] > 2^100 - 2^64 - 7*2^96 > 0
763 * out[2] > 2^100 - 2^36 + 2^4 - 5*2^64 - 5*2^96 > 0
764 * out[3] > 2^100 - 2^36 + 2^4 - 7*2^64 - 5*2^96 - 3*2^96 > 0
765 *
766 * out[0] < 2^100 + 2^64 + 7*2^64 + 5*2^96 < 2^101
767 * out[1] < 2^100 + 3*2^64 + 5*2^64 + 3*2^97 < 2^101
768 * out[2] < 2^100 + 5*2^64 + 2^64 + 3*2^65 + 2^97 < 2^101
769 * out[3] < 2^100 + 7*2^64 + 7*2^96 + 3*2^64 < 2^101
770 */
771 }
772
773/* felem_reduce_zero105 converts a larger longfelem into an felem.
774 * On entry:
775 * in[0] < 2^71
776 * On exit:
777 * out[i] < 2^106
778 */
779static void felem_reduce_zero105(felem out, const longfelem in)
780 {
781 out[0] = zero105[0] + in[0];
782 out[1] = zero105[1] + in[1];
783 out[2] = zero105[2] + in[2];
784 out[3] = zero105[3] + in[3];
785
786 felem_reduce_(out, in);
787
788 /* out[0] > 2^105 - 2^41 - 2^9 - 2^71 - 2^103 - 2^71 - 2^103 > 0
789 * out[1] > 2^105 - 2^71 - 2^103 > 0
790 * out[2] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 > 0
791 * out[3] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 - 2^103 > 0
792 *
793 * out[0] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106
794 * out[1] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106
795 * out[2] < 2^105 + 2^71 + 2^71 + 2^71 + 2^103 < 2^106
796 * out[3] < 2^105 + 2^71 + 2^103 + 2^71 < 2^106
797 */
798 }
799
800/* subtract_u64 sets *result = *result - v and *carry to one if the subtraction
801 * underflowed. */
802static void subtract_u64(u64* result, u64* carry, u64 v)
803 {
804 uint128_t r = *result;
805 r -= v;
806 *carry = (r >> 64) & 1;
807 *result = (u64) r;
808 }
809
810/* felem_contract converts |in| to its unique, minimal representation.
811 * On entry:
812 * in[i] < 2^109
813 */
814static void felem_contract(smallfelem out, const felem in)
815 {
816 unsigned i;
817 u64 all_equal_so_far = 0, result = 0, carry;
818
819 felem_shrink(out, in);
820 /* small is minimal except that the value might be > p */
821
822 all_equal_so_far--;
823 /* We are doing a constant time test if out >= kPrime. We need to
824 * compare each u64, from most-significant to least significant. For
825 * each one, if all words so far have been equal (m is all ones) then a
826 * non-equal result is the answer. Otherwise we continue. */
827 for (i = 3; i < 4; i--)
828 {
829 u64 equal;
830 uint128_t a = ((uint128_t) kPrime[i]) - out[i];
831 /* if out[i] > kPrime[i] then a will underflow and the high
832 * 64-bits will all be set. */
833 result |= all_equal_so_far & ((u64) (a >> 64));
834
835 /* if kPrime[i] == out[i] then |equal| will be all zeros and
836 * the decrement will make it all ones. */
837 equal = kPrime[i] ^ out[i];
838 equal--;
839 equal &= equal << 32;
840 equal &= equal << 16;
841 equal &= equal << 8;
842 equal &= equal << 4;
843 equal &= equal << 2;
844 equal &= equal << 1;
845 equal = ((s64) equal) >> 63;
846
847 all_equal_so_far &= equal;
848 }
849
850 /* if all_equal_so_far is still all ones then the two values are equal
851 * and so out >= kPrime is true. */
852 result |= all_equal_so_far;
853
854 /* if out >= kPrime then we subtract kPrime. */
855 subtract_u64(&out[0], &carry, result & kPrime[0]);
856 subtract_u64(&out[1], &carry, carry);
857 subtract_u64(&out[2], &carry, carry);
858 subtract_u64(&out[3], &carry, carry);
859
860 subtract_u64(&out[1], &carry, result & kPrime[1]);
861 subtract_u64(&out[2], &carry, carry);
862 subtract_u64(&out[3], &carry, carry);
863
864 subtract_u64(&out[2], &carry, result & kPrime[2]);
865 subtract_u64(&out[3], &carry, carry);
866
867 subtract_u64(&out[3], &carry, result & kPrime[3]);
868 }
869
870static void smallfelem_square_contract(smallfelem out, const smallfelem in)
871 {
872 longfelem longtmp;
873 felem tmp;
874
875 smallfelem_square(longtmp, in);
876 felem_reduce(tmp, longtmp);
877 felem_contract(out, tmp);
878 }
879
880static void smallfelem_mul_contract(smallfelem out, const smallfelem in1, const smallfelem in2)
881 {
882 longfelem longtmp;
883 felem tmp;
884
885 smallfelem_mul(longtmp, in1, in2);
886 felem_reduce(tmp, longtmp);
887 felem_contract(out, tmp);
888 }
889
890/* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0
891 * otherwise.
892 * On entry:
893 * small[i] < 2^64
894 */
895static limb smallfelem_is_zero(const smallfelem small)
896 {
897 limb result;
898 u64 is_p;
899
900 u64 is_zero = small[0] | small[1] | small[2] | small[3];
901 is_zero--;
902 is_zero &= is_zero << 32;
903 is_zero &= is_zero << 16;
904 is_zero &= is_zero << 8;
905 is_zero &= is_zero << 4;
906 is_zero &= is_zero << 2;
907 is_zero &= is_zero << 1;
908 is_zero = ((s64) is_zero) >> 63;
909
910 is_p = (small[0] ^ kPrime[0]) |
911 (small[1] ^ kPrime[1]) |
912 (small[2] ^ kPrime[2]) |
913 (small[3] ^ kPrime[3]);
914 is_p--;
915 is_p &= is_p << 32;
916 is_p &= is_p << 16;
917 is_p &= is_p << 8;
918 is_p &= is_p << 4;
919 is_p &= is_p << 2;
920 is_p &= is_p << 1;
921 is_p = ((s64) is_p) >> 63;
922
923 is_zero |= is_p;
924
925 result = is_zero;
926 result |= ((limb) is_zero) << 64;
927 return result;
928 }
929
930static int smallfelem_is_zero_int(const smallfelem small)
931 {
932 return (int) (smallfelem_is_zero(small) & ((limb)1));
933 }
934
935/* felem_inv calculates |out| = |in|^{-1}
936 *
937 * Based on Fermat's Little Theorem:
938 * a^p = a (mod p)
939 * a^{p-1} = 1 (mod p)
940 * a^{p-2} = a^{-1} (mod p)
941 */
942static void felem_inv(felem out, const felem in)
943 {
944 felem ftmp, ftmp2;
945 /* each e_I will hold |in|^{2^I - 1} */
946 felem e2, e4, e8, e16, e32, e64;
947 longfelem tmp;
948 unsigned i;
949
950 felem_square(tmp, in); felem_reduce(ftmp, tmp); /* 2^1 */
951 felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */
952 felem_assign(e2, ftmp);
953 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */
954 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^4 - 2^2 */
955 felem_mul(tmp, ftmp, e2); felem_reduce(ftmp, tmp); /* 2^4 - 2^0 */
956 felem_assign(e4, ftmp);
957 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^5 - 2^1 */
958 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^6 - 2^2 */
959 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^7 - 2^3 */
960 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^8 - 2^4 */
961 felem_mul(tmp, ftmp, e4); felem_reduce(ftmp, tmp); /* 2^8 - 2^0 */
962 felem_assign(e8, ftmp);
963 for (i = 0; i < 8; i++) {
964 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp);
965 } /* 2^16 - 2^8 */
966 felem_mul(tmp, ftmp, e8); felem_reduce(ftmp, tmp); /* 2^16 - 2^0 */
967 felem_assign(e16, ftmp);
968 for (i = 0; i < 16; i++) {
969 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp);
970 } /* 2^32 - 2^16 */
971 felem_mul(tmp, ftmp, e16); felem_reduce(ftmp, tmp); /* 2^32 - 2^0 */
972 felem_assign(e32, ftmp);
973 for (i = 0; i < 32; i++) {
974 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp);
975 } /* 2^64 - 2^32 */
976 felem_assign(e64, ftmp);
977 felem_mul(tmp, ftmp, in); felem_reduce(ftmp, tmp); /* 2^64 - 2^32 + 2^0 */
978 for (i = 0; i < 192; i++) {
979 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp);
980 } /* 2^256 - 2^224 + 2^192 */
981
982 felem_mul(tmp, e64, e32); felem_reduce(ftmp2, tmp); /* 2^64 - 2^0 */
983 for (i = 0; i < 16; i++) {
984 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp);
985 } /* 2^80 - 2^16 */
986 felem_mul(tmp, ftmp2, e16); felem_reduce(ftmp2, tmp); /* 2^80 - 2^0 */
987 for (i = 0; i < 8; i++) {
988 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp);
989 } /* 2^88 - 2^8 */
990 felem_mul(tmp, ftmp2, e8); felem_reduce(ftmp2, tmp); /* 2^88 - 2^0 */
991 for (i = 0; i < 4; i++) {
992 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp);
993 } /* 2^92 - 2^4 */
994 felem_mul(tmp, ftmp2, e4); felem_reduce(ftmp2, tmp); /* 2^92 - 2^0 */
995 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^93 - 2^1 */
996 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^94 - 2^2 */
997 felem_mul(tmp, ftmp2, e2); felem_reduce(ftmp2, tmp); /* 2^94 - 2^0 */
998 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^95 - 2^1 */
999 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^96 - 2^2 */
1000 felem_mul(tmp, ftmp2, in); felem_reduce(ftmp2, tmp); /* 2^96 - 3 */
1001
1002 felem_mul(tmp, ftmp2, ftmp); felem_reduce(out, tmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */
1003 }
1004
1005static void smallfelem_inv_contract(smallfelem out, const smallfelem in)
1006 {
1007 felem tmp;
1008
1009 smallfelem_expand(tmp, in);
1010 felem_inv(tmp, tmp);
1011 felem_contract(out, tmp);
1012 }
1013
1014/* Group operations
1015 * ----------------
1016 *
1017 * Building on top of the field operations we have the operations on the
1018 * elliptic curve group itself. Points on the curve are represented in Jacobian
1019 * coordinates */
1020
1021/* point_double calculates 2*(x_in, y_in, z_in)
1022 *
1023 * The method is taken from:
1024 * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
1025 *
1026 * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed.
1027 * while x_out == y_in is not (maybe this works, but it's not tested). */
1028static void
1029point_double(felem x_out, felem y_out, felem z_out,
1030 const felem x_in, const felem y_in, const felem z_in)
1031 {
1032 longfelem tmp, tmp2;
1033 felem delta, gamma, beta, alpha, ftmp, ftmp2;
1034 smallfelem small1, small2;
1035
1036 felem_assign(ftmp, x_in);
1037 /* ftmp[i] < 2^106 */
1038 felem_assign(ftmp2, x_in);
1039 /* ftmp2[i] < 2^106 */
1040
1041 /* delta = z^2 */
1042 felem_square(tmp, z_in);
1043 felem_reduce(delta, tmp);
1044 /* delta[i] < 2^101 */
1045
1046 /* gamma = y^2 */
1047 felem_square(tmp, y_in);
1048 felem_reduce(gamma, tmp);
1049 /* gamma[i] < 2^101 */
1050 felem_shrink(small1, gamma);
1051
1052 /* beta = x*gamma */
1053 felem_small_mul(tmp, small1, x_in);
1054 felem_reduce(beta, tmp);
1055 /* beta[i] < 2^101 */
1056
1057 /* alpha = 3*(x-delta)*(x+delta) */
1058 felem_diff(ftmp, delta);
1059 /* ftmp[i] < 2^105 + 2^106 < 2^107 */
1060 felem_sum(ftmp2, delta);
1061 /* ftmp2[i] < 2^105 + 2^106 < 2^107 */
1062 felem_scalar(ftmp2, 3);
1063 /* ftmp2[i] < 3 * 2^107 < 2^109 */
1064 felem_mul(tmp, ftmp, ftmp2);
1065 felem_reduce(alpha, tmp);
1066 /* alpha[i] < 2^101 */
1067 felem_shrink(small2, alpha);
1068
1069 /* x' = alpha^2 - 8*beta */
1070 smallfelem_square(tmp, small2);
1071 felem_reduce(x_out, tmp);
1072 felem_assign(ftmp, beta);
1073 felem_scalar(ftmp, 8);
1074 /* ftmp[i] < 8 * 2^101 = 2^104 */
1075 felem_diff(x_out, ftmp);
1076 /* x_out[i] < 2^105 + 2^101 < 2^106 */
1077
1078 /* z' = (y + z)^2 - gamma - delta */
1079 felem_sum(delta, gamma);
1080 /* delta[i] < 2^101 + 2^101 = 2^102 */
1081 felem_assign(ftmp, y_in);
1082 felem_sum(ftmp, z_in);
1083 /* ftmp[i] < 2^106 + 2^106 = 2^107 */
1084 felem_square(tmp, ftmp);
1085 felem_reduce(z_out, tmp);
1086 felem_diff(z_out, delta);
1087 /* z_out[i] < 2^105 + 2^101 < 2^106 */
1088
1089 /* y' = alpha*(4*beta - x') - 8*gamma^2 */
1090 felem_scalar(beta, 4);
1091 /* beta[i] < 4 * 2^101 = 2^103 */
1092 felem_diff_zero107(beta, x_out);
1093 /* beta[i] < 2^107 + 2^103 < 2^108 */
1094 felem_small_mul(tmp, small2, beta);
1095 /* tmp[i] < 7 * 2^64 < 2^67 */
1096 smallfelem_square(tmp2, small1);
1097 /* tmp2[i] < 7 * 2^64 */
1098 longfelem_scalar(tmp2, 8);
1099 /* tmp2[i] < 8 * 7 * 2^64 = 7 * 2^67 */
1100 longfelem_diff(tmp, tmp2);
1101 /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */
1102 felem_reduce_zero105(y_out, tmp);
1103 /* y_out[i] < 2^106 */
1104 }
1105
1106/* point_double_small is the same as point_double, except that it operates on
1107 * smallfelems */
1108static void
1109point_double_small(smallfelem x_out, smallfelem y_out, smallfelem z_out,
1110 const smallfelem x_in, const smallfelem y_in, const smallfelem z_in)
1111 {
1112 felem felem_x_out, felem_y_out, felem_z_out;
1113 felem felem_x_in, felem_y_in, felem_z_in;
1114
1115 smallfelem_expand(felem_x_in, x_in);
1116 smallfelem_expand(felem_y_in, y_in);
1117 smallfelem_expand(felem_z_in, z_in);
1118 point_double(felem_x_out, felem_y_out, felem_z_out,
1119 felem_x_in, felem_y_in, felem_z_in);
1120 felem_shrink(x_out, felem_x_out);
1121 felem_shrink(y_out, felem_y_out);
1122 felem_shrink(z_out, felem_z_out);
1123 }
1124
1125/* copy_conditional copies in to out iff mask is all ones. */
1126static void
1127copy_conditional(felem out, const felem in, limb mask)
1128 {
1129 unsigned i;
1130 for (i = 0; i < NLIMBS; ++i)
1131 {
1132 const limb tmp = mask & (in[i] ^ out[i]);
1133 out[i] ^= tmp;
1134 }
1135 }
1136
1137/* copy_small_conditional copies in to out iff mask is all ones. */
1138static void
1139copy_small_conditional(felem out, const smallfelem in, limb mask)
1140 {
1141 unsigned i;
1142 const u64 mask64 = mask;
1143 for (i = 0; i < NLIMBS; ++i)
1144 {
1145 out[i] = ((limb) (in[i] & mask64)) | (out[i] & ~mask);
1146 }
1147 }
1148
1149/* point_add calcuates (x1, y1, z1) + (x2, y2, z2)
1150 *
1151 * The method is taken from:
1152 * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl,
1153 * adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity).
1154 *
1155 * This function includes a branch for checking whether the two input points
1156 * are equal, (while not equal to the point at infinity). This case never
1157 * happens during single point multiplication, so there is no timing leak for
1158 * ECDH or ECDSA signing. */
1159static void point_add(felem x3, felem y3, felem z3,
1160 const felem x1, const felem y1, const felem z1,
1161 const int mixed, const smallfelem x2, const smallfelem y2, const smallfelem z2)
1162 {
1163 felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out;
1164 longfelem tmp, tmp2;
1165 smallfelem small1, small2, small3, small4, small5;
1166 limb x_equal, y_equal, z1_is_zero, z2_is_zero;
1167
1168 felem_shrink(small3, z1);
1169
1170 z1_is_zero = smallfelem_is_zero(small3);
1171 z2_is_zero = smallfelem_is_zero(z2);
1172
1173 /* ftmp = z1z1 = z1**2 */
1174 smallfelem_square(tmp, small3);
1175 felem_reduce(ftmp, tmp);
1176 /* ftmp[i] < 2^101 */
1177 felem_shrink(small1, ftmp);
1178
1179 if(!mixed)
1180 {
1181 /* ftmp2 = z2z2 = z2**2 */
1182 smallfelem_square(tmp, z2);
1183 felem_reduce(ftmp2, tmp);
1184 /* ftmp2[i] < 2^101 */
1185 felem_shrink(small2, ftmp2);
1186
1187 felem_shrink(small5, x1);
1188
1189 /* u1 = ftmp3 = x1*z2z2 */
1190 smallfelem_mul(tmp, small5, small2);
1191 felem_reduce(ftmp3, tmp);
1192 /* ftmp3[i] < 2^101 */
1193
1194 /* ftmp5 = z1 + z2 */
1195 felem_assign(ftmp5, z1);
1196 felem_small_sum(ftmp5, z2);
1197 /* ftmp5[i] < 2^107 */
1198
1199 /* ftmp5 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 */
1200 felem_square(tmp, ftmp5);
1201 felem_reduce(ftmp5, tmp);
1202 /* ftmp2 = z2z2 + z1z1 */
1203 felem_sum(ftmp2, ftmp);
1204 /* ftmp2[i] < 2^101 + 2^101 = 2^102 */
1205 felem_diff(ftmp5, ftmp2);
1206 /* ftmp5[i] < 2^105 + 2^101 < 2^106 */
1207
1208 /* ftmp2 = z2 * z2z2 */
1209 smallfelem_mul(tmp, small2, z2);
1210 felem_reduce(ftmp2, tmp);
1211
1212 /* s1 = ftmp2 = y1 * z2**3 */
1213 felem_mul(tmp, y1, ftmp2);
1214 felem_reduce(ftmp6, tmp);
1215 /* ftmp6[i] < 2^101 */
1216 }
1217 else
1218 {
1219 /* We'll assume z2 = 1 (special case z2 = 0 is handled later) */
1220
1221 /* u1 = ftmp3 = x1*z2z2 */
1222 felem_assign(ftmp3, x1);
1223 /* ftmp3[i] < 2^106 */
1224
1225 /* ftmp5 = 2z1z2 */
1226 felem_assign(ftmp5, z1);
1227 felem_scalar(ftmp5, 2);
1228 /* ftmp5[i] < 2*2^106 = 2^107 */
1229
1230 /* s1 = ftmp2 = y1 * z2**3 */
1231 felem_assign(ftmp6, y1);
1232 /* ftmp6[i] < 2^106 */
1233 }
1234
1235 /* u2 = x2*z1z1 */
1236 smallfelem_mul(tmp, x2, small1);
1237 felem_reduce(ftmp4, tmp);
1238
1239 /* h = ftmp4 = u2 - u1 */
1240 felem_diff_zero107(ftmp4, ftmp3);
1241 /* ftmp4[i] < 2^107 + 2^101 < 2^108 */
1242 felem_shrink(small4, ftmp4);
1243
1244 x_equal = smallfelem_is_zero(small4);
1245
1246 /* z_out = ftmp5 * h */
1247 felem_small_mul(tmp, small4, ftmp5);
1248 felem_reduce(z_out, tmp);
1249 /* z_out[i] < 2^101 */
1250
1251 /* ftmp = z1 * z1z1 */
1252 smallfelem_mul(tmp, small1, small3);
1253 felem_reduce(ftmp, tmp);
1254
1255 /* s2 = tmp = y2 * z1**3 */
1256 felem_small_mul(tmp, y2, ftmp);
1257 felem_reduce(ftmp5, tmp);
1258
1259 /* r = ftmp5 = (s2 - s1)*2 */
1260 felem_diff_zero107(ftmp5, ftmp6);
1261 /* ftmp5[i] < 2^107 + 2^107 = 2^108*/
1262 felem_scalar(ftmp5, 2);
1263 /* ftmp5[i] < 2^109 */
1264 felem_shrink(small1, ftmp5);
1265 y_equal = smallfelem_is_zero(small1);
1266
1267 if (x_equal && y_equal && !z1_is_zero && !z2_is_zero)
1268 {
1269 point_double(x3, y3, z3, x1, y1, z1);
1270 return;
1271 }
1272
1273 /* I = ftmp = (2h)**2 */
1274 felem_assign(ftmp, ftmp4);
1275 felem_scalar(ftmp, 2);
1276 /* ftmp[i] < 2*2^108 = 2^109 */
1277 felem_square(tmp, ftmp);
1278 felem_reduce(ftmp, tmp);
1279
1280 /* J = ftmp2 = h * I */
1281 felem_mul(tmp, ftmp4, ftmp);
1282 felem_reduce(ftmp2, tmp);
1283
1284 /* V = ftmp4 = U1 * I */
1285 felem_mul(tmp, ftmp3, ftmp);
1286 felem_reduce(ftmp4, tmp);
1287
1288 /* x_out = r**2 - J - 2V */
1289 smallfelem_square(tmp, small1);
1290 felem_reduce(x_out, tmp);
1291 felem_assign(ftmp3, ftmp4);
1292 felem_scalar(ftmp4, 2);
1293 felem_sum(ftmp4, ftmp2);
1294 /* ftmp4[i] < 2*2^101 + 2^101 < 2^103 */
1295 felem_diff(x_out, ftmp4);
1296 /* x_out[i] < 2^105 + 2^101 */
1297
1298 /* y_out = r(V-x_out) - 2 * s1 * J */
1299 felem_diff_zero107(ftmp3, x_out);
1300 /* ftmp3[i] < 2^107 + 2^101 < 2^108 */
1301 felem_small_mul(tmp, small1, ftmp3);
1302 felem_mul(tmp2, ftmp6, ftmp2);
1303 longfelem_scalar(tmp2, 2);
1304 /* tmp2[i] < 2*2^67 = 2^68 */
1305 longfelem_diff(tmp, tmp2);
1306 /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */
1307 felem_reduce_zero105(y_out, tmp);
1308 /* y_out[i] < 2^106 */
1309
1310 copy_small_conditional(x_out, x2, z1_is_zero);
1311 copy_conditional(x_out, x1, z2_is_zero);
1312 copy_small_conditional(y_out, y2, z1_is_zero);
1313 copy_conditional(y_out, y1, z2_is_zero);
1314 copy_small_conditional(z_out, z2, z1_is_zero);
1315 copy_conditional(z_out, z1, z2_is_zero);
1316 felem_assign(x3, x_out);
1317 felem_assign(y3, y_out);
1318 felem_assign(z3, z_out);
1319 }
1320
1321/* point_add_small is the same as point_add, except that it operates on
1322 * smallfelems */
1323static void point_add_small(smallfelem x3, smallfelem y3, smallfelem z3,
1324 smallfelem x1, smallfelem y1, smallfelem z1,
1325 smallfelem x2, smallfelem y2, smallfelem z2)
1326 {
1327 felem felem_x3, felem_y3, felem_z3;
1328 felem felem_x1, felem_y1, felem_z1;
1329 smallfelem_expand(felem_x1, x1);
1330 smallfelem_expand(felem_y1, y1);
1331 smallfelem_expand(felem_z1, z1);
1332 point_add(felem_x3, felem_y3, felem_z3, felem_x1, felem_y1, felem_z1, 0, x2, y2, z2);
1333 felem_shrink(x3, felem_x3);
1334 felem_shrink(y3, felem_y3);
1335 felem_shrink(z3, felem_z3);
1336 }
1337
1338/* Base point pre computation
1339 * --------------------------
1340 *
1341 * Two different sorts of precomputed tables are used in the following code.
1342 * Each contain various points on the curve, where each point is three field
1343 * elements (x, y, z).
1344 *
1345 * For the base point table, z is usually 1 (0 for the point at infinity).
1346 * This table has 2 * 16 elements, starting with the following:
1347 * index | bits | point
1348 * ------+---------+------------------------------
1349 * 0 | 0 0 0 0 | 0G
1350 * 1 | 0 0 0 1 | 1G
1351 * 2 | 0 0 1 0 | 2^64G
1352 * 3 | 0 0 1 1 | (2^64 + 1)G
1353 * 4 | 0 1 0 0 | 2^128G
1354 * 5 | 0 1 0 1 | (2^128 + 1)G
1355 * 6 | 0 1 1 0 | (2^128 + 2^64)G
1356 * 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G
1357 * 8 | 1 0 0 0 | 2^192G
1358 * 9 | 1 0 0 1 | (2^192 + 1)G
1359 * 10 | 1 0 1 0 | (2^192 + 2^64)G
1360 * 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G
1361 * 12 | 1 1 0 0 | (2^192 + 2^128)G
1362 * 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G
1363 * 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G
1364 * 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G
1365 * followed by a copy of this with each element multiplied by 2^32.
1366 *
1367 * The reason for this is so that we can clock bits into four different
1368 * locations when doing simple scalar multiplies against the base point,
1369 * and then another four locations using the second 16 elements.
1370 *
1371 * Tables for other points have table[i] = iG for i in 0 .. 16. */
1372
1373/* gmul is the table of precomputed base points */
1374static const smallfelem gmul[2][16][3] =
1375{{{{0, 0, 0, 0},
1376 {0, 0, 0, 0},
1377 {0, 0, 0, 0}},
1378 {{0xf4a13945d898c296, 0x77037d812deb33a0, 0xf8bce6e563a440f2, 0x6b17d1f2e12c4247},
1379 {0xcbb6406837bf51f5, 0x2bce33576b315ece, 0x8ee7eb4a7c0f9e16, 0x4fe342e2fe1a7f9b},
1380 {1, 0, 0, 0}},
1381 {{0x90e75cb48e14db63, 0x29493baaad651f7e, 0x8492592e326e25de, 0x0fa822bc2811aaa5},
1382 {0xe41124545f462ee7, 0x34b1a65050fe82f5, 0x6f4ad4bcb3df188b, 0xbff44ae8f5dba80d},
1383 {1, 0, 0, 0}},
1384 {{0x93391ce2097992af, 0xe96c98fd0d35f1fa, 0xb257c0de95e02789, 0x300a4bbc89d6726f},
1385 {0xaa54a291c08127a0, 0x5bb1eeada9d806a5, 0x7f1ddb25ff1e3c6f, 0x72aac7e0d09b4644},
1386 {1, 0, 0, 0}},
1387 {{0x57c84fc9d789bd85, 0xfc35ff7dc297eac3, 0xfb982fd588c6766e, 0x447d739beedb5e67},
1388 {0x0c7e33c972e25b32, 0x3d349b95a7fae500, 0xe12e9d953a4aaff7, 0x2d4825ab834131ee},
1389 {1, 0, 0, 0}},
1390 {{0x13949c932a1d367f, 0xef7fbd2b1a0a11b7, 0xddc6068bb91dfc60, 0xef9519328a9c72ff},
1391 {0x196035a77376d8a8, 0x23183b0895ca1740, 0xc1ee9807022c219c, 0x611e9fc37dbb2c9b},
1392 {1, 0, 0, 0}},
1393 {{0xcae2b1920b57f4bc, 0x2936df5ec6c9bc36, 0x7dea6482e11238bf, 0x550663797b51f5d8},
1394 {0x44ffe216348a964c, 0x9fb3d576dbdefbe1, 0x0afa40018d9d50e5, 0x157164848aecb851},
1395 {1, 0, 0, 0}},
1396 {{0xe48ecafffc5cde01, 0x7ccd84e70d715f26, 0xa2e8f483f43e4391, 0xeb5d7745b21141ea},
1397 {0xcac917e2731a3479, 0x85f22cfe2844b645, 0x0990e6a158006cee, 0xeafd72ebdbecc17b},
1398 {1, 0, 0, 0}},
1399 {{0x6cf20ffb313728be, 0x96439591a3c6b94a, 0x2736ff8344315fc5, 0xa6d39677a7849276},
1400 {0xf2bab833c357f5f4, 0x824a920c2284059b, 0x66b8babd2d27ecdf, 0x674f84749b0b8816},
1401 {1, 0, 0, 0}},
1402 {{0x2df48c04677c8a3e, 0x74e02f080203a56b, 0x31855f7db8c7fedb, 0x4e769e7672c9ddad},
1403 {0xa4c36165b824bbb0, 0xfb9ae16f3b9122a5, 0x1ec0057206947281, 0x42b99082de830663},
1404 {1, 0, 0, 0}},
1405 {{0x6ef95150dda868b9, 0xd1f89e799c0ce131, 0x7fdc1ca008a1c478, 0x78878ef61c6ce04d},
1406 {0x9c62b9121fe0d976, 0x6ace570ebde08d4f, 0xde53142c12309def, 0xb6cb3f5d7b72c321},
1407 {1, 0, 0, 0}},
1408 {{0x7f991ed2c31a3573, 0x5b82dd5bd54fb496, 0x595c5220812ffcae, 0x0c88bc4d716b1287},
1409 {0x3a57bf635f48aca8, 0x7c8181f4df2564f3, 0x18d1b5b39c04e6aa, 0xdd5ddea3f3901dc6},
1410 {1, 0, 0, 0}},
1411 {{0xe96a79fb3e72ad0c, 0x43a0a28c42ba792f, 0xefe0a423083e49f3, 0x68f344af6b317466},
1412 {0xcdfe17db3fb24d4a, 0x668bfc2271f5c626, 0x604ed93c24d67ff3, 0x31b9c405f8540a20},
1413 {1, 0, 0, 0}},
1414 {{0xd36b4789a2582e7f, 0x0d1a10144ec39c28, 0x663c62c3edbad7a0, 0x4052bf4b6f461db9},
1415 {0x235a27c3188d25eb, 0xe724f33999bfcc5b, 0x862be6bd71d70cc8, 0xfecf4d5190b0fc61},
1416 {1, 0, 0, 0}},
1417 {{0x74346c10a1d4cfac, 0xafdf5cc08526a7a4, 0x123202a8f62bff7a, 0x1eddbae2c802e41a},
1418 {0x8fa0af2dd603f844, 0x36e06b7e4c701917, 0x0c45f45273db33a0, 0x43104d86560ebcfc},
1419 {1, 0, 0, 0}},
1420 {{0x9615b5110d1d78e5, 0x66b0de3225c4744b, 0x0a4a46fb6aaf363a, 0xb48e26b484f7a21c},
1421 {0x06ebb0f621a01b2d, 0xc004e4048b7b0f98, 0x64131bcdfed6f668, 0xfac015404d4d3dab},
1422 {1, 0, 0, 0}}},
1423 {{{0, 0, 0, 0},
1424 {0, 0, 0, 0},
1425 {0, 0, 0, 0}},
1426 {{0x3a5a9e22185a5943, 0x1ab919365c65dfb6, 0x21656b32262c71da, 0x7fe36b40af22af89},
1427 {0xd50d152c699ca101, 0x74b3d5867b8af212, 0x9f09f40407dca6f1, 0xe697d45825b63624},
1428 {1, 0, 0, 0}},
1429 {{0xa84aa9397512218e, 0xe9a521b074ca0141, 0x57880b3a18a2e902, 0x4a5b506612a677a6},
1430 {0x0beada7a4c4f3840, 0x626db15419e26d9d, 0xc42604fbe1627d40, 0xeb13461ceac089f1},
1431 {1, 0, 0, 0}},
1432 {{0xf9faed0927a43281, 0x5e52c4144103ecbc, 0xc342967aa815c857, 0x0781b8291c6a220a},
1433 {0x5a8343ceeac55f80, 0x88f80eeee54a05e3, 0x97b2a14f12916434, 0x690cde8df0151593},
1434 {1, 0, 0, 0}},
1435 {{0xaee9c75df7f82f2a, 0x9e4c35874afdf43a, 0xf5622df437371326, 0x8a535f566ec73617},
1436 {0xc5f9a0ac223094b7, 0xcde533864c8c7669, 0x37e02819085a92bf, 0x0455c08468b08bd7},
1437 {1, 0, 0, 0}},
1438 {{0x0c0a6e2c9477b5d9, 0xf9a4bf62876dc444, 0x5050a949b6cdc279, 0x06bada7ab77f8276},
1439 {0xc8b4aed1ea48dac9, 0xdebd8a4b7ea1070f, 0x427d49101366eb70, 0x5b476dfd0e6cb18a},
1440 {1, 0, 0, 0}},
1441 {{0x7c5c3e44278c340a, 0x4d54606812d66f3b, 0x29a751b1ae23c5d8, 0x3e29864e8a2ec908},
1442 {0x142d2a6626dbb850, 0xad1744c4765bd780, 0x1f150e68e322d1ed, 0x239b90ea3dc31e7e},
1443 {1, 0, 0, 0}},
1444 {{0x78c416527a53322a, 0x305dde6709776f8e, 0xdbcab759f8862ed4, 0x820f4dd949f72ff7},
1445 {0x6cc544a62b5debd4, 0x75be5d937b4e8cc4, 0x1b481b1b215c14d3, 0x140406ec783a05ec},
1446 {1, 0, 0, 0}},
1447 {{0x6a703f10e895df07, 0xfd75f3fa01876bd8, 0xeb5b06e70ce08ffe, 0x68f6b8542783dfee},
1448 {0x90c76f8a78712655, 0xcf5293d2f310bf7f, 0xfbc8044dfda45028, 0xcbe1feba92e40ce6},
1449 {1, 0, 0, 0}},
1450 {{0xe998ceea4396e4c1, 0xfc82ef0b6acea274, 0x230f729f2250e927, 0xd0b2f94d2f420109},
1451 {0x4305adddb38d4966, 0x10b838f8624c3b45, 0x7db2636658954e7a, 0x971459828b0719e5},
1452 {1, 0, 0, 0}},
1453 {{0x4bd6b72623369fc9, 0x57f2929e53d0b876, 0xc2d5cba4f2340687, 0x961610004a866aba},
1454 {0x49997bcd2e407a5e, 0x69ab197d92ddcb24, 0x2cf1f2438fe5131c, 0x7acb9fadcee75e44},
1455 {1, 0, 0, 0}},
1456 {{0x254e839423d2d4c0, 0xf57f0c917aea685b, 0xa60d880f6f75aaea, 0x24eb9acca333bf5b},
1457 {0xe3de4ccb1cda5dea, 0xfeef9341c51a6b4f, 0x743125f88bac4c4d, 0x69f891c5acd079cc},
1458 {1, 0, 0, 0}},
1459 {{0xeee44b35702476b5, 0x7ed031a0e45c2258, 0xb422d1e7bd6f8514, 0xe51f547c5972a107},
1460 {0xa25bcd6fc9cf343d, 0x8ca922ee097c184e, 0xa62f98b3a9fe9a06, 0x1c309a2b25bb1387},
1461 {1, 0, 0, 0}},
1462 {{0x9295dbeb1967c459, 0xb00148833472c98e, 0xc504977708011828, 0x20b87b8aa2c4e503},
1463 {0x3063175de057c277, 0x1bd539338fe582dd, 0x0d11adef5f69a044, 0xf5c6fa49919776be},
1464 {1, 0, 0, 0}},
1465 {{0x8c944e760fd59e11, 0x3876cba1102fad5f, 0xa454c3fad83faa56, 0x1ed7d1b9332010b9},
1466 {0xa1011a270024b889, 0x05e4d0dcac0cd344, 0x52b520f0eb6a2a24, 0x3a2b03f03217257a},
1467 {1, 0, 0, 0}},
1468 {{0xf20fc2afdf1d043d, 0xf330240db58d5a62, 0xfc7d229ca0058c3b, 0x15fee545c78dd9f6},
1469 {0x501e82885bc98cda, 0x41ef80e5d046ac04, 0x557d9f49461210fb, 0x4ab5b6b2b8753f81},
1470 {1, 0, 0, 0}}}};
1471
1472/* select_point selects the |idx|th point from a precomputation table and
1473 * copies it to out. */
1474static void select_point(const u64 idx, unsigned int size, const smallfelem pre_comp[16][3], smallfelem out[3])
1475 {
1476 unsigned i, j;
1477 u64 *outlimbs = &out[0][0];
1478 memset(outlimbs, 0, 3 * sizeof(smallfelem));
1479
1480 for (i = 0; i < size; i++)
1481 {
1482 const u64 *inlimbs = (u64*) &pre_comp[i][0][0];
1483 u64 mask = i ^ idx;
1484 mask |= mask >> 4;
1485 mask |= mask >> 2;
1486 mask |= mask >> 1;
1487 mask &= 1;
1488 mask--;
1489 for (j = 0; j < NLIMBS * 3; j++)
1490 outlimbs[j] |= inlimbs[j] & mask;
1491 }
1492 }
1493
1494/* get_bit returns the |i|th bit in |in| */
1495static char get_bit(const felem_bytearray in, int i)
1496 {
1497 if ((i < 0) || (i >= 256))
1498 return 0;
1499 return (in[i >> 3] >> (i & 7)) & 1;
1500 }
1501
1502/* Interleaved point multiplication using precomputed point multiples:
1503 * The small point multiples 0*P, 1*P, ..., 17*P are in pre_comp[],
1504 * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple
1505 * of the generator, using certain (large) precomputed multiples in g_pre_comp.
1506 * Output point (X, Y, Z) is stored in x_out, y_out, z_out */
1507static void batch_mul(felem x_out, felem y_out, felem z_out,
1508 const felem_bytearray scalars[], const unsigned num_points, const u8 *g_scalar,
1509 const int mixed, const smallfelem pre_comp[][17][3], const smallfelem g_pre_comp[2][16][3])
1510 {
1511 int i, skip;
1512 unsigned num, gen_mul = (g_scalar != NULL);
1513 felem nq[3], ftmp;
1514 smallfelem tmp[3];
1515 u64 bits;
1516 u8 sign, digit;
1517
1518 /* set nq to the point at infinity */
1519 memset(nq, 0, 3 * sizeof(felem));
1520
1521 /* Loop over all scalars msb-to-lsb, interleaving additions
1522 * of multiples of the generator (two in each of the last 32 rounds)
1523 * and additions of other points multiples (every 5th round).
1524 */
1525 skip = 1; /* save two point operations in the first round */
1526 for (i = (num_points ? 255 : 31); i >= 0; --i)
1527 {
1528 /* double */
1529 if (!skip)
1530 point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
1531
1532 /* add multiples of the generator */
1533 if (gen_mul && (i <= 31))
1534 {
1535 /* first, look 32 bits upwards */
1536 bits = get_bit(g_scalar, i + 224) << 3;
1537 bits |= get_bit(g_scalar, i + 160) << 2;
1538 bits |= get_bit(g_scalar, i + 96) << 1;
1539 bits |= get_bit(g_scalar, i + 32);
1540 /* select the point to add, in constant time */
1541 select_point(bits, 16, g_pre_comp[1], tmp);
1542
1543 if (!skip)
1544 {
1545 point_add(nq[0], nq[1], nq[2],
1546 nq[0], nq[1], nq[2],
1547 1 /* mixed */, tmp[0], tmp[1], tmp[2]);
1548 }
1549 else
1550 {
1551 smallfelem_expand(nq[0], tmp[0]);
1552 smallfelem_expand(nq[1], tmp[1]);
1553 smallfelem_expand(nq[2], tmp[2]);
1554 skip = 0;
1555 }
1556
1557 /* second, look at the current position */
1558 bits = get_bit(g_scalar, i + 192) << 3;
1559 bits |= get_bit(g_scalar, i + 128) << 2;
1560 bits |= get_bit(g_scalar, i + 64) << 1;
1561 bits |= get_bit(g_scalar, i);
1562 /* select the point to add, in constant time */
1563 select_point(bits, 16, g_pre_comp[0], tmp);
1564 point_add(nq[0], nq[1], nq[2],
1565 nq[0], nq[1], nq[2],
1566 1 /* mixed */, tmp[0], tmp[1], tmp[2]);
1567 }
1568
1569 /* do other additions every 5 doublings */
1570 if (num_points && (i % 5 == 0))
1571 {
1572 /* loop over all scalars */
1573 for (num = 0; num < num_points; ++num)
1574 {
1575 bits = get_bit(scalars[num], i + 4) << 5;
1576 bits |= get_bit(scalars[num], i + 3) << 4;
1577 bits |= get_bit(scalars[num], i + 2) << 3;
1578 bits |= get_bit(scalars[num], i + 1) << 2;
1579 bits |= get_bit(scalars[num], i) << 1;
1580 bits |= get_bit(scalars[num], i - 1);
1581 ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
1582
1583 /* select the point to add or subtract, in constant time */
1584 select_point(digit, 17, pre_comp[num], tmp);
1585 smallfelem_neg(ftmp, tmp[1]); /* (X, -Y, Z) is the negative point */
1586 copy_small_conditional(ftmp, tmp[1], (((limb) sign) - 1));
1587 felem_contract(tmp[1], ftmp);
1588
1589 if (!skip)
1590 {
1591 point_add(nq[0], nq[1], nq[2],
1592 nq[0], nq[1], nq[2],
1593 mixed, tmp[0], tmp[1], tmp[2]);
1594 }
1595 else
1596 {
1597 smallfelem_expand(nq[0], tmp[0]);
1598 smallfelem_expand(nq[1], tmp[1]);
1599 smallfelem_expand(nq[2], tmp[2]);
1600 skip = 0;
1601 }
1602 }
1603 }
1604 }
1605 felem_assign(x_out, nq[0]);
1606 felem_assign(y_out, nq[1]);
1607 felem_assign(z_out, nq[2]);
1608 }
1609
1610/* Precomputation for the group generator. */
1611typedef struct {
1612 smallfelem g_pre_comp[2][16][3];
1613 int references;
1614} NISTP256_PRE_COMP;
1615
1616const EC_METHOD *EC_GFp_nistp256_method(void)
1617 {
1618 static const EC_METHOD ret = {
1619 EC_FLAGS_DEFAULT_OCT,
1620 NID_X9_62_prime_field,
1621 ec_GFp_nistp256_group_init,
1622 ec_GFp_simple_group_finish,
1623 ec_GFp_simple_group_clear_finish,
1624 ec_GFp_nist_group_copy,
1625 ec_GFp_nistp256_group_set_curve,
1626 ec_GFp_simple_group_get_curve,
1627 ec_GFp_simple_group_get_degree,
1628 ec_GFp_simple_group_check_discriminant,
1629 ec_GFp_simple_point_init,
1630 ec_GFp_simple_point_finish,
1631 ec_GFp_simple_point_clear_finish,
1632 ec_GFp_simple_point_copy,
1633 ec_GFp_simple_point_set_to_infinity,
1634 ec_GFp_simple_set_Jprojective_coordinates_GFp,
1635 ec_GFp_simple_get_Jprojective_coordinates_GFp,
1636 ec_GFp_simple_point_set_affine_coordinates,
1637 ec_GFp_nistp256_point_get_affine_coordinates,
1638 0 /* point_set_compressed_coordinates */,
1639 0 /* point2oct */,
1640 0 /* oct2point */,
1641 ec_GFp_simple_add,
1642 ec_GFp_simple_dbl,
1643 ec_GFp_simple_invert,
1644 ec_GFp_simple_is_at_infinity,
1645 ec_GFp_simple_is_on_curve,
1646 ec_GFp_simple_cmp,
1647 ec_GFp_simple_make_affine,
1648 ec_GFp_simple_points_make_affine,
1649 ec_GFp_nistp256_points_mul,
1650 ec_GFp_nistp256_precompute_mult,
1651 ec_GFp_nistp256_have_precompute_mult,
1652 ec_GFp_nist_field_mul,
1653 ec_GFp_nist_field_sqr,
1654 0 /* field_div */,
1655 0 /* field_encode */,
1656 0 /* field_decode */,
1657 0 /* field_set_to_one */ };
1658
1659 return &ret;
1660 }
1661
1662/******************************************************************************/
1663/* FUNCTIONS TO MANAGE PRECOMPUTATION
1664 */
1665
1666static NISTP256_PRE_COMP *nistp256_pre_comp_new()
1667 {
1668 NISTP256_PRE_COMP *ret = NULL;
1669 ret = (NISTP256_PRE_COMP *) OPENSSL_malloc(sizeof *ret);
1670 if (!ret)
1671 {
1672 ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
1673 return ret;
1674 }
1675 memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp));
1676 ret->references = 1;
1677 return ret;
1678 }
1679
1680static void *nistp256_pre_comp_dup(void *src_)
1681 {
1682 NISTP256_PRE_COMP *src = src_;
1683
1684 /* no need to actually copy, these objects never change! */
1685 CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
1686
1687 return src_;
1688 }
1689
1690static void nistp256_pre_comp_free(void *pre_)
1691 {
1692 int i;
1693 NISTP256_PRE_COMP *pre = pre_;
1694
1695 if (!pre)
1696 return;
1697
1698 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1699 if (i > 0)
1700 return;
1701
1702 OPENSSL_free(pre);
1703 }
1704
1705static void nistp256_pre_comp_clear_free(void *pre_)
1706 {
1707 int i;
1708 NISTP256_PRE_COMP *pre = pre_;
1709
1710 if (!pre)
1711 return;
1712
1713 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1714 if (i > 0)
1715 return;
1716
1717 OPENSSL_cleanse(pre, sizeof *pre);
1718 OPENSSL_free(pre);
1719 }
1720
1721/******************************************************************************/
1722/* OPENSSL EC_METHOD FUNCTIONS
1723 */
1724
1725int ec_GFp_nistp256_group_init(EC_GROUP *group)
1726 {
1727 int ret;
1728 ret = ec_GFp_simple_group_init(group);
1729 group->a_is_minus3 = 1;
1730 return ret;
1731 }
1732
1733int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
1734 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1735 {
1736 int ret = 0;
1737 BN_CTX *new_ctx = NULL;
1738 BIGNUM *curve_p, *curve_a, *curve_b;
1739
1740 if (ctx == NULL)
1741 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1742 BN_CTX_start(ctx);
1743 if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
1744 ((curve_a = BN_CTX_get(ctx)) == NULL) ||
1745 ((curve_b = BN_CTX_get(ctx)) == NULL)) goto err;
1746 BN_bin2bn(nistp256_curve_params[0], sizeof(felem_bytearray), curve_p);
1747 BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a);
1748 BN_bin2bn(nistp256_curve_params[2], sizeof(felem_bytearray), curve_b);
1749 if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) ||
1750 (BN_cmp(curve_b, b)))
1751 {
1752 ECerr(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE,
1753 EC_R_WRONG_CURVE_PARAMETERS);
1754 goto err;
1755 }
1756 group->field_mod_func = BN_nist_mod_256;
1757 ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
1758err:
1759 BN_CTX_end(ctx);
1760 if (new_ctx != NULL)
1761 BN_CTX_free(new_ctx);
1762 return ret;
1763 }
1764
1765/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns
1766 * (X', Y') = (X/Z^2, Y/Z^3) */
1767int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
1768 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
1769 {
1770 felem z1, z2, x_in, y_in;
1771 smallfelem x_out, y_out;
1772 longfelem tmp;
1773
1774 if (EC_POINT_is_at_infinity(group, point))
1775 {
1776 ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
1777 EC_R_POINT_AT_INFINITY);
1778 return 0;
1779 }
1780 if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) ||
1781 (!BN_to_felem(z1, &point->Z))) return 0;
1782 felem_inv(z2, z1);
1783 felem_square(tmp, z2); felem_reduce(z1, tmp);
1784 felem_mul(tmp, x_in, z1); felem_reduce(x_in, tmp);
1785 felem_contract(x_out, x_in);
1786 if (x != NULL)
1787 {
1788 if (!smallfelem_to_BN(x, x_out)) {
1789 ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
1790 ERR_R_BN_LIB);
1791 return 0;
1792 }
1793 }
1794 felem_mul(tmp, z1, z2); felem_reduce(z1, tmp);
1795 felem_mul(tmp, y_in, z1); felem_reduce(y_in, tmp);
1796 felem_contract(y_out, y_in);
1797 if (y != NULL)
1798 {
1799 if (!smallfelem_to_BN(y, y_out))
1800 {
1801 ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
1802 ERR_R_BN_LIB);
1803 return 0;
1804 }
1805 }
1806 return 1;
1807 }
1808
1809static void make_points_affine(size_t num, smallfelem points[/* num */][3], smallfelem tmp_smallfelems[/* num+1 */])
1810 {
1811 /* Runs in constant time, unless an input is the point at infinity
1812 * (which normally shouldn't happen). */
1813 ec_GFp_nistp_points_make_affine_internal(
1814 num,
1815 points,
1816 sizeof(smallfelem),
1817 tmp_smallfelems,
1818 (void (*)(void *)) smallfelem_one,
1819 (int (*)(const void *)) smallfelem_is_zero_int,
1820 (void (*)(void *, const void *)) smallfelem_assign,
1821 (void (*)(void *, const void *)) smallfelem_square_contract,
1822 (void (*)(void *, const void *, const void *)) smallfelem_mul_contract,
1823 (void (*)(void *, const void *)) smallfelem_inv_contract,
1824 (void (*)(void *, const void *)) smallfelem_assign /* nothing to contract */);
1825 }
1826
1827/* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL values
1828 * Result is stored in r (r can equal one of the inputs). */
1829int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
1830 const BIGNUM *scalar, size_t num, const EC_POINT *points[],
1831 const BIGNUM *scalars[], BN_CTX *ctx)
1832 {
1833 int ret = 0;
1834 int j;
1835 int mixed = 0;
1836 BN_CTX *new_ctx = NULL;
1837 BIGNUM *x, *y, *z, *tmp_scalar;
1838 felem_bytearray g_secret;
1839 felem_bytearray *secrets = NULL;
1840 smallfelem (*pre_comp)[17][3] = NULL;
1841 smallfelem *tmp_smallfelems = NULL;
1842 felem_bytearray tmp;
1843 unsigned i, num_bytes;
1844 int have_pre_comp = 0;
1845 size_t num_points = num;
1846 smallfelem x_in, y_in, z_in;
1847 felem x_out, y_out, z_out;
1848 NISTP256_PRE_COMP *pre = NULL;
1849 const smallfelem (*g_pre_comp)[16][3] = NULL;
1850 EC_POINT *generator = NULL;
1851 const EC_POINT *p = NULL;
1852 const BIGNUM *p_scalar = NULL;
1853
1854 if (ctx == NULL)
1855 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1856 BN_CTX_start(ctx);
1857 if (((x = BN_CTX_get(ctx)) == NULL) ||
1858 ((y = BN_CTX_get(ctx)) == NULL) ||
1859 ((z = BN_CTX_get(ctx)) == NULL) ||
1860 ((tmp_scalar = BN_CTX_get(ctx)) == NULL))
1861 goto err;
1862
1863 if (scalar != NULL)
1864 {
1865 pre = EC_EX_DATA_get_data(group->extra_data,
1866 nistp256_pre_comp_dup, nistp256_pre_comp_free,
1867 nistp256_pre_comp_clear_free);
1868 if (pre)
1869 /* we have precomputation, try to use it */
1870 g_pre_comp = (const smallfelem (*)[16][3]) pre->g_pre_comp;
1871 else
1872 /* try to use the standard precomputation */
1873 g_pre_comp = &gmul[0];
1874 generator = EC_POINT_new(group);
1875 if (generator == NULL)
1876 goto err;
1877 /* get the generator from precomputation */
1878 if (!smallfelem_to_BN(x, g_pre_comp[0][1][0]) ||
1879 !smallfelem_to_BN(y, g_pre_comp[0][1][1]) ||
1880 !smallfelem_to_BN(z, g_pre_comp[0][1][2]))
1881 {
1882 ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
1883 goto err;
1884 }
1885 if (!EC_POINT_set_Jprojective_coordinates_GFp(group,
1886 generator, x, y, z, ctx))
1887 goto err;
1888 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
1889 /* precomputation matches generator */
1890 have_pre_comp = 1;
1891 else
1892 /* we don't have valid precomputation:
1893 * treat the generator as a random point */
1894 num_points++;
1895 }
1896 if (num_points > 0)
1897 {
1898 if (num_points >= 3)
1899 {
1900 /* unless we precompute multiples for just one or two points,
1901 * converting those into affine form is time well spent */
1902 mixed = 1;
1903 }
1904 secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
1905 pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(smallfelem));
1906 if (mixed)
1907 tmp_smallfelems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(smallfelem));
1908 if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_smallfelems == NULL)))
1909 {
1910 ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
1911 goto err;
1912 }
1913
1914 /* we treat NULL scalars as 0, and NULL points as points at infinity,
1915 * i.e., they contribute nothing to the linear combination */
1916 memset(secrets, 0, num_points * sizeof(felem_bytearray));
1917 memset(pre_comp, 0, num_points * 17 * 3 * sizeof(smallfelem));
1918 for (i = 0; i < num_points; ++i)
1919 {
1920 if (i == num)
1921 /* we didn't have a valid precomputation, so we pick
1922 * the generator */
1923 {
1924 p = EC_GROUP_get0_generator(group);
1925 p_scalar = scalar;
1926 }
1927 else
1928 /* the i^th point */
1929 {
1930 p = points[i];
1931 p_scalar = scalars[i];
1932 }
1933 if ((p_scalar != NULL) && (p != NULL))
1934 {
1935 /* reduce scalar to 0 <= scalar < 2^256 */
1936 if ((BN_num_bits(p_scalar) > 256) || (BN_is_negative(p_scalar)))
1937 {
1938 /* this is an unusual input, and we don't guarantee
1939 * constant-timeness */
1940 if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx))
1941 {
1942 ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
1943 goto err;
1944 }
1945 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1946 }
1947 else
1948 num_bytes = BN_bn2bin(p_scalar, tmp);
1949 flip_endian(secrets[i], tmp, num_bytes);
1950 /* precompute multiples */
1951 if ((!BN_to_felem(x_out, &p->X)) ||
1952 (!BN_to_felem(y_out, &p->Y)) ||
1953 (!BN_to_felem(z_out, &p->Z))) goto err;
1954 felem_shrink(pre_comp[i][1][0], x_out);
1955 felem_shrink(pre_comp[i][1][1], y_out);
1956 felem_shrink(pre_comp[i][1][2], z_out);
1957 for (j = 2; j <= 16; ++j)
1958 {
1959 if (j & 1)
1960 {
1961 point_add_small(
1962 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1963 pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2],
1964 pre_comp[i][j-1][0], pre_comp[i][j-1][1], pre_comp[i][j-1][2]);
1965 }
1966 else
1967 {
1968 point_double_small(
1969 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1970 pre_comp[i][j/2][0], pre_comp[i][j/2][1], pre_comp[i][j/2][2]);
1971 }
1972 }
1973 }
1974 }
1975 if (mixed)
1976 make_points_affine(num_points * 17, pre_comp[0], tmp_smallfelems);
1977 }
1978
1979 /* the scalar for the generator */
1980 if ((scalar != NULL) && (have_pre_comp))
1981 {
1982 memset(g_secret, 0, sizeof(g_secret));
1983 /* reduce scalar to 0 <= scalar < 2^256 */
1984 if ((BN_num_bits(scalar) > 256) || (BN_is_negative(scalar)))
1985 {
1986 /* this is an unusual input, and we don't guarantee
1987 * constant-timeness */
1988 if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx))
1989 {
1990 ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
1991 goto err;
1992 }
1993 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1994 }
1995 else
1996 num_bytes = BN_bn2bin(scalar, tmp);
1997 flip_endian(g_secret, tmp, num_bytes);
1998 /* do the multiplication with generator precomputation*/
1999 batch_mul(x_out, y_out, z_out,
2000 (const felem_bytearray (*)) secrets, num_points,
2001 g_secret,
2002 mixed, (const smallfelem (*)[17][3]) pre_comp,
2003 g_pre_comp);
2004 }
2005 else
2006 /* do the multiplication without generator precomputation */
2007 batch_mul(x_out, y_out, z_out,
2008 (const felem_bytearray (*)) secrets, num_points,
2009 NULL, mixed, (const smallfelem (*)[17][3]) pre_comp, NULL);
2010 /* reduce the output to its unique minimal representation */
2011 felem_contract(x_in, x_out);
2012 felem_contract(y_in, y_out);
2013 felem_contract(z_in, z_out);
2014 if ((!smallfelem_to_BN(x, x_in)) || (!smallfelem_to_BN(y, y_in)) ||
2015 (!smallfelem_to_BN(z, z_in)))
2016 {
2017 ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
2018 goto err;
2019 }
2020 ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
2021
2022err:
2023 BN_CTX_end(ctx);
2024 if (generator != NULL)
2025 EC_POINT_free(generator);
2026 if (new_ctx != NULL)
2027 BN_CTX_free(new_ctx);
2028 if (secrets != NULL)
2029 OPENSSL_free(secrets);
2030 if (pre_comp != NULL)
2031 OPENSSL_free(pre_comp);
2032 if (tmp_smallfelems != NULL)
2033 OPENSSL_free(tmp_smallfelems);
2034 return ret;
2035 }
2036
2037int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
2038 {
2039 int ret = 0;
2040 NISTP256_PRE_COMP *pre = NULL;
2041 int i, j;
2042 BN_CTX *new_ctx = NULL;
2043 BIGNUM *x, *y;
2044 EC_POINT *generator = NULL;
2045 smallfelem tmp_smallfelems[32];
2046 felem x_tmp, y_tmp, z_tmp;
2047
2048 /* throw away old precomputation */
2049 EC_EX_DATA_free_data(&group->extra_data, nistp256_pre_comp_dup,
2050 nistp256_pre_comp_free, nistp256_pre_comp_clear_free);
2051 if (ctx == NULL)
2052 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
2053 BN_CTX_start(ctx);
2054 if (((x = BN_CTX_get(ctx)) == NULL) ||
2055 ((y = BN_CTX_get(ctx)) == NULL))
2056 goto err;
2057 /* get the generator */
2058 if (group->generator == NULL) goto err;
2059 generator = EC_POINT_new(group);
2060 if (generator == NULL)
2061 goto err;
2062 BN_bin2bn(nistp256_curve_params[3], sizeof (felem_bytearray), x);
2063 BN_bin2bn(nistp256_curve_params[4], sizeof (felem_bytearray), y);
2064 if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx))
2065 goto err;
2066 if ((pre = nistp256_pre_comp_new()) == NULL)
2067 goto err;
2068 /* if the generator is the standard one, use built-in precomputation */
2069 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
2070 {
2071 memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp));
2072 ret = 1;
2073 goto err;
2074 }
2075 if ((!BN_to_felem(x_tmp, &group->generator->X)) ||
2076 (!BN_to_felem(y_tmp, &group->generator->Y)) ||
2077 (!BN_to_felem(z_tmp, &group->generator->Z)))
2078 goto err;
2079 felem_shrink(pre->g_pre_comp[0][1][0], x_tmp);
2080 felem_shrink(pre->g_pre_comp[0][1][1], y_tmp);
2081 felem_shrink(pre->g_pre_comp[0][1][2], z_tmp);
2082 /* compute 2^64*G, 2^128*G, 2^192*G for the first table,
2083 * 2^32*G, 2^96*G, 2^160*G, 2^224*G for the second one
2084 */
2085 for (i = 1; i <= 8; i <<= 1)
2086 {
2087 point_double_small(
2088 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2],
2089 pre->g_pre_comp[0][i][0], pre->g_pre_comp[0][i][1], pre->g_pre_comp[0][i][2]);
2090 for (j = 0; j < 31; ++j)
2091 {
2092 point_double_small(
2093 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2],
2094 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]);
2095 }
2096 if (i == 8)
2097 break;
2098 point_double_small(
2099 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2],
2100 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]);
2101 for (j = 0; j < 31; ++j)
2102 {
2103 point_double_small(
2104 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2],
2105 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2]);
2106 }
2107 }
2108 for (i = 0; i < 2; i++)
2109 {
2110 /* g_pre_comp[i][0] is the point at infinity */
2111 memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0]));
2112 /* the remaining multiples */
2113 /* 2^64*G + 2^128*G resp. 2^96*G + 2^160*G */
2114 point_add_small(
2115 pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1], pre->g_pre_comp[i][6][2],
2116 pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2],
2117 pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]);
2118 /* 2^64*G + 2^192*G resp. 2^96*G + 2^224*G */
2119 point_add_small(
2120 pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1], pre->g_pre_comp[i][10][2],
2121 pre->g_pre_comp[i][8][0], pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
2122 pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]);
2123 /* 2^128*G + 2^192*G resp. 2^160*G + 2^224*G */
2124 point_add_small(
2125 pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2],
2126 pre->g_pre_comp[i][8][0], pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
2127 pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2]);
2128 /* 2^64*G + 2^128*G + 2^192*G resp. 2^96*G + 2^160*G + 2^224*G */
2129 point_add_small(
2130 pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1], pre->g_pre_comp[i][14][2],
2131 pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2],
2132 pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]);
2133 for (j = 1; j < 8; ++j)
2134 {
2135 /* odd multiples: add G resp. 2^32*G */
2136 point_add_small(
2137 pre->g_pre_comp[i][2*j+1][0], pre->g_pre_comp[i][2*j+1][1], pre->g_pre_comp[i][2*j+1][2],
2138 pre->g_pre_comp[i][2*j][0], pre->g_pre_comp[i][2*j][1], pre->g_pre_comp[i][2*j][2],
2139 pre->g_pre_comp[i][1][0], pre->g_pre_comp[i][1][1], pre->g_pre_comp[i][1][2]);
2140 }
2141 }
2142 make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_smallfelems);
2143
2144 if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp256_pre_comp_dup,
2145 nistp256_pre_comp_free, nistp256_pre_comp_clear_free))
2146 goto err;
2147 ret = 1;
2148 pre = NULL;
2149 err:
2150 BN_CTX_end(ctx);
2151 if (generator != NULL)
2152 EC_POINT_free(generator);
2153 if (new_ctx != NULL)
2154 BN_CTX_free(new_ctx);
2155 if (pre)
2156 nistp256_pre_comp_free(pre);
2157 return ret;
2158 }
2159
2160int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group)
2161 {
2162 if (EC_EX_DATA_get_data(group->extra_data, nistp256_pre_comp_dup,
2163 nistp256_pre_comp_free, nistp256_pre_comp_clear_free)
2164 != NULL)
2165 return 1;
2166 else
2167 return 0;
2168 }
2169#else
2170static void *dummy=&dummy;
2171#endif
diff --git a/src/lib/libcrypto/ec/ecp_nistp521.c b/src/lib/libcrypto/ec/ecp_nistp521.c
new file mode 100644
index 0000000000..178b655f7f
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_nistp521.c
@@ -0,0 +1,2025 @@
1/* crypto/ec/ecp_nistp521.c */
2/*
3 * Written by Adam Langley (Google) for the OpenSSL project
4 */
5/* Copyright 2011 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 *
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21/*
22 * A 64-bit implementation of the NIST P-521 elliptic curve point multiplication
23 *
24 * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c.
25 * Otherwise based on Emilia's P224 work, which was inspired by my curve25519
26 * work which got its smarts from Daniel J. Bernstein's work on the same.
27 */
28
29#include <openssl/opensslconf.h>
30#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
31
32#ifndef OPENSSL_SYS_VMS
33#include <stdint.h>
34#else
35#include <inttypes.h>
36#endif
37
38#include <string.h>
39#include <openssl/err.h>
40#include "ec_lcl.h"
41
42#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
43 /* even with gcc, the typedef won't work for 32-bit platforms */
44 typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit platforms */
45#else
46 #error "Need GCC 3.1 or later to define type uint128_t"
47#endif
48
49typedef uint8_t u8;
50typedef uint64_t u64;
51typedef int64_t s64;
52
53/* The underlying field.
54 *
55 * P521 operates over GF(2^521-1). We can serialise an element of this field
56 * into 66 bytes where the most significant byte contains only a single bit. We
57 * call this an felem_bytearray. */
58
59typedef u8 felem_bytearray[66];
60
61/* These are the parameters of P521, taken from FIPS 186-3, section D.1.2.5.
62 * These values are big-endian. */
63static const felem_bytearray nistp521_curve_params[5] =
64 {
65 {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* p */
66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
68 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
70 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
71 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
73 0xff, 0xff},
74 {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* a = -3 */
75 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
76 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
77 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
78 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
79 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
80 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
81 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
82 0xff, 0xfc},
83 {0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, /* b */
84 0x9a, 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85,
85 0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3,
86 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1,
87 0x09, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e,
88 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1,
89 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c,
90 0x34, 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50,
91 0x3f, 0x00},
92 {0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, /* x */
93 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95,
94 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f,
95 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d,
96 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7,
97 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
98 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a,
99 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5,
100 0xbd, 0x66},
101 {0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, /* y */
102 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d,
103 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
104 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e,
105 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4,
106 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
107 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72,
108 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1,
109 0x66, 0x50}
110 };
111
112/* The representation of field elements.
113 * ------------------------------------
114 *
115 * We represent field elements with nine values. These values are either 64 or
116 * 128 bits and the field element represented is:
117 * v[0]*2^0 + v[1]*2^58 + v[2]*2^116 + ... + v[8]*2^464 (mod p)
118 * Each of the nine values is called a 'limb'. Since the limbs are spaced only
119 * 58 bits apart, but are greater than 58 bits in length, the most significant
120 * bits of each limb overlap with the least significant bits of the next.
121 *
122 * A field element with 64-bit limbs is an 'felem'. One with 128-bit limbs is a
123 * 'largefelem' */
124
125#define NLIMBS 9
126
127typedef uint64_t limb;
128typedef limb felem[NLIMBS];
129typedef uint128_t largefelem[NLIMBS];
130
131static const limb bottom57bits = 0x1ffffffffffffff;
132static const limb bottom58bits = 0x3ffffffffffffff;
133
134/* bin66_to_felem takes a little-endian byte array and converts it into felem
135 * form. This assumes that the CPU is little-endian. */
136static void bin66_to_felem(felem out, const u8 in[66])
137 {
138 out[0] = (*((limb*) &in[0])) & bottom58bits;
139 out[1] = (*((limb*) &in[7]) >> 2) & bottom58bits;
140 out[2] = (*((limb*) &in[14]) >> 4) & bottom58bits;
141 out[3] = (*((limb*) &in[21]) >> 6) & bottom58bits;
142 out[4] = (*((limb*) &in[29])) & bottom58bits;
143 out[5] = (*((limb*) &in[36]) >> 2) & bottom58bits;
144 out[6] = (*((limb*) &in[43]) >> 4) & bottom58bits;
145 out[7] = (*((limb*) &in[50]) >> 6) & bottom58bits;
146 out[8] = (*((limb*) &in[58])) & bottom57bits;
147 }
148
149/* felem_to_bin66 takes an felem and serialises into a little endian, 66 byte
150 * array. This assumes that the CPU is little-endian. */
151static void felem_to_bin66(u8 out[66], const felem in)
152 {
153 memset(out, 0, 66);
154 (*((limb*) &out[0])) = in[0];
155 (*((limb*) &out[7])) |= in[1] << 2;
156 (*((limb*) &out[14])) |= in[2] << 4;
157 (*((limb*) &out[21])) |= in[3] << 6;
158 (*((limb*) &out[29])) = in[4];
159 (*((limb*) &out[36])) |= in[5] << 2;
160 (*((limb*) &out[43])) |= in[6] << 4;
161 (*((limb*) &out[50])) |= in[7] << 6;
162 (*((limb*) &out[58])) = in[8];
163 }
164
165/* To preserve endianness when using BN_bn2bin and BN_bin2bn */
166static void flip_endian(u8 *out, const u8 *in, unsigned len)
167 {
168 unsigned i;
169 for (i = 0; i < len; ++i)
170 out[i] = in[len-1-i];
171 }
172
173/* BN_to_felem converts an OpenSSL BIGNUM into an felem */
174static int BN_to_felem(felem out, const BIGNUM *bn)
175 {
176 felem_bytearray b_in;
177 felem_bytearray b_out;
178 unsigned num_bytes;
179
180 /* BN_bn2bin eats leading zeroes */
181 memset(b_out, 0, sizeof b_out);
182 num_bytes = BN_num_bytes(bn);
183 if (num_bytes > sizeof b_out)
184 {
185 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
186 return 0;
187 }
188 if (BN_is_negative(bn))
189 {
190 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
191 return 0;
192 }
193 num_bytes = BN_bn2bin(bn, b_in);
194 flip_endian(b_out, b_in, num_bytes);
195 bin66_to_felem(out, b_out);
196 return 1;
197 }
198
199/* felem_to_BN converts an felem into an OpenSSL BIGNUM */
200static BIGNUM *felem_to_BN(BIGNUM *out, const felem in)
201 {
202 felem_bytearray b_in, b_out;
203 felem_to_bin66(b_in, in);
204 flip_endian(b_out, b_in, sizeof b_out);
205 return BN_bin2bn(b_out, sizeof b_out, out);
206 }
207
208
209/* Field operations
210 * ---------------- */
211
212static void felem_one(felem out)
213 {
214 out[0] = 1;
215 out[1] = 0;
216 out[2] = 0;
217 out[3] = 0;
218 out[4] = 0;
219 out[5] = 0;
220 out[6] = 0;
221 out[7] = 0;
222 out[8] = 0;
223 }
224
225static void felem_assign(felem out, const felem in)
226 {
227 out[0] = in[0];
228 out[1] = in[1];
229 out[2] = in[2];
230 out[3] = in[3];
231 out[4] = in[4];
232 out[5] = in[5];
233 out[6] = in[6];
234 out[7] = in[7];
235 out[8] = in[8];
236 }
237
238/* felem_sum64 sets out = out + in. */
239static void felem_sum64(felem out, const felem in)
240 {
241 out[0] += in[0];
242 out[1] += in[1];
243 out[2] += in[2];
244 out[3] += in[3];
245 out[4] += in[4];
246 out[5] += in[5];
247 out[6] += in[6];
248 out[7] += in[7];
249 out[8] += in[8];
250 }
251
252/* felem_scalar sets out = in * scalar */
253static void felem_scalar(felem out, const felem in, limb scalar)
254 {
255 out[0] = in[0] * scalar;
256 out[1] = in[1] * scalar;
257 out[2] = in[2] * scalar;
258 out[3] = in[3] * scalar;
259 out[4] = in[4] * scalar;
260 out[5] = in[5] * scalar;
261 out[6] = in[6] * scalar;
262 out[7] = in[7] * scalar;
263 out[8] = in[8] * scalar;
264 }
265
266/* felem_scalar64 sets out = out * scalar */
267static void felem_scalar64(felem out, limb scalar)
268 {
269 out[0] *= scalar;
270 out[1] *= scalar;
271 out[2] *= scalar;
272 out[3] *= scalar;
273 out[4] *= scalar;
274 out[5] *= scalar;
275 out[6] *= scalar;
276 out[7] *= scalar;
277 out[8] *= scalar;
278 }
279
280/* felem_scalar128 sets out = out * scalar */
281static void felem_scalar128(largefelem out, limb scalar)
282 {
283 out[0] *= scalar;
284 out[1] *= scalar;
285 out[2] *= scalar;
286 out[3] *= scalar;
287 out[4] *= scalar;
288 out[5] *= scalar;
289 out[6] *= scalar;
290 out[7] *= scalar;
291 out[8] *= scalar;
292 }
293
294/* felem_neg sets |out| to |-in|
295 * On entry:
296 * in[i] < 2^59 + 2^14
297 * On exit:
298 * out[i] < 2^62
299 */
300static void felem_neg(felem out, const felem in)
301 {
302 /* In order to prevent underflow, we subtract from 0 mod p. */
303 static const limb two62m3 = (((limb)1) << 62) - (((limb)1) << 5);
304 static const limb two62m2 = (((limb)1) << 62) - (((limb)1) << 4);
305
306 out[0] = two62m3 - in[0];
307 out[1] = two62m2 - in[1];
308 out[2] = two62m2 - in[2];
309 out[3] = two62m2 - in[3];
310 out[4] = two62m2 - in[4];
311 out[5] = two62m2 - in[5];
312 out[6] = two62m2 - in[6];
313 out[7] = two62m2 - in[7];
314 out[8] = two62m2 - in[8];
315 }
316
317/* felem_diff64 subtracts |in| from |out|
318 * On entry:
319 * in[i] < 2^59 + 2^14
320 * On exit:
321 * out[i] < out[i] + 2^62
322 */
323static void felem_diff64(felem out, const felem in)
324 {
325 /* In order to prevent underflow, we add 0 mod p before subtracting. */
326 static const limb two62m3 = (((limb)1) << 62) - (((limb)1) << 5);
327 static const limb two62m2 = (((limb)1) << 62) - (((limb)1) << 4);
328
329 out[0] += two62m3 - in[0];
330 out[1] += two62m2 - in[1];
331 out[2] += two62m2 - in[2];
332 out[3] += two62m2 - in[3];
333 out[4] += two62m2 - in[4];
334 out[5] += two62m2 - in[5];
335 out[6] += two62m2 - in[6];
336 out[7] += two62m2 - in[7];
337 out[8] += two62m2 - in[8];
338 }
339
340/* felem_diff_128_64 subtracts |in| from |out|
341 * On entry:
342 * in[i] < 2^62 + 2^17
343 * On exit:
344 * out[i] < out[i] + 2^63
345 */
346static void felem_diff_128_64(largefelem out, const felem in)
347 {
348 /* In order to prevent underflow, we add 0 mod p before subtracting. */
349 static const limb two63m6 = (((limb)1) << 62) - (((limb)1) << 5);
350 static const limb two63m5 = (((limb)1) << 62) - (((limb)1) << 4);
351
352 out[0] += two63m6 - in[0];
353 out[1] += two63m5 - in[1];
354 out[2] += two63m5 - in[2];
355 out[3] += two63m5 - in[3];
356 out[4] += two63m5 - in[4];
357 out[5] += two63m5 - in[5];
358 out[6] += two63m5 - in[6];
359 out[7] += two63m5 - in[7];
360 out[8] += two63m5 - in[8];
361 }
362
363/* felem_diff_128_64 subtracts |in| from |out|
364 * On entry:
365 * in[i] < 2^126
366 * On exit:
367 * out[i] < out[i] + 2^127 - 2^69
368 */
369static void felem_diff128(largefelem out, const largefelem in)
370 {
371 /* In order to prevent underflow, we add 0 mod p before subtracting. */
372 static const uint128_t two127m70 = (((uint128_t)1) << 127) - (((uint128_t)1) << 70);
373 static const uint128_t two127m69 = (((uint128_t)1) << 127) - (((uint128_t)1) << 69);
374
375 out[0] += (two127m70 - in[0]);
376 out[1] += (two127m69 - in[1]);
377 out[2] += (two127m69 - in[2]);
378 out[3] += (two127m69 - in[3]);
379 out[4] += (two127m69 - in[4]);
380 out[5] += (two127m69 - in[5]);
381 out[6] += (two127m69 - in[6]);
382 out[7] += (two127m69 - in[7]);
383 out[8] += (two127m69 - in[8]);
384 }
385
386/* felem_square sets |out| = |in|^2
387 * On entry:
388 * in[i] < 2^62
389 * On exit:
390 * out[i] < 17 * max(in[i]) * max(in[i])
391 */
392static void felem_square(largefelem out, const felem in)
393 {
394 felem inx2, inx4;
395 felem_scalar(inx2, in, 2);
396 felem_scalar(inx4, in, 4);
397
398 /* We have many cases were we want to do
399 * in[x] * in[y] +
400 * in[y] * in[x]
401 * This is obviously just
402 * 2 * in[x] * in[y]
403 * However, rather than do the doubling on the 128 bit result, we
404 * double one of the inputs to the multiplication by reading from
405 * |inx2| */
406
407 out[0] = ((uint128_t) in[0]) * in[0];
408 out[1] = ((uint128_t) in[0]) * inx2[1];
409 out[2] = ((uint128_t) in[0]) * inx2[2] +
410 ((uint128_t) in[1]) * in[1];
411 out[3] = ((uint128_t) in[0]) * inx2[3] +
412 ((uint128_t) in[1]) * inx2[2];
413 out[4] = ((uint128_t) in[0]) * inx2[4] +
414 ((uint128_t) in[1]) * inx2[3] +
415 ((uint128_t) in[2]) * in[2];
416 out[5] = ((uint128_t) in[0]) * inx2[5] +
417 ((uint128_t) in[1]) * inx2[4] +
418 ((uint128_t) in[2]) * inx2[3];
419 out[6] = ((uint128_t) in[0]) * inx2[6] +
420 ((uint128_t) in[1]) * inx2[5] +
421 ((uint128_t) in[2]) * inx2[4] +
422 ((uint128_t) in[3]) * in[3];
423 out[7] = ((uint128_t) in[0]) * inx2[7] +
424 ((uint128_t) in[1]) * inx2[6] +
425 ((uint128_t) in[2]) * inx2[5] +
426 ((uint128_t) in[3]) * inx2[4];
427 out[8] = ((uint128_t) in[0]) * inx2[8] +
428 ((uint128_t) in[1]) * inx2[7] +
429 ((uint128_t) in[2]) * inx2[6] +
430 ((uint128_t) in[3]) * inx2[5] +
431 ((uint128_t) in[4]) * in[4];
432
433 /* The remaining limbs fall above 2^521, with the first falling at
434 * 2^522. They correspond to locations one bit up from the limbs
435 * produced above so we would have to multiply by two to align them.
436 * Again, rather than operate on the 128-bit result, we double one of
437 * the inputs to the multiplication. If we want to double for both this
438 * reason, and the reason above, then we end up multiplying by four. */
439
440 /* 9 */
441 out[0] += ((uint128_t) in[1]) * inx4[8] +
442 ((uint128_t) in[2]) * inx4[7] +
443 ((uint128_t) in[3]) * inx4[6] +
444 ((uint128_t) in[4]) * inx4[5];
445
446 /* 10 */
447 out[1] += ((uint128_t) in[2]) * inx4[8] +
448 ((uint128_t) in[3]) * inx4[7] +
449 ((uint128_t) in[4]) * inx4[6] +
450 ((uint128_t) in[5]) * inx2[5];
451
452 /* 11 */
453 out[2] += ((uint128_t) in[3]) * inx4[8] +
454 ((uint128_t) in[4]) * inx4[7] +
455 ((uint128_t) in[5]) * inx4[6];
456
457 /* 12 */
458 out[3] += ((uint128_t) in[4]) * inx4[8] +
459 ((uint128_t) in[5]) * inx4[7] +
460 ((uint128_t) in[6]) * inx2[6];
461
462 /* 13 */
463 out[4] += ((uint128_t) in[5]) * inx4[8] +
464 ((uint128_t) in[6]) * inx4[7];
465
466 /* 14 */
467 out[5] += ((uint128_t) in[6]) * inx4[8] +
468 ((uint128_t) in[7]) * inx2[7];
469
470 /* 15 */
471 out[6] += ((uint128_t) in[7]) * inx4[8];
472
473 /* 16 */
474 out[7] += ((uint128_t) in[8]) * inx2[8];
475 }
476
477/* felem_mul sets |out| = |in1| * |in2|
478 * On entry:
479 * in1[i] < 2^64
480 * in2[i] < 2^63
481 * On exit:
482 * out[i] < 17 * max(in1[i]) * max(in2[i])
483 */
484static void felem_mul(largefelem out, const felem in1, const felem in2)
485 {
486 felem in2x2;
487 felem_scalar(in2x2, in2, 2);
488
489 out[0] = ((uint128_t) in1[0]) * in2[0];
490
491 out[1] = ((uint128_t) in1[0]) * in2[1] +
492 ((uint128_t) in1[1]) * in2[0];
493
494 out[2] = ((uint128_t) in1[0]) * in2[2] +
495 ((uint128_t) in1[1]) * in2[1] +
496 ((uint128_t) in1[2]) * in2[0];
497
498 out[3] = ((uint128_t) in1[0]) * in2[3] +
499 ((uint128_t) in1[1]) * in2[2] +
500 ((uint128_t) in1[2]) * in2[1] +
501 ((uint128_t) in1[3]) * in2[0];
502
503 out[4] = ((uint128_t) in1[0]) * in2[4] +
504 ((uint128_t) in1[1]) * in2[3] +
505 ((uint128_t) in1[2]) * in2[2] +
506 ((uint128_t) in1[3]) * in2[1] +
507 ((uint128_t) in1[4]) * in2[0];
508
509 out[5] = ((uint128_t) in1[0]) * in2[5] +
510 ((uint128_t) in1[1]) * in2[4] +
511 ((uint128_t) in1[2]) * in2[3] +
512 ((uint128_t) in1[3]) * in2[2] +
513 ((uint128_t) in1[4]) * in2[1] +
514 ((uint128_t) in1[5]) * in2[0];
515
516 out[6] = ((uint128_t) in1[0]) * in2[6] +
517 ((uint128_t) in1[1]) * in2[5] +
518 ((uint128_t) in1[2]) * in2[4] +
519 ((uint128_t) in1[3]) * in2[3] +
520 ((uint128_t) in1[4]) * in2[2] +
521 ((uint128_t) in1[5]) * in2[1] +
522 ((uint128_t) in1[6]) * in2[0];
523
524 out[7] = ((uint128_t) in1[0]) * in2[7] +
525 ((uint128_t) in1[1]) * in2[6] +
526 ((uint128_t) in1[2]) * in2[5] +
527 ((uint128_t) in1[3]) * in2[4] +
528 ((uint128_t) in1[4]) * in2[3] +
529 ((uint128_t) in1[5]) * in2[2] +
530 ((uint128_t) in1[6]) * in2[1] +
531 ((uint128_t) in1[7]) * in2[0];
532
533 out[8] = ((uint128_t) in1[0]) * in2[8] +
534 ((uint128_t) in1[1]) * in2[7] +
535 ((uint128_t) in1[2]) * in2[6] +
536 ((uint128_t) in1[3]) * in2[5] +
537 ((uint128_t) in1[4]) * in2[4] +
538 ((uint128_t) in1[5]) * in2[3] +
539 ((uint128_t) in1[6]) * in2[2] +
540 ((uint128_t) in1[7]) * in2[1] +
541 ((uint128_t) in1[8]) * in2[0];
542
543 /* See comment in felem_square about the use of in2x2 here */
544
545 out[0] += ((uint128_t) in1[1]) * in2x2[8] +
546 ((uint128_t) in1[2]) * in2x2[7] +
547 ((uint128_t) in1[3]) * in2x2[6] +
548 ((uint128_t) in1[4]) * in2x2[5] +
549 ((uint128_t) in1[5]) * in2x2[4] +
550 ((uint128_t) in1[6]) * in2x2[3] +
551 ((uint128_t) in1[7]) * in2x2[2] +
552 ((uint128_t) in1[8]) * in2x2[1];
553
554 out[1] += ((uint128_t) in1[2]) * in2x2[8] +
555 ((uint128_t) in1[3]) * in2x2[7] +
556 ((uint128_t) in1[4]) * in2x2[6] +
557 ((uint128_t) in1[5]) * in2x2[5] +
558 ((uint128_t) in1[6]) * in2x2[4] +
559 ((uint128_t) in1[7]) * in2x2[3] +
560 ((uint128_t) in1[8]) * in2x2[2];
561
562 out[2] += ((uint128_t) in1[3]) * in2x2[8] +
563 ((uint128_t) in1[4]) * in2x2[7] +
564 ((uint128_t) in1[5]) * in2x2[6] +
565 ((uint128_t) in1[6]) * in2x2[5] +
566 ((uint128_t) in1[7]) * in2x2[4] +
567 ((uint128_t) in1[8]) * in2x2[3];
568
569 out[3] += ((uint128_t) in1[4]) * in2x2[8] +
570 ((uint128_t) in1[5]) * in2x2[7] +
571 ((uint128_t) in1[6]) * in2x2[6] +
572 ((uint128_t) in1[7]) * in2x2[5] +
573 ((uint128_t) in1[8]) * in2x2[4];
574
575 out[4] += ((uint128_t) in1[5]) * in2x2[8] +
576 ((uint128_t) in1[6]) * in2x2[7] +
577 ((uint128_t) in1[7]) * in2x2[6] +
578 ((uint128_t) in1[8]) * in2x2[5];
579
580 out[5] += ((uint128_t) in1[6]) * in2x2[8] +
581 ((uint128_t) in1[7]) * in2x2[7] +
582 ((uint128_t) in1[8]) * in2x2[6];
583
584 out[6] += ((uint128_t) in1[7]) * in2x2[8] +
585 ((uint128_t) in1[8]) * in2x2[7];
586
587 out[7] += ((uint128_t) in1[8]) * in2x2[8];
588 }
589
590static const limb bottom52bits = 0xfffffffffffff;
591
592/* felem_reduce converts a largefelem to an felem.
593 * On entry:
594 * in[i] < 2^128
595 * On exit:
596 * out[i] < 2^59 + 2^14
597 */
598static void felem_reduce(felem out, const largefelem in)
599 {
600 u64 overflow1, overflow2;
601
602 out[0] = ((limb) in[0]) & bottom58bits;
603 out[1] = ((limb) in[1]) & bottom58bits;
604 out[2] = ((limb) in[2]) & bottom58bits;
605 out[3] = ((limb) in[3]) & bottom58bits;
606 out[4] = ((limb) in[4]) & bottom58bits;
607 out[5] = ((limb) in[5]) & bottom58bits;
608 out[6] = ((limb) in[6]) & bottom58bits;
609 out[7] = ((limb) in[7]) & bottom58bits;
610 out[8] = ((limb) in[8]) & bottom58bits;
611
612 /* out[i] < 2^58 */
613
614 out[1] += ((limb) in[0]) >> 58;
615 out[1] += (((limb) (in[0] >> 64)) & bottom52bits) << 6;
616 /* out[1] < 2^58 + 2^6 + 2^58
617 * = 2^59 + 2^6 */
618 out[2] += ((limb) (in[0] >> 64)) >> 52;
619
620 out[2] += ((limb) in[1]) >> 58;
621 out[2] += (((limb) (in[1] >> 64)) & bottom52bits) << 6;
622 out[3] += ((limb) (in[1] >> 64)) >> 52;
623
624 out[3] += ((limb) in[2]) >> 58;
625 out[3] += (((limb) (in[2] >> 64)) & bottom52bits) << 6;
626 out[4] += ((limb) (in[2] >> 64)) >> 52;
627
628 out[4] += ((limb) in[3]) >> 58;
629 out[4] += (((limb) (in[3] >> 64)) & bottom52bits) << 6;
630 out[5] += ((limb) (in[3] >> 64)) >> 52;
631
632 out[5] += ((limb) in[4]) >> 58;
633 out[5] += (((limb) (in[4] >> 64)) & bottom52bits) << 6;
634 out[6] += ((limb) (in[4] >> 64)) >> 52;
635
636 out[6] += ((limb) in[5]) >> 58;
637 out[6] += (((limb) (in[5] >> 64)) & bottom52bits) << 6;
638 out[7] += ((limb) (in[5] >> 64)) >> 52;
639
640 out[7] += ((limb) in[6]) >> 58;
641 out[7] += (((limb) (in[6] >> 64)) & bottom52bits) << 6;
642 out[8] += ((limb) (in[6] >> 64)) >> 52;
643
644 out[8] += ((limb) in[7]) >> 58;
645 out[8] += (((limb) (in[7] >> 64)) & bottom52bits) << 6;
646 /* out[x > 1] < 2^58 + 2^6 + 2^58 + 2^12
647 * < 2^59 + 2^13 */
648 overflow1 = ((limb) (in[7] >> 64)) >> 52;
649
650 overflow1 += ((limb) in[8]) >> 58;
651 overflow1 += (((limb) (in[8] >> 64)) & bottom52bits) << 6;
652 overflow2 = ((limb) (in[8] >> 64)) >> 52;
653
654 overflow1 <<= 1; /* overflow1 < 2^13 + 2^7 + 2^59 */
655 overflow2 <<= 1; /* overflow2 < 2^13 */
656
657 out[0] += overflow1; /* out[0] < 2^60 */
658 out[1] += overflow2; /* out[1] < 2^59 + 2^6 + 2^13 */
659
660 out[1] += out[0] >> 58; out[0] &= bottom58bits;
661 /* out[0] < 2^58
662 * out[1] < 2^59 + 2^6 + 2^13 + 2^2
663 * < 2^59 + 2^14 */
664 }
665
666static void felem_square_reduce(felem out, const felem in)
667 {
668 largefelem tmp;
669 felem_square(tmp, in);
670 felem_reduce(out, tmp);
671 }
672
673static void felem_mul_reduce(felem out, const felem in1, const felem in2)
674 {
675 largefelem tmp;
676 felem_mul(tmp, in1, in2);
677 felem_reduce(out, tmp);
678 }
679
680/* felem_inv calculates |out| = |in|^{-1}
681 *
682 * Based on Fermat's Little Theorem:
683 * a^p = a (mod p)
684 * a^{p-1} = 1 (mod p)
685 * a^{p-2} = a^{-1} (mod p)
686 */
687static void felem_inv(felem out, const felem in)
688 {
689 felem ftmp, ftmp2, ftmp3, ftmp4;
690 largefelem tmp;
691 unsigned i;
692
693 felem_square(tmp, in); felem_reduce(ftmp, tmp); /* 2^1 */
694 felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */
695 felem_assign(ftmp2, ftmp);
696 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */
697 felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2^0 */
698 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^4 - 2^1 */
699
700 felem_square(tmp, ftmp2); felem_reduce(ftmp3, tmp); /* 2^3 - 2^1 */
701 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^4 - 2^2 */
702 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^4 - 2^0 */
703
704 felem_assign(ftmp2, ftmp3);
705 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^5 - 2^1 */
706 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^6 - 2^2 */
707 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^7 - 2^3 */
708 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^8 - 2^4 */
709 felem_assign(ftmp4, ftmp3);
710 felem_mul(tmp, ftmp3, ftmp); felem_reduce(ftmp4, tmp); /* 2^8 - 2^1 */
711 felem_square(tmp, ftmp4); felem_reduce(ftmp4, tmp); /* 2^9 - 2^2 */
712 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^8 - 2^0 */
713 felem_assign(ftmp2, ftmp3);
714
715 for (i = 0; i < 8; i++)
716 {
717 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^16 - 2^8 */
718 }
719 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^16 - 2^0 */
720 felem_assign(ftmp2, ftmp3);
721
722 for (i = 0; i < 16; i++)
723 {
724 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^32 - 2^16 */
725 }
726 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^32 - 2^0 */
727 felem_assign(ftmp2, ftmp3);
728
729 for (i = 0; i < 32; i++)
730 {
731 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^64 - 2^32 */
732 }
733 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^64 - 2^0 */
734 felem_assign(ftmp2, ftmp3);
735
736 for (i = 0; i < 64; i++)
737 {
738 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^128 - 2^64 */
739 }
740 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^128 - 2^0 */
741 felem_assign(ftmp2, ftmp3);
742
743 for (i = 0; i < 128; i++)
744 {
745 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^256 - 2^128 */
746 }
747 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^256 - 2^0 */
748 felem_assign(ftmp2, ftmp3);
749
750 for (i = 0; i < 256; i++)
751 {
752 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^512 - 2^256 */
753 }
754 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^512 - 2^0 */
755
756 for (i = 0; i < 9; i++)
757 {
758 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^521 - 2^9 */
759 }
760 felem_mul(tmp, ftmp3, ftmp4); felem_reduce(ftmp3, tmp); /* 2^512 - 2^2 */
761 felem_mul(tmp, ftmp3, in); felem_reduce(out, tmp); /* 2^512 - 3 */
762}
763
764/* This is 2^521-1, expressed as an felem */
765static const felem kPrime =
766 {
767 0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff,
768 0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff,
769 0x03ffffffffffffff, 0x03ffffffffffffff, 0x01ffffffffffffff
770 };
771
772/* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0
773 * otherwise.
774 * On entry:
775 * in[i] < 2^59 + 2^14
776 */
777static limb felem_is_zero(const felem in)
778 {
779 felem ftmp;
780 limb is_zero, is_p;
781 felem_assign(ftmp, in);
782
783 ftmp[0] += ftmp[8] >> 57; ftmp[8] &= bottom57bits;
784 /* ftmp[8] < 2^57 */
785 ftmp[1] += ftmp[0] >> 58; ftmp[0] &= bottom58bits;
786 ftmp[2] += ftmp[1] >> 58; ftmp[1] &= bottom58bits;
787 ftmp[3] += ftmp[2] >> 58; ftmp[2] &= bottom58bits;
788 ftmp[4] += ftmp[3] >> 58; ftmp[3] &= bottom58bits;
789 ftmp[5] += ftmp[4] >> 58; ftmp[4] &= bottom58bits;
790 ftmp[6] += ftmp[5] >> 58; ftmp[5] &= bottom58bits;
791 ftmp[7] += ftmp[6] >> 58; ftmp[6] &= bottom58bits;
792 ftmp[8] += ftmp[7] >> 58; ftmp[7] &= bottom58bits;
793 /* ftmp[8] < 2^57 + 4 */
794
795 /* The ninth limb of 2*(2^521-1) is 0x03ffffffffffffff, which is
796 * greater than our bound for ftmp[8]. Therefore we only have to check
797 * if the zero is zero or 2^521-1. */
798
799 is_zero = 0;
800 is_zero |= ftmp[0];
801 is_zero |= ftmp[1];
802 is_zero |= ftmp[2];
803 is_zero |= ftmp[3];
804 is_zero |= ftmp[4];
805 is_zero |= ftmp[5];
806 is_zero |= ftmp[6];
807 is_zero |= ftmp[7];
808 is_zero |= ftmp[8];
809
810 is_zero--;
811 /* We know that ftmp[i] < 2^63, therefore the only way that the top bit
812 * can be set is if is_zero was 0 before the decrement. */
813 is_zero = ((s64) is_zero) >> 63;
814
815 is_p = ftmp[0] ^ kPrime[0];
816 is_p |= ftmp[1] ^ kPrime[1];
817 is_p |= ftmp[2] ^ kPrime[2];
818 is_p |= ftmp[3] ^ kPrime[3];
819 is_p |= ftmp[4] ^ kPrime[4];
820 is_p |= ftmp[5] ^ kPrime[5];
821 is_p |= ftmp[6] ^ kPrime[6];
822 is_p |= ftmp[7] ^ kPrime[7];
823 is_p |= ftmp[8] ^ kPrime[8];
824
825 is_p--;
826 is_p = ((s64) is_p) >> 63;
827
828 is_zero |= is_p;
829 return is_zero;
830 }
831
832static int felem_is_zero_int(const felem in)
833 {
834 return (int) (felem_is_zero(in) & ((limb)1));
835 }
836
837/* felem_contract converts |in| to its unique, minimal representation.
838 * On entry:
839 * in[i] < 2^59 + 2^14
840 */
841static void felem_contract(felem out, const felem in)
842 {
843 limb is_p, is_greater, sign;
844 static const limb two58 = ((limb)1) << 58;
845
846 felem_assign(out, in);
847
848 out[0] += out[8] >> 57; out[8] &= bottom57bits;
849 /* out[8] < 2^57 */
850 out[1] += out[0] >> 58; out[0] &= bottom58bits;
851 out[2] += out[1] >> 58; out[1] &= bottom58bits;
852 out[3] += out[2] >> 58; out[2] &= bottom58bits;
853 out[4] += out[3] >> 58; out[3] &= bottom58bits;
854 out[5] += out[4] >> 58; out[4] &= bottom58bits;
855 out[6] += out[5] >> 58; out[5] &= bottom58bits;
856 out[7] += out[6] >> 58; out[6] &= bottom58bits;
857 out[8] += out[7] >> 58; out[7] &= bottom58bits;
858 /* out[8] < 2^57 + 4 */
859
860 /* If the value is greater than 2^521-1 then we have to subtract
861 * 2^521-1 out. See the comments in felem_is_zero regarding why we
862 * don't test for other multiples of the prime. */
863
864 /* First, if |out| is equal to 2^521-1, we subtract it out to get zero. */
865
866 is_p = out[0] ^ kPrime[0];
867 is_p |= out[1] ^ kPrime[1];
868 is_p |= out[2] ^ kPrime[2];
869 is_p |= out[3] ^ kPrime[3];
870 is_p |= out[4] ^ kPrime[4];
871 is_p |= out[5] ^ kPrime[5];
872 is_p |= out[6] ^ kPrime[6];
873 is_p |= out[7] ^ kPrime[7];
874 is_p |= out[8] ^ kPrime[8];
875
876 is_p--;
877 is_p &= is_p << 32;
878 is_p &= is_p << 16;
879 is_p &= is_p << 8;
880 is_p &= is_p << 4;
881 is_p &= is_p << 2;
882 is_p &= is_p << 1;
883 is_p = ((s64) is_p) >> 63;
884 is_p = ~is_p;
885
886 /* is_p is 0 iff |out| == 2^521-1 and all ones otherwise */
887
888 out[0] &= is_p;
889 out[1] &= is_p;
890 out[2] &= is_p;
891 out[3] &= is_p;
892 out[4] &= is_p;
893 out[5] &= is_p;
894 out[6] &= is_p;
895 out[7] &= is_p;
896 out[8] &= is_p;
897
898 /* In order to test that |out| >= 2^521-1 we need only test if out[8]
899 * >> 57 is greater than zero as (2^521-1) + x >= 2^522 */
900 is_greater = out[8] >> 57;
901 is_greater |= is_greater << 32;
902 is_greater |= is_greater << 16;
903 is_greater |= is_greater << 8;
904 is_greater |= is_greater << 4;
905 is_greater |= is_greater << 2;
906 is_greater |= is_greater << 1;
907 is_greater = ((s64) is_greater) >> 63;
908
909 out[0] -= kPrime[0] & is_greater;
910 out[1] -= kPrime[1] & is_greater;
911 out[2] -= kPrime[2] & is_greater;
912 out[3] -= kPrime[3] & is_greater;
913 out[4] -= kPrime[4] & is_greater;
914 out[5] -= kPrime[5] & is_greater;
915 out[6] -= kPrime[6] & is_greater;
916 out[7] -= kPrime[7] & is_greater;
917 out[8] -= kPrime[8] & is_greater;
918
919 /* Eliminate negative coefficients */
920 sign = -(out[0] >> 63); out[0] += (two58 & sign); out[1] -= (1 & sign);
921 sign = -(out[1] >> 63); out[1] += (two58 & sign); out[2] -= (1 & sign);
922 sign = -(out[2] >> 63); out[2] += (two58 & sign); out[3] -= (1 & sign);
923 sign = -(out[3] >> 63); out[3] += (two58 & sign); out[4] -= (1 & sign);
924 sign = -(out[4] >> 63); out[4] += (two58 & sign); out[5] -= (1 & sign);
925 sign = -(out[0] >> 63); out[5] += (two58 & sign); out[6] -= (1 & sign);
926 sign = -(out[6] >> 63); out[6] += (two58 & sign); out[7] -= (1 & sign);
927 sign = -(out[7] >> 63); out[7] += (two58 & sign); out[8] -= (1 & sign);
928 sign = -(out[5] >> 63); out[5] += (two58 & sign); out[6] -= (1 & sign);
929 sign = -(out[6] >> 63); out[6] += (two58 & sign); out[7] -= (1 & sign);
930 sign = -(out[7] >> 63); out[7] += (two58 & sign); out[8] -= (1 & sign);
931 }
932
933/* Group operations
934 * ----------------
935 *
936 * Building on top of the field operations we have the operations on the
937 * elliptic curve group itself. Points on the curve are represented in Jacobian
938 * coordinates */
939
940/* point_double calcuates 2*(x_in, y_in, z_in)
941 *
942 * The method is taken from:
943 * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
944 *
945 * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed.
946 * while x_out == y_in is not (maybe this works, but it's not tested). */
947static void
948point_double(felem x_out, felem y_out, felem z_out,
949 const felem x_in, const felem y_in, const felem z_in)
950 {
951 largefelem tmp, tmp2;
952 felem delta, gamma, beta, alpha, ftmp, ftmp2;
953
954 felem_assign(ftmp, x_in);
955 felem_assign(ftmp2, x_in);
956
957 /* delta = z^2 */
958 felem_square(tmp, z_in);
959 felem_reduce(delta, tmp); /* delta[i] < 2^59 + 2^14 */
960
961 /* gamma = y^2 */
962 felem_square(tmp, y_in);
963 felem_reduce(gamma, tmp); /* gamma[i] < 2^59 + 2^14 */
964
965 /* beta = x*gamma */
966 felem_mul(tmp, x_in, gamma);
967 felem_reduce(beta, tmp); /* beta[i] < 2^59 + 2^14 */
968
969 /* alpha = 3*(x-delta)*(x+delta) */
970 felem_diff64(ftmp, delta);
971 /* ftmp[i] < 2^61 */
972 felem_sum64(ftmp2, delta);
973 /* ftmp2[i] < 2^60 + 2^15 */
974 felem_scalar64(ftmp2, 3);
975 /* ftmp2[i] < 3*2^60 + 3*2^15 */
976 felem_mul(tmp, ftmp, ftmp2);
977 /* tmp[i] < 17(3*2^121 + 3*2^76)
978 * = 61*2^121 + 61*2^76
979 * < 64*2^121 + 64*2^76
980 * = 2^127 + 2^82
981 * < 2^128 */
982 felem_reduce(alpha, tmp);
983
984 /* x' = alpha^2 - 8*beta */
985 felem_square(tmp, alpha);
986 /* tmp[i] < 17*2^120
987 * < 2^125 */
988 felem_assign(ftmp, beta);
989 felem_scalar64(ftmp, 8);
990 /* ftmp[i] < 2^62 + 2^17 */
991 felem_diff_128_64(tmp, ftmp);
992 /* tmp[i] < 2^125 + 2^63 + 2^62 + 2^17 */
993 felem_reduce(x_out, tmp);
994
995 /* z' = (y + z)^2 - gamma - delta */
996 felem_sum64(delta, gamma);
997 /* delta[i] < 2^60 + 2^15 */
998 felem_assign(ftmp, y_in);
999 felem_sum64(ftmp, z_in);
1000 /* ftmp[i] < 2^60 + 2^15 */
1001 felem_square(tmp, ftmp);
1002 /* tmp[i] < 17(2^122)
1003 * < 2^127 */
1004 felem_diff_128_64(tmp, delta);
1005 /* tmp[i] < 2^127 + 2^63 */
1006 felem_reduce(z_out, tmp);
1007
1008 /* y' = alpha*(4*beta - x') - 8*gamma^2 */
1009 felem_scalar64(beta, 4);
1010 /* beta[i] < 2^61 + 2^16 */
1011 felem_diff64(beta, x_out);
1012 /* beta[i] < 2^61 + 2^60 + 2^16 */
1013 felem_mul(tmp, alpha, beta);
1014 /* tmp[i] < 17*((2^59 + 2^14)(2^61 + 2^60 + 2^16))
1015 * = 17*(2^120 + 2^75 + 2^119 + 2^74 + 2^75 + 2^30)
1016 * = 17*(2^120 + 2^119 + 2^76 + 2^74 + 2^30)
1017 * < 2^128 */
1018 felem_square(tmp2, gamma);
1019 /* tmp2[i] < 17*(2^59 + 2^14)^2
1020 * = 17*(2^118 + 2^74 + 2^28) */
1021 felem_scalar128(tmp2, 8);
1022 /* tmp2[i] < 8*17*(2^118 + 2^74 + 2^28)
1023 * = 2^125 + 2^121 + 2^81 + 2^77 + 2^35 + 2^31
1024 * < 2^126 */
1025 felem_diff128(tmp, tmp2);
1026 /* tmp[i] < 2^127 - 2^69 + 17(2^120 + 2^119 + 2^76 + 2^74 + 2^30)
1027 * = 2^127 + 2^124 + 2^122 + 2^120 + 2^118 + 2^80 + 2^78 + 2^76 +
1028 * 2^74 + 2^69 + 2^34 + 2^30
1029 * < 2^128 */
1030 felem_reduce(y_out, tmp);
1031 }
1032
1033/* copy_conditional copies in to out iff mask is all ones. */
1034static void
1035copy_conditional(felem out, const felem in, limb mask)
1036 {
1037 unsigned i;
1038 for (i = 0; i < NLIMBS; ++i)
1039 {
1040 const limb tmp = mask & (in[i] ^ out[i]);
1041 out[i] ^= tmp;
1042 }
1043 }
1044
1045/* point_add calcuates (x1, y1, z1) + (x2, y2, z2)
1046 *
1047 * The method is taken from
1048 * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl,
1049 * adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity).
1050 *
1051 * This function includes a branch for checking whether the two input points
1052 * are equal (while not equal to the point at infinity). This case never
1053 * happens during single point multiplication, so there is no timing leak for
1054 * ECDH or ECDSA signing. */
1055static void point_add(felem x3, felem y3, felem z3,
1056 const felem x1, const felem y1, const felem z1,
1057 const int mixed, const felem x2, const felem y2, const felem z2)
1058 {
1059 felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out;
1060 largefelem tmp, tmp2;
1061 limb x_equal, y_equal, z1_is_zero, z2_is_zero;
1062
1063 z1_is_zero = felem_is_zero(z1);
1064 z2_is_zero = felem_is_zero(z2);
1065
1066 /* ftmp = z1z1 = z1**2 */
1067 felem_square(tmp, z1);
1068 felem_reduce(ftmp, tmp);
1069
1070 if (!mixed)
1071 {
1072 /* ftmp2 = z2z2 = z2**2 */
1073 felem_square(tmp, z2);
1074 felem_reduce(ftmp2, tmp);
1075
1076 /* u1 = ftmp3 = x1*z2z2 */
1077 felem_mul(tmp, x1, ftmp2);
1078 felem_reduce(ftmp3, tmp);
1079
1080 /* ftmp5 = z1 + z2 */
1081 felem_assign(ftmp5, z1);
1082 felem_sum64(ftmp5, z2);
1083 /* ftmp5[i] < 2^61 */
1084
1085 /* ftmp5 = (z1 + z2)**2 - z1z1 - z2z2 = 2*z1z2 */
1086 felem_square(tmp, ftmp5);
1087 /* tmp[i] < 17*2^122 */
1088 felem_diff_128_64(tmp, ftmp);
1089 /* tmp[i] < 17*2^122 + 2^63 */
1090 felem_diff_128_64(tmp, ftmp2);
1091 /* tmp[i] < 17*2^122 + 2^64 */
1092 felem_reduce(ftmp5, tmp);
1093
1094 /* ftmp2 = z2 * z2z2 */
1095 felem_mul(tmp, ftmp2, z2);
1096 felem_reduce(ftmp2, tmp);
1097
1098 /* s1 = ftmp6 = y1 * z2**3 */
1099 felem_mul(tmp, y1, ftmp2);
1100 felem_reduce(ftmp6, tmp);
1101 }
1102 else
1103 {
1104 /* We'll assume z2 = 1 (special case z2 = 0 is handled later) */
1105
1106 /* u1 = ftmp3 = x1*z2z2 */
1107 felem_assign(ftmp3, x1);
1108
1109 /* ftmp5 = 2*z1z2 */
1110 felem_scalar(ftmp5, z1, 2);
1111
1112 /* s1 = ftmp6 = y1 * z2**3 */
1113 felem_assign(ftmp6, y1);
1114 }
1115
1116 /* u2 = x2*z1z1 */
1117 felem_mul(tmp, x2, ftmp);
1118 /* tmp[i] < 17*2^120 */
1119
1120 /* h = ftmp4 = u2 - u1 */
1121 felem_diff_128_64(tmp, ftmp3);
1122 /* tmp[i] < 17*2^120 + 2^63 */
1123 felem_reduce(ftmp4, tmp);
1124
1125 x_equal = felem_is_zero(ftmp4);
1126
1127 /* z_out = ftmp5 * h */
1128 felem_mul(tmp, ftmp5, ftmp4);
1129 felem_reduce(z_out, tmp);
1130
1131 /* ftmp = z1 * z1z1 */
1132 felem_mul(tmp, ftmp, z1);
1133 felem_reduce(ftmp, tmp);
1134
1135 /* s2 = tmp = y2 * z1**3 */
1136 felem_mul(tmp, y2, ftmp);
1137 /* tmp[i] < 17*2^120 */
1138
1139 /* r = ftmp5 = (s2 - s1)*2 */
1140 felem_diff_128_64(tmp, ftmp6);
1141 /* tmp[i] < 17*2^120 + 2^63 */
1142 felem_reduce(ftmp5, tmp);
1143 y_equal = felem_is_zero(ftmp5);
1144 felem_scalar64(ftmp5, 2);
1145 /* ftmp5[i] < 2^61 */
1146
1147 if (x_equal && y_equal && !z1_is_zero && !z2_is_zero)
1148 {
1149 point_double(x3, y3, z3, x1, y1, z1);
1150 return;
1151 }
1152
1153 /* I = ftmp = (2h)**2 */
1154 felem_assign(ftmp, ftmp4);
1155 felem_scalar64(ftmp, 2);
1156 /* ftmp[i] < 2^61 */
1157 felem_square(tmp, ftmp);
1158 /* tmp[i] < 17*2^122 */
1159 felem_reduce(ftmp, tmp);
1160
1161 /* J = ftmp2 = h * I */
1162 felem_mul(tmp, ftmp4, ftmp);
1163 felem_reduce(ftmp2, tmp);
1164
1165 /* V = ftmp4 = U1 * I */
1166 felem_mul(tmp, ftmp3, ftmp);
1167 felem_reduce(ftmp4, tmp);
1168
1169 /* x_out = r**2 - J - 2V */
1170 felem_square(tmp, ftmp5);
1171 /* tmp[i] < 17*2^122 */
1172 felem_diff_128_64(tmp, ftmp2);
1173 /* tmp[i] < 17*2^122 + 2^63 */
1174 felem_assign(ftmp3, ftmp4);
1175 felem_scalar64(ftmp4, 2);
1176 /* ftmp4[i] < 2^61 */
1177 felem_diff_128_64(tmp, ftmp4);
1178 /* tmp[i] < 17*2^122 + 2^64 */
1179 felem_reduce(x_out, tmp);
1180
1181 /* y_out = r(V-x_out) - 2 * s1 * J */
1182 felem_diff64(ftmp3, x_out);
1183 /* ftmp3[i] < 2^60 + 2^60
1184 * = 2^61 */
1185 felem_mul(tmp, ftmp5, ftmp3);
1186 /* tmp[i] < 17*2^122 */
1187 felem_mul(tmp2, ftmp6, ftmp2);
1188 /* tmp2[i] < 17*2^120 */
1189 felem_scalar128(tmp2, 2);
1190 /* tmp2[i] < 17*2^121 */
1191 felem_diff128(tmp, tmp2);
1192 /* tmp[i] < 2^127 - 2^69 + 17*2^122
1193 * = 2^126 - 2^122 - 2^6 - 2^2 - 1
1194 * < 2^127 */
1195 felem_reduce(y_out, tmp);
1196
1197 copy_conditional(x_out, x2, z1_is_zero);
1198 copy_conditional(x_out, x1, z2_is_zero);
1199 copy_conditional(y_out, y2, z1_is_zero);
1200 copy_conditional(y_out, y1, z2_is_zero);
1201 copy_conditional(z_out, z2, z1_is_zero);
1202 copy_conditional(z_out, z1, z2_is_zero);
1203 felem_assign(x3, x_out);
1204 felem_assign(y3, y_out);
1205 felem_assign(z3, z_out);
1206 }
1207
1208/* Base point pre computation
1209 * --------------------------
1210 *
1211 * Two different sorts of precomputed tables are used in the following code.
1212 * Each contain various points on the curve, where each point is three field
1213 * elements (x, y, z).
1214 *
1215 * For the base point table, z is usually 1 (0 for the point at infinity).
1216 * This table has 16 elements:
1217 * index | bits | point
1218 * ------+---------+------------------------------
1219 * 0 | 0 0 0 0 | 0G
1220 * 1 | 0 0 0 1 | 1G
1221 * 2 | 0 0 1 0 | 2^130G
1222 * 3 | 0 0 1 1 | (2^130 + 1)G
1223 * 4 | 0 1 0 0 | 2^260G
1224 * 5 | 0 1 0 1 | (2^260 + 1)G
1225 * 6 | 0 1 1 0 | (2^260 + 2^130)G
1226 * 7 | 0 1 1 1 | (2^260 + 2^130 + 1)G
1227 * 8 | 1 0 0 0 | 2^390G
1228 * 9 | 1 0 0 1 | (2^390 + 1)G
1229 * 10 | 1 0 1 0 | (2^390 + 2^130)G
1230 * 11 | 1 0 1 1 | (2^390 + 2^130 + 1)G
1231 * 12 | 1 1 0 0 | (2^390 + 2^260)G
1232 * 13 | 1 1 0 1 | (2^390 + 2^260 + 1)G
1233 * 14 | 1 1 1 0 | (2^390 + 2^260 + 2^130)G
1234 * 15 | 1 1 1 1 | (2^390 + 2^260 + 2^130 + 1)G
1235 *
1236 * The reason for this is so that we can clock bits into four different
1237 * locations when doing simple scalar multiplies against the base point.
1238 *
1239 * Tables for other points have table[i] = iG for i in 0 .. 16. */
1240
1241/* gmul is the table of precomputed base points */
1242static const felem gmul[16][3] =
1243 {{{0, 0, 0, 0, 0, 0, 0, 0, 0},
1244 {0, 0, 0, 0, 0, 0, 0, 0, 0},
1245 {0, 0, 0, 0, 0, 0, 0, 0, 0}},
1246 {{0x017e7e31c2e5bd66, 0x022cf0615a90a6fe, 0x00127a2ffa8de334,
1247 0x01dfbf9d64a3f877, 0x006b4d3dbaa14b5e, 0x014fed487e0a2bd8,
1248 0x015b4429c6481390, 0x03a73678fb2d988e, 0x00c6858e06b70404},
1249 {0x00be94769fd16650, 0x031c21a89cb09022, 0x039013fad0761353,
1250 0x02657bd099031542, 0x03273e662c97ee72, 0x01e6d11a05ebef45,
1251 0x03d1bd998f544495, 0x03001172297ed0b1, 0x011839296a789a3b},
1252 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1253 {{0x0373faacbc875bae, 0x00f325023721c671, 0x00f666fd3dbde5ad,
1254 0x01a6932363f88ea7, 0x01fc6d9e13f9c47b, 0x03bcbffc2bbf734e,
1255 0x013ee3c3647f3a92, 0x029409fefe75d07d, 0x00ef9199963d85e5},
1256 {0x011173743ad5b178, 0x02499c7c21bf7d46, 0x035beaeabb8b1a58,
1257 0x00f989c4752ea0a3, 0x0101e1de48a9c1a3, 0x01a20076be28ba6c,
1258 0x02f8052e5eb2de95, 0x01bfe8f82dea117c, 0x0160074d3c36ddb7},
1259 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1260 {{0x012f3fc373393b3b, 0x03d3d6172f1419fa, 0x02adc943c0b86873,
1261 0x00d475584177952b, 0x012a4d1673750ee2, 0x00512517a0f13b0c,
1262 0x02b184671a7b1734, 0x0315b84236f1a50a, 0x00a4afc472edbdb9},
1263 {0x00152a7077f385c4, 0x03044007d8d1c2ee, 0x0065829d61d52b52,
1264 0x00494ff6b6631d0d, 0x00a11d94d5f06bcf, 0x02d2f89474d9282e,
1265 0x0241c5727c06eeb9, 0x0386928710fbdb9d, 0x01f883f727b0dfbe},
1266 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1267 {{0x019b0c3c9185544d, 0x006243a37c9d97db, 0x02ee3cbe030a2ad2,
1268 0x00cfdd946bb51e0d, 0x0271c00932606b91, 0x03f817d1ec68c561,
1269 0x03f37009806a369c, 0x03c1f30baf184fd5, 0x01091022d6d2f065},
1270 {0x0292c583514c45ed, 0x0316fca51f9a286c, 0x00300af507c1489a,
1271 0x0295f69008298cf1, 0x02c0ed8274943d7b, 0x016509b9b47a431e,
1272 0x02bc9de9634868ce, 0x005b34929bffcb09, 0x000c1a0121681524},
1273 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1274 {{0x0286abc0292fb9f2, 0x02665eee9805b3f7, 0x01ed7455f17f26d6,
1275 0x0346355b83175d13, 0x006284944cd0a097, 0x0191895bcdec5e51,
1276 0x02e288370afda7d9, 0x03b22312bfefa67a, 0x01d104d3fc0613fe},
1277 {0x0092421a12f7e47f, 0x0077a83fa373c501, 0x03bd25c5f696bd0d,
1278 0x035c41e4d5459761, 0x01ca0d1742b24f53, 0x00aaab27863a509c,
1279 0x018b6de47df73917, 0x025c0b771705cd01, 0x01fd51d566d760a7},
1280 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1281 {{0x01dd92ff6b0d1dbd, 0x039c5e2e8f8afa69, 0x0261ed13242c3b27,
1282 0x0382c6e67026e6a0, 0x01d60b10be2089f9, 0x03c15f3dce86723f,
1283 0x03c764a32d2a062d, 0x017307eac0fad056, 0x018207c0b96c5256},
1284 {0x0196a16d60e13154, 0x03e6ce74c0267030, 0x00ddbf2b4e52a5aa,
1285 0x012738241bbf31c8, 0x00ebe8dc04685a28, 0x024c2ad6d380d4a2,
1286 0x035ee062a6e62d0e, 0x0029ed74af7d3a0f, 0x00eef32aec142ebd},
1287 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1288 {{0x00c31ec398993b39, 0x03a9f45bcda68253, 0x00ac733c24c70890,
1289 0x00872b111401ff01, 0x01d178c23195eafb, 0x03bca2c816b87f74,
1290 0x0261a9af46fbad7a, 0x0324b2a8dd3d28f9, 0x00918121d8f24e23},
1291 {0x032bc8c1ca983cd7, 0x00d869dfb08fc8c6, 0x01693cb61fce1516,
1292 0x012a5ea68f4e88a8, 0x010869cab88d7ae3, 0x009081ad277ceee1,
1293 0x033a77166d064cdc, 0x03955235a1fb3a95, 0x01251a4a9b25b65e},
1294 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1295 {{0x00148a3a1b27f40b, 0x0123186df1b31fdc, 0x00026e7beaad34ce,
1296 0x01db446ac1d3dbba, 0x0299c1a33437eaec, 0x024540610183cbb7,
1297 0x0173bb0e9ce92e46, 0x02b937e43921214b, 0x01ab0436a9bf01b5},
1298 {0x0383381640d46948, 0x008dacbf0e7f330f, 0x03602122bcc3f318,
1299 0x01ee596b200620d6, 0x03bd0585fda430b3, 0x014aed77fd123a83,
1300 0x005ace749e52f742, 0x0390fe041da2b842, 0x0189a8ceb3299242},
1301 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1302 {{0x012a19d6b3282473, 0x00c0915918b423ce, 0x023a954eb94405ae,
1303 0x00529f692be26158, 0x0289fa1b6fa4b2aa, 0x0198ae4ceea346ef,
1304 0x0047d8cdfbdedd49, 0x00cc8c8953f0f6b8, 0x001424abbff49203},
1305 {0x0256732a1115a03a, 0x0351bc38665c6733, 0x03f7b950fb4a6447,
1306 0x000afffa94c22155, 0x025763d0a4dab540, 0x000511e92d4fc283,
1307 0x030a7e9eda0ee96c, 0x004c3cd93a28bf0a, 0x017edb3a8719217f},
1308 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1309 {{0x011de5675a88e673, 0x031d7d0f5e567fbe, 0x0016b2062c970ae5,
1310 0x03f4a2be49d90aa7, 0x03cef0bd13822866, 0x03f0923dcf774a6c,
1311 0x0284bebc4f322f72, 0x016ab2645302bb2c, 0x01793f95dace0e2a},
1312 {0x010646e13527a28f, 0x01ca1babd59dc5e7, 0x01afedfd9a5595df,
1313 0x01f15785212ea6b1, 0x0324e5d64f6ae3f4, 0x02d680f526d00645,
1314 0x0127920fadf627a7, 0x03b383f75df4f684, 0x0089e0057e783b0a},
1315 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1316 {{0x00f334b9eb3c26c6, 0x0298fdaa98568dce, 0x01c2d24843a82292,
1317 0x020bcb24fa1b0711, 0x02cbdb3d2b1875e6, 0x0014907598f89422,
1318 0x03abe3aa43b26664, 0x02cbf47f720bc168, 0x0133b5e73014b79b},
1319 {0x034aab5dab05779d, 0x00cdc5d71fee9abb, 0x0399f16bd4bd9d30,
1320 0x03582fa592d82647, 0x02be1cdfb775b0e9, 0x0034f7cea32e94cb,
1321 0x0335a7f08f56f286, 0x03b707e9565d1c8b, 0x0015c946ea5b614f},
1322 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1323 {{0x024676f6cff72255, 0x00d14625cac96378, 0x00532b6008bc3767,
1324 0x01fc16721b985322, 0x023355ea1b091668, 0x029de7afdc0317c3,
1325 0x02fc8a7ca2da037c, 0x02de1217d74a6f30, 0x013f7173175b73bf},
1326 {0x0344913f441490b5, 0x0200f9e272b61eca, 0x0258a246b1dd55d2,
1327 0x03753db9ea496f36, 0x025e02937a09c5ef, 0x030cbd3d14012692,
1328 0x01793a67e70dc72a, 0x03ec1d37048a662e, 0x006550f700c32a8d},
1329 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1330 {{0x00d3f48a347eba27, 0x008e636649b61bd8, 0x00d3b93716778fb3,
1331 0x004d1915757bd209, 0x019d5311a3da44e0, 0x016d1afcbbe6aade,
1332 0x0241bf5f73265616, 0x0384672e5d50d39b, 0x005009fee522b684},
1333 {0x029b4fab064435fe, 0x018868ee095bbb07, 0x01ea3d6936cc92b8,
1334 0x000608b00f78a2f3, 0x02db911073d1c20f, 0x018205938470100a,
1335 0x01f1e4964cbe6ff2, 0x021a19a29eed4663, 0x01414485f42afa81},
1336 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1337 {{0x01612b3a17f63e34, 0x03813992885428e6, 0x022b3c215b5a9608,
1338 0x029b4057e19f2fcb, 0x0384059a587af7e6, 0x02d6400ace6fe610,
1339 0x029354d896e8e331, 0x00c047ee6dfba65e, 0x0037720542e9d49d},
1340 {0x02ce9eed7c5e9278, 0x0374ed703e79643b, 0x01316c54c4072006,
1341 0x005aaa09054b2ee8, 0x002824000c840d57, 0x03d4eba24771ed86,
1342 0x0189c50aabc3bdae, 0x0338c01541e15510, 0x00466d56e38eed42},
1343 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1344 {{0x007efd8330ad8bd6, 0x02465ed48047710b, 0x0034c6606b215e0c,
1345 0x016ae30c53cbf839, 0x01fa17bd37161216, 0x018ead4e61ce8ab9,
1346 0x005482ed5f5dee46, 0x037543755bba1d7f, 0x005e5ac7e70a9d0f},
1347 {0x0117e1bb2fdcb2a2, 0x03deea36249f40c4, 0x028d09b4a6246cb7,
1348 0x03524b8855bcf756, 0x023d7d109d5ceb58, 0x0178e43e3223ef9c,
1349 0x0154536a0c6e966a, 0x037964d1286ee9fe, 0x0199bcd90e125055},
1350 {1, 0, 0, 0, 0, 0, 0, 0, 0}}};
1351
1352/* select_point selects the |idx|th point from a precomputation table and
1353 * copies it to out. */
1354static void select_point(const limb idx, unsigned int size, const felem pre_comp[/* size */][3],
1355 felem out[3])
1356 {
1357 unsigned i, j;
1358 limb *outlimbs = &out[0][0];
1359 memset(outlimbs, 0, 3 * sizeof(felem));
1360
1361 for (i = 0; i < size; i++)
1362 {
1363 const limb *inlimbs = &pre_comp[i][0][0];
1364 limb mask = i ^ idx;
1365 mask |= mask >> 4;
1366 mask |= mask >> 2;
1367 mask |= mask >> 1;
1368 mask &= 1;
1369 mask--;
1370 for (j = 0; j < NLIMBS * 3; j++)
1371 outlimbs[j] |= inlimbs[j] & mask;
1372 }
1373 }
1374
1375/* get_bit returns the |i|th bit in |in| */
1376static char get_bit(const felem_bytearray in, int i)
1377 {
1378 if (i < 0)
1379 return 0;
1380 return (in[i >> 3] >> (i & 7)) & 1;
1381 }
1382
1383/* Interleaved point multiplication using precomputed point multiples:
1384 * The small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[],
1385 * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple
1386 * of the generator, using certain (large) precomputed multiples in g_pre_comp.
1387 * Output point (X, Y, Z) is stored in x_out, y_out, z_out */
1388static void batch_mul(felem x_out, felem y_out, felem z_out,
1389 const felem_bytearray scalars[], const unsigned num_points, const u8 *g_scalar,
1390 const int mixed, const felem pre_comp[][17][3], const felem g_pre_comp[16][3])
1391 {
1392 int i, skip;
1393 unsigned num, gen_mul = (g_scalar != NULL);
1394 felem nq[3], tmp[4];
1395 limb bits;
1396 u8 sign, digit;
1397
1398 /* set nq to the point at infinity */
1399 memset(nq, 0, 3 * sizeof(felem));
1400
1401 /* Loop over all scalars msb-to-lsb, interleaving additions
1402 * of multiples of the generator (last quarter of rounds)
1403 * and additions of other points multiples (every 5th round).
1404 */
1405 skip = 1; /* save two point operations in the first round */
1406 for (i = (num_points ? 520 : 130); i >= 0; --i)
1407 {
1408 /* double */
1409 if (!skip)
1410 point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
1411
1412 /* add multiples of the generator */
1413 if (gen_mul && (i <= 130))
1414 {
1415 bits = get_bit(g_scalar, i + 390) << 3;
1416 if (i < 130)
1417 {
1418 bits |= get_bit(g_scalar, i + 260) << 2;
1419 bits |= get_bit(g_scalar, i + 130) << 1;
1420 bits |= get_bit(g_scalar, i);
1421 }
1422 /* select the point to add, in constant time */
1423 select_point(bits, 16, g_pre_comp, tmp);
1424 if (!skip)
1425 {
1426 point_add(nq[0], nq[1], nq[2],
1427 nq[0], nq[1], nq[2],
1428 1 /* mixed */, tmp[0], tmp[1], tmp[2]);
1429 }
1430 else
1431 {
1432 memcpy(nq, tmp, 3 * sizeof(felem));
1433 skip = 0;
1434 }
1435 }
1436
1437 /* do other additions every 5 doublings */
1438 if (num_points && (i % 5 == 0))
1439 {
1440 /* loop over all scalars */
1441 for (num = 0; num < num_points; ++num)
1442 {
1443 bits = get_bit(scalars[num], i + 4) << 5;
1444 bits |= get_bit(scalars[num], i + 3) << 4;
1445 bits |= get_bit(scalars[num], i + 2) << 3;
1446 bits |= get_bit(scalars[num], i + 1) << 2;
1447 bits |= get_bit(scalars[num], i) << 1;
1448 bits |= get_bit(scalars[num], i - 1);
1449 ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
1450
1451 /* select the point to add or subtract, in constant time */
1452 select_point(digit, 17, pre_comp[num], tmp);
1453 felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative point */
1454 copy_conditional(tmp[1], tmp[3], (-(limb) sign));
1455
1456 if (!skip)
1457 {
1458 point_add(nq[0], nq[1], nq[2],
1459 nq[0], nq[1], nq[2],
1460 mixed, tmp[0], tmp[1], tmp[2]);
1461 }
1462 else
1463 {
1464 memcpy(nq, tmp, 3 * sizeof(felem));
1465 skip = 0;
1466 }
1467 }
1468 }
1469 }
1470 felem_assign(x_out, nq[0]);
1471 felem_assign(y_out, nq[1]);
1472 felem_assign(z_out, nq[2]);
1473 }
1474
1475
1476/* Precomputation for the group generator. */
1477typedef struct {
1478 felem g_pre_comp[16][3];
1479 int references;
1480} NISTP521_PRE_COMP;
1481
1482const EC_METHOD *EC_GFp_nistp521_method(void)
1483 {
1484 static const EC_METHOD ret = {
1485 EC_FLAGS_DEFAULT_OCT,
1486 NID_X9_62_prime_field,
1487 ec_GFp_nistp521_group_init,
1488 ec_GFp_simple_group_finish,
1489 ec_GFp_simple_group_clear_finish,
1490 ec_GFp_nist_group_copy,
1491 ec_GFp_nistp521_group_set_curve,
1492 ec_GFp_simple_group_get_curve,
1493 ec_GFp_simple_group_get_degree,
1494 ec_GFp_simple_group_check_discriminant,
1495 ec_GFp_simple_point_init,
1496 ec_GFp_simple_point_finish,
1497 ec_GFp_simple_point_clear_finish,
1498 ec_GFp_simple_point_copy,
1499 ec_GFp_simple_point_set_to_infinity,
1500 ec_GFp_simple_set_Jprojective_coordinates_GFp,
1501 ec_GFp_simple_get_Jprojective_coordinates_GFp,
1502 ec_GFp_simple_point_set_affine_coordinates,
1503 ec_GFp_nistp521_point_get_affine_coordinates,
1504 0 /* point_set_compressed_coordinates */,
1505 0 /* point2oct */,
1506 0 /* oct2point */,
1507 ec_GFp_simple_add,
1508 ec_GFp_simple_dbl,
1509 ec_GFp_simple_invert,
1510 ec_GFp_simple_is_at_infinity,
1511 ec_GFp_simple_is_on_curve,
1512 ec_GFp_simple_cmp,
1513 ec_GFp_simple_make_affine,
1514 ec_GFp_simple_points_make_affine,
1515 ec_GFp_nistp521_points_mul,
1516 ec_GFp_nistp521_precompute_mult,
1517 ec_GFp_nistp521_have_precompute_mult,
1518 ec_GFp_nist_field_mul,
1519 ec_GFp_nist_field_sqr,
1520 0 /* field_div */,
1521 0 /* field_encode */,
1522 0 /* field_decode */,
1523 0 /* field_set_to_one */ };
1524
1525 return &ret;
1526 }
1527
1528
1529/******************************************************************************/
1530/* FUNCTIONS TO MANAGE PRECOMPUTATION
1531 */
1532
1533static NISTP521_PRE_COMP *nistp521_pre_comp_new()
1534 {
1535 NISTP521_PRE_COMP *ret = NULL;
1536 ret = (NISTP521_PRE_COMP *)OPENSSL_malloc(sizeof(NISTP521_PRE_COMP));
1537 if (!ret)
1538 {
1539 ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
1540 return ret;
1541 }
1542 memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp));
1543 ret->references = 1;
1544 return ret;
1545 }
1546
1547static void *nistp521_pre_comp_dup(void *src_)
1548 {
1549 NISTP521_PRE_COMP *src = src_;
1550
1551 /* no need to actually copy, these objects never change! */
1552 CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
1553
1554 return src_;
1555 }
1556
1557static void nistp521_pre_comp_free(void *pre_)
1558 {
1559 int i;
1560 NISTP521_PRE_COMP *pre = pre_;
1561
1562 if (!pre)
1563 return;
1564
1565 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1566 if (i > 0)
1567 return;
1568
1569 OPENSSL_free(pre);
1570 }
1571
1572static void nistp521_pre_comp_clear_free(void *pre_)
1573 {
1574 int i;
1575 NISTP521_PRE_COMP *pre = pre_;
1576
1577 if (!pre)
1578 return;
1579
1580 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1581 if (i > 0)
1582 return;
1583
1584 OPENSSL_cleanse(pre, sizeof(*pre));
1585 OPENSSL_free(pre);
1586 }
1587
1588/******************************************************************************/
1589/* OPENSSL EC_METHOD FUNCTIONS
1590 */
1591
1592int ec_GFp_nistp521_group_init(EC_GROUP *group)
1593 {
1594 int ret;
1595 ret = ec_GFp_simple_group_init(group);
1596 group->a_is_minus3 = 1;
1597 return ret;
1598 }
1599
1600int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
1601 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1602 {
1603 int ret = 0;
1604 BN_CTX *new_ctx = NULL;
1605 BIGNUM *curve_p, *curve_a, *curve_b;
1606
1607 if (ctx == NULL)
1608 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1609 BN_CTX_start(ctx);
1610 if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
1611 ((curve_a = BN_CTX_get(ctx)) == NULL) ||
1612 ((curve_b = BN_CTX_get(ctx)) == NULL)) goto err;
1613 BN_bin2bn(nistp521_curve_params[0], sizeof(felem_bytearray), curve_p);
1614 BN_bin2bn(nistp521_curve_params[1], sizeof(felem_bytearray), curve_a);
1615 BN_bin2bn(nistp521_curve_params[2], sizeof(felem_bytearray), curve_b);
1616 if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) ||
1617 (BN_cmp(curve_b, b)))
1618 {
1619 ECerr(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE,
1620 EC_R_WRONG_CURVE_PARAMETERS);
1621 goto err;
1622 }
1623 group->field_mod_func = BN_nist_mod_521;
1624 ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
1625err:
1626 BN_CTX_end(ctx);
1627 if (new_ctx != NULL)
1628 BN_CTX_free(new_ctx);
1629 return ret;
1630 }
1631
1632/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns
1633 * (X', Y') = (X/Z^2, Y/Z^3) */
1634int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group,
1635 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
1636 {
1637 felem z1, z2, x_in, y_in, x_out, y_out;
1638 largefelem tmp;
1639
1640 if (EC_POINT_is_at_infinity(group, point))
1641 {
1642 ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES,
1643 EC_R_POINT_AT_INFINITY);
1644 return 0;
1645 }
1646 if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) ||
1647 (!BN_to_felem(z1, &point->Z))) return 0;
1648 felem_inv(z2, z1);
1649 felem_square(tmp, z2); felem_reduce(z1, tmp);
1650 felem_mul(tmp, x_in, z1); felem_reduce(x_in, tmp);
1651 felem_contract(x_out, x_in);
1652 if (x != NULL)
1653 {
1654 if (!felem_to_BN(x, x_out))
1655 {
1656 ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
1657 return 0;
1658 }
1659 }
1660 felem_mul(tmp, z1, z2); felem_reduce(z1, tmp);
1661 felem_mul(tmp, y_in, z1); felem_reduce(y_in, tmp);
1662 felem_contract(y_out, y_in);
1663 if (y != NULL)
1664 {
1665 if (!felem_to_BN(y, y_out))
1666 {
1667 ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
1668 return 0;
1669 }
1670 }
1671 return 1;
1672 }
1673
1674static void make_points_affine(size_t num, felem points[/* num */][3], felem tmp_felems[/* num+1 */])
1675 {
1676 /* Runs in constant time, unless an input is the point at infinity
1677 * (which normally shouldn't happen). */
1678 ec_GFp_nistp_points_make_affine_internal(
1679 num,
1680 points,
1681 sizeof(felem),
1682 tmp_felems,
1683 (void (*)(void *)) felem_one,
1684 (int (*)(const void *)) felem_is_zero_int,
1685 (void (*)(void *, const void *)) felem_assign,
1686 (void (*)(void *, const void *)) felem_square_reduce,
1687 (void (*)(void *, const void *, const void *)) felem_mul_reduce,
1688 (void (*)(void *, const void *)) felem_inv,
1689 (void (*)(void *, const void *)) felem_contract);
1690 }
1691
1692/* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL values
1693 * Result is stored in r (r can equal one of the inputs). */
1694int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
1695 const BIGNUM *scalar, size_t num, const EC_POINT *points[],
1696 const BIGNUM *scalars[], BN_CTX *ctx)
1697 {
1698 int ret = 0;
1699 int j;
1700 int mixed = 0;
1701 BN_CTX *new_ctx = NULL;
1702 BIGNUM *x, *y, *z, *tmp_scalar;
1703 felem_bytearray g_secret;
1704 felem_bytearray *secrets = NULL;
1705 felem (*pre_comp)[17][3] = NULL;
1706 felem *tmp_felems = NULL;
1707 felem_bytearray tmp;
1708 unsigned i, num_bytes;
1709 int have_pre_comp = 0;
1710 size_t num_points = num;
1711 felem x_in, y_in, z_in, x_out, y_out, z_out;
1712 NISTP521_PRE_COMP *pre = NULL;
1713 felem (*g_pre_comp)[3] = NULL;
1714 EC_POINT *generator = NULL;
1715 const EC_POINT *p = NULL;
1716 const BIGNUM *p_scalar = NULL;
1717
1718 if (ctx == NULL)
1719 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1720 BN_CTX_start(ctx);
1721 if (((x = BN_CTX_get(ctx)) == NULL) ||
1722 ((y = BN_CTX_get(ctx)) == NULL) ||
1723 ((z = BN_CTX_get(ctx)) == NULL) ||
1724 ((tmp_scalar = BN_CTX_get(ctx)) == NULL))
1725 goto err;
1726
1727 if (scalar != NULL)
1728 {
1729 pre = EC_EX_DATA_get_data(group->extra_data,
1730 nistp521_pre_comp_dup, nistp521_pre_comp_free,
1731 nistp521_pre_comp_clear_free);
1732 if (pre)
1733 /* we have precomputation, try to use it */
1734 g_pre_comp = &pre->g_pre_comp[0];
1735 else
1736 /* try to use the standard precomputation */
1737 g_pre_comp = (felem (*)[3]) gmul;
1738 generator = EC_POINT_new(group);
1739 if (generator == NULL)
1740 goto err;
1741 /* get the generator from precomputation */
1742 if (!felem_to_BN(x, g_pre_comp[1][0]) ||
1743 !felem_to_BN(y, g_pre_comp[1][1]) ||
1744 !felem_to_BN(z, g_pre_comp[1][2]))
1745 {
1746 ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
1747 goto err;
1748 }
1749 if (!EC_POINT_set_Jprojective_coordinates_GFp(group,
1750 generator, x, y, z, ctx))
1751 goto err;
1752 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
1753 /* precomputation matches generator */
1754 have_pre_comp = 1;
1755 else
1756 /* we don't have valid precomputation:
1757 * treat the generator as a random point */
1758 num_points++;
1759 }
1760
1761 if (num_points > 0)
1762 {
1763 if (num_points >= 2)
1764 {
1765 /* unless we precompute multiples for just one point,
1766 * converting those into affine form is time well spent */
1767 mixed = 1;
1768 }
1769 secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
1770 pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(felem));
1771 if (mixed)
1772 tmp_felems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem));
1773 if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_felems == NULL)))
1774 {
1775 ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_MALLOC_FAILURE);
1776 goto err;
1777 }
1778
1779 /* we treat NULL scalars as 0, and NULL points as points at infinity,
1780 * i.e., they contribute nothing to the linear combination */
1781 memset(secrets, 0, num_points * sizeof(felem_bytearray));
1782 memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem));
1783 for (i = 0; i < num_points; ++i)
1784 {
1785 if (i == num)
1786 /* we didn't have a valid precomputation, so we pick
1787 * the generator */
1788 {
1789 p = EC_GROUP_get0_generator(group);
1790 p_scalar = scalar;
1791 }
1792 else
1793 /* the i^th point */
1794 {
1795 p = points[i];
1796 p_scalar = scalars[i];
1797 }
1798 if ((p_scalar != NULL) && (p != NULL))
1799 {
1800 /* reduce scalar to 0 <= scalar < 2^521 */
1801 if ((BN_num_bits(p_scalar) > 521) || (BN_is_negative(p_scalar)))
1802 {
1803 /* this is an unusual input, and we don't guarantee
1804 * constant-timeness */
1805 if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx))
1806 {
1807 ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
1808 goto err;
1809 }
1810 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1811 }
1812 else
1813 num_bytes = BN_bn2bin(p_scalar, tmp);
1814 flip_endian(secrets[i], tmp, num_bytes);
1815 /* precompute multiples */
1816 if ((!BN_to_felem(x_out, &p->X)) ||
1817 (!BN_to_felem(y_out, &p->Y)) ||
1818 (!BN_to_felem(z_out, &p->Z))) goto err;
1819 memcpy(pre_comp[i][1][0], x_out, sizeof(felem));
1820 memcpy(pre_comp[i][1][1], y_out, sizeof(felem));
1821 memcpy(pre_comp[i][1][2], z_out, sizeof(felem));
1822 for (j = 2; j <= 16; ++j)
1823 {
1824 if (j & 1)
1825 {
1826 point_add(
1827 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1828 pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2],
1829 0, pre_comp[i][j-1][0], pre_comp[i][j-1][1], pre_comp[i][j-1][2]);
1830 }
1831 else
1832 {
1833 point_double(
1834 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1835 pre_comp[i][j/2][0], pre_comp[i][j/2][1], pre_comp[i][j/2][2]);
1836 }
1837 }
1838 }
1839 }
1840 if (mixed)
1841 make_points_affine(num_points * 17, pre_comp[0], tmp_felems);
1842 }
1843
1844 /* the scalar for the generator */
1845 if ((scalar != NULL) && (have_pre_comp))
1846 {
1847 memset(g_secret, 0, sizeof(g_secret));
1848 /* reduce scalar to 0 <= scalar < 2^521 */
1849 if ((BN_num_bits(scalar) > 521) || (BN_is_negative(scalar)))
1850 {
1851 /* this is an unusual input, and we don't guarantee
1852 * constant-timeness */
1853 if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx))
1854 {
1855 ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
1856 goto err;
1857 }
1858 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1859 }
1860 else
1861 num_bytes = BN_bn2bin(scalar, tmp);
1862 flip_endian(g_secret, tmp, num_bytes);
1863 /* do the multiplication with generator precomputation*/
1864 batch_mul(x_out, y_out, z_out,
1865 (const felem_bytearray (*)) secrets, num_points,
1866 g_secret,
1867 mixed, (const felem (*)[17][3]) pre_comp,
1868 (const felem (*)[3]) g_pre_comp);
1869 }
1870 else
1871 /* do the multiplication without generator precomputation */
1872 batch_mul(x_out, y_out, z_out,
1873 (const felem_bytearray (*)) secrets, num_points,
1874 NULL, mixed, (const felem (*)[17][3]) pre_comp, NULL);
1875 /* reduce the output to its unique minimal representation */
1876 felem_contract(x_in, x_out);
1877 felem_contract(y_in, y_out);
1878 felem_contract(z_in, z_out);
1879 if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) ||
1880 (!felem_to_BN(z, z_in)))
1881 {
1882 ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
1883 goto err;
1884 }
1885 ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
1886
1887err:
1888 BN_CTX_end(ctx);
1889 if (generator != NULL)
1890 EC_POINT_free(generator);
1891 if (new_ctx != NULL)
1892 BN_CTX_free(new_ctx);
1893 if (secrets != NULL)
1894 OPENSSL_free(secrets);
1895 if (pre_comp != NULL)
1896 OPENSSL_free(pre_comp);
1897 if (tmp_felems != NULL)
1898 OPENSSL_free(tmp_felems);
1899 return ret;
1900 }
1901
1902int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1903 {
1904 int ret = 0;
1905 NISTP521_PRE_COMP *pre = NULL;
1906 int i, j;
1907 BN_CTX *new_ctx = NULL;
1908 BIGNUM *x, *y;
1909 EC_POINT *generator = NULL;
1910 felem tmp_felems[16];
1911
1912 /* throw away old precomputation */
1913 EC_EX_DATA_free_data(&group->extra_data, nistp521_pre_comp_dup,
1914 nistp521_pre_comp_free, nistp521_pre_comp_clear_free);
1915 if (ctx == NULL)
1916 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1917 BN_CTX_start(ctx);
1918 if (((x = BN_CTX_get(ctx)) == NULL) ||
1919 ((y = BN_CTX_get(ctx)) == NULL))
1920 goto err;
1921 /* get the generator */
1922 if (group->generator == NULL) goto err;
1923 generator = EC_POINT_new(group);
1924 if (generator == NULL)
1925 goto err;
1926 BN_bin2bn(nistp521_curve_params[3], sizeof (felem_bytearray), x);
1927 BN_bin2bn(nistp521_curve_params[4], sizeof (felem_bytearray), y);
1928 if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx))
1929 goto err;
1930 if ((pre = nistp521_pre_comp_new()) == NULL)
1931 goto err;
1932 /* if the generator is the standard one, use built-in precomputation */
1933 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
1934 {
1935 memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp));
1936 ret = 1;
1937 goto err;
1938 }
1939 if ((!BN_to_felem(pre->g_pre_comp[1][0], &group->generator->X)) ||
1940 (!BN_to_felem(pre->g_pre_comp[1][1], &group->generator->Y)) ||
1941 (!BN_to_felem(pre->g_pre_comp[1][2], &group->generator->Z)))
1942 goto err;
1943 /* compute 2^130*G, 2^260*G, 2^390*G */
1944 for (i = 1; i <= 4; i <<= 1)
1945 {
1946 point_double(pre->g_pre_comp[2*i][0], pre->g_pre_comp[2*i][1],
1947 pre->g_pre_comp[2*i][2], pre->g_pre_comp[i][0],
1948 pre->g_pre_comp[i][1], pre->g_pre_comp[i][2]);
1949 for (j = 0; j < 129; ++j)
1950 {
1951 point_double(pre->g_pre_comp[2*i][0],
1952 pre->g_pre_comp[2*i][1],
1953 pre->g_pre_comp[2*i][2],
1954 pre->g_pre_comp[2*i][0],
1955 pre->g_pre_comp[2*i][1],
1956 pre->g_pre_comp[2*i][2]);
1957 }
1958 }
1959 /* g_pre_comp[0] is the point at infinity */
1960 memset(pre->g_pre_comp[0], 0, sizeof(pre->g_pre_comp[0]));
1961 /* the remaining multiples */
1962 /* 2^130*G + 2^260*G */
1963 point_add(pre->g_pre_comp[6][0], pre->g_pre_comp[6][1],
1964 pre->g_pre_comp[6][2], pre->g_pre_comp[4][0],
1965 pre->g_pre_comp[4][1], pre->g_pre_comp[4][2],
1966 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1],
1967 pre->g_pre_comp[2][2]);
1968 /* 2^130*G + 2^390*G */
1969 point_add(pre->g_pre_comp[10][0], pre->g_pre_comp[10][1],
1970 pre->g_pre_comp[10][2], pre->g_pre_comp[8][0],
1971 pre->g_pre_comp[8][1], pre->g_pre_comp[8][2],
1972 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1],
1973 pre->g_pre_comp[2][2]);
1974 /* 2^260*G + 2^390*G */
1975 point_add(pre->g_pre_comp[12][0], pre->g_pre_comp[12][1],
1976 pre->g_pre_comp[12][2], pre->g_pre_comp[8][0],
1977 pre->g_pre_comp[8][1], pre->g_pre_comp[8][2],
1978 0, pre->g_pre_comp[4][0], pre->g_pre_comp[4][1],
1979 pre->g_pre_comp[4][2]);
1980 /* 2^130*G + 2^260*G + 2^390*G */
1981 point_add(pre->g_pre_comp[14][0], pre->g_pre_comp[14][1],
1982 pre->g_pre_comp[14][2], pre->g_pre_comp[12][0],
1983 pre->g_pre_comp[12][1], pre->g_pre_comp[12][2],
1984 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1],
1985 pre->g_pre_comp[2][2]);
1986 for (i = 1; i < 8; ++i)
1987 {
1988 /* odd multiples: add G */
1989 point_add(pre->g_pre_comp[2*i+1][0], pre->g_pre_comp[2*i+1][1],
1990 pre->g_pre_comp[2*i+1][2], pre->g_pre_comp[2*i][0],
1991 pre->g_pre_comp[2*i][1], pre->g_pre_comp[2*i][2],
1992 0, pre->g_pre_comp[1][0], pre->g_pre_comp[1][1],
1993 pre->g_pre_comp[1][2]);
1994 }
1995 make_points_affine(15, &(pre->g_pre_comp[1]), tmp_felems);
1996
1997 if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp521_pre_comp_dup,
1998 nistp521_pre_comp_free, nistp521_pre_comp_clear_free))
1999 goto err;
2000 ret = 1;
2001 pre = NULL;
2002 err:
2003 BN_CTX_end(ctx);
2004 if (generator != NULL)
2005 EC_POINT_free(generator);
2006 if (new_ctx != NULL)
2007 BN_CTX_free(new_ctx);
2008 if (pre)
2009 nistp521_pre_comp_free(pre);
2010 return ret;
2011 }
2012
2013int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group)
2014 {
2015 if (EC_EX_DATA_get_data(group->extra_data, nistp521_pre_comp_dup,
2016 nistp521_pre_comp_free, nistp521_pre_comp_clear_free)
2017 != NULL)
2018 return 1;
2019 else
2020 return 0;
2021 }
2022
2023#else
2024static void *dummy=&dummy;
2025#endif
diff --git a/src/lib/libcrypto/ec/ecp_nistputil.c b/src/lib/libcrypto/ec/ecp_nistputil.c
new file mode 100644
index 0000000000..c8140c807f
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_nistputil.c
@@ -0,0 +1,197 @@
1/* crypto/ec/ecp_nistputil.c */
2/*
3 * Written by Bodo Moeller for the OpenSSL project.
4 */
5/* Copyright 2011 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 *
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21#include <openssl/opensslconf.h>
22#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
23
24/*
25 * Common utility functions for ecp_nistp224.c, ecp_nistp256.c, ecp_nistp521.c.
26 */
27
28#include <stddef.h>
29#include "ec_lcl.h"
30
31/* Convert an array of points into affine coordinates.
32 * (If the point at infinity is found (Z = 0), it remains unchanged.)
33 * This function is essentially an equivalent to EC_POINTs_make_affine(), but
34 * works with the internal representation of points as used by ecp_nistp###.c
35 * rather than with (BIGNUM-based) EC_POINT data structures.
36 *
37 * point_array is the input/output buffer ('num' points in projective form,
38 * i.e. three coordinates each), based on an internal representation of
39 * field elements of size 'felem_size'.
40 *
41 * tmp_felems needs to point to a temporary array of 'num'+1 field elements
42 * for storage of intermediate values.
43 */
44void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
45 size_t felem_size, void *tmp_felems,
46 void (*felem_one)(void *out),
47 int (*felem_is_zero)(const void *in),
48 void (*felem_assign)(void *out, const void *in),
49 void (*felem_square)(void *out, const void *in),
50 void (*felem_mul)(void *out, const void *in1, const void *in2),
51 void (*felem_inv)(void *out, const void *in),
52 void (*felem_contract)(void *out, const void *in))
53 {
54 int i = 0;
55
56#define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size])
57#define X(I) (&((char *)point_array)[3*(I) * felem_size])
58#define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size])
59#define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size])
60
61 if (!felem_is_zero(Z(0)))
62 felem_assign(tmp_felem(0), Z(0));
63 else
64 felem_one(tmp_felem(0));
65 for (i = 1; i < (int)num; i++)
66 {
67 if (!felem_is_zero(Z(i)))
68 felem_mul(tmp_felem(i), tmp_felem(i-1), Z(i));
69 else
70 felem_assign(tmp_felem(i), tmp_felem(i-1));
71 }
72 /* Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any zero-valued factors:
73 * if Z(i) = 0, we essentially pretend that Z(i) = 1 */
74
75 felem_inv(tmp_felem(num-1), tmp_felem(num-1));
76 for (i = num - 1; i >= 0; i--)
77 {
78 if (i > 0)
79 /* tmp_felem(i-1) is the product of Z(0) .. Z(i-1),
80 * tmp_felem(i) is the inverse of the product of Z(0) .. Z(i)
81 */
82 felem_mul(tmp_felem(num), tmp_felem(i-1), tmp_felem(i)); /* 1/Z(i) */
83 else
84 felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */
85
86 if (!felem_is_zero(Z(i)))
87 {
88 if (i > 0)
89 /* For next iteration, replace tmp_felem(i-1) by its inverse */
90 felem_mul(tmp_felem(i-1), tmp_felem(i), Z(i));
91
92 /* Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1) */
93 felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */
94 felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */
95 felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */
96 felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */
97 felem_contract(X(i), X(i));
98 felem_contract(Y(i), Y(i));
99 felem_one(Z(i));
100 }
101 else
102 {
103 if (i > 0)
104 /* For next iteration, replace tmp_felem(i-1) by its inverse */
105 felem_assign(tmp_felem(i-1), tmp_felem(i));
106 }
107 }
108 }
109
110/*
111 * This function looks at 5+1 scalar bits (5 current, 1 adjacent less
112 * significant bit), and recodes them into a signed digit for use in fast point
113 * multiplication: the use of signed rather than unsigned digits means that
114 * fewer points need to be precomputed, given that point inversion is easy
115 * (a precomputed point dP makes -dP available as well).
116 *
117 * BACKGROUND:
118 *
119 * Signed digits for multiplication were introduced by Booth ("A signed binary
120 * multiplication technique", Quart. Journ. Mech. and Applied Math., vol. IV,
121 * pt. 2 (1951), pp. 236-240), in that case for multiplication of integers.
122 * Booth's original encoding did not generally improve the density of nonzero
123 * digits over the binary representation, and was merely meant to simplify the
124 * handling of signed factors given in two's complement; but it has since been
125 * shown to be the basis of various signed-digit representations that do have
126 * further advantages, including the wNAF, using the following general approach:
127 *
128 * (1) Given a binary representation
129 *
130 * b_k ... b_2 b_1 b_0,
131 *
132 * of a nonnegative integer (b_k in {0, 1}), rewrite it in digits 0, 1, -1
133 * by using bit-wise subtraction as follows:
134 *
135 * b_k b_(k-1) ... b_2 b_1 b_0
136 * - b_k ... b_3 b_2 b_1 b_0
137 * -------------------------------------
138 * s_k b_(k-1) ... s_3 s_2 s_1 s_0
139 *
140 * A left-shift followed by subtraction of the original value yields a new
141 * representation of the same value, using signed bits s_i = b_(i+1) - b_i.
142 * This representation from Booth's paper has since appeared in the
143 * literature under a variety of different names including "reversed binary
144 * form", "alternating greedy expansion", "mutual opposite form", and
145 * "sign-alternating {+-1}-representation".
146 *
147 * An interesting property is that among the nonzero bits, values 1 and -1
148 * strictly alternate.
149 *
150 * (2) Various window schemes can be applied to the Booth representation of
151 * integers: for example, right-to-left sliding windows yield the wNAF
152 * (a signed-digit encoding independently discovered by various researchers
153 * in the 1990s), and left-to-right sliding windows yield a left-to-right
154 * equivalent of the wNAF (independently discovered by various researchers
155 * around 2004).
156 *
157 * To prevent leaking information through side channels in point multiplication,
158 * we need to recode the given integer into a regular pattern: sliding windows
159 * as in wNAFs won't do, we need their fixed-window equivalent -- which is a few
160 * decades older: we'll be using the so-called "modified Booth encoding" due to
161 * MacSorley ("High-speed arithmetic in binary computers", Proc. IRE, vol. 49
162 * (1961), pp. 67-91), in a radix-2^5 setting. That is, we always combine five
163 * signed bits into a signed digit:
164 *
165 * s_(4j + 4) s_(4j + 3) s_(4j + 2) s_(4j + 1) s_(4j)
166 *
167 * The sign-alternating property implies that the resulting digit values are
168 * integers from -16 to 16.
169 *
170 * Of course, we don't actually need to compute the signed digits s_i as an
171 * intermediate step (that's just a nice way to see how this scheme relates
172 * to the wNAF): a direct computation obtains the recoded digit from the
173 * six bits b_(4j + 4) ... b_(4j - 1).
174 *
175 * This function takes those five bits as an integer (0 .. 63), writing the
176 * recoded digit to *sign (0 for positive, 1 for negative) and *digit (absolute
177 * value, in the range 0 .. 8). Note that this integer essentially provides the
178 * input bits "shifted to the left" by one position: for example, the input to
179 * compute the least significant recoded digit, given that there's no bit b_-1,
180 * has to be b_4 b_3 b_2 b_1 b_0 0.
181 *
182 */
183void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in)
184 {
185 unsigned char s, d;
186
187 s = ~((in >> 5) - 1); /* sets all bits to MSB(in), 'in' seen as 6-bit value */
188 d = (1 << 6) - in - 1;
189 d = (d & s) | (in & ~s);
190 d = (d >> 1) + (d & 1);
191
192 *sign = s & 1;
193 *digit = d;
194 }
195#else
196static void *dummy=&dummy;
197#endif
diff --git a/src/lib/libcrypto/ec/ecp_oct.c b/src/lib/libcrypto/ec/ecp_oct.c
new file mode 100644
index 0000000000..374a0ee731
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_oct.c
@@ -0,0 +1,433 @@
1/* crypto/ec/ecp_oct.c */
2/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
3 * for the OpenSSL project.
4 * Includes code written by Bodo Moeller for the OpenSSL project.
5*/
6/* ====================================================================
7 * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * openssl-core@openssl.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 * acknowledgment:
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com). This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
57 *
58 */
59/* ====================================================================
60 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
61 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
62 * and contributed to the OpenSSL project.
63 */
64
65#include <openssl/err.h>
66#include <openssl/symhacks.h>
67
68#include "ec_lcl.h"
69
70int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
71 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
72 {
73 BN_CTX *new_ctx = NULL;
74 BIGNUM *tmp1, *tmp2, *x, *y;
75 int ret = 0;
76
77 /* clear error queue*/
78 ERR_clear_error();
79
80 if (ctx == NULL)
81 {
82 ctx = new_ctx = BN_CTX_new();
83 if (ctx == NULL)
84 return 0;
85 }
86
87 y_bit = (y_bit != 0);
88
89 BN_CTX_start(ctx);
90 tmp1 = BN_CTX_get(ctx);
91 tmp2 = BN_CTX_get(ctx);
92 x = BN_CTX_get(ctx);
93 y = BN_CTX_get(ctx);
94 if (y == NULL) goto err;
95
96 /* Recover y. We have a Weierstrass equation
97 * y^2 = x^3 + a*x + b,
98 * so y is one of the square roots of x^3 + a*x + b.
99 */
100
101 /* tmp1 := x^3 */
102 if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
103 if (group->meth->field_decode == 0)
104 {
105 /* field_{sqr,mul} work on standard representation */
106 if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
107 if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
108 }
109 else
110 {
111 if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
112 if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
113 }
114
115 /* tmp1 := tmp1 + a*x */
116 if (group->a_is_minus3)
117 {
118 if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
119 if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
120 if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
121 }
122 else
123 {
124 if (group->meth->field_decode)
125 {
126 if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
127 if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
128 }
129 else
130 {
131 /* field_mul works on standard representation */
132 if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
133 }
134
135 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
136 }
137
138 /* tmp1 := tmp1 + b */
139 if (group->meth->field_decode)
140 {
141 if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
142 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
143 }
144 else
145 {
146 if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
147 }
148
149 if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
150 {
151 unsigned long err = ERR_peek_last_error();
152
153 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
154 {
155 ERR_clear_error();
156 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
157 }
158 else
159 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
160 goto err;
161 }
162
163 if (y_bit != BN_is_odd(y))
164 {
165 if (BN_is_zero(y))
166 {
167 int kron;
168
169 kron = BN_kronecker(x, &group->field, ctx);
170 if (kron == -2) goto err;
171
172 if (kron == 1)
173 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
174 else
175 /* BN_mod_sqrt() should have cought this error (not a square) */
176 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
177 goto err;
178 }
179 if (!BN_usub(y, &group->field, y)) goto err;
180 }
181 if (y_bit != BN_is_odd(y))
182 {
183 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
184 goto err;
185 }
186
187 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
188
189 ret = 1;
190
191 err:
192 BN_CTX_end(ctx);
193 if (new_ctx != NULL)
194 BN_CTX_free(new_ctx);
195 return ret;
196 }
197
198
199size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
200 unsigned char *buf, size_t len, BN_CTX *ctx)
201 {
202 size_t ret;
203 BN_CTX *new_ctx = NULL;
204 int used_ctx = 0;
205 BIGNUM *x, *y;
206 size_t field_len, i, skip;
207
208 if ((form != POINT_CONVERSION_COMPRESSED)
209 && (form != POINT_CONVERSION_UNCOMPRESSED)
210 && (form != POINT_CONVERSION_HYBRID))
211 {
212 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
213 goto err;
214 }
215
216 if (EC_POINT_is_at_infinity(group, point))
217 {
218 /* encodes to a single 0 octet */
219 if (buf != NULL)
220 {
221 if (len < 1)
222 {
223 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
224 return 0;
225 }
226 buf[0] = 0;
227 }
228 return 1;
229 }
230
231
232 /* ret := required output buffer length */
233 field_len = BN_num_bytes(&group->field);
234 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
235
236 /* if 'buf' is NULL, just return required length */
237 if (buf != NULL)
238 {
239 if (len < ret)
240 {
241 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
242 goto err;
243 }
244
245 if (ctx == NULL)
246 {
247 ctx = new_ctx = BN_CTX_new();
248 if (ctx == NULL)
249 return 0;
250 }
251
252 BN_CTX_start(ctx);
253 used_ctx = 1;
254 x = BN_CTX_get(ctx);
255 y = BN_CTX_get(ctx);
256 if (y == NULL) goto err;
257
258 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
259
260 if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
261 buf[0] = form + 1;
262 else
263 buf[0] = form;
264
265 i = 1;
266
267 skip = field_len - BN_num_bytes(x);
268 if (skip > field_len)
269 {
270 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
271 goto err;
272 }
273 while (skip > 0)
274 {
275 buf[i++] = 0;
276 skip--;
277 }
278 skip = BN_bn2bin(x, buf + i);
279 i += skip;
280 if (i != 1 + field_len)
281 {
282 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
283 goto err;
284 }
285
286 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
287 {
288 skip = field_len - BN_num_bytes(y);
289 if (skip > field_len)
290 {
291 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
292 goto err;
293 }
294 while (skip > 0)
295 {
296 buf[i++] = 0;
297 skip--;
298 }
299 skip = BN_bn2bin(y, buf + i);
300 i += skip;
301 }
302
303 if (i != ret)
304 {
305 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
306 goto err;
307 }
308 }
309
310 if (used_ctx)
311 BN_CTX_end(ctx);
312 if (new_ctx != NULL)
313 BN_CTX_free(new_ctx);
314 return ret;
315
316 err:
317 if (used_ctx)
318 BN_CTX_end(ctx);
319 if (new_ctx != NULL)
320 BN_CTX_free(new_ctx);
321 return 0;
322 }
323
324
325int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
326 const unsigned char *buf, size_t len, BN_CTX *ctx)
327 {
328 point_conversion_form_t form;
329 int y_bit;
330 BN_CTX *new_ctx = NULL;
331 BIGNUM *x, *y;
332 size_t field_len, enc_len;
333 int ret = 0;
334
335 if (len == 0)
336 {
337 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
338 return 0;
339 }
340 form = buf[0];
341 y_bit = form & 1;
342 form = form & ~1U;
343 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
344 && (form != POINT_CONVERSION_UNCOMPRESSED)
345 && (form != POINT_CONVERSION_HYBRID))
346 {
347 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
348 return 0;
349 }
350 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
351 {
352 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
353 return 0;
354 }
355
356 if (form == 0)
357 {
358 if (len != 1)
359 {
360 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
361 return 0;
362 }
363
364 return EC_POINT_set_to_infinity(group, point);
365 }
366
367 field_len = BN_num_bytes(&group->field);
368 enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
369
370 if (len != enc_len)
371 {
372 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
373 return 0;
374 }
375
376 if (ctx == NULL)
377 {
378 ctx = new_ctx = BN_CTX_new();
379 if (ctx == NULL)
380 return 0;
381 }
382
383 BN_CTX_start(ctx);
384 x = BN_CTX_get(ctx);
385 y = BN_CTX_get(ctx);
386 if (y == NULL) goto err;
387
388 if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
389 if (BN_ucmp(x, &group->field) >= 0)
390 {
391 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
392 goto err;
393 }
394
395 if (form == POINT_CONVERSION_COMPRESSED)
396 {
397 if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
398 }
399 else
400 {
401 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
402 if (BN_ucmp(y, &group->field) >= 0)
403 {
404 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
405 goto err;
406 }
407 if (form == POINT_CONVERSION_HYBRID)
408 {
409 if (y_bit != BN_is_odd(y))
410 {
411 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
412 goto err;
413 }
414 }
415
416 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
417 }
418
419 if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
420 {
421 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
422 goto err;
423 }
424
425 ret = 1;
426
427 err:
428 BN_CTX_end(ctx);
429 if (new_ctx != NULL)
430 BN_CTX_free(new_ctx);
431 return ret;
432 }
433
diff --git a/src/lib/libcrypto/ec/ecp_smpl.c b/src/lib/libcrypto/ec/ecp_smpl.c
new file mode 100644
index 0000000000..66a92e2a90
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_smpl.c
@@ -0,0 +1,1719 @@
1/* crypto/ec/ecp_smpl.c */
2/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
3 * for the OpenSSL project.
4 * Includes code written by Bodo Moeller for the OpenSSL project.
5*/
6/* ====================================================================
7 * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * openssl-core@openssl.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 * acknowledgment:
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com). This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
57 *
58 */
59/* ====================================================================
60 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
61 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
62 * and contributed to the OpenSSL project.
63 */
64
65#include <openssl/err.h>
66#include <openssl/symhacks.h>
67
68#include "ec_lcl.h"
69
70const EC_METHOD *EC_GFp_simple_method(void)
71 {
72 static const EC_METHOD ret = {
73 NID_X9_62_prime_field,
74 ec_GFp_simple_group_init,
75 ec_GFp_simple_group_finish,
76 ec_GFp_simple_group_clear_finish,
77 ec_GFp_simple_group_copy,
78 ec_GFp_simple_group_set_curve,
79 ec_GFp_simple_group_get_curve,
80 ec_GFp_simple_group_get_degree,
81 ec_GFp_simple_group_check_discriminant,
82 ec_GFp_simple_point_init,
83 ec_GFp_simple_point_finish,
84 ec_GFp_simple_point_clear_finish,
85 ec_GFp_simple_point_copy,
86 ec_GFp_simple_point_set_to_infinity,
87 ec_GFp_simple_set_Jprojective_coordinates_GFp,
88 ec_GFp_simple_get_Jprojective_coordinates_GFp,
89 ec_GFp_simple_point_set_affine_coordinates,
90 ec_GFp_simple_point_get_affine_coordinates,
91 ec_GFp_simple_set_compressed_coordinates,
92 ec_GFp_simple_point2oct,
93 ec_GFp_simple_oct2point,
94 ec_GFp_simple_add,
95 ec_GFp_simple_dbl,
96 ec_GFp_simple_invert,
97 ec_GFp_simple_is_at_infinity,
98 ec_GFp_simple_is_on_curve,
99 ec_GFp_simple_cmp,
100 ec_GFp_simple_make_affine,
101 ec_GFp_simple_points_make_affine,
102 0 /* mul */,
103 0 /* precompute_mult */,
104 0 /* have_precompute_mult */,
105 ec_GFp_simple_field_mul,
106 ec_GFp_simple_field_sqr,
107 0 /* field_div */,
108 0 /* field_encode */,
109 0 /* field_decode */,
110 0 /* field_set_to_one */ };
111
112 return &ret;
113 }
114
115
116/* Most method functions in this file are designed to work with
117 * non-trivial representations of field elements if necessary
118 * (see ecp_mont.c): while standard modular addition and subtraction
119 * are used, the field_mul and field_sqr methods will be used for
120 * multiplication, and field_encode and field_decode (if defined)
121 * will be used for converting between representations.
122
123 * Functions ec_GFp_simple_points_make_affine() and
124 * ec_GFp_simple_point_get_affine_coordinates() specifically assume
125 * that if a non-trivial representation is used, it is a Montgomery
126 * representation (i.e. 'encoding' means multiplying by some factor R).
127 */
128
129
130int ec_GFp_simple_group_init(EC_GROUP *group)
131 {
132 BN_init(&group->field);
133 BN_init(&group->a);
134 BN_init(&group->b);
135 group->a_is_minus3 = 0;
136 return 1;
137 }
138
139
140void ec_GFp_simple_group_finish(EC_GROUP *group)
141 {
142 BN_free(&group->field);
143 BN_free(&group->a);
144 BN_free(&group->b);
145 }
146
147
148void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
149 {
150 BN_clear_free(&group->field);
151 BN_clear_free(&group->a);
152 BN_clear_free(&group->b);
153 }
154
155
156int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
157 {
158 if (!BN_copy(&dest->field, &src->field)) return 0;
159 if (!BN_copy(&dest->a, &src->a)) return 0;
160 if (!BN_copy(&dest->b, &src->b)) return 0;
161
162 dest->a_is_minus3 = src->a_is_minus3;
163
164 return 1;
165 }
166
167
168int ec_GFp_simple_group_set_curve(EC_GROUP *group,
169 const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
170 {
171 int ret = 0;
172 BN_CTX *new_ctx = NULL;
173 BIGNUM *tmp_a;
174
175 /* p must be a prime > 3 */
176 if (BN_num_bits(p) <= 2 || !BN_is_odd(p))
177 {
178 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
179 return 0;
180 }
181
182 if (ctx == NULL)
183 {
184 ctx = new_ctx = BN_CTX_new();
185 if (ctx == NULL)
186 return 0;
187 }
188
189 BN_CTX_start(ctx);
190 tmp_a = BN_CTX_get(ctx);
191 if (tmp_a == NULL) goto err;
192
193 /* group->field */
194 if (!BN_copy(&group->field, p)) goto err;
195 BN_set_negative(&group->field, 0);
196
197 /* group->a */
198 if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
199 if (group->meth->field_encode)
200 { if (!group->meth->field_encode(group, &group->a, tmp_a, ctx)) goto err; }
201 else
202 if (!BN_copy(&group->a, tmp_a)) goto err;
203
204 /* group->b */
205 if (!BN_nnmod(&group->b, b, p, ctx)) goto err;
206 if (group->meth->field_encode)
207 if (!group->meth->field_encode(group, &group->b, &group->b, ctx)) goto err;
208
209 /* group->a_is_minus3 */
210 if (!BN_add_word(tmp_a, 3)) goto err;
211 group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
212
213 ret = 1;
214
215 err:
216 BN_CTX_end(ctx);
217 if (new_ctx != NULL)
218 BN_CTX_free(new_ctx);
219 return ret;
220 }
221
222
223int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
224 {
225 int ret = 0;
226 BN_CTX *new_ctx = NULL;
227
228 if (p != NULL)
229 {
230 if (!BN_copy(p, &group->field)) return 0;
231 }
232
233 if (a != NULL || b != NULL)
234 {
235 if (group->meth->field_decode)
236 {
237 if (ctx == NULL)
238 {
239 ctx = new_ctx = BN_CTX_new();
240 if (ctx == NULL)
241 return 0;
242 }
243 if (a != NULL)
244 {
245 if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
246 }
247 if (b != NULL)
248 {
249 if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
250 }
251 }
252 else
253 {
254 if (a != NULL)
255 {
256 if (!BN_copy(a, &group->a)) goto err;
257 }
258 if (b != NULL)
259 {
260 if (!BN_copy(b, &group->b)) goto err;
261 }
262 }
263 }
264
265 ret = 1;
266
267 err:
268 if (new_ctx)
269 BN_CTX_free(new_ctx);
270 return ret;
271 }
272
273
274int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
275 {
276 return BN_num_bits(&group->field);
277 }
278
279
280int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
281 {
282 int ret = 0;
283 BIGNUM *a,*b,*order,*tmp_1,*tmp_2;
284 const BIGNUM *p = &group->field;
285 BN_CTX *new_ctx = NULL;
286
287 if (ctx == NULL)
288 {
289 ctx = new_ctx = BN_CTX_new();
290 if (ctx == NULL)
291 {
292 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
293 goto err;
294 }
295 }
296 BN_CTX_start(ctx);
297 a = BN_CTX_get(ctx);
298 b = BN_CTX_get(ctx);
299 tmp_1 = BN_CTX_get(ctx);
300 tmp_2 = BN_CTX_get(ctx);
301 order = BN_CTX_get(ctx);
302 if (order == NULL) goto err;
303
304 if (group->meth->field_decode)
305 {
306 if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
307 if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
308 }
309 else
310 {
311 if (!BN_copy(a, &group->a)) goto err;
312 if (!BN_copy(b, &group->b)) goto err;
313 }
314
315 /* check the discriminant:
316 * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
317 * 0 =< a, b < p */
318 if (BN_is_zero(a))
319 {
320 if (BN_is_zero(b)) goto err;
321 }
322 else if (!BN_is_zero(b))
323 {
324 if (!BN_mod_sqr(tmp_1, a, p, ctx)) goto err;
325 if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) goto err;
326 if (!BN_lshift(tmp_1, tmp_2, 2)) goto err;
327 /* tmp_1 = 4*a^3 */
328
329 if (!BN_mod_sqr(tmp_2, b, p, ctx)) goto err;
330 if (!BN_mul_word(tmp_2, 27)) goto err;
331 /* tmp_2 = 27*b^2 */
332
333 if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) goto err;
334 if (BN_is_zero(a)) goto err;
335 }
336 ret = 1;
337
338err:
339 if (ctx != NULL)
340 BN_CTX_end(ctx);
341 if (new_ctx != NULL)
342 BN_CTX_free(new_ctx);
343 return ret;
344 }
345
346
347int ec_GFp_simple_point_init(EC_POINT *point)
348 {
349 BN_init(&point->X);
350 BN_init(&point->Y);
351 BN_init(&point->Z);
352 point->Z_is_one = 0;
353
354 return 1;
355 }
356
357
358void ec_GFp_simple_point_finish(EC_POINT *point)
359 {
360 BN_free(&point->X);
361 BN_free(&point->Y);
362 BN_free(&point->Z);
363 }
364
365
366void ec_GFp_simple_point_clear_finish(EC_POINT *point)
367 {
368 BN_clear_free(&point->X);
369 BN_clear_free(&point->Y);
370 BN_clear_free(&point->Z);
371 point->Z_is_one = 0;
372 }
373
374
375int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
376 {
377 if (!BN_copy(&dest->X, &src->X)) return 0;
378 if (!BN_copy(&dest->Y, &src->Y)) return 0;
379 if (!BN_copy(&dest->Z, &src->Z)) return 0;
380 dest->Z_is_one = src->Z_is_one;
381
382 return 1;
383 }
384
385
386int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
387 {
388 point->Z_is_one = 0;
389 BN_zero(&point->Z);
390 return 1;
391 }
392
393
394int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
395 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
396 {
397 BN_CTX *new_ctx = NULL;
398 int ret = 0;
399
400 if (ctx == NULL)
401 {
402 ctx = new_ctx = BN_CTX_new();
403 if (ctx == NULL)
404 return 0;
405 }
406
407 if (x != NULL)
408 {
409 if (!BN_nnmod(&point->X, x, &group->field, ctx)) goto err;
410 if (group->meth->field_encode)
411 {
412 if (!group->meth->field_encode(group, &point->X, &point->X, ctx)) goto err;
413 }
414 }
415
416 if (y != NULL)
417 {
418 if (!BN_nnmod(&point->Y, y, &group->field, ctx)) goto err;
419 if (group->meth->field_encode)
420 {
421 if (!group->meth->field_encode(group, &point->Y, &point->Y, ctx)) goto err;
422 }
423 }
424
425 if (z != NULL)
426 {
427 int Z_is_one;
428
429 if (!BN_nnmod(&point->Z, z, &group->field, ctx)) goto err;
430 Z_is_one = BN_is_one(&point->Z);
431 if (group->meth->field_encode)
432 {
433 if (Z_is_one && (group->meth->field_set_to_one != 0))
434 {
435 if (!group->meth->field_set_to_one(group, &point->Z, ctx)) goto err;
436 }
437 else
438 {
439 if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) goto err;
440 }
441 }
442 point->Z_is_one = Z_is_one;
443 }
444
445 ret = 1;
446
447 err:
448 if (new_ctx != NULL)
449 BN_CTX_free(new_ctx);
450 return ret;
451 }
452
453
454int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
455 BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
456 {
457 BN_CTX *new_ctx = NULL;
458 int ret = 0;
459
460 if (group->meth->field_decode != 0)
461 {
462 if (ctx == NULL)
463 {
464 ctx = new_ctx = BN_CTX_new();
465 if (ctx == NULL)
466 return 0;
467 }
468
469 if (x != NULL)
470 {
471 if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
472 }
473 if (y != NULL)
474 {
475 if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
476 }
477 if (z != NULL)
478 {
479 if (!group->meth->field_decode(group, z, &point->Z, ctx)) goto err;
480 }
481 }
482 else
483 {
484 if (x != NULL)
485 {
486 if (!BN_copy(x, &point->X)) goto err;
487 }
488 if (y != NULL)
489 {
490 if (!BN_copy(y, &point->Y)) goto err;
491 }
492 if (z != NULL)
493 {
494 if (!BN_copy(z, &point->Z)) goto err;
495 }
496 }
497
498 ret = 1;
499
500 err:
501 if (new_ctx != NULL)
502 BN_CTX_free(new_ctx);
503 return ret;
504 }
505
506
507int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
508 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
509 {
510 if (x == NULL || y == NULL)
511 {
512 /* unlike for projective coordinates, we do not tolerate this */
513 ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
514 return 0;
515 }
516
517 return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx);
518 }
519
520
521int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
522 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
523 {
524 BN_CTX *new_ctx = NULL;
525 BIGNUM *Z, *Z_1, *Z_2, *Z_3;
526 const BIGNUM *Z_;
527 int ret = 0;
528
529 if (EC_POINT_is_at_infinity(group, point))
530 {
531 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
532 return 0;
533 }
534
535 if (ctx == NULL)
536 {
537 ctx = new_ctx = BN_CTX_new();
538 if (ctx == NULL)
539 return 0;
540 }
541
542 BN_CTX_start(ctx);
543 Z = BN_CTX_get(ctx);
544 Z_1 = BN_CTX_get(ctx);
545 Z_2 = BN_CTX_get(ctx);
546 Z_3 = BN_CTX_get(ctx);
547 if (Z_3 == NULL) goto err;
548
549 /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
550
551 if (group->meth->field_decode)
552 {
553 if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
554 Z_ = Z;
555 }
556 else
557 {
558 Z_ = &point->Z;
559 }
560
561 if (BN_is_one(Z_))
562 {
563 if (group->meth->field_decode)
564 {
565 if (x != NULL)
566 {
567 if (!group->meth->field_decode(group, x, &point->X, ctx)) goto err;
568 }
569 if (y != NULL)
570 {
571 if (!group->meth->field_decode(group, y, &point->Y, ctx)) goto err;
572 }
573 }
574 else
575 {
576 if (x != NULL)
577 {
578 if (!BN_copy(x, &point->X)) goto err;
579 }
580 if (y != NULL)
581 {
582 if (!BN_copy(y, &point->Y)) goto err;
583 }
584 }
585 }
586 else
587 {
588 if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
589 {
590 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
591 goto err;
592 }
593
594 if (group->meth->field_encode == 0)
595 {
596 /* field_sqr works on standard representation */
597 if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err;
598 }
599 else
600 {
601 if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) goto err;
602 }
603
604 if (x != NULL)
605 {
606 /* in the Montgomery case, field_mul will cancel out Montgomery factor in X: */
607 if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) goto err;
608 }
609
610 if (y != NULL)
611 {
612 if (group->meth->field_encode == 0)
613 {
614 /* field_mul works on standard representation */
615 if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
616 }
617 else
618 {
619 if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
620 }
621
622 /* in the Montgomery case, field_mul will cancel out Montgomery factor in Y: */
623 if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) goto err;
624 }
625 }
626
627 ret = 1;
628
629 err:
630 BN_CTX_end(ctx);
631 if (new_ctx != NULL)
632 BN_CTX_free(new_ctx);
633 return ret;
634 }
635
636
637int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
638 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
639 {
640 BN_CTX *new_ctx = NULL;
641 BIGNUM *tmp1, *tmp2, *x, *y;
642 int ret = 0;
643
644 /* clear error queue*/
645 ERR_clear_error();
646
647 if (ctx == NULL)
648 {
649 ctx = new_ctx = BN_CTX_new();
650 if (ctx == NULL)
651 return 0;
652 }
653
654 y_bit = (y_bit != 0);
655
656 BN_CTX_start(ctx);
657 tmp1 = BN_CTX_get(ctx);
658 tmp2 = BN_CTX_get(ctx);
659 x = BN_CTX_get(ctx);
660 y = BN_CTX_get(ctx);
661 if (y == NULL) goto err;
662
663 /* Recover y. We have a Weierstrass equation
664 * y^2 = x^3 + a*x + b,
665 * so y is one of the square roots of x^3 + a*x + b.
666 */
667
668 /* tmp1 := x^3 */
669 if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
670 if (group->meth->field_decode == 0)
671 {
672 /* field_{sqr,mul} work on standard representation */
673 if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
674 if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
675 }
676 else
677 {
678 if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
679 if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
680 }
681
682 /* tmp1 := tmp1 + a*x */
683 if (group->a_is_minus3)
684 {
685 if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
686 if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
687 if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
688 }
689 else
690 {
691 if (group->meth->field_decode)
692 {
693 if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
694 if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
695 }
696 else
697 {
698 /* field_mul works on standard representation */
699 if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
700 }
701
702 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
703 }
704
705 /* tmp1 := tmp1 + b */
706 if (group->meth->field_decode)
707 {
708 if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
709 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
710 }
711 else
712 {
713 if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
714 }
715
716 if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
717 {
718 unsigned long err = ERR_peek_last_error();
719
720 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
721 {
722 ERR_clear_error();
723 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
724 }
725 else
726 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
727 goto err;
728 }
729
730 if (y_bit != BN_is_odd(y))
731 {
732 if (BN_is_zero(y))
733 {
734 int kron;
735
736 kron = BN_kronecker(x, &group->field, ctx);
737 if (kron == -2) goto err;
738
739 if (kron == 1)
740 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
741 else
742 /* BN_mod_sqrt() should have cought this error (not a square) */
743 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
744 goto err;
745 }
746 if (!BN_usub(y, &group->field, y)) goto err;
747 }
748 if (y_bit != BN_is_odd(y))
749 {
750 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
751 goto err;
752 }
753
754 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
755
756 ret = 1;
757
758 err:
759 BN_CTX_end(ctx);
760 if (new_ctx != NULL)
761 BN_CTX_free(new_ctx);
762 return ret;
763 }
764
765
766size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
767 unsigned char *buf, size_t len, BN_CTX *ctx)
768 {
769 size_t ret;
770 BN_CTX *new_ctx = NULL;
771 int used_ctx = 0;
772 BIGNUM *x, *y;
773 size_t field_len, i, skip;
774
775 if ((form != POINT_CONVERSION_COMPRESSED)
776 && (form != POINT_CONVERSION_UNCOMPRESSED)
777 && (form != POINT_CONVERSION_HYBRID))
778 {
779 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
780 goto err;
781 }
782
783 if (EC_POINT_is_at_infinity(group, point))
784 {
785 /* encodes to a single 0 octet */
786 if (buf != NULL)
787 {
788 if (len < 1)
789 {
790 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
791 return 0;
792 }
793 buf[0] = 0;
794 }
795 return 1;
796 }
797
798
799 /* ret := required output buffer length */
800 field_len = BN_num_bytes(&group->field);
801 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
802
803 /* if 'buf' is NULL, just return required length */
804 if (buf != NULL)
805 {
806 if (len < ret)
807 {
808 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
809 goto err;
810 }
811
812 if (ctx == NULL)
813 {
814 ctx = new_ctx = BN_CTX_new();
815 if (ctx == NULL)
816 return 0;
817 }
818
819 BN_CTX_start(ctx);
820 used_ctx = 1;
821 x = BN_CTX_get(ctx);
822 y = BN_CTX_get(ctx);
823 if (y == NULL) goto err;
824
825 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
826
827 if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
828 buf[0] = form + 1;
829 else
830 buf[0] = form;
831
832 i = 1;
833
834 skip = field_len - BN_num_bytes(x);
835 if (skip > field_len)
836 {
837 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
838 goto err;
839 }
840 while (skip > 0)
841 {
842 buf[i++] = 0;
843 skip--;
844 }
845 skip = BN_bn2bin(x, buf + i);
846 i += skip;
847 if (i != 1 + field_len)
848 {
849 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
850 goto err;
851 }
852
853 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
854 {
855 skip = field_len - BN_num_bytes(y);
856 if (skip > field_len)
857 {
858 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
859 goto err;
860 }
861 while (skip > 0)
862 {
863 buf[i++] = 0;
864 skip--;
865 }
866 skip = BN_bn2bin(y, buf + i);
867 i += skip;
868 }
869
870 if (i != ret)
871 {
872 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
873 goto err;
874 }
875 }
876
877 if (used_ctx)
878 BN_CTX_end(ctx);
879 if (new_ctx != NULL)
880 BN_CTX_free(new_ctx);
881 return ret;
882
883 err:
884 if (used_ctx)
885 BN_CTX_end(ctx);
886 if (new_ctx != NULL)
887 BN_CTX_free(new_ctx);
888 return 0;
889 }
890
891
892int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
893 const unsigned char *buf, size_t len, BN_CTX *ctx)
894 {
895 point_conversion_form_t form;
896 int y_bit;
897 BN_CTX *new_ctx = NULL;
898 BIGNUM *x, *y;
899 size_t field_len, enc_len;
900 int ret = 0;
901
902 if (len == 0)
903 {
904 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
905 return 0;
906 }
907 form = buf[0];
908 y_bit = form & 1;
909 form = form & ~1U;
910 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
911 && (form != POINT_CONVERSION_UNCOMPRESSED)
912 && (form != POINT_CONVERSION_HYBRID))
913 {
914 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
915 return 0;
916 }
917 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
918 {
919 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
920 return 0;
921 }
922
923 if (form == 0)
924 {
925 if (len != 1)
926 {
927 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
928 return 0;
929 }
930
931 return EC_POINT_set_to_infinity(group, point);
932 }
933
934 field_len = BN_num_bytes(&group->field);
935 enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
936
937 if (len != enc_len)
938 {
939 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
940 return 0;
941 }
942
943 if (ctx == NULL)
944 {
945 ctx = new_ctx = BN_CTX_new();
946 if (ctx == NULL)
947 return 0;
948 }
949
950 BN_CTX_start(ctx);
951 x = BN_CTX_get(ctx);
952 y = BN_CTX_get(ctx);
953 if (y == NULL) goto err;
954
955 if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
956 if (BN_ucmp(x, &group->field) >= 0)
957 {
958 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
959 goto err;
960 }
961
962 if (form == POINT_CONVERSION_COMPRESSED)
963 {
964 if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
965 }
966 else
967 {
968 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
969 if (BN_ucmp(y, &group->field) >= 0)
970 {
971 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
972 goto err;
973 }
974 if (form == POINT_CONVERSION_HYBRID)
975 {
976 if (y_bit != BN_is_odd(y))
977 {
978 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
979 goto err;
980 }
981 }
982
983 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
984 }
985
986 if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
987 {
988 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
989 goto err;
990 }
991
992 ret = 1;
993
994 err:
995 BN_CTX_end(ctx);
996 if (new_ctx != NULL)
997 BN_CTX_free(new_ctx);
998 return ret;
999 }
1000
1001
1002int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
1003 {
1004 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1005 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1006 const BIGNUM *p;
1007 BN_CTX *new_ctx = NULL;
1008 BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
1009 int ret = 0;
1010
1011 if (a == b)
1012 return EC_POINT_dbl(group, r, a, ctx);
1013 if (EC_POINT_is_at_infinity(group, a))
1014 return EC_POINT_copy(r, b);
1015 if (EC_POINT_is_at_infinity(group, b))
1016 return EC_POINT_copy(r, a);
1017
1018 field_mul = group->meth->field_mul;
1019 field_sqr = group->meth->field_sqr;
1020 p = &group->field;
1021
1022 if (ctx == NULL)
1023 {
1024 ctx = new_ctx = BN_CTX_new();
1025 if (ctx == NULL)
1026 return 0;
1027 }
1028
1029 BN_CTX_start(ctx);
1030 n0 = BN_CTX_get(ctx);
1031 n1 = BN_CTX_get(ctx);
1032 n2 = BN_CTX_get(ctx);
1033 n3 = BN_CTX_get(ctx);
1034 n4 = BN_CTX_get(ctx);
1035 n5 = BN_CTX_get(ctx);
1036 n6 = BN_CTX_get(ctx);
1037 if (n6 == NULL) goto end;
1038
1039 /* Note that in this function we must not read components of 'a' or 'b'
1040 * once we have written the corresponding components of 'r'.
1041 * ('r' might be one of 'a' or 'b'.)
1042 */
1043
1044 /* n1, n2 */
1045 if (b->Z_is_one)
1046 {
1047 if (!BN_copy(n1, &a->X)) goto end;
1048 if (!BN_copy(n2, &a->Y)) goto end;
1049 /* n1 = X_a */
1050 /* n2 = Y_a */
1051 }
1052 else
1053 {
1054 if (!field_sqr(group, n0, &b->Z, ctx)) goto end;
1055 if (!field_mul(group, n1, &a->X, n0, ctx)) goto end;
1056 /* n1 = X_a * Z_b^2 */
1057
1058 if (!field_mul(group, n0, n0, &b->Z, ctx)) goto end;
1059 if (!field_mul(group, n2, &a->Y, n0, ctx)) goto end;
1060 /* n2 = Y_a * Z_b^3 */
1061 }
1062
1063 /* n3, n4 */
1064 if (a->Z_is_one)
1065 {
1066 if (!BN_copy(n3, &b->X)) goto end;
1067 if (!BN_copy(n4, &b->Y)) goto end;
1068 /* n3 = X_b */
1069 /* n4 = Y_b */
1070 }
1071 else
1072 {
1073 if (!field_sqr(group, n0, &a->Z, ctx)) goto end;
1074 if (!field_mul(group, n3, &b->X, n0, ctx)) goto end;
1075 /* n3 = X_b * Z_a^2 */
1076
1077 if (!field_mul(group, n0, n0, &a->Z, ctx)) goto end;
1078 if (!field_mul(group, n4, &b->Y, n0, ctx)) goto end;
1079 /* n4 = Y_b * Z_a^3 */
1080 }
1081
1082 /* n5, n6 */
1083 if (!BN_mod_sub_quick(n5, n1, n3, p)) goto end;
1084 if (!BN_mod_sub_quick(n6, n2, n4, p)) goto end;
1085 /* n5 = n1 - n3 */
1086 /* n6 = n2 - n4 */
1087
1088 if (BN_is_zero(n5))
1089 {
1090 if (BN_is_zero(n6))
1091 {
1092 /* a is the same point as b */
1093 BN_CTX_end(ctx);
1094 ret = EC_POINT_dbl(group, r, a, ctx);
1095 ctx = NULL;
1096 goto end;
1097 }
1098 else
1099 {
1100 /* a is the inverse of b */
1101 BN_zero(&r->Z);
1102 r->Z_is_one = 0;
1103 ret = 1;
1104 goto end;
1105 }
1106 }
1107
1108 /* 'n7', 'n8' */
1109 if (!BN_mod_add_quick(n1, n1, n3, p)) goto end;
1110 if (!BN_mod_add_quick(n2, n2, n4, p)) goto end;
1111 /* 'n7' = n1 + n3 */
1112 /* 'n8' = n2 + n4 */
1113
1114 /* Z_r */
1115 if (a->Z_is_one && b->Z_is_one)
1116 {
1117 if (!BN_copy(&r->Z, n5)) goto end;
1118 }
1119 else
1120 {
1121 if (a->Z_is_one)
1122 { if (!BN_copy(n0, &b->Z)) goto end; }
1123 else if (b->Z_is_one)
1124 { if (!BN_copy(n0, &a->Z)) goto end; }
1125 else
1126 { if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; }
1127 if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end;
1128 }
1129 r->Z_is_one = 0;
1130 /* Z_r = Z_a * Z_b * n5 */
1131
1132 /* X_r */
1133 if (!field_sqr(group, n0, n6, ctx)) goto end;
1134 if (!field_sqr(group, n4, n5, ctx)) goto end;
1135 if (!field_mul(group, n3, n1, n4, ctx)) goto end;
1136 if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end;
1137 /* X_r = n6^2 - n5^2 * 'n7' */
1138
1139 /* 'n9' */
1140 if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end;
1141 if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end;
1142 /* n9 = n5^2 * 'n7' - 2 * X_r */
1143
1144 /* Y_r */
1145 if (!field_mul(group, n0, n0, n6, ctx)) goto end;
1146 if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */
1147 if (!field_mul(group, n1, n2, n5, ctx)) goto end;
1148 if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end;
1149 if (BN_is_odd(n0))
1150 if (!BN_add(n0, n0, p)) goto end;
1151 /* now 0 <= n0 < 2*p, and n0 is even */
1152 if (!BN_rshift1(&r->Y, n0)) goto end;
1153 /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
1154
1155 ret = 1;
1156
1157 end:
1158 if (ctx) /* otherwise we already called BN_CTX_end */
1159 BN_CTX_end(ctx);
1160 if (new_ctx != NULL)
1161 BN_CTX_free(new_ctx);
1162 return ret;
1163 }
1164
1165
1166int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
1167 {
1168 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1169 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1170 const BIGNUM *p;
1171 BN_CTX *new_ctx = NULL;
1172 BIGNUM *n0, *n1, *n2, *n3;
1173 int ret = 0;
1174
1175 if (EC_POINT_is_at_infinity(group, a))
1176 {
1177 BN_zero(&r->Z);
1178 r->Z_is_one = 0;
1179 return 1;
1180 }
1181
1182 field_mul = group->meth->field_mul;
1183 field_sqr = group->meth->field_sqr;
1184 p = &group->field;
1185
1186 if (ctx == NULL)
1187 {
1188 ctx = new_ctx = BN_CTX_new();
1189 if (ctx == NULL)
1190 return 0;
1191 }
1192
1193 BN_CTX_start(ctx);
1194 n0 = BN_CTX_get(ctx);
1195 n1 = BN_CTX_get(ctx);
1196 n2 = BN_CTX_get(ctx);
1197 n3 = BN_CTX_get(ctx);
1198 if (n3 == NULL) goto err;
1199
1200 /* Note that in this function we must not read components of 'a'
1201 * once we have written the corresponding components of 'r'.
1202 * ('r' might the same as 'a'.)
1203 */
1204
1205 /* n1 */
1206 if (a->Z_is_one)
1207 {
1208 if (!field_sqr(group, n0, &a->X, ctx)) goto err;
1209 if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
1210 if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
1211 if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err;
1212 /* n1 = 3 * X_a^2 + a_curve */
1213 }
1214 else if (group->a_is_minus3)
1215 {
1216 if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
1217 if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err;
1218 if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err;
1219 if (!field_mul(group, n1, n0, n2, ctx)) goto err;
1220 if (!BN_mod_lshift1_quick(n0, n1, p)) goto err;
1221 if (!BN_mod_add_quick(n1, n0, n1, p)) goto err;
1222 /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
1223 * = 3 * X_a^2 - 3 * Z_a^4 */
1224 }
1225 else
1226 {
1227 if (!field_sqr(group, n0, &a->X, ctx)) goto err;
1228 if (!BN_mod_lshift1_quick(n1, n0, p)) goto err;
1229 if (!BN_mod_add_quick(n0, n0, n1, p)) goto err;
1230 if (!field_sqr(group, n1, &a->Z, ctx)) goto err;
1231 if (!field_sqr(group, n1, n1, ctx)) goto err;
1232 if (!field_mul(group, n1, n1, &group->a, ctx)) goto err;
1233 if (!BN_mod_add_quick(n1, n1, n0, p)) goto err;
1234 /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
1235 }
1236
1237 /* Z_r */
1238 if (a->Z_is_one)
1239 {
1240 if (!BN_copy(n0, &a->Y)) goto err;
1241 }
1242 else
1243 {
1244 if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err;
1245 }
1246 if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err;
1247 r->Z_is_one = 0;
1248 /* Z_r = 2 * Y_a * Z_a */
1249
1250 /* n2 */
1251 if (!field_sqr(group, n3, &a->Y, ctx)) goto err;
1252 if (!field_mul(group, n2, &a->X, n3, ctx)) goto err;
1253 if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err;
1254 /* n2 = 4 * X_a * Y_a^2 */
1255
1256 /* X_r */
1257 if (!BN_mod_lshift1_quick(n0, n2, p)) goto err;
1258 if (!field_sqr(group, &r->X, n1, ctx)) goto err;
1259 if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err;
1260 /* X_r = n1^2 - 2 * n2 */
1261
1262 /* n3 */
1263 if (!field_sqr(group, n0, n3, ctx)) goto err;
1264 if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err;
1265 /* n3 = 8 * Y_a^4 */
1266
1267 /* Y_r */
1268 if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err;
1269 if (!field_mul(group, n0, n1, n0, ctx)) goto err;
1270 if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err;
1271 /* Y_r = n1 * (n2 - X_r) - n3 */
1272
1273 ret = 1;
1274
1275 err:
1276 BN_CTX_end(ctx);
1277 if (new_ctx != NULL)
1278 BN_CTX_free(new_ctx);
1279 return ret;
1280 }
1281
1282
1283int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1284 {
1285 if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
1286 /* point is its own inverse */
1287 return 1;
1288
1289 return BN_usub(&point->Y, &group->field, &point->Y);
1290 }
1291
1292
1293int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
1294 {
1295 return BN_is_zero(&point->Z);
1296 }
1297
1298
1299int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
1300 {
1301 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1302 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1303 const BIGNUM *p;
1304 BN_CTX *new_ctx = NULL;
1305 BIGNUM *rh, *tmp, *Z4, *Z6;
1306 int ret = -1;
1307
1308 if (EC_POINT_is_at_infinity(group, point))
1309 return 1;
1310
1311 field_mul = group->meth->field_mul;
1312 field_sqr = group->meth->field_sqr;
1313 p = &group->field;
1314
1315 if (ctx == NULL)
1316 {
1317 ctx = new_ctx = BN_CTX_new();
1318 if (ctx == NULL)
1319 return -1;
1320 }
1321
1322 BN_CTX_start(ctx);
1323 rh = BN_CTX_get(ctx);
1324 tmp = BN_CTX_get(ctx);
1325 Z4 = BN_CTX_get(ctx);
1326 Z6 = BN_CTX_get(ctx);
1327 if (Z6 == NULL) goto err;
1328
1329 /* We have a curve defined by a Weierstrass equation
1330 * y^2 = x^3 + a*x + b.
1331 * The point to consider is given in Jacobian projective coordinates
1332 * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3).
1333 * Substituting this and multiplying by Z^6 transforms the above equation into
1334 * Y^2 = X^3 + a*X*Z^4 + b*Z^6.
1335 * To test this, we add up the right-hand side in 'rh'.
1336 */
1337
1338 /* rh := X^2 */
1339 if (!field_sqr(group, rh, &point->X, ctx)) goto err;
1340
1341 if (!point->Z_is_one)
1342 {
1343 if (!field_sqr(group, tmp, &point->Z, ctx)) goto err;
1344 if (!field_sqr(group, Z4, tmp, ctx)) goto err;
1345 if (!field_mul(group, Z6, Z4, tmp, ctx)) goto err;
1346
1347 /* rh := (rh + a*Z^4)*X */
1348 if (group->a_is_minus3)
1349 {
1350 if (!BN_mod_lshift1_quick(tmp, Z4, p)) goto err;
1351 if (!BN_mod_add_quick(tmp, tmp, Z4, p)) goto err;
1352 if (!BN_mod_sub_quick(rh, rh, tmp, p)) goto err;
1353 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1354 }
1355 else
1356 {
1357 if (!field_mul(group, tmp, Z4, &group->a, ctx)) goto err;
1358 if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
1359 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1360 }
1361
1362 /* rh := rh + b*Z^6 */
1363 if (!field_mul(group, tmp, &group->b, Z6, ctx)) goto err;
1364 if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
1365 }
1366 else
1367 {
1368 /* point->Z_is_one */
1369
1370 /* rh := (rh + a)*X */
1371 if (!BN_mod_add_quick(rh, rh, &group->a, p)) goto err;
1372 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1373 /* rh := rh + b */
1374 if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
1375 }
1376
1377 /* 'lh' := Y^2 */
1378 if (!field_sqr(group, tmp, &point->Y, ctx)) goto err;
1379
1380 ret = (0 == BN_ucmp(tmp, rh));
1381
1382 err:
1383 BN_CTX_end(ctx);
1384 if (new_ctx != NULL)
1385 BN_CTX_free(new_ctx);
1386 return ret;
1387 }
1388
1389
1390int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
1391 {
1392 /* return values:
1393 * -1 error
1394 * 0 equal (in affine coordinates)
1395 * 1 not equal
1396 */
1397
1398 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
1399 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1400 BN_CTX *new_ctx = NULL;
1401 BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
1402 const BIGNUM *tmp1_, *tmp2_;
1403 int ret = -1;
1404
1405 if (EC_POINT_is_at_infinity(group, a))
1406 {
1407 return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
1408 }
1409
1410 if (EC_POINT_is_at_infinity(group, b))
1411 return 1;
1412
1413 if (a->Z_is_one && b->Z_is_one)
1414 {
1415 return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
1416 }
1417
1418 field_mul = group->meth->field_mul;
1419 field_sqr = group->meth->field_sqr;
1420
1421 if (ctx == NULL)
1422 {
1423 ctx = new_ctx = BN_CTX_new();
1424 if (ctx == NULL)
1425 return -1;
1426 }
1427
1428 BN_CTX_start(ctx);
1429 tmp1 = BN_CTX_get(ctx);
1430 tmp2 = BN_CTX_get(ctx);
1431 Za23 = BN_CTX_get(ctx);
1432 Zb23 = BN_CTX_get(ctx);
1433 if (Zb23 == NULL) goto end;
1434
1435 /* We have to decide whether
1436 * (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
1437 * or equivalently, whether
1438 * (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
1439 */
1440
1441 if (!b->Z_is_one)
1442 {
1443 if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end;
1444 if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end;
1445 tmp1_ = tmp1;
1446 }
1447 else
1448 tmp1_ = &a->X;
1449 if (!a->Z_is_one)
1450 {
1451 if (!field_sqr(group, Za23, &a->Z, ctx)) goto end;
1452 if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end;
1453 tmp2_ = tmp2;
1454 }
1455 else
1456 tmp2_ = &b->X;
1457
1458 /* compare X_a*Z_b^2 with X_b*Z_a^2 */
1459 if (BN_cmp(tmp1_, tmp2_) != 0)
1460 {
1461 ret = 1; /* points differ */
1462 goto end;
1463 }
1464
1465
1466 if (!b->Z_is_one)
1467 {
1468 if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end;
1469 if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end;
1470 /* tmp1_ = tmp1 */
1471 }
1472 else
1473 tmp1_ = &a->Y;
1474 if (!a->Z_is_one)
1475 {
1476 if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end;
1477 if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end;
1478 /* tmp2_ = tmp2 */
1479 }
1480 else
1481 tmp2_ = &b->Y;
1482
1483 /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */
1484 if (BN_cmp(tmp1_, tmp2_) != 0)
1485 {
1486 ret = 1; /* points differ */
1487 goto end;
1488 }
1489
1490 /* points are equal */
1491 ret = 0;
1492
1493 end:
1494 BN_CTX_end(ctx);
1495 if (new_ctx != NULL)
1496 BN_CTX_free(new_ctx);
1497 return ret;
1498 }
1499
1500
1501int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1502 {
1503 BN_CTX *new_ctx = NULL;
1504 BIGNUM *x, *y;
1505 int ret = 0;
1506
1507 if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
1508 return 1;
1509
1510 if (ctx == NULL)
1511 {
1512 ctx = new_ctx = BN_CTX_new();
1513 if (ctx == NULL)
1514 return 0;
1515 }
1516
1517 BN_CTX_start(ctx);
1518 x = BN_CTX_get(ctx);
1519 y = BN_CTX_get(ctx);
1520 if (y == NULL) goto err;
1521
1522 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
1523 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
1524 if (!point->Z_is_one)
1525 {
1526 ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
1527 goto err;
1528 }
1529
1530 ret = 1;
1531
1532 err:
1533 BN_CTX_end(ctx);
1534 if (new_ctx != NULL)
1535 BN_CTX_free(new_ctx);
1536 return ret;
1537 }
1538
1539
1540int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
1541 {
1542 BN_CTX *new_ctx = NULL;
1543 BIGNUM *tmp0, *tmp1;
1544 size_t pow2 = 0;
1545 BIGNUM **heap = NULL;
1546 size_t i;
1547 int ret = 0;
1548
1549 if (num == 0)
1550 return 1;
1551
1552 if (ctx == NULL)
1553 {
1554 ctx = new_ctx = BN_CTX_new();
1555 if (ctx == NULL)
1556 return 0;
1557 }
1558
1559 BN_CTX_start(ctx);
1560 tmp0 = BN_CTX_get(ctx);
1561 tmp1 = BN_CTX_get(ctx);
1562 if (tmp0 == NULL || tmp1 == NULL) goto err;
1563
1564 /* Before converting the individual points, compute inverses of all Z values.
1565 * Modular inversion is rather slow, but luckily we can do with a single
1566 * explicit inversion, plus about 3 multiplications per input value.
1567 */
1568
1569 pow2 = 1;
1570 while (num > pow2)
1571 pow2 <<= 1;
1572 /* Now pow2 is the smallest power of 2 satifsying pow2 >= num.
1573 * We need twice that. */
1574 pow2 <<= 1;
1575
1576 heap = OPENSSL_malloc(pow2 * sizeof heap[0]);
1577 if (heap == NULL) goto err;
1578
1579 /* The array is used as a binary tree, exactly as in heapsort:
1580 *
1581 * heap[1]
1582 * heap[2] heap[3]
1583 * heap[4] heap[5] heap[6] heap[7]
1584 * heap[8]heap[9] heap[10]heap[11] heap[12]heap[13] heap[14] heap[15]
1585 *
1586 * We put the Z's in the last line;
1587 * then we set each other node to the product of its two child-nodes (where
1588 * empty or 0 entries are treated as ones);
1589 * then we invert heap[1];
1590 * then we invert each other node by replacing it by the product of its
1591 * parent (after inversion) and its sibling (before inversion).
1592 */
1593 heap[0] = NULL;
1594 for (i = pow2/2 - 1; i > 0; i--)
1595 heap[i] = NULL;
1596 for (i = 0; i < num; i++)
1597 heap[pow2/2 + i] = &points[i]->Z;
1598 for (i = pow2/2 + num; i < pow2; i++)
1599 heap[i] = NULL;
1600
1601 /* set each node to the product of its children */
1602 for (i = pow2/2 - 1; i > 0; i--)
1603 {
1604 heap[i] = BN_new();
1605 if (heap[i] == NULL) goto err;
1606
1607 if (heap[2*i] != NULL)
1608 {
1609 if ((heap[2*i + 1] == NULL) || BN_is_zero(heap[2*i + 1]))
1610 {
1611 if (!BN_copy(heap[i], heap[2*i])) goto err;
1612 }
1613 else
1614 {
1615 if (BN_is_zero(heap[2*i]))
1616 {
1617 if (!BN_copy(heap[i], heap[2*i + 1])) goto err;
1618 }
1619 else
1620 {
1621 if (!group->meth->field_mul(group, heap[i],
1622 heap[2*i], heap[2*i + 1], ctx)) goto err;
1623 }
1624 }
1625 }
1626 }
1627
1628 /* invert heap[1] */
1629 if (!BN_is_zero(heap[1]))
1630 {
1631 if (!BN_mod_inverse(heap[1], heap[1], &group->field, ctx))
1632 {
1633 ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
1634 goto err;
1635 }
1636 }
1637 if (group->meth->field_encode != 0)
1638 {
1639 /* in the Montgomery case, we just turned R*H (representing H)
1640 * into 1/(R*H), but we need R*(1/H) (representing 1/H);
1641 * i.e. we have need to multiply by the Montgomery factor twice */
1642 if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
1643 if (!group->meth->field_encode(group, heap[1], heap[1], ctx)) goto err;
1644 }
1645
1646 /* set other heap[i]'s to their inverses */
1647 for (i = 2; i < pow2/2 + num; i += 2)
1648 {
1649 /* i is even */
1650 if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1]))
1651 {
1652 if (!group->meth->field_mul(group, tmp0, heap[i/2], heap[i + 1], ctx)) goto err;
1653 if (!group->meth->field_mul(group, tmp1, heap[i/2], heap[i], ctx)) goto err;
1654 if (!BN_copy(heap[i], tmp0)) goto err;
1655 if (!BN_copy(heap[i + 1], tmp1)) goto err;
1656 }
1657 else
1658 {
1659 if (!BN_copy(heap[i], heap[i/2])) goto err;
1660 }
1661 }
1662
1663 /* we have replaced all non-zero Z's by their inverses, now fix up all the points */
1664 for (i = 0; i < num; i++)
1665 {
1666 EC_POINT *p = points[i];
1667
1668 if (!BN_is_zero(&p->Z))
1669 {
1670 /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1) */
1671
1672 if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx)) goto err;
1673 if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx)) goto err;
1674
1675 if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx)) goto err;
1676 if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx)) goto err;
1677
1678 if (group->meth->field_set_to_one != 0)
1679 {
1680 if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err;
1681 }
1682 else
1683 {
1684 if (!BN_one(&p->Z)) goto err;
1685 }
1686 p->Z_is_one = 1;
1687 }
1688 }
1689
1690 ret = 1;
1691
1692 err:
1693 BN_CTX_end(ctx);
1694 if (new_ctx != NULL)
1695 BN_CTX_free(new_ctx);
1696 if (heap != NULL)
1697 {
1698 /* heap[pow2/2] .. heap[pow2-1] have not been allocated locally! */
1699 for (i = pow2/2 - 1; i > 0; i--)
1700 {
1701 if (heap[i] != NULL)
1702 BN_clear_free(heap[i]);
1703 }
1704 OPENSSL_free(heap);
1705 }
1706 return ret;
1707 }
1708
1709
1710int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1711 {
1712 return BN_mod_mul(r, a, b, &group->field, ctx);
1713 }
1714
1715
1716int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
1717 {
1718 return BN_mod_sqr(r, a, &group->field, ctx);
1719 }
diff --git a/src/lib/libcrypto/ec/ectest.c b/src/lib/libcrypto/ec/ectest.c
index f107782de0..7509cb9c7c 100644
--- a/src/lib/libcrypto/ec/ectest.c
+++ b/src/lib/libcrypto/ec/ectest.c
@@ -94,7 +94,6 @@ int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); retur
94#include <openssl/objects.h> 94#include <openssl/objects.h>
95#include <openssl/rand.h> 95#include <openssl/rand.h>
96#include <openssl/bn.h> 96#include <openssl/bn.h>
97#include <openssl/opensslconf.h>
98 97
99#if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12) 98#if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12)
100/* suppress "too big too optimize" warning */ 99/* suppress "too big too optimize" warning */
@@ -108,6 +107,10 @@ int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); retur
108 EXIT(1); \ 107 EXIT(1); \
109} while (0) 108} while (0)
110 109
110void prime_field_tests(void);
111void char2_field_tests(void);
112void internal_curve_test(void);
113
111#define TIMING_BASE_PT 0 114#define TIMING_BASE_PT 0
112#define TIMING_RAND_PT 1 115#define TIMING_RAND_PT 1
113#define TIMING_SIMUL 2 116#define TIMING_SIMUL 2
@@ -192,50 +195,7 @@ static void timings(EC_GROUP *group, int type, BN_CTX *ctx)
192 } 195 }
193#endif 196#endif
194 197
195/* test multiplication with group order, long and negative scalars */ 198void prime_field_tests()
196static void group_order_tests(EC_GROUP *group)
197 {
198 BIGNUM *n1, *n2, *order;
199 EC_POINT *P = EC_POINT_new(group);
200 EC_POINT *Q = EC_POINT_new(group);
201 BN_CTX *ctx = BN_CTX_new();
202
203 n1 = BN_new(); n2 = BN_new(); order = BN_new();
204 fprintf(stdout, "verify group order ...");
205 fflush(stdout);
206 if (!EC_GROUP_get_order(group, order, ctx)) ABORT;
207 if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) ABORT;
208 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
209 fprintf(stdout, ".");
210 fflush(stdout);
211 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
212 if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) ABORT;
213 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
214 fprintf(stdout, " ok\n");
215 fprintf(stdout, "long/negative scalar tests ... ");
216 if (!BN_one(n1)) ABORT;
217 /* n1 = 1 - order */
218 if (!BN_sub(n1, n1, order)) ABORT;
219 if(!EC_POINT_mul(group, Q, NULL, P, n1, ctx)) ABORT;
220 if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
221 /* n2 = 1 + order */
222 if (!BN_add(n2, order, BN_value_one())) ABORT;
223 if(!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT;
224 if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
225 /* n2 = (1 - order) * (1 + order) */
226 if (!BN_mul(n2, n1, n2, ctx)) ABORT;
227 if(!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) ABORT;
228 if (0 != EC_POINT_cmp(group, Q, P, ctx)) ABORT;
229 fprintf(stdout, "ok\n");
230 EC_POINT_free(P);
231 EC_POINT_free(Q);
232 BN_free(n1);
233 BN_free(n2);
234 BN_free(order);
235 BN_CTX_free(ctx);
236 }
237
238static void prime_field_tests(void)
239 { 199 {
240 BN_CTX *ctx = NULL; 200 BN_CTX *ctx = NULL;
241 BIGNUM *p, *a, *b; 201 BIGNUM *p, *a, *b;
@@ -361,21 +321,21 @@ static void prime_field_tests(void)
361 if (len == 0) ABORT; 321 if (len == 0) ABORT;
362 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; 322 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
363 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; 323 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
364 fprintf(stdout, "Generator as octet string, compressed form:\n "); 324 fprintf(stdout, "Generator as octect string, compressed form:\n ");
365 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); 325 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
366 326
367 len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); 327 len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
368 if (len == 0) ABORT; 328 if (len == 0) ABORT;
369 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; 329 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
370 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; 330 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
371 fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n "); 331 fprintf(stdout, "\nGenerator as octect string, uncompressed form:\n ");
372 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); 332 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
373 333
374 len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); 334 len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
375 if (len == 0) ABORT; 335 if (len == 0) ABORT;
376 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT; 336 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
377 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT; 337 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
378 fprintf(stdout, "\nGenerator as octet string, hybrid form:\n "); 338 fprintf(stdout, "\nGenerator as octect string, hybrid form:\n ");
379 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); 339 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
380 340
381 if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT; 341 if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) ABORT;
@@ -421,7 +381,17 @@ static void prime_field_tests(void)
421 if (EC_GROUP_get_degree(group) != 160) ABORT; 381 if (EC_GROUP_get_degree(group) != 160) ABORT;
422 fprintf(stdout, " ok\n"); 382 fprintf(stdout, " ok\n");
423 383
424 group_order_tests(group); 384 fprintf(stdout, "verify group order ...");
385 fflush(stdout);
386 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
387 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
388 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
389 fprintf(stdout, ".");
390 fflush(stdout);
391 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
392 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
393 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
394 fprintf(stdout, " ok\n");
425 395
426 if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 396 if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
427 if (!EC_GROUP_copy(P_160, group)) ABORT; 397 if (!EC_GROUP_copy(P_160, group)) ABORT;
@@ -455,7 +425,17 @@ static void prime_field_tests(void)
455 if (EC_GROUP_get_degree(group) != 192) ABORT; 425 if (EC_GROUP_get_degree(group) != 192) ABORT;
456 fprintf(stdout, " ok\n"); 426 fprintf(stdout, " ok\n");
457 427
458 group_order_tests(group); 428 fprintf(stdout, "verify group order ...");
429 fflush(stdout);
430 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
431 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
432 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
433 fprintf(stdout, ".");
434 fflush(stdout);
435 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
436 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
437 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
438 fprintf(stdout, " ok\n");
459 439
460 if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 440 if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
461 if (!EC_GROUP_copy(P_192, group)) ABORT; 441 if (!EC_GROUP_copy(P_192, group)) ABORT;
@@ -489,7 +469,17 @@ static void prime_field_tests(void)
489 if (EC_GROUP_get_degree(group) != 224) ABORT; 469 if (EC_GROUP_get_degree(group) != 224) ABORT;
490 fprintf(stdout, " ok\n"); 470 fprintf(stdout, " ok\n");
491 471
492 group_order_tests(group); 472 fprintf(stdout, "verify group order ...");
473 fflush(stdout);
474 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
475 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
476 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
477 fprintf(stdout, ".");
478 fflush(stdout);
479 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
480 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
481 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
482 fprintf(stdout, " ok\n");
493 483
494 if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 484 if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
495 if (!EC_GROUP_copy(P_224, group)) ABORT; 485 if (!EC_GROUP_copy(P_224, group)) ABORT;
@@ -524,7 +514,17 @@ static void prime_field_tests(void)
524 if (EC_GROUP_get_degree(group) != 256) ABORT; 514 if (EC_GROUP_get_degree(group) != 256) ABORT;
525 fprintf(stdout, " ok\n"); 515 fprintf(stdout, " ok\n");
526 516
527 group_order_tests(group); 517 fprintf(stdout, "verify group order ...");
518 fflush(stdout);
519 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
520 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
521 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
522 fprintf(stdout, ".");
523 fflush(stdout);
524 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
525 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
526 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
527 fprintf(stdout, " ok\n");
528 528
529 if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 529 if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
530 if (!EC_GROUP_copy(P_256, group)) ABORT; 530 if (!EC_GROUP_copy(P_256, group)) ABORT;
@@ -563,8 +563,18 @@ static void prime_field_tests(void)
563 fprintf(stdout, "verify degree ..."); 563 fprintf(stdout, "verify degree ...");
564 if (EC_GROUP_get_degree(group) != 384) ABORT; 564 if (EC_GROUP_get_degree(group) != 384) ABORT;
565 fprintf(stdout, " ok\n"); 565 fprintf(stdout, " ok\n");
566 566
567 group_order_tests(group); 567 fprintf(stdout, "verify group order ...");
568 fflush(stdout);
569 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
570 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
571 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
572 fprintf(stdout, ".");
573 fflush(stdout);
574 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
575 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
576 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
577 fprintf(stdout, " ok\n");
568 578
569 if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 579 if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
570 if (!EC_GROUP_copy(P_384, group)) ABORT; 580 if (!EC_GROUP_copy(P_384, group)) ABORT;
@@ -609,8 +619,18 @@ static void prime_field_tests(void)
609 fprintf(stdout, "verify degree ..."); 619 fprintf(stdout, "verify degree ...");
610 if (EC_GROUP_get_degree(group) != 521) ABORT; 620 if (EC_GROUP_get_degree(group) != 521) ABORT;
611 fprintf(stdout, " ok\n"); 621 fprintf(stdout, " ok\n");
612 622
613 group_order_tests(group); 623 fprintf(stdout, "verify group order ...");
624 fflush(stdout);
625 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
626 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
627 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
628 fprintf(stdout, ".");
629 fflush(stdout);
630 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
631 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
632 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
633 fprintf(stdout, " ok\n");
614 634
615 if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; 635 if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
616 if (!EC_GROUP_copy(P_521, group)) ABORT; 636 if (!EC_GROUP_copy(P_521, group)) ABORT;
@@ -639,7 +659,6 @@ static void prime_field_tests(void)
639 points[2] = Q; 659 points[2] = Q;
640 points[3] = Q; 660 points[3] = Q;
641 661
642 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
643 if (!BN_add(y, z, BN_value_one())) ABORT; 662 if (!BN_add(y, z, BN_value_one())) ABORT;
644 if (BN_is_odd(y)) ABORT; 663 if (BN_is_odd(y)) ABORT;
645 if (!BN_rshift1(y, y)) ABORT; 664 if (!BN_rshift1(y, y)) ABORT;
@@ -773,14 +792,22 @@ static void prime_field_tests(void)
773 fprintf(stdout, "verify degree ..."); \ 792 fprintf(stdout, "verify degree ..."); \
774 if (EC_GROUP_get_degree(group) != _degree) ABORT; \ 793 if (EC_GROUP_get_degree(group) != _degree) ABORT; \
775 fprintf(stdout, " ok\n"); \ 794 fprintf(stdout, " ok\n"); \
776 group_order_tests(group); \ 795 fprintf(stdout, "verify group order ..."); \
796 fflush(stdout); \
797 if (!EC_GROUP_get_order(group, z, ctx)) ABORT; \
798 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; \
799 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; \
800 fprintf(stdout, "."); \
801 fflush(stdout); \
802 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; \
803 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; \
804 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; \
805 fprintf(stdout, " ok\n"); \
777 if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \ 806 if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \
778 if (!EC_GROUP_copy(_variable, group)) ABORT; \ 807 if (!EC_GROUP_copy(_variable, group)) ABORT;
779 808
780#ifndef OPENSSL_NO_EC2M 809void char2_field_tests()
781 810 {
782static void char2_field_tests(void)
783 {
784 BN_CTX *ctx = NULL; 811 BN_CTX *ctx = NULL;
785 BIGNUM *p, *a, *b; 812 BIGNUM *p, *a, *b;
786 EC_GROUP *group; 813 EC_GROUP *group;
@@ -1212,9 +1239,8 @@ static void char2_field_tests(void)
1212 if (C2_B571) EC_GROUP_free(C2_B571); 1239 if (C2_B571) EC_GROUP_free(C2_B571);
1213 1240
1214 } 1241 }
1215#endif
1216 1242
1217static void internal_curve_test(void) 1243void internal_curve_test(void)
1218 { 1244 {
1219 EC_builtin_curve *curves = NULL; 1245 EC_builtin_curve *curves = NULL;
1220 size_t crv_len = 0, n = 0; 1246 size_t crv_len = 0, n = 0;
@@ -1261,189 +1287,13 @@ static void internal_curve_test(void)
1261 EC_GROUP_free(group); 1287 EC_GROUP_free(group);
1262 } 1288 }
1263 if (ok) 1289 if (ok)
1264 fprintf(stdout, " ok\n\n"); 1290 fprintf(stdout, " ok\n");
1265 else 1291 else
1266 { 1292 fprintf(stdout, " failed\n");
1267 fprintf(stdout, " failed\n\n");
1268 ABORT;
1269 }
1270 OPENSSL_free(curves); 1293 OPENSSL_free(curves);
1271 return; 1294 return;
1272 } 1295 }
1273 1296
1274#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1275/* nistp_test_params contains magic numbers for testing our optimized
1276 * implementations of several NIST curves with characteristic > 3. */
1277struct nistp_test_params
1278 {
1279 const EC_METHOD* (*meth) ();
1280 int degree;
1281 /* Qx, Qy and D are taken from
1282 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
1283 * Otherwise, values are standard curve parameters from FIPS 180-3 */
1284 const char *p, *a, *b, *Qx, *Qy, *Gx, *Gy, *order, *d;
1285 };
1286
1287static const struct nistp_test_params nistp_tests_params[] =
1288 {
1289 {
1290 /* P-224 */
1291 EC_GFp_nistp224_method,
1292 224,
1293 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* p */
1294 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* a */
1295 "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* b */
1296 "E84FB0B8E7000CB657D7973CF6B42ED78B301674276DF744AF130B3E", /* Qx */
1297 "4376675C6FC5612C21A0FF2D2A89D2987DF7A2BC52183B5982298555", /* Qy */
1298 "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gx */
1299 "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy */
1300 "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* order */
1301 "3F0C488E987C80BE0FEE521F8D90BE6034EC69AE11CA72AA777481E8", /* d */
1302 },
1303 {
1304 /* P-256 */
1305 EC_GFp_nistp256_method,
1306 256,
1307 "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", /* p */
1308 "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", /* a */
1309 "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", /* b */
1310 "b7e08afdfe94bad3f1dc8c734798ba1c62b3a0ad1e9ea2a38201cd0889bc7a19", /* Qx */
1311 "3603f747959dbf7a4bb226e41928729063adc7ae43529e61b563bbc606cc5e09", /* Qy */
1312 "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", /* Gx */
1313 "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", /* Gy */
1314 "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", /* order */
1315 "c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96", /* d */
1316 },
1317 {
1318 /* P-521 */
1319 EC_GFp_nistp521_method,
1320 521,
1321 "1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", /* p */
1322 "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc", /* a */
1323 "051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", /* b */
1324 "0098e91eef9a68452822309c52fab453f5f117c1da8ed796b255e9ab8f6410cca16e59df403a6bdc6ca467a37056b1e54b3005d8ac030decfeb68df18b171885d5c4", /* Qx */
1325 "0164350c321aecfc1cca1ba4364c9b15656150b4b78d6a48d7d28e7f31985ef17be8554376b72900712c4b83ad668327231526e313f5f092999a4632fd50d946bc2e", /* Qy */
1326 "c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", /* Gx */
1327 "11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", /* Gy */
1328 "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409", /* order */
1329 "0100085f47b8e1b8b11b7eb33028c0b2888e304bfc98501955b45bba1478dc184eeedf09b86a5f7c21994406072787205e69a63709fe35aa93ba333514b24f961722", /* d */
1330 },
1331 };
1332
1333void nistp_single_test(const struct nistp_test_params *test)
1334 {
1335 BN_CTX *ctx;
1336 BIGNUM *p, *a, *b, *x, *y, *n, *m, *order;
1337 EC_GROUP *NISTP;
1338 EC_POINT *G, *P, *Q, *Q_CHECK;
1339
1340 fprintf(stdout, "\nNIST curve P-%d (optimised implementation):\n", test->degree);
1341 ctx = BN_CTX_new();
1342 p = BN_new();
1343 a = BN_new();
1344 b = BN_new();
1345 x = BN_new(); y = BN_new();
1346 m = BN_new(); n = BN_new(); order = BN_new();
1347
1348 NISTP = EC_GROUP_new(test->meth());
1349 if(!NISTP) ABORT;
1350 if (!BN_hex2bn(&p, test->p)) ABORT;
1351 if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
1352 if (!BN_hex2bn(&a, test->a)) ABORT;
1353 if (!BN_hex2bn(&b, test->b)) ABORT;
1354 if (!EC_GROUP_set_curve_GFp(NISTP, p, a, b, ctx)) ABORT;
1355 G = EC_POINT_new(NISTP);
1356 P = EC_POINT_new(NISTP);
1357 Q = EC_POINT_new(NISTP);
1358 Q_CHECK = EC_POINT_new(NISTP);
1359 if(!BN_hex2bn(&x, test->Qx)) ABORT;
1360 if(!BN_hex2bn(&y, test->Qy)) ABORT;
1361 if(!EC_POINT_set_affine_coordinates_GFp(NISTP, Q_CHECK, x, y, ctx)) ABORT;
1362 if (!BN_hex2bn(&x, test->Gx)) ABORT;
1363 if (!BN_hex2bn(&y, test->Gy)) ABORT;
1364 if (!EC_POINT_set_affine_coordinates_GFp(NISTP, G, x, y, ctx)) ABORT;
1365 if (!BN_hex2bn(&order, test->order)) ABORT;
1366 if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) ABORT;
1367
1368 fprintf(stdout, "verify degree ... ");
1369 if (EC_GROUP_get_degree(NISTP) != test->degree) ABORT;
1370 fprintf(stdout, "ok\n");
1371
1372 fprintf(stdout, "NIST test vectors ... ");
1373 if (!BN_hex2bn(&n, test->d)) ABORT;
1374 /* fixed point multiplication */
1375 EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
1376 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1377 /* random point multiplication */
1378 EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
1379 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1380
1381 /* set generator to P = 2*G, where G is the standard generator */
1382 if (!EC_POINT_dbl(NISTP, P, G, ctx)) ABORT;
1383 if (!EC_GROUP_set_generator(NISTP, P, order, BN_value_one())) ABORT;
1384 /* set the scalar to m=n/2, where n is the NIST test scalar */
1385 if (!BN_rshift(m, n, 1)) ABORT;
1386
1387 /* test the non-standard generator */
1388 /* fixed point multiplication */
1389 EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
1390 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1391 /* random point multiplication */
1392 EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
1393 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1394
1395 /* now repeat all tests with precomputation */
1396 if (!EC_GROUP_precompute_mult(NISTP, ctx)) ABORT;
1397
1398 /* fixed point multiplication */
1399 EC_POINT_mul(NISTP, Q, m, NULL, NULL, ctx);
1400 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1401 /* random point multiplication */
1402 EC_POINT_mul(NISTP, Q, NULL, P, m, ctx);
1403 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1404
1405 /* reset generator */
1406 if (!EC_GROUP_set_generator(NISTP, G, order, BN_value_one())) ABORT;
1407 /* fixed point multiplication */
1408 EC_POINT_mul(NISTP, Q, n, NULL, NULL, ctx);
1409 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1410 /* random point multiplication */
1411 EC_POINT_mul(NISTP, Q, NULL, G, n, ctx);
1412 if (0 != EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)) ABORT;
1413
1414 fprintf(stdout, "ok\n");
1415 group_order_tests(NISTP);
1416#if 0
1417 timings(NISTP, TIMING_BASE_PT, ctx);
1418 timings(NISTP, TIMING_RAND_PT, ctx);
1419#endif
1420 EC_GROUP_free(NISTP);
1421 EC_POINT_free(G);
1422 EC_POINT_free(P);
1423 EC_POINT_free(Q);
1424 EC_POINT_free(Q_CHECK);
1425 BN_free(n);
1426 BN_free(m);
1427 BN_free(p);
1428 BN_free(a);
1429 BN_free(b);
1430 BN_free(x);
1431 BN_free(y);
1432 BN_free(order);
1433 BN_CTX_free(ctx);
1434 }
1435
1436void nistp_tests()
1437 {
1438 unsigned i;
1439
1440 for (i = 0; i < sizeof(nistp_tests_params) / sizeof(struct nistp_test_params); i++)
1441 {
1442 nistp_single_test(&nistp_tests_params[i]);
1443 }
1444 }
1445#endif
1446
1447static const char rnd_seed[] = "string to make the random number generator think it has entropy"; 1297static const char rnd_seed[] = "string to make the random number generator think it has entropy";
1448 1298
1449int main(int argc, char *argv[]) 1299int main(int argc, char *argv[])
@@ -1467,12 +1317,7 @@ int main(int argc, char *argv[])
1467 1317
1468 prime_field_tests(); 1318 prime_field_tests();
1469 puts(""); 1319 puts("");
1470#ifndef OPENSSL_NO_EC2M
1471 char2_field_tests(); 1320 char2_field_tests();
1472#endif
1473#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1474 nistp_tests();
1475#endif
1476 /* test the internal curves */ 1321 /* test the internal curves */
1477 internal_curve_test(); 1322 internal_curve_test();
1478 1323