2002-08-02 22:28:37 +08:00
|
|
|
/*
|
2021-01-28 20:54:57 +08:00
|
|
|
* Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
|
2017-06-15 22:16:46 +08:00
|
|
|
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
2001-03-06 04:13:37 +08:00
|
|
|
*
|
2018-12-06 20:38:06 +08:00
|
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
2016-05-18 03:38:09 +08:00
|
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
|
|
* in the file LICENSE in the source distribution or at
|
|
|
|
* https://www.openssl.org/source/license.html
|
2001-03-06 04:13:37 +08:00
|
|
|
*/
|
2016-05-18 03:38:09 +08:00
|
|
|
|
2020-01-28 13:14:18 +08:00
|
|
|
/*
|
2020-10-15 11:41:59 +08:00
|
|
|
* EC_GROUP low level APIs are deprecated for public use, but still ok for
|
2020-01-28 13:14:18 +08:00
|
|
|
* internal use.
|
|
|
|
*/
|
|
|
|
#include "internal/deprecated.h"
|
|
|
|
|
2001-03-07 09:41:20 +08:00
|
|
|
#include <string.h>
|
2020-08-22 12:55:41 +08:00
|
|
|
#include <openssl/params.h>
|
|
|
|
#include <openssl/core_names.h>
|
2001-03-07 09:17:05 +08:00
|
|
|
#include <openssl/err.h>
|
2001-03-09 03:14:52 +08:00
|
|
|
#include <openssl/opensslv.h>
|
2020-08-22 12:55:41 +08:00
|
|
|
#include "crypto/ec.h"
|
|
|
|
#include "internal/nelem.h"
|
2019-09-28 06:45:40 +08:00
|
|
|
#include "ec_local.h"
|
2022-02-04 22:13:01 +08:00
|
|
|
#include "internal/e_os.h" /* strcasecmp */
|
2001-03-07 09:17:05 +08:00
|
|
|
|
|
|
|
/* functions for EC_GROUP objects */
|
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
EC_GROUP *ossl_ec_group_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
|
|
|
|
const EC_METHOD *meth)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
EC_GROUP *ret;
|
|
|
|
|
|
|
|
if (meth == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_SLOT_FULL);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (meth->group_init == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-09-03 21:15:26 +08:00
|
|
|
ret = OPENSSL_zalloc(sizeof(*ret));
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ret == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-07-04 00:30:03 +08:00
|
|
|
ret->libctx = libctx;
|
2020-06-15 21:21:00 +08:00
|
|
|
if (propq != NULL) {
|
|
|
|
ret->propq = OPENSSL_strdup(propq);
|
|
|
|
if (ret->propq == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
2020-06-15 21:21:00 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
ret->meth = meth;
|
2016-02-02 02:15:57 +08:00
|
|
|
if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
|
|
|
|
ret->order = BN_new();
|
|
|
|
if (ret->order == NULL)
|
|
|
|
goto err;
|
|
|
|
ret->cofactor = BN_new();
|
|
|
|
if (ret->cofactor == NULL)
|
|
|
|
goto err;
|
|
|
|
}
|
2021-01-27 21:55:28 +08:00
|
|
|
ret->asn1_flag = OPENSSL_EC_EXPLICIT_CURVE;
|
2015-01-22 11:40:55 +08:00
|
|
|
ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
|
|
|
|
if (!meth->group_init(ret))
|
|
|
|
goto err;
|
|
|
|
return ret;
|
2015-09-03 21:15:26 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
err:
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_free(ret->order);
|
|
|
|
BN_free(ret->cofactor);
|
2020-06-15 21:21:00 +08:00
|
|
|
OPENSSL_free(ret->propq);
|
2015-01-22 11:40:55 +08:00
|
|
|
OPENSSL_free(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
2001-03-07 09:17:05 +08:00
|
|
|
|
2020-05-27 18:30:04 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
|
|
|
# ifndef FIPS_MODULE
|
2019-07-04 00:30:03 +08:00
|
|
|
EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
|
|
|
|
{
|
2021-02-18 18:27:26 +08:00
|
|
|
return ossl_ec_group_new_ex(NULL, NULL, meth);
|
2019-07-04 00:30:03 +08:00
|
|
|
}
|
2020-05-27 18:30:04 +08:00
|
|
|
# endif
|
2019-07-04 00:30:03 +08:00
|
|
|
#endif
|
|
|
|
|
2016-01-14 10:26:00 +08:00
|
|
|
void EC_pre_comp_free(EC_GROUP *group)
|
2016-01-06 02:06:03 +08:00
|
|
|
{
|
|
|
|
switch (group->pre_comp_type) {
|
2016-08-31 01:31:18 +08:00
|
|
|
case PCT_none:
|
2016-01-06 02:06:03 +08:00
|
|
|
break;
|
2016-08-29 20:23:25 +08:00
|
|
|
case PCT_nistz256:
|
2016-08-31 01:31:18 +08:00
|
|
|
#ifdef ECP_NISTZ256_ASM
|
2016-01-06 02:06:03 +08:00
|
|
|
EC_nistz256_pre_comp_free(group->pre_comp.nistz256);
|
2016-01-14 05:39:37 +08:00
|
|
|
#endif
|
2016-08-31 01:31:18 +08:00
|
|
|
break;
|
2016-01-06 02:06:03 +08:00
|
|
|
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
|
2016-08-29 20:23:25 +08:00
|
|
|
case PCT_nistp224:
|
2016-01-06 02:06:03 +08:00
|
|
|
EC_nistp224_pre_comp_free(group->pre_comp.nistp224);
|
|
|
|
break;
|
2016-08-29 20:23:25 +08:00
|
|
|
case PCT_nistp256:
|
2016-01-06 02:06:03 +08:00
|
|
|
EC_nistp256_pre_comp_free(group->pre_comp.nistp256);
|
|
|
|
break;
|
2016-08-29 20:23:25 +08:00
|
|
|
case PCT_nistp521:
|
2016-01-06 02:06:03 +08:00
|
|
|
EC_nistp521_pre_comp_free(group->pre_comp.nistp521);
|
|
|
|
break;
|
2016-08-31 01:31:18 +08:00
|
|
|
#else
|
|
|
|
case PCT_nistp224:
|
|
|
|
case PCT_nistp256:
|
|
|
|
case PCT_nistp521:
|
|
|
|
break;
|
2016-01-06 02:06:03 +08:00
|
|
|
#endif
|
2016-08-29 20:23:25 +08:00
|
|
|
case PCT_ec:
|
2016-01-06 02:06:03 +08:00
|
|
|
EC_ec_pre_comp_free(group->pre_comp.ec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
group->pre_comp.ec = NULL;
|
|
|
|
}
|
|
|
|
|
2001-03-07 09:17:05 +08:00
|
|
|
void EC_GROUP_free(EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (!group)
|
|
|
|
return;
|
2002-05-21 16:59:57 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (group->meth->group_finish != 0)
|
|
|
|
group->meth->group_finish(group);
|
2001-03-07 17:03:32 +08:00
|
|
|
|
2016-01-14 10:26:00 +08:00
|
|
|
EC_pre_comp_free(group);
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_MONT_CTX_free(group->mont_data);
|
2015-03-26 06:35:24 +08:00
|
|
|
EC_POINT_free(group->generator);
|
2015-01-22 11:40:55 +08:00
|
|
|
BN_free(group->order);
|
|
|
|
BN_free(group->cofactor);
|
2015-05-02 02:37:16 +08:00
|
|
|
OPENSSL_free(group->seed);
|
2020-06-15 21:21:00 +08:00
|
|
|
OPENSSL_free(group->propq);
|
2015-01-22 11:40:55 +08:00
|
|
|
OPENSSL_free(group);
|
|
|
|
}
|
2001-03-07 09:17:05 +08:00
|
|
|
|
2019-11-06 00:28:50 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
2001-03-07 09:17:05 +08:00
|
|
|
void EC_GROUP_clear_free(EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (!group)
|
|
|
|
return;
|
2001-03-07 17:03:32 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (group->meth->group_clear_finish != 0)
|
|
|
|
group->meth->group_clear_finish(group);
|
|
|
|
else if (group->meth->group_finish != 0)
|
|
|
|
group->meth->group_finish(group);
|
2001-03-07 17:03:32 +08:00
|
|
|
|
2016-01-14 10:26:00 +08:00
|
|
|
EC_pre_comp_free(group);
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_MONT_CTX_free(group->mont_data);
|
2015-03-26 06:35:24 +08:00
|
|
|
EC_POINT_clear_free(group->generator);
|
2015-01-22 11:40:55 +08:00
|
|
|
BN_clear_free(group->order);
|
|
|
|
BN_clear_free(group->cofactor);
|
2015-05-01 05:57:32 +08:00
|
|
|
OPENSSL_clear_free(group->seed, group->seed_len);
|
2015-05-02 11:10:31 +08:00
|
|
|
OPENSSL_clear_free(group, sizeof(*group));
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2019-10-18 20:54:20 +08:00
|
|
|
#endif
|
2001-03-07 09:17:05 +08:00
|
|
|
|
|
|
|
int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (dest->meth->group_copy == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (dest->meth != src->meth) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (dest == src)
|
|
|
|
return 1;
|
|
|
|
|
2019-07-04 00:30:03 +08:00
|
|
|
dest->libctx = src->libctx;
|
2018-05-21 22:24:56 +08:00
|
|
|
dest->curve_name = src->curve_name;
|
|
|
|
|
2016-01-06 02:06:03 +08:00
|
|
|
/* Copy precomputed */
|
|
|
|
dest->pre_comp_type = src->pre_comp_type;
|
|
|
|
switch (src->pre_comp_type) {
|
2016-08-31 01:31:18 +08:00
|
|
|
case PCT_none:
|
2016-01-06 02:06:03 +08:00
|
|
|
dest->pre_comp.ec = NULL;
|
|
|
|
break;
|
2016-08-29 20:23:25 +08:00
|
|
|
case PCT_nistz256:
|
2016-08-31 01:31:18 +08:00
|
|
|
#ifdef ECP_NISTZ256_ASM
|
2016-01-06 02:06:03 +08:00
|
|
|
dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
|
2016-01-14 05:39:37 +08:00
|
|
|
#endif
|
2016-08-31 01:31:18 +08:00
|
|
|
break;
|
2016-01-06 02:06:03 +08:00
|
|
|
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
|
2016-08-29 20:23:25 +08:00
|
|
|
case PCT_nistp224:
|
2016-01-06 02:06:03 +08:00
|
|
|
dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
|
|
|
|
break;
|
2016-08-29 20:23:25 +08:00
|
|
|
case PCT_nistp256:
|
2016-01-06 02:06:03 +08:00
|
|
|
dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256);
|
|
|
|
break;
|
2016-08-29 20:23:25 +08:00
|
|
|
case PCT_nistp521:
|
2016-01-06 02:06:03 +08:00
|
|
|
dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
|
|
|
|
break;
|
2016-08-31 01:31:18 +08:00
|
|
|
#else
|
|
|
|
case PCT_nistp224:
|
|
|
|
case PCT_nistp256:
|
|
|
|
case PCT_nistp521:
|
|
|
|
break;
|
2016-01-06 02:06:03 +08:00
|
|
|
#endif
|
2016-08-29 20:23:25 +08:00
|
|
|
case PCT_ec:
|
2016-01-06 02:06:03 +08:00
|
|
|
dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
|
|
|
|
break;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (src->mont_data != NULL) {
|
|
|
|
if (dest->mont_data == NULL) {
|
|
|
|
dest->mont_data = BN_MONT_CTX_new();
|
|
|
|
if (dest->mont_data == NULL)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
/* src->generator == NULL */
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_MONT_CTX_free(dest->mont_data);
|
|
|
|
dest->mont_data = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2001-03-07 09:17:05 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (src->generator != NULL) {
|
|
|
|
if (dest->generator == NULL) {
|
|
|
|
dest->generator = EC_POINT_new(dest);
|
|
|
|
if (dest->generator == NULL)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!EC_POINT_copy(dest->generator, src->generator))
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
/* src->generator == NULL */
|
2015-03-26 06:35:24 +08:00
|
|
|
EC_POINT_clear_free(dest->generator);
|
|
|
|
dest->generator = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
|
2016-02-02 02:15:57 +08:00
|
|
|
if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
|
|
|
|
if (!BN_copy(dest->order, src->order))
|
|
|
|
return 0;
|
|
|
|
if (!BN_copy(dest->cofactor, src->cofactor))
|
|
|
|
return 0;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
dest->asn1_flag = src->asn1_flag;
|
|
|
|
dest->asn1_form = src->asn1_form;
|
2020-08-21 20:50:52 +08:00
|
|
|
dest->decoded_from_explicit_params = src->decoded_from_explicit_params;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
if (src->seed) {
|
2015-05-01 22:02:07 +08:00
|
|
|
OPENSSL_free(dest->seed);
|
2018-04-03 23:31:16 +08:00
|
|
|
if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
2018-04-03 23:31:16 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
if (!memcpy(dest->seed, src->seed, src->seed_len))
|
|
|
|
return 0;
|
|
|
|
dest->seed_len = src->seed_len;
|
|
|
|
} else {
|
2015-05-01 22:02:07 +08:00
|
|
|
OPENSSL_free(dest->seed);
|
2015-01-22 11:40:55 +08:00
|
|
|
dest->seed = NULL;
|
|
|
|
dest->seed_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dest->meth->group_copy(dest, src);
|
|
|
|
}
|
2001-03-07 09:17:05 +08:00
|
|
|
|
2002-08-02 21:42:24 +08:00
|
|
|
EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
EC_GROUP *t = NULL;
|
|
|
|
int ok = 0;
|
2002-08-02 21:42:24 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (a == NULL)
|
|
|
|
return NULL;
|
2002-08-02 21:42:24 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
if ((t = ossl_ec_group_new_ex(a->libctx, a->propq, a->meth)) == NULL)
|
2017-10-17 22:04:09 +08:00
|
|
|
return NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
if (!EC_GROUP_copy(t, a))
|
|
|
|
goto err;
|
2002-08-02 21:42:24 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
ok = 1;
|
2002-08-02 21:42:24 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
err:
|
|
|
|
if (!ok) {
|
2015-03-26 06:35:24 +08:00
|
|
|
EC_GROUP_free(t);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
2015-03-26 06:35:24 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
return t;
|
|
|
|
}
|
2002-08-02 21:42:24 +08:00
|
|
|
|
2020-05-27 18:30:04 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
2001-03-11 07:18:35 +08:00
|
|
|
const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return group->meth;
|
|
|
|
}
|
2001-03-11 07:18:35 +08:00
|
|
|
|
2002-06-10 20:18:21 +08:00
|
|
|
int EC_METHOD_get_field_type(const EC_METHOD *meth)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return meth->field_type;
|
|
|
|
}
|
2020-05-27 18:30:04 +08:00
|
|
|
#endif
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2017-12-30 22:08:31 +08:00
|
|
|
static int ec_precompute_mont_data(EC_GROUP *);
|
|
|
|
|
2019-09-02 20:02:30 +08:00
|
|
|
/*-
|
|
|
|
* Try computing cofactor from the generator order (n) and field cardinality (q).
|
|
|
|
* This works for all curves of cryptographic interest.
|
|
|
|
*
|
|
|
|
* Hasse thm: q + 1 - 2*sqrt(q) <= n*h <= q + 1 + 2*sqrt(q)
|
|
|
|
* h_min = (q + 1 - 2*sqrt(q))/n
|
|
|
|
* h_max = (q + 1 + 2*sqrt(q))/n
|
|
|
|
* h_max - h_min = 4*sqrt(q)/n
|
|
|
|
* So if n > 4*sqrt(q) holds, there is only one possible value for h:
|
|
|
|
* h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil
|
|
|
|
*
|
|
|
|
* Otherwise, zero cofactor and return success.
|
|
|
|
*/
|
|
|
|
static int ec_guess_cofactor(EC_GROUP *group) {
|
|
|
|
int ret = 0;
|
|
|
|
BN_CTX *ctx = NULL;
|
|
|
|
BIGNUM *q = NULL;
|
|
|
|
|
|
|
|
/*-
|
|
|
|
* If the cofactor is too large, we cannot guess it.
|
|
|
|
* The RHS of below is a strict overestimate of lg(4 * sqrt(q))
|
|
|
|
*/
|
|
|
|
if (BN_num_bits(group->order) <= (BN_num_bits(group->field) + 1) / 2 + 3) {
|
|
|
|
/* default to 0 */
|
|
|
|
BN_zero(group->cofactor);
|
|
|
|
/* return success */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ctx = BN_CTX_new_ex(group->libctx)) == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
BN_CTX_start(ctx);
|
|
|
|
if ((q = BN_CTX_get(ctx)) == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* set q = 2**m for binary fields; q = p otherwise */
|
|
|
|
if (group->meth->field_type == NID_X9_62_characteristic_two_field) {
|
|
|
|
BN_zero(q);
|
|
|
|
if (!BN_set_bit(q, BN_num_bits(group->field) - 1))
|
|
|
|
goto err;
|
|
|
|
} else {
|
|
|
|
if (!BN_copy(q, group->field))
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* compute h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2)/n \rfloor */
|
|
|
|
if (!BN_rshift1(group->cofactor, group->order) /* n/2 */
|
|
|
|
|| !BN_add(group->cofactor, group->cofactor, q) /* q + n/2 */
|
|
|
|
/* q + 1 + n/2 */
|
|
|
|
|| !BN_add(group->cofactor, group->cofactor, BN_value_one())
|
|
|
|
/* (q + 1 + n/2)/n */
|
|
|
|
|| !BN_div(group->cofactor, NULL, group->cofactor, group->order, ctx))
|
|
|
|
goto err;
|
|
|
|
ret = 1;
|
|
|
|
err:
|
|
|
|
BN_CTX_end(ctx);
|
|
|
|
BN_CTX_free(ctx);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
|
|
|
|
const BIGNUM *order, const BIGNUM *cofactor)
|
|
|
|
{
|
|
|
|
if (generator == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-02 20:02:30 +08:00
|
|
|
/* require group->field >= 1 */
|
|
|
|
if (group->field == NULL || BN_is_zero(group->field)
|
|
|
|
|| BN_is_negative(group->field)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
|
2019-09-02 20:02:30 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
* - require order >= 1
|
|
|
|
* - enforce upper bound due to Hasse thm: order can be no more than one bit
|
|
|
|
* longer than field cardinality
|
|
|
|
*/
|
|
|
|
if (order == NULL || BN_is_zero(order) || BN_is_negative(order)
|
|
|
|
|| BN_num_bits(order) > BN_num_bits(group->field) + 1) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
|
2019-09-02 20:02:30 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
* Unfortunately the cofactor is an optional field in many standards.
|
|
|
|
* Internally, the lib uses 0 cofactor as a marker for "unknown cofactor".
|
|
|
|
* So accept cofactor == NULL or cofactor >= 0.
|
|
|
|
*/
|
|
|
|
if (cofactor != NULL && BN_is_negative(cofactor)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR);
|
2019-09-02 20:02:30 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (group->generator == NULL) {
|
|
|
|
group->generator = EC_POINT_new(group);
|
|
|
|
if (group->generator == NULL)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!EC_POINT_copy(group->generator, generator))
|
|
|
|
return 0;
|
|
|
|
|
2019-09-02 20:02:30 +08:00
|
|
|
if (!BN_copy(group->order, order))
|
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2019-09-02 20:02:30 +08:00
|
|
|
/* Either take the provided positive cofactor, or try to compute it */
|
|
|
|
if (cofactor != NULL && !BN_is_zero(cofactor)) {
|
2015-01-22 11:40:55 +08:00
|
|
|
if (!BN_copy(group->cofactor, cofactor))
|
|
|
|
return 0;
|
2019-09-02 20:02:30 +08:00
|
|
|
} else if (!ec_guess_cofactor(group)) {
|
2015-01-22 11:40:55 +08:00
|
|
|
BN_zero(group->cofactor);
|
2019-09-02 20:02:30 +08:00
|
|
|
return 0;
|
2019-03-21 18:09:02 +08:00
|
|
|
}
|
2019-09-02 20:02:30 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
/*
|
2016-01-20 19:18:21 +08:00
|
|
|
* Some groups have an order with
|
2015-01-22 11:40:55 +08:00
|
|
|
* factors of two, which makes the Montgomery setup fail.
|
|
|
|
* |group->mont_data| will be NULL in this case.
|
|
|
|
*/
|
2016-01-20 19:18:21 +08:00
|
|
|
if (BN_is_odd(group->order)) {
|
|
|
|
return ec_precompute_mont_data(group);
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2016-01-20 19:18:21 +08:00
|
|
|
BN_MONT_CTX_free(group->mont_data);
|
|
|
|
group->mont_data = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2001-03-09 03:14:52 +08:00
|
|
|
|
2005-05-16 18:11:04 +08:00
|
|
|
const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return group->generator;
|
|
|
|
}
|
2001-03-09 03:14:52 +08:00
|
|
|
|
2014-09-12 06:13:20 +08:00
|
|
|
BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return group->mont_data;
|
|
|
|
}
|
2001-03-09 03:14:52 +08:00
|
|
|
|
2002-05-08 19:54:24 +08:00
|
|
|
int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2016-02-01 00:34:07 +08:00
|
|
|
if (group->order == NULL)
|
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
if (!BN_copy(order, group->order))
|
|
|
|
return 0;
|
2001-03-07 09:17:05 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
return !BN_is_zero(order);
|
|
|
|
}
|
2001-03-07 09:17:05 +08:00
|
|
|
|
2016-02-01 00:34:07 +08:00
|
|
|
const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group)
|
|
|
|
{
|
|
|
|
return group->order;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EC_GROUP_order_bits(const EC_GROUP *group)
|
|
|
|
{
|
2016-02-29 01:47:06 +08:00
|
|
|
return group->meth->group_order_bits(group);
|
2016-02-01 00:34:07 +08:00
|
|
|
}
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
|
|
|
|
BN_CTX *ctx)
|
|
|
|
{
|
2016-02-01 00:34:07 +08:00
|
|
|
|
|
|
|
if (group->cofactor == NULL)
|
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
if (!BN_copy(cofactor, group->cofactor))
|
|
|
|
return 0;
|
2001-03-11 07:18:35 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
return !BN_is_zero(group->cofactor);
|
|
|
|
}
|
2001-03-11 07:18:35 +08:00
|
|
|
|
2016-02-01 00:34:07 +08:00
|
|
|
const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group)
|
|
|
|
{
|
|
|
|
return group->cofactor;
|
|
|
|
}
|
|
|
|
|
2005-05-09 06:09:12 +08:00
|
|
|
void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
group->curve_name = nid;
|
2021-01-27 21:55:28 +08:00
|
|
|
group->asn1_flag =
|
|
|
|
(nid != NID_undef)
|
|
|
|
? OPENSSL_EC_NAMED_CURVE
|
|
|
|
: OPENSSL_EC_EXPLICIT_CURVE;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2002-05-08 19:54:24 +08:00
|
|
|
|
2005-05-09 06:09:12 +08:00
|
|
|
int EC_GROUP_get_curve_name(const EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return group->curve_name;
|
|
|
|
}
|
2002-05-08 19:54:24 +08:00
|
|
|
|
2019-02-07 17:51:39 +08:00
|
|
|
const BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group)
|
|
|
|
{
|
|
|
|
return group->field;
|
|
|
|
}
|
|
|
|
|
2020-05-27 18:30:04 +08:00
|
|
|
int EC_GROUP_get_field_type(const EC_GROUP *group)
|
|
|
|
{
|
|
|
|
return group->meth->field_type;
|
|
|
|
}
|
|
|
|
|
2002-06-10 20:18:21 +08:00
|
|
|
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
group->asn1_flag = flag;
|
|
|
|
}
|
2002-06-10 20:18:21 +08:00
|
|
|
|
|
|
|
int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return group->asn1_flag;
|
|
|
|
}
|
2002-06-10 20:18:21 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
|
2002-06-12 22:01:17 +08:00
|
|
|
point_conversion_form_t form)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
group->asn1_form = form;
|
|
|
|
}
|
2002-06-12 22:01:17 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
|
|
|
|
*group)
|
|
|
|
{
|
|
|
|
return group->asn1_form;
|
|
|
|
}
|
2002-06-12 22:01:17 +08:00
|
|
|
|
2002-06-18 16:38:59 +08:00
|
|
|
size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2015-05-01 22:02:07 +08:00
|
|
|
OPENSSL_free(group->seed);
|
|
|
|
group->seed = NULL;
|
|
|
|
group->seed_len = 0;
|
2002-06-18 16:38:59 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (!len || !p)
|
|
|
|
return 1;
|
2002-06-18 16:38:59 +08:00
|
|
|
|
2018-04-27 00:06:17 +08:00
|
|
|
if ((group->seed = OPENSSL_malloc(len)) == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
2018-04-27 00:06:17 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
memcpy(group->seed, p, len);
|
|
|
|
group->seed_len = len;
|
2002-06-18 16:38:59 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
return len;
|
|
|
|
}
|
2002-06-18 16:38:59 +08:00
|
|
|
|
|
|
|
unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return group->seed;
|
|
|
|
}
|
2002-06-18 16:38:59 +08:00
|
|
|
|
|
|
|
size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return group->seed_len;
|
|
|
|
}
|
|
|
|
|
2018-07-30 22:39:41 +08:00
|
|
|
int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
|
|
|
|
const BIGNUM *b, BN_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (group->meth->group_set_curve == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return group->meth->group_set_curve(group, p, a, b, ctx);
|
|
|
|
}
|
|
|
|
|
2018-07-30 22:39:41 +08:00
|
|
|
int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
|
|
|
|
BN_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2018-07-30 22:39:41 +08:00
|
|
|
if (group->meth->group_get_curve == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return group->meth->group_get_curve(group, p, a, b, ctx);
|
|
|
|
}
|
2002-08-02 21:42:24 +08:00
|
|
|
|
2019-11-06 00:28:50 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
2018-07-30 22:39:41 +08:00
|
|
|
int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
|
|
|
|
const BIGNUM *b, BN_CTX *ctx)
|
|
|
|
{
|
|
|
|
return EC_GROUP_set_curve(group, p, a, b, ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
|
|
|
|
BIGNUM *b, BN_CTX *ctx)
|
|
|
|
{
|
|
|
|
return EC_GROUP_get_curve(group, p, a, b, ctx);
|
|
|
|
}
|
|
|
|
|
2018-07-30 23:56:41 +08:00
|
|
|
# ifndef OPENSSL_NO_EC2M
|
2015-01-22 11:40:55 +08:00
|
|
|
int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
|
|
|
|
const BIGNUM *b, BN_CTX *ctx)
|
|
|
|
{
|
2018-07-30 22:39:41 +08:00
|
|
|
return EC_GROUP_set_curve(group, p, a, b, ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
|
|
|
|
BIGNUM *b, BN_CTX *ctx)
|
|
|
|
{
|
2018-07-30 22:39:41 +08:00
|
|
|
return EC_GROUP_get_curve(group, p, a, b, ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2018-07-30 23:56:41 +08:00
|
|
|
# endif
|
2011-02-13 01:23:32 +08:00
|
|
|
#endif
|
2002-08-02 21:42:24 +08:00
|
|
|
|
|
|
|
int EC_GROUP_get_degree(const EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (group->meth->group_get_degree == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return group->meth->group_get_degree(group);
|
|
|
|
}
|
2001-03-11 07:18:35 +08:00
|
|
|
|
2002-03-20 18:18:07 +08:00
|
|
|
int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (group->meth->group_check_discriminant == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return group->meth->group_check_discriminant(group, ctx);
|
|
|
|
}
|
2002-03-18 21:10:45 +08:00
|
|
|
|
2003-07-21 21:43:28 +08:00
|
|
|
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int r = 0;
|
|
|
|
BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2015-01-22 11:40:55 +08:00
|
|
|
BN_CTX *ctx_new = NULL;
|
2019-07-04 00:30:03 +08:00
|
|
|
#endif
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
/* compare the field types */
|
2020-05-27 18:30:04 +08:00
|
|
|
if (EC_GROUP_get_field_type(a) != EC_GROUP_get_field_type(b))
|
2015-01-22 11:40:55 +08:00
|
|
|
return 1;
|
|
|
|
/* compare the curve name (if present in both) */
|
|
|
|
if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
|
|
|
|
EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
|
|
|
|
return 1;
|
2016-02-02 02:15:57 +08:00
|
|
|
if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE)
|
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-31 14:47:58 +08:00
|
|
|
if (ctx == NULL)
|
|
|
|
ctx_new = ctx = BN_CTX_new();
|
|
|
|
#endif
|
|
|
|
if (ctx == NULL)
|
|
|
|
return -1;
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
BN_CTX_start(ctx);
|
|
|
|
a1 = BN_CTX_get(ctx);
|
|
|
|
a2 = BN_CTX_get(ctx);
|
|
|
|
a3 = BN_CTX_get(ctx);
|
|
|
|
b1 = BN_CTX_get(ctx);
|
|
|
|
b2 = BN_CTX_get(ctx);
|
|
|
|
b3 = BN_CTX_get(ctx);
|
2015-10-30 19:12:26 +08:00
|
|
|
if (b3 == NULL) {
|
2015-01-22 11:40:55 +08:00
|
|
|
BN_CTX_end(ctx);
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_CTX_free(ctx_new);
|
2019-07-04 00:30:03 +08:00
|
|
|
#endif
|
2015-01-22 11:40:55 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX This approach assumes that the external representation of curves
|
|
|
|
* over the same field type is the same.
|
|
|
|
*/
|
|
|
|
if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
|
|
|
|
!b->meth->group_get_curve(b, b1, b2, b3, ctx))
|
|
|
|
r = 1;
|
|
|
|
|
2019-03-21 18:09:02 +08:00
|
|
|
/* return 1 if the curve parameters are different */
|
|
|
|
if (r || BN_cmp(a1, b1) != 0 || BN_cmp(a2, b2) != 0 || BN_cmp(a3, b3) != 0)
|
2015-01-22 11:40:55 +08:00
|
|
|
r = 1;
|
|
|
|
|
2019-03-31 23:46:53 +08:00
|
|
|
/* XXX EC_POINT_cmp() assumes that the methods are equal */
|
2019-03-21 18:09:02 +08:00
|
|
|
/* return 1 if the generators are different */
|
2015-01-22 11:40:55 +08:00
|
|
|
if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
|
2019-03-21 18:09:02 +08:00
|
|
|
EC_GROUP_get0_generator(b), ctx) != 0)
|
2015-01-22 11:40:55 +08:00
|
|
|
r = 1;
|
|
|
|
|
|
|
|
if (!r) {
|
2016-02-01 00:34:07 +08:00
|
|
|
const BIGNUM *ao, *bo, *ac, *bc;
|
2019-03-31 23:46:53 +08:00
|
|
|
/* compare the orders */
|
2016-02-01 00:34:07 +08:00
|
|
|
ao = EC_GROUP_get0_order(a);
|
|
|
|
bo = EC_GROUP_get0_order(b);
|
|
|
|
if (ao == NULL || bo == NULL) {
|
2019-03-21 18:09:02 +08:00
|
|
|
/* return an error if either order is NULL */
|
|
|
|
r = -1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (BN_cmp(ao, bo) != 0) {
|
|
|
|
/* return 1 if orders are different */
|
|
|
|
r = 1;
|
|
|
|
goto end;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2019-03-21 18:09:02 +08:00
|
|
|
/*
|
|
|
|
* It gets here if the curve parameters and generator matched.
|
|
|
|
* Now check the optional cofactors (if both are present).
|
|
|
|
*/
|
|
|
|
ac = EC_GROUP_get0_cofactor(a);
|
|
|
|
bc = EC_GROUP_get0_cofactor(b);
|
|
|
|
/* Returns 1 (mismatch) if both cofactors are specified and different */
|
|
|
|
if (!BN_is_zero(ac) && !BN_is_zero(bc) && BN_cmp(ac, bc) != 0)
|
2015-01-22 11:40:55 +08:00
|
|
|
r = 1;
|
2019-03-21 18:09:02 +08:00
|
|
|
/* Returns 0 if the parameters matched */
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2019-03-21 18:09:02 +08:00
|
|
|
end:
|
2015-01-22 11:40:55 +08:00
|
|
|
BN_CTX_end(ctx);
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_CTX_free(ctx_new);
|
2019-07-04 00:30:03 +08:00
|
|
|
#endif
|
2015-01-22 11:40:55 +08:00
|
|
|
return r;
|
|
|
|
}
|
2003-07-21 21:43:28 +08:00
|
|
|
|
2001-03-07 09:17:05 +08:00
|
|
|
/* functions for EC_POINT objects */
|
|
|
|
|
|
|
|
EC_POINT *EC_POINT_new(const EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
EC_POINT *ret;
|
|
|
|
|
|
|
|
if (group == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2018-04-27 00:06:17 +08:00
|
|
|
if (group->meth->point_init == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-02-01 02:13:43 +08:00
|
|
|
ret = OPENSSL_zalloc(sizeof(*ret));
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ret == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret->meth = group->meth;
|
2018-05-21 22:24:56 +08:00
|
|
|
ret->curve_name = group->curve_name;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
if (!ret->meth->point_init(ret)) {
|
|
|
|
OPENSSL_free(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2001-03-07 09:17:05 +08:00
|
|
|
|
|
|
|
void EC_POINT_free(EC_POINT *point)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-09-17 03:28:57 +08:00
|
|
|
if (point == NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
return;
|
2002-05-21 16:59:57 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (point->meth->point_finish != 0)
|
|
|
|
point->meth->point_finish(point);
|
|
|
|
OPENSSL_free(point);
|
|
|
|
}
|
2001-03-07 09:17:05 +08:00
|
|
|
|
|
|
|
void EC_POINT_clear_free(EC_POINT *point)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-09-17 03:28:57 +08:00
|
|
|
if (point == NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (point->meth->point_clear_finish != 0)
|
|
|
|
point->meth->point_clear_finish(point);
|
|
|
|
else if (point->meth->point_finish != 0)
|
|
|
|
point->meth->point_finish(point);
|
2015-05-02 11:10:31 +08:00
|
|
|
OPENSSL_clear_free(point, sizeof(*point));
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2001-03-07 09:17:05 +08:00
|
|
|
|
|
|
|
int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (dest->meth->point_copy == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (dest->meth != src->meth
|
|
|
|
|| (dest->curve_name != src->curve_name
|
2019-03-21 18:09:02 +08:00
|
|
|
&& dest->curve_name != 0
|
|
|
|
&& src->curve_name != 0)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (dest == src)
|
|
|
|
return 1;
|
|
|
|
return dest->meth->point_copy(dest, src);
|
|
|
|
}
|
2001-03-07 09:17:05 +08:00
|
|
|
|
2002-08-02 21:42:24 +08:00
|
|
|
EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
EC_POINT *t;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (a == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
t = EC_POINT_new(group);
|
|
|
|
if (t == NULL)
|
2017-10-17 22:04:09 +08:00
|
|
|
return NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
r = EC_POINT_copy(t, a);
|
|
|
|
if (!r) {
|
|
|
|
EC_POINT_free(t);
|
|
|
|
return NULL;
|
2015-03-26 06:35:24 +08:00
|
|
|
}
|
|
|
|
return t;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2002-08-02 21:42:24 +08:00
|
|
|
|
2020-05-27 18:30:04 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
2001-03-11 07:18:35 +08:00
|
|
|
const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return point->meth;
|
|
|
|
}
|
2020-05-27 18:30:04 +08:00
|
|
|
#endif
|
2001-03-11 07:18:35 +08:00
|
|
|
|
2001-03-08 09:23:28 +08:00
|
|
|
int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (group->meth->point_set_to_infinity == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (group->meth != point->meth) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return group->meth->point_set_to_infinity(group, point);
|
|
|
|
}
|
|
|
|
|
2020-04-12 23:17:19 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
2015-01-22 11:40:55 +08:00
|
|
|
int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
|
|
|
|
EC_POINT *point, const BIGNUM *x,
|
|
|
|
const BIGNUM *y, const BIGNUM *z,
|
|
|
|
BN_CTX *ctx)
|
|
|
|
{
|
2020-04-12 23:17:19 +08:00
|
|
|
if (group->meth->field_type != NID_X9_62_prime_field) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(point, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2021-02-18 18:27:26 +08:00
|
|
|
return ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, point,
|
|
|
|
x, y, z, ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
|
|
|
|
const EC_POINT *point, BIGNUM *x,
|
|
|
|
BIGNUM *y, BIGNUM *z,
|
|
|
|
BN_CTX *ctx)
|
|
|
|
{
|
2020-04-12 23:17:19 +08:00
|
|
|
if (group->meth->field_type != NID_X9_62_prime_field) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(point, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2021-02-18 18:27:26 +08:00
|
|
|
return ossl_ec_GFp_simple_get_Jprojective_coordinates_GFp(group, point,
|
|
|
|
x, y, z, ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2020-04-12 23:17:19 +08:00
|
|
|
#endif
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2018-07-30 22:39:41 +08:00
|
|
|
int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
|
|
|
|
const BIGNUM *x, const BIGNUM *y,
|
|
|
|
BN_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2018-07-30 22:39:41 +08:00
|
|
|
if (group->meth->point_set_affine_coordinates == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(point, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2016-06-03 20:42:04 +08:00
|
|
|
if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE);
|
2016-06-03 20:42:04 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2001-03-08 09:23:28 +08:00
|
|
|
|
2019-11-06 00:28:50 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
2018-07-30 22:39:41 +08:00
|
|
|
int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
|
|
|
|
EC_POINT *point, const BIGNUM *x,
|
|
|
|
const BIGNUM *y, BN_CTX *ctx)
|
|
|
|
{
|
|
|
|
return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
|
|
|
|
}
|
|
|
|
|
2018-07-30 23:56:41 +08:00
|
|
|
# ifndef OPENSSL_NO_EC2M
|
2015-01-22 11:40:55 +08:00
|
|
|
int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
|
|
|
|
EC_POINT *point, const BIGNUM *x,
|
|
|
|
const BIGNUM *y, BN_CTX *ctx)
|
|
|
|
{
|
2018-07-30 22:39:41 +08:00
|
|
|
return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
|
|
|
|
}
|
2018-07-30 23:56:41 +08:00
|
|
|
# endif
|
2018-07-30 22:39:41 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
|
|
|
|
const EC_POINT *point, BIGNUM *x, BIGNUM *y,
|
|
|
|
BN_CTX *ctx)
|
|
|
|
{
|
|
|
|
if (group->meth->point_get_affine_coordinates == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(point, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2016-06-03 20:42:04 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-08-22 17:27:34 +08:00
|
|
|
if (EC_POINT_is_at_infinity(group, point)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
|
2018-08-22 17:27:34 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-07-30 22:39:41 +08:00
|
|
|
return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2002-08-02 21:42:24 +08:00
|
|
|
|
2019-11-06 00:28:50 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
2015-01-22 11:40:55 +08:00
|
|
|
int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
|
|
|
|
const EC_POINT *point, BIGNUM *x,
|
|
|
|
BIGNUM *y, BN_CTX *ctx)
|
|
|
|
{
|
2018-07-30 22:39:41 +08:00
|
|
|
return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2002-08-02 21:42:24 +08:00
|
|
|
|
2018-07-30 23:56:41 +08:00
|
|
|
# ifndef OPENSSL_NO_EC2M
|
2015-01-22 11:40:55 +08:00
|
|
|
int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
|
|
|
|
const EC_POINT *point, BIGNUM *x,
|
|
|
|
BIGNUM *y, BN_CTX *ctx)
|
|
|
|
{
|
2018-07-30 22:39:41 +08:00
|
|
|
return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2018-07-30 23:56:41 +08:00
|
|
|
# endif
|
2011-02-13 01:23:32 +08:00
|
|
|
#endif
|
2002-08-02 21:42:24 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
|
|
|
|
const EC_POINT *b, BN_CTX *ctx)
|
|
|
|
{
|
|
|
|
if (group->meth->add == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)
|
|
|
|
|| !ec_point_is_compat(b, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return group->meth->add(group, r, a, b, ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
|
|
|
|
BN_CTX *ctx)
|
|
|
|
{
|
|
|
|
if (group->meth->dbl == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return group->meth->dbl(group, r, a, ctx);
|
|
|
|
}
|
2001-03-07 09:17:05 +08:00
|
|
|
|
2001-03-08 19:16:33 +08:00
|
|
|
int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (group->meth->invert == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(a, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return group->meth->invert(group, a, ctx);
|
|
|
|
}
|
2001-03-08 19:16:33 +08:00
|
|
|
|
2001-03-07 09:17:05 +08:00
|
|
|
int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (group->meth->is_at_infinity == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(point, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return group->meth->is_at_infinity(group, point);
|
|
|
|
}
|
|
|
|
|
2015-06-04 21:22:00 +08:00
|
|
|
/*
|
|
|
|
* Check whether an EC_POINT is on the curve or not. Note that the return
|
|
|
|
* value for this function should NOT be treated as a boolean. Return values:
|
|
|
|
* 1: The point is on the curve
|
|
|
|
* 0: The point is not on the curve
|
|
|
|
* -1: An error occurred
|
|
|
|
*/
|
2015-01-22 11:40:55 +08:00
|
|
|
int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
|
|
|
|
BN_CTX *ctx)
|
|
|
|
{
|
|
|
|
if (group->meth->is_on_curve == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(point, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return group->meth->is_on_curve(group, point, ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
|
|
|
|
BN_CTX *ctx)
|
|
|
|
{
|
|
|
|
if (group->meth->point_cmp == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(a, group) || !ec_point_is_compat(b, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return group->meth->point_cmp(group, a, b, ctx);
|
|
|
|
}
|
2001-03-08 19:16:33 +08:00
|
|
|
|
2020-05-19 22:48:36 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
2001-03-08 04:56:48 +08:00
|
|
|
int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (group->meth->make_affine == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(point, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return group->meth->make_affine(group, point, ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
|
|
|
|
EC_POINT *points[], BN_CTX *ctx)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (group->meth->points_make_affine == 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
for (i = 0; i < num; i++) {
|
2018-05-21 22:24:56 +08:00
|
|
|
if (!ec_point_is_compat(points[i], group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return group->meth->points_make_affine(group, num, points, ctx);
|
|
|
|
}
|
2020-05-19 22:48:36 +08:00
|
|
|
#endif
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Functions for point multiplication. If group->meth->mul is 0, we use the
|
|
|
|
* wNAF-based implementations in ec_mult.c; otherwise we dispatch through
|
|
|
|
* methods.
|
2003-02-07 03:25:12 +08:00
|
|
|
*/
|
|
|
|
|
2020-05-13 12:33:59 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
2003-02-07 03:25:12 +08:00
|
|
|
int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
|
2015-01-22 11:40:55 +08:00
|
|
|
size_t num, const EC_POINT *points[],
|
|
|
|
const BIGNUM *scalars[], BN_CTX *ctx)
|
|
|
|
{
|
2018-07-08 15:39:39 +08:00
|
|
|
int ret = 0;
|
|
|
|
size_t i = 0;
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2018-07-08 15:39:39 +08:00
|
|
|
BN_CTX *new_ctx = NULL;
|
2019-07-04 00:30:03 +08:00
|
|
|
#endif
|
|
|
|
|
2018-07-08 15:39:39 +08:00
|
|
|
if (!ec_point_is_compat(r, group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2018-07-08 15:39:39 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2020-04-06 16:41:36 +08:00
|
|
|
|
|
|
|
if (scalar == NULL && num == 0)
|
|
|
|
return EC_POINT_set_to_infinity(group, r);
|
|
|
|
|
2018-07-08 15:39:39 +08:00
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
if (!ec_point_is_compat(points[i], group)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2018-07-08 15:39:39 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-31 14:47:58 +08:00
|
|
|
if (ctx == NULL)
|
|
|
|
ctx = new_ctx = BN_CTX_secure_new();
|
|
|
|
#endif
|
|
|
|
if (ctx == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
|
2020-03-31 14:47:58 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-07-08 15:39:39 +08:00
|
|
|
if (group->meth->mul != NULL)
|
|
|
|
ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx);
|
|
|
|
else
|
2015-01-22 11:40:55 +08:00
|
|
|
/* use default */
|
2021-02-18 18:27:26 +08:00
|
|
|
ret = ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
|
2003-02-07 03:25:12 +08:00
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2018-07-08 15:39:39 +08:00
|
|
|
BN_CTX_free(new_ctx);
|
2019-07-04 00:30:03 +08:00
|
|
|
#endif
|
2018-07-08 15:39:39 +08:00
|
|
|
return ret;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2020-05-13 12:33:59 +08:00
|
|
|
#endif
|
2003-02-07 03:25:12 +08:00
|
|
|
|
|
|
|
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
|
2015-01-22 11:40:55 +08:00
|
|
|
const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
|
|
|
|
{
|
2020-05-13 12:33:59 +08:00
|
|
|
int ret = 0;
|
Fix coverity issues in EC after #11807
This should fix 2 issues detected by Coverity and introduced with
https://github.com/openssl/openssl/pull/11807
- CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
- CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
In practice the tests seem to show that they both aren't real issues,
yet I believe this small change should appease the scanner and at the
same time improve clarity for the reader.
Here is the original report:
```
** CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
________________________________________________________________________________________________________
*** CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
/crypto/ec/ec_lib.c: 1123 in EC_POINT_mul()
1117
1118 if (group->meth->mul != NULL)
1119 ret = group->meth->mul(group, r, g_scalar, point != NULL
1120 && p_scalar != NULL, &point, &p_scalar, ctx);
1121 else
1122 /* use default */
CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
Passing "&point" to function "ec_wNAF_mul" which uses it as an array. This might corrupt or misinterpret adjacent memory locations.
1123 ret = ec_wNAF_mul(group, r, g_scalar, point != NULL
1124 && p_scalar != NULL, &point, &p_scalar, ctx);
1125
1126 #ifndef FIPS_MODULE
1127 BN_CTX_free(new_ctx);
1128 #endif
** CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
________________________________________________________________________________________________________
*** CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
/crypto/ec/ec_lib.c: 1123 in EC_POINT_mul()
1117
1118 if (group->meth->mul != NULL)
1119 ret = group->meth->mul(group, r, g_scalar, point != NULL
1120 && p_scalar != NULL, &point, &p_scalar, ctx);
1121 else
1122 /* use default */
CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
Passing "&p_scalar" to function "ec_wNAF_mul" which uses it as an array. This might corrupt or misinterpret adjacent memory locations.
1123 ret = ec_wNAF_mul(group, r, g_scalar, point != NULL
1124 && p_scalar != NULL, &point, &p_scalar, ctx);
1125
1126 #ifndef FIPS_MODULE
1127 BN_CTX_free(new_ctx);
1128 #endif
```
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11919)
2020-05-23 00:50:17 +08:00
|
|
|
size_t num;
|
2020-05-13 12:33:59 +08:00
|
|
|
#ifndef FIPS_MODULE
|
|
|
|
BN_CTX *new_ctx = NULL;
|
|
|
|
#endif
|
2003-02-07 03:25:12 +08:00
|
|
|
|
2020-05-13 12:33:59 +08:00
|
|
|
if (!ec_point_is_compat(r, group)
|
|
|
|
|| (point != NULL && !ec_point_is_compat(point, group))) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
|
2020-05-13 12:33:59 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2003-02-07 03:25:12 +08:00
|
|
|
|
2020-05-13 12:33:59 +08:00
|
|
|
if (g_scalar == NULL && p_scalar == NULL)
|
|
|
|
return EC_POINT_set_to_infinity(group, r);
|
2003-02-07 03:25:12 +08:00
|
|
|
|
2020-05-13 12:33:59 +08:00
|
|
|
#ifndef FIPS_MODULE
|
|
|
|
if (ctx == NULL)
|
|
|
|
ctx = new_ctx = BN_CTX_secure_new();
|
|
|
|
#endif
|
|
|
|
if (ctx == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
|
2020-05-13 12:33:59 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Fix coverity issues in EC after #11807
This should fix 2 issues detected by Coverity and introduced with
https://github.com/openssl/openssl/pull/11807
- CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
- CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
In practice the tests seem to show that they both aren't real issues,
yet I believe this small change should appease the scanner and at the
same time improve clarity for the reader.
Here is the original report:
```
** CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
________________________________________________________________________________________________________
*** CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
/crypto/ec/ec_lib.c: 1123 in EC_POINT_mul()
1117
1118 if (group->meth->mul != NULL)
1119 ret = group->meth->mul(group, r, g_scalar, point != NULL
1120 && p_scalar != NULL, &point, &p_scalar, ctx);
1121 else
1122 /* use default */
CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
Passing "&point" to function "ec_wNAF_mul" which uses it as an array. This might corrupt or misinterpret adjacent memory locations.
1123 ret = ec_wNAF_mul(group, r, g_scalar, point != NULL
1124 && p_scalar != NULL, &point, &p_scalar, ctx);
1125
1126 #ifndef FIPS_MODULE
1127 BN_CTX_free(new_ctx);
1128 #endif
** CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
________________________________________________________________________________________________________
*** CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
/crypto/ec/ec_lib.c: 1123 in EC_POINT_mul()
1117
1118 if (group->meth->mul != NULL)
1119 ret = group->meth->mul(group, r, g_scalar, point != NULL
1120 && p_scalar != NULL, &point, &p_scalar, ctx);
1121 else
1122 /* use default */
CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
Passing "&p_scalar" to function "ec_wNAF_mul" which uses it as an array. This might corrupt or misinterpret adjacent memory locations.
1123 ret = ec_wNAF_mul(group, r, g_scalar, point != NULL
1124 && p_scalar != NULL, &point, &p_scalar, ctx);
1125
1126 #ifndef FIPS_MODULE
1127 BN_CTX_free(new_ctx);
1128 #endif
```
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11919)
2020-05-23 00:50:17 +08:00
|
|
|
num = (point != NULL && p_scalar != NULL) ? 1 : 0;
|
2020-05-13 12:33:59 +08:00
|
|
|
if (group->meth->mul != NULL)
|
Fix coverity issues in EC after #11807
This should fix 2 issues detected by Coverity and introduced with
https://github.com/openssl/openssl/pull/11807
- CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
- CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
In practice the tests seem to show that they both aren't real issues,
yet I believe this small change should appease the scanner and at the
same time improve clarity for the reader.
Here is the original report:
```
** CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
________________________________________________________________________________________________________
*** CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
/crypto/ec/ec_lib.c: 1123 in EC_POINT_mul()
1117
1118 if (group->meth->mul != NULL)
1119 ret = group->meth->mul(group, r, g_scalar, point != NULL
1120 && p_scalar != NULL, &point, &p_scalar, ctx);
1121 else
1122 /* use default */
CID 1463577: Memory - corruptions (ARRAY_VS_SINGLETON)
Passing "&point" to function "ec_wNAF_mul" which uses it as an array. This might corrupt or misinterpret adjacent memory locations.
1123 ret = ec_wNAF_mul(group, r, g_scalar, point != NULL
1124 && p_scalar != NULL, &point, &p_scalar, ctx);
1125
1126 #ifndef FIPS_MODULE
1127 BN_CTX_free(new_ctx);
1128 #endif
** CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
________________________________________________________________________________________________________
*** CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
/crypto/ec/ec_lib.c: 1123 in EC_POINT_mul()
1117
1118 if (group->meth->mul != NULL)
1119 ret = group->meth->mul(group, r, g_scalar, point != NULL
1120 && p_scalar != NULL, &point, &p_scalar, ctx);
1121 else
1122 /* use default */
CID 1463573: Memory - corruptions (ARRAY_VS_SINGLETON)
Passing "&p_scalar" to function "ec_wNAF_mul" which uses it as an array. This might corrupt or misinterpret adjacent memory locations.
1123 ret = ec_wNAF_mul(group, r, g_scalar, point != NULL
1124 && p_scalar != NULL, &point, &p_scalar, ctx);
1125
1126 #ifndef FIPS_MODULE
1127 BN_CTX_free(new_ctx);
1128 #endif
```
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11919)
2020-05-23 00:50:17 +08:00
|
|
|
ret = group->meth->mul(group, r, g_scalar, num, &point, &p_scalar, ctx);
|
2020-05-13 12:33:59 +08:00
|
|
|
else
|
|
|
|
/* use default */
|
2021-02-18 18:27:26 +08:00
|
|
|
ret = ossl_ec_wNAF_mul(group, r, g_scalar, num, &point, &p_scalar, ctx);
|
2020-05-13 12:33:59 +08:00
|
|
|
|
|
|
|
#ifndef FIPS_MODULE
|
|
|
|
BN_CTX_free(new_ctx);
|
|
|
|
#endif
|
|
|
|
return ret;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2003-02-07 03:25:12 +08:00
|
|
|
|
2020-05-17 21:09:00 +08:00
|
|
|
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
2003-02-07 03:25:12 +08:00
|
|
|
int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (group->meth->mul == 0)
|
|
|
|
/* use default */
|
2021-02-18 18:27:26 +08:00
|
|
|
return ossl_ec_wNAF_precompute_mult(group, ctx);
|
2003-02-07 03:25:12 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (group->meth->precompute_mult != 0)
|
|
|
|
return group->meth->precompute_mult(group, ctx);
|
|
|
|
else
|
|
|
|
return 1; /* nothing to do, so report success */
|
|
|
|
}
|
2003-02-07 03:25:12 +08:00
|
|
|
|
|
|
|
int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (group->meth->mul == 0)
|
|
|
|
/* use default */
|
2021-02-18 18:27:26 +08:00
|
|
|
return ossl_ec_wNAF_have_precompute_mult(group);
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
if (group->meth->have_precompute_mult != 0)
|
|
|
|
return group->meth->have_precompute_mult(group);
|
|
|
|
else
|
|
|
|
return 0; /* cannot tell whether precomputation has
|
|
|
|
* been performed */
|
|
|
|
}
|
2020-05-17 21:09:00 +08:00
|
|
|
#endif
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ec_precompute_mont_data sets |group->mont_data| from |group->order| and
|
|
|
|
* returns one on success. On error it returns zero.
|
|
|
|
*/
|
2017-12-30 22:08:31 +08:00
|
|
|
static int ec_precompute_mont_data(EC_GROUP *group)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-07-04 00:30:03 +08:00
|
|
|
BN_CTX *ctx = BN_CTX_new_ex(group->libctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
int ret = 0;
|
|
|
|
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_MONT_CTX_free(group->mont_data);
|
|
|
|
group->mont_data = NULL;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
|
|
|
if (ctx == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
group->mont_data = BN_MONT_CTX_new();
|
2015-10-30 19:12:26 +08:00
|
|
|
if (group->mont_data == NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) {
|
|
|
|
BN_MONT_CTX_free(group->mont_data);
|
|
|
|
group->mont_data = NULL;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
2015-05-01 09:37:06 +08:00
|
|
|
BN_CTX_free(ctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
return ret;
|
|
|
|
}
|
2016-01-06 02:06:03 +08:00
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2016-01-06 02:06:03 +08:00
|
|
|
int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
|
|
|
|
{
|
|
|
|
return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
|
|
|
|
{
|
|
|
|
return CRYPTO_get_ex_data(&key->ex_data, idx);
|
|
|
|
}
|
2019-07-04 00:30:03 +08:00
|
|
|
#endif
|
2016-02-29 01:47:06 +08:00
|
|
|
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_group_simple_order_bits(const EC_GROUP *group)
|
2016-02-29 01:47:06 +08:00
|
|
|
{
|
|
|
|
if (group->order == NULL)
|
|
|
|
return 0;
|
|
|
|
return BN_num_bits(group->order);
|
|
|
|
}
|
2017-12-30 22:08:31 +08:00
|
|
|
|
2018-04-27 22:45:51 +08:00
|
|
|
static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
|
2018-05-08 19:00:30 +08:00
|
|
|
const BIGNUM *x, BN_CTX *ctx)
|
2018-04-27 22:45:51 +08:00
|
|
|
{
|
2018-05-05 16:03:02 +08:00
|
|
|
BIGNUM *e = NULL;
|
2018-04-27 22:45:51 +08:00
|
|
|
int ret = 0;
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2019-07-04 00:30:03 +08:00
|
|
|
BN_CTX *new_ctx = NULL;
|
2020-03-31 14:47:58 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (group->mont_data == NULL)
|
|
|
|
return 0;
|
2018-04-27 22:45:51 +08:00
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2019-07-04 00:30:03 +08:00
|
|
|
if (ctx == NULL)
|
|
|
|
ctx = new_ctx = BN_CTX_secure_new();
|
|
|
|
#endif
|
|
|
|
if (ctx == NULL)
|
2018-05-08 19:00:30 +08:00
|
|
|
return 0;
|
|
|
|
|
2018-04-27 22:45:51 +08:00
|
|
|
BN_CTX_start(ctx);
|
2018-05-05 16:03:02 +08:00
|
|
|
if ((e = BN_CTX_get(ctx)) == NULL)
|
2018-04-27 22:45:51 +08:00
|
|
|
goto err;
|
|
|
|
|
2018-05-08 19:00:30 +08:00
|
|
|
/*-
|
|
|
|
* We want inverse in constant time, therefore we utilize the fact
|
|
|
|
* order must be prime and use Fermats Little Theorem instead.
|
|
|
|
*/
|
|
|
|
if (!BN_set_word(e, 2))
|
|
|
|
goto err;
|
|
|
|
if (!BN_sub(e, group->order, e))
|
|
|
|
goto err;
|
|
|
|
/*-
|
|
|
|
* Exponent e is public.
|
|
|
|
* No need for scatter-gather or BN_FLG_CONSTTIME.
|
|
|
|
*/
|
|
|
|
if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data))
|
|
|
|
goto err;
|
2018-04-27 22:45:51 +08:00
|
|
|
|
2018-05-08 19:00:30 +08:00
|
|
|
ret = 1;
|
2018-04-27 22:45:51 +08:00
|
|
|
|
|
|
|
err:
|
2019-03-19 07:58:09 +08:00
|
|
|
BN_CTX_end(ctx);
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2018-04-27 22:45:51 +08:00
|
|
|
BN_CTX_free(new_ctx);
|
2019-07-04 00:30:03 +08:00
|
|
|
#endif
|
2018-04-27 22:45:51 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-05-08 19:00:30 +08:00
|
|
|
/*-
|
|
|
|
* Default behavior, if group->meth->field_inverse_mod_ord is NULL:
|
|
|
|
* - When group->order is even, this function returns an error.
|
|
|
|
* - When group->order is otherwise composite, the correctness
|
|
|
|
* of the output is not guaranteed.
|
|
|
|
* - When x is outside the range [1, group->order), the correctness
|
|
|
|
* of the output is not guaranteed.
|
|
|
|
* - Otherwise, this function returns the multiplicative inverse in the
|
|
|
|
* range [1, group->order).
|
|
|
|
*
|
|
|
|
* EC_METHODs must implement their own field_inverse_mod_ord for
|
|
|
|
* other functionality.
|
|
|
|
*/
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
|
|
|
|
const BIGNUM *x, BN_CTX *ctx)
|
2017-12-30 22:08:31 +08:00
|
|
|
{
|
|
|
|
if (group->meth->field_inverse_mod_ord != NULL)
|
|
|
|
return group->meth->field_inverse_mod_ord(group, res, x, ctx);
|
|
|
|
else
|
2018-04-27 22:45:51 +08:00
|
|
|
return ec_field_inverse_mod_ord(group, res, x, ctx);
|
2017-12-30 22:08:31 +08:00
|
|
|
}
|
Implement coordinate blinding for EC_POINT
This commit implements coordinate blinding, i.e., it randomizes the
representative of an elliptic curve point in its equivalence class, for
prime curves implemented through EC_GFp_simple_method,
EC_GFp_mont_method, and EC_GFp_nist_method.
This commit is derived from the patch
https://marc.info/?l=openssl-dev&m=131194808413635 by Billy Brumley.
Coordinate blinding is a generally useful side-channel countermeasure
and is (mostly) free. The function itself takes a few field
multiplicationss, but is usually only necessary at the beginning of a
scalar multiplication (as implemented in the patch). When used this way,
it makes the values that variables take (i.e., field elements in an
algorithm state) unpredictable.
For instance, this mitigates chosen EC point side-channel attacks for
settings such as ECDH and EC private key decryption, for the
aforementioned curves.
For EC_METHODs using different coordinate representations this commit
does nothing, but the corresponding coordinate blinding function can be
easily added in the future to extend these changes to such curves.
Co-authored-by: Nicola Tuveri <nic.tuv@gmail.com>
Co-authored-by: Billy Brumley <bbrumley@gmail.com>
Reviewed-by: Andy Polyakov <appro@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6501)
2018-06-16 22:07:40 +08:00
|
|
|
|
|
|
|
/*-
|
|
|
|
* Coordinate blinding for EC_POINT.
|
|
|
|
*
|
|
|
|
* The underlying EC_METHOD can optionally implement this function:
|
|
|
|
* underlying implementations should return 0 on errors, or 1 on
|
|
|
|
* success.
|
|
|
|
*
|
|
|
|
* This wrapper returns 1 in case the underlying EC_METHOD does not
|
|
|
|
* support coordinate blinding.
|
|
|
|
*/
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
|
|
|
|
BN_CTX *ctx)
|
Implement coordinate blinding for EC_POINT
This commit implements coordinate blinding, i.e., it randomizes the
representative of an elliptic curve point in its equivalence class, for
prime curves implemented through EC_GFp_simple_method,
EC_GFp_mont_method, and EC_GFp_nist_method.
This commit is derived from the patch
https://marc.info/?l=openssl-dev&m=131194808413635 by Billy Brumley.
Coordinate blinding is a generally useful side-channel countermeasure
and is (mostly) free. The function itself takes a few field
multiplicationss, but is usually only necessary at the beginning of a
scalar multiplication (as implemented in the patch). When used this way,
it makes the values that variables take (i.e., field elements in an
algorithm state) unpredictable.
For instance, this mitigates chosen EC point side-channel attacks for
settings such as ECDH and EC private key decryption, for the
aforementioned curves.
For EC_METHODs using different coordinate representations this commit
does nothing, but the corresponding coordinate blinding function can be
easily added in the future to extend these changes to such curves.
Co-authored-by: Nicola Tuveri <nic.tuv@gmail.com>
Co-authored-by: Billy Brumley <bbrumley@gmail.com>
Reviewed-by: Andy Polyakov <appro@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6501)
2018-06-16 22:07:40 +08:00
|
|
|
{
|
|
|
|
if (group->meth->blind_coordinates == NULL)
|
|
|
|
return 1; /* ignore if not implemented */
|
|
|
|
|
|
|
|
return group->meth->blind_coordinates(group, p, ctx);
|
|
|
|
}
|
2020-08-22 12:55:41 +08:00
|
|
|
|
|
|
|
int EC_GROUP_get_basis_type(const EC_GROUP *group)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field)
|
|
|
|
/* everything else is currently not supported */
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Find the last non-zero element of group->poly[] */
|
|
|
|
for (i = 0;
|
|
|
|
i < (int)OSSL_NELEM(group->poly) && group->poly[i] != 0;
|
|
|
|
i++)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (i == 4)
|
|
|
|
return NID_X9_62_ppBasis;
|
|
|
|
else if (i == 2)
|
|
|
|
return NID_X9_62_tpBasis;
|
|
|
|
else
|
|
|
|
/* everything else is currently not supported */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef OPENSSL_NO_EC2M
|
|
|
|
int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
|
|
|
|
{
|
|
|
|
if (group == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field
|
|
|
|
|| !((group->poly[0] != 0) && (group->poly[1] != 0)
|
|
|
|
&& (group->poly[2] == 0))) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2020-08-22 12:55:41 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (k)
|
|
|
|
*k = group->poly[1];
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
|
|
|
|
unsigned int *k2, unsigned int *k3)
|
|
|
|
{
|
|
|
|
if (group == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field
|
|
|
|
|| !((group->poly[0] != 0) && (group->poly[1] != 0)
|
|
|
|
&& (group->poly[2] != 0) && (group->poly[3] != 0)
|
|
|
|
&& (group->poly[4] == 0))) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
2020-08-22 12:55:41 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (k1)
|
|
|
|
*k1 = group->poly[3];
|
|
|
|
if (k2)
|
|
|
|
*k2 = group->poly[2];
|
|
|
|
if (k3)
|
|
|
|
*k3 = group->poly[1];
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if the explicit parameters group matches any built-in curves.
|
|
|
|
*
|
|
|
|
* We create a copy of the group just built, so that we can remove optional
|
|
|
|
* fields for the lookup: we do this to avoid the possibility that one of
|
|
|
|
* the optional parameters is used to force the library into using a less
|
|
|
|
* performant and less secure EC_METHOD instead of the specialized one.
|
|
|
|
* In any case, `seed` is not really used in any computation, while a
|
|
|
|
* cofactor different from the one in the built-in table is just
|
|
|
|
* mathematically wrong anyway and should not be used.
|
|
|
|
*/
|
|
|
|
static EC_GROUP *ec_group_explicit_to_named(const EC_GROUP *group,
|
2020-10-15 17:55:50 +08:00
|
|
|
OSSL_LIB_CTX *libctx,
|
2020-08-22 12:55:41 +08:00
|
|
|
const char *propq,
|
|
|
|
BN_CTX *ctx)
|
|
|
|
{
|
|
|
|
EC_GROUP *ret_group = NULL, *dup = NULL;
|
|
|
|
int curve_name_nid;
|
|
|
|
|
|
|
|
const EC_POINT *point = EC_GROUP_get0_generator(group);
|
|
|
|
const BIGNUM *order = EC_GROUP_get0_order(group);
|
|
|
|
int no_seed = (EC_GROUP_get0_seed(group) == NULL);
|
|
|
|
|
|
|
|
if ((dup = EC_GROUP_dup(group)) == NULL
|
|
|
|
|| EC_GROUP_set_seed(dup, NULL, 0) != 1
|
|
|
|
|| !EC_GROUP_set_generator(dup, point, order, NULL))
|
|
|
|
goto err;
|
2021-02-18 18:27:26 +08:00
|
|
|
if ((curve_name_nid = ossl_ec_curve_nid_from_params(dup, ctx)) != NID_undef) {
|
2020-08-22 12:55:41 +08:00
|
|
|
/*
|
|
|
|
* The input explicit parameters successfully matched one of the
|
|
|
|
* built-in curves: often for built-in curves we have specialized
|
|
|
|
* methods with better performance and hardening.
|
|
|
|
*
|
|
|
|
* In this case we replace the `EC_GROUP` created through explicit
|
|
|
|
* parameters with one created from a named group.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
|
|
|
|
/*
|
|
|
|
* NID_wap_wsg_idm_ecid_wtls12 and NID_secp224r1 are both aliases for
|
|
|
|
* the same curve, we prefer the SECP nid when matching explicit
|
|
|
|
* parameters as that is associated with a specialized EC_METHOD.
|
|
|
|
*/
|
|
|
|
if (curve_name_nid == NID_wap_wsg_idm_ecid_wtls12)
|
|
|
|
curve_name_nid = NID_secp224r1;
|
|
|
|
#endif /* !def(OPENSSL_NO_EC_NISTP_64_GCC_128) */
|
|
|
|
|
2020-09-24 17:42:23 +08:00
|
|
|
ret_group = EC_GROUP_new_by_curve_name_ex(libctx, propq, curve_name_nid);
|
2020-08-22 12:55:41 +08:00
|
|
|
if (ret_group == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the flag so that EC_GROUPs created from explicit parameters are
|
|
|
|
* serialized using explicit parameters by default.
|
|
|
|
*/
|
|
|
|
EC_GROUP_set_asn1_flag(ret_group, OPENSSL_EC_EXPLICIT_CURVE);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the input params do not contain the optional seed field we make
|
|
|
|
* sure it is not added to the returned group.
|
|
|
|
*
|
|
|
|
* The seed field is not really used inside libcrypto anyway, and
|
|
|
|
* adding it to parsed explicit parameter keys would alter their DER
|
|
|
|
* encoding output (because of the extra field) which could impact
|
|
|
|
* applications fingerprinting keys by their DER encoding.
|
|
|
|
*/
|
|
|
|
if (no_seed) {
|
|
|
|
if (EC_GROUP_set_seed(ret_group, NULL, 0) != 1)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret_group = (EC_GROUP *)group;
|
|
|
|
}
|
|
|
|
EC_GROUP_free(dup);
|
|
|
|
return ret_group;
|
|
|
|
err:
|
|
|
|
EC_GROUP_free(dup);
|
|
|
|
EC_GROUP_free(ret_group);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static EC_GROUP *group_new_from_name(const OSSL_PARAM *p,
|
2020-10-15 17:55:50 +08:00
|
|
|
OSSL_LIB_CTX *libctx, const char *propq)
|
2020-08-22 12:55:41 +08:00
|
|
|
{
|
|
|
|
int ok = 0, nid;
|
|
|
|
const char *curve_name = NULL;
|
|
|
|
|
|
|
|
switch (p->data_type) {
|
|
|
|
case OSSL_PARAM_UTF8_STRING:
|
|
|
|
/* The OSSL_PARAM functions have no support for this */
|
|
|
|
curve_name = p->data;
|
|
|
|
ok = (curve_name != NULL);
|
|
|
|
break;
|
|
|
|
case OSSL_PARAM_UTF8_PTR:
|
|
|
|
ok = OSSL_PARAM_get_utf8_ptr(p, &curve_name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ok) {
|
2021-02-18 18:27:26 +08:00
|
|
|
nid = ossl_ec_curve_name2nid(curve_name);
|
2020-08-22 12:55:41 +08:00
|
|
|
if (nid == NID_undef) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
|
2020-08-22 12:55:41 +08:00
|
|
|
return NULL;
|
|
|
|
} else {
|
2020-09-24 17:42:23 +08:00
|
|
|
return EC_GROUP_new_by_curve_name_ex(libctx, propq, nid);
|
2020-08-22 12:55:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-10-15 11:41:59 +08:00
|
|
|
/* These parameters can be set directly into an EC_GROUP */
|
2021-02-18 18:27:26 +08:00
|
|
|
int ossl_ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[])
|
2020-10-15 11:41:59 +08:00
|
|
|
{
|
|
|
|
int encoding_flag = -1, format = -1;
|
|
|
|
const OSSL_PARAM *p;
|
|
|
|
|
|
|
|
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT);
|
|
|
|
if (p != NULL) {
|
2021-02-18 18:27:26 +08:00
|
|
|
if (!ossl_ec_pt_format_param2id(p, &format)) {
|
2020-10-15 11:41:59 +08:00
|
|
|
ECerr(0, EC_R_INVALID_FORM);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EC_GROUP_set_point_conversion_form(group, format);
|
|
|
|
}
|
|
|
|
|
|
|
|
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING);
|
|
|
|
if (p != NULL) {
|
2021-02-18 18:27:26 +08:00
|
|
|
if (!ossl_ec_encoding_param2id(p, &encoding_flag)) {
|
2020-10-15 11:41:59 +08:00
|
|
|
ECerr(0, EC_R_INVALID_FORM);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EC_GROUP_set_asn1_flag(group, encoding_flag);
|
|
|
|
}
|
|
|
|
/* Optional seed */
|
|
|
|
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
|
|
|
|
if (p != NULL) {
|
|
|
|
/* The seed is allowed to be NULL */
|
|
|
|
if (p->data_type != OSSL_PARAM_OCTET_STRING
|
|
|
|
|| !EC_GROUP_set_seed(group, p->data, p->data_size)) {
|
|
|
|
ECerr(0, EC_R_INVALID_SEED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-08-22 12:55:41 +08:00
|
|
|
EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
|
2020-10-15 17:55:50 +08:00
|
|
|
OSSL_LIB_CTX *libctx, const char *propq)
|
2020-08-22 12:55:41 +08:00
|
|
|
{
|
|
|
|
const OSSL_PARAM *ptmp, *pa, *pb;
|
|
|
|
int ok = 0;
|
|
|
|
EC_GROUP *group = NULL, *named_group = NULL;
|
|
|
|
BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL, *cofactor = NULL;
|
|
|
|
EC_POINT *point = NULL;
|
|
|
|
int field_bits = 0;
|
|
|
|
int is_prime_field = 1;
|
|
|
|
BN_CTX *bnctx = NULL;
|
|
|
|
const unsigned char *buf = NULL;
|
|
|
|
int encoding_flag = -1;
|
|
|
|
|
2020-10-15 11:41:59 +08:00
|
|
|
/* This is the simple named group case */
|
2020-08-22 12:55:41 +08:00
|
|
|
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
|
|
|
|
if (ptmp != NULL) {
|
|
|
|
group = group_new_from_name(ptmp, libctx, propq);
|
2020-10-15 11:41:59 +08:00
|
|
|
if (group != NULL) {
|
2021-02-18 18:27:26 +08:00
|
|
|
if (!ossl_ec_group_set_params(group, params)) {
|
2020-10-15 11:41:59 +08:00
|
|
|
EC_GROUP_free(group);
|
|
|
|
group = NULL;
|
|
|
|
}
|
|
|
|
}
|
2020-08-22 12:55:41 +08:00
|
|
|
return group;
|
|
|
|
}
|
2020-10-15 11:41:59 +08:00
|
|
|
/* If it gets here then we are trying explicit parameters */
|
2020-08-22 12:55:41 +08:00
|
|
|
bnctx = BN_CTX_new_ex(libctx);
|
|
|
|
if (bnctx == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
2020-08-22 12:55:41 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
BN_CTX_start(bnctx);
|
|
|
|
|
|
|
|
p = BN_CTX_get(bnctx);
|
|
|
|
a = BN_CTX_get(bnctx);
|
|
|
|
b = BN_CTX_get(bnctx);
|
|
|
|
order = BN_CTX_get(bnctx);
|
|
|
|
if (order == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE);
|
|
|
|
if (ptmp == NULL || ptmp->data_type != OSSL_PARAM_UTF8_STRING) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (strcasecmp(ptmp->data, SN_X9_62_prime_field) == 0) {
|
|
|
|
is_prime_field = 1;
|
|
|
|
} else if (strcasecmp(ptmp->data, SN_X9_62_characteristic_two_field) == 0) {
|
|
|
|
is_prime_field = 0;
|
|
|
|
} else {
|
|
|
|
/* Invalid field */
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
pa = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_A);
|
|
|
|
if (!OSSL_PARAM_get_BN(pa, &a)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_A);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
pb = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_B);
|
|
|
|
if (!OSSL_PARAM_get_BN(pb, &b)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_B);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* extract the prime number or irreducible polynomial */
|
|
|
|
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_P);
|
|
|
|
if (!OSSL_PARAM_get_BN(ptmp, &p)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_P);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_prime_field) {
|
|
|
|
if (BN_is_negative(p) || BN_is_zero(p)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_P);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
field_bits = BN_num_bits(p);
|
|
|
|
if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create the EC_GROUP structure */
|
|
|
|
group = EC_GROUP_new_curve_GFp(p, a, b, bnctx);
|
|
|
|
} else {
|
|
|
|
#ifdef OPENSSL_NO_EC2M
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
#else
|
|
|
|
/* create the EC_GROUP structure */
|
|
|
|
group = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
|
|
|
|
if (group != NULL) {
|
|
|
|
field_bits = EC_GROUP_get_degree(group);
|
|
|
|
if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* OPENSSL_NO_EC2M */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Optional seed */
|
|
|
|
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
|
|
|
|
if (ptmp != NULL) {
|
|
|
|
if (ptmp->data_type != OSSL_PARAM_OCTET_STRING) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_SEED);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (!EC_GROUP_set_seed(group, ptmp->data, ptmp->data_size))
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* generator base point */
|
|
|
|
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GENERATOR);
|
|
|
|
if (ptmp == NULL
|
|
|
|
|| ptmp->data_type != OSSL_PARAM_OCTET_STRING) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
buf = (const unsigned char *)(ptmp->data);
|
|
|
|
if ((point = EC_POINT_new(group)) == NULL)
|
|
|
|
goto err;
|
|
|
|
EC_GROUP_set_point_conversion_form(group,
|
|
|
|
(point_conversion_form_t)buf[0] & ~0x01);
|
|
|
|
if (!EC_POINT_oct2point(group, point, buf, ptmp->data_size, bnctx)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* order */
|
|
|
|
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ORDER);
|
|
|
|
if (!OSSL_PARAM_get_BN(ptmp, &order)
|
|
|
|
|| (BN_is_negative(order) || BN_is_zero(order))
|
|
|
|
|| (BN_num_bits(order) > (int)field_bits + 1)) { /* Hasse bound */
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Optional cofactor */
|
|
|
|
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_COFACTOR);
|
|
|
|
if (ptmp != NULL) {
|
|
|
|
cofactor = BN_CTX_get(bnctx);
|
|
|
|
if (cofactor == NULL || !OSSL_PARAM_get_BN(ptmp, &cofactor)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_COFACTOR);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set the generator, order and cofactor (if present) */
|
|
|
|
if (!EC_GROUP_set_generator(group, point, order, cofactor)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
named_group = ec_group_explicit_to_named(group, libctx, propq, bnctx);
|
|
|
|
if (named_group == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_NAMED_GROUP_CONVERSION);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (named_group == group) {
|
|
|
|
/*
|
|
|
|
* If we did not find a named group then the encoding should be explicit
|
|
|
|
* if it was specified
|
|
|
|
*/
|
2020-10-15 11:41:59 +08:00
|
|
|
ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING);
|
|
|
|
if (ptmp != NULL
|
2021-02-18 18:27:26 +08:00
|
|
|
&& !ossl_ec_encoding_param2id(ptmp, &encoding_flag)) {
|
2022-01-05 23:17:53 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
|
|
|
|
goto err;
|
2020-10-15 11:41:59 +08:00
|
|
|
}
|
2020-08-22 12:55:41 +08:00
|
|
|
if (encoding_flag == OPENSSL_EC_NAMED_CURVE) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
|
2020-08-22 12:55:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE);
|
|
|
|
} else {
|
|
|
|
EC_GROUP_free(group);
|
|
|
|
group = named_group;
|
|
|
|
}
|
|
|
|
ok = 1;
|
|
|
|
err:
|
|
|
|
if (!ok) {
|
|
|
|
EC_GROUP_free(group);
|
|
|
|
group = NULL;
|
|
|
|
}
|
|
|
|
EC_POINT_free(point);
|
|
|
|
BN_CTX_end(bnctx);
|
|
|
|
BN_CTX_free(bnctx);
|
|
|
|
|
|
|
|
return group;
|
|
|
|
}
|