-/* crypto/ec/ec_mult.c */
/*
- * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
- */
-/* ====================================================================
- * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
+ * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
*
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
*/
+
/* ====================================================================
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
* Portions of this software developed by SUN MICROSYSTEMS, INC.,
#include <string.h>
#include <openssl/err.h>
+#include "internal/cryptlib.h"
#include "internal/bn_int.h"
#include "ec_lcl.h"
/*
- * This file implements the wNAF-based interleaving multi-exponentation method
+ * This file implements the wNAF-based interleaving multi-exponentiation 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 {
+struct ec_pre_comp_st {
const EC_GROUP *group; /* parent EC_GROUP object */
size_t blocksize; /* block size for wNAF splitting */
size_t numblocks; /* max. number of blocks for which we have
* objects followed by a NULL */
size_t num; /* numblocks * 2^(w-1) */
int references;
-} EC_PRE_COMP;
-
-/* functions to manage EC_PRE_COMP within the EC_GROUP extra_data framework */
-static void *ec_pre_comp_dup(void *);
-static void ec_pre_comp_free(void *);
-static void ec_pre_comp_clear_free(void *);
+ CRYPTO_RWLOCK *lock;
+};
static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group)
{
if (!group)
return NULL;
- ret = OPENSSL_malloc(sizeof(EC_PRE_COMP));
- if (!ret) {
+ ret = OPENSSL_zalloc(sizeof(*ret));
+ if (ret == NULL) {
ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
return ret;
}
+
ret->group = group;
ret->blocksize = 8; /* default */
- ret->numblocks = 0;
ret->w = 4; /* default */
- ret->points = NULL;
- ret->num = 0;
ret->references = 1;
- return ret;
-}
-
-static void *ec_pre_comp_dup(void *src_)
-{
- EC_PRE_COMP *src = src_;
-
- /* no need to actually copy, these objects never change! */
- CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
-
- return src_;
+ ret->lock = CRYPTO_THREAD_lock_new();
+ if (ret->lock == NULL) {
+ ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(ret);
+ return NULL;
+ }
+ return ret;
}
-static void ec_pre_comp_free(void *pre_)
+EC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *pre)
{
int i;
- EC_PRE_COMP *pre = pre_;
-
- if (!pre)
- return;
-
- i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
- if (i > 0)
- return;
-
- if (pre->points) {
- EC_POINT **p;
-
- for (p = pre->points; *p != NULL; p++)
- EC_POINT_free(*p);
- OPENSSL_free(pre->points);
- }
- OPENSSL_free(pre);
+ if (pre != NULL)
+ CRYPTO_atomic_add(&pre->references, 1, &i, pre->lock);
+ return pre;
}
-static void ec_pre_comp_clear_free(void *pre_)
+void EC_ec_pre_comp_free(EC_PRE_COMP *pre)
{
int i;
- EC_PRE_COMP *pre = pre_;
- if (!pre)
+ if (pre == NULL)
return;
- i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP);
+ CRYPTO_atomic_add(&pre->references, -1, &i, pre->lock);
+ REF_PRINT_COUNT("EC_ec", pre);
if (i > 0)
return;
+ REF_ASSERT_ISNT(i < 0);
- if (pre->points) {
- EC_POINT **p;
+ if (pre->points != NULL) {
+ EC_POINT **pts;
- for (p = pre->points; *p != NULL; p++) {
- EC_POINT_clear_free(*p);
- OPENSSL_cleanse(p, sizeof *p);
- }
+ for (pts = pre->points; *pts != NULL; pts++)
+ EC_POINT_free(*pts);
OPENSSL_free(pre->points);
}
- OPENSSL_cleanse(pre, sizeof *pre);
+ CRYPTO_THREAD_lock_free(pre->lock);
OPENSSL_free(pre);
}
/* look if we can use precomputed multiples of generator */
- pre_comp =
- EC_EX_DATA_get_data(group->extra_data, ec_pre_comp_dup,
- ec_pre_comp_free, ec_pre_comp_clear_free);
-
+ pre_comp = group->pre_comp.ec;
if (pre_comp && pre_comp->numblocks
&& (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) ==
0)) {
val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]);
/* Ensure wNAF is initialised in case we end up going to err */
- if (wNAF)
+ if (wNAF != NULL)
wNAF[0] = NULL; /* preliminary pivot */
- if (!wsize || !wNAF_len || !wNAF || !val_sub) {
+ if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
goto err;
}
wNAF[num] = tmp_wNAF;
wNAF[num + 1] = NULL;
wNAF_len[num] = tmp_len;
- if (tmp_len > max_len)
- max_len = tmp_len;
/*
* pre_comp->points starts with the points that we need here:
*/
numblocks = (tmp_len + blocksize - 1) / blocksize;
if (numblocks > pre_comp->numblocks) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(tmp_wNAF);
goto err;
}
totalnum = num + numblocks;
wNAF_len[i] = blocksize;
if (tmp_len < blocksize) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(tmp_wNAF);
goto err;
}
tmp_len -= blocksize;
goto err;
}
- if (!(tmp = EC_POINT_new(group)))
+ if ((tmp = EC_POINT_new(group)) == NULL)
goto err;
/*-
ret = 1;
err:
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
+ BN_CTX_free(new_ctx);
EC_POINT_free(tmp);
- if (wsize != NULL)
- OPENSSL_free(wsize);
- if (wNAF_len != NULL)
- OPENSSL_free(wNAF_len);
+ OPENSSL_free(wsize);
+ OPENSSL_free(wNAF_len);
if (wNAF != NULL) {
signed char **w;
OPENSSL_free(val);
}
- if (val_sub != NULL) {
- OPENSSL_free(val_sub);
- }
+ OPENSSL_free(val_sub);
return ret;
}
const EC_POINT *generator;
EC_POINT *tmp_point = NULL, *base = NULL, **var;
BN_CTX *new_ctx = NULL;
- BIGNUM *order;
+ const 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_EX_DATA_free_data(&group->extra_data, ec_pre_comp_dup,
- ec_pre_comp_free, ec_pre_comp_clear_free);
-
+ EC_pre_comp_free(group);
if ((pre_comp = ec_pre_comp_new(group)) == NULL)
return 0;
}
BN_CTX_start(ctx);
- order = BN_CTX_get(ctx);
- if (order == NULL)
- goto err;
- if (!EC_GROUP_get_order(group, order, ctx))
+ order = EC_GROUP_get0_order(group);
+ if (order == NULL)
goto err;
if (BN_is_zero(order)) {
ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER);
num = pre_points_per_block * numblocks; /* number of points to compute
* and store */
- points = OPENSSL_malloc(sizeof(EC_POINT *) * (num + 1));
- if (!points) {
+ points = OPENSSL_malloc(sizeof(*points) * (num + 1));
+ if (points == NULL) {
ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
goto err;
}
}
}
- if (!(tmp_point = EC_POINT_new(group)) || !(base = EC_POINT_new(group))) {
+ if ((tmp_point = EC_POINT_new(group)) == NULL
+ || (base = EC_POINT_new(group)) == NULL) {
ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
goto err;
}
pre_comp->points = points;
points = NULL;
pre_comp->num = num;
-
- if (!EC_EX_DATA_set_data(&group->extra_data, pre_comp,
- ec_pre_comp_dup, ec_pre_comp_free,
- ec_pre_comp_clear_free))
- goto err;
+ SETPRECOMP(group, ec, pre_comp);
pre_comp = NULL;
-
ret = 1;
+
err:
if (ctx != NULL)
BN_CTX_end(ctx);
- if (new_ctx != NULL)
- BN_CTX_free(new_ctx);
- if (pre_comp)
- ec_pre_comp_free(pre_comp);
+ BN_CTX_free(new_ctx);
+ EC_ec_pre_comp_free(pre_comp);
if (points) {
EC_POINT **p;
int ec_wNAF_have_precompute_mult(const EC_GROUP *group)
{
- if (EC_EX_DATA_get_data
- (group->extra_data, ec_pre_comp_dup, ec_pre_comp_free,
- ec_pre_comp_clear_free) != NULL)
- return 1;
- else
- return 0;
+ return HAVEPRECOMP(group, ec);
}