mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-06 16:36:16 +08:00
Update SM2 arithmetic implementations
Decouple API and implementations. SM2 arithmetic exposes 3 types: GF(p), GF(n), and Point.
This commit is contained in:
@@ -20,6 +20,7 @@ set(src
|
||||
src/sm3_digest.c
|
||||
src/sm2_alg.c
|
||||
src/sm2_key.c
|
||||
src/sm2_sign.c
|
||||
src/sm2_lib.c
|
||||
src/sm2_ctx.c
|
||||
src/sm9_alg.c
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
|
||||
* Copyright 2014-2024 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.
|
||||
@@ -317,6 +317,8 @@ typedef struct {
|
||||
uint8_t ciphertext[SM2_MAX_PLAINTEXT_SIZE];
|
||||
} SM2_CIPHERTEXT;
|
||||
|
||||
int sm2_kdf(const uint8_t *in, size_t inlen, size_t outlen, uint8_t *out);
|
||||
|
||||
int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out);
|
||||
int sm2_do_decrypt(const SM2_KEY *key, const SM2_CIPHERTEXT *in, uint8_t *out, size_t *outlen);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint64_t SM2_Z256[4];
|
||||
|
||||
void sm2_z256_copy(uint64_t r[4], const uint64_t a[4]);
|
||||
void sm2_z256_copy_conditional(uint64_t dst[4], const uint64_t src[4], uint64_t move);
|
||||
@@ -43,12 +44,25 @@ void sm2_z256_modp_mul_by_2(uint64_t r[4], const uint64_t a[4]);
|
||||
void sm2_z256_modp_mul_by_3(uint64_t r[4], const uint64_t a[4]);
|
||||
void sm2_z256_modp_div_by_2(uint64_t r[4], const uint64_t a[4]);
|
||||
|
||||
void sm2_z256_to_mont(const uint64_t a[4], uint64_t r[4]);
|
||||
void sm2_z256_from_mont(uint64_t r[4], const uint64_t a[4]);
|
||||
void sm2_z256_mont_mul(uint64_t r[4], const uint64_t a[4], const uint64_t b[4]);
|
||||
void sm2_z256_mont_sqr(uint64_t r[4], const uint64_t a[4]);
|
||||
void sm2_z256_mont_inv(uint64_t r[4], const uint64_t a[4]);
|
||||
int sm2_z256_mont_print(FILE *fp, int ind, int fmt, const char *label, const uint64_t a[4]);
|
||||
void sm2_z256_modp_to_mont(const uint64_t a[4], uint64_t r[4]);
|
||||
void sm2_z256_modp_from_mont(uint64_t r[4], const uint64_t a[4]);
|
||||
void sm2_z256_modp_mont_mul(uint64_t r[4], const uint64_t a[4], const uint64_t b[4]);
|
||||
void sm2_z256_modp_mont_sqr(uint64_t r[4], const uint64_t a[4]);
|
||||
void sm2_z256_modp_mont_exp(uint64_t r[4], const uint64_t a[4], const uint64_t e[4]);
|
||||
void sm2_z256_modp_mont_inv(uint64_t r[4], const uint64_t a[4]);
|
||||
int sm2_z256_modp_mont_print(FILE *fp, int ind, int fmt, const char *label, const uint64_t a[4]);
|
||||
|
||||
void sm2_z256_modn_add(uint64_t r[4], const uint64_t a[4], const uint64_t b[4]);
|
||||
void sm2_z256_modn_sub(uint64_t r[4], const uint64_t a[4], const uint64_t b[4]);
|
||||
void sm2_z256_modn_neg(uint64_t r[4], const uint64_t a[4]);
|
||||
|
||||
void sm2_z256_modn_to_mont(const uint64_t a[4], uint64_t r[4]);
|
||||
void sm2_z256_modn_from_mont(uint64_t r[4], const uint64_t a[4]);
|
||||
void sm2_z256_modn_mont_mul(uint64_t r[4], const uint64_t a[4], const uint64_t b[4]);
|
||||
void sm2_z256_modn_mont_sqr(uint64_t r[4], const uint64_t a[4]);
|
||||
void sm2_z256_modn_mont_exp(uint64_t r[4], const uint64_t a[4], const uint64_t e[4]);
|
||||
void sm2_z256_modn_mont_inv(uint64_t r[4], const uint64_t a[4]);
|
||||
int sm2_z256_modn_mont_print(FILE *fp, int ind, int fmt, const char *label, const uint64_t a[4]);
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
|
||||
/*
|
||||
* Copyright 2014-2024 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.
|
||||
@@ -20,10 +20,6 @@
|
||||
#include <gmssl/endian.h>
|
||||
|
||||
|
||||
#define sm2_print_bn(label,a) sm2_bn_print(stderr,0,0,label,a) // 这个不应该放在这里,应该放在测试文件中
|
||||
|
||||
|
||||
|
||||
const SM2_BN SM2_P = {
|
||||
0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe,
|
||||
@@ -65,7 +61,6 @@ 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 sm2_bn_check(const SM2_BN a)
|
||||
{
|
||||
int err = 0;
|
||||
@@ -775,8 +770,6 @@ int sm2_fn_rand(SM2_BN r)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sm2_jacobian_point_init(SM2_JACOBIAN_POINT *R)
|
||||
{
|
||||
memset(R, 0, sizeof(SM2_JACOBIAN_POINT));
|
||||
@@ -817,7 +810,7 @@ void sm2_jacobian_point_get_xy(const SM2_JACOBIAN_POINT *P, SM2_BN x, SM2_BN y)
|
||||
}
|
||||
}
|
||||
|
||||
int sm2_jacobian_pointpoint_print(FILE *fp, int fmt, int ind, const char *label, const SM2_JACOBIAN_POINT *P)
|
||||
int sm2_jacobian_point_print(FILE *fp, int fmt, int ind, const char *label, const SM2_JACOBIAN_POINT *P)
|
||||
{
|
||||
int len = 0;
|
||||
SM2_BN x;
|
||||
@@ -1321,6 +1314,7 @@ int sm2_point_from_hash(SM2_POINT *R, const uint8_t *data, size_t datalen)
|
||||
sm2_bn_add(u, SM2_P, SM2_ONE);
|
||||
sm2_bn_rshift(u, u, 2);
|
||||
|
||||
// How many times?
|
||||
do {
|
||||
sm3_digest(data, datalen, dgst);
|
||||
|
||||
|
||||
405
src/sm2_lib.c
405
src/sm2_lib.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
|
||||
* Copyright 2014-2024 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.
|
||||
@@ -20,144 +20,6 @@
|
||||
#include <gmssl/endian.h>
|
||||
|
||||
|
||||
extern const SM2_BN SM2_N;
|
||||
extern const SM2_BN SM2_ONE;
|
||||
|
||||
int sm2_do_sign(const SM2_KEY *key, const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
{
|
||||
SM2_JACOBIAN_POINT _P, *P = &_P;
|
||||
SM2_BN d;
|
||||
SM2_BN d_inv;
|
||||
SM2_BN e;
|
||||
SM2_BN k;
|
||||
SM2_BN x;
|
||||
SM2_BN t;
|
||||
SM2_BN r;
|
||||
SM2_BN s;
|
||||
|
||||
//fprintf(stderr, "sm2_do_sign\n");
|
||||
sm2_bn_from_bytes(d, key->private_key);
|
||||
|
||||
// compute (d + 1)^-1 (mod n)
|
||||
sm2_fn_add(d_inv, d, SM2_ONE); //sm2_bn_print(stderr, 0, 4, "(1+d)", d_inv);
|
||||
if (sm2_bn_is_zero(d_inv)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm2_fn_inv(d_inv, d_inv); //sm2_bn_print(stderr, 0, 4, "(1+d)^-1", d_inv);
|
||||
|
||||
// e = H(M)
|
||||
sm2_bn_from_bytes(e, dgst); //sm2_bn_print(stderr, 0, 4, "e", e);
|
||||
|
||||
retry:
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_fn_rand(k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (sm2_bn_is_zero(k)); //sm2_bn_print(stderr, 0, 4, "k", k);
|
||||
|
||||
// (x, y) = kG
|
||||
sm2_jacobian_point_mul_generator(P, k);
|
||||
sm2_jacobian_point_get_xy(P, x, NULL);
|
||||
//sm2_bn_print(stderr, 0, 4, "x", x);
|
||||
|
||||
// r = e + x (mod n)
|
||||
if (sm2_bn_cmp(e, SM2_N) >= 0) {
|
||||
sm2_bn_sub(e, e, SM2_N);
|
||||
}
|
||||
if (sm2_bn_cmp(x, SM2_N) >= 0) {
|
||||
sm2_bn_sub(x, x, SM2_N);
|
||||
}
|
||||
sm2_fn_add(r, e, x); //sm2_bn_print(stderr, 0, 4, "r = e + x (mod n)", r);
|
||||
|
||||
// if r == 0 or r + k == n re-generate k
|
||||
sm2_bn_add(t, r, k);
|
||||
if (sm2_bn_is_zero(r) || sm2_bn_cmp(t, SM2_N) == 0) {
|
||||
//sm2_bn_print(stderr, 0, 4, "r + k", t);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
// s = ((1 + d)^-1 * (k - r * d)) mod n
|
||||
sm2_fn_mul(t, r, d); //sm2_bn_print(stderr, 0, 4, "r*d", t);
|
||||
sm2_fn_sub(k, k, t); //sm2_bn_print(stderr, 0, 4, "k-r*d", k);
|
||||
sm2_fn_mul(s, d_inv, k); //sm2_bn_print(stderr, 0, 4, "s = ((1 + d)^-1 * (k - r * d)) mod n", s);
|
||||
|
||||
// check s != 0
|
||||
if (sm2_bn_is_zero(s)) {
|
||||
goto retry;
|
||||
}
|
||||
|
||||
sm2_bn_to_bytes(r, sig->r); //sm2_bn_print_bn(stderr, 0, 4, "r", r);
|
||||
sm2_bn_to_bytes(s, sig->s); //sm2_bn_print_bn(stderr, 0, 4, "s", s);
|
||||
|
||||
gmssl_secure_clear(d, sizeof(d));
|
||||
gmssl_secure_clear(d_inv, sizeof(d_inv ));
|
||||
gmssl_secure_clear(k, sizeof(k));
|
||||
gmssl_secure_clear(t, sizeof(t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATURE *sig)
|
||||
{
|
||||
SM2_JACOBIAN_POINT _P, *P = &_P;
|
||||
SM2_JACOBIAN_POINT _R, *R = &_R;
|
||||
SM2_BN r;
|
||||
SM2_BN s;
|
||||
SM2_BN e;
|
||||
SM2_BN x;
|
||||
SM2_BN t;
|
||||
|
||||
// parse public key
|
||||
sm2_jacobian_point_from_bytes(P, (const uint8_t *)&key->public_key);
|
||||
//sm2_jacobian_point_print(stderr, 0, 4, "P", P);
|
||||
|
||||
// parse signature values
|
||||
sm2_bn_from_bytes(r, sig->r); //sm2_bn_print(stderr, 0, 4, "r", r);
|
||||
sm2_bn_from_bytes(s, sig->s); //sm2_bn_print(stderr, 0, 4, "s", s);
|
||||
|
||||
// check r, s in [1, n-1]
|
||||
if (sm2_bn_is_zero(r) == 1
|
||||
|| sm2_bn_cmp(r, SM2_N) >= 0
|
||||
|| sm2_bn_is_zero(s) == 1
|
||||
|| sm2_bn_cmp(s, SM2_N) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// e = H(M)
|
||||
sm2_bn_from_bytes(e, dgst); //sm2_bn_print(stderr, 0, 4, "e = H(M)", e);
|
||||
|
||||
// t = r + s (mod n), check t != 0
|
||||
sm2_fn_add(t, r, s); //sm2_bn_print(stderr, 0, 4, "t = r + s (mod n)", t);
|
||||
if (sm2_bn_is_zero(t)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Q = s * G + t * P
|
||||
sm2_jacobian_point_mul_sum(R, t, P, s);
|
||||
sm2_jacobian_point_get_xy(R, x, NULL);
|
||||
//sm2_bn_print(stderr, 0, 4, "x", x);
|
||||
|
||||
// r' = e + x (mod n)
|
||||
if (sm2_bn_cmp(e, SM2_N) >= 0) {
|
||||
sm2_bn_sub(e, e, SM2_N);
|
||||
}
|
||||
if (sm2_bn_cmp(x, SM2_N) >= 0) {
|
||||
sm2_bn_sub(x, x, SM2_N);
|
||||
}
|
||||
sm2_fn_add(e, e, x); //sm2_bn_print(stderr, 0, 4, "e + x (mod n)", e);
|
||||
|
||||
// check if r == r'
|
||||
if (sm2_bn_cmp(e, r) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_signature_to_der(const SM2_SIGNATURE *sig, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
@@ -360,223 +222,6 @@ int sm2_kdf(const uint8_t *in, size_t inlen, size_t outlen, uint8_t *out)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int all_zero(const uint8_t *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out)
|
||||
{
|
||||
SM2_BN k;
|
||||
SM2_JACOBIAN_POINT _P, *P = &_P;
|
||||
SM2_JACOBIAN_POINT _C1, *C1 = &_C1;
|
||||
SM2_JACOBIAN_POINT _kP, *kP = &_kP;
|
||||
uint8_t x2y2[64];
|
||||
SM3_CTX sm3_ctx;
|
||||
|
||||
if (!(SM2_MIN_PLAINTEXT_SIZE <= inlen && inlen <= SM2_MAX_PLAINTEXT_SIZE)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_jacobian_point_from_bytes(P, (uint8_t *)&key->public_key);
|
||||
|
||||
// S = h * P, check S != O
|
||||
// for sm2 curve, h == 1 and S == P
|
||||
// SM2_POINT can not present point at infinity, do do nothing here
|
||||
|
||||
retry:
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_fn_rand(k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (sm2_bn_is_zero(k)); //sm2_bn_print(stderr, 0, 4, "k", k);
|
||||
|
||||
// output C1 = k * G = (x1, y1)
|
||||
sm2_jacobian_point_mul_generator(C1, k);
|
||||
sm2_jacobian_point_to_bytes(C1, (uint8_t *)&out->point);
|
||||
|
||||
// k * P = (x2, y2)
|
||||
sm2_jacobian_point_mul(kP, k, P);
|
||||
sm2_jacobian_point_to_bytes(kP, x2y2);
|
||||
|
||||
// t = KDF(x2 || y2, inlen)
|
||||
sm2_kdf(x2y2, 64, inlen, out->ciphertext);
|
||||
|
||||
// if t is all zero, retry
|
||||
if (all_zero(out->ciphertext, inlen)) {
|
||||
goto retry;
|
||||
}
|
||||
|
||||
// output C2 = M xor t
|
||||
gmssl_memxor(out->ciphertext, out->ciphertext, in, inlen);
|
||||
out->ciphertext_size = (uint32_t)inlen;
|
||||
|
||||
// output C3 = Hash(x2 || m || y2)
|
||||
sm3_init(&sm3_ctx);
|
||||
sm3_update(&sm3_ctx, x2y2, 32);
|
||||
sm3_update(&sm3_ctx, in, inlen);
|
||||
sm3_update(&sm3_ctx, x2y2 + 32, 32);
|
||||
sm3_finish(&sm3_ctx, out->hash);
|
||||
|
||||
gmssl_secure_clear(k, sizeof(k));
|
||||
gmssl_secure_clear(kP, sizeof(SM2_JACOBIAN_POINT));
|
||||
gmssl_secure_clear(x2y2, sizeof(x2y2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_do_encrypt_fixlen(const SM2_KEY *key, const uint8_t *in, size_t inlen, int point_size, SM2_CIPHERTEXT *out)
|
||||
{
|
||||
unsigned int trys = 200;
|
||||
SM2_BN k;
|
||||
SM2_JACOBIAN_POINT _P, *P = &_P;
|
||||
SM2_JACOBIAN_POINT _C1, *C1 = &_C1;
|
||||
SM2_JACOBIAN_POINT _kP, *kP = &_kP;
|
||||
uint8_t x2y2[64];
|
||||
SM3_CTX sm3_ctx;
|
||||
|
||||
if (!(SM2_MIN_PLAINTEXT_SIZE <= inlen && inlen <= SM2_MAX_PLAINTEXT_SIZE)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (point_size) {
|
||||
case SM2_ciphertext_compact_point_size:
|
||||
case SM2_ciphertext_typical_point_size:
|
||||
case SM2_ciphertext_max_point_size:
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_jacobian_point_from_bytes(P, (uint8_t *)&key->public_key);
|
||||
|
||||
// S = h * P, check S != O
|
||||
// for sm2 curve, h == 1 and S == P
|
||||
// SM2_POINT can not present point at infinity, do do nothing here
|
||||
|
||||
retry:
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_fn_rand(k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (sm2_bn_is_zero(k)); //sm2_bn_print(stderr, 0, 4, "k", k);
|
||||
|
||||
// output C1 = k * G = (x1, y1)
|
||||
sm2_jacobian_point_mul_generator(C1, k);
|
||||
sm2_jacobian_point_to_bytes(C1, (uint8_t *)&out->point);
|
||||
|
||||
// check fixlen
|
||||
if (trys) {
|
||||
size_t len = 0;
|
||||
asn1_integer_to_der(out->point.x, 32, NULL, &len);
|
||||
asn1_integer_to_der(out->point.y, 32, NULL, &len);
|
||||
if (len != point_size) {
|
||||
trys--;
|
||||
goto retry;
|
||||
}
|
||||
} else {
|
||||
gmssl_secure_clear(k, sizeof(k));
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// k * P = (x2, y2)
|
||||
sm2_jacobian_point_mul(kP, k, P);
|
||||
sm2_jacobian_point_to_bytes(kP, x2y2);
|
||||
|
||||
// t = KDF(x2 || y2, inlen)
|
||||
sm2_kdf(x2y2, 64, inlen, out->ciphertext);
|
||||
|
||||
// if t is all zero, retry
|
||||
if (all_zero(out->ciphertext, inlen)) {
|
||||
goto retry;
|
||||
}
|
||||
|
||||
// output C2 = M xor t
|
||||
gmssl_memxor(out->ciphertext, out->ciphertext, in, inlen);
|
||||
out->ciphertext_size = (uint32_t)inlen;
|
||||
|
||||
// output C3 = Hash(x2 || m || y2)
|
||||
sm3_init(&sm3_ctx);
|
||||
sm3_update(&sm3_ctx, x2y2, 32);
|
||||
sm3_update(&sm3_ctx, in, inlen);
|
||||
sm3_update(&sm3_ctx, x2y2 + 32, 32);
|
||||
sm3_finish(&sm3_ctx, out->hash);
|
||||
|
||||
gmssl_secure_clear(k, sizeof(k));
|
||||
gmssl_secure_clear(kP, sizeof(SM2_JACOBIAN_POINT));
|
||||
gmssl_secure_clear(x2y2, sizeof(x2y2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_do_decrypt(const SM2_KEY *key, const SM2_CIPHERTEXT *in, uint8_t *out, size_t *outlen)
|
||||
{
|
||||
int ret = -1;
|
||||
SM2_BN d;
|
||||
SM2_JACOBIAN_POINT _C1, *C1 = &_C1;
|
||||
uint8_t x2y2[64];
|
||||
SM3_CTX sm3_ctx;
|
||||
uint8_t hash[32];
|
||||
|
||||
// check C1 is on sm2 curve
|
||||
sm2_jacobian_point_from_bytes(C1, (uint8_t *)&in->point);
|
||||
if (!sm2_jacobian_point_is_on_curve(C1)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check if S = h * C1 is point at infinity
|
||||
// this will not happen, as SM2_POINT can not present point at infinity
|
||||
|
||||
// d * C1 = (x2, y2)
|
||||
sm2_bn_from_bytes(d, key->private_key);
|
||||
sm2_jacobian_point_mul(C1, d, C1);
|
||||
|
||||
// t = KDF(x2 || y2, klen) and check t is not all zeros
|
||||
sm2_jacobian_point_to_bytes(C1, x2y2);
|
||||
sm2_kdf(x2y2, 64, in->ciphertext_size, out);
|
||||
if (all_zero(out, in->ciphertext_size)) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
// M = C2 xor t
|
||||
gmssl_memxor(out, out, in->ciphertext, in->ciphertext_size);
|
||||
*outlen = in->ciphertext_size;
|
||||
|
||||
// u = Hash(x2 || M || y2)
|
||||
sm3_init(&sm3_ctx);
|
||||
sm3_update(&sm3_ctx, x2y2, 32);
|
||||
sm3_update(&sm3_ctx, out, in->ciphertext_size);
|
||||
sm3_update(&sm3_ctx, x2y2 + 32, 32);
|
||||
sm3_finish(&sm3_ctx, hash);
|
||||
|
||||
// check if u == C3
|
||||
if (memcmp(in->hash, hash, sizeof(hash)) != 0) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
gmssl_secure_clear(d, sizeof(d));
|
||||
gmssl_secure_clear(C1, sizeof(SM2_JACOBIAN_POINT));
|
||||
gmssl_secure_clear(x2y2, sizeof(x2y2));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sm2_ciphertext_to_der(const SM2_CIPHERTEXT *C, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
@@ -773,51 +418,3 @@ int sm2_ecdh(const SM2_KEY *key, const uint8_t *peer_public, size_t peer_public_
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// (x1, y1) = k * G
|
||||
// r = e + x1
|
||||
// s = (k - r * d)/(1 + d) = (k +r - r * d - r)/(1 + d) = (k + r - r(1 +d))/(1 + d) = (k + r)/(1 + d) - r
|
||||
// = -r + (k + r)*(1 + d)^-1
|
||||
// = -r + (k + r) * d'
|
||||
|
||||
int sm2_do_sign_fast(const SM2_Fn d, const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
{
|
||||
SM2_JACOBIAN_POINT R;
|
||||
SM2_BN e;
|
||||
SM2_BN k;
|
||||
SM2_BN x1;
|
||||
SM2_BN r;
|
||||
SM2_BN s;
|
||||
|
||||
// e = H(M)
|
||||
sm2_bn_from_bytes(e, dgst);
|
||||
if (sm2_bn_cmp(e, SM2_N) >= 0) {
|
||||
sm2_bn_sub(e, e, SM2_N);
|
||||
}
|
||||
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_fn_rand(k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (sm2_bn_is_zero(k));
|
||||
|
||||
// (x1, y1) = kG
|
||||
sm2_jacobian_point_mul_generator(&R, k);
|
||||
sm2_jacobian_point_get_xy(&R, x1, NULL);
|
||||
|
||||
// r = e + x1 (mod n)
|
||||
sm2_fn_add(r, e, x1);
|
||||
|
||||
// s = (k + r) * d' - r
|
||||
sm2_bn_add(s, k, r);
|
||||
sm2_fn_mul(s, s, d);
|
||||
sm2_fn_sub(s, s, r);
|
||||
|
||||
sm2_bn_to_bytes(r, sig->r);
|
||||
sm2_bn_to_bytes(s, sig->s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
421
src/sm2_sign.c
Normal file
421
src/sm2_sign.c
Normal file
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
* Copyright 2014-2024 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/sm3.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/endian.h>
|
||||
|
||||
|
||||
extern const SM2_BN SM2_N;
|
||||
extern const SM2_BN SM2_ONE;
|
||||
|
||||
int sm2_do_sign(const SM2_KEY *key, const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
{
|
||||
SM2_JACOBIAN_POINT _P, *P = &_P;
|
||||
SM2_BN d;
|
||||
SM2_BN d_inv;
|
||||
SM2_BN e;
|
||||
SM2_BN k;
|
||||
SM2_BN x;
|
||||
SM2_BN t;
|
||||
SM2_BN r;
|
||||
SM2_BN s;
|
||||
|
||||
//fprintf(stderr, "sm2_do_sign\n");
|
||||
sm2_bn_from_bytes(d, key->private_key);
|
||||
|
||||
// compute (d + 1)^-1 (mod n)
|
||||
sm2_fn_add(d_inv, d, SM2_ONE); //sm2_bn_print(stderr, 0, 4, "(1+d)", d_inv);
|
||||
if (sm2_bn_is_zero(d_inv)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm2_fn_inv(d_inv, d_inv); //sm2_bn_print(stderr, 0, 4, "(1+d)^-1", d_inv);
|
||||
|
||||
// e = H(M)
|
||||
sm2_bn_from_bytes(e, dgst); //sm2_bn_print(stderr, 0, 4, "e", e);
|
||||
|
||||
retry:
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_fn_rand(k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (sm2_bn_is_zero(k)); //sm2_bn_print(stderr, 0, 4, "k", k);
|
||||
|
||||
// (x, y) = kG
|
||||
sm2_jacobian_point_mul_generator(P, k);
|
||||
sm2_jacobian_point_get_xy(P, x, NULL);
|
||||
//sm2_bn_print(stderr, 0, 4, "x", x);
|
||||
|
||||
// r = e + x (mod n)
|
||||
if (sm2_bn_cmp(e, SM2_N) >= 0) {
|
||||
sm2_bn_sub(e, e, SM2_N);
|
||||
}
|
||||
if (sm2_bn_cmp(x, SM2_N) >= 0) {
|
||||
sm2_bn_sub(x, x, SM2_N);
|
||||
}
|
||||
sm2_fn_add(r, e, x); //sm2_bn_print(stderr, 0, 4, "r = e + x (mod n)", r);
|
||||
|
||||
// if r == 0 or r + k == n re-generate k
|
||||
sm2_bn_add(t, r, k);
|
||||
if (sm2_bn_is_zero(r) || sm2_bn_cmp(t, SM2_N) == 0) {
|
||||
//sm2_bn_print(stderr, 0, 4, "r + k", t);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
// s = ((1 + d)^-1 * (k - r * d)) mod n
|
||||
sm2_fn_mul(t, r, d); //sm2_bn_print(stderr, 0, 4, "r*d", t);
|
||||
sm2_fn_sub(k, k, t); //sm2_bn_print(stderr, 0, 4, "k-r*d", k);
|
||||
sm2_fn_mul(s, d_inv, k); //sm2_bn_print(stderr, 0, 4, "s = ((1 + d)^-1 * (k - r * d)) mod n", s);
|
||||
|
||||
// check s != 0
|
||||
if (sm2_bn_is_zero(s)) {
|
||||
goto retry;
|
||||
}
|
||||
|
||||
sm2_bn_to_bytes(r, sig->r); //sm2_bn_print_bn(stderr, 0, 4, "r", r);
|
||||
sm2_bn_to_bytes(s, sig->s); //sm2_bn_print_bn(stderr, 0, 4, "s", s);
|
||||
|
||||
gmssl_secure_clear(d, sizeof(d));
|
||||
gmssl_secure_clear(d_inv, sizeof(d_inv ));
|
||||
gmssl_secure_clear(k, sizeof(k));
|
||||
gmssl_secure_clear(t, sizeof(t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// (x1, y1) = k * G
|
||||
// r = e + x1
|
||||
// s = (k - r * d)/(1 + d) = (k +r - r * d - r)/(1 + d) = (k + r - r(1 +d))/(1 + d) = (k + r)/(1 + d) - r
|
||||
// = -r + (k + r)*(1 + d)^-1
|
||||
// = -r + (k + r) * d'
|
||||
|
||||
int sm2_do_sign_fast(const SM2_Fn d, const uint8_t dgst[32], SM2_SIGNATURE *sig)
|
||||
{
|
||||
SM2_JACOBIAN_POINT R;
|
||||
SM2_BN e;
|
||||
SM2_BN k;
|
||||
SM2_BN x1;
|
||||
SM2_BN r;
|
||||
SM2_BN s;
|
||||
|
||||
// e = H(M)
|
||||
sm2_bn_from_bytes(e, dgst);
|
||||
if (sm2_bn_cmp(e, SM2_N) >= 0) {
|
||||
sm2_bn_sub(e, e, SM2_N);
|
||||
}
|
||||
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_fn_rand(k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (sm2_bn_is_zero(k));
|
||||
|
||||
// (x1, y1) = kG
|
||||
sm2_jacobian_point_mul_generator(&R, k);
|
||||
sm2_jacobian_point_get_xy(&R, x1, NULL);
|
||||
|
||||
// r = e + x1 (mod n)
|
||||
sm2_fn_add(r, e, x1);
|
||||
|
||||
// s = (k + r) * d' - r
|
||||
sm2_bn_add(s, k, r);
|
||||
sm2_fn_mul(s, s, d);
|
||||
sm2_fn_sub(s, s, r);
|
||||
|
||||
sm2_bn_to_bytes(r, sig->r);
|
||||
sm2_bn_to_bytes(s, sig->s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATURE *sig)
|
||||
{
|
||||
SM2_JACOBIAN_POINT _P, *P = &_P;
|
||||
SM2_JACOBIAN_POINT _R, *R = &_R;
|
||||
SM2_BN r;
|
||||
SM2_BN s;
|
||||
SM2_BN e;
|
||||
SM2_BN x;
|
||||
SM2_BN t;
|
||||
|
||||
// parse public key
|
||||
sm2_jacobian_point_from_bytes(P, (const uint8_t *)&key->public_key);
|
||||
//sm2_jacobian_point_print(stderr, 0, 4, "P", P);
|
||||
|
||||
// parse signature values
|
||||
sm2_bn_from_bytes(r, sig->r); //sm2_bn_print(stderr, 0, 4, "r", r);
|
||||
sm2_bn_from_bytes(s, sig->s); //sm2_bn_print(stderr, 0, 4, "s", s);
|
||||
|
||||
// check r, s in [1, n-1]
|
||||
if (sm2_bn_is_zero(r) == 1
|
||||
|| sm2_bn_cmp(r, SM2_N) >= 0
|
||||
|| sm2_bn_is_zero(s) == 1
|
||||
|| sm2_bn_cmp(s, SM2_N) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// e = H(M)
|
||||
sm2_bn_from_bytes(e, dgst); //sm2_bn_print(stderr, 0, 4, "e = H(M)", e);
|
||||
|
||||
// t = r + s (mod n), check t != 0
|
||||
sm2_fn_add(t, r, s); //sm2_bn_print(stderr, 0, 4, "t = r + s (mod n)", t);
|
||||
if (sm2_bn_is_zero(t)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Q = s * G + t * P
|
||||
sm2_jacobian_point_mul_sum(R, t, P, s);
|
||||
sm2_jacobian_point_get_xy(R, x, NULL);
|
||||
//sm2_bn_print(stderr, 0, 4, "x", x);
|
||||
|
||||
// r' = e + x (mod n)
|
||||
if (sm2_bn_cmp(e, SM2_N) >= 0) {
|
||||
sm2_bn_sub(e, e, SM2_N);
|
||||
}
|
||||
if (sm2_bn_cmp(x, SM2_N) >= 0) {
|
||||
sm2_bn_sub(x, x, SM2_N);
|
||||
}
|
||||
sm2_fn_add(e, e, x); //sm2_bn_print(stderr, 0, 4, "e + x (mod n)", e);
|
||||
|
||||
// check if r == r'
|
||||
if (sm2_bn_cmp(e, r) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int all_zero(const uint8_t *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out)
|
||||
{
|
||||
SM2_BN k;
|
||||
SM2_JACOBIAN_POINT _P, *P = &_P;
|
||||
SM2_JACOBIAN_POINT _C1, *C1 = &_C1;
|
||||
SM2_JACOBIAN_POINT _kP, *kP = &_kP;
|
||||
uint8_t x2y2[64];
|
||||
SM3_CTX sm3_ctx;
|
||||
|
||||
if (!(SM2_MIN_PLAINTEXT_SIZE <= inlen && inlen <= SM2_MAX_PLAINTEXT_SIZE)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_jacobian_point_from_bytes(P, (uint8_t *)&key->public_key);
|
||||
|
||||
// S = h * P, check S != O
|
||||
// for sm2 curve, h == 1 and S == P
|
||||
// SM2_POINT can not present point at infinity, do do nothing here
|
||||
|
||||
retry:
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_fn_rand(k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (sm2_bn_is_zero(k)); //sm2_bn_print(stderr, 0, 4, "k", k);
|
||||
|
||||
// output C1 = k * G = (x1, y1)
|
||||
sm2_jacobian_point_mul_generator(C1, k);
|
||||
sm2_jacobian_point_to_bytes(C1, (uint8_t *)&out->point);
|
||||
|
||||
// k * P = (x2, y2)
|
||||
sm2_jacobian_point_mul(kP, k, P);
|
||||
sm2_jacobian_point_to_bytes(kP, x2y2);
|
||||
|
||||
// t = KDF(x2 || y2, inlen)
|
||||
sm2_kdf(x2y2, 64, inlen, out->ciphertext);
|
||||
|
||||
// if t is all zero, retry
|
||||
if (all_zero(out->ciphertext, inlen)) {
|
||||
goto retry;
|
||||
}
|
||||
|
||||
// output C2 = M xor t
|
||||
gmssl_memxor(out->ciphertext, out->ciphertext, in, inlen);
|
||||
out->ciphertext_size = (uint32_t)inlen;
|
||||
|
||||
// output C3 = Hash(x2 || m || y2)
|
||||
sm3_init(&sm3_ctx);
|
||||
sm3_update(&sm3_ctx, x2y2, 32);
|
||||
sm3_update(&sm3_ctx, in, inlen);
|
||||
sm3_update(&sm3_ctx, x2y2 + 32, 32);
|
||||
sm3_finish(&sm3_ctx, out->hash);
|
||||
|
||||
gmssl_secure_clear(k, sizeof(k));
|
||||
gmssl_secure_clear(kP, sizeof(SM2_JACOBIAN_POINT));
|
||||
gmssl_secure_clear(x2y2, sizeof(x2y2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_do_encrypt_fixlen(const SM2_KEY *key, const uint8_t *in, size_t inlen, int point_size, SM2_CIPHERTEXT *out)
|
||||
{
|
||||
unsigned int trys = 200;
|
||||
SM2_BN k;
|
||||
SM2_JACOBIAN_POINT _P, *P = &_P;
|
||||
SM2_JACOBIAN_POINT _C1, *C1 = &_C1;
|
||||
SM2_JACOBIAN_POINT _kP, *kP = &_kP;
|
||||
uint8_t x2y2[64];
|
||||
SM3_CTX sm3_ctx;
|
||||
|
||||
if (!(SM2_MIN_PLAINTEXT_SIZE <= inlen && inlen <= SM2_MAX_PLAINTEXT_SIZE)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (point_size) {
|
||||
case SM2_ciphertext_compact_point_size:
|
||||
case SM2_ciphertext_typical_point_size:
|
||||
case SM2_ciphertext_max_point_size:
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm2_jacobian_point_from_bytes(P, (uint8_t *)&key->public_key);
|
||||
|
||||
// S = h * P, check S != O
|
||||
// for sm2 curve, h == 1 and S == P
|
||||
// SM2_POINT can not present point at infinity, do do nothing here
|
||||
|
||||
retry:
|
||||
// rand k in [1, n - 1]
|
||||
do {
|
||||
if (sm2_fn_rand(k) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (sm2_bn_is_zero(k)); //sm2_bn_print(stderr, 0, 4, "k", k);
|
||||
|
||||
// output C1 = k * G = (x1, y1)
|
||||
sm2_jacobian_point_mul_generator(C1, k);
|
||||
sm2_jacobian_point_to_bytes(C1, (uint8_t *)&out->point);
|
||||
|
||||
// check fixlen
|
||||
if (trys) {
|
||||
size_t len = 0;
|
||||
asn1_integer_to_der(out->point.x, 32, NULL, &len);
|
||||
asn1_integer_to_der(out->point.y, 32, NULL, &len);
|
||||
if (len != point_size) {
|
||||
trys--;
|
||||
goto retry;
|
||||
}
|
||||
} else {
|
||||
gmssl_secure_clear(k, sizeof(k));
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// k * P = (x2, y2)
|
||||
sm2_jacobian_point_mul(kP, k, P);
|
||||
sm2_jacobian_point_to_bytes(kP, x2y2);
|
||||
|
||||
// t = KDF(x2 || y2, inlen)
|
||||
sm2_kdf(x2y2, 64, inlen, out->ciphertext);
|
||||
|
||||
// if t is all zero, retry
|
||||
if (all_zero(out->ciphertext, inlen)) {
|
||||
goto retry;
|
||||
}
|
||||
|
||||
// output C2 = M xor t
|
||||
gmssl_memxor(out->ciphertext, out->ciphertext, in, inlen);
|
||||
out->ciphertext_size = (uint32_t)inlen;
|
||||
|
||||
// output C3 = Hash(x2 || m || y2)
|
||||
sm3_init(&sm3_ctx);
|
||||
sm3_update(&sm3_ctx, x2y2, 32);
|
||||
sm3_update(&sm3_ctx, in, inlen);
|
||||
sm3_update(&sm3_ctx, x2y2 + 32, 32);
|
||||
sm3_finish(&sm3_ctx, out->hash);
|
||||
|
||||
gmssl_secure_clear(k, sizeof(k));
|
||||
gmssl_secure_clear(kP, sizeof(SM2_JACOBIAN_POINT));
|
||||
gmssl_secure_clear(x2y2, sizeof(x2y2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sm2_do_decrypt(const SM2_KEY *key, const SM2_CIPHERTEXT *in, uint8_t *out, size_t *outlen)
|
||||
{
|
||||
int ret = -1;
|
||||
SM2_BN d;
|
||||
SM2_JACOBIAN_POINT _C1, *C1 = &_C1;
|
||||
uint8_t x2y2[64];
|
||||
SM3_CTX sm3_ctx;
|
||||
uint8_t hash[32];
|
||||
|
||||
// check C1 is on sm2 curve
|
||||
sm2_jacobian_point_from_bytes(C1, (uint8_t *)&in->point);
|
||||
if (!sm2_jacobian_point_is_on_curve(C1)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check if S = h * C1 is point at infinity
|
||||
// this will not happen, as SM2_POINT can not present point at infinity
|
||||
|
||||
// d * C1 = (x2, y2)
|
||||
sm2_bn_from_bytes(d, key->private_key);
|
||||
sm2_jacobian_point_mul(C1, d, C1);
|
||||
|
||||
// t = KDF(x2 || y2, klen) and check t is not all zeros
|
||||
sm2_jacobian_point_to_bytes(C1, x2y2);
|
||||
sm2_kdf(x2y2, 64, in->ciphertext_size, out);
|
||||
if (all_zero(out, in->ciphertext_size)) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
// M = C2 xor t
|
||||
gmssl_memxor(out, out, in->ciphertext, in->ciphertext_size);
|
||||
*outlen = in->ciphertext_size;
|
||||
|
||||
// u = Hash(x2 || M || y2)
|
||||
sm3_init(&sm3_ctx);
|
||||
sm3_update(&sm3_ctx, x2y2, 32);
|
||||
sm3_update(&sm3_ctx, out, in->ciphertext_size);
|
||||
sm3_update(&sm3_ctx, x2y2 + 32, 32);
|
||||
sm3_finish(&sm3_ctx, hash);
|
||||
|
||||
// check if u == C3
|
||||
if (memcmp(in->hash, hash, sizeof(hash)) != 0) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
gmssl_secure_clear(d, sizeof(d));
|
||||
gmssl_secure_clear(C1, sizeof(SM2_JACOBIAN_POINT));
|
||||
gmssl_secure_clear(x2y2, sizeof(x2y2));
|
||||
return ret;
|
||||
}
|
||||
532
src/sm2_z256.c
532
src/sm2_z256.c
@@ -52,8 +52,35 @@
|
||||
#include <gmssl/endian.h>
|
||||
#include <gmssl/sm2_z256.h>
|
||||
|
||||
/*
|
||||
SM2 parameters
|
||||
|
||||
// z256
|
||||
p = 0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff
|
||||
a = 0xfffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc
|
||||
b = 0x28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93
|
||||
x = 0x32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7
|
||||
y = 0xbc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0
|
||||
n = 0xfffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123
|
||||
h = 0x1
|
||||
*/
|
||||
|
||||
const uint64_t SM2_Z256_ONE[4] = { 1,0,0,0 };
|
||||
|
||||
void sm2_z256_from_bytes(uint64_t r[4], const uint8_t in[32])
|
||||
{
|
||||
r[3] = GETU64(in);
|
||||
r[2] = GETU64(in + 8);
|
||||
r[1] = GETU64(in + 16);
|
||||
r[0] = GETU64(in + 24);
|
||||
}
|
||||
|
||||
void sm2_z256_to_bytes(const uint64_t a[4], uint8_t out[32])
|
||||
{
|
||||
PUTU64(out, a[3]);
|
||||
PUTU64(out + 8, a[2]);
|
||||
PUTU64(out + 16, a[1]);
|
||||
PUTU64(out + 24, a[0]);
|
||||
}
|
||||
|
||||
void sm2_z256_copy(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
@@ -74,22 +101,6 @@ void sm2_z256_copy_conditional(uint64_t dst[4], const uint64_t src[4], uint64_t
|
||||
dst[3] = (src[3] & mask1) ^ (dst[3] & mask2);
|
||||
}
|
||||
|
||||
void sm2_z256_from_bytes(uint64_t r[4], const uint8_t in[32])
|
||||
{
|
||||
r[3] = GETU64(in);
|
||||
r[2] = GETU64(in + 8);
|
||||
r[1] = GETU64(in + 16);
|
||||
r[0] = GETU64(in + 24);
|
||||
}
|
||||
|
||||
void sm2_z256_to_bytes(const uint64_t a[4], uint8_t out[32])
|
||||
{
|
||||
PUTU64(out, a[3]);
|
||||
PUTU64(out + 8, a[2]);
|
||||
PUTU64(out + 16, a[1]);
|
||||
PUTU64(out + 24, a[0]);
|
||||
}
|
||||
|
||||
static uint64_t is_zero(uint64_t in)
|
||||
{
|
||||
in |= (0 - in);
|
||||
@@ -294,18 +305,18 @@ int sm2_z512_print(FILE *fp, int ind, int fmt, const char *label, const uint64_t
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// z256 mod p
|
||||
// GF(p)
|
||||
|
||||
// p = 2^256 - 2^224 - 2^96 + 2^64 - 1
|
||||
// = 0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff
|
||||
const uint64_t SM2_Z256_P[4] = {
|
||||
0xffffffffffffffff, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffeffffffff
|
||||
0xffffffffffffffff, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffeffffffff,
|
||||
};
|
||||
|
||||
// mont(1) = 2^256 mod p = 2^224 + 2^96 - 2^64 + 1
|
||||
// 2^256 - p = 2^224 + 2^96 - 2^64 + 1
|
||||
const uint64_t SM2_Z256_NEG_P[4] = {
|
||||
1, ((uint64_t)1 << 32) - 1, 0, ((uint64_t)1 << 32) };
|
||||
|
||||
1, ((uint64_t)1 << 32) - 1, 0, ((uint64_t)1 << 32),
|
||||
};
|
||||
|
||||
void sm2_z256_modp_add(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
{
|
||||
@@ -373,24 +384,24 @@ void sm2_z256_modp_neg(uint64_t r[4], const uint64_t a[4])
|
||||
(void)sm2_z256_sub(r, SM2_Z256_P, a);
|
||||
}
|
||||
|
||||
// p' = -p^(-1) mod 2^256
|
||||
// = fffffffc00000001fffffffe00000000ffffffff000000010000000000000001
|
||||
// sage: -(IntegerModRing(2^256)(p))^-1
|
||||
const uint64_t SM2_Z256_P_PRIME[4] = {
|
||||
0x0000000000000001, 0xffffffff00000001, 0xfffffffe00000000, 0xfffffffc00000001,
|
||||
};
|
||||
|
||||
// montegomery
|
||||
|
||||
const uint64_t *SM2_Z256_MONT_ONE = SM2_Z256_NEG_P;
|
||||
// mont(1) (mod p) = 2^256 mod p = 2^256 - p
|
||||
const uint64_t *SM2_Z256_MODP_MONT_ONE = SM2_Z256_NEG_P;
|
||||
|
||||
// z = xy
|
||||
// c = (z + (z * p' mod 2^256) * p)/2^256
|
||||
void sm2_z256_mont_mul(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
void sm2_z256_modp_mont_mul(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
{
|
||||
uint64_t z[8];
|
||||
uint64_t t[8];
|
||||
uint64_t c;
|
||||
|
||||
// p' = -p^(-1) mod 2^256 = fffffffc00000001fffffffe00000000ffffffff000000010000000000000001
|
||||
const uint64_t p_[4] = {
|
||||
0x0000000000000001, 0xffffffff00000001, 0xfffffffe00000000, 0xfffffffc00000001
|
||||
};
|
||||
|
||||
//sm2_z256_print(stderr, 0, 0, "a", a);
|
||||
//sm2_z256_print(stderr, 0, 0, "b", b);
|
||||
|
||||
@@ -399,7 +410,7 @@ void sm2_z256_mont_mul(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
//sm2_z512_print(stderr, 0, 0, "z", z);
|
||||
|
||||
// t = low(z) * p'
|
||||
sm2_z256_mul(t, z, p_);
|
||||
sm2_z256_mul(t, z, SM2_Z256_P_PRIME);
|
||||
//sm2_z256_print(stderr, 0, 0, "z * p' mod 2^256", t);
|
||||
|
||||
// t = low(t) * p
|
||||
@@ -415,7 +426,7 @@ void sm2_z256_mont_mul(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
//sm2_z256_print(stderr, 0, 0, "r", r);
|
||||
|
||||
if (c) {
|
||||
sm2_z256_add(r, r, SM2_Z256_MONT_ONE);
|
||||
sm2_z256_add(r, r, SM2_Z256_MODP_MONT_ONE);
|
||||
//sm2_z256_print(stderr, 0, 0, "r1", r);
|
||||
|
||||
} else if (sm2_z256_cmp(r, SM2_Z256_P) >= 0) {
|
||||
@@ -424,12 +435,35 @@ void sm2_z256_mont_mul(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
}
|
||||
}
|
||||
|
||||
void sm2_z256_mont_sqr(uint64_t r[4], const uint64_t a[4])
|
||||
void sm2_z256_modp_mont_sqr(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
sm2_z256_mont_mul(r, a, a);
|
||||
sm2_z256_modp_mont_mul(r, a, a);
|
||||
}
|
||||
|
||||
void sm2_z256_mont_inv(uint64_t r[4], const uint64_t a[4])
|
||||
void sm2_z256_modp_mont_exp(uint64_t r[4], const uint64_t a[4], const uint64_t e[4])
|
||||
{
|
||||
uint64_t t[4];
|
||||
uint64_t w;
|
||||
int i, j;
|
||||
|
||||
// t = mont(1) (mod p)
|
||||
sm2_z256_copy(t, SM2_Z256_MODP_MONT_ONE);
|
||||
|
||||
for (i = 3; i >= 0; i--) {
|
||||
w = e[i];
|
||||
for (j = 0; j < 64; j++) {
|
||||
sm2_z256_modp_mont_sqr(t, t);
|
||||
if (w & 0x8000000000000000) {
|
||||
sm2_z256_modp_mont_mul(t, t, a);
|
||||
}
|
||||
w <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
sm2_z256_copy(r, t);
|
||||
}
|
||||
|
||||
void sm2_z256_modp_mont_inv(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
uint64_t a1[4];
|
||||
uint64_t a2[4];
|
||||
@@ -438,105 +472,264 @@ void sm2_z256_mont_inv(uint64_t r[4], const uint64_t a[4])
|
||||
uint64_t a5[4];
|
||||
int i;
|
||||
|
||||
sm2_z256_mont_sqr(a1, a);
|
||||
sm2_z256_mont_mul(a2, a1, a);
|
||||
sm2_z256_mont_sqr(a3, a2);
|
||||
sm2_z256_mont_sqr(a3, a3);
|
||||
sm2_z256_mont_mul(a3, a3, a2);
|
||||
sm2_z256_mont_sqr(a4, a3);
|
||||
sm2_z256_mont_sqr(a4, a4);
|
||||
sm2_z256_mont_sqr(a4, a4);
|
||||
sm2_z256_mont_sqr(a4, a4);
|
||||
sm2_z256_mont_mul(a4, a4, a3);
|
||||
sm2_z256_mont_sqr(a5, a4);
|
||||
sm2_z256_modp_mont_sqr(a1, a);
|
||||
sm2_z256_modp_mont_mul(a2, a1, a);
|
||||
sm2_z256_modp_mont_sqr(a3, a2);
|
||||
sm2_z256_modp_mont_sqr(a3, a3);
|
||||
sm2_z256_modp_mont_mul(a3, a3, a2);
|
||||
sm2_z256_modp_mont_sqr(a4, a3);
|
||||
sm2_z256_modp_mont_sqr(a4, a4);
|
||||
sm2_z256_modp_mont_sqr(a4, a4);
|
||||
sm2_z256_modp_mont_sqr(a4, a4);
|
||||
sm2_z256_modp_mont_mul(a4, a4, a3);
|
||||
sm2_z256_modp_mont_sqr(a5, a4);
|
||||
for (i = 1; i < 8; i++) {
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
}
|
||||
sm2_z256_mont_mul(a5, a5, a4);
|
||||
sm2_z256_modp_mont_mul(a5, a5, a4);
|
||||
for (i = 0; i < 8; i++) {
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
}
|
||||
sm2_z256_mont_mul(a5, a5, a4);
|
||||
sm2_z256_modp_mont_mul(a5, a5, a4);
|
||||
for (i = 0; i < 4; i++) {
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
}
|
||||
sm2_z256_mont_mul(a5, a5, a3);
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_mont_mul(a5, a5, a2);
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_mont_mul(a5, a5, a);
|
||||
sm2_z256_mont_sqr(a4, a5);
|
||||
sm2_z256_mont_mul(a3, a4, a1);
|
||||
sm2_z256_mont_sqr(a5, a4);
|
||||
sm2_z256_modp_mont_mul(a5, a5, a3);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_mul(a5, a5, a2);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_mul(a5, a5, a);
|
||||
sm2_z256_modp_mont_sqr(a4, a5);
|
||||
sm2_z256_modp_mont_mul(a3, a4, a1);
|
||||
sm2_z256_modp_mont_sqr(a5, a4);
|
||||
for (i = 1; i< 31; i++) {
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
}
|
||||
sm2_z256_mont_mul(a4, a5, a4);
|
||||
sm2_z256_mont_sqr(a4, a4);
|
||||
sm2_z256_mont_mul(a4, a4, a);
|
||||
sm2_z256_mont_mul(a3, a4, a2);
|
||||
sm2_z256_modp_mont_mul(a4, a5, a4);
|
||||
sm2_z256_modp_mont_sqr(a4, a4);
|
||||
sm2_z256_modp_mont_mul(a4, a4, a);
|
||||
sm2_z256_modp_mont_mul(a3, a4, a2);
|
||||
for (i = 0; i < 33; i++) {
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
}
|
||||
sm2_z256_mont_mul(a2, a5, a3);
|
||||
sm2_z256_mont_mul(a3, a2, a3);
|
||||
sm2_z256_modp_mont_mul(a2, a5, a3);
|
||||
sm2_z256_modp_mont_mul(a3, a2, a3);
|
||||
for (i = 0; i < 32; i++) {
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
}
|
||||
sm2_z256_mont_mul(a2, a5, a3);
|
||||
sm2_z256_mont_mul(a3, a2, a3);
|
||||
sm2_z256_mont_mul(a4, a2, a4);
|
||||
sm2_z256_modp_mont_mul(a2, a5, a3);
|
||||
sm2_z256_modp_mont_mul(a3, a2, a3);
|
||||
sm2_z256_modp_mont_mul(a4, a2, a4);
|
||||
for (i = 0; i < 32; i++) {
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
}
|
||||
sm2_z256_mont_mul(a2, a5, a3);
|
||||
sm2_z256_mont_mul(a3, a2, a3);
|
||||
sm2_z256_mont_mul(a4, a2, a4);
|
||||
sm2_z256_modp_mont_mul(a2, a5, a3);
|
||||
sm2_z256_modp_mont_mul(a3, a2, a3);
|
||||
sm2_z256_modp_mont_mul(a4, a2, a4);
|
||||
for (i = 0; i < 32; i++) {
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
}
|
||||
sm2_z256_mont_mul(a2, a5, a3);
|
||||
sm2_z256_mont_mul(a3, a2, a3);
|
||||
sm2_z256_mont_mul(a4, a2, a4);
|
||||
sm2_z256_modp_mont_mul(a2, a5, a3);
|
||||
sm2_z256_modp_mont_mul(a3, a2, a3);
|
||||
sm2_z256_modp_mont_mul(a4, a2, a4);
|
||||
for (i = 0; i < 32; i++) {
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
}
|
||||
sm2_z256_mont_mul(a2, a5, a3);
|
||||
sm2_z256_mont_mul(a3, a2, a3);
|
||||
sm2_z256_mont_mul(a4, a2, a4);
|
||||
sm2_z256_modp_mont_mul(a2, a5, a3);
|
||||
sm2_z256_modp_mont_mul(a3, a2, a3);
|
||||
sm2_z256_modp_mont_mul(a4, a2, a4);
|
||||
for (i = 0; i < 32; i++) {
|
||||
sm2_z256_mont_sqr(a5, a5);
|
||||
sm2_z256_modp_mont_sqr(a5, a5);
|
||||
}
|
||||
sm2_z256_mont_mul(r, a4, a5);
|
||||
sm2_z256_modp_mont_mul(r, a4, a5);
|
||||
}
|
||||
|
||||
// mont(mont(a), 1) = aR * 1 * R^-1 (mod p) = a (mod p)
|
||||
void sm2_z256_from_mont(uint64_t r[4], const uint64_t a[4])
|
||||
void sm2_z256_modp_from_mont(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
const uint64_t SM2_Z256_ONE[4] = { 1,0,0,0 };
|
||||
sm2_z256_mont_mul(r, a, SM2_Z256_ONE);
|
||||
sm2_z256_modp_mont_mul(r, a, SM2_Z256_ONE);
|
||||
}
|
||||
|
||||
// 2^512 (mod p)
|
||||
const uint64_t SM2_Z256_2e512modp[4] = {
|
||||
0x0000000200000003, 0x00000002ffffffff, 0x0000000100000001, 0x0000000400000002
|
||||
};
|
||||
|
||||
// mont(a) = a * 2^256 (mod p) = mont_mul(a, 2^512 mod p)
|
||||
void sm2_z256_to_mont(const uint64_t a[4], uint64_t r[4])
|
||||
void sm2_z256_modp_to_mont(const uint64_t a[4], uint64_t r[4])
|
||||
{
|
||||
// 2^512 (mod p)
|
||||
const uint64_t SM2_Z256_2e512modp[4] = {
|
||||
0x0000000200000003, 0x00000002ffffffff, 0x0000000100000001, 0x0000000400000002
|
||||
};
|
||||
|
||||
sm2_z256_mont_mul(r, a, SM2_Z256_2e512modp);
|
||||
sm2_z256_modp_mont_mul(r, a, SM2_Z256_2e512modp);
|
||||
}
|
||||
|
||||
int sm2_z256_mont_print(FILE *fp, int ind, int fmt, const char *label, const uint64_t a[4])
|
||||
int sm2_z256_modp_mont_print(FILE *fp, int ind, int fmt, const char *label, const uint64_t a[4])
|
||||
{
|
||||
uint64_t r[4];
|
||||
sm2_z256_from_mont(r, a);
|
||||
sm2_z256_modp_from_mont(r, a);
|
||||
sm2_z256_print(fp, ind, fmt, label, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// GF(n)
|
||||
|
||||
// n = 0xfffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123
|
||||
const uint64_t SM2_Z256_N[4] = {
|
||||
0x53bbf40939d54123, 0x7203df6b21c6052b, 0xffffffffffffffff, 0xfffffffeffffffff,
|
||||
};
|
||||
|
||||
// 2^256 - n = 0x10000000000000000000000008dfc2094de39fad4ac440bf6c62abedd
|
||||
const uint64_t SM2_Z256_NEG_N[4] = {
|
||||
0xac440bf6c62abedd, 0x8dfc2094de39fad4, 0x0000000000000000, 0x0000000100000000,
|
||||
};
|
||||
|
||||
void sm2_z256_modn_add(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
{
|
||||
uint64_t c;
|
||||
|
||||
c = sm2_z256_add(r, a, b);
|
||||
|
||||
if (c) {
|
||||
// a + b - n = (a + b - 2^256) + (2^256 - n)
|
||||
(void)sm2_z256_add(r, r, SM2_Z256_NEG_N);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sm2_z256_cmp(r, SM2_Z256_N) >= 0) {
|
||||
(void)sm2_z256_sub(r, r, SM2_Z256_N);
|
||||
}
|
||||
}
|
||||
|
||||
void sm2_z256_modn_sub(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
{
|
||||
uint64_t c;
|
||||
|
||||
c = sm2_z256_sub(r, a, b);
|
||||
|
||||
if (c) {
|
||||
// a - b + n = (a - b + 2^256) - (2^256 - n)
|
||||
(void)sm2_z256_sub(r, r, SM2_Z256_NEG_N);
|
||||
}
|
||||
}
|
||||
|
||||
void sm2_z256_modn_neg(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
(void)sm2_z256_sub(r, SM2_Z256_N, a);
|
||||
}
|
||||
|
||||
// n' = -n^(-1) mod 2^256
|
||||
// = 0x6f39132f82e4c7bc2b0068d3b08941d4df1e8d34fc8319a5327f9e8872350975
|
||||
// sage: -(IntegerModRing(2^256)(n))^-1
|
||||
const uint64_t SM2_Z256_N_PRIME[4] = {
|
||||
0x327f9e8872350975, 0xdf1e8d34fc8319a5, 0x2b0068d3b08941d4, 0x6f39132f82e4c7bc,
|
||||
};
|
||||
|
||||
// mont(1) (mod n) = 2^256 - n
|
||||
const uint64_t *SM2_Z256_MODN_MONT_ONE = SM2_Z256_NEG_N;
|
||||
|
||||
void sm2_z256_modn_mont_mul(uint64_t r[4], const uint64_t a[4], const uint64_t b[4])
|
||||
{
|
||||
uint64_t z[8];
|
||||
uint64_t t[8];
|
||||
uint64_t c;
|
||||
|
||||
//sm2_z256_print(stderr, 0, 0, "a", a);
|
||||
//sm2_z256_print(stderr, 0, 0, "b", b);
|
||||
|
||||
// z = a * b
|
||||
sm2_z256_mul(z, a, b);
|
||||
//sm2_z512_print(stderr, 0, 0, "z", z);
|
||||
|
||||
// t = low(z) * n'
|
||||
sm2_z256_mul(t, z, SM2_Z256_N_PRIME);
|
||||
//sm2_z256_print(stderr, 0, 0, "z * n' mod 2^256", t);
|
||||
|
||||
// t = low(t) * n
|
||||
sm2_z256_mul(t, t, SM2_Z256_N);
|
||||
//sm2_z512_print(stderr, 0, 0, "(z * n' mod 2^256) * n", t);
|
||||
|
||||
// z = z + t
|
||||
c = sm2_z512_add(z, z, t);
|
||||
//sm2_z512_print(stderr, 0, 0, "z", z);
|
||||
|
||||
// r = high(r)
|
||||
sm2_z256_copy(r, z + 4);
|
||||
//sm2_z256_print(stderr, 0, 0, "r", r);
|
||||
|
||||
if (c) {
|
||||
sm2_z256_add(r, r, SM2_Z256_MODN_MONT_ONE);
|
||||
//sm2_z256_print(stderr, 0, 0, "r1", r);
|
||||
|
||||
} else if (sm2_z256_cmp(r, SM2_Z256_N) >= 0) {
|
||||
(void)sm2_z256_sub(r, r, SM2_Z256_N);
|
||||
//sm2_z256_print(stderr, 0, 0, "r2", r);
|
||||
}
|
||||
}
|
||||
|
||||
void sm2_z256_modn_mont_sqr(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
sm2_z256_modn_mont_mul(r, a, a);
|
||||
}
|
||||
|
||||
void sm2_z256_modn_mont_exp(uint64_t r[4], const uint64_t a[4], const uint64_t e[4])
|
||||
{
|
||||
uint64_t t[4];
|
||||
uint64_t w;
|
||||
int i, j;
|
||||
|
||||
// t = mont(1)
|
||||
sm2_z256_copy(t, SM2_Z256_MODN_MONT_ONE);
|
||||
|
||||
for (i = 3; i >= 0; i--) {
|
||||
w = e[i];
|
||||
for (j = 0; j < 64; j++) {
|
||||
sm2_z256_modn_mont_sqr(t, t);
|
||||
if (w & 0x8000000000000000) {
|
||||
sm2_z256_modn_mont_mul(t, t, a);
|
||||
}
|
||||
w <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
sm2_z256_copy(r, t);
|
||||
}
|
||||
|
||||
// n - 2 = 0xfffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54121
|
||||
const uint64_t SM2_Z256_N_MINUS_TWO[4] = {
|
||||
0x53bbf40939d54121, 0x7203df6b21c6052b, 0xffffffffffffffff, 0xfffffffeffffffff,
|
||||
};
|
||||
|
||||
void sm2_z256_modn_mont_inv(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
sm2_z256_modn_mont_exp(r, a, SM2_Z256_N_MINUS_TWO);
|
||||
}
|
||||
|
||||
// mont(mont(a), 1) = aR * 1 * R^-1 (mod n) = a (mod p)
|
||||
void sm2_z256_modn_from_mont(uint64_t r[4], const uint64_t a[4])
|
||||
{
|
||||
sm2_z256_modn_mont_mul(r, a, SM2_Z256_ONE);
|
||||
}
|
||||
|
||||
|
||||
// 2^512 (mod n) = 0x1eb5e412a22b3d3b620fc84c3affe0d43464504ade6fa2fa901192af7c114f20
|
||||
const uint64_t SM2_Z256_2e512modn[4] = {
|
||||
0x901192af7c114f20, 0x3464504ade6fa2fa, 0x620fc84c3affe0d4, 0x1eb5e412a22b3d3b,
|
||||
};
|
||||
|
||||
// mont(a) = a * 2^256 (mod n) = mont_mul(a, 2^512 mod n)
|
||||
void sm2_z256_modn_to_mont(const uint64_t a[4], uint64_t r[4])
|
||||
{
|
||||
sm2_z256_modn_mont_mul(r, a, SM2_Z256_2e512modn);
|
||||
}
|
||||
|
||||
int sm2_z256_modn_mont_print(FILE *fp, int ind, int fmt, const char *label, const uint64_t a[4])
|
||||
{
|
||||
uint64_t r[4];
|
||||
sm2_z256_modn_from_mont(r, a);
|
||||
sm2_z256_print(fp, ind, fmt, label, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Jacobian Point with Montgomery coordinates
|
||||
|
||||
void sm2_z256_point_dbl(SM2_Z256_POINT *R, const SM2_Z256_POINT *A)
|
||||
@@ -554,75 +747,75 @@ void sm2_z256_point_dbl(SM2_Z256_POINT *R, const SM2_Z256_POINT *A)
|
||||
|
||||
// S = 2*Y1
|
||||
sm2_z256_modp_mul_by_2(S, Y1);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "1", S);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "1", S);
|
||||
|
||||
// Zsqr = Z1^2
|
||||
sm2_z256_mont_sqr(Zsqr, Z1);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "2", Zsqr);
|
||||
sm2_z256_modp_mont_sqr(Zsqr, Z1);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "2", Zsqr);
|
||||
|
||||
// S = S^2 = 4*Y1^2
|
||||
sm2_z256_mont_sqr(S, S);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "3", S);
|
||||
sm2_z256_modp_mont_sqr(S, S);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "3", S);
|
||||
|
||||
// Z3 = Z1 * Y1
|
||||
sm2_z256_mont_mul(Z3, Z1, Y1);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "4", Z3);
|
||||
sm2_z256_modp_mont_mul(Z3, Z1, Y1);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "4", Z3);
|
||||
|
||||
// Z3 = 2 * Z3 = 2*Y1*Z1
|
||||
sm2_z256_modp_mul_by_2(Z3, Z3);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "5", Z3);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "5", Z3);
|
||||
|
||||
// M = X1 + Zsqr = X1 + Z1^2
|
||||
sm2_z256_modp_add(M, X1, Zsqr);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "6", M);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "6", M);
|
||||
|
||||
// Zsqr = X1 - Zsqr = X1 - Z1^2
|
||||
sm2_z256_modp_sub(Zsqr, X1, Zsqr);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "7", Zsqr);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "7", Zsqr);
|
||||
|
||||
// Y3 = S^2 = 16 * Y1^4
|
||||
sm2_z256_mont_sqr(Y3, S);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "8", Y3);
|
||||
sm2_z256_modp_mont_sqr(Y3, S);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "8", Y3);
|
||||
|
||||
// Y3 = Y3/2 = 8 * Y1^4
|
||||
sm2_z256_modp_div_by_2(Y3, Y3);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "9", Y3);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "9", Y3);
|
||||
|
||||
// M = M * Zsqr = (X1 + Z1^2)(X1 - Z1^2)
|
||||
sm2_z256_mont_mul(M, M, Zsqr);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "10", M);
|
||||
sm2_z256_modp_mont_mul(M, M, Zsqr);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "10", M);
|
||||
|
||||
// M = 3*M = 3(X1 + Z1^2)(X1 - Z1^2)
|
||||
sm2_z256_modp_mul_by_3(M, M);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "11", M);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "11", M);
|
||||
|
||||
// S = S * X1 = 4 * X1 * Y1^2
|
||||
sm2_z256_mont_mul(S, S, X1);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "12", S);
|
||||
sm2_z256_modp_mont_mul(S, S, X1);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "12", S);
|
||||
|
||||
// tmp0 = 2 * S = 8 * X1 * Y1^2
|
||||
sm2_z256_modp_mul_by_2(tmp0, S);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "13", tmp0);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "13", tmp0);
|
||||
|
||||
// X3 = M^2 = (3(X1 + Z1^2)(X1 - Z1^2))^2
|
||||
sm2_z256_mont_sqr(X3, M);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "14", X3);
|
||||
sm2_z256_modp_mont_sqr(X3, M);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "14", X3);
|
||||
|
||||
// X3 = X3 - tmp0 = (3(X1 + Z1^2)(X1 - Z1^2))^2 - 8 * X1 * Y1^2
|
||||
sm2_z256_modp_sub(X3, X3, tmp0);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "15", X3);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "15", X3);
|
||||
|
||||
// S = S - X3 = 4 * X1 * Y1^2 - X3
|
||||
sm2_z256_modp_sub(S, S, X3);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "16", S);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "16", S);
|
||||
|
||||
// S = S * M = 3(X1 + Z1^2)(X1 - Z1^2)(4 * X1 * Y1^2 - X3)
|
||||
sm2_z256_mont_mul(S, S, M);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "17", S);
|
||||
sm2_z256_modp_mont_mul(S, S, M);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "17", S);
|
||||
|
||||
// Y3 = S - Y3 = 3(X1 + Z1^2)(X1 - Z1^2)(4 * X1 * Y1^2 - X3) - 8 * Y1^4
|
||||
sm2_z256_modp_sub(Y3, S, Y3);
|
||||
//sm2_z256_mont_print(stderr, 0, 0, "18", Y3);
|
||||
//sm2_z256_modp_mont_print(stderr, 0, 0, "18", Y3);
|
||||
}
|
||||
|
||||
void sm2_z256_point_add(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const SM2_Z256_POINT *b)
|
||||
@@ -660,18 +853,18 @@ void sm2_z256_point_add(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const SM2_Z2
|
||||
in1infty = is_zero(in1infty);
|
||||
in2infty = is_zero(in2infty);
|
||||
|
||||
sm2_z256_mont_sqr(Z2sqr, in2_z); /* Z2^2 */
|
||||
sm2_z256_mont_sqr(Z1sqr, in1_z); /* Z1^2 */
|
||||
sm2_z256_modp_mont_sqr(Z2sqr, in2_z); /* Z2^2 */
|
||||
sm2_z256_modp_mont_sqr(Z1sqr, in1_z); /* Z1^2 */
|
||||
|
||||
sm2_z256_mont_mul(S1, Z2sqr, in2_z); /* S1 = Z2^3 */
|
||||
sm2_z256_mont_mul(S2, Z1sqr, in1_z); /* S2 = Z1^3 */
|
||||
sm2_z256_modp_mont_mul(S1, Z2sqr, in2_z); /* S1 = Z2^3 */
|
||||
sm2_z256_modp_mont_mul(S2, Z1sqr, in1_z); /* S2 = Z1^3 */
|
||||
|
||||
sm2_z256_mont_mul(S1, S1, in1_y); /* S1 = Y1*Z2^3 */
|
||||
sm2_z256_mont_mul(S2, S2, in2_y); /* S2 = Y2*Z1^3 */
|
||||
sm2_z256_modp_mont_mul(S1, S1, in1_y); /* S1 = Y1*Z2^3 */
|
||||
sm2_z256_modp_mont_mul(S2, S2, in2_y); /* S2 = Y2*Z1^3 */
|
||||
sm2_z256_modp_sub(R, S2, S1); /* R = S2 - S1 */
|
||||
|
||||
sm2_z256_mont_mul(U1, in1_x, Z2sqr); /* U1 = X1*Z2^2 */
|
||||
sm2_z256_mont_mul(U2, in2_x, Z1sqr); /* U2 = X2*Z1^2 */
|
||||
sm2_z256_modp_mont_mul(U1, in1_x, Z2sqr); /* U1 = X1*Z2^2 */
|
||||
sm2_z256_modp_mont_mul(U2, in2_x, Z1sqr); /* U2 = X2*Z1^2 */
|
||||
sm2_z256_modp_sub(H, U2, U1); /* H = U2 - U1 */
|
||||
|
||||
/*
|
||||
@@ -687,13 +880,13 @@ void sm2_z256_point_add(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const SM2_Z2
|
||||
}
|
||||
}
|
||||
|
||||
sm2_z256_mont_sqr(Rsqr, R); /* R^2 */
|
||||
sm2_z256_mont_mul(res_z, H, in1_z); /* Z3 = H*Z1*Z2 */
|
||||
sm2_z256_mont_sqr(Hsqr, H); /* H^2 */
|
||||
sm2_z256_mont_mul(res_z, res_z, in2_z); /* Z3 = H*Z1*Z2 */
|
||||
sm2_z256_mont_mul(Hcub, Hsqr, H); /* H^3 */
|
||||
sm2_z256_modp_mont_sqr(Rsqr, R); /* R^2 */
|
||||
sm2_z256_modp_mont_mul(res_z, H, in1_z); /* Z3 = H*Z1*Z2 */
|
||||
sm2_z256_modp_mont_sqr(Hsqr, H); /* H^2 */
|
||||
sm2_z256_modp_mont_mul(res_z, res_z, in2_z); /* Z3 = H*Z1*Z2 */
|
||||
sm2_z256_modp_mont_mul(Hcub, Hsqr, H); /* H^3 */
|
||||
|
||||
sm2_z256_mont_mul(U2, U1, Hsqr); /* U1*H^2 */
|
||||
sm2_z256_modp_mont_mul(U2, U1, Hsqr); /* U1*H^2 */
|
||||
sm2_z256_modp_mul_by_2(Hsqr, U2); /* 2*U1*H^2 */
|
||||
|
||||
sm2_z256_modp_sub(res_x, Rsqr, Hsqr);
|
||||
@@ -701,8 +894,8 @@ void sm2_z256_point_add(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const SM2_Z2
|
||||
|
||||
sm2_z256_modp_sub(res_y, U2, res_x);
|
||||
|
||||
sm2_z256_mont_mul(S2, S1, Hcub);
|
||||
sm2_z256_mont_mul(res_y, R, res_y);
|
||||
sm2_z256_modp_mont_mul(S2, S1, Hcub);
|
||||
sm2_z256_modp_mont_mul(res_y, R, res_y);
|
||||
sm2_z256_modp_sub(res_y, res_y, S2);
|
||||
|
||||
sm2_z256_copy_conditional(res_x, in2_x, in1infty);
|
||||
@@ -739,34 +932,31 @@ void sm2_z256_point_get_affine(const SM2_Z256_POINT *P, uint64_t x[4], uint64_t
|
||||
uint64_t y_out[4];
|
||||
|
||||
// z_inv = 1/Z
|
||||
sm2_z256_mont_inv(z_inv, P->Z);
|
||||
sm2_z256_modp_mont_inv(z_inv, P->Z);
|
||||
|
||||
// y_out = Y/Z
|
||||
if (y) {
|
||||
sm2_z256_mont_mul(y_out, P->Y, z_inv);
|
||||
sm2_z256_modp_mont_mul(y_out, P->Y, z_inv);
|
||||
}
|
||||
|
||||
// z_inv = 1/Z^2
|
||||
sm2_z256_mont_sqr(z_inv, z_inv);
|
||||
sm2_z256_modp_mont_sqr(z_inv, z_inv);
|
||||
|
||||
// x_out = X/Z^2
|
||||
sm2_z256_mont_mul(x_out, P->X, z_inv);
|
||||
sm2_z256_from_mont(x, x_out);
|
||||
sm2_z256_modp_mont_mul(x_out, P->X, z_inv);
|
||||
sm2_z256_modp_from_mont(x, x_out);
|
||||
|
||||
if (y) {
|
||||
// y_out = Y/Z^3
|
||||
sm2_z256_mont_mul(y_out, y_out, z_inv);
|
||||
sm2_z256_from_mont(y, y_out);
|
||||
sm2_z256_modp_mont_mul(y_out, y_out, z_inv);
|
||||
sm2_z256_modp_from_mont(y, y_out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void sm2_z256_point_copy_affine(SM2_Z256_POINT *R, const SM2_Z256_POINT_AFFINE *P)
|
||||
{
|
||||
memcpy(R, P, sizeof(SM2_Z256_POINT_AFFINE));
|
||||
sm2_z256_copy(R->Z, SM2_Z256_MONT_ONE);
|
||||
sm2_z256_copy(R->Z, SM2_Z256_MODP_MONT_ONE);
|
||||
}
|
||||
|
||||
void sm2_z256_point_add_affine(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const SM2_Z256_POINT_AFFINE *b)
|
||||
@@ -807,33 +997,33 @@ void sm2_z256_point_add_affine(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const
|
||||
|
||||
|
||||
/* Z1^2 */
|
||||
sm2_z256_mont_sqr(Z1sqr, in1_z);
|
||||
sm2_z256_modp_mont_sqr(Z1sqr, in1_z);
|
||||
|
||||
/* U2 = X2*Z1^2 */
|
||||
sm2_z256_mont_mul(U2, in2_x, Z1sqr);
|
||||
sm2_z256_modp_mont_mul(U2, in2_x, Z1sqr);
|
||||
/* H = U2 - U1 */
|
||||
sm2_z256_modp_sub(H, U2, in1_x);
|
||||
|
||||
sm2_z256_mont_mul(S2, Z1sqr, in1_z); /* S2 = Z1^3 */
|
||||
sm2_z256_modp_mont_mul(S2, Z1sqr, in1_z); /* S2 = Z1^3 */
|
||||
|
||||
sm2_z256_mont_mul(res_z, H, in1_z); /* Z3 = H*Z1*Z2 */
|
||||
sm2_z256_modp_mont_mul(res_z, H, in1_z); /* Z3 = H*Z1*Z2 */
|
||||
|
||||
sm2_z256_mont_mul(S2, S2, in2_y); /* S2 = Y2*Z1^3 */
|
||||
sm2_z256_modp_mont_mul(S2, S2, in2_y); /* S2 = Y2*Z1^3 */
|
||||
sm2_z256_modp_sub(R, S2, in1_y); /* R = S2 - S1 */
|
||||
|
||||
sm2_z256_mont_sqr(Hsqr, H); /* H^2 */
|
||||
sm2_z256_mont_sqr(Rsqr, R); /* R^2 */
|
||||
sm2_z256_mont_mul(Hcub, Hsqr, H); /* H^3 */
|
||||
sm2_z256_modp_mont_sqr(Hsqr, H); /* H^2 */
|
||||
sm2_z256_modp_mont_sqr(Rsqr, R); /* R^2 */
|
||||
sm2_z256_modp_mont_mul(Hcub, Hsqr, H); /* H^3 */
|
||||
|
||||
sm2_z256_mont_mul(U2, in1_x, Hsqr); /* U1*H^2 */
|
||||
sm2_z256_modp_mont_mul(U2, in1_x, Hsqr); /* U1*H^2 */
|
||||
sm2_z256_modp_mul_by_2(Hsqr, U2); /* 2*U1*H^2 */
|
||||
|
||||
sm2_z256_modp_sub(res_x, Rsqr, Hsqr);
|
||||
sm2_z256_modp_sub(res_x, res_x, Hcub);
|
||||
sm2_z256_modp_sub(H, U2, res_x);
|
||||
|
||||
sm2_z256_mont_mul(S2, in1_y, Hcub);
|
||||
sm2_z256_mont_mul(H, H, R);
|
||||
sm2_z256_modp_mont_mul(S2, in1_y, Hcub);
|
||||
sm2_z256_modp_mont_mul(H, H, R);
|
||||
sm2_z256_modp_sub(res_y, H, S2);
|
||||
|
||||
sm2_z256_copy_conditional(res_x, in2_x, in1infty);
|
||||
@@ -842,7 +1032,7 @@ void sm2_z256_point_add_affine(SM2_Z256_POINT *r, const SM2_Z256_POINT *a, const
|
||||
sm2_z256_copy_conditional(res_y, in2_y, in1infty);
|
||||
sm2_z256_copy_conditional(res_y, in1_y, in2infty);
|
||||
|
||||
sm2_z256_copy_conditional(res_z, SM2_Z256_MONT_ONE, in1infty);
|
||||
sm2_z256_copy_conditional(res_z, SM2_Z256_MODP_MONT_ONE, in1infty);
|
||||
sm2_z256_copy_conditional(res_z, in1_z, in2infty);
|
||||
|
||||
memcpy(r->X, res_x, sizeof(res_x));
|
||||
@@ -880,10 +1070,10 @@ int sm2_z256_point_affine_print(FILE *fp, int fmt, int ind, const char *label, c
|
||||
uint8_t affine[64];
|
||||
uint64_t a[4];
|
||||
|
||||
sm2_z256_from_mont(a, P->x);
|
||||
sm2_z256_modp_from_mont(a, P->x);
|
||||
sm2_z256_to_bytes(a, affine);
|
||||
|
||||
sm2_z256_from_mont(a, P->y);
|
||||
sm2_z256_modp_from_mont(a, P->y);
|
||||
sm2_z256_to_bytes(a, affine + 32);
|
||||
|
||||
format_bytes(fp, fmt, ind, label, affine, 64);
|
||||
@@ -985,7 +1175,6 @@ void sm2_z256_point_mul_sum(SM2_Z256_POINT *R, const uint64_t t[4], const SM2_Z2
|
||||
sm2_z256_point_add(R, R, &Q);
|
||||
}
|
||||
|
||||
|
||||
void sm2_z256_point_to_bytes(const SM2_Z256_POINT *P, uint8_t out[64])
|
||||
{
|
||||
uint64_t x[4];
|
||||
@@ -995,10 +1184,3 @@ void sm2_z256_point_to_bytes(const SM2_Z256_POINT *P, uint8_t out[64])
|
||||
sm2_z256_to_bytes(x, out);
|
||||
sm2_z256_to_bytes(y, out + 32);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,69 +17,366 @@
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
enum {
|
||||
OP_ADD,
|
||||
OP_SUB,
|
||||
OP_NEG,
|
||||
OP_MUL,
|
||||
OP_SQR,
|
||||
OP_EXP,
|
||||
OP_INV,
|
||||
};
|
||||
|
||||
static int test_sm2_z256_modp(void)
|
||||
{
|
||||
struct {
|
||||
char *label;
|
||||
int op;
|
||||
char *r;
|
||||
char *a;
|
||||
char *b;
|
||||
} tests[] = {
|
||||
{
|
||||
"x + y (mod p)", OP_ADD,
|
||||
"eefbe4cf140ff8b5b956d329d5a2eae8608c933cb89053217439786e54866567",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
"bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
|
||||
},
|
||||
{
|
||||
"x - y (mod p)", OP_SUB,
|
||||
"768d77882a23097d05db3562fed0a840bf3984422c3bc4a26e7b12a412128426",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
"bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
|
||||
},
|
||||
{
|
||||
"y - x (mod p)", OP_SUB,
|
||||
"89728876d5dcf682fa24ca9d012f57bf40c67bbcd3c43b5e9184ed5beded7bd9",
|
||||
"bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
},
|
||||
{
|
||||
"-x (mod p)", OP_NEG,
|
||||
"cd3b51d2e0e67ee6a066fbb995c6366b701cf43f0d99f41f8ea5ba76ccb38b38",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
"x * y (mod p)", OP_MUL,
|
||||
"edd7e745bdc4630ccfa1da1057033a525346dbf202f082f3c431349991ace76a",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
"bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
|
||||
},
|
||||
{
|
||||
"x^2 (mod p)", OP_SQR,
|
||||
"f4e2cca0bcfd67fba8531eebff519e4cb3d47f9fe8c5eff5151f4c497ec99fbf",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
"x^y (mod p)", OP_EXP,
|
||||
"8cafd11b1a0d2072b82911ba87e0d376103a1be5986fce91d8d297b758f68146",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
"bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
|
||||
},
|
||||
{
|
||||
"x^-1 (mod p)", OP_INV,
|
||||
"053b878fb82e213c17e554b9a574b7bd31775222704b7fd9c7d6f8441026cd80",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
||||
uint64_t r[4];
|
||||
uint64_t a[4];
|
||||
uint64_t b[4];
|
||||
uint64_t c[4];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
|
||||
|
||||
sm2_z256_from_hex(r, tests[i].r);
|
||||
sm2_z256_from_hex(a, tests[i].a);
|
||||
if (tests[i].b) {
|
||||
sm2_z256_from_hex(b, tests[i].b);
|
||||
}
|
||||
|
||||
switch (tests[i].op) {
|
||||
case OP_ADD:
|
||||
sm2_z256_modp_add(c, a, b);
|
||||
break;
|
||||
case OP_SUB:
|
||||
sm2_z256_modp_sub(c, a, b);
|
||||
break;
|
||||
case OP_NEG:
|
||||
sm2_z256_modp_neg(c, a);
|
||||
break;
|
||||
case OP_MUL:
|
||||
sm2_z256_modp_to_mont(a, a);
|
||||
sm2_z256_modp_to_mont(b, b);
|
||||
sm2_z256_modp_mont_mul(c, a, b);
|
||||
sm2_z256_modp_from_mont(c, c);
|
||||
break;
|
||||
case OP_SQR:
|
||||
sm2_z256_modp_to_mont(a, a);
|
||||
sm2_z256_modp_mont_sqr(c, a);
|
||||
sm2_z256_modp_from_mont(c, c);
|
||||
break;
|
||||
case OP_EXP:
|
||||
sm2_z256_modp_to_mont(a, a);
|
||||
sm2_z256_modp_mont_exp(c, a, b);
|
||||
sm2_z256_modp_from_mont(c, c);
|
||||
break;
|
||||
case OP_INV:
|
||||
sm2_z256_modp_to_mont(a, a);
|
||||
sm2_z256_modp_mont_inv(c, a);
|
||||
sm2_z256_modp_from_mont(c, c);
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sm2_z256_cmp(r, c) != 0) {
|
||||
|
||||
fprintf(stderr, "%s: error\n", __FUNCTION__);
|
||||
fprintf(stderr, " %s\n", tests[i].label);
|
||||
sm2_z256_print(stderr, 0, 8, "err", c);
|
||||
fprintf(stderr, " ret: %s\n", tests[i].r);
|
||||
fprintf(stderr, " op1: %s\n", tests[i].a);
|
||||
if (tests[i].b) {
|
||||
fprintf(stderr, " op2: %s\n", tests[i].b);
|
||||
}
|
||||
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_sm2_z256_modn(void)
|
||||
{
|
||||
struct {
|
||||
char *label;
|
||||
int op;
|
||||
char *r;
|
||||
char *a;
|
||||
char *b;
|
||||
} tests[] = {
|
||||
{
|
||||
"x + y (mod n)", OP_ADD,
|
||||
"eefbe4cf140ff8b5b956d329d5a2eae8608c933cb89053217439786e54866567",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
"bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
|
||||
},
|
||||
{
|
||||
"x - y (mod n)", OP_SUB,
|
||||
"768d77882a23097d05db3562fed0a840313d63ae4e01c9ccc23706ad4be7c54a",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
"bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
|
||||
},
|
||||
{
|
||||
"y - x (mod n)", OP_SUB,
|
||||
"89728876d5dcf682fa24ca9d012f57bf40c67bbcd3c43b5e9184ed5beded7bd9",
|
||||
"bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
},
|
||||
{
|
||||
"-x (mod n)", OP_NEG,
|
||||
"cd3b51d2e0e67ee6a066fbb995c6366ae220d3ab2f5ff949e261ae800688cc5c",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
"x * y (mod n)", OP_MUL,
|
||||
"cf7296d5cbf0b64bb5e9a11b294962e9c779b41c038e9c8d815234a0df9d6623",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
"bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
|
||||
},
|
||||
{
|
||||
"x^2 (mod n)", OP_SQR,
|
||||
"82d3d1b296d3a3803888b7ffc78f23eca824e7ec8d7ddaf231ffb0d256a19da2",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
"x^y (mod n)", OP_EXP,
|
||||
"0cf4df7e76d7d49ff23b94853a98aba1e36e9ca0358acbf23a3bbda406f46df3",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
"bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
|
||||
},
|
||||
{
|
||||
"x^-1 (mod n)", OP_INV,
|
||||
"96340ec8b80f44e9b345a706bdb5c9e3ab8a6474a5cb4e0d4645dbaecf1cf03d",
|
||||
"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
||||
uint64_t r[4];
|
||||
uint64_t a[4];
|
||||
uint64_t b[4];
|
||||
uint64_t c[4];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
|
||||
|
||||
sm2_z256_from_hex(r, tests[i].r);
|
||||
sm2_z256_from_hex(a, tests[i].a);
|
||||
if (tests[i].b) {
|
||||
sm2_z256_from_hex(b, tests[i].b);
|
||||
}
|
||||
|
||||
switch (tests[i].op) {
|
||||
case OP_ADD:
|
||||
sm2_z256_modn_add(c, a, b);
|
||||
break;
|
||||
case OP_SUB:
|
||||
sm2_z256_modn_sub(c, a, b);
|
||||
break;
|
||||
case OP_NEG:
|
||||
sm2_z256_modn_neg(c, a);
|
||||
break;
|
||||
case OP_MUL:
|
||||
sm2_z256_modn_to_mont(a, a);
|
||||
sm2_z256_modn_to_mont(b, b);
|
||||
sm2_z256_modn_mont_mul(c, a, b);
|
||||
sm2_z256_modn_from_mont(c, c);
|
||||
break;
|
||||
case OP_SQR:
|
||||
sm2_z256_modn_to_mont(a, a);
|
||||
sm2_z256_modn_mont_sqr(c, a);
|
||||
sm2_z256_modn_from_mont(c, c);
|
||||
break;
|
||||
case OP_EXP:
|
||||
sm2_z256_modn_to_mont(a, a);
|
||||
sm2_z256_modn_mont_exp(c, a, b);
|
||||
sm2_z256_modn_from_mont(c, c);
|
||||
break;
|
||||
case OP_INV:
|
||||
sm2_z256_modn_to_mont(a, a);
|
||||
sm2_z256_modn_mont_inv(c, a);
|
||||
sm2_z256_modn_from_mont(c, c);
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sm2_z256_cmp(r, c) != 0) {
|
||||
|
||||
fprintf(stderr, "%s: error\n", __FUNCTION__);
|
||||
fprintf(stderr, " %s\n", tests[i].label);
|
||||
sm2_z256_print(stderr, 0, 8, "err", c);
|
||||
fprintf(stderr, " ret: %s\n", tests[i].r);
|
||||
fprintf(stderr, " op1: %s\n", tests[i].a);
|
||||
if (tests[i].b) {
|
||||
fprintf(stderr, " op2: %s\n", tests[i].b);
|
||||
}
|
||||
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_sm2_z256_point_mul_generator(void)
|
||||
{
|
||||
struct {
|
||||
char *label;
|
||||
char *k;
|
||||
char *kG;
|
||||
} tests[] = {
|
||||
// k = 0
|
||||
{"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"},
|
||||
// k = 1
|
||||
{"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
|
||||
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"},
|
||||
// k = 2
|
||||
{"0000000000000000000000000000000000000000000000000000000000000002",
|
||||
"56CEFD60D7C87C000D58EF57FA73BA4D9C0DFA08C08A7331495C2E1DA3F2BD52"
|
||||
"31B7E7E6CC8189F668535CE0F8EAF1BD6DE84C182F6C8E716F780D3A970A23C3"},
|
||||
// k = 3
|
||||
{"0000000000000000000000000000000000000000000000000000000000000003",
|
||||
"A97F7CD4B3C993B4BE2DAA8CDB41E24CA13F6BD945302244E26918F1D0509EBF"
|
||||
"530B5DD88C688EF5CCC5CEC08A72150F7C400EE5CD045292AAACDD037458F6E6"},
|
||||
// k = 4
|
||||
{"0000000000000000000000000000000000000000000000000000000000000004",
|
||||
"C239507105C683242A81052FF641ED69009A084AD5CC937DB21646CD34A0CED5"
|
||||
"B1BF7EC4080F3C8735F1294AC0DB19686BEE2E96AB8C71FB7A253666CB66E009"},
|
||||
// k = 5
|
||||
{"0000000000000000000000000000000000000000000000000000000000000005",
|
||||
"C749061668652E26040E008FDD5EB77A344A417B7FCE19DBA575DA57CC372A9E"
|
||||
"F2DF5DB2D144E9454504C622B51CF38F5006206EB579FF7DA6976EFF5FBE6480"},
|
||||
// k = 6
|
||||
{"0000000000000000000000000000000000000000000000000000000000000006",
|
||||
"0927AFB57D93483BBB17C93E71F22A3105FF8856A66016892C8B1A1A3C4B0D30"
|
||||
"150C6B1AB4D1FC7EAC1C0EF6EBF2664581ADF1F0855A064DD572103000088F63"},
|
||||
// k = 7
|
||||
{"0000000000000000000000000000000000000000000000000000000000000007",
|
||||
"DDF092555409C19DFDBE86A75C139906A80198337744EE78CD27E384D9FCAF15"
|
||||
"847D18FFB38E87065CD6B6E9C12D2922037937707D6A49A2223B949657E52BC1"},
|
||||
{
|
||||
"[0]G",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
},
|
||||
{
|
||||
"[1]G",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
|
||||
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0",
|
||||
},
|
||||
{
|
||||
"[2]G",
|
||||
"0000000000000000000000000000000000000000000000000000000000000002",
|
||||
"56CEFD60D7C87C000D58EF57FA73BA4D9C0DFA08C08A7331495C2E1DA3F2BD52"
|
||||
"31B7E7E6CC8189F668535CE0F8EAF1BD6DE84C182F6C8E716F780D3A970A23C3",
|
||||
},
|
||||
{
|
||||
"[3]G",
|
||||
"0000000000000000000000000000000000000000000000000000000000000003",
|
||||
"A97F7CD4B3C993B4BE2DAA8CDB41E24CA13F6BD945302244E26918F1D0509EBF"
|
||||
"530B5DD88C688EF5CCC5CEC08A72150F7C400EE5CD045292AAACDD037458F6E6",
|
||||
},
|
||||
{
|
||||
"[4]G",
|
||||
"0000000000000000000000000000000000000000000000000000000000000004",
|
||||
"C239507105C683242A81052FF641ED69009A084AD5CC937DB21646CD34A0CED5"
|
||||
"B1BF7EC4080F3C8735F1294AC0DB19686BEE2E96AB8C71FB7A253666CB66E009",
|
||||
},
|
||||
{
|
||||
"[5]G",
|
||||
"0000000000000000000000000000000000000000000000000000000000000005",
|
||||
"C749061668652E26040E008FDD5EB77A344A417B7FCE19DBA575DA57CC372A9E"
|
||||
"F2DF5DB2D144E9454504C622B51CF38F5006206EB579FF7DA6976EFF5FBE6480",
|
||||
},
|
||||
{
|
||||
"[6]G",
|
||||
"0000000000000000000000000000000000000000000000000000000000000006",
|
||||
"0927AFB57D93483BBB17C93E71F22A3105FF8856A66016892C8B1A1A3C4B0D30"
|
||||
"150C6B1AB4D1FC7EAC1C0EF6EBF2664581ADF1F0855A064DD572103000088F63",
|
||||
},
|
||||
{
|
||||
"[7]G",
|
||||
"0000000000000000000000000000000000000000000000000000000000000007",
|
||||
"DDF092555409C19DFDBE86A75C139906A80198337744EE78CD27E384D9FCAF15"
|
||||
"847D18FFB38E87065CD6B6E9C12D2922037937707D6A49A2223B949657E52BC1",
|
||||
},
|
||||
// k = G.x
|
||||
{"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
|
||||
"782E1941B8A8C802543BC831E19F3548235C94A9C42AAD1EA8952CEAAECF12BA"
|
||||
"EEE0D9A6939E87F3B47A85863F873B324B9859136E2BF3235E17B3270164202D"},
|
||||
// k = G.y
|
||||
{"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0",
|
||||
"1000165E3FFF85F1DFFFB3AA1DF9F5E62B9A86A9A2927B4FF1AC16D19FEFF330"
|
||||
"3116F22B65320DD3B7F73DCF4A4028063A9BE6EFBD1DB0915C72F1EE067C5ECF"},
|
||||
// k = n - 1 = -1
|
||||
{"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54122",
|
||||
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
|
||||
"43C8C95C0B098863A642311C9496DEAC2F56788239D5B8C0FD20CD1ADEC60F5F"},
|
||||
// k = n = 0
|
||||
{"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"},
|
||||
// k = n + 1 = 1
|
||||
{"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54124",
|
||||
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
|
||||
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"},
|
||||
// k = 2^256 - 1
|
||||
{"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"B3217D884BC175E6BA6B360EB0E6D4396EAEA725C3D66E87BFA5BEB6C0D3456B"
|
||||
"A5199445C54B56602AA60025E1907BFD26B30E867DB6C58A034263AE4A2E27C2"},
|
||||
{
|
||||
"[x]G",
|
||||
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
|
||||
"782E1941B8A8C802543BC831E19F3548235C94A9C42AAD1EA8952CEAAECF12BA"
|
||||
"EEE0D9A6939E87F3B47A85863F873B324B9859136E2BF3235E17B3270164202D",
|
||||
},
|
||||
{
|
||||
"[y]G",
|
||||
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0",
|
||||
"1000165E3FFF85F1DFFFB3AA1DF9F5E62B9A86A9A2927B4FF1AC16D19FEFF330"
|
||||
"3116F22B65320DD3B7F73DCF4A4028063A9BE6EFBD1DB0915C72F1EE067C5ECF",
|
||||
},
|
||||
{
|
||||
"[n-1]G",
|
||||
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54122",
|
||||
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
|
||||
"43C8C95C0B098863A642311C9496DEAC2F56788239D5B8C0FD20CD1ADEC60F5F",
|
||||
},
|
||||
{
|
||||
"[n]G",
|
||||
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
},
|
||||
{
|
||||
"[n+1]G",
|
||||
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54124",
|
||||
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7"
|
||||
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0",
|
||||
},
|
||||
{
|
||||
"[2^256 - 1]G",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"B3217D884BC175E6BA6B360EB0E6D4396EAEA725C3D66E87BFA5BEB6C0D3456B"
|
||||
"A5199445C54B56602AA60025E1907BFD26B30E867DB6C58A034263AE4A2E27C2",
|
||||
},
|
||||
};
|
||||
|
||||
uint64_t k[4];
|
||||
@@ -97,6 +394,13 @@ static int test_sm2_z256_point_mul_generator(void)
|
||||
sm2_z256_point_to_bytes(&P, P_bytes);
|
||||
|
||||
if (memcmp(P_bytes, kG_bytes, 64) != 0) {
|
||||
|
||||
fprintf(stderr, "%s: error\n", __FUNCTION__);
|
||||
fprintf(stderr, " %s\n", tests[i].label);
|
||||
fprintf(stderr, " k: %s\n", tests[i].k);
|
||||
fprintf(stderr, " R: %s\n", tests[i].kG);
|
||||
format_bytes(stderr, 0, 4, "P", P_bytes, 64);
|
||||
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -108,62 +412,8 @@ static int test_sm2_z256_point_mul_generator(void)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/*
|
||||
SM2_POINT P;
|
||||
uint8_t k[32] = {0};
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
k[31] = i;
|
||||
|
||||
format_bytes(stderr, 0, 0, "k", k, 32);
|
||||
|
||||
sm2_point_mul_generator(&P, k);
|
||||
sm2_point_print(stdout, 0, 4, "kG", &P);
|
||||
}
|
||||
|
||||
size_t len;
|
||||
|
||||
char *xG = "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7";
|
||||
char *yG = "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0";
|
||||
|
||||
hex_to_bytes(xG, strlen(xG), k, &len);
|
||||
|
||||
sm2_point_mul_generator(&P, k);
|
||||
format_bytes(stderr, 0, 0, "k", k, 32);
|
||||
sm2_point_print(stdout, 0, 4, "kG", &P);
|
||||
|
||||
hex_to_bytes(yG, strlen(yG), k, &len);
|
||||
sm2_point_mul_generator(&P, k);
|
||||
format_bytes(stderr, 0, 0, "k", k, 32);
|
||||
sm2_point_print(stdout, 0, 4, "kG", &P);
|
||||
|
||||
char *n = "fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123";
|
||||
char *n_minus_one = "fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54122";
|
||||
char *n_plus_one = "fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54124";
|
||||
char *max256 = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
|
||||
|
||||
hex_to_bytes(n_minus_one, strlen(n_minus_one), k, &len);
|
||||
sm2_point_mul_generator(&P, k);
|
||||
format_bytes(stderr, 0, 0, "n-1", k, 32);
|
||||
sm2_point_print(stdout, 0, 4, "kG", &P);
|
||||
|
||||
hex_to_bytes(n, strlen(n), k, &len);
|
||||
sm2_point_mul_generator(&P, k);
|
||||
format_bytes(stderr, 0, 0, "n", k, 32);
|
||||
sm2_point_print(stdout, 0, 4, "kG", &P);
|
||||
|
||||
hex_to_bytes(n_plus_one, strlen(n_plus_one), k, &len);
|
||||
sm2_point_mul_generator(&P, k);
|
||||
format_bytes(stderr, 0, 0, "n+1", k, 32);
|
||||
sm2_point_print(stdout, 0, 4, "kG", &P);
|
||||
|
||||
hex_to_bytes(max256, strlen(max256), k, &len);
|
||||
sm2_point_mul_generator(&P, k);
|
||||
format_bytes(stderr, 0, 0, "n+1", k, 32);
|
||||
sm2_point_print(stdout, 0, 4, "kG", &P);
|
||||
|
||||
*/
|
||||
if (test_sm2_z256_modp() != 1) goto err;
|
||||
if (test_sm2_z256_modn() != 1) goto err;
|
||||
if (test_sm2_z256_point_mul_generator() != 1) goto err;
|
||||
printf("%s all tests passed\n", __FILE__);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user