Files
GmSSL/crypto/sm9/sm9_rate.c
Zhi Guan 9f4e184ac5 Update SM9
to be continue ...
2018-09-19 11:56:07 +08:00

1520 lines
33 KiB
C

/* ====================================================================
* Copyright (c) 2018 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 <stdint.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include "sm9_lcl.h"
typedef BIGNUM *fp2_t[2];
typedef fp2_t fp4_t[2];
typedef fp4_t fp12_t[3];
typedef struct {
fp2_t X;
fp2_t Y;
fp2_t Z;
} point_t;
static const uint64_t sm9_a[2] = {
0x400000000215d93eul, 0x02ul
};
static int fp2_init(fp2_t a, BN_CTX *ctx)
{
a[0] = NULL;
a[1] = NULL;
a[0] = BN_CTX_get(ctx);
a[1] = BN_CTX_get(ctx);
if (!a[1]) {
BN_free(a[0]);
a[0] = NULL;
return 0;
}
return 1;
}
static void fp2_cleanup(fp2_t a)
{
BN_free(a[0]);
BN_free(a[1]);
a[0] = NULL;
a[1] = NULL;
}
static void fp2_clear_cleanup(fp2_t a)
{
BN_clear_free(a[0]);
BN_clear_free(a[1]);
a[0] = NULL;
a[1] = NULL;
}
static int fp2_is_zero(const fp2_t a)
{
return BN_is_zero(a[0])
&& BN_is_zero(a[1]);
}
static int fp2_is_one(const fp2_t a)
{
return BN_is_one(a[0])
&& BN_is_zero(a[1]);
}
static void fp2_set_zero(fp2_t r)
{
BN_zero(r[0]);
BN_zero(r[1]);
}
static int fp2_set_one(fp2_t r)
{
BN_zero(r[1]);
return BN_one(r[0]);
}
static int fp2_copy(fp2_t r, const fp2_t a)
{
return BN_copy(r[0], a[0])
&& BN_copy(r[1], a[1]);
}
static int fp2_set(fp2_t r, const BIGNUM *a0, const BIGNUM *a1)
{
return BN_copy(r[0], a0)
&& BN_copy(r[1], a1);
}
static int fp2_set_u(fp2_t r)
{
BN_zero(r[0]);
return BN_one(r[1]);
}
static int fp2_set_bn(fp2_t r, const BIGNUM *a)
{
BN_zero(r[1]);
return BN_copy(r[0], a) != NULL;
}
static int fp2_set_word(fp2_t r, unsigned long a)
{
BN_zero(r[1]);
return BN_set_word(r[0], a);
}
static int fp2_equ(const fp2_t a, const fp2_t b)
{
return !BN_cmp(a[0], b[0]) && !BN_cmp(a[1], b[1]);
}
static int fp2_add_word(fp2_t r, const fp2_t a, unsigned long b, const BIGNUM *p, BN_CTX *ctx)
{
BIGNUM *w = NULL;
if (!(w = BN_CTX_get(ctx))
|| !BN_set_word(w, b)
|| !BN_mod_add(r[0], a[0], w, p, ctx)
|| !BN_copy(r[1], a[1])) {
BN_free(w);
return 0;
}
BN_free(w);
return 1;
}
static int fp2_add(fp2_t r, const fp2_t a, const fp2_t b, const BIGNUM *p, BN_CTX *ctx)
{
return BN_mod_add(r[0], a[0], b[0], p, ctx)
&& BN_mod_add(r[1], a[1], b[1], p, ctx);
}
static int fp2_dbl(fp2_t r, const fp2_t a, const BIGNUM *p, BN_CTX *ctx)
{
return BN_mod_add(r[0], a[0], a[0], p, ctx)
&& BN_mod_add(r[1], a[1], a[1], p, ctx);
}
static int fp2_tri(fp2_t r, const fp2_t a, const BIGNUM *p, BN_CTX *ctx)
{
return BN_mod_add(r[0], a[0], a[0], p, ctx)
&& BN_mod_add(r[0], r[0], a[0], p, ctx)
&& BN_mod_add(r[1], a[1], a[1], p, ctx)
&& BN_mod_add(r[1], r[1], a[1], p, ctx);
}
static int fp2_sub(fp2_t r, const fp2_t a, const fp2_t b, const BIGNUM *p, BN_CTX *ctx)
{
return BN_mod_sub(r[0], a[0], b[0], p, ctx)
&& BN_mod_sub(r[1], a[1], b[1], p, ctx);
}
static int fp2_neg(fp2_t r, const fp2_t a, const BIGNUM *p)
{
return BN_sub(r[0], p, a[0])
&& BN_sub(r[1], p, a[1]);
}
static int fp2_mul(fp2_t r, const fp2_t a, const fp2_t b, const BIGNUM *p, BN_CTX *ctx)
{
BIGNUM *t = NULL;
if (!(t = BN_CTX_get(ctx))
/* r0 = a0 * b0 - 2 * a1 * b1 */
|| !BN_mod_mul(r[0], a[0], b[0], p, ctx)
|| !BN_mod_mul(t, a[1], b[1], p, ctx)
|| !BN_mod_add(t, t, t, p, ctx)
|| !BN_mod_sub(r[0], r[0], t, p, ctx)
/* r1 = a0 * b1 + a1 * b0 */
|| !BN_mod_mul(r[1], a[0], b[1], p, ctx)
|| !BN_mod_mul(t, a[1], b[0], p, ctx)
|| !BN_mod_add(r[1], r[1], t, p, ctx)) {
BN_free(t);
return 0;
}
BN_free(t);
return 1;
}
static int fp2_mul_u(fp2_t r, const fp2_t a, const fp2_t b, const BIGNUM *p, BN_CTX *ctx)
{
BIGNUM *t = NULL;
if (!(t = BN_CTX_get(ctx))
/* r0 = -2 * (a0 * b1 + a1 * b0) */
|| !BN_mod_mul(r[0], a[0], b[1], p, ctx)
|| !BN_mod_mul(t, a[1], b[0], p, ctx)
|| !BN_mod_add(r[0], r[0], t, p, ctx)
|| !BN_mod_add(r[0], r[0], r[0], p, ctx)
|| !BN_mod_sub(r[0], p, r[0], p, ctx)
/* r1 = a0 * b0 - 2 * a1 * b1 */
|| !BN_mod_mul(r[1], a[0], b[0], p, ctx)
|| !BN_mod_mul(t, a[1], b[1], p, ctx)
|| !BN_mod_add(t, t, t, p, ctx)
|| !BN_mod_sub(r[1], r[1], t, p, ctx)) {
BN_free(t);
return 0;
}
BN_free(t);
return 1;
}
static int fp2_sqr(fp2_t r, const fp2_t a, const BIGNUM *p, BN_CTX *ctx)
{
BIGNUM *t = NULL;
if (!(t = BN_CTX_get(ctx))
/* r0 = a0^2 - 2 * a1^2 */
|| !BN_mod_sqr(r[0], a[0], p, ctx)
|| !BN_mod_sqr(t, a[1], p, ctx)
|| !BN_mod_add(t, t, t, p, ctx)
|| !BN_mod_sub(r[0], r[0], t, p, ctx)
/* r1 = 2 * a0 * a1 */
|| !BN_mod_mul(r[1], a[0], a[1], p, ctx)
|| !BN_mod_add(r[1], r[1], r[1], p, ctx)) {
BN_free(t);
return 0;
}
BN_free(t);
return 1;
}
static int fp2_sqr_u(fp2_t r, const fp2_t a, const BIGNUM *p, BN_CTX *ctx)
{
BIGNUM *t = NULL;
if (!(t = BN_CTX_get(ctx))
/* r0 = -4 * a0 * a1 */
|| !BN_mod_mul(r[0], a[0], a[1], p, ctx)
|| !BN_mod_add(r[0], r[0], r[0], p, ctx)
|| !BN_mod_add(r[0], r[0], r[0], p, ctx)
|| !BN_mod_sub(r[0], p, r[0], p, ctx)
/* r1 = a0^2 - 2 * a1^2 */
|| !BN_mod_sqr(r[1], a[0], p, ctx)
|| !BN_mod_sqr(t, a[1], p, ctx)
|| !BN_mod_add(t, t, t, p, ctx)
|| !BN_mod_sub(r[1], r[1], t, p, ctx)) {
BN_free(t);
return 0;
}
BN_free(t);
return 1;
}
static int fp2_inv(fp2_t r, const fp2_t a, const BIGNUM *p, BN_CTX *ctx)
{
if (BN_is_zero(a[0])) {
/* r0 = 0 */
BN_zero(r[0]);
/* r1 = -(2 * a1)^-1 */
if (!BN_mod_add(r[0], a[1], a[1], p, ctx)
|| !BN_mod_inverse(r[0], r[0], p, ctx)
|| !BN_mod_sub(r[0], p, r[0], p, ctx)) {
return 0;
}
} else if (BN_is_zero(a[1])) {
/* r1 = 0 */
BN_zero(r[1]);
/* r0 = a0^-1 */
if (!BN_mod_inverse(r[0], a[0], p, ctx)) {
return 0;
}
} else {
BIGNUM *k = NULL;
BIGNUM *t = NULL;
if (!(k = BN_CTX_get(ctx))
|| !(t = BN_CTX_get(ctx))
/* k = (a[0]^2 + 2 * a[1]^2)^-1 */
|| !BN_mod_sqr(k, a[0], p, ctx)
|| !BN_mod_sqr(t, a[1], p, ctx)
|| !BN_mod_add(t, t, t, p, ctx)
|| !BN_mod_add(k, k, t, p, ctx)
|| !BN_mod_inverse(k, k, p, ctx)
/* r[0] = a[0] * k, r[1] = -a[1] * k */
|| !BN_mod_mul(r[0], a[0], k, p, ctx)
|| !BN_mod_mul(r[1], a[1], k, p, ctx)
|| !BN_mod_sub(r[1], p, r[1], p, ctx)) {
BN_free(k);
BN_free(t);
return 0;
}
BN_free(k);
BN_free(t);
}
return 1;
}
static int fp2_div(fp2_t r, const fp2_t a, const fp2_t b, const BIGNUM *p, BN_CTX *ctx)
{
return fp2_inv(r, b, p, ctx)
&& fp2_mul(r, a, r, p, ctx);
}
static int fp4_init(fp4_t a, BN_CTX *ctx)
{
int r;
r = fp2_init(a[0], ctx);
r &= fp2_init(a[1], ctx);
if (!r) {
fp2_cleanup(a[0]);
fp2_cleanup(a[1]);
}
return r;
}
static void fp4_cleanup(fp4_t a)
{
fp2_cleanup(a[0]);
fp2_cleanup(a[1]);
}
static void fp4_clear_cleanup(fp4_t a)
{
fp2_clear_cleanup(a[0]);
fp2_clear_cleanup(a[1]);
}
static int fp4_is_zero(const fp4_t a)
{
return fp2_is_zero(a[0])
&& fp2_is_zero(a[1]);
}
static int fp4_is_one(const fp4_t a)
{
return fp2_is_one(a[0])
&& fp2_is_zero(a[1]);
}
static void fp4_set_zero(fp4_t r)
{
fp2_set_zero(r[0]);
fp2_set_zero(r[1]);
}
static int fp4_set_one(fp4_t r)
{
fp2_set_zero(r[1]);
return fp2_set_one(r[0]);
}
static int fp4_set_bn(fp4_t r, const BIGNUM *a)
{
fp2_set_zero(r[1]);
return fp2_set_bn(r[0], a);
}
static int fp4_set_word(fp4_t r, unsigned long a)
{
fp2_set_zero(r[1]);
return fp2_set_word(r[0], a);
}
static int fp4_set_fp2(fp4_t r, const fp2_t a)
{
fp2_set_zero(r[1]);
return fp2_copy(r[0], a);
}
static int fp4_set(fp4_t r, const fp2_t a0, const fp2_t a1)
{
return fp2_copy(r[0], a0)
&& fp2_copy(r[1], a1);
}
static int fp4_copy(fp4_t r, const fp4_t a)
{
return fp2_copy(r[0], a[0])
&& fp2_copy(r[1], a[1]);
}
static int fp4_set_u(fp4_t r)
{
fp2_set_zero(r[1]);
return fp2_set_u(r[0]);
}
static int fp4_set_v(fp4_t r)
{
fp2_set_zero(r[0]);
return fp2_set_one(r[1]);
}
static int fp4_equ(const fp4_t a, const fp4_t b)
{
return fp2_equ(a[0], b[0])
&& fp2_equ(a[1], b[1]);
}
static int fp4_add(fp4_t r, const fp4_t a, const fp4_t b, const BIGNUM *p, BN_CTX *ctx)
{
return fp2_add(r[0], a[0], b[0], p, ctx)
&& fp2_add(r[1], a[1], b[1], p, ctx);
}
static int fp4_dbl(fp4_t r, const fp4_t a, const BIGNUM *p, BN_CTX *ctx)
{
return fp2_dbl(r[0], a[0], p, ctx)
&& fp2_dbl(r[1], a[1], p, ctx);
}
static int fp4_sub(fp4_t r, const fp4_t a, const fp4_t b, const BIGNUM *p, BN_CTX *ctx)
{
return fp2_sub(r[0], a[0], b[0], p, ctx)
&& fp2_sub(r[1], a[1], b[1], p, ctx);
}
static int fp4_neg(fp4_t r, const fp4_t a, const BIGNUM *p)
{
return fp2_neg(r[0], a[0], p)
&&fp2_neg(r[1], a[1], p);
}
static int fp4_mul(fp4_t r, const fp4_t a, const fp4_t b, const BIGNUM *p, BN_CTX *ctx)
{
fp2_t t;
if (!fp2_init(t, ctx)
/* r[0] = a[0] * b[0] + a[1] * b[1] * u */
|| !fp2_mul(r[0], a[0], b[0], p, ctx)
|| !fp2_mul_u(t, a[1], b[1], p, ctx)
|| !fp2_add(r[0], r[0], t, p, ctx)
/* r[1] = a[0] * b[1] + a[1] * b[0] */
|| !fp2_mul(r[1], a[0], b[1], p, ctx)
|| !fp2_mul(t, a[1], b[0], p, ctx)
|| !fp2_add(r[1], r[1], t, p, ctx)) {
fp2_cleanup(t);
return 0;
}
fp2_cleanup(t);
return 1;
}
static int fp4_mul_v(fp4_t r, const fp4_t a, const fp4_t b, const BIGNUM *p, BN_CTX *ctx)
{
fp2_t t;
if (!fp2_init(t, ctx)
/* r[0] = a[0] * b[1] * u + a[1] * b[0] * u */
|| !fp2_mul_u(r[0], a[0], b[1], p, ctx)
|| !fp2_mul_u(t, a[1], b[0], p, ctx)
|| !fp2_add(r[0], r[0], t, p, ctx)
/* r[1] = a[0] * b[0] + a[1] * b[1] * u */
|| !fp2_mul(r[1], a[0], b[0], p, ctx)
|| !fp2_mul_u(t, a[1], b[1], p, ctx)
|| !fp2_add(r[1], r[1], t, p, ctx)) {
fp2_cleanup(t);
return 0;
}
fp2_cleanup(t);
return 1;
}
static int fp4_sqr(fp4_t r, const fp4_t a, const BIGNUM *p, BN_CTX *ctx)
{
fp2_t t;
if (!fp2_init(t, ctx)
/* r[0] = a[0]^2 + a[1]^2 * u */
|| !fp2_sqr(r[0], a[0], p, ctx)
|| !fp2_sqr_u(t, a[1], p, ctx)
|| !fp2_add(r[0], r[0], t, p, ctx)
/* r[1] = 2 * (a[0] * a[1]) */
|| !fp2_mul(r[1], a[0], a[1], p, ctx)
|| !fp2_dbl(r[1], r[1], p, ctx)) {
fp2_cleanup(t);
return 0;
}
fp2_cleanup(t);
return 1;
}
static int fp4_sqr_v(fp4_t r, const fp4_t a, const BIGNUM *p, BN_CTX *ctx)
{
fp2_t t;
if (!fp2_init(t, ctx)
/* r[0] = 2 * (a[0] * a[1]) */
|| !fp2_mul_u(t, a[0], a[1], p, ctx)
|| !fp2_dbl(r[0], t, p, ctx)
/* r[1] = a[0]^2 + a[1]^2 * u */
|| !fp2_sqr(r[1], a[0], p, ctx)
|| !fp2_sqr_u(t, a[1], p, ctx)
|| !fp2_add(r[1], r[1], t, p, ctx)) {
fp2_cleanup(t);
return 0;
}
fp2_cleanup(t);
return 1;
}
static int fp4_inv(fp4_t r, const fp4_t a, const BIGNUM *p, BN_CTX *ctx)
{
fp2_t k;
if (!fp2_init(k, ctx)
/* k = (a[1]^2 * u - a[0]^2)^-1 */
|| !fp2_sqr_u(k, a[1], p, ctx)
|| !fp2_sqr(r[0], a[0], p, ctx)
|| !fp2_sub(k, k, r[0], p, ctx)
|| !fp2_inv(k, k, p, ctx)
/* r[0] = -(a[0] * k) */
|| !fp2_mul(r[0], a[0], k, p, ctx)
|| !fp2_neg(r[0], r[0], p)
/* r[1] = a[1] * k */
|| !fp2_mul(r[1], a[1], k, p, ctx)) {
fp2_cleanup(k);
return 0;
}
fp2_cleanup(k);
return 1;
}
static int fp12_init(fp12_t a, BN_CTX *ctx)
{
int r;
r = fp4_init(a[0], ctx);
r &= fp4_init(a[1], ctx);
r &= fp4_init(a[2], ctx);
if (!r) {
fp4_cleanup(a[0]);
fp4_cleanup(a[1]);
fp4_cleanup(a[2]);
}
return r;
}
static void fp12_cleanup(fp12_t a)
{
fp4_cleanup(a[0]);
fp4_cleanup(a[1]);
fp4_cleanup(a[2]);
}
static void fp12_clear_cleanup(fp12_t a)
{
fp4_clear_cleanup(a[0]);
fp4_clear_cleanup(a[1]);
fp4_clear_cleanup(a[2]);
}
static int fp12_is_zero(const fp12_t a)
{
return fp4_is_zero(a[0])
&& fp4_is_zero(a[1])
&& fp4_is_zero(a[2]);
}
static int fp12_is_one(const fp12_t a)
{
return fp4_is_one(a[0])
&& fp4_is_zero(a[1])
&& fp4_is_zero(a[2]);
}
static void fp12_set_zero(fp12_t r)
{
fp4_set_zero(r[0]);
fp4_set_zero(r[1]);
fp4_set_zero(r[2]);
}
static int fp12_set_one(fp12_t r)
{
fp4_set_zero(r[1]);
fp4_set_zero(r[2]);
return fp4_set_one(r[0]);
}
static int fp12_copy(fp12_t r, const fp12_t a)
{
return fp4_copy(r[0], a[0])
&& fp4_copy(r[1], a[1])
&& fp4_copy(r[2], a[2]);
}
static int fp12_set(fp12_t r, const fp4_t a0, const fp4_t a1, const fp4_t a2)
{
return fp4_copy(r[0], a0)
&& fp4_copy(r[1], a1)
&& fp4_copy(r[2], a2);
}
static int fp12_set_fp4(fp12_t r, const fp4_t a)
{
fp4_set_zero(r[1]);
fp4_set_zero(r[2]);
return fp4_copy(r[0], a);
}
static int fp12_set_fp2(fp12_t r, const fp2_t a)
{
fp4_set_zero(r[1]);
fp4_set_zero(r[2]);
return fp4_set_fp2(r[0], a);
}
static int fp12_set_bn(fp12_t r, const BIGNUM *a)
{
fp4_set_zero(r[1]);
fp4_set_zero(r[2]);
return fp4_set_bn(r[0], a);
}
static int fp12_set_word(fp12_t r, unsigned long a)
{
fp4_set_zero(r[1]);
fp4_set_zero(r[2]);
return fp4_set_word(r[0], a);
}
static int fp12_set_u(fp12_t r)
{
fp4_set_zero(r[1]);
fp4_set_zero(r[2]);
return fp4_set_u(r[0]);
}
static int fp12_set_v(fp12_t r)
{
fp4_set_zero(r[1]);
fp4_set_zero(r[2]);
return fp4_set_v(r[0]);
}
static int fp12_set_w(fp12_t r)
{
fp4_set_zero(r[0]);
fp4_set_zero(r[2]);
return fp4_set_one(r[1]);
}
static int fp12_set_w_sqr(fp12_t r)
{
fp4_set_zero(r[0]);
fp4_set_zero(r[1]);
return fp4_set_one(r[2]);
}
static int fp12_equ(const fp12_t a, const fp12_t b)
{
return fp4_equ(a[0], b[0])
&& fp4_equ(a[1], b[1])
&& fp4_equ(a[2], b[2]);
}
static int fp12_add(fp12_t r, const fp12_t a, const fp12_t b, const BIGNUM *p, BN_CTX *ctx)
{
return fp4_add(r[0], a[0], b[0], p, ctx)
&& fp4_add(r[1], a[1], b[1], p, ctx)
&& fp4_add(r[2], a[2], b[2], p, ctx);
}
static int fp12_dbl(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *ctx)
{
return fp4_dbl(r[0], a[0], p, ctx)
&& fp4_dbl(r[1], a[1], p, ctx)
&& fp4_dbl(r[2], a[2], p, ctx);
}
static int fp12_tri(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *ctx)
{
return fp12_dbl(r, a, p, ctx)
&& fp12_add(r, r, a, p, ctx);
}
static int fp12_sub(fp12_t r, const fp12_t a, const fp12_t b, const BIGNUM *p, BN_CTX *ctx)
{
return fp4_sub(r[0], a[0], b[0], p, ctx)
&& fp4_sub(r[1], a[1], b[1], p, ctx)
&& fp4_sub(r[2], a[2], b[2], p, ctx);
}
static int fp12_neg(fp12_t r, const fp12_t a, const BIGNUM *p)
{
return fp4_neg(r[0], a[0], p)
&& fp4_neg(r[1], a[1], p)
&& fp4_neg(r[2], a[2], p);
}
static int fp12_mul(fp12_t r, const fp12_t a, const fp12_t b, const BIGNUM *p, BN_CTX *ctx)
{
fp4_t t;
if (!fp4_init(t, ctx)
/* r0 = a0 * b0 + a1 * b2 * v + a2 * b1 * v */
|| !fp4_mul(r[0], a[0], b[0], p, ctx)
|| !fp4_mul_v(t, a[1], b[2], p, ctx)
|| !fp4_add(r[0], r[0], t, p, ctx)
|| !fp4_mul_v(t, a[2], b[1], p, ctx)
|| !fp4_add(r[0], r[0], t, p, ctx)
/* r1 = a0*b1 + a1*b0 + a2*b2*v */
|| !fp4_mul(r[1], a[0], b[1], p, ctx)
|| !fp4_mul(t, a[1], b[0], p, ctx)
|| !fp4_add(r[1], r[1], t, p, ctx)
|| !fp4_mul_v(t, a[2], b[2], p, ctx)
|| !fp4_add(r[1], r[1], t, p, ctx)
/* r2 = a0*b2 + a1*b1 + a2*b0 */
|| !fp4_mul(r[2], a[0], b[2], p, ctx)
|| !fp4_mul(t, a[1], b[1], p, ctx)
|| !fp4_add(r[2], r[2], t, p, ctx)
|| !fp4_mul(t, a[2], b[0], p, ctx)
|| !fp4_add(r[2], r[2], t, p, ctx)) {
fp4_cleanup(t);
return 0;
}
fp4_cleanup(t);
return 1;
}
static int fp12_sqr(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *ctx)
{
fp4_t t;
if (!(fp4_init(t, ctx))
/* r0 = a0^2 + 2*a1*a2*v */
|| !fp4_sqr(r[0], a[0], p, ctx)
|| !fp4_mul_v(t, a[1], a[2], p, ctx)
|| !fp4_dbl(t, t, p, ctx)
|| !fp4_add(r[0], r[0], t, p, ctx)
/* r1 = 2*a0*a1 + a^2 * v */
|| !fp4_mul(r[1], a[0], a[1], p, ctx)
|| !fp4_dbl(r[1], r[1], p, ctx)
|| !fp4_sqr_v(t, a[2], p, ctx)
|| !fp4_add(r[1], r[1], t, p, ctx)
/* r2 = 2*a0*a2 + a1^2*/
|| !fp4_mul(r[2], a[0], a[2], p, ctx)
|| !fp4_dbl(r[2], r[2], p, ctx)
|| !fp4_sqr(t, a[1], p, ctx)
|| !fp4_add(r[2], r[2], t, p, ctx)) {
fp4_cleanup(t);
return 0;
}
fp4_cleanup(t);
return 1;
}
static int fp12_inv(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *ctx)
{
if (fp4_is_zero(a[2])) {
fp4_t k;
fp4_t t;
if (!fp4_init(t, ctx)) {
return 0;
}
if (!(fp4_init(k, ctx))
/* k = (a0^3 + a1^3 * v)^-1 */
|| !fp4_sqr(k, a[0], p, ctx)
|| !fp4_mul(k, k, a[0], p, ctx)
|| !fp4_sqr_v(t, a[1], p, ctx)
|| !fp4_mul(t, t, a[1], p, ctx)
|| !fp4_add(k, k, t, p, ctx)
|| !fp4_inv(k, k, p, ctx)
/* r0 = a0^2 * k */
|| !fp4_sqr(r[0], a[0], p, ctx)
|| !fp4_mul(r[0], r[0], k, p, ctx)
/* r1 = -(a0 * a1 * k) */
|| !fp4_mul(r[0], a[0], a[1], p, ctx)
|| !fp4_mul(r[0], r[0], k, p, ctx)
|| fp4_neg(r[0], r[0], p)
/* r2 = a1^2 * k */
|| !fp4_sqr(r[2], a[1], p, ctx)
|| !fp4_mul(r[2], r[2], k, p, ctx)) {
fp4_cleanup(k);
fp4_cleanup(t);
return 0;
}
fp4_cleanup(k);
fp4_cleanup(t);
return 1;
} else {
fp4_t t0, t1, t2, t3;
if (!(fp4_init(t0, ctx))
|| !(fp4_init(t1, ctx))
|| !(fp4_init(t2, ctx))
|| !(fp4_init(t3, ctx))
// CHECK THIS!!!!!
/* t0 = a1^2 - a0 * a1 */
|| !fp4_sqr(t0, a[1], p, ctx)
|| !fp4_mul(t1, a[0], a[2], p, ctx)
|| !fp4_sub(t0, t0, t1, p, ctx)
/* t1 = a0 * a1 - a2^2 * v */
|| !fp4_mul(t1, a[0], a[1], p, ctx)
|| !fp4_sqr_v(t2, a[2], p, ctx)
|| !fp4_sub(t1, t1, t2, p, ctx)
/* t2 = a0^2 - a1 * a2 * v */
|| !fp4_sqr(t2, a[0], p, ctx)
|| !fp4_mul_v(t3, a[1], a[2], p, ctx)
|| !fp4_sub(t2, t2, t3, p, ctx)
/* t3 = a2 * (t1^2 - t0 * t2)^-1 */
|| !fp4_sqr(t1, t1, p, ctx)
|| !fp4_mul(r[0], t0, t2, p, ctx)
|| !fp4_sub(t1, t1, r[0], p, ctx)
|| !fp4_mul(t3, a[2], t3, p, ctx)
|| !fp4_inv(t3, t3, p, ctx)
/* r0 = t2 * t3 */
|| !fp4_mul(r[0], t2, t3, p, ctx)
/* r1 = -(t1 * t3) */
|| !fp4_mul(r[1], t1, t3, p, ctx)
|| !fp4_inv(r[1], r[1], p, ctx)
/* r2 = t0 * t3 */
|| !fp4_mul(r[2], t0, t3, p, ctx)) {
fp4_cleanup(t0);
fp4_cleanup(t1);
fp4_cleanup(t2);
fp4_cleanup(t3);
return 0;
}
fp4_cleanup(t0);
fp4_cleanup(t1);
fp4_cleanup(t2);
fp4_cleanup(t3);
return 1;
}
return 1;
}
static int fp12_div(fp12_t r, const fp12_t a, const fp12_t b, const BIGNUM *p, BN_CTX *ctx)
{
return fp12_inv(r, b, p, ctx)
&& fp12_mul(r, a, r, p, ctx);
}
static int fp12_pow(fp12_t r, const fp12_t a, const BIGNUM *k, const BIGNUM *p, BN_CTX *ctx)
{
int n, i;
if (BN_is_zero(k)) {
return fp12_set_one(r);
}
n = BN_num_bits(k);
if (n < 1 || n > 256 * 12) {
return 0;
}
if (!fp12_copy(r, a)) {
return 0;
}
for (i = n - 2; i >= 0; i--) {
if (!fp12_sqr(r, r, p, ctx)) {
return 0;
}
if (BN_is_bit_set(k, i)) {
if (!fp12_mul(r, r, a, p, ctx)) {
return 0;
}
}
}
return 1;
}
static int point_init(point_t P, BN_CTX *ctx)
{
int r;
r = fp2_init(P.X, ctx);
r &= fp2_init(P.Y, ctx);
r &= fp2_init(P.Z, ctx);
r &= fp2_set_one(P.Y);
if (!r) {
fp2_cleanup(P.X);
fp2_cleanup(P.Y);
fp2_cleanup(P.Z);
return 0;
}
fp2_set_zero(P.X);
fp2_set_zero(P.Z);
return 1;
}
static void point_cleanup(point_t P)
{
fp2_cleanup(P.X);
fp2_cleanup(P.Y);
fp2_cleanup(P.Z);
}
static int point_copy(point_t R, const point_t P)
{
return fp2_copy(R.X, P.X)
&& fp2_copy(R.Y, P.Y)
&& fp2_copy(R.Z, P.Z);
}
static int point_set_infinity(point_t P)
{
fp2_set_zero(P.X);
fp2_set_zero(P.Z);
return fp2_set_one(P.Y);
}
static int point_is_at_infinity(point_t P)
{
return fp2_is_zero(P.X)
&& fp2_is_one(P.Y)
&& fp2_is_zero(P.Z);
}
static int point_equ(const point_t P, const point_t Q)
{
return fp2_equ(P.X, Q.X)
&& fp2_equ(P.Y, Q.Y)
&& fp2_equ(P.Z, Q.Z);
}
static int point_set_affine_coordinates(point_t P, const fp2_t x, const fp2_t y)
{
return fp2_copy(P.X, x)
&& fp2_copy(P.Y, y)
&& fp2_set_one(P.Z);
}
static int point_set_affine_coordinates_bignums(point_t P,
const BIGNUM *x0, const BIGNUM *x1, const BIGNUM *y0, const BIGNUM *y1)
{
return fp2_set(P.X, x0, x1)
&& fp2_set(P.Y, y0, y1)
&& fp2_set_one(P.Z);
}
static int point_get_affine_coordinates(const point_t P, fp2_t x, fp2_t y)
{
return fp2_copy(x, P.X)
&& fp2_copy(y, P.Y)
&& fp2_is_one(P.Z);
}
static int point_is_on_curve(point_t P, const BIGNUM *p, BN_CTX *ctx)
{
int r;
fp2_t x, y, t;
r = fp2_init(x, ctx);
r &= fp2_init(y, ctx);
r &= fp2_init(t, ctx);
if (!r) {
goto end;
}
if (!point_get_affine_coordinates(P, x, y)
|| !fp2_sqr(t, x, p, ctx)
|| !fp2_mul(x, x, t, p, ctx)
|| !fp2_add_word(x, x, 5, p, ctx)
|| !fp2_sqr(y, y, p, ctx)) {
r = 0;
goto end;
}
r = fp2_equ(x, y);
end:
fp2_cleanup(x);
fp2_cleanup(y);
fp2_cleanup(t);
return r;
}
static int point_dbl(point_t R, const point_t P, const BIGNUM *p, BN_CTX *ctx)
{
int r;
fp2_t x3, y3, x1, y1, lambda, t;
r = 1;
r &= fp2_init(x1, ctx);
r &= fp2_init(y1, ctx);
r &= fp2_init(x3, ctx);
r &= fp2_init(y3, ctx);
r &= fp2_init(lambda, ctx);
r &= fp2_init(t, ctx);
if (!r) {
goto end;
}
if (point_is_at_infinity(P)) {
r = point_set_infinity(R);
goto end;
}
if (!point_get_affine_coordinates(P, x1, y1)
/* lambda = 3 * x1^2 / 2 * y1 */
|| !fp2_sqr(lambda, x1, p, ctx)
|| !fp2_tri(lambda, lambda, p, ctx)
|| !fp2_dbl(t, y1, p, ctx)
|| !fp2_div(lambda, lambda, t, p, ctx)
/* x3 = lambda^2 - 2 * x1 */
|| !fp2_sqr(x3, lambda, p, ctx)
|| !fp2_dbl(t, x1, p, ctx)
|| !fp2_sub(x3, x3, t, p, ctx)
/* y3 = lambda * (x1 - x3) - y1 */
|| !fp2_sub(y3, x1, x3, p, ctx)
|| !fp2_mul(y3, lambda, y3, p, ctx)
|| !fp2_sub(y3, y3, y1, p, ctx)) {
r = 0;
goto end;
}
r = point_set_affine_coordinates(R, x3, y3);
end:
fp2_cleanup(x1);
fp2_cleanup(y1);
fp2_cleanup(x3);
fp2_cleanup(y3);
fp2_cleanup(lambda);
fp2_cleanup(t);
return r;
}
static int point_add(point_t R, const point_t P, const point_t Q, const BIGNUM *p, BN_CTX *ctx)
{
int r;
fp2_t x1;
fp2_t y1;
fp2_t x2;
fp2_t y2;
fp2_t x3;
fp2_t y3;
fp2_t lambda;
fp2_t t;
if (point_is_at_infinity(P)) {
return point_copy(R, Q);
}
if (point_is_at_infinity(Q)) {
return point_copy(R, P);
}
if (point_equ(P, Q)) {
return point_dbl(R, P, p, ctx);
}
r = 1;
r &= fp2_init(x1, ctx);
r &= fp2_init(y1, ctx);
r &= fp2_init(x2, ctx);
r &= fp2_init(y2, ctx);
r &= fp2_init(x3, ctx);
r &= fp2_init(y3, ctx);
r &= fp2_init(lambda, ctx);
r &= fp2_init(t, ctx);
if (!r) {
goto end;
}
r = 0;
if (!point_get_affine_coordinates(P, x1, y1)
|| !point_get_affine_coordinates(Q, x2, y2)
|| !fp2_add(t, y1, y2, p, ctx)) {
goto end;
}
if (fp2_equ(x1, x2) && fp2_is_zero(t)) {
r = point_set_infinity(R);
goto end;
}
/* lambda = (y2 - y1)/(x2 - x1) */
if (!fp2_sub(lambda, y2, y1, p, ctx)
|| !fp2_sub(t, x2, x1, p, ctx)
|| !fp2_div(lambda, lambda, t, p, ctx)
/* x3 = lambda^2 - x1 - x2 */
|| !fp2_sqr(x3, lambda, p, ctx)
|| !fp2_sub(x3, x3, x1, p, ctx)
|| !fp2_sub(x3, x3, x2, p, ctx)
/* y3 = lambda * (x1 - x3) - y1 */
|| !fp2_sub(y3, x1, x3, p, ctx)
|| !fp2_mul(y3, lambda, y3, p, ctx)
|| !fp2_sub(y3, y3, y1, p, ctx)) {
goto end;
}
r = point_set_affine_coordinates(R, x3, y3);
end:
fp2_cleanup(x1);
fp2_cleanup(y1);
fp2_cleanup(x2);
fp2_cleanup(y2);
fp2_cleanup(x3);
fp2_cleanup(y3);
fp2_cleanup(lambda);
fp2_cleanup(t);
return r;
}
static int point_neg(point_t R, const point_t P, const BIGNUM *p)
{
return fp2_copy(R.X, P.X)
&& fp2_neg(R.Y, P.Y, p)
&& fp2_copy(R.Z, P.Z);
}
static int point_sub(point_t R, const point_t P, const point_t Q, const BIGNUM *p, BN_CTX *ctx)
{
point_t T;
if (!point_init(T, ctx)
|| !point_neg(T, Q, p)
|| !point_add(R, P, T, p, ctx)) {
point_cleanup(T);
return 0;
}
point_cleanup(T);
return 1;
}
static int point_mul(point_t R, const BIGNUM *k, const point_t P, const BIGNUM *p, BN_CTX *ctx)
{
int i, n;
if (BN_is_zero(k)) {
return point_set_infinity(R);
}
if (!point_copy(R, P)) {
return 0;
}
n = BN_num_bits(k);
for (i = n - 2; i >= 0; i--) {
if (!point_dbl(R, R, p, ctx)) {
return 0;
}
if (BN_is_bit_set(k, i)) {
if (!point_add(R, R, P, p, ctx)) {
return 0;
}
}
}
return 1;
}
static int point_mul_generator(point_t R, const BIGNUM *k, const BIGNUM *p, BN_CTX *ctx)
{
point_t G;
point_init(G, ctx);
point_set_affine_coordinates_bignums(G,
SM9_get0_generator2_x0,
SM9_get0_generator2_x1,
SM9_get0_generator2_y0,
SM9_get0_generator2_y1);
return point_mul(R, k, G, p, ctx);
}
static int eval_tangent(fp12_t r, const fp12_t xP, const fp12_t yP,
const BIGNUM *xQ, const BIGNUM *yQ,
const BIGNUM *p, BN_CTX *ctx)
{
int ret;
fp12_t x, y, lambda, t;
ret = 1;
ret &= fp12_init(x, ctx);
ret &= fp12_init(y, ctx);
ret &= fp12_init(lambda, ctx);
ret &= fp12_init(t, ctx);
if (!ret) {
goto end;
}
ret = 0;
if (!fp12_set_bn(x, xQ)
|| !fp12_set_bn(y, yQ)
/* lambda = (3 * xP^2)/(2 * yP) */
|| !fp12_sqr(lambda, xP, p, ctx)
|| !fp12_tri(lambda, lambda, p, ctx)
|| !fp12_dbl(t, yP, p, ctx)
/* r = lambda * (x - xP) - y + yP */
|| !fp12_div(lambda, lambda, t, p, ctx)
|| !fp12_sub(r, x, xP, p, ctx)
|| !fp12_mul(r, lambda, r, p, ctx)
|| !fp12_sub(r, r, y, p, ctx)
|| !fp12_add(r, r, yP, p, ctx)) {
goto end;
}
ret = 1;
end:
fp12_cleanup(x);
fp12_cleanup(y);
fp12_cleanup(lambda);
fp12_cleanup(t);
return ret;
}
static int eval_line(fp12_t r, const fp12_t xT, const fp12_t yT,
const fp12_t xP, const fp12_t yP,
const BIGNUM *xQ, const BIGNUM *yQ,
const BIGNUM *p, BN_CTX *ctx)
{
int ret;
fp12_t x, y, lambda, t;
ret = 1;
ret &= fp12_init(x, ctx);
ret &= fp12_init(y, ctx);
ret &= fp12_init(lambda, ctx);
ret &= fp12_init(t, ctx);
if (!ret) {
goto end;
}
ret = 0;
if (!fp12_set_bn(x, xQ)
|| !fp12_set_bn(y, yQ)
/* lambda = (yT - yP)/(xT - xP) */
|| !fp12_sub(lambda, yT, yP, p, ctx)
|| !fp12_sub(t, xT, xP, p, ctx)
|| !fp12_div(lambda, lambda, t, p, ctx)
/* r = lambda * (x - xP) - y + yP */
|| !fp12_sub(r, x, xP, p, ctx)
|| !fp12_mul(r, lambda, r, p, ctx)
|| !fp12_sub(r, r, y, p, ctx)
|| !fp12_add(r, r, yP, p, ctx)) {
goto end;
}
ret = 1;
end:
fp12_cleanup(x);
fp12_cleanup(y);
fp12_cleanup(lambda);
fp12_cleanup(t);
return ret;
}
static int point_get_ext_affine_coordinates(const point_t *P, fp12_t x, fp12_t y, const BIGNUM *p, BN_CTX *ctx)
{
int r;
fp2_t xP;
fp2_t yP;
fp12_t wem2;
fp12_t wem3;
r = 1;
r &= fp2_init(xP, ctx);
r &= fp2_init(yP, ctx);
r &= fp12_init(wem2, ctx);
r &= fp12_init(wem2, ctx);
if (!r) {
goto end;
}
r = 0;
if (!point_get_affine_coordinates(P, xP, yP)
|| !fp12_set_fp2(x, xP)
|| !fp12_set_fp2(y, yP)
/* x = x * w^-2 */
|| !fp12_set_w2(wem2)
|| !fp12_inv(wem2, wem2, p, ctx)
|| !fp12_mul(x, x, wem2, p, ctx)
/* y = y * w^-3 */
|| !fp12_set_v(wem3)
|| !fp12_inv(wem3, wem3, p, ctx)
|| !fp12_mul(y, y, wem3, p, ctx)) {
goto end;
}
r = 1;
end:
fp2_cleanup(xP);
fp2_cleanup(yP);
fp12_cleanup(wem2);
fp12_cleanup(wem3);
return r;
}
static int point_frob(const point_t P, fp12_t x, fp12_t y, const BIGNUM *p, BN_CTX *ctx)
{
return point_get_ext_affine_coordinates(P, x, y, p, ctx)
&& fp12_pow(x, x, p, p, ctx)
&& fp12_pow(y, y, p, p, ctx);
}
static int point_frob_twice(const point_t P, fp12_t x, fp12_t y, const BIGNUM *p, BN_CTX *ctx)
{
return point_frob(P, x, y, p, ctx)
&& fp12_pow(x, x, p, p, ctx)
&& fp12_pow(y, y, p, p, ctx);
}
static int final_expo(fp12_t r, const fp12_t a, const BIGNUM *k, const BIGNUM *p, BN_CTX *ctx)
{
int i, n;
if (!fp12_copy(r, a)) {
return 0;
}
n = BN_num_bits(k);
for (i = n - 2; i >= 0; i--) {
if (!fp12_sqr(r, r, p, ctx)) {
return 0;
}
if (BN_is_bit_set(k, i)) {
if (!fp12_mul(r, r, a, p, ctx)) {
return 0;
}
}
}
return 1;
}
static int rate(fp12_t r, const point_t Q, const BIGNUM *xP, const BIGNUM *yP,
const BIGNUM *p, BN_CTX *ctx)
{
int i;
point_t T;
fp12_t f, g;
point_init(T, ctx);
point_copy(T, Q);
fp12_set_one(f);
for (i = n - 2; i >= 0; i++) {
eval(g, T, T, xP, yP);
fp12_sqr_to(f);
fp12_mul_to(f, g);
point_dbl_to(T);
if (abits[i]) {
eval(g, T, Q, xP, yP);
fp12_mul_to(f, g);
point_add_to(T, Q);
}
}
frob(Q, Q1);
frob_twice(Q, Q2);
eval(g, T, Q1, xP, yP);
fp12_mul_to(f, g);
point_add_to(T, Q1);
point_neg_to(Q2);
eval(g, T, Q, xP, yP);
fp12_mul_to(f, g);
//point_add_to(T, Q2);
final_expo(r, f);
return 0;
}
int test()
{
/* P2 generator of the twist curve */
char *x_P2_str[] = {
"85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141",
"3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B"};
char *y_P2_str[] = {
"17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96",
"A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7"};
/* ks signing master secret */
char *ks_str =
"0130E78459D78545CB54C587E02CF480CE0B66340F319F348A1D5B1F2DC5F4";
/* Ppubs = ks * P2 */
char *x_Ppubs_str[] = {
"9F64080B3084F733E48AFF4B41B565011CE0711C5E392CFB0AB1B6791B94C408",
"29DBA116152D1F786CE843ED24A3B573414D2177386A92DD8F14D65696EA5E32"};
char *y_Ppubs_str[] = {
"69850938ABEA0112B57329F447E3A0CBAD3E2FDB1A77F335E89E1408D0EF1C25",
"41E00A53DDA532DA1A7CE027B7A46F741006E85F5CDFF0730E75C05FB4E3216D"};
/* g = e(P1, Ppubs) */
char *g_str[] = {
"4E378FB5561CD0668F906B731AC58FEE25738EDF09CADC7A29C0ABC0177AEA6D",
"28B3404A61908F5D6198815C99AF1990C8AF38655930058C28C21BB539CE0000",
"38BFFE40A22D529A0C66124B2C308DAC9229912656F62B4FACFCED408E02380F",
"A01F2C8BEE81769609462C69C96AA923FD863E209D3CE26DD889B55E2E3873DB",
"67E0E0C2EED7A6993DCE28FE9AA2EF56834307860839677F96685F2B44D0911F",
"5A1AE172102EFD95DF7338DBC577C66D8D6C15E0A0158C7507228EFB078F42A6",
"1604A3FCFA9783E667CE9FCB1062C2A5C6685C316DDA62DE0548BAA6BA30038B",
"93634F44FA13AF76169F3CC8FBEA880ADAFF8475D5FD28A75DEB83C44362B439",
"B3129A75D31D17194675A1BC56947920898FBF390A5BF5D931CE6CBB3340F66D",
"4C744E69C4A2E1C8ED72F796D151A17CE2325B943260FC460B9F73CB57C9014B",
"84B87422330D7936EABA1109FA5A7A7181EE16F2438B0AEB2F38FD5F7554E57A",
"AAB9F06A4EEBA4323A7833DB202E4E35639D93FA3305AF73F0F071D7D284FCFB"};
/* r = rand(1, n-1) */
char *r_str =
"033C8616B06704813203DFD00965022ED15975C662337AED648835DC4B1CBE";
char *w_str[] = {
"81377B8FDBC2839B4FA2D0E0F8AA6853BBBE9E9C4099608F8612C6078ACD7563",
"815AEBA217AD502DA0F48704CC73CABB3C06209BD87142E14CBD99E8BCA1680F",
"30DADC5CD9E207AEE32209F6C3CA3EC0D800A1A42D33C73153DED47C70A39D2E",
"8EAF5D179A1836B359A9D1D9BFC19F2EFCDB829328620962BD3FDF15F2567F58",
"A543D25609AE943920679194ED30328BB33FD15660BDE485C6B79A7B32B01398",
"3F012DB04BA59FE88DB889321CC2373D4C0C35E84F7AB1FF33679BCA575D6765",
"4F8624EB435B838CCA77B2D0347E65D5E46964412A096F4150D8C5EDE5440DDF",
"0656FCB663D24731E80292188A2471B8B68AA993899268499D23C89755A1A897",
"44643CEAD40F0965F28E1CD2895C3D118E4F65C9A0E3E741B6DD52C0EE2D25F5",
"898D60848026B7EFB8FCC1B2442ECF0795F8A81CEE99A6248F294C82C90D26BD",
"6A814AAF475F128AEF43A128E37F80154AE6CB92CAD7D1501BAE30F750B3A9BD",
"1F96B08E97997363911314705BFB9A9DBB97F75553EC90FBB2DDAE53C8F68E42"};
const EC_GROUP *group;
const EC_POINT *P1;
const BIGNUM *n;
BIGNUM *p = NULL;
BIGNUM *a = NULL;
BIGNUM *b = NULL;
BIGNUM *ks = NULL;
point_t P2;
point_t Ppubs;
p = BN_new();
a = BN_new();
b = BN_new();
/* check curve is correct */
if (!(group = EC_GROUP_new_by_curve_name(NID_sm9bn256v1))
|| !EC_GROUP_get_curve_GFp(group, p, a, b, ctx)
|| !(P1 = EC_GROUP_get0_generator(group))
|| !(n = EC_GROUP_get0_order(group))
|| !POINT_is_on_curve(group, P1, ctx)) {
ERR_print_errors_fp(stderr);
goto end;
}
EC_POINT_mul(group, Q, n, NULL, NULL, ctx)
if (!POINT_is_at_infinity(Q)) {
}
point_mul_generator(Ppubs, ks, P2, p, ctx);
return 0;
}