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.h319
-rw-r--r--src/lib/libcrypto/ec/ec_cvt.c76
-rw-r--r--src/lib/libcrypto/ec/ec_err.c114
-rw-r--r--src/lib/libcrypto/ec/ec_lcl.h241
-rw-r--r--src/lib/libcrypto/ec/ec_lib.c678
-rw-r--r--src/lib/libcrypto/ec/ec_mult.c673
-rw-r--r--src/lib/libcrypto/ec/ecp_mont.c151
-rw-r--r--src/lib/libcrypto/ec/ecp_nist.c180
-rw-r--r--src/lib/libcrypto/ec/ecp_smpl.c335
-rw-r--r--src/lib/libcrypto/ec/ectest.c813
10 files changed, 2950 insertions, 630 deletions
diff --git a/src/lib/libcrypto/ec/ec.h b/src/lib/libcrypto/ec/ec.h
index 6d6a9b7127..8bc2a235b1 100644
--- a/src/lib/libcrypto/ec/ec.h
+++ b/src/lib/libcrypto/ec/ec.h
@@ -1,6 +1,9 @@
1/* crypto/ec/ec.h */ 1/* crypto/ec/ec.h */
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-2003 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,22 +55,48 @@
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
56#ifndef HEADER_EC_H 72#ifndef HEADER_EC_H
57#define HEADER_EC_H 73#define HEADER_EC_H
58 74
75#include <openssl/opensslconf.h>
76
59#ifdef OPENSSL_NO_EC 77#ifdef OPENSSL_NO_EC
60#error EC is disabled. 78#error EC is disabled.
61#endif 79#endif
62 80
63#include <openssl/bn.h> 81#include <openssl/asn1.h>
64#include <openssl/symhacks.h> 82#include <openssl/symhacks.h>
83#ifndef OPENSSL_NO_DEPRECATED
84#include <openssl/bn.h>
85#endif
65 86
66#ifdef __cplusplus 87#ifdef __cplusplus
67extern "C" { 88extern "C" {
89#elif defined(__SUNPRO_C)
90# if __SUNPRO_C >= 0x520
91# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
92# endif
68#endif 93#endif
69 94
70 95
96#ifndef OPENSSL_ECC_MAX_FIELD_BITS
97# define OPENSSL_ECC_MAX_FIELD_BITS 661
98#endif
99
71typedef enum { 100typedef enum {
72 /* values as defined in X9.62 (ECDSA) and elsewhere */ 101 /* values as defined in X9.62 (ECDSA) and elsewhere */
73 POINT_CONVERSION_COMPRESSED = 2, 102 POINT_CONVERSION_COMPRESSED = 2,
@@ -84,7 +113,8 @@ typedef struct ec_group_st
84 -- field definition 113 -- field definition
85 -- curve coefficients 114 -- curve coefficients
86 -- optional generator with associated information (order, cofactor) 115 -- optional generator with associated information (order, cofactor)
87 -- optional extra data (TODO: precomputed table for fast computation of multiples of generator) 116 -- optional extra data (precomputed table for fast computation of multiples of generator)
117 -- ASN1 stuff
88 */ 118 */
89 EC_GROUP; 119 EC_GROUP;
90 120
@@ -96,40 +126,84 @@ typedef struct ec_point_st EC_POINT;
96 */ 126 */
97const EC_METHOD *EC_GFp_simple_method(void); 127const EC_METHOD *EC_GFp_simple_method(void);
98const EC_METHOD *EC_GFp_mont_method(void); 128const EC_METHOD *EC_GFp_mont_method(void);
99#if 0 129const EC_METHOD *EC_GFp_nist_method(void);
100const EC_METHOD *EC_GFp_recp_method(void); /* TODO */ 130
101const EC_METHOD *EC_GFp_nist_method(void); /* TODO */ 131/* EC_METHOD for curves over GF(2^m).
102#endif 132 */
133const EC_METHOD *EC_GF2m_simple_method(void);
103 134
104 135
105EC_GROUP *EC_GROUP_new(const EC_METHOD *); 136EC_GROUP *EC_GROUP_new(const EC_METHOD *);
106void EC_GROUP_free(EC_GROUP *); 137void EC_GROUP_free(EC_GROUP *);
107void EC_GROUP_clear_free(EC_GROUP *); 138void EC_GROUP_clear_free(EC_GROUP *);
108int EC_GROUP_copy(EC_GROUP *, const EC_GROUP *); 139int EC_GROUP_copy(EC_GROUP *, const EC_GROUP *);
140EC_GROUP *EC_GROUP_dup(const EC_GROUP *);
109 141
110const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *); 142const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *);
111 143int EC_METHOD_get_field_type(const EC_METHOD *);
144
145int EC_GROUP_set_generator(EC_GROUP *, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor);
146const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *);
147int EC_GROUP_get_order(const EC_GROUP *, BIGNUM *order, BN_CTX *);
148int EC_GROUP_get_cofactor(const EC_GROUP *, BIGNUM *cofactor, BN_CTX *);
149
150void EC_GROUP_set_curve_name(EC_GROUP *, int nid);
151int EC_GROUP_get_curve_name(const EC_GROUP *);
152
153void EC_GROUP_set_asn1_flag(EC_GROUP *, int flag);
154int EC_GROUP_get_asn1_flag(const EC_GROUP *);
155
156void EC_GROUP_set_point_conversion_form(EC_GROUP *, point_conversion_form_t);
157point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *);
158
159unsigned char *EC_GROUP_get0_seed(const EC_GROUP *);
160size_t EC_GROUP_get_seed_len(const EC_GROUP *);
161size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len);
112 162
113/* We don't have types for field specifications and field elements in general.
114 * Otherwise we could declare
115 * int EC_GROUP_set_curve(EC_GROUP *, .....);
116 */
117int EC_GROUP_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); 163int EC_GROUP_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
118int EC_GROUP_get_curve_GFp(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *); 164int EC_GROUP_get_curve_GFp(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
165int EC_GROUP_set_curve_GF2m(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
166int EC_GROUP_get_curve_GF2m(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
167
168/* returns the number of bits needed to represent a field element */
169int EC_GROUP_get_degree(const EC_GROUP *);
170
171/* EC_GROUP_check() returns 1 if 'group' defines a valid group, 0 otherwise */
172int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx);
173/* EC_GROUP_check_discriminant() returns 1 if the discriminant of the
174 * elliptic curve is not zero, 0 otherwise */
175int EC_GROUP_check_discriminant(const EC_GROUP *, BN_CTX *);
119 176
120/* EC_GROUP_new_GFp() calls EC_GROUP_new() and EC_GROUP_set_GFp() 177/* EC_GROUP_cmp() returns 0 if both groups are equal and 1 otherwise */
178int EC_GROUP_cmp(const EC_GROUP *, const EC_GROUP *, BN_CTX *);
179
180/* EC_GROUP_new_GF*() calls EC_GROUP_new() and EC_GROUP_set_GF*()
121 * after choosing an appropriate EC_METHOD */ 181 * after choosing an appropriate EC_METHOD */
122EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); 182EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
183EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
123 184
124int EC_GROUP_set_generator(EC_GROUP *, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor); 185/* EC_GROUP_new_by_curve_name() creates a EC_GROUP structure
125EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *); 186 * specified by a curve name (in form of a NID) */
126int EC_GROUP_get_order(const EC_GROUP *, BIGNUM *order, BN_CTX *); 187EC_GROUP *EC_GROUP_new_by_curve_name(int nid);
127int EC_GROUP_get_cofactor(const EC_GROUP *, BIGNUM *cofactor, BN_CTX *); 188/* handling of internal curves */
189typedef struct {
190 int nid;
191 const char *comment;
192 } EC_builtin_curve;
193/* EC_builtin_curves(EC_builtin_curve *r, size_t size) returns number
194 * of all available curves or zero if a error occurred.
195 * In case r ist not zero nitems EC_builtin_curve structures
196 * are filled with the data of the first nitems internal groups */
197size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems);
198
199
200/* EC_POINT functions */
128 201
129EC_POINT *EC_POINT_new(const EC_GROUP *); 202EC_POINT *EC_POINT_new(const EC_GROUP *);
130void EC_POINT_free(EC_POINT *); 203void EC_POINT_free(EC_POINT *);
131void EC_POINT_clear_free(EC_POINT *); 204void EC_POINT_clear_free(EC_POINT *);
132int EC_POINT_copy(EC_POINT *, const EC_POINT *); 205int EC_POINT_copy(EC_POINT *, const EC_POINT *);
206EC_POINT *EC_POINT_dup(const EC_POINT *, const EC_GROUP *);
133 207
134const EC_METHOD *EC_POINT_method_of(const EC_POINT *); 208const EC_METHOD *EC_POINT_method_of(const EC_POINT *);
135 209
@@ -145,11 +219,28 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
145int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *, EC_POINT *, 219int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *, EC_POINT *,
146 const BIGNUM *x, int y_bit, BN_CTX *); 220 const BIGNUM *x, int y_bit, BN_CTX *);
147 221
222int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *, EC_POINT *,
223 const BIGNUM *x, const BIGNUM *y, BN_CTX *);
224int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *, const EC_POINT *,
225 BIGNUM *x, BIGNUM *y, BN_CTX *);
226int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *, EC_POINT *,
227 const BIGNUM *x, int y_bit, BN_CTX *);
228
148size_t EC_POINT_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form, 229size_t EC_POINT_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
149 unsigned char *buf, size_t len, BN_CTX *); 230 unsigned char *buf, size_t len, BN_CTX *);
150int EC_POINT_oct2point(const EC_GROUP *, EC_POINT *, 231int EC_POINT_oct2point(const EC_GROUP *, EC_POINT *,
151 const unsigned char *buf, size_t len, BN_CTX *); 232 const unsigned char *buf, size_t len, BN_CTX *);
152 233
234/* other interfaces to point2oct/oct2point: */
235BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *,
236 point_conversion_form_t form, BIGNUM *, BN_CTX *);
237EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *,
238 EC_POINT *, BN_CTX *);
239char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *,
240 point_conversion_form_t form, BN_CTX *);
241EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *,
242 EC_POINT *, BN_CTX *);
243
153int EC_POINT_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *); 244int EC_POINT_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
154int EC_POINT_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *); 245int EC_POINT_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
155int EC_POINT_invert(const EC_GROUP *, EC_POINT *, BN_CTX *); 246int EC_POINT_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
@@ -164,9 +255,112 @@ int EC_POINTs_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
164 255
165int EC_POINTs_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, size_t num, const EC_POINT *[], const BIGNUM *[], BN_CTX *); 256int EC_POINTs_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, size_t num, const EC_POINT *[], const BIGNUM *[], BN_CTX *);
166int EC_POINT_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, const EC_POINT *, const BIGNUM *, BN_CTX *); 257int EC_POINT_mul(const EC_GROUP *, EC_POINT *r, const BIGNUM *, const EC_POINT *, const BIGNUM *, BN_CTX *);
258
259/* EC_GROUP_precompute_mult() stores multiples of generator for faster point multiplication */
167int EC_GROUP_precompute_mult(EC_GROUP *, BN_CTX *); 260int EC_GROUP_precompute_mult(EC_GROUP *, BN_CTX *);
261/* EC_GROUP_have_precompute_mult() reports whether such precomputation has been done */
262int EC_GROUP_have_precompute_mult(const EC_GROUP *);
263
264
168 265
266/* ASN1 stuff */
169 267
268/* EC_GROUP_get_basis_type() returns the NID of the basis type
269 * used to represent the field elements */
270int EC_GROUP_get_basis_type(const EC_GROUP *);
271int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
272int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,
273 unsigned int *k2, unsigned int *k3);
274
275#define OPENSSL_EC_NAMED_CURVE 0x001
276
277typedef struct ecpk_parameters_st ECPKPARAMETERS;
278
279EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len);
280int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out);
281
282#define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x)
283#define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x)
284#define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \
285 (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x))
286#define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \
287 (unsigned char *)(x))
288
289#ifndef OPENSSL_NO_BIO
290int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off);
291#endif
292#ifndef OPENSSL_NO_FP_API
293int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off);
294#endif
295
296/* the EC_KEY stuff */
297typedef struct ec_key_st EC_KEY;
298
299/* some values for the encoding_flag */
300#define EC_PKEY_NO_PARAMETERS 0x001
301#define EC_PKEY_NO_PUBKEY 0x002
302
303EC_KEY *EC_KEY_new(void);
304EC_KEY *EC_KEY_new_by_curve_name(int nid);
305void EC_KEY_free(EC_KEY *);
306EC_KEY *EC_KEY_copy(EC_KEY *, const EC_KEY *);
307EC_KEY *EC_KEY_dup(const EC_KEY *);
308
309int EC_KEY_up_ref(EC_KEY *);
310
311const EC_GROUP *EC_KEY_get0_group(const EC_KEY *);
312int EC_KEY_set_group(EC_KEY *, const EC_GROUP *);
313const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *);
314int EC_KEY_set_private_key(EC_KEY *, const BIGNUM *);
315const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *);
316int EC_KEY_set_public_key(EC_KEY *, const EC_POINT *);
317unsigned EC_KEY_get_enc_flags(const EC_KEY *);
318void EC_KEY_set_enc_flags(EC_KEY *, unsigned int);
319point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *);
320void EC_KEY_set_conv_form(EC_KEY *, point_conversion_form_t);
321/* functions to set/get method specific data */
322void *EC_KEY_get_key_method_data(EC_KEY *,
323 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
324void EC_KEY_insert_key_method_data(EC_KEY *, void *data,
325 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
326/* wrapper functions for the underlying EC_GROUP object */
327void EC_KEY_set_asn1_flag(EC_KEY *, int);
328int EC_KEY_precompute_mult(EC_KEY *, BN_CTX *ctx);
329
330/* EC_KEY_generate_key() creates a ec private (public) key */
331int EC_KEY_generate_key(EC_KEY *);
332/* EC_KEY_check_key() */
333int EC_KEY_check_key(const EC_KEY *);
334
335/* de- and encoding functions for SEC1 ECPrivateKey */
336EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len);
337int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out);
338/* de- and encoding functions for EC parameters */
339EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len);
340int i2d_ECParameters(EC_KEY *a, unsigned char **out);
341/* de- and encoding functions for EC public key
342 * (octet string, not DER -- hence 'o2i' and 'i2o') */
343EC_KEY *o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len);
344int i2o_ECPublicKey(EC_KEY *a, unsigned char **out);
345
346#ifndef OPENSSL_NO_BIO
347int ECParameters_print(BIO *bp, const EC_KEY *x);
348int EC_KEY_print(BIO *bp, const EC_KEY *x, int off);
349#endif
350#ifndef OPENSSL_NO_FP_API
351int ECParameters_print_fp(FILE *fp, const EC_KEY *x);
352int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off);
353#endif
354
355#define ECParameters_dup(x) ASN1_dup_of(EC_KEY,i2d_ECParameters,d2i_ECParameters,x)
356
357#ifndef __cplusplus
358#if defined(__SUNPRO_C)
359# if __SUNPRO_C >= 0x520
360# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
361# endif
362# endif
363#endif
170 364
171/* BEGIN ERROR CODES */ 365/* BEGIN ERROR CODES */
172/* The following lines are auto generated by the script mkerr.pl. Any changes 366/* The following lines are auto generated by the script mkerr.pl. Any changes
@@ -178,51 +372,124 @@ void ERR_load_EC_strings(void);
178 372
179/* Function codes. */ 373/* Function codes. */
180#define EC_F_COMPUTE_WNAF 143 374#define EC_F_COMPUTE_WNAF 143
375#define EC_F_D2I_ECPARAMETERS 144
376#define EC_F_D2I_ECPKPARAMETERS 145
377#define EC_F_D2I_ECPRIVATEKEY 146
378#define EC_F_ECPARAMETERS_PRINT 147
379#define EC_F_ECPARAMETERS_PRINT_FP 148
380#define EC_F_ECPKPARAMETERS_PRINT 149
381#define EC_F_ECPKPARAMETERS_PRINT_FP 150
382#define EC_F_ECP_NIST_MOD_192 203
383#define EC_F_ECP_NIST_MOD_224 204
384#define EC_F_ECP_NIST_MOD_256 205
385#define EC_F_ECP_NIST_MOD_521 206
386#define EC_F_EC_ASN1_GROUP2CURVE 153
387#define EC_F_EC_ASN1_GROUP2FIELDID 154
388#define EC_F_EC_ASN1_GROUP2PARAMETERS 155
389#define EC_F_EC_ASN1_GROUP2PKPARAMETERS 156
390#define EC_F_EC_ASN1_PARAMETERS2GROUP 157
391#define EC_F_EC_ASN1_PKPARAMETERS2GROUP 158
392#define EC_F_EC_EX_DATA_SET_DATA 211
393#define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208
394#define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159
395#define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195
396#define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160
397#define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161
398#define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162
399#define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163
400#define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164
181#define EC_F_EC_GFP_MONT_FIELD_DECODE 133 401#define EC_F_EC_GFP_MONT_FIELD_DECODE 133
182#define EC_F_EC_GFP_MONT_FIELD_ENCODE 134 402#define EC_F_EC_GFP_MONT_FIELD_ENCODE 134
183#define EC_F_EC_GFP_MONT_FIELD_MUL 131 403#define EC_F_EC_GFP_MONT_FIELD_MUL 131
404#define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 209
184#define EC_F_EC_GFP_MONT_FIELD_SQR 132 405#define EC_F_EC_GFP_MONT_FIELD_SQR 132
406#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189
407#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135
408#define EC_F_EC_GFP_NIST_FIELD_MUL 200
409#define EC_F_EC_GFP_NIST_FIELD_SQR 201
410#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202
411#define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 165
412#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 166
185#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP 100 413#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP 100
186#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 101 414#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 101
187#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102 415#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102
188#define EC_F_EC_GFP_SIMPLE_OCT2POINT 103 416#define EC_F_EC_GFP_SIMPLE_OCT2POINT 103
189#define EC_F_EC_GFP_SIMPLE_POINT2OCT 104 417#define EC_F_EC_GFP_SIMPLE_POINT2OCT 104
190#define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137 418#define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137
419#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 167
191#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105 420#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105
421#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 168
192#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128 422#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128
423#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 169
193#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129 424#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129
425#define EC_F_EC_GROUP_CHECK 170
426#define EC_F_EC_GROUP_CHECK_DISCRIMINANT 171
194#define EC_F_EC_GROUP_COPY 106 427#define EC_F_EC_GROUP_COPY 106
195#define EC_F_EC_GROUP_GET0_GENERATOR 139 428#define EC_F_EC_GROUP_GET0_GENERATOR 139
196#define EC_F_EC_GROUP_GET_COFACTOR 140 429#define EC_F_EC_GROUP_GET_COFACTOR 140
430#define EC_F_EC_GROUP_GET_CURVE_GF2M 172
197#define EC_F_EC_GROUP_GET_CURVE_GFP 130 431#define EC_F_EC_GROUP_GET_CURVE_GFP 130
432#define EC_F_EC_GROUP_GET_DEGREE 173
198#define EC_F_EC_GROUP_GET_ORDER 141 433#define EC_F_EC_GROUP_GET_ORDER 141
434#define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 193
435#define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 194
199#define EC_F_EC_GROUP_NEW 108 436#define EC_F_EC_GROUP_NEW 108
437#define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 174
438#define EC_F_EC_GROUP_NEW_FROM_DATA 175
200#define EC_F_EC_GROUP_PRECOMPUTE_MULT 142 439#define EC_F_EC_GROUP_PRECOMPUTE_MULT 142
440#define EC_F_EC_GROUP_SET_CURVE_GF2M 176
201#define EC_F_EC_GROUP_SET_CURVE_GFP 109 441#define EC_F_EC_GROUP_SET_CURVE_GFP 109
202#define EC_F_EC_GROUP_SET_EXTRA_DATA 110 442#define EC_F_EC_GROUP_SET_EXTRA_DATA 110
203#define EC_F_EC_GROUP_SET_GENERATOR 111 443#define EC_F_EC_GROUP_SET_GENERATOR 111
444#define EC_F_EC_KEY_CHECK_KEY 177
445#define EC_F_EC_KEY_COPY 178
446#define EC_F_EC_KEY_GENERATE_KEY 179
447#define EC_F_EC_KEY_NEW 182
448#define EC_F_EC_KEY_PRINT 180
449#define EC_F_EC_KEY_PRINT_FP 181
204#define EC_F_EC_POINTS_MAKE_AFFINE 136 450#define EC_F_EC_POINTS_MAKE_AFFINE 136
205#define EC_F_EC_POINTS_MUL 138 451#define EC_F_EC_POINTS_MUL 138
206#define EC_F_EC_POINT_ADD 112 452#define EC_F_EC_POINT_ADD 112
207#define EC_F_EC_POINT_CMP 113 453#define EC_F_EC_POINT_CMP 113
208#define EC_F_EC_POINT_COPY 114 454#define EC_F_EC_POINT_COPY 114
209#define EC_F_EC_POINT_DBL 115 455#define EC_F_EC_POINT_DBL 115
456#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 183
210#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116 457#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116
211#define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117 458#define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117
459#define EC_F_EC_POINT_INVERT 210
212#define EC_F_EC_POINT_IS_AT_INFINITY 118 460#define EC_F_EC_POINT_IS_AT_INFINITY 118
213#define EC_F_EC_POINT_IS_ON_CURVE 119 461#define EC_F_EC_POINT_IS_ON_CURVE 119
214#define EC_F_EC_POINT_MAKE_AFFINE 120 462#define EC_F_EC_POINT_MAKE_AFFINE 120
463#define EC_F_EC_POINT_MUL 184
215#define EC_F_EC_POINT_NEW 121 464#define EC_F_EC_POINT_NEW 121
216#define EC_F_EC_POINT_OCT2POINT 122 465#define EC_F_EC_POINT_OCT2POINT 122
217#define EC_F_EC_POINT_POINT2OCT 123 466#define EC_F_EC_POINT_POINT2OCT 123
467#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 185
218#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124 468#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124
469#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 186
219#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125 470#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125
220#define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126 471#define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126
221#define EC_F_EC_POINT_SET_TO_INFINITY 127 472#define EC_F_EC_POINT_SET_TO_INFINITY 127
222#define EC_F_GFP_MONT_GROUP_SET_CURVE_GFP 135 473#define EC_F_EC_PRE_COMP_DUP 207
474#define EC_F_EC_PRE_COMP_NEW 196
475#define EC_F_EC_WNAF_MUL 187
476#define EC_F_EC_WNAF_PRECOMPUTE_MULT 188
477#define EC_F_I2D_ECPARAMETERS 190
478#define EC_F_I2D_ECPKPARAMETERS 191
479#define EC_F_I2D_ECPRIVATEKEY 192
480#define EC_F_I2O_ECPUBLICKEY 151
481#define EC_F_O2I_ECPUBLICKEY 152
223 482
224/* Reason codes. */ 483/* Reason codes. */
484#define EC_R_ASN1_ERROR 115
485#define EC_R_ASN1_UNKNOWN_FIELD 116
225#define EC_R_BUFFER_TOO_SMALL 100 486#define EC_R_BUFFER_TOO_SMALL 100
487#define EC_R_D2I_ECPKPARAMETERS_FAILURE 117
488#define EC_R_DISCRIMINANT_IS_ZERO 118
489#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119
490#define EC_R_FIELD_TOO_LARGE 138
491#define EC_R_GROUP2PKPARAMETERS_FAILURE 120
492#define EC_R_I2D_ECPKPARAMETERS_FAILURE 121
226#define EC_R_INCOMPATIBLE_OBJECTS 101 493#define EC_R_INCOMPATIBLE_OBJECTS 101
227#define EC_R_INVALID_ARGUMENT 112 494#define EC_R_INVALID_ARGUMENT 112
228#define EC_R_INVALID_COMPRESSED_POINT 110 495#define EC_R_INVALID_COMPRESSED_POINT 110
@@ -230,12 +497,28 @@ void ERR_load_EC_strings(void);
230#define EC_R_INVALID_ENCODING 102 497#define EC_R_INVALID_ENCODING 102
231#define EC_R_INVALID_FIELD 103 498#define EC_R_INVALID_FIELD 103
232#define EC_R_INVALID_FORM 104 499#define EC_R_INVALID_FORM 104
500#define EC_R_INVALID_GROUP_ORDER 122
501#define EC_R_INVALID_PENTANOMIAL_BASIS 132
502#define EC_R_INVALID_PRIVATE_KEY 123
503#define EC_R_INVALID_TRINOMIAL_BASIS 137
504#define EC_R_MISSING_PARAMETERS 124
505#define EC_R_MISSING_PRIVATE_KEY 125
506#define EC_R_NOT_A_NIST_PRIME 135
507#define EC_R_NOT_A_SUPPORTED_NIST_PRIME 136
508#define EC_R_NOT_IMPLEMENTED 126
233#define EC_R_NOT_INITIALIZED 111 509#define EC_R_NOT_INITIALIZED 111
510#define EC_R_NO_FIELD_MOD 133
511#define EC_R_PASSED_NULL_PARAMETER 134
512#define EC_R_PKPARAMETERS2GROUP_FAILURE 127
234#define EC_R_POINT_AT_INFINITY 106 513#define EC_R_POINT_AT_INFINITY 106
235#define EC_R_POINT_IS_NOT_ON_CURVE 107 514#define EC_R_POINT_IS_NOT_ON_CURVE 107
236#define EC_R_SLOT_FULL 108 515#define EC_R_SLOT_FULL 108
237#define EC_R_UNDEFINED_GENERATOR 113 516#define EC_R_UNDEFINED_GENERATOR 113
517#define EC_R_UNDEFINED_ORDER 128
518#define EC_R_UNKNOWN_GROUP 129
238#define EC_R_UNKNOWN_ORDER 114 519#define EC_R_UNKNOWN_ORDER 114
520#define EC_R_UNSUPPORTED_FIELD 131
521#define EC_R_WRONG_ORDER 130
239 522
240#ifdef __cplusplus 523#ifdef __cplusplus
241} 524}
diff --git a/src/lib/libcrypto/ec/ec_cvt.c b/src/lib/libcrypto/ec/ec_cvt.c
index 45b0ec33a0..d45640bab9 100644
--- a/src/lib/libcrypto/ec/ec_cvt.c
+++ b/src/lib/libcrypto/ec/ec_cvt.c
@@ -1,6 +1,9 @@
1/* crypto/ec/ec_cvt.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,7 +55,21 @@
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 75
@@ -60,11 +77,8 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM
60 { 77 {
61 const EC_METHOD *meth; 78 const EC_METHOD *meth;
62 EC_GROUP *ret; 79 EC_GROUP *ret;
63 80
64 /* Finally, this will use EC_GFp_nist_method if 'p' is a special 81 meth = EC_GFp_nist_method();
65 * prime with optimized modular arithmetics (for NIST curves)
66 */
67 meth = EC_GFp_mont_method();
68 82
69 ret = EC_GROUP_new(meth); 83 ret = EC_GROUP_new(meth);
70 if (ret == NULL) 84 if (ret == NULL)
@@ -72,6 +86,56 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM
72 86
73 if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx)) 87 if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx))
74 { 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;
123 }
124
125
126EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
127 {
128 const EC_METHOD *meth;
129 EC_GROUP *ret;
130
131 meth = EC_GF2m_simple_method();
132
133 ret = EC_GROUP_new(meth);
134 if (ret == NULL)
135 return NULL;
136
137 if (!EC_GROUP_set_curve_GF2m(ret, p, a, b, ctx))
138 {
75 EC_GROUP_clear_free(ret); 139 EC_GROUP_clear_free(ret);
76 return NULL; 140 return NULL;
77 } 141 }
diff --git a/src/lib/libcrypto/ec/ec_err.c b/src/lib/libcrypto/ec/ec_err.c
index 5b70f94382..d04c895560 100644
--- a/src/lib/libcrypto/ec/ec_err.c
+++ b/src/lib/libcrypto/ec/ec_err.c
@@ -1,6 +1,6 @@
1/* crypto/ec/ec_err.c */ 1/* crypto/ec/ec_err.c */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
@@ -71,54 +71,127 @@
71static ERR_STRING_DATA EC_str_functs[]= 71static ERR_STRING_DATA EC_str_functs[]=
72 { 72 {
73{ERR_FUNC(EC_F_COMPUTE_WNAF), "COMPUTE_WNAF"}, 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_ECPARAMETERS_PRINT), "ECParameters_print"},
78{ERR_FUNC(EC_F_ECPARAMETERS_PRINT_FP), "ECParameters_print_fp"},
79{ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT), "ECPKParameters_print"},
80{ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT_FP), "ECPKParameters_print_fp"},
81{ERR_FUNC(EC_F_ECP_NIST_MOD_192), "ECP_NIST_MOD_192"},
82{ERR_FUNC(EC_F_ECP_NIST_MOD_224), "ECP_NIST_MOD_224"},
83{ERR_FUNC(EC_F_ECP_NIST_MOD_256), "ECP_NIST_MOD_256"},
84{ERR_FUNC(EC_F_ECP_NIST_MOD_521), "ECP_NIST_MOD_521"},
85{ERR_FUNC(EC_F_EC_ASN1_GROUP2CURVE), "EC_ASN1_GROUP2CURVE"},
86{ERR_FUNC(EC_F_EC_ASN1_GROUP2FIELDID), "EC_ASN1_GROUP2FIELDID"},
87{ERR_FUNC(EC_F_EC_ASN1_GROUP2PARAMETERS), "EC_ASN1_GROUP2PARAMETERS"},
88{ERR_FUNC(EC_F_EC_ASN1_GROUP2PKPARAMETERS), "EC_ASN1_GROUP2PKPARAMETERS"},
89{ERR_FUNC(EC_F_EC_ASN1_PARAMETERS2GROUP), "EC_ASN1_PARAMETERS2GROUP"},
90{ERR_FUNC(EC_F_EC_ASN1_PKPARAMETERS2GROUP), "EC_ASN1_PKPARAMETERS2GROUP"},
91{ERR_FUNC(EC_F_EC_EX_DATA_SET_DATA), "EC_EX_DATA_set_data"},
92{ERR_FUNC(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY), "EC_GF2M_MONTGOMERY_POINT_MULTIPLY"},
93{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT), "ec_GF2m_simple_group_check_discriminant"},
94{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE), "ec_GF2m_simple_group_set_curve"},
95{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_OCT2POINT), "ec_GF2m_simple_oct2point"},
96{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT2OCT), "ec_GF2m_simple_point2oct"},
97{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES), "ec_GF2m_simple_point_get_affine_coordinates"},
98{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES), "ec_GF2m_simple_point_set_affine_coordinates"},
99{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES), "ec_GF2m_simple_set_compressed_coordinates"},
74{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_DECODE), "ec_GFp_mont_field_decode"}, 100{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_DECODE), "ec_GFp_mont_field_decode"},
75{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_ENCODE), "ec_GFp_mont_field_encode"}, 101{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_ENCODE), "ec_GFp_mont_field_encode"},
76{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_MUL), "ec_GFp_mont_field_mul"}, 102{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_MUL), "ec_GFp_mont_field_mul"},
103{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE), "ec_GFp_mont_field_set_to_one"},
77{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"}, 104{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"},
78{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP), "ec_GFp_simple_group_set_curve_GFp"}, 105{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE), "ec_GFp_mont_group_set_curve"},
79{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR), "ec_GFp_simple_group_set_generator"}, 106{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP), "EC_GFP_MONT_GROUP_SET_CURVE_GFP"},
107{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL), "ec_GFp_nist_field_mul"},
108{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"},
109{ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE), "ec_GFp_nist_group_set_curve"},
110{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT), "ec_GFp_simple_group_check_discriminant"},
111{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE), "ec_GFp_simple_group_set_curve"},
112{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP), "EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP"},
113{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR), "EC_GFP_SIMPLE_GROUP_SET_GENERATOR"},
80{ERR_FUNC(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE), "ec_GFp_simple_make_affine"}, 114{ERR_FUNC(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE), "ec_GFp_simple_make_affine"},
81{ERR_FUNC(EC_F_EC_GFP_SIMPLE_OCT2POINT), "ec_GFp_simple_oct2point"}, 115{ERR_FUNC(EC_F_EC_GFP_SIMPLE_OCT2POINT), "ec_GFp_simple_oct2point"},
82{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT2OCT), "ec_GFp_simple_point2oct"}, 116{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT2OCT), "ec_GFp_simple_point2oct"},
83{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE), "ec_GFp_simple_points_make_affine"}, 117{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE), "ec_GFp_simple_points_make_affine"},
84{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP), "ec_GFp_simple_point_get_affine_coordinates_GFp"}, 118{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES), "ec_GFp_simple_point_get_affine_coordinates"},
85{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP), "ec_GFp_simple_point_set_affine_coordinates_GFp"}, 119{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP), "EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP"},
86{ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP), "ec_GFp_simple_set_compressed_coordinates_GFp"}, 120{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES), "ec_GFp_simple_point_set_affine_coordinates"},
121{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP), "EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP"},
122{ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES), "ec_GFp_simple_set_compressed_coordinates"},
123{ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP), "EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP"},
124{ERR_FUNC(EC_F_EC_GROUP_CHECK), "EC_GROUP_check"},
125{ERR_FUNC(EC_F_EC_GROUP_CHECK_DISCRIMINANT), "EC_GROUP_check_discriminant"},
87{ERR_FUNC(EC_F_EC_GROUP_COPY), "EC_GROUP_copy"}, 126{ERR_FUNC(EC_F_EC_GROUP_COPY), "EC_GROUP_copy"},
88{ERR_FUNC(EC_F_EC_GROUP_GET0_GENERATOR), "EC_GROUP_get0_generator"}, 127{ERR_FUNC(EC_F_EC_GROUP_GET0_GENERATOR), "EC_GROUP_get0_generator"},
89{ERR_FUNC(EC_F_EC_GROUP_GET_COFACTOR), "EC_GROUP_get_cofactor"}, 128{ERR_FUNC(EC_F_EC_GROUP_GET_COFACTOR), "EC_GROUP_get_cofactor"},
129{ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GF2M), "EC_GROUP_get_curve_GF2m"},
90{ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GFP), "EC_GROUP_get_curve_GFp"}, 130{ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GFP), "EC_GROUP_get_curve_GFp"},
131{ERR_FUNC(EC_F_EC_GROUP_GET_DEGREE), "EC_GROUP_get_degree"},
91{ERR_FUNC(EC_F_EC_GROUP_GET_ORDER), "EC_GROUP_get_order"}, 132{ERR_FUNC(EC_F_EC_GROUP_GET_ORDER), "EC_GROUP_get_order"},
133{ERR_FUNC(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS), "EC_GROUP_get_pentanomial_basis"},
134{ERR_FUNC(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS), "EC_GROUP_get_trinomial_basis"},
92{ERR_FUNC(EC_F_EC_GROUP_NEW), "EC_GROUP_new"}, 135{ERR_FUNC(EC_F_EC_GROUP_NEW), "EC_GROUP_new"},
136{ERR_FUNC(EC_F_EC_GROUP_NEW_BY_CURVE_NAME), "EC_GROUP_new_by_curve_name"},
137{ERR_FUNC(EC_F_EC_GROUP_NEW_FROM_DATA), "EC_GROUP_NEW_FROM_DATA"},
93{ERR_FUNC(EC_F_EC_GROUP_PRECOMPUTE_MULT), "EC_GROUP_precompute_mult"}, 138{ERR_FUNC(EC_F_EC_GROUP_PRECOMPUTE_MULT), "EC_GROUP_precompute_mult"},
139{ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GF2M), "EC_GROUP_set_curve_GF2m"},
94{ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GFP), "EC_GROUP_set_curve_GFp"}, 140{ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GFP), "EC_GROUP_set_curve_GFp"},
95{ERR_FUNC(EC_F_EC_GROUP_SET_EXTRA_DATA), "EC_GROUP_set_extra_data"}, 141{ERR_FUNC(EC_F_EC_GROUP_SET_EXTRA_DATA), "EC_GROUP_SET_EXTRA_DATA"},
96{ERR_FUNC(EC_F_EC_GROUP_SET_GENERATOR), "EC_GROUP_set_generator"}, 142{ERR_FUNC(EC_F_EC_GROUP_SET_GENERATOR), "EC_GROUP_set_generator"},
143{ERR_FUNC(EC_F_EC_KEY_CHECK_KEY), "EC_KEY_check_key"},
144{ERR_FUNC(EC_F_EC_KEY_COPY), "EC_KEY_copy"},
145{ERR_FUNC(EC_F_EC_KEY_GENERATE_KEY), "EC_KEY_generate_key"},
146{ERR_FUNC(EC_F_EC_KEY_NEW), "EC_KEY_new"},
147{ERR_FUNC(EC_F_EC_KEY_PRINT), "EC_KEY_print"},
148{ERR_FUNC(EC_F_EC_KEY_PRINT_FP), "EC_KEY_print_fp"},
97{ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"}, 149{ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"},
98{ERR_FUNC(EC_F_EC_POINTS_MUL), "EC_POINTs_mul"}, 150{ERR_FUNC(EC_F_EC_POINTS_MUL), "EC_POINTs_mul"},
99{ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"}, 151{ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"},
100{ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"}, 152{ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"},
101{ERR_FUNC(EC_F_EC_POINT_COPY), "EC_POINT_copy"}, 153{ERR_FUNC(EC_F_EC_POINT_COPY), "EC_POINT_copy"},
102{ERR_FUNC(EC_F_EC_POINT_DBL), "EC_POINT_dbl"}, 154{ERR_FUNC(EC_F_EC_POINT_DBL), "EC_POINT_dbl"},
155{ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M), "EC_POINT_get_affine_coordinates_GF2m"},
103{ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP), "EC_POINT_get_affine_coordinates_GFp"}, 156{ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP), "EC_POINT_get_affine_coordinates_GFp"},
104{ERR_FUNC(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP), "EC_POINT_get_Jprojective_coordinates_GFp"}, 157{ERR_FUNC(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP), "EC_POINT_get_Jprojective_coordinates_GFp"},
158{ERR_FUNC(EC_F_EC_POINT_INVERT), "EC_POINT_invert"},
105{ERR_FUNC(EC_F_EC_POINT_IS_AT_INFINITY), "EC_POINT_is_at_infinity"}, 159{ERR_FUNC(EC_F_EC_POINT_IS_AT_INFINITY), "EC_POINT_is_at_infinity"},
106{ERR_FUNC(EC_F_EC_POINT_IS_ON_CURVE), "EC_POINT_is_on_curve"}, 160{ERR_FUNC(EC_F_EC_POINT_IS_ON_CURVE), "EC_POINT_is_on_curve"},
107{ERR_FUNC(EC_F_EC_POINT_MAKE_AFFINE), "EC_POINT_make_affine"}, 161{ERR_FUNC(EC_F_EC_POINT_MAKE_AFFINE), "EC_POINT_make_affine"},
162{ERR_FUNC(EC_F_EC_POINT_MUL), "EC_POINT_mul"},
108{ERR_FUNC(EC_F_EC_POINT_NEW), "EC_POINT_new"}, 163{ERR_FUNC(EC_F_EC_POINT_NEW), "EC_POINT_new"},
109{ERR_FUNC(EC_F_EC_POINT_OCT2POINT), "EC_POINT_oct2point"}, 164{ERR_FUNC(EC_F_EC_POINT_OCT2POINT), "EC_POINT_oct2point"},
110{ERR_FUNC(EC_F_EC_POINT_POINT2OCT), "EC_POINT_point2oct"}, 165{ERR_FUNC(EC_F_EC_POINT_POINT2OCT), "EC_POINT_point2oct"},
166{ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M), "EC_POINT_set_affine_coordinates_GF2m"},
111{ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP), "EC_POINT_set_affine_coordinates_GFp"}, 167{ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP), "EC_POINT_set_affine_coordinates_GFp"},
168{ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M), "EC_POINT_set_compressed_coordinates_GF2m"},
112{ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP), "EC_POINT_set_compressed_coordinates_GFp"}, 169{ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP), "EC_POINT_set_compressed_coordinates_GFp"},
113{ERR_FUNC(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP), "EC_POINT_set_Jprojective_coordinates_GFp"}, 170{ERR_FUNC(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP), "EC_POINT_set_Jprojective_coordinates_GFp"},
114{ERR_FUNC(EC_F_EC_POINT_SET_TO_INFINITY), "EC_POINT_set_to_infinity"}, 171{ERR_FUNC(EC_F_EC_POINT_SET_TO_INFINITY), "EC_POINT_set_to_infinity"},
115{ERR_FUNC(EC_F_GFP_MONT_GROUP_SET_CURVE_GFP), "GFP_MONT_GROUP_SET_CURVE_GFP"}, 172{ERR_FUNC(EC_F_EC_PRE_COMP_DUP), "EC_PRE_COMP_DUP"},
173{ERR_FUNC(EC_F_EC_PRE_COMP_NEW), "EC_PRE_COMP_NEW"},
174{ERR_FUNC(EC_F_EC_WNAF_MUL), "ec_wNAF_mul"},
175{ERR_FUNC(EC_F_EC_WNAF_PRECOMPUTE_MULT), "ec_wNAF_precompute_mult"},
176{ERR_FUNC(EC_F_I2D_ECPARAMETERS), "i2d_ECParameters"},
177{ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"},
178{ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"},
179{ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"},
180{ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"},
116{0,NULL} 181{0,NULL}
117 }; 182 };
118 183
119static ERR_STRING_DATA EC_str_reasons[]= 184static ERR_STRING_DATA EC_str_reasons[]=
120 { 185 {
186{ERR_REASON(EC_R_ASN1_ERROR) ,"asn1 error"},
187{ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD) ,"asn1 unknown field"},
121{ERR_REASON(EC_R_BUFFER_TOO_SMALL) ,"buffer too small"}, 188{ERR_REASON(EC_R_BUFFER_TOO_SMALL) ,"buffer too small"},
189{ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE),"d2i ecpkparameters failure"},
190{ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO) ,"discriminant is zero"},
191{ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),"ec group new by name failure"},
192{ERR_REASON(EC_R_FIELD_TOO_LARGE) ,"field too large"},
193{ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE),"group2pkparameters failure"},
194{ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE),"i2d ecpkparameters failure"},
122{ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS) ,"incompatible objects"}, 195{ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS) ,"incompatible objects"},
123{ERR_REASON(EC_R_INVALID_ARGUMENT) ,"invalid argument"}, 196{ERR_REASON(EC_R_INVALID_ARGUMENT) ,"invalid argument"},
124{ERR_REASON(EC_R_INVALID_COMPRESSED_POINT),"invalid compressed point"}, 197{ERR_REASON(EC_R_INVALID_COMPRESSED_POINT),"invalid compressed point"},
@@ -126,12 +199,28 @@ static ERR_STRING_DATA EC_str_reasons[]=
126{ERR_REASON(EC_R_INVALID_ENCODING) ,"invalid encoding"}, 199{ERR_REASON(EC_R_INVALID_ENCODING) ,"invalid encoding"},
127{ERR_REASON(EC_R_INVALID_FIELD) ,"invalid field"}, 200{ERR_REASON(EC_R_INVALID_FIELD) ,"invalid field"},
128{ERR_REASON(EC_R_INVALID_FORM) ,"invalid form"}, 201{ERR_REASON(EC_R_INVALID_FORM) ,"invalid form"},
202{ERR_REASON(EC_R_INVALID_GROUP_ORDER) ,"invalid group order"},
203{ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS),"invalid pentanomial basis"},
204{ERR_REASON(EC_R_INVALID_PRIVATE_KEY) ,"invalid private key"},
205{ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS),"invalid trinomial basis"},
206{ERR_REASON(EC_R_MISSING_PARAMETERS) ,"missing parameters"},
207{ERR_REASON(EC_R_MISSING_PRIVATE_KEY) ,"missing private key"},
208{ERR_REASON(EC_R_NOT_A_NIST_PRIME) ,"not a NIST prime"},
209{ERR_REASON(EC_R_NOT_A_SUPPORTED_NIST_PRIME),"not a supported NIST prime"},
210{ERR_REASON(EC_R_NOT_IMPLEMENTED) ,"not implemented"},
129{ERR_REASON(EC_R_NOT_INITIALIZED) ,"not initialized"}, 211{ERR_REASON(EC_R_NOT_INITIALIZED) ,"not initialized"},
212{ERR_REASON(EC_R_NO_FIELD_MOD) ,"no field mod"},
213{ERR_REASON(EC_R_PASSED_NULL_PARAMETER) ,"passed null parameter"},
214{ERR_REASON(EC_R_PKPARAMETERS2GROUP_FAILURE),"pkparameters2group failure"},
130{ERR_REASON(EC_R_POINT_AT_INFINITY) ,"point at infinity"}, 215{ERR_REASON(EC_R_POINT_AT_INFINITY) ,"point at infinity"},
131{ERR_REASON(EC_R_POINT_IS_NOT_ON_CURVE) ,"point is not on curve"}, 216{ERR_REASON(EC_R_POINT_IS_NOT_ON_CURVE) ,"point is not on curve"},
132{ERR_REASON(EC_R_SLOT_FULL) ,"slot full"}, 217{ERR_REASON(EC_R_SLOT_FULL) ,"slot full"},
133{ERR_REASON(EC_R_UNDEFINED_GENERATOR) ,"undefined generator"}, 218{ERR_REASON(EC_R_UNDEFINED_GENERATOR) ,"undefined generator"},
219{ERR_REASON(EC_R_UNDEFINED_ORDER) ,"undefined order"},
220{ERR_REASON(EC_R_UNKNOWN_GROUP) ,"unknown group"},
134{ERR_REASON(EC_R_UNKNOWN_ORDER) ,"unknown order"}, 221{ERR_REASON(EC_R_UNKNOWN_ORDER) ,"unknown order"},
222{ERR_REASON(EC_R_UNSUPPORTED_FIELD) ,"unsupported field"},
223{ERR_REASON(EC_R_WRONG_ORDER) ,"wrong order"},
135{0,NULL} 224{0,NULL}
136 }; 225 };
137 226
@@ -139,15 +228,12 @@ static ERR_STRING_DATA EC_str_reasons[]=
139 228
140void ERR_load_EC_strings(void) 229void ERR_load_EC_strings(void)
141 { 230 {
142 static int init=1; 231#ifndef OPENSSL_NO_ERR
143 232
144 if (init) 233 if (ERR_func_error_string(EC_str_functs[0].error) == NULL)
145 { 234 {
146 init=0;
147#ifndef OPENSSL_NO_ERR
148 ERR_load_strings(0,EC_str_functs); 235 ERR_load_strings(0,EC_str_functs);
149 ERR_load_strings(0,EC_str_reasons); 236 ERR_load_strings(0,EC_str_reasons);
150#endif
151
152 } 237 }
238#endif
153 } 239 }
diff --git a/src/lib/libcrypto/ec/ec_lcl.h b/src/lib/libcrypto/ec/ec_lcl.h
index cc4cf27755..fdd7aa2755 100644
--- a/src/lib/libcrypto/ec/ec_lcl.h
+++ b/src/lib/libcrypto/ec/ec_lcl.h
@@ -1,6 +1,9 @@
1/* crypto/ec/ec_lcl.h */ 1/* crypto/ec/ec_lcl.h */
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-2003 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,35 +55,56 @@
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
56 72
57#include <stdlib.h> 73#include <stdlib.h>
58 74
75#include <openssl/obj_mac.h>
59#include <openssl/ec.h> 76#include <openssl/ec.h>
77#include <openssl/bn.h>
60 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
61 84
62/* Structure details are not part of the exported interface, 85/* Structure details are not part of the exported interface,
63 * so all this may change in future versions. */ 86 * so all this may change in future versions. */
64 87
65struct ec_method_st { 88struct ec_method_st {
89 /* used by EC_METHOD_get_field_type: */
90 int field_type; /* a NID */
91
66 /* used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, EC_GROUP_copy: */ 92 /* used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, EC_GROUP_copy: */
67 int (*group_init)(EC_GROUP *); 93 int (*group_init)(EC_GROUP *);
68 void (*group_finish)(EC_GROUP *); 94 void (*group_finish)(EC_GROUP *);
69 void (*group_clear_finish)(EC_GROUP *); 95 void (*group_clear_finish)(EC_GROUP *);
70 int (*group_copy)(EC_GROUP *, const EC_GROUP *); 96 int (*group_copy)(EC_GROUP *, const EC_GROUP *);
71 97
72 /* used by EC_GROUP_set_curve_GFp and EC_GROUP_get_curve_GFp: */ 98 /* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */
73 int (*group_set_curve_GFp)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); 99 /* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */
74 int (*group_get_curve_GFp)(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *); 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 *);
75 102
76 /* used by EC_GROUP_set_generator, EC_GROUP_get0_generator, 103 /* used by EC_GROUP_get_degree: */
77 * EC_GROUP_get_order, EC_GROUP_get_cofactor: 104 int (*group_get_degree)(const EC_GROUP *);
78 */ 105
79 int (*group_set_generator)(EC_GROUP *, const EC_POINT *generator, 106 /* used by EC_GROUP_check: */
80 const BIGNUM *order, const BIGNUM *cofactor); 107 int (*group_check_discriminant)(const EC_GROUP *, BN_CTX *);
81 EC_POINT *(*group_get0_generator)(const EC_GROUP *);
82 int (*group_get_order)(const EC_GROUP *, BIGNUM *order, BN_CTX *);
83 int (*group_get_cofactor)(const EC_GROUP *, BIGNUM *cofactor, BN_CTX *);
84 108
85 /* used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_free, EC_POINT_copy: */ 109 /* used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_free, EC_POINT_copy: */
86 int (*point_init)(EC_POINT *); 110 int (*point_init)(EC_POINT *);
@@ -89,20 +113,22 @@ struct ec_method_st {
89 int (*point_copy)(EC_POINT *, const EC_POINT *); 113 int (*point_copy)(EC_POINT *, const EC_POINT *);
90 114
91 /* used by EC_POINT_set_to_infinity, 115 /* used by EC_POINT_set_to_infinity,
92 * EC_POINT_set_Jprojective_coordinates_GFp, EC_POINT_get_Jprojective_coordinates_GFp, 116 * EC_POINT_set_Jprojective_coordinates_GFp,
93 * EC_POINT_set_affine_coordinates_GFp, EC_POINT_get_affine_coordinates_GFp, 117 * EC_POINT_get_Jprojective_coordinates_GFp,
94 * EC_POINT_set_compressed_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:
95 */ 121 */
96 int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *); 122 int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *);
97 int (*point_set_Jprojective_coordinates_GFp)(const EC_GROUP *, EC_POINT *, 123 int (*point_set_Jprojective_coordinates_GFp)(const EC_GROUP *, EC_POINT *,
98 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *); 124 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
99 int (*point_get_Jprojective_coordinates_GFp)(const EC_GROUP *, const EC_POINT *, 125 int (*point_get_Jprojective_coordinates_GFp)(const EC_GROUP *, const EC_POINT *,
100 BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *); 126 BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *);
101 int (*point_set_affine_coordinates_GFp)(const EC_GROUP *, EC_POINT *, 127 int (*point_set_affine_coordinates)(const EC_GROUP *, EC_POINT *,
102 const BIGNUM *x, const BIGNUM *y, BN_CTX *); 128 const BIGNUM *x, const BIGNUM *y, BN_CTX *);
103 int (*point_get_affine_coordinates_GFp)(const EC_GROUP *, const EC_POINT *, 129 int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_POINT *,
104 BIGNUM *x, BIGNUM *y, BN_CTX *); 130 BIGNUM *x, BIGNUM *y, BN_CTX *);
105 int (*point_set_compressed_coordinates_GFp)(const EC_GROUP *, EC_POINT *, 131 int (*point_set_compressed_coordinates)(const EC_GROUP *, EC_POINT *,
106 const BIGNUM *x, int y_bit, BN_CTX *); 132 const BIGNUM *x, int y_bit, BN_CTX *);
107 133
108 /* used by EC_POINT_point2oct, EC_POINT_oct2point: */ 134 /* used by EC_POINT_point2oct, EC_POINT_oct2point: */
@@ -125,34 +151,65 @@ struct ec_method_st {
125 int (*make_affine)(const EC_GROUP *, EC_POINT *, BN_CTX *); 151 int (*make_affine)(const EC_GROUP *, EC_POINT *, BN_CTX *);
126 int (*points_make_affine)(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *); 152 int (*points_make_affine)(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
127 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
128 161
129 /* internal functions */ 162 /* internal functions */
130 163
131 /* 'field_mul' and 'field_sqr' can be used by 'add' and 'dbl' so that 164 /* 'field_mul', 'field_sqr', and 'field_div' can be used by 'add' and 'dbl' so that
132 * the same implementations of point operations can be used with different 165 * the same implementations of point operations can be used with different
133 * optimized implementations of expensive field operations: */ 166 * optimized implementations of expensive field operations: */
134 int (*field_mul)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); 167 int (*field_mul)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
135 int (*field_sqr)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, 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 *);
136 170
137 int (*field_encode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. to Montgomery */ 171 int (*field_encode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. to Montgomery */
138 int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. from Montgomery */ 172 int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. from Montgomery */
139 int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *); 173 int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *);
140} /* EC_METHOD */; 174} /* EC_METHOD */;
141 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 */
142 183
143struct ec_group_st { 184struct ec_group_st {
144 const EC_METHOD *meth; 185 const EC_METHOD *meth;
145 186
146 void *extra_data; 187 EC_POINT *generator; /* optional */
147 void *(*extra_data_dup_func)(void *); 188 BIGNUM order, cofactor;
148 void (*extra_data_free_func)(void *); 189
149 void (*extra_data_clear_free_func)(void *); 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;
150 196
151 /* All members except 'meth' and 'extra_data...' are handled by 197 EC_EXTRA_DATA *extra_data; /* linked list */
152 * the method functions, even if they appear generic */ 198
199 /* The following members are handled by the method functions,
200 * even if they appear generic */
153 201
154 BIGNUM field; /* Field specification. 202 BIGNUM field; /* Field specification.
155 * For curves over GF(p), this is the modulus. */ 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 unsigned int poly[5]; /* 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 */
156 213
157 BIGNUM a, b; /* Curve coefficients. 214 BIGNUM a, b; /* Curve coefficients.
158 * (Here the assumption is that BIGNUMs can be used 215 * (Here the assumption is that BIGNUMs can be used
@@ -160,29 +217,49 @@ struct ec_group_st {
160 * For characteristic > 3, the curve is defined 217 * For characteristic > 3, the curve is defined
161 * by a Weierstrass equation of the form 218 * by a Weierstrass equation of the form
162 * y^2 = x^3 + a*x + b. 219 * y^2 = x^3 + a*x + b.
220 * For characteristic 2, the curve is defined by
221 * an equation of the form
222 * y^2 + x*y = x^3 + a*x^2 + b.
163 */ 223 */
164 int a_is_minus3; /* enable optimized point arithmetics for special case */
165 224
166 EC_POINT *generator; /* optional */ 225 int a_is_minus3; /* enable optimized point arithmetics for special case */
167 BIGNUM order, cofactor;
168 226
169 void *field_data1; /* method-specific (e.g., Montgomery structure) */ 227 void *field_data1; /* method-specific (e.g., Montgomery structure) */
170 void *field_data2; /* method-specific */ 228 void *field_data2; /* method-specific */
229 int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); /* method-specific */
171} /* EC_GROUP */; 230} /* EC_GROUP */;
172 231
232struct ec_key_st {
233 int version;
234
235 EC_GROUP *group;
236
237 EC_POINT *pub_key;
238 BIGNUM *priv_key;
239
240 unsigned int enc_flag;
241 point_conversion_form_t conv_form;
173 242
174/* Basically a 'mixin' for extra data, but available for EC_GROUPs only 243 int references;
244
245 EC_EXTRA_DATA *method_data;
246} /* EC_KEY */;
247
248/* Basically a 'mixin' for extra data, but available for EC_GROUPs/EC_KEYs only
175 * (with visibility limited to 'package' level for now). 249 * (with visibility limited to 'package' level for now).
176 * We use the function pointers as index for retrieval; this obviates 250 * We use the function pointers as index for retrieval; this obviates
177 * global ex_data-style index tables. 251 * global ex_data-style index tables.
178 * (Currently, we have one slot only, but is is possible to extend this 252 */
179 * if necessary.) */ 253int EC_EX_DATA_set_data(EC_EXTRA_DATA **, void *data,
180int EC_GROUP_set_extra_data(EC_GROUP *, void *extra_data, void *(*extra_data_dup_func)(void *), 254 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
181 void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *)); 255void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *,
182void *EC_GROUP_get_extra_data(const EC_GROUP *, void *(*extra_data_dup_func)(void *), 256 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
183 void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *)); 257void EC_EX_DATA_free_data(EC_EXTRA_DATA **,
184void EC_GROUP_free_extra_data(EC_GROUP *); 258 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
185void EC_GROUP_clear_free_extra_data(EC_GROUP *); 259void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **,
260 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
261void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **);
262void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **);
186 263
187 264
188 265
@@ -201,18 +278,23 @@ struct ec_point_st {
201 278
202 279
203 280
281/* method functions in ec_mult.c
282 * (ec_lib.c uses these as defaults if group->method->mul is 0) */
283int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
284 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
285int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *);
286int ec_wNAF_have_precompute_mult(const EC_GROUP *group);
287
288
204/* method functions in ecp_smpl.c */ 289/* method functions in ecp_smpl.c */
205int ec_GFp_simple_group_init(EC_GROUP *); 290int ec_GFp_simple_group_init(EC_GROUP *);
206void ec_GFp_simple_group_finish(EC_GROUP *); 291void ec_GFp_simple_group_finish(EC_GROUP *);
207void ec_GFp_simple_group_clear_finish(EC_GROUP *); 292void ec_GFp_simple_group_clear_finish(EC_GROUP *);
208int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *); 293int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);
209int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); 294int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
210int ec_GFp_simple_group_get_curve_GFp(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *); 295int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
211int ec_GFp_simple_group_set_generator(EC_GROUP *, const EC_POINT *generator, 296int ec_GFp_simple_group_get_degree(const EC_GROUP *);
212 const BIGNUM *order, const BIGNUM *cofactor); 297int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
213EC_POINT *ec_GFp_simple_group_get0_generator(const EC_GROUP *);
214int ec_GFp_simple_group_get_order(const EC_GROUP *, BIGNUM *order, BN_CTX *);
215int ec_GFp_simple_group_get_cofactor(const EC_GROUP *, BIGNUM *cofactor, BN_CTX *);
216int ec_GFp_simple_point_init(EC_POINT *); 298int ec_GFp_simple_point_init(EC_POINT *);
217void ec_GFp_simple_point_finish(EC_POINT *); 299void ec_GFp_simple_point_finish(EC_POINT *);
218void ec_GFp_simple_point_clear_finish(EC_POINT *); 300void ec_GFp_simple_point_clear_finish(EC_POINT *);
@@ -222,11 +304,11 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *,
222 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *); 304 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
223int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, const EC_POINT *, 305int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *, const EC_POINT *,
224 BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *); 306 BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *);
225int ec_GFp_simple_point_set_affine_coordinates_GFp(const EC_GROUP *, EC_POINT *, 307int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
226 const BIGNUM *x, const BIGNUM *y, BN_CTX *); 308 const BIGNUM *x, const BIGNUM *y, BN_CTX *);
227int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *, const EC_POINT *, 309int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *, const EC_POINT *,
228 BIGNUM *x, BIGNUM *y, BN_CTX *); 310 BIGNUM *x, BIGNUM *y, BN_CTX *);
229int ec_GFp_simple_set_compressed_coordinates_GFp(const EC_GROUP *, EC_POINT *, 311int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
230 const BIGNUM *x, int y_bit, BN_CTX *); 312 const BIGNUM *x, int y_bit, BN_CTX *);
231size_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form, 313size_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
232 unsigned char *buf, size_t len, BN_CTX *); 314 unsigned char *buf, size_t len, BN_CTX *);
@@ -246,7 +328,7 @@ int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX
246 328
247/* method functions in ecp_mont.c */ 329/* method functions in ecp_mont.c */
248int ec_GFp_mont_group_init(EC_GROUP *); 330int ec_GFp_mont_group_init(EC_GROUP *);
249int ec_GFp_mont_group_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); 331int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
250void ec_GFp_mont_group_finish(EC_GROUP *); 332void ec_GFp_mont_group_finish(EC_GROUP *);
251void ec_GFp_mont_group_clear_finish(EC_GROUP *); 333void ec_GFp_mont_group_clear_finish(EC_GROUP *);
252int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *); 334int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);
@@ -257,21 +339,52 @@ int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CT
257int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *); 339int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *);
258 340
259 341
260/* method functions in ecp_recp.c */
261int ec_GFp_recp_group_init(EC_GROUP *);
262int ec_GFp_recp_group_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
263void ec_GFp_recp_group_finish(EC_GROUP *);
264void ec_GFp_recp_group_clear_finish(EC_GROUP *);
265int ec_GFp_recp_group_copy(EC_GROUP *, const EC_GROUP *);
266int ec_GFp_recp_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
267int ec_GFp_recp_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
268
269
270/* method functions in ecp_nist.c */ 342/* method functions in ecp_nist.c */
271int ec_GFp_nist_group_init(EC_GROUP *); 343int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src);
272int ec_GFp_nist_group_set_curve_GFp(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); 344int ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
273void ec_GFp_nist_group_finish(EC_GROUP *);
274void ec_GFp_nist_group_clear_finish(EC_GROUP *);
275int ec_GFp_nist_group_copy(EC_GROUP *, const EC_GROUP *);
276int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); 345int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
277int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); 346int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
347
348
349/* method functions in ec2_smpl.c */
350int ec_GF2m_simple_group_init(EC_GROUP *);
351void ec_GF2m_simple_group_finish(EC_GROUP *);
352void ec_GF2m_simple_group_clear_finish(EC_GROUP *);
353int ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *);
354int ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
355int ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *);
356int ec_GF2m_simple_group_get_degree(const EC_GROUP *);
357int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
358int ec_GF2m_simple_point_init(EC_POINT *);
359void ec_GF2m_simple_point_finish(EC_POINT *);
360void ec_GF2m_simple_point_clear_finish(EC_POINT *);
361int ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *);
362int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
363int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
364 const BIGNUM *x, const BIGNUM *y, BN_CTX *);
365int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *, const EC_POINT *,
366 BIGNUM *x, BIGNUM *y, BN_CTX *);
367int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
368 const BIGNUM *x, int y_bit, BN_CTX *);
369size_t ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *, point_conversion_form_t form,
370 unsigned char *buf, size_t len, BN_CTX *);
371int ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *,
372 const unsigned char *buf, size_t len, BN_CTX *);
373int ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
374int ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
375int ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
376int ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);
377int ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
378int ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b, BN_CTX *);
379int ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
380int ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *);
381int ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
382int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
383int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *);
384
385
386/* method functions in ec2_mult.c */
387int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
388 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
389int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
390int 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
index deb522060f..5af84376c6 100644
--- a/src/lib/libcrypto/ec/ec_lib.c
+++ b/src/lib/libcrypto/ec/ec_lib.c
@@ -1,6 +1,9 @@
1/* crypto/ec/ec_lib.c */ 1/* crypto/ec/ec_lib.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-2003 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,6 +55,11 @@
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 * Binary polynomial ECC support in OpenSSL originally developed by
61 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
62 */
55 63
56#include <string.h> 64#include <string.h>
57 65
@@ -90,10 +98,18 @@ EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
90 ret->meth = meth; 98 ret->meth = meth;
91 99
92 ret->extra_data = NULL; 100 ret->extra_data = NULL;
93 ret->extra_data_dup_func = 0; 101
94 ret->extra_data_free_func = 0; 102 ret->generator = NULL;
95 ret->extra_data_clear_free_func = 0; 103 BN_init(&ret->order);
96 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
97 if (!meth->group_init(ret)) 113 if (!meth->group_init(ret))
98 { 114 {
99 OPENSSL_free(ret); 115 OPENSSL_free(ret);
@@ -111,7 +127,15 @@ void EC_GROUP_free(EC_GROUP *group)
111 if (group->meth->group_finish != 0) 127 if (group->meth->group_finish != 0)
112 group->meth->group_finish(group); 128 group->meth->group_finish(group);
113 129
114 EC_GROUP_free_extra_data(group); 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);
115 139
116 OPENSSL_free(group); 140 OPENSSL_free(group);
117 } 141 }
@@ -123,10 +147,21 @@ void EC_GROUP_clear_free(EC_GROUP *group)
123 147
124 if (group->meth->group_clear_finish != 0) 148 if (group->meth->group_clear_finish != 0)
125 group->meth->group_clear_finish(group); 149 group->meth->group_clear_finish(group);
126 else if (group->meth != NULL && group->meth->group_finish != 0) 150 else if (group->meth->group_finish != 0)
127 group->meth->group_finish(group); 151 group->meth->group_finish(group);
128 152
129 EC_GROUP_clear_free_extra_data(group); 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 }
130 165
131 OPENSSL_cleanse(group, sizeof *group); 166 OPENSSL_cleanse(group, sizeof *group);
132 OPENSSL_free(group); 167 OPENSSL_free(group);
@@ -135,6 +170,8 @@ void EC_GROUP_clear_free(EC_GROUP *group)
135 170
136int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) 171int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
137 { 172 {
173 EC_EXTRA_DATA *d;
174
138 if (dest->meth->group_copy == 0) 175 if (dest->meth->group_copy == 0)
139 { 176 {
140 ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 177 ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
@@ -148,161 +185,507 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
148 if (dest == src) 185 if (dest == src)
149 return 1; 186 return 1;
150 187
151 EC_GROUP_clear_free_extra_data(dest); 188 EC_EX_DATA_free_all_data(&dest->extra_data);
152 if (src->extra_data_dup_func) 189
190 for (d = src->extra_data; d != NULL; d = d->next)
153 { 191 {
154 if (src->extra_data != NULL) 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)
155 { 213 {
156 dest->extra_data = src->extra_data_dup_func(src->extra_data); 214 EC_POINT_clear_free(dest->generator);
157 if (dest->extra_data == NULL) 215 dest->generator = NULL;
158 return 0;
159 } 216 }
217 }
218
219 if (!BN_copy(&dest->order, &src->order)) return 0;
220 if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
160 221
161 dest->extra_data_dup_func = src->extra_data_dup_func; 222 dest->curve_name = src->curve_name;
162 dest->extra_data_free_func = src->extra_data_free_func; 223 dest->asn1_flag = src->asn1_flag;
163 dest->extra_data_clear_free_func = src->extra_data_clear_free_func; 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;
164 } 243 }
244
165 245
166 return dest->meth->group_copy(dest, src); 246 return dest->meth->group_copy(dest, src);
167 } 247 }
168 248
169 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
170const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) 272const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
171 { 273 {
172 return group->meth; 274 return group->meth;
173 } 275 }
174 276
175 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
176int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 407int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
177 { 408 {
178 if (group->meth->group_set_curve_GFp == 0) 409 if (group->meth->group_set_curve == 0)
179 { 410 {
180 ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 411 ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
181 return 0; 412 return 0;
182 } 413 }
183 return group->meth->group_set_curve_GFp(group, p, a, b, ctx); 414 return group->meth->group_set_curve(group, p, a, b, ctx);
184 } 415 }
185 416
186 417
187int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) 418int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
188 { 419 {
189 if (group->meth->group_get_curve_GFp == 0) 420 if (group->meth->group_get_curve == 0)
190 { 421 {
191 ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 422 ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
192 return 0; 423 return 0;
193 } 424 }
194 return group->meth->group_get_curve_GFp(group, p, a, b, ctx); 425 return group->meth->group_get_curve(group, p, a, b, ctx);
195 } 426 }
196 427
197 428
198int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor) 429int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
199 { 430 {
200 if (group->meth->group_set_generator == 0) 431 if (group->meth->group_set_curve == 0)
201 { 432 {
202 ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 433 ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
203 return 0; 434 return 0;
204 } 435 }
205 return group->meth->group_set_generator(group, generator, order, cofactor); 436 return group->meth->group_set_curve(group, p, a, b, ctx);
206 } 437 }
207 438
208 439
209EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) 440int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
210 { 441 {
211 if (group->meth->group_get0_generator == 0) 442 if (group->meth->group_get_curve == 0)
212 { 443 {
213 ECerr(EC_F_EC_GROUP_GET0_GENERATOR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 444 ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
214 return 0; 445 return 0;
215 } 446 }
216 return group->meth->group_get0_generator(group); 447 return group->meth->group_get_curve(group, p, a, b, ctx);
217 } 448 }
218 449
219 450
220int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 451int EC_GROUP_get_degree(const EC_GROUP *group)
221 { 452 {
222 if (group->meth->group_get_order == 0) 453 if (group->meth->group_get_degree == 0)
223 { 454 {
224 ECerr(EC_F_EC_GROUP_GET_ORDER, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 455 ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
225 return 0; 456 return 0;
226 } 457 }
227 return group->meth->group_get_order(group, order, ctx); 458 return group->meth->group_get_degree(group);
228 } 459 }
229 460
230 461
231int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) 462int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
232 { 463 {
233 if (group->meth->group_get_cofactor == 0) 464 if (group->meth->group_check_discriminant == 0)
234 { 465 {
235 ECerr(EC_F_EC_GROUP_GET_COFACTOR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 466 ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
236 return 0; 467 return 0;
237 } 468 }
238 return group->meth->group_get_cofactor(group, cofactor, ctx); 469 return group->meth->group_check_discriminant(group, ctx);
239 } 470 }
240 471
241 472
242/* this has 'package' visibility */ 473int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
243int EC_GROUP_set_extra_data(EC_GROUP *group, void *extra_data, void *(*extra_data_dup_func)(void *),
244 void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *))
245 { 474 {
246 if ((group->extra_data != NULL) 475 int r = 0;
247 || (group->extra_data_dup_func != 0) 476 BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
248 || (group->extra_data_free_func != 0) 477 BN_CTX *ctx_new = NULL;
249 || (group->extra_data_clear_free_func != 0)) 478
250 { 479 /* compare the field types*/
251 ECerr(EC_F_EC_GROUP_SET_EXTRA_DATA, EC_R_SLOT_FULL); 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))
252 return 0; 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;
253 } 506 }
254 507
255 group->extra_data = extra_data; 508 /* XXX This approach assumes that the external representation
256 group->extra_data_dup_func = extra_data_dup_func; 509 * of curves over the same field type is the same.
257 group->extra_data_free_func = extra_data_free_func; 510 */
258 group->extra_data_clear_free_func = extra_data_clear_free_func; 511 if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
259 return 1; 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;
260 } 545 }
261 546
262 547
263/* this has 'package' visibility */ 548/* this has 'package' visibility */
264void *EC_GROUP_get_extra_data(const EC_GROUP *group, void *(*extra_data_dup_func)(void *), 549int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
265 void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *)) 550 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
266 { 551 {
267 if ((group->extra_data_dup_func != extra_data_dup_func) 552 EC_EXTRA_DATA *d;
268 || (group->extra_data_free_func != extra_data_free_func) 553
269 || (group->extra_data_clear_free_func != extra_data_clear_free_func)) 554 if (ex_data == NULL)
555 return 0;
556
557 for (d = *ex_data; d != NULL; d = d->next)
270 { 558 {
271#if 0 /* this was an error in 0.9.7, but that does not make a lot of sense */ 559 if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
272 ECerr(..._F_EC_GROUP_GET_EXTRA_DATA, ..._R_NO_SUCH_EXTRA_DATA); 560 {
273#endif 561 ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
274 return NULL; 562 return 0;
563 }
275 } 564 }
276 565
277 return group->extra_data; 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;
278 } 583 }
279 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 }
280 599
281/* this has 'package' visibility */ 600/* this has 'package' visibility */
282void EC_GROUP_free_extra_data(EC_GROUP *group) 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 *))
283 { 603 {
284 if (group->extra_data_free_func) 604 EC_EXTRA_DATA **p;
285 group->extra_data_free_func(group->extra_data); 605
286 group->extra_data = NULL; 606 if (ex_data == NULL)
287 group->extra_data_dup_func = 0; 607 return;
288 group->extra_data_free_func = 0; 608
289 group->extra_data_clear_free_func = 0; 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 }
290 } 622 }
291 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 }
292 647
293/* this has 'package' visibility */ 648/* this has 'package' visibility */
294void EC_GROUP_clear_free_extra_data(EC_GROUP *group) 649void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
295 { 650 {
296 if (group->extra_data_clear_free_func) 651 EC_EXTRA_DATA *d;
297 group->extra_data_clear_free_func(group->extra_data); 652
298 else if (group->extra_data_free_func) 653 if (ex_data == NULL)
299 group->extra_data_free_func(group->extra_data); 654 return;
300 group->extra_data = NULL; 655
301 group->extra_data_dup_func = 0; 656 d = *ex_data;
302 group->extra_data_free_func = 0; 657 while (d)
303 group->extra_data_clear_free_func = 0; 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;
304 } 667 }
305 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 }
306 689
307 690
308/* functions for EC_POINT objects */ 691/* functions for EC_POINT objects */
@@ -382,6 +765,25 @@ int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
382 } 765 }
383 766
384 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
385const EC_METHOD *EC_POINT_method_of(const EC_POINT *point) 787const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
386 { 788 {
387 return point->meth; 789 return point->meth;
@@ -441,7 +843,7 @@ int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POI
441int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 843int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
442 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 844 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
443 { 845 {
444 if (group->meth->point_set_affine_coordinates_GFp == 0) 846 if (group->meth->point_set_affine_coordinates == 0)
445 { 847 {
446 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 848 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
447 return 0; 849 return 0;
@@ -451,14 +853,31 @@ int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
451 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); 853 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
452 return 0; 854 return 0;
453 } 855 }
454 return group->meth->point_set_affine_coordinates_GFp(group, point, x, y, ctx); 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);
455 } 874 }
456 875
457 876
458int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, 877int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
459 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 878 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
460 { 879 {
461 if (group->meth->point_get_affine_coordinates_GFp == 0) 880 if (group->meth->point_get_affine_coordinates == 0)
462 { 881 {
463 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 882 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
464 return 0; 883 return 0;
@@ -468,14 +887,31 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *p
468 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); 887 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
469 return 0; 888 return 0;
470 } 889 }
471 return group->meth->point_get_affine_coordinates_GFp(group, point, x, y, ctx); 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);
472 } 908 }
473 909
474 910
475int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 911int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
476 const BIGNUM *x, int y_bit, BN_CTX *ctx) 912 const BIGNUM *x, int y_bit, BN_CTX *ctx)
477 { 913 {
478 if (group->meth->point_set_compressed_coordinates_GFp == 0) 914 if (group->meth->point_set_compressed_coordinates == 0)
479 { 915 {
480 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 916 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
481 return 0; 917 return 0;
@@ -485,7 +921,24 @@ int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *poi
485 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS); 921 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
486 return 0; 922 return 0;
487 } 923 }
488 return group->meth->point_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx); 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);
489 } 942 }
490 943
491 944
@@ -559,12 +1012,12 @@ int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
559 { 1012 {
560 if (group->meth->dbl == 0) 1013 if (group->meth->dbl == 0)
561 { 1014 {
562 ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 1015 ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
563 return 0; 1016 return 0;
564 } 1017 }
565 if (group->meth != a->meth) 1018 if (group->meth != a->meth)
566 { 1019 {
567 ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS); 1020 ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
568 return 0; 1021 return 0;
569 } 1022 }
570 return group->meth->invert(group, a, ctx); 1023 return group->meth->invert(group, a, ctx);
@@ -654,3 +1107,58 @@ int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
654 } 1107 }
655 return group->meth->points_make_affine(group, num, points, ctx); 1108 return group->meth->points_make_affine(group, num, points, ctx);
656 } 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
index 16822a73cf..2ba173ef36 100644
--- a/src/lib/libcrypto/ec/ec_mult.c
+++ b/src/lib/libcrypto/ec/ec_mult.c
@@ -1,6 +1,9 @@
1/* crypto/ec/ec_mult.c */ 1/* crypto/ec/ec_mult.c */
2/*
3 * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
4 */
2/* ==================================================================== 5/* ====================================================================
3 * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 6 * Copyright (c) 1998-2007 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,41 +55,161 @@
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 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
61 * and contributed to the OpenSSL project.
62 */
63
64#include <string.h>
55 65
56#include <openssl/err.h> 66#include <openssl/err.h>
57 67
58#include "ec_lcl.h" 68#include "ec_lcl.h"
59 69
60 70
61/* TODO: optional precomputation of multiples of the generator */ 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 */
62 77
63 78
64 79
65/* 80
66 * wNAF-based interleaving multi-exponentation method 81/* structure for precomputed multiples of the generator */
67 * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>) 82typedef struct ec_pre_comp_st {
68 */ 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 EC_POINT_clear_free(*p);
173 OPENSSL_cleanse(pre->points, sizeof pre->points);
174 OPENSSL_free(pre->points);
175 }
176 OPENSSL_cleanse(pre, sizeof pre);
177 OPENSSL_free(pre);
178 }
179
69 180
70 181
71/* Determine the width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'. 182
183/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'.
72 * This is an array r[] of values that are either zero or odd with an 184 * This is an array r[] of values that are either zero or odd with an
73 * absolute value less than 2^w satisfying 185 * absolute value less than 2^w satisfying
74 * scalar = \sum_j r[j]*2^j 186 * scalar = \sum_j r[j]*2^j
75 * where at most one of any w+1 consecutive digits is non-zero. 187 * where at most one of any w+1 consecutive digits is non-zero
188 * with the exception that the most significant digit may be only
189 * w-1 zeros away from that next non-zero digit.
76 */ 190 */
77static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len, BN_CTX *ctx) 191static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
78 { 192 {
79 BIGNUM *c; 193 int window_val;
80 int ok = 0; 194 int ok = 0;
81 signed char *r = NULL; 195 signed char *r = NULL;
82 int sign = 1; 196 int sign = 1;
83 int bit, next_bit, mask; 197 int bit, next_bit, mask;
84 size_t len = 0, j; 198 size_t len = 0, j;
85 199
86 BN_CTX_start(ctx); 200 if (BN_is_zero(scalar))
87 c = BN_CTX_get(ctx); 201 {
88 if (c == NULL) goto err; 202 r = OPENSSL_malloc(1);
89 203 if (!r)
204 {
205 ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
206 goto err;
207 }
208 r[0] = 0;
209 *ret_len = 1;
210 return r;
211 }
212
90 if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute values less than 2^7 */ 213 if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute values less than 2^7 */
91 { 214 {
92 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); 215 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
@@ -96,60 +219,90 @@ static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len, B
96 next_bit = bit << 1; /* at most 256 */ 219 next_bit = bit << 1; /* at most 256 */
97 mask = next_bit - 1; /* at most 255 */ 220 mask = next_bit - 1; /* at most 255 */
98 221
99 if (!BN_copy(c, scalar)) goto err; 222 if (BN_is_negative(scalar))
100 if (c->neg)
101 { 223 {
102 sign = -1; 224 sign = -1;
103 c->neg = 0;
104 } 225 }
105 226
106 len = BN_num_bits(c) + 1; /* wNAF may be one digit longer than binary representation */ 227 len = BN_num_bits(scalar);
107 r = OPENSSL_malloc(len); 228 r = OPENSSL_malloc(len + 1); /* modified wNAF may be one digit longer than binary representation
108 if (r == NULL) goto err; 229 * (*ret_len will be set to the actual length, i.e. at most
230 * BN_num_bits(scalar) + 1) */
231 if (r == NULL)
232 {
233 ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
234 goto err;
235 }
109 236
237 if (scalar->d == NULL || scalar->top == 0)
238 {
239 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
240 goto err;
241 }
242 window_val = scalar->d[0] & mask;
110 j = 0; 243 j = 0;
111 while (!BN_is_zero(c)) 244 while ((window_val != 0) || (j + w + 1 < len)) /* if j+w+1 >= len, window_val will not increase */
112 { 245 {
113 int u = 0; 246 int digit = 0;
114 247
115 if (BN_is_odd(c)) 248 /* 0 <= window_val <= 2^(w+1) */
249
250 if (window_val & 1)
116 { 251 {
117 if (c->d == NULL || c->top == 0) 252 /* 0 < window_val < 2^(w+1) */
253
254 if (window_val & bit)
118 { 255 {
119 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); 256 digit = window_val - next_bit; /* -2^w < digit < 0 */
120 goto err; 257
258#if 1 /* modified wNAF */
259 if (j + w + 1 >= len)
260 {
261 /* special case for generating modified wNAFs:
262 * no new bits will be added into window_val,
263 * so using a positive digit here will decrease
264 * the total length of the representation */
265
266 digit = window_val & (mask >> 1); /* 0 < digit < 2^w */
267 }
268#endif
121 } 269 }
122 u = c->d[0] & mask; 270 else
123 if (u & bit)
124 { 271 {
125 u -= next_bit; 272 digit = window_val; /* 0 < digit < 2^w */
126 /* u < 0 */
127 if (!BN_add_word(c, -u)) goto err;
128 } 273 }
129 else 274
275 if (digit <= -bit || digit >= bit || !(digit & 1))
130 { 276 {
131 /* u > 0 */ 277 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
132 if (!BN_sub_word(c, u)) goto err; 278 goto err;
133 } 279 }
134 280
135 if (u <= -bit || u >= bit || !(u & 1) || c->neg) 281 window_val -= digit;
282
283 /* now window_val is 0 or 2^(w+1) in standard wNAF generation;
284 * for modified window NAFs, it may also be 2^w
285 */
286 if (window_val != 0 && window_val != next_bit && window_val != bit)
136 { 287 {
137 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); 288 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
138 goto err; 289 goto err;
139 } 290 }
140 } 291 }
141 292
142 r[j++] = sign * u; 293 r[j++] = sign * digit;
143 294
144 if (BN_is_odd(c)) 295 window_val >>= 1;
296 window_val += bit * BN_is_bit_set(scalar, j + w);
297
298 if (window_val > next_bit)
145 { 299 {
146 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); 300 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
147 goto err; 301 goto err;
148 } 302 }
149 if (!BN_rshift1(c, c)) goto err;
150 } 303 }
151 304
152 if (j > len) 305 if (j > len + 1)
153 { 306 {
154 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR); 307 ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
155 goto err; 308 goto err;
@@ -158,7 +311,6 @@ static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len, B
158 ok = 1; 311 ok = 1;
159 312
160 err: 313 err:
161 BN_CTX_end(ctx);
162 if (!ok) 314 if (!ok)
163 { 315 {
164 OPENSSL_free(r); 316 OPENSSL_free(r);
@@ -181,7 +333,7 @@ static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len, B
181 (b) >= 300 ? 4 : \ 333 (b) >= 300 ? 4 : \
182 (b) >= 70 ? 3 : \ 334 (b) >= 70 ? 3 : \
183 (b) >= 20 ? 2 : \ 335 (b) >= 20 ? 2 : \
184 1)) 336 1))
185 337
186/* Compute 338/* Compute
187 * \sum scalars[i]*points[i], 339 * \sum scalars[i]*points[i],
@@ -189,13 +341,15 @@ static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len, B
189 * scalar*generator 341 * scalar*generator
190 * in the addition if scalar != NULL 342 * in the addition if scalar != NULL
191 */ 343 */
192int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, 344int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
193 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) 345 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
194 { 346 {
195 BN_CTX *new_ctx = NULL; 347 BN_CTX *new_ctx = NULL;
196 EC_POINT *generator = NULL; 348 const EC_POINT *generator = NULL;
197 EC_POINT *tmp = NULL; 349 EC_POINT *tmp = NULL;
198 size_t totalnum; 350 size_t totalnum;
351 size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */
352 size_t pre_points_per_block = 0;
199 size_t i, j; 353 size_t i, j;
200 int k; 354 int k;
201 int r_is_inverted = 0; 355 int r_is_inverted = 0;
@@ -207,12 +361,15 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
207 size_t num_val; 361 size_t num_val;
208 EC_POINT **val = NULL; /* precomputation */ 362 EC_POINT **val = NULL; /* precomputation */
209 EC_POINT **v; 363 EC_POINT **v;
210 EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' */ 364 EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or 'pre_comp->points' */
365 const EC_PRE_COMP *pre_comp = NULL;
366 int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be treated like other scalars,
367 * i.e. precomputation is not available */
211 int ret = 0; 368 int ret = 0;
212 369
213 if (group->meth != r->meth) 370 if (group->meth != r->meth)
214 { 371 {
215 ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); 372 ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
216 return 0; 373 return 0;
217 } 374 }
218 375
@@ -221,59 +378,226 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
221 return EC_POINT_set_to_infinity(group, r); 378 return EC_POINT_set_to_infinity(group, r);
222 } 379 }
223 380
224 if (scalar != NULL) 381 for (i = 0; i < num; i++)
225 { 382 {
226 generator = EC_GROUP_get0_generator(group); 383 if (group->meth != points[i]->meth)
227 if (generator == NULL)
228 { 384 {
229 ECerr(EC_F_EC_POINTS_MUL, EC_R_UNDEFINED_GENERATOR); 385 ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
230 return 0; 386 return 0;
231 } 387 }
232 } 388 }
233 389
234 for (i = 0; i < num; i++) 390 if (ctx == NULL)
235 { 391 {
236 if (group->meth != points[i]->meth) 392 ctx = new_ctx = BN_CTX_new();
393 if (ctx == NULL)
394 goto err;
395 }
396
397 if (scalar != NULL)
398 {
399 generator = EC_GROUP_get0_generator(group);
400 if (generator == NULL)
237 { 401 {
238 ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); 402 ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR);
239 return 0; 403 goto err;
240 } 404 }
241 } 405
406 /* look if we can use precomputed multiples of generator */
407
408 pre_comp = EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free);
409
410 if (pre_comp && pre_comp->numblocks && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) == 0))
411 {
412 blocksize = pre_comp->blocksize;
242 413
243 totalnum = num + (scalar != NULL); 414 /* determine maximum number of blocks that wNAF splitting may yield
415 * (NB: maximum wNAF length is bit length plus one) */
416 numblocks = (BN_num_bits(scalar) / blocksize) + 1;
244 417
245 wsize = OPENSSL_malloc(totalnum * sizeof wsize[0]); 418 /* we cannot use more blocks than we have precomputation for */
419 if (numblocks > pre_comp->numblocks)
420 numblocks = pre_comp->numblocks;
421
422 pre_points_per_block = 1u << (pre_comp->w - 1);
423
424 /* check that pre_comp looks sane */
425 if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block))
426 {
427 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
428 goto err;
429 }
430 }
431 else
432 {
433 /* can't use precomputation */
434 pre_comp = NULL;
435 numblocks = 1;
436 num_scalar = 1; /* treat 'scalar' like 'num'-th element of 'scalars' */
437 }
438 }
439
440 totalnum = num + numblocks;
441
442 wsize = OPENSSL_malloc(totalnum * sizeof wsize[0]);
246 wNAF_len = OPENSSL_malloc(totalnum * sizeof wNAF_len[0]); 443 wNAF_len = OPENSSL_malloc(totalnum * sizeof wNAF_len[0]);
247 wNAF = OPENSSL_malloc((totalnum + 1) * sizeof wNAF[0]); 444 wNAF = OPENSSL_malloc((totalnum + 1) * sizeof wNAF[0]); /* includes space for pivot */
248 if (wNAF != NULL) 445 val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]);
446
447 if (!wsize || !wNAF_len || !wNAF || !val_sub)
249 { 448 {
250 wNAF[0] = NULL; /* preliminary pivot */ 449 ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
450 goto err;
251 } 451 }
252 if (wsize == NULL || wNAF_len == NULL || wNAF == NULL) goto err;
253 452
254 /* num_val := total number of points to precompute */ 453 wNAF[0] = NULL; /* preliminary pivot */
454
455 /* num_val will be the total number of temporarily precomputed points */
255 num_val = 0; 456 num_val = 0;
256 for (i = 0; i < totalnum; i++) 457
458 for (i = 0; i < num + num_scalar; i++)
257 { 459 {
258 size_t bits; 460 size_t bits;
259 461
260 bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar); 462 bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);
261 wsize[i] = EC_window_bits_for_scalar_size(bits); 463 wsize[i] = EC_window_bits_for_scalar_size(bits);
262 num_val += 1u << (wsize[i] - 1); 464 num_val += 1u << (wsize[i] - 1);
465 wNAF[i + 1] = NULL; /* make sure we always have a pivot */
466 wNAF[i] = compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], &wNAF_len[i]);
467 if (wNAF[i] == NULL)
468 goto err;
469 if (wNAF_len[i] > max_len)
470 max_len = wNAF_len[i];
471 }
472
473 if (numblocks)
474 {
475 /* we go here iff scalar != NULL */
476
477 if (pre_comp == NULL)
478 {
479 if (num_scalar != 1)
480 {
481 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
482 goto err;
483 }
484 /* we have already generated a wNAF for 'scalar' */
485 }
486 else
487 {
488 signed char *tmp_wNAF = NULL;
489 size_t tmp_len = 0;
490
491 if (num_scalar != 0)
492 {
493 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
494 goto err;
495 }
496
497 /* use the window size for which we have precomputation */
498 wsize[num] = pre_comp->w;
499 tmp_wNAF = compute_wNAF(scalar, wsize[num], &tmp_len);
500 if (!tmp_wNAF)
501 goto err;
502
503 if (tmp_len <= max_len)
504 {
505 /* One of the other wNAFs is at least as long
506 * as the wNAF belonging to the generator,
507 * so wNAF splitting will not buy us anything. */
508
509 numblocks = 1;
510 totalnum = num + 1; /* don't use wNAF splitting */
511 wNAF[num] = tmp_wNAF;
512 wNAF[num + 1] = NULL;
513 wNAF_len[num] = tmp_len;
514 if (tmp_len > max_len)
515 max_len = tmp_len;
516 /* pre_comp->points starts with the points that we need here: */
517 val_sub[num] = pre_comp->points;
518 }
519 else
520 {
521 /* don't include tmp_wNAF directly into wNAF array
522 * - use wNAF splitting and include the blocks */
523
524 signed char *pp;
525 EC_POINT **tmp_points;
526
527 if (tmp_len < numblocks * blocksize)
528 {
529 /* possibly we can do with fewer blocks than estimated */
530 numblocks = (tmp_len + blocksize - 1) / blocksize;
531 if (numblocks > pre_comp->numblocks)
532 {
533 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
534 goto err;
535 }
536 totalnum = num + numblocks;
537 }
538
539 /* split wNAF in 'numblocks' parts */
540 pp = tmp_wNAF;
541 tmp_points = pre_comp->points;
542
543 for (i = num; i < totalnum; i++)
544 {
545 if (i < totalnum - 1)
546 {
547 wNAF_len[i] = blocksize;
548 if (tmp_len < blocksize)
549 {
550 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
551 goto err;
552 }
553 tmp_len -= blocksize;
554 }
555 else
556 /* last block gets whatever is left
557 * (this could be more or less than 'blocksize'!) */
558 wNAF_len[i] = tmp_len;
559
560 wNAF[i + 1] = NULL;
561 wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
562 if (wNAF[i] == NULL)
563 {
564 ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
565 OPENSSL_free(tmp_wNAF);
566 goto err;
567 }
568 memcpy(wNAF[i], pp, wNAF_len[i]);
569 if (wNAF_len[i] > max_len)
570 max_len = wNAF_len[i];
571
572 if (*tmp_points == NULL)
573 {
574 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
575 OPENSSL_free(tmp_wNAF);
576 goto err;
577 }
578 val_sub[i] = tmp_points;
579 tmp_points += pre_points_per_block;
580 pp += blocksize;
581 }
582 OPENSSL_free(tmp_wNAF);
583 }
584 }
263 } 585 }
264 586
265 /* all precomputed points go into a single array 'val', 587 /* All points we precompute now go into a single array 'val'.
266 * 'val_sub[i]' is a pointer to the subarray for the i-th point */ 588 * 'val_sub[i]' is a pointer to the subarray for the i-th point,
589 * or to a subarray of 'pre_comp->points' if we already have precomputation. */
267 val = OPENSSL_malloc((num_val + 1) * sizeof val[0]); 590 val = OPENSSL_malloc((num_val + 1) * sizeof val[0]);
268 if (val == NULL) goto err; 591 if (val == NULL)
592 {
593 ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
594 goto err;
595 }
269 val[num_val] = NULL; /* pivot element */ 596 val[num_val] = NULL; /* pivot element */
270 597
271 val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]);
272 if (val_sub == NULL) goto err;
273
274 /* allocate points for precomputation */ 598 /* allocate points for precomputation */
275 v = val; 599 v = val;
276 for (i = 0; i < totalnum; i++) 600 for (i = 0; i < num + num_scalar; i++)
277 { 601 {
278 val_sub[i] = v; 602 val_sub[i] = v;
279 for (j = 0; j < (1u << (wsize[i] - 1)); j++) 603 for (j = 0; j < (1u << (wsize[i] - 1)); j++)
@@ -285,19 +609,12 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
285 } 609 }
286 if (!(v == val + num_val)) 610 if (!(v == val + num_val))
287 { 611 {
288 ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR); 612 ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
289 goto err; 613 goto err;
290 } 614 }
291 615
292 if (ctx == NULL) 616 if (!(tmp = EC_POINT_new(group)))
293 { 617 goto err;
294 ctx = new_ctx = BN_CTX_new();
295 if (ctx == NULL)
296 goto err;
297 }
298
299 tmp = EC_POINT_new(group);
300 if (tmp == NULL) goto err;
301 618
302 /* prepare precomputed values: 619 /* prepare precomputed values:
303 * val_sub[i][0] := points[i] 620 * val_sub[i][0] := points[i]
@@ -305,7 +622,7 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
305 * val_sub[i][2] := 5 * points[i] 622 * val_sub[i][2] := 5 * points[i]
306 * ... 623 * ...
307 */ 624 */
308 for (i = 0; i < totalnum; i++) 625 for (i = 0; i < num + num_scalar; i++)
309 { 626 {
310 if (i < num) 627 if (i < num)
311 { 628 {
@@ -324,16 +641,11 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
324 if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) goto err; 641 if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx)) goto err;
325 } 642 }
326 } 643 }
327
328 wNAF[i + 1] = NULL; /* make sure we always have a pivot */
329 wNAF[i] = compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], &wNAF_len[i], ctx);
330 if (wNAF[i] == NULL) goto err;
331 if (wNAF_len[i] > max_len)
332 max_len = wNAF_len[i];
333 } 644 }
334 645
335#if 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */ 646#if 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */
336 if (!EC_POINTs_make_affine(group, num_val, val, ctx)) goto err; 647 if (!EC_POINTs_make_affine(group, num_val, val, ctx))
648 goto err;
337#endif 649#endif
338 650
339 r_is_at_infinity = 1; 651 r_is_at_infinity = 1;
@@ -429,57 +741,198 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
429 } 741 }
430 742
431 743
432int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) 744/* ec_wNAF_precompute_mult()
433 { 745 * creates an EC_PRE_COMP object with preprecomputed multiples of the generator
434 const EC_POINT *points[1]; 746 * for use with wNAF splitting as implemented in ec_wNAF_mul().
435 const BIGNUM *scalars[1]; 747 *
436 748 * 'pre_comp->points' is an array of multiples of the generator
437 points[0] = point; 749 * of the following form:
438 scalars[0] = p_scalar; 750 * points[0] = generator;
439 751 * points[1] = 3 * generator;
440 return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx); 752 * ...
441 } 753 * points[2^(w-1)-1] = (2^(w-1)-1) * generator;
442 754 * points[2^(w-1)] = 2^blocksize * generator;
443 755 * points[2^(w-1)+1] = 3 * 2^blocksize * generator;
444int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) 756 * ...
757 * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) * 2^(blocksize*(numblocks-2)) * generator
758 * points[2^(w-1)*(numblocks-1)] = 2^(blocksize*(numblocks-1)) * generator
759 * ...
760 * points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) * generator
761 * points[2^(w-1)*numblocks] = NULL
762 */
763int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
445 { 764 {
446 const EC_POINT *generator; 765 const EC_POINT *generator;
766 EC_POINT *tmp_point = NULL, *base = NULL, **var;
447 BN_CTX *new_ctx = NULL; 767 BN_CTX *new_ctx = NULL;
448 BIGNUM *order; 768 BIGNUM *order;
769 size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;
770 EC_POINT **points = NULL;
771 EC_PRE_COMP *pre_comp;
449 int ret = 0; 772 int ret = 0;
450 773
774 /* if there is an old EC_PRE_COMP object, throw it away */
775 EC_EX_DATA_free_data(&group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free);
776
777 if ((pre_comp = ec_pre_comp_new(group)) == NULL)
778 return 0;
779
451 generator = EC_GROUP_get0_generator(group); 780 generator = EC_GROUP_get0_generator(group);
452 if (generator == NULL) 781 if (generator == NULL)
453 { 782 {
454 ECerr(EC_F_EC_GROUP_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR); 783 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR);
455 return 0; 784 goto err;
456 } 785 }
457 786
458 if (ctx == NULL) 787 if (ctx == NULL)
459 { 788 {
460 ctx = new_ctx = BN_CTX_new(); 789 ctx = new_ctx = BN_CTX_new();
461 if (ctx == NULL) 790 if (ctx == NULL)
462 return 0; 791 goto err;
463 } 792 }
464 793
465 BN_CTX_start(ctx); 794 BN_CTX_start(ctx);
466 order = BN_CTX_get(ctx); 795 order = BN_CTX_get(ctx);
467 if (order == NULL) goto err; 796 if (order == NULL) goto err;
468 797
469 if (!EC_GROUP_get_order(group, order, ctx)) return 0; 798 if (!EC_GROUP_get_order(group, order, ctx)) goto err;
470 if (BN_is_zero(order)) 799 if (BN_is_zero(order))
471 { 800 {
472 ECerr(EC_F_EC_GROUP_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER); 801 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER);
473 goto err; 802 goto err;
474 } 803 }
475 804
476 /* TODO */ 805 bits = BN_num_bits(order);
806 /* The following parameters mean we precompute (approximately)
807 * one point per bit.
808 *
809 * TBD: The combination 8, 4 is perfect for 160 bits; for other
810 * bit lengths, other parameter combinations might provide better
811 * efficiency.
812 */
813 blocksize = 8;
814 w = 4;
815 if (EC_window_bits_for_scalar_size(bits) > w)
816 {
817 /* let's not make the window too small ... */
818 w = EC_window_bits_for_scalar_size(bits);
819 }
820
821 numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks to use for wNAF splitting */
822
823 pre_points_per_block = 1u << (w - 1);
824 num = pre_points_per_block * numblocks; /* number of points to compute and store */
477 825
478 ret = 1; 826 points = OPENSSL_malloc(sizeof (EC_POINT*)*(num + 1));
827 if (!points)
828 {
829 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
830 goto err;
831 }
832
833 var = points;
834 var[num] = NULL; /* pivot */
835 for (i = 0; i < num; i++)
836 {
837 if ((var[i] = EC_POINT_new(group)) == NULL)
838 {
839 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
840 goto err;
841 }
842 }
843
844 if (!(tmp_point = EC_POINT_new(group)) || !(base = EC_POINT_new(group)))
845 {
846 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
847 goto err;
848 }
849
850 if (!EC_POINT_copy(base, generator))
851 goto err;
852
853 /* do the precomputation */
854 for (i = 0; i < numblocks; i++)
855 {
856 size_t j;
857
858 if (!EC_POINT_dbl(group, tmp_point, base, ctx))
859 goto err;
860
861 if (!EC_POINT_copy(*var++, base))
862 goto err;
863
864 for (j = 1; j < pre_points_per_block; j++, var++)
865 {
866 /* calculate odd multiples of the current base point */
867 if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx))
868 goto err;
869 }
870
871 if (i < numblocks - 1)
872 {
873 /* get the next base (multiply current one by 2^blocksize) */
874 size_t k;
875
876 if (blocksize <= 2)
877 {
878 ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR);
879 goto err;
880 }
881
882 if (!EC_POINT_dbl(group, base, tmp_point, ctx))
883 goto err;
884 for (k = 2; k < blocksize; k++)
885 {
886 if (!EC_POINT_dbl(group,base,base,ctx))
887 goto err;
888 }
889 }
890 }
891
892 if (!EC_POINTs_make_affine(group, num, points, ctx))
893 goto err;
479 894
895 pre_comp->group = group;
896 pre_comp->blocksize = blocksize;
897 pre_comp->numblocks = numblocks;
898 pre_comp->w = w;
899 pre_comp->points = points;
900 points = NULL;
901 pre_comp->num = num;
902
903 if (!EC_EX_DATA_set_data(&group->extra_data, pre_comp,
904 ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free))
905 goto err;
906 pre_comp = NULL;
907
908 ret = 1;
480 err: 909 err:
481 BN_CTX_end(ctx); 910 if (ctx != NULL)
911 BN_CTX_end(ctx);
482 if (new_ctx != NULL) 912 if (new_ctx != NULL)
483 BN_CTX_free(new_ctx); 913 BN_CTX_free(new_ctx);
914 if (pre_comp)
915 ec_pre_comp_free(pre_comp);
916 if (points)
917 {
918 EC_POINT **p;
919
920 for (p = points; *p != NULL; p++)
921 EC_POINT_free(*p);
922 OPENSSL_free(points);
923 }
924 if (tmp_point)
925 EC_POINT_free(tmp_point);
926 if (base)
927 EC_POINT_free(base);
484 return ret; 928 return ret;
485 } 929 }
930
931
932int ec_wNAF_have_precompute_mult(const EC_GROUP *group)
933 {
934 if (EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup, ec_pre_comp_free, ec_pre_comp_clear_free) != NULL)
935 return 1;
936 else
937 return 0;
938 }
diff --git a/src/lib/libcrypto/ec/ecp_mont.c b/src/lib/libcrypto/ec/ecp_mont.c
index 7b30d4c38a..9fc4a466a5 100644
--- a/src/lib/libcrypto/ec/ecp_mont.c
+++ b/src/lib/libcrypto/ec/ecp_mont.c
@@ -1,4 +1,7 @@
1/* crypto/ec/ecp_mont.c */ 1/* crypto/ec/ecp_mont.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-2001 The OpenSSL Project. All rights reserved.
4 * 7 *
@@ -52,6 +55,11 @@
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 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
61 * and contributed to the OpenSSL project.
62 */
55 63
56#include <openssl/err.h> 64#include <openssl/err.h>
57 65
@@ -61,16 +69,15 @@
61const EC_METHOD *EC_GFp_mont_method(void) 69const EC_METHOD *EC_GFp_mont_method(void)
62 { 70 {
63 static const EC_METHOD ret = { 71 static const EC_METHOD ret = {
72 NID_X9_62_prime_field,
64 ec_GFp_mont_group_init, 73 ec_GFp_mont_group_init,
65 ec_GFp_mont_group_finish, 74 ec_GFp_mont_group_finish,
66 ec_GFp_mont_group_clear_finish, 75 ec_GFp_mont_group_clear_finish,
67 ec_GFp_mont_group_copy, 76 ec_GFp_mont_group_copy,
68 ec_GFp_mont_group_set_curve_GFp, 77 ec_GFp_mont_group_set_curve,
69 ec_GFp_simple_group_get_curve_GFp, 78 ec_GFp_simple_group_get_curve,
70 ec_GFp_simple_group_set_generator, 79 ec_GFp_simple_group_get_degree,
71 ec_GFp_simple_group_get0_generator, 80 ec_GFp_simple_group_check_discriminant,
72 ec_GFp_simple_group_get_order,
73 ec_GFp_simple_group_get_cofactor,
74 ec_GFp_simple_point_init, 81 ec_GFp_simple_point_init,
75 ec_GFp_simple_point_finish, 82 ec_GFp_simple_point_finish,
76 ec_GFp_simple_point_clear_finish, 83 ec_GFp_simple_point_clear_finish,
@@ -78,9 +85,9 @@ const EC_METHOD *EC_GFp_mont_method(void)
78 ec_GFp_simple_point_set_to_infinity, 85 ec_GFp_simple_point_set_to_infinity,
79 ec_GFp_simple_set_Jprojective_coordinates_GFp, 86 ec_GFp_simple_set_Jprojective_coordinates_GFp,
80 ec_GFp_simple_get_Jprojective_coordinates_GFp, 87 ec_GFp_simple_get_Jprojective_coordinates_GFp,
81 ec_GFp_simple_point_set_affine_coordinates_GFp, 88 ec_GFp_simple_point_set_affine_coordinates,
82 ec_GFp_simple_point_get_affine_coordinates_GFp, 89 ec_GFp_simple_point_get_affine_coordinates,
83 ec_GFp_simple_set_compressed_coordinates_GFp, 90 ec_GFp_simple_set_compressed_coordinates,
84 ec_GFp_simple_point2oct, 91 ec_GFp_simple_point2oct,
85 ec_GFp_simple_oct2point, 92 ec_GFp_simple_oct2point,
86 ec_GFp_simple_add, 93 ec_GFp_simple_add,
@@ -91,8 +98,12 @@ const EC_METHOD *EC_GFp_mont_method(void)
91 ec_GFp_simple_cmp, 98 ec_GFp_simple_cmp,
92 ec_GFp_simple_make_affine, 99 ec_GFp_simple_make_affine,
93 ec_GFp_simple_points_make_affine, 100 ec_GFp_simple_points_make_affine,
101 0 /* mul */,
102 0 /* precompute_mult */,
103 0 /* have_precompute_mult */,
94 ec_GFp_mont_field_mul, 104 ec_GFp_mont_field_mul,
95 ec_GFp_mont_field_sqr, 105 ec_GFp_mont_field_sqr,
106 0 /* field_div */,
96 ec_GFp_mont_field_encode, 107 ec_GFp_mont_field_encode,
97 ec_GFp_mont_field_decode, 108 ec_GFp_mont_field_decode,
98 ec_GFp_mont_field_set_to_one }; 109 ec_GFp_mont_field_set_to_one };
@@ -112,66 +123,6 @@ int ec_GFp_mont_group_init(EC_GROUP *group)
112 } 123 }
113 124
114 125
115int ec_GFp_mont_group_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
116 {
117 BN_CTX *new_ctx = NULL;
118 BN_MONT_CTX *mont = NULL;
119 BIGNUM *one = NULL;
120 int ret = 0;
121
122 if (group->field_data1 != NULL)
123 {
124 BN_MONT_CTX_free(group->field_data1);
125 group->field_data1 = NULL;
126 }
127 if (group->field_data2 != NULL)
128 {
129 BN_free(group->field_data2);
130 group->field_data2 = NULL;
131 }
132
133 if (ctx == NULL)
134 {
135 ctx = new_ctx = BN_CTX_new();
136 if (ctx == NULL)
137 return 0;
138 }
139
140 mont = BN_MONT_CTX_new();
141 if (mont == NULL) goto err;
142 if (!BN_MONT_CTX_set(mont, p, ctx))
143 {
144 ECerr(EC_F_GFP_MONT_GROUP_SET_CURVE_GFP, ERR_R_BN_LIB);
145 goto err;
146 }
147 one = BN_new();
148 if (one == NULL) goto err;
149 if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) goto err;
150
151 group->field_data1 = mont;
152 mont = NULL;
153 group->field_data2 = one;
154 one = NULL;
155
156 ret = ec_GFp_simple_group_set_curve_GFp(group, p, a, b, ctx);
157
158 if (!ret)
159 {
160 BN_MONT_CTX_free(group->field_data1);
161 group->field_data1 = NULL;
162 BN_free(group->field_data2);
163 group->field_data2 = NULL;
164 }
165
166 err:
167 if (new_ctx != NULL)
168 BN_CTX_free(new_ctx);
169 if (mont != NULL)
170 BN_MONT_CTX_free(mont);
171 return ret;
172 }
173
174
175void ec_GFp_mont_group_finish(EC_GROUP *group) 126void ec_GFp_mont_group_finish(EC_GROUP *group)
176 { 127 {
177 if (group->field_data1 != NULL) 128 if (group->field_data1 != NULL)
@@ -243,6 +194,66 @@ int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src)
243 } 194 }
244 195
245 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
246int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 257int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
247 { 258 {
248 if (group->field_data1 == NULL) 259 if (group->field_data1 == NULL)
@@ -295,7 +306,7 @@ int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, BN_CTX *ctx)
295 { 306 {
296 if (group->field_data2 == NULL) 307 if (group->field_data2 == NULL)
297 { 308 {
298 ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED); 309 ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED);
299 return 0; 310 return 0;
300 } 311 }
301 312
diff --git a/src/lib/libcrypto/ec/ecp_nist.c b/src/lib/libcrypto/ec/ecp_nist.c
index ed07748675..71893d5eab 100644
--- a/src/lib/libcrypto/ec/ecp_nist.c
+++ b/src/lib/libcrypto/ec/ecp_nist.c
@@ -1,6 +1,9 @@
1/* crypto/ec/ecp_nist.c */ 1/* crypto/ec/ecp_nist.c */
2/*
3 * Written by Nils Larsch for the OpenSSL project.
4 */
2/* ==================================================================== 5/* ====================================================================
3 * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 6 * Copyright (c) 1998-2003 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,23 +55,30 @@
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 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
61 * and contributed to the OpenSSL project.
62 */
55 63
64#include <limits.h>
65
66#include <openssl/err.h>
67#include <openssl/obj_mac.h>
56#include "ec_lcl.h" 68#include "ec_lcl.h"
57 69
58#if 0
59const EC_METHOD *EC_GFp_nist_method(void) 70const EC_METHOD *EC_GFp_nist_method(void)
60 { 71 {
61 static const EC_METHOD ret = { 72 static const EC_METHOD ret = {
62 ec_GFp_nist_group_init, 73 NID_X9_62_prime_field,
63 ec_GFp_nist_group_finish, 74 ec_GFp_simple_group_init,
64 ec_GFp_nist_group_clear_finish, 75 ec_GFp_simple_group_finish,
76 ec_GFp_simple_group_clear_finish,
65 ec_GFp_nist_group_copy, 77 ec_GFp_nist_group_copy,
66 ec_GFp_nist_group_set_curve_GFp, 78 ec_GFp_nist_group_set_curve,
67 ec_GFp_simple_group_get_curve_GFp, 79 ec_GFp_simple_group_get_curve,
68 ec_GFp_simple_group_set_generator, 80 ec_GFp_simple_group_get_degree,
69 ec_GFp_simple_group_get0_generator, 81 ec_GFp_simple_group_check_discriminant,
70 ec_GFp_simple_group_get_order,
71 ec_GFp_simple_group_get_cofactor,
72 ec_GFp_simple_point_init, 82 ec_GFp_simple_point_init,
73 ec_GFp_simple_point_finish, 83 ec_GFp_simple_point_finish,
74 ec_GFp_simple_point_clear_finish, 84 ec_GFp_simple_point_clear_finish,
@@ -76,9 +86,9 @@ const EC_METHOD *EC_GFp_nist_method(void)
76 ec_GFp_simple_point_set_to_infinity, 86 ec_GFp_simple_point_set_to_infinity,
77 ec_GFp_simple_set_Jprojective_coordinates_GFp, 87 ec_GFp_simple_set_Jprojective_coordinates_GFp,
78 ec_GFp_simple_get_Jprojective_coordinates_GFp, 88 ec_GFp_simple_get_Jprojective_coordinates_GFp,
79 ec_GFp_simple_point_set_affine_coordinates_GFp, 89 ec_GFp_simple_point_set_affine_coordinates,
80 ec_GFp_simple_point_get_affine_coordinates_GFp, 90 ec_GFp_simple_point_get_affine_coordinates,
81 ec_GFp_simple_set_compressed_coordinates_GFp, 91 ec_GFp_simple_set_compressed_coordinates,
82 ec_GFp_simple_point2oct, 92 ec_GFp_simple_point2oct,
83 ec_GFp_simple_oct2point, 93 ec_GFp_simple_oct2point,
84 ec_GFp_simple_add, 94 ec_GFp_simple_add,
@@ -89,46 +99,138 @@ const EC_METHOD *EC_GFp_nist_method(void)
89 ec_GFp_simple_cmp, 99 ec_GFp_simple_cmp,
90 ec_GFp_simple_make_affine, 100 ec_GFp_simple_make_affine,
91 ec_GFp_simple_points_make_affine, 101 ec_GFp_simple_points_make_affine,
102 0 /* mul */,
103 0 /* precompute_mult */,
104 0 /* have_precompute_mult */,
92 ec_GFp_nist_field_mul, 105 ec_GFp_nist_field_mul,
93 ec_GFp_nist_field_sqr, 106 ec_GFp_nist_field_sqr,
107 0 /* field_div */,
94 0 /* field_encode */, 108 0 /* field_encode */,
95 0 /* field_decode */, 109 0 /* field_decode */,
96 0 /* field_set_to_one */ }; 110 0 /* field_set_to_one */ };
97 111
98 return &ret; 112 return &ret;
99 } 113 }
100#endif
101 114
115#if BN_BITS2 == 64
116#define NO_32_BIT_TYPE
117#endif
102 118
103int ec_GFp_nist_group_init(EC_GROUP *group) 119int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src)
104 { 120 {
105 int ok; 121 dest->field_mod_func = src->field_mod_func;
106 122
107 ok = ec_GFp_simple_group_init(group); 123 return ec_GFp_simple_group_copy(dest, src);
108 group->field_data1 = NULL;
109 return ok;
110 } 124 }
111 125
112 126int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p,
113int ec_GFp_nist_group_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); 127 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
114/* TODO */ 128 {
115 129 int ret = 0;
116 130 BN_CTX *new_ctx = NULL;
117void ec_GFp_nist_group_finish(EC_GROUP *group); 131 BIGNUM *tmp_bn;
118/* TODO */ 132
119 133 if (ctx == NULL)
120 134 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
121void ec_GFp_nist_group_clear_finish(EC_GROUP *group); 135
122/* TODO */ 136 BN_CTX_start(ctx);
123 137 if ((tmp_bn = BN_CTX_get(ctx)) == NULL) goto err;
124 138
125int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src); 139 if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0)
126/* TODO */ 140 group->field_mod_func = BN_nist_mod_192;
141 else if (BN_ucmp(BN_get0_nist_prime_224(), p) == 0)
142 {
143#ifndef NO_32_BIT_TYPE
144 group->field_mod_func = BN_nist_mod_224;
145#else
146 ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_SUPPORTED_NIST_PRIME);
147 goto err;
148#endif
149 }
150 else if (BN_ucmp(BN_get0_nist_prime_256(), p) == 0)
151 {
152#ifndef NO_32_BIT_TYPE
153 group->field_mod_func = BN_nist_mod_256;
154#else
155 ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_SUPPORTED_NIST_PRIME);
156 goto err;
157#endif
158 }
159 else if (BN_ucmp(BN_get0_nist_prime_384(), p) == 0)
160 {
161#ifndef NO_32_BIT_TYPE
162 group->field_mod_func = BN_nist_mod_384;
163#else
164 ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_SUPPORTED_NIST_PRIME);
165 goto err;
166#endif
167 }
168 else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0)
169 /* this one works in the NO_32_BIT_TYPE case */
170 group->field_mod_func = BN_nist_mod_521;
171 else
172 {
173 ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_NIST_PRIME);
174 goto err;
175 }
176
177 ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
178
179 err:
180 BN_CTX_end(ctx);
181 if (new_ctx != NULL)
182 BN_CTX_free(new_ctx);
183 return ret;
184 }
127 185
128 186
129int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); 187int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
130/* TODO */ 188 const BIGNUM *b, BN_CTX *ctx)
189 {
190 int ret=0;
191 BN_CTX *ctx_new=NULL;
192
193 if (!group || !r || !a || !b)
194 {
195 ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_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_mul(r, a, b, 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 }
131 211
132 212
133int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); 213int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
134/* TODO */ 214 BN_CTX *ctx)
215 {
216 int ret=0;
217 BN_CTX *ctx_new=NULL;
218
219 if (!group || !r || !a)
220 {
221 ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER);
222 goto err;
223 }
224 if (!ctx)
225 if ((ctx_new = ctx = BN_CTX_new()) == NULL) goto err;
226
227 if (!BN_sqr(r, a, ctx)) goto err;
228 if (!group->field_mod_func(r, r, &group->field, ctx))
229 goto err;
230
231 ret=1;
232err:
233 if (ctx_new)
234 BN_CTX_free(ctx_new);
235 return ret;
236 }
diff --git a/src/lib/libcrypto/ec/ecp_smpl.c b/src/lib/libcrypto/ec/ecp_smpl.c
index e9a51fb87a..4d26f8bdf6 100644
--- a/src/lib/libcrypto/ec/ecp_smpl.c
+++ b/src/lib/libcrypto/ec/ecp_smpl.c
@@ -1,8 +1,10 @@
1/* crypto/ec/ecp_smpl.c */ 1/* crypto/ec/ecp_smpl.c */
2/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> 2/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
3 * for the OpenSSL project. */ 3 * for the OpenSSL project.
4 * Includes code written by Bodo Moeller for the OpenSSL project.
5*/
4/* ==================================================================== 6/* ====================================================================
5 * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 7 * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
@@ -54,25 +56,29 @@
54 * Hudson (tjh@cryptsoft.com). 56 * Hudson (tjh@cryptsoft.com).
55 * 57 *
56 */ 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 */
57 64
58#include <openssl/err.h> 65#include <openssl/err.h>
66#include <openssl/symhacks.h>
59 67
60#include "ec_lcl.h" 68#include "ec_lcl.h"
61 69
62
63const EC_METHOD *EC_GFp_simple_method(void) 70const EC_METHOD *EC_GFp_simple_method(void)
64 { 71 {
65 static const EC_METHOD ret = { 72 static const EC_METHOD ret = {
73 NID_X9_62_prime_field,
66 ec_GFp_simple_group_init, 74 ec_GFp_simple_group_init,
67 ec_GFp_simple_group_finish, 75 ec_GFp_simple_group_finish,
68 ec_GFp_simple_group_clear_finish, 76 ec_GFp_simple_group_clear_finish,
69 ec_GFp_simple_group_copy, 77 ec_GFp_simple_group_copy,
70 ec_GFp_simple_group_set_curve_GFp, 78 ec_GFp_simple_group_set_curve,
71 ec_GFp_simple_group_get_curve_GFp, 79 ec_GFp_simple_group_get_curve,
72 ec_GFp_simple_group_set_generator, 80 ec_GFp_simple_group_get_degree,
73 ec_GFp_simple_group_get0_generator, 81 ec_GFp_simple_group_check_discriminant,
74 ec_GFp_simple_group_get_order,
75 ec_GFp_simple_group_get_cofactor,
76 ec_GFp_simple_point_init, 82 ec_GFp_simple_point_init,
77 ec_GFp_simple_point_finish, 83 ec_GFp_simple_point_finish,
78 ec_GFp_simple_point_clear_finish, 84 ec_GFp_simple_point_clear_finish,
@@ -80,9 +86,9 @@ const EC_METHOD *EC_GFp_simple_method(void)
80 ec_GFp_simple_point_set_to_infinity, 86 ec_GFp_simple_point_set_to_infinity,
81 ec_GFp_simple_set_Jprojective_coordinates_GFp, 87 ec_GFp_simple_set_Jprojective_coordinates_GFp,
82 ec_GFp_simple_get_Jprojective_coordinates_GFp, 88 ec_GFp_simple_get_Jprojective_coordinates_GFp,
83 ec_GFp_simple_point_set_affine_coordinates_GFp, 89 ec_GFp_simple_point_set_affine_coordinates,
84 ec_GFp_simple_point_get_affine_coordinates_GFp, 90 ec_GFp_simple_point_get_affine_coordinates,
85 ec_GFp_simple_set_compressed_coordinates_GFp, 91 ec_GFp_simple_set_compressed_coordinates,
86 ec_GFp_simple_point2oct, 92 ec_GFp_simple_point2oct,
87 ec_GFp_simple_oct2point, 93 ec_GFp_simple_oct2point,
88 ec_GFp_simple_add, 94 ec_GFp_simple_add,
@@ -93,8 +99,12 @@ const EC_METHOD *EC_GFp_simple_method(void)
93 ec_GFp_simple_cmp, 99 ec_GFp_simple_cmp,
94 ec_GFp_simple_make_affine, 100 ec_GFp_simple_make_affine,
95 ec_GFp_simple_points_make_affine, 101 ec_GFp_simple_points_make_affine,
102 0 /* mul */,
103 0 /* precompute_mult */,
104 0 /* have_precompute_mult */,
96 ec_GFp_simple_field_mul, 105 ec_GFp_simple_field_mul,
97 ec_GFp_simple_field_sqr, 106 ec_GFp_simple_field_sqr,
107 0 /* field_div */,
98 0 /* field_encode */, 108 0 /* field_encode */,
99 0 /* field_decode */, 109 0 /* field_decode */,
100 0 /* field_set_to_one */ }; 110 0 /* field_set_to_one */ };
@@ -103,15 +113,26 @@ const EC_METHOD *EC_GFp_simple_method(void)
103 } 113 }
104 114
105 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
106int ec_GFp_simple_group_init(EC_GROUP *group) 130int ec_GFp_simple_group_init(EC_GROUP *group)
107 { 131 {
108 BN_init(&group->field); 132 BN_init(&group->field);
109 BN_init(&group->a); 133 BN_init(&group->a);
110 BN_init(&group->b); 134 BN_init(&group->b);
111 group->a_is_minus3 = 0; 135 group->a_is_minus3 = 0;
112 group->generator = NULL;
113 BN_init(&group->order);
114 BN_init(&group->cofactor);
115 return 1; 136 return 1;
116 } 137 }
117 138
@@ -121,10 +142,6 @@ void ec_GFp_simple_group_finish(EC_GROUP *group)
121 BN_free(&group->field); 142 BN_free(&group->field);
122 BN_free(&group->a); 143 BN_free(&group->a);
123 BN_free(&group->b); 144 BN_free(&group->b);
124 if (group->generator != NULL)
125 EC_POINT_free(group->generator);
126 BN_free(&group->order);
127 BN_free(&group->cofactor);
128 } 145 }
129 146
130 147
@@ -133,13 +150,6 @@ void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
133 BN_clear_free(&group->field); 150 BN_clear_free(&group->field);
134 BN_clear_free(&group->a); 151 BN_clear_free(&group->a);
135 BN_clear_free(&group->b); 152 BN_clear_free(&group->b);
136 if (group->generator != NULL)
137 {
138 EC_POINT_clear_free(group->generator);
139 group->generator = NULL;
140 }
141 BN_clear_free(&group->order);
142 BN_clear_free(&group->cofactor);
143 } 153 }
144 154
145 155
@@ -151,33 +161,11 @@ int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
151 161
152 dest->a_is_minus3 = src->a_is_minus3; 162 dest->a_is_minus3 = src->a_is_minus3;
153 163
154 if (src->generator != NULL)
155 {
156 if (dest->generator == NULL)
157 {
158 dest->generator = EC_POINT_new(dest);
159 if (dest->generator == NULL) return 0;
160 }
161 if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
162 }
163 else
164 {
165 /* src->generator == NULL */
166 if (dest->generator != NULL)
167 {
168 EC_POINT_clear_free(dest->generator);
169 dest->generator = NULL;
170 }
171 }
172
173 if (!BN_copy(&dest->order, &src->order)) return 0;
174 if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
175
176 return 1; 164 return 1;
177 } 165 }
178 166
179 167
180int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group, 168int ec_GFp_simple_group_set_curve(EC_GROUP *group,
181 const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 169 const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
182 { 170 {
183 int ret = 0; 171 int ret = 0;
@@ -187,7 +175,7 @@ int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group,
187 /* p must be a prime > 3 */ 175 /* p must be a prime > 3 */
188 if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) 176 if (BN_num_bits(p) <= 2 || !BN_is_odd(p))
189 { 177 {
190 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP, EC_R_INVALID_FIELD); 178 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
191 return 0; 179 return 0;
192 } 180 }
193 181
@@ -204,7 +192,7 @@ int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group,
204 192
205 /* group->field */ 193 /* group->field */
206 if (!BN_copy(&group->field, p)) goto err; 194 if (!BN_copy(&group->field, p)) goto err;
207 group->field.neg = 0; 195 BN_set_negative(&group->field, 0);
208 196
209 /* group->a */ 197 /* group->a */
210 if (!BN_nnmod(tmp_a, a, p, ctx)) goto err; 198 if (!BN_nnmod(tmp_a, a, p, ctx)) goto err;
@@ -232,7 +220,7 @@ int ec_GFp_simple_group_set_curve_GFp(EC_GROUP *group,
232 } 220 }
233 221
234 222
235int ec_GFp_simple_group_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx) 223int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
236 { 224 {
237 int ret = 0; 225 int ret = 0;
238 BN_CTX *new_ctx = NULL; 226 BN_CTX *new_ctx = NULL;
@@ -283,58 +271,76 @@ int ec_GFp_simple_group_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *
283 } 271 }
284 272
285 273
274int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
275 {
276 return BN_num_bits(&group->field);
277 }
278
286 279
287int ec_GFp_simple_group_set_generator(EC_GROUP *group, const EC_POINT *generator, 280int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
288 const BIGNUM *order, const BIGNUM *cofactor)
289 { 281 {
290 if (generator == NULL) 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)
291 { 288 {
292 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER); 289 ctx = new_ctx = BN_CTX_new();
293 return 0 ; 290 if (ctx == NULL)
291 {
292 ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, ERR_R_MALLOC_FAILURE);
293 goto err;
294 }
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;
295 303
296 if (group->generator == NULL) 304 if (group->meth->field_decode)
297 { 305 {
298 group->generator = EC_POINT_new(group); 306 if (!group->meth->field_decode(group, a, &group->a, ctx)) goto err;
299 if (group->generator == NULL) return 0; 307 if (!group->meth->field_decode(group, b, &group->b, ctx)) goto err;
300 } 308 }
301 if (!EC_POINT_copy(group->generator, generator)) return 0;
302
303 if (order != NULL)
304 { if (!BN_copy(&group->order, order)) return 0; }
305 else
306 { if (!BN_zero(&group->order)) return 0; }
307
308 if (cofactor != NULL)
309 { if (!BN_copy(&group->cofactor, cofactor)) return 0; }
310 else 309 else
311 { if (!BN_zero(&group->cofactor)) return 0; } 310 {
312 311 if (!BN_copy(a, &group->a)) goto err;
313 return 1; 312 if (!BN_copy(b, &group->b)) goto err;
314 } 313 }
315 314
316 315 /* check the discriminant:
317EC_POINT *ec_GFp_simple_group_get0_generator(const EC_GROUP *group) 316 * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
318 { 317 * 0 =< a, b < p */
319 return group->generator; 318 if (BN_is_zero(a))
320 } 319 {
321 320 if (BN_is_zero(b)) goto err;
322 321 }
323int ec_GFp_simple_group_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) 322 else if (!BN_is_zero(b))
324 { 323 {
325 if (!BN_copy(order, &group->order)) 324 if (!BN_mod_sqr(tmp_1, a, p, ctx)) goto err;
326 return 0; 325 if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx)) goto err;
327 326 if (!BN_lshift(tmp_1, tmp_2, 2)) goto err;
328 return !BN_is_zero(&group->order); 327 /* tmp_1 = 4*a^3 */
329 }
330 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 */
331 332
332int ec_GFp_simple_group_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx) 333 if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx)) goto err;
333 { 334 if (BN_is_zero(a)) goto err;
334 if (!BN_copy(cofactor, &group->cofactor)) 335 }
335 return 0; 336 ret = 1;
336 337
337 return !BN_is_zero(&group->cofactor); 338err:
339 if (ctx != NULL)
340 BN_CTX_end(ctx);
341 if (new_ctx != NULL)
342 BN_CTX_free(new_ctx);
343 return ret;
338 } 344 }
339 345
340 346
@@ -380,7 +386,8 @@ int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
380int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point) 386int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
381 { 387 {
382 point->Z_is_one = 0; 388 point->Z_is_one = 0;
383 return (BN_zero(&point->Z)); 389 BN_zero(&point->Z);
390 return 1;
384 } 391 }
385 392
386 393
@@ -497,13 +504,13 @@ int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const E
497 } 504 }
498 505
499 506
500int ec_GFp_simple_point_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 507int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
501 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 508 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
502 { 509 {
503 if (x == NULL || y == NULL) 510 if (x == NULL || y == NULL)
504 { 511 {
505 /* unlike for projective coordinates, we do not tolerate this */ 512 /* unlike for projective coordinates, we do not tolerate this */
506 ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_PASSED_NULL_PARAMETER); 513 ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER);
507 return 0; 514 return 0;
508 } 515 }
509 516
@@ -511,17 +518,17 @@ int ec_GFp_simple_point_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POI
511 } 518 }
512 519
513 520
514int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point, 521int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
515 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 522 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
516 { 523 {
517 BN_CTX *new_ctx = NULL; 524 BN_CTX *new_ctx = NULL;
518 BIGNUM *X, *Y, *Z, *Z_1, *Z_2, *Z_3; 525 BIGNUM *Z, *Z_1, *Z_2, *Z_3;
519 const BIGNUM *X_, *Y_, *Z_; 526 const BIGNUM *Z_;
520 int ret = 0; 527 int ret = 0;
521 528
522 if (EC_POINT_is_at_infinity(group, point)) 529 if (EC_POINT_is_at_infinity(group, point))
523 { 530 {
524 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_POINT_AT_INFINITY); 531 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
525 return 0; 532 return 0;
526 } 533 }
527 534
@@ -533,8 +540,6 @@ int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const
533 } 540 }
534 541
535 BN_CTX_start(ctx); 542 BN_CTX_start(ctx);
536 X = BN_CTX_get(ctx);
537 Y = BN_CTX_get(ctx);
538 Z = BN_CTX_get(ctx); 543 Z = BN_CTX_get(ctx);
539 Z_1 = BN_CTX_get(ctx); 544 Z_1 = BN_CTX_get(ctx);
540 Z_2 = BN_CTX_get(ctx); 545 Z_2 = BN_CTX_get(ctx);
@@ -545,34 +550,44 @@ int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const
545 550
546 if (group->meth->field_decode) 551 if (group->meth->field_decode)
547 { 552 {
548 if (!group->meth->field_decode(group, X, &point->X, ctx)) goto err;
549 if (!group->meth->field_decode(group, Y, &point->Y, ctx)) goto err;
550 if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err; 553 if (!group->meth->field_decode(group, Z, &point->Z, ctx)) goto err;
551 X_ = X; Y_ = Y; Z_ = Z; 554 Z_ = Z;
552 } 555 }
553 else 556 else
554 { 557 {
555 X_ = &point->X;
556 Y_ = &point->Y;
557 Z_ = &point->Z; 558 Z_ = &point->Z;
558 } 559 }
559 560
560 if (BN_is_one(Z_)) 561 if (BN_is_one(Z_))
561 { 562 {
562 if (x != NULL) 563 if (group->meth->field_decode)
563 { 564 {
564 if (!BN_copy(x, X_)) goto err; 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 }
565 } 573 }
566 if (y != NULL) 574 else
567 { 575 {
568 if (!BN_copy(y, Y_)) goto err; 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 }
569 } 584 }
570 } 585 }
571 else 586 else
572 { 587 {
573 if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) 588 if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx))
574 { 589 {
575 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_BN_LIB); 590 ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
576 goto err; 591 goto err;
577 } 592 }
578 593
@@ -588,15 +603,8 @@ int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const
588 603
589 if (x != NULL) 604 if (x != NULL)
590 { 605 {
591 if (group->meth->field_encode == 0) 606 /* in the Montgomery case, field_mul will cancel out Montgomery factor in X: */
592 { 607 if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx)) goto err;
593 /* field_mul works on standard representation */
594 if (!group->meth->field_mul(group, x, X_, Z_2, ctx)) goto err;
595 }
596 else
597 {
598 if (!BN_mod_mul(x, X_, Z_2, &group->field, ctx)) goto err;
599 }
600 } 608 }
601 609
602 if (y != NULL) 610 if (y != NULL)
@@ -605,14 +613,14 @@ int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const
605 { 613 {
606 /* field_mul works on standard representation */ 614 /* field_mul works on standard representation */
607 if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err; 615 if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) goto err;
608 if (!group->meth->field_mul(group, y, Y_, Z_3, ctx)) goto err;
609
610 } 616 }
611 else 617 else
612 { 618 {
613 if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err; 619 if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) goto err;
614 if (!BN_mod_mul(y, Y_, Z_3, &group->field, ctx)) goto err;
615 } 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;
616 } 624 }
617 } 625 }
618 626
@@ -626,13 +634,16 @@ int ec_GFp_simple_point_get_affine_coordinates_GFp(const EC_GROUP *group, const
626 } 634 }
627 635
628 636
629int ec_GFp_simple_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point, 637int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
630 const BIGNUM *x_, int y_bit, BN_CTX *ctx) 638 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
631 { 639 {
632 BN_CTX *new_ctx = NULL; 640 BN_CTX *new_ctx = NULL;
633 BIGNUM *tmp1, *tmp2, *x, *y; 641 BIGNUM *tmp1, *tmp2, *x, *y;
634 int ret = 0; 642 int ret = 0;
635 643
644 /* clear error queue*/
645 ERR_clear_error();
646
636 if (ctx == NULL) 647 if (ctx == NULL)
637 { 648 {
638 ctx = new_ctx = BN_CTX_new(); 649 ctx = new_ctx = BN_CTX_new();
@@ -704,19 +715,17 @@ int ec_GFp_simple_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT
704 715
705 if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) 716 if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
706 { 717 {
707 unsigned long err = ERR_peek_error(); 718 unsigned long err = ERR_peek_last_error();
708 719
709 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) 720 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
710 { 721 {
711 (void)ERR_get_error(); 722 ERR_clear_error();
712 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, EC_R_INVALID_COMPRESSED_POINT); 723 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
713 } 724 }
714 else 725 else
715 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, ERR_R_BN_LIB); 726 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
716 goto err; 727 goto err;
717 } 728 }
718 /* If tmp1 is not a square (i.e. there is no point on the curve with
719 * our x), then y now is a nonsense value too */
720 729
721 if (y_bit != BN_is_odd(y)) 730 if (y_bit != BN_is_odd(y))
722 { 731 {
@@ -728,16 +737,17 @@ int ec_GFp_simple_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT
728 if (kron == -2) goto err; 737 if (kron == -2) goto err;
729 738
730 if (kron == 1) 739 if (kron == 1)
731 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, EC_R_INVALID_COMPRESSION_BIT); 740 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
732 else 741 else
733 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, EC_R_INVALID_COMPRESSED_POINT); 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);
734 goto err; 744 goto err;
735 } 745 }
736 if (!BN_usub(y, &group->field, y)) goto err; 746 if (!BN_usub(y, &group->field, y)) goto err;
737 } 747 }
738 if (y_bit != BN_is_odd(y)) 748 if (y_bit != BN_is_odd(y))
739 { 749 {
740 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP, ERR_R_INTERNAL_ERROR); 750 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
741 goto err; 751 goto err;
742 } 752 }
743 753
@@ -1088,7 +1098,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, con
1088 else 1098 else
1089 { 1099 {
1090 /* a is the inverse of b */ 1100 /* a is the inverse of b */
1091 if (!BN_zero(&r->Z)) goto end; 1101 BN_zero(&r->Z);
1092 r->Z_is_one = 0; 1102 r->Z_is_one = 0;
1093 ret = 1; 1103 ret = 1;
1094 goto end; 1104 goto end;
@@ -1164,7 +1174,7 @@ int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_
1164 1174
1165 if (EC_POINT_is_at_infinity(group, a)) 1175 if (EC_POINT_is_at_infinity(group, a))
1166 { 1176 {
1167 if (!BN_zero(&r->Z)) return 0; 1177 BN_zero(&r->Z);
1168 r->Z_is_one = 0; 1178 r->Z_is_one = 0;
1169 return 1; 1179 return 1;
1170 } 1180 }
@@ -1292,7 +1302,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C
1292 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); 1302 int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
1293 const BIGNUM *p; 1303 const BIGNUM *p;
1294 BN_CTX *new_ctx = NULL; 1304 BN_CTX *new_ctx = NULL;
1295 BIGNUM *rh, *tmp1, *tmp2, *Z4, *Z6; 1305 BIGNUM *rh, *tmp, *Z4, *Z6;
1296 int ret = -1; 1306 int ret = -1;
1297 1307
1298 if (EC_POINT_is_at_infinity(group, point)) 1308 if (EC_POINT_is_at_infinity(group, point))
@@ -1311,8 +1321,7 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C
1311 1321
1312 BN_CTX_start(ctx); 1322 BN_CTX_start(ctx);
1313 rh = BN_CTX_get(ctx); 1323 rh = BN_CTX_get(ctx);
1314 tmp1 = BN_CTX_get(ctx); 1324 tmp = BN_CTX_get(ctx);
1315 tmp2 = BN_CTX_get(ctx);
1316 Z4 = BN_CTX_get(ctx); 1325 Z4 = BN_CTX_get(ctx);
1317 Z6 = BN_CTX_get(ctx); 1326 Z6 = BN_CTX_get(ctx);
1318 if (Z6 == NULL) goto err; 1327 if (Z6 == NULL) goto err;
@@ -1326,59 +1335,49 @@ int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_C
1326 * To test this, we add up the right-hand side in 'rh'. 1335 * To test this, we add up the right-hand side in 'rh'.
1327 */ 1336 */
1328 1337
1329 /* rh := X^3 */ 1338 /* rh := X^2 */
1330 if (!field_sqr(group, rh, &point->X, ctx)) goto err; 1339 if (!field_sqr(group, rh, &point->X, ctx)) goto err;
1331 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1332 1340
1333 if (!point->Z_is_one) 1341 if (!point->Z_is_one)
1334 { 1342 {
1335 if (!field_sqr(group, tmp1, &point->Z, ctx)) goto err; 1343 if (!field_sqr(group, tmp, &point->Z, ctx)) goto err;
1336 if (!field_sqr(group, Z4, tmp1, ctx)) goto err; 1344 if (!field_sqr(group, Z4, tmp, ctx)) goto err;
1337 if (!field_mul(group, Z6, Z4, tmp1, ctx)) goto err; 1345 if (!field_mul(group, Z6, Z4, tmp, ctx)) goto err;
1338 1346
1339 /* rh := rh + a*X*Z^4 */ 1347 /* rh := (rh + a*Z^4)*X */
1340 if (!field_mul(group, tmp1, &point->X, Z4, ctx)) goto err;
1341 if (group->a_is_minus3) 1348 if (group->a_is_minus3)
1342 { 1349 {
1343 if (!BN_mod_lshift1_quick(tmp2, tmp1, p)) goto err; 1350 if (!BN_mod_lshift1_quick(tmp, Z4, p)) goto err;
1344 if (!BN_mod_add_quick(tmp2, tmp2, tmp1, p)) goto err; 1351 if (!BN_mod_add_quick(tmp, tmp, Z4, p)) goto err;
1345 if (!BN_mod_sub_quick(rh, rh, tmp2, 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;
1346 } 1354 }
1347 else 1355 else
1348 { 1356 {
1349 if (!field_mul(group, tmp2, tmp1, &group->a, ctx)) goto err; 1357 if (!field_mul(group, tmp, Z4, &group->a, ctx)) goto err;
1350 if (!BN_mod_add_quick(rh, rh, tmp2, p)) 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;
1351 } 1360 }
1352 1361
1353 /* rh := rh + b*Z^6 */ 1362 /* rh := rh + b*Z^6 */
1354 if (!field_mul(group, tmp1, &group->b, Z6, ctx)) goto err; 1363 if (!field_mul(group, tmp, &group->b, Z6, ctx)) goto err;
1355 if (!BN_mod_add_quick(rh, rh, tmp1, p)) goto err; 1364 if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err;
1356 } 1365 }
1357 else 1366 else
1358 { 1367 {
1359 /* point->Z_is_one */ 1368 /* point->Z_is_one */
1360 1369
1361 /* rh := rh + a*X */ 1370 /* rh := (rh + a)*X */
1362 if (group->a_is_minus3) 1371 if (!BN_mod_add_quick(rh, rh, &group->a, p)) goto err;
1363 { 1372 if (!field_mul(group, rh, rh, &point->X, ctx)) goto err;
1364 if (!BN_mod_lshift1_quick(tmp2, &point->X, p)) goto err;
1365 if (!BN_mod_add_quick(tmp2, tmp2, &point->X, p)) goto err;
1366 if (!BN_mod_sub_quick(rh, rh, tmp2, p)) goto err;
1367 }
1368 else
1369 {
1370 if (!field_mul(group, tmp2, &point->X, &group->a, ctx)) goto err;
1371 if (!BN_mod_add_quick(rh, rh, tmp2, p)) goto err;
1372 }
1373
1374 /* rh := rh + b */ 1373 /* rh := rh + b */
1375 if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err; 1374 if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err;
1376 } 1375 }
1377 1376
1378 /* 'lh' := Y^2 */ 1377 /* 'lh' := Y^2 */
1379 if (!field_sqr(group, tmp1, &point->Y, ctx)) goto err; 1378 if (!field_sqr(group, tmp, &point->Y, ctx)) goto err;
1380 1379
1381 ret = (0 == BN_cmp(tmp1, rh)); 1380 ret = (0 == BN_ucmp(tmp, rh));
1382 1381
1383 err: 1382 err:
1384 BN_CTX_end(ctx); 1383 BN_CTX_end(ctx);
diff --git a/src/lib/libcrypto/ec/ectest.c b/src/lib/libcrypto/ec/ectest.c
index fcf969f3cf..6148d553f9 100644
--- a/src/lib/libcrypto/ec/ectest.c
+++ b/src/lib/libcrypto/ec/ectest.c
@@ -1,4 +1,7 @@
1/* crypto/ec/ectest.c */ 1/* crypto/ec/ectest.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-2001 The OpenSSL Project. All rights reserved.
4 * 7 *
@@ -52,6 +55,19 @@
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
56#include <stdio.h> 72#include <stdio.h>
57#include <stdlib.h> 73#include <stdlib.h>
@@ -74,6 +90,15 @@ int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); retur
74#include <openssl/engine.h> 90#include <openssl/engine.h>
75#endif 91#endif
76#include <openssl/err.h> 92#include <openssl/err.h>
93#include <openssl/obj_mac.h>
94#include <openssl/objects.h>
95#include <openssl/rand.h>
96#include <openssl/bn.h>
97
98#if defined(_MSC_VER) && defined(_MIPS_) && (_MSC_VER/100==12)
99/* suppress "too big too optimize" warning */
100#pragma warning(disable:4959)
101#endif
77 102
78#define ABORT do { \ 103#define ABORT do { \
79 fflush(stdout); \ 104 fflush(stdout); \
@@ -82,47 +107,59 @@ int main(int argc, char * argv[]) { puts("Elliptic curves are disabled."); retur
82 EXIT(1); \ 107 EXIT(1); \
83} while (0) 108} while (0)
84 109
110void prime_field_tests(void);
111void char2_field_tests(void);
112void internal_curve_test(void);
113
114#define TIMING_BASE_PT 0
115#define TIMING_RAND_PT 1
116#define TIMING_SIMUL 2
117
85#if 0 118#if 0
86static void timings(EC_GROUP *group, int multi, BN_CTX *ctx) 119static void timings(EC_GROUP *group, int type, BN_CTX *ctx)
87 { 120 {
88 clock_t clck; 121 clock_t clck;
89 int i, j; 122 int i, j;
90 BIGNUM *s, *s0; 123 BIGNUM *s;
124 BIGNUM *r[10], *r0[10];
91 EC_POINT *P; 125 EC_POINT *P;
92 126
93 s = BN_new(); 127 s = BN_new();
94 s0 = BN_new(); 128 if (s == NULL) ABORT;
95 if (s == NULL || s0 == NULL) ABORT;
96 129
97 if (!EC_GROUP_get_curve_GFp(group, s, NULL, NULL, ctx)) ABORT; 130 fprintf(stdout, "Timings for %d-bit field, ", EC_GROUP_get_degree(group));
98 fprintf(stdout, "Timings for %d bit prime, ", (int)BN_num_bits(s));
99 if (!EC_GROUP_get_order(group, s, ctx)) ABORT; 131 if (!EC_GROUP_get_order(group, s, ctx)) ABORT;
100 fprintf(stdout, "%d bit scalars ", (int)BN_num_bits(s)); 132 fprintf(stdout, "%d-bit scalars ", (int)BN_num_bits(s));
101 fflush(stdout); 133 fflush(stdout);
102 134
103 P = EC_POINT_new(group); 135 P = EC_POINT_new(group);
104 if (P == NULL) ABORT; 136 if (P == NULL) ABORT;
105 EC_POINT_copy(P, EC_GROUP_get0_generator(group)); 137 EC_POINT_copy(P, EC_GROUP_get0_generator(group));
106 138
107 clck = clock();
108 for (i = 0; i < 10; i++) 139 for (i = 0; i < 10; i++)
109 { 140 {
110 if (!BN_pseudo_rand(s, BN_num_bits(s), 0, 0)) ABORT; 141 if ((r[i] = BN_new()) == NULL) ABORT;
111 if (multi) 142 if (!BN_pseudo_rand(r[i], BN_num_bits(s), 0, 0)) ABORT;
143 if (type != TIMING_BASE_PT)
112 { 144 {
113 if (!BN_pseudo_rand(s0, BN_num_bits(s), 0, 0)) ABORT; 145 if ((r0[i] = BN_new()) == NULL) ABORT;
146 if (!BN_pseudo_rand(r0[i], BN_num_bits(s), 0, 0)) ABORT;
114 } 147 }
148 }
149
150 clck = clock();
151 for (i = 0; i < 10; i++)
152 {
115 for (j = 0; j < 10; j++) 153 for (j = 0; j < 10; j++)
116 { 154 {
117 if (!EC_POINT_mul(group, P, s, multi ? P : NULL, multi ? s0 : NULL, ctx)) ABORT; 155 if (!EC_POINT_mul(group, P, (type != TIMING_RAND_PT) ? r[i] : NULL,
156 (type != TIMING_BASE_PT) ? P : NULL, (type != TIMING_BASE_PT) ? r0[i] : NULL, ctx)) ABORT;
118 } 157 }
119 fprintf(stdout, ".");
120 fflush(stdout);
121 } 158 }
122 fprintf(stdout, "\n");
123
124 clck = clock() - clck; 159 clck = clock() - clck;
125 160
161 fprintf(stdout, "\n");
162
126#ifdef CLOCKS_PER_SEC 163#ifdef CLOCKS_PER_SEC
127 /* "To determine the time in seconds, the value returned 164 /* "To determine the time in seconds, the value returned
128 * by the clock function should be divided by the value 165 * by the clock function should be divided by the value
@@ -136,43 +173,40 @@ static void timings(EC_GROUP *group, int multi, BN_CTX *ctx)
136# define CLOCKS_PER_SEC 1 173# define CLOCKS_PER_SEC 1
137#endif 174#endif
138 175
139 fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j, 176 if (type == TIMING_BASE_PT) {
140 multi ? "s*P+t*Q operations" : "point multiplications", 177 fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
141 (double)clck/CLOCKS_PER_SEC); 178 "base point multiplications", (double)clck/CLOCKS_PER_SEC);
179 } else if (type == TIMING_RAND_PT) {
180 fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
181 "random point multiplications", (double)clck/CLOCKS_PER_SEC);
182 } else if (type == TIMING_SIMUL) {
183 fprintf(stdout, "%i %s in %.2f " UNIT "\n", i*j,
184 "s*P+t*Q operations", (double)clck/CLOCKS_PER_SEC);
185 }
142 fprintf(stdout, "average: %.4f " UNIT "\n", (double)clck/(CLOCKS_PER_SEC*i*j)); 186 fprintf(stdout, "average: %.4f " UNIT "\n", (double)clck/(CLOCKS_PER_SEC*i*j));
143 187
144 EC_POINT_free(P); 188 EC_POINT_free(P);
145 BN_free(s); 189 BN_free(s);
146 BN_free(s0); 190 for (i = 0; i < 10; i++)
191 {
192 BN_free(r[i]);
193 if (type != TIMING_BASE_PT) BN_free(r0[i]);
194 }
147 } 195 }
148#endif 196#endif
149 197
150int main(int argc, char *argv[]) 198void prime_field_tests()
151 { 199 {
152 BN_CTX *ctx = NULL; 200 BN_CTX *ctx = NULL;
153 BIGNUM *p, *a, *b; 201 BIGNUM *p, *a, *b;
154 EC_GROUP *group; 202 EC_GROUP *group;
155 EC_GROUP *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL; 203 EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL;
156 EC_POINT *P, *Q, *R; 204 EC_POINT *P, *Q, *R;
157 BIGNUM *x, *y, *z; 205 BIGNUM *x, *y, *z;
158 unsigned char buf[100]; 206 unsigned char buf[100];
159 size_t i, len; 207 size_t i, len;
160 int k; 208 int k;
161 209
162 /* enable memory leak checking unless explicitly disabled */
163 if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
164 {
165 CRYPTO_malloc_debug_init();
166 CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
167 }
168 else
169 {
170 /* OPENSSL_DEBUG_MEMORY=off */
171 CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
172 }
173 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
174 ERR_load_crypto_strings();
175
176#if 1 /* optional */ 210#if 1 /* optional */
177 ctx = BN_CTX_new(); 211 ctx = BN_CTX_new();
178 if (!ctx) ABORT; 212 if (!ctx) ABORT;
@@ -317,10 +351,56 @@ int main(int argc, char *argv[])
317 if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT; 351 if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
318 352
319 353
354 /* Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, 2000)
355 * -- not a NIST curve, but commonly used */
356
357 if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) ABORT;
358 if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
359 if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) ABORT;
360 if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) ABORT;
361 if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
362
363 if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT;
364 if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
365 if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
366 if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
367 if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT;
368 if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
369
370 if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
371 fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n x = 0x");
372 BN_print_fp(stdout, x);
373 fprintf(stdout, "\n y = 0x");
374 BN_print_fp(stdout, y);
375 fprintf(stdout, "\n");
376 /* G_y value taken from the standard: */
377 if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
378 if (0 != BN_cmp(y, z)) ABORT;
379
380 fprintf(stdout, "verify degree ...");
381 if (EC_GROUP_get_degree(group) != 160) ABORT;
382 fprintf(stdout, " ok\n");
383
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");
395
396 if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT;
397 if (!EC_GROUP_copy(P_160, group)) ABORT;
398
399
320 /* Curve P-192 (FIPS PUB 186-2, App. 6) */ 400 /* Curve P-192 (FIPS PUB 186-2, App. 6) */
321 401
322 if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT; 402 if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) ABORT;
323 if (1 != BN_is_prime(p, BN_prime_checks, 0, ctx, NULL)) ABORT; 403 if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
324 if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT; 404 if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) ABORT;
325 if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT; 405 if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) ABORT;
326 if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; 406 if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
@@ -340,6 +420,10 @@ int main(int argc, char *argv[])
340 /* G_y value taken from the standard: */ 420 /* G_y value taken from the standard: */
341 if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT; 421 if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) ABORT;
342 if (0 != BN_cmp(y, z)) ABORT; 422 if (0 != BN_cmp(y, z)) ABORT;
423
424 fprintf(stdout, "verify degree ...");
425 if (EC_GROUP_get_degree(group) != 192) ABORT;
426 fprintf(stdout, " ok\n");
343 427
344 fprintf(stdout, "verify group order ..."); 428 fprintf(stdout, "verify group order ...");
345 fflush(stdout); 429 fflush(stdout);
@@ -348,7 +432,9 @@ int main(int argc, char *argv[])
348 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; 432 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
349 fprintf(stdout, "."); 433 fprintf(stdout, ".");
350 fflush(stdout); 434 fflush(stdout);
435#if 0
351 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; 436 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
437#endif
352 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; 438 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
353 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; 439 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
354 fprintf(stdout, " ok\n"); 440 fprintf(stdout, " ok\n");
@@ -360,7 +446,7 @@ int main(int argc, char *argv[])
360 /* Curve P-224 (FIPS PUB 186-2, App. 6) */ 446 /* Curve P-224 (FIPS PUB 186-2, App. 6) */
361 447
362 if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT; 448 if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) ABORT;
363 if (1 != BN_is_prime(p, BN_prime_checks, 0, ctx, NULL)) ABORT; 449 if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
364 if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT; 450 if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) ABORT;
365 if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT; 451 if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) ABORT;
366 if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; 452 if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
@@ -381,6 +467,10 @@ int main(int argc, char *argv[])
381 if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT; 467 if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) ABORT;
382 if (0 != BN_cmp(y, z)) ABORT; 468 if (0 != BN_cmp(y, z)) ABORT;
383 469
470 fprintf(stdout, "verify degree ...");
471 if (EC_GROUP_get_degree(group) != 224) ABORT;
472 fprintf(stdout, " ok\n");
473
384 fprintf(stdout, "verify group order ..."); 474 fprintf(stdout, "verify group order ...");
385 fflush(stdout); 475 fflush(stdout);
386 if (!EC_GROUP_get_order(group, z, ctx)) ABORT; 476 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
@@ -388,7 +478,9 @@ int main(int argc, char *argv[])
388 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; 478 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
389 fprintf(stdout, "."); 479 fprintf(stdout, ".");
390 fflush(stdout); 480 fflush(stdout);
481#if 0
391 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; 482 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
483#endif
392 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; 484 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
393 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; 485 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
394 fprintf(stdout, " ok\n"); 486 fprintf(stdout, " ok\n");
@@ -400,7 +492,7 @@ int main(int argc, char *argv[])
400 /* Curve P-256 (FIPS PUB 186-2, App. 6) */ 492 /* Curve P-256 (FIPS PUB 186-2, App. 6) */
401 493
402 if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT; 494 if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
403 if (1 != BN_is_prime(p, BN_prime_checks, 0, ctx, NULL)) ABORT; 495 if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
404 if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) ABORT; 496 if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
405 if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) ABORT; 497 if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) ABORT;
406 if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT; 498 if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
@@ -422,6 +514,10 @@ int main(int argc, char *argv[])
422 if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) ABORT; 514 if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) ABORT;
423 if (0 != BN_cmp(y, z)) ABORT; 515 if (0 != BN_cmp(y, z)) ABORT;
424 516
517 fprintf(stdout, "verify degree ...");
518 if (EC_GROUP_get_degree(group) != 256) ABORT;
519 fprintf(stdout, " ok\n");
520
425 fprintf(stdout, "verify group order ..."); 521 fprintf(stdout, "verify group order ...");
426 fflush(stdout); 522 fflush(stdout);
427 if (!EC_GROUP_get_order(group, z, ctx)) ABORT; 523 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
@@ -429,7 +525,9 @@ int main(int argc, char *argv[])
429 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; 525 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
430 fprintf(stdout, "."); 526 fprintf(stdout, ".");
431 fflush(stdout); 527 fflush(stdout);
528#if 0
432 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; 529 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
530#endif
433 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; 531 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
434 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; 532 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
435 fprintf(stdout, " ok\n"); 533 fprintf(stdout, " ok\n");
@@ -442,7 +540,7 @@ int main(int argc, char *argv[])
442 540
443 if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 541 if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
444 "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT; 542 "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT;
445 if (1 != BN_is_prime(p, BN_prime_checks, 0, ctx, NULL)) ABORT; 543 if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
446 if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 544 if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
447 "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT; 545 "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT;
448 if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141" 546 if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141"
@@ -468,6 +566,10 @@ int main(int argc, char *argv[])
468 "7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT; 566 "7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT;
469 if (0 != BN_cmp(y, z)) ABORT; 567 if (0 != BN_cmp(y, z)) ABORT;
470 568
569 fprintf(stdout, "verify degree ...");
570 if (EC_GROUP_get_degree(group) != 384) ABORT;
571 fprintf(stdout, " ok\n");
572
471 fprintf(stdout, "verify group order ..."); 573 fprintf(stdout, "verify group order ...");
472 fflush(stdout); 574 fflush(stdout);
473 if (!EC_GROUP_get_order(group, z, ctx)) ABORT; 575 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
@@ -475,7 +577,9 @@ int main(int argc, char *argv[])
475 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; 577 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
476 fprintf(stdout, "."); 578 fprintf(stdout, ".");
477 fflush(stdout); 579 fflush(stdout);
580#if 0
478 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; 581 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
582#endif
479 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; 583 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
480 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; 584 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
481 fprintf(stdout, " ok\n"); 585 fprintf(stdout, " ok\n");
@@ -489,7 +593,7 @@ int main(int argc, char *argv[])
489 if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 593 if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
490 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 594 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
491 "FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT; 595 "FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT;
492 if (1 != BN_is_prime(p, BN_prime_checks, 0, ctx, NULL)) ABORT; 596 if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
493 if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 597 if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
494 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 598 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
495 "FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT; 599 "FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT;
@@ -520,6 +624,10 @@ int main(int argc, char *argv[])
520 "7086A272C24088BE94769FD16650")) ABORT; 624 "7086A272C24088BE94769FD16650")) ABORT;
521 if (0 != BN_cmp(y, z)) ABORT; 625 if (0 != BN_cmp(y, z)) ABORT;
522 626
627 fprintf(stdout, "verify degree ...");
628 if (EC_GROUP_get_degree(group) != 521) ABORT;
629 fprintf(stdout, " ok\n");
630
523 fprintf(stdout, "verify group order ..."); 631 fprintf(stdout, "verify group order ...");
524 fflush(stdout); 632 fflush(stdout);
525 if (!EC_GROUP_get_order(group, z, ctx)) ABORT; 633 if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
@@ -527,7 +635,9 @@ int main(int argc, char *argv[])
527 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; 635 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
528 fprintf(stdout, "."); 636 fprintf(stdout, ".");
529 fflush(stdout); 637 fflush(stdout);
638#if 0
530 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; 639 if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
640#endif
531 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; 641 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
532 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; 642 if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
533 fprintf(stdout, " ok\n"); 643 fprintf(stdout, " ok\n");
@@ -549,13 +659,15 @@ int main(int argc, char *argv[])
549 if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */ 659 if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */
550 660
551 { 661 {
552 const EC_POINT *points[3]; 662 const EC_POINT *points[4];
553 const BIGNUM *scalars[3]; 663 const BIGNUM *scalars[4];
664 BIGNUM scalar3;
554 665
555 if (EC_POINT_is_at_infinity(group, Q)) ABORT; 666 if (EC_POINT_is_at_infinity(group, Q)) ABORT;
556 points[0] = Q; 667 points[0] = Q;
557 points[1] = Q; 668 points[1] = Q;
558 points[2] = Q; 669 points[2] = Q;
670 points[3] = Q;
559 671
560 if (!BN_add(y, z, BN_value_one())) ABORT; 672 if (!BN_add(y, z, BN_value_one())) ABORT;
561 if (BN_is_odd(y)) ABORT; 673 if (BN_is_odd(y)) ABORT;
@@ -577,7 +689,7 @@ int main(int argc, char *argv[])
577 689
578 if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT; 690 if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
579 if (!BN_add(z, z, y)) ABORT; 691 if (!BN_add(z, z, y)) ABORT;
580 z->neg = 1; 692 BN_set_negative(z, 1);
581 scalars[0] = y; 693 scalars[0] = y;
582 scalars[1] = z; /* z = -(order + y) */ 694 scalars[1] = z; /* z = -(order + y) */
583 695
@@ -589,29 +701,43 @@ int main(int argc, char *argv[])
589 701
590 if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT; 702 if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
591 if (!BN_add(z, x, y)) ABORT; 703 if (!BN_add(z, x, y)) ABORT;
592 z->neg = 1; 704 BN_set_negative(z, 1);
593 scalars[0] = x; 705 scalars[0] = x;
594 scalars[1] = y; 706 scalars[1] = y;
595 scalars[2] = z; /* z = -(x+y) */ 707 scalars[2] = z; /* z = -(x+y) */
596 708
597 if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT; 709 BN_init(&scalar3);
710 BN_zero(&scalar3);
711 scalars[3] = &scalar3;
712
713 if (!EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx)) ABORT;
598 if (!EC_POINT_is_at_infinity(group, P)) ABORT; 714 if (!EC_POINT_is_at_infinity(group, P)) ABORT;
599 715
600 fprintf(stdout, " ok\n\n"); 716 fprintf(stdout, " ok\n\n");
717
718 BN_free(&scalar3);
601 } 719 }
602 720
603 721
604#if 0 722#if 0
605 timings(P_192, 0, ctx); 723 timings(P_160, TIMING_BASE_PT, ctx);
606 timings(P_192, 1, ctx); 724 timings(P_160, TIMING_RAND_PT, ctx);
607 timings(P_224, 0, ctx); 725 timings(P_160, TIMING_SIMUL, ctx);
608 timings(P_224, 1, ctx); 726 timings(P_192, TIMING_BASE_PT, ctx);
609 timings(P_256, 0, ctx); 727 timings(P_192, TIMING_RAND_PT, ctx);
610 timings(P_256, 1, ctx); 728 timings(P_192, TIMING_SIMUL, ctx);
611 timings(P_384, 0, ctx); 729 timings(P_224, TIMING_BASE_PT, ctx);
612 timings(P_384, 1, ctx); 730 timings(P_224, TIMING_RAND_PT, ctx);
613 timings(P_521, 0, ctx); 731 timings(P_224, TIMING_SIMUL, ctx);
614 timings(P_521, 1, ctx); 732 timings(P_256, TIMING_BASE_PT, ctx);
733 timings(P_256, TIMING_RAND_PT, ctx);
734 timings(P_256, TIMING_SIMUL, ctx);
735 timings(P_384, TIMING_BASE_PT, ctx);
736 timings(P_384, TIMING_RAND_PT, ctx);
737 timings(P_384, TIMING_SIMUL, ctx);
738 timings(P_521, TIMING_BASE_PT, ctx);
739 timings(P_521, TIMING_RAND_PT, ctx);
740 timings(P_521, TIMING_SIMUL, ctx);
615#endif 741#endif
616 742
617 743
@@ -624,12 +750,587 @@ int main(int argc, char *argv[])
624 EC_POINT_free(R); 750 EC_POINT_free(R);
625 BN_free(x); BN_free(y); BN_free(z); 751 BN_free(x); BN_free(y); BN_free(z);
626 752
753 if (P_160) EC_GROUP_free(P_160);
627 if (P_192) EC_GROUP_free(P_192); 754 if (P_192) EC_GROUP_free(P_192);
628 if (P_224) EC_GROUP_free(P_224); 755 if (P_224) EC_GROUP_free(P_224);
629 if (P_256) EC_GROUP_free(P_256); 756 if (P_256) EC_GROUP_free(P_256);
630 if (P_384) EC_GROUP_free(P_384); 757 if (P_384) EC_GROUP_free(P_384);
631 if (P_521) EC_GROUP_free(P_521); 758 if (P_521) EC_GROUP_free(P_521);
632 759
760 }
761
762/* Change test based on whether binary point compression is enabled or not. */
763#ifdef OPENSSL_EC_BIN_PT_COMP
764#define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
765 if (!BN_hex2bn(&x, _x)) ABORT; \
766 if (!EC_POINT_set_compressed_coordinates_GF2m(group, P, x, _y_bit, ctx)) ABORT; \
767 if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
768 if (!BN_hex2bn(&z, _order)) ABORT; \
769 if (!BN_hex2bn(&cof, _cof)) ABORT; \
770 if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
771 if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \
772 fprintf(stdout, "\n%s -- Generator:\n x = 0x", _name); \
773 BN_print_fp(stdout, x); \
774 fprintf(stdout, "\n y = 0x"); \
775 BN_print_fp(stdout, y); \
776 fprintf(stdout, "\n"); \
777 /* G_y value taken from the standard: */ \
778 if (!BN_hex2bn(&z, _y)) ABORT; \
779 if (0 != BN_cmp(y, z)) ABORT;
780#else
781#define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
782 if (!BN_hex2bn(&x, _x)) ABORT; \
783 if (!BN_hex2bn(&y, _y)) ABORT; \
784 if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \
785 if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
786 if (!BN_hex2bn(&z, _order)) ABORT; \
787 if (!BN_hex2bn(&cof, _cof)) ABORT; \
788 if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
789 fprintf(stdout, "\n%s -- Generator:\n x = 0x", _name); \
790 BN_print_fp(stdout, x); \
791 fprintf(stdout, "\n y = 0x"); \
792 BN_print_fp(stdout, y); \
793 fprintf(stdout, "\n");
794#endif
795
796#define CHAR2_CURVE_TEST(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
797 if (!BN_hex2bn(&p, _p)) ABORT; \
798 if (!BN_hex2bn(&a, _a)) ABORT; \
799 if (!BN_hex2bn(&b, _b)) ABORT; \
800 if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT; \
801 CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
802 fprintf(stdout, "verify degree ..."); \
803 if (EC_GROUP_get_degree(group) != _degree) ABORT; \
804 fprintf(stdout, " ok\n"); \
805 fprintf(stdout, "verify group order ..."); \
806 fflush(stdout); \
807 if (!EC_GROUP_get_order(group, z, ctx)) ABORT; \
808 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; \
809 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; \
810 fprintf(stdout, "."); \
811 fflush(stdout); \
812 /* if (!EC_GROUP_precompute_mult(group, ctx)) ABORT; */ \
813 if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT; \
814 if (!EC_POINT_is_at_infinity(group, Q)) ABORT; \
815 fprintf(stdout, " ok\n"); \
816 if (!(_variable = EC_GROUP_new(EC_GROUP_method_of(group)))) ABORT; \
817 if (!EC_GROUP_copy(_variable, group)) ABORT;
818
819void char2_field_tests()
820 {
821 BN_CTX *ctx = NULL;
822 BIGNUM *p, *a, *b;
823 EC_GROUP *group;
824 EC_GROUP *C2_K163 = NULL, *C2_K233 = NULL, *C2_K283 = NULL, *C2_K409 = NULL, *C2_K571 = NULL;
825 EC_GROUP *C2_B163 = NULL, *C2_B233 = NULL, *C2_B283 = NULL, *C2_B409 = NULL, *C2_B571 = NULL;
826 EC_POINT *P, *Q, *R;
827 BIGNUM *x, *y, *z, *cof;
828 unsigned char buf[100];
829 size_t i, len;
830 int k;
831
832#if 1 /* optional */
833 ctx = BN_CTX_new();
834 if (!ctx) ABORT;
835#endif
836
837 p = BN_new();
838 a = BN_new();
839 b = BN_new();
840 if (!p || !a || !b) ABORT;
841
842 if (!BN_hex2bn(&p, "13")) ABORT;
843 if (!BN_hex2bn(&a, "3")) ABORT;
844 if (!BN_hex2bn(&b, "1")) ABORT;
845
846 group = EC_GROUP_new(EC_GF2m_simple_method()); /* applications should use EC_GROUP_new_curve_GF2m
847 * so that the library gets to choose the EC_METHOD */
848 if (!group) ABORT;
849 if (!EC_GROUP_set_curve_GF2m(group, p, a, b, ctx)) ABORT;
850
851 {
852 EC_GROUP *tmp;
853 tmp = EC_GROUP_new(EC_GROUP_method_of(group));
854 if (!tmp) ABORT;
855 if (!EC_GROUP_copy(tmp, group)) ABORT;
856 EC_GROUP_free(group);
857 group = tmp;
858 }
859
860 if (!EC_GROUP_get_curve_GF2m(group, p, a, b, ctx)) ABORT;
861
862 fprintf(stdout, "Curve defined by Weierstrass equation\n y^2 + x*y = x^3 + a*x^2 + b (mod 0x");
863 BN_print_fp(stdout, p);
864 fprintf(stdout, ")\n a = 0x");
865 BN_print_fp(stdout, a);
866 fprintf(stdout, "\n b = 0x");
867 BN_print_fp(stdout, b);
868 fprintf(stdout, "\n(0x... means binary polynomial)\n");
869
870 P = EC_POINT_new(group);
871 Q = EC_POINT_new(group);
872 R = EC_POINT_new(group);
873 if (!P || !Q || !R) ABORT;
874
875 if (!EC_POINT_set_to_infinity(group, P)) ABORT;
876 if (!EC_POINT_is_at_infinity(group, P)) ABORT;
877
878 buf[0] = 0;
879 if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) ABORT;
880
881 if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
882 if (!EC_POINT_is_at_infinity(group, P)) ABORT;
883
884 x = BN_new();
885 y = BN_new();
886 z = BN_new();
887 cof = BN_new();
888 if (!x || !y || !z || !cof) ABORT;
889
890 if (!BN_hex2bn(&x, "6")) ABORT;
891/* Change test based on whether binary point compression is enabled or not. */
892#ifdef OPENSSL_EC_BIN_PT_COMP
893 if (!EC_POINT_set_compressed_coordinates_GF2m(group, Q, x, 1, ctx)) ABORT;
894#else
895 if (!BN_hex2bn(&y, "8")) ABORT;
896 if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
897#endif
898 if (!EC_POINT_is_on_curve(group, Q, ctx))
899 {
900/* Change test based on whether binary point compression is enabled or not. */
901#ifdef OPENSSL_EC_BIN_PT_COMP
902 if (!EC_POINT_get_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
903#endif
904 fprintf(stderr, "Point is not on curve: x = 0x");
905 BN_print_fp(stderr, x);
906 fprintf(stderr, ", y = 0x");
907 BN_print_fp(stderr, y);
908 fprintf(stderr, "\n");
909 ABORT;
910 }
911
912 fprintf(stdout, "A cyclic subgroup:\n");
913 k = 100;
914 do
915 {
916 if (k-- == 0) ABORT;
917
918 if (EC_POINT_is_at_infinity(group, P))
919 fprintf(stdout, " point at infinity\n");
920 else
921 {
922 if (!EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT;
923
924 fprintf(stdout, " x = 0x");
925 BN_print_fp(stdout, x);
926 fprintf(stdout, ", y = 0x");
927 BN_print_fp(stdout, y);
928 fprintf(stdout, "\n");
929 }
930
931 if (!EC_POINT_copy(R, P)) ABORT;
932 if (!EC_POINT_add(group, P, P, Q, ctx)) ABORT;
933 }
934 while (!EC_POINT_is_at_infinity(group, P));
935
936 if (!EC_POINT_add(group, P, Q, R, ctx)) ABORT;
937 if (!EC_POINT_is_at_infinity(group, P)) ABORT;
938
939/* Change test based on whether binary point compression is enabled or not. */
940#ifdef OPENSSL_EC_BIN_PT_COMP
941 len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx);
942 if (len == 0) ABORT;
943 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
944 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
945 fprintf(stdout, "Generator as octet string, compressed form:\n ");
946 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
947#endif
948
949 len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx);
950 if (len == 0) ABORT;
951 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
952 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
953 fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n ");
954 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
955
956/* Change test based on whether binary point compression is enabled or not. */
957#ifdef OPENSSL_EC_BIN_PT_COMP
958 len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx);
959 if (len == 0) ABORT;
960 if (!EC_POINT_oct2point(group, P, buf, len, ctx)) ABORT;
961 if (0 != EC_POINT_cmp(group, P, Q, ctx)) ABORT;
962 fprintf(stdout, "\nGenerator as octet string, hybrid form:\n ");
963 for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]);
964#endif
965
966 fprintf(stdout, "\n");
967
968 if (!EC_POINT_invert(group, P, ctx)) ABORT;
969 if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
970
971
972 /* Curve K-163 (FIPS PUB 186-2, App. 6) */
973 CHAR2_CURVE_TEST
974 (
975 "NIST curve K-163",
976 "0800000000000000000000000000000000000000C9",
977 "1",
978 "1",
979 "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",
980 "0289070FB05D38FF58321F2E800536D538CCDAA3D9",
981 1,
982 "04000000000000000000020108A2E0CC0D99F8A5EF",
983 "2",
984 163,
985 C2_K163
986 );
987
988 /* Curve B-163 (FIPS PUB 186-2, App. 6) */
989 CHAR2_CURVE_TEST
990 (
991 "NIST curve B-163",
992 "0800000000000000000000000000000000000000C9",
993 "1",
994 "020A601907B8C953CA1481EB10512F78744A3205FD",
995 "03F0EBA16286A2D57EA0991168D4994637E8343E36",
996 "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
997 1,
998 "040000000000000000000292FE77E70C12A4234C33",
999 "2",
1000 163,
1001 C2_B163
1002 );
1003
1004 /* Curve K-233 (FIPS PUB 186-2, App. 6) */
1005 CHAR2_CURVE_TEST
1006 (
1007 "NIST curve K-233",
1008 "020000000000000000000000000000000000000004000000000000000001",
1009 "0",
1010 "1",
1011 "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126",
1012 "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
1013 0,
1014 "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",
1015 "4",
1016 233,
1017 C2_K233
1018 );
1019
1020 /* Curve B-233 (FIPS PUB 186-2, App. 6) */
1021 CHAR2_CURVE_TEST
1022 (
1023 "NIST curve B-233",
1024 "020000000000000000000000000000000000000004000000000000000001",
1025 "000000000000000000000000000000000000000000000000000000000001",
1026 "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD",
1027 "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B",
1028 "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
1029 1,
1030 "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",
1031 "2",
1032 233,
1033 C2_B233
1034 );
1035
1036 /* Curve K-283 (FIPS PUB 186-2, App. 6) */
1037 CHAR2_CURVE_TEST
1038 (
1039 "NIST curve K-283",
1040 "0800000000000000000000000000000000000000000000000000000000000000000010A1",
1041 "0",
1042 "1",
1043 "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836",
1044 "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259",
1045 0,
1046 "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
1047 "4",
1048 283,
1049 C2_K283
1050 );
1051
1052 /* Curve B-283 (FIPS PUB 186-2, App. 6) */
1053 CHAR2_CURVE_TEST
1054 (
1055 "NIST curve B-283",
1056 "0800000000000000000000000000000000000000000000000000000000000000000010A1",
1057 "000000000000000000000000000000000000000000000000000000000000000000000001",
1058 "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
1059 "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",
1060 "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
1061 1,
1062 "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
1063 "2",
1064 283,
1065 C2_B283
1066 );
1067
1068 /* Curve K-409 (FIPS PUB 186-2, App. 6) */
1069 CHAR2_CURVE_TEST
1070 (
1071 "NIST curve K-409",
1072 "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
1073 "0",
1074 "1",
1075 "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746",
1076 "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B",
1077 1,
1078 "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
1079 "4",
1080 409,
1081 C2_K409
1082 );
1083
1084 /* Curve B-409 (FIPS PUB 186-2, App. 6) */
1085 CHAR2_CURVE_TEST
1086 (
1087 "NIST curve B-409",
1088 "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001",
1089 "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
1090 "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F",
1091 "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7",
1092 "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706",
1093 1,
1094 "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
1095 "2",
1096 409,
1097 C2_B409
1098 );
1099
1100 /* Curve K-571 (FIPS PUB 186-2, App. 6) */
1101 CHAR2_CURVE_TEST
1102 (
1103 "NIST curve K-571",
1104 "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
1105 "0",
1106 "1",
1107 "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972",
1108 "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3",
1109 0,
1110 "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
1111 "4",
1112 571,
1113 C2_K571
1114 );
1115
1116 /* Curve B-571 (FIPS PUB 186-2, App. 6) */
1117 CHAR2_CURVE_TEST
1118 (
1119 "NIST curve B-571",
1120 "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425",
1121 "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
1122 "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A",
1123 "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19",
1124 "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B",
1125 1,
1126 "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
1127 "2",
1128 571,
1129 C2_B571
1130 );
1131
1132 /* more tests using the last curve */
1133
1134 if (!EC_POINT_copy(Q, P)) ABORT;
1135 if (EC_POINT_is_at_infinity(group, Q)) ABORT;
1136 if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
1137 if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
1138 if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */
1139
1140 if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
1141 if (!EC_POINT_add(group, R, R, Q, ctx)) ABORT;
1142 if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */
1143
1144 {
1145 const EC_POINT *points[3];
1146 const BIGNUM *scalars[3];
1147
1148 if (EC_POINT_is_at_infinity(group, Q)) ABORT;
1149 points[0] = Q;
1150 points[1] = Q;
1151 points[2] = Q;
1152
1153 if (!BN_add(y, z, BN_value_one())) ABORT;
1154 if (BN_is_odd(y)) ABORT;
1155 if (!BN_rshift1(y, y)) ABORT;
1156 scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */
1157 scalars[1] = y;
1158
1159 fprintf(stdout, "combined multiplication ...");
1160 fflush(stdout);
1161
1162 /* z is still the group order */
1163 if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
1164 if (!EC_POINTs_mul(group, R, z, 2, points, scalars, ctx)) ABORT;
1165 if (0 != EC_POINT_cmp(group, P, R, ctx)) ABORT;
1166 if (0 != EC_POINT_cmp(group, R, Q, ctx)) ABORT;
1167
1168 fprintf(stdout, ".");
1169 fflush(stdout);
1170
1171 if (!BN_pseudo_rand(y, BN_num_bits(y), 0, 0)) ABORT;
1172 if (!BN_add(z, z, y)) ABORT;
1173 BN_set_negative(z, 1);
1174 scalars[0] = y;
1175 scalars[1] = z; /* z = -(order + y) */
1176
1177 if (!EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) ABORT;
1178 if (!EC_POINT_is_at_infinity(group, P)) ABORT;
1179
1180 fprintf(stdout, ".");
1181 fflush(stdout);
1182
1183 if (!BN_pseudo_rand(x, BN_num_bits(y) - 1, 0, 0)) ABORT;
1184 if (!BN_add(z, x, y)) ABORT;
1185 BN_set_negative(z, 1);
1186 scalars[0] = x;
1187 scalars[1] = y;
1188 scalars[2] = z; /* z = -(x+y) */
1189
1190 if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT;
1191 if (!EC_POINT_is_at_infinity(group, P)) ABORT;
1192
1193 fprintf(stdout, " ok\n\n");
1194 }
1195
1196
1197#if 0
1198 timings(C2_K163, TIMING_BASE_PT, ctx);
1199 timings(C2_K163, TIMING_RAND_PT, ctx);
1200 timings(C2_K163, TIMING_SIMUL, ctx);
1201 timings(C2_B163, TIMING_BASE_PT, ctx);
1202 timings(C2_B163, TIMING_RAND_PT, ctx);
1203 timings(C2_B163, TIMING_SIMUL, ctx);
1204 timings(C2_K233, TIMING_BASE_PT, ctx);
1205 timings(C2_K233, TIMING_RAND_PT, ctx);
1206 timings(C2_K233, TIMING_SIMUL, ctx);
1207 timings(C2_B233, TIMING_BASE_PT, ctx);
1208 timings(C2_B233, TIMING_RAND_PT, ctx);
1209 timings(C2_B233, TIMING_SIMUL, ctx);
1210 timings(C2_K283, TIMING_BASE_PT, ctx);
1211 timings(C2_K283, TIMING_RAND_PT, ctx);
1212 timings(C2_K283, TIMING_SIMUL, ctx);
1213 timings(C2_B283, TIMING_BASE_PT, ctx);
1214 timings(C2_B283, TIMING_RAND_PT, ctx);
1215 timings(C2_B283, TIMING_SIMUL, ctx);
1216 timings(C2_K409, TIMING_BASE_PT, ctx);
1217 timings(C2_K409, TIMING_RAND_PT, ctx);
1218 timings(C2_K409, TIMING_SIMUL, ctx);
1219 timings(C2_B409, TIMING_BASE_PT, ctx);
1220 timings(C2_B409, TIMING_RAND_PT, ctx);
1221 timings(C2_B409, TIMING_SIMUL, ctx);
1222 timings(C2_K571, TIMING_BASE_PT, ctx);
1223 timings(C2_K571, TIMING_RAND_PT, ctx);
1224 timings(C2_K571, TIMING_SIMUL, ctx);
1225 timings(C2_B571, TIMING_BASE_PT, ctx);
1226 timings(C2_B571, TIMING_RAND_PT, ctx);
1227 timings(C2_B571, TIMING_SIMUL, ctx);
1228#endif
1229
1230
1231 if (ctx)
1232 BN_CTX_free(ctx);
1233 BN_free(p); BN_free(a); BN_free(b);
1234 EC_GROUP_free(group);
1235 EC_POINT_free(P);
1236 EC_POINT_free(Q);
1237 EC_POINT_free(R);
1238 BN_free(x); BN_free(y); BN_free(z); BN_free(cof);
1239
1240 if (C2_K163) EC_GROUP_free(C2_K163);
1241 if (C2_B163) EC_GROUP_free(C2_B163);
1242 if (C2_K233) EC_GROUP_free(C2_K233);
1243 if (C2_B233) EC_GROUP_free(C2_B233);
1244 if (C2_K283) EC_GROUP_free(C2_K283);
1245 if (C2_B283) EC_GROUP_free(C2_B283);
1246 if (C2_K409) EC_GROUP_free(C2_K409);
1247 if (C2_B409) EC_GROUP_free(C2_B409);
1248 if (C2_K571) EC_GROUP_free(C2_K571);
1249 if (C2_B571) EC_GROUP_free(C2_B571);
1250
1251 }
1252
1253void internal_curve_test(void)
1254 {
1255 EC_builtin_curve *curves = NULL;
1256 size_t crv_len = 0, n = 0;
1257 int ok = 1;
1258
1259 crv_len = EC_get_builtin_curves(NULL, 0);
1260
1261 curves = OPENSSL_malloc(sizeof(EC_builtin_curve) * crv_len);
1262
1263 if (curves == NULL)
1264 return;
1265
1266 if (!EC_get_builtin_curves(curves, crv_len))
1267 {
1268 OPENSSL_free(curves);
1269 return;
1270 }
1271
1272 fprintf(stdout, "testing internal curves: ");
1273
1274 for (n = 0; n < crv_len; n++)
1275 {
1276 EC_GROUP *group = NULL;
1277 int nid = curves[n].nid;
1278 if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL)
1279 {
1280 ok = 0;
1281 fprintf(stdout, "\nEC_GROUP_new_curve_name() failed with"
1282 " curve %s\n", OBJ_nid2sn(nid));
1283 /* try next curve */
1284 continue;
1285 }
1286 if (!EC_GROUP_check(group, NULL))
1287 {
1288 ok = 0;
1289 fprintf(stdout, "\nEC_GROUP_check() failed with"
1290 " curve %s\n", OBJ_nid2sn(nid));
1291 EC_GROUP_free(group);
1292 /* try the next curve */
1293 continue;
1294 }
1295 fprintf(stdout, ".");
1296 fflush(stdout);
1297 EC_GROUP_free(group);
1298 }
1299 if (ok)
1300 fprintf(stdout, " ok\n");
1301 else
1302 fprintf(stdout, " failed\n");
1303 OPENSSL_free(curves);
1304 return;
1305 }
1306
1307static const char rnd_seed[] = "string to make the random number generator think it has entropy";
1308
1309int main(int argc, char *argv[])
1310 {
1311
1312 /* enable memory leak checking unless explicitly disabled */
1313 if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
1314 {
1315 CRYPTO_malloc_debug_init();
1316 CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
1317 }
1318 else
1319 {
1320 /* OPENSSL_DEBUG_MEMORY=off */
1321 CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
1322 }
1323 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
1324 ERR_load_crypto_strings();
1325
1326 RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */
1327
1328 prime_field_tests();
1329 puts("");
1330 char2_field_tests();
1331 /* test the internal curves */
1332 internal_curve_test();
1333
633#ifndef OPENSSL_NO_ENGINE 1334#ifndef OPENSSL_NO_ENGINE
634 ENGINE_cleanup(); 1335 ENGINE_cleanup();
635#endif 1336#endif