Files
2025-11-07 09:57:14 +08:00

2549 lines
70 KiB
C

/*****************************************************************************
*
*
*Copyright (c) 2021-2029 Semidrive Incorporated. All rights reserved.
*Software License Agreement
*
******************************************************************************
*/
#include <hash.h>
#include <pke.h>
#include <ske.h>
#include <sm9.h>
#define SM9_BYTE_LEN (32)
#define SM9_WORD_LEN (8)
typedef struct {
uint32_t re[8];
uint32_t im[8];
} __mpc_struct;
typedef __mpc_struct mpc_t[1];
typedef __mpc_struct *mpc_ptr;
typedef struct {
mpc_t ft2;
mpc_t ft;
mpc_t f;
} __mpc6_struct;
typedef __mpc6_struct mpc6_t[1];
typedef __mpc6_struct *mpc6_ptr;
typedef struct {
mpc6_t fW;
mpc6_t f;
} __mpc12_struct;
typedef __mpc12_struct mpc12_t[1];
typedef __mpc12_struct *mpc12_ptr;
typedef struct {
uint32_t x[8];
uint32_t y[8];
uint32_t z[8];
} FP_POINT;
typedef FP_POINT fp_pt_t[1];
typedef struct {
mpc_t x;
mpc_t y;
mpc_t z;
} FP2_POINT;
typedef FP2_POINT fp2_pt_t[1];
/*sm9 algorithm parameters*/
const uint32_t sm9p256v1_t[2] = {0x0058F98A, 0x60000000};
const uint32_t sm9p256v1_p[8] = {0xE351457D, 0xE56F9B27, 0x1A7AEEDB,
0x21F2934B, 0xF58EC745, 0xD603AB4F,
0x02A3A6F1, 0xB6400000};
const uint32_t sm9p256v1_p_h[8] = {0xB417E2D2, 0x27DEA312, 0xAE1A5D3F,
0x88F8105F, 0xD6706E7B, 0xE479B522,
0x56F62FBD, 0x2EA795A6};
const uint32_t sm9p256v1_p_n1[1] = {
0x2F2EE42B,
};
const uint32_t sm9p256v1_a[8] = {0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000};
const uint32_t sm9p256v1_b[8] = {0x00000005, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000};
const uint32_t sm9p256v1_Gx[8] = {0x7C66DDDD, 0xE8C4E481, 0x09DC3280,
0xE1E40869, 0x487D01D6, 0xF5ED0704,
0x62BF718F, 0x93DE051D};
const uint32_t sm9p256v1_Gy[8] = {0x0A3EA616, 0x0C464CD7, 0xFA602435,
0x1C1C00CB, 0x5C395BBC, 0x63106512,
0x4F21E607, 0x21FE8DDA};
const uint32_t sm9p256v1_n[8] = {0xD69ECF25, 0xE56EE19C, 0x18EA8BEE,
0x49F2934B, 0xF58EC744, 0xD603AB4F,
0x02A3A6F1, 0xB6400000};
const uint32_t sm9p256v1_n_h[8] = {0xCD750C35, 0x7598CD79, 0xBB6DAEAB,
0xE4A08110, 0x7D78A1F9, 0xBFEE4BAE,
0x63695D0E, 0x8894F5D1};
const uint32_t sm9p256v1_n_n1[1] = {
0x51974B53,
};
/*sm9 para (n-1), for private key checking*/
uint32_t const sm9p256v1_n_1[8] = {0xD69ECF24, 0xE56EE19C, 0x18EA8BEE,
0x49F2934B, 0xF58EC744, 0xD603AB4F,
0x02A3A6F1, 0xB6400000};
const eccp_curve_t sm9_curve[1] = {
{
256,
256,
(uint32_t *)sm9p256v1_p,
(uint32_t *)sm9p256v1_p_h,
(uint32_t *)sm9p256v1_a,
(uint32_t *)sm9p256v1_b,
(uint32_t *)sm9p256v1_Gx,
(uint32_t *)sm9p256v1_Gy,
(uint32_t *)sm9p256v1_n,
(uint32_t *)sm9p256v1_n_h,
NULL,
NULL,
},
};
/*P1*/
const fp2_pt_t fp2ptP1 = {
{{{{0x7C66DDDD, 0xE8C4E481, 0x09DC3280, 0xE1E40869, 0x487D01D6, 0xF5ED0704,
0x62BF718F, 0x93DE051D},
{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000}}},
{{{0x0A3EA616, 0x0C464CD7, 0xFA602435, 0x1C1C00CB, 0x5C395BBC, 0x63106512,
0x4F21E607, 0x21FE8DDA},
{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000}}},
{{{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000},
{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000}}}}};
/*P2*/
const fp2_pt_t fp2ptP2 = {
{{{{0xAF82D65B, 0xF9B7213B, 0xD19C17AB, 0xEE265948, 0xD34EC120, 0xD2AAB97F,
0x92130B08, 0x37227552},
{0xD8806141, 0x54806C11, 0x0F5E93C4, 0xF1DD2C19, 0xB441A01F, 0x597B6027,
0x78640C98, 0x85AEF3D0}}},
{{{0xC999A7C7, 0x6215BBA5, 0xA71A0811, 0x47EFBA98, 0x3D278FF2, 0x5F317015,
0x19BE3DA6, 0xA7CF28D5},
{0x84EBEB96, 0x856DC76B, 0xA347C8BD, 0x0736A96F, 0x2CBEE6ED, 0x66BA0D26,
0x2E845C12, 0x17509B09}}},
{{{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000},
{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000}}}}};
static void U8Big_to_U32Small_8(uint32_t out[], const uint8_t in[])
{
out[7] = ((uint32_t)in[3]) | ((uint32_t)in[2] << 8u) |
((uint32_t)in[1] << 16u) | ((uint32_t)in[0] << 24u);
out[6] = ((uint32_t)in[7]) | ((uint32_t)in[6] << 8u) |
((uint32_t)in[5] << 16u) | ((uint32_t)in[4] << 24u);
out[5] = ((uint32_t)in[11]) | ((uint32_t)in[10] << 8u) |
((uint32_t)in[9] << 16u) | ((uint32_t)in[8] << 24u);
out[4] = ((uint32_t)in[15]) | ((uint32_t)in[14] << 8u) |
((uint32_t)in[13] << 16u) | ((uint32_t)in[12] << 24u);
out[3] = ((uint32_t)in[19]) | ((uint32_t)in[18] << 8u) |
((uint32_t)in[17] << 16u) | ((uint32_t)in[16] << 24u);
out[2] = ((uint32_t)in[23]) | ((uint32_t)in[22] << 8u) |
((uint32_t)in[21] << 16u) | ((uint32_t)in[20] << 24u);
out[1] = ((uint32_t)in[27]) | ((uint32_t)in[26] << 8u) |
((uint32_t)in[25] << 16u) | ((uint32_t)in[24] << 24u);
out[0] = ((uint32_t)in[31]) | ((uint32_t)in[30] << 8u) |
((uint32_t)in[29] << 16u) | ((uint32_t)in[28] << 24u);
}
static void U32Small_to_U8Big(uint8_t out[], const uint32_t in[])
{
uint32_t i, j;
for (i = 0; i < 8; i++) {
j = 28 - (i << 2);
out[j] = ((uint8_t)(in[i] >> 24)) & 0xffu;
out[j + 1] = ((uint8_t)(in[i] >> 16)) & 0xffu;
out[j + 2] = ((uint8_t)(in[i] >> 8)) & 0xffu;
out[j + 3] = ((uint8_t)in[i]) & 0xffu;
}
}
/* Function: get aimed bit value of big integer a
* Parameters:
* a ----------- big integer a
* bitLen ------ aimed bit location
* Return:
* bit value of aimed bit
* Caution:
* 1. make sure bitLen > 0
*/
static uint32_t Get_BitValue(const uint32_t a[], uint32_t bitLen)
{
bitLen--;
if (0u != (a[(bitLen) >> 5u] & ((uint32_t)1u << (bitLen & 31u)))) {
return 1u;
} else {
return 0u;
}
}
/* function: a=a+1 (for SM2 KDF counter addition)
* parameters:
* a[4] ----------------------- input, count of 4 bytes, big-endian
* return: none
* caution: if a of 4 bytes can not hold the carry, then the carry will be
* discarded
*/
void sm9_counter_add_one(uint8_t a[4])
{
int32_t i;
uint8_t carry;
carry = 1;
for (i = 3; i >= 0; i--) {
a[i] += carry;
if (a[i] < carry) {
carry = 1;
} else {
break;
}
}
}
/* function: a=a+1
* parameters:
* a -------------------------- input, destination data
* wordLen -------------------- input, word length of data
* return: none
* caution:
* 1. if a of wordLen words can not hold the carry, then the carry will be
* discarded
*/
static void sm9_BigNum_Add_One(uint32_t *a, uint32_t wordLen)
{
uint32_t i, carry;
carry = 1;
for (i = 0; i < wordLen; i++) {
a[i] += carry;
if (a[i] < carry) {
carry = 1;
} else {
break;
}
}
}
static void ibe_kdf_H1_H2_mod(uint32_t *result, uint8_t res[40])
{
uint32_t t[8];
uint32_t Ha[8];
uint32_t Hb[8];
uint32_t Hc[8];
uint32_t N_compl[8] = {0x296130DB, 0x1A911E63, 0xE7157411, 0xB60D6CB4,
0x0A7138BB, 0x29FC54B0, 0xFD5C590E, 0x49BFFFFF};
uint32_t N2[8] = {0xFFFFF8A5, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
uint32_t N2_inv[8] = {0xD81AE00B, 0x73FFE2F2, 0x3CA00AC3, 0x6EE46995,
0x859A2700, 0xECEE7342, 0xE23BB01C, 0xB707F075};
uint32_t N2_compl[8] = {0x0000075B, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000};
Ha[0] = ((uint32_t)res[7]) | ((uint32_t)res[6] << 8u) |
((uint32_t)res[5] << 16u) | ((uint32_t)res[4] << 24u);
Ha[1] = ((uint32_t)res[3]) | ((uint32_t)res[2] << 8u) |
((uint32_t)res[1] << 16u) | ((uint32_t)res[0] << 24u);
Ha[2] = 0x00000000;
Ha[3] = 0x00000000;
Ha[4] = 0x00000000;
Ha[5] = 0x00000000;
Ha[6] = 0x00000000;
Ha[7] = 0x00000000;
U8Big_to_U32Small_8(Hb, (uint8_t *)(res + 8));
pke_modmul(sm9p256v1_n, Ha, N_compl, Hc, 8);
if (uint32_bignumcmp(Hb, 8, (uint32_t *)sm9p256v1_n, 8) >= 0) {
pke_sub(Hb, sm9p256v1_n, t, 8);
pke_modadd(sm9p256v1_n, Hc, t, Hc, 8);
} else {
pke_modadd(sm9p256v1_n, Hc, Hb, Hc, 8);
}
if (uint32_bignumcmp(Hb, 8, Hc, 8) >= 0) {
pke_sub(Hb, Hc, Hb, 8);
} else {
pke_sub(Hb, Hc, Hb, 8);
if (Ha[0] != 0x00000000) {
Ha[0] -= 0x00000001;
} else {
Ha[0] = 0xFFFFFFFF;
Ha[1] -= 0x00000001;
}
}
pke_modmul(N2, Ha, N2_compl, Ha, 8);
if (uint32_bignumcmp(Hb, 8, N2, 8) >= 0) {
pke_sub(Hb, N2, Hb, 8);
}
pke_modadd(N2, Ha, Hb, Ha, 8);
pke_modmul(N2, Ha, N2_inv, Hb, 8);
if (uint32_bignumcmp(Hc, 8, (uint32_t *)sm9p256v1_n_1, 8) >= 0) {
pke_sub(Hc, sm9p256v1_n_1, Hc, 8);
}
pke_modadd(sm9p256v1_n_1, Hc, Hb, result, 8);
sm9_BigNum_Add_One(result, 8);
}
/*K1 can not be NULL, K2 is ok*/
static void ibe_kdf_wrap_enc(const uint8_t *C1, const uint8_t *W,
const uint8_t *ID, uint32_t byteLenofID,
uint8_t *K1, uint32_t byteLenofK1, uint8_t *K2,
uint32_t byteLenofK2)
{
uint8_t counter[4] = {0x00, 0x00, 0x00, 0x01};
uint8_t digest[32];
uint32_t i, t;
hash_ctx_t ctx[1];
t = byteLenofK1 >> 5;
for (i = 0; i < t; i++) {
hash_init(ctx, HASH_SM3);
hash_update(ctx, C1, 64);
hash_update(ctx, W, 32 * 12);
hash_update(ctx, ID, byteLenofID);
hash_update(ctx, counter, 4);
hash_final(ctx, K1 + (i << 5));
sm9_counter_add_one(counter);
}
i = byteLenofK1 & 0x1F;
if (i) {
hash_init(ctx, HASH_SM3);
hash_update(ctx, C1, 64);
hash_update(ctx, W, 32 * 12);
hash_update(ctx, ID, byteLenofID);
hash_update(ctx, counter, 4);
hash_final(ctx, digest);
memcpy_(K1 + (t << 5), digest, i);
}
if (K2 && byteLenofK2) {
if (i) {
t = 0x20 - i;
if (byteLenofK2 <= t) {
memcpy_(K2, digest + i, byteLenofK2);
return;
} else {
memcpy_(K2, digest + i, t);
byteLenofK2 -= t;
K2 += t;
sm9_counter_add_one(counter);
}
}
t = byteLenofK2 >> 5;
for (i = 0; i < t; i++) {
hash_init(ctx, HASH_SM3);
hash_update(ctx, C1, 64);
hash_update(ctx, W, 32 * 12);
hash_update(ctx, ID, byteLenofID);
hash_update(ctx, counter, 4);
hash_final(ctx, K2 + (i << 5));
sm9_counter_add_one(counter);
}
i = byteLenofK2 & 0x1F;
if (i) {
hash_init(ctx, HASH_SM3);
hash_update(ctx, C1, 64);
hash_update(ctx, W, 32 * 12);
hash_update(ctx, ID, byteLenofID);
hash_update(ctx, counter, 4);
hash_final(ctx, digest);
memcpy_(K2 + (t << 5), digest, i);
}
}
}
static void ibe_kdf_H1_H2(uint8_t *res, hash_ctx_t *ctx, const uint8_t *z1,
uint32_t z1ByteLen, const uint8_t *z2,
uint32_t z2ByteLen, const uint8_t *cnt,
const uint8_t *tag)
{
hash_init(ctx, HASH_SM3);
hash_update(ctx, tag, 1);
hash_update(ctx, z1, z1ByteLen);
hash_update(ctx, z2, z2ByteLen);
hash_update(ctx, cnt, 4);
hash_final(ctx, res);
}
static void ibe_kdf_exc_key(const uint8_t *IDA, uint32_t byteLenofIDA,
const uint8_t *IDB, uint32_t byteLenofIDB,
const uint8_t *RA, const uint8_t *RB,
const uint8_t *g, uint8_t *K, uint32_t byteLenofK)
{
uint8_t digest[32];
uint32_t i, t;
hash_ctx_t ctx[1];
uint8_t counter[4] = {0x00, 0x00, 0x00, 0x01};
t = byteLenofK >> 5;
for (i = 0; i < t; i++) {
hash_init(ctx, HASH_SM3);
hash_update(ctx, IDA, byteLenofIDA);
hash_update(ctx, IDB, byteLenofIDB);
hash_update(ctx, RA, 64);
hash_update(ctx, RB, 64);
hash_update(ctx, g, 32 * 12 * 3);
hash_update(ctx, counter, 4);
hash_final(ctx, K + (i << 5));
sm9_counter_add_one(counter);
}
i = byteLenofK & 0x1F;
if (i) {
hash_init(ctx, HASH_SM3);
hash_update(ctx, IDA, byteLenofIDA);
hash_update(ctx, IDB, byteLenofIDB);
hash_update(ctx, RA, 64);
hash_update(ctx, RB, 64);
hash_update(ctx, g, 32 * 12 * 3);
hash_update(ctx, counter, 4);
hash_final(ctx, digest);
memcpy_(K + (t << 5), digest, i);
}
}
/*The realization of the functions H1(Z,n) and H2(Z,n), the difference between
the two is only the tag value is different
Where Z=z1||z2, n is the order of the elliptic curve, after the function is
executed, a large number less than n is generated*/
static void ibe_H1_H2(uint8_t tag, const uint8_t *z1, uint32_t z1ByteLen,
const uint8_t *z2, uint32_t z2ByteLen, uint32_t *result)
{
uint8_t cnt[4] = {0, 0, 0, 1};
uint8_t res[64];
hash_ctx_t ctx[1];
ibe_kdf_H1_H2(res, ctx, z1, z1ByteLen, z2, z2ByteLen, cnt, &tag);
cnt[3] = 0x02;
ibe_kdf_H1_H2(res + 32, ctx, z1, z1ByteLen, z2, z2ByteLen, cnt, &tag);
ibe_kdf_H1_H2_mod(result, res);
}
static void FE2OSP(mpc12_t input, uint8_t *result)
{
U32Small_to_U8Big(result + 32 * 11, input->f->f->re);
U32Small_to_U8Big(result + 32 * 10, input->f->f->im);
U32Small_to_U8Big(result + 32 * 3, input->f->ft->re);
U32Small_to_U8Big(result + 32 * 2, input->f->ft->im);
U32Small_to_U8Big(result + 32 * 5, input->f->ft2->re);
U32Small_to_U8Big(result + 32 * 4, input->f->ft2->im);
U32Small_to_U8Big(result + 32 * 7, input->fW->f->re);
U32Small_to_U8Big(result + 32 * 6, input->fW->f->im);
U32Small_to_U8Big(result + 32 * 9, input->fW->ft->re);
U32Small_to_U8Big(result + 32 * 8, input->fW->ft->im);
U32Small_to_U8Big(result + 32, input->fW->ft2->re);
U32Small_to_U8Big(result, input->fW->ft2->im);
}
static uint8_t uint32_cmp(uint32_t out[8], const uint32_t in[8])
{
uint32_t i;
for (i = 0; i < 8u; i++) {
if (out[i] != in[i]) {
return 1;
}
}
return 0;
}
static void uint32_mod(uint32_t out[8], const uint32_t in[8],
const uint32_t p[8])
{
const uint32_t tmp[8] = {0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000};
(void)pke_modadd(p, in, tmp, out, 8);
}
static void mpc_fp2_set(mpc_t dst, const mpc_t src)
{
uint32_copy(dst->re, (uint32_t *)src->re, 8);
uint32_copy(dst->im, (uint32_t *)src->im, 8);
}
static void mpc_fp2_mod(mpc_t dst, const mpc_t src, const uint32_t p[8])
{
uint32_mod(dst->re, src->re, p);
uint32_mod(dst->im, src->im, p);
}
static void mpc_fp2_add(mpc_t dst, const mpc_t x, const mpc_t y,
const uint32_t p[8])
{
pke_modadd(p, x->re, y->re, dst->re, 8);
pke_modadd(p, x->im, y->im, dst->im, 8);
}
static void mpc_fp2_sub(mpc_t dst, const mpc_t x, const mpc_t y,
const uint32_t p[8])
{
pke_modsub(p, x->re, y->re, dst->re, 8);
pke_modsub(p, x->im, y->im, dst->im, 8);
}
/*Two-element modular multiplication in Fp^2, dst = (x * y) mod p*/
static void mpc_fp2_mul(mpc_t dst, const mpc_t x, const mpc_t y,
const uint32_t p[8])
{
uint32_t a[8];
uint32_t b[8];
uint32_t c[8];
(void)pke_modmul(p, x->re, y->re, a, 8);
(void)pke_modmul(p, x->im, y->im, b, 8);
pke_modadd(p, b, b, b, 8);
pke_modsub(p, a, b, c, 8);
(void)pke_modmul(p, x->re, y->im, a, 8);
(void)pke_modmul(p, x->im, y->re, b, 8);
pke_modadd(p, a, b, dst->im, 8);
uint32_copy(dst->re, c, 8);
}
static void mpc_fp2_clears(mpc_ptr x)
{
uint32_clear(x->re, 8);
uint32_clear(x->im, 8);
}
/*E(Fp^2) point on Jacobian coordinates to point on affine coordinates*/
static void coordinate_convert(mpc_t x_in, mpc_t y_in, mpc_t z_in, mpc_t x_out,
mpc_t y_out)
{
mpc_t z1, z2;
uint32_t inv1[8];
uint32_t inv2[8];
pke_modmul(sm9p256v1_p, z_in->im, z_in->im, inv1, 8);
pke_sub(sm9p256v1_p, inv1, inv1, 8);
pke_modadd(sm9p256v1_p, inv1, inv1, inv1, 8);
pke_modmul(sm9p256v1_p, z_in->re, z_in->re, inv2, 8);
pke_modsub(sm9p256v1_p, inv1, inv2, inv1, 8);
(void)pke_modinv(sm9p256v1_p, inv1, inv1, 8, 8);
mpc_fp2_set(z1, z_in);
pke_sub(sm9p256v1_p, z1->re, z1->re, 8);
uint32_copy(z2->re, inv1, 8);
uint32_clear(z2->im, 8);
mpc_fp2_mul(z1, z1, z2, sm9p256v1_p);
mpc_fp2_mul(z2, z1, z1, sm9p256v1_p);
mpc_fp2_mul(z1, z2, z1, sm9p256v1_p);
mpc_fp2_mul(x_out, x_in, z2, sm9p256v1_p);
mpc_fp2_mul(y_out, y_in, z1, sm9p256v1_p);
mpc_fp2_clears(z_in);
z_in->re[0] = 0x00000001;
}
static void mpc_fp6_add(mpc6_t dst, mpc6_t a, mpc6_t b, const uint32_t p[8])
{
mpc_fp2_add(dst->f, a->f, b->f, p);
mpc_fp2_add(dst->ft, a->ft, b->ft, p);
mpc_fp2_add(dst->ft2, a->ft2, b->ft2, p);
}
static void mpc_fp6_sub(mpc6_t dst, mpc6_t a, mpc6_t b, const uint32_t p[8])
{
mpc_fp2_sub(dst->f, a->f, b->f, p);
mpc_fp2_sub(dst->ft, a->ft, b->ft, p);
mpc_fp2_sub(dst->ft2, a->ft2, b->ft2, p);
}
static void mpc_fp6_set(mpc6_t dst, mpc6_t src)
{
mpc_fp2_set(dst->f, src->f);
mpc_fp2_set(dst->ft, src->ft);
mpc_fp2_set(dst->ft2, src->ft2);
}
static void mpc_fp6_clears(mpc6_ptr x)
{
mpc_fp2_clears(x->f);
mpc_fp2_clears(x->ft);
mpc_fp2_clears(x->ft2);
}
static void mpc_fp12_clears(mpc12_ptr x)
{
mpc_fp2_clears(x->f->f);
mpc_fp2_clears(x->f->ft);
mpc_fp2_clears(x->f->ft2);
mpc_fp2_clears(x->fW->f);
mpc_fp2_clears(x->fW->ft);
mpc_fp2_clears(x->fW->ft2);
}
/*all declared as mpc_t to fit multiplications in the later functions*/
mpc_t KECI;
mpc_t k1, k2, k3, k4, k5;
mpc_t g1, g2, g3, g4, g5;
mpc_t e1, e2, e3, e4, e5;
mpc_t scal1, scal2;
static void KECI_init(void)
{
uint32_clear(KECI->re, 8);
uint32_clear(KECI->im, 8);
KECI->im[0] = 1;
}
static void kn_init(void)
{
uint32_t k1_re[SM9_WORD_LEN] = {
0x377b698b, 0xa91d8354, 0x0ddd04ed, 0x47c5c86e,
0x9c086749, 0x843c6cfa, 0xe5720bdb, 0x3f23ea58,
};
uint32_t k2_re[SM9_WORD_LEN] = {
0x7be65334, 0xd5fc1196, 0x4f8b78f4, 0x78027235,
0x02a3a6f2, 0xf3000000, 0x00000000, 0x00000000,
};
uint32_t k3_re[SM9_WORD_LEN] = {
0xda24d011, 0xf5b21fd3, 0x06dc5177, 0x9f9d4118,
0xee0baf15, 0xf55acc93, 0xdc0a3f2c, 0x6c648de5,
};
uint32_t k4_re[SM9_WORD_LEN] = {
0x7be65333, 0xd5fc1196, 0x4f8b78f4, 0x78027235,
0x02a3a6f2, 0xf3000000, 0x00000000, 0x00000000,
};
uint32_t k5_re[SM9_WORD_LEN] = {
0xa2a96686, 0x4c949c7f, 0xf8ff4c8a, 0x57d778a9,
0x520347cc, 0x711e5f99, 0xf6983351, 0x2d40a38c,
};
uint32_copy(k1->re, (uint32_t *)k1_re, SM9_WORD_LEN);
uint32_copy(k2->re, (uint32_t *)k2_re, SM9_WORD_LEN);
uint32_copy(k3->re, (uint32_t *)k3_re, SM9_WORD_LEN);
uint32_copy(k4->re, (uint32_t *)k4_re, SM9_WORD_LEN);
uint32_copy(k5->re, (uint32_t *)k5_re, SM9_WORD_LEN);
uint32_clear(k1->im, SM9_WORD_LEN);
uint32_clear(k2->im, SM9_WORD_LEN);
uint32_clear(k3->im, SM9_WORD_LEN);
uint32_clear(k4->im, SM9_WORD_LEN);
uint32_clear(k5->im, SM9_WORD_LEN);
}
static void kn_clear()
{
mpc_fp2_clears(k1);
mpc_fp2_clears(k2);
mpc_fp2_clears(k3);
mpc_fp2_clears(k4);
mpc_fp2_clears(k5);
}
static void gn_init(void)
{
uint32_t g1_re[SM9_WORD_LEN] = {
0x7be65334, 0xd5fc1196, 0x4f8b78f4, 0x78027235,
0x02a3a6f2, 0xf3000000, 0x00000000, 0x00000000,
};
uint32_t g2_re[SM9_WORD_LEN] = {
0x7be65333, 0xd5fc1196, 0x4f8b78f4, 0x78027235,
0x02a3a6f2, 0xf3000000, 0x00000000, 0x00000000,
};
uint32_t g3_re[SM9_WORD_LEN] = {
0xe351457c, 0xe56f9b27, 0x1a7aeedb, 0x21f2934b,
0xf58ec745, 0xd603ab4f, 0x02a3a6f1, 0xb6400000,
};
uint32_t g4_re[SM9_WORD_LEN] = {
0x676af249, 0x0f738991, 0xcaef75e7, 0xa9f02115,
0xf2eb2052, 0xe303ab4f, 0x02a3a6f0, 0xb6400000,
};
uint32_t g5_re[SM9_WORD_LEN] = {
0x676af24a, 0x0f738991, 0xcaef75e7, 0xa9f02115,
0xf2eb2052, 0xe303ab4f, 0x02a3a6f0, 0xb6400000,
};
uint32_copy(g1->re, (uint32_t *)g1_re, SM9_WORD_LEN);
uint32_copy(g2->re, (uint32_t *)g2_re, SM9_WORD_LEN);
uint32_copy(g3->re, (uint32_t *)g3_re, SM9_WORD_LEN);
uint32_copy(g4->re, (uint32_t *)g4_re, SM9_WORD_LEN);
uint32_copy(g5->re, (uint32_t *)g5_re, SM9_WORD_LEN);
uint32_clear(g1->im, SM9_WORD_LEN);
uint32_clear(g2->im, SM9_WORD_LEN);
uint32_clear(g3->im, SM9_WORD_LEN);
uint32_clear(g4->im, SM9_WORD_LEN);
uint32_clear(g5->im, SM9_WORD_LEN);
}
static void gn_clear(void)
{
mpc_fp2_clears(g1);
mpc_fp2_clears(g2);
mpc_fp2_clears(g3);
mpc_fp2_clears(g4);
mpc_fp2_clears(g5);
}
static void en_init(void)
{
uint32_t e1_re[SM9_WORD_LEN] = {
0xda24d011, 0xf5b21fd3, 0x06dc5177, 0x9f9d4118,
0xee0baf15, 0xf55acc93, 0xdc0a3f2c, 0x6c648de5,
};
uint32_t e2_re[SM9_WORD_LEN] = {
0xe351457c, 0xe56f9b27, 0x1a7aeedb, 0x21f2934b,
0xf58ec745, 0xd603ab4f, 0x02a3a6f1, 0xb6400000,
};
uint32_t e3_re[SM9_WORD_LEN] = {
0x092c756c, 0xefbd7b54, 0x139e9d63, 0x82555233,
0x0783182f, 0xe0a8debc, 0x269967c4, 0x49db721a,
};
uint32_t e4_re[SM9_WORD_LEN] = {
0x00000001, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
};
uint32_t e5_re[SM9_WORD_LEN] = {
0xda24d011, 0xf5b21fd3, 0x06dc5177, 0x9f9d4118,
0xee0baf15, 0xf55acc93, 0xdc0a3f2c, 0x6c648de5,
};
kn_init();
uint32_copy(e1->re, (uint32_t *)e1_re, SM9_WORD_LEN);
uint32_copy(e2->re, (uint32_t *)e2_re, SM9_WORD_LEN);
uint32_copy(e3->re, (uint32_t *)e3_re, SM9_WORD_LEN);
uint32_copy(e4->re, (uint32_t *)e4_re, SM9_WORD_LEN);
uint32_copy(e5->re, (uint32_t *)e5_re, SM9_WORD_LEN);
uint32_clear(e1->im, SM9_WORD_LEN);
uint32_clear(e2->im, SM9_WORD_LEN);
uint32_clear(e3->im, SM9_WORD_LEN);
uint32_clear(e4->im, SM9_WORD_LEN);
uint32_clear(e5->im, SM9_WORD_LEN);
}
static void en_clear(void)
{
mpc_fp2_clears(e1);
mpc_fp2_clears(e2);
mpc_fp2_clears(e3);
mpc_fp2_clears(e4);
mpc_fp2_clears(e5);
}
static void scal_init(void)
{
uint32_t scal1_re[SM9_WORD_LEN] = {
0x676af24a, 0x0f738991, 0xcaef75e7, 0xa9f02115,
0xf2eb2052, 0xe303ab4f, 0x02a3a6f0, 0xb6400000,
};
uint32_t scal2_re[SM9_WORD_LEN] = {
0x092c756c, 0xefbd7b54, 0x139e9d63, 0x82555233,
0x0783182f, 0xe0a8debc, 0x269967c4, 0x49db721a,
};
uint32_copy(scal1->re, (uint32_t *)scal1_re, SM9_WORD_LEN);
uint32_copy(scal2->re, (uint32_t *)scal2_re, SM9_WORD_LEN);
uint32_clear(scal1->im, SM9_WORD_LEN);
uint32_clear(scal2->im, SM9_WORD_LEN);
}
/*Point multiplication operation of curve E(Fp^2)*/
static void PD_fp2(mpc_t x, mpc_t y, mpc_t z, mpc_t xo, mpc_t yo, mpc_t zo,
const uint32_t p[8])
{
mpc_t R1, R2, R3, R5, R6, R7;
mpc_fp2_set(R1, x);
mpc_fp2_set(R2, y);
mpc_fp2_set(R3, z);
mpc_fp2_mul(R6, R3, R2, p);
mpc_fp2_mul(R5, R1, R1, p);
mpc_fp2_add(R1, R1, R1, p);
mpc_fp2_add(R1, R1, R1, p);
mpc_fp2_add(R3, R6, R6, p);
mpc_fp2_add(R6, R5, R5, p);
mpc_fp2_add(R5, R6, R5, p);
mpc_fp2_mul(R6, R2, R2, p);
mpc_fp2_mul(R2, R6, R1, p);
mpc_fp2_mul(R7, R5, R5, p);
mpc_fp2_add(R1, R2, R2, p);
mpc_fp2_sub(R1, R7, R1, p);
mpc_fp2_mul(R7, R6, R6, p);
mpc_fp2_sub(R2, R2, R1, p);
mpc_fp2_mul(R5, R5, R2, p);
mpc_fp2_add(R7, R7, R7, p);
mpc_fp2_add(R7, R7, R7, p);
mpc_fp2_add(R7, R7, R7, p);
mpc_fp2_sub(R2, R5, R7, p);
mpc_fp2_mod(xo, R1, p);
mpc_fp2_mod(yo, R2, p);
mpc_fp2_mod(zo, R3, p);
}
/*Point addition operation of curve E(Fp^2)
x:=(y2*z^3-y)^2-(x2*z^2-x)^2*(x+x2*z^2);
y:=(y2*z^3-y)*(x*(x2*z^2-x)^2-X)-y*(x2*z^2-x)^3;
z:=(x2*z^2-x)*z;*/
static void PA_fp2(mpc_t x, mpc_t y, mpc_t z, const mpc_t x2, const mpc_t y2,
const uint32_t p[8])
{
mpc_t A, B, C, D, E;
mpc_fp2_mul(A, z, z, p);
mpc_fp2_mul(B, x2, A, p);
mpc_fp2_mul(A, A, z, p);
/*x2*z^2-x*/
mpc_fp2_sub(D, B, x, p);
mpc_fp2_mul(z, D, z, p);
/*x2*z^2+x*/
mpc_fp2_add(E, B, x, p);
/*y2*z^3*/
mpc_fp2_mul(B, A, y2, p);
/*(x2*z^2-x)^2*/
mpc_fp2_mul(C, D, D, p);
mpc_fp2_mul(A, C, E, p);
mpc_fp2_mul(E, x, C, p);
mpc_fp2_mul(C, C, D, p);
mpc_fp2_mul(C, C, y, p);
/*y2*z^3-y*/
mpc_fp2_sub(D, B, y, p);
mpc_fp2_mul(B, D, D, p);
mpc_fp2_sub(x, B, A, p);
/*(x*(x2*z^2-x)^2-X)*/
mpc_fp2_sub(E, E, x, p);
mpc_fp2_mul(E, E, D, p);
mpc_fp2_sub(y, E, C, p);
mpc_fp2_mod(x, x, p);
mpc_fp2_mod(z, z, p);
mpc_fp2_mod(y, y, p);
}
/*Fp2 multiplication*/
static void Mp2(const mpc_t a, const mpc_t b, mpc_t k, const uint32_t p[8])
{
uint32_t A[8];
uint32_t B[8];
uint32_t C[8];
pke_modadd(p, a->re, a->im, C, 8);
pke_modadd(p, b->re, b->im, B, 8);
(void)pke_modmul(p, C, B, C, 8);
(void)pke_modmul(p, a->re, b->re, A, 8);
(void)pke_modmul(p, a->im, b->im, B, 8);
pke_modsub(p, C, A, C, 8);
pke_modsub(p, C, B, k->im, 8);
pke_modadd(p, B, B, B, 8);
pke_modsub(p, A, B, k->re, 8);
}
static void sp6(mpc_t ft2, mpc_t ft, mpc_t f, const uint32_t p[8])
{
mpc_t a1, a2, a3, A, B, D;
KECI_init();
mpc_fp2_set(a1, f);
mpc_fp2_set(a2, ft);
mpc_fp2_set(a3, ft2);
mpc_fp2_mul(A, a1, a1, p);
mpc_fp2_mul(B, a1, a2, p);
mpc_fp2_add(B, B, B, p);
mpc_fp2_sub(a1, a1, a2, p);
mpc_fp2_add(a1, a1, a3, p);
mpc_fp2_mul(a1, a1, a1, p);
mpc_fp2_mul(D, a2, a3, p);
mpc_fp2_add(D, D, D, p);
mpc_fp2_mul(a2, a3, a3, p);
mpc_fp2_sub(a1, a1, a2, p);
mpc_fp2_add(a1, a1, D, p);
mpc_fp2_mul(D, D, KECI, p);
mpc_fp2_mul(a2, a2, KECI, p);
mpc_fp2_sub(a1, a1, A, p);
mpc_fp2_add(A, A, D, p);
mpc_fp2_add(a1, a1, B, p);
mpc_fp2_add(B, B, a2, p);
mpc_fp2_mod(f, A, p);
mpc_fp2_mod(ft, B, p);
mpc_fp2_mod(ft2, a1, p);
}
static void sp12(mpc12_t f, const uint32_t p[8])
{
mpc_t Bt2, Bt, B, Ct2, Ct, C, Dt2, Dt, D;
KECI_init();
mpc_fp2_set(Ct2, f->fW->ft2);
mpc_fp2_set(Ct, f->fW->ft);
mpc_fp2_set(C, f->fW->f);
sp6(Ct2, Ct, C, p);
mpc_fp2_set(Bt2, f->f->ft2);
mpc_fp2_set(Bt, f->f->ft);
mpc_fp2_set(B, f->f->f);
sp6(Bt2, Bt, B, p);
mpc_fp2_add(Dt2, f->fW->ft2, f->f->ft2, p);
mpc_fp2_add(Dt, f->fW->ft, f->f->ft, p);
mpc_fp2_add(D, f->fW->f, f->f->f, p);
sp6(Dt2, Dt, D, p);
mpc_fp2_sub(Dt2, Dt2, Bt2, p);
mpc_fp2_sub(Dt, Dt, Bt, p);
mpc_fp2_sub(D, D, B, p);
mpc_fp2_sub(Dt2, Dt2, Ct2, p);
mpc_fp2_sub(Dt, Dt, Ct, p);
mpc_fp2_sub(D, D, C, p);
mpc_fp2_add(Bt2, Bt2, Ct, p);
mpc_fp2_add(Bt, Bt, C, p);
mpc_fp2_mul(Ct2, Ct2, KECI, p);
mpc_fp2_add(B, B, Ct2, p);
mpc_fp2_set(f->f->ft2, Bt2);
mpc_fp2_set(f->f->ft, Bt);
mpc_fp2_set(f->f->f, B);
mpc_fp2_set(f->fW->ft2, Dt2);
mpc_fp2_set(f->fW->ft, Dt);
mpc_fp2_set(f->fW->f, D);
}
static void Mp6(mpc6_t a, mpc6_t b, mpc6_t g, const uint32_t p[8])
{
mpc_t a1, a2, a3, b1, b2, b3, A, B, C, D, E, F, G;
KECI_init();
mpc_fp2_set(a1, a->f);
mpc_fp2_set(a2, a->ft);
mpc_fp2_set(a3, a->ft2);
mpc_fp2_set(b1, b->f);
mpc_fp2_set(b2, b->ft);
mpc_fp2_set(b3, b->ft2);
mpc_fp2_mul(A, a1, b1, p);
mpc_fp2_mul(B, a2, b2, p);
mpc_fp2_add(C, a1, a2, p);
mpc_fp2_add(D, b1, b2, p);
mpc_fp2_mul(E, C, D, p);
mpc_fp2_sub(E, E, A, p);
mpc_fp2_sub(E, E, B, p);
mpc_fp2_add(C, a1, a3, p);
mpc_fp2_add(D, b1, b3, p);
mpc_fp2_mul(F, a3, b3, p);
mpc_fp2_mul(C, C, D, p);
mpc_fp2_sub(C, C, A, p);
mpc_fp2_sub(C, C, F, p);
mpc_fp2_add(D, B, C, p);
mpc_fp2_add(C, a2, a3, p);
mpc_fp2_add(G, b2, b3, p);
mpc_fp2_mul(C, C, G, p);
mpc_fp2_sub(C, C, B, p);
mpc_fp2_sub(C, C, F, p);
mpc_fp2_mul(C, C, KECI, p);
mpc_fp2_add(C, C, A, p);
mpc_fp2_set(g->f, C);
mpc_fp2_mul(F, F, KECI, p);
mpc_fp2_add(F, F, E, p);
mpc_fp2_set(g->ft, F);
mpc_fp2_set(g->ft2, D);
}
/*calculate Fp12 multiplication by down-dimension to Fp6*/
static void fl(mpc12_t F, mpc12_t L, const uint32_t p[8])
{
mpc_t m;
mpc6_t C1, C2, A1, A2;
mpc_fp6_add(C1, F->f, F->fW, p);
mpc_fp6_add(C2, L->f, L->fW, p);
Mp6(C1, C2, C1, p);
Mp6(F->f, L->f, A1, p);
Mp6(F->fW, L->fW, A2, p);
mpc_fp6_sub(C1, C1, A1, p);
mpc_fp6_sub(C1, C1, A2, p);
/*A2:=A2*t*/
KECI_init();
/*ft2->f*/
mpc_fp2_mul(m, A2->ft2, KECI, p);
mpc_fp2_set(A2->ft2, A2->ft);
mpc_fp2_set(A2->ft, A2->f);
mpc_fp2_set(A2->f, m);
mpc_fp6_add(A2, A2, A1, p);
mpc_fp6_set(F->f, A2);
mpc_fp6_set(F->fW, C1);
}
/*Two-element modular multiplication in Fq^12, g = a * b % p*/
static void Mp12(mpc12_t a, mpc12_t b, mpc12_t g, const uint32_t p[8])
{
mpc6_t a1, a2, b1, b2, C, D;
mpc_t m;
mpc_fp6_set(a1, a->f);
mpc_fp6_set(a2, a->fW);
mpc_fp6_set(b1, b->f);
mpc_fp6_set(b2, b->fW);
Mp6(a1, b1, C, p);
Mp6(a2, b2, D, p);
mpc_fp6_add(a1, a1, a2, p);
mpc_fp6_add(a2, b1, b2, p);
Mp6(a1, a2, a1, p);
mpc_fp6_sub(a1, a1, D, p);
mpc_fp6_sub(a1, a1, C, p);
KECI_init();
mpc_fp2_mul(m, D->ft2, KECI, p);
mpc_fp2_set(D->ft2, D->ft);
mpc_fp2_set(D->ft, D->f);
mpc_fp2_set(D->f, m);
mpc_fp6_add(D, D, C, p);
mpc_fp6_set(g->f, D);
mpc_fp6_set(g->fW, a1);
}
static void mpc_fp12_set(mpc12_t dst, const mpc12_t src)
{
mpc_fp2_set(dst->f->f, src->f->f);
mpc_fp2_set(dst->f->ft, src->f->ft);
mpc_fp2_set(dst->f->ft2, src->f->ft2);
mpc_fp2_set(dst->fW->f, src->fW->f);
mpc_fp2_set(dst->fW->ft, src->fW->ft);
mpc_fp2_set(dst->fW->ft2, src->fW->ft2);
}
/*please make sure a != c*/
void fp12_modexp(mpc12_t a, uint32_t b[], uint32_t bWordLen, mpc12_t c)
{
uint32_t i;
mpc_fp12_set(c, a);
i = get_valid_bits(b, bWordLen);
while (0u != (--i)) {
/*squaring*/
Mp12(c, c, c, sm9p256v1_p);
if (1u == Get_BitValue(b, i)) {
Mp12(c, a, c, sm9p256v1_p);
}
}
}
static void line1(const mpc_t Tx, const mpc_t Ty, const mpc_t Tz,
const mpc_t P1x, const mpc_t P1y, const mpc_t Gz, mpc12_t ret,
const uint32_t p[8])
{
mpc_t A, B, D, E, tmp;
Mp2(Tz, Tz, A, p);
Mp2(Gz, A, B, p);
mpc_fp2_mul(A, A, P1x, p);
mpc_fp2_mul(B, B, P1y, p);
mpc_fp2_mul(D, Ty, Ty, p);
mpc_fp2_add(D, D, D, p);
mpc_fp2_mul(E, Tx, Tx, p);
mpc_fp2_add(E, E, E, p);
mpc_fp2_mul(tmp, Tx, Tx, p);
mpc_fp2_add(E, E, tmp, p);
Mp2(A, E, A, p);
Mp2(E, Tx, E, p);
mpc_fp2_sub(D, D, E, p);
pke_sub(p, D->im, D->im, 8);
pke_sub(p, D->re, D->re, 8);
pke_sub(p, A->im, A->im, 8);
pke_sub(p, A->re, A->re, 8);
mpc_fp2_set(ret->f->ft2, B);
mpc_fp2_set(ret->fW->f, D);
mpc_fp2_set(ret->fW->ft, A);
}
static void line2(const mpc_t Tx, const mpc_t Ty, const mpc_t Tz,
const mpc_t Q1x, const mpc_t Q1y, const mpc_t P1x,
const mpc_t P1y, const mpc_t Gz, mpc12_t ret,
const uint32_t p[8])
{
mpc_t A, B, C, G;
mpc_fp2_mul(A, Gz, P1y, p);
mpc_fp2_mul(C, Tz, Tz, p);
mpc_fp2_mul(C, C, Tz, p);
mpc_fp2_mul(C, C, Q1y, p);
mpc_fp2_sub(C, C, Ty, p);
Mp2(C, Q1x, G, p);
mpc_fp2_mul(C, C, P1x, p);
Mp2(Q1y, Gz, B, p);
mpc_fp2_sub(B, B, G, p);
pke_sub(p, B->im, B->im, 8);
pke_sub(p, B->re, B->re, 8);
pke_sub(p, C->im, C->im, 8);
pke_sub(p, C->re, C->re, 8);
/*new combine 2015/11/6,fit M type*/
mpc_fp2_set(ret->f->ft2, A);
mpc_fp2_set(ret->fW->f, B);
mpc_fp2_set(ret->fW->ft, C);
}
static void to_p(mpc12_t f, mpc12_t g, const uint32_t p[8])
{
mpc_t a1, a2, a3, a4, a5, a6;
mpc_fp2_set(a1, f->f->f);
mpc_fp2_set(a2, f->f->ft);
mpc_fp2_set(a3, f->f->ft2);
mpc_fp2_set(a4, f->fW->f);
mpc_fp2_set(a5, f->fW->ft);
mpc_fp2_set(a6, f->fW->ft2);
pke_sub(p, a1->im, a1->im, 8);
pke_sub(p, a2->im, a2->im, 8);
pke_sub(p, a3->im, a3->im, 8);
pke_sub(p, a4->im, a4->im, 8);
pke_sub(p, a5->im, a5->im, 8);
pke_sub(p, a6->im, a6->im, 8);
kn_init();
mpc_fp2_mod(a1, a1, p);
mpc_fp2_mul(a2, a2, k2, p);
mpc_fp2_mul(a3, a3, k4, p);
mpc_fp2_mul(a4, a4, k1, p);
mpc_fp2_mul(a5, a5, k3, p);
mpc_fp2_mul(a6, a6, k5, p);
mpc_fp2_set(g->f->f, a1);
mpc_fp2_set(g->f->ft, a2);
mpc_fp2_set(g->f->ft2, a3);
mpc_fp2_set(g->fW->f, a4);
mpc_fp2_set(g->fW->ft, a5);
mpc_fp2_set(g->fW->ft2, a6);
kn_clear();
}
static void to_p2(mpc12_t f, mpc12_t g, const uint32_t p[8])
{
mpc_t a1, a2, a3, a4, a5, a6;
mpc_fp2_set(a1, f->f->f);
mpc_fp2_set(a2, f->f->ft);
mpc_fp2_set(a3, f->f->ft2);
mpc_fp2_set(a4, f->fW->f);
mpc_fp2_set(a5, f->fW->ft);
mpc_fp2_set(a6, f->fW->ft2);
gn_init();
mpc_fp2_mod(a1, a1, p);
mpc_fp2_mul(a2, a2, g2, p);
mpc_fp2_mul(a3, a3, g4, p);
mpc_fp2_mul(a4, a4, g1, p);
mpc_fp2_mul(a5, a5, g3, p);
mpc_fp2_mul(a6, a6, g5, p);
mpc_fp2_set(g->f->f, a1);
mpc_fp2_set(g->f->ft, a2);
mpc_fp2_set(g->f->ft2, a3);
mpc_fp2_set(g->fW->f, a4);
mpc_fp2_set(g->fW->ft, a5);
mpc_fp2_set(g->fW->ft2, a6);
gn_clear();
}
static void to_p3(mpc12_t f, mpc12_t g, const uint32_t p[8])
{
mpc_t a1, a2, a3, a4, a5, a6;
mpc_fp2_set(a1, f->f->f);
mpc_fp2_set(a2, f->f->ft);
mpc_fp2_set(a3, f->f->ft2);
mpc_fp2_set(a4, f->fW->f);
mpc_fp2_set(a5, f->fW->ft);
mpc_fp2_set(a6, f->fW->ft2);
pke_sub(p, a1->im, a1->im, 8);
pke_sub(p, a2->im, a2->im, 8);
pke_sub(p, a3->im, a3->im, 8);
pke_sub(p, a4->im, a4->im, 8);
pke_sub(p, a5->im, a5->im, 8);
pke_sub(p, a6->im, a6->im, 8);
en_init();
mpc_fp2_mod(a1, a1, p);
mpc_fp2_mul(a2, a2, e2, p);
mpc_fp2_mul(a3, a3, e4, p);
mpc_fp2_mul(a4, a4, e1, p);
mpc_fp2_mul(a5, a5, e3, p);
mpc_fp2_mul(a6, a6, e5, p);
mpc_fp2_set(g->f->f, a1);
mpc_fp2_set(g->f->ft, a2);
mpc_fp2_set(g->f->ft2, a3);
mpc_fp2_set(g->fW->f, a4);
mpc_fp2_set(g->fW->ft, a5);
mpc_fp2_set(g->fW->ft2, a6);
en_clear();
}
/*Invert the elements in Fp^2, g = f^(-1) mod p*/
static void inv_p2(mpc_t f, mpc_t g, const uint32_t p[8])
{
uint32_t c1[8];
uint32_t c2[8];
pke_sub(p, f->im, g->im, 8);
(void)pke_modmul(p, f->re, f->re, c1, 8);
(void)pke_modmul(p, f->im, f->im, c2, 8);
(void)pke_modadd(p, c2, c2, c2, 8);
(void)pke_modadd(p, c1, c2, c1, 8);
(void)pke_modinv(p, c1, c1, 8, 8);
(void)pke_modmul(p, f->re, c1, g->re, 8);
(void)pke_modmul(p, g->im, c1, g->im, 8);
}
/*Invert the elements in Fp^6, g = f^(-1) mod p*/
static void inv_p6(mpc6_t f, mpc6_t g, const uint32_t p[8])
{
mpc_t a, b, c, A, B, C, D, E, F;
mpc_fp2_set(a, f->f);
mpc_fp2_set(b, f->ft);
mpc_fp2_set(c, f->ft2);
mpc_fp2_mul(A, a, a, p);
mpc_fp2_mul(B, b, c, p);
KECI_init();
mpc_fp2_mul(B, KECI, B, p);
mpc_fp2_sub(A, A, B, p);
mpc_fp2_mul(B, c, c, p);
mpc_fp2_mul(B, KECI, B, p);
mpc_fp2_mul(C, a, b, p);
mpc_fp2_sub(B, B, C, p);
mpc_fp2_mul(C, b, b, p);
mpc_fp2_mul(D, a, c, p);
mpc_fp2_sub(C, C, D, p);
mpc_fp2_mul(F, KECI, b, p);
mpc_fp2_mul(F, F, C, p);
mpc_fp2_mul(E, a, A, p);
mpc_fp2_add(F, F, E, p);
mpc_fp2_mul(E, KECI, c, p);
mpc_fp2_mul(E, E, B, p);
mpc_fp2_add(F, F, E, p);
inv_p2(F, F, p);
mpc_fp2_mul(A, A, F, p);
mpc_fp2_mul(B, B, F, p);
mpc_fp2_mul(C, C, F, p);
mpc_fp2_set(g->f, A);
mpc_fp2_set(g->ft, B);
mpc_fp2_set(g->ft2, C);
}
static void finalexp(mpc12_t f, const uint32_t p[8])
{
uint32_t i;
const uint32_t t_6_5[3] = {0x0215D941, 0x40000000, 0x00000002};
const uint32_t t2_6_1[4] = {0x0CB27659, 0x0000B98B, 0x019062ED, 0xD8000000};
mpc12_t A, S, D, E, G, a, b, f1, f2, f3, f4, ff1, bf, ab, tmp12;
mpc6_t c6, zero6, tmp1, tmp2, invc;
mpc_t m;
mpc_fp6_clears((mpc6_ptr)&zero6);
mpc_fp12_clears((mpc12_ptr)&D);
mpc_fp12_clears((mpc12_ptr)&E);
to_p2(f, A, p);
Mp12(A, f, A, p);
mpc_fp6_set(S->f, A->f);
/*S:=B[1] - B[2]*W;*/
mpc_fp6_sub(S->fW, zero6, A->fW, p);
Mp6(A->f, A->f, tmp1, p);
Mp6(A->fW, A->fW, tmp2, p);
/*-B[2]^2*/
mpc_fp6_sub(tmp2, zero6, tmp2, p);
KECI_init();
mpc_fp2_mul(m, tmp2->ft2, KECI, p);
mpc_fp2_set(tmp2->ft2, tmp2->ft);
mpc_fp2_set(tmp2->ft, tmp2->f);
/*-B[2]^2*t*/
mpc_fp2_set(tmp2->f, m);
/*finish C:=B[1]^2 - t*B[2]^2;*/
mpc_fp6_add(c6, tmp1, tmp2, p);
inv_p6(c6, invc, p);
mpc_fp6_set(D->f, invc);
Mp12(D, S, D, p);
mpc_fp6_set(E->f, invc);
Mp12(E, A, E, p);
Mp12(A, E, G, p);
Mp12(S, D, f, p);
fp12_modexp(G, (uint32_t *)t_6_5, 3, a);
to_p(a, b, p);
Mp12(a, b, b, p);
to_p(f, f1, p);
to_p2(f, f2, p);
to_p3(f, f3, p);
Mp12(f, f, f4, p);
Mp12(f, f4, f4, p);
/*make f^4 = f4*/
Mp12(f, f4, f4, p);
Mp12(f4, f3, f4, p);
Mp12(f1, f, ff1, p);
/*f1=f1^2*/
Mp12(f1, f1, f1, p);
Mp12(b, f1, bf, p);
Mp12(bf, f2, bf, p);
Mp12(a, b, ab, p);
/*ff1=ff1^9, tmp12=ff1*/
mpc_fp6_set(tmp12->f, ff1->f);
mpc_fp6_set(tmp12->fW, ff1->fW);
for (i = 0; i < 3; i++) {
/*doubling ff1*/
Mp12(ff1, ff1, ff1, p);
}
Mp12(ff1, tmp12, ff1, p);
Mp12(ff1, ab, ff1, p);
Mp12(f4, ff1, f4, p);
fp12_modexp(bf, (uint32_t *)t2_6_1, 4, tmp12);
Mp12(f4, tmp12, f, p);
}
static void FrobeniusTwist(const mpc_t Qx, const mpc_t Qy, mpc_t Fx, mpc_t Fy)
{
pke_sub(sm9p256v1_p, Qx->im, Fx->im, 8);
pke_sub(sm9p256v1_p, Qy->im, Fy->im, 8);
uint32_copy((uint32_t *)Fx->re, (uint32_t *)Qx->re, 8);
uint32_copy((uint32_t *)Fy->re, (uint32_t *)Qy->re, 8);
scal_init();
mpc_fp2_mul(Fx, Fx, scal1, sm9p256v1_p);
mpc_fp2_mul(Fy, Fy, scal2, sm9p256v1_p);
}
static void f_gen(mpc12_t f, const mpc_t Q1x, const mpc_t Q1y, const mpc_t Q1z,
const mpc_t P1x, const mpc_t P1y)
{
uint32_t i;
const uint32_t t_6_2[3] = {0x0215D93E, 0x40000000, 0x00000002};
mpc_t Tx, Ty, Tz, Gx, Gy, Gz, QFrobx, QFroby, QFrobmx, QFrobmy;
mpc12_t L1, tmp12;
mpc_fp2_set(Tx, Q1x);
mpc_fp2_set(Ty, Q1y);
mpc_fp2_set(Tz, Q1z);
mpc_fp12_clears(f);
f->f->f->re[0] = 0x00000001;
mpc_fp12_clears(L1);
mpc_fp12_clears(tmp12);
i = 66;
while (0u != (--i)) {
PD_fp2(Tx, Ty, Tz, Gx, Gy, Gz, sm9p256v1_p);
sp12(f, sm9p256v1_p);
line1(Tx, Ty, Tz, P1x, P1y, Gz, L1, sm9p256v1_p);
fl(f, L1, sm9p256v1_p);
mpc_fp2_set(Tx, Gx);
mpc_fp2_set(Ty, Gy);
mpc_fp2_set(Tz, Gz);
if (1u == Get_BitValue(t_6_2, i)) {
PA_fp2(Tx, Ty, Tz, Q1x, Q1y, sm9p256v1_p);
line2(Gx, Gy, Gz, Q1x, Q1y, P1x, P1y, Tz, tmp12, sm9p256v1_p);
Mp12(f, tmp12, f, sm9p256v1_p);
}
}
mpc_fp2_set(Tx, Gx);
mpc_fp2_set(Ty, Gy);
mpc_fp2_set(Tz, Gz);
FrobeniusTwist(Q1x, Q1y, QFrobx, QFroby);
PA_fp2(Tx, Ty, Tz, QFrobx, QFroby, sm9p256v1_p);
line2(Gx, Gy, Gz, QFrobx, QFroby, P1x, P1y, Tz, tmp12, sm9p256v1_p);
Mp12(f, tmp12, f, sm9p256v1_p);
mpc_fp2_set(Gx, Tx);
mpc_fp2_set(Gy, Ty);
mpc_fp2_set(Gz, Tz);
FrobeniusTwist(QFrobx, QFroby, QFrobmx, QFrobmy);
pke_sub(sm9p256v1_p, QFrobmy->re, QFrobmy->re, 8);
pke_sub(sm9p256v1_p, QFrobmy->im, QFrobmy->im, 8);
PA_fp2(Tx, Ty, Tz, QFrobmx, QFrobmy, sm9p256v1_p);
line2(Gx, Gy, Gz, QFrobmx, QFrobmy, P1x, P1y, Tz, tmp12, sm9p256v1_p);
Mp12(f, tmp12, f, sm9p256v1_p);
}
/*Calculation of bilinear pair transformation e*/
static void pairing_raw(mpc12_t f, const mpc_t Q1x, const mpc_t Q1y,
const mpc_t Q1z, const mpc_t P1x, const mpc_t P1y)
{
f_gen(f, Q1x, Q1y, Q1z, P1x, P1y);
finalexp(f, sm9p256v1_p);
}
void G2_pointMul_P2(uint32_t *k, uint32_t kWordLen, fp2_pt_t Q)
{
uint32_t i;
i = get_valid_bits(k, 8);
mpc_fp2_set(Q->x, fp2ptP2->x);
mpc_fp2_set(Q->y, fp2ptP2->y);
mpc_fp2_set(Q->z, fp2ptP2->z);
while (0u != (--i)) {
PD_fp2(Q->x, Q->y, Q->z, Q->x, Q->y, Q->z, sm9p256v1_p);
if (1u == Get_BitValue(k, i)) {
PA_fp2(Q->x, Q->y, Q->z, fp2ptP2->x, fp2ptP2->y, sm9p256v1_p);
}
}
}
void set_G1_point_buffer_2_G2_point(uint8_t g1_point_buffer[64],
fp2_pt_t g2_point)
{
U8Big_to_U32Small_8(g2_point->x->re, (const uint8_t *)(g1_point_buffer));
U8Big_to_U32Small_8(g2_point->y->re,
(const uint8_t *)(g1_point_buffer + 32));
uint32_clear(g2_point->x->im, 8);
uint32_clear(g2_point->y->im, 8);
mpc_fp2_clears(g2_point->z);
g2_point->z->re[0] = 0x00000001;
}
void set_G2_point_buffer_2_G2_point(uint8_t g1_point_buffer[128],
fp2_pt_t g2_point)
{
U8Big_to_U32Small_8(g2_point->x->im, (const uint8_t *)g1_point_buffer);
U8Big_to_U32Small_8(g2_point->x->re,
(const uint8_t *)(g1_point_buffer + 32));
U8Big_to_U32Small_8(g2_point->y->im,
(const uint8_t *)(g1_point_buffer + 64));
U8Big_to_U32Small_8(g2_point->y->re,
(const uint8_t *)(g1_point_buffer + 96));
mpc_fp2_clears(g2_point->z);
g2_point->z->re[0] = 0x00000001;
}
uint32_t sm9_sign_gen_mastPubKey_from_mastPriKey(uint8_t ks[32],
uint8_t Ppub_s[128])
{
uint32_t tmp_ks[8];
fp2_pt_t MastPubKey;
if (NULL == ks || NULL == Ppub_s) {
return SM9_BUFFER_NULL;
} else {
;
}
U8Big_to_U32Small_8(tmp_ks, ks);
/*make sure sysPriKey in [1, n-1]*/
if (uint32_bignum_check_zero(tmp_ks, 8)) {
return SM9_ZERO_ALL;
} else if (uint32_bignumcmp(tmp_ks, 8, (uint32_t *)sm9p256v1_n, 8) >= 0) {
return SM9_INTEGER_TOO_BIG;
} else {
;
}
G2_pointMul_P2(tmp_ks, 8, MastPubKey);
coordinate_convert(MastPubKey->x, MastPubKey->y, MastPubKey->z,
MastPubKey->x, MastPubKey->y);
U32Small_to_U8Big(Ppub_s, MastPubKey->x->im);
U32Small_to_U8Big((uint8_t *)(Ppub_s + 32), MastPubKey->x->re);
U32Small_to_U8Big((uint8_t *)(Ppub_s + 64), MastPubKey->y->im);
U32Small_to_U8Big((uint8_t *)(Ppub_s + 96), MastPubKey->y->re);
return SM9_SUCCESS;
}
uint32_t sm9_sign_gen_mastKeyPair(uint8_t ks[32], uint8_t Ppub_s[128])
{
uint32_t ret;
if (NULL == ks || NULL == Ppub_s) {
return SM9_BUFFER_NULL;
} else {
;
}
SM9_GETKEY_LOOP:
get_rand(ks, 32);
ret = sm9_sign_gen_mastPubKey_from_mastPriKey(ks, Ppub_s);
/*make sure priKey in [1, n-1]*/
if ((SM9_ZERO_ALL == ret) || (SM9_INTEGER_TOO_BIG == ret)) {
goto SM9_GETKEY_LOOP;
} else {
;
}
return ret;
}
uint32_t sm9_sign_gen_userPriKey(const uint8_t *IDA, uint32_t IDA_byteLen,
uint8_t hid, uint8_t ks[32], uint8_t dsA[64])
{
uint32_t tmp_ks[8];
uint32_t tmp[8];
if (NULL == IDA || NULL == ks || NULL == dsA) {
return SM9_BUFFER_NULL;
} else if ((0 == IDA_byteLen) || (IDA_byteLen >= SM9_MAX_ID_BYTE_LEN)) {
return SM9_INPUT_INVALID;
} else {
;
}
U8Big_to_U32Small_8(tmp_ks, ks);
/*make sure sysPriKey in [1, n-1]*/
if (uint32_bignum_check_zero(tmp_ks, 8)) {
return SM9_ZERO_ALL;
} else if (uint32_bignumcmp(tmp_ks, 8, (uint32_t *)sm9p256v1_n, 8) >= 0) {
return SM9_INTEGER_TOO_BIG;
} else {
;
}
ibe_H1_H2(1, IDA, IDA_byteLen, (uint8_t *)(&hid), 1, tmp);
pke_modadd(sm9p256v1_n, tmp, tmp_ks, tmp, 8);
if (uint32_bignum_check_zero(tmp, 8)) {
return SM9_ZERO_ALL;
} else {
;
}
pke_modinv(sm9p256v1_n, tmp, tmp, 8, 8);
pke_modmul(sm9p256v1_n, tmp, tmp_ks, tmp, 8);
eccp_pointMul((eccp_curve_t *)sm9_curve, tmp, (uint32_t *)fp2ptP1->x->re,
(uint32_t *)fp2ptP1->y->re, tmp_ks, tmp);
U32Small_to_U8Big(dsA, tmp_ks);
U32Small_to_U8Big((uint8_t *)(dsA + 32), tmp);
return SM9_SUCCESS;
}
/*random r*/
static uint8_t sm9_sign_with_r(mpc12_t fg, uint32_t *r, const uint8_t *M,
uint32_t MByteLen, uint32_t tmp[8],
uint8_t h[32])
{
uint8_t h2rf_para[32 * 12];
mpc12_t omega;
fp12_modexp(fg, r, 8, omega);
FE2OSP(omega, h2rf_para);
ibe_H1_H2(2, M, MByteLen, h2rf_para, 32 * 12, tmp);
U32Small_to_U8Big(h, tmp);
pke_modsub(sm9p256v1_n, r, tmp, tmp, 8);
if (uint32_bignum_check_zero(tmp, 8)) {
return SM9_ZERO_ALL;
}
return 0;
}
uint32_t sm9_sign(const uint8_t *M, uint32_t MByteLen,
const uint8_t Ppub_s[128], const uint8_t dsA[64],
uint8_t r[32], uint8_t h[32], uint8_t S[65])
{
uint32_t tmp_r[8];
uint32_t tmp[8];
mpc12_t fp12g;
fp2_pt_t MastPubKey, SigPriKey;
set_G2_point_buffer_2_G2_point((uint8_t *)Ppub_s, MastPubKey);
set_G1_point_buffer_2_G2_point((uint8_t *)dsA, SigPriKey);
pairing_raw(fp12g, MastPubKey->x, MastPubKey->y, MastPubKey->z, fp2ptP1->x,
fp2ptP1->y);
if (NULL == r) {
SM9_SIGN_LOOP:
get_rand((uint8_t *)tmp_r, 32);
/*make sure r in [1, n-1]*/
if (uint32_bignum_check_zero(tmp_r, 8)) {
goto SM9_SIGN_LOOP;
} else if (uint32_bignumcmp(tmp_r, 8, (uint32_t *)sm9p256v1_n, 8) >=
0) {
goto SM9_SIGN_LOOP;
} else {
;
}
if (sm9_sign_with_r(fp12g, tmp_r, M, MByteLen, tmp, h)) {
goto SM9_SIGN_LOOP;
} else {
;
}
} else {
U8Big_to_U32Small_8(tmp_r, r);
/*make sure r in [1, n-1]*/
if (uint32_bignum_check_zero(tmp_r, 8)) {
return SM9_ZERO_ALL;
} else if (uint32_bignumcmp(tmp_r, 8, (uint32_t *)sm9p256v1_n, 8) >=
0) {
return SM9_INTEGER_TOO_BIG;
} else {
;
}
if (sm9_sign_with_r(fp12g, tmp_r, M, MByteLen, tmp, h)) {
return SM9_ZERO_ALL;
} else {
;
}
}
eccp_pointMul((eccp_curve_t *)sm9_curve, tmp, SigPriKey->x->re,
SigPriKey->y->re, tmp, tmp_r);
S[0] = 0x04;
U32Small_to_U8Big((uint8_t *)(S + 1), tmp);
U32Small_to_U8Big((uint8_t *)(S + 33), tmp_r);
return SM9_SUCCESS;
}
static uint8_t sm9_pointVerify(fp2_pt_t S)
{
uint32_t A[8], B[8], C[8];
uint32_clear(C, 8);
C[0] = 0x00000005;
pke_modmul(sm9p256v1_p, S->x->re, S->x->re, A, 8);
pke_modmul(sm9p256v1_p, A, S->x->re, A, 8);
pke_modmul(sm9p256v1_p, S->y->re, S->y->re, B, 8);
pke_modadd(sm9p256v1_p, A, C, A, 8);
return uint32_cmp(A, B);
}
uint32_t sm9_verify(const uint8_t *M, uint32_t MByteLen, const uint8_t *IDA,
uint32_t IDA_byteLen, uint8_t hid,
const uint8_t Ppub_s[128], const uint8_t h[32],
const uint8_t S[65])
{
uint8_t h2rf_para[32 * 12];
uint32_t SigH[8];
uint32_t tmp[8];
fp2_pt_t MastPubKey, SigS, TP2;
mpc12_t fp12g, omega;
if (NULL == M || NULL == IDA || NULL == Ppub_s || NULL == h || NULL == S) {
return SM9_BUFFER_NULL;
}
if ((0 == IDA_byteLen) || (IDA_byteLen >= SM9_MAX_ID_BYTE_LEN) ||
(SM9_POINT_NOT_COMPRESSED != S[0])) {
return SM9_INPUT_INVALID;
}
U8Big_to_U32Small_8(SigH, h);
/*check h in [1, n-1]*/
if (uint32_bignum_check_zero(SigH, 8)) {
return SM9_ZERO_ALL;
}
if (uint32_bignumcmp(SigH, 8, (uint32_t *)sm9p256v1_n, 8) >= 0) {
return SM9_INTEGER_TOO_BIG;
}
set_G1_point_buffer_2_G2_point((uint8_t *)(S + 1), SigS);
if (sm9_pointVerify(SigS)) {
return SM9_NOT_ON_CURVE;
}
set_G2_point_buffer_2_G2_point((uint8_t *)Ppub_s, MastPubKey);
pairing_raw(fp12g, MastPubKey->x, MastPubKey->y, MastPubKey->z, fp2ptP1->x,
fp2ptP1->y);
fp12_modexp(fp12g, SigH, 8, omega);
ibe_H1_H2(1, IDA, IDA_byteLen, (uint8_t *)(&hid), 1, tmp);
G2_pointMul_P2(tmp, 8, TP2);
PA_fp2(TP2->x, TP2->y, TP2->z, MastPubKey->x, MastPubKey->y, sm9p256v1_p);
coordinate_convert(TP2->x, TP2->y, TP2->z, TP2->x, TP2->y);
pairing_raw(fp12g, TP2->x, TP2->y, TP2->z, SigS->x, SigS->y);
Mp12(omega, fp12g, omega, sm9p256v1_p);
FE2OSP(omega, h2rf_para);
ibe_H1_H2(2, M, MByteLen, h2rf_para, 32 * 12, tmp);
if (uint32_cmp(tmp, SigH)) {
return SM9_VERIFY_FAILED;
}
return SM9_SUCCESS;
}
uint32_t sm9_enc_gen_mastPubKey_from_mastPriKey(uint8_t ke[32],
uint8_t Ppub_e[64])
{
uint32_t tmp_ke[8];
uint32_t tmp1[8];
uint32_t tmp2[8];
if (NULL == ke || NULL == Ppub_e) {
return SM9_BUFFER_NULL;
} else {
;
}
U8Big_to_U32Small_8(tmp_ke, ke);
/*make sure priKey in [1, n-1]*/
if (uint32_bignum_check_zero(tmp_ke, 8)) {
return SM9_ZERO_ALL;
}
if (uint32_bignumcmp(tmp_ke, 8, (uint32_t *)sm9p256v1_n, 8) >= 0) {
return SM9_INTEGER_TOO_BIG;
}
eccp_pointMul((eccp_curve_t *)sm9_curve, tmp_ke, (uint32_t *)fp2ptP1->x->re,
(uint32_t *)fp2ptP1->y->re, tmp1, tmp2);
U32Small_to_U8Big(Ppub_e, tmp1);
U32Small_to_U8Big((uint8_t *)(Ppub_e + 32), tmp2);
return SM9_SUCCESS;
}
uint32_t sm9_enc_gen_mastKeyPair(uint8_t ke[32], uint8_t Ppub_e[64])
{
uint32_t ret;
if (NULL == ke || NULL == Ppub_e) {
return SM9_BUFFER_NULL;
} else {
;
}
SM9_GETKEY_LOOP:
get_rand(ke, 32);
ret = sm9_enc_gen_mastPubKey_from_mastPriKey(ke, Ppub_e);
/*make sure priKey in [1, n-1]*/
if ((SM9_ZERO_ALL == ret) || (SM9_INTEGER_TOO_BIG == ret)) {
goto SM9_GETKEY_LOOP;
} else {
;
}
return ret;
}
uint32_t sm9_enc_gen_userPriKey(const uint8_t *IDB, uint32_t IDB_byteLen,
uint8_t hid, uint8_t ke[32], uint8_t deB[128])
{
uint32_t tmp_ke[8];
uint32_t tmp1[8];
uint32_t tmp2[8];
fp2_pt_t UserPrivKey;
if (NULL == IDB || NULL == ke || NULL == deB) {
return SM9_BUFFER_NULL;
} else if ((0 == IDB_byteLen) || (IDB_byteLen >= SM9_MAX_ID_BYTE_LEN)) {
return SM9_INPUT_INVALID;
} else {
;
}
U8Big_to_U32Small_8(tmp_ke, ke);
/*make sure sysPriKey in [1, n-1]*/
if (uint32_bignum_check_zero(tmp_ke, 8)) {
return SM9_ZERO_ALL;
} else if (uint32_bignumcmp(tmp_ke, 8, (uint32_t *)sm9p256v1_n, 8) >= 0) {
return SM9_INTEGER_TOO_BIG;
} else {
;
}
ibe_H1_H2(1, IDB, IDB_byteLen, (uint8_t *)(&hid), 1, tmp1);
pke_modadd(sm9p256v1_n, tmp1, tmp_ke, tmp2, 8);
if (uint32_bignum_check_zero(tmp2, 8)) {
return SM9_ZERO_ALL;
} else {
;
}
pke_modinv(sm9p256v1_n, tmp2, tmp1, 8, 8);
pke_modmul(sm9p256v1_n, tmp1, tmp_ke, tmp2, 8);
G2_pointMul_P2(tmp2, 8, UserPrivKey);
coordinate_convert(UserPrivKey->x, UserPrivKey->y, UserPrivKey->z,
UserPrivKey->x, UserPrivKey->y);
U32Small_to_U8Big(deB, UserPrivKey->x->im);
U32Small_to_U8Big((uint8_t *)(deB + 32), UserPrivKey->x->re);
U32Small_to_U8Big((uint8_t *)(deB + 64), UserPrivKey->y->im);
U32Small_to_U8Big((uint8_t *)(deB + 96), UserPrivKey->y->re);
return SM9_SUCCESS;
}
uint32_t sm9_wrap_key(const uint8_t *IDB, uint32_t IDB_byteLen, uint8_t hid,
const uint8_t Ppub_e[64], uint8_t r[32], uint8_t C[64],
uint32_t KByteLen, uint8_t *K)
{
uint32_t tmp_r[8];
uint32_t tmp[8], Ax[8], Ay[8];
uint8_t h2rf_para[32 * 12];
mpc12_t fp12g, omega;
fp2_pt_t MastPubKey;
if (NULL == IDB || NULL == Ppub_e || NULL == K || NULL == C) {
return SM9_BUFFER_NULL;
}
if ((0 == IDB_byteLen) || (IDB_byteLen >= SM9_MAX_ID_BYTE_LEN)) {
return SM9_INPUT_INVALID;
}
set_G1_point_buffer_2_G2_point((uint8_t *)Ppub_e, MastPubKey);
ibe_H1_H2(1, IDB, IDB_byteLen, (uint8_t *)(&hid), 1, tmp);
eccp_pointMul((eccp_curve_t *)sm9_curve, tmp, (uint32_t *)fp2ptP1->x->re,
(uint32_t *)fp2ptP1->y->re, Ax, Ay);
eccp_pointAdd((eccp_curve_t *)sm9_curve, Ax, Ay, MastPubKey->x->re,
MastPubKey->y->re, Ax, Ay);
if (NULL == r) {
SM9_WRAP_LOOP:
get_rand((uint8_t *)tmp_r, 32);
/*make sure r in [1, n-1]*/
if (uint32_bignum_check_zero(tmp_r, 8)) {
goto SM9_WRAP_LOOP;
} else if (uint32_bignumcmp(tmp_r, 8, (uint32_t *)sm9p256v1_n, 8) >=
0) {
goto SM9_WRAP_LOOP;
} else {
;
}
} else {
U8Big_to_U32Small_8(tmp_r, r);
/*make sure r in [1, n-1]*/
if (uint32_bignum_check_zero(tmp_r, 8)) {
return SM9_ZERO_ALL;
} else if (uint32_bignumcmp(tmp_r, 8, (uint32_t *)sm9p256v1_n, 8) >=
0) {
return SM9_INTEGER_TOO_BIG;
} else {
;
}
}
eccp_pointMul((eccp_curve_t *)sm9_curve, tmp_r, Ax, Ay, Ax, Ay);
pairing_raw(fp12g, fp2ptP2->x, fp2ptP2->y, fp2ptP2->z, MastPubKey->x,
MastPubKey->y);
fp12_modexp(fp12g, tmp_r, 8, omega);
FE2OSP(omega, h2rf_para);
U32Small_to_U8Big(C, Ax);
U32Small_to_U8Big(C + 32, Ay);
ibe_kdf_wrap_enc(C, h2rf_para, IDB, IDB_byteLen, K, KByteLen, NULL, 0);
if (uint8_bignum_check_zero(K, KByteLen)) {
if (NULL == r) {
goto SM9_WRAP_LOOP;
} else {
return SM9_ZERO_ALL;
}
}
return SM9_SUCCESS;
}
uint32_t sm9_unwrap_key(const uint8_t *IDB, uint32_t IDB_byteLen,
const uint8_t deB[128], const uint8_t C[64],
uint32_t KByteLen, uint8_t *K)
{
uint8_t h2rf_para[32 * 12];
mpc12_t fp12g;
fp2_pt_t DecPriKey, C1;
if (NULL == IDB || NULL == deB || NULL == C || NULL == K) {
return SM9_BUFFER_NULL;
}
if ((0 == IDB_byteLen) || (IDB_byteLen >= SM9_MAX_ID_BYTE_LEN)) {
return SM9_INPUT_INVALID;
}
set_G1_point_buffer_2_G2_point((uint8_t *)C, C1);
if (sm9_pointVerify(C1)) {
return SM9_NOT_ON_CURVE;
}
set_G2_point_buffer_2_G2_point((uint8_t *)deB, DecPriKey);
pairing_raw(fp12g, DecPriKey->x, DecPriKey->y, DecPriKey->z, C1->x, C1->y);
FE2OSP(fp12g, h2rf_para);
ibe_kdf_wrap_enc(C, h2rf_para, IDB, IDB_byteLen, K, KByteLen, NULL, 0);
if (uint8_bignum_check_zero(K, KByteLen)) {
return SM9_VERIFY_FAILED;
}
return SM9_SUCCESS;
}
uint32_t sm9_enc(const uint8_t *IDB, uint32_t IDB_byteLen, uint8_t hid,
const uint8_t *M, uint32_t MByteLen, const uint8_t Ppub_e[64],
uint8_t r[32], sm9_enc_type_e enc_type,
sm9_enc_padding_e padding_type, uint32_t K2ByteLen, uint8_t *C,
uint32_t *CByteLen)
{
uint32_t tmp_r[8];
uint32_t tmp[8], Ax[8], Ay[8];
uint8_t h2rf_para[32 * 12];
uint8_t tmpc1[64];
uint8_t K2[SM9_MAX_ENC_K2_BYTE_LEN];
hash_ctx_t ctx[1];
mpc12_t fp12g, omega;
fp2_pt_t MastPubKey;
uint32_t i, j, k, mlen;
uint8_t *pC;
if (enc_type > SM9_ENC_KDF_BLOCK_CIPHER) {
return SM9_INPUT_INVALID;
}
if (SM9_ENC_KDF_BLOCK_CIPHER == enc_type) {
if (padding_type > SM9_ENC_PKCS7_PADDING) {
return SM9_INPUT_INVALID;
} else if ((MByteLen & 0x0F) && (SM9_ENC_NO_PADDING == padding_type)) {
return SM9_INPUT_INVALID;
} else {
;
}
}
if (NULL == IDB || NULL == Ppub_e || NULL == M || NULL == C) {
return SM9_BUFFER_NULL;
}
if (M == C) {
return SM9_IN_OUT_SAME_BUFFER;
}
if ((0 == MByteLen) || (MByteLen >= SM9_MAX_MSG_BYTE_LEN)) {
return SM9_INPUT_INVALID;
}
if ((0 == IDB_byteLen) || (IDB_byteLen >= SM9_MAX_ID_BYTE_LEN)) {
return SM9_INPUT_INVALID;
}
if (K2ByteLen > SM9_MAX_ENC_K2_BYTE_LEN) {
return SM9_INPUT_INVALID;
}
set_G1_point_buffer_2_G2_point((uint8_t *)Ppub_e, MastPubKey);
ibe_H1_H2(1, IDB, IDB_byteLen, (uint8_t *)(&hid), 1, tmp);
eccp_pointMul((eccp_curve_t *)sm9_curve, tmp, (uint32_t *)fp2ptP1->x->re,
(uint32_t *)fp2ptP1->y->re, Ax, Ay);
eccp_pointAdd((eccp_curve_t *)sm9_curve, Ax, Ay, MastPubKey->x->re,
MastPubKey->y->re, Ax, Ay);
if (NULL == r) {
SM9_ENC_LOOP:
get_rand((uint8_t *)tmp_r, 32);
/*make sure r in [1, n-1]*/
if (uint32_bignum_check_zero(tmp_r, 8)) {
goto SM9_ENC_LOOP;
} else if (uint32_bignumcmp(tmp_r, 8, (uint32_t *)sm9p256v1_n, 8) >=
0) {
goto SM9_ENC_LOOP;
} else {
;
}
} else {
U8Big_to_U32Small_8(tmp_r, r);
/*make sure r in [1, n-1]*/
if (uint32_bignum_check_zero(tmp_r, 8)) {
return SM9_ZERO_ALL;
} else if (uint32_bignumcmp(tmp_r, 8, (uint32_t *)sm9p256v1_n, 8) >=
0) {
return SM9_INTEGER_TOO_BIG;
} else {
;
}
}
eccp_pointMul((eccp_curve_t *)sm9_curve, tmp_r, Ax, Ay, Ax, Ay);
pairing_raw(fp12g, fp2ptP2->x, fp2ptP2->y, fp2ptP2->z, MastPubKey->x,
MastPubKey->y);
fp12_modexp(fp12g, tmp_r, 8, omega);
FE2OSP(omega, h2rf_para);
U32Small_to_U8Big(tmpc1, Ax);
U32Small_to_U8Big(tmpc1 + 32, Ay);
pC = C + 96;
mlen = MByteLen;
if (SM9_ENC_KDF_STREAM_CIPHER == enc_type) {
i = ~mlen;
if (i < K2ByteLen) {
return SM9_INPUT_INVALID;
}
ibe_kdf_wrap_enc(tmpc1, h2rf_para, IDB, IDB_byteLen, pC, mlen, K2,
K2ByteLen);
if (uint8_bignum_check_zero(pC, mlen)) {
if (NULL == r) {
goto SM9_ENC_LOOP;
} else {
return SM9_ZERO_ALL;
}
}
for (i = 0; i < mlen; i++) {
pC[i] ^= M[i];
}
} else if (SM9_ENC_KDF_BLOCK_CIPHER == enc_type) {
ibe_kdf_wrap_enc(tmpc1, h2rf_para, IDB, IDB_byteLen, pC, 16, K2,
K2ByteLen);
if (uint8_bignum_check_zero(pC, 16)) {
if (NULL == r) {
goto SM9_ENC_LOOP;
} else {
return SM9_ZERO_ALL;
}
}
ske_hp_init(SKE_ALG_SM4, SKE_MODE_ECB, SKE_CRYPTO_ENCRYPT, pC, 0, NULL);
i = mlen & 0x0F;
j = mlen - i;
ske_hp_update_blocks((uint8_t *)M, pC, j);
if (SM9_ENC_PKCS7_PADDING == padding_type) {
k = 0x10 - i;
memset_(h2rf_para, k, 0x10);
if (i) {
memcpy_(h2rf_para, (uint8_t *)(M + j), i);
}
mlen += k;
ske_hp_update_blocks(h2rf_para, pC + j, 16);
}
} else {
;
}
*CByteLen = 96 + mlen;
for (i = 0; i < 64; i++) {
C[i] = tmpc1[i];
}
hash_init(ctx, HASH_SM3);
hash_update(ctx, pC, mlen);
hash_update(ctx, K2, K2ByteLen);
hash_final(ctx, C + 64);
return SM9_SUCCESS;
}
uint32_t sm9_dec(const uint8_t *IDB, uint32_t IDB_byteLen, const uint8_t *C,
uint32_t CByteLen, const uint8_t deB[128],
sm9_enc_type_e enc_type, sm9_enc_padding_e padding_type,
uint32_t K2ByteLen, uint8_t *M, uint32_t *MByteLen)
{
uint8_t K1[16];
uint8_t K2[SM9_MAX_ENC_K2_BYTE_LEN];
uint8_t h2rf_para[32 * 12];
const uint8_t *pC;
uint32_t i, j, tmplen;
hash_ctx_t ctx[1];
mpc12_t fp12g;
fp2_pt_t DecPriKey, C1;
if (enc_type > SM9_ENC_KDF_BLOCK_CIPHER) {
return SM9_INPUT_INVALID;
}
if (SM9_ENC_KDF_BLOCK_CIPHER == enc_type) {
if (padding_type > SM9_ENC_PKCS7_PADDING) {
return SM9_INPUT_INVALID;
} else if ((CByteLen - 96) & 0x0F) {
return SM9_INPUT_INVALID;
}
}
if (NULL == IDB || NULL == deB || NULL == M || NULL == C) {
return SM9_BUFFER_NULL;
}
if (M == C) {
return SM9_IN_OUT_SAME_BUFFER;
}
if (CByteLen < (96 + 1)) {
return SM9_INPUT_INVALID;
}
if ((0 == IDB_byteLen) || (IDB_byteLen >= SM9_MAX_ID_BYTE_LEN)) {
return SM9_INPUT_INVALID;
}
if (K2ByteLen > SM9_MAX_ENC_K2_BYTE_LEN) {
return SM9_INPUT_INVALID;
}
set_G1_point_buffer_2_G2_point((uint8_t *)C, C1);
if (sm9_pointVerify(C1)) {
return SM9_NOT_ON_CURVE;
}
set_G2_point_buffer_2_G2_point((uint8_t *)deB, DecPriKey);
pairing_raw(fp12g, DecPriKey->x, DecPriKey->y, DecPriKey->z, C1->x, C1->y);
FE2OSP(fp12g, h2rf_para);
pC = C + 96;
tmplen = CByteLen - 96;
j = 0;
if (SM9_ENC_KDF_STREAM_CIPHER == enc_type) {
ibe_kdf_wrap_enc(C, h2rf_para, IDB, IDB_byteLen, M, tmplen, K2,
K2ByteLen);
if (uint8_bignum_check_zero(M, tmplen)) {
return SM9_ZERO_ALL;
}
for (i = 0; i < tmplen; i++) {
M[i] ^= pC[i];
}
} else if (SM9_ENC_KDF_BLOCK_CIPHER == enc_type) {
if (CByteLen & 0x0F) {
return SM9_INPUT_INVALID;
}
ibe_kdf_wrap_enc(C, h2rf_para, IDB, IDB_byteLen, K1, 16, K2, K2ByteLen);
if (uint8_bignum_check_zero(K1, 16)) {
return SM9_ZERO_ALL;
}
ske_hp_init(SKE_ALG_SM4, SKE_MODE_ECB, SKE_CRYPTO_DECRYPT, K1, 0, NULL);
if (SM9_ENC_NO_PADDING == padding_type) {
ske_hp_update_blocks((uint8_t *)pC, M, tmplen);
} else {
ske_hp_update_blocks((uint8_t *)pC, M, tmplen - 16);
ske_hp_update_blocks((uint8_t *)(pC + tmplen - 16), h2rf_para, 16);
j = h2rf_para[16 - 1];
if ((j > 0x10) || (j == 0)) {
return SM9_DECRY_VERIFY_FAILED;
}
for (i = 16 - j; i < 16; i++) {
if (h2rf_para[i] != j) {
return SM9_DECRY_VERIFY_FAILED;
}
}
memcpy_(M + (tmplen - 16), h2rf_para, 16 - j);
}
} else {
;
}
hash_init(ctx, HASH_SM3);
hash_update(ctx, pC, tmplen);
hash_update(ctx, K2, K2ByteLen);
hash_final(ctx, h2rf_para);
pC = C + 64;
for (i = 0; i < 32; i++) {
if (pC[i] != h2rf_para[i]) {
return SM9_DECRY_VERIFY_FAILED;
}
}
if ((SM9_ENC_KDF_BLOCK_CIPHER == enc_type) &&
(SM9_ENC_PKCS7_PADDING == padding_type)) {
*MByteLen = tmplen - j;
} else {
*MByteLen = tmplen;
}
return SM9_SUCCESS;
}
uint32_t sm9_exckey_gen_mastPubKey_from_mastPriKey(uint8_t ke[32],
uint8_t Ppub_e[64])
{
return sm9_enc_gen_mastPubKey_from_mastPriKey(ke, Ppub_e);
}
uint32_t sm9_exckey_gen_mastKeyPair(uint8_t ke[32], uint8_t Ppub_e[64])
{
return sm9_enc_gen_mastKeyPair(ke, Ppub_e);
}
uint32_t sm9_exckey_gen_userPriKey(const uint8_t *IDA, uint32_t IDA_byteLen,
uint8_t hid, uint8_t ke[32],
uint8_t deA[128])
{
return sm9_enc_gen_userPriKey(IDA, IDA_byteLen, hid, ke, deA);
}
uint32_t sm9_exckey_gen_tmpPubKey_from_tmpPriKey(const uint8_t *IDB,
uint32_t IDB_byteLen,
uint8_t hid,
const uint8_t Ppub_e[64],
uint8_t rA[32], uint8_t RA[64])
{
uint32_t tmp_r[8];
uint32_t tmp1[8];
uint32_t tmp2[8];
uint32_t tmp3[8];
if ((NULL == IDB) || (NULL == Ppub_e) || (NULL == rA) || (NULL == RA)) {
return SM9_BUFFER_NULL;
}
if ((0 == IDB_byteLen) || (IDB_byteLen >= SM9_MAX_ID_BYTE_LEN)) {
return SM9_INPUT_INVALID;
}
ibe_H1_H2(1, IDB, IDB_byteLen, (uint8_t *)(&hid), 1, tmp1);
eccp_pointMul((eccp_curve_t *)sm9_curve, tmp1, (uint32_t *)fp2ptP1->x->re,
(uint32_t *)fp2ptP1->y->re, tmp1, tmp2);
U8Big_to_U32Small_8(tmp_r, (const uint8_t *)(Ppub_e));
U8Big_to_U32Small_8(tmp3, (const uint8_t *)(Ppub_e + 32));
eccp_pointAdd((eccp_curve_t *)sm9_curve, tmp1, tmp2, tmp_r, tmp3, tmp1,
tmp2);
U8Big_to_U32Small_8(tmp_r, rA);
/*make sure priKey in [1, n-1]*/
if (uint32_bignum_check_zero(tmp_r, 8)) {
return SM9_ZERO_ALL;
} else if (uint32_bignumcmp(tmp_r, 8, (uint32_t *)sm9p256v1_n, 8) >= 0) {
return SM9_INTEGER_TOO_BIG;
} else {
;
}
eccp_pointMul((eccp_curve_t *)sm9_curve, tmp_r, tmp1, tmp2, tmp1, tmp2);
U32Small_to_U8Big(RA, tmp1);
U32Small_to_U8Big((uint8_t *)(RA + 32), tmp2);
return SM9_SUCCESS;
}
uint32_t sm9_exckey_gen_tmpKeyPair(const uint8_t *IDB, uint32_t IDB_byteLen,
uint8_t hid, const uint8_t Ppub_e[64],
uint8_t rA[32], uint8_t RA[64])
{
uint32_t ret;
SM9_GETKEY_LOOP:
get_rand(rA, 32);
ret = sm9_exckey_gen_tmpPubKey_from_tmpPriKey(IDB, IDB_byteLen, hid, Ppub_e,
rA, RA);
if ((SM9_ZERO_ALL == ret) || (SM9_INTEGER_TOO_BIG == ret)) {
goto SM9_GETKEY_LOOP;
} else {
;
}
return SM9_SUCCESS;
}
static void sm9_exchkey_hash(sm9_exchange_role_e role, const uint8_t *g23,
const uint8_t *IDA, uint32_t IDA_byteLen,
const uint8_t *IDB, uint32_t IDB_byteLen,
const uint8_t *RA, const uint8_t *RB, uint8_t *out)
{
hash_ctx_t ctx[1];
hash_init(ctx, HASH_SM3);
hash_update(ctx, g23, 32 * 12 * 2);
if (SM9_ROLE_SPONSOR == role) {
hash_update(ctx, IDA, IDA_byteLen);
hash_update(ctx, IDB, IDB_byteLen);
hash_update(ctx, RA, 64);
hash_update(ctx, RB, 64);
} else if (SM9_ROLE_RESPONSOR == role) {
hash_update(ctx, IDB, IDB_byteLen);
hash_update(ctx, IDA, IDA_byteLen);
hash_update(ctx, RB, 64);
hash_update(ctx, RA, 64);
}
hash_final(ctx, out);
}
uint32_t sm9_exchangekey(sm9_exchange_role_e role, const uint8_t *IDA,
uint32_t IDA_byteLen, const uint8_t *IDB,
uint32_t IDB_byteLen, const uint8_t Ppub_e[64],
const uint8_t deA[128], const uint8_t rA[32],
const uint8_t RA[64], const uint8_t RB[64],
uint32_t KByteLen, uint8_t *KA, uint8_t S1[32],
uint8_t SA[32])
{
uint32_t tmp[8];
uint8_t digest[32];
hash_ctx_t ctx[1];
uint8_t tag;
fp2_pt_t MastPubKey, RRA, RRB;
mpc12_t fp12g1, fp12g2, fp12g3;
uint8_t h2rf_para[32 * 12 * 3];
if ((NULL == IDA) || (NULL == IDB) || (NULL == Ppub_e)) {
return SM9_BUFFER_NULL;
}
if ((NULL == deA) || (NULL == rA) || (NULL == RA) || (NULL == RB)) {
return SM9_BUFFER_NULL;
}
if ((NULL == KA) || (NULL == S1) || (NULL == SA)) {
return SM9_BUFFER_NULL;
}
if (role > SM9_ROLE_RESPONSOR) {
return SM9_EXCHANGE_ROLE_INVALID;
}
if ((0 == IDA_byteLen) || (IDA_byteLen >= SM9_MAX_ID_BYTE_LEN)) {
return SM9_INPUT_INVALID;
}
if ((0 == IDB_byteLen) || (IDB_byteLen >= SM9_MAX_ID_BYTE_LEN)) {
return SM9_INPUT_INVALID;
}
if (0 == KByteLen) {
return SM9_INPUT_INVALID;
}
set_G1_point_buffer_2_G2_point((uint8_t *)RA, RRA);
set_G1_point_buffer_2_G2_point((uint8_t *)RB, RRB);
if (sm9_pointVerify(RRB)) {
return SM9_NOT_ON_CURVE;
}
set_G1_point_buffer_2_G2_point((uint8_t *)Ppub_e, MastPubKey);
pairing_raw(fp12g2, fp2ptP2->x, fp2ptP2->y, fp2ptP2->z, MastPubKey->x,
MastPubKey->y);
U8Big_to_U32Small_8(tmp, rA);
fp12_modexp(fp12g2, tmp, 8, fp12g1);
set_G2_point_buffer_2_G2_point((uint8_t *)deA, MastPubKey);
pairing_raw(fp12g2, MastPubKey->x, MastPubKey->y, MastPubKey->z, RRB->x,
RRB->y);
fp12_modexp(fp12g2, tmp, 8, fp12g3);
if (SM9_ROLE_SPONSOR == role) {
FE2OSP(fp12g1, h2rf_para);
FE2OSP(fp12g2, h2rf_para + 32 * 12);
} else if (SM9_ROLE_RESPONSOR == role) {
FE2OSP(fp12g2, h2rf_para);
FE2OSP(fp12g1, h2rf_para + 32 * 12);
}
FE2OSP(fp12g3, h2rf_para + 32 * 12 * 2);
if (SM9_ROLE_SPONSOR == role) {
ibe_kdf_exc_key(IDA, IDA_byteLen, IDB, IDB_byteLen, RA, RB, h2rf_para,
KA, KByteLen);
} else if (SM9_ROLE_RESPONSOR == role) {
ibe_kdf_exc_key(IDB, IDB_byteLen, IDA, IDA_byteLen, RB, RA, h2rf_para,
KA, KByteLen);
} else {
;
}
tag = 0x82;
sm9_exchkey_hash(role, h2rf_para + 32 * 12, IDA, IDA_byteLen, IDB,
IDB_byteLen, RA, RB, digest);
hash_init(ctx, HASH_SM3);
hash_update(ctx, &tag, 1);
hash_update(ctx, h2rf_para, 32 * 12);
hash_update(ctx, digest, 32);
if (SM9_ROLE_SPONSOR == role) {
hash_final(ctx, S1);
} else if (SM9_ROLE_RESPONSOR == role) {
hash_final(ctx, SA);
} else {
;
}
tag = 0x83;
hash_init(ctx, HASH_SM3);
hash_update(ctx, &tag, 1);
hash_update(ctx, h2rf_para, 32 * 12);
hash_update(ctx, digest, 32);
if (SM9_ROLE_SPONSOR == role) {
hash_final(ctx, SA);
} else if (SM9_ROLE_RESPONSOR == role) {
hash_final(ctx, S1);
} else {
;
}
return SM9_SUCCESS;
}