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.h69
-rw-r--r--src/lib/libcrypto/ec/ec2_mult.c4
-rw-r--r--src/lib/libcrypto/ec/ec2_oct.c407
-rw-r--r--src/lib/libcrypto/ec/ec2_smpl.c351
-rw-r--r--src/lib/libcrypto/ec/ec_ameth.c1
-rw-r--r--src/lib/libcrypto/ec/ec_asn1.c24
-rw-r--r--src/lib/libcrypto/ec/ec_curve.c197
-rw-r--r--src/lib/libcrypto/ec/ec_cvt.c28
-rw-r--r--src/lib/libcrypto/ec/ec_err.c20
-rw-r--r--src/lib/libcrypto/ec/ec_key.c102
-rw-r--r--src/lib/libcrypto/ec/ec_lcl.h55
-rw-r--r--src/lib/libcrypto/ec/ec_lib.c80
-rw-r--r--src/lib/libcrypto/ec/ec_oct.c199
-rw-r--r--src/lib/libcrypto/ec/ec_pmeth.c1
-rw-r--r--src/lib/libcrypto/ec/eck_prn.c3
-rw-r--r--src/lib/libcrypto/ec/ecp_mont.c14
-rw-r--r--src/lib/libcrypto/ec/ecp_nist.c13
-rw-r--r--src/lib/libcrypto/ec/ecp_nistp224.c1658
-rw-r--r--src/lib/libcrypto/ec/ecp_nistp256.c2171
-rw-r--r--src/lib/libcrypto/ec/ecp_nistp521.c2025
-rw-r--r--src/lib/libcrypto/ec/ecp_nistputil.c197
-rw-r--r--src/lib/libcrypto/ec/ecp_oct.c433
-rw-r--r--src/lib/libcrypto/ec/ecp_smpl.c379
23 files changed, 7552 insertions, 879 deletions
diff --git a/src/lib/libcrypto/ec/ec.h b/src/lib/libcrypto/ec/ec.h
index ee7078130c..9d01325af3 100644
--- a/src/lib/libcrypto/ec/ec.h
+++ b/src/lib/libcrypto/ec/ec.h
@@ -151,7 +151,24 @@ const EC_METHOD *EC_GFp_mont_method(void);
151 */ 151 */
152const EC_METHOD *EC_GFp_nist_method(void); 152const EC_METHOD *EC_GFp_nist_method(void);
153 153
154#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
155/** Returns 64-bit optimized methods for nistp224
156 * \return EC_METHOD object
157 */
158const EC_METHOD *EC_GFp_nistp224_method(void);
159
160/** Returns 64-bit optimized methods for nistp256
161 * \return EC_METHOD object
162 */
163const EC_METHOD *EC_GFp_nistp256_method(void);
164
165/** Returns 64-bit optimized methods for nistp521
166 * \return EC_METHOD object
167 */
168const EC_METHOD *EC_GFp_nistp521_method(void);
169#endif
154 170
171#ifndef OPENSSL_NO_EC2M
155/********************************************************************/ 172/********************************************************************/
156/* EC_METHOD for curves over GF(2^m) */ 173/* EC_METHOD for curves over GF(2^m) */
157/********************************************************************/ 174/********************************************************************/
@@ -161,6 +178,8 @@ const EC_METHOD *EC_GFp_nist_method(void);
161 */ 178 */
162const EC_METHOD *EC_GF2m_simple_method(void); 179const EC_METHOD *EC_GF2m_simple_method(void);
163 180
181#endif
182
164 183
165/********************************************************************/ 184/********************************************************************/
166/* EC_GROUP functions */ 185/* EC_GROUP functions */
@@ -282,6 +301,7 @@ int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, co
282 */ 301 */
283int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); 302int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
284 303
304#ifndef OPENSSL_NO_EC2M
285/** Sets the parameter of a ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b 305/** Sets the parameter of a ec over GF2m defined by y^2 + x*y = x^3 + a*x^2 + b
286 * \param group EC_GROUP object 306 * \param group EC_GROUP object
287 * \param p BIGNUM with the polynomial defining the underlying field 307 * \param p BIGNUM with the polynomial defining the underlying field
@@ -301,7 +321,7 @@ int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, c
301 * \return 1 on success and 0 if an error occured 321 * \return 1 on success and 0 if an error occured
302 */ 322 */
303int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); 323int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx);
304 324#endif
305/** Returns the number of bits needed to represent a field element 325/** Returns the number of bits needed to represent a field element
306 * \param group EC_GROUP object 326 * \param group EC_GROUP object
307 * \return number of bits needed to represent a field element 327 * \return number of bits needed to represent a field element
@@ -342,7 +362,7 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx);
342 * \return newly created EC_GROUP object with the specified parameters 362 * \return newly created EC_GROUP object with the specified parameters
343 */ 363 */
344EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); 364EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
345 365#ifndef OPENSSL_NO_EC2M
346/** Creates a new EC_GROUP object with the specified parameters defined 366/** Creates a new EC_GROUP object with the specified parameters defined
347 * over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b) 367 * over GF2m (defined by the equation y^2 + x*y = x^3 + a*x^2 + b)
348 * \param p BIGNUM with the polynomial defining the underlying field 368 * \param p BIGNUM with the polynomial defining the underlying field
@@ -352,7 +372,7 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM
352 * \return newly created EC_GROUP object with the specified parameters 372 * \return newly created EC_GROUP object with the specified parameters
353 */ 373 */
354EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); 374EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
355 375#endif
356/** Creates a EC_GROUP object with a curve specified by a NID 376/** Creates a EC_GROUP object with a curve specified by a NID
357 * \param nid NID of the OID of the curve name 377 * \param nid NID of the OID of the curve name
358 * \return newly created EC_GROUP object with specified curve or NULL 378 * \return newly created EC_GROUP object with specified curve or NULL
@@ -481,7 +501,7 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
481 */ 501 */
482int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, 502int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *p,
483 const BIGNUM *x, int y_bit, BN_CTX *ctx); 503 const BIGNUM *x, int y_bit, BN_CTX *ctx);
484 504#ifndef OPENSSL_NO_EC2M
485/** Sets the affine coordinates of a EC_POINT over GF2m 505/** Sets the affine coordinates of a EC_POINT over GF2m
486 * \param group underlying EC_GROUP object 506 * \param group underlying EC_GROUP object
487 * \param p EC_POINT object 507 * \param p EC_POINT object
@@ -514,7 +534,7 @@ int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
514 */ 534 */
515int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p, 535int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p,
516 const BIGNUM *x, int y_bit, BN_CTX *ctx); 536 const BIGNUM *x, int y_bit, BN_CTX *ctx);
517 537#endif
518/** Encodes a EC_POINT object to a octet string 538/** Encodes a EC_POINT object to a octet string
519 * \param group underlying EC_GROUP object 539 * \param group underlying EC_GROUP object
520 * \param p EC_POINT object 540 * \param p EC_POINT object
@@ -653,9 +673,11 @@ int EC_GROUP_have_precompute_mult(const EC_GROUP *group);
653/* EC_GROUP_get_basis_type() returns the NID of the basis type 673/* EC_GROUP_get_basis_type() returns the NID of the basis type
654 * used to represent the field elements */ 674 * used to represent the field elements */
655int EC_GROUP_get_basis_type(const EC_GROUP *); 675int EC_GROUP_get_basis_type(const EC_GROUP *);
676#ifndef OPENSSL_NO_EC2M
656int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k); 677int EC_GROUP_get_trinomial_basis(const EC_GROUP *, unsigned int *k);
657int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1, 678int EC_GROUP_get_pentanomial_basis(const EC_GROUP *, unsigned int *k1,
658 unsigned int *k2, unsigned int *k3); 679 unsigned int *k2, unsigned int *k3);
680#endif
659 681
660#define OPENSSL_EC_NAMED_CURVE 0x001 682#define OPENSSL_EC_NAMED_CURVE 0x001
661 683
@@ -689,11 +711,21 @@ typedef struct ec_key_st EC_KEY;
689#define EC_PKEY_NO_PARAMETERS 0x001 711#define EC_PKEY_NO_PARAMETERS 0x001
690#define EC_PKEY_NO_PUBKEY 0x002 712#define EC_PKEY_NO_PUBKEY 0x002
691 713
714/* some values for the flags field */
715#define EC_FLAG_NON_FIPS_ALLOW 0x1
716#define EC_FLAG_FIPS_CHECKED 0x2
717
692/** Creates a new EC_KEY object. 718/** Creates a new EC_KEY object.
693 * \return EC_KEY object or NULL if an error occurred. 719 * \return EC_KEY object or NULL if an error occurred.
694 */ 720 */
695EC_KEY *EC_KEY_new(void); 721EC_KEY *EC_KEY_new(void);
696 722
723int EC_KEY_get_flags(const EC_KEY *key);
724
725void EC_KEY_set_flags(EC_KEY *key, int flags);
726
727void EC_KEY_clear_flags(EC_KEY *key, int flags);
728
697/** Creates a new EC_KEY object using a named curve as underlying 729/** Creates a new EC_KEY object using a named curve as underlying
698 * EC_GROUP object. 730 * EC_GROUP object.
699 * \param nid NID of the named curve. 731 * \param nid NID of the named curve.
@@ -799,6 +831,15 @@ int EC_KEY_generate_key(EC_KEY *key);
799 */ 831 */
800int EC_KEY_check_key(const EC_KEY *key); 832int EC_KEY_check_key(const EC_KEY *key);
801 833
834/** Sets a public key from affine coordindates performing
835 * neccessary NIST PKV tests.
836 * \param key the EC_KEY object
837 * \param x public key x coordinate
838 * \param y public key y coordinate
839 * \return 1 on success and 0 otherwise.
840 */
841int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y);
842
802 843
803/********************************************************************/ 844/********************************************************************/
804/* de- and encoding functions for SEC1 ECPrivateKey */ 845/* de- and encoding functions for SEC1 ECPrivateKey */
@@ -926,6 +967,7 @@ void ERR_load_EC_strings(void);
926/* Error codes for the EC functions. */ 967/* Error codes for the EC functions. */
927 968
928/* Function codes. */ 969/* Function codes. */
970#define EC_F_BN_TO_FELEM 224
929#define EC_F_COMPUTE_WNAF 143 971#define EC_F_COMPUTE_WNAF 143
930#define EC_F_D2I_ECPARAMETERS 144 972#define EC_F_D2I_ECPARAMETERS 144
931#define EC_F_D2I_ECPKPARAMETERS 145 973#define EC_F_D2I_ECPKPARAMETERS 145
@@ -968,6 +1010,15 @@ void ERR_load_EC_strings(void);
968#define EC_F_EC_GFP_MONT_FIELD_SQR 132 1010#define EC_F_EC_GFP_MONT_FIELD_SQR 132
969#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189 1011#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189
970#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135 1012#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135
1013#define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE 225
1014#define EC_F_EC_GFP_NISTP224_POINTS_MUL 228
1015#define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226
1016#define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE 230
1017#define EC_F_EC_GFP_NISTP256_POINTS_MUL 231
1018#define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232
1019#define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE 233
1020#define EC_F_EC_GFP_NISTP521_POINTS_MUL 234
1021#define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235
971#define EC_F_EC_GFP_NIST_FIELD_MUL 200 1022#define EC_F_EC_GFP_NIST_FIELD_MUL 200
972#define EC_F_EC_GFP_NIST_FIELD_SQR 201 1023#define EC_F_EC_GFP_NIST_FIELD_SQR 201
973#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202 1024#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202
@@ -1010,6 +1061,7 @@ void ERR_load_EC_strings(void);
1010#define EC_F_EC_KEY_NEW 182 1061#define EC_F_EC_KEY_NEW 182
1011#define EC_F_EC_KEY_PRINT 180 1062#define EC_F_EC_KEY_PRINT 180
1012#define EC_F_EC_KEY_PRINT_FP 181 1063#define EC_F_EC_KEY_PRINT_FP 181
1064#define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES 229
1013#define EC_F_EC_POINTS_MAKE_AFFINE 136 1065#define EC_F_EC_POINTS_MAKE_AFFINE 136
1014#define EC_F_EC_POINT_ADD 112 1066#define EC_F_EC_POINT_ADD 112
1015#define EC_F_EC_POINT_CMP 113 1067#define EC_F_EC_POINT_CMP 113
@@ -1040,6 +1092,9 @@ void ERR_load_EC_strings(void);
1040#define EC_F_I2D_ECPKPARAMETERS 191 1092#define EC_F_I2D_ECPKPARAMETERS 191
1041#define EC_F_I2D_ECPRIVATEKEY 192 1093#define EC_F_I2D_ECPRIVATEKEY 192
1042#define EC_F_I2O_ECPUBLICKEY 151 1094#define EC_F_I2O_ECPUBLICKEY 151
1095#define EC_F_NISTP224_PRE_COMP_NEW 227
1096#define EC_F_NISTP256_PRE_COMP_NEW 236
1097#define EC_F_NISTP521_PRE_COMP_NEW 237
1043#define EC_F_O2I_ECPUBLICKEY 152 1098#define EC_F_O2I_ECPUBLICKEY 152
1044#define EC_F_OLD_EC_PRIV_DECODE 222 1099#define EC_F_OLD_EC_PRIV_DECODE 222
1045#define EC_F_PKEY_EC_CTRL 197 1100#define EC_F_PKEY_EC_CTRL 197
@@ -1052,12 +1107,15 @@ void ERR_load_EC_strings(void);
1052/* Reason codes. */ 1107/* Reason codes. */
1053#define EC_R_ASN1_ERROR 115 1108#define EC_R_ASN1_ERROR 115
1054#define EC_R_ASN1_UNKNOWN_FIELD 116 1109#define EC_R_ASN1_UNKNOWN_FIELD 116
1110#define EC_R_BIGNUM_OUT_OF_RANGE 144
1055#define EC_R_BUFFER_TOO_SMALL 100 1111#define EC_R_BUFFER_TOO_SMALL 100
1112#define EC_R_COORDINATES_OUT_OF_RANGE 146
1056#define EC_R_D2I_ECPKPARAMETERS_FAILURE 117 1113#define EC_R_D2I_ECPKPARAMETERS_FAILURE 117
1057#define EC_R_DECODE_ERROR 142 1114#define EC_R_DECODE_ERROR 142
1058#define EC_R_DISCRIMINANT_IS_ZERO 118 1115#define EC_R_DISCRIMINANT_IS_ZERO 118
1059#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 1116#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119
1060#define EC_R_FIELD_TOO_LARGE 143 1117#define EC_R_FIELD_TOO_LARGE 143
1118#define EC_R_GF2M_NOT_SUPPORTED 147
1061#define EC_R_GROUP2PKPARAMETERS_FAILURE 120 1119#define EC_R_GROUP2PKPARAMETERS_FAILURE 120
1062#define EC_R_I2D_ECPKPARAMETERS_FAILURE 121 1120#define EC_R_I2D_ECPKPARAMETERS_FAILURE 121
1063#define EC_R_INCOMPATIBLE_OBJECTS 101 1121#define EC_R_INCOMPATIBLE_OBJECTS 101
@@ -1092,6 +1150,7 @@ void ERR_load_EC_strings(void);
1092#define EC_R_UNKNOWN_GROUP 129 1150#define EC_R_UNKNOWN_GROUP 129
1093#define EC_R_UNKNOWN_ORDER 114 1151#define EC_R_UNKNOWN_ORDER 114
1094#define EC_R_UNSUPPORTED_FIELD 131 1152#define EC_R_UNSUPPORTED_FIELD 131
1153#define EC_R_WRONG_CURVE_PARAMETERS 145
1095#define EC_R_WRONG_ORDER 130 1154#define EC_R_WRONG_ORDER 130
1096 1155
1097#ifdef __cplusplus 1156#ifdef __cplusplus
diff --git a/src/lib/libcrypto/ec/ec2_mult.c b/src/lib/libcrypto/ec/ec2_mult.c
index e12b9b284a..26f4a783fc 100644
--- a/src/lib/libcrypto/ec/ec2_mult.c
+++ b/src/lib/libcrypto/ec/ec2_mult.c
@@ -71,6 +71,8 @@
71 71
72#include "ec_lcl.h" 72#include "ec_lcl.h"
73 73
74#ifndef OPENSSL_NO_EC2M
75
74 76
75/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective 77/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective
76 * coordinates. 78 * coordinates.
@@ -384,3 +386,5 @@ int ec_GF2m_have_precompute_mult(const EC_GROUP *group)
384 { 386 {
385 return ec_wNAF_have_precompute_mult(group); 387 return ec_wNAF_have_precompute_mult(group);
386 } 388 }
389
390#endif
diff --git a/src/lib/libcrypto/ec/ec2_oct.c b/src/lib/libcrypto/ec/ec2_oct.c
new file mode 100644
index 0000000000..f1d75e5ddf
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec2_oct.c
@@ -0,0 +1,407 @@
1/* crypto/ec/ec2_oct.c */
2/* ====================================================================
3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4 *
5 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7 * to the OpenSSL project.
8 *
9 * The ECC Code is licensed pursuant to the OpenSSL open source
10 * license provided below.
11 *
12 * The software is originally written by Sheueling Chang Shantz and
13 * Douglas Stebila of Sun Microsystems Laboratories.
14 *
15 */
16/* ====================================================================
17 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 *
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 *
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in
28 * the documentation and/or other materials provided with the
29 * distribution.
30 *
31 * 3. All advertising materials mentioning features or use of this
32 * software must display the following acknowledgment:
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35 *
36 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37 * endorse or promote products derived from this software without
38 * prior written permission. For written permission, please contact
39 * openssl-core@openssl.org.
40 *
41 * 5. Products derived from this software may not be called "OpenSSL"
42 * nor may "OpenSSL" appear in their names without prior written
43 * permission of the OpenSSL Project.
44 *
45 * 6. Redistributions of any form whatsoever must retain the following
46 * acknowledgment:
47 * "This product includes software developed by the OpenSSL Project
48 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
54 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61 * OF THE POSSIBILITY OF SUCH DAMAGE.
62 * ====================================================================
63 *
64 * This product includes cryptographic software written by Eric Young
65 * (eay@cryptsoft.com). This product includes software written by Tim
66 * Hudson (tjh@cryptsoft.com).
67 *
68 */
69
70#include <openssl/err.h>
71
72#include "ec_lcl.h"
73
74#ifndef OPENSSL_NO_EC2M
75
76/* Calculates and sets the affine coordinates of an EC_POINT from the given
77 * compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
78 * Note that the simple implementation only uses affine coordinates.
79 *
80 * The method is from the following publication:
81 *
82 * Harper, Menezes, Vanstone:
83 * "Public-Key Cryptosystems with Very Small Key Lengths",
84 * EUROCRYPT '92, Springer-Verlag LNCS 658,
85 * published February 1993
86 *
87 * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
88 * the same method, but claim no priority date earlier than July 29, 1994
89 * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
90 */
91int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
92 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
93 {
94 BN_CTX *new_ctx = NULL;
95 BIGNUM *tmp, *x, *y, *z;
96 int ret = 0, z0;
97
98 /* clear error queue */
99 ERR_clear_error();
100
101 if (ctx == NULL)
102 {
103 ctx = new_ctx = BN_CTX_new();
104 if (ctx == NULL)
105 return 0;
106 }
107
108 y_bit = (y_bit != 0) ? 1 : 0;
109
110 BN_CTX_start(ctx);
111 tmp = BN_CTX_get(ctx);
112 x = BN_CTX_get(ctx);
113 y = BN_CTX_get(ctx);
114 z = BN_CTX_get(ctx);
115 if (z == NULL) goto err;
116
117 if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
118 if (BN_is_zero(x))
119 {
120 if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
121 }
122 else
123 {
124 if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
125 if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
126 if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
127 if (!BN_GF2m_add(tmp, x, tmp)) goto err;
128 if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
129 {
130 unsigned long err = ERR_peek_last_error();
131
132 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
133 {
134 ERR_clear_error();
135 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
136 }
137 else
138 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
139 goto err;
140 }
141 z0 = (BN_is_odd(z)) ? 1 : 0;
142 if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
143 if (z0 != y_bit)
144 {
145 if (!BN_GF2m_add(y, y, x)) goto err;
146 }
147 }
148
149 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
150
151 ret = 1;
152
153 err:
154 BN_CTX_end(ctx);
155 if (new_ctx != NULL)
156 BN_CTX_free(new_ctx);
157 return ret;
158 }
159
160
161/* Converts an EC_POINT to an octet string.
162 * If buf is NULL, the encoded length will be returned.
163 * If the length len of buf is smaller than required an error will be returned.
164 */
165size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
166 unsigned char *buf, size_t len, BN_CTX *ctx)
167 {
168 size_t ret;
169 BN_CTX *new_ctx = NULL;
170 int used_ctx = 0;
171 BIGNUM *x, *y, *yxi;
172 size_t field_len, i, skip;
173
174 if ((form != POINT_CONVERSION_COMPRESSED)
175 && (form != POINT_CONVERSION_UNCOMPRESSED)
176 && (form != POINT_CONVERSION_HYBRID))
177 {
178 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
179 goto err;
180 }
181
182 if (EC_POINT_is_at_infinity(group, point))
183 {
184 /* encodes to a single 0 octet */
185 if (buf != NULL)
186 {
187 if (len < 1)
188 {
189 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
190 return 0;
191 }
192 buf[0] = 0;
193 }
194 return 1;
195 }
196
197
198 /* ret := required output buffer length */
199 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
200 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
201
202 /* if 'buf' is NULL, just return required length */
203 if (buf != NULL)
204 {
205 if (len < ret)
206 {
207 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
208 goto err;
209 }
210
211 if (ctx == NULL)
212 {
213 ctx = new_ctx = BN_CTX_new();
214 if (ctx == NULL)
215 return 0;
216 }
217
218 BN_CTX_start(ctx);
219 used_ctx = 1;
220 x = BN_CTX_get(ctx);
221 y = BN_CTX_get(ctx);
222 yxi = BN_CTX_get(ctx);
223 if (yxi == NULL) goto err;
224
225 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
226
227 buf[0] = form;
228 if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
229 {
230 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
231 if (BN_is_odd(yxi)) buf[0]++;
232 }
233
234 i = 1;
235
236 skip = field_len - BN_num_bytes(x);
237 if (skip > field_len)
238 {
239 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
240 goto err;
241 }
242 while (skip > 0)
243 {
244 buf[i++] = 0;
245 skip--;
246 }
247 skip = BN_bn2bin(x, buf + i);
248 i += skip;
249 if (i != 1 + field_len)
250 {
251 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
252 goto err;
253 }
254
255 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
256 {
257 skip = field_len - BN_num_bytes(y);
258 if (skip > field_len)
259 {
260 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
261 goto err;
262 }
263 while (skip > 0)
264 {
265 buf[i++] = 0;
266 skip--;
267 }
268 skip = BN_bn2bin(y, buf + i);
269 i += skip;
270 }
271
272 if (i != ret)
273 {
274 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
275 goto err;
276 }
277 }
278
279 if (used_ctx)
280 BN_CTX_end(ctx);
281 if (new_ctx != NULL)
282 BN_CTX_free(new_ctx);
283 return ret;
284
285 err:
286 if (used_ctx)
287 BN_CTX_end(ctx);
288 if (new_ctx != NULL)
289 BN_CTX_free(new_ctx);
290 return 0;
291 }
292
293
294/* Converts an octet string representation to an EC_POINT.
295 * Note that the simple implementation only uses affine coordinates.
296 */
297int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
298 const unsigned char *buf, size_t len, BN_CTX *ctx)
299 {
300 point_conversion_form_t form;
301 int y_bit;
302 BN_CTX *new_ctx = NULL;
303 BIGNUM *x, *y, *yxi;
304 size_t field_len, enc_len;
305 int ret = 0;
306
307 if (len == 0)
308 {
309 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
310 return 0;
311 }
312 form = buf[0];
313 y_bit = form & 1;
314 form = form & ~1U;
315 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
316 && (form != POINT_CONVERSION_UNCOMPRESSED)
317 && (form != POINT_CONVERSION_HYBRID))
318 {
319 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
320 return 0;
321 }
322 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
323 {
324 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
325 return 0;
326 }
327
328 if (form == 0)
329 {
330 if (len != 1)
331 {
332 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
333 return 0;
334 }
335
336 return EC_POINT_set_to_infinity(group, point);
337 }
338
339 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
340 enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
341
342 if (len != enc_len)
343 {
344 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
345 return 0;
346 }
347
348 if (ctx == NULL)
349 {
350 ctx = new_ctx = BN_CTX_new();
351 if (ctx == NULL)
352 return 0;
353 }
354
355 BN_CTX_start(ctx);
356 x = BN_CTX_get(ctx);
357 y = BN_CTX_get(ctx);
358 yxi = BN_CTX_get(ctx);
359 if (yxi == NULL) goto err;
360
361 if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
362 if (BN_ucmp(x, &group->field) >= 0)
363 {
364 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
365 goto err;
366 }
367
368 if (form == POINT_CONVERSION_COMPRESSED)
369 {
370 if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
371 }
372 else
373 {
374 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
375 if (BN_ucmp(y, &group->field) >= 0)
376 {
377 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
378 goto err;
379 }
380 if (form == POINT_CONVERSION_HYBRID)
381 {
382 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
383 if (y_bit != BN_is_odd(yxi))
384 {
385 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
386 goto err;
387 }
388 }
389
390 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
391 }
392
393 if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
394 {
395 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
396 goto err;
397 }
398
399 ret = 1;
400
401 err:
402 BN_CTX_end(ctx);
403 if (new_ctx != NULL)
404 BN_CTX_free(new_ctx);
405 return ret;
406 }
407#endif
diff --git a/src/lib/libcrypto/ec/ec2_smpl.c b/src/lib/libcrypto/ec/ec2_smpl.c
index 03deae6674..e0e59c7d82 100644
--- a/src/lib/libcrypto/ec/ec2_smpl.c
+++ b/src/lib/libcrypto/ec/ec2_smpl.c
@@ -71,10 +71,20 @@
71 71
72#include "ec_lcl.h" 72#include "ec_lcl.h"
73 73
74#ifndef OPENSSL_NO_EC2M
75
76#ifdef OPENSSL_FIPS
77#include <openssl/fips.h>
78#endif
79
74 80
75const EC_METHOD *EC_GF2m_simple_method(void) 81const EC_METHOD *EC_GF2m_simple_method(void)
76 { 82 {
83#ifdef OPENSSL_FIPS
84 return fips_ec_gf2m_simple_method();
85#else
77 static const EC_METHOD ret = { 86 static const EC_METHOD ret = {
87 EC_FLAGS_DEFAULT_OCT,
78 NID_X9_62_characteristic_two_field, 88 NID_X9_62_characteristic_two_field,
79 ec_GF2m_simple_group_init, 89 ec_GF2m_simple_group_init,
80 ec_GF2m_simple_group_finish, 90 ec_GF2m_simple_group_finish,
@@ -93,9 +103,7 @@ const EC_METHOD *EC_GF2m_simple_method(void)
93 0 /* get_Jprojective_coordinates_GFp */, 103 0 /* get_Jprojective_coordinates_GFp */,
94 ec_GF2m_simple_point_set_affine_coordinates, 104 ec_GF2m_simple_point_set_affine_coordinates,
95 ec_GF2m_simple_point_get_affine_coordinates, 105 ec_GF2m_simple_point_get_affine_coordinates,
96 ec_GF2m_simple_set_compressed_coordinates, 106 0,0,0,
97 ec_GF2m_simple_point2oct,
98 ec_GF2m_simple_oct2point,
99 ec_GF2m_simple_add, 107 ec_GF2m_simple_add,
100 ec_GF2m_simple_dbl, 108 ec_GF2m_simple_dbl,
101 ec_GF2m_simple_invert, 109 ec_GF2m_simple_invert,
@@ -118,6 +126,7 @@ const EC_METHOD *EC_GF2m_simple_method(void)
118 0 /* field_set_to_one */ }; 126 0 /* field_set_to_one */ };
119 127
120 return &ret; 128 return &ret;
129#endif
121 } 130 }
122 131
123 132
@@ -405,340 +414,6 @@ int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_
405 return ret; 414 return ret;
406 } 415 }
407 416
408
409/* Calculates and sets the affine coordinates of an EC_POINT from the given
410 * compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
411 * Note that the simple implementation only uses affine coordinates.
412 *
413 * The method is from the following publication:
414 *
415 * Harper, Menezes, Vanstone:
416 * "Public-Key Cryptosystems with Very Small Key Lengths",
417 * EUROCRYPT '92, Springer-Verlag LNCS 658,
418 * published February 1993
419 *
420 * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
421 * the same method, but claim no priority date earlier than July 29, 1994
422 * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
423 */
424int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
425 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
426 {
427 BN_CTX *new_ctx = NULL;
428 BIGNUM *tmp, *x, *y, *z;
429 int ret = 0, z0;
430
431 /* clear error queue */
432 ERR_clear_error();
433
434 if (ctx == NULL)
435 {
436 ctx = new_ctx = BN_CTX_new();
437 if (ctx == NULL)
438 return 0;
439 }
440
441 y_bit = (y_bit != 0) ? 1 : 0;
442
443 BN_CTX_start(ctx);
444 tmp = BN_CTX_get(ctx);
445 x = BN_CTX_get(ctx);
446 y = BN_CTX_get(ctx);
447 z = BN_CTX_get(ctx);
448 if (z == NULL) goto err;
449
450 if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
451 if (BN_is_zero(x))
452 {
453 if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
454 }
455 else
456 {
457 if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
458 if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
459 if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
460 if (!BN_GF2m_add(tmp, x, tmp)) goto err;
461 if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
462 {
463 unsigned long err = ERR_peek_last_error();
464
465 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
466 {
467 ERR_clear_error();
468 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
469 }
470 else
471 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
472 goto err;
473 }
474 z0 = (BN_is_odd(z)) ? 1 : 0;
475 if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
476 if (z0 != y_bit)
477 {
478 if (!BN_GF2m_add(y, y, x)) goto err;
479 }
480 }
481
482 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
483
484 ret = 1;
485
486 err:
487 BN_CTX_end(ctx);
488 if (new_ctx != NULL)
489 BN_CTX_free(new_ctx);
490 return ret;
491 }
492
493
494/* Converts an EC_POINT to an octet string.
495 * If buf is NULL, the encoded length will be returned.
496 * If the length len of buf is smaller than required an error will be returned.
497 */
498size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
499 unsigned char *buf, size_t len, BN_CTX *ctx)
500 {
501 size_t ret;
502 BN_CTX *new_ctx = NULL;
503 int used_ctx = 0;
504 BIGNUM *x, *y, *yxi;
505 size_t field_len, i, skip;
506
507 if ((form != POINT_CONVERSION_COMPRESSED)
508 && (form != POINT_CONVERSION_UNCOMPRESSED)
509 && (form != POINT_CONVERSION_HYBRID))
510 {
511 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
512 goto err;
513 }
514
515 if (EC_POINT_is_at_infinity(group, point))
516 {
517 /* encodes to a single 0 octet */
518 if (buf != NULL)
519 {
520 if (len < 1)
521 {
522 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
523 return 0;
524 }
525 buf[0] = 0;
526 }
527 return 1;
528 }
529
530
531 /* ret := required output buffer length */
532 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
533 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
534
535 /* if 'buf' is NULL, just return required length */
536 if (buf != NULL)
537 {
538 if (len < ret)
539 {
540 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
541 goto err;
542 }
543
544 if (ctx == NULL)
545 {
546 ctx = new_ctx = BN_CTX_new();
547 if (ctx == NULL)
548 return 0;
549 }
550
551 BN_CTX_start(ctx);
552 used_ctx = 1;
553 x = BN_CTX_get(ctx);
554 y = BN_CTX_get(ctx);
555 yxi = BN_CTX_get(ctx);
556 if (yxi == NULL) goto err;
557
558 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
559
560 buf[0] = form;
561 if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
562 {
563 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
564 if (BN_is_odd(yxi)) buf[0]++;
565 }
566
567 i = 1;
568
569 skip = field_len - BN_num_bytes(x);
570 if (skip > field_len)
571 {
572 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
573 goto err;
574 }
575 while (skip > 0)
576 {
577 buf[i++] = 0;
578 skip--;
579 }
580 skip = BN_bn2bin(x, buf + i);
581 i += skip;
582 if (i != 1 + field_len)
583 {
584 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
585 goto err;
586 }
587
588 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
589 {
590 skip = field_len - BN_num_bytes(y);
591 if (skip > field_len)
592 {
593 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
594 goto err;
595 }
596 while (skip > 0)
597 {
598 buf[i++] = 0;
599 skip--;
600 }
601 skip = BN_bn2bin(y, buf + i);
602 i += skip;
603 }
604
605 if (i != ret)
606 {
607 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
608 goto err;
609 }
610 }
611
612 if (used_ctx)
613 BN_CTX_end(ctx);
614 if (new_ctx != NULL)
615 BN_CTX_free(new_ctx);
616 return ret;
617
618 err:
619 if (used_ctx)
620 BN_CTX_end(ctx);
621 if (new_ctx != NULL)
622 BN_CTX_free(new_ctx);
623 return 0;
624 }
625
626
627/* Converts an octet string representation to an EC_POINT.
628 * Note that the simple implementation only uses affine coordinates.
629 */
630int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
631 const unsigned char *buf, size_t len, BN_CTX *ctx)
632 {
633 point_conversion_form_t form;
634 int y_bit;
635 BN_CTX *new_ctx = NULL;
636 BIGNUM *x, *y, *yxi;
637 size_t field_len, enc_len;
638 int ret = 0;
639
640 if (len == 0)
641 {
642 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
643 return 0;
644 }
645 form = buf[0];
646 y_bit = form & 1;
647 form = form & ~1U;
648 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
649 && (form != POINT_CONVERSION_UNCOMPRESSED)
650 && (form != POINT_CONVERSION_HYBRID))
651 {
652 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
653 return 0;
654 }
655 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
656 {
657 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
658 return 0;
659 }
660
661 if (form == 0)
662 {
663 if (len != 1)
664 {
665 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
666 return 0;
667 }
668
669 return EC_POINT_set_to_infinity(group, point);
670 }
671
672 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
673 enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
674
675 if (len != enc_len)
676 {
677 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
678 return 0;
679 }
680
681 if (ctx == NULL)
682 {
683 ctx = new_ctx = BN_CTX_new();
684 if (ctx == NULL)
685 return 0;
686 }
687
688 BN_CTX_start(ctx);
689 x = BN_CTX_get(ctx);
690 y = BN_CTX_get(ctx);
691 yxi = BN_CTX_get(ctx);
692 if (yxi == NULL) goto err;
693
694 if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
695 if (BN_ucmp(x, &group->field) >= 0)
696 {
697 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
698 goto err;
699 }
700
701 if (form == POINT_CONVERSION_COMPRESSED)
702 {
703 if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
704 }
705 else
706 {
707 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
708 if (BN_ucmp(y, &group->field) >= 0)
709 {
710 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
711 goto err;
712 }
713 if (form == POINT_CONVERSION_HYBRID)
714 {
715 if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
716 if (y_bit != BN_is_odd(yxi))
717 {
718 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
719 goto err;
720 }
721 }
722
723 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
724 }
725
726 if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
727 {
728 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
729 goto err;
730 }
731
732 ret = 1;
733
734 err:
735 BN_CTX_end(ctx);
736 if (new_ctx != NULL)
737 BN_CTX_free(new_ctx);
738 return ret;
739 }
740
741
742/* Computes a + b and stores the result in r. r could be a or b, a could be b. 417/* Computes a + b and stores the result in r. r could be a or b, a could be b.
743 * Uses algorithm A.10.2 of IEEE P1363. 418 * Uses algorithm A.10.2 of IEEE P1363.
744 */ 419 */
@@ -1040,3 +715,5 @@ int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
1040 { 715 {
1041 return BN_GF2m_mod_div(r, a, b, &group->field, ctx); 716 return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
1042 } 717 }
718
719#endif
diff --git a/src/lib/libcrypto/ec/ec_ameth.c b/src/lib/libcrypto/ec/ec_ameth.c
index c00f7d746c..83909c1853 100644
--- a/src/lib/libcrypto/ec/ec_ameth.c
+++ b/src/lib/libcrypto/ec/ec_ameth.c
@@ -651,6 +651,7 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth =
651 ec_copy_parameters, 651 ec_copy_parameters,
652 ec_cmp_parameters, 652 ec_cmp_parameters,
653 eckey_param_print, 653 eckey_param_print,
654 0,
654 655
655 int_ec_free, 656 int_ec_free,
656 ec_pkey_ctrl, 657 ec_pkey_ctrl,
diff --git a/src/lib/libcrypto/ec/ec_asn1.c b/src/lib/libcrypto/ec/ec_asn1.c
index ae55539859..175eec5342 100644
--- a/src/lib/libcrypto/ec/ec_asn1.c
+++ b/src/lib/libcrypto/ec/ec_asn1.c
@@ -83,7 +83,7 @@ int EC_GROUP_get_basis_type(const EC_GROUP *group)
83 /* everything else is currently not supported */ 83 /* everything else is currently not supported */
84 return 0; 84 return 0;
85 } 85 }
86 86#ifndef OPENSSL_NO_EC2M
87int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k) 87int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
88 { 88 {
89 if (group == NULL) 89 if (group == NULL)
@@ -101,7 +101,6 @@ int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
101 101
102 return 1; 102 return 1;
103 } 103 }
104
105int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1, 104int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
106 unsigned int *k2, unsigned int *k3) 105 unsigned int *k2, unsigned int *k3)
107 { 106 {
@@ -124,7 +123,7 @@ int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
124 123
125 return 1; 124 return 1;
126 } 125 }
127 126#endif
128 127
129 128
130/* some structures needed for the asn1 encoding */ 129/* some structures needed for the asn1 encoding */
@@ -340,6 +339,12 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
340 } 339 }
341 } 340 }
342 else /* nid == NID_X9_62_characteristic_two_field */ 341 else /* nid == NID_X9_62_characteristic_two_field */
342#ifdef OPENSSL_NO_EC2M
343 {
344 ECerr(EC_F_EC_ASN1_GROUP2FIELDID, EC_R_GF2M_NOT_SUPPORTED);
345 goto err;
346 }
347#else
343 { 348 {
344 int field_type; 349 int field_type;
345 X9_62_CHARACTERISTIC_TWO *char_two; 350 X9_62_CHARACTERISTIC_TWO *char_two;
@@ -419,6 +424,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
419 } 424 }
420 } 425 }
421 } 426 }
427#endif
422 428
423 ok = 1; 429 ok = 1;
424 430
@@ -456,6 +462,7 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
456 goto err; 462 goto err;
457 } 463 }
458 } 464 }
465#ifndef OPENSSL_NO_EC2M
459 else /* nid == NID_X9_62_characteristic_two_field */ 466 else /* nid == NID_X9_62_characteristic_two_field */
460 { 467 {
461 if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL)) 468 if (!EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL))
@@ -464,7 +471,7 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
464 goto err; 471 goto err;
465 } 472 }
466 } 473 }
467 474#endif
468 len_1 = (size_t)BN_num_bytes(tmp_1); 475 len_1 = (size_t)BN_num_bytes(tmp_1);
469 len_2 = (size_t)BN_num_bytes(tmp_2); 476 len_2 = (size_t)BN_num_bytes(tmp_2);
470 477
@@ -775,8 +782,13 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
775 782
776 /* get the field parameters */ 783 /* get the field parameters */
777 tmp = OBJ_obj2nid(params->fieldID->fieldType); 784 tmp = OBJ_obj2nid(params->fieldID->fieldType);
778
779 if (tmp == NID_X9_62_characteristic_two_field) 785 if (tmp == NID_X9_62_characteristic_two_field)
786#ifdef OPENSSL_NO_EC2M
787 {
788 ECerr(EC_F_EC_ASN1_PARAMETERS2GROUP, EC_R_GF2M_NOT_SUPPORTED);
789 goto err;
790 }
791#else
780 { 792 {
781 X9_62_CHARACTERISTIC_TWO *char_two; 793 X9_62_CHARACTERISTIC_TWO *char_two;
782 794
@@ -862,6 +874,7 @@ static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *params)
862 /* create the EC_GROUP structure */ 874 /* create the EC_GROUP structure */
863 ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL); 875 ret = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
864 } 876 }
877#endif
865 else if (tmp == NID_X9_62_prime_field) 878 else if (tmp == NID_X9_62_prime_field)
866 { 879 {
867 /* we have a curve over a prime field */ 880 /* we have a curve over a prime field */
@@ -1065,6 +1078,7 @@ EC_GROUP *d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
1065 if ((group = ec_asn1_pkparameters2group(params)) == NULL) 1078 if ((group = ec_asn1_pkparameters2group(params)) == NULL)
1066 { 1079 {
1067 ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE); 1080 ECerr(EC_F_D2I_ECPKPARAMETERS, EC_R_PKPARAMETERS2GROUP_FAILURE);
1081 ECPKPARAMETERS_free(params);
1068 return NULL; 1082 return NULL;
1069 } 1083 }
1070 1084
diff --git a/src/lib/libcrypto/ec/ec_curve.c b/src/lib/libcrypto/ec/ec_curve.c
index 23274e4031..c72fb2697c 100644
--- a/src/lib/libcrypto/ec/ec_curve.c
+++ b/src/lib/libcrypto/ec/ec_curve.c
@@ -3,7 +3,7 @@
3 * Written by Nils Larsch for the OpenSSL project. 3 * Written by Nils Larsch for the OpenSSL project.
4 */ 4 */
5/* ==================================================================== 5/* ====================================================================
6 * Copyright (c) 1998-2004 The OpenSSL Project. All rights reserved. 6 * Copyright (c) 1998-2010 The OpenSSL Project. All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
@@ -72,6 +72,7 @@
72#include "ec_lcl.h" 72#include "ec_lcl.h"
73#include <openssl/err.h> 73#include <openssl/err.h>
74#include <openssl/obj_mac.h> 74#include <openssl/obj_mac.h>
75#include <openssl/opensslconf.h>
75 76
76typedef struct { 77typedef struct {
77 int field_type, /* either NID_X9_62_prime_field or 78 int field_type, /* either NID_X9_62_prime_field or
@@ -703,6 +704,8 @@ static const struct { EC_CURVE_DATA h; unsigned char data[0+28*6]; }
703 0x13,0xDD,0x29,0x45,0x5C,0x5C,0x2A,0x3D } 704 0x13,0xDD,0x29,0x45,0x5C,0x5C,0x2A,0x3D }
704 }; 705 };
705 706
707#ifndef OPENSSL_NO_EC2M
708
706/* characteristic two curves */ 709/* characteristic two curves */
707static const struct { EC_CURVE_DATA h; unsigned char data[20+15*6]; } 710static const struct { EC_CURVE_DATA h; unsigned char data[20+15*6]; }
708 _EC_SECG_CHAR2_113R1 = { 711 _EC_SECG_CHAR2_113R1 = {
@@ -1300,7 +1303,7 @@ static const struct { EC_CURVE_DATA h; unsigned char data[20+21*6]; }
1300 { 0x53,0x81,0x4C,0x05,0x0D,0x44,0xD6,0x96,0xE6,0x76, /* seed */ 1303 { 0x53,0x81,0x4C,0x05,0x0D,0x44,0xD6,0x96,0xE6,0x76, /* seed */
1301 0x87,0x56,0x15,0x17,0x58,0x0C,0xA4,0xE2,0x9F,0xFD, 1304 0x87,0x56,0x15,0x17,0x58,0x0C,0xA4,0xE2,0x9F,0xFD,
1302 1305
1303 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */ 1306 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* p */
1304 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 1307 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
1305 0x07, 1308 0x07,
1306 0x01,0x08,0xB3,0x9E,0x77,0xC4,0xB1,0x08,0xBE,0xD9, /* a */ 1309 0x01,0x08,0xB3,0x9E,0x77,0xC4,0xB1,0x08,0xBE,0xD9, /* a */
@@ -1817,103 +1820,128 @@ static const struct { EC_CURVE_DATA h; unsigned char data[0+24*6]; }
1817 0xBA,0xFC,0xA7,0x5E } 1820 0xBA,0xFC,0xA7,0x5E }
1818 }; 1821 };
1819 1822
1823#endif
1824
1820typedef struct _ec_list_element_st { 1825typedef struct _ec_list_element_st {
1821 int nid; 1826 int nid;
1822 const EC_CURVE_DATA *data; 1827 const EC_CURVE_DATA *data;
1828 const EC_METHOD *(*meth)(void);
1823 const char *comment; 1829 const char *comment;
1824 } ec_list_element; 1830 } ec_list_element;
1825 1831
1826static const ec_list_element curve_list[] = { 1832static const ec_list_element curve_list[] = {
1827 /* prime field curves */ 1833 /* prime field curves */
1828 /* secg curves */ 1834 /* secg curves */
1829 { NID_secp112r1, &_EC_SECG_PRIME_112R1.h, "SECG/WTLS curve over a 112 bit prime field"}, 1835 { NID_secp112r1, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field" },
1830 { NID_secp112r2, &_EC_SECG_PRIME_112R2.h, "SECG curve over a 112 bit prime field"}, 1836 { NID_secp112r2, &_EC_SECG_PRIME_112R2.h, 0, "SECG curve over a 112 bit prime field" },
1831 { NID_secp128r1, &_EC_SECG_PRIME_128R1.h, "SECG curve over a 128 bit prime field"}, 1837 { NID_secp128r1, &_EC_SECG_PRIME_128R1.h, 0, "SECG curve over a 128 bit prime field" },
1832 { NID_secp128r2, &_EC_SECG_PRIME_128R2.h, "SECG curve over a 128 bit prime field"}, 1838 { NID_secp128r2, &_EC_SECG_PRIME_128R2.h, 0, "SECG curve over a 128 bit prime field" },
1833 { NID_secp160k1, &_EC_SECG_PRIME_160K1.h, "SECG curve over a 160 bit prime field"}, 1839 { NID_secp160k1, &_EC_SECG_PRIME_160K1.h, 0, "SECG curve over a 160 bit prime field" },
1834 { NID_secp160r1, &_EC_SECG_PRIME_160R1.h, "SECG curve over a 160 bit prime field"}, 1840 { NID_secp160r1, &_EC_SECG_PRIME_160R1.h, 0, "SECG curve over a 160 bit prime field" },
1835 { NID_secp160r2, &_EC_SECG_PRIME_160R2.h, "SECG/WTLS curve over a 160 bit prime field"}, 1841 { NID_secp160r2, &_EC_SECG_PRIME_160R2.h, 0, "SECG/WTLS curve over a 160 bit prime field" },
1836 /* SECG secp192r1 is the same as X9.62 prime192v1 and hence omitted */ 1842 /* SECG secp192r1 is the same as X9.62 prime192v1 and hence omitted */
1837 { NID_secp192k1, &_EC_SECG_PRIME_192K1.h, "SECG curve over a 192 bit prime field"}, 1843 { NID_secp192k1, &_EC_SECG_PRIME_192K1.h, 0, "SECG curve over a 192 bit prime field" },
1838 { NID_secp224k1, &_EC_SECG_PRIME_224K1.h, "SECG curve over a 224 bit prime field"}, 1844 { NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0, "SECG curve over a 224 bit prime field" },
1839 { NID_secp224r1, &_EC_NIST_PRIME_224.h, "NIST/SECG curve over a 224 bit prime field"}, 1845#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1840 { NID_secp256k1, &_EC_SECG_PRIME_256K1.h, "SECG curve over a 256 bit prime field"}, 1846 { NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method, "NIST/SECG curve over a 224 bit prime field" },
1847#else
1848 { NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, "NIST/SECG curve over a 224 bit prime field" },
1849#endif
1850 { NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0, "SECG curve over a 256 bit prime field" },
1841 /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */ 1851 /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
1842 { NID_secp384r1, &_EC_NIST_PRIME_384.h, "NIST/SECG curve over a 384 bit prime field"}, 1852 { NID_secp384r1, &_EC_NIST_PRIME_384.h, 0, "NIST/SECG curve over a 384 bit prime field" },
1843 { NID_secp521r1, &_EC_NIST_PRIME_521.h, "NIST/SECG curve over a 521 bit prime field"}, 1853#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1854 { NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method, "NIST/SECG curve over a 521 bit prime field" },
1855#else
1856 { NID_secp521r1, &_EC_NIST_PRIME_521.h, 0, "NIST/SECG curve over a 521 bit prime field" },
1857#endif
1844 /* X9.62 curves */ 1858 /* X9.62 curves */
1845 { NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, "NIST/X9.62/SECG curve over a 192 bit prime field"}, 1859 { NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, "NIST/X9.62/SECG curve over a 192 bit prime field" },
1846 { NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, "X9.62 curve over a 192 bit prime field"}, 1860 { NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0, "X9.62 curve over a 192 bit prime field" },
1847 { NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, "X9.62 curve over a 192 bit prime field"}, 1861 { NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, 0, "X9.62 curve over a 192 bit prime field" },
1848 { NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, "X9.62 curve over a 239 bit prime field"}, 1862 { NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, 0, "X9.62 curve over a 239 bit prime field" },
1849 { NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, "X9.62 curve over a 239 bit prime field"}, 1863 { NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0, "X9.62 curve over a 239 bit prime field" },
1850 { NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, "X9.62 curve over a 239 bit prime field"}, 1864 { NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0, "X9.62 curve over a 239 bit prime field" },
1851 { NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, "X9.62/SECG curve over a 256 bit prime field"}, 1865#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1866 { NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, EC_GFp_nistp256_method, "X9.62/SECG curve over a 256 bit prime field" },
1867#else
1868 { NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, 0, "X9.62/SECG curve over a 256 bit prime field" },
1869#endif
1870#ifndef OPENSSL_NO_EC2M
1852 /* characteristic two field curves */ 1871 /* characteristic two field curves */
1853 /* NIST/SECG curves */ 1872 /* NIST/SECG curves */
1854 { NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, "SECG curve over a 113 bit binary field"}, 1873 { NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field" },
1855 { NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, "SECG curve over a 113 bit binary field"}, 1874 { NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, 0, "SECG curve over a 113 bit binary field" },
1856 { NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, "SECG/WTLS curve over a 131 bit binary field"}, 1875 { NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, 0, "SECG/WTLS curve over a 131 bit binary field" },
1857 { NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, "SECG curve over a 131 bit binary field"}, 1876 { NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, 0, "SECG curve over a 131 bit binary field" },
1858 { NID_sect163k1, &_EC_NIST_CHAR2_163K.h, "NIST/SECG/WTLS curve over a 163 bit binary field" }, 1877 { NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field" },
1859 { NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, "SECG curve over a 163 bit binary field"}, 1878 { NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, 0, "SECG curve over a 163 bit binary field" },
1860 { NID_sect163r2, &_EC_NIST_CHAR2_163B.h, "NIST/SECG curve over a 163 bit binary field" }, 1879 { NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0, "NIST/SECG curve over a 163 bit binary field" },
1861 { NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, "SECG curve over a 193 bit binary field"}, 1880 { NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, 0, "SECG curve over a 193 bit binary field" },
1862 { NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, "SECG curve over a 193 bit binary field"}, 1881 { NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, 0, "SECG curve over a 193 bit binary field" },
1863 { NID_sect233k1, &_EC_NIST_CHAR2_233K.h, "NIST/SECG/WTLS curve over a 233 bit binary field" }, 1882 { NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
1864 { NID_sect233r1, &_EC_NIST_CHAR2_233B.h, "NIST/SECG/WTLS curve over a 233 bit binary field" }, 1883 { NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
1865 { NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, "SECG curve over a 239 bit binary field"}, 1884 { NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, 0, "SECG curve over a 239 bit binary field" },
1866 { NID_sect283k1, &_EC_NIST_CHAR2_283K.h, "NIST/SECG curve over a 283 bit binary field" }, 1885 { NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0, "NIST/SECG curve over a 283 bit binary field" },
1867 { NID_sect283r1, &_EC_NIST_CHAR2_283B.h, "NIST/SECG curve over a 283 bit binary field" }, 1886 { NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0, "NIST/SECG curve over a 283 bit binary field" },
1868 { NID_sect409k1, &_EC_NIST_CHAR2_409K.h, "NIST/SECG curve over a 409 bit binary field" }, 1887 { NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0, "NIST/SECG curve over a 409 bit binary field" },
1869 { NID_sect409r1, &_EC_NIST_CHAR2_409B.h, "NIST/SECG curve over a 409 bit binary field" }, 1888 { NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0, "NIST/SECG curve over a 409 bit binary field" },
1870 { NID_sect571k1, &_EC_NIST_CHAR2_571K.h, "NIST/SECG curve over a 571 bit binary field" }, 1889 { NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0, "NIST/SECG curve over a 571 bit binary field" },
1871 { NID_sect571r1, &_EC_NIST_CHAR2_571B.h, "NIST/SECG curve over a 571 bit binary field" }, 1890 { NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0, "NIST/SECG curve over a 571 bit binary field" },
1872 /* X9.62 curves */ 1891 /* X9.62 curves */
1873 { NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, "X9.62 curve over a 163 bit binary field"}, 1892 { NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field" },
1874 { NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, "X9.62 curve over a 163 bit binary field"}, 1893 { NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, 0, "X9.62 curve over a 163 bit binary field" },
1875 { NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, "X9.62 curve over a 163 bit binary field"}, 1894 { NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, 0, "X9.62 curve over a 163 bit binary field" },
1876 { NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, "X9.62 curve over a 176 bit binary field"}, 1895 { NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, 0, "X9.62 curve over a 176 bit binary field" },
1877 { NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, "X9.62 curve over a 191 bit binary field"}, 1896 { NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, 0, "X9.62 curve over a 191 bit binary field" },
1878 { NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, "X9.62 curve over a 191 bit binary field"}, 1897 { NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, 0, "X9.62 curve over a 191 bit binary field" },
1879 { NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, "X9.62 curve over a 191 bit binary field"}, 1898 { NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, 0, "X9.62 curve over a 191 bit binary field" },
1880 { NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, "X9.62 curve over a 208 bit binary field"}, 1899 { NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, 0, "X9.62 curve over a 208 bit binary field" },
1881 { NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, "X9.62 curve over a 239 bit binary field"}, 1900 { NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, 0, "X9.62 curve over a 239 bit binary field" },
1882 { NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, "X9.62 curve over a 239 bit binary field"}, 1901 { NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, 0, "X9.62 curve over a 239 bit binary field" },
1883 { NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, "X9.62 curve over a 239 bit binary field"}, 1902 { NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, 0, "X9.62 curve over a 239 bit binary field" },
1884 { NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, "X9.62 curve over a 272 bit binary field"}, 1903 { NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, 0, "X9.62 curve over a 272 bit binary field" },
1885 { NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, "X9.62 curve over a 304 bit binary field"}, 1904 { NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, 0, "X9.62 curve over a 304 bit binary field" },
1886 { NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, "X9.62 curve over a 359 bit binary field"}, 1905 { NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, 0, "X9.62 curve over a 359 bit binary field" },
1887 { NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, "X9.62 curve over a 368 bit binary field"}, 1906 { NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, 0, "X9.62 curve over a 368 bit binary field" },
1888 { NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, "X9.62 curve over a 431 bit binary field"}, 1907 { NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, 0, "X9.62 curve over a 431 bit binary field" },
1889 /* the WAP/WTLS curves 1908 /* the WAP/WTLS curves
1890 * [unlike SECG, spec has its own OIDs for curves from X9.62] */ 1909 * [unlike SECG, spec has its own OIDs for curves from X9.62] */
1891 { NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, "WTLS curve over a 113 bit binary field"}, 1910 { NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, 0, "WTLS curve over a 113 bit binary field" },
1892 { NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, "NIST/SECG/WTLS curve over a 163 bit binary field"}, 1911 { NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0, "NIST/SECG/WTLS curve over a 163 bit binary field" },
1893 { NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, "SECG curve over a 113 bit binary field"}, 1912 { NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0, "SECG curve over a 113 bit binary field" },
1894 { NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, "X9.62 curve over a 163 bit binary field"}, 1913 { NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0, "X9.62 curve over a 163 bit binary field" },
1895 { NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, "SECG/WTLS curve over a 112 bit prime field"}, 1914#endif
1896 { NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, "SECG/WTLS curve over a 160 bit prime field"}, 1915 { NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0, "SECG/WTLS curve over a 112 bit prime field" },
1897 { NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, "WTLS curve over a 112 bit prime field"}, 1916 { NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0, "SECG/WTLS curve over a 160 bit prime field" },
1898 { NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, "WTLS curve over a 160 bit prime field" }, 1917 { NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0, "WTLS curve over a 112 bit prime field" },
1899 { NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, "NIST/SECG/WTLS curve over a 233 bit binary field"}, 1918 { NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0, "WTLS curve over a 160 bit prime field" },
1900 { NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, "NIST/SECG/WTLS curve over a 233 bit binary field"}, 1919#ifndef OPENSSL_NO_EC2M
1901 { NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, "WTLS curvs over a 224 bit prime field"}, 1920 { NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
1921 { NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0, "NIST/SECG/WTLS curve over a 233 bit binary field" },
1922#endif
1923 { NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0, "WTLS curvs over a 224 bit prime field" },
1924#ifndef OPENSSL_NO_EC2M
1902 /* IPSec curves */ 1925 /* IPSec curves */
1903 { NID_ipsec3, &_EC_IPSEC_155_ID3.h, "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n""\tNot suitable for ECDSA.\n\tQuestionable extension field!"}, 1926 { NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0, "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n"
1904 { NID_ipsec4, &_EC_IPSEC_185_ID4.h, "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n""\tNot suitable for ECDSA.\n\tQuestionable extension field!"}, 1927 "\tNot suitable for ECDSA.\n\tQuestionable extension field!" },
1928 { NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0, "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n"
1929 "\tNot suitable for ECDSA.\n\tQuestionable extension field!" },
1930#endif
1905}; 1931};
1906 1932
1907#define curve_list_length (sizeof(curve_list)/sizeof(ec_list_element)) 1933#define curve_list_length (sizeof(curve_list)/sizeof(ec_list_element))
1908 1934
1909static EC_GROUP *ec_group_new_from_data(const EC_CURVE_DATA *data) 1935static EC_GROUP *ec_group_new_from_data(const ec_list_element curve)
1910 { 1936 {
1911 EC_GROUP *group=NULL; 1937 EC_GROUP *group=NULL;
1912 EC_POINT *P=NULL; 1938 EC_POINT *P=NULL;
1913 BN_CTX *ctx=NULL; 1939 BN_CTX *ctx=NULL;
1914 BIGNUM *p=NULL, *a=NULL, *b=NULL, *x=NULL, *y=NULL, *order=NULL; 1940 BIGNUM *p=NULL, *a=NULL, *b=NULL, *x=NULL, *y=NULL, *order=NULL;
1915 int ok=0; 1941 int ok=0;
1916 int seed_len,param_len; 1942 int seed_len,param_len;
1943 const EC_METHOD *meth;
1944 const EC_CURVE_DATA *data;
1917 const unsigned char *params; 1945 const unsigned char *params;
1918 1946
1919 if ((ctx = BN_CTX_new()) == NULL) 1947 if ((ctx = BN_CTX_new()) == NULL)
@@ -1922,10 +1950,11 @@ static EC_GROUP *ec_group_new_from_data(const EC_CURVE_DATA *data)
1922 goto err; 1950 goto err;
1923 } 1951 }
1924 1952
1953 data = curve.data;
1925 seed_len = data->seed_len; 1954 seed_len = data->seed_len;
1926 param_len = data->param_len; 1955 param_len = data->param_len;
1927 params = (const unsigned char *)(data+1); /* skip header */ 1956 params = (const unsigned char *)(data+1); /* skip header */
1928 params += seed_len; /* skip seed */ 1957 params += seed_len; /* skip seed */
1929 1958
1930 if (!(p = BN_bin2bn(params+0*param_len, param_len, NULL)) 1959 if (!(p = BN_bin2bn(params+0*param_len, param_len, NULL))
1931 || !(a = BN_bin2bn(params+1*param_len, param_len, NULL)) 1960 || !(a = BN_bin2bn(params+1*param_len, param_len, NULL))
@@ -1935,7 +1964,17 @@ static EC_GROUP *ec_group_new_from_data(const EC_CURVE_DATA *data)
1935 goto err; 1964 goto err;
1936 } 1965 }
1937 1966
1938 if (data->field_type == NID_X9_62_prime_field) 1967 if (curve.meth != 0)
1968 {
1969 meth = curve.meth();
1970 if (((group = EC_GROUP_new(meth)) == NULL) ||
1971 (!(group->meth->group_set_curve(group, p, a, b, ctx))))
1972 {
1973 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
1974 goto err;
1975 }
1976 }
1977 else if (data->field_type == NID_X9_62_prime_field)
1939 { 1978 {
1940 if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) 1979 if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL)
1941 { 1980 {
@@ -1943,6 +1982,7 @@ static EC_GROUP *ec_group_new_from_data(const EC_CURVE_DATA *data)
1943 goto err; 1982 goto err;
1944 } 1983 }
1945 } 1984 }
1985#ifndef OPENSSL_NO_EC2M
1946 else /* field_type == NID_X9_62_characteristic_two_field */ 1986 else /* field_type == NID_X9_62_characteristic_two_field */
1947 { 1987 {
1948 if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL) 1988 if ((group = EC_GROUP_new_curve_GF2m(p, a, b, ctx)) == NULL)
@@ -1951,20 +1991,21 @@ static EC_GROUP *ec_group_new_from_data(const EC_CURVE_DATA *data)
1951 goto err; 1991 goto err;
1952 } 1992 }
1953 } 1993 }
1994#endif
1954 1995
1955 if ((P = EC_POINT_new(group)) == NULL) 1996 if ((P = EC_POINT_new(group)) == NULL)
1956 { 1997 {
1957 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); 1998 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
1958 goto err; 1999 goto err;
1959 } 2000 }
1960 2001
1961 if (!(x = BN_bin2bn(params+3*param_len, param_len, NULL)) 2002 if (!(x = BN_bin2bn(params+3*param_len, param_len, NULL))
1962 || !(y = BN_bin2bn(params+4*param_len, param_len, NULL))) 2003 || !(y = BN_bin2bn(params+4*param_len, param_len, NULL)))
1963 { 2004 {
1964 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB); 2005 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
1965 goto err; 2006 goto err;
1966 } 2007 }
1967 if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx)) 2008 if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx))
1968 { 2009 {
1969 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB); 2010 ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
1970 goto err; 2011 goto err;
@@ -2025,7 +2066,7 @@ EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
2025 for (i=0; i<curve_list_length; i++) 2066 for (i=0; i<curve_list_length; i++)
2026 if (curve_list[i].nid == nid) 2067 if (curve_list[i].nid == nid)
2027 { 2068 {
2028 ret = ec_group_new_from_data(curve_list[i].data); 2069 ret = ec_group_new_from_data(curve_list[i]);
2029 break; 2070 break;
2030 } 2071 }
2031 2072
diff --git a/src/lib/libcrypto/ec/ec_cvt.c b/src/lib/libcrypto/ec/ec_cvt.c
index d45640bab9..bfcbab35fe 100644
--- a/src/lib/libcrypto/ec/ec_cvt.c
+++ b/src/lib/libcrypto/ec/ec_cvt.c
@@ -78,7 +78,32 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM
78 const EC_METHOD *meth; 78 const EC_METHOD *meth;
79 EC_GROUP *ret; 79 EC_GROUP *ret;
80 80
81#if defined(OPENSSL_BN_ASM_MONT)
82 /*
83 * This might appear controversial, but the fact is that generic
84 * prime method was observed to deliver better performance even
85 * for NIST primes on a range of platforms, e.g.: 60%-15%
86 * improvement on IA-64, ~25% on ARM, 30%-90% on P4, 20%-25%
87 * in 32-bit build and 35%--12% in 64-bit build on Core2...
88 * Coefficients are relative to optimized bn_nist.c for most
89 * intensive ECDSA verify and ECDH operations for 192- and 521-
90 * bit keys respectively. Choice of these boundary values is
91 * arguable, because the dependency of improvement coefficient
92 * from key length is not a "monotone" curve. For example while
93 * 571-bit result is 23% on ARM, 384-bit one is -1%. But it's
94 * generally faster, sometimes "respectfully" faster, sometimes
95 * "tolerably" slower... What effectively happens is that loop
96 * with bn_mul_add_words is put against bn_mul_mont, and the
97 * latter "wins" on short vectors. Correct solution should be
98 * implementing dedicated NxN multiplication subroutines for
99 * small N. But till it materializes, let's stick to generic
100 * prime method...
101 * <appro>
102 */
103 meth = EC_GFp_mont_method();
104#else
81 meth = EC_GFp_nist_method(); 105 meth = EC_GFp_nist_method();
106#endif
82 107
83 ret = EC_GROUP_new(meth); 108 ret = EC_GROUP_new(meth);
84 if (ret == NULL) 109 if (ret == NULL)
@@ -122,7 +147,7 @@ EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM
122 return ret; 147 return ret;
123 } 148 }
124 149
125 150#ifndef OPENSSL_NO_EC2M
126EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 151EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
127 { 152 {
128 const EC_METHOD *meth; 153 const EC_METHOD *meth;
@@ -142,3 +167,4 @@ EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a, const BIGNUM
142 167
143 return ret; 168 return ret;
144 } 169 }
170#endif
diff --git a/src/lib/libcrypto/ec/ec_err.c b/src/lib/libcrypto/ec/ec_err.c
index 84b4833371..0d19398731 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-2007 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 1999-2011 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
@@ -70,6 +70,7 @@
70 70
71static ERR_STRING_DATA EC_str_functs[]= 71static ERR_STRING_DATA EC_str_functs[]=
72 { 72 {
73{ERR_FUNC(EC_F_BN_TO_FELEM), "BN_TO_FELEM"},
73{ERR_FUNC(EC_F_COMPUTE_WNAF), "COMPUTE_WNAF"}, 74{ERR_FUNC(EC_F_COMPUTE_WNAF), "COMPUTE_WNAF"},
74{ERR_FUNC(EC_F_D2I_ECPARAMETERS), "d2i_ECParameters"}, 75{ERR_FUNC(EC_F_D2I_ECPARAMETERS), "d2i_ECParameters"},
75{ERR_FUNC(EC_F_D2I_ECPKPARAMETERS), "d2i_ECPKParameters"}, 76{ERR_FUNC(EC_F_D2I_ECPKPARAMETERS), "d2i_ECPKParameters"},
@@ -112,6 +113,15 @@ static ERR_STRING_DATA EC_str_functs[]=
112{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"}, 113{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"},
113{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE), "ec_GFp_mont_group_set_curve"}, 114{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE), "ec_GFp_mont_group_set_curve"},
114{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP), "EC_GFP_MONT_GROUP_SET_CURVE_GFP"}, 115{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP), "EC_GFP_MONT_GROUP_SET_CURVE_GFP"},
116{ERR_FUNC(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE), "ec_GFp_nistp224_group_set_curve"},
117{ERR_FUNC(EC_F_EC_GFP_NISTP224_POINTS_MUL), "ec_GFp_nistp224_points_mul"},
118{ERR_FUNC(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES), "ec_GFp_nistp224_point_get_affine_coordinates"},
119{ERR_FUNC(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE), "ec_GFp_nistp256_group_set_curve"},
120{ERR_FUNC(EC_F_EC_GFP_NISTP256_POINTS_MUL), "ec_GFp_nistp256_points_mul"},
121{ERR_FUNC(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES), "ec_GFp_nistp256_point_get_affine_coordinates"},
122{ERR_FUNC(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE), "ec_GFp_nistp521_group_set_curve"},
123{ERR_FUNC(EC_F_EC_GFP_NISTP521_POINTS_MUL), "ec_GFp_nistp521_points_mul"},
124{ERR_FUNC(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES), "ec_GFp_nistp521_point_get_affine_coordinates"},
115{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL), "ec_GFp_nist_field_mul"}, 125{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL), "ec_GFp_nist_field_mul"},
116{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"}, 126{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"},
117{ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE), "ec_GFp_nist_group_set_curve"}, 127{ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE), "ec_GFp_nist_group_set_curve"},
@@ -154,6 +164,7 @@ static ERR_STRING_DATA EC_str_functs[]=
154{ERR_FUNC(EC_F_EC_KEY_NEW), "EC_KEY_new"}, 164{ERR_FUNC(EC_F_EC_KEY_NEW), "EC_KEY_new"},
155{ERR_FUNC(EC_F_EC_KEY_PRINT), "EC_KEY_print"}, 165{ERR_FUNC(EC_F_EC_KEY_PRINT), "EC_KEY_print"},
156{ERR_FUNC(EC_F_EC_KEY_PRINT_FP), "EC_KEY_print_fp"}, 166{ERR_FUNC(EC_F_EC_KEY_PRINT_FP), "EC_KEY_print_fp"},
167{ERR_FUNC(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES), "EC_KEY_set_public_key_affine_coordinates"},
157{ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"}, 168{ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"},
158{ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"}, 169{ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"},
159{ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"}, 170{ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"},
@@ -184,6 +195,9 @@ static ERR_STRING_DATA EC_str_functs[]=
184{ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"}, 195{ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"},
185{ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"}, 196{ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"},
186{ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"}, 197{ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"},
198{ERR_FUNC(EC_F_NISTP224_PRE_COMP_NEW), "NISTP224_PRE_COMP_NEW"},
199{ERR_FUNC(EC_F_NISTP256_PRE_COMP_NEW), "NISTP256_PRE_COMP_NEW"},
200{ERR_FUNC(EC_F_NISTP521_PRE_COMP_NEW), "NISTP521_PRE_COMP_NEW"},
187{ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"}, 201{ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"},
188{ERR_FUNC(EC_F_OLD_EC_PRIV_DECODE), "OLD_EC_PRIV_DECODE"}, 202{ERR_FUNC(EC_F_OLD_EC_PRIV_DECODE), "OLD_EC_PRIV_DECODE"},
189{ERR_FUNC(EC_F_PKEY_EC_CTRL), "PKEY_EC_CTRL"}, 203{ERR_FUNC(EC_F_PKEY_EC_CTRL), "PKEY_EC_CTRL"},
@@ -199,12 +213,15 @@ static ERR_STRING_DATA EC_str_reasons[]=
199 { 213 {
200{ERR_REASON(EC_R_ASN1_ERROR) ,"asn1 error"}, 214{ERR_REASON(EC_R_ASN1_ERROR) ,"asn1 error"},
201{ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD) ,"asn1 unknown field"}, 215{ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD) ,"asn1 unknown field"},
216{ERR_REASON(EC_R_BIGNUM_OUT_OF_RANGE) ,"bignum out of range"},
202{ERR_REASON(EC_R_BUFFER_TOO_SMALL) ,"buffer too small"}, 217{ERR_REASON(EC_R_BUFFER_TOO_SMALL) ,"buffer too small"},
218{ERR_REASON(EC_R_COORDINATES_OUT_OF_RANGE),"coordinates out of range"},
203{ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE),"d2i ecpkparameters failure"}, 219{ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE),"d2i ecpkparameters failure"},
204{ERR_REASON(EC_R_DECODE_ERROR) ,"decode error"}, 220{ERR_REASON(EC_R_DECODE_ERROR) ,"decode error"},
205{ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO) ,"discriminant is zero"}, 221{ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO) ,"discriminant is zero"},
206{ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),"ec group new by name failure"}, 222{ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),"ec group new by name failure"},
207{ERR_REASON(EC_R_FIELD_TOO_LARGE) ,"field too large"}, 223{ERR_REASON(EC_R_FIELD_TOO_LARGE) ,"field too large"},
224{ERR_REASON(EC_R_GF2M_NOT_SUPPORTED) ,"gf2m not supported"},
208{ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE),"group2pkparameters failure"}, 225{ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE),"group2pkparameters failure"},
209{ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE),"i2d ecpkparameters failure"}, 226{ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE),"i2d ecpkparameters failure"},
210{ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS) ,"incompatible objects"}, 227{ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS) ,"incompatible objects"},
@@ -239,6 +256,7 @@ static ERR_STRING_DATA EC_str_reasons[]=
239{ERR_REASON(EC_R_UNKNOWN_GROUP) ,"unknown group"}, 256{ERR_REASON(EC_R_UNKNOWN_GROUP) ,"unknown group"},
240{ERR_REASON(EC_R_UNKNOWN_ORDER) ,"unknown order"}, 257{ERR_REASON(EC_R_UNKNOWN_ORDER) ,"unknown order"},
241{ERR_REASON(EC_R_UNSUPPORTED_FIELD) ,"unsupported field"}, 258{ERR_REASON(EC_R_UNSUPPORTED_FIELD) ,"unsupported field"},
259{ERR_REASON(EC_R_WRONG_CURVE_PARAMETERS) ,"wrong curve parameters"},
242{ERR_REASON(EC_R_WRONG_ORDER) ,"wrong order"}, 260{ERR_REASON(EC_R_WRONG_ORDER) ,"wrong order"},
243{0,NULL} 261{0,NULL}
244 }; 262 };
diff --git a/src/lib/libcrypto/ec/ec_key.c b/src/lib/libcrypto/ec/ec_key.c
index 522802c07a..bf9fd2dc2c 100644
--- a/src/lib/libcrypto/ec/ec_key.c
+++ b/src/lib/libcrypto/ec/ec_key.c
@@ -64,7 +64,9 @@
64#include <string.h> 64#include <string.h>
65#include "ec_lcl.h" 65#include "ec_lcl.h"
66#include <openssl/err.h> 66#include <openssl/err.h>
67#include <string.h> 67#ifdef OPENSSL_FIPS
68#include <openssl/fips.h>
69#endif
68 70
69EC_KEY *EC_KEY_new(void) 71EC_KEY *EC_KEY_new(void)
70 { 72 {
@@ -78,6 +80,7 @@ EC_KEY *EC_KEY_new(void)
78 } 80 }
79 81
80 ret->version = 1; 82 ret->version = 1;
83 ret->flags = 0;
81 ret->group = NULL; 84 ret->group = NULL;
82 ret->pub_key = NULL; 85 ret->pub_key = NULL;
83 ret->priv_key= NULL; 86 ret->priv_key= NULL;
@@ -197,6 +200,7 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
197 dest->enc_flag = src->enc_flag; 200 dest->enc_flag = src->enc_flag;
198 dest->conv_form = src->conv_form; 201 dest->conv_form = src->conv_form;
199 dest->version = src->version; 202 dest->version = src->version;
203 dest->flags = src->flags;
200 204
201 return dest; 205 return dest;
202 } 206 }
@@ -237,6 +241,11 @@ int EC_KEY_generate_key(EC_KEY *eckey)
237 BIGNUM *priv_key = NULL, *order = NULL; 241 BIGNUM *priv_key = NULL, *order = NULL;
238 EC_POINT *pub_key = NULL; 242 EC_POINT *pub_key = NULL;
239 243
244#ifdef OPENSSL_FIPS
245 if (FIPS_mode())
246 return FIPS_ec_key_generate_key(eckey);
247#endif
248
240 if (!eckey || !eckey->group) 249 if (!eckey || !eckey->group)
241 { 250 {
242 ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER); 251 ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
@@ -371,6 +380,82 @@ err:
371 return(ok); 380 return(ok);
372 } 381 }
373 382
383int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y)
384 {
385 BN_CTX *ctx = NULL;
386 BIGNUM *tx, *ty;
387 EC_POINT *point = NULL;
388 int ok = 0, tmp_nid, is_char_two = 0;
389
390 if (!key || !key->group || !x || !y)
391 {
392 ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
393 ERR_R_PASSED_NULL_PARAMETER);
394 return 0;
395 }
396 ctx = BN_CTX_new();
397 if (!ctx)
398 goto err;
399
400 point = EC_POINT_new(key->group);
401
402 if (!point)
403 goto err;
404
405 tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));
406
407 if (tmp_nid == NID_X9_62_characteristic_two_field)
408 is_char_two = 1;
409
410 tx = BN_CTX_get(ctx);
411 ty = BN_CTX_get(ctx);
412#ifndef OPENSSL_NO_EC2M
413 if (is_char_two)
414 {
415 if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point,
416 x, y, ctx))
417 goto err;
418 if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point,
419 tx, ty, ctx))
420 goto err;
421 }
422 else
423#endif
424 {
425 if (!EC_POINT_set_affine_coordinates_GFp(key->group, point,
426 x, y, ctx))
427 goto err;
428 if (!EC_POINT_get_affine_coordinates_GFp(key->group, point,
429 tx, ty, ctx))
430 goto err;
431 }
432 /* Check if retrieved coordinates match originals: if not values
433 * are out of range.
434 */
435 if (BN_cmp(x, tx) || BN_cmp(y, ty))
436 {
437 ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
438 EC_R_COORDINATES_OUT_OF_RANGE);
439 goto err;
440 }
441
442 if (!EC_KEY_set_public_key(key, point))
443 goto err;
444
445 if (EC_KEY_check_key(key) == 0)
446 goto err;
447
448 ok = 1;
449
450 err:
451 if (ctx)
452 BN_CTX_free(ctx);
453 if (point)
454 EC_POINT_free(point);
455 return ok;
456
457 }
458
374const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key) 459const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
375 { 460 {
376 return key->group; 461 return key->group;
@@ -461,3 +546,18 @@ int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
461 return 0; 546 return 0;
462 return EC_GROUP_precompute_mult(key->group, ctx); 547 return EC_GROUP_precompute_mult(key->group, ctx);
463 } 548 }
549
550int EC_KEY_get_flags(const EC_KEY *key)
551 {
552 return key->flags;
553 }
554
555void EC_KEY_set_flags(EC_KEY *key, int flags)
556 {
557 key->flags |= flags;
558 }
559
560void EC_KEY_clear_flags(EC_KEY *key, int flags)
561 {
562 key->flags &= ~flags;
563 }
diff --git a/src/lib/libcrypto/ec/ec_lcl.h b/src/lib/libcrypto/ec/ec_lcl.h
index 3e2c34b0bc..da7967df38 100644
--- a/src/lib/libcrypto/ec/ec_lcl.h
+++ b/src/lib/libcrypto/ec/ec_lcl.h
@@ -3,7 +3,7 @@
3 * Originally written by Bodo Moeller for the OpenSSL project. 3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */ 4 */
5/* ==================================================================== 5/* ====================================================================
6 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 6 * Copyright (c) 1998-2010 The OpenSSL Project. All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
@@ -82,10 +82,15 @@
82# endif 82# endif
83#endif 83#endif
84 84
85/* Use default functions for poin2oct, oct2point and compressed coordinates */
86#define EC_FLAGS_DEFAULT_OCT 0x1
87
85/* Structure details are not part of the exported interface, 88/* Structure details are not part of the exported interface,
86 * so all this may change in future versions. */ 89 * so all this may change in future versions. */
87 90
88struct ec_method_st { 91struct ec_method_st {
92 /* Various method flags */
93 int flags;
89 /* used by EC_METHOD_get_field_type: */ 94 /* used by EC_METHOD_get_field_type: */
90 int field_type; /* a NID */ 95 int field_type; /* a NID */
91 96
@@ -244,6 +249,7 @@ struct ec_key_st {
244 point_conversion_form_t conv_form; 249 point_conversion_form_t conv_form;
245 250
246 int references; 251 int references;
252 int flags;
247 253
248 EC_EXTRA_DATA *method_data; 254 EC_EXTRA_DATA *method_data;
249} /* EC_KEY */; 255} /* EC_KEY */;
@@ -391,3 +397,50 @@ int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
391 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *); 397 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
392int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx); 398int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
393int ec_GF2m_have_precompute_mult(const EC_GROUP *group); 399int ec_GF2m_have_precompute_mult(const EC_GROUP *group);
400
401/* method functions in ec2_mult.c */
402int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
403 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
404int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
405int ec_GF2m_have_precompute_mult(const EC_GROUP *group);
406
407#ifndef OPENSSL_EC_NISTP_64_GCC_128
408/* method functions in ecp_nistp224.c */
409int ec_GFp_nistp224_group_init(EC_GROUP *group);
410int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *);
411int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
412int ec_GFp_nistp224_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
413int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx);
414int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
415int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group);
416
417/* method functions in ecp_nistp256.c */
418int ec_GFp_nistp256_group_init(EC_GROUP *group);
419int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *);
420int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
421int ec_GFp_nistp256_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
422int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx);
423int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
424int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group);
425
426/* method functions in ecp_nistp521.c */
427int ec_GFp_nistp521_group_init(EC_GROUP *group);
428int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *n, BN_CTX *);
429int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx);
430int ec_GFp_nistp521_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *);
431int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx);
432int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
433int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group);
434
435/* utility functions in ecp_nistputil.c */
436void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
437 size_t felem_size, void *tmp_felems,
438 void (*felem_one)(void *out),
439 int (*felem_is_zero)(const void *in),
440 void (*felem_assign)(void *out, const void *in),
441 void (*felem_square)(void *out, const void *in),
442 void (*felem_mul)(void *out, const void *in1, const void *in2),
443 void (*felem_inv)(void *out, const void *in),
444 void (*felem_contract)(void *out, const void *in));
445void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in);
446#endif
diff --git a/src/lib/libcrypto/ec/ec_lib.c b/src/lib/libcrypto/ec/ec_lib.c
index dd7da0fcf9..25247b5803 100644
--- a/src/lib/libcrypto/ec/ec_lib.c
+++ b/src/lib/libcrypto/ec/ec_lib.c
@@ -425,7 +425,7 @@ int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *
425 return group->meth->group_get_curve(group, p, a, b, ctx); 425 return group->meth->group_get_curve(group, p, a, b, ctx);
426 } 426 }
427 427
428 428#ifndef OPENSSL_NO_EC2M
429int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) 429int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
430 { 430 {
431 if (group->meth->group_set_curve == 0) 431 if (group->meth->group_set_curve == 0)
@@ -446,7 +446,7 @@ int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM
446 } 446 }
447 return group->meth->group_get_curve(group, p, a, b, ctx); 447 return group->meth->group_get_curve(group, p, a, b, ctx);
448 } 448 }
449 449#endif
450 450
451int EC_GROUP_get_degree(const EC_GROUP *group) 451int EC_GROUP_get_degree(const EC_GROUP *group)
452 { 452 {
@@ -856,7 +856,7 @@ int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
856 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 856 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
857 } 857 }
858 858
859 859#ifndef OPENSSL_NO_EC2M
860int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point, 860int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
861 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) 861 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
862 { 862 {
@@ -872,7 +872,7 @@ int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
872 } 872 }
873 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx); 873 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
874 } 874 }
875 875#endif
876 876
877int 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,
878 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 878 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
@@ -890,7 +890,7 @@ int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *p
890 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 890 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
891 } 891 }
892 892
893 893#ifndef OPENSSL_NO_EC2M
894int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point, 894int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
895 BIGNUM *x, BIGNUM *y, BN_CTX *ctx) 895 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
896 { 896 {
@@ -906,75 +906,7 @@ int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *
906 } 906 }
907 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx); 907 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
908 } 908 }
909 909#endif
910
911int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
912 const BIGNUM *x, int y_bit, BN_CTX *ctx)
913 {
914 if (group->meth->point_set_compressed_coordinates == 0)
915 {
916 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
917 return 0;
918 }
919 if (group->meth != point->meth)
920 {
921 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
922 return 0;
923 }
924 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
925 }
926
927
928int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
929 const BIGNUM *x, int y_bit, BN_CTX *ctx)
930 {
931 if (group->meth->point_set_compressed_coordinates == 0)
932 {
933 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
934 return 0;
935 }
936 if (group->meth != point->meth)
937 {
938 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
939 return 0;
940 }
941 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
942 }
943
944
945size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
946 unsigned char *buf, size_t len, BN_CTX *ctx)
947 {
948 if (group->meth->point2oct == 0)
949 {
950 ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
951 return 0;
952 }
953 if (group->meth != point->meth)
954 {
955 ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
956 return 0;
957 }
958 return group->meth->point2oct(group, point, form, buf, len, ctx);
959 }
960
961
962int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
963 const unsigned char *buf, size_t len, BN_CTX *ctx)
964 {
965 if (group->meth->oct2point == 0)
966 {
967 ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
968 return 0;
969 }
970 if (group->meth != point->meth)
971 {
972 ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
973 return 0;
974 }
975 return group->meth->oct2point(group, point, buf, len, ctx);
976 }
977
978 910
979int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) 911int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
980 { 912 {
diff --git a/src/lib/libcrypto/ec/ec_oct.c b/src/lib/libcrypto/ec/ec_oct.c
new file mode 100644
index 0000000000..fd9db0798d
--- /dev/null
+++ b/src/lib/libcrypto/ec/ec_oct.c
@@ -0,0 +1,199 @@
1/* crypto/ec/ec_lib.c */
2/*
3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */
5/* ====================================================================
6 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58/* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Binary polynomial ECC support in OpenSSL originally developed by
61 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
62 */
63
64#include <string.h>
65
66#include <openssl/err.h>
67#include <openssl/opensslv.h>
68
69#include "ec_lcl.h"
70
71int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
72 const BIGNUM *x, int y_bit, BN_CTX *ctx)
73 {
74 if (group->meth->point_set_compressed_coordinates == 0
75 && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
76 {
77 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
78 return 0;
79 }
80 if (group->meth != point->meth)
81 {
82 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
83 return 0;
84 }
85 if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
86 {
87 if (group->meth->field_type == NID_X9_62_prime_field)
88 return ec_GFp_simple_set_compressed_coordinates(
89 group, point, x, y_bit, ctx);
90 else
91#ifdef OPENSSL_NO_EC2M
92 {
93 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_GF2M_NOT_SUPPORTED);
94 return 0;
95 }
96#else
97 return ec_GF2m_simple_set_compressed_coordinates(
98 group, point, x, y_bit, ctx);
99#endif
100 }
101 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
102 }
103
104#ifndef OPENSSL_NO_EC2M
105int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
106 const BIGNUM *x, int y_bit, BN_CTX *ctx)
107 {
108 if (group->meth->point_set_compressed_coordinates == 0
109 && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
110 {
111 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
112 return 0;
113 }
114 if (group->meth != point->meth)
115 {
116 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
117 return 0;
118 }
119 if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
120 {
121 if (group->meth->field_type == NID_X9_62_prime_field)
122 return ec_GFp_simple_set_compressed_coordinates(
123 group, point, x, y_bit, ctx);
124 else
125 return ec_GF2m_simple_set_compressed_coordinates(
126 group, point, x, y_bit, ctx);
127 }
128 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
129 }
130#endif
131
132size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
133 unsigned char *buf, size_t len, BN_CTX *ctx)
134 {
135 if (group->meth->point2oct == 0
136 && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
137 {
138 ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
139 return 0;
140 }
141 if (group->meth != point->meth)
142 {
143 ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
144 return 0;
145 }
146 if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
147 {
148 if (group->meth->field_type == NID_X9_62_prime_field)
149 return ec_GFp_simple_point2oct(group, point,
150 form, buf, len, ctx);
151 else
152#ifdef OPENSSL_NO_EC2M
153 {
154 ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_GF2M_NOT_SUPPORTED);
155 return 0;
156 }
157#else
158 return ec_GF2m_simple_point2oct(group, point,
159 form, buf, len, ctx);
160#endif
161 }
162
163 return group->meth->point2oct(group, point, form, buf, len, ctx);
164 }
165
166
167int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
168 const unsigned char *buf, size_t len, BN_CTX *ctx)
169 {
170 if (group->meth->oct2point == 0
171 && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT))
172 {
173 ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
174 return 0;
175 }
176 if (group->meth != point->meth)
177 {
178 ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
179 return 0;
180 }
181 if(group->meth->flags & EC_FLAGS_DEFAULT_OCT)
182 {
183 if (group->meth->field_type == NID_X9_62_prime_field)
184 return ec_GFp_simple_oct2point(group, point,
185 buf, len, ctx);
186 else
187#ifdef OPENSSL_NO_EC2M
188 {
189 ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_GF2M_NOT_SUPPORTED);
190 return 0;
191 }
192#else
193 return ec_GF2m_simple_oct2point(group, point,
194 buf, len, ctx);
195#endif
196 }
197 return group->meth->oct2point(group, point, buf, len, ctx);
198 }
199
diff --git a/src/lib/libcrypto/ec/ec_pmeth.c b/src/lib/libcrypto/ec/ec_pmeth.c
index f433076ca1..d1ed66c37e 100644
--- a/src/lib/libcrypto/ec/ec_pmeth.c
+++ b/src/lib/libcrypto/ec/ec_pmeth.c
@@ -221,6 +221,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
221 221
222 case EVP_PKEY_CTRL_MD: 222 case EVP_PKEY_CTRL_MD:
223 if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && 223 if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
224 EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
224 EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && 225 EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
225 EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && 226 EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
226 EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && 227 EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
diff --git a/src/lib/libcrypto/ec/eck_prn.c b/src/lib/libcrypto/ec/eck_prn.c
index 7d3e175ae7..06de8f3959 100644
--- a/src/lib/libcrypto/ec/eck_prn.c
+++ b/src/lib/libcrypto/ec/eck_prn.c
@@ -207,7 +207,7 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
207 reason = ERR_R_MALLOC_FAILURE; 207 reason = ERR_R_MALLOC_FAILURE;
208 goto err; 208 goto err;
209 } 209 }
210 210#ifndef OPENSSL_NO_EC2M
211 if (is_char_two) 211 if (is_char_two)
212 { 212 {
213 if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) 213 if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx))
@@ -217,6 +217,7 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
217 } 217 }
218 } 218 }
219 else /* prime field */ 219 else /* prime field */
220#endif
220 { 221 {
221 if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) 222 if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx))
222 { 223 {
diff --git a/src/lib/libcrypto/ec/ecp_mont.c b/src/lib/libcrypto/ec/ecp_mont.c
index 9fc4a466a5..079e47431b 100644
--- a/src/lib/libcrypto/ec/ecp_mont.c
+++ b/src/lib/libcrypto/ec/ecp_mont.c
@@ -63,12 +63,20 @@
63 63
64#include <openssl/err.h> 64#include <openssl/err.h>
65 65
66#ifdef OPENSSL_FIPS
67#include <openssl/fips.h>
68#endif
69
66#include "ec_lcl.h" 70#include "ec_lcl.h"
67 71
68 72
69const EC_METHOD *EC_GFp_mont_method(void) 73const EC_METHOD *EC_GFp_mont_method(void)
70 { 74 {
75#ifdef OPENSSL_FIPS
76 return fips_ec_gfp_mont_method();
77#else
71 static const EC_METHOD ret = { 78 static const EC_METHOD ret = {
79 EC_FLAGS_DEFAULT_OCT,
72 NID_X9_62_prime_field, 80 NID_X9_62_prime_field,
73 ec_GFp_mont_group_init, 81 ec_GFp_mont_group_init,
74 ec_GFp_mont_group_finish, 82 ec_GFp_mont_group_finish,
@@ -87,9 +95,7 @@ const EC_METHOD *EC_GFp_mont_method(void)
87 ec_GFp_simple_get_Jprojective_coordinates_GFp, 95 ec_GFp_simple_get_Jprojective_coordinates_GFp,
88 ec_GFp_simple_point_set_affine_coordinates, 96 ec_GFp_simple_point_set_affine_coordinates,
89 ec_GFp_simple_point_get_affine_coordinates, 97 ec_GFp_simple_point_get_affine_coordinates,
90 ec_GFp_simple_set_compressed_coordinates, 98 0,0,0,
91 ec_GFp_simple_point2oct,
92 ec_GFp_simple_oct2point,
93 ec_GFp_simple_add, 99 ec_GFp_simple_add,
94 ec_GFp_simple_dbl, 100 ec_GFp_simple_dbl,
95 ec_GFp_simple_invert, 101 ec_GFp_simple_invert,
@@ -108,7 +114,9 @@ const EC_METHOD *EC_GFp_mont_method(void)
108 ec_GFp_mont_field_decode, 114 ec_GFp_mont_field_decode,
109 ec_GFp_mont_field_set_to_one }; 115 ec_GFp_mont_field_set_to_one };
110 116
117
111 return &ret; 118 return &ret;
119#endif
112 } 120 }
113 121
114 122
diff --git a/src/lib/libcrypto/ec/ecp_nist.c b/src/lib/libcrypto/ec/ecp_nist.c
index 2a5682ea41..aad2d5f443 100644
--- a/src/lib/libcrypto/ec/ecp_nist.c
+++ b/src/lib/libcrypto/ec/ecp_nist.c
@@ -67,9 +67,17 @@
67#include <openssl/obj_mac.h> 67#include <openssl/obj_mac.h>
68#include "ec_lcl.h" 68#include "ec_lcl.h"
69 69
70#ifdef OPENSSL_FIPS
71#include <openssl/fips.h>
72#endif
73
70const EC_METHOD *EC_GFp_nist_method(void) 74const EC_METHOD *EC_GFp_nist_method(void)
71 { 75 {
76#ifdef OPENSSL_FIPS
77 return fips_ec_gfp_nist_method();
78#else
72 static const EC_METHOD ret = { 79 static const EC_METHOD ret = {
80 EC_FLAGS_DEFAULT_OCT,
73 NID_X9_62_prime_field, 81 NID_X9_62_prime_field,
74 ec_GFp_simple_group_init, 82 ec_GFp_simple_group_init,
75 ec_GFp_simple_group_finish, 83 ec_GFp_simple_group_finish,
@@ -88,9 +96,7 @@ const EC_METHOD *EC_GFp_nist_method(void)
88 ec_GFp_simple_get_Jprojective_coordinates_GFp, 96 ec_GFp_simple_get_Jprojective_coordinates_GFp,
89 ec_GFp_simple_point_set_affine_coordinates, 97 ec_GFp_simple_point_set_affine_coordinates,
90 ec_GFp_simple_point_get_affine_coordinates, 98 ec_GFp_simple_point_get_affine_coordinates,
91 ec_GFp_simple_set_compressed_coordinates, 99 0,0,0,
92 ec_GFp_simple_point2oct,
93 ec_GFp_simple_oct2point,
94 ec_GFp_simple_add, 100 ec_GFp_simple_add,
95 ec_GFp_simple_dbl, 101 ec_GFp_simple_dbl,
96 ec_GFp_simple_invert, 102 ec_GFp_simple_invert,
@@ -110,6 +116,7 @@ const EC_METHOD *EC_GFp_nist_method(void)
110 0 /* field_set_to_one */ }; 116 0 /* field_set_to_one */ };
111 117
112 return &ret; 118 return &ret;
119#endif
113 } 120 }
114 121
115int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src) 122int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src)
diff --git a/src/lib/libcrypto/ec/ecp_nistp224.c b/src/lib/libcrypto/ec/ecp_nistp224.c
new file mode 100644
index 0000000000..b5ff56c252
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_nistp224.c
@@ -0,0 +1,1658 @@
1/* crypto/ec/ecp_nistp224.c */
2/*
3 * Written by Emilia Kasper (Google) for the OpenSSL project.
4 */
5/* Copyright 2011 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 *
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21/*
22 * A 64-bit implementation of the NIST P-224 elliptic curve point multiplication
23 *
24 * Inspired by Daniel J. Bernstein's public domain nistp224 implementation
25 * and Adam Langley's public domain 64-bit C implementation of curve25519
26 */
27
28#include <openssl/opensslconf.h>
29#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
30
31#ifndef OPENSSL_SYS_VMS
32#include <stdint.h>
33#else
34#include <inttypes.h>
35#endif
36
37#include <string.h>
38#include <openssl/err.h>
39#include "ec_lcl.h"
40
41#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
42 /* even with gcc, the typedef won't work for 32-bit platforms */
43 typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit platforms */
44#else
45 #error "Need GCC 3.1 or later to define type uint128_t"
46#endif
47
48typedef uint8_t u8;
49typedef uint64_t u64;
50typedef int64_t s64;
51
52
53/******************************************************************************/
54/* INTERNAL REPRESENTATION OF FIELD ELEMENTS
55 *
56 * Field elements are represented as a_0 + 2^56*a_1 + 2^112*a_2 + 2^168*a_3
57 * using 64-bit coefficients called 'limbs',
58 * and sometimes (for multiplication results) as
59 * b_0 + 2^56*b_1 + 2^112*b_2 + 2^168*b_3 + 2^224*b_4 + 2^280*b_5 + 2^336*b_6
60 * using 128-bit coefficients called 'widelimbs'.
61 * A 4-limb representation is an 'felem';
62 * a 7-widelimb representation is a 'widefelem'.
63 * Even within felems, bits of adjacent limbs overlap, and we don't always
64 * reduce the representations: we ensure that inputs to each felem
65 * multiplication satisfy a_i < 2^60, so outputs satisfy b_i < 4*2^60*2^60,
66 * and fit into a 128-bit word without overflow. The coefficients are then
67 * again partially reduced to obtain an felem satisfying a_i < 2^57.
68 * We only reduce to the unique minimal representation at the end of the
69 * computation.
70 */
71
72typedef uint64_t limb;
73typedef uint128_t widelimb;
74
75typedef limb felem[4];
76typedef widelimb widefelem[7];
77
78/* Field element represented as a byte arrary.
79 * 28*8 = 224 bits is also the group order size for the elliptic curve,
80 * and we also use this type for scalars for point multiplication.
81 */
82typedef u8 felem_bytearray[28];
83
84static const felem_bytearray nistp224_curve_params[5] = {
85 {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* p */
86 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
87 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01},
88 {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
89 0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,
90 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE},
91 {0xB4,0x05,0x0A,0x85,0x0C,0x04,0xB3,0xAB,0xF5,0x41, /* b */
92 0x32,0x56,0x50,0x44,0xB0,0xB7,0xD7,0xBF,0xD8,0xBA,
93 0x27,0x0B,0x39,0x43,0x23,0x55,0xFF,0xB4},
94 {0xB7,0x0E,0x0C,0xBD,0x6B,0xB4,0xBF,0x7F,0x32,0x13, /* x */
95 0x90,0xB9,0x4A,0x03,0xC1,0xD3,0x56,0xC2,0x11,0x22,
96 0x34,0x32,0x80,0xD6,0x11,0x5C,0x1D,0x21},
97 {0xbd,0x37,0x63,0x88,0xb5,0xf7,0x23,0xfb,0x4c,0x22, /* y */
98 0xdf,0xe6,0xcd,0x43,0x75,0xa0,0x5a,0x07,0x47,0x64,
99 0x44,0xd5,0x81,0x99,0x85,0x00,0x7e,0x34}
100};
101
102/* Precomputed multiples of the standard generator
103 * Points are given in coordinates (X, Y, Z) where Z normally is 1
104 * (0 for the point at infinity).
105 * For each field element, slice a_0 is word 0, etc.
106 *
107 * The table has 2 * 16 elements, starting with the following:
108 * index | bits | point
109 * ------+---------+------------------------------
110 * 0 | 0 0 0 0 | 0G
111 * 1 | 0 0 0 1 | 1G
112 * 2 | 0 0 1 0 | 2^56G
113 * 3 | 0 0 1 1 | (2^56 + 1)G
114 * 4 | 0 1 0 0 | 2^112G
115 * 5 | 0 1 0 1 | (2^112 + 1)G
116 * 6 | 0 1 1 0 | (2^112 + 2^56)G
117 * 7 | 0 1 1 1 | (2^112 + 2^56 + 1)G
118 * 8 | 1 0 0 0 | 2^168G
119 * 9 | 1 0 0 1 | (2^168 + 1)G
120 * 10 | 1 0 1 0 | (2^168 + 2^56)G
121 * 11 | 1 0 1 1 | (2^168 + 2^56 + 1)G
122 * 12 | 1 1 0 0 | (2^168 + 2^112)G
123 * 13 | 1 1 0 1 | (2^168 + 2^112 + 1)G
124 * 14 | 1 1 1 0 | (2^168 + 2^112 + 2^56)G
125 * 15 | 1 1 1 1 | (2^168 + 2^112 + 2^56 + 1)G
126 * followed by a copy of this with each element multiplied by 2^28.
127 *
128 * The reason for this is so that we can clock bits into four different
129 * locations when doing simple scalar multiplies against the base point,
130 * and then another four locations using the second 16 elements.
131 */
132static const felem gmul[2][16][3] =
133{{{{0, 0, 0, 0},
134 {0, 0, 0, 0},
135 {0, 0, 0, 0}},
136 {{0x3280d6115c1d21, 0xc1d356c2112234, 0x7f321390b94a03, 0xb70e0cbd6bb4bf},
137 {0xd5819985007e34, 0x75a05a07476444, 0xfb4c22dfe6cd43, 0xbd376388b5f723},
138 {1, 0, 0, 0}},
139 {{0xfd9675666ebbe9, 0xbca7664d40ce5e, 0x2242df8d8a2a43, 0x1f49bbb0f99bc5},
140 {0x29e0b892dc9c43, 0xece8608436e662, 0xdc858f185310d0, 0x9812dd4eb8d321},
141 {1, 0, 0, 0}},
142 {{0x6d3e678d5d8eb8, 0x559eed1cb362f1, 0x16e9a3bbce8a3f, 0xeedcccd8c2a748},
143 {0xf19f90ed50266d, 0xabf2b4bf65f9df, 0x313865468fafec, 0x5cb379ba910a17},
144 {1, 0, 0, 0}},
145 {{0x0641966cab26e3, 0x91fb2991fab0a0, 0xefec27a4e13a0b, 0x0499aa8a5f8ebe},
146 {0x7510407766af5d, 0x84d929610d5450, 0x81d77aae82f706, 0x6916f6d4338c5b},
147 {1, 0, 0, 0}},
148 {{0xea95ac3b1f15c6, 0x086000905e82d4, 0xdd323ae4d1c8b1, 0x932b56be7685a3},
149 {0x9ef93dea25dbbf, 0x41665960f390f0, 0xfdec76dbe2a8a7, 0x523e80f019062a},
150 {1, 0, 0, 0}},
151 {{0x822fdd26732c73, 0xa01c83531b5d0f, 0x363f37347c1ba4, 0xc391b45c84725c},
152 {0xbbd5e1b2d6ad24, 0xddfbcde19dfaec, 0xc393da7e222a7f, 0x1efb7890ede244},
153 {1, 0, 0, 0}},
154 {{0x4c9e90ca217da1, 0xd11beca79159bb, 0xff8d33c2c98b7c, 0x2610b39409f849},
155 {0x44d1352ac64da0, 0xcdbb7b2c46b4fb, 0x966c079b753c89, 0xfe67e4e820b112},
156 {1, 0, 0, 0}},
157 {{0xe28cae2df5312d, 0xc71b61d16f5c6e, 0x79b7619a3e7c4c, 0x05c73240899b47},
158 {0x9f7f6382c73e3a, 0x18615165c56bda, 0x641fab2116fd56, 0x72855882b08394},
159 {1, 0, 0, 0}},
160 {{0x0469182f161c09, 0x74a98ca8d00fb5, 0xb89da93489a3e0, 0x41c98768fb0c1d},
161 {0xe5ea05fb32da81, 0x3dce9ffbca6855, 0x1cfe2d3fbf59e6, 0x0e5e03408738a7},
162 {1, 0, 0, 0}},
163 {{0xdab22b2333e87f, 0x4430137a5dd2f6, 0xe03ab9f738beb8, 0xcb0c5d0dc34f24},
164 {0x764a7df0c8fda5, 0x185ba5c3fa2044, 0x9281d688bcbe50, 0xc40331df893881},
165 {1, 0, 0, 0}},
166 {{0xb89530796f0f60, 0xade92bd26909a3, 0x1a0c83fb4884da, 0x1765bf22a5a984},
167 {0x772a9ee75db09e, 0x23bc6c67cec16f, 0x4c1edba8b14e2f, 0xe2a215d9611369},
168 {1, 0, 0, 0}},
169 {{0x571e509fb5efb3, 0xade88696410552, 0xc8ae85fada74fe, 0x6c7e4be83bbde3},
170 {0xff9f51160f4652, 0xb47ce2495a6539, 0xa2946c53b582f4, 0x286d2db3ee9a60},
171 {1, 0, 0, 0}},
172 {{0x40bbd5081a44af, 0x0995183b13926c, 0xbcefba6f47f6d0, 0x215619e9cc0057},
173 {0x8bc94d3b0df45e, 0xf11c54a3694f6f, 0x8631b93cdfe8b5, 0xe7e3f4b0982db9},
174 {1, 0, 0, 0}},
175 {{0xb17048ab3e1c7b, 0xac38f36ff8a1d8, 0x1c29819435d2c6, 0xc813132f4c07e9},
176 {0x2891425503b11f, 0x08781030579fea, 0xf5426ba5cc9674, 0x1e28ebf18562bc},
177 {1, 0, 0, 0}},
178 {{0x9f31997cc864eb, 0x06cd91d28b5e4c, 0xff17036691a973, 0xf1aef351497c58},
179 {0xdd1f2d600564ff, 0xdead073b1402db, 0x74a684435bd693, 0xeea7471f962558},
180 {1, 0, 0, 0}}},
181 {{{0, 0, 0, 0},
182 {0, 0, 0, 0},
183 {0, 0, 0, 0}},
184 {{0x9665266dddf554, 0x9613d78b60ef2d, 0xce27a34cdba417, 0xd35ab74d6afc31},
185 {0x85ccdd22deb15e, 0x2137e5783a6aab, 0xa141cffd8c93c6, 0x355a1830e90f2d},
186 {1, 0, 0, 0}},
187 {{0x1a494eadaade65, 0xd6da4da77fe53c, 0xe7992996abec86, 0x65c3553c6090e3},
188 {0xfa610b1fb09346, 0xf1c6540b8a4aaf, 0xc51a13ccd3cbab, 0x02995b1b18c28a},
189 {1, 0, 0, 0}},
190 {{0x7874568e7295ef, 0x86b419fbe38d04, 0xdc0690a7550d9a, 0xd3966a44beac33},
191 {0x2b7280ec29132f, 0xbeaa3b6a032df3, 0xdc7dd88ae41200, 0xd25e2513e3a100},
192 {1, 0, 0, 0}},
193 {{0x924857eb2efafd, 0xac2bce41223190, 0x8edaa1445553fc, 0x825800fd3562d5},
194 {0x8d79148ea96621, 0x23a01c3dd9ed8d, 0xaf8b219f9416b5, 0xd8db0cc277daea},
195 {1, 0, 0, 0}},
196 {{0x76a9c3b1a700f0, 0xe9acd29bc7e691, 0x69212d1a6b0327, 0x6322e97fe154be},
197 {0x469fc5465d62aa, 0x8d41ed18883b05, 0x1f8eae66c52b88, 0xe4fcbe9325be51},
198 {1, 0, 0, 0}},
199 {{0x825fdf583cac16, 0x020b857c7b023a, 0x683c17744b0165, 0x14ffd0a2daf2f1},
200 {0x323b36184218f9, 0x4944ec4e3b47d4, 0xc15b3080841acf, 0x0bced4b01a28bb},
201 {1, 0, 0, 0}},
202 {{0x92ac22230df5c4, 0x52f33b4063eda8, 0xcb3f19870c0c93, 0x40064f2ba65233},
203 {0xfe16f0924f8992, 0x012da25af5b517, 0x1a57bb24f723a6, 0x06f8bc76760def},
204 {1, 0, 0, 0}},
205 {{0x4a7084f7817cb9, 0xbcab0738ee9a78, 0x3ec11e11d9c326, 0xdc0fe90e0f1aae},
206 {0xcf639ea5f98390, 0x5c350aa22ffb74, 0x9afae98a4047b7, 0x956ec2d617fc45},
207 {1, 0, 0, 0}},
208 {{0x4306d648c1be6a, 0x9247cd8bc9a462, 0xf5595e377d2f2e, 0xbd1c3caff1a52e},
209 {0x045e14472409d0, 0x29f3e17078f773, 0x745a602b2d4f7d, 0x191837685cdfbb},
210 {1, 0, 0, 0}},
211 {{0x5b6ee254a8cb79, 0x4953433f5e7026, 0xe21faeb1d1def4, 0xc4c225785c09de},
212 {0x307ce7bba1e518, 0x31b125b1036db8, 0x47e91868839e8f, 0xc765866e33b9f3},
213 {1, 0, 0, 0}},
214 {{0x3bfece24f96906, 0x4794da641e5093, 0xde5df64f95db26, 0x297ecd89714b05},
215 {0x701bd3ebb2c3aa, 0x7073b4f53cb1d5, 0x13c5665658af16, 0x9895089d66fe58},
216 {1, 0, 0, 0}},
217 {{0x0fef05f78c4790, 0x2d773633b05d2e, 0x94229c3a951c94, 0xbbbd70df4911bb},
218 {0xb2c6963d2c1168, 0x105f47a72b0d73, 0x9fdf6111614080, 0x7b7e94b39e67b0},
219 {1, 0, 0, 0}},
220 {{0xad1a7d6efbe2b3, 0xf012482c0da69d, 0x6b3bdf12438345, 0x40d7558d7aa4d9},
221 {0x8a09fffb5c6d3d, 0x9a356e5d9ffd38, 0x5973f15f4f9b1c, 0xdcd5f59f63c3ea},
222 {1, 0, 0, 0}},
223 {{0xacf39f4c5ca7ab, 0x4c8071cc5fd737, 0xc64e3602cd1184, 0x0acd4644c9abba},
224 {0x6c011a36d8bf6e, 0xfecd87ba24e32a, 0x19f6f56574fad8, 0x050b204ced9405},
225 {1, 0, 0, 0}},
226 {{0xed4f1cae7d9a96, 0x5ceef7ad94c40a, 0x778e4a3bf3ef9b, 0x7405783dc3b55e},
227 {0x32477c61b6e8c6, 0xb46a97570f018b, 0x91176d0a7e95d1, 0x3df90fbc4c7d0e},
228 {1, 0, 0, 0}}}};
229
230/* Precomputation for the group generator. */
231typedef struct {
232 felem g_pre_comp[2][16][3];
233 int references;
234} NISTP224_PRE_COMP;
235
236const EC_METHOD *EC_GFp_nistp224_method(void)
237 {
238 static const EC_METHOD ret = {
239 EC_FLAGS_DEFAULT_OCT,
240 NID_X9_62_prime_field,
241 ec_GFp_nistp224_group_init,
242 ec_GFp_simple_group_finish,
243 ec_GFp_simple_group_clear_finish,
244 ec_GFp_nist_group_copy,
245 ec_GFp_nistp224_group_set_curve,
246 ec_GFp_simple_group_get_curve,
247 ec_GFp_simple_group_get_degree,
248 ec_GFp_simple_group_check_discriminant,
249 ec_GFp_simple_point_init,
250 ec_GFp_simple_point_finish,
251 ec_GFp_simple_point_clear_finish,
252 ec_GFp_simple_point_copy,
253 ec_GFp_simple_point_set_to_infinity,
254 ec_GFp_simple_set_Jprojective_coordinates_GFp,
255 ec_GFp_simple_get_Jprojective_coordinates_GFp,
256 ec_GFp_simple_point_set_affine_coordinates,
257 ec_GFp_nistp224_point_get_affine_coordinates,
258 0 /* point_set_compressed_coordinates */,
259 0 /* point2oct */,
260 0 /* oct2point */,
261 ec_GFp_simple_add,
262 ec_GFp_simple_dbl,
263 ec_GFp_simple_invert,
264 ec_GFp_simple_is_at_infinity,
265 ec_GFp_simple_is_on_curve,
266 ec_GFp_simple_cmp,
267 ec_GFp_simple_make_affine,
268 ec_GFp_simple_points_make_affine,
269 ec_GFp_nistp224_points_mul,
270 ec_GFp_nistp224_precompute_mult,
271 ec_GFp_nistp224_have_precompute_mult,
272 ec_GFp_nist_field_mul,
273 ec_GFp_nist_field_sqr,
274 0 /* field_div */,
275 0 /* field_encode */,
276 0 /* field_decode */,
277 0 /* field_set_to_one */ };
278
279 return &ret;
280 }
281
282/* Helper functions to convert field elements to/from internal representation */
283static void bin28_to_felem(felem out, const u8 in[28])
284 {
285 out[0] = *((const uint64_t *)(in)) & 0x00ffffffffffffff;
286 out[1] = (*((const uint64_t *)(in+7))) & 0x00ffffffffffffff;
287 out[2] = (*((const uint64_t *)(in+14))) & 0x00ffffffffffffff;
288 out[3] = (*((const uint64_t *)(in+21))) & 0x00ffffffffffffff;
289 }
290
291static void felem_to_bin28(u8 out[28], const felem in)
292 {
293 unsigned i;
294 for (i = 0; i < 7; ++i)
295 {
296 out[i] = in[0]>>(8*i);
297 out[i+7] = in[1]>>(8*i);
298 out[i+14] = in[2]>>(8*i);
299 out[i+21] = in[3]>>(8*i);
300 }
301 }
302
303/* To preserve endianness when using BN_bn2bin and BN_bin2bn */
304static void flip_endian(u8 *out, const u8 *in, unsigned len)
305 {
306 unsigned i;
307 for (i = 0; i < len; ++i)
308 out[i] = in[len-1-i];
309 }
310
311/* From OpenSSL BIGNUM to internal representation */
312static int BN_to_felem(felem out, const BIGNUM *bn)
313 {
314 felem_bytearray b_in;
315 felem_bytearray b_out;
316 unsigned num_bytes;
317
318 /* BN_bn2bin eats leading zeroes */
319 memset(b_out, 0, sizeof b_out);
320 num_bytes = BN_num_bytes(bn);
321 if (num_bytes > sizeof b_out)
322 {
323 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
324 return 0;
325 }
326 if (BN_is_negative(bn))
327 {
328 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
329 return 0;
330 }
331 num_bytes = BN_bn2bin(bn, b_in);
332 flip_endian(b_out, b_in, num_bytes);
333 bin28_to_felem(out, b_out);
334 return 1;
335 }
336
337/* From internal representation to OpenSSL BIGNUM */
338static BIGNUM *felem_to_BN(BIGNUM *out, const felem in)
339 {
340 felem_bytearray b_in, b_out;
341 felem_to_bin28(b_in, in);
342 flip_endian(b_out, b_in, sizeof b_out);
343 return BN_bin2bn(b_out, sizeof b_out, out);
344 }
345
346/******************************************************************************/
347/* FIELD OPERATIONS
348 *
349 * Field operations, using the internal representation of field elements.
350 * NB! These operations are specific to our point multiplication and cannot be
351 * expected to be correct in general - e.g., multiplication with a large scalar
352 * will cause an overflow.
353 *
354 */
355
356static void felem_one(felem out)
357 {
358 out[0] = 1;
359 out[1] = 0;
360 out[2] = 0;
361 out[3] = 0;
362 }
363
364static void felem_assign(felem out, const felem in)
365 {
366 out[0] = in[0];
367 out[1] = in[1];
368 out[2] = in[2];
369 out[3] = in[3];
370 }
371
372/* Sum two field elements: out += in */
373static void felem_sum(felem out, const felem in)
374 {
375 out[0] += in[0];
376 out[1] += in[1];
377 out[2] += in[2];
378 out[3] += in[3];
379 }
380
381/* Get negative value: out = -in */
382/* Assumes in[i] < 2^57 */
383static void felem_neg(felem out, const felem in)
384 {
385 static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2);
386 static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2);
387 static const limb two58m42m2 = (((limb) 1) << 58) -
388 (((limb) 1) << 42) - (((limb) 1) << 2);
389
390 /* Set to 0 mod 2^224-2^96+1 to ensure out > in */
391 out[0] = two58p2 - in[0];
392 out[1] = two58m42m2 - in[1];
393 out[2] = two58m2 - in[2];
394 out[3] = two58m2 - in[3];
395 }
396
397/* Subtract field elements: out -= in */
398/* Assumes in[i] < 2^57 */
399static void felem_diff(felem out, const felem in)
400 {
401 static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2);
402 static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2);
403 static const limb two58m42m2 = (((limb) 1) << 58) -
404 (((limb) 1) << 42) - (((limb) 1) << 2);
405
406 /* Add 0 mod 2^224-2^96+1 to ensure out > in */
407 out[0] += two58p2;
408 out[1] += two58m42m2;
409 out[2] += two58m2;
410 out[3] += two58m2;
411
412 out[0] -= in[0];
413 out[1] -= in[1];
414 out[2] -= in[2];
415 out[3] -= in[3];
416 }
417
418/* Subtract in unreduced 128-bit mode: out -= in */
419/* Assumes in[i] < 2^119 */
420static void widefelem_diff(widefelem out, const widefelem in)
421 {
422 static const widelimb two120 = ((widelimb) 1) << 120;
423 static const widelimb two120m64 = (((widelimb) 1) << 120) -
424 (((widelimb) 1) << 64);
425 static const widelimb two120m104m64 = (((widelimb) 1) << 120) -
426 (((widelimb) 1) << 104) - (((widelimb) 1) << 64);
427
428 /* Add 0 mod 2^224-2^96+1 to ensure out > in */
429 out[0] += two120;
430 out[1] += two120m64;
431 out[2] += two120m64;
432 out[3] += two120;
433 out[4] += two120m104m64;
434 out[5] += two120m64;
435 out[6] += two120m64;
436
437 out[0] -= in[0];
438 out[1] -= in[1];
439 out[2] -= in[2];
440 out[3] -= in[3];
441 out[4] -= in[4];
442 out[5] -= in[5];
443 out[6] -= in[6];
444 }
445
446/* Subtract in mixed mode: out128 -= in64 */
447/* in[i] < 2^63 */
448static void felem_diff_128_64(widefelem out, const felem in)
449 {
450 static const widelimb two64p8 = (((widelimb) 1) << 64) +
451 (((widelimb) 1) << 8);
452 static const widelimb two64m8 = (((widelimb) 1) << 64) -
453 (((widelimb) 1) << 8);
454 static const widelimb two64m48m8 = (((widelimb) 1) << 64) -
455 (((widelimb) 1) << 48) - (((widelimb) 1) << 8);
456
457 /* Add 0 mod 2^224-2^96+1 to ensure out > in */
458 out[0] += two64p8;
459 out[1] += two64m48m8;
460 out[2] += two64m8;
461 out[3] += two64m8;
462
463 out[0] -= in[0];
464 out[1] -= in[1];
465 out[2] -= in[2];
466 out[3] -= in[3];
467 }
468
469/* Multiply a field element by a scalar: out = out * scalar
470 * The scalars we actually use are small, so results fit without overflow */
471static void felem_scalar(felem out, const limb scalar)
472 {
473 out[0] *= scalar;
474 out[1] *= scalar;
475 out[2] *= scalar;
476 out[3] *= scalar;
477 }
478
479/* Multiply an unreduced field element by a scalar: out = out * scalar
480 * The scalars we actually use are small, so results fit without overflow */
481static void widefelem_scalar(widefelem out, const widelimb scalar)
482 {
483 out[0] *= scalar;
484 out[1] *= scalar;
485 out[2] *= scalar;
486 out[3] *= scalar;
487 out[4] *= scalar;
488 out[5] *= scalar;
489 out[6] *= scalar;
490 }
491
492/* Square a field element: out = in^2 */
493static void felem_square(widefelem out, const felem in)
494 {
495 limb tmp0, tmp1, tmp2;
496 tmp0 = 2 * in[0]; tmp1 = 2 * in[1]; tmp2 = 2 * in[2];
497 out[0] = ((widelimb) in[0]) * in[0];
498 out[1] = ((widelimb) in[0]) * tmp1;
499 out[2] = ((widelimb) in[0]) * tmp2 + ((widelimb) in[1]) * in[1];
500 out[3] = ((widelimb) in[3]) * tmp0 +
501 ((widelimb) in[1]) * tmp2;
502 out[4] = ((widelimb) in[3]) * tmp1 + ((widelimb) in[2]) * in[2];
503 out[5] = ((widelimb) in[3]) * tmp2;
504 out[6] = ((widelimb) in[3]) * in[3];
505 }
506
507/* Multiply two field elements: out = in1 * in2 */
508static void felem_mul(widefelem out, const felem in1, const felem in2)
509 {
510 out[0] = ((widelimb) in1[0]) * in2[0];
511 out[1] = ((widelimb) in1[0]) * in2[1] + ((widelimb) in1[1]) * in2[0];
512 out[2] = ((widelimb) in1[0]) * in2[2] + ((widelimb) in1[1]) * in2[1] +
513 ((widelimb) in1[2]) * in2[0];
514 out[3] = ((widelimb) in1[0]) * in2[3] + ((widelimb) in1[1]) * in2[2] +
515 ((widelimb) in1[2]) * in2[1] + ((widelimb) in1[3]) * in2[0];
516 out[4] = ((widelimb) in1[1]) * in2[3] + ((widelimb) in1[2]) * in2[2] +
517 ((widelimb) in1[3]) * in2[1];
518 out[5] = ((widelimb) in1[2]) * in2[3] + ((widelimb) in1[3]) * in2[2];
519 out[6] = ((widelimb) in1[3]) * in2[3];
520 }
521
522/* Reduce seven 128-bit coefficients to four 64-bit coefficients.
523 * Requires in[i] < 2^126,
524 * ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16 */
525static void felem_reduce(felem out, const widefelem in)
526 {
527 static const widelimb two127p15 = (((widelimb) 1) << 127) +
528 (((widelimb) 1) << 15);
529 static const widelimb two127m71 = (((widelimb) 1) << 127) -
530 (((widelimb) 1) << 71);
531 static const widelimb two127m71m55 = (((widelimb) 1) << 127) -
532 (((widelimb) 1) << 71) - (((widelimb) 1) << 55);
533 widelimb output[5];
534
535 /* Add 0 mod 2^224-2^96+1 to ensure all differences are positive */
536 output[0] = in[0] + two127p15;
537 output[1] = in[1] + two127m71m55;
538 output[2] = in[2] + two127m71;
539 output[3] = in[3];
540 output[4] = in[4];
541
542 /* Eliminate in[4], in[5], in[6] */
543 output[4] += in[6] >> 16;
544 output[3] += (in[6] & 0xffff) << 40;
545 output[2] -= in[6];
546
547 output[3] += in[5] >> 16;
548 output[2] += (in[5] & 0xffff) << 40;
549 output[1] -= in[5];
550
551 output[2] += output[4] >> 16;
552 output[1] += (output[4] & 0xffff) << 40;
553 output[0] -= output[4];
554
555 /* Carry 2 -> 3 -> 4 */
556 output[3] += output[2] >> 56;
557 output[2] &= 0x00ffffffffffffff;
558
559 output[4] = output[3] >> 56;
560 output[3] &= 0x00ffffffffffffff;
561
562 /* Now output[2] < 2^56, output[3] < 2^56, output[4] < 2^72 */
563
564 /* Eliminate output[4] */
565 output[2] += output[4] >> 16;
566 /* output[2] < 2^56 + 2^56 = 2^57 */
567 output[1] += (output[4] & 0xffff) << 40;
568 output[0] -= output[4];
569
570 /* Carry 0 -> 1 -> 2 -> 3 */
571 output[1] += output[0] >> 56;
572 out[0] = output[0] & 0x00ffffffffffffff;
573
574 output[2] += output[1] >> 56;
575 /* output[2] < 2^57 + 2^72 */
576 out[1] = output[1] & 0x00ffffffffffffff;
577 output[3] += output[2] >> 56;
578 /* output[3] <= 2^56 + 2^16 */
579 out[2] = output[2] & 0x00ffffffffffffff;
580
581 /* out[0] < 2^56, out[1] < 2^56, out[2] < 2^56,
582 * out[3] <= 2^56 + 2^16 (due to final carry),
583 * so out < 2*p */
584 out[3] = output[3];
585 }
586
587static void felem_square_reduce(felem out, const felem in)
588 {
589 widefelem tmp;
590 felem_square(tmp, in);
591 felem_reduce(out, tmp);
592 }
593
594static void felem_mul_reduce(felem out, const felem in1, const felem in2)
595 {
596 widefelem tmp;
597 felem_mul(tmp, in1, in2);
598 felem_reduce(out, tmp);
599 }
600
601/* Reduce to unique minimal representation.
602 * Requires 0 <= in < 2*p (always call felem_reduce first) */
603static void felem_contract(felem out, const felem in)
604 {
605 static const int64_t two56 = ((limb) 1) << 56;
606 /* 0 <= in < 2*p, p = 2^224 - 2^96 + 1 */
607 /* if in > p , reduce in = in - 2^224 + 2^96 - 1 */
608 int64_t tmp[4], a;
609 tmp[0] = in[0];
610 tmp[1] = in[1];
611 tmp[2] = in[2];
612 tmp[3] = in[3];
613 /* Case 1: a = 1 iff in >= 2^224 */
614 a = (in[3] >> 56);
615 tmp[0] -= a;
616 tmp[1] += a << 40;
617 tmp[3] &= 0x00ffffffffffffff;
618 /* Case 2: a = 0 iff p <= in < 2^224, i.e.,
619 * the high 128 bits are all 1 and the lower part is non-zero */
620 a = ((in[3] & in[2] & (in[1] | 0x000000ffffffffff)) + 1) |
621 (((int64_t)(in[0] + (in[1] & 0x000000ffffffffff)) - 1) >> 63);
622 a &= 0x00ffffffffffffff;
623 /* turn a into an all-one mask (if a = 0) or an all-zero mask */
624 a = (a - 1) >> 63;
625 /* subtract 2^224 - 2^96 + 1 if a is all-one*/
626 tmp[3] &= a ^ 0xffffffffffffffff;
627 tmp[2] &= a ^ 0xffffffffffffffff;
628 tmp[1] &= (a ^ 0xffffffffffffffff) | 0x000000ffffffffff;
629 tmp[0] -= 1 & a;
630
631 /* eliminate negative coefficients: if tmp[0] is negative, tmp[1] must
632 * be non-zero, so we only need one step */
633 a = tmp[0] >> 63;
634 tmp[0] += two56 & a;
635 tmp[1] -= 1 & a;
636
637 /* carry 1 -> 2 -> 3 */
638 tmp[2] += tmp[1] >> 56;
639 tmp[1] &= 0x00ffffffffffffff;
640
641 tmp[3] += tmp[2] >> 56;
642 tmp[2] &= 0x00ffffffffffffff;
643
644 /* Now 0 <= out < p */
645 out[0] = tmp[0];
646 out[1] = tmp[1];
647 out[2] = tmp[2];
648 out[3] = tmp[3];
649 }
650
651/* Zero-check: returns 1 if input is 0, and 0 otherwise.
652 * We know that field elements are reduced to in < 2^225,
653 * so we only need to check three cases: 0, 2^224 - 2^96 + 1,
654 * and 2^225 - 2^97 + 2 */
655static limb felem_is_zero(const felem in)
656 {
657 limb zero, two224m96p1, two225m97p2;
658
659 zero = in[0] | in[1] | in[2] | in[3];
660 zero = (((int64_t)(zero) - 1) >> 63) & 1;
661 two224m96p1 = (in[0] ^ 1) | (in[1] ^ 0x00ffff0000000000)
662 | (in[2] ^ 0x00ffffffffffffff) | (in[3] ^ 0x00ffffffffffffff);
663 two224m96p1 = (((int64_t)(two224m96p1) - 1) >> 63) & 1;
664 two225m97p2 = (in[0] ^ 2) | (in[1] ^ 0x00fffe0000000000)
665 | (in[2] ^ 0x00ffffffffffffff) | (in[3] ^ 0x01ffffffffffffff);
666 two225m97p2 = (((int64_t)(two225m97p2) - 1) >> 63) & 1;
667 return (zero | two224m96p1 | two225m97p2);
668 }
669
670static limb felem_is_zero_int(const felem in)
671 {
672 return (int) (felem_is_zero(in) & ((limb)1));
673 }
674
675/* Invert a field element */
676/* Computation chain copied from djb's code */
677static void felem_inv(felem out, const felem in)
678 {
679 felem ftmp, ftmp2, ftmp3, ftmp4;
680 widefelem tmp;
681 unsigned i;
682
683 felem_square(tmp, in); felem_reduce(ftmp, tmp); /* 2 */
684 felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^2 - 1 */
685 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2 */
686 felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 1 */
687 felem_square(tmp, ftmp); felem_reduce(ftmp2, tmp); /* 2^4 - 2 */
688 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^5 - 4 */
689 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^6 - 8 */
690 felem_mul(tmp, ftmp2, ftmp); felem_reduce(ftmp, tmp); /* 2^6 - 1 */
691 felem_square(tmp, ftmp); felem_reduce(ftmp2, tmp); /* 2^7 - 2 */
692 for (i = 0; i < 5; ++i) /* 2^12 - 2^6 */
693 {
694 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp);
695 }
696 felem_mul(tmp, ftmp2, ftmp); felem_reduce(ftmp2, tmp); /* 2^12 - 1 */
697 felem_square(tmp, ftmp2); felem_reduce(ftmp3, tmp); /* 2^13 - 2 */
698 for (i = 0; i < 11; ++i) /* 2^24 - 2^12 */
699 {
700 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp);
701 }
702 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp2, tmp); /* 2^24 - 1 */
703 felem_square(tmp, ftmp2); felem_reduce(ftmp3, tmp); /* 2^25 - 2 */
704 for (i = 0; i < 23; ++i) /* 2^48 - 2^24 */
705 {
706 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp);
707 }
708 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^48 - 1 */
709 felem_square(tmp, ftmp3); felem_reduce(ftmp4, tmp); /* 2^49 - 2 */
710 for (i = 0; i < 47; ++i) /* 2^96 - 2^48 */
711 {
712 felem_square(tmp, ftmp4); felem_reduce(ftmp4, tmp);
713 }
714 felem_mul(tmp, ftmp3, ftmp4); felem_reduce(ftmp3, tmp); /* 2^96 - 1 */
715 felem_square(tmp, ftmp3); felem_reduce(ftmp4, tmp); /* 2^97 - 2 */
716 for (i = 0; i < 23; ++i) /* 2^120 - 2^24 */
717 {
718 felem_square(tmp, ftmp4); felem_reduce(ftmp4, tmp);
719 }
720 felem_mul(tmp, ftmp2, ftmp4); felem_reduce(ftmp2, tmp); /* 2^120 - 1 */
721 for (i = 0; i < 6; ++i) /* 2^126 - 2^6 */
722 {
723 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp);
724 }
725 felem_mul(tmp, ftmp2, ftmp); felem_reduce(ftmp, tmp); /* 2^126 - 1 */
726 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^127 - 2 */
727 felem_mul(tmp, ftmp, in); felem_reduce(ftmp, tmp); /* 2^127 - 1 */
728 for (i = 0; i < 97; ++i) /* 2^224 - 2^97 */
729 {
730 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp);
731 }
732 felem_mul(tmp, ftmp, ftmp3); felem_reduce(out, tmp); /* 2^224 - 2^96 - 1 */
733 }
734
735/* Copy in constant time:
736 * if icopy == 1, copy in to out,
737 * if icopy == 0, copy out to itself. */
738static void
739copy_conditional(felem out, const felem in, limb icopy)
740 {
741 unsigned i;
742 /* icopy is a (64-bit) 0 or 1, so copy is either all-zero or all-one */
743 const limb copy = -icopy;
744 for (i = 0; i < 4; ++i)
745 {
746 const limb tmp = copy & (in[i] ^ out[i]);
747 out[i] ^= tmp;
748 }
749 }
750
751/******************************************************************************/
752/* ELLIPTIC CURVE POINT OPERATIONS
753 *
754 * Points are represented in Jacobian projective coordinates:
755 * (X, Y, Z) corresponds to the affine point (X/Z^2, Y/Z^3),
756 * or to the point at infinity if Z == 0.
757 *
758 */
759
760/* Double an elliptic curve point:
761 * (X', Y', Z') = 2 * (X, Y, Z), where
762 * X' = (3 * (X - Z^2) * (X + Z^2))^2 - 8 * X * Y^2
763 * Y' = 3 * (X - Z^2) * (X + Z^2) * (4 * X * Y^2 - X') - 8 * Y^2
764 * Z' = (Y + Z)^2 - Y^2 - Z^2 = 2 * Y * Z
765 * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed,
766 * while x_out == y_in is not (maybe this works, but it's not tested). */
767static void
768point_double(felem x_out, felem y_out, felem z_out,
769 const felem x_in, const felem y_in, const felem z_in)
770 {
771 widefelem tmp, tmp2;
772 felem delta, gamma, beta, alpha, ftmp, ftmp2;
773
774 felem_assign(ftmp, x_in);
775 felem_assign(ftmp2, x_in);
776
777 /* delta = z^2 */
778 felem_square(tmp, z_in);
779 felem_reduce(delta, tmp);
780
781 /* gamma = y^2 */
782 felem_square(tmp, y_in);
783 felem_reduce(gamma, tmp);
784
785 /* beta = x*gamma */
786 felem_mul(tmp, x_in, gamma);
787 felem_reduce(beta, tmp);
788
789 /* alpha = 3*(x-delta)*(x+delta) */
790 felem_diff(ftmp, delta);
791 /* ftmp[i] < 2^57 + 2^58 + 2 < 2^59 */
792 felem_sum(ftmp2, delta);
793 /* ftmp2[i] < 2^57 + 2^57 = 2^58 */
794 felem_scalar(ftmp2, 3);
795 /* ftmp2[i] < 3 * 2^58 < 2^60 */
796 felem_mul(tmp, ftmp, ftmp2);
797 /* tmp[i] < 2^60 * 2^59 * 4 = 2^121 */
798 felem_reduce(alpha, tmp);
799
800 /* x' = alpha^2 - 8*beta */
801 felem_square(tmp, alpha);
802 /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */
803 felem_assign(ftmp, beta);
804 felem_scalar(ftmp, 8);
805 /* ftmp[i] < 8 * 2^57 = 2^60 */
806 felem_diff_128_64(tmp, ftmp);
807 /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */
808 felem_reduce(x_out, tmp);
809
810 /* z' = (y + z)^2 - gamma - delta */
811 felem_sum(delta, gamma);
812 /* delta[i] < 2^57 + 2^57 = 2^58 */
813 felem_assign(ftmp, y_in);
814 felem_sum(ftmp, z_in);
815 /* ftmp[i] < 2^57 + 2^57 = 2^58 */
816 felem_square(tmp, ftmp);
817 /* tmp[i] < 4 * 2^58 * 2^58 = 2^118 */
818 felem_diff_128_64(tmp, delta);
819 /* tmp[i] < 2^118 + 2^64 + 8 < 2^119 */
820 felem_reduce(z_out, tmp);
821
822 /* y' = alpha*(4*beta - x') - 8*gamma^2 */
823 felem_scalar(beta, 4);
824 /* beta[i] < 4 * 2^57 = 2^59 */
825 felem_diff(beta, x_out);
826 /* beta[i] < 2^59 + 2^58 + 2 < 2^60 */
827 felem_mul(tmp, alpha, beta);
828 /* tmp[i] < 4 * 2^57 * 2^60 = 2^119 */
829 felem_square(tmp2, gamma);
830 /* tmp2[i] < 4 * 2^57 * 2^57 = 2^116 */
831 widefelem_scalar(tmp2, 8);
832 /* tmp2[i] < 8 * 2^116 = 2^119 */
833 widefelem_diff(tmp, tmp2);
834 /* tmp[i] < 2^119 + 2^120 < 2^121 */
835 felem_reduce(y_out, tmp);
836 }
837
838/* Add two elliptic curve points:
839 * (X_1, Y_1, Z_1) + (X_2, Y_2, Z_2) = (X_3, Y_3, Z_3), where
840 * X_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1)^2 - (Z_1^2 * X_2 - Z_2^2 * X_1)^3 -
841 * 2 * Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^2
842 * Y_3 = (Z_1^3 * Y_2 - Z_2^3 * Y_1) * (Z_2^2 * X_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^2 - X_3) -
843 * Z_2^3 * Y_1 * (Z_1^2 * X_2 - Z_2^2 * X_1)^3
844 * Z_3 = (Z_1^2 * X_2 - Z_2^2 * X_1) * (Z_1 * Z_2)
845 *
846 * This runs faster if 'mixed' is set, which requires Z_2 = 1 or Z_2 = 0.
847 */
848
849/* This function is not entirely constant-time:
850 * it includes a branch for checking whether the two input points are equal,
851 * (while not equal to the point at infinity).
852 * This case never happens during single point multiplication,
853 * so there is no timing leak for ECDH or ECDSA signing. */
854static void point_add(felem x3, felem y3, felem z3,
855 const felem x1, const felem y1, const felem z1,
856 const int mixed, const felem x2, const felem y2, const felem z2)
857 {
858 felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, x_out, y_out, z_out;
859 widefelem tmp, tmp2;
860 limb z1_is_zero, z2_is_zero, x_equal, y_equal;
861
862 if (!mixed)
863 {
864 /* ftmp2 = z2^2 */
865 felem_square(tmp, z2);
866 felem_reduce(ftmp2, tmp);
867
868 /* ftmp4 = z2^3 */
869 felem_mul(tmp, ftmp2, z2);
870 felem_reduce(ftmp4, tmp);
871
872 /* ftmp4 = z2^3*y1 */
873 felem_mul(tmp2, ftmp4, y1);
874 felem_reduce(ftmp4, tmp2);
875
876 /* ftmp2 = z2^2*x1 */
877 felem_mul(tmp2, ftmp2, x1);
878 felem_reduce(ftmp2, tmp2);
879 }
880 else
881 {
882 /* We'll assume z2 = 1 (special case z2 = 0 is handled later) */
883
884 /* ftmp4 = z2^3*y1 */
885 felem_assign(ftmp4, y1);
886
887 /* ftmp2 = z2^2*x1 */
888 felem_assign(ftmp2, x1);
889 }
890
891 /* ftmp = z1^2 */
892 felem_square(tmp, z1);
893 felem_reduce(ftmp, tmp);
894
895 /* ftmp3 = z1^3 */
896 felem_mul(tmp, ftmp, z1);
897 felem_reduce(ftmp3, tmp);
898
899 /* tmp = z1^3*y2 */
900 felem_mul(tmp, ftmp3, y2);
901 /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */
902
903 /* ftmp3 = z1^3*y2 - z2^3*y1 */
904 felem_diff_128_64(tmp, ftmp4);
905 /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */
906 felem_reduce(ftmp3, tmp);
907
908 /* tmp = z1^2*x2 */
909 felem_mul(tmp, ftmp, x2);
910 /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */
911
912 /* ftmp = z1^2*x2 - z2^2*x1 */
913 felem_diff_128_64(tmp, ftmp2);
914 /* tmp[i] < 2^116 + 2^64 + 8 < 2^117 */
915 felem_reduce(ftmp, tmp);
916
917 /* the formulae are incorrect if the points are equal
918 * so we check for this and do doubling if this happens */
919 x_equal = felem_is_zero(ftmp);
920 y_equal = felem_is_zero(ftmp3);
921 z1_is_zero = felem_is_zero(z1);
922 z2_is_zero = felem_is_zero(z2);
923 /* In affine coordinates, (X_1, Y_1) == (X_2, Y_2) */
924 if (x_equal && y_equal && !z1_is_zero && !z2_is_zero)
925 {
926 point_double(x3, y3, z3, x1, y1, z1);
927 return;
928 }
929
930 /* ftmp5 = z1*z2 */
931 if (!mixed)
932 {
933 felem_mul(tmp, z1, z2);
934 felem_reduce(ftmp5, tmp);
935 }
936 else
937 {
938 /* special case z2 = 0 is handled later */
939 felem_assign(ftmp5, z1);
940 }
941
942 /* z_out = (z1^2*x2 - z2^2*x1)*(z1*z2) */
943 felem_mul(tmp, ftmp, ftmp5);
944 felem_reduce(z_out, tmp);
945
946 /* ftmp = (z1^2*x2 - z2^2*x1)^2 */
947 felem_assign(ftmp5, ftmp);
948 felem_square(tmp, ftmp);
949 felem_reduce(ftmp, tmp);
950
951 /* ftmp5 = (z1^2*x2 - z2^2*x1)^3 */
952 felem_mul(tmp, ftmp, ftmp5);
953 felem_reduce(ftmp5, tmp);
954
955 /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */
956 felem_mul(tmp, ftmp2, ftmp);
957 felem_reduce(ftmp2, tmp);
958
959 /* tmp = z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */
960 felem_mul(tmp, ftmp4, ftmp5);
961 /* tmp[i] < 4 * 2^57 * 2^57 = 2^116 */
962
963 /* tmp2 = (z1^3*y2 - z2^3*y1)^2 */
964 felem_square(tmp2, ftmp3);
965 /* tmp2[i] < 4 * 2^57 * 2^57 < 2^116 */
966
967 /* tmp2 = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 */
968 felem_diff_128_64(tmp2, ftmp5);
969 /* tmp2[i] < 2^116 + 2^64 + 8 < 2^117 */
970
971 /* ftmp5 = 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */
972 felem_assign(ftmp5, ftmp2);
973 felem_scalar(ftmp5, 2);
974 /* ftmp5[i] < 2 * 2^57 = 2^58 */
975
976 /* x_out = (z1^3*y2 - z2^3*y1)^2 - (z1^2*x2 - z2^2*x1)^3 -
977 2*z2^2*x1*(z1^2*x2 - z2^2*x1)^2 */
978 felem_diff_128_64(tmp2, ftmp5);
979 /* tmp2[i] < 2^117 + 2^64 + 8 < 2^118 */
980 felem_reduce(x_out, tmp2);
981
982 /* ftmp2 = z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out */
983 felem_diff(ftmp2, x_out);
984 /* ftmp2[i] < 2^57 + 2^58 + 2 < 2^59 */
985
986 /* tmp2 = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) */
987 felem_mul(tmp2, ftmp3, ftmp2);
988 /* tmp2[i] < 4 * 2^57 * 2^59 = 2^118 */
989
990 /* y_out = (z1^3*y2 - z2^3*y1)*(z2^2*x1*(z1^2*x2 - z2^2*x1)^2 - x_out) -
991 z2^3*y1*(z1^2*x2 - z2^2*x1)^3 */
992 widefelem_diff(tmp2, tmp);
993 /* tmp2[i] < 2^118 + 2^120 < 2^121 */
994 felem_reduce(y_out, tmp2);
995
996 /* the result (x_out, y_out, z_out) is incorrect if one of the inputs is
997 * the point at infinity, so we need to check for this separately */
998
999 /* if point 1 is at infinity, copy point 2 to output, and vice versa */
1000 copy_conditional(x_out, x2, z1_is_zero);
1001 copy_conditional(x_out, x1, z2_is_zero);
1002 copy_conditional(y_out, y2, z1_is_zero);
1003 copy_conditional(y_out, y1, z2_is_zero);
1004 copy_conditional(z_out, z2, z1_is_zero);
1005 copy_conditional(z_out, z1, z2_is_zero);
1006 felem_assign(x3, x_out);
1007 felem_assign(y3, y_out);
1008 felem_assign(z3, z_out);
1009 }
1010
1011/* select_point selects the |idx|th point from a precomputation table and
1012 * copies it to out. */
1013static void select_point(const u64 idx, unsigned int size, const felem pre_comp[/*size*/][3], felem out[3])
1014 {
1015 unsigned i, j;
1016 limb *outlimbs = &out[0][0];
1017 memset(outlimbs, 0, 3 * sizeof(felem));
1018
1019 for (i = 0; i < size; i++)
1020 {
1021 const limb *inlimbs = &pre_comp[i][0][0];
1022 u64 mask = i ^ idx;
1023 mask |= mask >> 4;
1024 mask |= mask >> 2;
1025 mask |= mask >> 1;
1026 mask &= 1;
1027 mask--;
1028 for (j = 0; j < 4 * 3; j++)
1029 outlimbs[j] |= inlimbs[j] & mask;
1030 }
1031 }
1032
1033/* get_bit returns the |i|th bit in |in| */
1034static char get_bit(const felem_bytearray in, unsigned i)
1035 {
1036 if (i >= 224)
1037 return 0;
1038 return (in[i >> 3] >> (i & 7)) & 1;
1039 }
1040
1041/* Interleaved point multiplication using precomputed point multiples:
1042 * The small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[],
1043 * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple
1044 * of the generator, using certain (large) precomputed multiples in g_pre_comp.
1045 * Output point (X, Y, Z) is stored in x_out, y_out, z_out */
1046static void batch_mul(felem x_out, felem y_out, felem z_out,
1047 const felem_bytearray scalars[], const unsigned num_points, const u8 *g_scalar,
1048 const int mixed, const felem pre_comp[][17][3], const felem g_pre_comp[2][16][3])
1049 {
1050 int i, skip;
1051 unsigned num;
1052 unsigned gen_mul = (g_scalar != NULL);
1053 felem nq[3], tmp[4];
1054 u64 bits;
1055 u8 sign, digit;
1056
1057 /* set nq to the point at infinity */
1058 memset(nq, 0, 3 * sizeof(felem));
1059
1060 /* Loop over all scalars msb-to-lsb, interleaving additions
1061 * of multiples of the generator (two in each of the last 28 rounds)
1062 * and additions of other points multiples (every 5th round).
1063 */
1064 skip = 1; /* save two point operations in the first round */
1065 for (i = (num_points ? 220 : 27); i >= 0; --i)
1066 {
1067 /* double */
1068 if (!skip)
1069 point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
1070
1071 /* add multiples of the generator */
1072 if (gen_mul && (i <= 27))
1073 {
1074 /* first, look 28 bits upwards */
1075 bits = get_bit(g_scalar, i + 196) << 3;
1076 bits |= get_bit(g_scalar, i + 140) << 2;
1077 bits |= get_bit(g_scalar, i + 84) << 1;
1078 bits |= get_bit(g_scalar, i + 28);
1079 /* select the point to add, in constant time */
1080 select_point(bits, 16, g_pre_comp[1], tmp);
1081
1082 if (!skip)
1083 {
1084 point_add(nq[0], nq[1], nq[2],
1085 nq[0], nq[1], nq[2],
1086 1 /* mixed */, tmp[0], tmp[1], tmp[2]);
1087 }
1088 else
1089 {
1090 memcpy(nq, tmp, 3 * sizeof(felem));
1091 skip = 0;
1092 }
1093
1094 /* second, look at the current position */
1095 bits = get_bit(g_scalar, i + 168) << 3;
1096 bits |= get_bit(g_scalar, i + 112) << 2;
1097 bits |= get_bit(g_scalar, i + 56) << 1;
1098 bits |= get_bit(g_scalar, i);
1099 /* select the point to add, in constant time */
1100 select_point(bits, 16, g_pre_comp[0], tmp);
1101 point_add(nq[0], nq[1], nq[2],
1102 nq[0], nq[1], nq[2],
1103 1 /* mixed */, tmp[0], tmp[1], tmp[2]);
1104 }
1105
1106 /* do other additions every 5 doublings */
1107 if (num_points && (i % 5 == 0))
1108 {
1109 /* loop over all scalars */
1110 for (num = 0; num < num_points; ++num)
1111 {
1112 bits = get_bit(scalars[num], i + 4) << 5;
1113 bits |= get_bit(scalars[num], i + 3) << 4;
1114 bits |= get_bit(scalars[num], i + 2) << 3;
1115 bits |= get_bit(scalars[num], i + 1) << 2;
1116 bits |= get_bit(scalars[num], i) << 1;
1117 bits |= get_bit(scalars[num], i - 1);
1118 ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
1119
1120 /* select the point to add or subtract */
1121 select_point(digit, 17, pre_comp[num], tmp);
1122 felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative point */
1123 copy_conditional(tmp[1], tmp[3], sign);
1124
1125 if (!skip)
1126 {
1127 point_add(nq[0], nq[1], nq[2],
1128 nq[0], nq[1], nq[2],
1129 mixed, tmp[0], tmp[1], tmp[2]);
1130 }
1131 else
1132 {
1133 memcpy(nq, tmp, 3 * sizeof(felem));
1134 skip = 0;
1135 }
1136 }
1137 }
1138 }
1139 felem_assign(x_out, nq[0]);
1140 felem_assign(y_out, nq[1]);
1141 felem_assign(z_out, nq[2]);
1142 }
1143
1144/******************************************************************************/
1145/* FUNCTIONS TO MANAGE PRECOMPUTATION
1146 */
1147
1148static NISTP224_PRE_COMP *nistp224_pre_comp_new()
1149 {
1150 NISTP224_PRE_COMP *ret = NULL;
1151 ret = (NISTP224_PRE_COMP *) OPENSSL_malloc(sizeof *ret);
1152 if (!ret)
1153 {
1154 ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
1155 return ret;
1156 }
1157 memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp));
1158 ret->references = 1;
1159 return ret;
1160 }
1161
1162static void *nistp224_pre_comp_dup(void *src_)
1163 {
1164 NISTP224_PRE_COMP *src = src_;
1165
1166 /* no need to actually copy, these objects never change! */
1167 CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
1168
1169 return src_;
1170 }
1171
1172static void nistp224_pre_comp_free(void *pre_)
1173 {
1174 int i;
1175 NISTP224_PRE_COMP *pre = pre_;
1176
1177 if (!pre)
1178 return;
1179
1180 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1181 if (i > 0)
1182 return;
1183
1184 OPENSSL_free(pre);
1185 }
1186
1187static void nistp224_pre_comp_clear_free(void *pre_)
1188 {
1189 int i;
1190 NISTP224_PRE_COMP *pre = pre_;
1191
1192 if (!pre)
1193 return;
1194
1195 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1196 if (i > 0)
1197 return;
1198
1199 OPENSSL_cleanse(pre, sizeof *pre);
1200 OPENSSL_free(pre);
1201 }
1202
1203/******************************************************************************/
1204/* OPENSSL EC_METHOD FUNCTIONS
1205 */
1206
1207int ec_GFp_nistp224_group_init(EC_GROUP *group)
1208 {
1209 int ret;
1210 ret = ec_GFp_simple_group_init(group);
1211 group->a_is_minus3 = 1;
1212 return ret;
1213 }
1214
1215int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
1216 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1217 {
1218 int ret = 0;
1219 BN_CTX *new_ctx = NULL;
1220 BIGNUM *curve_p, *curve_a, *curve_b;
1221
1222 if (ctx == NULL)
1223 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1224 BN_CTX_start(ctx);
1225 if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
1226 ((curve_a = BN_CTX_get(ctx)) == NULL) ||
1227 ((curve_b = BN_CTX_get(ctx)) == NULL)) goto err;
1228 BN_bin2bn(nistp224_curve_params[0], sizeof(felem_bytearray), curve_p);
1229 BN_bin2bn(nistp224_curve_params[1], sizeof(felem_bytearray), curve_a);
1230 BN_bin2bn(nistp224_curve_params[2], sizeof(felem_bytearray), curve_b);
1231 if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) ||
1232 (BN_cmp(curve_b, b)))
1233 {
1234 ECerr(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE,
1235 EC_R_WRONG_CURVE_PARAMETERS);
1236 goto err;
1237 }
1238 group->field_mod_func = BN_nist_mod_224;
1239 ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
1240err:
1241 BN_CTX_end(ctx);
1242 if (new_ctx != NULL)
1243 BN_CTX_free(new_ctx);
1244 return ret;
1245 }
1246
1247/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns
1248 * (X', Y') = (X/Z^2, Y/Z^3) */
1249int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
1250 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
1251 {
1252 felem z1, z2, x_in, y_in, x_out, y_out;
1253 widefelem tmp;
1254
1255 if (EC_POINT_is_at_infinity(group, point))
1256 {
1257 ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES,
1258 EC_R_POINT_AT_INFINITY);
1259 return 0;
1260 }
1261 if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) ||
1262 (!BN_to_felem(z1, &point->Z))) return 0;
1263 felem_inv(z2, z1);
1264 felem_square(tmp, z2); felem_reduce(z1, tmp);
1265 felem_mul(tmp, x_in, z1); felem_reduce(x_in, tmp);
1266 felem_contract(x_out, x_in);
1267 if (x != NULL)
1268 {
1269 if (!felem_to_BN(x, x_out)) {
1270 ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES,
1271 ERR_R_BN_LIB);
1272 return 0;
1273 }
1274 }
1275 felem_mul(tmp, z1, z2); felem_reduce(z1, tmp);
1276 felem_mul(tmp, y_in, z1); felem_reduce(y_in, tmp);
1277 felem_contract(y_out, y_in);
1278 if (y != NULL)
1279 {
1280 if (!felem_to_BN(y, y_out)) {
1281 ECerr(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES,
1282 ERR_R_BN_LIB);
1283 return 0;
1284 }
1285 }
1286 return 1;
1287 }
1288
1289static void make_points_affine(size_t num, felem points[/*num*/][3], felem tmp_felems[/*num+1*/])
1290 {
1291 /* Runs in constant time, unless an input is the point at infinity
1292 * (which normally shouldn't happen). */
1293 ec_GFp_nistp_points_make_affine_internal(
1294 num,
1295 points,
1296 sizeof(felem),
1297 tmp_felems,
1298 (void (*)(void *)) felem_one,
1299 (int (*)(const void *)) felem_is_zero_int,
1300 (void (*)(void *, const void *)) felem_assign,
1301 (void (*)(void *, const void *)) felem_square_reduce,
1302 (void (*)(void *, const void *, const void *)) felem_mul_reduce,
1303 (void (*)(void *, const void *)) felem_inv,
1304 (void (*)(void *, const void *)) felem_contract);
1305 }
1306
1307/* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL values
1308 * Result is stored in r (r can equal one of the inputs). */
1309int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
1310 const BIGNUM *scalar, size_t num, const EC_POINT *points[],
1311 const BIGNUM *scalars[], BN_CTX *ctx)
1312 {
1313 int ret = 0;
1314 int j;
1315 unsigned i;
1316 int mixed = 0;
1317 BN_CTX *new_ctx = NULL;
1318 BIGNUM *x, *y, *z, *tmp_scalar;
1319 felem_bytearray g_secret;
1320 felem_bytearray *secrets = NULL;
1321 felem (*pre_comp)[17][3] = NULL;
1322 felem *tmp_felems = NULL;
1323 felem_bytearray tmp;
1324 unsigned num_bytes;
1325 int have_pre_comp = 0;
1326 size_t num_points = num;
1327 felem x_in, y_in, z_in, x_out, y_out, z_out;
1328 NISTP224_PRE_COMP *pre = NULL;
1329 const felem (*g_pre_comp)[16][3] = NULL;
1330 EC_POINT *generator = NULL;
1331 const EC_POINT *p = NULL;
1332 const BIGNUM *p_scalar = NULL;
1333
1334 if (ctx == NULL)
1335 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1336 BN_CTX_start(ctx);
1337 if (((x = BN_CTX_get(ctx)) == NULL) ||
1338 ((y = BN_CTX_get(ctx)) == NULL) ||
1339 ((z = BN_CTX_get(ctx)) == NULL) ||
1340 ((tmp_scalar = BN_CTX_get(ctx)) == NULL))
1341 goto err;
1342
1343 if (scalar != NULL)
1344 {
1345 pre = EC_EX_DATA_get_data(group->extra_data,
1346 nistp224_pre_comp_dup, nistp224_pre_comp_free,
1347 nistp224_pre_comp_clear_free);
1348 if (pre)
1349 /* we have precomputation, try to use it */
1350 g_pre_comp = (const felem (*)[16][3]) pre->g_pre_comp;
1351 else
1352 /* try to use the standard precomputation */
1353 g_pre_comp = &gmul[0];
1354 generator = EC_POINT_new(group);
1355 if (generator == NULL)
1356 goto err;
1357 /* get the generator from precomputation */
1358 if (!felem_to_BN(x, g_pre_comp[0][1][0]) ||
1359 !felem_to_BN(y, g_pre_comp[0][1][1]) ||
1360 !felem_to_BN(z, g_pre_comp[0][1][2]))
1361 {
1362 ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
1363 goto err;
1364 }
1365 if (!EC_POINT_set_Jprojective_coordinates_GFp(group,
1366 generator, x, y, z, ctx))
1367 goto err;
1368 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
1369 /* precomputation matches generator */
1370 have_pre_comp = 1;
1371 else
1372 /* we don't have valid precomputation:
1373 * treat the generator as a random point */
1374 num_points = num_points + 1;
1375 }
1376
1377 if (num_points > 0)
1378 {
1379 if (num_points >= 3)
1380 {
1381 /* unless we precompute multiples for just one or two points,
1382 * converting those into affine form is time well spent */
1383 mixed = 1;
1384 }
1385 secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
1386 pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(felem));
1387 if (mixed)
1388 tmp_felems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem));
1389 if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_felems == NULL)))
1390 {
1391 ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_MALLOC_FAILURE);
1392 goto err;
1393 }
1394
1395 /* we treat NULL scalars as 0, and NULL points as points at infinity,
1396 * i.e., they contribute nothing to the linear combination */
1397 memset(secrets, 0, num_points * sizeof(felem_bytearray));
1398 memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem));
1399 for (i = 0; i < num_points; ++i)
1400 {
1401 if (i == num)
1402 /* the generator */
1403 {
1404 p = EC_GROUP_get0_generator(group);
1405 p_scalar = scalar;
1406 }
1407 else
1408 /* the i^th point */
1409 {
1410 p = points[i];
1411 p_scalar = scalars[i];
1412 }
1413 if ((p_scalar != NULL) && (p != NULL))
1414 {
1415 /* reduce scalar to 0 <= scalar < 2^224 */
1416 if ((BN_num_bits(p_scalar) > 224) || (BN_is_negative(p_scalar)))
1417 {
1418 /* this is an unusual input, and we don't guarantee
1419 * constant-timeness */
1420 if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx))
1421 {
1422 ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
1423 goto err;
1424 }
1425 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1426 }
1427 else
1428 num_bytes = BN_bn2bin(p_scalar, tmp);
1429 flip_endian(secrets[i], tmp, num_bytes);
1430 /* precompute multiples */
1431 if ((!BN_to_felem(x_out, &p->X)) ||
1432 (!BN_to_felem(y_out, &p->Y)) ||
1433 (!BN_to_felem(z_out, &p->Z))) goto err;
1434 felem_assign(pre_comp[i][1][0], x_out);
1435 felem_assign(pre_comp[i][1][1], y_out);
1436 felem_assign(pre_comp[i][1][2], z_out);
1437 for (j = 2; j <= 16; ++j)
1438 {
1439 if (j & 1)
1440 {
1441 point_add(
1442 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1443 pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2],
1444 0, pre_comp[i][j-1][0], pre_comp[i][j-1][1], pre_comp[i][j-1][2]);
1445 }
1446 else
1447 {
1448 point_double(
1449 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1450 pre_comp[i][j/2][0], pre_comp[i][j/2][1], pre_comp[i][j/2][2]);
1451 }
1452 }
1453 }
1454 }
1455 if (mixed)
1456 make_points_affine(num_points * 17, pre_comp[0], tmp_felems);
1457 }
1458
1459 /* the scalar for the generator */
1460 if ((scalar != NULL) && (have_pre_comp))
1461 {
1462 memset(g_secret, 0, sizeof g_secret);
1463 /* reduce scalar to 0 <= scalar < 2^224 */
1464 if ((BN_num_bits(scalar) > 224) || (BN_is_negative(scalar)))
1465 {
1466 /* this is an unusual input, and we don't guarantee
1467 * constant-timeness */
1468 if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx))
1469 {
1470 ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
1471 goto err;
1472 }
1473 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1474 }
1475 else
1476 num_bytes = BN_bn2bin(scalar, tmp);
1477 flip_endian(g_secret, tmp, num_bytes);
1478 /* do the multiplication with generator precomputation*/
1479 batch_mul(x_out, y_out, z_out,
1480 (const felem_bytearray (*)) secrets, num_points,
1481 g_secret,
1482 mixed, (const felem (*)[17][3]) pre_comp,
1483 g_pre_comp);
1484 }
1485 else
1486 /* do the multiplication without generator precomputation */
1487 batch_mul(x_out, y_out, z_out,
1488 (const felem_bytearray (*)) secrets, num_points,
1489 NULL, mixed, (const felem (*)[17][3]) pre_comp, NULL);
1490 /* reduce the output to its unique minimal representation */
1491 felem_contract(x_in, x_out);
1492 felem_contract(y_in, y_out);
1493 felem_contract(z_in, z_out);
1494 if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) ||
1495 (!felem_to_BN(z, z_in)))
1496 {
1497 ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_BN_LIB);
1498 goto err;
1499 }
1500 ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
1501
1502err:
1503 BN_CTX_end(ctx);
1504 if (generator != NULL)
1505 EC_POINT_free(generator);
1506 if (new_ctx != NULL)
1507 BN_CTX_free(new_ctx);
1508 if (secrets != NULL)
1509 OPENSSL_free(secrets);
1510 if (pre_comp != NULL)
1511 OPENSSL_free(pre_comp);
1512 if (tmp_felems != NULL)
1513 OPENSSL_free(tmp_felems);
1514 return ret;
1515 }
1516
1517int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1518 {
1519 int ret = 0;
1520 NISTP224_PRE_COMP *pre = NULL;
1521 int i, j;
1522 BN_CTX *new_ctx = NULL;
1523 BIGNUM *x, *y;
1524 EC_POINT *generator = NULL;
1525 felem tmp_felems[32];
1526
1527 /* throw away old precomputation */
1528 EC_EX_DATA_free_data(&group->extra_data, nistp224_pre_comp_dup,
1529 nistp224_pre_comp_free, nistp224_pre_comp_clear_free);
1530 if (ctx == NULL)
1531 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1532 BN_CTX_start(ctx);
1533 if (((x = BN_CTX_get(ctx)) == NULL) ||
1534 ((y = BN_CTX_get(ctx)) == NULL))
1535 goto err;
1536 /* get the generator */
1537 if (group->generator == NULL) goto err;
1538 generator = EC_POINT_new(group);
1539 if (generator == NULL)
1540 goto err;
1541 BN_bin2bn(nistp224_curve_params[3], sizeof (felem_bytearray), x);
1542 BN_bin2bn(nistp224_curve_params[4], sizeof (felem_bytearray), y);
1543 if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx))
1544 goto err;
1545 if ((pre = nistp224_pre_comp_new()) == NULL)
1546 goto err;
1547 /* if the generator is the standard one, use built-in precomputation */
1548 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
1549 {
1550 memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp));
1551 ret = 1;
1552 goto err;
1553 }
1554 if ((!BN_to_felem(pre->g_pre_comp[0][1][0], &group->generator->X)) ||
1555 (!BN_to_felem(pre->g_pre_comp[0][1][1], &group->generator->Y)) ||
1556 (!BN_to_felem(pre->g_pre_comp[0][1][2], &group->generator->Z)))
1557 goto err;
1558 /* compute 2^56*G, 2^112*G, 2^168*G for the first table,
1559 * 2^28*G, 2^84*G, 2^140*G, 2^196*G for the second one
1560 */
1561 for (i = 1; i <= 8; i <<= 1)
1562 {
1563 point_double(
1564 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2],
1565 pre->g_pre_comp[0][i][0], pre->g_pre_comp[0][i][1], pre->g_pre_comp[0][i][2]);
1566 for (j = 0; j < 27; ++j)
1567 {
1568 point_double(
1569 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2],
1570 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]);
1571 }
1572 if (i == 8)
1573 break;
1574 point_double(
1575 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2],
1576 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]);
1577 for (j = 0; j < 27; ++j)
1578 {
1579 point_double(
1580 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2],
1581 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2]);
1582 }
1583 }
1584 for (i = 0; i < 2; i++)
1585 {
1586 /* g_pre_comp[i][0] is the point at infinity */
1587 memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0]));
1588 /* the remaining multiples */
1589 /* 2^56*G + 2^112*G resp. 2^84*G + 2^140*G */
1590 point_add(
1591 pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1],
1592 pre->g_pre_comp[i][6][2], pre->g_pre_comp[i][4][0],
1593 pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2],
1594 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1],
1595 pre->g_pre_comp[i][2][2]);
1596 /* 2^56*G + 2^168*G resp. 2^84*G + 2^196*G */
1597 point_add(
1598 pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1],
1599 pre->g_pre_comp[i][10][2], pre->g_pre_comp[i][8][0],
1600 pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
1601 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1],
1602 pre->g_pre_comp[i][2][2]);
1603 /* 2^112*G + 2^168*G resp. 2^140*G + 2^196*G */
1604 point_add(
1605 pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1],
1606 pre->g_pre_comp[i][12][2], pre->g_pre_comp[i][8][0],
1607 pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
1608 0, pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1],
1609 pre->g_pre_comp[i][4][2]);
1610 /* 2^56*G + 2^112*G + 2^168*G resp. 2^84*G + 2^140*G + 2^196*G */
1611 point_add(
1612 pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1],
1613 pre->g_pre_comp[i][14][2], pre->g_pre_comp[i][12][0],
1614 pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2],
1615 0, pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1],
1616 pre->g_pre_comp[i][2][2]);
1617 for (j = 1; j < 8; ++j)
1618 {
1619 /* odd multiples: add G resp. 2^28*G */
1620 point_add(
1621 pre->g_pre_comp[i][2*j+1][0], pre->g_pre_comp[i][2*j+1][1],
1622 pre->g_pre_comp[i][2*j+1][2], pre->g_pre_comp[i][2*j][0],
1623 pre->g_pre_comp[i][2*j][1], pre->g_pre_comp[i][2*j][2],
1624 0, pre->g_pre_comp[i][1][0], pre->g_pre_comp[i][1][1],
1625 pre->g_pre_comp[i][1][2]);
1626 }
1627 }
1628 make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_felems);
1629
1630 if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp224_pre_comp_dup,
1631 nistp224_pre_comp_free, nistp224_pre_comp_clear_free))
1632 goto err;
1633 ret = 1;
1634 pre = NULL;
1635 err:
1636 BN_CTX_end(ctx);
1637 if (generator != NULL)
1638 EC_POINT_free(generator);
1639 if (new_ctx != NULL)
1640 BN_CTX_free(new_ctx);
1641 if (pre)
1642 nistp224_pre_comp_free(pre);
1643 return ret;
1644 }
1645
1646int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group)
1647 {
1648 if (EC_EX_DATA_get_data(group->extra_data, nistp224_pre_comp_dup,
1649 nistp224_pre_comp_free, nistp224_pre_comp_clear_free)
1650 != NULL)
1651 return 1;
1652 else
1653 return 0;
1654 }
1655
1656#else
1657static void *dummy=&dummy;
1658#endif
diff --git a/src/lib/libcrypto/ec/ecp_nistp256.c b/src/lib/libcrypto/ec/ecp_nistp256.c
new file mode 100644
index 0000000000..4bc0f5dce0
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_nistp256.c
@@ -0,0 +1,2171 @@
1/* crypto/ec/ecp_nistp256.c */
2/*
3 * Written by Adam Langley (Google) for the OpenSSL project
4 */
5/* Copyright 2011 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 *
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21/*
22 * A 64-bit implementation of the NIST P-256 elliptic curve point multiplication
23 *
24 * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c.
25 * Otherwise based on Emilia's P224 work, which was inspired by my curve25519
26 * work which got its smarts from Daniel J. Bernstein's work on the same.
27 */
28
29#include <openssl/opensslconf.h>
30#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
31
32#ifndef OPENSSL_SYS_VMS
33#include <stdint.h>
34#else
35#include <inttypes.h>
36#endif
37
38#include <string.h>
39#include <openssl/err.h>
40#include "ec_lcl.h"
41
42#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
43 /* even with gcc, the typedef won't work for 32-bit platforms */
44 typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit platforms */
45 typedef __int128_t int128_t;
46#else
47 #error "Need GCC 3.1 or later to define type uint128_t"
48#endif
49
50typedef uint8_t u8;
51typedef uint32_t u32;
52typedef uint64_t u64;
53typedef int64_t s64;
54
55/* The underlying field.
56 *
57 * P256 operates over GF(2^256-2^224+2^192+2^96-1). We can serialise an element
58 * of this field into 32 bytes. We call this an felem_bytearray. */
59
60typedef u8 felem_bytearray[32];
61
62/* These are the parameters of P256, taken from FIPS 186-3, page 86. These
63 * values are big-endian. */
64static const felem_bytearray nistp256_curve_params[5] = {
65 {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* p */
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
68 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
69 {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* a = -3 */
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
72 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc}, /* b */
73 {0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7,
74 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc,
75 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6,
76 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b},
77 {0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, /* x */
78 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2,
79 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
80 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96},
81 {0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, /* y */
82 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
83 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
84 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5}
85};
86
87/* The representation of field elements.
88 * ------------------------------------
89 *
90 * We represent field elements with either four 128-bit values, eight 128-bit
91 * values, or four 64-bit values. The field element represented is:
92 * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + v[3]*2^192 (mod p)
93 * or:
94 * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + ... + v[8]*2^512 (mod p)
95 *
96 * 128-bit values are called 'limbs'. Since the limbs are spaced only 64 bits
97 * apart, but are 128-bits wide, the most significant bits of each limb overlap
98 * with the least significant bits of the next.
99 *
100 * A field element with four limbs is an 'felem'. One with eight limbs is a
101 * 'longfelem'
102 *
103 * A field element with four, 64-bit values is called a 'smallfelem'. Small
104 * values are used as intermediate values before multiplication.
105 */
106
107#define NLIMBS 4
108
109typedef uint128_t limb;
110typedef limb felem[NLIMBS];
111typedef limb longfelem[NLIMBS * 2];
112typedef u64 smallfelem[NLIMBS];
113
114/* This is the value of the prime as four 64-bit words, little-endian. */
115static const u64 kPrime[4] = { 0xfffffffffffffffful, 0xffffffff, 0, 0xffffffff00000001ul };
116static const limb bottom32bits = 0xffffffff;
117static const u64 bottom63bits = 0x7ffffffffffffffful;
118
119/* bin32_to_felem takes a little-endian byte array and converts it into felem
120 * form. This assumes that the CPU is little-endian. */
121static void bin32_to_felem(felem out, const u8 in[32])
122 {
123 out[0] = *((u64*) &in[0]);
124 out[1] = *((u64*) &in[8]);
125 out[2] = *((u64*) &in[16]);
126 out[3] = *((u64*) &in[24]);
127 }
128
129/* smallfelem_to_bin32 takes a smallfelem and serialises into a little endian,
130 * 32 byte array. This assumes that the CPU is little-endian. */
131static void smallfelem_to_bin32(u8 out[32], const smallfelem in)
132 {
133 *((u64*) &out[0]) = in[0];
134 *((u64*) &out[8]) = in[1];
135 *((u64*) &out[16]) = in[2];
136 *((u64*) &out[24]) = in[3];
137 }
138
139/* To preserve endianness when using BN_bn2bin and BN_bin2bn */
140static void flip_endian(u8 *out, const u8 *in, unsigned len)
141 {
142 unsigned i;
143 for (i = 0; i < len; ++i)
144 out[i] = in[len-1-i];
145 }
146
147/* BN_to_felem converts an OpenSSL BIGNUM into an felem */
148static int BN_to_felem(felem out, const BIGNUM *bn)
149 {
150 felem_bytearray b_in;
151 felem_bytearray b_out;
152 unsigned num_bytes;
153
154 /* BN_bn2bin eats leading zeroes */
155 memset(b_out, 0, sizeof b_out);
156 num_bytes = BN_num_bytes(bn);
157 if (num_bytes > sizeof b_out)
158 {
159 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
160 return 0;
161 }
162 if (BN_is_negative(bn))
163 {
164 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
165 return 0;
166 }
167 num_bytes = BN_bn2bin(bn, b_in);
168 flip_endian(b_out, b_in, num_bytes);
169 bin32_to_felem(out, b_out);
170 return 1;
171 }
172
173/* felem_to_BN converts an felem into an OpenSSL BIGNUM */
174static BIGNUM *smallfelem_to_BN(BIGNUM *out, const smallfelem in)
175 {
176 felem_bytearray b_in, b_out;
177 smallfelem_to_bin32(b_in, in);
178 flip_endian(b_out, b_in, sizeof b_out);
179 return BN_bin2bn(b_out, sizeof b_out, out);
180 }
181
182
183/* Field operations
184 * ---------------- */
185
186static void smallfelem_one(smallfelem out)
187 {
188 out[0] = 1;
189 out[1] = 0;
190 out[2] = 0;
191 out[3] = 0;
192 }
193
194static void smallfelem_assign(smallfelem out, const smallfelem in)
195 {
196 out[0] = in[0];
197 out[1] = in[1];
198 out[2] = in[2];
199 out[3] = in[3];
200 }
201
202static void felem_assign(felem out, const felem in)
203 {
204 out[0] = in[0];
205 out[1] = in[1];
206 out[2] = in[2];
207 out[3] = in[3];
208 }
209
210/* felem_sum sets out = out + in. */
211static void felem_sum(felem out, const felem in)
212 {
213 out[0] += in[0];
214 out[1] += in[1];
215 out[2] += in[2];
216 out[3] += in[3];
217 }
218
219/* felem_small_sum sets out = out + in. */
220static void felem_small_sum(felem out, const smallfelem in)
221 {
222 out[0] += in[0];
223 out[1] += in[1];
224 out[2] += in[2];
225 out[3] += in[3];
226 }
227
228/* felem_scalar sets out = out * scalar */
229static void felem_scalar(felem out, const u64 scalar)
230 {
231 out[0] *= scalar;
232 out[1] *= scalar;
233 out[2] *= scalar;
234 out[3] *= scalar;
235 }
236
237/* longfelem_scalar sets out = out * scalar */
238static void longfelem_scalar(longfelem out, const u64 scalar)
239 {
240 out[0] *= scalar;
241 out[1] *= scalar;
242 out[2] *= scalar;
243 out[3] *= scalar;
244 out[4] *= scalar;
245 out[5] *= scalar;
246 out[6] *= scalar;
247 out[7] *= scalar;
248 }
249
250#define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9)
251#define two105 (((limb)1) << 105)
252#define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9)
253
254/* zero105 is 0 mod p */
255static const felem zero105 = { two105m41m9, two105, two105m41p9, two105m41p9 };
256
257/* smallfelem_neg sets |out| to |-small|
258 * On exit:
259 * out[i] < out[i] + 2^105
260 */
261static void smallfelem_neg(felem out, const smallfelem small)
262 {
263 /* In order to prevent underflow, we subtract from 0 mod p. */
264 out[0] = zero105[0] - small[0];
265 out[1] = zero105[1] - small[1];
266 out[2] = zero105[2] - small[2];
267 out[3] = zero105[3] - small[3];
268 }
269
270/* felem_diff subtracts |in| from |out|
271 * On entry:
272 * in[i] < 2^104
273 * On exit:
274 * out[i] < out[i] + 2^105
275 */
276static void felem_diff(felem out, const felem in)
277 {
278 /* In order to prevent underflow, we add 0 mod p before subtracting. */
279 out[0] += zero105[0];
280 out[1] += zero105[1];
281 out[2] += zero105[2];
282 out[3] += zero105[3];
283
284 out[0] -= in[0];
285 out[1] -= in[1];
286 out[2] -= in[2];
287 out[3] -= in[3];
288 }
289
290#define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11)
291#define two107 (((limb)1) << 107)
292#define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11)
293
294/* zero107 is 0 mod p */
295static const felem zero107 = { two107m43m11, two107, two107m43p11, two107m43p11 };
296
297/* An alternative felem_diff for larger inputs |in|
298 * felem_diff_zero107 subtracts |in| from |out|
299 * On entry:
300 * in[i] < 2^106
301 * On exit:
302 * out[i] < out[i] + 2^107
303 */
304static void felem_diff_zero107(felem out, const felem in)
305 {
306 /* In order to prevent underflow, we add 0 mod p before subtracting. */
307 out[0] += zero107[0];
308 out[1] += zero107[1];
309 out[2] += zero107[2];
310 out[3] += zero107[3];
311
312 out[0] -= in[0];
313 out[1] -= in[1];
314 out[2] -= in[2];
315 out[3] -= in[3];
316 }
317
318/* longfelem_diff subtracts |in| from |out|
319 * On entry:
320 * in[i] < 7*2^67
321 * On exit:
322 * out[i] < out[i] + 2^70 + 2^40
323 */
324static void longfelem_diff(longfelem out, const longfelem in)
325 {
326 static const limb two70m8p6 = (((limb)1) << 70) - (((limb)1) << 8) + (((limb)1) << 6);
327 static const limb two70p40 = (((limb)1) << 70) + (((limb)1) << 40);
328 static const limb two70 = (((limb)1) << 70);
329 static const limb two70m40m38p6 = (((limb)1) << 70) - (((limb)1) << 40) - (((limb)1) << 38) + (((limb)1) << 6);
330 static const limb two70m6 = (((limb)1) << 70) - (((limb)1) << 6);
331
332 /* add 0 mod p to avoid underflow */
333 out[0] += two70m8p6;
334 out[1] += two70p40;
335 out[2] += two70;
336 out[3] += two70m40m38p6;
337 out[4] += two70m6;
338 out[5] += two70m6;
339 out[6] += two70m6;
340 out[7] += two70m6;
341
342 /* in[i] < 7*2^67 < 2^70 - 2^40 - 2^38 + 2^6 */
343 out[0] -= in[0];
344 out[1] -= in[1];
345 out[2] -= in[2];
346 out[3] -= in[3];
347 out[4] -= in[4];
348 out[5] -= in[5];
349 out[6] -= in[6];
350 out[7] -= in[7];
351 }
352
353#define two64m0 (((limb)1) << 64) - 1
354#define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1
355#define two64m46 (((limb)1) << 64) - (((limb)1) << 46)
356#define two64m32 (((limb)1) << 64) - (((limb)1) << 32)
357
358/* zero110 is 0 mod p */
359static const felem zero110 = { two64m0, two110p32m0, two64m46, two64m32 };
360
361/* felem_shrink converts an felem into a smallfelem. The result isn't quite
362 * minimal as the value may be greater than p.
363 *
364 * On entry:
365 * in[i] < 2^109
366 * On exit:
367 * out[i] < 2^64
368 */
369static void felem_shrink(smallfelem out, const felem in)
370 {
371 felem tmp;
372 u64 a, b, mask;
373 s64 high, low;
374 static const u64 kPrime3Test = 0x7fffffff00000001ul; /* 2^63 - 2^32 + 1 */
375
376 /* Carry 2->3 */
377 tmp[3] = zero110[3] + in[3] + ((u64) (in[2] >> 64));
378 /* tmp[3] < 2^110 */
379
380 tmp[2] = zero110[2] + (u64) in[2];
381 tmp[0] = zero110[0] + in[0];
382 tmp[1] = zero110[1] + in[1];
383 /* tmp[0] < 2**110, tmp[1] < 2^111, tmp[2] < 2**65 */
384
385 /* We perform two partial reductions where we eliminate the
386 * high-word of tmp[3]. We don't update the other words till the end.
387 */
388 a = tmp[3] >> 64; /* a < 2^46 */
389 tmp[3] = (u64) tmp[3];
390 tmp[3] -= a;
391 tmp[3] += ((limb)a) << 32;
392 /* tmp[3] < 2^79 */
393
394 b = a;
395 a = tmp[3] >> 64; /* a < 2^15 */
396 b += a; /* b < 2^46 + 2^15 < 2^47 */
397 tmp[3] = (u64) tmp[3];
398 tmp[3] -= a;
399 tmp[3] += ((limb)a) << 32;
400 /* tmp[3] < 2^64 + 2^47 */
401
402 /* This adjusts the other two words to complete the two partial
403 * reductions. */
404 tmp[0] += b;
405 tmp[1] -= (((limb)b) << 32);
406
407 /* In order to make space in tmp[3] for the carry from 2 -> 3, we
408 * conditionally subtract kPrime if tmp[3] is large enough. */
409 high = tmp[3] >> 64;
410 /* As tmp[3] < 2^65, high is either 1 or 0 */
411 high <<= 63;
412 high >>= 63;
413 /* high is:
414 * all ones if the high word of tmp[3] is 1
415 * all zeros if the high word of tmp[3] if 0 */
416 low = tmp[3];
417 mask = low >> 63;
418 /* mask is:
419 * all ones if the MSB of low is 1
420 * all zeros if the MSB of low if 0 */
421 low &= bottom63bits;
422 low -= kPrime3Test;
423 /* if low was greater than kPrime3Test then the MSB is zero */
424 low = ~low;
425 low >>= 63;
426 /* low is:
427 * all ones if low was > kPrime3Test
428 * all zeros if low was <= kPrime3Test */
429 mask = (mask & low) | high;
430 tmp[0] -= mask & kPrime[0];
431 tmp[1] -= mask & kPrime[1];
432 /* kPrime[2] is zero, so omitted */
433 tmp[3] -= mask & kPrime[3];
434 /* tmp[3] < 2**64 - 2**32 + 1 */
435
436 tmp[1] += ((u64) (tmp[0] >> 64)); tmp[0] = (u64) tmp[0];
437 tmp[2] += ((u64) (tmp[1] >> 64)); tmp[1] = (u64) tmp[1];
438 tmp[3] += ((u64) (tmp[2] >> 64)); tmp[2] = (u64) tmp[2];
439 /* tmp[i] < 2^64 */
440
441 out[0] = tmp[0];
442 out[1] = tmp[1];
443 out[2] = tmp[2];
444 out[3] = tmp[3];
445 }
446
447/* smallfelem_expand converts a smallfelem to an felem */
448static void smallfelem_expand(felem out, const smallfelem in)
449 {
450 out[0] = in[0];
451 out[1] = in[1];
452 out[2] = in[2];
453 out[3] = in[3];
454 }
455
456/* smallfelem_square sets |out| = |small|^2
457 * On entry:
458 * small[i] < 2^64
459 * On exit:
460 * out[i] < 7 * 2^64 < 2^67
461 */
462static void smallfelem_square(longfelem out, const smallfelem small)
463 {
464 limb a;
465 u64 high, low;
466
467 a = ((uint128_t) small[0]) * small[0];
468 low = a;
469 high = a >> 64;
470 out[0] = low;
471 out[1] = high;
472
473 a = ((uint128_t) small[0]) * small[1];
474 low = a;
475 high = a >> 64;
476 out[1] += low;
477 out[1] += low;
478 out[2] = high;
479
480 a = ((uint128_t) small[0]) * small[2];
481 low = a;
482 high = a >> 64;
483 out[2] += low;
484 out[2] *= 2;
485 out[3] = high;
486
487 a = ((uint128_t) small[0]) * small[3];
488 low = a;
489 high = a >> 64;
490 out[3] += low;
491 out[4] = high;
492
493 a = ((uint128_t) small[1]) * small[2];
494 low = a;
495 high = a >> 64;
496 out[3] += low;
497 out[3] *= 2;
498 out[4] += high;
499
500 a = ((uint128_t) small[1]) * small[1];
501 low = a;
502 high = a >> 64;
503 out[2] += low;
504 out[3] += high;
505
506 a = ((uint128_t) small[1]) * small[3];
507 low = a;
508 high = a >> 64;
509 out[4] += low;
510 out[4] *= 2;
511 out[5] = high;
512
513 a = ((uint128_t) small[2]) * small[3];
514 low = a;
515 high = a >> 64;
516 out[5] += low;
517 out[5] *= 2;
518 out[6] = high;
519 out[6] += high;
520
521 a = ((uint128_t) small[2]) * small[2];
522 low = a;
523 high = a >> 64;
524 out[4] += low;
525 out[5] += high;
526
527 a = ((uint128_t) small[3]) * small[3];
528 low = a;
529 high = a >> 64;
530 out[6] += low;
531 out[7] = high;
532 }
533
534/* felem_square sets |out| = |in|^2
535 * On entry:
536 * in[i] < 2^109
537 * On exit:
538 * out[i] < 7 * 2^64 < 2^67
539 */
540static void felem_square(longfelem out, const felem in)
541 {
542 u64 small[4];
543 felem_shrink(small, in);
544 smallfelem_square(out, small);
545 }
546
547/* smallfelem_mul sets |out| = |small1| * |small2|
548 * On entry:
549 * small1[i] < 2^64
550 * small2[i] < 2^64
551 * On exit:
552 * out[i] < 7 * 2^64 < 2^67
553 */
554static void smallfelem_mul(longfelem out, const smallfelem small1, const smallfelem small2)
555 {
556 limb a;
557 u64 high, low;
558
559 a = ((uint128_t) small1[0]) * small2[0];
560 low = a;
561 high = a >> 64;
562 out[0] = low;
563 out[1] = high;
564
565
566 a = ((uint128_t) small1[0]) * small2[1];
567 low = a;
568 high = a >> 64;
569 out[1] += low;
570 out[2] = high;
571
572 a = ((uint128_t) small1[1]) * small2[0];
573 low = a;
574 high = a >> 64;
575 out[1] += low;
576 out[2] += high;
577
578
579 a = ((uint128_t) small1[0]) * small2[2];
580 low = a;
581 high = a >> 64;
582 out[2] += low;
583 out[3] = high;
584
585 a = ((uint128_t) small1[1]) * small2[1];
586 low = a;
587 high = a >> 64;
588 out[2] += low;
589 out[3] += high;
590
591 a = ((uint128_t) small1[2]) * small2[0];
592 low = a;
593 high = a >> 64;
594 out[2] += low;
595 out[3] += high;
596
597
598 a = ((uint128_t) small1[0]) * small2[3];
599 low = a;
600 high = a >> 64;
601 out[3] += low;
602 out[4] = high;
603
604 a = ((uint128_t) small1[1]) * small2[2];
605 low = a;
606 high = a >> 64;
607 out[3] += low;
608 out[4] += high;
609
610 a = ((uint128_t) small1[2]) * small2[1];
611 low = a;
612 high = a >> 64;
613 out[3] += low;
614 out[4] += high;
615
616 a = ((uint128_t) small1[3]) * small2[0];
617 low = a;
618 high = a >> 64;
619 out[3] += low;
620 out[4] += high;
621
622
623 a = ((uint128_t) small1[1]) * small2[3];
624 low = a;
625 high = a >> 64;
626 out[4] += low;
627 out[5] = high;
628
629 a = ((uint128_t) small1[2]) * small2[2];
630 low = a;
631 high = a >> 64;
632 out[4] += low;
633 out[5] += high;
634
635 a = ((uint128_t) small1[3]) * small2[1];
636 low = a;
637 high = a >> 64;
638 out[4] += low;
639 out[5] += high;
640
641
642 a = ((uint128_t) small1[2]) * small2[3];
643 low = a;
644 high = a >> 64;
645 out[5] += low;
646 out[6] = high;
647
648 a = ((uint128_t) small1[3]) * small2[2];
649 low = a;
650 high = a >> 64;
651 out[5] += low;
652 out[6] += high;
653
654
655 a = ((uint128_t) small1[3]) * small2[3];
656 low = a;
657 high = a >> 64;
658 out[6] += low;
659 out[7] = high;
660 }
661
662/* felem_mul sets |out| = |in1| * |in2|
663 * On entry:
664 * in1[i] < 2^109
665 * in2[i] < 2^109
666 * On exit:
667 * out[i] < 7 * 2^64 < 2^67
668 */
669static void felem_mul(longfelem out, const felem in1, const felem in2)
670 {
671 smallfelem small1, small2;
672 felem_shrink(small1, in1);
673 felem_shrink(small2, in2);
674 smallfelem_mul(out, small1, small2);
675 }
676
677/* felem_small_mul sets |out| = |small1| * |in2|
678 * On entry:
679 * small1[i] < 2^64
680 * in2[i] < 2^109
681 * On exit:
682 * out[i] < 7 * 2^64 < 2^67
683 */
684static void felem_small_mul(longfelem out, const smallfelem small1, const felem in2)
685 {
686 smallfelem small2;
687 felem_shrink(small2, in2);
688 smallfelem_mul(out, small1, small2);
689 }
690
691#define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4)
692#define two100 (((limb)1) << 100)
693#define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4)
694/* zero100 is 0 mod p */
695static const felem zero100 = { two100m36m4, two100, two100m36p4, two100m36p4 };
696
697/* Internal function for the different flavours of felem_reduce.
698 * felem_reduce_ reduces the higher coefficients in[4]-in[7].
699 * On entry:
700 * out[0] >= in[6] + 2^32*in[6] + in[7] + 2^32*in[7]
701 * out[1] >= in[7] + 2^32*in[4]
702 * out[2] >= in[5] + 2^32*in[5]
703 * out[3] >= in[4] + 2^32*in[5] + 2^32*in[6]
704 * On exit:
705 * out[0] <= out[0] + in[4] + 2^32*in[5]
706 * out[1] <= out[1] + in[5] + 2^33*in[6]
707 * out[2] <= out[2] + in[7] + 2*in[6] + 2^33*in[7]
708 * out[3] <= out[3] + 2^32*in[4] + 3*in[7]
709 */
710static void felem_reduce_(felem out, const longfelem in)
711 {
712 int128_t c;
713 /* combine common terms from below */
714 c = in[4] + (in[5] << 32);
715 out[0] += c;
716 out[3] -= c;
717
718 c = in[5] - in[7];
719 out[1] += c;
720 out[2] -= c;
721
722 /* the remaining terms */
723 /* 256: [(0,1),(96,-1),(192,-1),(224,1)] */
724 out[1] -= (in[4] << 32);
725 out[3] += (in[4] << 32);
726
727 /* 320: [(32,1),(64,1),(128,-1),(160,-1),(224,-1)] */
728 out[2] -= (in[5] << 32);
729
730 /* 384: [(0,-1),(32,-1),(96,2),(128,2),(224,-1)] */
731 out[0] -= in[6];
732 out[0] -= (in[6] << 32);
733 out[1] += (in[6] << 33);
734 out[2] += (in[6] * 2);
735 out[3] -= (in[6] << 32);
736
737 /* 448: [(0,-1),(32,-1),(64,-1),(128,1),(160,2),(192,3)] */
738 out[0] -= in[7];
739 out[0] -= (in[7] << 32);
740 out[2] += (in[7] << 33);
741 out[3] += (in[7] * 3);
742 }
743
744/* felem_reduce converts a longfelem into an felem.
745 * To be called directly after felem_square or felem_mul.
746 * On entry:
747 * in[0] < 2^64, in[1] < 3*2^64, in[2] < 5*2^64, in[3] < 7*2^64
748 * in[4] < 7*2^64, in[5] < 5*2^64, in[6] < 3*2^64, in[7] < 2*64
749 * On exit:
750 * out[i] < 2^101
751 */
752static void felem_reduce(felem out, const longfelem in)
753 {
754 out[0] = zero100[0] + in[0];
755 out[1] = zero100[1] + in[1];
756 out[2] = zero100[2] + in[2];
757 out[3] = zero100[3] + in[3];
758
759 felem_reduce_(out, in);
760
761 /* out[0] > 2^100 - 2^36 - 2^4 - 3*2^64 - 3*2^96 - 2^64 - 2^96 > 0
762 * out[1] > 2^100 - 2^64 - 7*2^96 > 0
763 * out[2] > 2^100 - 2^36 + 2^4 - 5*2^64 - 5*2^96 > 0
764 * out[3] > 2^100 - 2^36 + 2^4 - 7*2^64 - 5*2^96 - 3*2^96 > 0
765 *
766 * out[0] < 2^100 + 2^64 + 7*2^64 + 5*2^96 < 2^101
767 * out[1] < 2^100 + 3*2^64 + 5*2^64 + 3*2^97 < 2^101
768 * out[2] < 2^100 + 5*2^64 + 2^64 + 3*2^65 + 2^97 < 2^101
769 * out[3] < 2^100 + 7*2^64 + 7*2^96 + 3*2^64 < 2^101
770 */
771 }
772
773/* felem_reduce_zero105 converts a larger longfelem into an felem.
774 * On entry:
775 * in[0] < 2^71
776 * On exit:
777 * out[i] < 2^106
778 */
779static void felem_reduce_zero105(felem out, const longfelem in)
780 {
781 out[0] = zero105[0] + in[0];
782 out[1] = zero105[1] + in[1];
783 out[2] = zero105[2] + in[2];
784 out[3] = zero105[3] + in[3];
785
786 felem_reduce_(out, in);
787
788 /* out[0] > 2^105 - 2^41 - 2^9 - 2^71 - 2^103 - 2^71 - 2^103 > 0
789 * out[1] > 2^105 - 2^71 - 2^103 > 0
790 * out[2] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 > 0
791 * out[3] > 2^105 - 2^41 + 2^9 - 2^71 - 2^103 - 2^103 > 0
792 *
793 * out[0] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106
794 * out[1] < 2^105 + 2^71 + 2^71 + 2^103 < 2^106
795 * out[2] < 2^105 + 2^71 + 2^71 + 2^71 + 2^103 < 2^106
796 * out[3] < 2^105 + 2^71 + 2^103 + 2^71 < 2^106
797 */
798 }
799
800/* subtract_u64 sets *result = *result - v and *carry to one if the subtraction
801 * underflowed. */
802static void subtract_u64(u64* result, u64* carry, u64 v)
803 {
804 uint128_t r = *result;
805 r -= v;
806 *carry = (r >> 64) & 1;
807 *result = (u64) r;
808 }
809
810/* felem_contract converts |in| to its unique, minimal representation.
811 * On entry:
812 * in[i] < 2^109
813 */
814static void felem_contract(smallfelem out, const felem in)
815 {
816 unsigned i;
817 u64 all_equal_so_far = 0, result = 0, carry;
818
819 felem_shrink(out, in);
820 /* small is minimal except that the value might be > p */
821
822 all_equal_so_far--;
823 /* We are doing a constant time test if out >= kPrime. We need to
824 * compare each u64, from most-significant to least significant. For
825 * each one, if all words so far have been equal (m is all ones) then a
826 * non-equal result is the answer. Otherwise we continue. */
827 for (i = 3; i < 4; i--)
828 {
829 u64 equal;
830 uint128_t a = ((uint128_t) kPrime[i]) - out[i];
831 /* if out[i] > kPrime[i] then a will underflow and the high
832 * 64-bits will all be set. */
833 result |= all_equal_so_far & ((u64) (a >> 64));
834
835 /* if kPrime[i] == out[i] then |equal| will be all zeros and
836 * the decrement will make it all ones. */
837 equal = kPrime[i] ^ out[i];
838 equal--;
839 equal &= equal << 32;
840 equal &= equal << 16;
841 equal &= equal << 8;
842 equal &= equal << 4;
843 equal &= equal << 2;
844 equal &= equal << 1;
845 equal = ((s64) equal) >> 63;
846
847 all_equal_so_far &= equal;
848 }
849
850 /* if all_equal_so_far is still all ones then the two values are equal
851 * and so out >= kPrime is true. */
852 result |= all_equal_so_far;
853
854 /* if out >= kPrime then we subtract kPrime. */
855 subtract_u64(&out[0], &carry, result & kPrime[0]);
856 subtract_u64(&out[1], &carry, carry);
857 subtract_u64(&out[2], &carry, carry);
858 subtract_u64(&out[3], &carry, carry);
859
860 subtract_u64(&out[1], &carry, result & kPrime[1]);
861 subtract_u64(&out[2], &carry, carry);
862 subtract_u64(&out[3], &carry, carry);
863
864 subtract_u64(&out[2], &carry, result & kPrime[2]);
865 subtract_u64(&out[3], &carry, carry);
866
867 subtract_u64(&out[3], &carry, result & kPrime[3]);
868 }
869
870static void smallfelem_square_contract(smallfelem out, const smallfelem in)
871 {
872 longfelem longtmp;
873 felem tmp;
874
875 smallfelem_square(longtmp, in);
876 felem_reduce(tmp, longtmp);
877 felem_contract(out, tmp);
878 }
879
880static void smallfelem_mul_contract(smallfelem out, const smallfelem in1, const smallfelem in2)
881 {
882 longfelem longtmp;
883 felem tmp;
884
885 smallfelem_mul(longtmp, in1, in2);
886 felem_reduce(tmp, longtmp);
887 felem_contract(out, tmp);
888 }
889
890/* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0
891 * otherwise.
892 * On entry:
893 * small[i] < 2^64
894 */
895static limb smallfelem_is_zero(const smallfelem small)
896 {
897 limb result;
898 u64 is_p;
899
900 u64 is_zero = small[0] | small[1] | small[2] | small[3];
901 is_zero--;
902 is_zero &= is_zero << 32;
903 is_zero &= is_zero << 16;
904 is_zero &= is_zero << 8;
905 is_zero &= is_zero << 4;
906 is_zero &= is_zero << 2;
907 is_zero &= is_zero << 1;
908 is_zero = ((s64) is_zero) >> 63;
909
910 is_p = (small[0] ^ kPrime[0]) |
911 (small[1] ^ kPrime[1]) |
912 (small[2] ^ kPrime[2]) |
913 (small[3] ^ kPrime[3]);
914 is_p--;
915 is_p &= is_p << 32;
916 is_p &= is_p << 16;
917 is_p &= is_p << 8;
918 is_p &= is_p << 4;
919 is_p &= is_p << 2;
920 is_p &= is_p << 1;
921 is_p = ((s64) is_p) >> 63;
922
923 is_zero |= is_p;
924
925 result = is_zero;
926 result |= ((limb) is_zero) << 64;
927 return result;
928 }
929
930static int smallfelem_is_zero_int(const smallfelem small)
931 {
932 return (int) (smallfelem_is_zero(small) & ((limb)1));
933 }
934
935/* felem_inv calculates |out| = |in|^{-1}
936 *
937 * Based on Fermat's Little Theorem:
938 * a^p = a (mod p)
939 * a^{p-1} = 1 (mod p)
940 * a^{p-2} = a^{-1} (mod p)
941 */
942static void felem_inv(felem out, const felem in)
943 {
944 felem ftmp, ftmp2;
945 /* each e_I will hold |in|^{2^I - 1} */
946 felem e2, e4, e8, e16, e32, e64;
947 longfelem tmp;
948 unsigned i;
949
950 felem_square(tmp, in); felem_reduce(ftmp, tmp); /* 2^1 */
951 felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */
952 felem_assign(e2, ftmp);
953 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */
954 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^4 - 2^2 */
955 felem_mul(tmp, ftmp, e2); felem_reduce(ftmp, tmp); /* 2^4 - 2^0 */
956 felem_assign(e4, ftmp);
957 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^5 - 2^1 */
958 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^6 - 2^2 */
959 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^7 - 2^3 */
960 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^8 - 2^4 */
961 felem_mul(tmp, ftmp, e4); felem_reduce(ftmp, tmp); /* 2^8 - 2^0 */
962 felem_assign(e8, ftmp);
963 for (i = 0; i < 8; i++) {
964 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp);
965 } /* 2^16 - 2^8 */
966 felem_mul(tmp, ftmp, e8); felem_reduce(ftmp, tmp); /* 2^16 - 2^0 */
967 felem_assign(e16, ftmp);
968 for (i = 0; i < 16; i++) {
969 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp);
970 } /* 2^32 - 2^16 */
971 felem_mul(tmp, ftmp, e16); felem_reduce(ftmp, tmp); /* 2^32 - 2^0 */
972 felem_assign(e32, ftmp);
973 for (i = 0; i < 32; i++) {
974 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp);
975 } /* 2^64 - 2^32 */
976 felem_assign(e64, ftmp);
977 felem_mul(tmp, ftmp, in); felem_reduce(ftmp, tmp); /* 2^64 - 2^32 + 2^0 */
978 for (i = 0; i < 192; i++) {
979 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp);
980 } /* 2^256 - 2^224 + 2^192 */
981
982 felem_mul(tmp, e64, e32); felem_reduce(ftmp2, tmp); /* 2^64 - 2^0 */
983 for (i = 0; i < 16; i++) {
984 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp);
985 } /* 2^80 - 2^16 */
986 felem_mul(tmp, ftmp2, e16); felem_reduce(ftmp2, tmp); /* 2^80 - 2^0 */
987 for (i = 0; i < 8; i++) {
988 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp);
989 } /* 2^88 - 2^8 */
990 felem_mul(tmp, ftmp2, e8); felem_reduce(ftmp2, tmp); /* 2^88 - 2^0 */
991 for (i = 0; i < 4; i++) {
992 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp);
993 } /* 2^92 - 2^4 */
994 felem_mul(tmp, ftmp2, e4); felem_reduce(ftmp2, tmp); /* 2^92 - 2^0 */
995 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^93 - 2^1 */
996 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^94 - 2^2 */
997 felem_mul(tmp, ftmp2, e2); felem_reduce(ftmp2, tmp); /* 2^94 - 2^0 */
998 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^95 - 2^1 */
999 felem_square(tmp, ftmp2); felem_reduce(ftmp2, tmp); /* 2^96 - 2^2 */
1000 felem_mul(tmp, ftmp2, in); felem_reduce(ftmp2, tmp); /* 2^96 - 3 */
1001
1002 felem_mul(tmp, ftmp2, ftmp); felem_reduce(out, tmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */
1003 }
1004
1005static void smallfelem_inv_contract(smallfelem out, const smallfelem in)
1006 {
1007 felem tmp;
1008
1009 smallfelem_expand(tmp, in);
1010 felem_inv(tmp, tmp);
1011 felem_contract(out, tmp);
1012 }
1013
1014/* Group operations
1015 * ----------------
1016 *
1017 * Building on top of the field operations we have the operations on the
1018 * elliptic curve group itself. Points on the curve are represented in Jacobian
1019 * coordinates */
1020
1021/* point_double calculates 2*(x_in, y_in, z_in)
1022 *
1023 * The method is taken from:
1024 * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
1025 *
1026 * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed.
1027 * while x_out == y_in is not (maybe this works, but it's not tested). */
1028static void
1029point_double(felem x_out, felem y_out, felem z_out,
1030 const felem x_in, const felem y_in, const felem z_in)
1031 {
1032 longfelem tmp, tmp2;
1033 felem delta, gamma, beta, alpha, ftmp, ftmp2;
1034 smallfelem small1, small2;
1035
1036 felem_assign(ftmp, x_in);
1037 /* ftmp[i] < 2^106 */
1038 felem_assign(ftmp2, x_in);
1039 /* ftmp2[i] < 2^106 */
1040
1041 /* delta = z^2 */
1042 felem_square(tmp, z_in);
1043 felem_reduce(delta, tmp);
1044 /* delta[i] < 2^101 */
1045
1046 /* gamma = y^2 */
1047 felem_square(tmp, y_in);
1048 felem_reduce(gamma, tmp);
1049 /* gamma[i] < 2^101 */
1050 felem_shrink(small1, gamma);
1051
1052 /* beta = x*gamma */
1053 felem_small_mul(tmp, small1, x_in);
1054 felem_reduce(beta, tmp);
1055 /* beta[i] < 2^101 */
1056
1057 /* alpha = 3*(x-delta)*(x+delta) */
1058 felem_diff(ftmp, delta);
1059 /* ftmp[i] < 2^105 + 2^106 < 2^107 */
1060 felem_sum(ftmp2, delta);
1061 /* ftmp2[i] < 2^105 + 2^106 < 2^107 */
1062 felem_scalar(ftmp2, 3);
1063 /* ftmp2[i] < 3 * 2^107 < 2^109 */
1064 felem_mul(tmp, ftmp, ftmp2);
1065 felem_reduce(alpha, tmp);
1066 /* alpha[i] < 2^101 */
1067 felem_shrink(small2, alpha);
1068
1069 /* x' = alpha^2 - 8*beta */
1070 smallfelem_square(tmp, small2);
1071 felem_reduce(x_out, tmp);
1072 felem_assign(ftmp, beta);
1073 felem_scalar(ftmp, 8);
1074 /* ftmp[i] < 8 * 2^101 = 2^104 */
1075 felem_diff(x_out, ftmp);
1076 /* x_out[i] < 2^105 + 2^101 < 2^106 */
1077
1078 /* z' = (y + z)^2 - gamma - delta */
1079 felem_sum(delta, gamma);
1080 /* delta[i] < 2^101 + 2^101 = 2^102 */
1081 felem_assign(ftmp, y_in);
1082 felem_sum(ftmp, z_in);
1083 /* ftmp[i] < 2^106 + 2^106 = 2^107 */
1084 felem_square(tmp, ftmp);
1085 felem_reduce(z_out, tmp);
1086 felem_diff(z_out, delta);
1087 /* z_out[i] < 2^105 + 2^101 < 2^106 */
1088
1089 /* y' = alpha*(4*beta - x') - 8*gamma^2 */
1090 felem_scalar(beta, 4);
1091 /* beta[i] < 4 * 2^101 = 2^103 */
1092 felem_diff_zero107(beta, x_out);
1093 /* beta[i] < 2^107 + 2^103 < 2^108 */
1094 felem_small_mul(tmp, small2, beta);
1095 /* tmp[i] < 7 * 2^64 < 2^67 */
1096 smallfelem_square(tmp2, small1);
1097 /* tmp2[i] < 7 * 2^64 */
1098 longfelem_scalar(tmp2, 8);
1099 /* tmp2[i] < 8 * 7 * 2^64 = 7 * 2^67 */
1100 longfelem_diff(tmp, tmp2);
1101 /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */
1102 felem_reduce_zero105(y_out, tmp);
1103 /* y_out[i] < 2^106 */
1104 }
1105
1106/* point_double_small is the same as point_double, except that it operates on
1107 * smallfelems */
1108static void
1109point_double_small(smallfelem x_out, smallfelem y_out, smallfelem z_out,
1110 const smallfelem x_in, const smallfelem y_in, const smallfelem z_in)
1111 {
1112 felem felem_x_out, felem_y_out, felem_z_out;
1113 felem felem_x_in, felem_y_in, felem_z_in;
1114
1115 smallfelem_expand(felem_x_in, x_in);
1116 smallfelem_expand(felem_y_in, y_in);
1117 smallfelem_expand(felem_z_in, z_in);
1118 point_double(felem_x_out, felem_y_out, felem_z_out,
1119 felem_x_in, felem_y_in, felem_z_in);
1120 felem_shrink(x_out, felem_x_out);
1121 felem_shrink(y_out, felem_y_out);
1122 felem_shrink(z_out, felem_z_out);
1123 }
1124
1125/* copy_conditional copies in to out iff mask is all ones. */
1126static void
1127copy_conditional(felem out, const felem in, limb mask)
1128 {
1129 unsigned i;
1130 for (i = 0; i < NLIMBS; ++i)
1131 {
1132 const limb tmp = mask & (in[i] ^ out[i]);
1133 out[i] ^= tmp;
1134 }
1135 }
1136
1137/* copy_small_conditional copies in to out iff mask is all ones. */
1138static void
1139copy_small_conditional(felem out, const smallfelem in, limb mask)
1140 {
1141 unsigned i;
1142 const u64 mask64 = mask;
1143 for (i = 0; i < NLIMBS; ++i)
1144 {
1145 out[i] = ((limb) (in[i] & mask64)) | (out[i] & ~mask);
1146 }
1147 }
1148
1149/* point_add calcuates (x1, y1, z1) + (x2, y2, z2)
1150 *
1151 * The method is taken from:
1152 * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl,
1153 * adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity).
1154 *
1155 * This function includes a branch for checking whether the two input points
1156 * are equal, (while not equal to the point at infinity). This case never
1157 * happens during single point multiplication, so there is no timing leak for
1158 * ECDH or ECDSA signing. */
1159static void point_add(felem x3, felem y3, felem z3,
1160 const felem x1, const felem y1, const felem z1,
1161 const int mixed, const smallfelem x2, const smallfelem y2, const smallfelem z2)
1162 {
1163 felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out;
1164 longfelem tmp, tmp2;
1165 smallfelem small1, small2, small3, small4, small5;
1166 limb x_equal, y_equal, z1_is_zero, z2_is_zero;
1167
1168 felem_shrink(small3, z1);
1169
1170 z1_is_zero = smallfelem_is_zero(small3);
1171 z2_is_zero = smallfelem_is_zero(z2);
1172
1173 /* ftmp = z1z1 = z1**2 */
1174 smallfelem_square(tmp, small3);
1175 felem_reduce(ftmp, tmp);
1176 /* ftmp[i] < 2^101 */
1177 felem_shrink(small1, ftmp);
1178
1179 if(!mixed)
1180 {
1181 /* ftmp2 = z2z2 = z2**2 */
1182 smallfelem_square(tmp, z2);
1183 felem_reduce(ftmp2, tmp);
1184 /* ftmp2[i] < 2^101 */
1185 felem_shrink(small2, ftmp2);
1186
1187 felem_shrink(small5, x1);
1188
1189 /* u1 = ftmp3 = x1*z2z2 */
1190 smallfelem_mul(tmp, small5, small2);
1191 felem_reduce(ftmp3, tmp);
1192 /* ftmp3[i] < 2^101 */
1193
1194 /* ftmp5 = z1 + z2 */
1195 felem_assign(ftmp5, z1);
1196 felem_small_sum(ftmp5, z2);
1197 /* ftmp5[i] < 2^107 */
1198
1199 /* ftmp5 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 */
1200 felem_square(tmp, ftmp5);
1201 felem_reduce(ftmp5, tmp);
1202 /* ftmp2 = z2z2 + z1z1 */
1203 felem_sum(ftmp2, ftmp);
1204 /* ftmp2[i] < 2^101 + 2^101 = 2^102 */
1205 felem_diff(ftmp5, ftmp2);
1206 /* ftmp5[i] < 2^105 + 2^101 < 2^106 */
1207
1208 /* ftmp2 = z2 * z2z2 */
1209 smallfelem_mul(tmp, small2, z2);
1210 felem_reduce(ftmp2, tmp);
1211
1212 /* s1 = ftmp2 = y1 * z2**3 */
1213 felem_mul(tmp, y1, ftmp2);
1214 felem_reduce(ftmp6, tmp);
1215 /* ftmp6[i] < 2^101 */
1216 }
1217 else
1218 {
1219 /* We'll assume z2 = 1 (special case z2 = 0 is handled later) */
1220
1221 /* u1 = ftmp3 = x1*z2z2 */
1222 felem_assign(ftmp3, x1);
1223 /* ftmp3[i] < 2^106 */
1224
1225 /* ftmp5 = 2z1z2 */
1226 felem_assign(ftmp5, z1);
1227 felem_scalar(ftmp5, 2);
1228 /* ftmp5[i] < 2*2^106 = 2^107 */
1229
1230 /* s1 = ftmp2 = y1 * z2**3 */
1231 felem_assign(ftmp6, y1);
1232 /* ftmp6[i] < 2^106 */
1233 }
1234
1235 /* u2 = x2*z1z1 */
1236 smallfelem_mul(tmp, x2, small1);
1237 felem_reduce(ftmp4, tmp);
1238
1239 /* h = ftmp4 = u2 - u1 */
1240 felem_diff_zero107(ftmp4, ftmp3);
1241 /* ftmp4[i] < 2^107 + 2^101 < 2^108 */
1242 felem_shrink(small4, ftmp4);
1243
1244 x_equal = smallfelem_is_zero(small4);
1245
1246 /* z_out = ftmp5 * h */
1247 felem_small_mul(tmp, small4, ftmp5);
1248 felem_reduce(z_out, tmp);
1249 /* z_out[i] < 2^101 */
1250
1251 /* ftmp = z1 * z1z1 */
1252 smallfelem_mul(tmp, small1, small3);
1253 felem_reduce(ftmp, tmp);
1254
1255 /* s2 = tmp = y2 * z1**3 */
1256 felem_small_mul(tmp, y2, ftmp);
1257 felem_reduce(ftmp5, tmp);
1258
1259 /* r = ftmp5 = (s2 - s1)*2 */
1260 felem_diff_zero107(ftmp5, ftmp6);
1261 /* ftmp5[i] < 2^107 + 2^107 = 2^108*/
1262 felem_scalar(ftmp5, 2);
1263 /* ftmp5[i] < 2^109 */
1264 felem_shrink(small1, ftmp5);
1265 y_equal = smallfelem_is_zero(small1);
1266
1267 if (x_equal && y_equal && !z1_is_zero && !z2_is_zero)
1268 {
1269 point_double(x3, y3, z3, x1, y1, z1);
1270 return;
1271 }
1272
1273 /* I = ftmp = (2h)**2 */
1274 felem_assign(ftmp, ftmp4);
1275 felem_scalar(ftmp, 2);
1276 /* ftmp[i] < 2*2^108 = 2^109 */
1277 felem_square(tmp, ftmp);
1278 felem_reduce(ftmp, tmp);
1279
1280 /* J = ftmp2 = h * I */
1281 felem_mul(tmp, ftmp4, ftmp);
1282 felem_reduce(ftmp2, tmp);
1283
1284 /* V = ftmp4 = U1 * I */
1285 felem_mul(tmp, ftmp3, ftmp);
1286 felem_reduce(ftmp4, tmp);
1287
1288 /* x_out = r**2 - J - 2V */
1289 smallfelem_square(tmp, small1);
1290 felem_reduce(x_out, tmp);
1291 felem_assign(ftmp3, ftmp4);
1292 felem_scalar(ftmp4, 2);
1293 felem_sum(ftmp4, ftmp2);
1294 /* ftmp4[i] < 2*2^101 + 2^101 < 2^103 */
1295 felem_diff(x_out, ftmp4);
1296 /* x_out[i] < 2^105 + 2^101 */
1297
1298 /* y_out = r(V-x_out) - 2 * s1 * J */
1299 felem_diff_zero107(ftmp3, x_out);
1300 /* ftmp3[i] < 2^107 + 2^101 < 2^108 */
1301 felem_small_mul(tmp, small1, ftmp3);
1302 felem_mul(tmp2, ftmp6, ftmp2);
1303 longfelem_scalar(tmp2, 2);
1304 /* tmp2[i] < 2*2^67 = 2^68 */
1305 longfelem_diff(tmp, tmp2);
1306 /* tmp[i] < 2^67 + 2^70 + 2^40 < 2^71 */
1307 felem_reduce_zero105(y_out, tmp);
1308 /* y_out[i] < 2^106 */
1309
1310 copy_small_conditional(x_out, x2, z1_is_zero);
1311 copy_conditional(x_out, x1, z2_is_zero);
1312 copy_small_conditional(y_out, y2, z1_is_zero);
1313 copy_conditional(y_out, y1, z2_is_zero);
1314 copy_small_conditional(z_out, z2, z1_is_zero);
1315 copy_conditional(z_out, z1, z2_is_zero);
1316 felem_assign(x3, x_out);
1317 felem_assign(y3, y_out);
1318 felem_assign(z3, z_out);
1319 }
1320
1321/* point_add_small is the same as point_add, except that it operates on
1322 * smallfelems */
1323static void point_add_small(smallfelem x3, smallfelem y3, smallfelem z3,
1324 smallfelem x1, smallfelem y1, smallfelem z1,
1325 smallfelem x2, smallfelem y2, smallfelem z2)
1326 {
1327 felem felem_x3, felem_y3, felem_z3;
1328 felem felem_x1, felem_y1, felem_z1;
1329 smallfelem_expand(felem_x1, x1);
1330 smallfelem_expand(felem_y1, y1);
1331 smallfelem_expand(felem_z1, z1);
1332 point_add(felem_x3, felem_y3, felem_z3, felem_x1, felem_y1, felem_z1, 0, x2, y2, z2);
1333 felem_shrink(x3, felem_x3);
1334 felem_shrink(y3, felem_y3);
1335 felem_shrink(z3, felem_z3);
1336 }
1337
1338/* Base point pre computation
1339 * --------------------------
1340 *
1341 * Two different sorts of precomputed tables are used in the following code.
1342 * Each contain various points on the curve, where each point is three field
1343 * elements (x, y, z).
1344 *
1345 * For the base point table, z is usually 1 (0 for the point at infinity).
1346 * This table has 2 * 16 elements, starting with the following:
1347 * index | bits | point
1348 * ------+---------+------------------------------
1349 * 0 | 0 0 0 0 | 0G
1350 * 1 | 0 0 0 1 | 1G
1351 * 2 | 0 0 1 0 | 2^64G
1352 * 3 | 0 0 1 1 | (2^64 + 1)G
1353 * 4 | 0 1 0 0 | 2^128G
1354 * 5 | 0 1 0 1 | (2^128 + 1)G
1355 * 6 | 0 1 1 0 | (2^128 + 2^64)G
1356 * 7 | 0 1 1 1 | (2^128 + 2^64 + 1)G
1357 * 8 | 1 0 0 0 | 2^192G
1358 * 9 | 1 0 0 1 | (2^192 + 1)G
1359 * 10 | 1 0 1 0 | (2^192 + 2^64)G
1360 * 11 | 1 0 1 1 | (2^192 + 2^64 + 1)G
1361 * 12 | 1 1 0 0 | (2^192 + 2^128)G
1362 * 13 | 1 1 0 1 | (2^192 + 2^128 + 1)G
1363 * 14 | 1 1 1 0 | (2^192 + 2^128 + 2^64)G
1364 * 15 | 1 1 1 1 | (2^192 + 2^128 + 2^64 + 1)G
1365 * followed by a copy of this with each element multiplied by 2^32.
1366 *
1367 * The reason for this is so that we can clock bits into four different
1368 * locations when doing simple scalar multiplies against the base point,
1369 * and then another four locations using the second 16 elements.
1370 *
1371 * Tables for other points have table[i] = iG for i in 0 .. 16. */
1372
1373/* gmul is the table of precomputed base points */
1374static const smallfelem gmul[2][16][3] =
1375{{{{0, 0, 0, 0},
1376 {0, 0, 0, 0},
1377 {0, 0, 0, 0}},
1378 {{0xf4a13945d898c296, 0x77037d812deb33a0, 0xf8bce6e563a440f2, 0x6b17d1f2e12c4247},
1379 {0xcbb6406837bf51f5, 0x2bce33576b315ece, 0x8ee7eb4a7c0f9e16, 0x4fe342e2fe1a7f9b},
1380 {1, 0, 0, 0}},
1381 {{0x90e75cb48e14db63, 0x29493baaad651f7e, 0x8492592e326e25de, 0x0fa822bc2811aaa5},
1382 {0xe41124545f462ee7, 0x34b1a65050fe82f5, 0x6f4ad4bcb3df188b, 0xbff44ae8f5dba80d},
1383 {1, 0, 0, 0}},
1384 {{0x93391ce2097992af, 0xe96c98fd0d35f1fa, 0xb257c0de95e02789, 0x300a4bbc89d6726f},
1385 {0xaa54a291c08127a0, 0x5bb1eeada9d806a5, 0x7f1ddb25ff1e3c6f, 0x72aac7e0d09b4644},
1386 {1, 0, 0, 0}},
1387 {{0x57c84fc9d789bd85, 0xfc35ff7dc297eac3, 0xfb982fd588c6766e, 0x447d739beedb5e67},
1388 {0x0c7e33c972e25b32, 0x3d349b95a7fae500, 0xe12e9d953a4aaff7, 0x2d4825ab834131ee},
1389 {1, 0, 0, 0}},
1390 {{0x13949c932a1d367f, 0xef7fbd2b1a0a11b7, 0xddc6068bb91dfc60, 0xef9519328a9c72ff},
1391 {0x196035a77376d8a8, 0x23183b0895ca1740, 0xc1ee9807022c219c, 0x611e9fc37dbb2c9b},
1392 {1, 0, 0, 0}},
1393 {{0xcae2b1920b57f4bc, 0x2936df5ec6c9bc36, 0x7dea6482e11238bf, 0x550663797b51f5d8},
1394 {0x44ffe216348a964c, 0x9fb3d576dbdefbe1, 0x0afa40018d9d50e5, 0x157164848aecb851},
1395 {1, 0, 0, 0}},
1396 {{0xe48ecafffc5cde01, 0x7ccd84e70d715f26, 0xa2e8f483f43e4391, 0xeb5d7745b21141ea},
1397 {0xcac917e2731a3479, 0x85f22cfe2844b645, 0x0990e6a158006cee, 0xeafd72ebdbecc17b},
1398 {1, 0, 0, 0}},
1399 {{0x6cf20ffb313728be, 0x96439591a3c6b94a, 0x2736ff8344315fc5, 0xa6d39677a7849276},
1400 {0xf2bab833c357f5f4, 0x824a920c2284059b, 0x66b8babd2d27ecdf, 0x674f84749b0b8816},
1401 {1, 0, 0, 0}},
1402 {{0x2df48c04677c8a3e, 0x74e02f080203a56b, 0x31855f7db8c7fedb, 0x4e769e7672c9ddad},
1403 {0xa4c36165b824bbb0, 0xfb9ae16f3b9122a5, 0x1ec0057206947281, 0x42b99082de830663},
1404 {1, 0, 0, 0}},
1405 {{0x6ef95150dda868b9, 0xd1f89e799c0ce131, 0x7fdc1ca008a1c478, 0x78878ef61c6ce04d},
1406 {0x9c62b9121fe0d976, 0x6ace570ebde08d4f, 0xde53142c12309def, 0xb6cb3f5d7b72c321},
1407 {1, 0, 0, 0}},
1408 {{0x7f991ed2c31a3573, 0x5b82dd5bd54fb496, 0x595c5220812ffcae, 0x0c88bc4d716b1287},
1409 {0x3a57bf635f48aca8, 0x7c8181f4df2564f3, 0x18d1b5b39c04e6aa, 0xdd5ddea3f3901dc6},
1410 {1, 0, 0, 0}},
1411 {{0xe96a79fb3e72ad0c, 0x43a0a28c42ba792f, 0xefe0a423083e49f3, 0x68f344af6b317466},
1412 {0xcdfe17db3fb24d4a, 0x668bfc2271f5c626, 0x604ed93c24d67ff3, 0x31b9c405f8540a20},
1413 {1, 0, 0, 0}},
1414 {{0xd36b4789a2582e7f, 0x0d1a10144ec39c28, 0x663c62c3edbad7a0, 0x4052bf4b6f461db9},
1415 {0x235a27c3188d25eb, 0xe724f33999bfcc5b, 0x862be6bd71d70cc8, 0xfecf4d5190b0fc61},
1416 {1, 0, 0, 0}},
1417 {{0x74346c10a1d4cfac, 0xafdf5cc08526a7a4, 0x123202a8f62bff7a, 0x1eddbae2c802e41a},
1418 {0x8fa0af2dd603f844, 0x36e06b7e4c701917, 0x0c45f45273db33a0, 0x43104d86560ebcfc},
1419 {1, 0, 0, 0}},
1420 {{0x9615b5110d1d78e5, 0x66b0de3225c4744b, 0x0a4a46fb6aaf363a, 0xb48e26b484f7a21c},
1421 {0x06ebb0f621a01b2d, 0xc004e4048b7b0f98, 0x64131bcdfed6f668, 0xfac015404d4d3dab},
1422 {1, 0, 0, 0}}},
1423 {{{0, 0, 0, 0},
1424 {0, 0, 0, 0},
1425 {0, 0, 0, 0}},
1426 {{0x3a5a9e22185a5943, 0x1ab919365c65dfb6, 0x21656b32262c71da, 0x7fe36b40af22af89},
1427 {0xd50d152c699ca101, 0x74b3d5867b8af212, 0x9f09f40407dca6f1, 0xe697d45825b63624},
1428 {1, 0, 0, 0}},
1429 {{0xa84aa9397512218e, 0xe9a521b074ca0141, 0x57880b3a18a2e902, 0x4a5b506612a677a6},
1430 {0x0beada7a4c4f3840, 0x626db15419e26d9d, 0xc42604fbe1627d40, 0xeb13461ceac089f1},
1431 {1, 0, 0, 0}},
1432 {{0xf9faed0927a43281, 0x5e52c4144103ecbc, 0xc342967aa815c857, 0x0781b8291c6a220a},
1433 {0x5a8343ceeac55f80, 0x88f80eeee54a05e3, 0x97b2a14f12916434, 0x690cde8df0151593},
1434 {1, 0, 0, 0}},
1435 {{0xaee9c75df7f82f2a, 0x9e4c35874afdf43a, 0xf5622df437371326, 0x8a535f566ec73617},
1436 {0xc5f9a0ac223094b7, 0xcde533864c8c7669, 0x37e02819085a92bf, 0x0455c08468b08bd7},
1437 {1, 0, 0, 0}},
1438 {{0x0c0a6e2c9477b5d9, 0xf9a4bf62876dc444, 0x5050a949b6cdc279, 0x06bada7ab77f8276},
1439 {0xc8b4aed1ea48dac9, 0xdebd8a4b7ea1070f, 0x427d49101366eb70, 0x5b476dfd0e6cb18a},
1440 {1, 0, 0, 0}},
1441 {{0x7c5c3e44278c340a, 0x4d54606812d66f3b, 0x29a751b1ae23c5d8, 0x3e29864e8a2ec908},
1442 {0x142d2a6626dbb850, 0xad1744c4765bd780, 0x1f150e68e322d1ed, 0x239b90ea3dc31e7e},
1443 {1, 0, 0, 0}},
1444 {{0x78c416527a53322a, 0x305dde6709776f8e, 0xdbcab759f8862ed4, 0x820f4dd949f72ff7},
1445 {0x6cc544a62b5debd4, 0x75be5d937b4e8cc4, 0x1b481b1b215c14d3, 0x140406ec783a05ec},
1446 {1, 0, 0, 0}},
1447 {{0x6a703f10e895df07, 0xfd75f3fa01876bd8, 0xeb5b06e70ce08ffe, 0x68f6b8542783dfee},
1448 {0x90c76f8a78712655, 0xcf5293d2f310bf7f, 0xfbc8044dfda45028, 0xcbe1feba92e40ce6},
1449 {1, 0, 0, 0}},
1450 {{0xe998ceea4396e4c1, 0xfc82ef0b6acea274, 0x230f729f2250e927, 0xd0b2f94d2f420109},
1451 {0x4305adddb38d4966, 0x10b838f8624c3b45, 0x7db2636658954e7a, 0x971459828b0719e5},
1452 {1, 0, 0, 0}},
1453 {{0x4bd6b72623369fc9, 0x57f2929e53d0b876, 0xc2d5cba4f2340687, 0x961610004a866aba},
1454 {0x49997bcd2e407a5e, 0x69ab197d92ddcb24, 0x2cf1f2438fe5131c, 0x7acb9fadcee75e44},
1455 {1, 0, 0, 0}},
1456 {{0x254e839423d2d4c0, 0xf57f0c917aea685b, 0xa60d880f6f75aaea, 0x24eb9acca333bf5b},
1457 {0xe3de4ccb1cda5dea, 0xfeef9341c51a6b4f, 0x743125f88bac4c4d, 0x69f891c5acd079cc},
1458 {1, 0, 0, 0}},
1459 {{0xeee44b35702476b5, 0x7ed031a0e45c2258, 0xb422d1e7bd6f8514, 0xe51f547c5972a107},
1460 {0xa25bcd6fc9cf343d, 0x8ca922ee097c184e, 0xa62f98b3a9fe9a06, 0x1c309a2b25bb1387},
1461 {1, 0, 0, 0}},
1462 {{0x9295dbeb1967c459, 0xb00148833472c98e, 0xc504977708011828, 0x20b87b8aa2c4e503},
1463 {0x3063175de057c277, 0x1bd539338fe582dd, 0x0d11adef5f69a044, 0xf5c6fa49919776be},
1464 {1, 0, 0, 0}},
1465 {{0x8c944e760fd59e11, 0x3876cba1102fad5f, 0xa454c3fad83faa56, 0x1ed7d1b9332010b9},
1466 {0xa1011a270024b889, 0x05e4d0dcac0cd344, 0x52b520f0eb6a2a24, 0x3a2b03f03217257a},
1467 {1, 0, 0, 0}},
1468 {{0xf20fc2afdf1d043d, 0xf330240db58d5a62, 0xfc7d229ca0058c3b, 0x15fee545c78dd9f6},
1469 {0x501e82885bc98cda, 0x41ef80e5d046ac04, 0x557d9f49461210fb, 0x4ab5b6b2b8753f81},
1470 {1, 0, 0, 0}}}};
1471
1472/* select_point selects the |idx|th point from a precomputation table and
1473 * copies it to out. */
1474static void select_point(const u64 idx, unsigned int size, const smallfelem pre_comp[16][3], smallfelem out[3])
1475 {
1476 unsigned i, j;
1477 u64 *outlimbs = &out[0][0];
1478 memset(outlimbs, 0, 3 * sizeof(smallfelem));
1479
1480 for (i = 0; i < size; i++)
1481 {
1482 const u64 *inlimbs = (u64*) &pre_comp[i][0][0];
1483 u64 mask = i ^ idx;
1484 mask |= mask >> 4;
1485 mask |= mask >> 2;
1486 mask |= mask >> 1;
1487 mask &= 1;
1488 mask--;
1489 for (j = 0; j < NLIMBS * 3; j++)
1490 outlimbs[j] |= inlimbs[j] & mask;
1491 }
1492 }
1493
1494/* get_bit returns the |i|th bit in |in| */
1495static char get_bit(const felem_bytearray in, int i)
1496 {
1497 if ((i < 0) || (i >= 256))
1498 return 0;
1499 return (in[i >> 3] >> (i & 7)) & 1;
1500 }
1501
1502/* Interleaved point multiplication using precomputed point multiples:
1503 * The small point multiples 0*P, 1*P, ..., 17*P are in pre_comp[],
1504 * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple
1505 * of the generator, using certain (large) precomputed multiples in g_pre_comp.
1506 * Output point (X, Y, Z) is stored in x_out, y_out, z_out */
1507static void batch_mul(felem x_out, felem y_out, felem z_out,
1508 const felem_bytearray scalars[], const unsigned num_points, const u8 *g_scalar,
1509 const int mixed, const smallfelem pre_comp[][17][3], const smallfelem g_pre_comp[2][16][3])
1510 {
1511 int i, skip;
1512 unsigned num, gen_mul = (g_scalar != NULL);
1513 felem nq[3], ftmp;
1514 smallfelem tmp[3];
1515 u64 bits;
1516 u8 sign, digit;
1517
1518 /* set nq to the point at infinity */
1519 memset(nq, 0, 3 * sizeof(felem));
1520
1521 /* Loop over all scalars msb-to-lsb, interleaving additions
1522 * of multiples of the generator (two in each of the last 32 rounds)
1523 * and additions of other points multiples (every 5th round).
1524 */
1525 skip = 1; /* save two point operations in the first round */
1526 for (i = (num_points ? 255 : 31); i >= 0; --i)
1527 {
1528 /* double */
1529 if (!skip)
1530 point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
1531
1532 /* add multiples of the generator */
1533 if (gen_mul && (i <= 31))
1534 {
1535 /* first, look 32 bits upwards */
1536 bits = get_bit(g_scalar, i + 224) << 3;
1537 bits |= get_bit(g_scalar, i + 160) << 2;
1538 bits |= get_bit(g_scalar, i + 96) << 1;
1539 bits |= get_bit(g_scalar, i + 32);
1540 /* select the point to add, in constant time */
1541 select_point(bits, 16, g_pre_comp[1], tmp);
1542
1543 if (!skip)
1544 {
1545 point_add(nq[0], nq[1], nq[2],
1546 nq[0], nq[1], nq[2],
1547 1 /* mixed */, tmp[0], tmp[1], tmp[2]);
1548 }
1549 else
1550 {
1551 smallfelem_expand(nq[0], tmp[0]);
1552 smallfelem_expand(nq[1], tmp[1]);
1553 smallfelem_expand(nq[2], tmp[2]);
1554 skip = 0;
1555 }
1556
1557 /* second, look at the current position */
1558 bits = get_bit(g_scalar, i + 192) << 3;
1559 bits |= get_bit(g_scalar, i + 128) << 2;
1560 bits |= get_bit(g_scalar, i + 64) << 1;
1561 bits |= get_bit(g_scalar, i);
1562 /* select the point to add, in constant time */
1563 select_point(bits, 16, g_pre_comp[0], tmp);
1564 point_add(nq[0], nq[1], nq[2],
1565 nq[0], nq[1], nq[2],
1566 1 /* mixed */, tmp[0], tmp[1], tmp[2]);
1567 }
1568
1569 /* do other additions every 5 doublings */
1570 if (num_points && (i % 5 == 0))
1571 {
1572 /* loop over all scalars */
1573 for (num = 0; num < num_points; ++num)
1574 {
1575 bits = get_bit(scalars[num], i + 4) << 5;
1576 bits |= get_bit(scalars[num], i + 3) << 4;
1577 bits |= get_bit(scalars[num], i + 2) << 3;
1578 bits |= get_bit(scalars[num], i + 1) << 2;
1579 bits |= get_bit(scalars[num], i) << 1;
1580 bits |= get_bit(scalars[num], i - 1);
1581 ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
1582
1583 /* select the point to add or subtract, in constant time */
1584 select_point(digit, 17, pre_comp[num], tmp);
1585 smallfelem_neg(ftmp, tmp[1]); /* (X, -Y, Z) is the negative point */
1586 copy_small_conditional(ftmp, tmp[1], (((limb) sign) - 1));
1587 felem_contract(tmp[1], ftmp);
1588
1589 if (!skip)
1590 {
1591 point_add(nq[0], nq[1], nq[2],
1592 nq[0], nq[1], nq[2],
1593 mixed, tmp[0], tmp[1], tmp[2]);
1594 }
1595 else
1596 {
1597 smallfelem_expand(nq[0], tmp[0]);
1598 smallfelem_expand(nq[1], tmp[1]);
1599 smallfelem_expand(nq[2], tmp[2]);
1600 skip = 0;
1601 }
1602 }
1603 }
1604 }
1605 felem_assign(x_out, nq[0]);
1606 felem_assign(y_out, nq[1]);
1607 felem_assign(z_out, nq[2]);
1608 }
1609
1610/* Precomputation for the group generator. */
1611typedef struct {
1612 smallfelem g_pre_comp[2][16][3];
1613 int references;
1614} NISTP256_PRE_COMP;
1615
1616const EC_METHOD *EC_GFp_nistp256_method(void)
1617 {
1618 static const EC_METHOD ret = {
1619 EC_FLAGS_DEFAULT_OCT,
1620 NID_X9_62_prime_field,
1621 ec_GFp_nistp256_group_init,
1622 ec_GFp_simple_group_finish,
1623 ec_GFp_simple_group_clear_finish,
1624 ec_GFp_nist_group_copy,
1625 ec_GFp_nistp256_group_set_curve,
1626 ec_GFp_simple_group_get_curve,
1627 ec_GFp_simple_group_get_degree,
1628 ec_GFp_simple_group_check_discriminant,
1629 ec_GFp_simple_point_init,
1630 ec_GFp_simple_point_finish,
1631 ec_GFp_simple_point_clear_finish,
1632 ec_GFp_simple_point_copy,
1633 ec_GFp_simple_point_set_to_infinity,
1634 ec_GFp_simple_set_Jprojective_coordinates_GFp,
1635 ec_GFp_simple_get_Jprojective_coordinates_GFp,
1636 ec_GFp_simple_point_set_affine_coordinates,
1637 ec_GFp_nistp256_point_get_affine_coordinates,
1638 0 /* point_set_compressed_coordinates */,
1639 0 /* point2oct */,
1640 0 /* oct2point */,
1641 ec_GFp_simple_add,
1642 ec_GFp_simple_dbl,
1643 ec_GFp_simple_invert,
1644 ec_GFp_simple_is_at_infinity,
1645 ec_GFp_simple_is_on_curve,
1646 ec_GFp_simple_cmp,
1647 ec_GFp_simple_make_affine,
1648 ec_GFp_simple_points_make_affine,
1649 ec_GFp_nistp256_points_mul,
1650 ec_GFp_nistp256_precompute_mult,
1651 ec_GFp_nistp256_have_precompute_mult,
1652 ec_GFp_nist_field_mul,
1653 ec_GFp_nist_field_sqr,
1654 0 /* field_div */,
1655 0 /* field_encode */,
1656 0 /* field_decode */,
1657 0 /* field_set_to_one */ };
1658
1659 return &ret;
1660 }
1661
1662/******************************************************************************/
1663/* FUNCTIONS TO MANAGE PRECOMPUTATION
1664 */
1665
1666static NISTP256_PRE_COMP *nistp256_pre_comp_new()
1667 {
1668 NISTP256_PRE_COMP *ret = NULL;
1669 ret = (NISTP256_PRE_COMP *) OPENSSL_malloc(sizeof *ret);
1670 if (!ret)
1671 {
1672 ECerr(EC_F_NISTP256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
1673 return ret;
1674 }
1675 memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp));
1676 ret->references = 1;
1677 return ret;
1678 }
1679
1680static void *nistp256_pre_comp_dup(void *src_)
1681 {
1682 NISTP256_PRE_COMP *src = src_;
1683
1684 /* no need to actually copy, these objects never change! */
1685 CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
1686
1687 return src_;
1688 }
1689
1690static void nistp256_pre_comp_free(void *pre_)
1691 {
1692 int i;
1693 NISTP256_PRE_COMP *pre = pre_;
1694
1695 if (!pre)
1696 return;
1697
1698 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1699 if (i > 0)
1700 return;
1701
1702 OPENSSL_free(pre);
1703 }
1704
1705static void nistp256_pre_comp_clear_free(void *pre_)
1706 {
1707 int i;
1708 NISTP256_PRE_COMP *pre = pre_;
1709
1710 if (!pre)
1711 return;
1712
1713 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1714 if (i > 0)
1715 return;
1716
1717 OPENSSL_cleanse(pre, sizeof *pre);
1718 OPENSSL_free(pre);
1719 }
1720
1721/******************************************************************************/
1722/* OPENSSL EC_METHOD FUNCTIONS
1723 */
1724
1725int ec_GFp_nistp256_group_init(EC_GROUP *group)
1726 {
1727 int ret;
1728 ret = ec_GFp_simple_group_init(group);
1729 group->a_is_minus3 = 1;
1730 return ret;
1731 }
1732
1733int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
1734 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1735 {
1736 int ret = 0;
1737 BN_CTX *new_ctx = NULL;
1738 BIGNUM *curve_p, *curve_a, *curve_b;
1739
1740 if (ctx == NULL)
1741 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1742 BN_CTX_start(ctx);
1743 if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
1744 ((curve_a = BN_CTX_get(ctx)) == NULL) ||
1745 ((curve_b = BN_CTX_get(ctx)) == NULL)) goto err;
1746 BN_bin2bn(nistp256_curve_params[0], sizeof(felem_bytearray), curve_p);
1747 BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a);
1748 BN_bin2bn(nistp256_curve_params[2], sizeof(felem_bytearray), curve_b);
1749 if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) ||
1750 (BN_cmp(curve_b, b)))
1751 {
1752 ECerr(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE,
1753 EC_R_WRONG_CURVE_PARAMETERS);
1754 goto err;
1755 }
1756 group->field_mod_func = BN_nist_mod_256;
1757 ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
1758err:
1759 BN_CTX_end(ctx);
1760 if (new_ctx != NULL)
1761 BN_CTX_free(new_ctx);
1762 return ret;
1763 }
1764
1765/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns
1766 * (X', Y') = (X/Z^2, Y/Z^3) */
1767int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
1768 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
1769 {
1770 felem z1, z2, x_in, y_in;
1771 smallfelem x_out, y_out;
1772 longfelem tmp;
1773
1774 if (EC_POINT_is_at_infinity(group, point))
1775 {
1776 ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
1777 EC_R_POINT_AT_INFINITY);
1778 return 0;
1779 }
1780 if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) ||
1781 (!BN_to_felem(z1, &point->Z))) return 0;
1782 felem_inv(z2, z1);
1783 felem_square(tmp, z2); felem_reduce(z1, tmp);
1784 felem_mul(tmp, x_in, z1); felem_reduce(x_in, tmp);
1785 felem_contract(x_out, x_in);
1786 if (x != NULL)
1787 {
1788 if (!smallfelem_to_BN(x, x_out)) {
1789 ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
1790 ERR_R_BN_LIB);
1791 return 0;
1792 }
1793 }
1794 felem_mul(tmp, z1, z2); felem_reduce(z1, tmp);
1795 felem_mul(tmp, y_in, z1); felem_reduce(y_in, tmp);
1796 felem_contract(y_out, y_in);
1797 if (y != NULL)
1798 {
1799 if (!smallfelem_to_BN(y, y_out))
1800 {
1801 ECerr(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES,
1802 ERR_R_BN_LIB);
1803 return 0;
1804 }
1805 }
1806 return 1;
1807 }
1808
1809static void make_points_affine(size_t num, smallfelem points[/* num */][3], smallfelem tmp_smallfelems[/* num+1 */])
1810 {
1811 /* Runs in constant time, unless an input is the point at infinity
1812 * (which normally shouldn't happen). */
1813 ec_GFp_nistp_points_make_affine_internal(
1814 num,
1815 points,
1816 sizeof(smallfelem),
1817 tmp_smallfelems,
1818 (void (*)(void *)) smallfelem_one,
1819 (int (*)(const void *)) smallfelem_is_zero_int,
1820 (void (*)(void *, const void *)) smallfelem_assign,
1821 (void (*)(void *, const void *)) smallfelem_square_contract,
1822 (void (*)(void *, const void *, const void *)) smallfelem_mul_contract,
1823 (void (*)(void *, const void *)) smallfelem_inv_contract,
1824 (void (*)(void *, const void *)) smallfelem_assign /* nothing to contract */);
1825 }
1826
1827/* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL values
1828 * Result is stored in r (r can equal one of the inputs). */
1829int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
1830 const BIGNUM *scalar, size_t num, const EC_POINT *points[],
1831 const BIGNUM *scalars[], BN_CTX *ctx)
1832 {
1833 int ret = 0;
1834 int j;
1835 int mixed = 0;
1836 BN_CTX *new_ctx = NULL;
1837 BIGNUM *x, *y, *z, *tmp_scalar;
1838 felem_bytearray g_secret;
1839 felem_bytearray *secrets = NULL;
1840 smallfelem (*pre_comp)[17][3] = NULL;
1841 smallfelem *tmp_smallfelems = NULL;
1842 felem_bytearray tmp;
1843 unsigned i, num_bytes;
1844 int have_pre_comp = 0;
1845 size_t num_points = num;
1846 smallfelem x_in, y_in, z_in;
1847 felem x_out, y_out, z_out;
1848 NISTP256_PRE_COMP *pre = NULL;
1849 const smallfelem (*g_pre_comp)[16][3] = NULL;
1850 EC_POINT *generator = NULL;
1851 const EC_POINT *p = NULL;
1852 const BIGNUM *p_scalar = NULL;
1853
1854 if (ctx == NULL)
1855 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1856 BN_CTX_start(ctx);
1857 if (((x = BN_CTX_get(ctx)) == NULL) ||
1858 ((y = BN_CTX_get(ctx)) == NULL) ||
1859 ((z = BN_CTX_get(ctx)) == NULL) ||
1860 ((tmp_scalar = BN_CTX_get(ctx)) == NULL))
1861 goto err;
1862
1863 if (scalar != NULL)
1864 {
1865 pre = EC_EX_DATA_get_data(group->extra_data,
1866 nistp256_pre_comp_dup, nistp256_pre_comp_free,
1867 nistp256_pre_comp_clear_free);
1868 if (pre)
1869 /* we have precomputation, try to use it */
1870 g_pre_comp = (const smallfelem (*)[16][3]) pre->g_pre_comp;
1871 else
1872 /* try to use the standard precomputation */
1873 g_pre_comp = &gmul[0];
1874 generator = EC_POINT_new(group);
1875 if (generator == NULL)
1876 goto err;
1877 /* get the generator from precomputation */
1878 if (!smallfelem_to_BN(x, g_pre_comp[0][1][0]) ||
1879 !smallfelem_to_BN(y, g_pre_comp[0][1][1]) ||
1880 !smallfelem_to_BN(z, g_pre_comp[0][1][2]))
1881 {
1882 ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
1883 goto err;
1884 }
1885 if (!EC_POINT_set_Jprojective_coordinates_GFp(group,
1886 generator, x, y, z, ctx))
1887 goto err;
1888 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
1889 /* precomputation matches generator */
1890 have_pre_comp = 1;
1891 else
1892 /* we don't have valid precomputation:
1893 * treat the generator as a random point */
1894 num_points++;
1895 }
1896 if (num_points > 0)
1897 {
1898 if (num_points >= 3)
1899 {
1900 /* unless we precompute multiples for just one or two points,
1901 * converting those into affine form is time well spent */
1902 mixed = 1;
1903 }
1904 secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
1905 pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(smallfelem));
1906 if (mixed)
1907 tmp_smallfelems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(smallfelem));
1908 if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_smallfelems == NULL)))
1909 {
1910 ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
1911 goto err;
1912 }
1913
1914 /* we treat NULL scalars as 0, and NULL points as points at infinity,
1915 * i.e., they contribute nothing to the linear combination */
1916 memset(secrets, 0, num_points * sizeof(felem_bytearray));
1917 memset(pre_comp, 0, num_points * 17 * 3 * sizeof(smallfelem));
1918 for (i = 0; i < num_points; ++i)
1919 {
1920 if (i == num)
1921 /* we didn't have a valid precomputation, so we pick
1922 * the generator */
1923 {
1924 p = EC_GROUP_get0_generator(group);
1925 p_scalar = scalar;
1926 }
1927 else
1928 /* the i^th point */
1929 {
1930 p = points[i];
1931 p_scalar = scalars[i];
1932 }
1933 if ((p_scalar != NULL) && (p != NULL))
1934 {
1935 /* reduce scalar to 0 <= scalar < 2^256 */
1936 if ((BN_num_bits(p_scalar) > 256) || (BN_is_negative(p_scalar)))
1937 {
1938 /* this is an unusual input, and we don't guarantee
1939 * constant-timeness */
1940 if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx))
1941 {
1942 ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
1943 goto err;
1944 }
1945 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1946 }
1947 else
1948 num_bytes = BN_bn2bin(p_scalar, tmp);
1949 flip_endian(secrets[i], tmp, num_bytes);
1950 /* precompute multiples */
1951 if ((!BN_to_felem(x_out, &p->X)) ||
1952 (!BN_to_felem(y_out, &p->Y)) ||
1953 (!BN_to_felem(z_out, &p->Z))) goto err;
1954 felem_shrink(pre_comp[i][1][0], x_out);
1955 felem_shrink(pre_comp[i][1][1], y_out);
1956 felem_shrink(pre_comp[i][1][2], z_out);
1957 for (j = 2; j <= 16; ++j)
1958 {
1959 if (j & 1)
1960 {
1961 point_add_small(
1962 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1963 pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2],
1964 pre_comp[i][j-1][0], pre_comp[i][j-1][1], pre_comp[i][j-1][2]);
1965 }
1966 else
1967 {
1968 point_double_small(
1969 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1970 pre_comp[i][j/2][0], pre_comp[i][j/2][1], pre_comp[i][j/2][2]);
1971 }
1972 }
1973 }
1974 }
1975 if (mixed)
1976 make_points_affine(num_points * 17, pre_comp[0], tmp_smallfelems);
1977 }
1978
1979 /* the scalar for the generator */
1980 if ((scalar != NULL) && (have_pre_comp))
1981 {
1982 memset(g_secret, 0, sizeof(g_secret));
1983 /* reduce scalar to 0 <= scalar < 2^256 */
1984 if ((BN_num_bits(scalar) > 256) || (BN_is_negative(scalar)))
1985 {
1986 /* this is an unusual input, and we don't guarantee
1987 * constant-timeness */
1988 if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx))
1989 {
1990 ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
1991 goto err;
1992 }
1993 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1994 }
1995 else
1996 num_bytes = BN_bn2bin(scalar, tmp);
1997 flip_endian(g_secret, tmp, num_bytes);
1998 /* do the multiplication with generator precomputation*/
1999 batch_mul(x_out, y_out, z_out,
2000 (const felem_bytearray (*)) secrets, num_points,
2001 g_secret,
2002 mixed, (const smallfelem (*)[17][3]) pre_comp,
2003 g_pre_comp);
2004 }
2005 else
2006 /* do the multiplication without generator precomputation */
2007 batch_mul(x_out, y_out, z_out,
2008 (const felem_bytearray (*)) secrets, num_points,
2009 NULL, mixed, (const smallfelem (*)[17][3]) pre_comp, NULL);
2010 /* reduce the output to its unique minimal representation */
2011 felem_contract(x_in, x_out);
2012 felem_contract(y_in, y_out);
2013 felem_contract(z_in, z_out);
2014 if ((!smallfelem_to_BN(x, x_in)) || (!smallfelem_to_BN(y, y_in)) ||
2015 (!smallfelem_to_BN(z, z_in)))
2016 {
2017 ECerr(EC_F_EC_GFP_NISTP256_POINTS_MUL, ERR_R_BN_LIB);
2018 goto err;
2019 }
2020 ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
2021
2022err:
2023 BN_CTX_end(ctx);
2024 if (generator != NULL)
2025 EC_POINT_free(generator);
2026 if (new_ctx != NULL)
2027 BN_CTX_free(new_ctx);
2028 if (secrets != NULL)
2029 OPENSSL_free(secrets);
2030 if (pre_comp != NULL)
2031 OPENSSL_free(pre_comp);
2032 if (tmp_smallfelems != NULL)
2033 OPENSSL_free(tmp_smallfelems);
2034 return ret;
2035 }
2036
2037int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
2038 {
2039 int ret = 0;
2040 NISTP256_PRE_COMP *pre = NULL;
2041 int i, j;
2042 BN_CTX *new_ctx = NULL;
2043 BIGNUM *x, *y;
2044 EC_POINT *generator = NULL;
2045 smallfelem tmp_smallfelems[32];
2046 felem x_tmp, y_tmp, z_tmp;
2047
2048 /* throw away old precomputation */
2049 EC_EX_DATA_free_data(&group->extra_data, nistp256_pre_comp_dup,
2050 nistp256_pre_comp_free, nistp256_pre_comp_clear_free);
2051 if (ctx == NULL)
2052 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
2053 BN_CTX_start(ctx);
2054 if (((x = BN_CTX_get(ctx)) == NULL) ||
2055 ((y = BN_CTX_get(ctx)) == NULL))
2056 goto err;
2057 /* get the generator */
2058 if (group->generator == NULL) goto err;
2059 generator = EC_POINT_new(group);
2060 if (generator == NULL)
2061 goto err;
2062 BN_bin2bn(nistp256_curve_params[3], sizeof (felem_bytearray), x);
2063 BN_bin2bn(nistp256_curve_params[4], sizeof (felem_bytearray), y);
2064 if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx))
2065 goto err;
2066 if ((pre = nistp256_pre_comp_new()) == NULL)
2067 goto err;
2068 /* if the generator is the standard one, use built-in precomputation */
2069 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
2070 {
2071 memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp));
2072 ret = 1;
2073 goto err;
2074 }
2075 if ((!BN_to_felem(x_tmp, &group->generator->X)) ||
2076 (!BN_to_felem(y_tmp, &group->generator->Y)) ||
2077 (!BN_to_felem(z_tmp, &group->generator->Z)))
2078 goto err;
2079 felem_shrink(pre->g_pre_comp[0][1][0], x_tmp);
2080 felem_shrink(pre->g_pre_comp[0][1][1], y_tmp);
2081 felem_shrink(pre->g_pre_comp[0][1][2], z_tmp);
2082 /* compute 2^64*G, 2^128*G, 2^192*G for the first table,
2083 * 2^32*G, 2^96*G, 2^160*G, 2^224*G for the second one
2084 */
2085 for (i = 1; i <= 8; i <<= 1)
2086 {
2087 point_double_small(
2088 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2],
2089 pre->g_pre_comp[0][i][0], pre->g_pre_comp[0][i][1], pre->g_pre_comp[0][i][2]);
2090 for (j = 0; j < 31; ++j)
2091 {
2092 point_double_small(
2093 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2],
2094 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]);
2095 }
2096 if (i == 8)
2097 break;
2098 point_double_small(
2099 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2],
2100 pre->g_pre_comp[1][i][0], pre->g_pre_comp[1][i][1], pre->g_pre_comp[1][i][2]);
2101 for (j = 0; j < 31; ++j)
2102 {
2103 point_double_small(
2104 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2],
2105 pre->g_pre_comp[0][2*i][0], pre->g_pre_comp[0][2*i][1], pre->g_pre_comp[0][2*i][2]);
2106 }
2107 }
2108 for (i = 0; i < 2; i++)
2109 {
2110 /* g_pre_comp[i][0] is the point at infinity */
2111 memset(pre->g_pre_comp[i][0], 0, sizeof(pre->g_pre_comp[i][0]));
2112 /* the remaining multiples */
2113 /* 2^64*G + 2^128*G resp. 2^96*G + 2^160*G */
2114 point_add_small(
2115 pre->g_pre_comp[i][6][0], pre->g_pre_comp[i][6][1], pre->g_pre_comp[i][6][2],
2116 pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2],
2117 pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]);
2118 /* 2^64*G + 2^192*G resp. 2^96*G + 2^224*G */
2119 point_add_small(
2120 pre->g_pre_comp[i][10][0], pre->g_pre_comp[i][10][1], pre->g_pre_comp[i][10][2],
2121 pre->g_pre_comp[i][8][0], pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
2122 pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]);
2123 /* 2^128*G + 2^192*G resp. 2^160*G + 2^224*G */
2124 point_add_small(
2125 pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2],
2126 pre->g_pre_comp[i][8][0], pre->g_pre_comp[i][8][1], pre->g_pre_comp[i][8][2],
2127 pre->g_pre_comp[i][4][0], pre->g_pre_comp[i][4][1], pre->g_pre_comp[i][4][2]);
2128 /* 2^64*G + 2^128*G + 2^192*G resp. 2^96*G + 2^160*G + 2^224*G */
2129 point_add_small(
2130 pre->g_pre_comp[i][14][0], pre->g_pre_comp[i][14][1], pre->g_pre_comp[i][14][2],
2131 pre->g_pre_comp[i][12][0], pre->g_pre_comp[i][12][1], pre->g_pre_comp[i][12][2],
2132 pre->g_pre_comp[i][2][0], pre->g_pre_comp[i][2][1], pre->g_pre_comp[i][2][2]);
2133 for (j = 1; j < 8; ++j)
2134 {
2135 /* odd multiples: add G resp. 2^32*G */
2136 point_add_small(
2137 pre->g_pre_comp[i][2*j+1][0], pre->g_pre_comp[i][2*j+1][1], pre->g_pre_comp[i][2*j+1][2],
2138 pre->g_pre_comp[i][2*j][0], pre->g_pre_comp[i][2*j][1], pre->g_pre_comp[i][2*j][2],
2139 pre->g_pre_comp[i][1][0], pre->g_pre_comp[i][1][1], pre->g_pre_comp[i][1][2]);
2140 }
2141 }
2142 make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_smallfelems);
2143
2144 if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp256_pre_comp_dup,
2145 nistp256_pre_comp_free, nistp256_pre_comp_clear_free))
2146 goto err;
2147 ret = 1;
2148 pre = NULL;
2149 err:
2150 BN_CTX_end(ctx);
2151 if (generator != NULL)
2152 EC_POINT_free(generator);
2153 if (new_ctx != NULL)
2154 BN_CTX_free(new_ctx);
2155 if (pre)
2156 nistp256_pre_comp_free(pre);
2157 return ret;
2158 }
2159
2160int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group)
2161 {
2162 if (EC_EX_DATA_get_data(group->extra_data, nistp256_pre_comp_dup,
2163 nistp256_pre_comp_free, nistp256_pre_comp_clear_free)
2164 != NULL)
2165 return 1;
2166 else
2167 return 0;
2168 }
2169#else
2170static void *dummy=&dummy;
2171#endif
diff --git a/src/lib/libcrypto/ec/ecp_nistp521.c b/src/lib/libcrypto/ec/ecp_nistp521.c
new file mode 100644
index 0000000000..178b655f7f
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_nistp521.c
@@ -0,0 +1,2025 @@
1/* crypto/ec/ecp_nistp521.c */
2/*
3 * Written by Adam Langley (Google) for the OpenSSL project
4 */
5/* Copyright 2011 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 *
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21/*
22 * A 64-bit implementation of the NIST P-521 elliptic curve point multiplication
23 *
24 * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c.
25 * Otherwise based on Emilia's P224 work, which was inspired by my curve25519
26 * work which got its smarts from Daniel J. Bernstein's work on the same.
27 */
28
29#include <openssl/opensslconf.h>
30#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
31
32#ifndef OPENSSL_SYS_VMS
33#include <stdint.h>
34#else
35#include <inttypes.h>
36#endif
37
38#include <string.h>
39#include <openssl/err.h>
40#include "ec_lcl.h"
41
42#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
43 /* even with gcc, the typedef won't work for 32-bit platforms */
44 typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit platforms */
45#else
46 #error "Need GCC 3.1 or later to define type uint128_t"
47#endif
48
49typedef uint8_t u8;
50typedef uint64_t u64;
51typedef int64_t s64;
52
53/* The underlying field.
54 *
55 * P521 operates over GF(2^521-1). We can serialise an element of this field
56 * into 66 bytes where the most significant byte contains only a single bit. We
57 * call this an felem_bytearray. */
58
59typedef u8 felem_bytearray[66];
60
61/* These are the parameters of P521, taken from FIPS 186-3, section D.1.2.5.
62 * These values are big-endian. */
63static const felem_bytearray nistp521_curve_params[5] =
64 {
65 {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* p */
66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
68 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
70 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
71 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
73 0xff, 0xff},
74 {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* a = -3 */
75 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
76 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
77 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
78 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
79 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
80 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
81 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
82 0xff, 0xfc},
83 {0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, /* b */
84 0x9a, 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85,
85 0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3,
86 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1,
87 0x09, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e,
88 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1,
89 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c,
90 0x34, 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50,
91 0x3f, 0x00},
92 {0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, /* x */
93 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95,
94 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f,
95 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d,
96 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7,
97 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
98 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a,
99 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5,
100 0xbd, 0x66},
101 {0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, /* y */
102 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d,
103 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
104 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e,
105 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4,
106 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
107 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72,
108 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1,
109 0x66, 0x50}
110 };
111
112/* The representation of field elements.
113 * ------------------------------------
114 *
115 * We represent field elements with nine values. These values are either 64 or
116 * 128 bits and the field element represented is:
117 * v[0]*2^0 + v[1]*2^58 + v[2]*2^116 + ... + v[8]*2^464 (mod p)
118 * Each of the nine values is called a 'limb'. Since the limbs are spaced only
119 * 58 bits apart, but are greater than 58 bits in length, the most significant
120 * bits of each limb overlap with the least significant bits of the next.
121 *
122 * A field element with 64-bit limbs is an 'felem'. One with 128-bit limbs is a
123 * 'largefelem' */
124
125#define NLIMBS 9
126
127typedef uint64_t limb;
128typedef limb felem[NLIMBS];
129typedef uint128_t largefelem[NLIMBS];
130
131static const limb bottom57bits = 0x1ffffffffffffff;
132static const limb bottom58bits = 0x3ffffffffffffff;
133
134/* bin66_to_felem takes a little-endian byte array and converts it into felem
135 * form. This assumes that the CPU is little-endian. */
136static void bin66_to_felem(felem out, const u8 in[66])
137 {
138 out[0] = (*((limb*) &in[0])) & bottom58bits;
139 out[1] = (*((limb*) &in[7]) >> 2) & bottom58bits;
140 out[2] = (*((limb*) &in[14]) >> 4) & bottom58bits;
141 out[3] = (*((limb*) &in[21]) >> 6) & bottom58bits;
142 out[4] = (*((limb*) &in[29])) & bottom58bits;
143 out[5] = (*((limb*) &in[36]) >> 2) & bottom58bits;
144 out[6] = (*((limb*) &in[43]) >> 4) & bottom58bits;
145 out[7] = (*((limb*) &in[50]) >> 6) & bottom58bits;
146 out[8] = (*((limb*) &in[58])) & bottom57bits;
147 }
148
149/* felem_to_bin66 takes an felem and serialises into a little endian, 66 byte
150 * array. This assumes that the CPU is little-endian. */
151static void felem_to_bin66(u8 out[66], const felem in)
152 {
153 memset(out, 0, 66);
154 (*((limb*) &out[0])) = in[0];
155 (*((limb*) &out[7])) |= in[1] << 2;
156 (*((limb*) &out[14])) |= in[2] << 4;
157 (*((limb*) &out[21])) |= in[3] << 6;
158 (*((limb*) &out[29])) = in[4];
159 (*((limb*) &out[36])) |= in[5] << 2;
160 (*((limb*) &out[43])) |= in[6] << 4;
161 (*((limb*) &out[50])) |= in[7] << 6;
162 (*((limb*) &out[58])) = in[8];
163 }
164
165/* To preserve endianness when using BN_bn2bin and BN_bin2bn */
166static void flip_endian(u8 *out, const u8 *in, unsigned len)
167 {
168 unsigned i;
169 for (i = 0; i < len; ++i)
170 out[i] = in[len-1-i];
171 }
172
173/* BN_to_felem converts an OpenSSL BIGNUM into an felem */
174static int BN_to_felem(felem out, const BIGNUM *bn)
175 {
176 felem_bytearray b_in;
177 felem_bytearray b_out;
178 unsigned num_bytes;
179
180 /* BN_bn2bin eats leading zeroes */
181 memset(b_out, 0, sizeof b_out);
182 num_bytes = BN_num_bytes(bn);
183 if (num_bytes > sizeof b_out)
184 {
185 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
186 return 0;
187 }
188 if (BN_is_negative(bn))
189 {
190 ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
191 return 0;
192 }
193 num_bytes = BN_bn2bin(bn, b_in);
194 flip_endian(b_out, b_in, num_bytes);
195 bin66_to_felem(out, b_out);
196 return 1;
197 }
198
199/* felem_to_BN converts an felem into an OpenSSL BIGNUM */
200static BIGNUM *felem_to_BN(BIGNUM *out, const felem in)
201 {
202 felem_bytearray b_in, b_out;
203 felem_to_bin66(b_in, in);
204 flip_endian(b_out, b_in, sizeof b_out);
205 return BN_bin2bn(b_out, sizeof b_out, out);
206 }
207
208
209/* Field operations
210 * ---------------- */
211
212static void felem_one(felem out)
213 {
214 out[0] = 1;
215 out[1] = 0;
216 out[2] = 0;
217 out[3] = 0;
218 out[4] = 0;
219 out[5] = 0;
220 out[6] = 0;
221 out[7] = 0;
222 out[8] = 0;
223 }
224
225static void felem_assign(felem out, const felem in)
226 {
227 out[0] = in[0];
228 out[1] = in[1];
229 out[2] = in[2];
230 out[3] = in[3];
231 out[4] = in[4];
232 out[5] = in[5];
233 out[6] = in[6];
234 out[7] = in[7];
235 out[8] = in[8];
236 }
237
238/* felem_sum64 sets out = out + in. */
239static void felem_sum64(felem out, const felem in)
240 {
241 out[0] += in[0];
242 out[1] += in[1];
243 out[2] += in[2];
244 out[3] += in[3];
245 out[4] += in[4];
246 out[5] += in[5];
247 out[6] += in[6];
248 out[7] += in[7];
249 out[8] += in[8];
250 }
251
252/* felem_scalar sets out = in * scalar */
253static void felem_scalar(felem out, const felem in, limb scalar)
254 {
255 out[0] = in[0] * scalar;
256 out[1] = in[1] * scalar;
257 out[2] = in[2] * scalar;
258 out[3] = in[3] * scalar;
259 out[4] = in[4] * scalar;
260 out[5] = in[5] * scalar;
261 out[6] = in[6] * scalar;
262 out[7] = in[7] * scalar;
263 out[8] = in[8] * scalar;
264 }
265
266/* felem_scalar64 sets out = out * scalar */
267static void felem_scalar64(felem out, limb scalar)
268 {
269 out[0] *= scalar;
270 out[1] *= scalar;
271 out[2] *= scalar;
272 out[3] *= scalar;
273 out[4] *= scalar;
274 out[5] *= scalar;
275 out[6] *= scalar;
276 out[7] *= scalar;
277 out[8] *= scalar;
278 }
279
280/* felem_scalar128 sets out = out * scalar */
281static void felem_scalar128(largefelem out, limb scalar)
282 {
283 out[0] *= scalar;
284 out[1] *= scalar;
285 out[2] *= scalar;
286 out[3] *= scalar;
287 out[4] *= scalar;
288 out[5] *= scalar;
289 out[6] *= scalar;
290 out[7] *= scalar;
291 out[8] *= scalar;
292 }
293
294/* felem_neg sets |out| to |-in|
295 * On entry:
296 * in[i] < 2^59 + 2^14
297 * On exit:
298 * out[i] < 2^62
299 */
300static void felem_neg(felem out, const felem in)
301 {
302 /* In order to prevent underflow, we subtract from 0 mod p. */
303 static const limb two62m3 = (((limb)1) << 62) - (((limb)1) << 5);
304 static const limb two62m2 = (((limb)1) << 62) - (((limb)1) << 4);
305
306 out[0] = two62m3 - in[0];
307 out[1] = two62m2 - in[1];
308 out[2] = two62m2 - in[2];
309 out[3] = two62m2 - in[3];
310 out[4] = two62m2 - in[4];
311 out[5] = two62m2 - in[5];
312 out[6] = two62m2 - in[6];
313 out[7] = two62m2 - in[7];
314 out[8] = two62m2 - in[8];
315 }
316
317/* felem_diff64 subtracts |in| from |out|
318 * On entry:
319 * in[i] < 2^59 + 2^14
320 * On exit:
321 * out[i] < out[i] + 2^62
322 */
323static void felem_diff64(felem out, const felem in)
324 {
325 /* In order to prevent underflow, we add 0 mod p before subtracting. */
326 static const limb two62m3 = (((limb)1) << 62) - (((limb)1) << 5);
327 static const limb two62m2 = (((limb)1) << 62) - (((limb)1) << 4);
328
329 out[0] += two62m3 - in[0];
330 out[1] += two62m2 - in[1];
331 out[2] += two62m2 - in[2];
332 out[3] += two62m2 - in[3];
333 out[4] += two62m2 - in[4];
334 out[5] += two62m2 - in[5];
335 out[6] += two62m2 - in[6];
336 out[7] += two62m2 - in[7];
337 out[8] += two62m2 - in[8];
338 }
339
340/* felem_diff_128_64 subtracts |in| from |out|
341 * On entry:
342 * in[i] < 2^62 + 2^17
343 * On exit:
344 * out[i] < out[i] + 2^63
345 */
346static void felem_diff_128_64(largefelem out, const felem in)
347 {
348 /* In order to prevent underflow, we add 0 mod p before subtracting. */
349 static const limb two63m6 = (((limb)1) << 62) - (((limb)1) << 5);
350 static const limb two63m5 = (((limb)1) << 62) - (((limb)1) << 4);
351
352 out[0] += two63m6 - in[0];
353 out[1] += two63m5 - in[1];
354 out[2] += two63m5 - in[2];
355 out[3] += two63m5 - in[3];
356 out[4] += two63m5 - in[4];
357 out[5] += two63m5 - in[5];
358 out[6] += two63m5 - in[6];
359 out[7] += two63m5 - in[7];
360 out[8] += two63m5 - in[8];
361 }
362
363/* felem_diff_128_64 subtracts |in| from |out|
364 * On entry:
365 * in[i] < 2^126
366 * On exit:
367 * out[i] < out[i] + 2^127 - 2^69
368 */
369static void felem_diff128(largefelem out, const largefelem in)
370 {
371 /* In order to prevent underflow, we add 0 mod p before subtracting. */
372 static const uint128_t two127m70 = (((uint128_t)1) << 127) - (((uint128_t)1) << 70);
373 static const uint128_t two127m69 = (((uint128_t)1) << 127) - (((uint128_t)1) << 69);
374
375 out[0] += (two127m70 - in[0]);
376 out[1] += (two127m69 - in[1]);
377 out[2] += (two127m69 - in[2]);
378 out[3] += (two127m69 - in[3]);
379 out[4] += (two127m69 - in[4]);
380 out[5] += (two127m69 - in[5]);
381 out[6] += (two127m69 - in[6]);
382 out[7] += (two127m69 - in[7]);
383 out[8] += (two127m69 - in[8]);
384 }
385
386/* felem_square sets |out| = |in|^2
387 * On entry:
388 * in[i] < 2^62
389 * On exit:
390 * out[i] < 17 * max(in[i]) * max(in[i])
391 */
392static void felem_square(largefelem out, const felem in)
393 {
394 felem inx2, inx4;
395 felem_scalar(inx2, in, 2);
396 felem_scalar(inx4, in, 4);
397
398 /* We have many cases were we want to do
399 * in[x] * in[y] +
400 * in[y] * in[x]
401 * This is obviously just
402 * 2 * in[x] * in[y]
403 * However, rather than do the doubling on the 128 bit result, we
404 * double one of the inputs to the multiplication by reading from
405 * |inx2| */
406
407 out[0] = ((uint128_t) in[0]) * in[0];
408 out[1] = ((uint128_t) in[0]) * inx2[1];
409 out[2] = ((uint128_t) in[0]) * inx2[2] +
410 ((uint128_t) in[1]) * in[1];
411 out[3] = ((uint128_t) in[0]) * inx2[3] +
412 ((uint128_t) in[1]) * inx2[2];
413 out[4] = ((uint128_t) in[0]) * inx2[4] +
414 ((uint128_t) in[1]) * inx2[3] +
415 ((uint128_t) in[2]) * in[2];
416 out[5] = ((uint128_t) in[0]) * inx2[5] +
417 ((uint128_t) in[1]) * inx2[4] +
418 ((uint128_t) in[2]) * inx2[3];
419 out[6] = ((uint128_t) in[0]) * inx2[6] +
420 ((uint128_t) in[1]) * inx2[5] +
421 ((uint128_t) in[2]) * inx2[4] +
422 ((uint128_t) in[3]) * in[3];
423 out[7] = ((uint128_t) in[0]) * inx2[7] +
424 ((uint128_t) in[1]) * inx2[6] +
425 ((uint128_t) in[2]) * inx2[5] +
426 ((uint128_t) in[3]) * inx2[4];
427 out[8] = ((uint128_t) in[0]) * inx2[8] +
428 ((uint128_t) in[1]) * inx2[7] +
429 ((uint128_t) in[2]) * inx2[6] +
430 ((uint128_t) in[3]) * inx2[5] +
431 ((uint128_t) in[4]) * in[4];
432
433 /* The remaining limbs fall above 2^521, with the first falling at
434 * 2^522. They correspond to locations one bit up from the limbs
435 * produced above so we would have to multiply by two to align them.
436 * Again, rather than operate on the 128-bit result, we double one of
437 * the inputs to the multiplication. If we want to double for both this
438 * reason, and the reason above, then we end up multiplying by four. */
439
440 /* 9 */
441 out[0] += ((uint128_t) in[1]) * inx4[8] +
442 ((uint128_t) in[2]) * inx4[7] +
443 ((uint128_t) in[3]) * inx4[6] +
444 ((uint128_t) in[4]) * inx4[5];
445
446 /* 10 */
447 out[1] += ((uint128_t) in[2]) * inx4[8] +
448 ((uint128_t) in[3]) * inx4[7] +
449 ((uint128_t) in[4]) * inx4[6] +
450 ((uint128_t) in[5]) * inx2[5];
451
452 /* 11 */
453 out[2] += ((uint128_t) in[3]) * inx4[8] +
454 ((uint128_t) in[4]) * inx4[7] +
455 ((uint128_t) in[5]) * inx4[6];
456
457 /* 12 */
458 out[3] += ((uint128_t) in[4]) * inx4[8] +
459 ((uint128_t) in[5]) * inx4[7] +
460 ((uint128_t) in[6]) * inx2[6];
461
462 /* 13 */
463 out[4] += ((uint128_t) in[5]) * inx4[8] +
464 ((uint128_t) in[6]) * inx4[7];
465
466 /* 14 */
467 out[5] += ((uint128_t) in[6]) * inx4[8] +
468 ((uint128_t) in[7]) * inx2[7];
469
470 /* 15 */
471 out[6] += ((uint128_t) in[7]) * inx4[8];
472
473 /* 16 */
474 out[7] += ((uint128_t) in[8]) * inx2[8];
475 }
476
477/* felem_mul sets |out| = |in1| * |in2|
478 * On entry:
479 * in1[i] < 2^64
480 * in2[i] < 2^63
481 * On exit:
482 * out[i] < 17 * max(in1[i]) * max(in2[i])
483 */
484static void felem_mul(largefelem out, const felem in1, const felem in2)
485 {
486 felem in2x2;
487 felem_scalar(in2x2, in2, 2);
488
489 out[0] = ((uint128_t) in1[0]) * in2[0];
490
491 out[1] = ((uint128_t) in1[0]) * in2[1] +
492 ((uint128_t) in1[1]) * in2[0];
493
494 out[2] = ((uint128_t) in1[0]) * in2[2] +
495 ((uint128_t) in1[1]) * in2[1] +
496 ((uint128_t) in1[2]) * in2[0];
497
498 out[3] = ((uint128_t) in1[0]) * in2[3] +
499 ((uint128_t) in1[1]) * in2[2] +
500 ((uint128_t) in1[2]) * in2[1] +
501 ((uint128_t) in1[3]) * in2[0];
502
503 out[4] = ((uint128_t) in1[0]) * in2[4] +
504 ((uint128_t) in1[1]) * in2[3] +
505 ((uint128_t) in1[2]) * in2[2] +
506 ((uint128_t) in1[3]) * in2[1] +
507 ((uint128_t) in1[4]) * in2[0];
508
509 out[5] = ((uint128_t) in1[0]) * in2[5] +
510 ((uint128_t) in1[1]) * in2[4] +
511 ((uint128_t) in1[2]) * in2[3] +
512 ((uint128_t) in1[3]) * in2[2] +
513 ((uint128_t) in1[4]) * in2[1] +
514 ((uint128_t) in1[5]) * in2[0];
515
516 out[6] = ((uint128_t) in1[0]) * in2[6] +
517 ((uint128_t) in1[1]) * in2[5] +
518 ((uint128_t) in1[2]) * in2[4] +
519 ((uint128_t) in1[3]) * in2[3] +
520 ((uint128_t) in1[4]) * in2[2] +
521 ((uint128_t) in1[5]) * in2[1] +
522 ((uint128_t) in1[6]) * in2[0];
523
524 out[7] = ((uint128_t) in1[0]) * in2[7] +
525 ((uint128_t) in1[1]) * in2[6] +
526 ((uint128_t) in1[2]) * in2[5] +
527 ((uint128_t) in1[3]) * in2[4] +
528 ((uint128_t) in1[4]) * in2[3] +
529 ((uint128_t) in1[5]) * in2[2] +
530 ((uint128_t) in1[6]) * in2[1] +
531 ((uint128_t) in1[7]) * in2[0];
532
533 out[8] = ((uint128_t) in1[0]) * in2[8] +
534 ((uint128_t) in1[1]) * in2[7] +
535 ((uint128_t) in1[2]) * in2[6] +
536 ((uint128_t) in1[3]) * in2[5] +
537 ((uint128_t) in1[4]) * in2[4] +
538 ((uint128_t) in1[5]) * in2[3] +
539 ((uint128_t) in1[6]) * in2[2] +
540 ((uint128_t) in1[7]) * in2[1] +
541 ((uint128_t) in1[8]) * in2[0];
542
543 /* See comment in felem_square about the use of in2x2 here */
544
545 out[0] += ((uint128_t) in1[1]) * in2x2[8] +
546 ((uint128_t) in1[2]) * in2x2[7] +
547 ((uint128_t) in1[3]) * in2x2[6] +
548 ((uint128_t) in1[4]) * in2x2[5] +
549 ((uint128_t) in1[5]) * in2x2[4] +
550 ((uint128_t) in1[6]) * in2x2[3] +
551 ((uint128_t) in1[7]) * in2x2[2] +
552 ((uint128_t) in1[8]) * in2x2[1];
553
554 out[1] += ((uint128_t) in1[2]) * in2x2[8] +
555 ((uint128_t) in1[3]) * in2x2[7] +
556 ((uint128_t) in1[4]) * in2x2[6] +
557 ((uint128_t) in1[5]) * in2x2[5] +
558 ((uint128_t) in1[6]) * in2x2[4] +
559 ((uint128_t) in1[7]) * in2x2[3] +
560 ((uint128_t) in1[8]) * in2x2[2];
561
562 out[2] += ((uint128_t) in1[3]) * in2x2[8] +
563 ((uint128_t) in1[4]) * in2x2[7] +
564 ((uint128_t) in1[5]) * in2x2[6] +
565 ((uint128_t) in1[6]) * in2x2[5] +
566 ((uint128_t) in1[7]) * in2x2[4] +
567 ((uint128_t) in1[8]) * in2x2[3];
568
569 out[3] += ((uint128_t) in1[4]) * in2x2[8] +
570 ((uint128_t) in1[5]) * in2x2[7] +
571 ((uint128_t) in1[6]) * in2x2[6] +
572 ((uint128_t) in1[7]) * in2x2[5] +
573 ((uint128_t) in1[8]) * in2x2[4];
574
575 out[4] += ((uint128_t) in1[5]) * in2x2[8] +
576 ((uint128_t) in1[6]) * in2x2[7] +
577 ((uint128_t) in1[7]) * in2x2[6] +
578 ((uint128_t) in1[8]) * in2x2[5];
579
580 out[5] += ((uint128_t) in1[6]) * in2x2[8] +
581 ((uint128_t) in1[7]) * in2x2[7] +
582 ((uint128_t) in1[8]) * in2x2[6];
583
584 out[6] += ((uint128_t) in1[7]) * in2x2[8] +
585 ((uint128_t) in1[8]) * in2x2[7];
586
587 out[7] += ((uint128_t) in1[8]) * in2x2[8];
588 }
589
590static const limb bottom52bits = 0xfffffffffffff;
591
592/* felem_reduce converts a largefelem to an felem.
593 * On entry:
594 * in[i] < 2^128
595 * On exit:
596 * out[i] < 2^59 + 2^14
597 */
598static void felem_reduce(felem out, const largefelem in)
599 {
600 u64 overflow1, overflow2;
601
602 out[0] = ((limb) in[0]) & bottom58bits;
603 out[1] = ((limb) in[1]) & bottom58bits;
604 out[2] = ((limb) in[2]) & bottom58bits;
605 out[3] = ((limb) in[3]) & bottom58bits;
606 out[4] = ((limb) in[4]) & bottom58bits;
607 out[5] = ((limb) in[5]) & bottom58bits;
608 out[6] = ((limb) in[6]) & bottom58bits;
609 out[7] = ((limb) in[7]) & bottom58bits;
610 out[8] = ((limb) in[8]) & bottom58bits;
611
612 /* out[i] < 2^58 */
613
614 out[1] += ((limb) in[0]) >> 58;
615 out[1] += (((limb) (in[0] >> 64)) & bottom52bits) << 6;
616 /* out[1] < 2^58 + 2^6 + 2^58
617 * = 2^59 + 2^6 */
618 out[2] += ((limb) (in[0] >> 64)) >> 52;
619
620 out[2] += ((limb) in[1]) >> 58;
621 out[2] += (((limb) (in[1] >> 64)) & bottom52bits) << 6;
622 out[3] += ((limb) (in[1] >> 64)) >> 52;
623
624 out[3] += ((limb) in[2]) >> 58;
625 out[3] += (((limb) (in[2] >> 64)) & bottom52bits) << 6;
626 out[4] += ((limb) (in[2] >> 64)) >> 52;
627
628 out[4] += ((limb) in[3]) >> 58;
629 out[4] += (((limb) (in[3] >> 64)) & bottom52bits) << 6;
630 out[5] += ((limb) (in[3] >> 64)) >> 52;
631
632 out[5] += ((limb) in[4]) >> 58;
633 out[5] += (((limb) (in[4] >> 64)) & bottom52bits) << 6;
634 out[6] += ((limb) (in[4] >> 64)) >> 52;
635
636 out[6] += ((limb) in[5]) >> 58;
637 out[6] += (((limb) (in[5] >> 64)) & bottom52bits) << 6;
638 out[7] += ((limb) (in[5] >> 64)) >> 52;
639
640 out[7] += ((limb) in[6]) >> 58;
641 out[7] += (((limb) (in[6] >> 64)) & bottom52bits) << 6;
642 out[8] += ((limb) (in[6] >> 64)) >> 52;
643
644 out[8] += ((limb) in[7]) >> 58;
645 out[8] += (((limb) (in[7] >> 64)) & bottom52bits) << 6;
646 /* out[x > 1] < 2^58 + 2^6 + 2^58 + 2^12
647 * < 2^59 + 2^13 */
648 overflow1 = ((limb) (in[7] >> 64)) >> 52;
649
650 overflow1 += ((limb) in[8]) >> 58;
651 overflow1 += (((limb) (in[8] >> 64)) & bottom52bits) << 6;
652 overflow2 = ((limb) (in[8] >> 64)) >> 52;
653
654 overflow1 <<= 1; /* overflow1 < 2^13 + 2^7 + 2^59 */
655 overflow2 <<= 1; /* overflow2 < 2^13 */
656
657 out[0] += overflow1; /* out[0] < 2^60 */
658 out[1] += overflow2; /* out[1] < 2^59 + 2^6 + 2^13 */
659
660 out[1] += out[0] >> 58; out[0] &= bottom58bits;
661 /* out[0] < 2^58
662 * out[1] < 2^59 + 2^6 + 2^13 + 2^2
663 * < 2^59 + 2^14 */
664 }
665
666static void felem_square_reduce(felem out, const felem in)
667 {
668 largefelem tmp;
669 felem_square(tmp, in);
670 felem_reduce(out, tmp);
671 }
672
673static void felem_mul_reduce(felem out, const felem in1, const felem in2)
674 {
675 largefelem tmp;
676 felem_mul(tmp, in1, in2);
677 felem_reduce(out, tmp);
678 }
679
680/* felem_inv calculates |out| = |in|^{-1}
681 *
682 * Based on Fermat's Little Theorem:
683 * a^p = a (mod p)
684 * a^{p-1} = 1 (mod p)
685 * a^{p-2} = a^{-1} (mod p)
686 */
687static void felem_inv(felem out, const felem in)
688 {
689 felem ftmp, ftmp2, ftmp3, ftmp4;
690 largefelem tmp;
691 unsigned i;
692
693 felem_square(tmp, in); felem_reduce(ftmp, tmp); /* 2^1 */
694 felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */
695 felem_assign(ftmp2, ftmp);
696 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */
697 felem_mul(tmp, in, ftmp); felem_reduce(ftmp, tmp); /* 2^3 - 2^0 */
698 felem_square(tmp, ftmp); felem_reduce(ftmp, tmp); /* 2^4 - 2^1 */
699
700 felem_square(tmp, ftmp2); felem_reduce(ftmp3, tmp); /* 2^3 - 2^1 */
701 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^4 - 2^2 */
702 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^4 - 2^0 */
703
704 felem_assign(ftmp2, ftmp3);
705 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^5 - 2^1 */
706 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^6 - 2^2 */
707 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^7 - 2^3 */
708 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^8 - 2^4 */
709 felem_assign(ftmp4, ftmp3);
710 felem_mul(tmp, ftmp3, ftmp); felem_reduce(ftmp4, tmp); /* 2^8 - 2^1 */
711 felem_square(tmp, ftmp4); felem_reduce(ftmp4, tmp); /* 2^9 - 2^2 */
712 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^8 - 2^0 */
713 felem_assign(ftmp2, ftmp3);
714
715 for (i = 0; i < 8; i++)
716 {
717 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^16 - 2^8 */
718 }
719 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^16 - 2^0 */
720 felem_assign(ftmp2, ftmp3);
721
722 for (i = 0; i < 16; i++)
723 {
724 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^32 - 2^16 */
725 }
726 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^32 - 2^0 */
727 felem_assign(ftmp2, ftmp3);
728
729 for (i = 0; i < 32; i++)
730 {
731 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^64 - 2^32 */
732 }
733 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^64 - 2^0 */
734 felem_assign(ftmp2, ftmp3);
735
736 for (i = 0; i < 64; i++)
737 {
738 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^128 - 2^64 */
739 }
740 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^128 - 2^0 */
741 felem_assign(ftmp2, ftmp3);
742
743 for (i = 0; i < 128; i++)
744 {
745 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^256 - 2^128 */
746 }
747 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^256 - 2^0 */
748 felem_assign(ftmp2, ftmp3);
749
750 for (i = 0; i < 256; i++)
751 {
752 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^512 - 2^256 */
753 }
754 felem_mul(tmp, ftmp3, ftmp2); felem_reduce(ftmp3, tmp); /* 2^512 - 2^0 */
755
756 for (i = 0; i < 9; i++)
757 {
758 felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^521 - 2^9 */
759 }
760 felem_mul(tmp, ftmp3, ftmp4); felem_reduce(ftmp3, tmp); /* 2^512 - 2^2 */
761 felem_mul(tmp, ftmp3, in); felem_reduce(out, tmp); /* 2^512 - 3 */
762}
763
764/* This is 2^521-1, expressed as an felem */
765static const felem kPrime =
766 {
767 0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff,
768 0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff,
769 0x03ffffffffffffff, 0x03ffffffffffffff, 0x01ffffffffffffff
770 };
771
772/* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0
773 * otherwise.
774 * On entry:
775 * in[i] < 2^59 + 2^14
776 */
777static limb felem_is_zero(const felem in)
778 {
779 felem ftmp;
780 limb is_zero, is_p;
781 felem_assign(ftmp, in);
782
783 ftmp[0] += ftmp[8] >> 57; ftmp[8] &= bottom57bits;
784 /* ftmp[8] < 2^57 */
785 ftmp[1] += ftmp[0] >> 58; ftmp[0] &= bottom58bits;
786 ftmp[2] += ftmp[1] >> 58; ftmp[1] &= bottom58bits;
787 ftmp[3] += ftmp[2] >> 58; ftmp[2] &= bottom58bits;
788 ftmp[4] += ftmp[3] >> 58; ftmp[3] &= bottom58bits;
789 ftmp[5] += ftmp[4] >> 58; ftmp[4] &= bottom58bits;
790 ftmp[6] += ftmp[5] >> 58; ftmp[5] &= bottom58bits;
791 ftmp[7] += ftmp[6] >> 58; ftmp[6] &= bottom58bits;
792 ftmp[8] += ftmp[7] >> 58; ftmp[7] &= bottom58bits;
793 /* ftmp[8] < 2^57 + 4 */
794
795 /* The ninth limb of 2*(2^521-1) is 0x03ffffffffffffff, which is
796 * greater than our bound for ftmp[8]. Therefore we only have to check
797 * if the zero is zero or 2^521-1. */
798
799 is_zero = 0;
800 is_zero |= ftmp[0];
801 is_zero |= ftmp[1];
802 is_zero |= ftmp[2];
803 is_zero |= ftmp[3];
804 is_zero |= ftmp[4];
805 is_zero |= ftmp[5];
806 is_zero |= ftmp[6];
807 is_zero |= ftmp[7];
808 is_zero |= ftmp[8];
809
810 is_zero--;
811 /* We know that ftmp[i] < 2^63, therefore the only way that the top bit
812 * can be set is if is_zero was 0 before the decrement. */
813 is_zero = ((s64) is_zero) >> 63;
814
815 is_p = ftmp[0] ^ kPrime[0];
816 is_p |= ftmp[1] ^ kPrime[1];
817 is_p |= ftmp[2] ^ kPrime[2];
818 is_p |= ftmp[3] ^ kPrime[3];
819 is_p |= ftmp[4] ^ kPrime[4];
820 is_p |= ftmp[5] ^ kPrime[5];
821 is_p |= ftmp[6] ^ kPrime[6];
822 is_p |= ftmp[7] ^ kPrime[7];
823 is_p |= ftmp[8] ^ kPrime[8];
824
825 is_p--;
826 is_p = ((s64) is_p) >> 63;
827
828 is_zero |= is_p;
829 return is_zero;
830 }
831
832static int felem_is_zero_int(const felem in)
833 {
834 return (int) (felem_is_zero(in) & ((limb)1));
835 }
836
837/* felem_contract converts |in| to its unique, minimal representation.
838 * On entry:
839 * in[i] < 2^59 + 2^14
840 */
841static void felem_contract(felem out, const felem in)
842 {
843 limb is_p, is_greater, sign;
844 static const limb two58 = ((limb)1) << 58;
845
846 felem_assign(out, in);
847
848 out[0] += out[8] >> 57; out[8] &= bottom57bits;
849 /* out[8] < 2^57 */
850 out[1] += out[0] >> 58; out[0] &= bottom58bits;
851 out[2] += out[1] >> 58; out[1] &= bottom58bits;
852 out[3] += out[2] >> 58; out[2] &= bottom58bits;
853 out[4] += out[3] >> 58; out[3] &= bottom58bits;
854 out[5] += out[4] >> 58; out[4] &= bottom58bits;
855 out[6] += out[5] >> 58; out[5] &= bottom58bits;
856 out[7] += out[6] >> 58; out[6] &= bottom58bits;
857 out[8] += out[7] >> 58; out[7] &= bottom58bits;
858 /* out[8] < 2^57 + 4 */
859
860 /* If the value is greater than 2^521-1 then we have to subtract
861 * 2^521-1 out. See the comments in felem_is_zero regarding why we
862 * don't test for other multiples of the prime. */
863
864 /* First, if |out| is equal to 2^521-1, we subtract it out to get zero. */
865
866 is_p = out[0] ^ kPrime[0];
867 is_p |= out[1] ^ kPrime[1];
868 is_p |= out[2] ^ kPrime[2];
869 is_p |= out[3] ^ kPrime[3];
870 is_p |= out[4] ^ kPrime[4];
871 is_p |= out[5] ^ kPrime[5];
872 is_p |= out[6] ^ kPrime[6];
873 is_p |= out[7] ^ kPrime[7];
874 is_p |= out[8] ^ kPrime[8];
875
876 is_p--;
877 is_p &= is_p << 32;
878 is_p &= is_p << 16;
879 is_p &= is_p << 8;
880 is_p &= is_p << 4;
881 is_p &= is_p << 2;
882 is_p &= is_p << 1;
883 is_p = ((s64) is_p) >> 63;
884 is_p = ~is_p;
885
886 /* is_p is 0 iff |out| == 2^521-1 and all ones otherwise */
887
888 out[0] &= is_p;
889 out[1] &= is_p;
890 out[2] &= is_p;
891 out[3] &= is_p;
892 out[4] &= is_p;
893 out[5] &= is_p;
894 out[6] &= is_p;
895 out[7] &= is_p;
896 out[8] &= is_p;
897
898 /* In order to test that |out| >= 2^521-1 we need only test if out[8]
899 * >> 57 is greater than zero as (2^521-1) + x >= 2^522 */
900 is_greater = out[8] >> 57;
901 is_greater |= is_greater << 32;
902 is_greater |= is_greater << 16;
903 is_greater |= is_greater << 8;
904 is_greater |= is_greater << 4;
905 is_greater |= is_greater << 2;
906 is_greater |= is_greater << 1;
907 is_greater = ((s64) is_greater) >> 63;
908
909 out[0] -= kPrime[0] & is_greater;
910 out[1] -= kPrime[1] & is_greater;
911 out[2] -= kPrime[2] & is_greater;
912 out[3] -= kPrime[3] & is_greater;
913 out[4] -= kPrime[4] & is_greater;
914 out[5] -= kPrime[5] & is_greater;
915 out[6] -= kPrime[6] & is_greater;
916 out[7] -= kPrime[7] & is_greater;
917 out[8] -= kPrime[8] & is_greater;
918
919 /* Eliminate negative coefficients */
920 sign = -(out[0] >> 63); out[0] += (two58 & sign); out[1] -= (1 & sign);
921 sign = -(out[1] >> 63); out[1] += (two58 & sign); out[2] -= (1 & sign);
922 sign = -(out[2] >> 63); out[2] += (two58 & sign); out[3] -= (1 & sign);
923 sign = -(out[3] >> 63); out[3] += (two58 & sign); out[4] -= (1 & sign);
924 sign = -(out[4] >> 63); out[4] += (two58 & sign); out[5] -= (1 & sign);
925 sign = -(out[0] >> 63); out[5] += (two58 & sign); out[6] -= (1 & sign);
926 sign = -(out[6] >> 63); out[6] += (two58 & sign); out[7] -= (1 & sign);
927 sign = -(out[7] >> 63); out[7] += (two58 & sign); out[8] -= (1 & sign);
928 sign = -(out[5] >> 63); out[5] += (two58 & sign); out[6] -= (1 & sign);
929 sign = -(out[6] >> 63); out[6] += (two58 & sign); out[7] -= (1 & sign);
930 sign = -(out[7] >> 63); out[7] += (two58 & sign); out[8] -= (1 & sign);
931 }
932
933/* Group operations
934 * ----------------
935 *
936 * Building on top of the field operations we have the operations on the
937 * elliptic curve group itself. Points on the curve are represented in Jacobian
938 * coordinates */
939
940/* point_double calcuates 2*(x_in, y_in, z_in)
941 *
942 * The method is taken from:
943 * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
944 *
945 * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed.
946 * while x_out == y_in is not (maybe this works, but it's not tested). */
947static void
948point_double(felem x_out, felem y_out, felem z_out,
949 const felem x_in, const felem y_in, const felem z_in)
950 {
951 largefelem tmp, tmp2;
952 felem delta, gamma, beta, alpha, ftmp, ftmp2;
953
954 felem_assign(ftmp, x_in);
955 felem_assign(ftmp2, x_in);
956
957 /* delta = z^2 */
958 felem_square(tmp, z_in);
959 felem_reduce(delta, tmp); /* delta[i] < 2^59 + 2^14 */
960
961 /* gamma = y^2 */
962 felem_square(tmp, y_in);
963 felem_reduce(gamma, tmp); /* gamma[i] < 2^59 + 2^14 */
964
965 /* beta = x*gamma */
966 felem_mul(tmp, x_in, gamma);
967 felem_reduce(beta, tmp); /* beta[i] < 2^59 + 2^14 */
968
969 /* alpha = 3*(x-delta)*(x+delta) */
970 felem_diff64(ftmp, delta);
971 /* ftmp[i] < 2^61 */
972 felem_sum64(ftmp2, delta);
973 /* ftmp2[i] < 2^60 + 2^15 */
974 felem_scalar64(ftmp2, 3);
975 /* ftmp2[i] < 3*2^60 + 3*2^15 */
976 felem_mul(tmp, ftmp, ftmp2);
977 /* tmp[i] < 17(3*2^121 + 3*2^76)
978 * = 61*2^121 + 61*2^76
979 * < 64*2^121 + 64*2^76
980 * = 2^127 + 2^82
981 * < 2^128 */
982 felem_reduce(alpha, tmp);
983
984 /* x' = alpha^2 - 8*beta */
985 felem_square(tmp, alpha);
986 /* tmp[i] < 17*2^120
987 * < 2^125 */
988 felem_assign(ftmp, beta);
989 felem_scalar64(ftmp, 8);
990 /* ftmp[i] < 2^62 + 2^17 */
991 felem_diff_128_64(tmp, ftmp);
992 /* tmp[i] < 2^125 + 2^63 + 2^62 + 2^17 */
993 felem_reduce(x_out, tmp);
994
995 /* z' = (y + z)^2 - gamma - delta */
996 felem_sum64(delta, gamma);
997 /* delta[i] < 2^60 + 2^15 */
998 felem_assign(ftmp, y_in);
999 felem_sum64(ftmp, z_in);
1000 /* ftmp[i] < 2^60 + 2^15 */
1001 felem_square(tmp, ftmp);
1002 /* tmp[i] < 17(2^122)
1003 * < 2^127 */
1004 felem_diff_128_64(tmp, delta);
1005 /* tmp[i] < 2^127 + 2^63 */
1006 felem_reduce(z_out, tmp);
1007
1008 /* y' = alpha*(4*beta - x') - 8*gamma^2 */
1009 felem_scalar64(beta, 4);
1010 /* beta[i] < 2^61 + 2^16 */
1011 felem_diff64(beta, x_out);
1012 /* beta[i] < 2^61 + 2^60 + 2^16 */
1013 felem_mul(tmp, alpha, beta);
1014 /* tmp[i] < 17*((2^59 + 2^14)(2^61 + 2^60 + 2^16))
1015 * = 17*(2^120 + 2^75 + 2^119 + 2^74 + 2^75 + 2^30)
1016 * = 17*(2^120 + 2^119 + 2^76 + 2^74 + 2^30)
1017 * < 2^128 */
1018 felem_square(tmp2, gamma);
1019 /* tmp2[i] < 17*(2^59 + 2^14)^2
1020 * = 17*(2^118 + 2^74 + 2^28) */
1021 felem_scalar128(tmp2, 8);
1022 /* tmp2[i] < 8*17*(2^118 + 2^74 + 2^28)
1023 * = 2^125 + 2^121 + 2^81 + 2^77 + 2^35 + 2^31
1024 * < 2^126 */
1025 felem_diff128(tmp, tmp2);
1026 /* tmp[i] < 2^127 - 2^69 + 17(2^120 + 2^119 + 2^76 + 2^74 + 2^30)
1027 * = 2^127 + 2^124 + 2^122 + 2^120 + 2^118 + 2^80 + 2^78 + 2^76 +
1028 * 2^74 + 2^69 + 2^34 + 2^30
1029 * < 2^128 */
1030 felem_reduce(y_out, tmp);
1031 }
1032
1033/* copy_conditional copies in to out iff mask is all ones. */
1034static void
1035copy_conditional(felem out, const felem in, limb mask)
1036 {
1037 unsigned i;
1038 for (i = 0; i < NLIMBS; ++i)
1039 {
1040 const limb tmp = mask & (in[i] ^ out[i]);
1041 out[i] ^= tmp;
1042 }
1043 }
1044
1045/* point_add calcuates (x1, y1, z1) + (x2, y2, z2)
1046 *
1047 * The method is taken from
1048 * http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl,
1049 * adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity).
1050 *
1051 * This function includes a branch for checking whether the two input points
1052 * are equal (while not equal to the point at infinity). This case never
1053 * happens during single point multiplication, so there is no timing leak for
1054 * ECDH or ECDSA signing. */
1055static void point_add(felem x3, felem y3, felem z3,
1056 const felem x1, const felem y1, const felem z1,
1057 const int mixed, const felem x2, const felem y2, const felem z2)
1058 {
1059 felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out;
1060 largefelem tmp, tmp2;
1061 limb x_equal, y_equal, z1_is_zero, z2_is_zero;
1062
1063 z1_is_zero = felem_is_zero(z1);
1064 z2_is_zero = felem_is_zero(z2);
1065
1066 /* ftmp = z1z1 = z1**2 */
1067 felem_square(tmp, z1);
1068 felem_reduce(ftmp, tmp);
1069
1070 if (!mixed)
1071 {
1072 /* ftmp2 = z2z2 = z2**2 */
1073 felem_square(tmp, z2);
1074 felem_reduce(ftmp2, tmp);
1075
1076 /* u1 = ftmp3 = x1*z2z2 */
1077 felem_mul(tmp, x1, ftmp2);
1078 felem_reduce(ftmp3, tmp);
1079
1080 /* ftmp5 = z1 + z2 */
1081 felem_assign(ftmp5, z1);
1082 felem_sum64(ftmp5, z2);
1083 /* ftmp5[i] < 2^61 */
1084
1085 /* ftmp5 = (z1 + z2)**2 - z1z1 - z2z2 = 2*z1z2 */
1086 felem_square(tmp, ftmp5);
1087 /* tmp[i] < 17*2^122 */
1088 felem_diff_128_64(tmp, ftmp);
1089 /* tmp[i] < 17*2^122 + 2^63 */
1090 felem_diff_128_64(tmp, ftmp2);
1091 /* tmp[i] < 17*2^122 + 2^64 */
1092 felem_reduce(ftmp5, tmp);
1093
1094 /* ftmp2 = z2 * z2z2 */
1095 felem_mul(tmp, ftmp2, z2);
1096 felem_reduce(ftmp2, tmp);
1097
1098 /* s1 = ftmp6 = y1 * z2**3 */
1099 felem_mul(tmp, y1, ftmp2);
1100 felem_reduce(ftmp6, tmp);
1101 }
1102 else
1103 {
1104 /* We'll assume z2 = 1 (special case z2 = 0 is handled later) */
1105
1106 /* u1 = ftmp3 = x1*z2z2 */
1107 felem_assign(ftmp3, x1);
1108
1109 /* ftmp5 = 2*z1z2 */
1110 felem_scalar(ftmp5, z1, 2);
1111
1112 /* s1 = ftmp6 = y1 * z2**3 */
1113 felem_assign(ftmp6, y1);
1114 }
1115
1116 /* u2 = x2*z1z1 */
1117 felem_mul(tmp, x2, ftmp);
1118 /* tmp[i] < 17*2^120 */
1119
1120 /* h = ftmp4 = u2 - u1 */
1121 felem_diff_128_64(tmp, ftmp3);
1122 /* tmp[i] < 17*2^120 + 2^63 */
1123 felem_reduce(ftmp4, tmp);
1124
1125 x_equal = felem_is_zero(ftmp4);
1126
1127 /* z_out = ftmp5 * h */
1128 felem_mul(tmp, ftmp5, ftmp4);
1129 felem_reduce(z_out, tmp);
1130
1131 /* ftmp = z1 * z1z1 */
1132 felem_mul(tmp, ftmp, z1);
1133 felem_reduce(ftmp, tmp);
1134
1135 /* s2 = tmp = y2 * z1**3 */
1136 felem_mul(tmp, y2, ftmp);
1137 /* tmp[i] < 17*2^120 */
1138
1139 /* r = ftmp5 = (s2 - s1)*2 */
1140 felem_diff_128_64(tmp, ftmp6);
1141 /* tmp[i] < 17*2^120 + 2^63 */
1142 felem_reduce(ftmp5, tmp);
1143 y_equal = felem_is_zero(ftmp5);
1144 felem_scalar64(ftmp5, 2);
1145 /* ftmp5[i] < 2^61 */
1146
1147 if (x_equal && y_equal && !z1_is_zero && !z2_is_zero)
1148 {
1149 point_double(x3, y3, z3, x1, y1, z1);
1150 return;
1151 }
1152
1153 /* I = ftmp = (2h)**2 */
1154 felem_assign(ftmp, ftmp4);
1155 felem_scalar64(ftmp, 2);
1156 /* ftmp[i] < 2^61 */
1157 felem_square(tmp, ftmp);
1158 /* tmp[i] < 17*2^122 */
1159 felem_reduce(ftmp, tmp);
1160
1161 /* J = ftmp2 = h * I */
1162 felem_mul(tmp, ftmp4, ftmp);
1163 felem_reduce(ftmp2, tmp);
1164
1165 /* V = ftmp4 = U1 * I */
1166 felem_mul(tmp, ftmp3, ftmp);
1167 felem_reduce(ftmp4, tmp);
1168
1169 /* x_out = r**2 - J - 2V */
1170 felem_square(tmp, ftmp5);
1171 /* tmp[i] < 17*2^122 */
1172 felem_diff_128_64(tmp, ftmp2);
1173 /* tmp[i] < 17*2^122 + 2^63 */
1174 felem_assign(ftmp3, ftmp4);
1175 felem_scalar64(ftmp4, 2);
1176 /* ftmp4[i] < 2^61 */
1177 felem_diff_128_64(tmp, ftmp4);
1178 /* tmp[i] < 17*2^122 + 2^64 */
1179 felem_reduce(x_out, tmp);
1180
1181 /* y_out = r(V-x_out) - 2 * s1 * J */
1182 felem_diff64(ftmp3, x_out);
1183 /* ftmp3[i] < 2^60 + 2^60
1184 * = 2^61 */
1185 felem_mul(tmp, ftmp5, ftmp3);
1186 /* tmp[i] < 17*2^122 */
1187 felem_mul(tmp2, ftmp6, ftmp2);
1188 /* tmp2[i] < 17*2^120 */
1189 felem_scalar128(tmp2, 2);
1190 /* tmp2[i] < 17*2^121 */
1191 felem_diff128(tmp, tmp2);
1192 /* tmp[i] < 2^127 - 2^69 + 17*2^122
1193 * = 2^126 - 2^122 - 2^6 - 2^2 - 1
1194 * < 2^127 */
1195 felem_reduce(y_out, tmp);
1196
1197 copy_conditional(x_out, x2, z1_is_zero);
1198 copy_conditional(x_out, x1, z2_is_zero);
1199 copy_conditional(y_out, y2, z1_is_zero);
1200 copy_conditional(y_out, y1, z2_is_zero);
1201 copy_conditional(z_out, z2, z1_is_zero);
1202 copy_conditional(z_out, z1, z2_is_zero);
1203 felem_assign(x3, x_out);
1204 felem_assign(y3, y_out);
1205 felem_assign(z3, z_out);
1206 }
1207
1208/* Base point pre computation
1209 * --------------------------
1210 *
1211 * Two different sorts of precomputed tables are used in the following code.
1212 * Each contain various points on the curve, where each point is three field
1213 * elements (x, y, z).
1214 *
1215 * For the base point table, z is usually 1 (0 for the point at infinity).
1216 * This table has 16 elements:
1217 * index | bits | point
1218 * ------+---------+------------------------------
1219 * 0 | 0 0 0 0 | 0G
1220 * 1 | 0 0 0 1 | 1G
1221 * 2 | 0 0 1 0 | 2^130G
1222 * 3 | 0 0 1 1 | (2^130 + 1)G
1223 * 4 | 0 1 0 0 | 2^260G
1224 * 5 | 0 1 0 1 | (2^260 + 1)G
1225 * 6 | 0 1 1 0 | (2^260 + 2^130)G
1226 * 7 | 0 1 1 1 | (2^260 + 2^130 + 1)G
1227 * 8 | 1 0 0 0 | 2^390G
1228 * 9 | 1 0 0 1 | (2^390 + 1)G
1229 * 10 | 1 0 1 0 | (2^390 + 2^130)G
1230 * 11 | 1 0 1 1 | (2^390 + 2^130 + 1)G
1231 * 12 | 1 1 0 0 | (2^390 + 2^260)G
1232 * 13 | 1 1 0 1 | (2^390 + 2^260 + 1)G
1233 * 14 | 1 1 1 0 | (2^390 + 2^260 + 2^130)G
1234 * 15 | 1 1 1 1 | (2^390 + 2^260 + 2^130 + 1)G
1235 *
1236 * The reason for this is so that we can clock bits into four different
1237 * locations when doing simple scalar multiplies against the base point.
1238 *
1239 * Tables for other points have table[i] = iG for i in 0 .. 16. */
1240
1241/* gmul is the table of precomputed base points */
1242static const felem gmul[16][3] =
1243 {{{0, 0, 0, 0, 0, 0, 0, 0, 0},
1244 {0, 0, 0, 0, 0, 0, 0, 0, 0},
1245 {0, 0, 0, 0, 0, 0, 0, 0, 0}},
1246 {{0x017e7e31c2e5bd66, 0x022cf0615a90a6fe, 0x00127a2ffa8de334,
1247 0x01dfbf9d64a3f877, 0x006b4d3dbaa14b5e, 0x014fed487e0a2bd8,
1248 0x015b4429c6481390, 0x03a73678fb2d988e, 0x00c6858e06b70404},
1249 {0x00be94769fd16650, 0x031c21a89cb09022, 0x039013fad0761353,
1250 0x02657bd099031542, 0x03273e662c97ee72, 0x01e6d11a05ebef45,
1251 0x03d1bd998f544495, 0x03001172297ed0b1, 0x011839296a789a3b},
1252 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1253 {{0x0373faacbc875bae, 0x00f325023721c671, 0x00f666fd3dbde5ad,
1254 0x01a6932363f88ea7, 0x01fc6d9e13f9c47b, 0x03bcbffc2bbf734e,
1255 0x013ee3c3647f3a92, 0x029409fefe75d07d, 0x00ef9199963d85e5},
1256 {0x011173743ad5b178, 0x02499c7c21bf7d46, 0x035beaeabb8b1a58,
1257 0x00f989c4752ea0a3, 0x0101e1de48a9c1a3, 0x01a20076be28ba6c,
1258 0x02f8052e5eb2de95, 0x01bfe8f82dea117c, 0x0160074d3c36ddb7},
1259 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1260 {{0x012f3fc373393b3b, 0x03d3d6172f1419fa, 0x02adc943c0b86873,
1261 0x00d475584177952b, 0x012a4d1673750ee2, 0x00512517a0f13b0c,
1262 0x02b184671a7b1734, 0x0315b84236f1a50a, 0x00a4afc472edbdb9},
1263 {0x00152a7077f385c4, 0x03044007d8d1c2ee, 0x0065829d61d52b52,
1264 0x00494ff6b6631d0d, 0x00a11d94d5f06bcf, 0x02d2f89474d9282e,
1265 0x0241c5727c06eeb9, 0x0386928710fbdb9d, 0x01f883f727b0dfbe},
1266 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1267 {{0x019b0c3c9185544d, 0x006243a37c9d97db, 0x02ee3cbe030a2ad2,
1268 0x00cfdd946bb51e0d, 0x0271c00932606b91, 0x03f817d1ec68c561,
1269 0x03f37009806a369c, 0x03c1f30baf184fd5, 0x01091022d6d2f065},
1270 {0x0292c583514c45ed, 0x0316fca51f9a286c, 0x00300af507c1489a,
1271 0x0295f69008298cf1, 0x02c0ed8274943d7b, 0x016509b9b47a431e,
1272 0x02bc9de9634868ce, 0x005b34929bffcb09, 0x000c1a0121681524},
1273 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1274 {{0x0286abc0292fb9f2, 0x02665eee9805b3f7, 0x01ed7455f17f26d6,
1275 0x0346355b83175d13, 0x006284944cd0a097, 0x0191895bcdec5e51,
1276 0x02e288370afda7d9, 0x03b22312bfefa67a, 0x01d104d3fc0613fe},
1277 {0x0092421a12f7e47f, 0x0077a83fa373c501, 0x03bd25c5f696bd0d,
1278 0x035c41e4d5459761, 0x01ca0d1742b24f53, 0x00aaab27863a509c,
1279 0x018b6de47df73917, 0x025c0b771705cd01, 0x01fd51d566d760a7},
1280 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1281 {{0x01dd92ff6b0d1dbd, 0x039c5e2e8f8afa69, 0x0261ed13242c3b27,
1282 0x0382c6e67026e6a0, 0x01d60b10be2089f9, 0x03c15f3dce86723f,
1283 0x03c764a32d2a062d, 0x017307eac0fad056, 0x018207c0b96c5256},
1284 {0x0196a16d60e13154, 0x03e6ce74c0267030, 0x00ddbf2b4e52a5aa,
1285 0x012738241bbf31c8, 0x00ebe8dc04685a28, 0x024c2ad6d380d4a2,
1286 0x035ee062a6e62d0e, 0x0029ed74af7d3a0f, 0x00eef32aec142ebd},
1287 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1288 {{0x00c31ec398993b39, 0x03a9f45bcda68253, 0x00ac733c24c70890,
1289 0x00872b111401ff01, 0x01d178c23195eafb, 0x03bca2c816b87f74,
1290 0x0261a9af46fbad7a, 0x0324b2a8dd3d28f9, 0x00918121d8f24e23},
1291 {0x032bc8c1ca983cd7, 0x00d869dfb08fc8c6, 0x01693cb61fce1516,
1292 0x012a5ea68f4e88a8, 0x010869cab88d7ae3, 0x009081ad277ceee1,
1293 0x033a77166d064cdc, 0x03955235a1fb3a95, 0x01251a4a9b25b65e},
1294 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1295 {{0x00148a3a1b27f40b, 0x0123186df1b31fdc, 0x00026e7beaad34ce,
1296 0x01db446ac1d3dbba, 0x0299c1a33437eaec, 0x024540610183cbb7,
1297 0x0173bb0e9ce92e46, 0x02b937e43921214b, 0x01ab0436a9bf01b5},
1298 {0x0383381640d46948, 0x008dacbf0e7f330f, 0x03602122bcc3f318,
1299 0x01ee596b200620d6, 0x03bd0585fda430b3, 0x014aed77fd123a83,
1300 0x005ace749e52f742, 0x0390fe041da2b842, 0x0189a8ceb3299242},
1301 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1302 {{0x012a19d6b3282473, 0x00c0915918b423ce, 0x023a954eb94405ae,
1303 0x00529f692be26158, 0x0289fa1b6fa4b2aa, 0x0198ae4ceea346ef,
1304 0x0047d8cdfbdedd49, 0x00cc8c8953f0f6b8, 0x001424abbff49203},
1305 {0x0256732a1115a03a, 0x0351bc38665c6733, 0x03f7b950fb4a6447,
1306 0x000afffa94c22155, 0x025763d0a4dab540, 0x000511e92d4fc283,
1307 0x030a7e9eda0ee96c, 0x004c3cd93a28bf0a, 0x017edb3a8719217f},
1308 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1309 {{0x011de5675a88e673, 0x031d7d0f5e567fbe, 0x0016b2062c970ae5,
1310 0x03f4a2be49d90aa7, 0x03cef0bd13822866, 0x03f0923dcf774a6c,
1311 0x0284bebc4f322f72, 0x016ab2645302bb2c, 0x01793f95dace0e2a},
1312 {0x010646e13527a28f, 0x01ca1babd59dc5e7, 0x01afedfd9a5595df,
1313 0x01f15785212ea6b1, 0x0324e5d64f6ae3f4, 0x02d680f526d00645,
1314 0x0127920fadf627a7, 0x03b383f75df4f684, 0x0089e0057e783b0a},
1315 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1316 {{0x00f334b9eb3c26c6, 0x0298fdaa98568dce, 0x01c2d24843a82292,
1317 0x020bcb24fa1b0711, 0x02cbdb3d2b1875e6, 0x0014907598f89422,
1318 0x03abe3aa43b26664, 0x02cbf47f720bc168, 0x0133b5e73014b79b},
1319 {0x034aab5dab05779d, 0x00cdc5d71fee9abb, 0x0399f16bd4bd9d30,
1320 0x03582fa592d82647, 0x02be1cdfb775b0e9, 0x0034f7cea32e94cb,
1321 0x0335a7f08f56f286, 0x03b707e9565d1c8b, 0x0015c946ea5b614f},
1322 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1323 {{0x024676f6cff72255, 0x00d14625cac96378, 0x00532b6008bc3767,
1324 0x01fc16721b985322, 0x023355ea1b091668, 0x029de7afdc0317c3,
1325 0x02fc8a7ca2da037c, 0x02de1217d74a6f30, 0x013f7173175b73bf},
1326 {0x0344913f441490b5, 0x0200f9e272b61eca, 0x0258a246b1dd55d2,
1327 0x03753db9ea496f36, 0x025e02937a09c5ef, 0x030cbd3d14012692,
1328 0x01793a67e70dc72a, 0x03ec1d37048a662e, 0x006550f700c32a8d},
1329 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1330 {{0x00d3f48a347eba27, 0x008e636649b61bd8, 0x00d3b93716778fb3,
1331 0x004d1915757bd209, 0x019d5311a3da44e0, 0x016d1afcbbe6aade,
1332 0x0241bf5f73265616, 0x0384672e5d50d39b, 0x005009fee522b684},
1333 {0x029b4fab064435fe, 0x018868ee095bbb07, 0x01ea3d6936cc92b8,
1334 0x000608b00f78a2f3, 0x02db911073d1c20f, 0x018205938470100a,
1335 0x01f1e4964cbe6ff2, 0x021a19a29eed4663, 0x01414485f42afa81},
1336 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1337 {{0x01612b3a17f63e34, 0x03813992885428e6, 0x022b3c215b5a9608,
1338 0x029b4057e19f2fcb, 0x0384059a587af7e6, 0x02d6400ace6fe610,
1339 0x029354d896e8e331, 0x00c047ee6dfba65e, 0x0037720542e9d49d},
1340 {0x02ce9eed7c5e9278, 0x0374ed703e79643b, 0x01316c54c4072006,
1341 0x005aaa09054b2ee8, 0x002824000c840d57, 0x03d4eba24771ed86,
1342 0x0189c50aabc3bdae, 0x0338c01541e15510, 0x00466d56e38eed42},
1343 {1, 0, 0, 0, 0, 0, 0, 0, 0}},
1344 {{0x007efd8330ad8bd6, 0x02465ed48047710b, 0x0034c6606b215e0c,
1345 0x016ae30c53cbf839, 0x01fa17bd37161216, 0x018ead4e61ce8ab9,
1346 0x005482ed5f5dee46, 0x037543755bba1d7f, 0x005e5ac7e70a9d0f},
1347 {0x0117e1bb2fdcb2a2, 0x03deea36249f40c4, 0x028d09b4a6246cb7,
1348 0x03524b8855bcf756, 0x023d7d109d5ceb58, 0x0178e43e3223ef9c,
1349 0x0154536a0c6e966a, 0x037964d1286ee9fe, 0x0199bcd90e125055},
1350 {1, 0, 0, 0, 0, 0, 0, 0, 0}}};
1351
1352/* select_point selects the |idx|th point from a precomputation table and
1353 * copies it to out. */
1354static void select_point(const limb idx, unsigned int size, const felem pre_comp[/* size */][3],
1355 felem out[3])
1356 {
1357 unsigned i, j;
1358 limb *outlimbs = &out[0][0];
1359 memset(outlimbs, 0, 3 * sizeof(felem));
1360
1361 for (i = 0; i < size; i++)
1362 {
1363 const limb *inlimbs = &pre_comp[i][0][0];
1364 limb mask = i ^ idx;
1365 mask |= mask >> 4;
1366 mask |= mask >> 2;
1367 mask |= mask >> 1;
1368 mask &= 1;
1369 mask--;
1370 for (j = 0; j < NLIMBS * 3; j++)
1371 outlimbs[j] |= inlimbs[j] & mask;
1372 }
1373 }
1374
1375/* get_bit returns the |i|th bit in |in| */
1376static char get_bit(const felem_bytearray in, int i)
1377 {
1378 if (i < 0)
1379 return 0;
1380 return (in[i >> 3] >> (i & 7)) & 1;
1381 }
1382
1383/* Interleaved point multiplication using precomputed point multiples:
1384 * The small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[],
1385 * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple
1386 * of the generator, using certain (large) precomputed multiples in g_pre_comp.
1387 * Output point (X, Y, Z) is stored in x_out, y_out, z_out */
1388static void batch_mul(felem x_out, felem y_out, felem z_out,
1389 const felem_bytearray scalars[], const unsigned num_points, const u8 *g_scalar,
1390 const int mixed, const felem pre_comp[][17][3], const felem g_pre_comp[16][3])
1391 {
1392 int i, skip;
1393 unsigned num, gen_mul = (g_scalar != NULL);
1394 felem nq[3], tmp[4];
1395 limb bits;
1396 u8 sign, digit;
1397
1398 /* set nq to the point at infinity */
1399 memset(nq, 0, 3 * sizeof(felem));
1400
1401 /* Loop over all scalars msb-to-lsb, interleaving additions
1402 * of multiples of the generator (last quarter of rounds)
1403 * and additions of other points multiples (every 5th round).
1404 */
1405 skip = 1; /* save two point operations in the first round */
1406 for (i = (num_points ? 520 : 130); i >= 0; --i)
1407 {
1408 /* double */
1409 if (!skip)
1410 point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
1411
1412 /* add multiples of the generator */
1413 if (gen_mul && (i <= 130))
1414 {
1415 bits = get_bit(g_scalar, i + 390) << 3;
1416 if (i < 130)
1417 {
1418 bits |= get_bit(g_scalar, i + 260) << 2;
1419 bits |= get_bit(g_scalar, i + 130) << 1;
1420 bits |= get_bit(g_scalar, i);
1421 }
1422 /* select the point to add, in constant time */
1423 select_point(bits, 16, g_pre_comp, tmp);
1424 if (!skip)
1425 {
1426 point_add(nq[0], nq[1], nq[2],
1427 nq[0], nq[1], nq[2],
1428 1 /* mixed */, tmp[0], tmp[1], tmp[2]);
1429 }
1430 else
1431 {
1432 memcpy(nq, tmp, 3 * sizeof(felem));
1433 skip = 0;
1434 }
1435 }
1436
1437 /* do other additions every 5 doublings */
1438 if (num_points && (i % 5 == 0))
1439 {
1440 /* loop over all scalars */
1441 for (num = 0; num < num_points; ++num)
1442 {
1443 bits = get_bit(scalars[num], i + 4) << 5;
1444 bits |= get_bit(scalars[num], i + 3) << 4;
1445 bits |= get_bit(scalars[num], i + 2) << 3;
1446 bits |= get_bit(scalars[num], i + 1) << 2;
1447 bits |= get_bit(scalars[num], i) << 1;
1448 bits |= get_bit(scalars[num], i - 1);
1449 ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
1450
1451 /* select the point to add or subtract, in constant time */
1452 select_point(digit, 17, pre_comp[num], tmp);
1453 felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative point */
1454 copy_conditional(tmp[1], tmp[3], (-(limb) sign));
1455
1456 if (!skip)
1457 {
1458 point_add(nq[0], nq[1], nq[2],
1459 nq[0], nq[1], nq[2],
1460 mixed, tmp[0], tmp[1], tmp[2]);
1461 }
1462 else
1463 {
1464 memcpy(nq, tmp, 3 * sizeof(felem));
1465 skip = 0;
1466 }
1467 }
1468 }
1469 }
1470 felem_assign(x_out, nq[0]);
1471 felem_assign(y_out, nq[1]);
1472 felem_assign(z_out, nq[2]);
1473 }
1474
1475
1476/* Precomputation for the group generator. */
1477typedef struct {
1478 felem g_pre_comp[16][3];
1479 int references;
1480} NISTP521_PRE_COMP;
1481
1482const EC_METHOD *EC_GFp_nistp521_method(void)
1483 {
1484 static const EC_METHOD ret = {
1485 EC_FLAGS_DEFAULT_OCT,
1486 NID_X9_62_prime_field,
1487 ec_GFp_nistp521_group_init,
1488 ec_GFp_simple_group_finish,
1489 ec_GFp_simple_group_clear_finish,
1490 ec_GFp_nist_group_copy,
1491 ec_GFp_nistp521_group_set_curve,
1492 ec_GFp_simple_group_get_curve,
1493 ec_GFp_simple_group_get_degree,
1494 ec_GFp_simple_group_check_discriminant,
1495 ec_GFp_simple_point_init,
1496 ec_GFp_simple_point_finish,
1497 ec_GFp_simple_point_clear_finish,
1498 ec_GFp_simple_point_copy,
1499 ec_GFp_simple_point_set_to_infinity,
1500 ec_GFp_simple_set_Jprojective_coordinates_GFp,
1501 ec_GFp_simple_get_Jprojective_coordinates_GFp,
1502 ec_GFp_simple_point_set_affine_coordinates,
1503 ec_GFp_nistp521_point_get_affine_coordinates,
1504 0 /* point_set_compressed_coordinates */,
1505 0 /* point2oct */,
1506 0 /* oct2point */,
1507 ec_GFp_simple_add,
1508 ec_GFp_simple_dbl,
1509 ec_GFp_simple_invert,
1510 ec_GFp_simple_is_at_infinity,
1511 ec_GFp_simple_is_on_curve,
1512 ec_GFp_simple_cmp,
1513 ec_GFp_simple_make_affine,
1514 ec_GFp_simple_points_make_affine,
1515 ec_GFp_nistp521_points_mul,
1516 ec_GFp_nistp521_precompute_mult,
1517 ec_GFp_nistp521_have_precompute_mult,
1518 ec_GFp_nist_field_mul,
1519 ec_GFp_nist_field_sqr,
1520 0 /* field_div */,
1521 0 /* field_encode */,
1522 0 /* field_decode */,
1523 0 /* field_set_to_one */ };
1524
1525 return &ret;
1526 }
1527
1528
1529/******************************************************************************/
1530/* FUNCTIONS TO MANAGE PRECOMPUTATION
1531 */
1532
1533static NISTP521_PRE_COMP *nistp521_pre_comp_new()
1534 {
1535 NISTP521_PRE_COMP *ret = NULL;
1536 ret = (NISTP521_PRE_COMP *)OPENSSL_malloc(sizeof(NISTP521_PRE_COMP));
1537 if (!ret)
1538 {
1539 ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
1540 return ret;
1541 }
1542 memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp));
1543 ret->references = 1;
1544 return ret;
1545 }
1546
1547static void *nistp521_pre_comp_dup(void *src_)
1548 {
1549 NISTP521_PRE_COMP *src = src_;
1550
1551 /* no need to actually copy, these objects never change! */
1552 CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
1553
1554 return src_;
1555 }
1556
1557static void nistp521_pre_comp_free(void *pre_)
1558 {
1559 int i;
1560 NISTP521_PRE_COMP *pre = pre_;
1561
1562 if (!pre)
1563 return;
1564
1565 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1566 if (i > 0)
1567 return;
1568
1569 OPENSSL_free(pre);
1570 }
1571
1572static void nistp521_pre_comp_clear_free(void *pre_)
1573 {
1574 int i;
1575 NISTP521_PRE_COMP *pre = pre_;
1576
1577 if (!pre)
1578 return;
1579
1580 i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
1581 if (i > 0)
1582 return;
1583
1584 OPENSSL_cleanse(pre, sizeof(*pre));
1585 OPENSSL_free(pre);
1586 }
1587
1588/******************************************************************************/
1589/* OPENSSL EC_METHOD FUNCTIONS
1590 */
1591
1592int ec_GFp_nistp521_group_init(EC_GROUP *group)
1593 {
1594 int ret;
1595 ret = ec_GFp_simple_group_init(group);
1596 group->a_is_minus3 = 1;
1597 return ret;
1598 }
1599
1600int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
1601 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
1602 {
1603 int ret = 0;
1604 BN_CTX *new_ctx = NULL;
1605 BIGNUM *curve_p, *curve_a, *curve_b;
1606
1607 if (ctx == NULL)
1608 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1609 BN_CTX_start(ctx);
1610 if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
1611 ((curve_a = BN_CTX_get(ctx)) == NULL) ||
1612 ((curve_b = BN_CTX_get(ctx)) == NULL)) goto err;
1613 BN_bin2bn(nistp521_curve_params[0], sizeof(felem_bytearray), curve_p);
1614 BN_bin2bn(nistp521_curve_params[1], sizeof(felem_bytearray), curve_a);
1615 BN_bin2bn(nistp521_curve_params[2], sizeof(felem_bytearray), curve_b);
1616 if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) ||
1617 (BN_cmp(curve_b, b)))
1618 {
1619 ECerr(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE,
1620 EC_R_WRONG_CURVE_PARAMETERS);
1621 goto err;
1622 }
1623 group->field_mod_func = BN_nist_mod_521;
1624 ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
1625err:
1626 BN_CTX_end(ctx);
1627 if (new_ctx != NULL)
1628 BN_CTX_free(new_ctx);
1629 return ret;
1630 }
1631
1632/* Takes the Jacobian coordinates (X, Y, Z) of a point and returns
1633 * (X', Y') = (X/Z^2, Y/Z^3) */
1634int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group,
1635 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
1636 {
1637 felem z1, z2, x_in, y_in, x_out, y_out;
1638 largefelem tmp;
1639
1640 if (EC_POINT_is_at_infinity(group, point))
1641 {
1642 ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES,
1643 EC_R_POINT_AT_INFINITY);
1644 return 0;
1645 }
1646 if ((!BN_to_felem(x_in, &point->X)) || (!BN_to_felem(y_in, &point->Y)) ||
1647 (!BN_to_felem(z1, &point->Z))) return 0;
1648 felem_inv(z2, z1);
1649 felem_square(tmp, z2); felem_reduce(z1, tmp);
1650 felem_mul(tmp, x_in, z1); felem_reduce(x_in, tmp);
1651 felem_contract(x_out, x_in);
1652 if (x != NULL)
1653 {
1654 if (!felem_to_BN(x, x_out))
1655 {
1656 ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
1657 return 0;
1658 }
1659 }
1660 felem_mul(tmp, z1, z2); felem_reduce(z1, tmp);
1661 felem_mul(tmp, y_in, z1); felem_reduce(y_in, tmp);
1662 felem_contract(y_out, y_in);
1663 if (y != NULL)
1664 {
1665 if (!felem_to_BN(y, y_out))
1666 {
1667 ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, ERR_R_BN_LIB);
1668 return 0;
1669 }
1670 }
1671 return 1;
1672 }
1673
1674static void make_points_affine(size_t num, felem points[/* num */][3], felem tmp_felems[/* num+1 */])
1675 {
1676 /* Runs in constant time, unless an input is the point at infinity
1677 * (which normally shouldn't happen). */
1678 ec_GFp_nistp_points_make_affine_internal(
1679 num,
1680 points,
1681 sizeof(felem),
1682 tmp_felems,
1683 (void (*)(void *)) felem_one,
1684 (int (*)(const void *)) felem_is_zero_int,
1685 (void (*)(void *, const void *)) felem_assign,
1686 (void (*)(void *, const void *)) felem_square_reduce,
1687 (void (*)(void *, const void *, const void *)) felem_mul_reduce,
1688 (void (*)(void *, const void *)) felem_inv,
1689 (void (*)(void *, const void *)) felem_contract);
1690 }
1691
1692/* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL values
1693 * Result is stored in r (r can equal one of the inputs). */
1694int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
1695 const BIGNUM *scalar, size_t num, const EC_POINT *points[],
1696 const BIGNUM *scalars[], BN_CTX *ctx)
1697 {
1698 int ret = 0;
1699 int j;
1700 int mixed = 0;
1701 BN_CTX *new_ctx = NULL;
1702 BIGNUM *x, *y, *z, *tmp_scalar;
1703 felem_bytearray g_secret;
1704 felem_bytearray *secrets = NULL;
1705 felem (*pre_comp)[17][3] = NULL;
1706 felem *tmp_felems = NULL;
1707 felem_bytearray tmp;
1708 unsigned i, num_bytes;
1709 int have_pre_comp = 0;
1710 size_t num_points = num;
1711 felem x_in, y_in, z_in, x_out, y_out, z_out;
1712 NISTP521_PRE_COMP *pre = NULL;
1713 felem (*g_pre_comp)[3] = NULL;
1714 EC_POINT *generator = NULL;
1715 const EC_POINT *p = NULL;
1716 const BIGNUM *p_scalar = NULL;
1717
1718 if (ctx == NULL)
1719 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1720 BN_CTX_start(ctx);
1721 if (((x = BN_CTX_get(ctx)) == NULL) ||
1722 ((y = BN_CTX_get(ctx)) == NULL) ||
1723 ((z = BN_CTX_get(ctx)) == NULL) ||
1724 ((tmp_scalar = BN_CTX_get(ctx)) == NULL))
1725 goto err;
1726
1727 if (scalar != NULL)
1728 {
1729 pre = EC_EX_DATA_get_data(group->extra_data,
1730 nistp521_pre_comp_dup, nistp521_pre_comp_free,
1731 nistp521_pre_comp_clear_free);
1732 if (pre)
1733 /* we have precomputation, try to use it */
1734 g_pre_comp = &pre->g_pre_comp[0];
1735 else
1736 /* try to use the standard precomputation */
1737 g_pre_comp = (felem (*)[3]) gmul;
1738 generator = EC_POINT_new(group);
1739 if (generator == NULL)
1740 goto err;
1741 /* get the generator from precomputation */
1742 if (!felem_to_BN(x, g_pre_comp[1][0]) ||
1743 !felem_to_BN(y, g_pre_comp[1][1]) ||
1744 !felem_to_BN(z, g_pre_comp[1][2]))
1745 {
1746 ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
1747 goto err;
1748 }
1749 if (!EC_POINT_set_Jprojective_coordinates_GFp(group,
1750 generator, x, y, z, ctx))
1751 goto err;
1752 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
1753 /* precomputation matches generator */
1754 have_pre_comp = 1;
1755 else
1756 /* we don't have valid precomputation:
1757 * treat the generator as a random point */
1758 num_points++;
1759 }
1760
1761 if (num_points > 0)
1762 {
1763 if (num_points >= 2)
1764 {
1765 /* unless we precompute multiples for just one point,
1766 * converting those into affine form is time well spent */
1767 mixed = 1;
1768 }
1769 secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
1770 pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(felem));
1771 if (mixed)
1772 tmp_felems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem));
1773 if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_felems == NULL)))
1774 {
1775 ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_MALLOC_FAILURE);
1776 goto err;
1777 }
1778
1779 /* we treat NULL scalars as 0, and NULL points as points at infinity,
1780 * i.e., they contribute nothing to the linear combination */
1781 memset(secrets, 0, num_points * sizeof(felem_bytearray));
1782 memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem));
1783 for (i = 0; i < num_points; ++i)
1784 {
1785 if (i == num)
1786 /* we didn't have a valid precomputation, so we pick
1787 * the generator */
1788 {
1789 p = EC_GROUP_get0_generator(group);
1790 p_scalar = scalar;
1791 }
1792 else
1793 /* the i^th point */
1794 {
1795 p = points[i];
1796 p_scalar = scalars[i];
1797 }
1798 if ((p_scalar != NULL) && (p != NULL))
1799 {
1800 /* reduce scalar to 0 <= scalar < 2^521 */
1801 if ((BN_num_bits(p_scalar) > 521) || (BN_is_negative(p_scalar)))
1802 {
1803 /* this is an unusual input, and we don't guarantee
1804 * constant-timeness */
1805 if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx))
1806 {
1807 ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
1808 goto err;
1809 }
1810 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1811 }
1812 else
1813 num_bytes = BN_bn2bin(p_scalar, tmp);
1814 flip_endian(secrets[i], tmp, num_bytes);
1815 /* precompute multiples */
1816 if ((!BN_to_felem(x_out, &p->X)) ||
1817 (!BN_to_felem(y_out, &p->Y)) ||
1818 (!BN_to_felem(z_out, &p->Z))) goto err;
1819 memcpy(pre_comp[i][1][0], x_out, sizeof(felem));
1820 memcpy(pre_comp[i][1][1], y_out, sizeof(felem));
1821 memcpy(pre_comp[i][1][2], z_out, sizeof(felem));
1822 for (j = 2; j <= 16; ++j)
1823 {
1824 if (j & 1)
1825 {
1826 point_add(
1827 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1828 pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2],
1829 0, pre_comp[i][j-1][0], pre_comp[i][j-1][1], pre_comp[i][j-1][2]);
1830 }
1831 else
1832 {
1833 point_double(
1834 pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
1835 pre_comp[i][j/2][0], pre_comp[i][j/2][1], pre_comp[i][j/2][2]);
1836 }
1837 }
1838 }
1839 }
1840 if (mixed)
1841 make_points_affine(num_points * 17, pre_comp[0], tmp_felems);
1842 }
1843
1844 /* the scalar for the generator */
1845 if ((scalar != NULL) && (have_pre_comp))
1846 {
1847 memset(g_secret, 0, sizeof(g_secret));
1848 /* reduce scalar to 0 <= scalar < 2^521 */
1849 if ((BN_num_bits(scalar) > 521) || (BN_is_negative(scalar)))
1850 {
1851 /* this is an unusual input, and we don't guarantee
1852 * constant-timeness */
1853 if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx))
1854 {
1855 ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
1856 goto err;
1857 }
1858 num_bytes = BN_bn2bin(tmp_scalar, tmp);
1859 }
1860 else
1861 num_bytes = BN_bn2bin(scalar, tmp);
1862 flip_endian(g_secret, tmp, num_bytes);
1863 /* do the multiplication with generator precomputation*/
1864 batch_mul(x_out, y_out, z_out,
1865 (const felem_bytearray (*)) secrets, num_points,
1866 g_secret,
1867 mixed, (const felem (*)[17][3]) pre_comp,
1868 (const felem (*)[3]) g_pre_comp);
1869 }
1870 else
1871 /* do the multiplication without generator precomputation */
1872 batch_mul(x_out, y_out, z_out,
1873 (const felem_bytearray (*)) secrets, num_points,
1874 NULL, mixed, (const felem (*)[17][3]) pre_comp, NULL);
1875 /* reduce the output to its unique minimal representation */
1876 felem_contract(x_in, x_out);
1877 felem_contract(y_in, y_out);
1878 felem_contract(z_in, z_out);
1879 if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) ||
1880 (!felem_to_BN(z, z_in)))
1881 {
1882 ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
1883 goto err;
1884 }
1885 ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
1886
1887err:
1888 BN_CTX_end(ctx);
1889 if (generator != NULL)
1890 EC_POINT_free(generator);
1891 if (new_ctx != NULL)
1892 BN_CTX_free(new_ctx);
1893 if (secrets != NULL)
1894 OPENSSL_free(secrets);
1895 if (pre_comp != NULL)
1896 OPENSSL_free(pre_comp);
1897 if (tmp_felems != NULL)
1898 OPENSSL_free(tmp_felems);
1899 return ret;
1900 }
1901
1902int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1903 {
1904 int ret = 0;
1905 NISTP521_PRE_COMP *pre = NULL;
1906 int i, j;
1907 BN_CTX *new_ctx = NULL;
1908 BIGNUM *x, *y;
1909 EC_POINT *generator = NULL;
1910 felem tmp_felems[16];
1911
1912 /* throw away old precomputation */
1913 EC_EX_DATA_free_data(&group->extra_data, nistp521_pre_comp_dup,
1914 nistp521_pre_comp_free, nistp521_pre_comp_clear_free);
1915 if (ctx == NULL)
1916 if ((ctx = new_ctx = BN_CTX_new()) == NULL) return 0;
1917 BN_CTX_start(ctx);
1918 if (((x = BN_CTX_get(ctx)) == NULL) ||
1919 ((y = BN_CTX_get(ctx)) == NULL))
1920 goto err;
1921 /* get the generator */
1922 if (group->generator == NULL) goto err;
1923 generator = EC_POINT_new(group);
1924 if (generator == NULL)
1925 goto err;
1926 BN_bin2bn(nistp521_curve_params[3], sizeof (felem_bytearray), x);
1927 BN_bin2bn(nistp521_curve_params[4], sizeof (felem_bytearray), y);
1928 if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx))
1929 goto err;
1930 if ((pre = nistp521_pre_comp_new()) == NULL)
1931 goto err;
1932 /* if the generator is the standard one, use built-in precomputation */
1933 if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
1934 {
1935 memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp));
1936 ret = 1;
1937 goto err;
1938 }
1939 if ((!BN_to_felem(pre->g_pre_comp[1][0], &group->generator->X)) ||
1940 (!BN_to_felem(pre->g_pre_comp[1][1], &group->generator->Y)) ||
1941 (!BN_to_felem(pre->g_pre_comp[1][2], &group->generator->Z)))
1942 goto err;
1943 /* compute 2^130*G, 2^260*G, 2^390*G */
1944 for (i = 1; i <= 4; i <<= 1)
1945 {
1946 point_double(pre->g_pre_comp[2*i][0], pre->g_pre_comp[2*i][1],
1947 pre->g_pre_comp[2*i][2], pre->g_pre_comp[i][0],
1948 pre->g_pre_comp[i][1], pre->g_pre_comp[i][2]);
1949 for (j = 0; j < 129; ++j)
1950 {
1951 point_double(pre->g_pre_comp[2*i][0],
1952 pre->g_pre_comp[2*i][1],
1953 pre->g_pre_comp[2*i][2],
1954 pre->g_pre_comp[2*i][0],
1955 pre->g_pre_comp[2*i][1],
1956 pre->g_pre_comp[2*i][2]);
1957 }
1958 }
1959 /* g_pre_comp[0] is the point at infinity */
1960 memset(pre->g_pre_comp[0], 0, sizeof(pre->g_pre_comp[0]));
1961 /* the remaining multiples */
1962 /* 2^130*G + 2^260*G */
1963 point_add(pre->g_pre_comp[6][0], pre->g_pre_comp[6][1],
1964 pre->g_pre_comp[6][2], pre->g_pre_comp[4][0],
1965 pre->g_pre_comp[4][1], pre->g_pre_comp[4][2],
1966 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1],
1967 pre->g_pre_comp[2][2]);
1968 /* 2^130*G + 2^390*G */
1969 point_add(pre->g_pre_comp[10][0], pre->g_pre_comp[10][1],
1970 pre->g_pre_comp[10][2], pre->g_pre_comp[8][0],
1971 pre->g_pre_comp[8][1], pre->g_pre_comp[8][2],
1972 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1],
1973 pre->g_pre_comp[2][2]);
1974 /* 2^260*G + 2^390*G */
1975 point_add(pre->g_pre_comp[12][0], pre->g_pre_comp[12][1],
1976 pre->g_pre_comp[12][2], pre->g_pre_comp[8][0],
1977 pre->g_pre_comp[8][1], pre->g_pre_comp[8][2],
1978 0, pre->g_pre_comp[4][0], pre->g_pre_comp[4][1],
1979 pre->g_pre_comp[4][2]);
1980 /* 2^130*G + 2^260*G + 2^390*G */
1981 point_add(pre->g_pre_comp[14][0], pre->g_pre_comp[14][1],
1982 pre->g_pre_comp[14][2], pre->g_pre_comp[12][0],
1983 pre->g_pre_comp[12][1], pre->g_pre_comp[12][2],
1984 0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1],
1985 pre->g_pre_comp[2][2]);
1986 for (i = 1; i < 8; ++i)
1987 {
1988 /* odd multiples: add G */
1989 point_add(pre->g_pre_comp[2*i+1][0], pre->g_pre_comp[2*i+1][1],
1990 pre->g_pre_comp[2*i+1][2], pre->g_pre_comp[2*i][0],
1991 pre->g_pre_comp[2*i][1], pre->g_pre_comp[2*i][2],
1992 0, pre->g_pre_comp[1][0], pre->g_pre_comp[1][1],
1993 pre->g_pre_comp[1][2]);
1994 }
1995 make_points_affine(15, &(pre->g_pre_comp[1]), tmp_felems);
1996
1997 if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp521_pre_comp_dup,
1998 nistp521_pre_comp_free, nistp521_pre_comp_clear_free))
1999 goto err;
2000 ret = 1;
2001 pre = NULL;
2002 err:
2003 BN_CTX_end(ctx);
2004 if (generator != NULL)
2005 EC_POINT_free(generator);
2006 if (new_ctx != NULL)
2007 BN_CTX_free(new_ctx);
2008 if (pre)
2009 nistp521_pre_comp_free(pre);
2010 return ret;
2011 }
2012
2013int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group)
2014 {
2015 if (EC_EX_DATA_get_data(group->extra_data, nistp521_pre_comp_dup,
2016 nistp521_pre_comp_free, nistp521_pre_comp_clear_free)
2017 != NULL)
2018 return 1;
2019 else
2020 return 0;
2021 }
2022
2023#else
2024static void *dummy=&dummy;
2025#endif
diff --git a/src/lib/libcrypto/ec/ecp_nistputil.c b/src/lib/libcrypto/ec/ecp_nistputil.c
new file mode 100644
index 0000000000..c8140c807f
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_nistputil.c
@@ -0,0 +1,197 @@
1/* crypto/ec/ecp_nistputil.c */
2/*
3 * Written by Bodo Moeller for the OpenSSL project.
4 */
5/* Copyright 2011 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 *
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21#include <openssl/opensslconf.h>
22#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
23
24/*
25 * Common utility functions for ecp_nistp224.c, ecp_nistp256.c, ecp_nistp521.c.
26 */
27
28#include <stddef.h>
29#include "ec_lcl.h"
30
31/* Convert an array of points into affine coordinates.
32 * (If the point at infinity is found (Z = 0), it remains unchanged.)
33 * This function is essentially an equivalent to EC_POINTs_make_affine(), but
34 * works with the internal representation of points as used by ecp_nistp###.c
35 * rather than with (BIGNUM-based) EC_POINT data structures.
36 *
37 * point_array is the input/output buffer ('num' points in projective form,
38 * i.e. three coordinates each), based on an internal representation of
39 * field elements of size 'felem_size'.
40 *
41 * tmp_felems needs to point to a temporary array of 'num'+1 field elements
42 * for storage of intermediate values.
43 */
44void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
45 size_t felem_size, void *tmp_felems,
46 void (*felem_one)(void *out),
47 int (*felem_is_zero)(const void *in),
48 void (*felem_assign)(void *out, const void *in),
49 void (*felem_square)(void *out, const void *in),
50 void (*felem_mul)(void *out, const void *in1, const void *in2),
51 void (*felem_inv)(void *out, const void *in),
52 void (*felem_contract)(void *out, const void *in))
53 {
54 int i = 0;
55
56#define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size])
57#define X(I) (&((char *)point_array)[3*(I) * felem_size])
58#define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size])
59#define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size])
60
61 if (!felem_is_zero(Z(0)))
62 felem_assign(tmp_felem(0), Z(0));
63 else
64 felem_one(tmp_felem(0));
65 for (i = 1; i < (int)num; i++)
66 {
67 if (!felem_is_zero(Z(i)))
68 felem_mul(tmp_felem(i), tmp_felem(i-1), Z(i));
69 else
70 felem_assign(tmp_felem(i), tmp_felem(i-1));
71 }
72 /* Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any zero-valued factors:
73 * if Z(i) = 0, we essentially pretend that Z(i) = 1 */
74
75 felem_inv(tmp_felem(num-1), tmp_felem(num-1));
76 for (i = num - 1; i >= 0; i--)
77 {
78 if (i > 0)
79 /* tmp_felem(i-1) is the product of Z(0) .. Z(i-1),
80 * tmp_felem(i) is the inverse of the product of Z(0) .. Z(i)
81 */
82 felem_mul(tmp_felem(num), tmp_felem(i-1), tmp_felem(i)); /* 1/Z(i) */
83 else
84 felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */
85
86 if (!felem_is_zero(Z(i)))
87 {
88 if (i > 0)
89 /* For next iteration, replace tmp_felem(i-1) by its inverse */
90 felem_mul(tmp_felem(i-1), tmp_felem(i), Z(i));
91
92 /* Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1) */
93 felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */
94 felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */
95 felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */
96 felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */
97 felem_contract(X(i), X(i));
98 felem_contract(Y(i), Y(i));
99 felem_one(Z(i));
100 }
101 else
102 {
103 if (i > 0)
104 /* For next iteration, replace tmp_felem(i-1) by its inverse */
105 felem_assign(tmp_felem(i-1), tmp_felem(i));
106 }
107 }
108 }
109
110/*
111 * This function looks at 5+1 scalar bits (5 current, 1 adjacent less
112 * significant bit), and recodes them into a signed digit for use in fast point
113 * multiplication: the use of signed rather than unsigned digits means that
114 * fewer points need to be precomputed, given that point inversion is easy
115 * (a precomputed point dP makes -dP available as well).
116 *
117 * BACKGROUND:
118 *
119 * Signed digits for multiplication were introduced by Booth ("A signed binary
120 * multiplication technique", Quart. Journ. Mech. and Applied Math., vol. IV,
121 * pt. 2 (1951), pp. 236-240), in that case for multiplication of integers.
122 * Booth's original encoding did not generally improve the density of nonzero
123 * digits over the binary representation, and was merely meant to simplify the
124 * handling of signed factors given in two's complement; but it has since been
125 * shown to be the basis of various signed-digit representations that do have
126 * further advantages, including the wNAF, using the following general approach:
127 *
128 * (1) Given a binary representation
129 *
130 * b_k ... b_2 b_1 b_0,
131 *
132 * of a nonnegative integer (b_k in {0, 1}), rewrite it in digits 0, 1, -1
133 * by using bit-wise subtraction as follows:
134 *
135 * b_k b_(k-1) ... b_2 b_1 b_0
136 * - b_k ... b_3 b_2 b_1 b_0
137 * -------------------------------------
138 * s_k b_(k-1) ... s_3 s_2 s_1 s_0
139 *
140 * A left-shift followed by subtraction of the original value yields a new
141 * representation of the same value, using signed bits s_i = b_(i+1) - b_i.
142 * This representation from Booth's paper has since appeared in the
143 * literature under a variety of different names including "reversed binary
144 * form", "alternating greedy expansion", "mutual opposite form", and
145 * "sign-alternating {+-1}-representation".
146 *
147 * An interesting property is that among the nonzero bits, values 1 and -1
148 * strictly alternate.
149 *
150 * (2) Various window schemes can be applied to the Booth representation of
151 * integers: for example, right-to-left sliding windows yield the wNAF
152 * (a signed-digit encoding independently discovered by various researchers
153 * in the 1990s), and left-to-right sliding windows yield a left-to-right
154 * equivalent of the wNAF (independently discovered by various researchers
155 * around 2004).
156 *
157 * To prevent leaking information through side channels in point multiplication,
158 * we need to recode the given integer into a regular pattern: sliding windows
159 * as in wNAFs won't do, we need their fixed-window equivalent -- which is a few
160 * decades older: we'll be using the so-called "modified Booth encoding" due to
161 * MacSorley ("High-speed arithmetic in binary computers", Proc. IRE, vol. 49
162 * (1961), pp. 67-91), in a radix-2^5 setting. That is, we always combine five
163 * signed bits into a signed digit:
164 *
165 * s_(4j + 4) s_(4j + 3) s_(4j + 2) s_(4j + 1) s_(4j)
166 *
167 * The sign-alternating property implies that the resulting digit values are
168 * integers from -16 to 16.
169 *
170 * Of course, we don't actually need to compute the signed digits s_i as an
171 * intermediate step (that's just a nice way to see how this scheme relates
172 * to the wNAF): a direct computation obtains the recoded digit from the
173 * six bits b_(4j + 4) ... b_(4j - 1).
174 *
175 * This function takes those five bits as an integer (0 .. 63), writing the
176 * recoded digit to *sign (0 for positive, 1 for negative) and *digit (absolute
177 * value, in the range 0 .. 8). Note that this integer essentially provides the
178 * input bits "shifted to the left" by one position: for example, the input to
179 * compute the least significant recoded digit, given that there's no bit b_-1,
180 * has to be b_4 b_3 b_2 b_1 b_0 0.
181 *
182 */
183void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in)
184 {
185 unsigned char s, d;
186
187 s = ~((in >> 5) - 1); /* sets all bits to MSB(in), 'in' seen as 6-bit value */
188 d = (1 << 6) - in - 1;
189 d = (d & s) | (in & ~s);
190 d = (d >> 1) + (d & 1);
191
192 *sign = s & 1;
193 *digit = d;
194 }
195#else
196static void *dummy=&dummy;
197#endif
diff --git a/src/lib/libcrypto/ec/ecp_oct.c b/src/lib/libcrypto/ec/ecp_oct.c
new file mode 100644
index 0000000000..374a0ee731
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecp_oct.c
@@ -0,0 +1,433 @@
1/* crypto/ec/ecp_oct.c */
2/* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
3 * for the OpenSSL project.
4 * Includes code written by Bodo Moeller for the OpenSSL project.
5*/
6/* ====================================================================
7 * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * openssl-core@openssl.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 * acknowledgment:
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com). This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
57 *
58 */
59/* ====================================================================
60 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
61 * Portions of this software developed by SUN MICROSYSTEMS, INC.,
62 * and contributed to the OpenSSL project.
63 */
64
65#include <openssl/err.h>
66#include <openssl/symhacks.h>
67
68#include "ec_lcl.h"
69
70int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
71 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
72 {
73 BN_CTX *new_ctx = NULL;
74 BIGNUM *tmp1, *tmp2, *x, *y;
75 int ret = 0;
76
77 /* clear error queue*/
78 ERR_clear_error();
79
80 if (ctx == NULL)
81 {
82 ctx = new_ctx = BN_CTX_new();
83 if (ctx == NULL)
84 return 0;
85 }
86
87 y_bit = (y_bit != 0);
88
89 BN_CTX_start(ctx);
90 tmp1 = BN_CTX_get(ctx);
91 tmp2 = BN_CTX_get(ctx);
92 x = BN_CTX_get(ctx);
93 y = BN_CTX_get(ctx);
94 if (y == NULL) goto err;
95
96 /* Recover y. We have a Weierstrass equation
97 * y^2 = x^3 + a*x + b,
98 * so y is one of the square roots of x^3 + a*x + b.
99 */
100
101 /* tmp1 := x^3 */
102 if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
103 if (group->meth->field_decode == 0)
104 {
105 /* field_{sqr,mul} work on standard representation */
106 if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
107 if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
108 }
109 else
110 {
111 if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
112 if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
113 }
114
115 /* tmp1 := tmp1 + a*x */
116 if (group->a_is_minus3)
117 {
118 if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
119 if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
120 if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
121 }
122 else
123 {
124 if (group->meth->field_decode)
125 {
126 if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
127 if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
128 }
129 else
130 {
131 /* field_mul works on standard representation */
132 if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
133 }
134
135 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
136 }
137
138 /* tmp1 := tmp1 + b */
139 if (group->meth->field_decode)
140 {
141 if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
142 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
143 }
144 else
145 {
146 if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
147 }
148
149 if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
150 {
151 unsigned long err = ERR_peek_last_error();
152
153 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
154 {
155 ERR_clear_error();
156 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
157 }
158 else
159 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
160 goto err;
161 }
162
163 if (y_bit != BN_is_odd(y))
164 {
165 if (BN_is_zero(y))
166 {
167 int kron;
168
169 kron = BN_kronecker(x, &group->field, ctx);
170 if (kron == -2) goto err;
171
172 if (kron == 1)
173 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
174 else
175 /* BN_mod_sqrt() should have cought this error (not a square) */
176 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
177 goto err;
178 }
179 if (!BN_usub(y, &group->field, y)) goto err;
180 }
181 if (y_bit != BN_is_odd(y))
182 {
183 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
184 goto err;
185 }
186
187 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
188
189 ret = 1;
190
191 err:
192 BN_CTX_end(ctx);
193 if (new_ctx != NULL)
194 BN_CTX_free(new_ctx);
195 return ret;
196 }
197
198
199size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
200 unsigned char *buf, size_t len, BN_CTX *ctx)
201 {
202 size_t ret;
203 BN_CTX *new_ctx = NULL;
204 int used_ctx = 0;
205 BIGNUM *x, *y;
206 size_t field_len, i, skip;
207
208 if ((form != POINT_CONVERSION_COMPRESSED)
209 && (form != POINT_CONVERSION_UNCOMPRESSED)
210 && (form != POINT_CONVERSION_HYBRID))
211 {
212 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
213 goto err;
214 }
215
216 if (EC_POINT_is_at_infinity(group, point))
217 {
218 /* encodes to a single 0 octet */
219 if (buf != NULL)
220 {
221 if (len < 1)
222 {
223 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
224 return 0;
225 }
226 buf[0] = 0;
227 }
228 return 1;
229 }
230
231
232 /* ret := required output buffer length */
233 field_len = BN_num_bytes(&group->field);
234 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
235
236 /* if 'buf' is NULL, just return required length */
237 if (buf != NULL)
238 {
239 if (len < ret)
240 {
241 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
242 goto err;
243 }
244
245 if (ctx == NULL)
246 {
247 ctx = new_ctx = BN_CTX_new();
248 if (ctx == NULL)
249 return 0;
250 }
251
252 BN_CTX_start(ctx);
253 used_ctx = 1;
254 x = BN_CTX_get(ctx);
255 y = BN_CTX_get(ctx);
256 if (y == NULL) goto err;
257
258 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
259
260 if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
261 buf[0] = form + 1;
262 else
263 buf[0] = form;
264
265 i = 1;
266
267 skip = field_len - BN_num_bytes(x);
268 if (skip > field_len)
269 {
270 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
271 goto err;
272 }
273 while (skip > 0)
274 {
275 buf[i++] = 0;
276 skip--;
277 }
278 skip = BN_bn2bin(x, buf + i);
279 i += skip;
280 if (i != 1 + field_len)
281 {
282 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
283 goto err;
284 }
285
286 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
287 {
288 skip = field_len - BN_num_bytes(y);
289 if (skip > field_len)
290 {
291 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
292 goto err;
293 }
294 while (skip > 0)
295 {
296 buf[i++] = 0;
297 skip--;
298 }
299 skip = BN_bn2bin(y, buf + i);
300 i += skip;
301 }
302
303 if (i != ret)
304 {
305 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
306 goto err;
307 }
308 }
309
310 if (used_ctx)
311 BN_CTX_end(ctx);
312 if (new_ctx != NULL)
313 BN_CTX_free(new_ctx);
314 return ret;
315
316 err:
317 if (used_ctx)
318 BN_CTX_end(ctx);
319 if (new_ctx != NULL)
320 BN_CTX_free(new_ctx);
321 return 0;
322 }
323
324
325int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
326 const unsigned char *buf, size_t len, BN_CTX *ctx)
327 {
328 point_conversion_form_t form;
329 int y_bit;
330 BN_CTX *new_ctx = NULL;
331 BIGNUM *x, *y;
332 size_t field_len, enc_len;
333 int ret = 0;
334
335 if (len == 0)
336 {
337 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
338 return 0;
339 }
340 form = buf[0];
341 y_bit = form & 1;
342 form = form & ~1U;
343 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
344 && (form != POINT_CONVERSION_UNCOMPRESSED)
345 && (form != POINT_CONVERSION_HYBRID))
346 {
347 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
348 return 0;
349 }
350 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
351 {
352 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
353 return 0;
354 }
355
356 if (form == 0)
357 {
358 if (len != 1)
359 {
360 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
361 return 0;
362 }
363
364 return EC_POINT_set_to_infinity(group, point);
365 }
366
367 field_len = BN_num_bytes(&group->field);
368 enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
369
370 if (len != enc_len)
371 {
372 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
373 return 0;
374 }
375
376 if (ctx == NULL)
377 {
378 ctx = new_ctx = BN_CTX_new();
379 if (ctx == NULL)
380 return 0;
381 }
382
383 BN_CTX_start(ctx);
384 x = BN_CTX_get(ctx);
385 y = BN_CTX_get(ctx);
386 if (y == NULL) goto err;
387
388 if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
389 if (BN_ucmp(x, &group->field) >= 0)
390 {
391 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
392 goto err;
393 }
394
395 if (form == POINT_CONVERSION_COMPRESSED)
396 {
397 if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
398 }
399 else
400 {
401 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
402 if (BN_ucmp(y, &group->field) >= 0)
403 {
404 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
405 goto err;
406 }
407 if (form == POINT_CONVERSION_HYBRID)
408 {
409 if (y_bit != BN_is_odd(y))
410 {
411 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
412 goto err;
413 }
414 }
415
416 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
417 }
418
419 if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
420 {
421 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
422 goto err;
423 }
424
425 ret = 1;
426
427 err:
428 BN_CTX_end(ctx);
429 if (new_ctx != NULL)
430 BN_CTX_free(new_ctx);
431 return ret;
432 }
433
diff --git a/src/lib/libcrypto/ec/ecp_smpl.c b/src/lib/libcrypto/ec/ecp_smpl.c
index 66a92e2a90..7cbb321f9a 100644
--- a/src/lib/libcrypto/ec/ecp_smpl.c
+++ b/src/lib/libcrypto/ec/ecp_smpl.c
@@ -65,11 +65,19 @@
65#include <openssl/err.h> 65#include <openssl/err.h>
66#include <openssl/symhacks.h> 66#include <openssl/symhacks.h>
67 67
68#ifdef OPENSSL_FIPS
69#include <openssl/fips.h>
70#endif
71
68#include "ec_lcl.h" 72#include "ec_lcl.h"
69 73
70const EC_METHOD *EC_GFp_simple_method(void) 74const EC_METHOD *EC_GFp_simple_method(void)
71 { 75 {
76#ifdef OPENSSL_FIPS
77 return fips_ec_gfp_simple_method();
78#else
72 static const EC_METHOD ret = { 79 static const EC_METHOD ret = {
80 EC_FLAGS_DEFAULT_OCT,
73 NID_X9_62_prime_field, 81 NID_X9_62_prime_field,
74 ec_GFp_simple_group_init, 82 ec_GFp_simple_group_init,
75 ec_GFp_simple_group_finish, 83 ec_GFp_simple_group_finish,
@@ -88,9 +96,7 @@ const EC_METHOD *EC_GFp_simple_method(void)
88 ec_GFp_simple_get_Jprojective_coordinates_GFp, 96 ec_GFp_simple_get_Jprojective_coordinates_GFp,
89 ec_GFp_simple_point_set_affine_coordinates, 97 ec_GFp_simple_point_set_affine_coordinates,
90 ec_GFp_simple_point_get_affine_coordinates, 98 ec_GFp_simple_point_get_affine_coordinates,
91 ec_GFp_simple_set_compressed_coordinates, 99 0,0,0,
92 ec_GFp_simple_point2oct,
93 ec_GFp_simple_oct2point,
94 ec_GFp_simple_add, 100 ec_GFp_simple_add,
95 ec_GFp_simple_dbl, 101 ec_GFp_simple_dbl,
96 ec_GFp_simple_invert, 102 ec_GFp_simple_invert,
@@ -110,6 +116,7 @@ const EC_METHOD *EC_GFp_simple_method(void)
110 0 /* field_set_to_one */ }; 116 0 /* field_set_to_one */ };
111 117
112 return &ret; 118 return &ret;
119#endif
113 } 120 }
114 121
115 122
@@ -633,372 +640,6 @@ int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_P
633 return ret; 640 return ret;
634 } 641 }
635 642
636
637int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
638 const BIGNUM *x_, int y_bit, BN_CTX *ctx)
639 {
640 BN_CTX *new_ctx = NULL;
641 BIGNUM *tmp1, *tmp2, *x, *y;
642 int ret = 0;
643
644 /* clear error queue*/
645 ERR_clear_error();
646
647 if (ctx == NULL)
648 {
649 ctx = new_ctx = BN_CTX_new();
650 if (ctx == NULL)
651 return 0;
652 }
653
654 y_bit = (y_bit != 0);
655
656 BN_CTX_start(ctx);
657 tmp1 = BN_CTX_get(ctx);
658 tmp2 = BN_CTX_get(ctx);
659 x = BN_CTX_get(ctx);
660 y = BN_CTX_get(ctx);
661 if (y == NULL) goto err;
662
663 /* Recover y. We have a Weierstrass equation
664 * y^2 = x^3 + a*x + b,
665 * so y is one of the square roots of x^3 + a*x + b.
666 */
667
668 /* tmp1 := x^3 */
669 if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
670 if (group->meth->field_decode == 0)
671 {
672 /* field_{sqr,mul} work on standard representation */
673 if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
674 if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
675 }
676 else
677 {
678 if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
679 if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
680 }
681
682 /* tmp1 := tmp1 + a*x */
683 if (group->a_is_minus3)
684 {
685 if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
686 if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
687 if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
688 }
689 else
690 {
691 if (group->meth->field_decode)
692 {
693 if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
694 if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
695 }
696 else
697 {
698 /* field_mul works on standard representation */
699 if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
700 }
701
702 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
703 }
704
705 /* tmp1 := tmp1 + b */
706 if (group->meth->field_decode)
707 {
708 if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
709 if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
710 }
711 else
712 {
713 if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
714 }
715
716 if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
717 {
718 unsigned long err = ERR_peek_last_error();
719
720 if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
721 {
722 ERR_clear_error();
723 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
724 }
725 else
726 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
727 goto err;
728 }
729
730 if (y_bit != BN_is_odd(y))
731 {
732 if (BN_is_zero(y))
733 {
734 int kron;
735
736 kron = BN_kronecker(x, &group->field, ctx);
737 if (kron == -2) goto err;
738
739 if (kron == 1)
740 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT);
741 else
742 /* BN_mod_sqrt() should have cought this error (not a square) */
743 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
744 goto err;
745 }
746 if (!BN_usub(y, &group->field, y)) goto err;
747 }
748 if (y_bit != BN_is_odd(y))
749 {
750 ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR);
751 goto err;
752 }
753
754 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
755
756 ret = 1;
757
758 err:
759 BN_CTX_end(ctx);
760 if (new_ctx != NULL)
761 BN_CTX_free(new_ctx);
762 return ret;
763 }
764
765
766size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
767 unsigned char *buf, size_t len, BN_CTX *ctx)
768 {
769 size_t ret;
770 BN_CTX *new_ctx = NULL;
771 int used_ctx = 0;
772 BIGNUM *x, *y;
773 size_t field_len, i, skip;
774
775 if ((form != POINT_CONVERSION_COMPRESSED)
776 && (form != POINT_CONVERSION_UNCOMPRESSED)
777 && (form != POINT_CONVERSION_HYBRID))
778 {
779 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
780 goto err;
781 }
782
783 if (EC_POINT_is_at_infinity(group, point))
784 {
785 /* encodes to a single 0 octet */
786 if (buf != NULL)
787 {
788 if (len < 1)
789 {
790 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
791 return 0;
792 }
793 buf[0] = 0;
794 }
795 return 1;
796 }
797
798
799 /* ret := required output buffer length */
800 field_len = BN_num_bytes(&group->field);
801 ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
802
803 /* if 'buf' is NULL, just return required length */
804 if (buf != NULL)
805 {
806 if (len < ret)
807 {
808 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
809 goto err;
810 }
811
812 if (ctx == NULL)
813 {
814 ctx = new_ctx = BN_CTX_new();
815 if (ctx == NULL)
816 return 0;
817 }
818
819 BN_CTX_start(ctx);
820 used_ctx = 1;
821 x = BN_CTX_get(ctx);
822 y = BN_CTX_get(ctx);
823 if (y == NULL) goto err;
824
825 if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
826
827 if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
828 buf[0] = form + 1;
829 else
830 buf[0] = form;
831
832 i = 1;
833
834 skip = field_len - BN_num_bytes(x);
835 if (skip > field_len)
836 {
837 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
838 goto err;
839 }
840 while (skip > 0)
841 {
842 buf[i++] = 0;
843 skip--;
844 }
845 skip = BN_bn2bin(x, buf + i);
846 i += skip;
847 if (i != 1 + field_len)
848 {
849 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
850 goto err;
851 }
852
853 if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
854 {
855 skip = field_len - BN_num_bytes(y);
856 if (skip > field_len)
857 {
858 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
859 goto err;
860 }
861 while (skip > 0)
862 {
863 buf[i++] = 0;
864 skip--;
865 }
866 skip = BN_bn2bin(y, buf + i);
867 i += skip;
868 }
869
870 if (i != ret)
871 {
872 ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
873 goto err;
874 }
875 }
876
877 if (used_ctx)
878 BN_CTX_end(ctx);
879 if (new_ctx != NULL)
880 BN_CTX_free(new_ctx);
881 return ret;
882
883 err:
884 if (used_ctx)
885 BN_CTX_end(ctx);
886 if (new_ctx != NULL)
887 BN_CTX_free(new_ctx);
888 return 0;
889 }
890
891
892int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
893 const unsigned char *buf, size_t len, BN_CTX *ctx)
894 {
895 point_conversion_form_t form;
896 int y_bit;
897 BN_CTX *new_ctx = NULL;
898 BIGNUM *x, *y;
899 size_t field_len, enc_len;
900 int ret = 0;
901
902 if (len == 0)
903 {
904 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
905 return 0;
906 }
907 form = buf[0];
908 y_bit = form & 1;
909 form = form & ~1U;
910 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
911 && (form != POINT_CONVERSION_UNCOMPRESSED)
912 && (form != POINT_CONVERSION_HYBRID))
913 {
914 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
915 return 0;
916 }
917 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
918 {
919 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
920 return 0;
921 }
922
923 if (form == 0)
924 {
925 if (len != 1)
926 {
927 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
928 return 0;
929 }
930
931 return EC_POINT_set_to_infinity(group, point);
932 }
933
934 field_len = BN_num_bytes(&group->field);
935 enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
936
937 if (len != enc_len)
938 {
939 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
940 return 0;
941 }
942
943 if (ctx == NULL)
944 {
945 ctx = new_ctx = BN_CTX_new();
946 if (ctx == NULL)
947 return 0;
948 }
949
950 BN_CTX_start(ctx);
951 x = BN_CTX_get(ctx);
952 y = BN_CTX_get(ctx);
953 if (y == NULL) goto err;
954
955 if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
956 if (BN_ucmp(x, &group->field) >= 0)
957 {
958 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
959 goto err;
960 }
961
962 if (form == POINT_CONVERSION_COMPRESSED)
963 {
964 if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
965 }
966 else
967 {
968 if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
969 if (BN_ucmp(y, &group->field) >= 0)
970 {
971 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
972 goto err;
973 }
974 if (form == POINT_CONVERSION_HYBRID)
975 {
976 if (y_bit != BN_is_odd(y))
977 {
978 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
979 goto err;
980 }
981 }
982
983 if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
984 }
985
986 if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
987 {
988 ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
989 goto err;
990 }
991
992 ret = 1;
993
994 err:
995 BN_CTX_end(ctx);
996 if (new_ctx != NULL)
997 BN_CTX_free(new_ctx);
998 return ret;
999 }
1000
1001
1002int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) 643int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
1003 { 644 {
1004 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); 645 int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);