From c7aa2cc1ff7dd2aa7d3ca4121caa810fa71dca61 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Fri, 21 Sep 2018 22:42:11 +0800 Subject: [PATCH] A workable SM9 R-ate pairing over BN curve This textbook version R-ate pairing is very slow. About 0.5 seconds on my Macbook Pro 2018 with 2.7 GHz Core i7. --- crypto/sm9/build.info | 3 +- crypto/sm9/sm9_lcl.h | 20 +- crypto/sm9/sm9_params.c | 66 +- crypto/sm9/sm9_rate.c | 1775 ++++++++++++++++++++++++++++-------- crypto/sm9/sm9_setup.c | 4 +- include/openssl/opensslv.h | 4 +- 6 files changed, 1457 insertions(+), 415 deletions(-) diff --git a/crypto/sm9/build.info b/crypto/sm9/build.info index 47d1d391..14268567 100644 --- a/crypto/sm9/build.info +++ b/crypto/sm9/build.info @@ -1,3 +1,4 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]=sm9_lib.c sm9_err.c sm9_asn1.c sm9_params.c \ - sm9_setup.c sm9_keygen.c sm9_sign.c sm9_enc.c sm9_exch.c + sm9_setup.c sm9_keygen.c sm9_sign.c sm9_enc.c sm9_exch.c \ + sm9_rate.c diff --git a/crypto/sm9/sm9_lcl.h b/crypto/sm9/sm9_lcl.h index 38c5e02b..f7f47dff 100644 --- a/crypto/sm9/sm9_lcl.h +++ b/crypto/sm9/sm9_lcl.h @@ -76,15 +76,8 @@ extern "C" { #endif - -const BIGNUM *SM9_get0_prime(void); -const BIGNUM *SM9_get0_order(void); -const BIGNUM *SM9_get0_trace(void); -const BIGNUM *SM9_get0_generator2_x0(void); -const BIGNUM *SM9_get0_generator2_x1(void); -const BIGNUM *SM9_get0_generator2_y0(void); -const BIGNUM *SM9_get0_generator2_y1(void); - +int SM9_rate_pairing(BIGNUM *r[12], const BIGNUM *xQ[2], const BIGNUM *yQ[2], + const BIGNUM *xP, const BIGNUM *yP, BN_CTX *ctx); struct SM9PublicParameters_st { ASN1_OBJECT *curve; @@ -136,7 +129,14 @@ int SM9_hash2(const EVP_MD *md, BIGNUM **r, const unsigned char *elem, size_t elemlen, const BIGNUM *range, BN_CTX *ctx); -EC_GROUP *EC_GROUP_new_sm9s256t1(void); +const BIGNUM *SM9_get0_prime(void); +const BIGNUM *SM9_get0_order(void); +const BIGNUM *SM9_get0_loop_count(void); +const BIGNUM *SM9_get0_final_exponent(void); +const BIGNUM *SM9_get0_generator2_x0(void); +const BIGNUM *SM9_get0_generator2_x1(void); +const BIGNUM *SM9_get0_generator2_y0(void); +const BIGNUM *SM9_get0_generator2_y1(void); #ifdef __cplusplus diff --git a/crypto/sm9/sm9_params.c b/crypto/sm9/sm9_params.c index 5bc161b5..2d887d31 100644 --- a/crypto/sm9/sm9_params.c +++ b/crypto/sm9/sm9_params.c @@ -60,8 +60,8 @@ #define BN_SM9_BN256_TOP (256+BN_BITS2-1)/BN_BITS2 -#define BN_SM9_TRACE_TOP (66+BN_BITS2-1)/BN_BITS2 -#define BN_SM9_FINAL_EXPO_TOP (66+BN_BITS2-1)/BN_BITS2 +#define BN_SM9_LOOP_TOP (66+BN_BITS2-1)/BN_BITS2 +#define BN_SM9_FINAL_EXPO_TOP (2816+BN_BITS2-1)/BN_BITS2 #if BN_BITS2 == 64 static const BN_ULONG _sm9bn256v1_prime[BN_SM9_BN256_TOP] = { @@ -74,7 +74,7 @@ static const BN_ULONG _sm9bn256v1_order[BN_SM9_BN256_TOP] = { 0xD603AB4FF58EC744ULL, 0xB640000002A3A6F1ULL, }; -static const BN_ULONG _sm9bn256v1_trace[BN_SM9_TRACE_TOP] = { +static const BN_ULONG _sm9bn256v1_loop[BN_SM9_LOOP_TOP] = { 0x400000000215D93EULL, 0x02ULL, }; @@ -93,7 +93,28 @@ static const BN_ULONG _sm9bn256v1_y2[][BN_SM9_BN256_TOP] = { }; static const BN_ULONG _sm9bn256v1_final_expo[BN_SM9_FINAL_EXPO_TOP] = { - 0x400000000215D93EULL, 0x02ULL, + 0x2FACDD0F0D042330ULL, 0xB19FE1764AC0B748ULL, + 0xC6135FEC864E1676ULL, 0x8E4890AB7E824DC7ULL, + 0x5B83E3D7E2D0B969ULL, 0xCBD806A8225955B0ULL, + 0x6FE5E935A4B5F799ULL, 0x0B48EE8FD4C31B8FULL, + 0x8478B1A3E843D1FAULL, 0xBB6793F9FE39F256ULL, + 0xB760558913D719F2ULL, 0xEFE915CAB1B62D11ULL, + 0x1D16182C1D978AD0ULL, 0x5BBD6C4AA78C62F3ULL, + 0xF703B00C9E53535AULL, 0x0F4C6983D64089BDULL, + 0xC3E3945F87BF2203ULL, 0xE804F361D729E88DULL, + 0x6B948EBD4AA170BAULL, 0x4550E98DCA2042C3ULL, + 0x5A54D51E82F7DD63ULL, 0x2FB14FC5412315ECULL, + 0xE2C3601D19F32C69ULL, 0x335D59C358AAC66EULL, + 0x96FD3135583D5AA1ULL, 0xB78BD480FF56FA06ULL, + 0xA4DEFA394C04689AULL, 0xCB5A6B4B9EC19BA7ULL, + 0x80357732739295EDULL, 0x3BED65F00632C9CCULL, + 0x93DC562FA23AFA5AULL, 0xF1C8D7D0598EEE9BULL, + 0xB97559B180EE9629ULL, 0x5ED57CD410455806ULL, + 0x239E0CB2A1387366ULL, 0x96F691269CEB7907ULL, + 0x93B5122D974B7BA1ULL, 0xBE8CB0476C5042CBULL, + 0x9BF41BCB4067AA64ULL, 0xDD9D1D3019DBA153ULL, + 0xC16BE7FBACA54D38ULL, 0xACEF6F4E86411255ULL, + 0x1A09A6AE43ADE454ULL, 0x061835E8B1259499ULL, }; #elif BN_BITS2 == 32 @@ -107,7 +128,7 @@ static const BN_ULONG _sm9bn256v1_order[BN_SM9_BN256_TOP] = { 0xF58EC744, 0xD603AB4F, 0x02A3A6F1, 0xB6400000, }; -static const BN_ULONG _sm9bn256v1_trace[BN_SM9_TRACE_TOP] = { +static const BN_ULONG _sm9bn256v1_loop[BN_SM9_LOOP_TOP] = { 0x0215D93E, 0x40000000, 0x02, }; @@ -126,7 +147,28 @@ static const BN_ULONG _sm9bn256v1_y2[][BN_SM9_BN256_TOP] = { }; static const BN_ULONG _sm9bn256v1_final_expo[BN_SM9_FINAL_EXPO_TOP] = { - 0, 0, 0 + 0x0D042330, 0x2FACDD0F, 0x4AC0B748, 0xB19FE176, + 0x864E1676, 0xC6135FEC, 0x7E824DC7, 0x8E4890AB, + 0xE2D0B969, 0x5B83E3D7, 0x225955B0, 0xCBD806A8, + 0xA4B5F799, 0x6FE5E935, 0xD4C31B8F, 0x0B48EE8F, + 0xE843D1FA, 0x8478B1A3, 0xFE39F256, 0xBB6793F9, + 0x13D719F2, 0xB7605589, 0xB1B62D11, 0xEFE915CA, + 0x1D978AD0, 0x1D16182C, 0xA78C62F3, 0x5BBD6C4A, + 0x9E53535A, 0xF703B00C, 0xD64089BD, 0x0F4C6983, + 0x87BF2203, 0xC3E3945F, 0xD729E88D, 0xE804F361, + 0x4AA170BA, 0x6B948EBD, 0xCA2042C3, 0x4550E98D, + 0x82F7DD63, 0x5A54D51E, 0x412315EC, 0x2FB14FC5, + 0x19F32C69, 0xE2C3601D, 0x58AAC66E, 0x335D59C3, + 0x583D5AA1, 0x96FD3135, 0xFF56FA06, 0xB78BD480, + 0x4C04689A, 0xA4DEFA39, 0x9EC19BA7, 0xCB5A6B4B, + 0x739295ED, 0x80357732, 0x0632C9CC, 0x3BED65F0, + 0xA23AFA5A, 0x93DC562F, 0x598EEE9B, 0xF1C8D7D0, + 0x80EE9629, 0xB97559B1, 0x10455806, 0x5ED57CD4, + 0xA1387366, 0x239E0CB2, 0x9CEB7907, 0x96F69126, + 0x974B7BA1, 0x93B5122D, 0x6C5042CB, 0xBE8CB047, + 0x4067AA64, 0x9BF41BCB, 0x19DBA153, 0xDD9D1D30, + 0xACA54D38, 0xC16BE7FB, 0x86411255, 0xACEF6F4E, + 0x43ADE454, 0x1A09A6AE, 0xB1259499, 0x061835E8, }; #else @@ -149,10 +191,10 @@ static const BIGNUM _bignum_sm9bn256v1_order = { BN_FLG_STATIC_DATA }; -static const BIGNUM _bignum_sm9bn256v1_trace = { - (BN_ULONG *)_sm9bn256v1_trace, - BN_SM9_TRACE_TOP, - BN_SM9_TRACE_TOP, +static const BIGNUM _bignum_sm9bn256v1_loop = { + (BN_ULONG *)_sm9bn256v1_loop, + BN_SM9_LOOP_TOP, + BN_SM9_LOOP_TOP, 0, BN_FLG_STATIC_DATA }; @@ -227,9 +269,9 @@ const BIGNUM *SM9_get0_order(void) return &_bignum_sm9bn256v1_order; } -const BIGNUM *SM9_get0_trace(void) +const BIGNUM *SM9_get0_loop_count(void) { - return &_bignum_sm9bn256v1_trace; + return &_bignum_sm9bn256v1_loop; } const BIGNUM *SM9_get0_final_exponent(void) diff --git a/crypto/sm9/sm9_rate.c b/crypto/sm9/sm9_rate.c index cf30c62e..a9a11b90 100644 --- a/crypto/sm9/sm9_rate.c +++ b/crypto/sm9/sm9_rate.c @@ -58,15 +58,13 @@ typedef BIGNUM *fp2_t[2]; typedef fp2_t fp4_t[2]; typedef fp4_t fp12_t[3]; -typedef struct { +typedef struct point_t { 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) { @@ -74,11 +72,13 @@ static int fp2_init(fp2_t a, BN_CTX *ctx) 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; } @@ -104,6 +104,13 @@ static int fp2_is_zero(const fp2_t a) && BN_is_zero(a[1]); } +static int fp2_print(const fp2_t a) +{ + printf("%s\n", BN_bn2hex(a[0])); + printf("%s\n", BN_bn2hex(a[1])); + return 1; +} + static int fp2_is_one(const fp2_t a) { return BN_is_one(a[0]) @@ -134,12 +141,24 @@ static int fp2_set(fp2_t r, const BIGNUM *a0, const BIGNUM *a1) && BN_copy(r[1], a1); } +static int fp2_set_hex(fp2_t r, const char *str[2]) +{ + return BN_hex2bn(&r[0], str[0]) + && BN_hex2bn(&r[1], str[1]); +} + static int fp2_set_u(fp2_t r) { BN_zero(r[0]); return BN_one(r[1]); } +static int fp2_set_5u(fp2_t r) +{ + BN_zero(r[0]); + return BN_set_word(r[1], 5); +} + static int fp2_set_bn(fp2_t r, const BIGNUM *a) { BN_zero(r[1]); @@ -157,6 +176,14 @@ 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_equ_hex(const fp2_t a, const char *str[2], BN_CTX *ctx) +{ + fp2_t t; + fp2_init(t, ctx); + fp2_set_hex(t, str); + return fp2_equ(a, t); +} + static int fp2_add_word(fp2_t r, const fp2_t a, unsigned long b, const BIGNUM *p, BN_CTX *ctx) { BIGNUM *w = NULL; @@ -185,10 +212,15 @@ static int fp2_dbl(fp2_t r, const fp2_t a, const BIGNUM *p, BN_CTX *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); + fp2_t t; + if (!fp2_init(t, ctx) + || !fp2_dbl(t, a, p, ctx) + || !fp2_add(r, t, a, p, ctx)) { + fp2_cleanup(t); + return 0; + } + fp2_cleanup(t); + return 1; } static int fp2_sub(fp2_t r, const fp2_t a, const fp2_t b, const BIGNUM *p, BN_CTX *ctx) @@ -197,94 +229,139 @@ static int fp2_sub(fp2_t r, const fp2_t a, const fp2_t b, const BIGNUM *p, BN_CT && 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) +static int fp2_neg(fp2_t r, const fp2_t a, const BIGNUM *p, BN_CTX *ctx) { - return BN_sub(r[0], p, a[0]) - && BN_sub(r[1], p, a[1]); + return BN_mod_sub(r[0], p, a[0], p, ctx) + && BN_mod_sub(r[1], p, a[1], p, ctx); } static int fp2_mul(fp2_t r, const fp2_t a, const fp2_t b, const BIGNUM *p, BN_CTX *ctx) { BIGNUM *t = NULL; + BIGNUM *r0 = NULL; + BIGNUM *r1 = NULL; if (!(t = BN_CTX_get(ctx)) + || !(r0 = BN_CTX_get(ctx)) + || !(r1 = BN_CTX_get(ctx)) + /* r0 = a0 * b0 - 2 * a1 * b1 */ - || !BN_mod_mul(r[0], a[0], b[0], p, ctx) + || !BN_mod_mul(r0, 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) + || !BN_mod_sub(r0, r0, t, p, ctx) /* r1 = a0 * b1 + a1 * b0 */ - || !BN_mod_mul(r[1], a[0], b[1], p, ctx) + || !BN_mod_mul(r1, 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_mod_add(r1, r1, t, p, ctx) + + || !BN_copy(r[0], r0) + || !BN_copy(r[1], r1)) { BN_free(t); + BN_free(r0); + BN_free(r1); return 0; } BN_free(t); + BN_free(r0); + BN_free(r1); 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 *r0 = NULL; + BIGNUM *r1 = NULL; BIGNUM *t = NULL; - if (!(t = BN_CTX_get(ctx)) + if (!(r0 = BN_CTX_get(ctx)) + || !(r1 = BN_CTX_get(ctx)) + || !(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(r0, 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) + || !BN_mod_add(r0, r0, t, p, ctx) + || !BN_mod_add(r0, r0, r0, p, ctx) + || !BN_mod_sub(r0, p, r0, p, ctx) /* r1 = a0 * b0 - 2 * a1 * b1 */ - || !BN_mod_mul(r[1], a[0], b[0], p, ctx) + || !BN_mod_mul(r1, 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_mod_sub(r1, r1, t, p, ctx) + + || !BN_copy(r[0], r0) + || !BN_copy(r[1], r1)) { + BN_free(r0); + BN_free(r1); BN_free(t); return 0; } + BN_free(r0); + BN_free(r1); BN_free(t); return 1; } static int fp2_sqr(fp2_t r, const fp2_t a, const BIGNUM *p, BN_CTX *ctx) { + BIGNUM *r0 = NULL; + BIGNUM *r1 = NULL; BIGNUM *t = NULL; - if (!(t = BN_CTX_get(ctx)) + if (!(r0 = BN_CTX_get(ctx)) + || !(r1 = BN_CTX_get(ctx)) + ||!(t = BN_CTX_get(ctx)) /* r0 = a0^2 - 2 * a1^2 */ - || !BN_mod_sqr(r[0], a[0], p, ctx) + || !BN_mod_sqr(r0, 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) + || !BN_mod_sub(r0, r0, 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_mod_mul(r1, a[0], a[1], p, ctx) + || !BN_mod_add(r1, r1, r1, p, ctx) + || !BN_copy(r[0], r0) + || !BN_copy(r[1], r1)) { + BN_free(r0); + BN_free(r1); BN_free(t); return 0; } + BN_free(r0); + BN_free(r1); BN_free(t); return 1; } static int fp2_sqr_u(fp2_t r, const fp2_t a, const BIGNUM *p, BN_CTX *ctx) { + BIGNUM *r0 = NULL; + BIGNUM *r1 = NULL; BIGNUM *t = NULL; - if (!(t = BN_CTX_get(ctx)) + if (!(r0 = BN_CTX_get(ctx)) + || !(r1 = BN_CTX_get(ctx)) + || !(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) + || !BN_mod_mul(r0, a[0], a[1], p, ctx) + || !BN_mod_add(r0, r0, r0, p, ctx) + || !BN_mod_add(r0, r0, r0, p, ctx) + || !BN_mod_sub(r0, p, r0, p, ctx) /* r1 = a0^2 - 2 * a1^2 */ - || !BN_mod_sqr(r[1], a[0], p, ctx) + || !BN_mod_sqr(r1, 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_mod_sub(r1, r1, t, p, ctx) + + || !BN_copy(r[0], r0) + || !BN_copy(r[1], r1)) { + BN_free(r0); + BN_free(r1); BN_free(t); return 0; } + BN_free(r0); + BN_free(r1); BN_free(t); return 1; } @@ -295,9 +372,9 @@ static int fp2_inv(fp2_t r, const fp2_t a, const BIGNUM *p, BN_CTX *ctx) /* 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)) { + if (!BN_mod_add(r[1], a[1], a[1], p, ctx) + || !BN_mod_inverse(r[1], r[1], p, ctx) + || !BN_mod_sub(r[1], p, r[1], p, ctx)) { return 0; } @@ -326,6 +403,7 @@ static int fp2_inv(fp2_t r, const fp2_t a, const BIGNUM *p, BN_CTX *ctx) || !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; @@ -343,6 +421,122 @@ static int fp2_div(fp2_t r, const fp2_t a, const fp2_t b, const BIGNUM *p, BN_CT && fp2_mul(r, a, r, p, ctx); } +static int fp2_test(const BIGNUM *p, BN_CTX *ctx) +{ + const char *_a[] = { + "5f25ce2083fc970a6b9fdcd819fb1966d300af2afd58d480c59e02b320852183", + "9acddfef770bcdce452d72461f9d1482a8eff7662e1d591c70a7ce35f2f5710c"}; + const char *_b[] = { + "7114f0b7f50ebb85c124558f76f10bd277f71c27384deb67f229e582befde3ee", + "aa2714a30d7b8ae08b987fae8818881fb1952a1f53cda30a35c72841b174d7d"}; + const char *add_a_b[] = { + "19fabed87667ab9e56c087179b5d5df4290538071b2bd10cd2584d0dfc31bff4", + "a5705139a7e3867c4de6fa41081e9d04a4094a08235a334d140440ba0e0cbe89"}; + const char *dbl_a[] = { + "80b9c4105558723013c0e603e676b88840ecb0ae036ba25a5cc6a3e5db8fd89", + "7f5bbfdeeb73f4aab457393c49ab61c02fed5b8141bfc35cfbe0014402999c9b"}; + const char *tri_a[] = { + "67316a6189521e2d6cdbeb38586284ef570f7a35dd8f8ea66b6a6cf17e3e1f0c", + "63e99fce5fdc1b872381003273b9aefdb6eabf9c55622d9d87183452123dc82a"}; + const char *sub_a_b[] = { + "a450dd6891918276807f32989898d4d97cfc264edf85d7f4b8e3b85844d88312", + "902b6ea5463415203c73ea4b371b8c00add6a4c438e07eebcd4b5bb1d7de238f"}; + const char *neg_a[] = { + "571a31df7ea70fe76a63ce77db93adde4ef1e4201d221a5b1fd19874c2cc23fa", + "1b7220108b97d92390d63909d5f1b2c279029be4ec5d95bf74c7ccf1f05bd471"}; + const char *mul_a_b[] = { + "87c654e6949d4f119504b210360cc580fc5365c6d34c1321aec27fcf5a1f15b1", + "36e98d79d712f6a3d1bc6d5ac5a055ee0fcbf088c8744e6e943369538e863eb7"}; + const char *mulu_a_b[] = { + "486ce50c547db9aa328ad09a6a4e1b69025ab239899251febd08c880c644c80f", + "87c654e6949d4f119504b210360cc580fc5365c6d34c1321aec27fcf5a1f15b1"}; + const char *sqr_a[] = { + "b6011ba4cb9f083149a717c7829eb292c31a0800caf88db28bc71f5a084a0405", + "3a16d18809fca540de3543bdfa3317b45bd8117ce6e6a6be5837fbe70350b684"}; + const char *sqru_a[] = { + "42125cefeeaa5c70199923d4012897dc6a4270514cada15f34ffa359dcafd875", + "b6011ba4cb9f083149a717c7829eb292c31a0800caf88db28bc71f5a084a0405"}; + const char *inv_a[] = { + "5d25a81c4b20b093804befda14731ad2dfa436a450e8b40cf91939ba94fe84be", + "b317556351e184acb06cf1171069fcf3e9a36b60ca8cd718f55ff0c5769ad325"}; + const char *div_a_b[] = { + "107048b3442ccc880691cbeb5005bbeb3e71fbe1ec3899971b6caecd224b7dd9", + "7716a52c4911f52b519d9ec928b56561008469bf3403508d40a324bcd17f4a17"}; + const char *inv_1[] = { + "1", + "0"}; + const char *inv_u[] = { + "0", + "5b2000000151d378eb01d5a7fac763a290f949a58d3d776df2b7cd93f1a8a2be"}; + + + fp2_t a, b, r; + int ok; + + fp2_init(a, ctx); + fp2_init(b, ctx); + fp2_init(r, ctx); + + fp2_set_hex(a, _a); + fp2_set_hex(b, _b); + + fp2_add(r, a, b, p, ctx); + ok = fp2_equ_hex(r, add_a_b, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_dbl(r, a, p, ctx); + ok = fp2_equ_hex(r, dbl_a, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_tri(r, a, p, ctx); + ok = fp2_equ_hex(r, tri_a, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_sub(r, a, b, p, ctx); + ok = fp2_equ_hex(r, sub_a_b, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_neg(r, a, p, ctx); + ok = fp2_equ_hex(r, neg_a, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_mul(r, a, b, p, ctx); + ok = fp2_equ_hex(r, mul_a_b, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_mul_u(r, a, b, p, ctx); + ok = fp2_equ_hex(r, mulu_a_b, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_sqr(r, a, p, ctx); + ok = fp2_equ_hex(r, sqr_a, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_sqr_u(r, a, p, ctx); + ok = fp2_equ_hex(r, sqru_a, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_inv(r, a, p, ctx); + ok = fp2_equ_hex(r, inv_a, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_div(r, a, b, p, ctx); + ok = fp2_equ_hex(r, div_a_b, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_set_one(r); + fp2_inv(r, r, p, ctx); + ok = fp2_equ_hex(r, inv_1, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp2_set_u(r); + fp2_inv(r, r, p, ctx); + ok = fp2_equ_hex(r, inv_u, ctx); + printf("fp2 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + return 1; +} + static int fp4_init(fp4_t a, BN_CTX *ctx) { int r; @@ -367,6 +561,14 @@ static void fp4_clear_cleanup(fp4_t a) fp2_clear_cleanup(a[1]); } +static int fp4_print(const fp4_t a) +{ + fp2_print(a[0]); + fp2_print(a[1]); + printf("\n"); + return 1; +} + static int fp4_is_zero(const fp4_t a) { return fp2_is_zero(a[0]) @@ -415,6 +617,12 @@ static int fp4_set(fp4_t r, const fp2_t a0, const fp2_t a1) && fp2_copy(r[1], a1); } +static int fp4_set_hex(fp4_t r, const char *str[4]) +{ + return fp2_set_hex(r[0], str) + && fp2_set_hex(r[1], str+2); +} + static int fp4_copy(fp4_t r, const fp4_t a) { return fp2_copy(r[0], a[0]) @@ -439,6 +647,14 @@ static int fp4_equ(const fp4_t a, const fp4_t b) && fp2_equ(a[1], b[1]); } +static int fp4_equ_hex(const fp4_t a, const char *str[4], BN_CTX *ctx) +{ + fp4_t t; + fp4_init(t, ctx); + fp4_set_hex(t, str); + return fp4_equ(a, t); +} + 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) @@ -457,112 +673,297 @@ static int fp4_sub(fp4_t r, const fp4_t a, const fp4_t b, const BIGNUM *p, BN_CT && fp2_sub(r[1], a[1], b[1], p, ctx); } -static int fp4_neg(fp4_t r, const fp4_t a, const BIGNUM *p) +static int fp4_neg(fp4_t r, const fp4_t a, const BIGNUM *p, BN_CTX *ctx) { - return fp2_neg(r[0], a[0], p) - &&fp2_neg(r[1], a[1], p); + return fp2_neg(r[0], a[0], p, ctx) + &&fp2_neg(r[1], a[1], p, ctx); } static int fp4_mul(fp4_t r, const fp4_t a, const fp4_t b, const BIGNUM *p, BN_CTX *ctx) { - fp2_t t; + fp2_t r0, r1, t; + + fp2_init(r0, ctx); + fp2_init(r1, ctx); + 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) + /* r0 = a0 * b0 + a1 * b1 * u */ + || !fp2_mul(r0, 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) + || !fp2_add(r0, r0, 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(r1, 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_add(r1, r1, t, p, ctx) + + || !fp2_copy(r[0], r0) + || !fp2_copy(r[1], r1)) { + fp2_cleanup(r0); + fp2_cleanup(r1); fp2_cleanup(t); return 0; } + fp2_cleanup(r0); + fp2_cleanup(r1); 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; + fp2_t r0, r1, t; + fp2_init(r0, ctx); + fp2_init(r1, ctx); 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) + /* r0 = a0 * b1 * u + a1 * b0 * u */ + || !fp2_mul_u(r0, 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) + || !fp2_add(r0, r0, t, p, ctx) - /* r[1] = a[0] * b[0] + a[1] * b[1] * u */ - || !fp2_mul(r[1], a[0], b[0], p, ctx) + /* r1 = a0 * b0 + a1 * b1 * u */ + || !fp2_mul(r1, 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_add(r1, r1, t, p, ctx) + + || !fp2_copy(r[0], r0) + || !fp2_copy(r[1], r1)) { + fp2_cleanup(r0); + fp2_cleanup(r1); fp2_cleanup(t); return 0; } + fp2_cleanup(r0); + fp2_cleanup(r1); 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; + fp2_t r0, r1, t; + fp2_init(r0, ctx); + fp2_init(r1, ctx); if (!fp2_init(t, ctx) - /* r[0] = a[0]^2 + a[1]^2 * u */ - || !fp2_sqr(r[0], a[0], p, ctx) + /* r0 = a0^2 + a1^2 * u */ + || !fp2_sqr(r0, 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_add(r0, r0, t, p, ctx) + /* r1 = 2 * (a0 * a1) */ + || !fp2_mul(r1, a[0], a[1], p, ctx) + || !fp2_dbl(r1, r1, p, ctx) + || !fp2_copy(r[0], r0) + || !fp2_copy(r[1], r1)) { + fp2_cleanup(r0); + fp2_cleanup(r1); fp2_cleanup(t); return 0; } + fp2_cleanup(r0); + fp2_cleanup(r1); 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; + fp2_t r0, r1, t; + fp2_init(r0, ctx); + fp2_init(r1, ctx); if (!fp2_init(t, ctx) - /* r[0] = 2 * (a[0] * a[1]) */ + /* r0 = 2 * (a0 * a1) */ || !fp2_mul_u(t, a[0], a[1], p, ctx) - || !fp2_dbl(r[0], t, p, ctx) + || !fp2_dbl(r0, t, p, ctx) - /* r[1] = a[0]^2 + a[1]^2 * u */ - || !fp2_sqr(r[1], a[0], p, ctx) + /* r1 = a0^2 + a1^2 * u */ + || !fp2_sqr(r1, a[0], p, ctx) || !fp2_sqr_u(t, a[1], p, ctx) - || !fp2_add(r[1], r[1], t, p, ctx)) { + || !fp2_add(r1, r1, t, p, ctx) + || !fp2_copy(r[0], r0) + || !fp2_copy(r[1], r1)) { + fp2_cleanup(r0); + fp2_cleanup(r1); fp2_cleanup(t); return 0; } + fp2_cleanup(r0); + fp2_cleanup(r1); 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; + fp2_t r0, r1, k; + fp2_init(r0, ctx); + fp2_init(r1, ctx); + + if (!fp2_init(k, ctx) - /* k = (a[1]^2 * u - a[0]^2)^-1 */ + /* k = (a1^2 * u - a0^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_sqr(r0, a[0], p, ctx) + || !fp2_sub(k, k, r0, 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) + /* r0 = -(a0 * k) */ + || !fp2_mul(r0, a[0], k, p, ctx) + || !fp2_neg(r0, r0, p, ctx) - /* r[1] = a[1] * k */ - || !fp2_mul(r[1], a[1], k, p, ctx)) { + /* r1 = a1 * k */ + || !fp2_mul(r1, a[1], k, p, ctx) + + || !fp2_copy(r[0], r0) + || !fp2_copy(r[1], r1)) { + fp2_cleanup(r0); + fp2_cleanup(r1); fp2_cleanup(k); return 0; } + fp2_cleanup(r0); + fp2_cleanup(r1); fp2_cleanup(k); return 1; } +static int fp4_test(const BIGNUM *p, BN_CTX *ctx) +{ + const char *_a[] = { + "bec057c34cec656c05f236d9399cd00c64319632885d200f964e4591dd7ca77", + "55a10432b9095a12c106019c97fa1ed2a484d84bbb750bcf6a378c3f85ba9d09", + "9eb75c7b34e0259a59385602bd2210b844e6b9f6396443eed06dbd701b48a26c", + "76f63f8fb8272b173eaf93cb79e57444c816ef099b3fb11057977d1f3f50eb8"}; + const char *_b[] = { + "1dd8569e8b7d7a53a362334330ff5b4e3beeb180466cf7d268c157ff724c2de7", + "48619106bcf6f34107318044223fa5ae3ec74573829f9873e4f06b41d0210762", + "79fdcb2d33f115ef5405c62b509be15adc14cc82abbe6f89978ed0de987377c6", + "71a8d1fd3d68cd689b9ed04872690c41858d98065b2535e70d1a6a8f2547f07e"}; + const char *add_a_b[] = { + "29c45c1ac04c40aa63c156b0c499284f0231cae36ef2c9d362263c589023f85e", + "9e02953976004d53c83781e0ba39c480e34c1dbf3e14a4434f27f78155dba46b", + "627527a8662d9497d73a70de182f2acdff08f32dcaa7c49c828cf326d06ad4b5", + "791835f638eb401a0f89c9852a076385d20f06f6f4d930f81293e261193cff36"}; + const char *dbl_a[] = { + "17d80af8699d8cad80be46db27339a018c8632c6510ba401f2c9c8b23baf94ee", + "ab4208657212b425820c03392ff43da54909b09776ea179ed46f187f0b753a12", + "872eb8f6671ca442dc6d00b584b55a2b67dae0a1584d9901bb6bdfb8533fff5b", + "edec7f1f704e562e7d5f2796f3cae889902dde13367f6220af2efa3e7ea1d70"}; + const char *sub_a_b[] = { + "a453aeddabf4f2f4f3009b7a582938f7ac46fb2dfc93c90a761327818edce20d", + "d3f732bfc1266d1b9d4815875ba792465bd92d838d5735b854720fdb59995a7", + "24b9914e00ef0fab05328fd76c862f5d68d1ed738da5d46538deec9182d52aa6", + "4c0691fbc0bd4c3aae4fd4443ac41247e8e66a355909b405ddcea86ab1fe63b7"}; + const char *neg_a[] = { + "aa53fa83cdd4e09b15a487e261f4fa445baf79e7f1f51cdaec0ab6cec5797b06", + "609efbcd499a4cdf14fda9b35d94a8727d6dbaff5f05e30c7b380ee85d96a874", + "1788a384cdc381577ccb554d386cb68cdd0bd954e116aaed1501ddb7c808a311", + "aed09c07072134406218b2133df07000d571245a80c6f3cadff62355ef5c36c5"}; + const char *mul_a_b[] = { + "8e897a274c44e47c7db00d58bf08c020472e75f1e008a8a34975a6c947587f80", + "e8b79955f768f30ab48aa1b12b305a71fd12e252f34345d7692d58adf908739", + "a647307d347637d0525d62f9148d9bd7aabfb9c93ec03a7575404e5d4fa64310", + "65cbf741cdf37a3459727a9fcd84b10cc8b1d4c1a3641556de11434b330daf04"}; + const char *mulv_a_b[] = { + "a0e8117c6960597af922616050142c70b2817d12ee2db30a0ebcafb960872cf2", + "a647307d347637d0525d62f9148d9bd7aabfb9c93ec03a7575404e5d4fa64310", + "8e897a274c44e47c7db00d58bf08c020472e75f1e008a8a34975a6c947587f80", + "e8b79955f768f30ab48aa1b12b305a71fd12e252f34345d7692d58adf908739"}; + const char *sqr_a[] = { + "fb487bb1bee1c8d21956f8b5b7b1d93c5e7087b02666fc475f63b65cf5a2198", + "3a4deaf2a26a4f42fdb3bd34ae1c866a2d1ae5f5d9739d66ec758a38661d7639", + "a089b0d9a76cc56a2db2b56ab0df6e15f7a76ba8ad15e1f3b20accb2245bd827", + "8ad9618cfbada9f4cb296b5f219267785bc4d9b4d3070048e5301972005bb37f"}; + const char *sqrv_a[] = { + "56cd3ce60debf9fa15b47fe1a7f8bf998c5b732c8ee7dd26007f036bc5eb23fc", + "a089b0d9a76cc56a2db2b56ab0df6e15f7a76ba8ad15e1f3b20accb2245bd827", + "fb487bb1bee1c8d21956f8b5b7b1d93c5e7087b02666fc475f63b65cf5a2198", + "3a4deaf2a26a4f42fdb3bd34ae1c866a2d1ae5f5d9739d66ec758a38661d7639"}; + const char *inv_a[] = { + "7aa3d284401216d78e171627742b5a5dc3af41c15e112ceba1eb9e12ea3780cf", + "99711ed85be3e353d43f87600a9f416b64e1778d92e6b3fc374bc94f59772f70", + "8be97927776cbf6b7a162a5268df1d6a184ecd4ee56cc36273a7127ceabbebd4", + "7b4b924e6c5e548d2c5467e6db40bf35858f690d312d35066821af199a81ff67"}; + const char *inv_1[] = { + "1", + "0", + "0", + "0"}; + const char *inv_u[] = { + "0", + "5b2000000151d378eb01d5a7fac763a290f949a58d3d776df2b7cd93f1a8a2be", + "0", + "0"}; + const char *inv_v[] = { + "0", + "0", + "0", + "5b2000000151d378eb01d5a7fac763a290f949a58d3d776df2b7cd93f1a8a2be"}; + + fp4_t r, a, b; + int ok; + + fp4_init(r, ctx); + fp4_init(a, ctx); + fp4_init(b, ctx); + + fp4_set_hex(a, _a); + fp4_set_hex(b, _b); + + fp4_add(r, a, b, p, ctx); + ok = fp4_equ_hex(r, add_a_b, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp4_dbl(r, a, p, ctx); + ok = fp4_equ_hex(r, dbl_a, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp4_sub(r, a, b, p, ctx); + ok = fp4_equ_hex(r, sub_a_b, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp4_neg(r, a, p, ctx); + ok = fp4_equ_hex(r, neg_a, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp4_mul(r, a, b, p, ctx); + ok = fp4_equ_hex(r, mul_a_b, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp4_mul_v(r, a, b, p, ctx); + ok = fp4_equ_hex(r, mulv_a_b, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp4_sqr(r, a, p, ctx); + ok = fp4_equ_hex(r, sqr_a, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp4_sqr_v(r, a, p, ctx); + ok = fp4_equ_hex(r, sqrv_a, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp4_inv(r, a, p, ctx); + ok = fp4_equ_hex(r, inv_a, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp4_set_one(r); + fp4_inv(r, r, p, ctx); + ok = fp4_equ_hex(r, inv_1, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp4_set_u(r); + fp4_inv(r, r, p, ctx); + ok = fp4_equ_hex(r, inv_u, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp4_set_v(r); + fp4_inv(r, r, p, ctx); + ok = fp4_equ_hex(r, inv_v, ctx); + printf("fp4 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + return 0; +} + + static int fp12_init(fp12_t a, BN_CTX *ctx) { int r; @@ -591,6 +992,14 @@ static void fp12_clear_cleanup(fp12_t a) fp4_clear_cleanup(a[2]); } +static int fp12_print(const fp12_t a) +{ + fp4_print(a[0]); + fp4_print(a[1]); + fp4_print(a[2]); + return 1; +} + static int fp12_is_zero(const fp12_t a) { return fp4_is_zero(a[0]) @@ -633,6 +1042,13 @@ static int fp12_set(fp12_t r, const fp4_t a0, const fp4_t a1, const fp4_t a2) && fp4_copy(r[2], a2); } +static int fp12_set_hex(fp12_t r, const char *str[12]) +{ + return fp4_set_hex(r[0], str) + && fp4_set_hex(r[1], str + 4) + && fp4_set_hex(r[2], str + 8); +} + static int fp12_set_fp4(fp12_t r, const fp4_t a) { fp4_set_zero(r[1]); @@ -696,6 +1112,14 @@ static int fp12_equ(const fp12_t a, const fp12_t b) && fp4_equ(a[2], b[2]); } +static int fp12_equ_hex(const fp12_t a, const char *str[12], BN_CTX *ctx) +{ + fp12_t t; + fp12_init(t, ctx); + fp12_set_hex(t, str); + return fp12_equ(a, t); +} + static int fp12_add(fp12_t r, const fp12_t a, const fp12_t b, const BIGNUM *p, BN_CTX *ctx) { @@ -713,8 +1137,16 @@ static int fp12_dbl(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *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); + fp12_t t; + fp12_init(t, ctx); + + if (!fp12_dbl(t, a, p, ctx) + || !fp12_add(r, t, a, p, ctx)) { + fp12_cleanup(t); + return 0; + } + fp12_cleanup(t); + return 1; } static int fp12_sub(fp12_t r, const fp12_t a, const fp12_t b, const BIGNUM *p, BN_CTX *ctx) @@ -724,70 +1156,97 @@ static int fp12_sub(fp12_t r, const fp12_t a, const fp12_t b, const BIGNUM *p, B && fp4_sub(r[2], a[2], b[2], p, ctx); } -static int fp12_neg(fp12_t r, const fp12_t a, const BIGNUM *p) +static int fp12_neg(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *ctx) { - return fp4_neg(r[0], a[0], p) - && fp4_neg(r[1], a[1], p) - && fp4_neg(r[2], a[2], p); + return fp4_neg(r[0], a[0], p, ctx) + && fp4_neg(r[1], a[1], p, ctx) + && fp4_neg(r[2], a[2], p, ctx); } static int fp12_mul(fp12_t r, const fp12_t a, const fp12_t b, const BIGNUM *p, BN_CTX *ctx) { - fp4_t t; + fp4_t r0, r1, r2, t; + fp4_init(r0, ctx); + fp4_init(r1, ctx); + fp4_init(r2, ctx); + 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(r0, 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_add(r0, r0, t, p, ctx) || !fp4_mul_v(t, a[2], b[1], p, ctx) - || !fp4_add(r[0], r[0], t, p, ctx) + || !fp4_add(r0, r0, t, p, ctx) /* r1 = a0*b1 + a1*b0 + a2*b2*v */ - || !fp4_mul(r[1], a[0], b[1], p, ctx) + || !fp4_mul(r1, 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_add(r1, r1, t, p, ctx) || !fp4_mul_v(t, a[2], b[2], p, ctx) - || !fp4_add(r[1], r[1], t, p, ctx) + || !fp4_add(r1, r1, t, p, ctx) /* r2 = a0*b2 + a1*b1 + a2*b0 */ - || !fp4_mul(r[2], a[0], b[2], p, ctx) + || !fp4_mul(r2, 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_add(r2, r2, t, p, ctx) || !fp4_mul(t, a[2], b[0], p, ctx) - || !fp4_add(r[2], r[2], t, p, ctx)) { + || !fp4_add(r2, r2, t, p, ctx) + || !fp4_copy(r[0], r0) + || !fp4_copy(r[1], r1) + || !fp4_copy(r[2], r2)) { + + fp4_cleanup(r0); + fp4_cleanup(r1); + fp4_cleanup(r2); fp4_cleanup(t); return 0; } + fp4_cleanup(r0); + fp4_cleanup(r1); + fp4_cleanup(r2); 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; + fp4_t r0, r1, r2, t; + fp4_init(r0, ctx); + fp4_init(r1, ctx); + fp4_init(r2, ctx); if (!(fp4_init(t, ctx)) /* r0 = a0^2 + 2*a1*a2*v */ - || !fp4_sqr(r[0], a[0], p, ctx) + || !fp4_sqr(r0, 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) + || !fp4_add(r0, r0, 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_mul(r1, a[0], a[1], p, ctx) + || !fp4_dbl(r1, r1, p, ctx) || !fp4_sqr_v(t, a[2], p, ctx) - || !fp4_add(r[1], r[1], t, p, ctx) + || !fp4_add(r1, r1, 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_mul(r2, a[0], a[2], p, ctx) + || !fp4_dbl(r2, r2, p, ctx) || !fp4_sqr(t, a[1], p, ctx) - || !fp4_add(r[2], r[2], t, p, ctx)) { + || !fp4_add(r2, r2, t, p, ctx) + || !fp4_copy(r[0], r0) + || !fp4_copy(r[1], r1) + || !fp4_copy(r[2], r2)) { + + fp4_cleanup(r0); + fp4_cleanup(r1); + fp4_cleanup(r2); fp4_cleanup(t); return 0; } + fp4_cleanup(r0); + fp4_cleanup(r1); + fp4_cleanup(r2); fp4_cleanup(t); return 1; } @@ -800,6 +1259,12 @@ static int fp12_inv(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *ctx) if (!fp4_init(t, ctx)) { return 0; } + + fp4_t r0, r1, r2; + fp4_init(r0, ctx); + fp4_init(r1, ctx); + fp4_init(r2, ctx); + if (!(fp4_init(k, ctx)) /* k = (a0^3 + a1^3 * v)^-1 */ || !fp4_sqr(k, a[0], p, ctx) @@ -808,19 +1273,21 @@ static int fp12_inv(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *ctx) || !fp4_mul(t, t, a[1], p, ctx) || !fp4_add(k, k, t, p, ctx) || !fp4_inv(k, k, p, ctx) + + /* r2 = a1^2 * k */ + || !fp4_sqr(r[2], a[1], p, ctx) + || !fp4_mul(r[2], r[2], k, p, ctx) + + /* r1 = -(a0 * a1 * k) */ + || !fp4_mul(r[1], a[0], a[1], p, ctx) + || !fp4_mul(r[1], r[1], k, p, ctx) + || !fp4_neg(r[1], r[1], 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); @@ -835,13 +1302,11 @@ static int fp12_inv(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *ctx) fp4_t t0, t1, t2, t3; if (!(fp4_init(t0, ctx)) - || !(fp4_init(t1, ctx)) - || !(fp4_init(t2, ctx)) + || !(fp4_init(t1, ctx)) //FIXME + || !(fp4_init(t2, ctx)) || !(fp4_init(t3, ctx)) - // CHECK THIS!!!!! - - /* t0 = a1^2 - a0 * a1 */ + /* t0 = a1^2 - a0 * a2 */ || !fp4_sqr(t0, a[1], p, ctx) || !fp4_mul(t1, a[0], a[2], p, ctx) || !fp4_sub(t0, t0, t1, p, ctx) @@ -857,22 +1322,22 @@ static int fp12_inv(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *ctx) || !fp4_sub(t2, t2, t3, p, ctx) /* t3 = a2 * (t1^2 - t0 * t2)^-1 */ - || !fp4_sqr(t1, t1, p, ctx) + || !fp4_sqr(t3, 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_sub(t3, t3, r[0], p, ctx) || !fp4_inv(t3, t3, p, ctx) + || !fp4_mul(t3, a[2], 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) + || !fp4_neg(r[1], r[1], p, ctx) /* r2 = t0 * t3 */ - || !fp4_mul(r[2], t0, t3, p, ctx)) { - + || !fp4_mul(r[2], t0, t3, p, ctx) + ) { fp4_cleanup(t0); fp4_cleanup(t1); fp4_cleanup(t2); @@ -890,6 +1355,7 @@ static int fp12_inv(fp12_t r, const fp12_t a, const BIGNUM *p, BN_CTX *ctx) return 1; } +//TODO: check this! 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) @@ -899,6 +1365,9 @@ static int fp12_div(fp12_t r, const fp12_t a, const fp12_t b, const BIGNUM *p, B static int fp12_pow(fp12_t r, const fp12_t a, const BIGNUM *k, const BIGNUM *p, BN_CTX *ctx) { int n, i; + fp12_t t; + + fp12_init(t, ctx); if (BN_is_zero(k)) { return fp12_set_one(r); @@ -909,113 +1378,494 @@ static int fp12_pow(fp12_t r, const fp12_t a, const BIGNUM *k, const BIGNUM *p, return 0; } - if (!fp12_copy(r, a)) { + if (!fp12_copy(t, a)) { return 0; } for (i = n - 2; i >= 0; i--) { - if (!fp12_sqr(r, r, p, ctx)) { + if (!fp12_sqr(t, t, p, ctx)) { return 0; } if (BN_is_bit_set(k, i)) { - if (!fp12_mul(r, r, a, p, ctx)) { + if (!fp12_mul(t, t, a, p, ctx)) { return 0; } } } + + fp12_copy(r, t); return 1; } -static int point_init(point_t P, BN_CTX *ctx) +static int fp12_test(const BIGNUM *p, BN_CTX *ctx) +{ + const char *_a[] = { + "3a4b2fdf33cfe01aab98d17aefc8d38b0508061c3117685839bd0dfdeb5783a8", + "88a9043bdc9abb43d241e7f62b0182d2c9f8de39d77d154a57e126d871e7bcc0", + "cd2a13d8e31bc262757be16f34fab3632bfdf4c5be36e86799037305a73210f", + "c407de563b8393c590e35b4df002bc9c79e3098558412a7d48bd62ca8723f3e", + "66cbdec2300eebf35b0ab8637a93e0174a4182957b853b227c2a1612adbac39d", + "481431cd7d6b54175b2b95e0036821ed9d757e383ae1a8d4b4ee95614271d328", + "4b1d12f271aa058193adc626fa8dd7c510678cd9f6a330c69652deaf6287948d", + "ab075f5760464947bdb5a644a1292776d5b6cfd735df54c3b4f1948f2cc1ac7", + "b16b0b0bd0c14d693f2bcb13c738669ed806e67b7b18d6f0bb62a2e8d94aeff6", + "7ca6249c1b6d5793aca0549ffaf1debe372a3c72129599afeae445865d0f53cd", + "16390ad0d7dd96377a198a2c0736278a453e39f006275b64d2027ea1570eac51", + "ab12e62fcda3b9e62074960a8b036f564b6d45bab4b183be000827a3183f2878"}; + const char *_b[] = { + "7d09b50545b09312f786b5e0486de52aa79578b18961ede71e8e2e0b8a3aebb8", + "280070ecb08554a8bb799271eb3214f2b582c69858e2771aec594d72cd067f66", + "18ef945e265cc1a1b77a2c60db66a97b5365f939bd0dcf1cce578a822ce2fd74", + "9b0690c98e2c054afc4ddb3cf9e6e45f2ed8dbbf1edfd8eae8950454dd2f5033", + "540a59f0db96dba0c8efc44d50dc3b55b0b1a421ba8964b76759f5fa2db4604f", + "2a17506aeb7ce73497db53143dedda0429d1430453ee17d743a7d1425c19b79e", + "1ca32ffef87f1aeda06046ca9d345445424f00300daf0fd66d37b2620572db62", + "18c11cc3b61d709d7ed976e3da5ba630bc49d17bda470c3aace50d4db3e8ae5d", + "4b91ac95d741011137c66858ca98dbbcd5744b77c51894e1fda0c5b80959cfd3", + "1d8e5cae7d4463ee8f37b73037066455b284cca92ca0255eef8b0733b1d7b7f", + "839ea9892563527b6e653cd9ba665d6284c7696d5aedc884e469cb90e352a91c", + "ad699cb305b6d98aaac6fdb684e59c0d194db0213214a7df4bbed0240545a520"}; + const char *add_a_b[] = { + "114e4e476dccc3bcd1bdc0b42a7f1708aaaeb829ffe676372dba0e1924129e3", + "b0a975288d200fec8dbb7a68163397c57f7ba4d2305f8c65443a744b3eee3c26", + "25c2359bb48e7dc7ded1ea77ceb654b18625d88618f13da347e7c1b287561e83", + "a7470eaef1e43e87555c10f1d8e71028f6770c577463eb92bd20da8185a18f71", + "49638b3090220a24df6d160d5e15427d900936c1b93b0fdfe1470e4f81dde6f", + "722b823868e83b4bf306e8f44155fbf1c746c13c8ecfc0abf89666a39e8b8ac6", + "67c042f16a29206f340e0cf197c22c0a52b68d0a0452409d038a911167fa6fef", + "237192b92c21d531fab4d148246e38a829a53e794da50186e8342696a6b4c924", + "46bcb7a1a55ea788a0ee881c9c427b168b889ea825b67cf6d393cd78ff537a4c", + "7e7f0a6703419dd29593d012fe6245039252893ca55f9c05d9dcf5f9982ccf4c", + "99d7b459fd40e8b2e87ec705c19c84ecca05a35d611523e9b66c4a323a61556d", + "a23c82e2d0b6ec7ef537e8711a5a441e42c86290cc4b3cc166575c9f3a33881b"}; + const char *dbl_a[] = { + "74965fbe679fc0355731a2f5df91a7160a100c38622ed0b0737a1bfbd6af0750", + "5b120877b691cf95ce80249c60743e6071ff2928947f3bb8ca52b289007e3403", + "19a5427b1c63784c4eaf7c2de69f566c657fbe98b7c6dd0cf3206e60b4e6421e", + "1880fbcac7707278b21c6b69be0057938f3c6130ab08254fa917ac5950e47e7c", + "1757bd845d7a30f4e011c576ff98f8e9729071dfdc8f876912e490fd782441bd", + "9028639afad6a82eb6572bc006d043db3aeafc7075c351a969dd2ac284e3a650", + "963a25e4e3540b03275b8c4df51baf8a20cf19b3ed46618d2ca5bd5ec50f291a", + "1560ebeaec08c928f7b6b4c8942524eedab6d9fae6bbea98769e3291e598358e", + "ac9616179edef3e0a853ead798e205f88e1b39abdbb6bf059155aaa9cf449a6f", + "430c493834370835833cfdf00054f6374c61e5990ab04483f058efe4d6cd621d", + "2c7215a1afbb2c6ef43314580e6c4f148a7c73e00c4eb6c9a404fd42ae1d58a2", + "9fe5cc5f98a3ccda6ae580c52078176774e7f82a4ee818a01aa0b41e4d2d0b73"}; + const char *tri_a[] = { + "aee18f9d9b6fa05002ca7470cf5a7aa10f18125493463908ad3729f9c2068af8", + "2d7b0cb39088e3e7cabe614295e6f9ee1a057417518162273cc43e398f14ab46", + "2677e3b8aa95347276073a44d9ef01a2983f9de513aa4b936cb0a5910f59632d", + "24c179b02b28abb50b2aa11e9d00835d56da91c9008c37f77da38285f956bdba", + "7e239c468d891ce83b1c7dda7a2cd900bcd1f4755814c28b8f0ea71025df055a", + "21fc9568759e55543b7f165014a99e83b66de75d962a0ba2395c24fbe40433fb", + "2b1738d7525a6992e505a724fa1ac00a0f441342c96ea377dd8900e64445782a", + "201161e0620d2dbd73920f2cde37b766481246f85a19dfe4b1ed4bdad8645055", + "a7c121236cfc9a58117c0a9b6a8ba552442f8cdc3c54a71a6748b26ac53e44e8", + "9726dd44d00b8d759d9a74005b80db061998ec002caef57f5cd9a43508b706d", + "42ab20728798c2a66e4c9e8415a2769ecfbaadd01276122e76077be4052c04f3", + "94b8b28f63a3dfceb5566b7fb5ecbf789e62aa99e91ead8235394099821aee6e"}; + const char *sub_a_b[] = { + "73817ad9f0c2f3f98a15c6ea9ce9b5a57f6520b5c230694d009e7b1a446ddd6d", + "60a8934f2c15669b16c855843fcf6de0147617a17e9a9e2f6b87d965a4e13d5a", + "aa230cdf6a78a17645e13d060d77c900014c795db9508e4590a847d610e16918", + "2779ed1bd82fdae332c405c7daa80eafbab7e824511f2898d1666cffae943488", + "12c184d154781052921af41629b7a4c1998fde73c0fbd66b14d020188006634e", + "1dfce16291ee6ce2c35042cbc57a47e973a43b33e6f390fd7146c41ee6581b8a", + "2e79e2f3792aea93f34d7f5c5d59837fce188ca9e8f420f0291b2c4d5d14b92b", + "a82f5931c28a9ae8d3058ed06545b38bd3042eccb391d7ed73d9a7232234b1e7", + "65d95e75f9804c58076562bafc9f8ae202929b03b600420ebdc1dd30cff12023", + "7acd3ed133991154c3acd92cf7817878dc01efa77fcb9759fbeb951321f1d84e", + "48da6147b51deaade1b7f8a2425e916ce26963cdc5b481bbd3084e38570d48b2", + "b3e9497cca90874d4bb143a3fbac9a8e541228e49d17caba99b8f2a6f64ac8d5"}; + const char *neg_a[] = { + "7bf4d020ced3c6d72a6ad9d505c5f3ba1cea8d2ee9638683abb28d29f7f9c1d5", + "2d96fbc42608ebae03c1c359ca8d447257f9b51142fdd9918d8e744f716988bd", + "a96d5ec27471eacbaeabed39023f1c0eef32b3febe9780556bdf63f788de246e", + "a9ff821a9eeb6db57cf5759b168e9b7b5a5462b2c4f6dc3410e3c4fb3adf063f", + "4f74213dd294bafe7af8f2ec7afae72dd7b110b59ef5b3b969458515359681e0", + "6e2bce32853852da7ad8156ff226a557847d1512df994607308105c6a0df7255", + "6b22ed0d90f9a1704255e528fb00ef80118b067123d7be154f1cbc7880c9b0f0", + "ab8f8a0a8c9f425d5a2850ebab7c34cdb497264da71cf98faa2081def0852ab6", + "4d4f4f431e2598896d7e03c2e5660a649ebaccf9f6217eb2a0cf83f0a065587", + "3999db63e7364f5e296356affa9ce886eac856d907e5552bfa8b55a18641f1b0", + "a006f52f2ac610ba5bea2123ee589fbadcb4595b14539377136d1c868c42992c", + "b2d19d034ffed0bb58f15456a8b57eed6854d9065c96b1de5677384cb121d05"}; + const char *mul_a_b[] = { + "b053bed5afdc274ecf4d5ed22d464f121545c877192cb8bc2ee213fbd18c6a6d", + "b5b637e1176fdc19fe6eca269ae7653766f4583d9cef7c4afdf479f9f90253d2", + "b4f0bdbcf61a49b3d05760978b3f81ae2e14df914d39db2f9250d66a05dc6925", + "acb2108b6694c3123885af6df5b9b3ab9b68930ec54b7fccfd7228bcb78e9fd3", + "606eb0f669124e2afa06f4ed23bee5ca9445a1a9cc6f08202564ed69aab0dd2", + "3f9ca64637e2ff3453e54a450a2f5a05c1d3254cd785d841cb16b6bad0879de5", + "4c8165e6d96c598acee552bf0a98833af5e44dc867ca8fe7f48aa158bac619e0", + "5d8c852ab5b21eec17dd9919a60e6d1ba24f9a8064af5675b6173ec6279dc35e", + "3dca5d804536983f2d46853d58dd994a9212f18ef3e8df749342d71a9a92989c", + "64af38a985084da07ccbae1a91d2c7f09e7779d0285a1b9b753860e9937c4a47", + "77fe4dbaca161d0f7f99b4f186d8d12449201e7ba574ebbbb45bab99406b119c", + "e9f3cfc4c197176ad588c1d3fa965172ff9f1046831a92490885af616c3edb4"}; + const char *sqr_a[] = { + "1e92886bddb591a8f6ba96d288bdfd7f2e50f6c7151c58e3682628f1827a0a19", + "a939f4ca345e7007c25484bb222cbac1877b3bc19fde66051c3b4ad1afcd3be3", + "a911367ed1020dc600b229e755fd0e892035a7833feb5d1ec9735b0606bde3f7", + "5064e0d6b9aa4c5d0b1a345f7e51de0789bd91753fbc92bd041733a0b5618b58", + "426fddbc40017ef829487b9644308737cde22889931cd3c25d6d6b9c5a80eacc", + "b2b8d0264942b6f2ba2fce697ffd663e1f7d2337d964a6a1f1d3a8f274293074", + "ee7c6cd61ae3316b70d47c6e0ffffff18e7f9a11a1b1a3d4faee189c42946af", + "4cd26db84bbad4051abfe8e65071eb45ae0cb9edad42fbaebc624a4ab1624c06", + "59168d22a22f0e835aafb8e47f9e3ca3ac0787d75472f5bb2a3200d3d8fe8901", + "916ad4377c2939b7fa7c9e4ca76c7191a60db21db13e028b411af8cac9305355", + "816985d7bc47c4ebb55b186b8eefd2609d01623b7a9f034f31a2434d0d022e49", + "b1f0bc64e20661ce1067112a7306ff9dcf2b2394b038062cfcb79652f92e4678"}; + const char *inv_a[] = { + "76003429929c9970eb611b8579900f9806b1acb8955a8effea9c28a1156fe2f1", + "90682a0a7b278173bb8aed9bd9fed33e1c36af5dc968f8f4e01c8133ce552e5f", + "a29d8805baa933bd50ff7ba55ea3feb3df8811d773c7fa4f846bbbddbb9a5acf", + "20b64affa212b98e4ea552f87be84ea52183bac9df7c4bdbe07212cc8b9654da", + "addbc46339a3c49e7e856d73255974d0a5fd65da56a36f536a298a4d8082069e", + "8c43a01e79cef927fc9b2ec58d63ecfdc720d47e3b9cfaf7edf1ec30fd9764ef", + "46da195353db6d51fb72c9134f14db01552e84452b70109f1aa9c5bdca80d9b6", + "8a72fe0032b82fab1e83b5cd8945fd6c9cbe14486a5b0b4b3ee0680d2ac38f15", + "5270e560c6f81f183614c77e37bb9dba009b6769c91a856505ac3954ef244aa3", + "8640186e2f43c293f19f3470645fbafcfe132b5eefc60b7e3004702f2e41b906", + "2a46b3cb4d9484e9a20aa399e2a1a3895646f5784849abe5f251b6bb1394d135", + "99c14f695f65df2b583f7669f30b60ce9b7f2b01036d89917f095792fd072788"}; + char *r_str = + "033C8616B06704813203DFD00965022ED15975C662337AED648835DC4B1CBE"; + char *w_str[] = { /* w = g^r */ + "1F96B08E97997363911314705BFB9A9DBB97F75553EC90FBB2DDAE53C8F68E42", + "6A814AAF475F128AEF43A128E37F80154AE6CB92CAD7D1501BAE30F750B3A9BD", + "898D60848026B7EFB8FCC1B2442ECF0795F8A81CEE99A6248F294C82C90D26BD", + "44643CEAD40F0965F28E1CD2895C3D118E4F65C9A0E3E741B6DD52C0EE2D25F5", + "0656FCB663D24731E80292188A2471B8B68AA993899268499D23C89755A1A897", + "4F8624EB435B838CCA77B2D0347E65D5E46964412A096F4150D8C5EDE5440DDF", + "3F012DB04BA59FE88DB889321CC2373D4C0C35E84F7AB1FF33679BCA575D6765", + "A543D25609AE943920679194ED30328BB33FD15660BDE485C6B79A7B32B01398", + "8EAF5D179A1836B359A9D1D9BFC19F2EFCDB829328620962BD3FDF15F2567F58", + "30DADC5CD9E207AEE32209F6C3CA3EC0D800A1A42D33C73153DED47C70A39D2E", + "815AEBA217AD502DA0F48704CC73CABB3C06209BD87142E14CBD99E8BCA1680F", + "81377B8FDBC2839B4FA2D0E0F8AA6853BBBE9E9C4099608F8612C6078ACD7563"}; + const char *inv_1[] = { + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0"}; + const char *inv_u[] = { + "0", + "5b2000000151d378eb01d5a7fac763a290f949a58d3d776df2b7cd93f1a8a2be", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0"}; + const char *inv_v[] = { + "0", + "0", + "0", + "5b2000000151d378eb01d5a7fac763a290f949a58d3d776df2b7cd93f1a8a2be", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0"}; + const char *inv_w[] = { + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "5b2000000151d378eb01d5a7fac763a290f949a58d3d776df2b7cd93f1a8a2be"}; + const char *inv_w2[] = { + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "5b2000000151d378eb01d5a7fac763a290f949a58d3d776df2b7cd93f1a8a2be", + "0", + "0", + "0", + "0"}; + + + fp12_t r, a, b; + int ok; + + fp12_init(r, ctx); + fp12_init(a, ctx); + fp12_init(b, ctx); + + fp12_set_hex(a, _a); + fp12_set_hex(b, _b); + + fp12_add(r, a, b, p, ctx); + ok = fp12_equ_hex(r, add_a_b, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_dbl(r, a, p, ctx); + ok = fp12_equ_hex(r, dbl_a, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_tri(r, a, p, ctx); + ok = fp12_equ_hex(r, tri_a, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_sub(r, a, b, p, ctx); + ok = fp12_equ_hex(r, sub_a_b, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_neg(r, a, p, ctx); + ok = fp12_equ_hex(r, neg_a, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_mul(r, a, b, p, ctx); + ok = fp12_equ_hex(r, mul_a_b, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_sqr(r, a, p, ctx); + ok = fp12_equ_hex(r, sqr_a, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_inv(r, a, p, ctx); + ok = fp12_equ_hex(r, inv_a, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_set_one(r); + fp12_inv(r, r, p, ctx); + ok = fp12_equ_hex(r, inv_1, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_set_u(r); + fp12_inv(r, r, p, ctx); + ok = fp12_equ_hex(r, inv_u, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_set_v(r); + fp12_inv(r, r, p, ctx); + ok = fp12_equ_hex(r, inv_v, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_set_w(r); + fp12_inv(r, r, p, ctx); + ok = fp12_equ_hex(r, inv_w, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_set_w_sqr(r); + fp12_inv(r, r, p, ctx); + ok = fp12_equ_hex(r, inv_w2, ctx); + printf("fp12 test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + return 0; +} + +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); + 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); + fp2_cleanup(P->X); + fp2_cleanup(P->Y); + fp2_cleanup(P->Z); return 0; } - fp2_set_zero(P.X); - fp2_set_zero(P.Z); + fp2_set_zero(P->X); + fp2_set_zero(P->Z); return 1; } -static void point_cleanup(point_t P) +static void point_cleanup(point_t *P) { - fp2_cleanup(P.X); - fp2_cleanup(P.Y); - fp2_cleanup(P.Z); + fp2_cleanup(P->X); + fp2_cleanup(P->Y); + fp2_cleanup(P->Z); } -static int point_copy(point_t R, const point_t P) +static void point_print(const point_t *P) { - return fp2_copy(R.X, P.X) - && fp2_copy(R.Y, P.Y) - && fp2_copy(R.Z, P.Z); + printf(" X1: %s\n", BN_bn2hex((P->X)[1])); + printf(" X0: %s\n", BN_bn2hex((P->X)[0])); + printf(" Y1: %s\n", BN_bn2hex((P->Y)[1])); + printf(" Y0: %s\n", BN_bn2hex((P->Y)[0])); + printf(" Z1: %s\n", BN_bn2hex((P->Z)[1])); + printf(" Z0: %s\n", BN_bn2hex((P->Z)[0])); + printf("\n"); } -static int point_set_infinity(point_t P) +static int point_copy(point_t *R, const point_t *P) { - fp2_set_zero(P.X); - fp2_set_zero(P.Z); - return fp2_set_one(P.Y); + return fp2_copy(R->X, P->X) + && fp2_copy(R->Y, P->Y) + && fp2_copy(R->Z, P->Z); } -static int point_is_at_infinity(point_t P) +static int point_set_to_infinity(point_t *P) { - return fp2_is_zero(P.X) - && fp2_is_one(P.Y) - && fp2_is_zero(P.Z); + fp2_set_zero(P->X); + fp2_set_zero(P->Z); + return fp2_set_one(P->Y); } -static int point_equ(const point_t P, const point_t Q) +static int point_is_at_infinity(const point_t *P) { - return fp2_equ(P.X, Q.X) - && fp2_equ(P.Y, Q.Y) - && fp2_equ(P.Z, Q.Z); + return fp2_is_zero(P->X) + && fp2_is_one(P->Y) + && fp2_is_zero(P->Z); } -static int point_set_affine_coordinates(point_t P, const fp2_t x, const fp2_t y) +static int point_equ(const point_t *P, const point_t *Q) { - return fp2_copy(P.X, x) - && fp2_copy(P.Y, y) - && fp2_set_one(P.Z); + 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_bignums(point_t P, +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_hex(point_t *P, const char *str[4]) +{ + fp2_set_hex(P->X, str); + fp2_set_hex(P->Y, str + 2); + fp2_set_one(P->Z); + return 1; +} + +static int point_equ_hex(const point_t *P, const char *str[4], BN_CTX *ctx) +{ + point_t T; + point_init(&T, ctx); + point_set_affine_coordinates_hex(&T, str); + return point_equ(P, &T); +} + +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); + 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) +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); + 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) +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 x, y, t; + 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(wem3, 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_w_sqr(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_set_ext_affine_coordinates(point_t *P, const fp12_t x, const fp12_t y, const BIGNUM *p, BN_CTX *ctx) +{ + fp12_t tx; + fp12_t ty; + + fp12_init(tx, ctx); + fp12_init(ty, ctx); + + fp12_set_w_sqr(tx); + fp12_set_v(ty); + fp12_mul(tx, x, tx, p, ctx); + fp12_mul(ty, y, ty, p, ctx); + + point_set_affine_coordinates(P, tx[0][0], ty[0][0]); + + fp12_cleanup(tx); + fp12_cleanup(ty); + return 1; +} + +static int point_is_on_curve(point_t *P, const BIGNUM *p, BN_CTX *ctx) +{ + int r; + fp2_t x, y, b, t; r = fp2_init(x, ctx); r &= fp2_init(y, ctx); + r &= fp2_init(b, ctx); r &= fp2_init(t, ctx); if (!r) { goto end; - } + } + + fp2_set_5u(b); if (!point_get_affine_coordinates(P, x, y) + /* x^3 + 5 * u */ || !fp2_sqr(t, x, p, ctx) || !fp2_mul(x, x, t, p, ctx) - || !fp2_add_word(x, x, 5, p, ctx) + || !fp2_add(x, x, b, p, ctx) + /* y^2 */ || !fp2_sqr(y, y, p, ctx)) { r = 0; goto end; @@ -1029,7 +1879,7 @@ end: return r; } -static int point_dbl(point_t R, const point_t P, const BIGNUM *p, BN_CTX *ctx) +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; @@ -1046,7 +1896,7 @@ static int point_dbl(point_t R, const point_t P, const BIGNUM *p, BN_CTX *ctx) } if (point_is_at_infinity(P)) { - r = point_set_infinity(R); + r = point_set_to_infinity(R); goto end; } @@ -1055,7 +1905,8 @@ static int point_dbl(point_t R, const point_t P, const BIGNUM *p, BN_CTX *ctx) || !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) + || !fp2_inv(t, t, p, ctx) + || !fp2_mul(lambda, lambda, t, p, ctx) /* x3 = lambda^2 - 2 * x1 */ || !fp2_sqr(x3, lambda, p, ctx) @@ -1082,7 +1933,7 @@ end: return r; } -static int point_add(point_t R, const point_t P, const point_t Q, const BIGNUM *p, BN_CTX *ctx) +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; @@ -1129,14 +1980,15 @@ static int point_add(point_t R, const point_t P, const point_t Q, const BIGNUM * } if (fp2_equ(x1, x2) && fp2_is_zero(t)) { - r = point_set_infinity(R); + r = point_set_to_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) + || !fp2_inv(t, t, p, ctx) + || !fp2_mul(lambda, lambda, t, p, ctx) /* x3 = lambda^2 - x1 - x2 */ || !fp2_sqr(x3, lambda, p, ctx) @@ -1164,32 +2016,34 @@ end: return r; } -static int point_neg(point_t R, const point_t P, const BIGNUM *p) +static int point_neg(point_t *R, const point_t *P, const BIGNUM *p, BN_CTX *ctx) { - return fp2_copy(R.X, P.X) - && fp2_neg(R.Y, P.Y, p) - && fp2_copy(R.Z, P.Z); + return fp2_copy(R->X, P->X) + && fp2_neg(R->Y, P->Y, p, ctx) + && 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) +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); + + memset(&T, 0, sizeof(T)); + if (!point_init(&T, ctx) + || !point_neg(&T, Q, p, ctx) + || !point_add(R, P, &T, p, ctx)) { + point_cleanup(&T); return 0; } - point_cleanup(T); + 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) +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); + return point_set_to_infinity(R); } if (!point_copy(R, P)) { @@ -1197,6 +2051,7 @@ static int point_mul(point_t R, const BIGNUM *k, const point_t P, const BIGNUM * } n = BN_num_bits(k); for (i = n - 2; i >= 0; i--) { + if (!point_dbl(R, R, p, ctx)) { return 0; } @@ -1210,49 +2065,157 @@ static int point_mul(point_t R, const BIGNUM *k, const point_t P, const BIGNUM * return 1; } -static int point_mul_generator(point_t R, const BIGNUM *k, const BIGNUM *p, BN_CTX *ctx) +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); + memset(&G, 0, sizeof(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 point_test(const BIGNUM *p, BN_CTX *ctx) +{ + const char *_G[] = { + "3722755292130b08d2aab97fd34ec120ee265948d19c17abf9b7213baf82d65b", + "85aef3d078640c98597b6027b441a01ff1dd2c190f5e93c454806c11d8806141", + "a7cf28d519be3da65f3170153d278ff247efba98a71a08116215bba5c999a7c7", + "17509b092e845c1266ba0d262cbee6ed0736a96fa347c8bd856dc76b84ebeb96"}; + const char *dbl_G[] = { + "2a74f8561b91993205eb512576ad56221ea5963f3da078240d55594fb051ea86", + "513f149ab53e94bb3a0367c61ff87670e025db30c57f84594e4ba4d7b3c656cf", + "8e3d9ec4e63d5b9f83081fb97b715430c8bfc6f1a1321a89627b9a4e8961c7bd", + "776de41db0511b8976d69c982dd4757d641487c68d13cbee7069396c20cd3459"}; + const char *tri_G[] = { + "9e5437ea263653ea0617ca82c5ce5db4937dece2f762a6fbdae7fb3032f9b154", + "4dd9b503b00f0e8334e5cbdc9ff80deb4b207a1b1fda2382f3812bd5687937c0", + "3d491f4ffb2a4ab249e396fe8e58b6e8cb23ef935309e576bc5a9a3b4fd97090", + "b1174c2d2b36cee03e1a7081eb71f60c35fac603f2b550218ec935c1e00bdd5b"}; + const char *neg_G[] = { + "3722755292130b08d2aab97fd34ec120ee265948d19c17abf9b7213baf82d65b", + "85aef3d078640c98597b6027b441a01ff1dd2c190f5e93c454806c11d8806141", + "e70d72ae8e5694b76d23b3ab8673752da02d8b27360e6ca8359df8219b79db6", + "9eef64f6d41f4adf6f499e29c8cfe0581abbe9db7733261e6001d3bc5e6559e7"}; + const char *sub_3G_G[] = { + "2a74f8561b91993205eb512576ad56221ea5963f3da078240d55594fb051ea86", + "513f149ab53e94bb3a0367c61ff87670e025db30c57f84594e4ba4d7b3c656cf", + "8e3d9ec4e63d5b9f83081fb97b715430c8bfc6f1a1321a89627b9a4e8961c7bd", + "776de41db0511b8976d69c982dd4757d641487c68d13cbee7069396c20cd3459"}; + const char *ten_G[] = { + "1e3188d71ed78f5541bc77b3bdc75df1c93d9811e26793bba71a3f30de6ee9be", + "b0a3030bffb5a431f593a2375865d04c8a83516c0af56c7c63fb17aacb96c44c", + "8d7e1a49cddc2eccd0b757967e3fb669f66397ee4ba232562ed5a72850606471", + "1d2a27fd716f0b2ab9c9a40191c5c7ac00c48f554b1e976dc4d25324f29a8531"}; + const char *ks = + "0130E78459D78545CB54C587E02CF480CE0B66340F319F348A1D5B1F2DC5F4"; + const char *Ppubs[] = { + "29DBA116152D1F786CE843ED24A3B573414D2177386A92DD8F14D65696EA5E32", + "9F64080B3084F733E48AFF4B41B565011CE0711C5E392CFB0AB1B6791B94C408", + "41E00A53DDA532DA1A7CE027B7A46F741006E85F5CDFF0730E75C05FB4E3216D", + "69850938ABEA0112B57329F447E3A0CBAD3E2FDB1A77F335E89E1408D0EF1C25"}; + + point_t G, P; + BIGNUM *k = BN_new(); + int ok; + + point_init(&G, ctx); + point_init(&P, ctx); + + point_set_affine_coordinates_bignums(&G, + SM9_get0_generator2_x0(), + SM9_get0_generator2_x1(), + SM9_get0_generator2_y0(), + SM9_get0_generator2_y1()); + + ok = point_equ_hex(&G, _G, ctx); + printf("point test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + ok = point_is_on_curve(&G, p, ctx); + printf("point test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + point_dbl(&P, &G, p, ctx); + ok = point_equ_hex(&P, dbl_G, ctx); + printf("point test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + point_add(&P, &P, &G, p, ctx); + ok = point_equ_hex(&P, tri_G, ctx); + printf("point test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + point_sub(&P, &P, &G, p, ctx); + ok = point_equ_hex(&P, sub_3G_G, ctx); + printf("point test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + point_neg(&P, &G, p, ctx); + ok = point_equ_hex(&P, neg_G, ctx); + printf("point test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + BN_set_word(k, 10); + point_mul(&P, k, &G, p, ctx); + ok = point_equ_hex(&P, ten_G, ctx); + printf("point test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + BN_hex2bn(&k, ks); + point_mul_generator(&P, k, p, ctx); + ok = point_equ_hex(&P, Ppubs, ctx); + printf("point test %d: %s\n", __LINE__, ok ? "ok" : "error"); + + fp12_t x, y; + + fp12_init(x, ctx); + fp12_init(y, ctx); + + point_get_ext_affine_coordinates(&G, x, y, p, ctx); + point_set_ext_affine_coordinates(&P, x, y, p, ctx); + + ok = point_equ(&P, &G); + printf("point test %d: %s\n", __LINE__, ok ? "ok" : "error"); - return point_mul(R, k, G, p, ctx); + //fp12_cleanup(x); + //fp12_cleanup(y); + return 1; } -static int eval_tangent(fp12_t r, const fp12_t xP, const fp12_t yP, - const BIGNUM *xQ, const BIGNUM *yQ, +static int eval_tangent(fp12_t r, const point_t *T, const BIGNUM *xP, const BIGNUM *yP, const BIGNUM *p, BN_CTX *ctx) { int ret; fp12_t x, y, lambda, t; + fp12_t xT, yT; ret = 1; ret &= fp12_init(x, ctx); ret &= fp12_init(y, ctx); ret &= fp12_init(lambda, ctx); ret &= fp12_init(t, ctx); + ret &= fp12_init(xT, ctx); + ret &= fp12_init(yT, ctx); if (!ret) { goto end; } + point_get_ext_affine_coordinates(T, xT, yT, p, ctx); + 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) + if (!fp12_set_bn(x, xP) + || !fp12_set_bn(y, yP) + /* lambda = (3 * xT^2)/(2 * yT) */ + || !fp12_sqr(lambda, xT, 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_dbl(t, yT, p, ctx) + || !fp12_inv(t, t, p, ctx) + || !fp12_mul(lambda, lambda, t, p, ctx) + + /* r = lambda * (x - xT) - y + yT */ + || !fp12_sub(r, x, xT, p, ctx) || !fp12_mul(r, lambda, r, p, ctx) || !fp12_sub(r, r, y, p, ctx) - || !fp12_add(r, r, yP, p, ctx)) { + || !fp12_add(r, r, yT, p, ctx)) { goto end; } ret = 1; @@ -1265,35 +2228,44 @@ end: 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, +static int eval_line(fp12_t r, const point_t *T, const point_t *Q, + const BIGNUM *xP, const BIGNUM *yP, const BIGNUM *p, BN_CTX *ctx) { int ret; fp12_t x, y, lambda, t; - + fp12_t xT, yT, xQ, yQ; + ret = 1; ret &= fp12_init(x, ctx); ret &= fp12_init(y, ctx); ret &= fp12_init(lambda, ctx); ret &= fp12_init(t, ctx); + ret &= fp12_init(xT, ctx); + ret &= fp12_init(yT, ctx); + ret &= fp12_init(xQ, ctx); + ret &= fp12_init(yQ, ctx); if (!ret) { goto end; } + point_get_ext_affine_coordinates(T, xT, yT, p, ctx); + point_get_ext_affine_coordinates(Q, xQ, yQ, p, ctx); + 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) + if (!fp12_set_bn(x, xP) + || !fp12_set_bn(y, yP) + /* lambda = (yT - yQ)/(xT - xQ) */ + || !fp12_sub(lambda, yT, yQ, p, ctx) + || !fp12_sub(t, xT, xQ, p, ctx) + || !fp12_inv(t, t, p, ctx) + || !fp12_mul(lambda, lambda, t, p, ctx) + + /* r = lambda * (x - xQ) - y + yQ */ + || !fp12_sub(r, x, xQ, p, ctx) || !fp12_mul(r, lambda, r, p, ctx) || !fp12_sub(r, r, y, p, ctx) - || !fp12_add(r, r, yP, p, ctx)) { + || !fp12_add(r, r, yQ, p, ctx)) { goto end; } ret = 1; @@ -1306,214 +2278,243 @@ end: 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) +static int frobenius(point_t *R, const point_t *P, const BIGNUM *p, BN_CTX *ctx) { - int r; - fp2_t xP; - fp2_t yP; - fp12_t wem2; - fp12_t wem3; + fp12_t x, y; - 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; - } + fp12_init(x, ctx); + fp12_init(y, ctx); - 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; + point_get_ext_affine_coordinates(P, x, y, p, ctx); -end: - fp2_cleanup(xP); - fp2_cleanup(yP); - fp12_cleanup(wem2); - fp12_cleanup(wem3); - return r; + fp12_pow(x, x, p, p, ctx); + fp12_pow(y, y, p, p, ctx); + + point_set_ext_affine_coordinates(R, x, y, p, ctx); + + fp12_cleanup(x); + fp12_cleanup(y); + return 1; } -static int point_frob(const point_t P, fp12_t x, fp12_t y, const BIGNUM *p, BN_CTX *ctx) +static int frobenius_twice(point_t *R, const point_t *P, 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); + frobenius(R, P, p, ctx); + frobenius(R, R, p, ctx); + return 1; } static int final_expo(fp12_t r, const fp12_t a, const BIGNUM *k, const BIGNUM *p, BN_CTX *ctx) { int i, n; + fp12_t t; - if (!fp12_copy(r, a)) { + fp12_init(t, ctx); + + if (!fp12_copy(t, a)) { return 0; } n = BN_num_bits(k); for (i = n - 2; i >= 0; i--) { - if (!fp12_sqr(r, r, p, ctx)) { + if (!fp12_sqr(t, t, p, ctx)) { return 0; } - if (BN_is_bit_set(k, i)) { - if (!fp12_mul(r, r, a, p, ctx)) { + if (!fp12_mul(t, t, a, p, ctx)) { return 0; } } } + fp12_copy(r, t); + return 1; +} + +static int rate(fp12_t f, const point_t *Q, const BIGNUM *xP, const BIGNUM *yP, + const BIGNUM *a, const BIGNUM *k, const BIGNUM *p, BN_CTX *ctx) +{ + int ret = 0; + int i, n; + point_t T, Q1, Q2; + fp12_t g; + + memset(&T, 0, sizeof(T)); + memset(&Q1, 0, sizeof(Q1)); + memset(&Q2, 0, sizeof(Q2)); + + point_init(&T, ctx); + point_init(&Q1, ctx); + point_init(&Q2, ctx); + fp12_init(g, ctx); + + fp12_set_one(f); + point_copy(&T, Q); + + n = BN_num_bits(a); + for (i = n - 2; i >= 0; i--) { + //printf("miller loop %d\n", i); + + /* f = f^2 * g_{T,T}(P) */ + eval_tangent(g, &T, xP, yP, p, ctx); + + //printf("g\n"); + //fp12_print(g); + + fp12_sqr(f, f, p, ctx); + fp12_mul(f, f, g, p, ctx); + + //printf("f\n"); + //fp12_print(f); + + /* T = 2 * T */ + point_dbl(&T, &T, p, ctx); + + if (BN_is_bit_set(a, i)) { + /* f = f * g_{T,Q}(P) */ + eval_line(g, &T, Q, xP, yP, p, ctx); + + //printf("g\n"); + //fp12_print(g); + + + fp12_mul(f, f, g, p, ctx); + + //printf("f\n"); + //fp12_print(f); + + /* T = T + Q */ + point_add(&T, &T, Q, p, ctx); + } + + } + + /* Q1 = (x^p, y^p) */ + frobenius(&Q1, Q, p, ctx); + + /* Q2 = (x^(p^2), y^(p^2)) */ + frobenius_twice(&Q2, Q, p, ctx); + + /* f = f * g_{T, Q1}(P) */ + eval_line(g, &T, &Q1, xP, yP, p, ctx); + fp12_mul(f, f, g, p, ctx); + + /* T = T + Q1 */ + point_add(&T, &T, &Q1, p, ctx); + + /* f = f * g_{T, -Q2}(P) */ + point_neg(&Q2, &Q2, p, ctx); + eval_line(g, &T, &Q2, xP, yP, p, ctx); + fp12_mul(f, f, g, p, ctx); + + /* T = T - Q2 */ + point_add(&T, &T, &Q2, p, ctx); + + /* f = f^((p^12 - 1)/n) */ + final_expo(f, f, k, p, ctx); + + + point_cleanup(&T); + point_cleanup(&Q1); + point_cleanup(&Q2); + fp12_cleanup(g); + return ret; +} + +static int params_test(void) +{ + const BIGNUM *p = SM9_get0_prime(); + const BIGNUM *a = SM9_get0_loop_count(); + const BIGNUM *k = SM9_get0_final_exponent(); + + printf("p = %s\n", BN_bn2dec(p)); + printf("a = %s\n", BN_bn2dec(a)); + printf("k = %s\n", BN_bn2dec(k)); return 1; } -static int rate(fp12_t r, const point_t Q, const BIGNUM *xP, const BIGNUM *yP, - const BIGNUM *p, BN_CTX *ctx) +static int sm9_rate(fp12_t r, const point_t *Q, const EC_POINT *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"}; - + int ret = 1; const EC_GROUP *group; + const BIGNUM *p; + const BIGNUM *a; + const BIGNUM *k; + BIGNUM *xP = NULL; + BIGNUM *yP = NULL; + + group = EC_GROUP_new_by_curve_name(NID_sm9bn256v1); + p = SM9_get0_prime(); + a = SM9_get0_loop_count(); + k = SM9_get0_final_exponent(); + + xP = BN_CTX_get(ctx); + yP = BN_CTX_get(ctx); + + EC_POINT_get_affine_coordinates_GFp(group, P, xP, yP, ctx); + + rate(r, Q, xP, yP, a, k, p, ctx); + + BN_free(xP); + BN_free(yP); + return ret; +} + +static int rate_test(void) +{ + const char *Ppubs_str[] = { + "29DBA116152D1F786CE843ED24A3B573414D2177386A92DD8F14D65696EA5E32", + "9F64080B3084F733E48AFF4B41B565011CE0711C5E392CFB0AB1B6791B94C408", + "41E00A53DDA532DA1A7CE027B7A46F741006E85F5CDFF0730E75C05FB4E3216D", + "69850938ABEA0112B57329F447E3A0CBAD3E2FDB1A77F335E89E1408D0EF1C25"}; + const char *g_str[] = { + "AAB9F06A4EEBA4323A7833DB202E4E35639D93FA3305AF73F0F071D7D284FCFB", + "84B87422330D7936EABA1109FA5A7A7181EE16F2438B0AEB2F38FD5F7554E57A", + "4C744E69C4A2E1C8ED72F796D151A17CE2325B943260FC460B9F73CB57C9014B", + "B3129A75D31D17194675A1BC56947920898FBF390A5BF5D931CE6CBB3340F66D", + "93634F44FA13AF76169F3CC8FBEA880ADAFF8475D5FD28A75DEB83C44362B439", + "1604A3FCFA9783E667CE9FCB1062C2A5C6685C316DDA62DE0548BAA6BA30038B", + "5A1AE172102EFD95DF7338DBC577C66D8D6C15E0A0158C7507228EFB078F42A6", + "67E0E0C2EED7A6993DCE28FE9AA2EF56834307860839677F96685F2B44D0911F", + "A01F2C8BEE81769609462C69C96AA923FD863E209D3CE26DD889B55E2E3873DB", + "38BFFE40A22D529A0C66124B2C308DAC9229912656F62B4FACFCED408E02380F", + "28B3404A61908F5D6198815C99AF1990C8AF38655930058C28C21BB539CE0000", + "4E378FB5561CD0668F906B731AC58FEE25738EDF09CADC7A29C0ABC0177AEA6D"}; + + BN_CTX *ctx = NULL; + EC_GROUP *group = NULL; 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; + fp12_t g; + int ok; + ctx = BN_CTX_new(); + BN_CTX_start(ctx); + group = EC_GROUP_new_by_curve_name(NID_sm9bn256v1); + P1 = EC_GROUP_get0_generator(group); - p = BN_new(); - a = BN_new(); - b = BN_new(); + point_init(&Ppubs, ctx); + point_set_affine_coordinates_hex(&Ppubs, Ppubs_str); - /* 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; - } + fp12_init(g, ctx); + sm9_rate(g, &Ppubs, P1, ctx); - EC_POINT_mul(group, Q, n, NULL, NULL, ctx) - if (!POINT_is_at_infinity(Q)) { - } + ok = fp12_equ_hex(g, g_str, ctx); + printf("rate %d: %s\n", __LINE__, ok ? "ok" : "error"); - point_mul_generator(Ppubs, ks, P2, p, ctx); + fp12_cleanup(g); + point_cleanup(&Ppubs); + EC_GROUP_free(group); + BN_CTX_free(ctx); + + return 1; +} + +int SM9_rate_pairing(BIGNUM *r[12], const BIGNUM *xQ[2], const BIGNUM *yQ[2], + const BIGNUM *xP, const BIGNUM *yP, BN_CTX *ctx) +{ return 0; } + diff --git a/crypto/sm9/sm9_setup.c b/crypto/sm9/sm9_setup.c index 86e37f2e..92c21c60 100644 --- a/crypto/sm9/sm9_setup.c +++ b/crypto/sm9/sm9_setup.c @@ -218,7 +218,5 @@ end: int SM9_setup_by_pairing_name(int nid, int hid, SM9PublicParameters **mpk, SM9MasterSecret **msk) { - EC_GROUP *group = EC_GROUP_new_sm9s256t1(); - return SM9_setup_type1curve(group, EVP_sm3(), mpk, msk); + return 0; } - diff --git a/include/openssl/opensslv.h b/include/openssl/opensslv.h index 51839203..dc29ea23 100644 --- a/include/openssl/opensslv.h +++ b/include/openssl/opensslv.h @@ -41,9 +41,9 @@ extern "C" { */ # define OPENSSL_VERSION_NUMBER 0x1010004fL # ifdef OPENSSL_FIPS -# define OPENSSL_VERSION_TEXT "GmSSL 2.3.2 - OpenSSL 1.1.0d-fips 8 Sep 2018" +# define OPENSSL_VERSION_TEXT "GmSSL 2.3.2 - OpenSSL 1.1.0d-fips 21 Sep 2018" # else -# define OPENSSL_VERSION_TEXT "GmSSL 2.3.2 - OpenSSL 1.1.0d 8 Sep 2018" +# define OPENSSL_VERSION_TEXT "GmSSL 2.3.2 - OpenSSL 1.1.0d 21 Sep 2018" # endif /*-