original files of m241
This commit is contained in:
@@ -0,0 +1,491 @@
|
||||
/* crypto/ec/ec2_mult.c */
|
||||
/* ====================================================================
|
||||
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* The Elliptic Curve Public-Key Crypto Library (ECC Code) included
|
||||
* herein is developed by SUN MICROSYSTEMS, INC., and is contributed
|
||||
* to the OpenSSL project.
|
||||
*
|
||||
* The ECC Code is licensed pursuant to the OpenSSL open source
|
||||
* license provided below.
|
||||
*
|
||||
* The software is originally written by Sheueling Chang Shantz and
|
||||
* Douglas Stebila of Sun Microsystems Laboratories.
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2020 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).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "ec_lcl.h"
|
||||
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
|
||||
/*-
|
||||
* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective
|
||||
* coordinates.
|
||||
* Uses algorithm Mdouble in appendix of
|
||||
* Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation" (CHES '99, LNCS 1717).
|
||||
* modified to not require precomputation of c=b^{2^{m-1}}.
|
||||
*/
|
||||
static int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *t1;
|
||||
int ret = 0;
|
||||
|
||||
/* Since Mdouble is static we can guarantee that ctx != NULL. */
|
||||
BN_CTX_start(ctx);
|
||||
t1 = BN_CTX_get(ctx);
|
||||
if (t1 == NULL)
|
||||
goto err;
|
||||
|
||||
if (!group->meth->field_sqr(group, x, x, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_sqr(group, t1, z, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, z, x, t1, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_sqr(group, x, x, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_sqr(group, t1, t1, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, t1, &group->b, t1, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(x, x, t1))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery
|
||||
* projective coordinates.
|
||||
* Uses algorithm Madd in appendix of
|
||||
* Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation" (CHES '99, LNCS 1717).
|
||||
*/
|
||||
static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1,
|
||||
BIGNUM *z1, const BIGNUM *x2, const BIGNUM *z2,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *t1, *t2;
|
||||
int ret = 0;
|
||||
|
||||
/* Since Madd is static we can guarantee that ctx != NULL. */
|
||||
BN_CTX_start(ctx);
|
||||
t1 = BN_CTX_get(ctx);
|
||||
t2 = BN_CTX_get(ctx);
|
||||
if (t2 == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_copy(t1, x))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, x1, x1, z2, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, z1, z1, x2, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, t2, x1, z1, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(z1, z1, x1))
|
||||
goto err;
|
||||
if (!group->meth->field_sqr(group, z1, z1, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, x1, z1, t1, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(x1, x1, t2))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
|
||||
* using Montgomery point multiplication algorithm Mxy() in appendix of
|
||||
* Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation" (CHES '99, LNCS 1717).
|
||||
* Returns:
|
||||
* 0 on error
|
||||
* 1 if return value should be the point at infinity
|
||||
* 2 otherwise
|
||||
*/
|
||||
static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y,
|
||||
BIGNUM *x1, BIGNUM *z1, BIGNUM *x2, BIGNUM *z2,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *t3, *t4, *t5;
|
||||
int ret = 0;
|
||||
|
||||
if (BN_is_zero(z1)) {
|
||||
BN_zero(x2);
|
||||
BN_zero(z2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (BN_is_zero(z2)) {
|
||||
if (!BN_copy(x2, x))
|
||||
return 0;
|
||||
if (!BN_GF2m_add(z2, x, y))
|
||||
return 0;
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Since Mxy is static we can guarantee that ctx != NULL. */
|
||||
BN_CTX_start(ctx);
|
||||
t3 = BN_CTX_get(ctx);
|
||||
t4 = BN_CTX_get(ctx);
|
||||
t5 = BN_CTX_get(ctx);
|
||||
if (t5 == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_one(t5))
|
||||
goto err;
|
||||
|
||||
if (!group->meth->field_mul(group, t3, z1, z2, ctx))
|
||||
goto err;
|
||||
|
||||
if (!group->meth->field_mul(group, z1, z1, x, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(z1, z1, x1))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, z2, z2, x, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, x1, z2, x1, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(z2, z2, x2))
|
||||
goto err;
|
||||
|
||||
if (!group->meth->field_mul(group, z2, z2, z1, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_sqr(group, t4, x, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(t4, t4, y))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, t4, t4, t3, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(t4, t4, z2))
|
||||
goto err;
|
||||
|
||||
if (!group->meth->field_mul(group, t3, t3, x, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_div(group, t3, t5, t3, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, t4, t3, t4, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, x2, x1, t3, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(z2, x2, x))
|
||||
goto err;
|
||||
|
||||
if (!group->meth->field_mul(group, z2, z2, t4, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(z2, z2, y))
|
||||
goto err;
|
||||
|
||||
ret = 2;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Computes scalar*point and stores the result in r.
|
||||
* point can not equal r.
|
||||
* Uses a modified algorithm 2P of
|
||||
* Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
|
||||
* GF(2^m) without precomputation" (CHES '99, LNCS 1717).
|
||||
*
|
||||
* To protect against side-channel attack the function uses constant time swap,
|
||||
* avoiding conditional branches.
|
||||
*/
|
||||
static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group,
|
||||
EC_POINT *r,
|
||||
const BIGNUM *scalar,
|
||||
const EC_POINT *point,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *x1, *x2, *z1, *z2;
|
||||
int ret = 0, i, group_top;
|
||||
BN_ULONG mask, word;
|
||||
|
||||
if (r == point) {
|
||||
ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if result should be point at infinity */
|
||||
if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) ||
|
||||
EC_POINT_is_at_infinity(group, point)) {
|
||||
return EC_POINT_set_to_infinity(group, r);
|
||||
}
|
||||
|
||||
/* only support affine coordinates */
|
||||
if (!point->Z_is_one)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Since point_multiply is static we can guarantee that ctx != NULL.
|
||||
*/
|
||||
BN_CTX_start(ctx);
|
||||
x1 = BN_CTX_get(ctx);
|
||||
z1 = BN_CTX_get(ctx);
|
||||
if (z1 == NULL)
|
||||
goto err;
|
||||
|
||||
x2 = &r->X;
|
||||
z2 = &r->Y;
|
||||
|
||||
group_top = group->field.top;
|
||||
if (bn_wexpand(x1, group_top) == NULL
|
||||
|| bn_wexpand(z1, group_top) == NULL
|
||||
|| bn_wexpand(x2, group_top) == NULL
|
||||
|| bn_wexpand(z2, group_top) == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_GF2m_mod_arr(x1, &point->X, group->poly))
|
||||
goto err; /* x1 = x */
|
||||
if (!BN_one(z1))
|
||||
goto err; /* z1 = 1 */
|
||||
if (!group->meth->field_sqr(group, z2, x1, ctx))
|
||||
goto err; /* z2 = x1^2 = x^2 */
|
||||
if (!group->meth->field_sqr(group, x2, z2, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(x2, x2, &group->b))
|
||||
goto err; /* x2 = x^4 + b */
|
||||
|
||||
/* blinding: make sure z1 and z2 are independently blinded. */
|
||||
do {
|
||||
if (!BN_rand(z1, BN_num_bits(&group->field) - 1, -1, 0)) {
|
||||
ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, ERR_R_BN_LIB);
|
||||
return 0;
|
||||
}
|
||||
} while (BN_is_zero(z1));
|
||||
|
||||
/* first blind (x2,z2) using z1 as the random field element. */
|
||||
if ((group->meth->field_encode != NULL
|
||||
&& !group->meth->field_encode(group, z1, z1, ctx))
|
||||
|| !group->meth->field_mul(group, x2, x2, z1, ctx)
|
||||
|| !group->meth->field_mul(group, z2, z2, z1, ctx))
|
||||
return 0;
|
||||
|
||||
/* now generate another random field element to blind (x1,z1) */
|
||||
do {
|
||||
if (!BN_rand(z1, BN_num_bits(&group->field) - 1, -1, 0)) {
|
||||
ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, ERR_R_BN_LIB);
|
||||
return 0;
|
||||
}
|
||||
} while (BN_is_zero(z1));
|
||||
|
||||
if ((group->meth->field_encode != NULL
|
||||
&& !group->meth->field_encode(group, z1, z1, ctx))
|
||||
|| !group->meth->field_mul(group, x1, x1, z1, ctx))
|
||||
return 0;
|
||||
|
||||
/* find top most bit and go one past it */
|
||||
i = scalar->top - 1;
|
||||
mask = BN_TBIT;
|
||||
word = scalar->d[i];
|
||||
while (!(word & mask))
|
||||
mask >>= 1;
|
||||
mask >>= 1;
|
||||
/* if top most bit was at word break, go to next word */
|
||||
if (!mask) {
|
||||
i--;
|
||||
mask = BN_TBIT;
|
||||
}
|
||||
|
||||
for (; i >= 0; i--) {
|
||||
word = scalar->d[i];
|
||||
while (mask) {
|
||||
BN_consttime_swap(word & mask, x1, x2, group_top);
|
||||
BN_consttime_swap(word & mask, z1, z2, group_top);
|
||||
if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx))
|
||||
goto err;
|
||||
if (!gf2m_Mdouble(group, x1, z1, ctx))
|
||||
goto err;
|
||||
BN_consttime_swap(word & mask, x1, x2, group_top);
|
||||
BN_consttime_swap(word & mask, z1, z2, group_top);
|
||||
mask >>= 1;
|
||||
}
|
||||
mask = BN_TBIT;
|
||||
}
|
||||
|
||||
/* convert out of "projective" coordinates */
|
||||
i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx);
|
||||
if (i == 0)
|
||||
goto err;
|
||||
else if (i == 1) {
|
||||
if (!EC_POINT_set_to_infinity(group, r))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_one(&r->Z))
|
||||
goto err;
|
||||
r->Z_is_one = 1;
|
||||
}
|
||||
|
||||
/* GF(2^m) field elements should always have BIGNUM::neg = 0 */
|
||||
BN_set_negative(&r->X, 0);
|
||||
BN_set_negative(&r->Y, 0);
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Computes the sum
|
||||
* scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1]
|
||||
* gracefully ignoring NULL scalar values.
|
||||
*/
|
||||
int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
const BIGNUM *scalar, size_t num,
|
||||
const EC_POINT *points[], const BIGNUM *scalars[],
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BN_CTX *new_ctx = NULL;
|
||||
int ret = 0;
|
||||
size_t i;
|
||||
EC_POINT *p = NULL;
|
||||
EC_POINT *acc = NULL;
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This implementation is more efficient than the wNAF implementation for
|
||||
* 2 or fewer points. Use the ec_wNAF_mul implementation for 3 or more
|
||||
* points.
|
||||
*/
|
||||
if ((scalar && (num > 1)) || (num > 2)) {
|
||||
ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((p = EC_POINT_new(group)) == NULL)
|
||||
goto err;
|
||||
if ((acc = EC_POINT_new(group)) == NULL)
|
||||
goto err;
|
||||
|
||||
if (!EC_POINT_set_to_infinity(group, acc))
|
||||
goto err;
|
||||
|
||||
if (scalar) {
|
||||
if (!ec_GF2m_montgomery_point_multiply
|
||||
(group, p, scalar, group->generator, ctx))
|
||||
goto err;
|
||||
if (BN_is_negative(scalar))
|
||||
if (!group->meth->invert(group, p, ctx))
|
||||
goto err;
|
||||
if (!group->meth->add(group, acc, acc, p, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (!ec_GF2m_montgomery_point_multiply
|
||||
(group, p, scalars[i], points[i], ctx))
|
||||
goto err;
|
||||
if (BN_is_negative(scalars[i]))
|
||||
if (!group->meth->invert(group, p, ctx))
|
||||
goto err;
|
||||
if (!group->meth->add(group, acc, acc, p, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EC_POINT_copy(r, acc))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (p)
|
||||
EC_POINT_free(p);
|
||||
if (acc)
|
||||
EC_POINT_free(acc);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Precomputation for point multiplication: fall back to wNAF methods because
|
||||
* ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate
|
||||
*/
|
||||
|
||||
int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
|
||||
{
|
||||
return ec_wNAF_precompute_mult(group, ctx);
|
||||
}
|
||||
|
||||
int ec_GF2m_have_precompute_mult(const EC_GROUP *group)
|
||||
{
|
||||
return ec_wNAF_have_precompute_mult(group);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,402 @@
|
||||
/* crypto/ec/ec2_oct.c */
|
||||
/* ====================================================================
|
||||
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* The Elliptic Curve Public-Key Crypto Library (ECC Code) included
|
||||
* herein is developed by SUN MICROSYSTEMS, INC., and is contributed
|
||||
* to the OpenSSL project.
|
||||
*
|
||||
* The ECC Code is licensed pursuant to the OpenSSL open source
|
||||
* license provided below.
|
||||
*
|
||||
* The software is originally written by Sheueling Chang Shantz and
|
||||
* Douglas Stebila of Sun Microsystems Laboratories.
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2019 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).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "ec_lcl.h"
|
||||
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
|
||||
/*-
|
||||
* Calculates and sets the affine coordinates of an EC_POINT from the given
|
||||
* compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
|
||||
* Note that the simple implementation only uses affine coordinates.
|
||||
*
|
||||
* The method is from the following publication:
|
||||
*
|
||||
* Harper, Menezes, Vanstone:
|
||||
* "Public-Key Cryptosystems with Very Small Key Lengths",
|
||||
* EUROCRYPT '92, Springer-Verlag LNCS 658,
|
||||
* published February 1993
|
||||
*
|
||||
* US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
|
||||
* the same method, but claim no priority date earlier than July 29, 1994
|
||||
* (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
|
||||
*/
|
||||
int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
|
||||
EC_POINT *point,
|
||||
const BIGNUM *x_, int y_bit,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *tmp, *x, *y, *z;
|
||||
int ret = 0, z0;
|
||||
|
||||
/* clear error queue */
|
||||
ERR_clear_error();
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
y_bit = (y_bit != 0) ? 1 : 0;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
z = BN_CTX_get(ctx);
|
||||
if (z == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_GF2m_mod_arr(x, x_, group->poly))
|
||||
goto err;
|
||||
if (BN_is_zero(x)) {
|
||||
if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
if (!group->meth->field_sqr(group, tmp, x, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(tmp, &group->a, tmp))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(tmp, x, tmp))
|
||||
goto err;
|
||||
if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) {
|
||||
unsigned long err = ERR_peek_last_error();
|
||||
|
||||
if (ERR_GET_LIB(err) == ERR_LIB_BN
|
||||
&& ERR_GET_REASON(err) == BN_R_NO_SOLUTION) {
|
||||
ERR_clear_error();
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
|
||||
EC_R_INVALID_COMPRESSED_POINT);
|
||||
} else
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
|
||||
ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
z0 = (BN_is_odd(z)) ? 1 : 0;
|
||||
if (!group->meth->field_mul(group, y, x, z, ctx))
|
||||
goto err;
|
||||
if (z0 != y_bit) {
|
||||
if (!BN_GF2m_add(y, y, x))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts an EC_POINT to an octet string. If buf is NULL, the encoded
|
||||
* length will be returned. If the length len of buf is smaller than required
|
||||
* an error will be returned.
|
||||
*/
|
||||
size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
|
||||
point_conversion_form_t form,
|
||||
unsigned char *buf, size_t len, BN_CTX *ctx)
|
||||
{
|
||||
size_t ret;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
int used_ctx = 0;
|
||||
BIGNUM *x, *y, *yxi;
|
||||
size_t field_len, i, skip;
|
||||
|
||||
if ((form != POINT_CONVERSION_COMPRESSED)
|
||||
&& (form != POINT_CONVERSION_UNCOMPRESSED)
|
||||
&& (form != POINT_CONVERSION_HYBRID)) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EC_POINT_is_at_infinity(group, point)) {
|
||||
/* encodes to a single 0 octet */
|
||||
if (buf != NULL) {
|
||||
if (len < 1) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
buf[0] = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ret := required output buffer length */
|
||||
field_len = (EC_GROUP_get_degree(group) + 7) / 8;
|
||||
ret =
|
||||
(form ==
|
||||
POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
|
||||
|
||||
/* if 'buf' is NULL, just return required length */
|
||||
if (buf != NULL) {
|
||||
if (len < ret) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
used_ctx = 1;
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
yxi = BN_CTX_get(ctx);
|
||||
if (yxi == NULL)
|
||||
goto err;
|
||||
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
|
||||
goto err;
|
||||
|
||||
buf[0] = form;
|
||||
if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x)) {
|
||||
if (!group->meth->field_div(group, yxi, y, x, ctx))
|
||||
goto err;
|
||||
if (BN_is_odd(yxi))
|
||||
buf[0]++;
|
||||
}
|
||||
|
||||
i = 1;
|
||||
|
||||
skip = field_len - BN_num_bytes(x);
|
||||
if (skip > field_len) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
while (skip > 0) {
|
||||
buf[i++] = 0;
|
||||
skip--;
|
||||
}
|
||||
skip = BN_bn2bin(x, buf + i);
|
||||
i += skip;
|
||||
if (i != 1 + field_len) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (form == POINT_CONVERSION_UNCOMPRESSED
|
||||
|| form == POINT_CONVERSION_HYBRID) {
|
||||
skip = field_len - BN_num_bytes(y);
|
||||
if (skip > field_len) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
while (skip > 0) {
|
||||
buf[i++] = 0;
|
||||
skip--;
|
||||
}
|
||||
skip = BN_bn2bin(y, buf + i);
|
||||
i += skip;
|
||||
}
|
||||
|
||||
if (i != ret) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (used_ctx)
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if (used_ctx)
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts an octet string representation to an EC_POINT. Note that the
|
||||
* simple implementation only uses affine coordinates.
|
||||
*/
|
||||
int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
|
||||
const unsigned char *buf, size_t len,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
point_conversion_form_t form;
|
||||
int y_bit, m;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *x, *y, *yxi;
|
||||
size_t field_len, enc_len;
|
||||
int ret = 0;
|
||||
|
||||
if (len == 0) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
form = buf[0];
|
||||
y_bit = form & 1;
|
||||
form = form & ~1U;
|
||||
if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
|
||||
&& (form != POINT_CONVERSION_UNCOMPRESSED)
|
||||
&& (form != POINT_CONVERSION_HYBRID)) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (form == 0) {
|
||||
if (len != 1) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return EC_POINT_set_to_infinity(group, point);
|
||||
}
|
||||
|
||||
m = EC_GROUP_get_degree(group);
|
||||
field_len = (m + 7) / 8;
|
||||
enc_len =
|
||||
(form ==
|
||||
POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
|
||||
|
||||
if (len != enc_len) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
yxi = BN_CTX_get(ctx);
|
||||
if (yxi == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_bin2bn(buf + 1, field_len, x))
|
||||
goto err;
|
||||
if (BN_num_bits(x) > m) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (form == POINT_CONVERSION_COMPRESSED) {
|
||||
if (!EC_POINT_set_compressed_coordinates_GF2m
|
||||
(group, point, x, y_bit, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
|
||||
goto err;
|
||||
if (BN_num_bits(y) > m) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
goto err;
|
||||
}
|
||||
if (form == POINT_CONVERSION_HYBRID) {
|
||||
if (!group->meth->field_div(group, yxi, y, x, ctx))
|
||||
goto err;
|
||||
if (y_bit != BN_is_odd(yxi)) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* EC_POINT_set_affine_coordinates_GF2m is responsible for checking that
|
||||
* the point is on the curve.
|
||||
*/
|
||||
if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,798 @@
|
||||
/* crypto/ec/ec2_smpl.c */
|
||||
/* ====================================================================
|
||||
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* The Elliptic Curve Public-Key Crypto Library (ECC Code) included
|
||||
* herein is developed by SUN MICROSYSTEMS, INC., and is contributed
|
||||
* to the OpenSSL project.
|
||||
*
|
||||
* The ECC Code is licensed pursuant to the OpenSSL open source
|
||||
* license provided below.
|
||||
*
|
||||
* The software is originally written by Sheueling Chang Shantz and
|
||||
* Douglas Stebila of Sun Microsystems Laboratories.
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2005 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).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "ec_lcl.h"
|
||||
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
|
||||
# ifdef OPENSSL_FIPS
|
||||
# include <openssl/fips.h>
|
||||
# endif
|
||||
|
||||
const EC_METHOD *EC_GF2m_simple_method(void)
|
||||
{
|
||||
static const EC_METHOD ret = {
|
||||
EC_FLAGS_DEFAULT_OCT,
|
||||
NID_X9_62_characteristic_two_field,
|
||||
ec_GF2m_simple_group_init,
|
||||
ec_GF2m_simple_group_finish,
|
||||
ec_GF2m_simple_group_clear_finish,
|
||||
ec_GF2m_simple_group_copy,
|
||||
ec_GF2m_simple_group_set_curve,
|
||||
ec_GF2m_simple_group_get_curve,
|
||||
ec_GF2m_simple_group_get_degree,
|
||||
ec_GF2m_simple_group_check_discriminant,
|
||||
ec_GF2m_simple_point_init,
|
||||
ec_GF2m_simple_point_finish,
|
||||
ec_GF2m_simple_point_clear_finish,
|
||||
ec_GF2m_simple_point_copy,
|
||||
ec_GF2m_simple_point_set_to_infinity,
|
||||
0 /* set_Jprojective_coordinates_GFp */ ,
|
||||
0 /* get_Jprojective_coordinates_GFp */ ,
|
||||
ec_GF2m_simple_point_set_affine_coordinates,
|
||||
ec_GF2m_simple_point_get_affine_coordinates,
|
||||
0, 0, 0,
|
||||
ec_GF2m_simple_add,
|
||||
ec_GF2m_simple_dbl,
|
||||
ec_GF2m_simple_invert,
|
||||
ec_GF2m_simple_is_at_infinity,
|
||||
ec_GF2m_simple_is_on_curve,
|
||||
ec_GF2m_simple_cmp,
|
||||
ec_GF2m_simple_make_affine,
|
||||
ec_GF2m_simple_points_make_affine,
|
||||
|
||||
/*
|
||||
* the following three method functions are defined in ec2_mult.c
|
||||
*/
|
||||
ec_GF2m_simple_mul,
|
||||
ec_GF2m_precompute_mult,
|
||||
ec_GF2m_have_precompute_mult,
|
||||
|
||||
ec_GF2m_simple_field_mul,
|
||||
ec_GF2m_simple_field_sqr,
|
||||
ec_GF2m_simple_field_div,
|
||||
0 /* field_encode */ ,
|
||||
0 /* field_decode */ ,
|
||||
0 /* field_set_to_one */
|
||||
};
|
||||
|
||||
# ifdef OPENSSL_FIPS
|
||||
if (FIPS_mode())
|
||||
return fips_ec_gf2m_simple_method();
|
||||
# endif
|
||||
|
||||
return &ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members
|
||||
* are handled by EC_GROUP_new.
|
||||
*/
|
||||
int ec_GF2m_simple_group_init(EC_GROUP *group)
|
||||
{
|
||||
BN_init(&group->field);
|
||||
BN_init(&group->a);
|
||||
BN_init(&group->b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a GF(2^m)-based EC_GROUP structure. Note that all other members are
|
||||
* handled by EC_GROUP_free.
|
||||
*/
|
||||
void ec_GF2m_simple_group_finish(EC_GROUP *group)
|
||||
{
|
||||
BN_free(&group->field);
|
||||
BN_free(&group->a);
|
||||
BN_free(&group->b);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other
|
||||
* members are handled by EC_GROUP_clear_free.
|
||||
*/
|
||||
void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
|
||||
{
|
||||
BN_clear_free(&group->field);
|
||||
BN_clear_free(&group->a);
|
||||
BN_clear_free(&group->b);
|
||||
group->poly[0] = 0;
|
||||
group->poly[1] = 0;
|
||||
group->poly[2] = 0;
|
||||
group->poly[3] = 0;
|
||||
group->poly[4] = 0;
|
||||
group->poly[5] = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are
|
||||
* handled by EC_GROUP_copy.
|
||||
*/
|
||||
int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
|
||||
{
|
||||
int i;
|
||||
if (!BN_copy(&dest->field, &src->field))
|
||||
return 0;
|
||||
if (!BN_copy(&dest->a, &src->a))
|
||||
return 0;
|
||||
if (!BN_copy(&dest->b, &src->b))
|
||||
return 0;
|
||||
dest->poly[0] = src->poly[0];
|
||||
dest->poly[1] = src->poly[1];
|
||||
dest->poly[2] = src->poly[2];
|
||||
dest->poly[3] = src->poly[3];
|
||||
dest->poly[4] = src->poly[4];
|
||||
dest->poly[5] = src->poly[5];
|
||||
if (bn_wexpand(&dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2)
|
||||
== NULL)
|
||||
return 0;
|
||||
if (bn_wexpand(&dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2)
|
||||
== NULL)
|
||||
return 0;
|
||||
for (i = dest->a.top; i < dest->a.dmax; i++)
|
||||
dest->a.d[i] = 0;
|
||||
for (i = dest->b.top; i < dest->b.dmax; i++)
|
||||
dest->b.d[i] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set the curve parameters of an EC_GROUP structure. */
|
||||
int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
|
||||
const BIGNUM *p, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0, i;
|
||||
|
||||
/* group->field */
|
||||
if (!BN_copy(&group->field, p))
|
||||
goto err;
|
||||
i = BN_GF2m_poly2arr(&group->field, group->poly, 6) - 1;
|
||||
if ((i != 5) && (i != 3)) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* group->a */
|
||||
if (!BN_GF2m_mod_arr(&group->a, a, group->poly))
|
||||
goto err;
|
||||
if (bn_wexpand(&group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
|
||||
== NULL)
|
||||
goto err;
|
||||
for (i = group->a.top; i < group->a.dmax; i++)
|
||||
group->a.d[i] = 0;
|
||||
|
||||
/* group->b */
|
||||
if (!BN_GF2m_mod_arr(&group->b, b, group->poly))
|
||||
goto err;
|
||||
if (bn_wexpand(&group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
|
||||
== NULL)
|
||||
goto err;
|
||||
for (i = group->b.top; i < group->b.dmax; i++)
|
||||
group->b.d[i] = 0;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL
|
||||
* then there values will not be set but the method will return with success.
|
||||
*/
|
||||
int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p,
|
||||
BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (p != NULL) {
|
||||
if (!BN_copy(p, &group->field))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (a != NULL) {
|
||||
if (!BN_copy(a, &group->a))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (b != NULL) {
|
||||
if (!BN_copy(b, &group->b))
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the degree of the field. For a curve over GF(2^m) this is the value
|
||||
* m.
|
||||
*/
|
||||
int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
|
||||
{
|
||||
return BN_num_bits(&group->field) - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an
|
||||
* elliptic curve <=> b != 0 (mod p)
|
||||
*/
|
||||
int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
BIGNUM *b;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
BN_CTX_start(ctx);
|
||||
b = BN_CTX_get(ctx);
|
||||
if (b == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_GF2m_mod_arr(b, &group->b, group->poly))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic
|
||||
* curve <=> b != 0 (mod p)
|
||||
*/
|
||||
if (BN_is_zero(b))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (ctx != NULL)
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initializes an EC_POINT. */
|
||||
int ec_GF2m_simple_point_init(EC_POINT *point)
|
||||
{
|
||||
BN_init(&point->X);
|
||||
BN_init(&point->Y);
|
||||
BN_init(&point->Z);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Frees an EC_POINT. */
|
||||
void ec_GF2m_simple_point_finish(EC_POINT *point)
|
||||
{
|
||||
BN_free(&point->X);
|
||||
BN_free(&point->Y);
|
||||
BN_free(&point->Z);
|
||||
}
|
||||
|
||||
/* Clears and frees an EC_POINT. */
|
||||
void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
|
||||
{
|
||||
BN_clear_free(&point->X);
|
||||
BN_clear_free(&point->Y);
|
||||
BN_clear_free(&point->Z);
|
||||
point->Z_is_one = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the contents of one EC_POINT into another. Assumes dest is
|
||||
* initialized.
|
||||
*/
|
||||
int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
|
||||
{
|
||||
if (!BN_copy(&dest->X, &src->X))
|
||||
return 0;
|
||||
if (!BN_copy(&dest->Y, &src->Y))
|
||||
return 0;
|
||||
if (!BN_copy(&dest->Z, &src->Z))
|
||||
return 0;
|
||||
dest->Z_is_one = src->Z_is_one;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set an EC_POINT to the point at infinity. A point at infinity is
|
||||
* represented by having Z=0.
|
||||
*/
|
||||
int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group,
|
||||
EC_POINT *point)
|
||||
{
|
||||
point->Z_is_one = 0;
|
||||
BN_zero(&point->Z);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the coordinates of an EC_POINT using affine coordinates. Note that
|
||||
* the simple implementation only uses affine coordinates.
|
||||
*/
|
||||
int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group,
|
||||
EC_POINT *point,
|
||||
const BIGNUM *x,
|
||||
const BIGNUM *y, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
if (x == NULL || y == NULL) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES,
|
||||
ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!BN_copy(&point->X, x))
|
||||
goto err;
|
||||
BN_set_negative(&point->X, 0);
|
||||
if (!BN_copy(&point->Y, y))
|
||||
goto err;
|
||||
BN_set_negative(&point->Y, 0);
|
||||
if (!BN_copy(&point->Z, BN_value_one()))
|
||||
goto err;
|
||||
BN_set_negative(&point->Z, 0);
|
||||
point->Z_is_one = 1;
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the affine coordinates of an EC_POINT. Note that the simple
|
||||
* implementation only uses affine coordinates.
|
||||
*/
|
||||
int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
|
||||
const EC_POINT *point,
|
||||
BIGNUM *x, BIGNUM *y,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (EC_POINT_is_at_infinity(group, point)) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
|
||||
EC_R_POINT_AT_INFINITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (BN_cmp(&point->Z, BN_value_one())) {
|
||||
ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
|
||||
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
if (x != NULL) {
|
||||
if (!BN_copy(x, &point->X))
|
||||
goto err;
|
||||
BN_set_negative(x, 0);
|
||||
}
|
||||
if (y != NULL) {
|
||||
if (!BN_copy(y, &point->Y))
|
||||
goto err;
|
||||
BN_set_negative(y, 0);
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes a + b and stores the result in r. r could be a or b, a could be
|
||||
* b. Uses algorithm A.10.2 of IEEE P1363.
|
||||
*/
|
||||
int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
|
||||
const EC_POINT *b, BN_CTX *ctx)
|
||||
{
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
|
||||
int ret = 0;
|
||||
|
||||
if (EC_POINT_is_at_infinity(group, a)) {
|
||||
if (!EC_POINT_copy(r, b))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (EC_POINT_is_at_infinity(group, b)) {
|
||||
if (!EC_POINT_copy(r, a))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
x0 = BN_CTX_get(ctx);
|
||||
y0 = BN_CTX_get(ctx);
|
||||
x1 = BN_CTX_get(ctx);
|
||||
y1 = BN_CTX_get(ctx);
|
||||
x2 = BN_CTX_get(ctx);
|
||||
y2 = BN_CTX_get(ctx);
|
||||
s = BN_CTX_get(ctx);
|
||||
t = BN_CTX_get(ctx);
|
||||
if (t == NULL)
|
||||
goto err;
|
||||
|
||||
if (a->Z_is_one) {
|
||||
if (!BN_copy(x0, &a->X))
|
||||
goto err;
|
||||
if (!BN_copy(y0, &a->Y))
|
||||
goto err;
|
||||
} else {
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx))
|
||||
goto err;
|
||||
}
|
||||
if (b->Z_is_one) {
|
||||
if (!BN_copy(x1, &b->X))
|
||||
goto err;
|
||||
if (!BN_copy(y1, &b->Y))
|
||||
goto err;
|
||||
} else {
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (BN_GF2m_cmp(x0, x1)) {
|
||||
if (!BN_GF2m_add(t, x0, x1))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(s, y0, y1))
|
||||
goto err;
|
||||
if (!group->meth->field_div(group, s, s, t, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_sqr(group, x2, s, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(x2, x2, &group->a))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(x2, x2, s))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(x2, x2, t))
|
||||
goto err;
|
||||
} else {
|
||||
if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) {
|
||||
if (!EC_POINT_set_to_infinity(group, r))
|
||||
goto err;
|
||||
ret = 1;
|
||||
goto err;
|
||||
}
|
||||
if (!group->meth->field_div(group, s, y1, x1, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(s, s, x1))
|
||||
goto err;
|
||||
|
||||
if (!group->meth->field_sqr(group, x2, s, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(x2, x2, s))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(x2, x2, &group->a))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_GF2m_add(y2, x1, x2))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, y2, y2, s, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(y2, y2, x2))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(y2, y2, y1))
|
||||
goto err;
|
||||
|
||||
if (!EC_POINT_set_affine_coordinates_GF2m(group, r, x2, y2, ctx))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes 2 * a and stores the result in r. r could be a. Uses algorithm
|
||||
* A.10.2 of IEEE P1363.
|
||||
*/
|
||||
int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
return ec_GF2m_simple_add(group, r, a, a, ctx);
|
||||
}
|
||||
|
||||
int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
|
||||
{
|
||||
if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(&point->Y))
|
||||
/* point is its own inverse */
|
||||
return 1;
|
||||
|
||||
if (!EC_POINT_make_affine(group, point, ctx))
|
||||
return 0;
|
||||
return BN_GF2m_add(&point->Y, &point->X, &point->Y);
|
||||
}
|
||||
|
||||
/* Indicates whether the given point is the point at infinity. */
|
||||
int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
|
||||
const EC_POINT *point)
|
||||
{
|
||||
return BN_is_zero(&point->Z);
|
||||
}
|
||||
|
||||
/*-
|
||||
* Determines whether the given EC_POINT is an actual point on the curve defined
|
||||
* in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation:
|
||||
* y^2 + x*y = x^3 + a*x^2 + b.
|
||||
*/
|
||||
int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int ret = -1;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *lh, *y2;
|
||||
int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
|
||||
const BIGNUM *, BN_CTX *);
|
||||
int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
|
||||
|
||||
if (EC_POINT_is_at_infinity(group, point))
|
||||
return 1;
|
||||
|
||||
field_mul = group->meth->field_mul;
|
||||
field_sqr = group->meth->field_sqr;
|
||||
|
||||
/* only support affine coordinates */
|
||||
if (!point->Z_is_one)
|
||||
return -1;
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
y2 = BN_CTX_get(ctx);
|
||||
lh = BN_CTX_get(ctx);
|
||||
if (lh == NULL)
|
||||
goto err;
|
||||
|
||||
/*-
|
||||
* We have a curve defined by a Weierstrass equation
|
||||
* y^2 + x*y = x^3 + a*x^2 + b.
|
||||
* <=> x^3 + a*x^2 + x*y + b + y^2 = 0
|
||||
* <=> ((x + a) * x + y ) * x + b + y^2 = 0
|
||||
*/
|
||||
if (!BN_GF2m_add(lh, &point->X, &group->a))
|
||||
goto err;
|
||||
if (!field_mul(group, lh, lh, &point->X, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(lh, lh, &point->Y))
|
||||
goto err;
|
||||
if (!field_mul(group, lh, lh, &point->X, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(lh, lh, &group->b))
|
||||
goto err;
|
||||
if (!field_sqr(group, y2, &point->Y, ctx))
|
||||
goto err;
|
||||
if (!BN_GF2m_add(lh, lh, y2))
|
||||
goto err;
|
||||
ret = BN_is_zero(lh);
|
||||
err:
|
||||
if (ctx)
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Indicates whether two points are equal.
|
||||
* Return values:
|
||||
* -1 error
|
||||
* 0 equal (in affine coordinates)
|
||||
* 1 not equal
|
||||
*/
|
||||
int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
|
||||
const EC_POINT *b, BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *aX, *aY, *bX, *bY;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (EC_POINT_is_at_infinity(group, a)) {
|
||||
return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
|
||||
}
|
||||
|
||||
if (EC_POINT_is_at_infinity(group, b))
|
||||
return 1;
|
||||
|
||||
if (a->Z_is_one && b->Z_is_one) {
|
||||
return ((BN_cmp(&a->X, &b->X) == 0)
|
||||
&& BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
aX = BN_CTX_get(ctx);
|
||||
aY = BN_CTX_get(ctx);
|
||||
bX = BN_CTX_get(ctx);
|
||||
bY = BN_CTX_get(ctx);
|
||||
if (bY == NULL)
|
||||
goto err;
|
||||
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(group, a, aX, aY, ctx))
|
||||
goto err;
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(group, b, bX, bY, ctx))
|
||||
goto err;
|
||||
ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
|
||||
|
||||
err:
|
||||
if (ctx)
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Forces the given EC_POINT to internally use affine coordinates. */
|
||||
int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *x, *y;
|
||||
int ret = 0;
|
||||
|
||||
if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
|
||||
return 1;
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
if (y == NULL)
|
||||
goto err;
|
||||
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
|
||||
goto err;
|
||||
if (!BN_copy(&point->X, x))
|
||||
goto err;
|
||||
if (!BN_copy(&point->Y, y))
|
||||
goto err;
|
||||
if (!BN_one(&point->Z))
|
||||
goto err;
|
||||
point->Z_is_one = 1;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (ctx)
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Forces each of the EC_POINTs in the given array to use affine coordinates.
|
||||
*/
|
||||
int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
|
||||
EC_POINT *points[], BN_CTX *ctx)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (!group->meth->make_affine(group, points[i], ctx))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Wrapper to simple binary polynomial field multiplication implementation. */
|
||||
int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r,
|
||||
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
|
||||
}
|
||||
|
||||
/* Wrapper to simple binary polynomial field squaring implementation. */
|
||||
int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r,
|
||||
const BIGNUM *a, BN_CTX *ctx)
|
||||
{
|
||||
return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
|
||||
}
|
||||
|
||||
/* Wrapper to simple binary polynomial field division implementation. */
|
||||
int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
|
||||
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
return BN_GF2m_mod_div(r, a, b, &group->field, ctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,967 @@
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006-2018 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
|
||||
* licensing@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).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/bn.h>
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
# include <openssl/cms.h>
|
||||
#endif
|
||||
#include <openssl/asn1t.h>
|
||||
#include "asn1_locl.h"
|
||||
#include "ec_lcl.h"
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
static int ecdh_cms_decrypt(CMS_RecipientInfo *ri);
|
||||
static int ecdh_cms_encrypt(CMS_RecipientInfo *ri);
|
||||
#endif
|
||||
|
||||
static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
|
||||
{
|
||||
const EC_GROUP *group;
|
||||
int nid;
|
||||
if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
|
||||
ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
|
||||
return 0;
|
||||
}
|
||||
if (EC_GROUP_get_asn1_flag(group)
|
||||
&& (nid = EC_GROUP_get_curve_name(group)))
|
||||
/* we have a 'named curve' => just set the OID */
|
||||
{
|
||||
*ppval = OBJ_nid2obj(nid);
|
||||
*pptype = V_ASN1_OBJECT;
|
||||
} else { /* explicit parameters */
|
||||
|
||||
ASN1_STRING *pstr = NULL;
|
||||
pstr = ASN1_STRING_new();
|
||||
if (!pstr)
|
||||
return 0;
|
||||
pstr->length = i2d_ECParameters(ec_key, &pstr->data);
|
||||
if (pstr->length <= 0) {
|
||||
ASN1_STRING_free(pstr);
|
||||
ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB);
|
||||
return 0;
|
||||
}
|
||||
*ppval = pstr;
|
||||
*pptype = V_ASN1_SEQUENCE;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
|
||||
{
|
||||
EC_KEY *ec_key = pkey->pkey.ec;
|
||||
void *pval = NULL;
|
||||
int ptype;
|
||||
unsigned char *penc = NULL, *p;
|
||||
int penclen;
|
||||
|
||||
if (!eckey_param2type(&ptype, &pval, ec_key)) {
|
||||
ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB);
|
||||
return 0;
|
||||
}
|
||||
penclen = i2o_ECPublicKey(ec_key, NULL);
|
||||
if (penclen <= 0)
|
||||
goto err;
|
||||
penc = OPENSSL_malloc(penclen);
|
||||
if (!penc)
|
||||
goto err;
|
||||
p = penc;
|
||||
penclen = i2o_ECPublicKey(ec_key, &p);
|
||||
if (penclen <= 0)
|
||||
goto err;
|
||||
if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC),
|
||||
ptype, pval, penc, penclen))
|
||||
return 1;
|
||||
err:
|
||||
if (ptype == V_ASN1_OBJECT)
|
||||
ASN1_OBJECT_free(pval);
|
||||
else
|
||||
ASN1_STRING_free(pval);
|
||||
if (penc)
|
||||
OPENSSL_free(penc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static EC_KEY *eckey_type2param(int ptype, void *pval)
|
||||
{
|
||||
EC_KEY *eckey = NULL;
|
||||
EC_GROUP *group = NULL;
|
||||
|
||||
if (ptype == V_ASN1_SEQUENCE) {
|
||||
const ASN1_STRING *pstr = pval;
|
||||
const unsigned char *pm = pstr->data;
|
||||
int pmlen = pstr->length;
|
||||
|
||||
if ((eckey = d2i_ECParameters(NULL, &pm, pmlen)) == NULL) {
|
||||
ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
|
||||
goto ecerr;
|
||||
}
|
||||
} else if (ptype == V_ASN1_OBJECT) {
|
||||
const ASN1_OBJECT *poid = pval;
|
||||
|
||||
/*
|
||||
* type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
|
||||
*/
|
||||
if ((eckey = EC_KEY_new()) == NULL) {
|
||||
ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE);
|
||||
goto ecerr;
|
||||
}
|
||||
group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
|
||||
if (group == NULL)
|
||||
goto ecerr;
|
||||
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
|
||||
if (EC_KEY_set_group(eckey, group) == 0)
|
||||
goto ecerr;
|
||||
EC_GROUP_free(group);
|
||||
} else {
|
||||
ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
|
||||
goto ecerr;
|
||||
}
|
||||
|
||||
return eckey;
|
||||
|
||||
ecerr:
|
||||
EC_KEY_free(eckey);
|
||||
EC_GROUP_free(group);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
|
||||
{
|
||||
const unsigned char *p = NULL;
|
||||
void *pval;
|
||||
int ptype, pklen;
|
||||
EC_KEY *eckey = NULL;
|
||||
X509_ALGOR *palg;
|
||||
|
||||
if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
|
||||
return 0;
|
||||
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
|
||||
|
||||
eckey = eckey_type2param(ptype, pval);
|
||||
|
||||
if (!eckey) {
|
||||
ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We have parameters now set public key */
|
||||
if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
|
||||
ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR);
|
||||
goto ecerr;
|
||||
}
|
||||
|
||||
EVP_PKEY_assign_EC_KEY(pkey, eckey);
|
||||
return 1;
|
||||
|
||||
ecerr:
|
||||
if (eckey)
|
||||
EC_KEY_free(eckey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
|
||||
{
|
||||
int r;
|
||||
const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
|
||||
const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
|
||||
*pb = EC_KEY_get0_public_key(b->pkey.ec);
|
||||
if (group == NULL || pa == NULL || pb == NULL)
|
||||
return -2;
|
||||
r = EC_POINT_cmp(group, pa, pb, NULL);
|
||||
if (r == 0)
|
||||
return 1;
|
||||
if (r == 1)
|
||||
return 0;
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
|
||||
{
|
||||
const unsigned char *p = NULL;
|
||||
void *pval;
|
||||
int ptype, pklen;
|
||||
EC_KEY *eckey = NULL;
|
||||
X509_ALGOR *palg;
|
||||
|
||||
if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
|
||||
return 0;
|
||||
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
|
||||
|
||||
eckey = eckey_type2param(ptype, pval);
|
||||
|
||||
if (!eckey)
|
||||
goto ecliberr;
|
||||
|
||||
/* We have parameters now set private key */
|
||||
if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
|
||||
ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
|
||||
goto ecerr;
|
||||
}
|
||||
|
||||
/* calculate public key (if necessary) */
|
||||
if (EC_KEY_get0_public_key(eckey) == NULL) {
|
||||
const BIGNUM *priv_key;
|
||||
const EC_GROUP *group;
|
||||
EC_POINT *pub_key;
|
||||
/*
|
||||
* the public key was not included in the SEC1 private key =>
|
||||
* calculate the public key
|
||||
*/
|
||||
group = EC_KEY_get0_group(eckey);
|
||||
pub_key = EC_POINT_new(group);
|
||||
if (pub_key == NULL) {
|
||||
ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
|
||||
goto ecliberr;
|
||||
}
|
||||
if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
|
||||
EC_POINT_free(pub_key);
|
||||
ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
|
||||
goto ecliberr;
|
||||
}
|
||||
priv_key = EC_KEY_get0_private_key(eckey);
|
||||
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) {
|
||||
EC_POINT_free(pub_key);
|
||||
ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
|
||||
goto ecliberr;
|
||||
}
|
||||
if (EC_KEY_set_public_key(eckey, pub_key) == 0) {
|
||||
EC_POINT_free(pub_key);
|
||||
ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
|
||||
goto ecliberr;
|
||||
}
|
||||
EC_POINT_free(pub_key);
|
||||
}
|
||||
|
||||
EVP_PKEY_assign_EC_KEY(pkey, eckey);
|
||||
return 1;
|
||||
|
||||
ecliberr:
|
||||
ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
|
||||
ecerr:
|
||||
if (eckey)
|
||||
EC_KEY_free(eckey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
|
||||
{
|
||||
EC_KEY ec_key = *(pkey->pkey.ec);
|
||||
unsigned char *ep, *p;
|
||||
int eplen, ptype;
|
||||
void *pval;
|
||||
unsigned int old_flags;
|
||||
|
||||
if (!eckey_param2type(&ptype, &pval, &ec_key)) {
|
||||
ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the private key */
|
||||
|
||||
/*
|
||||
* do not include the parameters in the SEC1 private key see PKCS#11
|
||||
* 12.11
|
||||
*/
|
||||
old_flags = EC_KEY_get_enc_flags(&ec_key);
|
||||
EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS);
|
||||
|
||||
eplen = i2d_ECPrivateKey(&ec_key, NULL);
|
||||
if (!eplen) {
|
||||
ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
|
||||
return 0;
|
||||
}
|
||||
ep = (unsigned char *)OPENSSL_malloc(eplen);
|
||||
if (!ep) {
|
||||
ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
p = ep;
|
||||
if (!i2d_ECPrivateKey(&ec_key, &p)) {
|
||||
OPENSSL_free(ep);
|
||||
ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
|
||||
ptype, pval, ep, eplen)) {
|
||||
OPENSSL_free(ep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int int_ec_size(const EVP_PKEY *pkey)
|
||||
{
|
||||
return ECDSA_size(pkey->pkey.ec);
|
||||
}
|
||||
|
||||
static int ec_bits(const EVP_PKEY *pkey)
|
||||
{
|
||||
BIGNUM *order = BN_new();
|
||||
const EC_GROUP *group;
|
||||
int ret;
|
||||
|
||||
if (!order) {
|
||||
ERR_clear_error();
|
||||
return 0;
|
||||
}
|
||||
group = EC_KEY_get0_group(pkey->pkey.ec);
|
||||
if (!EC_GROUP_get_order(group, order, NULL)) {
|
||||
ERR_clear_error();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = BN_num_bits(order);
|
||||
BN_free(order);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ec_missing_parameters(const EVP_PKEY *pkey)
|
||||
{
|
||||
if (pkey->pkey.ec == NULL || EC_KEY_get0_group(pkey->pkey.ec) == NULL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
|
||||
{
|
||||
EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
|
||||
if (group == NULL)
|
||||
return 0;
|
||||
if (EC_KEY_set_group(to->pkey.ec, group) == 0)
|
||||
return 0;
|
||||
EC_GROUP_free(group);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
|
||||
{
|
||||
const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
|
||||
*group_b = EC_KEY_get0_group(b->pkey.ec);
|
||||
if (group_a == NULL || group_b == NULL)
|
||||
return -2;
|
||||
if (EC_GROUP_cmp(group_a, group_b, NULL))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void int_ec_free(EVP_PKEY *pkey)
|
||||
{
|
||||
EC_KEY_free(pkey->pkey.ec);
|
||||
}
|
||||
|
||||
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
|
||||
{
|
||||
unsigned char *buffer = NULL;
|
||||
const char *ecstr;
|
||||
size_t buf_len = 0, i;
|
||||
int ret = 0, reason = ERR_R_BIO_LIB;
|
||||
BIGNUM *pub_key = NULL, *order = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
const EC_GROUP *group;
|
||||
const EC_POINT *public_key;
|
||||
const BIGNUM *priv_key;
|
||||
|
||||
if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
|
||||
reason = ERR_R_PASSED_NULL_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ktype > 0) {
|
||||
public_key = EC_KEY_get0_public_key(x);
|
||||
if (public_key != NULL) {
|
||||
if ((pub_key = EC_POINT_point2bn(group, public_key,
|
||||
EC_KEY_get_conv_form(x), NULL,
|
||||
ctx)) == NULL) {
|
||||
reason = ERR_R_EC_LIB;
|
||||
goto err;
|
||||
}
|
||||
buf_len = (size_t)BN_num_bytes(pub_key);
|
||||
}
|
||||
}
|
||||
|
||||
if (ktype == 2) {
|
||||
priv_key = EC_KEY_get0_private_key(x);
|
||||
if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len)
|
||||
buf_len = i;
|
||||
} else
|
||||
priv_key = NULL;
|
||||
|
||||
if (ktype > 0) {
|
||||
buf_len += 10;
|
||||
if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (ktype == 2)
|
||||
ecstr = "Private-Key";
|
||||
else if (ktype == 1)
|
||||
ecstr = "Public-Key";
|
||||
else
|
||||
ecstr = "ECDSA-Parameters";
|
||||
|
||||
if (!BIO_indent(bp, off, 128))
|
||||
goto err;
|
||||
if ((order = BN_new()) == NULL)
|
||||
goto err;
|
||||
if (!EC_GROUP_get_order(group, order, NULL))
|
||||
goto err;
|
||||
if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0)
|
||||
goto err;
|
||||
|
||||
if ((priv_key != NULL) && !ASN1_bn_print(bp, "priv:", priv_key,
|
||||
buffer, off))
|
||||
goto err;
|
||||
if ((pub_key != NULL) && !ASN1_bn_print(bp, "pub: ", pub_key,
|
||||
buffer, off))
|
||||
goto err;
|
||||
if (!ECPKParameters_print(bp, group, off))
|
||||
goto err;
|
||||
ret = 1;
|
||||
err:
|
||||
if (!ret)
|
||||
ECerr(EC_F_DO_EC_KEY_PRINT, reason);
|
||||
if (pub_key)
|
||||
BN_free(pub_key);
|
||||
if (order)
|
||||
BN_free(order);
|
||||
if (ctx)
|
||||
BN_CTX_free(ctx);
|
||||
if (buffer != NULL)
|
||||
OPENSSL_free(buffer);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int eckey_param_decode(EVP_PKEY *pkey,
|
||||
const unsigned char **pder, int derlen)
|
||||
{
|
||||
EC_KEY *eckey;
|
||||
if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) {
|
||||
ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB);
|
||||
return 0;
|
||||
}
|
||||
EVP_PKEY_assign_EC_KEY(pkey, eckey);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
|
||||
{
|
||||
return i2d_ECParameters(pkey->pkey.ec, pder);
|
||||
}
|
||||
|
||||
static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx)
|
||||
{
|
||||
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
|
||||
}
|
||||
|
||||
static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx)
|
||||
{
|
||||
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
|
||||
}
|
||||
|
||||
static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx)
|
||||
{
|
||||
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
|
||||
}
|
||||
|
||||
static int old_ec_priv_decode(EVP_PKEY *pkey,
|
||||
const unsigned char **pder, int derlen)
|
||||
{
|
||||
EC_KEY *ec;
|
||||
if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) {
|
||||
ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
EVP_PKEY_assign_EC_KEY(pkey, ec);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
|
||||
{
|
||||
return i2d_ECPrivateKey(pkey->pkey.ec, pder);
|
||||
}
|
||||
|
||||
static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
||||
{
|
||||
switch (op) {
|
||||
case ASN1_PKEY_CTRL_PKCS7_SIGN:
|
||||
if (arg1 == 0) {
|
||||
int snid, hnid;
|
||||
X509_ALGOR *alg1, *alg2;
|
||||
PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
|
||||
if (alg1 == NULL || alg1->algorithm == NULL)
|
||||
return -1;
|
||||
hnid = OBJ_obj2nid(alg1->algorithm);
|
||||
if (hnid == NID_undef)
|
||||
return -1;
|
||||
if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
|
||||
return -1;
|
||||
X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
|
||||
}
|
||||
return 1;
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
case ASN1_PKEY_CTRL_CMS_SIGN:
|
||||
if (arg1 == 0) {
|
||||
int snid, hnid;
|
||||
X509_ALGOR *alg1, *alg2;
|
||||
CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
|
||||
if (alg1 == NULL || alg1->algorithm == NULL)
|
||||
return -1;
|
||||
hnid = OBJ_obj2nid(alg1->algorithm);
|
||||
if (hnid == NID_undef)
|
||||
return -1;
|
||||
if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
|
||||
return -1;
|
||||
X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
|
||||
}
|
||||
return 1;
|
||||
|
||||
case ASN1_PKEY_CTRL_CMS_ENVELOPE:
|
||||
if (arg1 == 1)
|
||||
return ecdh_cms_decrypt(arg2);
|
||||
else if (arg1 == 0)
|
||||
return ecdh_cms_encrypt(arg2);
|
||||
return -2;
|
||||
|
||||
case ASN1_PKEY_CTRL_CMS_RI_TYPE:
|
||||
*(int *)arg2 = CMS_RECIPINFO_AGREE;
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
|
||||
*(int *)arg2 = NID_sha256;
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
|
||||
EVP_PKEY_EC,
|
||||
EVP_PKEY_EC,
|
||||
0,
|
||||
"EC",
|
||||
"OpenSSL EC algorithm",
|
||||
|
||||
eckey_pub_decode,
|
||||
eckey_pub_encode,
|
||||
eckey_pub_cmp,
|
||||
eckey_pub_print,
|
||||
|
||||
eckey_priv_decode,
|
||||
eckey_priv_encode,
|
||||
eckey_priv_print,
|
||||
|
||||
int_ec_size,
|
||||
ec_bits,
|
||||
|
||||
eckey_param_decode,
|
||||
eckey_param_encode,
|
||||
ec_missing_parameters,
|
||||
ec_copy_parameters,
|
||||
ec_cmp_parameters,
|
||||
eckey_param_print,
|
||||
0,
|
||||
|
||||
int_ec_free,
|
||||
ec_pkey_ctrl,
|
||||
old_ec_priv_decode,
|
||||
old_ec_priv_encode
|
||||
};
|
||||
|
||||
#ifndef OPENSSL_NO_CMS
|
||||
|
||||
static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
|
||||
X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
|
||||
{
|
||||
ASN1_OBJECT *aoid;
|
||||
int atype;
|
||||
void *aval;
|
||||
int rv = 0;
|
||||
EVP_PKEY *pkpeer = NULL;
|
||||
EC_KEY *ecpeer = NULL;
|
||||
const unsigned char *p;
|
||||
int plen;
|
||||
X509_ALGOR_get0(&aoid, &atype, &aval, alg);
|
||||
if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey)
|
||||
goto err;
|
||||
/* If absent parameters get group from main key */
|
||||
if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) {
|
||||
const EC_GROUP *grp;
|
||||
EVP_PKEY *pk;
|
||||
pk = EVP_PKEY_CTX_get0_pkey(pctx);
|
||||
if (!pk)
|
||||
goto err;
|
||||
grp = EC_KEY_get0_group(pk->pkey.ec);
|
||||
ecpeer = EC_KEY_new();
|
||||
if (!ecpeer)
|
||||
goto err;
|
||||
if (!EC_KEY_set_group(ecpeer, grp))
|
||||
goto err;
|
||||
} else {
|
||||
ecpeer = eckey_type2param(atype, aval);
|
||||
if (!ecpeer)
|
||||
goto err;
|
||||
}
|
||||
/* We have parameters now set public key */
|
||||
plen = ASN1_STRING_length(pubkey);
|
||||
p = ASN1_STRING_data(pubkey);
|
||||
if (!p || !plen)
|
||||
goto err;
|
||||
if (!o2i_ECPublicKey(&ecpeer, &p, plen))
|
||||
goto err;
|
||||
pkpeer = EVP_PKEY_new();
|
||||
if (!pkpeer)
|
||||
goto err;
|
||||
EVP_PKEY_set1_EC_KEY(pkpeer, ecpeer);
|
||||
if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
|
||||
rv = 1;
|
||||
err:
|
||||
if (ecpeer)
|
||||
EC_KEY_free(ecpeer);
|
||||
if (pkpeer)
|
||||
EVP_PKEY_free(pkpeer);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Set KDF parameters based on KDF NID */
|
||||
static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
|
||||
{
|
||||
int kdf_nid, kdfmd_nid, cofactor;
|
||||
const EVP_MD *kdf_md;
|
||||
if (eckdf_nid == NID_undef)
|
||||
return 0;
|
||||
|
||||
/* Lookup KDF type, cofactor mode and digest */
|
||||
if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid))
|
||||
return 0;
|
||||
|
||||
if (kdf_nid == NID_dh_std_kdf)
|
||||
cofactor = 0;
|
||||
else if (kdf_nid == NID_dh_cofactor_kdf)
|
||||
cofactor = 1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
|
||||
return 0;
|
||||
|
||||
if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_62) <= 0)
|
||||
return 0;
|
||||
|
||||
kdf_md = EVP_get_digestbynid(kdfmd_nid);
|
||||
if (!kdf_md)
|
||||
return 0;
|
||||
|
||||
if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
X509_ALGOR *alg, *kekalg = NULL;
|
||||
ASN1_OCTET_STRING *ukm;
|
||||
const unsigned char *p;
|
||||
unsigned char *der = NULL;
|
||||
int plen, keylen;
|
||||
const EVP_CIPHER *kekcipher;
|
||||
EVP_CIPHER_CTX *kekctx;
|
||||
|
||||
if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
|
||||
return 0;
|
||||
|
||||
if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
|
||||
ECerr(EC_F_ECDH_CMS_SET_SHARED_INFO, EC_R_KDF_PARAMETER_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (alg->parameter->type != V_ASN1_SEQUENCE)
|
||||
return 0;
|
||||
|
||||
p = alg->parameter->value.sequence->data;
|
||||
plen = alg->parameter->value.sequence->length;
|
||||
kekalg = d2i_X509_ALGOR(NULL, &p, plen);
|
||||
if (!kekalg)
|
||||
goto err;
|
||||
kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
|
||||
if (!kekctx)
|
||||
goto err;
|
||||
kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
|
||||
if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
|
||||
goto err;
|
||||
if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
|
||||
goto err;
|
||||
if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
|
||||
goto err;
|
||||
|
||||
keylen = EVP_CIPHER_CTX_key_length(kekctx);
|
||||
if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
|
||||
goto err;
|
||||
|
||||
plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);
|
||||
|
||||
if (!plen)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
|
||||
goto err;
|
||||
der = NULL;
|
||||
|
||||
rv = 1;
|
||||
err:
|
||||
if (kekalg)
|
||||
X509_ALGOR_free(kekalg);
|
||||
if (der)
|
||||
OPENSSL_free(der);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int ecdh_cms_decrypt(CMS_RecipientInfo *ri)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx;
|
||||
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
||||
if (!pctx)
|
||||
return 0;
|
||||
/* See if we need to set peer key */
|
||||
if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
|
||||
X509_ALGOR *alg;
|
||||
ASN1_BIT_STRING *pubkey;
|
||||
if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
|
||||
NULL, NULL, NULL))
|
||||
return 0;
|
||||
if (!alg || !pubkey)
|
||||
return 0;
|
||||
if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) {
|
||||
ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_PEER_KEY_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Set ECDH derivation parameters and initialise unwrap context */
|
||||
if (!ecdh_cms_set_shared_info(pctx, ri)) {
|
||||
ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_SHARED_INFO_ERROR);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx;
|
||||
EVP_PKEY *pkey;
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int keylen;
|
||||
X509_ALGOR *talg, *wrap_alg = NULL;
|
||||
ASN1_OBJECT *aoid;
|
||||
ASN1_BIT_STRING *pubkey;
|
||||
ASN1_STRING *wrap_str;
|
||||
ASN1_OCTET_STRING *ukm;
|
||||
unsigned char *penc = NULL;
|
||||
int penclen;
|
||||
int rv = 0;
|
||||
int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
|
||||
const EVP_MD *kdf_md;
|
||||
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
|
||||
if (!pctx)
|
||||
return 0;
|
||||
/* Get ephemeral key */
|
||||
pkey = EVP_PKEY_CTX_get0_pkey(pctx);
|
||||
if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
|
||||
NULL, NULL, NULL))
|
||||
goto err;
|
||||
X509_ALGOR_get0(&aoid, NULL, NULL, talg);
|
||||
/* Is everything uninitialised? */
|
||||
if (aoid == OBJ_nid2obj(NID_undef)) {
|
||||
|
||||
EC_KEY *eckey = pkey->pkey.ec;
|
||||
/* Set the key */
|
||||
unsigned char *p;
|
||||
|
||||
penclen = i2o_ECPublicKey(eckey, NULL);
|
||||
if (penclen <= 0)
|
||||
goto err;
|
||||
penc = OPENSSL_malloc(penclen);
|
||||
if (!penc)
|
||||
goto err;
|
||||
p = penc;
|
||||
penclen = i2o_ECPublicKey(eckey, &p);
|
||||
if (penclen <= 0)
|
||||
goto err;
|
||||
ASN1_STRING_set0(pubkey, penc, penclen);
|
||||
pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
|
||||
pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
|
||||
|
||||
penc = NULL;
|
||||
X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
|
||||
V_ASN1_UNDEF, NULL);
|
||||
}
|
||||
|
||||
/* See if custom paraneters set */
|
||||
kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
|
||||
if (kdf_type <= 0)
|
||||
goto err;
|
||||
if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md))
|
||||
goto err;
|
||||
ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
|
||||
if (ecdh_nid < 0)
|
||||
goto err;
|
||||
else if (ecdh_nid == 0)
|
||||
ecdh_nid = NID_dh_std_kdf;
|
||||
else if (ecdh_nid == 1)
|
||||
ecdh_nid = NID_dh_cofactor_kdf;
|
||||
|
||||
if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
|
||||
kdf_type = EVP_PKEY_ECDH_KDF_X9_62;
|
||||
if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
|
||||
goto err;
|
||||
} else
|
||||
/* Uknown KDF */
|
||||
goto err;
|
||||
if (kdf_md == NULL) {
|
||||
/* Fixme later for better MD */
|
||||
kdf_md = EVP_sha1();
|
||||
if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
|
||||
goto err;
|
||||
|
||||
/* Lookup NID for KDF+cofactor+digest */
|
||||
|
||||
if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid))
|
||||
goto err;
|
||||
/* Get wrap NID */
|
||||
ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
|
||||
wrap_nid = EVP_CIPHER_CTX_type(ctx);
|
||||
keylen = EVP_CIPHER_CTX_key_length(ctx);
|
||||
|
||||
/* Package wrap algorithm in an AlgorithmIdentifier */
|
||||
|
||||
wrap_alg = X509_ALGOR_new();
|
||||
if (!wrap_alg)
|
||||
goto err;
|
||||
wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
|
||||
wrap_alg->parameter = ASN1_TYPE_new();
|
||||
if (!wrap_alg->parameter)
|
||||
goto err;
|
||||
if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
|
||||
goto err;
|
||||
if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
|
||||
ASN1_TYPE_free(wrap_alg->parameter);
|
||||
wrap_alg->parameter = NULL;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
|
||||
goto err;
|
||||
|
||||
penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);
|
||||
|
||||
if (!penclen)
|
||||
goto err;
|
||||
|
||||
if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
|
||||
goto err;
|
||||
penc = NULL;
|
||||
|
||||
/*
|
||||
* Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
|
||||
* of another AlgorithmIdentifier.
|
||||
*/
|
||||
penclen = i2d_X509_ALGOR(wrap_alg, &penc);
|
||||
if (!penc || !penclen)
|
||||
goto err;
|
||||
wrap_str = ASN1_STRING_new();
|
||||
if (!wrap_str)
|
||||
goto err;
|
||||
ASN1_STRING_set0(wrap_str, penc, penclen);
|
||||
penc = NULL;
|
||||
X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);
|
||||
|
||||
rv = 1;
|
||||
|
||||
err:
|
||||
if (penc)
|
||||
OPENSSL_free(penc);
|
||||
if (wrap_alg)
|
||||
X509_ALGOR_free(wrap_alg);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,120 @@
|
||||
/* crypto/ec/ec_check.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2002 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).
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ec_lcl.h"
|
||||
#include <openssl/err.h>
|
||||
|
||||
int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
BIGNUM *order;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
EC_POINT *point = NULL;
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
ECerr(EC_F_EC_GROUP_CHECK, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
BN_CTX_start(ctx);
|
||||
if ((order = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
/* check the discriminant */
|
||||
if (!EC_GROUP_check_discriminant(group, ctx)) {
|
||||
ECerr(EC_F_EC_GROUP_CHECK, EC_R_DISCRIMINANT_IS_ZERO);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* check the generator */
|
||||
if (group->generator == NULL) {
|
||||
ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
|
||||
goto err;
|
||||
}
|
||||
if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) {
|
||||
ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* check the order of the generator */
|
||||
if ((point = EC_POINT_new(group)) == NULL)
|
||||
goto err;
|
||||
if (!EC_GROUP_get_order(group, order, ctx))
|
||||
goto err;
|
||||
if (BN_is_zero(order)) {
|
||||
ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_ORDER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EC_POINT_mul(group, point, order, NULL, NULL, ctx))
|
||||
goto err;
|
||||
if (!EC_POINT_is_at_infinity(group, point)) {
|
||||
ECerr(EC_F_EC_GROUP_CHECK, EC_R_INVALID_GROUP_ORDER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (ctx != NULL)
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
if (point)
|
||||
EC_POINT_free(point);
|
||||
return ret;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,180 @@
|
||||
/* crypto/ec/ec_cvt.c */
|
||||
/*
|
||||
* Originally written by Bodo Moeller for the OpenSSL project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2002 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 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* Portions of the attached software ("Contribution") are developed by
|
||||
* SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
|
||||
*
|
||||
* The Contribution is licensed pursuant to the OpenSSL open source
|
||||
* license provided above.
|
||||
*
|
||||
* The elliptic curve binary polynomial software is originally written by
|
||||
* Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include "ec_lcl.h"
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
# include <openssl/fips.h>
|
||||
#endif
|
||||
|
||||
EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
const EC_METHOD *meth;
|
||||
EC_GROUP *ret;
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
if (FIPS_mode())
|
||||
return FIPS_ec_group_new_curve_gfp(p, a, b, ctx);
|
||||
#endif
|
||||
#if defined(OPENSSL_BN_ASM_MONT)
|
||||
/*
|
||||
* This might appear controversial, but the fact is that generic
|
||||
* prime method was observed to deliver better performance even
|
||||
* for NIST primes on a range of platforms, e.g.: 60%-15%
|
||||
* improvement on IA-64, ~25% on ARM, 30%-90% on P4, 20%-25%
|
||||
* in 32-bit build and 35%--12% in 64-bit build on Core2...
|
||||
* Coefficients are relative to optimized bn_nist.c for most
|
||||
* intensive ECDSA verify and ECDH operations for 192- and 521-
|
||||
* bit keys respectively. Choice of these boundary values is
|
||||
* arguable, because the dependency of improvement coefficient
|
||||
* from key length is not a "monotone" curve. For example while
|
||||
* 571-bit result is 23% on ARM, 384-bit one is -1%. But it's
|
||||
* generally faster, sometimes "respectfully" faster, sometimes
|
||||
* "tolerably" slower... What effectively happens is that loop
|
||||
* with bn_mul_add_words is put against bn_mul_mont, and the
|
||||
* latter "wins" on short vectors. Correct solution should be
|
||||
* implementing dedicated NxN multiplication subroutines for
|
||||
* small N. But till it materializes, let's stick to generic
|
||||
* prime method...
|
||||
* <appro>
|
||||
*/
|
||||
meth = EC_GFp_mont_method();
|
||||
#else
|
||||
meth = EC_GFp_nist_method();
|
||||
#endif
|
||||
|
||||
ret = EC_GROUP_new(meth);
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx)) {
|
||||
unsigned long err;
|
||||
|
||||
err = ERR_peek_last_error();
|
||||
|
||||
if (!(ERR_GET_LIB(err) == ERR_LIB_EC &&
|
||||
((ERR_GET_REASON(err) == EC_R_NOT_A_NIST_PRIME) ||
|
||||
(ERR_GET_REASON(err) == EC_R_NOT_A_SUPPORTED_NIST_PRIME)))) {
|
||||
/* real error */
|
||||
|
||||
EC_GROUP_clear_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* not an actual error, we just cannot use EC_GFp_nist_method
|
||||
*/
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
EC_GROUP_clear_free(ret);
|
||||
meth = EC_GFp_mont_method();
|
||||
|
||||
ret = EC_GROUP_new(meth);
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!EC_GROUP_set_curve_GFp(ret, p, a, b, ctx)) {
|
||||
EC_GROUP_clear_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
EC_GROUP *EC_GROUP_new_curve_GF2m(const BIGNUM *p, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
const EC_METHOD *meth;
|
||||
EC_GROUP *ret;
|
||||
|
||||
# ifdef OPENSSL_FIPS
|
||||
if (FIPS_mode())
|
||||
return FIPS_ec_group_new_curve_gf2m(p, a, b, ctx);
|
||||
# endif
|
||||
meth = EC_GF2m_simple_method();
|
||||
|
||||
ret = EC_GROUP_new(meth);
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!EC_GROUP_set_curve_GF2m(ret, p, a, b, ctx)) {
|
||||
EC_GROUP_clear_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,334 @@
|
||||
/* crypto/ec/ec_err.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2020 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).
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: this file was auto generated by the mkerr.pl script: any changes
|
||||
* made to it will be overwritten when the script next updates this file,
|
||||
* only reason strings will be preserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ec.h>
|
||||
|
||||
/* BEGIN ERROR CODES */
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
# define ERR_FUNC(func) ERR_PACK(ERR_LIB_EC,func,0)
|
||||
# define ERR_REASON(reason) ERR_PACK(ERR_LIB_EC,0,reason)
|
||||
|
||||
static ERR_STRING_DATA EC_str_functs[] = {
|
||||
{ERR_FUNC(EC_F_BN_TO_FELEM), "BN_TO_FELEM"},
|
||||
{ERR_FUNC(EC_F_COMPUTE_WNAF), "COMPUTE_WNAF"},
|
||||
{ERR_FUNC(EC_F_D2I_ECPARAMETERS), "d2i_ECParameters"},
|
||||
{ERR_FUNC(EC_F_D2I_ECPKPARAMETERS), "d2i_ECPKParameters"},
|
||||
{ERR_FUNC(EC_F_D2I_ECPRIVATEKEY), "d2i_ECPrivateKey"},
|
||||
{ERR_FUNC(EC_F_DO_EC_KEY_PRINT), "DO_EC_KEY_PRINT"},
|
||||
{ERR_FUNC(EC_F_ECDH_CMS_DECRYPT), "ECDH_CMS_DECRYPT"},
|
||||
{ERR_FUNC(EC_F_ECDH_CMS_SET_SHARED_INFO), "ECDH_CMS_SET_SHARED_INFO"},
|
||||
{ERR_FUNC(EC_F_ECKEY_PARAM2TYPE), "ECKEY_PARAM2TYPE"},
|
||||
{ERR_FUNC(EC_F_ECKEY_PARAM_DECODE), "ECKEY_PARAM_DECODE"},
|
||||
{ERR_FUNC(EC_F_ECKEY_PRIV_DECODE), "ECKEY_PRIV_DECODE"},
|
||||
{ERR_FUNC(EC_F_ECKEY_PRIV_ENCODE), "ECKEY_PRIV_ENCODE"},
|
||||
{ERR_FUNC(EC_F_ECKEY_PUB_DECODE), "ECKEY_PUB_DECODE"},
|
||||
{ERR_FUNC(EC_F_ECKEY_PUB_ENCODE), "ECKEY_PUB_ENCODE"},
|
||||
{ERR_FUNC(EC_F_ECKEY_TYPE2PARAM), "ECKEY_TYPE2PARAM"},
|
||||
{ERR_FUNC(EC_F_ECPARAMETERS_PRINT), "ECParameters_print"},
|
||||
{ERR_FUNC(EC_F_ECPARAMETERS_PRINT_FP), "ECParameters_print_fp"},
|
||||
{ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT), "ECPKParameters_print"},
|
||||
{ERR_FUNC(EC_F_ECPKPARAMETERS_PRINT_FP), "ECPKParameters_print_fp"},
|
||||
{ERR_FUNC(EC_F_ECP_NISTZ256_GET_AFFINE), "ecp_nistz256_get_affine"},
|
||||
{ERR_FUNC(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE),
|
||||
"ecp_nistz256_mult_precompute"},
|
||||
{ERR_FUNC(EC_F_ECP_NISTZ256_POINTS_MUL), "ecp_nistz256_points_mul"},
|
||||
{ERR_FUNC(EC_F_ECP_NISTZ256_PRE_COMP_NEW), "ecp_nistz256_pre_comp_new"},
|
||||
{ERR_FUNC(EC_F_ECP_NISTZ256_SET_WORDS), "ecp_nistz256_set_words"},
|
||||
{ERR_FUNC(EC_F_ECP_NISTZ256_WINDOWED_MUL), "ecp_nistz256_windowed_mul"},
|
||||
{ERR_FUNC(EC_F_ECP_NIST_MOD_192), "ECP_NIST_MOD_192"},
|
||||
{ERR_FUNC(EC_F_ECP_NIST_MOD_224), "ECP_NIST_MOD_224"},
|
||||
{ERR_FUNC(EC_F_ECP_NIST_MOD_256), "ECP_NIST_MOD_256"},
|
||||
{ERR_FUNC(EC_F_ECP_NIST_MOD_521), "ECP_NIST_MOD_521"},
|
||||
{ERR_FUNC(EC_F_EC_ASN1_GROUP2CURVE), "EC_ASN1_GROUP2CURVE"},
|
||||
{ERR_FUNC(EC_F_EC_ASN1_GROUP2FIELDID), "EC_ASN1_GROUP2FIELDID"},
|
||||
{ERR_FUNC(EC_F_EC_ASN1_GROUP2PARAMETERS), "EC_ASN1_GROUP2PARAMETERS"},
|
||||
{ERR_FUNC(EC_F_EC_ASN1_GROUP2PKPARAMETERS), "EC_ASN1_GROUP2PKPARAMETERS"},
|
||||
{ERR_FUNC(EC_F_EC_ASN1_PARAMETERS2GROUP), "EC_ASN1_PARAMETERS2GROUP"},
|
||||
{ERR_FUNC(EC_F_EC_ASN1_PKPARAMETERS2GROUP), "EC_ASN1_PKPARAMETERS2GROUP"},
|
||||
{ERR_FUNC(EC_F_EC_EX_DATA_SET_DATA), "EC_EX_DATA_set_data"},
|
||||
{ERR_FUNC(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY),
|
||||
"EC_GF2M_MONTGOMERY_POINT_MULTIPLY"},
|
||||
{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT),
|
||||
"ec_GF2m_simple_group_check_discriminant"},
|
||||
{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE),
|
||||
"ec_GF2m_simple_group_set_curve"},
|
||||
{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_OCT2POINT), "ec_GF2m_simple_oct2point"},
|
||||
{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT2OCT), "ec_GF2m_simple_point2oct"},
|
||||
{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES),
|
||||
"ec_GF2m_simple_point_get_affine_coordinates"},
|
||||
{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES),
|
||||
"ec_GF2m_simple_point_set_affine_coordinates"},
|
||||
{ERR_FUNC(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES),
|
||||
"ec_GF2m_simple_set_compressed_coordinates"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_DECODE), "ec_GFp_mont_field_decode"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_ENCODE), "ec_GFp_mont_field_encode"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_MUL), "ec_GFp_mont_field_mul"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE),
|
||||
"ec_GFp_mont_field_set_to_one"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_MONT_FIELD_SQR), "ec_GFp_mont_field_sqr"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE),
|
||||
"ec_GFp_mont_group_set_curve"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP),
|
||||
"EC_GFP_MONT_GROUP_SET_CURVE_GFP"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE),
|
||||
"ec_GFp_nistp224_group_set_curve"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NISTP224_POINTS_MUL), "ec_GFp_nistp224_points_mul"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES),
|
||||
"ec_GFp_nistp224_point_get_affine_coordinates"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE),
|
||||
"ec_GFp_nistp256_group_set_curve"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NISTP256_POINTS_MUL), "ec_GFp_nistp256_points_mul"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES),
|
||||
"ec_GFp_nistp256_point_get_affine_coordinates"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE),
|
||||
"ec_GFp_nistp521_group_set_curve"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NISTP521_POINTS_MUL), "ec_GFp_nistp521_points_mul"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES),
|
||||
"ec_GFp_nistp521_point_get_affine_coordinates"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_MUL), "ec_GFp_nist_field_mul"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE),
|
||||
"ec_GFp_nist_group_set_curve"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT),
|
||||
"ec_GFp_simple_group_check_discriminant"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE),
|
||||
"ec_GFp_simple_group_set_curve"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP),
|
||||
"EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR),
|
||||
"EC_GFP_SIMPLE_GROUP_SET_GENERATOR"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE), "ec_GFp_simple_make_affine"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_OCT2POINT), "ec_GFp_simple_oct2point"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT2OCT), "ec_GFp_simple_point2oct"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE),
|
||||
"ec_GFp_simple_points_make_affine"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES),
|
||||
"ec_GFp_simple_point_get_affine_coordinates"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP),
|
||||
"EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES),
|
||||
"ec_GFp_simple_point_set_affine_coordinates"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP),
|
||||
"EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES),
|
||||
"ec_GFp_simple_set_compressed_coordinates"},
|
||||
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP),
|
||||
"EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_CHECK), "EC_GROUP_check"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_CHECK_DISCRIMINANT),
|
||||
"EC_GROUP_check_discriminant"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_COPY), "EC_GROUP_copy"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_GET0_GENERATOR), "EC_GROUP_get0_generator"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_GET_COFACTOR), "EC_GROUP_get_cofactor"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GF2M), "EC_GROUP_get_curve_GF2m"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_GET_CURVE_GFP), "EC_GROUP_get_curve_GFp"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_GET_DEGREE), "EC_GROUP_get_degree"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_GET_ORDER), "EC_GROUP_get_order"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS),
|
||||
"EC_GROUP_get_pentanomial_basis"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_GET_TRINOMIAL_BASIS),
|
||||
"EC_GROUP_get_trinomial_basis"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_NEW), "EC_GROUP_new"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_NEW_BY_CURVE_NAME), "EC_GROUP_new_by_curve_name"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_NEW_FROM_DATA), "EC_GROUP_NEW_FROM_DATA"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_PRECOMPUTE_MULT), "EC_GROUP_precompute_mult"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GF2M), "EC_GROUP_set_curve_GF2m"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_SET_CURVE_GFP), "EC_GROUP_set_curve_GFp"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_SET_EXTRA_DATA), "EC_GROUP_SET_EXTRA_DATA"},
|
||||
{ERR_FUNC(EC_F_EC_GROUP_SET_GENERATOR), "EC_GROUP_set_generator"},
|
||||
{ERR_FUNC(EC_F_EC_KEY_CHECK_KEY), "EC_KEY_check_key"},
|
||||
{ERR_FUNC(EC_F_EC_KEY_COPY), "EC_KEY_copy"},
|
||||
{ERR_FUNC(EC_F_EC_KEY_GENERATE_KEY), "EC_KEY_generate_key"},
|
||||
{ERR_FUNC(EC_F_EC_KEY_NEW), "EC_KEY_new"},
|
||||
{ERR_FUNC(EC_F_EC_KEY_PRINT), "EC_KEY_print"},
|
||||
{ERR_FUNC(EC_F_EC_KEY_PRINT_FP), "EC_KEY_print_fp"},
|
||||
{ERR_FUNC(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES),
|
||||
"EC_KEY_set_public_key_affine_coordinates"},
|
||||
{ERR_FUNC(EC_F_EC_MUL_CONSTTIME), "EC_MUL_CONSTTIME"},
|
||||
{ERR_FUNC(EC_F_EC_POINTS_MAKE_AFFINE), "EC_POINTs_make_affine"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_ADD), "EC_POINT_add"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_CMP), "EC_POINT_cmp"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_COPY), "EC_POINT_copy"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_DBL), "EC_POINT_dbl"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M),
|
||||
"EC_POINT_get_affine_coordinates_GF2m"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP),
|
||||
"EC_POINT_get_affine_coordinates_GFp"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP),
|
||||
"EC_POINT_get_Jprojective_coordinates_GFp"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_INVERT), "EC_POINT_invert"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_IS_AT_INFINITY), "EC_POINT_is_at_infinity"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_IS_ON_CURVE), "EC_POINT_is_on_curve"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_MAKE_AFFINE), "EC_POINT_make_affine"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_MUL), "EC_POINT_mul"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_NEW), "EC_POINT_new"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_OCT2POINT), "EC_POINT_oct2point"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_POINT2OCT), "EC_POINT_point2oct"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M),
|
||||
"EC_POINT_set_affine_coordinates_GF2m"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP),
|
||||
"EC_POINT_set_affine_coordinates_GFp"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M),
|
||||
"EC_POINT_set_compressed_coordinates_GF2m"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP),
|
||||
"EC_POINT_set_compressed_coordinates_GFp"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP),
|
||||
"EC_POINT_set_Jprojective_coordinates_GFp"},
|
||||
{ERR_FUNC(EC_F_EC_POINT_SET_TO_INFINITY), "EC_POINT_set_to_infinity"},
|
||||
{ERR_FUNC(EC_F_EC_PRE_COMP_DUP), "EC_PRE_COMP_DUP"},
|
||||
{ERR_FUNC(EC_F_EC_PRE_COMP_NEW), "EC_PRE_COMP_NEW"},
|
||||
{ERR_FUNC(EC_F_EC_WNAF_MUL), "ec_wNAF_mul"},
|
||||
{ERR_FUNC(EC_F_EC_WNAF_PRECOMPUTE_MULT), "ec_wNAF_precompute_mult"},
|
||||
{ERR_FUNC(EC_F_I2D_ECPARAMETERS), "i2d_ECParameters"},
|
||||
{ERR_FUNC(EC_F_I2D_ECPKPARAMETERS), "i2d_ECPKParameters"},
|
||||
{ERR_FUNC(EC_F_I2D_ECPRIVATEKEY), "i2d_ECPrivateKey"},
|
||||
{ERR_FUNC(EC_F_I2O_ECPUBLICKEY), "i2o_ECPublicKey"},
|
||||
{ERR_FUNC(EC_F_NISTP224_PRE_COMP_NEW), "NISTP224_PRE_COMP_NEW"},
|
||||
{ERR_FUNC(EC_F_NISTP256_PRE_COMP_NEW), "NISTP256_PRE_COMP_NEW"},
|
||||
{ERR_FUNC(EC_F_NISTP521_PRE_COMP_NEW), "NISTP521_PRE_COMP_NEW"},
|
||||
{ERR_FUNC(EC_F_O2I_ECPUBLICKEY), "o2i_ECPublicKey"},
|
||||
{ERR_FUNC(EC_F_OLD_EC_PRIV_DECODE), "OLD_EC_PRIV_DECODE"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_CTRL), "PKEY_EC_CTRL"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_CTRL_STR), "PKEY_EC_CTRL_STR"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_DERIVE), "PKEY_EC_DERIVE"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_KEYGEN), "PKEY_EC_KEYGEN"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_PARAMGEN), "PKEY_EC_PARAMGEN"},
|
||||
{ERR_FUNC(EC_F_PKEY_EC_SIGN), "PKEY_EC_SIGN"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static ERR_STRING_DATA EC_str_reasons[] = {
|
||||
{ERR_REASON(EC_R_ASN1_ERROR), "asn1 error"},
|
||||
{ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD), "asn1 unknown field"},
|
||||
{ERR_REASON(EC_R_BIGNUM_OUT_OF_RANGE), "bignum out of range"},
|
||||
{ERR_REASON(EC_R_BUFFER_TOO_SMALL), "buffer too small"},
|
||||
{ERR_REASON(EC_R_COORDINATES_OUT_OF_RANGE), "coordinates out of range"},
|
||||
{ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE),
|
||||
"d2i ecpkparameters failure"},
|
||||
{ERR_REASON(EC_R_DECODE_ERROR), "decode error"},
|
||||
{ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO), "discriminant is zero"},
|
||||
{ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),
|
||||
"ec group new by name failure"},
|
||||
{ERR_REASON(EC_R_FIELD_TOO_LARGE), "field too large"},
|
||||
{ERR_REASON(EC_R_GF2M_NOT_SUPPORTED), "gf2m not supported"},
|
||||
{ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE),
|
||||
"group2pkparameters failure"},
|
||||
{ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE),
|
||||
"i2d ecpkparameters failure"},
|
||||
{ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS), "incompatible objects"},
|
||||
{ERR_REASON(EC_R_INVALID_ARGUMENT), "invalid argument"},
|
||||
{ERR_REASON(EC_R_INVALID_COMPRESSED_POINT), "invalid compressed point"},
|
||||
{ERR_REASON(EC_R_INVALID_COMPRESSION_BIT), "invalid compression bit"},
|
||||
{ERR_REASON(EC_R_INVALID_CURVE), "invalid curve"},
|
||||
{ERR_REASON(EC_R_INVALID_DIGEST), "invalid digest"},
|
||||
{ERR_REASON(EC_R_INVALID_DIGEST_TYPE), "invalid digest type"},
|
||||
{ERR_REASON(EC_R_INVALID_ENCODING), "invalid encoding"},
|
||||
{ERR_REASON(EC_R_INVALID_FIELD), "invalid field"},
|
||||
{ERR_REASON(EC_R_INVALID_FORM), "invalid form"},
|
||||
{ERR_REASON(EC_R_INVALID_GROUP_ORDER), "invalid group order"},
|
||||
{ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS), "invalid pentanomial basis"},
|
||||
{ERR_REASON(EC_R_INVALID_PRIVATE_KEY), "invalid private key"},
|
||||
{ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS), "invalid trinomial basis"},
|
||||
{ERR_REASON(EC_R_KDF_PARAMETER_ERROR), "kdf parameter error"},
|
||||
{ERR_REASON(EC_R_KEYS_NOT_SET), "keys not set"},
|
||||
{ERR_REASON(EC_R_MISSING_PARAMETERS), "missing parameters"},
|
||||
{ERR_REASON(EC_R_MISSING_PRIVATE_KEY), "missing private key"},
|
||||
{ERR_REASON(EC_R_NOT_A_NIST_PRIME), "not a NIST prime"},
|
||||
{ERR_REASON(EC_R_NOT_A_SUPPORTED_NIST_PRIME),
|
||||
"not a supported NIST prime"},
|
||||
{ERR_REASON(EC_R_NOT_IMPLEMENTED), "not implemented"},
|
||||
{ERR_REASON(EC_R_NOT_INITIALIZED), "not initialized"},
|
||||
{ERR_REASON(EC_R_NO_FIELD_MOD), "no field mod"},
|
||||
{ERR_REASON(EC_R_NO_PARAMETERS_SET), "no parameters set"},
|
||||
{ERR_REASON(EC_R_PASSED_NULL_PARAMETER), "passed null parameter"},
|
||||
{ERR_REASON(EC_R_PEER_KEY_ERROR), "peer key error"},
|
||||
{ERR_REASON(EC_R_PKPARAMETERS2GROUP_FAILURE),
|
||||
"pkparameters2group failure"},
|
||||
{ERR_REASON(EC_R_POINT_AT_INFINITY), "point at infinity"},
|
||||
{ERR_REASON(EC_R_POINT_IS_NOT_ON_CURVE), "point is not on curve"},
|
||||
{ERR_REASON(EC_R_SHARED_INFO_ERROR), "shared info error"},
|
||||
{ERR_REASON(EC_R_SLOT_FULL), "slot full"},
|
||||
{ERR_REASON(EC_R_UNDEFINED_GENERATOR), "undefined generator"},
|
||||
{ERR_REASON(EC_R_UNDEFINED_ORDER), "undefined order"},
|
||||
{ERR_REASON(EC_R_UNKNOWN_COFACTOR), "unknown cofactor"},
|
||||
{ERR_REASON(EC_R_UNKNOWN_GROUP), "unknown group"},
|
||||
{ERR_REASON(EC_R_UNKNOWN_ORDER), "unknown order"},
|
||||
{ERR_REASON(EC_R_UNSUPPORTED_FIELD), "unsupported field"},
|
||||
{ERR_REASON(EC_R_WRONG_CURVE_PARAMETERS), "wrong curve parameters"},
|
||||
{ERR_REASON(EC_R_WRONG_ORDER), "wrong order"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void ERR_load_EC_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
if (ERR_func_error_string(EC_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings(0, EC_str_functs);
|
||||
ERR_load_strings(0, EC_str_reasons);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,572 @@
|
||||
/* crypto/ec/ec_key.c */
|
||||
/*
|
||||
* Written by Nils Larsch for the OpenSSL project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2022 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 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
* Portions originally developed by SUN MICROSYSTEMS, INC., and
|
||||
* contributed to the OpenSSL project.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "ec_lcl.h"
|
||||
#include <openssl/err.h>
|
||||
#ifdef OPENSSL_FIPS
|
||||
# include <openssl/fips.h>
|
||||
#endif
|
||||
|
||||
EC_KEY *EC_KEY_new(void)
|
||||
{
|
||||
EC_KEY *ret;
|
||||
|
||||
ret = (EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY));
|
||||
if (ret == NULL) {
|
||||
ECerr(EC_F_EC_KEY_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ret->version = 1;
|
||||
ret->flags = 0;
|
||||
ret->group = NULL;
|
||||
ret->pub_key = NULL;
|
||||
ret->priv_key = NULL;
|
||||
ret->enc_flag = 0;
|
||||
ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
|
||||
ret->references = 1;
|
||||
ret->method_data = NULL;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
EC_KEY *EC_KEY_new_by_curve_name(int nid)
|
||||
{
|
||||
EC_KEY *ret = EC_KEY_new();
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
ret->group = EC_GROUP_new_by_curve_name(nid);
|
||||
if (ret->group == NULL) {
|
||||
EC_KEY_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void EC_KEY_free(EC_KEY *r)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (r == NULL)
|
||||
return;
|
||||
|
||||
i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC);
|
||||
#ifdef REF_PRINT
|
||||
REF_PRINT("EC_KEY", r);
|
||||
#endif
|
||||
if (i > 0)
|
||||
return;
|
||||
#ifdef REF_CHECK
|
||||
if (i < 0) {
|
||||
fprintf(stderr, "EC_KEY_free, bad reference count\n");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (r->group != NULL)
|
||||
EC_GROUP_free(r->group);
|
||||
if (r->pub_key != NULL)
|
||||
EC_POINT_free(r->pub_key);
|
||||
if (r->priv_key != NULL)
|
||||
BN_clear_free(r->priv_key);
|
||||
|
||||
EC_EX_DATA_free_all_data(&r->method_data);
|
||||
|
||||
OPENSSL_cleanse((void *)r, sizeof(EC_KEY));
|
||||
|
||||
OPENSSL_free(r);
|
||||
}
|
||||
|
||||
EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
|
||||
{
|
||||
EC_EXTRA_DATA *d;
|
||||
|
||||
if (dest == NULL || src == NULL) {
|
||||
ECerr(EC_F_EC_KEY_COPY, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
/* copy the parameters */
|
||||
if (src->group) {
|
||||
const EC_METHOD *meth = EC_GROUP_method_of(src->group);
|
||||
/* clear the old group */
|
||||
if (dest->group)
|
||||
EC_GROUP_free(dest->group);
|
||||
dest->group = EC_GROUP_new(meth);
|
||||
if (dest->group == NULL)
|
||||
return NULL;
|
||||
if (!EC_GROUP_copy(dest->group, src->group))
|
||||
return NULL;
|
||||
}
|
||||
/* copy the public key */
|
||||
if (src->pub_key && src->group) {
|
||||
if (dest->pub_key)
|
||||
EC_POINT_free(dest->pub_key);
|
||||
dest->pub_key = EC_POINT_new(src->group);
|
||||
if (dest->pub_key == NULL)
|
||||
return NULL;
|
||||
if (!EC_POINT_copy(dest->pub_key, src->pub_key))
|
||||
return NULL;
|
||||
}
|
||||
/* copy the private key */
|
||||
if (src->priv_key) {
|
||||
if (dest->priv_key == NULL) {
|
||||
dest->priv_key = BN_new();
|
||||
if (dest->priv_key == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if (!BN_copy(dest->priv_key, src->priv_key))
|
||||
return NULL;
|
||||
}
|
||||
/* copy method/extra data */
|
||||
EC_EX_DATA_free_all_data(&dest->method_data);
|
||||
|
||||
for (d = src->method_data; d != NULL; d = d->next) {
|
||||
void *t = d->dup_func(d->data);
|
||||
|
||||
if (t == NULL)
|
||||
return 0;
|
||||
if (!EC_EX_DATA_set_data
|
||||
(&dest->method_data, t, d->dup_func, d->free_func,
|
||||
d->clear_free_func))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* copy the rest */
|
||||
dest->enc_flag = src->enc_flag;
|
||||
dest->conv_form = src->conv_form;
|
||||
dest->version = src->version;
|
||||
dest->flags = src->flags;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
EC_KEY *EC_KEY_dup(const EC_KEY *ec_key)
|
||||
{
|
||||
EC_KEY *ret = EC_KEY_new();
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
if (EC_KEY_copy(ret, ec_key) == NULL) {
|
||||
EC_KEY_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int EC_KEY_up_ref(EC_KEY *r)
|
||||
{
|
||||
int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC);
|
||||
#ifdef REF_PRINT
|
||||
REF_PRINT("EC_KEY", r);
|
||||
#endif
|
||||
#ifdef REF_CHECK
|
||||
if (i < 2) {
|
||||
fprintf(stderr, "EC_KEY_up, bad reference count\n");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
return ((i > 1) ? 1 : 0);
|
||||
}
|
||||
|
||||
int EC_KEY_generate_key(EC_KEY *eckey)
|
||||
{
|
||||
int ok = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
BIGNUM *priv_key = NULL, *order = NULL;
|
||||
EC_POINT *pub_key = NULL;
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
if (FIPS_mode())
|
||||
return FIPS_ec_key_generate_key(eckey);
|
||||
#endif
|
||||
|
||||
if (!eckey || !eckey->group) {
|
||||
ECerr(EC_F_EC_KEY_GENERATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((order = BN_new()) == NULL)
|
||||
goto err;
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
if (eckey->priv_key == NULL) {
|
||||
priv_key = BN_new();
|
||||
if (priv_key == NULL)
|
||||
goto err;
|
||||
} else
|
||||
priv_key = eckey->priv_key;
|
||||
|
||||
if (!EC_GROUP_get_order(eckey->group, order, ctx))
|
||||
goto err;
|
||||
|
||||
do
|
||||
if (!BN_rand_range(priv_key, order))
|
||||
goto err;
|
||||
while (BN_is_zero(priv_key)) ;
|
||||
|
||||
if (eckey->pub_key == NULL) {
|
||||
pub_key = EC_POINT_new(eckey->group);
|
||||
if (pub_key == NULL)
|
||||
goto err;
|
||||
} else
|
||||
pub_key = eckey->pub_key;
|
||||
|
||||
if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx))
|
||||
goto err;
|
||||
|
||||
eckey->priv_key = priv_key;
|
||||
eckey->pub_key = pub_key;
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
if (order)
|
||||
BN_free(order);
|
||||
if (pub_key != NULL && eckey->pub_key == NULL)
|
||||
EC_POINT_free(pub_key);
|
||||
if (priv_key != NULL && eckey->priv_key == NULL)
|
||||
BN_free(priv_key);
|
||||
if (ctx != NULL)
|
||||
BN_CTX_free(ctx);
|
||||
return (ok);
|
||||
}
|
||||
|
||||
int EC_KEY_check_key(const EC_KEY *eckey)
|
||||
{
|
||||
int ok = 0;
|
||||
BN_CTX *ctx = NULL;
|
||||
const BIGNUM *order = NULL;
|
||||
EC_POINT *point = NULL;
|
||||
|
||||
if (!eckey || !eckey->group || !eckey->pub_key) {
|
||||
ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
|
||||
ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_AT_INFINITY);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
if ((point = EC_POINT_new(eckey->group)) == NULL)
|
||||
goto err;
|
||||
|
||||
/* testing whether the pub_key is on the elliptic curve */
|
||||
if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) {
|
||||
ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
|
||||
goto err;
|
||||
}
|
||||
/* testing whether pub_key * order is the point at infinity */
|
||||
order = &eckey->group->order;
|
||||
if (BN_is_zero(order)) {
|
||||
ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
|
||||
goto err;
|
||||
}
|
||||
if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
|
||||
ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (!EC_POINT_is_at_infinity(eckey->group, point)) {
|
||||
ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* in case the priv_key is present : check if generator * priv_key ==
|
||||
* pub_key
|
||||
*/
|
||||
if (eckey->priv_key) {
|
||||
if (BN_cmp(eckey->priv_key, order) >= 0) {
|
||||
ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_WRONG_ORDER);
|
||||
goto err;
|
||||
}
|
||||
if (!EC_POINT_mul(eckey->group, point, eckey->priv_key,
|
||||
NULL, NULL, ctx)) {
|
||||
ECerr(EC_F_EC_KEY_CHECK_KEY, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
|
||||
ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
ok = 1;
|
||||
err:
|
||||
if (ctx != NULL)
|
||||
BN_CTX_free(ctx);
|
||||
if (point != NULL)
|
||||
EC_POINT_free(point);
|
||||
return (ok);
|
||||
}
|
||||
|
||||
int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
|
||||
BIGNUM *y)
|
||||
{
|
||||
BN_CTX *ctx = NULL;
|
||||
BIGNUM *tx, *ty;
|
||||
EC_POINT *point = NULL;
|
||||
int ok = 0;
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
int tmp_nid, is_char_two = 0;
|
||||
#endif
|
||||
|
||||
if (!key || !key->group || !x || !y) {
|
||||
ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
|
||||
ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
BN_CTX_start(ctx);
|
||||
point = EC_POINT_new(key->group);
|
||||
|
||||
if (!point)
|
||||
goto err;
|
||||
|
||||
tx = BN_CTX_get(ctx);
|
||||
ty = BN_CTX_get(ctx);
|
||||
if (ty == NULL)
|
||||
goto err;
|
||||
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));
|
||||
|
||||
if (tmp_nid == NID_X9_62_characteristic_two_field)
|
||||
is_char_two = 1;
|
||||
|
||||
if (is_char_two) {
|
||||
if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point,
|
||||
x, y, ctx))
|
||||
goto err;
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point,
|
||||
tx, ty, ctx))
|
||||
goto err;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (!EC_POINT_set_affine_coordinates_GFp(key->group, point,
|
||||
x, y, ctx))
|
||||
goto err;
|
||||
if (!EC_POINT_get_affine_coordinates_GFp(key->group, point,
|
||||
tx, ty, ctx))
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Check if retrieved coordinates match originals: if not values are out
|
||||
* of range.
|
||||
*/
|
||||
if (BN_cmp(x, tx) || BN_cmp(y, ty)) {
|
||||
ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
|
||||
EC_R_COORDINATES_OUT_OF_RANGE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EC_KEY_set_public_key(key, point))
|
||||
goto err;
|
||||
|
||||
if (EC_KEY_check_key(key) == 0)
|
||||
goto err;
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
EC_POINT_free(point);
|
||||
return ok;
|
||||
|
||||
}
|
||||
|
||||
const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
|
||||
{
|
||||
return key->group;
|
||||
}
|
||||
|
||||
int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
|
||||
{
|
||||
if (key->group != NULL)
|
||||
EC_GROUP_free(key->group);
|
||||
key->group = EC_GROUP_dup(group);
|
||||
return (key->group == NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key)
|
||||
{
|
||||
return key->priv_key;
|
||||
}
|
||||
|
||||
int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
|
||||
{
|
||||
if (key->priv_key)
|
||||
BN_clear_free(key->priv_key);
|
||||
key->priv_key = BN_dup(priv_key);
|
||||
return (key->priv_key == NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key)
|
||||
{
|
||||
return key->pub_key;
|
||||
}
|
||||
|
||||
int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
|
||||
{
|
||||
if (key->pub_key != NULL)
|
||||
EC_POINT_free(key->pub_key);
|
||||
key->pub_key = EC_POINT_dup(pub_key, key->group);
|
||||
return (key->pub_key == NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
unsigned int EC_KEY_get_enc_flags(const EC_KEY *key)
|
||||
{
|
||||
return key->enc_flag;
|
||||
}
|
||||
|
||||
void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
|
||||
{
|
||||
key->enc_flag = flags;
|
||||
}
|
||||
|
||||
point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key)
|
||||
{
|
||||
return key->conv_form;
|
||||
}
|
||||
|
||||
void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
|
||||
{
|
||||
key->conv_form = cform;
|
||||
if (key->group != NULL)
|
||||
EC_GROUP_set_point_conversion_form(key->group, cform);
|
||||
}
|
||||
|
||||
void *EC_KEY_get_key_method_data(EC_KEY *key,
|
||||
void *(*dup_func) (void *),
|
||||
void (*free_func) (void *),
|
||||
void (*clear_free_func) (void *))
|
||||
{
|
||||
void *ret;
|
||||
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_EC);
|
||||
ret =
|
||||
EC_EX_DATA_get_data(key->method_data, dup_func, free_func,
|
||||
clear_free_func);
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_EC);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data,
|
||||
void *(*dup_func) (void *),
|
||||
void (*free_func) (void *),
|
||||
void (*clear_free_func) (void *))
|
||||
{
|
||||
EC_EXTRA_DATA *ex_data;
|
||||
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_EC);
|
||||
ex_data =
|
||||
EC_EX_DATA_get_data(key->method_data, dup_func, free_func,
|
||||
clear_free_func);
|
||||
if (ex_data == NULL)
|
||||
EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func,
|
||||
clear_free_func);
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_EC);
|
||||
|
||||
return ex_data;
|
||||
}
|
||||
|
||||
void EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
|
||||
{
|
||||
if (key->group != NULL)
|
||||
EC_GROUP_set_asn1_flag(key->group, flag);
|
||||
}
|
||||
|
||||
int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
|
||||
{
|
||||
if (key->group == NULL)
|
||||
return 0;
|
||||
return EC_GROUP_precompute_mult(key->group, ctx);
|
||||
}
|
||||
|
||||
int EC_KEY_get_flags(const EC_KEY *key)
|
||||
{
|
||||
return key->flags;
|
||||
}
|
||||
|
||||
void EC_KEY_set_flags(EC_KEY *key, int flags)
|
||||
{
|
||||
key->flags |= flags;
|
||||
}
|
||||
|
||||
void EC_KEY_clear_flags(EC_KEY *key, int flags)
|
||||
{
|
||||
key->flags &= ~flags;
|
||||
}
|
||||
|
||||
int EC_KEY_decoded_from_explicit_params(const EC_KEY *key)
|
||||
{
|
||||
if (key == NULL || key->group == NULL)
|
||||
return -1;
|
||||
return EC_GROUP_VERSION(key->group)
|
||||
&& key->group->decoded_from_explicit_params;
|
||||
}
|
||||
@@ -0,0 +1,584 @@
|
||||
/* crypto/ec/ec_lcl.h */
|
||||
/*
|
||||
* Originally written by Bodo Moeller for the OpenSSL project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2022 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 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* Portions of the attached software ("Contribution") are developed by
|
||||
* SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
|
||||
*
|
||||
* The Contribution is licensed pursuant to the OpenSSL open source
|
||||
* license provided above.
|
||||
*
|
||||
* The elliptic curve binary polynomial software is originally written by
|
||||
* Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <openssl/obj_mac.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#if defined(__SUNPRO_C)
|
||||
# if __SUNPRO_C >= 0x520
|
||||
# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Use default functions for poin2oct, oct2point and compressed coordinates */
|
||||
#define EC_FLAGS_DEFAULT_OCT 0x1
|
||||
|
||||
/*
|
||||
* Structure details are not part of the exported interface, so all this may
|
||||
* change in future versions.
|
||||
*/
|
||||
|
||||
struct ec_method_st {
|
||||
/* Various method flags */
|
||||
int flags;
|
||||
/* used by EC_METHOD_get_field_type: */
|
||||
int field_type; /* a NID */
|
||||
/*
|
||||
* used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free,
|
||||
* EC_GROUP_copy:
|
||||
*/
|
||||
int (*group_init) (EC_GROUP *);
|
||||
void (*group_finish) (EC_GROUP *);
|
||||
void (*group_clear_finish) (EC_GROUP *);
|
||||
int (*group_copy) (EC_GROUP *, const EC_GROUP *);
|
||||
/* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */
|
||||
/* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */
|
||||
int (*group_set_curve) (EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *);
|
||||
int (*group_get_curve) (const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b,
|
||||
BN_CTX *);
|
||||
/* used by EC_GROUP_get_degree: */
|
||||
int (*group_get_degree) (const EC_GROUP *);
|
||||
/* used by EC_GROUP_check: */
|
||||
int (*group_check_discriminant) (const EC_GROUP *, BN_CTX *);
|
||||
/*
|
||||
* used by EC_POINT_new, EC_POINT_free, EC_POINT_clear_free,
|
||||
* EC_POINT_copy:
|
||||
*/
|
||||
int (*point_init) (EC_POINT *);
|
||||
void (*point_finish) (EC_POINT *);
|
||||
void (*point_clear_finish) (EC_POINT *);
|
||||
int (*point_copy) (EC_POINT *, const EC_POINT *);
|
||||
/*-
|
||||
* used by EC_POINT_set_to_infinity,
|
||||
* EC_POINT_set_Jprojective_coordinates_GFp,
|
||||
* EC_POINT_get_Jprojective_coordinates_GFp,
|
||||
* EC_POINT_set_affine_coordinates_GFp, ..._GF2m,
|
||||
* EC_POINT_get_affine_coordinates_GFp, ..._GF2m,
|
||||
* EC_POINT_set_compressed_coordinates_GFp, ..._GF2m:
|
||||
*/
|
||||
int (*point_set_to_infinity) (const EC_GROUP *, EC_POINT *);
|
||||
int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *,
|
||||
EC_POINT *, const BIGNUM *x,
|
||||
const BIGNUM *y,
|
||||
const BIGNUM *z, BN_CTX *);
|
||||
int (*point_get_Jprojective_coordinates_GFp) (const EC_GROUP *,
|
||||
const EC_POINT *, BIGNUM *x,
|
||||
BIGNUM *y, BIGNUM *z,
|
||||
BN_CTX *);
|
||||
int (*point_set_affine_coordinates) (const EC_GROUP *, EC_POINT *,
|
||||
const BIGNUM *x, const BIGNUM *y,
|
||||
BN_CTX *);
|
||||
int (*point_get_affine_coordinates) (const EC_GROUP *, const EC_POINT *,
|
||||
BIGNUM *x, BIGNUM *y, BN_CTX *);
|
||||
int (*point_set_compressed_coordinates) (const EC_GROUP *, EC_POINT *,
|
||||
const BIGNUM *x, int y_bit,
|
||||
BN_CTX *);
|
||||
/* used by EC_POINT_point2oct, EC_POINT_oct2point: */
|
||||
size_t (*point2oct) (const EC_GROUP *, const EC_POINT *,
|
||||
point_conversion_form_t form, unsigned char *buf,
|
||||
size_t len, BN_CTX *);
|
||||
int (*oct2point) (const EC_GROUP *, EC_POINT *, const unsigned char *buf,
|
||||
size_t len, BN_CTX *);
|
||||
/* used by EC_POINT_add, EC_POINT_dbl, ECP_POINT_invert: */
|
||||
int (*add) (const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
|
||||
const EC_POINT *b, BN_CTX *);
|
||||
int (*dbl) (const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
|
||||
int (*invert) (const EC_GROUP *, EC_POINT *, BN_CTX *);
|
||||
/*
|
||||
* used by EC_POINT_is_at_infinity, EC_POINT_is_on_curve, EC_POINT_cmp:
|
||||
*/
|
||||
int (*is_at_infinity) (const EC_GROUP *, const EC_POINT *);
|
||||
int (*is_on_curve) (const EC_GROUP *, const EC_POINT *, BN_CTX *);
|
||||
int (*point_cmp) (const EC_GROUP *, const EC_POINT *a, const EC_POINT *b,
|
||||
BN_CTX *);
|
||||
/* used by EC_POINT_make_affine, EC_POINTs_make_affine: */
|
||||
int (*make_affine) (const EC_GROUP *, EC_POINT *, BN_CTX *);
|
||||
int (*points_make_affine) (const EC_GROUP *, size_t num, EC_POINT *[],
|
||||
BN_CTX *);
|
||||
/*
|
||||
* used by EC_POINTs_mul, EC_POINT_mul, EC_POINT_precompute_mult,
|
||||
* EC_POINT_have_precompute_mult (default implementations are used if the
|
||||
* 'mul' pointer is 0):
|
||||
*/
|
||||
int (*mul) (const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
||||
size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
|
||||
BN_CTX *);
|
||||
int (*precompute_mult) (EC_GROUP *group, BN_CTX *);
|
||||
int (*have_precompute_mult) (const EC_GROUP *group);
|
||||
/* internal functions */
|
||||
/*
|
||||
* 'field_mul', 'field_sqr', and 'field_div' can be used by 'add' and
|
||||
* 'dbl' so that the same implementations of point operations can be used
|
||||
* with different optimized implementations of expensive field
|
||||
* operations:
|
||||
*/
|
||||
int (*field_mul) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *);
|
||||
int (*field_sqr) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *);
|
||||
int (*field_div) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *);
|
||||
/* e.g. to Montgomery */
|
||||
int (*field_encode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
BN_CTX *);
|
||||
/* e.g. from Montgomery */
|
||||
int (*field_decode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
BN_CTX *);
|
||||
int (*field_set_to_one) (const EC_GROUP *, BIGNUM *r, BN_CTX *);
|
||||
} /* EC_METHOD */ ;
|
||||
|
||||
typedef struct ec_extra_data_st {
|
||||
struct ec_extra_data_st *next;
|
||||
void *data;
|
||||
void *(*dup_func) (void *);
|
||||
void (*free_func) (void *);
|
||||
void (*clear_free_func) (void *);
|
||||
} EC_EXTRA_DATA; /* used in EC_GROUP */
|
||||
|
||||
struct ec_group_st {
|
||||
const EC_METHOD *meth;
|
||||
EC_POINT *generator; /* optional */
|
||||
BIGNUM order, cofactor;
|
||||
int curve_name; /* optional NID for named curve */
|
||||
int asn1_flag; /* flag to control the asn1 encoding */
|
||||
/*
|
||||
* Kludge: upper bit of ans1_flag is used to denote structure
|
||||
* version. If set, then last field is present. This is done
|
||||
* for interoperation with FIPS code.
|
||||
*/
|
||||
#define EC_GROUP_ASN1_FLAG_MASK 0x7fffffff
|
||||
#define EC_GROUP_VERSION(p) (p->asn1_flag&~EC_GROUP_ASN1_FLAG_MASK)
|
||||
point_conversion_form_t asn1_form;
|
||||
unsigned char *seed; /* optional seed for parameters (appears in
|
||||
* ASN1) */
|
||||
size_t seed_len;
|
||||
EC_EXTRA_DATA *extra_data; /* linked list */
|
||||
/*
|
||||
* The following members are handled by the method functions, even if
|
||||
* they appear generic
|
||||
*/
|
||||
/*
|
||||
* Field specification. For curves over GF(p), this is the modulus; for
|
||||
* curves over GF(2^m), this is the irreducible polynomial defining the
|
||||
* field.
|
||||
*/
|
||||
BIGNUM field;
|
||||
/*
|
||||
* Field specification for curves over GF(2^m). The irreducible f(t) is
|
||||
* then of the form: t^poly[0] + t^poly[1] + ... + t^poly[k] where m =
|
||||
* poly[0] > poly[1] > ... > poly[k] = 0. The array is terminated with
|
||||
* poly[k+1]=-1. All elliptic curve irreducibles have at most 5 non-zero
|
||||
* terms.
|
||||
*/
|
||||
int poly[6];
|
||||
/*
|
||||
* Curve coefficients. (Here the assumption is that BIGNUMs can be used
|
||||
* or abused for all kinds of fields, not just GF(p).) For characteristic
|
||||
* > 3, the curve is defined by a Weierstrass equation of the form y^2 =
|
||||
* x^3 + a*x + b. For characteristic 2, the curve is defined by an
|
||||
* equation of the form y^2 + x*y = x^3 + a*x^2 + b.
|
||||
*/
|
||||
BIGNUM a, b;
|
||||
/* enable optimized point arithmetics for special case */
|
||||
int a_is_minus3;
|
||||
/* method-specific (e.g., Montgomery structure) */
|
||||
void *field_data1;
|
||||
/* method-specific */
|
||||
void *field_data2;
|
||||
/* method-specific */
|
||||
int (*field_mod_func) (BIGNUM *, const BIGNUM *, const BIGNUM *,
|
||||
BN_CTX *);
|
||||
BN_MONT_CTX *mont_data; /* data for ECDSA inverse */
|
||||
int decoded_from_explicit_params; /* set if decoded from explicit
|
||||
* curve parameters encoding */
|
||||
} /* EC_GROUP */ ;
|
||||
|
||||
struct ec_key_st {
|
||||
int version;
|
||||
EC_GROUP *group;
|
||||
EC_POINT *pub_key;
|
||||
BIGNUM *priv_key;
|
||||
unsigned int enc_flag;
|
||||
point_conversion_form_t conv_form;
|
||||
int references;
|
||||
int flags;
|
||||
EC_EXTRA_DATA *method_data;
|
||||
} /* EC_KEY */ ;
|
||||
|
||||
/*
|
||||
* Basically a 'mixin' for extra data, but available for EC_GROUPs/EC_KEYs
|
||||
* only (with visibility limited to 'package' level for now). We use the
|
||||
* function pointers as index for retrieval; this obviates global
|
||||
* ex_data-style index tables.
|
||||
*/
|
||||
int EC_EX_DATA_set_data(EC_EXTRA_DATA **, void *data,
|
||||
void *(*dup_func) (void *),
|
||||
void (*free_func) (void *),
|
||||
void (*clear_free_func) (void *));
|
||||
void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *, void *(*dup_func) (void *),
|
||||
void (*free_func) (void *),
|
||||
void (*clear_free_func) (void *));
|
||||
void EC_EX_DATA_free_data(EC_EXTRA_DATA **, void *(*dup_func) (void *),
|
||||
void (*free_func) (void *),
|
||||
void (*clear_free_func) (void *));
|
||||
void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **, void *(*dup_func) (void *),
|
||||
void (*free_func) (void *),
|
||||
void (*clear_free_func) (void *));
|
||||
void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **);
|
||||
void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **);
|
||||
|
||||
struct ec_point_st {
|
||||
const EC_METHOD *meth;
|
||||
/*
|
||||
* All members except 'meth' are handled by the method functions, even if
|
||||
* they appear generic
|
||||
*/
|
||||
BIGNUM X;
|
||||
BIGNUM Y;
|
||||
BIGNUM Z; /* Jacobian projective coordinates: (X, Y, Z)
|
||||
* represents (X/Z^2, Y/Z^3) if Z != 0 */
|
||||
int Z_is_one; /* enable optimized point arithmetics for
|
||||
* special case */
|
||||
} /* EC_POINT */ ;
|
||||
|
||||
/*
|
||||
* method functions in ec_mult.c (ec_lib.c uses these as defaults if
|
||||
* group->method->mul is 0)
|
||||
*/
|
||||
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 *);
|
||||
int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *);
|
||||
int ec_wNAF_have_precompute_mult(const EC_GROUP *group);
|
||||
|
||||
/* method functions in ecp_smpl.c */
|
||||
int ec_GFp_simple_group_init(EC_GROUP *);
|
||||
void ec_GFp_simple_group_finish(EC_GROUP *);
|
||||
void ec_GFp_simple_group_clear_finish(EC_GROUP *);
|
||||
int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);
|
||||
int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p,
|
||||
const BIGNUM *a, const BIGNUM *b, BN_CTX *);
|
||||
int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
|
||||
BIGNUM *b, BN_CTX *);
|
||||
int ec_GFp_simple_group_get_degree(const EC_GROUP *);
|
||||
int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
|
||||
int ec_GFp_simple_point_init(EC_POINT *);
|
||||
void ec_GFp_simple_point_finish(EC_POINT *);
|
||||
void ec_GFp_simple_point_clear_finish(EC_POINT *);
|
||||
int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *);
|
||||
int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
|
||||
int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *,
|
||||
EC_POINT *, const BIGNUM *x,
|
||||
const BIGNUM *y,
|
||||
const BIGNUM *z, BN_CTX *);
|
||||
int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *,
|
||||
const EC_POINT *, BIGNUM *x,
|
||||
BIGNUM *y, BIGNUM *z,
|
||||
BN_CTX *);
|
||||
int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
|
||||
const BIGNUM *x,
|
||||
const BIGNUM *y, BN_CTX *);
|
||||
int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *,
|
||||
const EC_POINT *, BIGNUM *x,
|
||||
BIGNUM *y, BN_CTX *);
|
||||
int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
|
||||
const BIGNUM *x, int y_bit,
|
||||
BN_CTX *);
|
||||
size_t ec_GFp_simple_point2oct(const EC_GROUP *, const EC_POINT *,
|
||||
point_conversion_form_t form,
|
||||
unsigned char *buf, size_t len, BN_CTX *);
|
||||
int ec_GFp_simple_oct2point(const EC_GROUP *, EC_POINT *,
|
||||
const unsigned char *buf, size_t len, BN_CTX *);
|
||||
int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
|
||||
const EC_POINT *b, BN_CTX *);
|
||||
int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
|
||||
BN_CTX *);
|
||||
int ec_GFp_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
|
||||
int ec_GFp_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);
|
||||
int ec_GFp_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
|
||||
int ec_GFp_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b,
|
||||
BN_CTX *);
|
||||
int ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
|
||||
int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num,
|
||||
EC_POINT *[], BN_CTX *);
|
||||
int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *);
|
||||
int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
BN_CTX *);
|
||||
|
||||
/* method functions in ecp_mont.c */
|
||||
int ec_GFp_mont_group_init(EC_GROUP *);
|
||||
int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *);
|
||||
void ec_GFp_mont_group_finish(EC_GROUP *);
|
||||
void ec_GFp_mont_group_clear_finish(EC_GROUP *);
|
||||
int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);
|
||||
int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *);
|
||||
int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
BN_CTX *);
|
||||
int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
BN_CTX *);
|
||||
int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
BN_CTX *);
|
||||
int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *);
|
||||
|
||||
/* method functions in ecp_nist.c */
|
||||
int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src);
|
||||
int ec_GFp_nist_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *);
|
||||
int ec_GFp_nist_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *);
|
||||
int ec_GFp_nist_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
BN_CTX *);
|
||||
|
||||
/* method functions in ec2_smpl.c */
|
||||
int ec_GF2m_simple_group_init(EC_GROUP *);
|
||||
void ec_GF2m_simple_group_finish(EC_GROUP *);
|
||||
void ec_GF2m_simple_group_clear_finish(EC_GROUP *);
|
||||
int ec_GF2m_simple_group_copy(EC_GROUP *, const EC_GROUP *);
|
||||
int ec_GF2m_simple_group_set_curve(EC_GROUP *, const BIGNUM *p,
|
||||
const BIGNUM *a, const BIGNUM *b,
|
||||
BN_CTX *);
|
||||
int ec_GF2m_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
|
||||
BIGNUM *b, BN_CTX *);
|
||||
int ec_GF2m_simple_group_get_degree(const EC_GROUP *);
|
||||
int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
|
||||
int ec_GF2m_simple_point_init(EC_POINT *);
|
||||
void ec_GF2m_simple_point_finish(EC_POINT *);
|
||||
void ec_GF2m_simple_point_clear_finish(EC_POINT *);
|
||||
int ec_GF2m_simple_point_copy(EC_POINT *, const EC_POINT *);
|
||||
int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
|
||||
int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
|
||||
const BIGNUM *x,
|
||||
const BIGNUM *y, BN_CTX *);
|
||||
int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *,
|
||||
const EC_POINT *, BIGNUM *x,
|
||||
BIGNUM *y, BN_CTX *);
|
||||
int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
|
||||
const BIGNUM *x, int y_bit,
|
||||
BN_CTX *);
|
||||
size_t ec_GF2m_simple_point2oct(const EC_GROUP *, const EC_POINT *,
|
||||
point_conversion_form_t form,
|
||||
unsigned char *buf, size_t len, BN_CTX *);
|
||||
int ec_GF2m_simple_oct2point(const EC_GROUP *, EC_POINT *,
|
||||
const unsigned char *buf, size_t len, BN_CTX *);
|
||||
int ec_GF2m_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
|
||||
const EC_POINT *b, BN_CTX *);
|
||||
int ec_GF2m_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
|
||||
BN_CTX *);
|
||||
int ec_GF2m_simple_invert(const EC_GROUP *, EC_POINT *, BN_CTX *);
|
||||
int ec_GF2m_simple_is_at_infinity(const EC_GROUP *, const EC_POINT *);
|
||||
int ec_GF2m_simple_is_on_curve(const EC_GROUP *, const EC_POINT *, BN_CTX *);
|
||||
int ec_GF2m_simple_cmp(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b,
|
||||
BN_CTX *);
|
||||
int ec_GF2m_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *);
|
||||
int ec_GF2m_simple_points_make_affine(const EC_GROUP *, size_t num,
|
||||
EC_POINT *[], BN_CTX *);
|
||||
int ec_GF2m_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *);
|
||||
int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
BN_CTX *);
|
||||
int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *);
|
||||
|
||||
/* method functions in ec2_mult.c */
|
||||
int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r,
|
||||
const BIGNUM *scalar, size_t num,
|
||||
const EC_POINT *points[], const BIGNUM *scalars[],
|
||||
BN_CTX *);
|
||||
int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
|
||||
int ec_GF2m_have_precompute_mult(const EC_GROUP *group);
|
||||
|
||||
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
|
||||
/* method functions in ecp_nistp224.c */
|
||||
int ec_GFp_nistp224_group_init(EC_GROUP *group);
|
||||
int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
|
||||
const BIGNUM *a, const BIGNUM *n,
|
||||
BN_CTX *);
|
||||
int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
|
||||
const EC_POINT *point,
|
||||
BIGNUM *x, BIGNUM *y,
|
||||
BN_CTX *ctx);
|
||||
int 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 *);
|
||||
int 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);
|
||||
int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
|
||||
int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group);
|
||||
|
||||
/* method functions in ecp_nistp256.c */
|
||||
int ec_GFp_nistp256_group_init(EC_GROUP *group);
|
||||
int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
|
||||
const BIGNUM *a, const BIGNUM *n,
|
||||
BN_CTX *);
|
||||
int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
|
||||
const EC_POINT *point,
|
||||
BIGNUM *x, BIGNUM *y,
|
||||
BN_CTX *ctx);
|
||||
int 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 *);
|
||||
int 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);
|
||||
int ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
|
||||
int ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group);
|
||||
|
||||
/* method functions in ecp_nistp521.c */
|
||||
int ec_GFp_nistp521_group_init(EC_GROUP *group);
|
||||
int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
|
||||
const BIGNUM *a, const BIGNUM *n,
|
||||
BN_CTX *);
|
||||
int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group,
|
||||
const EC_POINT *point,
|
||||
BIGNUM *x, BIGNUM *y,
|
||||
BN_CTX *ctx);
|
||||
int 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 *);
|
||||
int 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);
|
||||
int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
|
||||
int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group);
|
||||
|
||||
/* utility functions in ecp_nistputil.c */
|
||||
void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
|
||||
size_t felem_size,
|
||||
void *tmp_felems,
|
||||
void (*felem_one) (void *out),
|
||||
int (*felem_is_zero) (const void
|
||||
*in),
|
||||
void (*felem_assign) (void *out,
|
||||
const void
|
||||
*in),
|
||||
void (*felem_square) (void *out,
|
||||
const void
|
||||
*in),
|
||||
void (*felem_mul) (void *out,
|
||||
const void
|
||||
*in1,
|
||||
const void
|
||||
*in2),
|
||||
void (*felem_inv) (void *out,
|
||||
const void
|
||||
*in),
|
||||
void (*felem_contract) (void
|
||||
*out,
|
||||
const
|
||||
void
|
||||
*in));
|
||||
void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign,
|
||||
unsigned char *digit, unsigned char in);
|
||||
#endif
|
||||
|
||||
#ifdef ECP_NISTZ256_ASM
|
||||
/** Returns GFp methods using montgomery multiplication, with x86-64 optimized
|
||||
* P256. See http://eprint.iacr.org/2013/816.
|
||||
* \return EC_METHOD object
|
||||
*/
|
||||
const EC_METHOD *EC_GFp_nistz256_method(void);
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
EC_GROUP *FIPS_ec_group_new_curve_gfp(const BIGNUM *p, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *ctx);
|
||||
EC_GROUP *FIPS_ec_group_new_curve_gf2m(const BIGNUM *p, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *ctx);
|
||||
EC_GROUP *FIPS_ec_group_new_by_curve_name(int nid);
|
||||
#endif
|
||||
|
||||
int ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx);
|
||||
|
||||
/*
|
||||
* The next 2 functions are just internal wrappers around the omonimous
|
||||
* functions with either the `_GFp` or the `_GF2m` suffix.
|
||||
*
|
||||
* They are meant to facilitate backporting of code from newer branches, where
|
||||
* the public API includes a "field agnostic" version of these 2 functions.
|
||||
*/
|
||||
int ec_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
|
||||
BIGNUM *b, BN_CTX *ctx);
|
||||
int ec_point_get_affine_coordinates(const EC_GROUP *group,
|
||||
const EC_POINT *point, BIGNUM *x,
|
||||
BIGNUM *y, BN_CTX *ctx);
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,192 @@
|
||||
/* crypto/ec/ec_lib.c */
|
||||
/*
|
||||
* Originally written by Bodo Moeller for the OpenSSL project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2003 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 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
* Binary polynomial ECC support in OpenSSL originally developed by
|
||||
* SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/opensslv.h>
|
||||
|
||||
#include "ec_lcl.h"
|
||||
|
||||
int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
|
||||
EC_POINT *point, const BIGNUM *x,
|
||||
int y_bit, BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->point_set_compressed_coordinates == 0
|
||||
&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
|
||||
ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,
|
||||
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
if (group->meth != point->meth) {
|
||||
ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,
|
||||
EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
|
||||
if (group->meth->field_type == NID_X9_62_prime_field)
|
||||
return ec_GFp_simple_set_compressed_coordinates(group, point, x,
|
||||
y_bit, ctx);
|
||||
else
|
||||
#ifdef OPENSSL_NO_EC2M
|
||||
{
|
||||
ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP,
|
||||
EC_R_GF2M_NOT_SUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return ec_GF2m_simple_set_compressed_coordinates(group, point, x,
|
||||
y_bit, ctx);
|
||||
#endif
|
||||
}
|
||||
return group->meth->point_set_compressed_coordinates(group, point, x,
|
||||
y_bit, ctx);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group,
|
||||
EC_POINT *point, const BIGNUM *x,
|
||||
int y_bit, BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->point_set_compressed_coordinates == 0
|
||||
&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
|
||||
ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M,
|
||||
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
if (group->meth != point->meth) {
|
||||
ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M,
|
||||
EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
|
||||
if (group->meth->field_type == NID_X9_62_prime_field)
|
||||
return ec_GFp_simple_set_compressed_coordinates(group, point, x,
|
||||
y_bit, ctx);
|
||||
else
|
||||
return ec_GF2m_simple_set_compressed_coordinates(group, point, x,
|
||||
y_bit, ctx);
|
||||
}
|
||||
return group->meth->point_set_compressed_coordinates(group, point, x,
|
||||
y_bit, ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
|
||||
point_conversion_form_t form, unsigned char *buf,
|
||||
size_t len, BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->point2oct == 0
|
||||
&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
|
||||
ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
if (group->meth != point->meth) {
|
||||
ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
|
||||
if (group->meth->field_type == NID_X9_62_prime_field)
|
||||
return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx);
|
||||
else
|
||||
#ifdef OPENSSL_NO_EC2M
|
||||
{
|
||||
ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_GF2M_NOT_SUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return ec_GF2m_simple_point2oct(group, point,
|
||||
form, buf, len, ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
return group->meth->point2oct(group, point, form, buf, len, ctx);
|
||||
}
|
||||
|
||||
int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
|
||||
const unsigned char *buf, size_t len, BN_CTX *ctx)
|
||||
{
|
||||
if (group->meth->oct2point == 0
|
||||
&& !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
|
||||
ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
if (group->meth != point->meth) {
|
||||
ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
|
||||
return 0;
|
||||
}
|
||||
if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
|
||||
if (group->meth->field_type == NID_X9_62_prime_field)
|
||||
return ec_GFp_simple_oct2point(group, point, buf, len, ctx);
|
||||
else
|
||||
#ifdef OPENSSL_NO_EC2M
|
||||
{
|
||||
ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_GF2M_NOT_SUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return ec_GF2m_simple_oct2point(group, point, buf, len, ctx);
|
||||
#endif
|
||||
}
|
||||
return group->meth->oct2point(group, point, buf, len, ctx);
|
||||
}
|
||||
@@ -0,0 +1,530 @@
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2006.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 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
|
||||
* licensing@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).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/ec.h>
|
||||
#include "ec_lcl.h"
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "evp_locl.h"
|
||||
|
||||
/* EC pkey context structure */
|
||||
|
||||
typedef struct {
|
||||
/* Key and paramgen group */
|
||||
EC_GROUP *gen_group;
|
||||
/* message digest */
|
||||
const EVP_MD *md;
|
||||
/* Duplicate key if custom cofactor needed */
|
||||
EC_KEY *co_key;
|
||||
/* Cofactor mode */
|
||||
signed char cofactor_mode;
|
||||
/* KDF (if any) to use for ECDH */
|
||||
char kdf_type;
|
||||
/* Message digest to use for key derivation */
|
||||
const EVP_MD *kdf_md;
|
||||
/* User key material */
|
||||
unsigned char *kdf_ukm;
|
||||
size_t kdf_ukmlen;
|
||||
/* KDF output length */
|
||||
size_t kdf_outlen;
|
||||
} EC_PKEY_CTX;
|
||||
|
||||
static int pkey_ec_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
EC_PKEY_CTX *dctx;
|
||||
dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX));
|
||||
if (!dctx)
|
||||
return 0;
|
||||
dctx->gen_group = NULL;
|
||||
dctx->md = NULL;
|
||||
|
||||
dctx->cofactor_mode = -1;
|
||||
dctx->co_key = NULL;
|
||||
dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE;
|
||||
dctx->kdf_md = NULL;
|
||||
dctx->kdf_outlen = 0;
|
||||
dctx->kdf_ukm = NULL;
|
||||
dctx->kdf_ukmlen = 0;
|
||||
|
||||
ctx->data = dctx;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
||||
{
|
||||
EC_PKEY_CTX *dctx, *sctx;
|
||||
if (!pkey_ec_init(dst))
|
||||
return 0;
|
||||
sctx = src->data;
|
||||
dctx = dst->data;
|
||||
if (sctx->gen_group) {
|
||||
dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
|
||||
if (!dctx->gen_group)
|
||||
return 0;
|
||||
}
|
||||
dctx->md = sctx->md;
|
||||
|
||||
if (sctx->co_key) {
|
||||
dctx->co_key = EC_KEY_dup(sctx->co_key);
|
||||
if (!dctx->co_key)
|
||||
return 0;
|
||||
}
|
||||
dctx->kdf_type = sctx->kdf_type;
|
||||
dctx->kdf_md = sctx->kdf_md;
|
||||
dctx->kdf_outlen = sctx->kdf_outlen;
|
||||
if (sctx->kdf_ukm) {
|
||||
dctx->kdf_ukm = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
|
||||
if (!dctx->kdf_ukm)
|
||||
return 0;
|
||||
} else
|
||||
dctx->kdf_ukm = NULL;
|
||||
dctx->kdf_ukmlen = sctx->kdf_ukmlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
if (dctx) {
|
||||
if (dctx->gen_group)
|
||||
EC_GROUP_free(dctx->gen_group);
|
||||
if (dctx->co_key)
|
||||
EC_KEY_free(dctx->co_key);
|
||||
if (dctx->kdf_ukm)
|
||||
OPENSSL_free(dctx->kdf_ukm);
|
||||
OPENSSL_free(dctx);
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
|
||||
const unsigned char *tbs, size_t tbslen)
|
||||
{
|
||||
int ret, type;
|
||||
unsigned int sltmp;
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
EC_KEY *ec = ctx->pkey->pkey.ec;
|
||||
|
||||
if (!sig) {
|
||||
*siglen = ECDSA_size(ec);
|
||||
return 1;
|
||||
} else if (*siglen < (size_t)ECDSA_size(ec)) {
|
||||
ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dctx->md)
|
||||
type = EVP_MD_type(dctx->md);
|
||||
else
|
||||
type = NID_sha1;
|
||||
|
||||
ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
|
||||
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
*siglen = (size_t)sltmp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
|
||||
const unsigned char *sig, size_t siglen,
|
||||
const unsigned char *tbs, size_t tbslen)
|
||||
{
|
||||
int ret, type;
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
EC_KEY *ec = ctx->pkey->pkey.ec;
|
||||
|
||||
if (dctx->md)
|
||||
type = EVP_MD_type(dctx->md);
|
||||
else
|
||||
type = NID_sha1;
|
||||
|
||||
ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
|
||||
size_t *keylen)
|
||||
{
|
||||
int ret;
|
||||
size_t outlen;
|
||||
const EC_POINT *pubkey = NULL;
|
||||
EC_KEY *eckey;
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
if (!ctx->pkey || !ctx->peerkey) {
|
||||
ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
|
||||
|
||||
if (!key) {
|
||||
const EC_GROUP *group;
|
||||
group = EC_KEY_get0_group(eckey);
|
||||
*keylen = (EC_GROUP_get_degree(group) + 7) / 8;
|
||||
return 1;
|
||||
}
|
||||
pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
|
||||
|
||||
/*
|
||||
* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not
|
||||
* an error, the result is truncated.
|
||||
*/
|
||||
|
||||
outlen = *keylen;
|
||||
|
||||
ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
*keylen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx,
|
||||
unsigned char *key, size_t *keylen)
|
||||
{
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
unsigned char *ktmp = NULL;
|
||||
size_t ktmplen;
|
||||
int rv = 0;
|
||||
if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE)
|
||||
return pkey_ec_derive(ctx, key, keylen);
|
||||
if (!key) {
|
||||
*keylen = dctx->kdf_outlen;
|
||||
return 1;
|
||||
}
|
||||
if (*keylen != dctx->kdf_outlen)
|
||||
return 0;
|
||||
if (!pkey_ec_derive(ctx, NULL, &ktmplen))
|
||||
return 0;
|
||||
ktmp = OPENSSL_malloc(ktmplen);
|
||||
if (!ktmp)
|
||||
return 0;
|
||||
if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
|
||||
goto err;
|
||||
/* Do KDF stuff */
|
||||
if (!ECDH_KDF_X9_62(key, *keylen, ktmp, ktmplen,
|
||||
dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
|
||||
goto err;
|
||||
rv = 1;
|
||||
|
||||
err:
|
||||
if (ktmp) {
|
||||
OPENSSL_cleanse(ktmp, ktmplen);
|
||||
OPENSSL_free(ktmp);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
{
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
EC_GROUP *group;
|
||||
switch (type) {
|
||||
case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
|
||||
group = EC_GROUP_new_by_curve_name(p1);
|
||||
if (group == NULL) {
|
||||
ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE);
|
||||
return 0;
|
||||
}
|
||||
if (dctx->gen_group)
|
||||
EC_GROUP_free(dctx->gen_group);
|
||||
dctx->gen_group = group;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_EC_PARAM_ENC:
|
||||
if (!dctx->gen_group) {
|
||||
ECerr(EC_F_PKEY_EC_CTRL, EC_R_NO_PARAMETERS_SET);
|
||||
return 0;
|
||||
}
|
||||
EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
|
||||
return 1;
|
||||
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
|
||||
if (p1 == -2) {
|
||||
if (dctx->cofactor_mode != -1)
|
||||
return dctx->cofactor_mode;
|
||||
else {
|
||||
EC_KEY *ec_key = ctx->pkey->pkey.ec;
|
||||
return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 :
|
||||
0;
|
||||
}
|
||||
} else if (p1 < -1 || p1 > 1)
|
||||
return -2;
|
||||
dctx->cofactor_mode = p1;
|
||||
if (p1 != -1) {
|
||||
EC_KEY *ec_key = ctx->pkey->pkey.ec;
|
||||
if (!ec_key->group)
|
||||
return -2;
|
||||
/* If cofactor is 1 cofactor mode does nothing */
|
||||
if (BN_is_one(&ec_key->group->cofactor))
|
||||
return 1;
|
||||
if (!dctx->co_key) {
|
||||
dctx->co_key = EC_KEY_dup(ec_key);
|
||||
if (!dctx->co_key)
|
||||
return 0;
|
||||
}
|
||||
if (p1)
|
||||
EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
|
||||
else
|
||||
EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
|
||||
} else if (dctx->co_key) {
|
||||
EC_KEY_free(dctx->co_key);
|
||||
dctx->co_key = NULL;
|
||||
}
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
case EVP_PKEY_CTRL_EC_KDF_TYPE:
|
||||
if (p1 == -2)
|
||||
return dctx->kdf_type;
|
||||
if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62)
|
||||
return -2;
|
||||
dctx->kdf_type = p1;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_EC_KDF_MD:
|
||||
dctx->kdf_md = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_GET_EC_KDF_MD:
|
||||
*(const EVP_MD **)p2 = dctx->kdf_md;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
|
||||
if (p1 <= 0)
|
||||
return -2;
|
||||
dctx->kdf_outlen = (size_t)p1;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
|
||||
*(int *)p2 = dctx->kdf_outlen;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_EC_KDF_UKM:
|
||||
if (dctx->kdf_ukm)
|
||||
OPENSSL_free(dctx->kdf_ukm);
|
||||
dctx->kdf_ukm = p2;
|
||||
if (p2)
|
||||
dctx->kdf_ukmlen = p1;
|
||||
else
|
||||
dctx->kdf_ukmlen = 0;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
|
||||
*(unsigned char **)p2 = dctx->kdf_ukm;
|
||||
return dctx->kdf_ukmlen;
|
||||
|
||||
case EVP_PKEY_CTRL_MD:
|
||||
if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
|
||||
EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
|
||||
EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
|
||||
EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
|
||||
EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
|
||||
EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
|
||||
ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
|
||||
return 0;
|
||||
}
|
||||
dctx->md = p2;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_GET_MD:
|
||||
*(const EVP_MD **)p2 = dctx->md;
|
||||
return 1;
|
||||
|
||||
case EVP_PKEY_CTRL_PEER_KEY:
|
||||
/* Default behaviour is OK */
|
||||
case EVP_PKEY_CTRL_DIGESTINIT:
|
||||
case EVP_PKEY_CTRL_PKCS7_SIGN:
|
||||
case EVP_PKEY_CTRL_CMS_SIGN:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
|
||||
const char *type, const char *value)
|
||||
{
|
||||
if (!strcmp(type, "ec_paramgen_curve")) {
|
||||
int nid;
|
||||
nid = EC_curve_nist2nid(value);
|
||||
if (nid == NID_undef)
|
||||
nid = OBJ_sn2nid(value);
|
||||
if (nid == NID_undef)
|
||||
nid = OBJ_ln2nid(value);
|
||||
if (nid == NID_undef) {
|
||||
ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE);
|
||||
return 0;
|
||||
}
|
||||
return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
|
||||
} else if (!strcmp(type, "ec_param_enc")) {
|
||||
int param_enc;
|
||||
if (!strcmp(value, "explicit"))
|
||||
param_enc = 0;
|
||||
else if (!strcmp(value, "named_curve"))
|
||||
param_enc = OPENSSL_EC_NAMED_CURVE;
|
||||
else
|
||||
return -2;
|
||||
return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
|
||||
} else if (!strcmp(type, "ecdh_kdf_md")) {
|
||||
const EVP_MD *md;
|
||||
if (!(md = EVP_get_digestbyname(value))) {
|
||||
ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
|
||||
} else if (!strcmp(type, "ecdh_cofactor_mode")) {
|
||||
int co_mode;
|
||||
co_mode = atoi(value);
|
||||
return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode);
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
EC_KEY *ec = NULL;
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
int ret = 0;
|
||||
if (dctx->gen_group == NULL) {
|
||||
ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
|
||||
return 0;
|
||||
}
|
||||
ec = EC_KEY_new();
|
||||
if (!ec)
|
||||
return 0;
|
||||
ret = EC_KEY_set_group(ec, dctx->gen_group);
|
||||
if (ret)
|
||||
EVP_PKEY_assign_EC_KEY(pkey, ec);
|
||||
else
|
||||
EC_KEY_free(ec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
EC_KEY *ec = NULL;
|
||||
EC_PKEY_CTX *dctx = ctx->data;
|
||||
if (ctx->pkey == NULL && dctx->gen_group == NULL) {
|
||||
ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
|
||||
return 0;
|
||||
}
|
||||
ec = EC_KEY_new();
|
||||
if (!ec)
|
||||
return 0;
|
||||
EVP_PKEY_assign_EC_KEY(pkey, ec);
|
||||
if (ctx->pkey) {
|
||||
/* Note: if error return, pkey is freed by parent routine */
|
||||
if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
|
||||
return 0;
|
||||
} else {
|
||||
if (!EC_KEY_set_group(ec, dctx->gen_group))
|
||||
return 0;
|
||||
}
|
||||
return EC_KEY_generate_key(pkey->pkey.ec);
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD ec_pkey_meth = {
|
||||
EVP_PKEY_EC,
|
||||
0,
|
||||
pkey_ec_init,
|
||||
pkey_ec_copy,
|
||||
pkey_ec_cleanup,
|
||||
|
||||
0,
|
||||
pkey_ec_paramgen,
|
||||
|
||||
0,
|
||||
pkey_ec_keygen,
|
||||
|
||||
0,
|
||||
pkey_ec_sign,
|
||||
|
||||
0,
|
||||
pkey_ec_verify,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0, 0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
#ifndef OPENSSL_NO_ECDH
|
||||
pkey_ec_kdf_derive,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
|
||||
pkey_ec_ctrl,
|
||||
pkey_ec_ctrl_str
|
||||
};
|
||||
@@ -0,0 +1,179 @@
|
||||
/* crypto/ec/ec_print.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2002 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).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include "ec_lcl.h"
|
||||
|
||||
BIGNUM *EC_POINT_point2bn(const EC_GROUP *group,
|
||||
const EC_POINT *point,
|
||||
point_conversion_form_t form,
|
||||
BIGNUM *ret, BN_CTX *ctx)
|
||||
{
|
||||
size_t buf_len = 0;
|
||||
unsigned char *buf;
|
||||
|
||||
buf_len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx);
|
||||
if (buf_len == 0)
|
||||
return NULL;
|
||||
|
||||
if ((buf = OPENSSL_malloc(buf_len)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx)) {
|
||||
OPENSSL_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = BN_bin2bn(buf, buf_len, ret);
|
||||
|
||||
OPENSSL_free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EC_POINT *EC_POINT_bn2point(const EC_GROUP *group,
|
||||
const BIGNUM *bn, EC_POINT *point, BN_CTX *ctx)
|
||||
{
|
||||
size_t buf_len = 0;
|
||||
unsigned char *buf;
|
||||
EC_POINT *ret;
|
||||
|
||||
if ((buf_len = BN_num_bytes(bn)) == 0)
|
||||
return NULL;
|
||||
buf = OPENSSL_malloc(buf_len);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!BN_bn2bin(bn, buf)) {
|
||||
OPENSSL_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (point == NULL) {
|
||||
if ((ret = EC_POINT_new(group)) == NULL) {
|
||||
OPENSSL_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
ret = point;
|
||||
|
||||
if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) {
|
||||
if (point == NULL)
|
||||
EC_POINT_clear_free(ret);
|
||||
OPENSSL_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *HEX_DIGITS = "0123456789ABCDEF";
|
||||
|
||||
/* the return value must be freed (using OPENSSL_free()) */
|
||||
char *EC_POINT_point2hex(const EC_GROUP *group,
|
||||
const EC_POINT *point,
|
||||
point_conversion_form_t form, BN_CTX *ctx)
|
||||
{
|
||||
char *ret, *p;
|
||||
size_t buf_len = 0, i;
|
||||
unsigned char *buf, *pbuf;
|
||||
|
||||
buf_len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx);
|
||||
if (buf_len == 0)
|
||||
return NULL;
|
||||
|
||||
if ((buf = OPENSSL_malloc(buf_len)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx)) {
|
||||
OPENSSL_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = (char *)OPENSSL_malloc(buf_len * 2 + 2);
|
||||
if (ret == NULL) {
|
||||
OPENSSL_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
p = ret;
|
||||
pbuf = buf;
|
||||
for (i = buf_len; i > 0; i--) {
|
||||
int v = (int)*(pbuf++);
|
||||
*(p++) = HEX_DIGITS[v >> 4];
|
||||
*(p++) = HEX_DIGITS[v & 0x0F];
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
OPENSSL_free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EC_POINT *EC_POINT_hex2point(const EC_GROUP *group,
|
||||
const char *buf, EC_POINT *point, BN_CTX *ctx)
|
||||
{
|
||||
EC_POINT *ret = NULL;
|
||||
BIGNUM *tmp_bn = NULL;
|
||||
|
||||
if (!BN_hex2bn(&tmp_bn, buf))
|
||||
return NULL;
|
||||
|
||||
ret = EC_POINT_bn2point(group, tmp_bn, point, ctx);
|
||||
|
||||
BN_clear_free(tmp_bn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,377 @@
|
||||
/* crypto/ec/eck_prn.c */
|
||||
/*
|
||||
* Written by Nils Larsch for the OpenSSL project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2005 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 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
* Portions originally developed by SUN MICROSYSTEMS, INC., and
|
||||
* contributed to the OpenSSL project.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#ifndef OPENSSL_NO_FP_API
|
||||
int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
ECerr(EC_F_ECPKPARAMETERS_PRINT_FP, ERR_R_BUF_LIB);
|
||||
return (0);
|
||||
}
|
||||
BIO_set_fp(b, fp, BIO_NOCLOSE);
|
||||
ret = ECPKParameters_print(b, x, off);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB);
|
||||
return (0);
|
||||
}
|
||||
BIO_set_fp(b, fp, BIO_NOCLOSE);
|
||||
ret = EC_KEY_print(b, x, off);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int ECParameters_print_fp(FILE *fp, const EC_KEY *x)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL) {
|
||||
ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB);
|
||||
return (0);
|
||||
}
|
||||
BIO_set_fp(b, fp, BIO_NOCLOSE);
|
||||
ret = ECParameters_print(b, x);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
|
||||
{
|
||||
EVP_PKEY *pk;
|
||||
int ret;
|
||||
pk = EVP_PKEY_new();
|
||||
if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x))
|
||||
return 0;
|
||||
ret = EVP_PKEY_print_private(bp, pk, off, NULL);
|
||||
EVP_PKEY_free(pk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ECParameters_print(BIO *bp, const EC_KEY *x)
|
||||
{
|
||||
EVP_PKEY *pk;
|
||||
int ret;
|
||||
pk = EVP_PKEY_new();
|
||||
if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x))
|
||||
return 0;
|
||||
ret = EVP_PKEY_print_params(bp, pk, 4, NULL);
|
||||
EVP_PKEY_free(pk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int print_bin(BIO *fp, const char *str, const unsigned char *num,
|
||||
size_t len, int off);
|
||||
|
||||
int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
|
||||
{
|
||||
unsigned char *buffer = NULL;
|
||||
size_t buf_len = 0, i;
|
||||
int ret = 0, reason = ERR_R_BIO_LIB;
|
||||
BN_CTX *ctx = NULL;
|
||||
const EC_POINT *point = NULL;
|
||||
BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL,
|
||||
*order = NULL, *cofactor = NULL;
|
||||
const unsigned char *seed;
|
||||
size_t seed_len = 0;
|
||||
|
||||
static const char *gen_compressed = "Generator (compressed):";
|
||||
static const char *gen_uncompressed = "Generator (uncompressed):";
|
||||
static const char *gen_hybrid = "Generator (hybrid):";
|
||||
|
||||
if (!x) {
|
||||
reason = ERR_R_PASSED_NULL_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EC_GROUP_get_asn1_flag(x)) {
|
||||
/* the curve parameter are given by an asn1 OID */
|
||||
int nid;
|
||||
const char *nname;
|
||||
|
||||
if (!BIO_indent(bp, off, 128))
|
||||
goto err;
|
||||
|
||||
nid = EC_GROUP_get_curve_name(x);
|
||||
if (nid == 0)
|
||||
goto err;
|
||||
|
||||
if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0)
|
||||
goto err;
|
||||
if (BIO_printf(bp, "\n") <= 0)
|
||||
goto err;
|
||||
nname = EC_curve_nid2nist(nid);
|
||||
if (nname) {
|
||||
if (!BIO_indent(bp, off, 128))
|
||||
goto err;
|
||||
if (BIO_printf(bp, "NIST CURVE: %s\n", nname) <= 0)
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/* explicit parameters */
|
||||
int is_char_two = 0;
|
||||
point_conversion_form_t form;
|
||||
int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x));
|
||||
|
||||
if (tmp_nid == NID_X9_62_characteristic_two_field)
|
||||
is_char_two = 1;
|
||||
|
||||
if ((p = BN_new()) == NULL || (a = BN_new()) == NULL ||
|
||||
(b = BN_new()) == NULL || (order = BN_new()) == NULL ||
|
||||
(cofactor = BN_new()) == NULL) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_EC2M
|
||||
if (is_char_two) {
|
||||
if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) {
|
||||
reason = ERR_R_EC_LIB;
|
||||
goto err;
|
||||
}
|
||||
} else /* prime field */
|
||||
#endif
|
||||
{
|
||||
if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) {
|
||||
reason = ERR_R_EC_LIB;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if ((point = EC_GROUP_get0_generator(x)) == NULL) {
|
||||
reason = ERR_R_EC_LIB;
|
||||
goto err;
|
||||
}
|
||||
if (!EC_GROUP_get_order(x, order, NULL) ||
|
||||
!EC_GROUP_get_cofactor(x, cofactor, NULL)) {
|
||||
reason = ERR_R_EC_LIB;
|
||||
goto err;
|
||||
}
|
||||
|
||||
form = EC_GROUP_get_point_conversion_form(x);
|
||||
|
||||
if ((gen = EC_POINT_point2bn(x, point, form, NULL, ctx)) == NULL) {
|
||||
reason = ERR_R_EC_LIB;
|
||||
goto err;
|
||||
}
|
||||
|
||||
buf_len = (size_t)BN_num_bytes(p);
|
||||
if (buf_len < (i = (size_t)BN_num_bytes(a)))
|
||||
buf_len = i;
|
||||
if (buf_len < (i = (size_t)BN_num_bytes(b)))
|
||||
buf_len = i;
|
||||
if (buf_len < (i = (size_t)BN_num_bytes(gen)))
|
||||
buf_len = i;
|
||||
if (buf_len < (i = (size_t)BN_num_bytes(order)))
|
||||
buf_len = i;
|
||||
if (buf_len < (i = (size_t)BN_num_bytes(cofactor)))
|
||||
buf_len = i;
|
||||
|
||||
if ((seed = EC_GROUP_get0_seed(x)) != NULL)
|
||||
seed_len = EC_GROUP_get_seed_len(x);
|
||||
|
||||
buf_len += 10;
|
||||
if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BIO_indent(bp, off, 128))
|
||||
goto err;
|
||||
|
||||
/* print the 'short name' of the field type */
|
||||
if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid))
|
||||
<= 0)
|
||||
goto err;
|
||||
|
||||
if (is_char_two) {
|
||||
/* print the 'short name' of the base type OID */
|
||||
int basis_type = EC_GROUP_get_basis_type(x);
|
||||
if (basis_type == 0)
|
||||
goto err;
|
||||
|
||||
if (!BIO_indent(bp, off, 128))
|
||||
goto err;
|
||||
|
||||
if (BIO_printf(bp, "Basis Type: %s\n",
|
||||
OBJ_nid2sn(basis_type)) <= 0)
|
||||
goto err;
|
||||
|
||||
/* print the polynomial */
|
||||
if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer,
|
||||
off))
|
||||
goto err;
|
||||
} else {
|
||||
if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer, off))
|
||||
goto err;
|
||||
}
|
||||
if ((a != NULL) && !ASN1_bn_print(bp, "A: ", a, buffer, off))
|
||||
goto err;
|
||||
if ((b != NULL) && !ASN1_bn_print(bp, "B: ", b, buffer, off))
|
||||
goto err;
|
||||
if (form == POINT_CONVERSION_COMPRESSED) {
|
||||
if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen,
|
||||
buffer, off))
|
||||
goto err;
|
||||
} else if (form == POINT_CONVERSION_UNCOMPRESSED) {
|
||||
if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen,
|
||||
buffer, off))
|
||||
goto err;
|
||||
} else { /* form == POINT_CONVERSION_HYBRID */
|
||||
|
||||
if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen,
|
||||
buffer, off))
|
||||
goto err;
|
||||
}
|
||||
if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order,
|
||||
buffer, off))
|
||||
goto err;
|
||||
if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor,
|
||||
buffer, off))
|
||||
goto err;
|
||||
if (seed && !print_bin(bp, "Seed:", seed, seed_len, off))
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
if (!ret)
|
||||
ECerr(EC_F_ECPKPARAMETERS_PRINT, reason);
|
||||
if (p)
|
||||
BN_free(p);
|
||||
if (a)
|
||||
BN_free(a);
|
||||
if (b)
|
||||
BN_free(b);
|
||||
if (gen)
|
||||
BN_free(gen);
|
||||
if (order)
|
||||
BN_free(order);
|
||||
if (cofactor)
|
||||
BN_free(cofactor);
|
||||
if (ctx)
|
||||
BN_CTX_free(ctx);
|
||||
if (buffer != NULL)
|
||||
OPENSSL_free(buffer);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int print_bin(BIO *fp, const char *name, const unsigned char *buf,
|
||||
size_t len, int off)
|
||||
{
|
||||
size_t i;
|
||||
char str[128 + 1 + 4];
|
||||
|
||||
if (buf == NULL)
|
||||
return 1;
|
||||
if (off > 0) {
|
||||
if (off > 128)
|
||||
off = 128;
|
||||
memset(str, ' ', off);
|
||||
if (BIO_write(fp, str, off) <= 0)
|
||||
return 0;
|
||||
} else {
|
||||
off = 0;
|
||||
}
|
||||
|
||||
if (BIO_printf(fp, "%s", name) <= 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((i % 15) == 0) {
|
||||
str[0] = '\n';
|
||||
memset(&(str[1]), ' ', off + 4);
|
||||
if (BIO_write(fp, str, off + 1 + 4) <= 0)
|
||||
return 0;
|
||||
}
|
||||
if (BIO_printf(fp, "%02x%s", buf[i], ((i + 1) == len) ? "" : ":") <=
|
||||
0)
|
||||
return 0;
|
||||
}
|
||||
if (BIO_write(fp, "\n", 1) <= 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
/* crypto/ec/ecp_mont.c */
|
||||
/*
|
||||
* Originally written by Bodo Moeller for the OpenSSL project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2001 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 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
* Portions of this software developed by SUN MICROSYSTEMS, INC.,
|
||||
* and contributed to the OpenSSL project.
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
# include <openssl/fips.h>
|
||||
#endif
|
||||
|
||||
#include "ec_lcl.h"
|
||||
|
||||
const EC_METHOD *EC_GFp_mont_method(void)
|
||||
{
|
||||
static const EC_METHOD ret = {
|
||||
EC_FLAGS_DEFAULT_OCT,
|
||||
NID_X9_62_prime_field,
|
||||
ec_GFp_mont_group_init,
|
||||
ec_GFp_mont_group_finish,
|
||||
ec_GFp_mont_group_clear_finish,
|
||||
ec_GFp_mont_group_copy,
|
||||
ec_GFp_mont_group_set_curve,
|
||||
ec_GFp_simple_group_get_curve,
|
||||
ec_GFp_simple_group_get_degree,
|
||||
ec_GFp_simple_group_check_discriminant,
|
||||
ec_GFp_simple_point_init,
|
||||
ec_GFp_simple_point_finish,
|
||||
ec_GFp_simple_point_clear_finish,
|
||||
ec_GFp_simple_point_copy,
|
||||
ec_GFp_simple_point_set_to_infinity,
|
||||
ec_GFp_simple_set_Jprojective_coordinates_GFp,
|
||||
ec_GFp_simple_get_Jprojective_coordinates_GFp,
|
||||
ec_GFp_simple_point_set_affine_coordinates,
|
||||
ec_GFp_simple_point_get_affine_coordinates,
|
||||
0, 0, 0,
|
||||
ec_GFp_simple_add,
|
||||
ec_GFp_simple_dbl,
|
||||
ec_GFp_simple_invert,
|
||||
ec_GFp_simple_is_at_infinity,
|
||||
ec_GFp_simple_is_on_curve,
|
||||
ec_GFp_simple_cmp,
|
||||
ec_GFp_simple_make_affine,
|
||||
ec_GFp_simple_points_make_affine,
|
||||
0 /* mul */ ,
|
||||
0 /* precompute_mult */ ,
|
||||
0 /* have_precompute_mult */ ,
|
||||
ec_GFp_mont_field_mul,
|
||||
ec_GFp_mont_field_sqr,
|
||||
0 /* field_div */ ,
|
||||
ec_GFp_mont_field_encode,
|
||||
ec_GFp_mont_field_decode,
|
||||
ec_GFp_mont_field_set_to_one
|
||||
};
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
if (FIPS_mode())
|
||||
return fips_ec_gfp_mont_method();
|
||||
#endif
|
||||
|
||||
return &ret;
|
||||
}
|
||||
|
||||
int ec_GFp_mont_group_init(EC_GROUP *group)
|
||||
{
|
||||
int ok;
|
||||
|
||||
ok = ec_GFp_simple_group_init(group);
|
||||
group->field_data1 = NULL;
|
||||
group->field_data2 = NULL;
|
||||
return ok;
|
||||
}
|
||||
|
||||
void ec_GFp_mont_group_finish(EC_GROUP *group)
|
||||
{
|
||||
if (group->field_data1 != NULL) {
|
||||
BN_MONT_CTX_free(group->field_data1);
|
||||
group->field_data1 = NULL;
|
||||
}
|
||||
if (group->field_data2 != NULL) {
|
||||
BN_free(group->field_data2);
|
||||
group->field_data2 = NULL;
|
||||
}
|
||||
ec_GFp_simple_group_finish(group);
|
||||
}
|
||||
|
||||
void ec_GFp_mont_group_clear_finish(EC_GROUP *group)
|
||||
{
|
||||
if (group->field_data1 != NULL) {
|
||||
BN_MONT_CTX_free(group->field_data1);
|
||||
group->field_data1 = NULL;
|
||||
}
|
||||
if (group->field_data2 != NULL) {
|
||||
BN_clear_free(group->field_data2);
|
||||
group->field_data2 = NULL;
|
||||
}
|
||||
ec_GFp_simple_group_clear_finish(group);
|
||||
}
|
||||
|
||||
int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src)
|
||||
{
|
||||
if (dest->field_data1 != NULL) {
|
||||
BN_MONT_CTX_free(dest->field_data1);
|
||||
dest->field_data1 = NULL;
|
||||
}
|
||||
if (dest->field_data2 != NULL) {
|
||||
BN_clear_free(dest->field_data2);
|
||||
dest->field_data2 = NULL;
|
||||
}
|
||||
|
||||
if (!ec_GFp_simple_group_copy(dest, src))
|
||||
return 0;
|
||||
|
||||
if (src->field_data1 != NULL) {
|
||||
dest->field_data1 = BN_MONT_CTX_new();
|
||||
if (dest->field_data1 == NULL)
|
||||
return 0;
|
||||
if (!BN_MONT_CTX_copy(dest->field_data1, src->field_data1))
|
||||
goto err;
|
||||
}
|
||||
if (src->field_data2 != NULL) {
|
||||
dest->field_data2 = BN_dup(src->field_data2);
|
||||
if (dest->field_data2 == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
if (dest->field_data1 != NULL) {
|
||||
BN_MONT_CTX_free(dest->field_data1);
|
||||
dest->field_data1 = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
|
||||
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BN_MONT_CTX *mont = NULL;
|
||||
BIGNUM *one = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (group->field_data1 != NULL) {
|
||||
BN_MONT_CTX_free(group->field_data1);
|
||||
group->field_data1 = NULL;
|
||||
}
|
||||
if (group->field_data2 != NULL) {
|
||||
BN_free(group->field_data2);
|
||||
group->field_data2 = NULL;
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
mont = BN_MONT_CTX_new();
|
||||
if (mont == NULL)
|
||||
goto err;
|
||||
if (!BN_MONT_CTX_set(mont, p, ctx)) {
|
||||
ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
one = BN_new();
|
||||
if (one == NULL)
|
||||
goto err;
|
||||
if (!BN_to_montgomery(one, BN_value_one(), mont, ctx))
|
||||
goto err;
|
||||
|
||||
group->field_data1 = mont;
|
||||
mont = NULL;
|
||||
group->field_data2 = one;
|
||||
one = NULL;
|
||||
|
||||
ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
|
||||
|
||||
if (!ret) {
|
||||
BN_MONT_CTX_free(group->field_data1);
|
||||
group->field_data1 = NULL;
|
||||
BN_free(group->field_data2);
|
||||
group->field_data2 = NULL;
|
||||
}
|
||||
|
||||
err:
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
if (mont != NULL)
|
||||
BN_MONT_CTX_free(mont);
|
||||
if (one != NULL)
|
||||
BN_free(one);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
if (group->field_data1 == NULL) {
|
||||
ECerr(EC_F_EC_GFP_MONT_FIELD_MUL, EC_R_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BN_mod_mul_montgomery(r, a, b, group->field_data1, ctx);
|
||||
}
|
||||
|
||||
int ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
if (group->field_data1 == NULL) {
|
||||
ECerr(EC_F_EC_GFP_MONT_FIELD_SQR, EC_R_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BN_mod_mul_montgomery(r, a, a, group->field_data1, ctx);
|
||||
}
|
||||
|
||||
int ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r,
|
||||
const BIGNUM *a, BN_CTX *ctx)
|
||||
{
|
||||
if (group->field_data1 == NULL) {
|
||||
ECerr(EC_F_EC_GFP_MONT_FIELD_ENCODE, EC_R_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BN_to_montgomery(r, a, (BN_MONT_CTX *)group->field_data1, ctx);
|
||||
}
|
||||
|
||||
int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r,
|
||||
const BIGNUM *a, BN_CTX *ctx)
|
||||
{
|
||||
if (group->field_data1 == NULL) {
|
||||
ECerr(EC_F_EC_GFP_MONT_FIELD_DECODE, EC_R_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return BN_from_montgomery(r, a, group->field_data1, ctx);
|
||||
}
|
||||
|
||||
int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
if (group->field_data2 == NULL) {
|
||||
ECerr(EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE, EC_R_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!BN_copy(r, group->field_data2))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/* crypto/ec/ecp_nist.c */
|
||||
/*
|
||||
* Written by Nils Larsch for the OpenSSL project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2003 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 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
* Portions of this software developed by SUN MICROSYSTEMS, INC.,
|
||||
* and contributed to the OpenSSL project.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
#include "ec_lcl.h"
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
# include <openssl/fips.h>
|
||||
#endif
|
||||
|
||||
const EC_METHOD *EC_GFp_nist_method(void)
|
||||
{
|
||||
static const EC_METHOD ret = {
|
||||
EC_FLAGS_DEFAULT_OCT,
|
||||
NID_X9_62_prime_field,
|
||||
ec_GFp_simple_group_init,
|
||||
ec_GFp_simple_group_finish,
|
||||
ec_GFp_simple_group_clear_finish,
|
||||
ec_GFp_nist_group_copy,
|
||||
ec_GFp_nist_group_set_curve,
|
||||
ec_GFp_simple_group_get_curve,
|
||||
ec_GFp_simple_group_get_degree,
|
||||
ec_GFp_simple_group_check_discriminant,
|
||||
ec_GFp_simple_point_init,
|
||||
ec_GFp_simple_point_finish,
|
||||
ec_GFp_simple_point_clear_finish,
|
||||
ec_GFp_simple_point_copy,
|
||||
ec_GFp_simple_point_set_to_infinity,
|
||||
ec_GFp_simple_set_Jprojective_coordinates_GFp,
|
||||
ec_GFp_simple_get_Jprojective_coordinates_GFp,
|
||||
ec_GFp_simple_point_set_affine_coordinates,
|
||||
ec_GFp_simple_point_get_affine_coordinates,
|
||||
0, 0, 0,
|
||||
ec_GFp_simple_add,
|
||||
ec_GFp_simple_dbl,
|
||||
ec_GFp_simple_invert,
|
||||
ec_GFp_simple_is_at_infinity,
|
||||
ec_GFp_simple_is_on_curve,
|
||||
ec_GFp_simple_cmp,
|
||||
ec_GFp_simple_make_affine,
|
||||
ec_GFp_simple_points_make_affine,
|
||||
0 /* mul */ ,
|
||||
0 /* precompute_mult */ ,
|
||||
0 /* have_precompute_mult */ ,
|
||||
ec_GFp_nist_field_mul,
|
||||
ec_GFp_nist_field_sqr,
|
||||
0 /* field_div */ ,
|
||||
0 /* field_encode */ ,
|
||||
0 /* field_decode */ ,
|
||||
0 /* field_set_to_one */
|
||||
};
|
||||
|
||||
#ifdef OPENSSL_FIPS
|
||||
if (FIPS_mode())
|
||||
return fips_ec_gfp_nist_method();
|
||||
#endif
|
||||
|
||||
return &ret;
|
||||
}
|
||||
|
||||
int ec_GFp_nist_group_copy(EC_GROUP *dest, const EC_GROUP *src)
|
||||
{
|
||||
dest->field_mod_func = src->field_mod_func;
|
||||
|
||||
return ec_GFp_simple_group_copy(dest, src);
|
||||
}
|
||||
|
||||
int ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p,
|
||||
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *tmp_bn;
|
||||
|
||||
if (ctx == NULL)
|
||||
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
|
||||
return 0;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if ((tmp_bn = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_ucmp(BN_get0_nist_prime_192(), p) == 0)
|
||||
group->field_mod_func = BN_nist_mod_192;
|
||||
else if (BN_ucmp(BN_get0_nist_prime_224(), p) == 0)
|
||||
group->field_mod_func = BN_nist_mod_224;
|
||||
else if (BN_ucmp(BN_get0_nist_prime_256(), p) == 0)
|
||||
group->field_mod_func = BN_nist_mod_256;
|
||||
else if (BN_ucmp(BN_get0_nist_prime_384(), p) == 0)
|
||||
group->field_mod_func = BN_nist_mod_384;
|
||||
else if (BN_ucmp(BN_get0_nist_prime_521(), p) == 0)
|
||||
group->field_mod_func = BN_nist_mod_521;
|
||||
else {
|
||||
ECerr(EC_F_EC_GFP_NIST_GROUP_SET_CURVE, EC_R_NOT_A_NIST_PRIME);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
|
||||
const BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
BN_CTX *ctx_new = NULL;
|
||||
|
||||
if (!group || !r || !a || !b) {
|
||||
ECerr(EC_F_EC_GFP_NIST_FIELD_MUL, ERR_R_PASSED_NULL_PARAMETER);
|
||||
goto err;
|
||||
}
|
||||
if (!ctx)
|
||||
if ((ctx_new = ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_mul(r, a, b, ctx))
|
||||
goto err;
|
||||
if (!group->field_mod_func(r, r, &group->field, ctx))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
if (ctx_new)
|
||||
BN_CTX_free(ctx_new);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ec_GFp_nist_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
BN_CTX *ctx_new = NULL;
|
||||
|
||||
if (!group || !r || !a) {
|
||||
ECerr(EC_F_EC_GFP_NIST_FIELD_SQR, EC_R_PASSED_NULL_PARAMETER);
|
||||
goto err;
|
||||
}
|
||||
if (!ctx)
|
||||
if ((ctx_new = ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_sqr(r, a, ctx))
|
||||
goto err;
|
||||
if (!group->field_mod_func(r, r, &group->field, ctx))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
if (ctx_new)
|
||||
BN_CTX_free(ctx_new);
|
||||
return ret;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,218 @@
|
||||
/* crypto/ec/ecp_nistputil.c */
|
||||
/*
|
||||
* Written by Bodo Moeller for the OpenSSL project.
|
||||
*/
|
||||
/* Copyright 2011 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
*
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <openssl/opensslconf.h>
|
||||
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
|
||||
|
||||
/*
|
||||
* Common utility functions for ecp_nistp224.c, ecp_nistp256.c, ecp_nistp521.c.
|
||||
*/
|
||||
|
||||
# include <stddef.h>
|
||||
# include "ec_lcl.h"
|
||||
|
||||
/*
|
||||
* Convert an array of points into affine coordinates. (If the point at
|
||||
* infinity is found (Z = 0), it remains unchanged.) This function is
|
||||
* essentially an equivalent to EC_POINTs_make_affine(), but works with the
|
||||
* internal representation of points as used by ecp_nistp###.c rather than
|
||||
* with (BIGNUM-based) EC_POINT data structures. point_array is the
|
||||
* input/output buffer ('num' points in projective form, i.e. three
|
||||
* coordinates each), based on an internal representation of field elements
|
||||
* of size 'felem_size'. tmp_felems needs to point to a temporary array of
|
||||
* 'num'+1 field elements for storage of intermediate values.
|
||||
*/
|
||||
void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array,
|
||||
size_t felem_size,
|
||||
void *tmp_felems,
|
||||
void (*felem_one) (void *out),
|
||||
int (*felem_is_zero) (const void
|
||||
*in),
|
||||
void (*felem_assign) (void *out,
|
||||
const void
|
||||
*in),
|
||||
void (*felem_square) (void *out,
|
||||
const void
|
||||
*in),
|
||||
void (*felem_mul) (void *out,
|
||||
const void
|
||||
*in1,
|
||||
const void
|
||||
*in2),
|
||||
void (*felem_inv) (void *out,
|
||||
const void
|
||||
*in),
|
||||
void (*felem_contract) (void
|
||||
*out,
|
||||
const
|
||||
void
|
||||
*in))
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
# define tmp_felem(I) (&((char *)tmp_felems)[(I) * felem_size])
|
||||
# define X(I) (&((char *)point_array)[3*(I) * felem_size])
|
||||
# define Y(I) (&((char *)point_array)[(3*(I) + 1) * felem_size])
|
||||
# define Z(I) (&((char *)point_array)[(3*(I) + 2) * felem_size])
|
||||
|
||||
if (!felem_is_zero(Z(0)))
|
||||
felem_assign(tmp_felem(0), Z(0));
|
||||
else
|
||||
felem_one(tmp_felem(0));
|
||||
for (i = 1; i < (int)num; i++) {
|
||||
if (!felem_is_zero(Z(i)))
|
||||
felem_mul(tmp_felem(i), tmp_felem(i - 1), Z(i));
|
||||
else
|
||||
felem_assign(tmp_felem(i), tmp_felem(i - 1));
|
||||
}
|
||||
/*
|
||||
* Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any
|
||||
* zero-valued factors: if Z(i) = 0, we essentially pretend that Z(i) = 1
|
||||
*/
|
||||
|
||||
felem_inv(tmp_felem(num - 1), tmp_felem(num - 1));
|
||||
for (i = num - 1; i >= 0; i--) {
|
||||
if (i > 0)
|
||||
/*
|
||||
* tmp_felem(i-1) is the product of Z(0) .. Z(i-1), tmp_felem(i)
|
||||
* is the inverse of the product of Z(0) .. Z(i)
|
||||
*/
|
||||
/* 1/Z(i) */
|
||||
felem_mul(tmp_felem(num), tmp_felem(i - 1), tmp_felem(i));
|
||||
else
|
||||
felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */
|
||||
|
||||
if (!felem_is_zero(Z(i))) {
|
||||
if (i > 0)
|
||||
/*
|
||||
* For next iteration, replace tmp_felem(i-1) by its inverse
|
||||
*/
|
||||
felem_mul(tmp_felem(i - 1), tmp_felem(i), Z(i));
|
||||
|
||||
/*
|
||||
* Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1)
|
||||
*/
|
||||
felem_square(Z(i), tmp_felem(num)); /* 1/(Z^2) */
|
||||
felem_mul(X(i), X(i), Z(i)); /* X/(Z^2) */
|
||||
felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */
|
||||
felem_mul(Y(i), Y(i), Z(i)); /* Y/(Z^3) */
|
||||
felem_contract(X(i), X(i));
|
||||
felem_contract(Y(i), Y(i));
|
||||
felem_one(Z(i));
|
||||
} else {
|
||||
if (i > 0)
|
||||
/*
|
||||
* For next iteration, replace tmp_felem(i-1) by its inverse
|
||||
*/
|
||||
felem_assign(tmp_felem(i - 1), tmp_felem(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
* This function looks at 5+1 scalar bits (5 current, 1 adjacent less
|
||||
* significant bit), and recodes them into a signed digit for use in fast point
|
||||
* multiplication: the use of signed rather than unsigned digits means that
|
||||
* fewer points need to be precomputed, given that point inversion is easy
|
||||
* (a precomputed point dP makes -dP available as well).
|
||||
*
|
||||
* BACKGROUND:
|
||||
*
|
||||
* Signed digits for multiplication were introduced by Booth ("A signed binary
|
||||
* multiplication technique", Quart. Journ. Mech. and Applied Math., vol. IV,
|
||||
* pt. 2 (1951), pp. 236-240), in that case for multiplication of integers.
|
||||
* Booth's original encoding did not generally improve the density of nonzero
|
||||
* digits over the binary representation, and was merely meant to simplify the
|
||||
* handling of signed factors given in two's complement; but it has since been
|
||||
* shown to be the basis of various signed-digit representations that do have
|
||||
* further advantages, including the wNAF, using the following general approach:
|
||||
*
|
||||
* (1) Given a binary representation
|
||||
*
|
||||
* b_k ... b_2 b_1 b_0,
|
||||
*
|
||||
* of a nonnegative integer (b_k in {0, 1}), rewrite it in digits 0, 1, -1
|
||||
* by using bit-wise subtraction as follows:
|
||||
*
|
||||
* b_k b_(k-1) ... b_2 b_1 b_0
|
||||
* - b_k ... b_3 b_2 b_1 b_0
|
||||
* -------------------------------------
|
||||
* s_k b_(k-1) ... s_3 s_2 s_1 s_0
|
||||
*
|
||||
* A left-shift followed by subtraction of the original value yields a new
|
||||
* representation of the same value, using signed bits s_i = b_(i+1) - b_i.
|
||||
* This representation from Booth's paper has since appeared in the
|
||||
* literature under a variety of different names including "reversed binary
|
||||
* form", "alternating greedy expansion", "mutual opposite form", and
|
||||
* "sign-alternating {+-1}-representation".
|
||||
*
|
||||
* An interesting property is that among the nonzero bits, values 1 and -1
|
||||
* strictly alternate.
|
||||
*
|
||||
* (2) Various window schemes can be applied to the Booth representation of
|
||||
* integers: for example, right-to-left sliding windows yield the wNAF
|
||||
* (a signed-digit encoding independently discovered by various researchers
|
||||
* in the 1990s), and left-to-right sliding windows yield a left-to-right
|
||||
* equivalent of the wNAF (independently discovered by various researchers
|
||||
* around 2004).
|
||||
*
|
||||
* To prevent leaking information through side channels in point multiplication,
|
||||
* we need to recode the given integer into a regular pattern: sliding windows
|
||||
* as in wNAFs won't do, we need their fixed-window equivalent -- which is a few
|
||||
* decades older: we'll be using the so-called "modified Booth encoding" due to
|
||||
* MacSorley ("High-speed arithmetic in binary computers", Proc. IRE, vol. 49
|
||||
* (1961), pp. 67-91), in a radix-2^5 setting. That is, we always combine five
|
||||
* signed bits into a signed digit:
|
||||
*
|
||||
* s_(4j + 4) s_(4j + 3) s_(4j + 2) s_(4j + 1) s_(4j)
|
||||
*
|
||||
* The sign-alternating property implies that the resulting digit values are
|
||||
* integers from -16 to 16.
|
||||
*
|
||||
* Of course, we don't actually need to compute the signed digits s_i as an
|
||||
* intermediate step (that's just a nice way to see how this scheme relates
|
||||
* to the wNAF): a direct computation obtains the recoded digit from the
|
||||
* six bits b_(4j + 4) ... b_(4j - 1).
|
||||
*
|
||||
* This function takes those five bits as an integer (0 .. 63), writing the
|
||||
* recoded digit to *sign (0 for positive, 1 for negative) and *digit (absolute
|
||||
* value, in the range 0 .. 8). Note that this integer essentially provides the
|
||||
* input bits "shifted to the left" by one position: for example, the input to
|
||||
* compute the least significant recoded digit, given that there's no bit b_-1,
|
||||
* has to be b_4 b_3 b_2 b_1 b_0 0.
|
||||
*
|
||||
*/
|
||||
void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign,
|
||||
unsigned char *digit, unsigned char in)
|
||||
{
|
||||
unsigned char s, d;
|
||||
|
||||
s = ~((in >> 5) - 1); /* sets all bits to MSB(in), 'in' seen as
|
||||
* 6-bit value */
|
||||
d = (1 << 6) - in - 1;
|
||||
d = (d & s) | (in & ~s);
|
||||
d = (d >> 1) + (d & 1);
|
||||
|
||||
*sign = s & 1;
|
||||
*digit = d;
|
||||
}
|
||||
#else
|
||||
static void *dummy = &dummy;
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,426 @@
|
||||
/* crypto/ec/ecp_oct.c */
|
||||
/*
|
||||
* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
|
||||
* for the OpenSSL project. Includes code written by Bodo Moeller for the
|
||||
* OpenSSL project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2019 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 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
* Portions of this software developed by SUN MICROSYSTEMS, INC.,
|
||||
* and contributed to the OpenSSL project.
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/symhacks.h>
|
||||
|
||||
#include "ec_lcl.h"
|
||||
|
||||
int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
|
||||
EC_POINT *point,
|
||||
const BIGNUM *x_, int y_bit,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *tmp1, *tmp2, *x, *y;
|
||||
int ret = 0;
|
||||
|
||||
/* clear error queue */
|
||||
ERR_clear_error();
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
y_bit = (y_bit != 0);
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
tmp1 = BN_CTX_get(ctx);
|
||||
tmp2 = BN_CTX_get(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
if (y == NULL)
|
||||
goto err;
|
||||
|
||||
/*-
|
||||
* Recover y. We have a Weierstrass equation
|
||||
* y^2 = x^3 + a*x + b,
|
||||
* so y is one of the square roots of x^3 + a*x + b.
|
||||
*/
|
||||
|
||||
/* tmp1 := x^3 */
|
||||
if (!BN_nnmod(x, x_, &group->field, ctx))
|
||||
goto err;
|
||||
if (group->meth->field_decode == 0) {
|
||||
/* field_{sqr,mul} work on standard representation */
|
||||
if (!group->meth->field_sqr(group, tmp2, x_, ctx))
|
||||
goto err;
|
||||
if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_mod_sqr(tmp2, x_, &group->field, ctx))
|
||||
goto err;
|
||||
if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* tmp1 := tmp1 + a*x */
|
||||
if (group->a_is_minus3) {
|
||||
if (!BN_mod_lshift1_quick(tmp2, x, &group->field))
|
||||
goto err;
|
||||
if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field))
|
||||
goto err;
|
||||
if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field))
|
||||
goto err;
|
||||
} else {
|
||||
if (group->meth->field_decode) {
|
||||
if (!group->meth->field_decode(group, tmp2, &group->a, ctx))
|
||||
goto err;
|
||||
if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
/* field_mul works on standard representation */
|
||||
if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* tmp1 := tmp1 + b */
|
||||
if (group->meth->field_decode) {
|
||||
if (!group->meth->field_decode(group, tmp2, &group->b, ctx))
|
||||
goto err;
|
||||
if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) {
|
||||
unsigned long err = ERR_peek_last_error();
|
||||
|
||||
if (ERR_GET_LIB(err) == ERR_LIB_BN
|
||||
&& ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) {
|
||||
ERR_clear_error();
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
|
||||
EC_R_INVALID_COMPRESSED_POINT);
|
||||
} else
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
|
||||
ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (y_bit != BN_is_odd(y)) {
|
||||
if (BN_is_zero(y)) {
|
||||
int kron;
|
||||
|
||||
kron = BN_kronecker(x, &group->field, ctx);
|
||||
if (kron == -2)
|
||||
goto err;
|
||||
|
||||
if (kron == 1)
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
|
||||
EC_R_INVALID_COMPRESSION_BIT);
|
||||
else
|
||||
/*
|
||||
* BN_mod_sqrt() should have cought this error (not a square)
|
||||
*/
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
|
||||
EC_R_INVALID_COMPRESSED_POINT);
|
||||
goto err;
|
||||
}
|
||||
if (!BN_usub(y, &group->field, y))
|
||||
goto err;
|
||||
}
|
||||
if (y_bit != BN_is_odd(y)) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
|
||||
point_conversion_form_t form,
|
||||
unsigned char *buf, size_t len, BN_CTX *ctx)
|
||||
{
|
||||
size_t ret;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
int used_ctx = 0;
|
||||
BIGNUM *x, *y;
|
||||
size_t field_len, i, skip;
|
||||
|
||||
if ((form != POINT_CONVERSION_COMPRESSED)
|
||||
&& (form != POINT_CONVERSION_UNCOMPRESSED)
|
||||
&& (form != POINT_CONVERSION_HYBRID)) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EC_POINT_is_at_infinity(group, point)) {
|
||||
/* encodes to a single 0 octet */
|
||||
if (buf != NULL) {
|
||||
if (len < 1) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
buf[0] = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ret := required output buffer length */
|
||||
field_len = BN_num_bytes(&group->field);
|
||||
ret =
|
||||
(form ==
|
||||
POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
|
||||
|
||||
/* if 'buf' is NULL, just return required length */
|
||||
if (buf != NULL) {
|
||||
if (len < ret) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
used_ctx = 1;
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
if (y == NULL)
|
||||
goto err;
|
||||
|
||||
if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx))
|
||||
goto err;
|
||||
|
||||
if ((form == POINT_CONVERSION_COMPRESSED
|
||||
|| form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
|
||||
buf[0] = form + 1;
|
||||
else
|
||||
buf[0] = form;
|
||||
|
||||
i = 1;
|
||||
|
||||
skip = field_len - BN_num_bytes(x);
|
||||
if (skip > field_len) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
while (skip > 0) {
|
||||
buf[i++] = 0;
|
||||
skip--;
|
||||
}
|
||||
skip = BN_bn2bin(x, buf + i);
|
||||
i += skip;
|
||||
if (i != 1 + field_len) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (form == POINT_CONVERSION_UNCOMPRESSED
|
||||
|| form == POINT_CONVERSION_HYBRID) {
|
||||
skip = field_len - BN_num_bytes(y);
|
||||
if (skip > field_len) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
while (skip > 0) {
|
||||
buf[i++] = 0;
|
||||
skip--;
|
||||
}
|
||||
skip = BN_bn2bin(y, buf + i);
|
||||
i += skip;
|
||||
}
|
||||
|
||||
if (i != ret) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (used_ctx)
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if (used_ctx)
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
|
||||
const unsigned char *buf, size_t len, BN_CTX *ctx)
|
||||
{
|
||||
point_conversion_form_t form;
|
||||
int y_bit;
|
||||
BN_CTX *new_ctx = NULL;
|
||||
BIGNUM *x, *y;
|
||||
size_t field_len, enc_len;
|
||||
int ret = 0;
|
||||
|
||||
if (len == 0) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
form = buf[0];
|
||||
y_bit = form & 1;
|
||||
form = form & ~1U;
|
||||
if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
|
||||
&& (form != POINT_CONVERSION_UNCOMPRESSED)
|
||||
&& (form != POINT_CONVERSION_HYBRID)) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (form == 0) {
|
||||
if (len != 1) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return EC_POINT_set_to_infinity(group, point);
|
||||
}
|
||||
|
||||
field_len = BN_num_bytes(&group->field);
|
||||
enc_len =
|
||||
(form ==
|
||||
POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
|
||||
|
||||
if (len != enc_len) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx == NULL) {
|
||||
ctx = new_ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
if (y == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_bin2bn(buf + 1, field_len, x))
|
||||
goto err;
|
||||
if (BN_ucmp(x, &group->field) >= 0) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (form == POINT_CONVERSION_COMPRESSED) {
|
||||
if (!EC_POINT_set_compressed_coordinates_GFp
|
||||
(group, point, x, y_bit, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
|
||||
goto err;
|
||||
if (BN_ucmp(y, &group->field) >= 0) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
goto err;
|
||||
}
|
||||
if (form == POINT_CONVERSION_HYBRID) {
|
||||
if (y_bit != BN_is_odd(y)) {
|
||||
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* EC_POINT_set_affine_coordinates_GFp is responsible for checking that
|
||||
* the point is on the curve.
|
||||
*/
|
||||
if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
if (new_ctx != NULL)
|
||||
BN_CTX_free(new_ctx);
|
||||
return ret;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user