add extra ec

This commit is contained in:
Zhi Guan
2017-02-15 16:08:27 +08:00
parent c04b2060af
commit 5d5ea22fa7
22 changed files with 2695 additions and 3 deletions

497
crypto/ec2/bn_gfp2.c Normal file
View File

@@ -0,0 +1,497 @@
/* ====================================================================
* Copyright (c) 2016 The GmSSL 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 GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 file implement complex number over prime field
* a = a0 + a1 * i, i^2 == -1
* most of the routines should be replaced by macros
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn_gfp2.h>
/*
* to make it simple, currently both a0 and a1 will be inited
*/
BN_GFP2 *BN_GFP2_new(void)
{
int e = 1;
BN_GFP2 *ret = NULL;
if (!(ret = OPENSSL_malloc(sizeof(BN_GFP2)))) {
BNerr(BN_F_BN_GFP2_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->a0 = BN_new();
ret->a1 = BN_new();
if (!ret->a0 || !ret->a1) {
BNerr(BN_F_BN_GFP2_NEW, ERR_R_MALLOC_FAILURE);
goto end;
}
BN_zero(ret->a0);
BN_zero(ret->a1);
e = 0;
end:
if (e && ret) {
BN_GFP2_free(ret);
ret = NULL;
}
return ret;
}
void BN_GFP2_free(BN_GFP2 *a)
{
if (a) {
BN_free(a->a0);
BN_free(a->a1);
OPENSSL_free(a);
}
}
int BN_GFP2_copy(BN_GFP2 *r, const BN_GFP2 *a)
{
if (!r || !r->a0 || !r->a1 || !a || !a->a0 || !a->a1) {
BNerr(BN_F_BN_GFP2_COPY, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (!BN_copy(r->a0, a->a0)) {
BNerr(BN_F_BN_GFP2_COPY, ERR_R_BN_LIB);
return 0;
}
if (!BN_copy(r->a1, a->a1)) {
BNerr(BN_F_BN_GFP2_COPY, ERR_R_BN_LIB);
return 0;
}
return 1;
}
int BN_GFP2_zero(BN_GFP2 *a)
{
if (!a || !a->a0 || !a->a1) {
BNerr(BN_F_BN_GFP2_ZERO, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
BN_zero(a->a0);
BN_zero(a->a1);
return 1;
}
int BN_GFP2_one(BN_GFP2 *a)
{
if (!a || !a->a0 || !a->a1) {
BNerr(BN_F_BN_GFP2_ONE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
BN_one(a->a0);
BN_zero(a->a1);
return 1;
}
/* return 1 on success, so dont use !BN_GFP2_is_zero() to check return value */
int BN_GFP2_is_zero(const BN_GFP2 *a)
{
if (!a || !a->a0 || !a->a1) {
BNerr(BN_F_BN_GFP2_IS_ZERO, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
return (BN_is_zero(a->a0) && BN_is_zero(a->a1));
}
/*
* can we compare values on F_p^2 ?
*/
int BN_GFP2_cmp(const BN_GFP2 *a, const BN_GFP2 *b)
{
if (!a || !b || !a->a0 || !a->a1 || !b->a0 || !b->a1) {
BNerr(BN_F_BN_GFP2_CMP, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
return ((BN_cmp(a->a0, b->a0) == 0) && (BN_cmp(a->a1, b->a1) == 0));
}
int BN_GFP2_add(BN_GFP2 *r, const BN_GFP2 *a, const BN_GFP2 *b,
const BIGNUM *p, BN_CTX *ctx)
{
if (!a || !b || !a->a0 || !a->a1 || !b->a0 || !b->a1 || !p || !ctx) {
BNerr(BN_F_BN_GFP2_ADD, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (!BN_mod_add(r->a0, a->a0, b->a0, p, ctx)) {
BNerr(BN_F_BN_GFP2_ADD, ERR_R_BN_LIB);
return 0;
}
if (!BN_mod_add(r->a1, a->a1, b->a1, p, ctx)) {
BNerr(BN_F_BN_GFP2_ADD, ERR_R_BN_LIB);
return 0;
}
return 1;
}
int BN_GFP2_sub(BN_GFP2 *r, const BN_GFP2 *a, const BN_GFP2 *b,
const BIGNUM *p, BN_CTX *ctx)
{
if (!a || !b || !a->a0 || !a->a1 || !b->a0 || !b->a1 || !p || !ctx) {
BNerr(BN_F_BN_GFP2_SUB, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (!BN_mod_sub(r->a0, a->a0, b->a0, p, ctx)) {
BNerr(BN_F_BN_GFP2_SUB, ERR_R_BN_LIB);
return 0;
}
if (!BN_mod_sub(r->a1, a->a1, b->a1, p, ctx)) {
BNerr(BN_F_BN_GFP2_SUB, ERR_R_BN_LIB);
return 0;
}
return 1;
}
/*
* (a0 + a1 * i) * (b0 + b1 * i)
* = a0 * b0 + a1 * b1 * i^2 + (a0 * b1 + a1 * b0) * i
* = (a0 * b0 - a1 * b1) + (a0 * b1 + a1 * b0) * i
*/
int BN_GFP2_mul(BN_GFP2 *r, const BN_GFP2 *a, const BN_GFP2 *b,
const BIGNUM *p, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *t = NULL;
BN_CTX_start(ctx);
if (!(t = BN_CTX_get(ctx))) {
BNerr(BN_F_BN_GFP2_MUL, ERR_R_BN_LIB);
goto end;
}
/* r->a0 = a->a0 * b->a0 - a->a1 * b->a1 (mod p) */
if (!BN_mod_mul(r->a0, a->a0, b->a0, p, ctx)) {
BNerr(BN_F_BN_GFP2_MUL, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_mul(t, a->a1, b->a1, p, ctx)) {
BNerr(BN_F_BN_GFP2_MUL, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_sub(r->a0, r->a0, t, p, ctx)) {
BNerr(BN_F_BN_GFP2_MUL, ERR_R_BN_LIB);
goto end;
}
/* r->a1 = a->a0 * b->a1 + a->a1 * b->a0 (mod p) */
if (!BN_mod_mul(r->a1, a->a0, b->a1, p, ctx)) {
BNerr(BN_F_BN_GFP2_MUL, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_mul(t, a->a1, b->a0, p, ctx)) {
BNerr(BN_F_BN_GFP2_MUL, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_add(r->a1, r->a1, t, p, ctx)) {
BNerr(BN_F_BN_GFP2_MUL, ERR_R_BN_LIB);
goto end;
}
ret = 1;
end:
BN_CTX_end(ctx);
return ret;
}
int BN_GFP2_sqr(BN_GFP2 *r, const BN_GFP2 *a,
const BIGNUM *p, BN_CTX *ctx)
{
return BN_GFP2_mul(r, a, a, p, ctx);
}
/*
* (a0 + a1 * i) * (a0 - a1 * i)
* = a0^2 - a1^2 * i^2
* = a0^2 + a1^2
* ==> (a0 + a1 * i) * (a0 - a1 * i) * (a0^2 + a1^2)^-1 == 1
* ==> (a0 + a1 * i)^-1 == (a0 - a1 * i) * (a0^2 + a1^2)^-1
*/
int BN_GFP2_inv(BN_GFP2 *r, const BN_GFP2 *a, const BIGNUM *p, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *t = NULL;
BN_CTX_start(ctx);
if (!(t = BN_CTX_get(ctx))) {
BNerr(BN_F_BN_GFP2_INV, ERR_R_BN_LIB);
goto end;
}
/* t = (a0^2 + a1^2)^-1 */
if (!BN_mod_sqr(r->a0, a->a0, p, ctx)) {
BNerr(BN_F_BN_GFP2_INV, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_sqr(r->a1, a->a1, p, ctx)) {
BNerr(BN_F_BN_GFP2_INV, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_mul(t, r->a0, r->a1, p, ctx)) {
BNerr(BN_F_BN_GFP2_INV, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_inverse(t, t, p, ctx)) {
BNerr(BN_F_BN_GFP2_INV, ERR_R_BN_LIB);
goto end;
}
/* r0 = a0^ t (mod p) */
if (!BN_mod_mul(r->a0, a->a0, t, p, ctx)) {
BNerr(BN_F_BN_GFP2_INV, ERR_R_BN_LIB);
goto end;
}
/* r1 = p - a1^t (mod p) */
if (!BN_mod_mul(r->a1, a->a1, t, p, ctx)) {
BNerr(BN_F_BN_GFP2_INV, ERR_R_BN_LIB);
goto end;
}
if (!BN_sub(r->a1, p, r->a1)) {
BNerr(BN_F_BN_GFP2_INV, ERR_R_BN_LIB);
goto end;
}
ret = 1;
end:
BN_CTX_end(ctx);
return ret;
}
int BN_GFP2_div(BN_GFP2 *r, const BN_GFP2 *a, const BN_GFP2 *b, const BIGNUM *p, BN_CTX *ctx)
{
if (!BN_GFP2_inv(r, b, p, ctx)) {
return 0;
}
if (!BN_GFP2_mul(r, a, r, p, ctx)) {
return 0;
}
return 1;
}
/* need a fast implementation. check if k is solinas */
int BN_GFP2_exp(BN_GFP2 *r, const BN_GFP2 *a, const BIGNUM *k, const BIGNUM *p,
BN_CTX *ctx)
{
return 0;
}
int BN_GFP2_set_bn(BN_GFP2 *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
{
if (!r || !a || !p) {
BNerr(BN_F_BN_GFP2_SET_BN, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (!BN_copy(r->a0, a)) {
BNerr(BN_F_BN_GFP2_SET_BN, ERR_R_BN_LIB);
return 0;
}
if (!BN_zero(r->a1)) {
BNerr(BN_F_BN_GFP2_SET_BN, ERR_R_BN_LIB);
return 0;
}
return 1;
}
int BN_GFP2_add_bn(BN_GFP2 *r, const BN_GFP2 *a, const BIGNUM *b,
const BIGNUM *p, BN_CTX *ctx)
{
return BN_mod_add(r->a0, a->a0, b, p, ctx);
}
int BN_GFP2_sub_bn(BN_GFP2 *r, const BN_GFP2 *a, const BIGNUM *b,
const BIGNUM *p, BN_CTX *ctx)
{
return BN_mod_sub(r->a0, a->a0, b, p, ctx);
}
int BN_GFP2_mul_bn(BN_GFP2 *r, const BN_GFP2 *a, const BIGNUM *b,
const BIGNUM *p, BN_CTX *ctx)
{
return BN_mod_mul(r->a0, a->a0, b, p, ctx);
}
int BN_GFP2_div_bn(BN_GFP2 *r, const BN_GFP2 *a, const BIGNUM *b,
const BIGNUM *p, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *binv;
if (!(binv = BN_CTX_get(ctx))) {
BNerr(BN_F_BN_GFP2_DIV_BN, ERR_R_MALLOC_FAILURE);
goto end;
}
if (!BN_mod_inverse(binv, b, p, ctx)) {
BNerr(BN_F_BN_GFP2_DIV_BN, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_mul(r->a0, a->a0, binv, p, ctx)) {
BNerr(BN_F_BN_GFP2_DIV_BN, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_mul(r->a1, a->a1, binv, p, ctx)) {
BNerr(BN_F_BN_GFP2_DIV_BN, ERR_R_BN_LIB);
goto end;
}
ret = 1;
end:
BN_CTX_end(ctx);
return ret;
}
int BN_GFP2_canonical(const BN_GFP2 *a, unsigned char *out, size_t *outlen,
int order, const BIGNUM *p, BN_CTX *ctx)
{
size_t len;
if (!a || !a->a0 || !a->a1 || !outlen || !p) {
BNerr(BN_F_BN_GFP2_CANONICAL, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
len = BN_num_bytes(p) * 2;
if (!out) {
*outlen = len;
return 1;
}
if (*outlen < len) {
BNerr(BN_F_BN_GFP2_CANONICAL, BN_R_BUFFER_TOO_SMALL);
return 0;
}
memset(out, 0, len);
if (order == 0) {
/* low order first output (a0, a1) */
if (!BN_bn2bin(a->a0, out + len/2 - BN_num_bytes(a->a0))) {
BNerr(BN_F_BN_GFP2_CANONICAL, ERR_R_BN_LIB);
return 0;
}
if (!BN_bn2bin(a->a1, out + len - BN_num_bytes(a->a1))) {
BNerr(BN_F_BN_GFP2_CANONICAL, ERR_R_BN_LIB);
return 0;
}
} else {
/* high order first output (a1, a0) */
if (!BN_bn2bin(a->a1, out + len/2 - BN_num_bytes(a->a1))) {
BNerr(BN_F_BN_GFP2_CANONICAL, ERR_R_BN_LIB);
return 0;
}
if (!BN_bn2bin(a->a0, out + len - BN_num_bytes(a->a0))) {
BNerr(BN_F_BN_GFP2_CANONICAL, ERR_R_BN_LIB);
return 0;
}
}
*outlen = len;
return 1;
}
int BN_bn2gfp2(const BIGNUM *bn, BN_GFP2 *gfp2, const BIGNUM *p, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *a;
if (!(a = BN_CTX_get(ctx))) {
goto end;
}
BN_one(a);
if (!BN_lshift(a, a, BN_num_bytes(p)*8)) {
goto end;
}
if (!BN_rshift(gfp2->a1, bn, BN_num_bytes(p)*8)) {
goto end;
}
if (!BN_mod(gfp2->a0, bn, a, ctx)) {
goto end;
}
ret = 1;
end:
BN_CTX_end(ctx);
return ret;
}
/* return (a0 + a1 << 2^n), n = log_2(p), n % 8 == 0 */
int BN_gfp22bn(const BN_GFP2 *gfp2, BIGNUM *bn, const BIGNUM *p, BN_CTX *ctx)
{
if (!BN_lshift(bn, gfp2->a1, BN_num_bytes(p) * 8)) {
return 0;
}
if (!BN_add(bn, bn, gfp2->a0)) {
return 0;
}
return 1;
}

167
crypto/ec2/bn_hash.c Normal file
View File

@@ -0,0 +1,167 @@
/* ====================================================================
* Copyright (c) 2016 The GmSSL 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 GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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.
* ====================================================================
*/
#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include "../bn/bn_lcl.h"
int BN_hash_to_range(const EVP_MD *md, BIGNUM **bn,
const void *s, size_t slen, const BIGNUM *range, BN_CTX *bn_ctx)
{
int ret = 0;
BIGNUM *r = NULL;
BIGNUM *a = NULL;
unsigned char *buf = NULL;
size_t buflen, mdlen;
int nbytes, rounds, i;
if (!s || slen <= 0 || !md || !range) {
BNerr(BN_F_BN_HASH_TO_RANGE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (!(*bn)) {
if (!(r = BN_new())) {
BNerr(BN_F_BN_HASH_TO_RANGE, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
r = *bn;
BN_zero(r);
}
mdlen = EVP_MD_size(md);
buflen = mdlen + slen;
if (!(buf = OPENSSL_malloc(buflen))) {
BNerr(BN_F_BN_HASH_TO_RANGE, ERR_R_MALLOC_FAILURE);
goto end;
}
memset(buf, 0, mdlen);
memcpy(buf + mdlen, s, slen);
a = BN_new();
if (!a) {
BNerr(BN_F_BN_HASH_TO_RANGE, ERR_R_MALLOC_FAILURE);
goto end;
}
nbytes = BN_num_bytes(range);
rounds = (nbytes + mdlen - 1)/mdlen;
if (!bn_expand(r, rounds * mdlen * 8)) {
BNerr(BN_F_BN_HASH_TO_RANGE, ERR_R_BN_LIB);
goto end;
}
for (i = 0; i < rounds; i++) {
if (!EVP_Digest(buf, buflen, buf, (unsigned int *)&mdlen, md, NULL)) {
BNerr(BN_F_BN_HASH_TO_RANGE, ERR_R_EVP_LIB);
goto end;
}
if (!BN_bin2bn(buf, mdlen, a)) {
BNerr(BN_F_BN_HASH_TO_RANGE, ERR_R_BN_LIB);
goto end;
}
if (!BN_lshift(r, r, mdlen * 8)) {
BNerr(BN_F_BN_HASH_TO_RANGE, ERR_R_BN_LIB);
goto end;
}
if (!BN_uadd(r, r, a)) {
goto end;
}
}
if (!BN_mod(r, r, range, bn_ctx)) {
BNerr(BN_F_BN_HASH_TO_RANGE, ERR_R_BN_LIB);
goto end;
}
*bn = r;
ret = 1;
end:
if (!ret && !(*bn)) {
BN_free(r);
}
BN_free(a);
OPENSSL_free(buf);
return ret;
}
#if 0
int main(void)
{
char *s = "This ASCII string without null-terminator";
BIGNUM *bn = NULL;
BIGNUM *ret = NULL;
BIGNUM *range = NULL;
BN_hex2bn(&range, "ffffffffffffffffffffefffffffffffffffffff");
BN_hex2bn(&bn, "79317c1610c1fc018e9c53d89d59c108cd518608");
if (!BN_hash2bn(&ret, s, strlen(s), EVP_sha1(), range)) {
printf("BN_hash2bn() function failed\n");
return 0;
}
if (!ret) {
printf("shit\n");
}
printf("%s\n", BN_bn2hex(ret));
if (BN_cmp(ret, bn) != 0) {
printf("BN_hash2bn() test failed\n");
return 0;
}
printf("BN_hash2bn() test passed\n");
return 1;
}
#endif

193
crypto/ec2/bn_solinas.c Normal file
View File

@@ -0,0 +1,193 @@
/* ====================================================================
* Copyright (c) 2014 - 2016 The GmSSL 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 GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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.
* ====================================================================
*/
#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/bn_solinas.h>
#include "../bn/bn_lcl.h"
/*
* generate the solinas prime tables,
* use it for fast check of solinas
*/
static BN_SOLINAS BN_solinas_table[] = {
{ 192, 16, -1, -1 },
{ 192, 64, -1, -1 },
{ 224, 96, -1, 1 },
{ 256, 168, -1, 1 },
{ 384, 80, -1, 1 },
{ 512, 32, -1, 1 },
{ 512, 32, -1, -1 },
{ 1024, 424, -1, -1 },
{ 1024, 856, -1, 1 },
};
/*
* solinas = 2^a + s * 2^b + c, where s, c in {1, -1}
* solinas looks like:
* 2^a + 2^b + 1 = 10000100001
* 2^a - 2^b + 1 = 1111100001
* 2^a + 2^b - 1 = 10000011111
* 2^a - 2^b - 1 = 1111011111
* so:
* n = len(bits(solinas))
* c = bits(solinas)[1] == 0 ? 1 : -1
* s = bits(solinas)[n-2] == 0 ? 1 : -1
* a = bits(solinas)[n-2] == 0 ? n-1 : n-2
* b = len(bits(solinas - 2^a - s*2^b - c)) - 1
*
* examples:
* 0xfffffffffffffffffffffffffffbffff
* 0xffffffffffffffffffffffeffffffffffff
* 0xfffffffffbfffffffffffffffffffffffff
*/
int BN_bn2solinas(const BIGNUM *bn, BN_SOLINAS *solinas)
{
int ret = 0;
BIGNUM *tmp = NULL;
int nbits;
int i;
if (!solinas || !bn) {
BNerr(BN_F_BN_BN2SOLINAS, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (!BN_copy(tmp, bn)) {
goto end;
}
if ((nbits = BN_num_bits(bn) - 1) < 1) {
BNerr(BN_F_BN_BN2SOLINAS, BN_R_INVALID_SOLINAS);
goto end;
}
solinas->c = BN_is_bit_set(bn, 1) ? 1 : -1;
if (BN_is_bit_set(bn, nbits - 1)) {
solinas->s = -1;
solinas->a = nbits;
} else {
solinas->s = 1;
solinas->a = nbits - 1;
}
for (i = 1; i < nbits; i++) {
}
end:
return 0;
}
int BN_solinas2bn(const BN_SOLINAS *solinas, BIGNUM *bn)
{
int ret = 0;
BIGNUM *tmp = NULL;
#if 0
if (b <= 0 || a <= b || (s != 1 && s != -1) ||
(c != 1 && c != -1)) {
BNerr(BN_F_BN_SOLINAS2BN, BN_R_INVALID_SOLINAS_PARAMETERS);
return 0;
}
if (!(tmp = BN_new())) {
BNerr(BN_F_BN_SOLINAS2BN, ERR_R_MALLOC_FAILURE);
goto end;
}
BN_one(tmp);
if (!BN_lshift(solinas, tmp, a)) {
BNerr(BN_F_BN_SOLINAS2BN, ERR_R_BN_LIB);
goto end;
}
if (!BN_lshift(tmp, tmp, b)) {
BNerr(BN_F_BN_SOLINAS2BN, ERR_R_BN_LIB);
goto end;
}
if (!BN_add_word(tmp, c)) {
BNerr(BN_F_BN_SOLINAS2BN, ERR_R_BN_LIB);
goto end;
}
if (s > 0) {
if (!BN_add(solinas, solinas, tmp)) {
BNerr(BN_F_BN_SOLINAS2BN, ERR_R_BN_LIB);
goto end;
}
} else {
if (!BN_sub(solinas, solinas, tmp)) {
BNerr(BN_F_BN_SOLINAS2BN, ERR_R_BN_LIB);
goto end;
}
}
/* check if solinas is a prime */
ret = 1;
end:
BN_free(tmp);
#endif
return ret;
}
int BN_generate_solinas(BIGNUM *ret, BN_SOLINAS *solinas, BN_GENCB *cb)
{
return 0;
}
int BN_is_solinas(const BIGNUM *a)
{
return 0;
}

3
crypto/ec2/build.info Normal file
View File

@@ -0,0 +1,3 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=bn_gfp2.c bn_solinas.c bn_hash.c \
fppoint.c ec_expoint.c ec_hash.c ec_type1.c

90
crypto/ec2/ec_expoint.c Normal file
View File

@@ -0,0 +1,90 @@
/* ====================================================================
* Copyright (c) 2016 The GmSSL 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 GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 file is to implement elliptic curve operations over extension
* fields
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
typedef struct {
int security_bits;
int n_bits;
int p_bits;
int q_bits;
} PAIRING_SEC;
static PAIRING_SEC sec_tbl[] = {
/* k |n| |p| |q| */
{ 80, 1024, 512, 160},
{112, 2048, 1024, 224},
{128, 3072, 1536, 256},
{192, 7680, 3840, 384},
{256, 15360, 7680, 512}
};
const EVP_MD *PAIRING_nbits_to_md(int nbits)
{
switch (nbits) {
case 1024: return EVP_sha1();
case 2048: return EVP_sha224();
case 3072: return EVP_sha256();
case 7680: return EVP_sha384();
case 15360: return EVP_sha512();
}
return NULL;
}

181
crypto/ec2/ec_hash.c Normal file
View File

@@ -0,0 +1,181 @@
/* ====================================================================
* Copyright (c) 2016 The GmSSL 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 GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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.
* ====================================================================
*/
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/bn_hash.h>
/* currently the EC_POINT_hash2point only support type1curve! */
int EC_POINT_hash2point(const EC_GROUP *group, const EVP_MD *md,
const char *s, size_t slen, EC_POINT *point, BN_CTX *bn_ctx)
{
int ret = 0;
BIGNUM *p = NULL;
BIGNUM *x = NULL;
BIGNUM *y = NULL;
BIGNUM *k = NULL;
BIGNUM *q = NULL;
if (!group || !md || !point || !s || slen <= 0 || !bn_ctx) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != NID_X9_62_prime_field) {
ECerr(EC_F_EC_POINT_HASH2POINT, EC_R_INVALID_CURVE);
return 0;
}
p = BN_new();
x = BN_new();
y = BN_new();
k = BN_new();
q = BN_new();
if (!p || !x || !y || !k || !q) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_MALLOC_FAILURE);
goto end;
}
if (!EC_GROUP_get_curve_GFp(group, p, x, y, bn_ctx)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_EC_LIB);
goto end;
}
/* check group is type-1 curve */
if (!BN_is_zero(x) || !BN_is_one(y) || BN_mod_word(p, 12) != 11) {
ECerr(EC_F_EC_POINT_HASH2POINT, EC_R_INVALID_CURVE);
goto end;
}
/* get order */
if (!EC_GROUP_get_order(group, q, bn_ctx)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_EC_LIB);
goto end;
}
/* y = HashToRange(s) in [0, p - 1] */
if (!BN_hash_to_range(md, &y, s, slen, p, bn_ctx)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
/* x = (y + 1) * (y - 1) mod p */
if (!BN_copy(x, y)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
if (!BN_copy(k, y)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
if (!BN_add_word(x, 1)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
if (!BN_sub_word(k, 1)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_mul(x, x, k, p, bn_ctx)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
/* k = (p^2 - 1)/3 */
if (!BN_lshift1(k, p)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
if (!BN_sub_word(k, 1)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
if (!BN_div_word(k, 3)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
/* compute x and point = (x, y) */
if (!BN_mod_exp(x, x, k, p, bn_ctx)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, bn_ctx)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_EC_LIB);
goto end;
}
/* compute [(p + 1)/q] * point */
if (!BN_add_word(p, 1)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
if (!BN_div(k, NULL, p, q, bn_ctx)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_BN_LIB);
goto end;
}
if (!EC_POINT_mul(group, point, NULL, point, k, bn_ctx)) {
ECerr(EC_F_EC_POINT_HASH2POINT, ERR_R_EC_LIB);
goto end;
}
ret = 1;
end:
BN_free(p);
BN_free(x);
BN_free(y);
BN_free(k);
BN_free(q);
return ret;
}

783
crypto/ec2/ec_type1.c Normal file
View File

@@ -0,0 +1,783 @@
/* ====================================================================
* Copyright (c) 2016 The GmSSL 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 GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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.
* ====================================================================
*
*/
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/bn_gfp2.h>
EC_GROUP *EC_GROUP_generate_type1curve(const BIGNUM *order, BN_CTX *bn_ctx)
{
ECerr(EC_F_EC_GROUP_GENERATE_TYPE1CURVE, 0);
return 0;
}
EC_GROUP *EC_GROUP_new_type1curve_ex(const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, const unsigned char *point, size_t pointlen,
const BIGNUM *order, const BIGNUM *cofactor, BN_CTX *bn_ctx)
{
return NULL;
}
EC_GROUP *EC_GROUP_new_type1curve(const BIGNUM *p,
const BIGNUM *x, const BIGNUM *y, const BIGNUM *order, BN_CTX *bn_ctx)
{
int e = 1;
EC_GROUP *ret = NULL;
BIGNUM *a = NULL;
BIGNUM *b = NULL;
EC_POINT *point = NULL;
if (!p || !x || !y || !order) {
ECerr(EC_F_EC_GROUP_NEW_TYPE1CURVE, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
/* check p = 11 (mod 12) */
if (BN_mod_word(p, 12) != 11) {
ECerr(EC_F_EC_GROUP_NEW_TYPE1CURVE, EC_R_INVALID_TYPE1CURVE);
return NULL;
}
BN_CTX_start(bn_ctx);
a = BN_CTX_get(bn_ctx);
b = BN_CTX_get(bn_ctx);
if (!a || !b) {
ECerr(EC_F_EC_GROUP_NEW_TYPE1CURVE, ERR_R_MALLOC_FAILURE);
goto end;
}
BN_zero(a);
BN_one(b);
if (!(ret = EC_GROUP_new_curve_GFp(p, a, b, bn_ctx))) {
ECerr(EC_F_EC_GROUP_NEW_TYPE1CURVE, EC_R_INVALID_TYPE1CURVE);
goto end;
}
/* prepare generator point from (x, y) */
if (!(point = EC_POINT_new(ret))) {
ECerr(EC_F_EC_GROUP_NEW_TYPE1CURVE, ERR_R_MALLOC_FAILURE);
goto end;
}
if (!EC_POINT_set_affine_coordinates_GFp(ret, point, x, y, bn_ctx)) {
ECerr(EC_F_EC_GROUP_NEW_TYPE1CURVE, EC_R_INVALID_TYPE1CURVE);
goto end;
}
/*
* calculate cofactor h = (p + 1)/n
* check n|(p + 1) where n is the order
*/
if (!BN_copy(a, p)) {
ECerr(EC_F_EC_GROUP_NEW_TYPE1CURVE, ERR_R_BN_LIB);
goto end;
}
if (!BN_add_word(a, 1)) {
ECerr(EC_F_EC_GROUP_NEW_TYPE1CURVE, ERR_R_BN_LIB);
goto end;
}
/* check (p + 1)%n == 0 */
if (!BN_div(a, b, a, order, bn_ctx)) {
ECerr(EC_F_EC_GROUP_NEW_TYPE1CURVE, ERR_R_BN_LIB);
goto end;
}
if (!BN_is_zero(b)) {
ECerr(EC_F_EC_GROUP_NEW_TYPE1CURVE, EC_R_INVLID_TYPE1CURVE);
goto end;
}
/* set order and cofactor */
if (!EC_GROUP_set_generator(ret, point, order, a)) {
ECerr(EC_F_EC_GROUP_NEW_TYPE1CURVE, EC_R_INVALID_TYPE1CURVE);
goto end;
}
e = 0;
end:
if (e && ret) {
EC_GROUP_free(ret);
ret = NULL;
}
BN_CTX_end(bn_ctx);
EC_POINT_free(point);
return ret;
}
int EC_GROUP_is_type1curve(const EC_GROUP *group, BN_CTX *bn_ctx)
{
ECerr(EC_F_EC_GROUP_IS_TYPE1CURVE, 0);
return 0;
}
/*
* zeta = F_p((p-1)/2) + ((F_p(3)^((p + 1)/4))/2) * i, in F_p^2
* which is used in phi() mapping in tate pairing over type1 curve
*/
BN_GFP2 *EC_GROUP_get_type1curve_zeta(const EC_GROUP *group, BN_CTX *bn_ctx)
{
int e = 1;
BN_GFP2 *ret = NULL;
BIGNUM *a = NULL;
BIGNUM *b = NULL;
BIGNUM *p = NULL;
if (!group || !bn_ctx) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
BN_CTX_start(bn_ctx);
ret = BN_GFP2_new();
a = BN_CTX_get(bn_ctx);
b = BN_CTX_get(bn_ctx);
p = BN_CTX_get(bn_ctx);
if (!ret || !a || !b || !p) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_MALLOC_FAILURE);
goto end;
}
/* get curve p, a, b and check it is type1 curve
* p is prime at least 512 bits, a == 0 and b == 1
*/
if (!EC_GROUP_get_curve_GFp(group, a, b, p, bn_ctx)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_EC_LIB);
goto end;
}
if (!BN_is_zero(a) || !BN_is_one(b)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, EC_R_INVALID_TYPE1_CURVE);
goto end;
}
if (BN_num_bits(p) < 512) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, EC_R_INVALID_TYPE1_CURVE);
goto end;
}
/*
* set ret->a0 = (p - 1)/2
*/
if (!BN_copy(ret->a0, p)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_MALLOC_FAILURE);
goto end;
}
if (!BN_sub_word(ret->a0, 1)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_EC_LIB);
goto end;
}
/* BN_div_word() return remainder, while (p - 1)%2 == 0 */
if (BN_div_word(ret->a0, 2)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, EC_R_INVALID_TYPE1_CURVE);
goto end;
}
/*
* ret->a1 = (p + 1)/4, (ret->a1 + 1)%4 == 0
*/
if (!BN_copy(ret->a1, p)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_BN_LIB);
goto end;
}
if (!BN_add_word(ret->a1, 1)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_BN_LIB);
goto end;
}
if (BN_div_word(ret->a1, 4)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, EC_R_INVALID_TYPE1_CURVE);
goto end;
}
/*
* re-use a as 3
* ret->a1 = 3^(ret->a1) mod p = 3^((p + 1)/4) mod p
*/
if (!BN_set_word(a, 3)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_exp(ret->a1, a, ret->a1, p, bn_ctx)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_BN_LIB);
goto end;
}
/*
* re-use b as 1/2 mod p
* ret->a1 = ret->a1 / 2 mod p = (3^((p + 1)/4)) mod p
*/
if (!BN_set_word(b, 2)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_inverse(b, b, p, bn_ctx)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_mul(ret->a1, ret->a1, b, p, bn_ctx)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ZETA, ERR_R_BN_LIB);
goto end;
}
e = 0;
end:
if (e && ret) {
BN_GFP2_free(ret);
ret = NULL;
}
BN_CTX_end(bn_ctx);
return ret;
}
/*
* eta = (p^2 - 1)/n
* which is used in the final modular exponentiation of tate pairing over
* type1 curve
*/
BIGNUM *EC_GROUP_get_type1curve_eta(const EC_GROUP *group, BN_CTX *bn_ctx)
{
int e = 1;
BIGNUM *ret = NULL;
BIGNUM *a = NULL;
BIGNUM *b = NULL;
BIGNUM *p = NULL;
if (!group || !bn_ctx) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ETA, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
BN_CTX_start(bn_ctx);
ret = BN_new();
a = BN_CTX_get(bn_ctx);
b = BN_CTX_get(bn_ctx);
p = BN_CTX_get(bn_ctx);
if (!ret || !a || !b || !p) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ETA, ERR_R_MALLOC_FAILURE);
goto end;
}
/* get curve p, a, b and check it is type1 curve
* p is prime at least 512 bits, a == 0 and b == 1
*/
if (!EC_GROUP_get_curve_GFp(group, a, b, p, bn_ctx)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ETA, ERR_R_EC_LIB);
goto end;
}
if (!BN_is_zero(a) || !BN_is_one(b)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ETA, EC_R_INVALID_TYPE1_CURVE);
goto end;
}
if (BN_num_bits(p) < 512) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ETA, EC_R_INVALID_TYPE1_CURVE);
goto end;
}
/* get curve order n, re-use a for order n */
if (!EC_GROUP_get_order(group, a, bn_ctx)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ETA, ERR_R_EC_LIB);
goto end;
}
/*
* eta = (p^2 - 1)/n,
*/
if (!BN_sqr(ret, p, bn_ctx)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ETA, ERR_R_BN_LIB);
goto end;
}
if (!BN_sub_word(ret, 1)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ETA, ERR_R_BN_LIB);
goto end;
}
if (!BN_div(ret, NULL, ret, a, bn_ctx)) {
ECerr(EC_F_EC_GROUP_GET_TYPE1CURVE_ETA, ERR_R_BN_LIB);
goto end;
}
e = 1;
end:
if (e && ret) {
BN_free(ret);
ret = NULL;
}
BN_CTX_end(bn_ctx);
return ret;
}
/* phi: (x, y) => (zeta * x, y) */
static int type1curve_phi(const EC_GROUP *group, const EC_POINT *point,
BN_GFP2 *x, BN_GFP2 *y, const BIGNUM *p, BN_CTX *bn_ctx)
{
int ret = 0;
BN_GFP2 *zeta = NULL;
BIGNUM *xP;
BIGNUM *yP;
if (!group || !point || !x || !y || !p || !bn_ctx) {
ECerr(EC_F_TYPE1CURVE_PHI,
ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
BN_CTX_start(bn_ctx);
xP = BN_CTX_get(bn_ctx);
yP = BN_CTX_get(bn_ctx);
if (!xP || !yP) {
ECerr(EC_F_TYPE1CURVE_PHI, ERR_R_MALLOC_FAILURE);
goto end;
}
if (!(zeta = EC_GROUP_get_type1curve_zeta(group, bn_ctx))) {
ECerr(EC_F_TYPE1CURVE_PHI,
EC_R_GET_TYPE1CURVE_ZETA_FAILURE);
goto end;
}
if (!EC_POINT_get_affine_coordinates_GFp(group, point, xP, yP, bn_ctx))
{
ECerr(EC_F_TYPE1CURVE_PHI, ERR_R_EC_LIB);
goto end;
}
/* return x = zeta * point->x */
if (!BN_GFP2_mul_bn(x, zeta, xP, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_PHI, ERR_R_BN_LIB);
goto end;
}
/* return y = point->y */
if (!BN_GFP2_set_bn(y, yP, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_PHI, ERR_R_BN_LIB);
goto end;
}
ret = 1;
end:
BN_CTX_end(bn_ctx);
BN_GFP2_free(zeta);
return ret;
}
/*
* eval the function defined by the line through point T and P,
* with value Q = (xQ, yQ)
*/
static int type1curve_eval_line_textbook(const EC_GROUP *group, BN_GFP2 *r,
const EC_POINT *T, const EC_POINT *P, const BN_GFP2 *xQ, const BN_GFP2
*yQ,
BN_CTX *bn_ctx)
{
int ret = 0;
BN_GFP2 *num = NULL;
BN_GFP2 *den = NULL;
BIGNUM *p;
BIGNUM *xT;
BIGNUM *yT;
BIGNUM *xP;
BIGNUM *yP;
BIGNUM *bn;
BIGNUM *slope;
if (!group || !r || !T || !P || !xQ || !yQ || !bn_ctx) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
BN_CTX_start(bn_ctx);
p = BN_CTX_get(bn_ctx);
xT = BN_CTX_get(bn_ctx);
yT = BN_CTX_get(bn_ctx);
xP = BN_CTX_get(bn_ctx);
yP = BN_CTX_get(bn_ctx);
bn = BN_CTX_get(bn_ctx);
slope = BN_CTX_get(bn_ctx);
num = BN_GFP2_new();
den = BN_GFP2_new();
if (!p || !xT || !yT || !xP || !yP || !bn || !slope || !num || !den) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_MALLOC_FAILURE);
goto end;
}
/* get prime field p */
if (!EC_GROUP_get_curve_GFp(group, p, xT, yT, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_EC_LIB);
goto end;
}
/* get T and P */
if (!EC_POINT_get_affine_coordinates_GFp(group, T, xT, yT, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_EC_LIB);
goto end;
}
if (!EC_POINT_get_affine_coordinates_GFp(group, P, xP, yP, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_EC_LIB);
goto end;
}
#if 0
/* if T == P, slope = (3 * x_T^2 + a)/(2 * y_T) */
if (T == P || (BN_cmp(xT, xP) == 0 && BN_cmp(yT, yP) == 0)) {
if (!BN_mod_sqr(bn, xT, p, bn_ctx)) {
goto end;
}
if (!BN_mod_add(slope, bn, bn, p, bn_ctx)) {
goto end;
}
if (!BN_mod_add(slope, slope, bn, p, bn_ctx)) {
goto end;
}
if (!BN_mod_add(den, yT, yT, p, bn_ctx)) {
goto end;
}
if (!BN_mod_inverse(den, den, p, bn_ctx)) {
goto end;
}
if (!BN_mod_mul(slope, slope, den, p, bn_ctx)) {
goto end;
}
}
/*
* if xT == xP and yT + yP == 0, return xQ - xT
*/
if (BN_cmp(xT, xP) == 0) {
BIGNUM *t;
if (!(t = BN_CTX_get(bn_ctx))) {
goto end;
}
if (!BN_mod_add(t, yT, yP, p, ctx)) {
goto end;
}
if (BN_is_zero(t)) {
if (!BN_GFP2_sub_bn(r, xQ, xT, p, bn_ctx)) {
goto end;
}
}
}
/*
* if T == P, slope = (3 * x_T^2 + a)/(2 * y_T)
* else slope = (y_T - y_P)/(x_T - x_P)
*/
if (!BN_mod_sub(num, yT, yP, p, bn_ctx)) {
goto end;
}
if (!BN_mod_sub(den, xT, xP, p, bn_ctx)) {
goto end;
}
if (!BN_mod_inverse(den, den, p, bn_ctx)) {
goto end;
}
if (!BN_mod_mul(slope, num, den, p, bn_ctx)) {
goto end;
}
#endif
/*
* num = (yQ - ((xQ - xT) * slope)) - yT
* den = xQ + (xT + (xP - slope^2))
* return num/den
*/
if (!BN_GFP2_sub_bn(num, xQ, xT, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
if (!BN_GFP2_mul_bn(num, num, slope, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
if (!BN_GFP2_sub(num, yQ, num, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
if (!BN_GFP2_sub_bn(num, num, yT, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_sqr(bn, slope, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_sub(bn, xP, bn, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
if (!BN_mod_add(bn, xT, bn, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
if (!BN_GFP2_add_bn(den, xQ, bn, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
if (!BN_GFP2_div(ret, num, den, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_LINE_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
ret = 1;
end:
BN_CTX_end(bn_ctx);
BN_GFP2_free(num);
BN_GFP2_free(den);
return ret;
}
static int type1curve_eval_miller_textbook(const EC_GROUP *group, BN_GFP2 *r,
const EC_POINT *P, const BN_GFP2 *xQ, const BN_GFP2 *yQ,
const BIGNUM *p, BN_CTX *bn_ctx)
{
int ret = 0;
BN_GFP2 *f = NULL;
BN_GFP2 *g = NULL;
EC_POINT *T = NULL;
BIGNUM *n;
int nbits;
int i;
if (!group || !r || !P || !xQ || !yQ || !p || !bn_ctx) {
ECerr(EC_F_TYPE1CURVE_EVAL_MILLER_TEXTBOOK,
ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
BN_CTX_start(bn_ctx);
n = BN_CTX_get(bn_ctx);
f = BN_GFP2_new();
g = BN_GFP2_new();
T = EC_POINT_new(group);
if (!n || !f || !g || !T) {
ECerr(EC_F_TYPE1CURVE_EVAL_MILLER_TEXTBOOK,
ERR_R_MALLOC_FAILURE);
goto end;
}
if (!EC_GROUP_get_order(group, n, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_MILLER_TEXTBOOK,
ERR_R_EC_LIB);
goto end;
}
nbits = BN_num_bits(n);
/* miller loop */
for (i = nbits - 2; i >= 0; i--) {
/* f = f^2 */
if (!BN_GFP2_sqr(f, f, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_MILLER_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
/* compute g_{T,T}(Q) */
if (!type1curve_eval_line_textbook(group, g, T, T, xQ, yQ,
bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_MILLER_TEXTBOOK,
ERR_R_EC_LIB);
goto end;
}
/* f = f * g */
if (!BN_GFP2_mul(f, f, g, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_MILLER_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
/* T = 2T */
if (!EC_POINT_dbl(group, T, T, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_MILLER_TEXTBOOK,
ERR_R_EC_LIB);
goto end;
}
if (BN_is_bit_set(n, i)) {
/* g = g_{T,P}(Q) */
if (!type1curve_eval_line_textbook(group, g, T, P, xQ,
yQ, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_MILLER_TEXTBOOK,
ERR_R_EC_LIB);
goto end;
}
/* f = f * g */
if (!BN_GFP2_mul(f, f, g, p, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_MILLER_TEXTBOOK,
ERR_R_BN_LIB);
goto end;
}
/* T = T + P */
if (!EC_POINT_add(group, T, T, P, bn_ctx)) {
ECerr(EC_F_TYPE1CURVE_EVAL_MILLER_TEXTBOOK,
ERR_R_EC_LIB);
goto end;
}
}
}
/* set return value */
if (!BN_GFP2_copy(r, f)) {
ECerr(EC_F_TYPE1CURVE_EVAL_MILLER_TEXTBOOK, ERR_R_BN_LIB);
goto end;
}
ret = 1;
end:
BN_CTX_end(bn_ctx);
BN_GFP2_free(f);
BN_GFP2_free(g);
EC_POINT_free(T);
return ret;
}
int EC_type1curve_tate(const EC_GROUP *group, BN_GFP2 *r,
const EC_POINT *P, const EC_POINT *Q, BN_CTX *bn_ctx)
{
int ret = 0;
BN_GFP2 *xQ = NULL;
BN_GFP2 *yQ = NULL;
BIGNUM *eta = NULL;
BIGNUM *p;
BIGNUM *a;
BIGNUM *b;
if (!group || !ret || !P || !Q || !bn_ctx) {
ECerr(EC_F_EC_TYPE1CURVE_TATE, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
BN_CTX_start(bn_ctx);
xQ = BN_GFP2_new();
yQ = BN_GFP2_new();
p = BN_CTX_get(bn_ctx);
a = BN_CTX_get(bn_ctx);
b = BN_CTX_get(bn_ctx);
if (!xQ || !yQ || !p || !a || !b) {
ECerr(EC_F_EC_TYPE1CURVE_TATE, ERR_R_MALLOC_FAILURE);
goto end;
}
if (!EC_GROUP_get_curve_GFp(group, p, a, b, bn_ctx)) {
ECerr(EC_F_EC_TYPE1CURVE_TATE, EC_R_INVALID_TYPE1CURVE);
goto end;
}
/* (xQ, yQ) = phi(Q) */
if (!type1curve_phi(group, Q, xQ, yQ, p, bn_ctx)) {
ECerr(EC_F_EC_TYPE1CURVE_TATE, ERR_R_EC_LIB);
goto end;
}
/* compute e(P, phi(Q)) */
if (!type1curve_eval_miller_textbook(group, r, P, xQ, yQ, p, bn_ctx)) {
ECerr(EC_F_EC_TYPE1CURVE_TATE, ERR_R_EC_LIB);
goto end;
}
/* compute e(P, phi(Q))^eta, eta = (p^2 - 1)/q */
if (!(eta = EC_GROUP_get_type1curve_eta(group, bn_ctx))) {
ECerr(EC_F_EC_TYPE1CURVE_TATE, EC_R_INVALID_TYPE1CURVE);
goto end;
}
ret = 1;
end:
BN_GFP2_free(xQ);
BN_GFP2_free(yQ);
BN_CTX_end(bn_ctx);
BN_free(eta);
return ret;
}
int EC_type1curve_tate_ratio(const EC_GROUP *group, BN_GFP2 *r,
const EC_POINT *P1, const EC_POINT *Q1,
const EC_POINT *P2, const EC_POINT *Q2,
BN_CTX *bn_ctx)
{
return 0;
}

114
crypto/ec2/fppoint.c Normal file
View File

@@ -0,0 +1,114 @@
/* ====================================================================
* Copyright (c) 2016 The GmSSL 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 GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 file is to implement elliptic curve operations over extension
* fields
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/fppoint.h>
ASN1_SEQUENCE(FpPoint) = {
ASN1_SIMPLE(FpPoint, x, BIGNUM),
ASN1_SIMPLE(FpPoint, y, BIGNUM)
} ASN1_SEQUENCE_END(FpPoint)
IMPLEMENT_ASN1_FUNCTIONS(FpPoint)
IMPLEMENT_ASN1_DUP_FUNCTION(FpPoint)
int EC_POINT_cmp_fppoint(const EC_GROUP *group, const EC_POINT *a, const FpPoint *b,
BN_CTX *bn_ctx)
{
int ret = -1;
BIGNUM *x = NULL;
BIGNUM *y = NULL;
if (!group || !a || !b || !bn_ctx) {
ECerr(EC_F_EC_POINT_CMP_FPPOINT, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
BN_CTX_start(bn_ctx);
x = BN_CTX_get(bn_ctx);
y = BN_CTX_get(bn_ctx);
if (!x || !y) {
ECerr(EC_F_EC_POINT_CMP_FPPOINT, ERR_R_BN_LIB);
goto end;
}
if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) {
if (!EC_POINT_get_affine_coordinates_GFp(group, a, x, y, bn_ctx)) {
ECerr(EC_F_EC_POINT_CMP_FPPOINT, ERR_R_EC_LIB);
goto end;
}
} else {
if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x, y, bn_ctx)) {
ECerr(EC_F_EC_POINT_CMP_FPPOINT, ERR_R_EC_LIB);
goto end;
}
}
if (BN_cmp(x, b->x) == 0 && BN_cmp(y, b->y) == 0) {
ret = 0;
} else {
ret = 1;
}
end:
BN_CTX_end(bn_ctx);
return ret;
}