external/boringssl: sync to 7b8b9c17
This includes the following changes from BoringSSL :
7b8b9c1 Include 'asm' in the name of X25519 asm sources.
3202750 Update the fuzz tests for the server.
6544426 Fix a ** 0 mod 1 = 0 for real this time.
fe5f7c7 Only reserve EVP_MAX_MD_SIZE for the Finished, not twice of it.
0d56f88 Switch s to ssl everywhere.
974c7ba Route DHE through the SSL_ECDH abstraction as well.
4cc36ad Make it possible to tell what curve was used on the server.
4298d77 Implement draft-ietf-tls-curve25519-01 in C.
c18ef75 Allocate a NID for X25519.
3a2a480 Remove long-dead comment.
cba2b62 Implement draft-ietf-tls-curve25519-01 in Go.
ab14563 Bundle a copy of golang.org/x/crypto/curve25519 for testing.
a029ebc Switch the bundled poly1305 to relative imports.
64d9250 Completely remove P-224 from the TLS stack.
8c2b3bf Test all supported curves (including those off by default).
fc82512 Convert ssl3_send_cert_verify to CBB.
5fb18c6 Make MSVC happy.
2a0b391 Rewrite ssl3_send_server_key_exchange to use CBB.
d16bf34 Add a -lldb flag to runner.go.
af21bcf Remove other unnecessary BN_CTX allocations.
ae0eaaa Convert ssl3_send_client_key_exchange to CBB.
3ac4b3a Remove NO_ASM define that I accidently included in the previous commit.
e6c5402 Don't build X25519 asm code when NO_ASM is set.
77a173e Add x86-64 assembly for X25519.
c75c0ae Add #defines for ED25519 key and signature lengths.
48cce66 Tidy up ssl3_get_server_key_exchange slightly.
c1cc858 Check for EC_KEY_set_public_key error.
4cc671c Add CBB_reserve and CBB_did_write.
e13263d Resolve a few old TODOs.
841934f Remove stack macros for nonexistent types.
70ab223 Remove ASN1_R_MALLOC_FAILURE.
b965c63 Reject calls to X509_verify_cert that have not been reinitialised
3f5b43d Simplify RSA key exchange padding check.
3ef6085 Refuse to parse RSA pubkeys with invalid exponents.
afe57cb Add a tool to generate Ed25519 keys.
77c3c0b Enable Ed25519 when building with OPENSSL_SMALL.
9f897b2 Remove the stitched RC4-MD5 code and use the generic one.
1741a9d Save some mallocs in computing the MAC for e_tls.c.
df57163 Add RC4-SHA1 and DES-EDE3-CBC-SHA1 to bssl speed.
13414b3 Implement draft-ietf-tls-chacha20-poly1305-04.
3748990 Implement draft-ietf-tls-chacha20-poly1305-04 in Go.
2089fdd Implement RFC 7539 in Go.
86e412d Add client cert support to bssl client.
23a681b Fix build.
e320392 Rename the Go ChaCha20-Poly1305 implementation.
8ffab72 Point EVP_aead_chacha20_poly1305 at the standardized version.
fef6fb5 Fix ChaCha20-Poly1305 tests.
60a08ac Remove unreachable code to duplicate DH keys.
4ec0cce Slightly tweak some array allocations.
2936170 Fix memory leak in DSA redo case.
a01deee Make CBB_len relative to its argument.
77385bb Mark platform-specific HOST_[c2l|l2c] as (void).
6969971 Remove a dead prototype.
1b36716 Remove crypto/header_removed.h.
017231a Remove asm __asm__ define.
793c21e Make HOST_l2c return void.
0aff3ff Store the partial block as uint8_t, not uint32_t.
5a19d7d Use the straight-forward ROTATE macro.
78fefbf Reformat md32_common.h, part 2.
fea1137 Reformat md32_common.h, part 1.
871fff0 *_Update of length zero is legal.
d9f0671 Remove |need_record_splitting| from |SSL3_STATE|.
cd48038 Remove unused fields from SSL3_STATE.
7fc0100 Slightly simplify SSL3_RECORD.
ece5ba2 Reset ssl error codes.
a41280d Pull ChangeCipherSpec into the handshake state machine.
8fd5c23 Simplify fragmented HelloRequest state.
ef5dfd2 Add tests for malformed HelloRequests.
8411b24 Add tests for bad ChangeCipherSpecs.
502a843 Switch unrolled loop in BN_usub with memcpy.
c3ae38b Remove DH EVP_PKEY hooks.
7100ee9 Chromium's update.sh is dead, long live update.py
f28dd64 Fix flaky BadRSAClientKeyExchange-1 test.
4234885 Remove unused functions.
45dab25 Skip free callbacks on empty CRYPTO_EX_DATAs.
8a58933 Remove the CRYPTO_EX_new callback.
0abd6f2 Get struct timeval from sys/time.h.
1246670 Use UINT64_C in sha512.c table.
5ddffbb Make SSL_(CTX_)?set_tmp_ecdh call SSL_(CTX_)?set1_curves.
53e5c2c Remove SSL_(CTX_)?set_ecdh_callback.
756ad17 Initialize |one_index| in OAEP padding check.
1634a33 Convert rsa/padding.c to constant-time helpers.
b36a395 Add slightly better RSA key exchange tests.
0bd71eb Remove weird ret negation logic.
e9cddb8 Remove SSL_OP_LEGACY_SERVER_CONNECT.
3e052de Tighten SSL_OP_LEGACY_SERVER_CONNECT to align with RFC 5746.
03f0005 Remove SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER.
ef5e515 Remove SSL_OP_TLS_D5_BUG.
c100ef4 Limit depth of ASN1 parse printing.
2205093 Add a comment in SetTestState from bssl_shim.
6ae67df Don't leak Android hacks to other build platforms.
a0ef7b0 Enforce that |EC_KEY| private key is in [0, group->order).
533a273 Add |EC_METHOD| method for verifying public key order.
a3d9de0 Add |EC_GROUP_get0_order| to replace |EC_GROUP_get_order|.
8847856 Include <sys/time.h> in packeted_bio.h for 'timeval'
dca63cf Don't abort in |init_once| if |fcntl| returns ENOSYS
afd565f Add defines for SRTP profiles using GCM ciphers from RFC 7714.
902870e Gate SHA_CTX compatibility on !WINDOWS.
34aa55c Support the SHA_CTX hack without ANDROID.
6d9e5a7 Re-apply 75b833cc819a9d189adb0fdd56327bee600ff9e9
28243c0 Add PSS parameter check.
e701f16 bn/asm/x86_64-mont5.pl: fix carry propagating bug (CVE-2015-3193).
cb85298 Fix leak with ASN.1 combine.
c4f25ce Work around yaSSL bug.
c5eb467 Remove dead code in p256-x86_64.
758d127 Add get0 getters for EVP_PKEY.
fde89b4 avoid clashes with libc's 'open' in e_chacha20poly1305.c
60a45aa Remove reference to removed |RSA_FLAG_NO_CONSTTIME| flag.
81edc9b Do away with BN_LLONG in favor of BN_ULLONG.
e8fe07f Fix AES XTS mode key size.
93a5b44 Make CRYPTO_library_init use a CRYPTO_once_t.
bf76218 Remove the |ri| field of |BN_MONT_CTX|.
596ab10 s/BN_BITS/BN_BITS2/ in |BN_mod_inverse_ex|; remove |BN_BITS| & |BN_MASK|.
7af36e1 Share common definitions of |TOBN| and |BIGNUM_STATIC|.
ff2df33 Reformat the cipher suite table.
9f2e277 Remove strength_bits.
d6e9eec Remove algo_strength.
dcb6ef0 Remove algorithm_ssl.
d28f59c Switch the keylog BIO to a callback.
fba735c Register the *25519 tests as dependencies of all_tests.
f3376ac Remove |EC_POINTs_mul| & simplify p256-x86_64.
301efc8 Fix error handling in |p256-x86_64|.
e2136d9 Remove |EC_GROUP_precompute_mult| and |EC_KEY_precompute_mult|.
9b26297 Make |EC_GROUP_precompute_mult|/|EC_KEY_precompute_mult| no-ops.
5058d79 Remove p224-64 and p256-64 dead code for non-default generators.
b1b6229 Add NEON implementation of curve25519.
9e65d48 Allow |CRYPTO_is_NEON_capable| to be known at compile time, if possible.
3ac32b1 Fix curve25519 code for MSVC.
4fb0dc4 Add X25519 and Ed25519 support.
c324f17 Make sure pthread_once() succeeds.
9361243 Don't include <alloca.h>, it's no longer needed.
b00061c Add SSL_CIPHER_is_AES[128|256]CBC.
3a59611 size_t SSL*_use_*_ASN1.
b324159 Fix ssl3_send_server_key_exchange error path.
f584a5a Reset epoch state in one place.
2077cf9 Use UINT64_C instead of OPENSSL_U64.
af07365 Check for overflow when parsing a CBS with d2i_*.
780cd92 modes/asm/ghash-armv4.pl: extend Apple fix to all clang cases.
f9c77de Drop CBB allocation failure test.
a33915d Have |CBB_init| zero the |CBB| before any possible failures.
c5c85de Make RAND_seed read a byte of random data.
d9e2702 Don't encode or decode ∞.
e7806fd Remove point-on-curve check from |ec_GFp_simple_oct2point|.
20c3731 Become partially -Wmissing-variable-declarations-clean.
7308aaa Remove `EC_GFp_simple_method` (dead code).
f872951 Fix null pointer dereference when using "simple" EC.
8bde5d2 Remove the unused |Ni| member of |BN_MONT_CTX|.
ce7ae6f Enable AVX code for SHA-*.
9f1f04f Remove nistz256 dead code for non-default generators.
d7421eb Remove condition which always evaluates to true (size_t >= 0).
d386394 Test for underflow before subtraction.
ef14b2d Remove stl_compat.h.
cd24a39 Limit DHE groups to 4096-bit.
99fdfb9 Move curve check out of tls12_check_peer_sigalg.
Change-Id: Id2d7110569d250b1bae8f8ce7d4421a92f581a31
diff --git a/src/crypto/ec/wnaf.c b/src/crypto/ec/wnaf.c
index 4aaffd9..ba2257c 100644
--- a/src/crypto/ec/wnaf.c
+++ b/src/crypto/ec/wnaf.c
@@ -80,65 +80,8 @@
/* This file implements the wNAF-based interleaving multi-exponentation method
* (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>);
- * for multiplication with precomputation, we use wNAF splitting
- * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp>).
* */
-/* structure for precomputed multiples of the generator */
-typedef struct ec_pre_comp_st {
- size_t blocksize; /* block size for wNAF splitting */
- size_t numblocks; /* max. number of blocks for which we have precomputation */
- size_t w; /* window size */
- EC_POINT **points; /* array with pre-calculated multiples of generator:
- * 'num' pointers to EC_POINT objects followed by a NULL */
- size_t num; /* numblocks * 2^(w-1) */
- CRYPTO_refcount_t references;
-} EC_PRE_COMP;
-
-static EC_PRE_COMP *ec_pre_comp_new(void) {
- EC_PRE_COMP *ret = NULL;
-
- ret = (EC_PRE_COMP *)OPENSSL_malloc(sizeof(EC_PRE_COMP));
- if (!ret) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- return ret;
- }
- ret->blocksize = 8; /* default */
- ret->numblocks = 0;
- ret->w = 4; /* default */
- ret->points = NULL;
- ret->num = 0;
- ret->references = 1;
- return ret;
-}
-
-void *ec_pre_comp_dup(EC_PRE_COMP *pre_comp) {
- if (pre_comp == NULL) {
- return NULL;
- }
-
- CRYPTO_refcount_inc(&pre_comp->references);
- return pre_comp;
-}
-
-void ec_pre_comp_free(EC_PRE_COMP *pre_comp) {
- if (pre_comp == NULL ||
- !CRYPTO_refcount_dec_and_test_zero(&pre_comp->references)) {
- return;
- }
-
- if (pre_comp->points) {
- EC_POINT **p;
-
- for (p = pre_comp->points; *p != NULL; p++) {
- EC_POINT_free(*p);
- }
- OPENSSL_free(pre_comp->points);
- }
- OPENSSL_free(pre_comp);
-}
-
-
/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'.
* This is an array r[] of values that are either zero or odd with an
* absolute value less than 2^w satisfying
@@ -281,21 +224,12 @@
? 2 \
: 1))
-/* Compute
- * \sum scalars[i]*points[i],
- * also including
- * scalar*generator
- * in the addition if scalar != NULL
- */
-int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
- size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
- BN_CTX *ctx) {
+int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
+ const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) {
BN_CTX *new_ctx = NULL;
const EC_POINT *generator = NULL;
EC_POINT *tmp = NULL;
- size_t totalnum;
- size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */
- size_t pre_points_per_block = 0;
+ size_t total_num;
size_t i, j;
int k;
int r_is_inverted = 0;
@@ -307,30 +241,9 @@
size_t num_val;
EC_POINT **val = NULL; /* precomputation */
EC_POINT **v;
- EC_POINT ***val_sub =
- NULL; /* pointers to sub-arrays of 'val' or 'pre_comp->points' */
- const EC_PRE_COMP *pre_comp = NULL;
- int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be treated like
- * other scalars,
- * i.e. precomputation is not available */
+ EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' */
int ret = 0;
- if (group->meth != r->meth) {
- OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
- return 0;
- }
-
- if ((scalar == NULL) && (num == 0)) {
- return EC_POINT_set_to_infinity(group, r);
- }
-
- for (i = 0; i < num; i++) {
- if (group->meth != points[i]->meth) {
- OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
- return 0;
- }
- }
-
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
@@ -338,52 +251,31 @@
}
}
- if (scalar != NULL) {
+ /* TODO: This function used to take |points| and |scalars| as arrays of
+ * |num| elements. The code below should be simplified to work in terms of |p|
+ * and |p_scalar|. */
+ size_t num = p != NULL ? 1 : 0;
+ const EC_POINT **points = p != NULL ? &p : NULL;
+ const BIGNUM **scalars = p != NULL ? &p_scalar : NULL;
+
+ total_num = num;
+
+ if (g_scalar != NULL) {
generator = EC_GROUP_get0_generator(group);
if (generator == NULL) {
OPENSSL_PUT_ERROR(EC, EC_R_UNDEFINED_GENERATOR);
goto err;
}
- /* look if we can use precomputed multiples of generator */
-
- pre_comp = group->pre_comp;
-
- if (pre_comp && pre_comp->numblocks &&
- (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) == 0)) {
- blocksize = pre_comp->blocksize;
-
- /* determine maximum number of blocks that wNAF splitting may yield
- * (NB: maximum wNAF length is bit length plus one) */
- numblocks = (BN_num_bits(scalar) / blocksize) + 1;
-
- /* we cannot use more blocks than we have precomputation for */
- if (numblocks > pre_comp->numblocks) {
- numblocks = pre_comp->numblocks;
- }
-
- pre_points_per_block = (size_t)1 << (pre_comp->w - 1);
-
- /* check that pre_comp looks sane */
- if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- } else {
- /* can't use precomputation */
- pre_comp = NULL;
- numblocks = 1;
- num_scalar = 1; /* treat 'scalar' like 'num'-th element of 'scalars' */
- }
+ ++total_num; /* treat 'g_scalar' like 'num'-th element of 'scalars' */
}
- totalnum = num + numblocks;
- wsize = OPENSSL_malloc(totalnum * sizeof wsize[0]);
- wNAF_len = OPENSSL_malloc(totalnum * sizeof wNAF_len[0]);
- wNAF = OPENSSL_malloc((totalnum + 1) *
+ wsize = OPENSSL_malloc(total_num * sizeof wsize[0]);
+ wNAF_len = OPENSSL_malloc(total_num * sizeof wNAF_len[0]);
+ wNAF = OPENSSL_malloc((total_num + 1) *
sizeof wNAF[0]); /* includes space for pivot */
- val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]);
+ val_sub = OPENSSL_malloc(total_num * sizeof val_sub[0]);
/* Ensure wNAF is initialised in case we end up going to err. */
if (wNAF) {
@@ -398,15 +290,15 @@
/* num_val will be the total number of temporarily precomputed points */
num_val = 0;
- for (i = 0; i < num + num_scalar; i++) {
+ for (i = 0; i < total_num; i++) {
size_t bits;
- bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);
+ bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(g_scalar);
wsize[i] = EC_window_bits_for_scalar_size(bits);
num_val += (size_t)1 << (wsize[i] - 1);
wNAF[i + 1] = NULL; /* make sure we always have a pivot */
wNAF[i] =
- compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], &wNAF_len[i]);
+ compute_wNAF((i < num ? scalars[i] : g_scalar), wsize[i], &wNAF_len[i]);
if (wNAF[i] == NULL) {
goto err;
}
@@ -415,110 +307,8 @@
}
}
- if (numblocks) {
- /* we go here iff scalar != NULL */
-
- if (pre_comp == NULL) {
- if (num_scalar != 1) {
- OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- /* we have already generated a wNAF for 'scalar' */
- } else {
- signed char *tmp_wNAF = NULL;
- size_t tmp_len = 0;
-
- if (num_scalar != 0) {
- OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* use the window size for which we have precomputation */
- wsize[num] = pre_comp->w;
- tmp_wNAF = compute_wNAF(scalar, wsize[num], &tmp_len);
- if (!tmp_wNAF) {
- goto err;
- }
-
- if (tmp_len <= max_len) {
- /* One of the other wNAFs is at least as long
- * as the wNAF belonging to the generator,
- * so wNAF splitting will not buy us anything. */
-
- numblocks = 1; /* don't use wNAF splitting */
- totalnum = num + numblocks;
- wNAF[num] = tmp_wNAF;
- wNAF[num + 1] = NULL;
- wNAF_len[num] = tmp_len;
- /* pre_comp->points starts with the points that we need here: */
- val_sub[num] = pre_comp->points;
- } else {
- /* don't include tmp_wNAF directly into wNAF array
- * - use wNAF splitting and include the blocks */
-
- signed char *pp;
- EC_POINT **tmp_points;
-
- if (tmp_len < numblocks * blocksize) {
- /* possibly we can do with fewer blocks than estimated */
- numblocks = (tmp_len + blocksize - 1) / blocksize;
- if (numblocks > pre_comp->numblocks) {
- OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
- OPENSSL_free(tmp_wNAF);
- goto err;
- }
- totalnum = num + numblocks;
- }
-
- /* split wNAF in 'numblocks' parts */
- pp = tmp_wNAF;
- tmp_points = pre_comp->points;
-
- for (i = num; i < totalnum; i++) {
- if (i < totalnum - 1) {
- wNAF_len[i] = blocksize;
- if (tmp_len < blocksize) {
- OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
- OPENSSL_free(tmp_wNAF);
- goto err;
- }
- tmp_len -= blocksize;
- } else {
- /* last block gets whatever is left
- * (this could be more or less than 'blocksize'!) */
- wNAF_len[i] = tmp_len;
- }
-
- wNAF[i + 1] = NULL;
- wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
- if (wNAF[i] == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(tmp_wNAF);
- goto err;
- }
- memcpy(wNAF[i], pp, wNAF_len[i]);
- if (wNAF_len[i] > max_len) {
- max_len = wNAF_len[i];
- }
-
- if (*tmp_points == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
- OPENSSL_free(tmp_wNAF);
- goto err;
- }
- val_sub[i] = tmp_points;
- tmp_points += pre_points_per_block;
- pp += blocksize;
- }
- OPENSSL_free(tmp_wNAF);
- }
- }
- }
-
- /* All points we precompute now go into a single array 'val'.
- * 'val_sub[i]' is a pointer to the subarray for the i-th point,
- * or to a subarray of 'pre_comp->points' if we already have precomputation.
- */
+ /* All points we precompute now go into a single array 'val'. 'val_sub[i]' is
+ * a pointer to the subarray for the i-th point. */
val = OPENSSL_malloc((num_val + 1) * sizeof val[0]);
if (val == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
@@ -528,7 +318,7 @@
/* allocate points for precomputation */
v = val;
- for (i = 0; i < num + num_scalar; i++) {
+ for (i = 0; i < total_num; i++) {
val_sub[i] = v;
for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) {
*v = EC_POINT_new(group);
@@ -553,7 +343,7 @@
* val_sub[i][2] := 5 * points[i]
* ...
*/
- for (i = 0; i < num + num_scalar; i++) {
+ for (i = 0; i < total_num; i++) {
if (i < num) {
if (!EC_POINT_copy(val_sub[i][0], points[i])) {
goto err;
@@ -587,7 +377,7 @@
goto err;
}
- for (i = 0; i < totalnum; i++) {
+ for (i = 0; i < total_num; i++) {
if (wNAF_len[i] > (size_t)k) {
int digit = wNAF[i][k];
int is_neg;
@@ -657,192 +447,3 @@
OPENSSL_free(val_sub);
return ret;
}
-
-
-/* ec_wNAF_precompute_mult()
- * creates an EC_PRE_COMP object with preprecomputed multiples of the generator
- * for use with wNAF splitting as implemented in ec_wNAF_mul().
- *
- * 'pre_comp->points' is an array of multiples of the generator
- * of the following form:
- * points[0] = generator;
- * points[1] = 3 * generator;
- * ...
- * points[2^(w-1)-1] = (2^(w-1)-1) * generator;
- * points[2^(w-1)] = 2^blocksize * generator;
- * points[2^(w-1)+1] = 3 * 2^blocksize * generator;
- * ...
- * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) * 2^(blocksize*(numblocks-2)) *
- *generator
- * points[2^(w-1)*(numblocks-1)] = 2^(blocksize*(numblocks-1)) *
- *generator
- * ...
- * points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) *
- *generator
- * points[2^(w-1)*numblocks] = NULL
- */
-int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
- const EC_POINT *generator;
- EC_POINT *tmp_point = NULL, *base = NULL, **var;
- BN_CTX *new_ctx = NULL;
- BIGNUM *order;
- size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;
- EC_POINT **points = NULL;
- EC_PRE_COMP *pre_comp;
- int ret = 0;
-
- /* if there is an old EC_PRE_COMP object, throw it away */
- ec_pre_comp_free(group->pre_comp);
- group->pre_comp = NULL;
-
- generator = EC_GROUP_get0_generator(group);
- if (generator == NULL) {
- OPENSSL_PUT_ERROR(EC, EC_R_UNDEFINED_GENERATOR);
- return 0;
- }
-
- pre_comp = ec_pre_comp_new();
- if (pre_comp == NULL) {
- return 0;
- }
-
- if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
- if (ctx == NULL) {
- goto err;
- }
- }
-
- BN_CTX_start(ctx);
- order = BN_CTX_get(ctx);
- if (order == NULL) {
- goto err;
- }
-
- if (!EC_GROUP_get_order(group, order, ctx)) {
- goto err;
- }
- if (BN_is_zero(order)) {
- OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_ORDER);
- goto err;
- }
-
- bits = BN_num_bits(order);
- /* The following parameters mean we precompute (approximately)
- * one point per bit.
- *
- * TBD: The combination 8, 4 is perfect for 160 bits; for other
- * bit lengths, other parameter combinations might provide better
- * efficiency.
- */
- blocksize = 8;
- w = 4;
- if (EC_window_bits_for_scalar_size(bits) > w) {
- /* let's not make the window too small ... */
- w = EC_window_bits_for_scalar_size(bits);
- }
-
- numblocks = (bits + blocksize - 1) /
- blocksize; /* max. number of blocks to use for wNAF splitting */
-
- pre_points_per_block = (size_t)1 << (w - 1);
- num = pre_points_per_block *
- numblocks; /* number of points to compute and store */
-
- points = OPENSSL_malloc(sizeof(EC_POINT *) * (num + 1));
- if (!points) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- var = points;
- var[num] = NULL; /* pivot */
- for (i = 0; i < num; i++) {
- if ((var[i] = EC_POINT_new(group)) == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
-
- if (!(tmp_point = EC_POINT_new(group)) || !(base = EC_POINT_new(group))) {
- OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!EC_POINT_copy(base, generator)) {
- goto err;
- }
-
- /* do the precomputation */
- for (i = 0; i < numblocks; i++) {
- size_t j;
-
- if (!EC_POINT_dbl(group, tmp_point, base, ctx)) {
- goto err;
- }
-
- if (!EC_POINT_copy(*var++, base)) {
- goto err;
- }
-
- for (j = 1; j < pre_points_per_block; j++, var++) {
- /* calculate odd multiples of the current base point */
- if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx)) {
- goto err;
- }
- }
-
- if (i < numblocks - 1) {
- /* get the next base (multiply current one by 2^blocksize) */
- size_t k;
-
- if (blocksize <= 2) {
- OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (!EC_POINT_dbl(group, base, tmp_point, ctx)) {
- goto err;
- }
- for (k = 2; k < blocksize; k++) {
- if (!EC_POINT_dbl(group, base, base, ctx)) {
- goto err;
- }
- }
- }
- }
-
- if (!EC_POINTs_make_affine(group, num, points, ctx)) {
- goto err;
- }
-
- pre_comp->blocksize = blocksize;
- pre_comp->numblocks = numblocks;
- pre_comp->w = w;
- pre_comp->points = points;
- points = NULL;
- pre_comp->num = num;
-
- group->pre_comp = pre_comp;
- pre_comp = NULL;
-
- ret = 1;
-
-err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- }
- BN_CTX_free(new_ctx);
- ec_pre_comp_free(pre_comp);
- if (points) {
- EC_POINT **p;
-
- for (p = points; *p != NULL; p++) {
- EC_POINT_free(*p);
- }
- OPENSSL_free(points);
- }
- EC_POINT_free(tmp_point);
- EC_POINT_free(base);
- return ret;
-}