From 347a578fa37bb49aee76d8435fd5f0f34875a34e Mon Sep 17 00:00:00 2001 From: godcansee Date: Sun, 16 Oct 2022 05:00:04 +0800 Subject: [PATCH 2/4] nss add implement of SM2 signature algorithm Co-authored-by:Huaxin Lu --- nss/lib/freebl/sm2.c | 823 +++++++++++++++++++++++++++++++++++++++++++ nss/lib/freebl/sm2.h | 23 ++ 2 files changed, 846 insertions(+) create mode 100644 nss/lib/freebl/sm2.c create mode 100644 nss/lib/freebl/sm2.h diff --git a/nss/lib/freebl/sm2.c b/nss/lib/freebl/sm2.c new file mode 100644 index 0000000..0ea85bc --- /dev/null +++ b/nss/lib/freebl/sm2.c @@ -0,0 +1,823 @@ +/* + * Copyright 2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include "sm2.h" + + +#define GETU32(p) ((PRUint32)(p)[0] << 24 | (PRUint32)(p)[1] << 16 | (PRUint32)(p)[2] << 8 | (PRUint32)(p)[3]) +#define PUTU32(p,V) ((p)[0] = (PRUint8)((V) >> 24), (p)[1] = (PRUint8)((V) >> 16), (p)[2] = (PRUint8)((V) >> 8), (p)[3] = (PRUint8)(V)) + +#define sm2_bn_init(r) memset((r),0,sizeof(SM2_BN)) +#define sm2_bn_set_zero(r) memset((r),0,sizeof(SM2_BN)) +#define sm2_bn_set_one(r) sm2_bn_set_word((r),1) +#define sm2_bn_copy(r,a) memcpy((r),(a),sizeof(SM2_BN)) +#define sm2_bn_clean(r) memset((r),0,sizeof(SM2_BN)) + +#define sm2_fp_init(r) sm2_bn_init(r) +#define sm2_fp_set_zero(r) sm2_bn_set_zero(r) +#define sm2_fp_set_one(r) sm2_bn_set_one(r) +#define sm2_fp_copy(r,a) sm2_bn_copy(r,a) +#define sm2_fp_clean(r) sm2_bn_clean(r) + +#define sm2_fn_init(r) sm2_bn_init(r) +#define sm2_fn_set_zero(r) sm2_bn_set_zero(r) +#define sm2_fn_set_one(r) sm2_bn_set_one(r) +#define sm2_fn_copy(r,a) sm2_bn_copy(r,a) +#define sm2_fn_clean(r) sm2_bn_clean(r) + +#define sm2_jacobian_point_set_infinity(R) sm2_jacobian_point_init(R) +#define sm2_jacobian_point_copy(R, P) memcpy((R), (P), sizeof(SM2_JACOBIAN_POINT)) + +#define SM2_POINT_MAX_SIZE (2 + 65) + +typedef PRUint64 SM2_BN[8]; + +typedef SM2_BN SM2_Fp; +typedef SM2_BN SM2_Fn; + +typedef struct { + SM2_BN X; + SM2_BN Y; + SM2_BN Z; +} SM2_JACOBIAN_POINT; + +typedef struct { + PRUint8 x[32]; + PRUint8 y[32]; +} SM2_POINT; + +const SM2_BN SM2_P = { + 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, +}; + +const SM2_BN SM2_A = { + 0xfffffffc, 0xffffffff, 0x00000000, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, +}; + +const SM2_BN SM2_B = { + 0x4d940e93, 0xddbcbd41, 0x15ab8f92, 0xf39789f5, + 0xcf6509a7, 0x4d5a9e4b, 0x9d9f5e34, 0x28e9fa9e, +}; + +const SM2_JACOBIAN_POINT _SM2_G = { + { + 0x334c74c7, 0x715a4589, 0xf2660be1, 0x8fe30bbf, + 0x6a39c994, 0x5f990446, 0x1f198119, 0x32c4ae2c, + }, + { + 0x2139f0a0, 0x02df32e5, 0xc62a4740, 0xd0a9877c, + 0x6b692153, 0x59bdcee3, 0xf4f6779c, 0xbc3736a2, + }, + { + 1, 0, 0, 0, 0, 0, 0, 0, + }, +}; +const SM2_JACOBIAN_POINT* SM2_G = &_SM2_G; + +const SM2_BN SM2_N = { + 0x39d54123, 0x53bbf409, 0x21c6052b, 0x7203df6b, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, +}; + +const SM2_BN SM2_ONE = { 1,0,0,0,0,0,0,0 }; +const SM2_BN SM2_TWO = { 2,0,0,0,0,0,0,0 }; +const SM2_BN SM2_THREE = { 3,0,0,0,0,0,0,0 }; + + +int rand_bytes(PRUint8* buf, int len) +{ + FILE* fp; + if (!buf) { + return -1; + } + if (len > 4096) { + return -1; + } + if (!len) { + return 0; + } + + if (!(fp = fopen("/dev/urandom", "rb"))) { + return -1; + } + if (fread(buf, 1, len, fp) != len) { + fclose(fp); + return -1; + } + fclose(fp); + return 1; +} + +int sm2_bn_is_zero(const SM2_BN a) +{ + int i; + for (i = 0; i < 8; i++) { + if (a[i] != 0) + return 0; + } + return 1; +} + +int sm2_bn_is_one(const SM2_BN a) +{ + int i; + if (a[0] != 1) + return 0; + for (i = 1; i < 8; i++) { + if (a[i] != 0) + return 0; + } + return 1; +} + +void sm2_bn_to_bytes(const SM2_BN a, PRUint8 out[32]) +{ + int i; + for (i = 7; i >= 0; i--) { + PRUint32 ai = (PRUint32)a[i]; + PUTU32(out, ai); + out += sizeof(PRUint32); + } +} + +void sm2_bn_from_bytes(SM2_BN r, const PRUint8 in[32]) +{ + int i; + for (i = 7; i >= 0; i--) { + r[i] = GETU32(in); + in += sizeof(PRUint32); + } +} + +void sm2_bn_to_bits(const SM2_BN a, char bits[256]) +{ + int i, j; + for (i = 7; i >= 0; i--) { + PRUint32 w = a[i]; + for (j = 0; j < 32; j++) { + *bits++ = (w & 0x80000000) ? '1' : '0'; + w <<= 1; + } + } +} + +int sm2_bn_cmp(const SM2_BN a, const SM2_BN b) +{ + int i; + for (i = 7; i >= 0; i--) { + if (a[i] > b[i]) + return 1; + if (a[i] < b[i]) + return -1; + } + return 0; +} + +void sm2_bn_set_word(SM2_BN r, PRUint32 a) +{ + int i; + r[0] = a; + for (i = 1; i < 8; i++) { + r[i] = 0; + } +} + +void sm2_bn_add(SM2_BN r, const SM2_BN a, const SM2_BN b) +{ + int i; + r[0] = a[0] + b[0]; + + for (i = 1; i < 8; i++) { + r[i] = a[i] + b[i] + (r[i - 1] >> 32); + } + for (i = 0; i < 7; i++) { + r[i] &= 0xffffffff; + } +} + +void sm2_bn_sub(SM2_BN ret, const SM2_BN a, const SM2_BN b) +{ + int i; + SM2_BN r; + r[0] = ((PRUint64)1 << 32) + a[0] - b[0]; + for (i = 1; i < 7; i++) { + r[i] = 0xffffffff + a[i] - b[i] + (r[i - 1] >> 32); + r[i - 1] &= 0xffffffff; + } + r[i] = a[i] - b[i] + (r[i - 1] >> 32) - 1; + r[i - 1] &= 0xffffffff; + sm2_bn_copy(ret, r); +} + +void sm2_bn_rand_range(SM2_BN r, const SM2_BN range) +{ + PRUint8 buf[32]; + do { + (void)rand_bytes(buf, sizeof(buf)); + sm2_bn_from_bytes(r, buf); + } while (sm2_bn_cmp(r, range) >= 0); +} + +void sm2_fp_add(SM2_Fp r, const SM2_Fp a, const SM2_Fp b) +{ + sm2_bn_add(r, a, b); + if (sm2_bn_cmp(r, SM2_P) >= 0) { + sm2_bn_sub(r, r, SM2_P); + } +} + +void sm2_fp_sub(SM2_Fp r, const SM2_Fp a, const SM2_Fp b) +{ + if (sm2_bn_cmp(a, b) >= 0) { + sm2_bn_sub(r, a, b); + } + else { + SM2_BN t; + sm2_bn_sub(t, SM2_P, b); + sm2_bn_add(r, t, a); + } +} + +void sm2_fp_dbl(SM2_Fp r, const SM2_Fp a) +{ + sm2_fp_add(r, a, a); +} + +void sm2_fp_tri(SM2_Fp r, const SM2_Fp a) +{ + SM2_BN t; + sm2_fp_dbl(t, a); + sm2_fp_add(r, t, a); +} + +void sm2_fp_div2(SM2_Fp r, const SM2_Fp a) +{ + int i; + sm2_bn_copy(r, a); + if (r[0] & 0x01) { + sm2_bn_add(r, r, SM2_P); + } + for (i = 0; i < 7; i++) { + r[i] = (r[i] >> 1) | ((r[i + 1] & 0x01) << 31); + } + r[i] >>= 1; +} + +void sm2_fp_mul(SM2_Fp r, const SM2_Fp a, const SM2_Fp b) +{ + int i, j; + PRUint64 s[16] = { 0 }; + SM2_BN d = { 0 }; + PRUint64 u; + + for (i = 0; i < 8; i++) { + u = 0; + for (j = 0; j < 8; j++) { + u = s[i + j] + a[i] * b[j] + u; + s[i + j] = u & 0xffffffff; + u >>= 32; + } + s[i + 8] = u; + } + + r[0] = s[0] + s[8] + s[9] + s[10] + s[11] + s[12] + ((s[13] + s[14] + s[15]) << 1); + r[1] = s[1] + s[9] + s[10] + s[11] + s[12] + s[13] + ((s[14] + s[15]) << 1); + r[2] = s[2]; + r[3] = s[3] + s[8] + s[11] + s[12] + s[14] + s[15] + (s[13] << 1); + r[4] = s[4] + s[9] + s[12] + s[13] + s[15] + (s[14] << 1); + r[5] = s[5] + s[10] + s[13] + s[14] + (s[15] << 1); + r[6] = s[6] + s[11] + s[14] + s[15]; + r[7] = s[7] + s[8] + s[9] + s[10] + s[11] + s[15] + ((s[12] + s[13] + s[14] + s[15]) << 1); + + for (i = 1; i < 8; i++) { + r[i] += r[i - 1] >> 32; + r[i - 1] &= 0xffffffff; + } + + d[2] = s[8] + s[9] + s[13] + s[14]; + d[3] = d[2] >> 32; + d[2] &= 0xffffffff; + sm2_bn_sub(r, r, d); + + while (sm2_bn_cmp(r, SM2_P) >= 0) { + sm2_bn_sub(r, r, SM2_P); + } +} + +void sm2_fp_sqr(SM2_Fp r, const SM2_Fp a) +{ + sm2_fp_mul(r, a, a); +} + +void sm2_fp_inv(SM2_Fp r, const SM2_Fp a) +{ + SM2_BN a1; + SM2_BN a2; + SM2_BN a3; + SM2_BN a4; + SM2_BN a5; + int i; + + sm2_fp_sqr(a1, a); + sm2_fp_mul(a2, a1, a); + sm2_fp_sqr(a3, a2); + sm2_fp_sqr(a3, a3); + sm2_fp_mul(a3, a3, a2); + sm2_fp_sqr(a4, a3); + sm2_fp_sqr(a4, a4); + sm2_fp_sqr(a4, a4); + sm2_fp_sqr(a4, a4); + sm2_fp_mul(a4, a4, a3); + sm2_fp_sqr(a5, a4); + for (i = 1; i < 8; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a5, a5, a4); + for (i = 0; i < 8; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a5, a5, a4); + for (i = 0; i < 4; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a5, a5, a3); + sm2_fp_sqr(a5, a5); + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a5, a5, a2); + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a5, a5, a); + sm2_fp_sqr(a4, a5); + sm2_fp_mul(a3, a4, a1); + sm2_fp_sqr(a5, a4); + for (i = 1; i < 31; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a4, a5, a4); + sm2_fp_sqr(a4, a4); + sm2_fp_mul(a4, a4, a); + sm2_fp_mul(a3, a4, a2); + for (i = 0; i < 33; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a2, a5, a3); + sm2_fp_mul(a3, a2, a3); + for (i = 0; i < 32; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a2, a5, a3); + sm2_fp_mul(a3, a2, a3); + sm2_fp_mul(a4, a2, a4); + for (i = 0; i < 32; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a2, a5, a3); + sm2_fp_mul(a3, a2, a3); + sm2_fp_mul(a4, a2, a4); + for (i = 0; i < 32; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a2, a5, a3); + sm2_fp_mul(a3, a2, a3); + sm2_fp_mul(a4, a2, a4); + for (i = 0; i < 32; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(a2, a5, a3); + sm2_fp_mul(a3, a2, a3); + sm2_fp_mul(a4, a2, a4); + for (i = 0; i < 32; i++) + sm2_fp_sqr(a5, a5); + sm2_fp_mul(r, a4, a5); + + sm2_bn_clean(a1); + sm2_bn_clean(a2); + sm2_bn_clean(a3); + sm2_bn_clean(a4); + sm2_bn_clean(a5); +} + +void sm2_fn_add(SM2_Fn r, const SM2_Fn a, const SM2_Fn b) +{ + sm2_bn_add(r, a, b); + if (sm2_bn_cmp(r, SM2_N) >= 0) { + sm2_bn_sub(r, r, SM2_N); + } +} + +void sm2_fn_sub(SM2_Fn r, const SM2_Fn a, const SM2_Fn b) +{ + if (sm2_bn_cmp(a, b) >= 0) { + sm2_bn_sub(r, a, b); + } + else { + SM2_BN t; + sm2_bn_add(t, a, SM2_N); + sm2_bn_sub(r, t, b); + } +} + +/* barrett reduction */ +static int sm2_bn288_cmp(const PRUint64 a[9], const PRUint64 b[9]) +{ + int i; + for (i = 8; i >= 0; i--) { + if (a[i] > b[i]) + return 1; + if (a[i] < b[i]) + return -1; + } + return 0; +} + +static void sm2_bn288_add(PRUint64 r[9], const PRUint64 a[9], const PRUint64 b[9]) +{ + int i; + r[0] = a[0] + b[0]; + for (i = 1; i < 9; i++) { + r[i] = a[i] + b[i] + (r[i - 1] >> 32); + } + for (i = 0; i < 8; i++) { + r[i] &= 0xffffffff; + } +} + +static void sm2_bn288_sub(PRUint64 ret[9], const PRUint64 a[9], const PRUint64 b[9]) +{ + int i; + PRUint64 r[9]; + + r[0] = ((PRUint64)1 << 32) + a[0] - b[0]; + for (i = 1; i < 8; i++) { + r[i] = 0xffffffff + a[i] - b[i] + (r[i - 1] >> 32); + r[i - 1] &= 0xffffffff; + } + r[i] = a[i] - b[i] + (r[i - 1] >> 32) - 1; + r[i - 1] &= 0xffffffff; + + for (i = 0; i < 9; i++) { + ret[i] = r[i]; + } +} + +void sm2_fn_mul(SM2_BN r, const SM2_BN a, const SM2_BN b) +{ + static const PRUint64 mu[8] = { + 0xf15149a0, 0x12ac6361, 0xfa323c01, 0x8dfc2096, + 1, 1, 1, 0x100000001, + }; // only for N=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123 + + PRUint64 s[17]; + PRUint64 zh[9]; + PRUint64 zl[9]; + PRUint64 q[9]; + PRUint64 w; + int i, j; + + /* z = a * b */ + for (i = 0; i < 8; i++) { + s[i] = 0; + } + for (i = 0; i < 8; i++) { + w = 0; + for (j = 0; j < 8; j++) { + w += s[i + j] + a[i] * b[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 8] = w; + } + + /* zl = z mod (2^32)^9 = z[0..8] zh = z / (2^32)^7 = z[7..15] */ + for (i = 0; i < 9; i++) { + zl[i] = s[i]; + zh[i] = s[7 + i]; + } + + /* q = zh * mu / (2^32)^9 */ + for (i = 0; i < 9; i++) { + s[i] = 0; + } + for (i = 0; i < 9; i++) { + w = 0; + for (j = 0; j < 8; j++) { + w += s[i + j] + zh[i] * mu[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 8] = w; + } + for (i = 0; i < 8; i++) { + q[i] = s[9 + i]; + } + + /* q = q * n mod (2^32)^9 */ + for (i = 0; i < 8; i++) { + s[i] = 0; + } + for (i = 0; i < 8; i++) { + w = 0; + for (j = 0; j < 8; j++) { + w += s[i + j] + q[i] * SM2_N[j]; + s[i + j] = w & 0xffffffff; + w >>= 32; + } + s[i + 8] = w; + } + for (i = 0; i < 9; i++) { + q[i] = s[i]; + } + + /* r = zl - q (mod (2^32)^9) */ + if (sm2_bn288_cmp(zl, q)) { + sm2_bn288_sub(zl, zl, q); + } + else { + PRUint64 c[9] = { 0,0,0,0,0,0,0,0,0x100000000 }; + sm2_bn288_sub(q, c, q); + sm2_bn288_add(zl, q, zl); + } + + for (i = 0; i < 8; i++) { + r[i] = zl[i]; + } + r[7] += zl[8] << 32; + + /* if r >= p do: r = r - n */ + while (sm2_bn_cmp(r, SM2_N) >= 0) { + sm2_bn_sub(r, r, SM2_N); + } +} + +void sm2_fn_sqr(SM2_BN r, const SM2_BN a) +{ + sm2_fn_mul(r, a, a); +} + +void sm2_fn_exp(SM2_BN r, const SM2_BN a, const SM2_BN e) +{ + SM2_BN t; + PRUint32 w; + int i, j; + + sm2_bn_set_one(t); + for (i = 7; i >= 0; i--) { + w = (PRUint32)e[i]; + for (j = 0; j < 32; j++) { + sm2_fn_sqr(t, t); + if (w & 0x80000000) { + sm2_fn_mul(t, t, a); + } + w <<= 1; + } + } + + sm2_bn_copy(r, t); +} + +void sm2_fn_inv(SM2_BN r, const SM2_BN a) +{ + SM2_BN e; + sm2_bn_sub(e, SM2_N, SM2_TWO); + sm2_fn_exp(r, a, e); +} + +void sm2_fn_rand(SM2_BN r) +{ + sm2_bn_rand_range(r, SM2_N); +} + +void sm2_jacobian_point_init(SM2_JACOBIAN_POINT* R) +{ + memset(R, 0, sizeof(SM2_JACOBIAN_POINT)); + R->X[0] = 1; + R->Y[0] = 1; +} + +int sm2_jacobian_point_is_at_infinity(const SM2_JACOBIAN_POINT* P) +{ + return sm2_bn_is_zero(P->Z); +} + +void sm2_jacobian_point_set_xy(SM2_JACOBIAN_POINT* R, const SM2_BN x, const SM2_BN y) +{ + sm2_bn_copy(R->X, x); + sm2_bn_copy(R->Y, y); + sm2_bn_set_one(R->Z); +} + +void sm2_jacobian_point_get_xy(const SM2_JACOBIAN_POINT* P, SM2_BN x, SM2_BN y) +{ + SM2_BN z_inv; + + if (sm2_bn_is_one(P->Z)) { + sm2_bn_copy(x, P->X); + sm2_bn_copy(y, P->Y); + } + else { + sm2_fp_inv(z_inv, P->Z); + if (y) + sm2_fp_mul(y, P->Y, z_inv); + sm2_fp_sqr(z_inv, z_inv); + sm2_fp_mul(x, P->X, z_inv); + if (y) + sm2_fp_mul(y, y, z_inv); + } +} + +void sm2_jacobian_point_dbl(SM2_JACOBIAN_POINT* R, const SM2_JACOBIAN_POINT* P) +{ + const PRUint64* X1 = P->X; + const PRUint64* Y1 = P->Y; + const PRUint64* Z1 = P->Z; + SM2_BN T1; + SM2_BN T2; + SM2_BN T3; + SM2_BN X3; + SM2_BN Y3; + SM2_BN Z3; + + if (sm2_jacobian_point_is_at_infinity(P)) { + sm2_jacobian_point_copy(R, P); + return; + } + + sm2_fp_sqr(T1, Z1); //T1 = Z1^2 + sm2_fp_sub(T2, X1, T1); //T2 = X1 - T1 + sm2_fp_add(T1, X1, T1); //T1 = X1 + T1 + sm2_fp_mul(T2, T2, T1); //T2 = T2 * T1 + sm2_fp_tri(T2, T2); //T2 = 3 * T2 + sm2_fp_dbl(Y3, Y1); //Y3 = 2 * Y1 + sm2_fp_mul(Z3, Y3, Z1); //Z3 = Y3 * Z1 + sm2_fp_sqr(Y3, Y3); //Y3 = Y3^2 + sm2_fp_mul(T3, Y3, X1); //T3 = Y3 * X1 + sm2_fp_sqr(Y3, Y3); //Y3 = Y3^2 + sm2_fp_div2(Y3, Y3); //Y3 = Y3/2 + sm2_fp_sqr(X3, T2); //X3 = T2^2 + sm2_fp_dbl(T1, T3); //T1 = 2 * T1 + sm2_fp_sub(X3, X3, T1); //X3 = X3 - T1 + sm2_fp_sub(T1, T3, X3); //T1 = T3 - X3 + sm2_fp_mul(T1, T1, T2); //T1 = T1 * T2 + sm2_fp_sub(Y3, T1, Y3); //Y3 = T1 - Y3 + + sm2_bn_copy(R->X, X3); + sm2_bn_copy(R->Y, Y3); + sm2_bn_copy(R->Z, Z3); +} + +void sm2_jacobian_point_add(SM2_JACOBIAN_POINT* R, const SM2_JACOBIAN_POINT* P, const SM2_JACOBIAN_POINT* Q) +{ + const PRUint64* X1 = P->X; + const PRUint64* Y1 = P->Y; + const PRUint64* Z1 = P->Z; + const PRUint64* x2 = Q->X; + const PRUint64* y2 = Q->Y; + SM2_BN T1; + SM2_BN T2; + SM2_BN T3; + SM2_BN T4; + SM2_BN X3; + SM2_BN Y3; + SM2_BN Z3; + + if (sm2_jacobian_point_is_at_infinity(Q)) { + sm2_jacobian_point_copy(R, P); + return; + } + + if (sm2_jacobian_point_is_at_infinity(P)) { + sm2_jacobian_point_copy(R, Q); + return; + } + + assert(sm2_bn_is_one(Q->Z)); + + sm2_fp_sqr(T1, Z1); + sm2_fp_mul(T2, T1, Z1); + sm2_fp_mul(T1, T1, x2); + sm2_fp_mul(T2, T2, y2); + sm2_fp_sub(T1, T1, X1); + sm2_fp_sub(T2, T2, Y1); + if (sm2_bn_is_zero(T1)) { + if (sm2_bn_is_zero(T2)) { + SM2_JACOBIAN_POINT _Q, * QQ = &_Q; + sm2_jacobian_point_set_xy(QQ, x2, y2); + + sm2_jacobian_point_dbl(R, QQ); + return; + } + else { + sm2_jacobian_point_set_infinity(R); + return; + } + } + sm2_fp_mul(Z3, Z1, T1); + sm2_fp_sqr(T3, T1); + sm2_fp_mul(T4, T3, T1); + sm2_fp_mul(T3, T3, X1); + sm2_fp_dbl(T1, T3); + sm2_fp_sqr(X3, T2); + sm2_fp_sub(X3, X3, T1); + sm2_fp_sub(X3, X3, T4); + sm2_fp_sub(T3, T3, X3); + sm2_fp_mul(T3, T3, T2); + sm2_fp_mul(T4, T4, Y1); + sm2_fp_sub(Y3, T3, T4); + + sm2_bn_copy(R->X, X3); + sm2_bn_copy(R->Y, Y3); + sm2_bn_copy(R->Z, Z3); +} + +void sm2_jacobian_point_mul(SM2_JACOBIAN_POINT* R, const SM2_BN k, const SM2_JACOBIAN_POINT* P) +{ + char bits[257] = { 0 }; + SM2_JACOBIAN_POINT _Q, * Q = &_Q; + SM2_JACOBIAN_POINT _T, * T = &_T; + int i; + + //point_add need affine, can not use point_add + if (!sm2_bn_is_one(P->Z)) { + SM2_BN x; + SM2_BN y; + sm2_jacobian_point_get_xy(P, x, y); + sm2_jacobian_point_set_xy(T, x, y); + P = T; + } + + sm2_jacobian_point_set_infinity(Q); + sm2_bn_to_bits(k, bits); + for (i = 0; i < 256; i++) { + sm2_jacobian_point_dbl(Q, Q); + if (bits[i] == '1') { + sm2_jacobian_point_add(Q, Q, P); + } + } + sm2_jacobian_point_copy(R, Q); +} + +void sm2_jacobian_point_mul_generator(SM2_JACOBIAN_POINT* R, const SM2_BN k) +{ + sm2_jacobian_point_mul(R, k, SM2_G); +} + + +SECStatus +SM2_SignDigestWithSeed(ECPrivateKey* key, SECItem* signature, + const SECItem* digest, const unsigned char* kb, const int kblen) +{ + SECStatus rv = SECFailure; + + SM2_JACOBIAN_POINT _P, * P = &_P; + SM2_BN d; + SM2_BN e; + SM2_BN k; + SM2_BN x; + SM2_BN r; + SM2_BN s; + PRUint8 dgst[32]; + PRUint8 private_key[32]; + PRUint8 rr[32], ss[32]; + + memcpy(dgst, digest->data, 32); + memcpy(private_key, key->privateValue.data, 32); + +random: + sm2_bn_from_bytes(d, private_key); + + sm2_bn_from_bytes(e, dgst); + + do { + sm2_fn_rand(k); + } while (sm2_bn_is_zero(k)); + + sm2_jacobian_point_mul_generator(P, k); + sm2_jacobian_point_get_xy(P, x, NULL); + + sm2_fn_add(r, e, x); + + if (sm2_bn_is_zero(r)) { + goto random; + } + sm2_bn_add(x, r, k); + if (sm2_bn_cmp(x, SM2_N) == 0) { + goto random; + } + + sm2_fn_mul(e, r, d); + sm2_fn_sub(k, k, e); + sm2_fn_add(e, SM2_ONE, d); + sm2_fn_inv(e, e); + sm2_fn_mul(s, e, k); + + sm2_bn_to_bytes(r, rr); + sm2_bn_to_bytes(s, ss); + memcpy(signature->data, rr, 32); + memcpy(signature->data + 32, ss, 32); + + memset(d, 0, sizeof(d)); + memset(e, 0, sizeof(e)); + memset(k, 0, sizeof(k)); + memset(x, 0, sizeof(x)); + + rv = SECSuccess; + return rv; +} \ No newline at end of file diff --git a/nss/lib/freebl/sm2.h b/nss/lib/freebl/sm2.h new file mode 100644 index 0000000..e236dcd --- /dev/null +++ b/nss/lib/freebl/sm2.h @@ -0,0 +1,23 @@ +/* + * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +#ifndef _SM2_H_ +#define _SM2_H_ + +#include +#include +#include +#include +#include +#include "seccomon.h" +#include "blapit.h" + +SECStatus SM2_SignDigestWithSeed(ECPrivateKey* key, SECItem* signature, const SECItem* digest, const unsigned char* kb, const int kblen); + +#endif /* _SM2_H_ */ \ No newline at end of file -- 2.33.0