add some SM2\SM3 support to nss the main of SM3 implement:SM3_Hash the main of SM2 implement:SM2_SignDigestWithSeed
877 lines
21 KiB
Diff
877 lines
21 KiB
Diff
From 347a578fa37bb49aee76d8435fd5f0f34875a34e Mon Sep 17 00:00:00 2001
|
|
From: godcansee <liu332084460@foxmail.com>
|
|
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 <luhuaxin1@huawei.com>
|
|
---
|
|
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 <stdio.h>
|
|
+#include <stdint.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <assert.h>
|
|
+#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
|
|
|