Sorry for so long to reply, I tried to fork a branch in 
gitlab(https://git.lysator.liu.se/nettle/nettle) but failed, seemed that I 
don’t have enough permissions, or should I push my code in 
github(https://github.com/gnutls/nettle) ?
Here are the replies: 

>"zhongxuan (A)" <[email protected]> writes:
>
>> Anyway, I made a realization of SM2, Here is the first part of it, 
>> including the curve and sm2_add and sm2_mul in affine coordinate.
>
>Thanks, I'm having a first read, see comments below. It would be good to have 
>a link to the best english-language (and freely available) reference. I think 
>you have told me earlier, and I've found 
>https://datatracker.ietf.org/doc/html/draft-shen-sm2-ecdsa. It would be 
>helpful with a reference in a comment, e.g., at the top of ecc-sm2.c.

Insert a opensource link of this elliptic curve at the top of ecc-sm2.c

>
>> And if it's convenient to you, I can push the other parts including 
>> keygen, crypt and sign.
>
>I think it's a good first step to get basic scalar multiplication working, 
>i.e., ecc_point_mul and ecc_point_mul_g working and tested.

Thus this sm2 is also a 'a + 3 mod p = 0' elliptic curve, the mul_a and mul_g 
function of secp256r1 can also work.
We have tested the result with the geometric method like what in eccdata.c.

>
>For signatures, are they similar to ECDSA, or something different? For 
>encryption, how does that work?

Yes its similar to ECDSA, you can refer to this page:
https://datatracker.ietf.org/doc/html/draft-shen-sm2-ecdsa
Or there is an official public manual about this curve:
http://www.gmbz.org.cn/main/postDetail.html?id=20180724110812
I'm not sure whether could you access these pdfs.

>
>My initial comments on your patch inline below.
>
>Regards,
>/Niels
>
>> --- /dev/null
>> +++ b/ecc-sm2.c
>> @@ -0,0 +1,261 @@
>> +/* ecc-sm2.c
>> +
>> +   Compile time constant (but machine dependent) tables.
>
>Anything that is machine dependent should be in ecc-sm2.h, generated by 
>eccdata.

Removed.

>
>> +   Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights 
>> reserved.
>> +
>> +   This file is part of GNU Nettle.
>> +
>> +   GNU Nettle is free software: you can redistribute it and/or
>> +   modify it under the terms of either:
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or both in parallel, as here.
>> +
>> +   GNU Nettle is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see http://www.gnu.org/licenses/.
>> +*/
>> +
>> +/* Development of Nettle's ECC support was funded by the .SE 
>> +Internet Fund. */
>> +
>> +#if HAVE_CONFIG_H
>> +# include "config.h"
>> +#endif
>> +
>> +#include <string.h>
>> +#include <assert.h>
>> +
>> +#include "sm2.h"
>> +#include "sm2-internal.h"
>> +#include "ecc-internal.h"
>> +#include "ecc-sm2.h"
>> +#include "ecc-curve.h"
>> +
>> +const char *nettle_sm2_a =
>> +"fffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc";
>> +const char *nettle_sm2_xG =
>> +"32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7";
>> +const char *nettle_sm2_yG =
>> +"bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0";
>
>These strings appear unused.

Yep, this base point is unused, removed.
The nettle_sm2_a used to check whether a point is in sm2 curve, by checking y^2 
= x^3 + ax + b.

>
>> +static void
>> +ecc_sm2_inv (const struct ecc_modulo *p,
>> +                   mp_limb_t *rp, const mp_limb_t *ap,
>> +                   mp_limb_t *scratch) { #define a5m1 scratch 
>> +#define
>> +t0 (scratch + ECC_LIMB_SIZE) #define a15m1 t0 #define a32m1 a5m1 
>> +#define a62m1 (scratch + 2*ECC_LIMB_SIZE) #define a96m1 t0 #define 
>> +a3 (scratch + 3*ECC_LIMB_SIZE) #define tp (scratch + 
>> +4*ECC_LIMB_SIZE)
>> +/*
>> +   Addition chain for p - 2 = 2^{256} - 2^{224} + 2^{192} + 2^{96} -
>> +3
>> +
>> +    2^5 - 1 = 1 + 2 (2^4 - 1) = 1 + 2 (2^2+1)(2 + 1)    4 S + 3 M
>> +    2^{15} - 1 = (2^5 - 1) (1 + 2^5 (1 + 2^5)          10 S + 2 M
>> +    2^{16} - 1 = 1 + 2 (2^{15} - 1)                       S +   M
>> +    2^{32} - 1 = (2^{16} + 1) (2^{16} - 1)             16 S +   M
>> +
>> +    2^{31} - 1 = (2^{16} - 1) * 2^{15} + 2^{15} - 1
>> +    2^{62} - 1 = (2^{31} - 1) * 2^{31} + 2^{31} - 1
>> +    2^{94} - 1 = (2^{62} - 1) * 2^{32} + 2^{32} - 1
>> +    2^{96} - 1 = (2^{94} - 1) * 2^{2} + 3
>> +
>> +    2^{64} - 2^{32} - 1 = (2^{32} - 2) * 2^{32} + 2^{32} - 1
>> +    2^{160} - 2^{128} - 1 = (2^{64} - 2^{32} - 1) * 2^{96} + 2^{96} - 1
>> +    2^{254} - 2^{222} - 2^{94} + 2^{62} - 1 = (2^{160} - 2^{128} - 1) * 
>> 2^{94} + 2^{62} - 1
>> +    2^{256} - 2^{224} - 2^{96} + 2^{64} - 3 = (2^{254} - 2^{222} - 
>> + 2^{94} + 2^{62} - 1) * 2^{2} + 1
>> +
>> + */
>> +  ecc_mod_sqr (p, rp, ap, tp);                  /* a^2 */
>> +  ecc_mod_mul (p, a3, rp, ap, tp);              /* a^3 */
>> +  ecc_mod_pow_2kp1 (p, t0, a3, 2, tp);          /* a^{2^4 - 1} */
>> +  ecc_mod_sqr (p, rp, t0, tp);                  /* a^{2^5 - 2} */
>> +  ecc_mod_mul (p, a5m1, rp, ap, tp);            /* a^{2^5 - 1}, a5m1 */
>> +
>> +  ecc_mod_pow_2kp1 (p, rp, a5m1, 5, tp);        /* a^{2^{10} - 1, a5m1*/
>> +  ecc_mod_pow_2k_mul (p, a15m1, rp, 5, a5m1, tp); /* a^{2^{15} - 1}, a5m1 
>> a15m1 */
>> +  ecc_mod_sqr (p, rp, a15m1, tp);               /* a^{2^{16} - 2}, a15m1 */
>> +  ecc_mod_mul (p, rp, rp, ap, tp);              /* a^{2^{16} - 1}, a15m1 */
>> +  ecc_mod_pow_2kp1 (p, a32m1, rp, 16, tp);      /* a^{2^{32} - 1}, a15m1, 
>> a32m1 */
>> +  ecc_mod_pow_2k_mul (p, rp, rp, 15, a15m1, tp); /* a^{2^{31} - 1},
>> + a15m1 */
>> +
>> +  ecc_mod_pow_2kp1 (p, a62m1, rp, 31, tp); /* a^{2^{62} - 1}, a62m1 
>> + */  ecc_mod_pow_2k_mul (p, a96m1, a62m1, 32, a32m1, tp); /* 
>> + a^{2^{94} - 1}, a62m1, a32m1 */  ecc_mod_pow_2k_mul (p, a96m1, 
>> + a96m1, 2, a3, tp); /* a^{2^{96} - 1}, a96m1, a3 */
>> +
>> +  ecc_mod_sqr (p, rp, rp, tp);                  /* a^{2^{32} - 2} */
>> +  ecc_mod_pow_2k_mul (p, rp, rp, 32, a32m1, tp); /* a^{2^{64} - 
>> +2^{32} - 1 */
>> +  ecc_mod_pow_2k_mul (p, rp, rp, 96, a96m1, tp); /* a^{2^{160} - 
>> +2^{128} - 1 */
>> +  ecc_mod_pow_2k_mul (p, rp, rp, 94, a62m1, tp); /* a^{2^{254} - 
>> +2^{222} - 2^{94} + 2^{62} - 1}, a62m1 */
>> +  ecc_mod_pow_2k_mul (p, rp, rp, 2, ap, tp); /* a^{2^{256} - 2^{224}
>> +- 2^{96} + 2^{64} - 3} */ }
>> +
>> +void
>> +sm2_get_order (mpz_t order)
>> +{
>> +  if (!order->_mp_d)
>> +    return;
>> +  const struct ecc_curve *ecc = nettle_get_sm2();
>> +  mpz_set_n(order, ecc->q.m, ecc->q.size); }
>
>Why is the sm2_get_order needed? It appears unused in the current patch.

Yes, this is a test interface, removed.

>
>> +static mp_limb_t SM2_P[8] = {
>> +        0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
>> +        0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffe, };
>
>Is this for 32-bit limb size? On which platform have you tested the code? 
>Should probably use _nettle_sm2.p.m instead.

No, its still a 64-bit limb size, we use it in fast reduction, we will try to 
use a nettle interface instead.

>
>I'm a bit confused, because this looks like 32-bit limbs, but elsewhere you 
>shift by 32 bits which isn't valid for this limb size.
>
>> +static int sm2_bn_cmp(const mp_limb_t *a, const mp_limb_t *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;
>> +}
>
>This will not be side-channel silent.

Seems that we can use mpn_cmp instead, though I don’t get the difference 
between mpn_cmp and this sm2_bn_cmp, is mpn_cmp also not side-channel silent?

>
>> +static void sm2_bn_sub(mp_limb_t *ret, const mp_limb_t *a, const 
>> +mp_limb_t *b) {
>> +        int i;
>> +        mp_limb_t r[8];
>> +        r[0] = ((uint64_t)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;
>> +        memcpy(ret, r, 64);
>> +}
>
>Is there some reason the general ecc_mod_sub can't work work?

Seems that it can't work.
We use a fast reduction matrix, splitting a 64 bits limb into two 32 bits limbs.
I also tried mpn_sub_n but seems it doesn’t work too.
I am trying to optimize the calculation or use ecc_mod here instead.
>
>> +static void
>> +ecc_sm2_modp (const struct ecc_modulo *p, mp_limb_t *rp, mp_limb_t
>> +*xp) {
>> +  uint64_t s[16] = {0};
>> +  uint64_t d[8] = {0};
>> +  uint64_t r[8] = {0};
>> +
>> +  for (int i  = 0; i < 8; i++) {
>> +    s[2*i] = xp[i] & 0xffffffff;
>> +    s[2*i+1] = xp[i] >> 32;
>> +  }
>> +
>> +  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 (int 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);
>> +  }
>> +
>> +  rp[0] = (r[0] & 0xffffffff) + ((r[1] & 0xffffffff) << 32);  rp[1] 
>> + = (r[2] & 0xffffffff) + ((r[3] & 0xffffffff) << 32);  rp[2] = (r[4] 
>> + & 0xffffffff) + ((r[5] & 0xffffffff) << 32);  rp[3] = (r[6] & 
>> + 0xffffffff) + ((r[7] & 0xffffffff) << 32); }
>
>I would suggest starting with the general ecc_mod function (I think it should 
>work for the modulo used with sm2). When that is in place, one can add 
>optimized variants for 32-bit and/or 64-bit limbs to speed that up.

Here is a problem, ecc_mod stop in ' assert (bn < mn); ' in ecc-mod.c line 56, 
is sm2 different from other weierstrass curves or I made some mistakes?
To avoid this I still use ecc_sm2_modp but change the cmp functions with mpn 
functions.

>
>> +const struct ecc_curve _nettle_sm2 = {
>> +  {
>> +    256,
>> +    ECC_LIMB_SIZE,
>> +    ECC_BMODP_SIZE,
>> +    ECC_REDC_SIZE,
>> +    4 * ECC_LIMB_SIZE,
>> +    4 * ECC_LIMB_SIZE,
>> +    0,
>> +
>> +    ecc_p,
>> +    ecc_Bmodp,
>> +    ecc_Bmodp_shifted,
>> +    ecc_redc_ppm1,
>> +    ecc_pp1h,
>> +
>> +    NULL,
>> +    ecc_sm2_modp,
>> +    ecc_sm2_inv,
>> +    NULL,
>> +    NULL,
>> +  },
>> +  {
>> +    256,
>> +    ECC_LIMB_SIZE,
>> +    ECC_BMODQ_SIZE,
>> +    0,
>> +    ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
>> +    0,
>> +    0,
>> +
>> +    ecc_q,
>> +    ecc_Bmodq,
>> +    ecc_Bmodq_shifted,
>> +    NULL,
>> +    ecc_qp1h,
>> +
>> +    NULL,
>> +    NULL,
>> +    ecc_mod_inv,
>> +    NULL,
>> +    NULL,
>> +  },
>> +
>> +  ECC_REDC_SIZE == 0,
>> +  ECC_PIPPENGER_K,
>> +  ECC_PIPPENGER_C,
>> +
>> +  ECC_ADD_JJA_ITCH (ECC_LIMB_SIZE),
>> +  ECC_ADD_JJJ_ITCH (ECC_LIMB_SIZE),
>> +  ECC_DUP_JJ_ITCH (ECC_LIMB_SIZE),
>> +  ECC_MUL_A_ITCH (ECC_LIMB_SIZE),
>> +  ECC_MUL_G_ITCH (ECC_LIMB_SIZE),
>> +  ECC_J_TO_A_ITCH(ECC_LIMB_SIZE, 4 * ECC_LIMB_SIZE),
>> +
>> +  ecc_add_jja,
>> +  ecc_add_jjj,
>> +  ecc_dup_jj,
>
>I had expected pointers to new add and dup functions here, since existing 
>functions assume a = -3.

Thus this sm2's p = 2^256 - x^224 - 2^96 + 2^64 - 1, which is also a 'a + 3 mod 
p = 0' elliptic curve, the add_jja, add_jjj, dup_jj  can also work.
We proved it by comparing with geometric method.

>
>> +  ecc_mul_a,
>> +  ecc_mul_g,
>> +  ecc_j_to_a,
>> +
>> +  ecc_b,
>> +  ecc_unit,
>> +  ecc_table
>> +};
>> +
>> +const struct ecc_curve *nettle_get_sm2(void) {
>> +  return &_nettle_sm2;
>> +}
>> diff --git a/eccdata.c b/eccdata.c
>> index 4d8827f..71a524d 100644
>> --- a/eccdata.c
>> +++ b/eccdata.c
>> @@ -44,6 +44,9 @@
>>  
>>  /* Affine coordinates, for simplicity. Infinity point, i.e., te
>>     neutral group element, is represented using the is_zero flag. */
>> +
>> +const char *nettle_sm2_a =
>> +"fffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc";
>
>Do I get it right that sm2 uses a weierstrass curve, but with a different a 
>value than the a = -3 used for the other weierstrass curves?
>For the eccdata program, I would suggest adding the a constant to the struct 
>ecc_curve, and use the same formulas for all the weierstrass curves. E.g, add 
>an argument to ecc_curve_init_str to set a, and let NULL mean the default of 
>-3.

Now we add param a in eccdata first.
Besides, I let NULL in EDWARDS curve, which means also -3 although EDWARDS 
don’t have a param a, would it be fine?
Did some changes to ecc_dup to use same formulas in all weierstrass curves. 

>
>>  struct ecc_point
>>  {
>>    int is_zero;
>> @@ -59,6 +62,8 @@ enum ecc_type
>>      ECC_TYPE_EDWARDS,
>>      /* -x^2 + y^2 = 1 - d x^2 y^2 */
>>      ECC_TYPE_TWISTED_EDWARDS,
>> +    /* y^2 = x^3 + ax + b (mod p) */
>> +    ECC_TYPE_SM2,
>>    };
>>  
>>  struct ecc_curve
>> @@ -145,64 +150,111 @@ static void
>>  ecc_dup (const struct ecc_curve *ecc,
>>       struct ecc_point *r, const struct ecc_point *p)  {
>> -  if (ecc->type != ECC_TYPE_WEIERSTRASS)
>> -    {
>> -      ecc_add (ecc, r, p, p);
>> -      return;
>> -    }
>> +  if (ecc->type != ECC_TYPE_WEIERSTRASS && ecc->type != 
>> + ECC_TYPE_SM2) {
>> +    ecc_add (ecc, r, p, p);
>> +    return;
>> +  }
>>    if (ecc_zero_p (p))
>>      ecc_set_zero (ecc, r);
>>  
>> +  else if (ecc->type == ECC_TYPE_SM2)  {
>> +    mpz_t m, t, x, y, a;
>> +
>> +    mpz_init (m);
>> +    mpz_init (t);
>> +    mpz_init (x);
>> +    mpz_init (y);
>> +    mpz_init_set_str(a, nettle_sm2_a, 16);
>> +
>> +    /* m = (2 y)^-1 */
>> +    mpz_mul_ui (m, p->y, 2);
>> +    mpz_invert (m, m, ecc->p);
>> +
>> +    /* t = 3x^2 + a */
>> +    mpz_mul (t, p->x, p->x);
>> +    mpz_mod (t, t, ecc->p);
>> +    mpz_mul_ui (t, t, 3);
>> +    mpz_mod (t, t, ecc->p);
>> +    mpz_add(t, t, a);
>> +    mpz_mod (t, t, ecc->p);
>> +
>> +    /* t = t * m */
>> +    mpz_mul (t, t, m);
>> +    mpz_mod (t, t, ecc->p);
>> +
>> +    /* x' = t^2 - 2 x */
>> +    mpz_mul (x, t, t);
>> +    mpz_submul_ui (x, p->x, 2);
>> +
>> +    mpz_mod (x, x, ecc->p);
>> +
>> +    /* y' = (x - x') * t - y */
>> +    mpz_sub (y, p->x, x);
>> +    mpz_mul (y, y, t);
>> +    mpz_sub (y, y, p->y);
>> +    mpz_mod (y, y, ecc->p);
>> +
>> +    r->is_zero = 0;
>> +    mpz_swap (x, r->x);
>> +    mpz_swap (y, r->y);
>> +
>> +    mpz_clear (m);
>> +    mpz_clear (t);
>> +    mpz_clear (x);
>> +    mpz_clear (y);
>> +  }
>>    else
>> -    {
>> -      mpz_t m, t, x, y;
>> -
>> -      mpz_init (m);
>> -      mpz_init (t);
>> -      mpz_init (x);
>> -      mpz_init (y);
>> -
>> -      /* m = (2 y)^-1 */
>> -      mpz_mul_ui (m, p->y, 2);
>> -      mpz_invert (m, m, ecc->p);
>> -
>> -      /* t = 3 (x^2 - 1) * m */
>> -      mpz_mul (t, p->x, p->x);
>> -      mpz_mod (t, t, ecc->p);
>> -      mpz_sub_ui (t, t, 1);
>> -      mpz_mul_ui (t, t, 3);
>> -
>> -      mpz_mul (t, t, m);
>> -      mpz_mod (t, t, ecc->p);
>> -
>> -      /* x' = t^2 - 2 x */
>> -      mpz_mul (x, t, t);
>> -      mpz_submul_ui (x, p->x, 2);
>> -
>> -      mpz_mod (x, x, ecc->p);
>> -
>> -      /* y' = (x - x') * t - y */
>> -      mpz_sub (y, p->x, x);
>> -      mpz_mul (y, y, t);
>> -      mpz_sub (y, y, p->y);
>> -      mpz_mod (y, y, ecc->p);
>> -
>> -      r->is_zero = 0;
>> -      mpz_swap (x, r->x);
>> -      mpz_swap (y, r->y);
>> -
>> -      mpz_clear (m);
>> -      mpz_clear (t);
>> -      mpz_clear (x);
>> -      mpz_clear (y);
>> -    }
>> +  {
>> +    mpz_t m, t, x, y;
>> +
>> +    mpz_init (m);
>> +    mpz_init (t);
>> +    mpz_init (x);
>> +    mpz_init (y);
>> +
>> +    /* m = (2 y)^-1 */
>> +    mpz_mul_ui (m, p->y, 2);
>> +    mpz_invert (m, m, ecc->p);
>> +
>> +    /* t = 3 (x^2 - 1) * m */
>> +    mpz_mul (t, p->x, p->x);
>> +    mpz_mod (t, t, ecc->p);
>> +    mpz_sub_ui (t, t, 1);
>> +    mpz_mul_ui (t, t, 3);
>> +
>> +    mpz_mul (t, t, m);
>> +    mpz_mod (t, t, ecc->p);
>> +
>> +    /* x' = t^2 - 2 x */
>> +    mpz_mul (x, t, t);
>> +    mpz_submul_ui (x, p->x, 2);
>> +
>> +    mpz_mod (x, x, ecc->p);
>> +
>> +    /* y' = (x - x') * t - y */
>> +    mpz_sub (y, p->x, x);
>> +    mpz_mul (y, y, t);
>> +    mpz_sub (y, y, p->y);
>> +    mpz_mod (y, y, ecc->p);
>> +
>> +    r->is_zero = 0;
>> +    mpz_swap (x, r->x);
>> +    mpz_swap (y, r->y);
>> +
>> +    mpz_clear (m);
>> +    mpz_clear (t);
>> +    mpz_clear (x);
>> +    mpz_clear (y);
>> +  }
>>  }
>>  
>>  static void
>>  ecc_add (const struct ecc_curve *ecc, struct ecc_point *r,
>>       const struct ecc_point *p, const struct ecc_point *q)  {
>> -  if (ecc->type == ECC_TYPE_WEIERSTRASS)
>> +  if (ecc->type == ECC_TYPE_WEIERSTRASS || ecc->type == 
>> + ECC_TYPE_SM2)
>>      {
>>        if (ecc_zero_p (p))
>>      ecc_set (r, q);
>> @@ -760,6 +812,25 @@ ecc_curve_init (struct ecc_curve *ecc, const char 
>> *curve)
>>                 "c0d8f97ea1ca9472b5d444285d0d4f5b"
>>                 "32e236f86de51839");
>>      }
>> +  else if (!strcmp (curve, "sm2"))
>> +  {
>> +      ecc_curve_init_str (ecc, ECC_TYPE_SM2,
>> +               /* p */
>> +               "fffffffeffffffffffffffffffffffff"
>> +               "ffffffff00000000ffffffffffffffff",
>> +               /* b */
>> +               "28e9fa9e9d9f5e344d5a9e4bcf6509a7"
>> +               "f39789f515ab8f92ddbcbd414d940e93",
>> +               /* q (order) */
>> +               "fffffffeffffffffffffffffffffffff"
>> +               "7203df6b21c6052b53bbf40939d54123",
>> +               /* g_x */
>> +               "32c4ae2c1f1981195f9904466a39c994"
>> +               "8fe30bbff2660be1715a4589334c74c7",
>> +               /* g_y */
>> +               "bc3736a2f4f6779c59bdcee36b692153"
>> +               "d0a9877cc62a474002df32e52139f0a0");
>> +  }
>>    else
>>      {
>>        fprintf (stderr, "No known curve with name %s\n", curve); diff 
>> --git a/sm2-add.c b/sm2-add.c new file mode 100644 index 
>> 0000000..f32676c
>> --- /dev/null
>> +++ b/sm2-add.c
>> @@ -0,0 +1,67 @@
>> +/* sm2-mul.c
>> +
>> +   Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights 
>> reserved.
>> +
>> +   This file is part of GNU Nettle.
>> +
>> +   GNU Nettle is free software: you can redistribute it and/or
>> +   modify it under the terms of either:
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or both in parallel, as here.
>> +
>> +   GNU Nettle is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see http://www.gnu.org/licenses/.
>> +*/
>> +
>> +#if HAVE_CONFIG_H
>> +# include "config.h"
>> +#endif
>> +
>> +#include <string.h>
>> +
>> +#include "ecc.h"
>> +#include "ecc-internal.h"
>> +
>> +#include "sm2.h"
>> +#include "sm2-internal.h"
>> +
>> +int
>> +sm2_add (struct ecc_point *r, const struct ecc_point *p,
>> +         const struct ecc_point *q)
>
>What's the usecase for this function? If it is needed, it might be better with 
>a general ecc_point_add.

Its just an encapsulation, we will remove it.

>
>> +{
>> +  const struct ecc_curve *ecc = p->ecc;
>> +  if (!sm2_check_point(p) || !sm2_check_point(q)) {
>> +    return 0;
>> +  }
>> +
>> +  mp_size_t itch = 3*SM2_LIMB_SIZE + ecc->mul_itch;  mp_limb_t 
>> + *scratch = gmp_alloc_limbs (itch);  mp_limb_t *pj = xalloc_limbs 
>> + (3*ecc->p.size);  mp_limb_t *qj = xalloc_limbs (3*ecc->p.size); 
>> + ecc_a_to_j (ecc, pj, p->p);  ecc_a_to_j (ecc, qj, q->p);
>> +
>> +  ecc->add_hhh(p->ecc, scratch, pj, qj, scratch + 3*SM2_LIMB_SIZE);
>> + ecc->h_to_a (ecc, 0, r->p, scratch, scratch + 3*SM2_LIMB_SIZE);
>> +
>> +  gmp_free_limbs (scratch, itch);
>> +  free(pj);
>> +  free(qj);
>> +  return 1;
>> +}
>> diff --git a/sm2-internal.h b/sm2-internal.h new file mode 100644 
>> index 0000000..adcc379
>> --- /dev/null
>> +++ b/sm2-internal.h
>> @@ -0,0 +1,69 @@
>> +/* sm2-internal.h
>> +
>> +   Things that are used only by the testsuite and benchmark, and
>> +   not included in the library.
>
>Is that right? The file is included by library files, e.g., ecc-sm2.c.

That’s not accurate, removed this.

>
>> +   Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights 
>> reserved.
>> +
>> +   This file is part of GNU Nettle.
>> +
>> +   GNU Nettle is free software: you can redistribute it and/or
>> +   modify it under the terms of either:
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or both in parallel, as here.
>> +
>> +   GNU Nettle is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see http://www.gnu.org/licenses/.
>> +*/
>> +
>> +#ifndef SM2_INTERNAL_H_INCLUDED
>> +#define SM2_INTERNAL_H_INCLUDED
>> +
>> +#include <assert.h>
>> +
>> +#include "nettle-meta.h"
>> +
>> +#include "sm2.h"
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +#define xalloc nettle_xalloc
>> +#define xalloc_limbs nettle_xalloc_limbs
>> +
>> +#define SM2_LIMB_SIZE 4
>> +#define SM2_LIMB_BYTES 8
>> +
>> +#define IS_ILLEG_KEY(key) \
>> +    (!(key)) || (((key)->ecc) != &_nettle_sm2) || !((key)->p)
>> +
>> +extern const char *nettle_sm2_a;
>> +extern const char *nettle_sm2_xG;
>> +extern const char *nettle_sm2_yG;
>> +
>> +void *xalloc(size_t size);
>> +
>> +mp_limb_t *xalloc_limbs(mp_size_t n);
>
>Much of this looks questionable to me. SM2_LIMB_BYTES and SM2_LIMB_SIZE are 
>machine dependent. Using corresponding elements of struct ecc_curve would be 
>better than the nettle_sm2_a, nettle_sm2_xG and nettle_sm2_yG strings. (If 
>there's no good place in the current struct ecc_curve to store the a constant, 
>that should be added).

Yep, this should be changed.
ALL macros machine dependent moved, I tried add para a in ecc_curve.
Here is a problem, in the point check of ecc_point_set and 
test_ecc_point_valid_p

>
>And xalloc functions are already defined for the testsuite and benchmark.

Removed.

>
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif /* NETTLE_INTERNAL_H_INCLUDED */
>> diff --git a/sm2-lib.c b/sm2-lib.c
>> new file mode 100644
>> index 0000000..0fefb20
>> --- /dev/null
>> +++ b/sm2-lib.c
>> @@ -0,0 +1,63 @@
>> +/* sm2-lib.c
>> +
>> +   Things that are used only by the testsuite and benchmark, and
>> +   not included in the library.
>
>I'd prefer to not have this file. In particular, it's confusing with "lib" in 
>the name when it's not part of the library.

The description is not accurate, file removed.

>
>> +   Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights 
>> reserved.
>> +
>> +   This file is part of GNU Nettle.
>> +
>> +   GNU Nettle is free software: you can redistribute it and/or
>> +   modify it under the terms of either:
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or both in parallel, as here.
>> +
>> +   GNU Nettle is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see http://www.gnu.org/licenses/.
>> +*/
>> +
>> +#if HAVE_CONFIG_H
>> +# include "config.h"
>> +#endif
>> +
>> +#include <assert.h>
>> +#include <stdlib.h>
>> +#include <stdio.h>
>> +#include <string.h>
>> +
>> +#include "sm2-internal.h"
>> +#include "ecc-internal.h"
>> +
>> +void *
>> +xalloc(size_t size)
>> +{
>> +  void *p = malloc(size);
>> +  if (size && !p) {
>> +      fprintf(stderr, "Virtual memory exhausted.\n");
>> +      abort();
>> +    }
>> +
>> +  return p;
>> +}
>> +
>> +mp_limb_t *
>> +xalloc_limbs (mp_size_t n)
>> +{
>> +  return xalloc (n * sizeof (mp_limb_t)); }
>> diff --git a/sm2-mul.c b/sm2-mul.c
>> new file mode 100644
>> index 0000000..f65d196
>> --- /dev/null
>> +++ b/sm2-mul.c
>> @@ -0,0 +1,64 @@
>> +/* sm2-mul.c
>> +
>> +   Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights 
>> reserved.
>> +
>> +   This file is part of GNU Nettle.
>> +
>> +   GNU Nettle is free software: you can redistribute it and/or
>> +   modify it under the terms of either:
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or both in parallel, as here.
>> +
>> +   GNU Nettle is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see http://www.gnu.org/licenses/.
>> +*/
>> +
>> +#if HAVE_CONFIG_H
>> +# include "config.h"
>> +#endif
>> +
>> +#include <string.h>
>> +
>> +#include "ecc.h"
>> +#include "ecc-internal.h"
>> +
>> +#include "sm2.h"
>> +#include "sm2-internal.h"
>> +
>> +int
>> +sm2_mul (struct ecc_point *q, const struct ecc_scalar *n,
>> +         const struct ecc_point *p)
>> +{
>> +  const struct ecc_curve *ecc = p->ecc;
>> +  if (!sm2_check_point(p)) {
>> +    return 0;
>> +  }
>> +  mp_size_t itch = 3*SM2_LIMB_SIZE + p->ecc->mul_itch;
>> +  mp_limb_t *scratch = gmp_alloc_limbs (itch);
>> +
>> +  mp_limb_t *pj = xalloc_limbs (3*SM2_LIMB_SIZE);  ecc_a_to_j 
>> + (p->ecc, pj, p->p);
>> +
>> +  p->ecc->mul(p->ecc, scratch, n->p, pj, scratch + 3*SM2_LIMB_SIZE);
>> + p->ecc->h_to_a (p->ecc, 0, q->p, scratch, scratch +
>> + 3*SM2_LIMB_SIZE);
>> +
>> +  gmp_free_limbs (scratch, itch);
>> +  free(pj);
>> +  return 1;
>> +}
>
>I think the general ecc_point_mul (and other ecc_point_* functions) should be 
>used also for sm2. The validation done by sm2_check_point should go in 
>ecc_point_set (currently, handling various curves in that function is a bit 
>messy handling, it would make sense to add a function pointer in ecc_curve for 
>doing the point validation.

These encapsulations are removed.
Add an ecc_point_check function from ecc_point_set, I wonder is there necessary 
to add a function pointer in ecc_curve?

>
>> diff --git a/sm2-point.c b/sm2-point.c new file mode 100644 index
>> 0000000..0146692
>> --- /dev/null
>> +++ b/sm2-point.c
>> @@ -0,0 +1,105 @@
>> +/* sm2-point.c
>> +
>> +   Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights 
>> reserved.
>> +
>> +   This file is part of GNU Nettle.
>> +
>> +   GNU Nettle is free software: you can redistribute it and/or
>> +   modify it under the terms of either:
>> +
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or
>> +
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at your
>> +       option) any later version.
>> +
>> +   or both in parallel, as here.
>> +
>> +   GNU Nettle is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see http://www.gnu.org/licenses/.
>> +*/
>> +
>> +#if HAVE_CONFIG_H
>> +# include "config.h"
>> +#endif
>> +
>> +#include <stdio.h>
>> +#include <string.h>
>> +#include <stdlib.h>
>> +
>> +#include "ecc.h"
>> +#include "ecc-internal.h"
>> +
>> +#include "sm2.h"
>> +#include "sm2-internal.h"
>> +
>> +int
>> +sm2_check_point(const struct ecc_point *point) {
>> +  mpz_t t, x, y, a;
>> +  mpz_t lhs, rhs;
>> +  int res;
>> +  mp_size_t size;
>> +
>> +  if (IS_ILLEG_KEY(point) != 0)
>> +    return 0;
>> + 
>> +  size = point->ecc->p.size;
>> +
>> +  /* First check range */
>> +  if (mpn_cmp (point->p, point->ecc->p.m, size) >= 0
>> +      || mpn_cmp (point->p + size, point->ecc->p.m, size) >= 0)
>> +    return 0;
>> + 
>> +  mpz_init (lhs);
>> +  mpz_init (rhs);
>> + 
>> +  mpz_init_set_str(a, nettle_sm2_a, 16);  mpz_roinit_n (x, point->p, 
>> + size);  mpz_roinit_n (y, point->p + size, size);
>> + 
>> +  mpz_mul (lhs, y, y);
>> +  
>> +  /* Check y^2 = x^3 + ax + b */
>> +  mpz_mul (rhs, x, x);
>> +  mpz_add (rhs, rhs, a);
>> +  mpz_mul (rhs, rhs, x);
>> +  mpz_add (rhs, rhs, mpz_roinit_n (t, point->ecc->b, size));
>> +      
>> +  res = mpz_congruent_p (lhs, rhs, mpz_roinit_n (t, point->ecc->p.m, 
>> + size));
>> +  
>> +  mpz_clear (lhs);
>> +  mpz_clear (rhs);
>> +  mpz_clear (a);
>> + 
>> +  return res;
>> +}
>> +
>> +int
>> +sm2_point_set (struct ecc_point *p, const mpz_t x, const mpz_t y) {
>> +  if (p == NULL || p->p == NULL || x == NULL || y == NULL)
>> +    return 0;
>> +
>> +  p->ecc = &_nettle_sm2;
>> +  mp_size_t size = p->ecc->p.size;
>> +
>> +  mpz_limbs_copy (p->p, x, size);
>> +  mpz_limbs_copy (p->p + size, y, size);
>> +
>> +  if (!sm2_check_point(p)) {
>> +    return 0;
>> +  }
>> +
>> +  return 1;
>> +}
>> diff --git a/sm2.h b/sm2.h
>> new file mode 100644
>> index 0000000..1443b68
>> --- /dev/null
>> +++ b/sm2.h
>> @@ -0,0 +1,65 @@
>> +/* sm2.h
>> +   Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights 
>> reserved.
>> +   This file is part of GNU Nettle.
>> +   GNU Nettle is free software: you can redistribute it and/or
>> +   modify it under the terms of either:
>> +     * the GNU Lesser General Public License as published by the Free
>> +       Software Foundation; either version 3 of the License, or (at your
>> +       option) any later version.
>> +   or
>> +     * the GNU General Public License as published by the Free
>> +       Software Foundation; either version 2 of the License, or (at your
>> +       option) any later version.
>> +   or both in parallel, as here.
>> +   GNU Nettle is distributed in the hope that it will be useful,
>> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +   General Public License for more details.
>> +   You should have received copies of the GNU General Public License and
>> +   the GNU Lesser General Public License along with this program.  If
>> +   not, see http://www.gnu.org/licenses/.
>> +*/
>> +
>> +#ifndef NETTLE_SM2_H_INCLUDED
>> +#define NETTLE_SM2_H_INCLUDED
>> +
>> +#include "nettle-types.h"
>> +#include "nettle-meta.h"
>> +
>> +#include "ecc.h"
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +#define sm2_get_order nettle_sm2_get_order #define sm2_check_point 
>> +nettle_sm2_check_point #define sm2_point_set nettle_sm2_point_set 
>> +#define sm2_add nettle_sm2_add #define sm2_mul nettle_sm2_mul
>> +
>> +void
>> +sm2_get_order(mpz_t order);
>> +
>> +int
>> +sm2_check_point(const struct ecc_point *point);
>> +
>> +int
>> +sm2_point_set (struct ecc_point *p, const mpz_t x, const mpz_t y);
>> +
>> +int
>> +sm2_add (struct ecc_point *r, const struct ecc_point *p,
>> +         const struct ecc_point *q);
>> +
>> +int
>> +sm2_mul (struct ecc_point *q, const struct ecc_scalar *n,
>> +         const struct ecc_point *p);
>
>There are no curve-specific public functions like this for any of the other 
>curves, so it would be nice if we could eliminate them and just use the 
>ecc_point_* functions.

Sure. 

>
>> +const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE 
>> +nettle_get_sm2(void);
>
>I think this declaration belongs in ecc_curve.h.

Moved.

>
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif /* NETTLE_SM2_H_INCLUDED */
>> +
>> diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index
>> c266282..6bda2b7 100644
>> --- a/testsuite/Makefile.in
>> +++ b/testsuite/Makefile.in
>> @@ -56,7 +56,8 @@ TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
>>                   eddsa-compress-test.c eddsa-sign-test.c \
>>                   eddsa-verify-test.c ed25519-test.c ed448-test.c \
>>                   gostdsa-sign-test.c gostdsa-verify-test.c \
>> -                 gostdsa-keygen-test.c gostdsa-vko-test.c
>> +                 gostdsa-keygen-test.c gostdsa-vko-test.c \
>> +                 sm2-base-test.c \
>>  
>>  TS_SOURCES = $(TS_NETTLE_SOURCES) $(TS_HOGWEED_SOURCES)  CXX_SOURCES 
>> = cxx-test.cxx diff --git a/testsuite/sm2-base-test.c 
>> b/testsuite/sm2-base-test.c new file mode 100644 index
>> 0000000..be03970
>> --- /dev/null
>> +++ b/testsuite/sm2-base-test.c
>> @@ -0,0 +1,161 @@
>> +#include "testutils.h"
>> +
>> +char *order =
>> +"fffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123";
>
>If you add sm2 to the list ecc_curves in testutils.c, existing ecc tests will 
>test sm2 as well. You will need to also update the test_ecc_point_valid_p 
>function and the ecc_ref list in the same file.

Already added, seemed the ecc_mod is not compatible with sm2, I'm trying to 
figured out.

>
>> +char *pkey =
>> +"81a2088f008d0e28dd4add66041cf1050cbaf053ab48f4284eb701152be5c310";
>> +char *xG =
>> +"8ffdbc04ac27f21a41c878e171294962150fa9b3dece424d41abfa869260bbf0";
>> +char *yG =
>> +"a6648a20e162a7ac07597f199d722ff965cfdfab1744aed669565b11bcf15cfe";
>> +char *xR =
>> +"3e5641b3e68eb47e6fae1271057e1ea0faedbb49df0d690722eaca6e45f5a76c";
>> +char *yR =
>> +"d0b0bf0d16a1e4dbc814a6e7b53c07a84997660b7ed0fa0cdeb93bf12000cdf6";
>> +
>> +char *Px =
>> +"8070905f2cf1118ec1d41a0d07dd8dd4ac663bdbe4ad85df101d0baa875d4699";
>> +char *Py =
>> +"5a947c2c3b2a4bf6113e4e609190209b64f672ddca99b6a7dbf55e2fbf7019a3";
>> +char *Qx =
>> +"3dd60d9474b46d903f3daf7f532eb9e81a5ea97e2676dfca39493a218a223feb";
>> +char *Qy =
>> +"dd8fe0b3cf91c793d1df27a30f707d5d46b170478e210de110f6954749b40994";
>> +char *Rx =
>> +"df86af4b5b7830ac4d6730e93bc3a4dd67e303c3e2824eb76dc61b26e2884f7f";
>> +char *Ry =
>> +"23d8e385c6f7aea20d38df11de924427b3cea394e648e4b19b4ba086addc490a";
>> +
>> +char *gx =
>> +"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7";
>> +char *gy =
>> +"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0";
>> +
>> +void sm2_point_print (struct ecc_point *p); void test_get_order 
>> +(void); void test_add (void); void test_mul (void);
>> +
>> +void
>> +sm2_point_print (struct ecc_point *p) {
>> +  char str[1024];
>> +  mpz_t x, y;
>> +  mpz_init (x);
>> +  mpz_init (y);
>> +  ecc_point_get(p, x, y);
>> +  mpz_get_str(str, 16, x);
>> +  printf("Px : %s\n", str);
>> +  mpz_get_str(str, 16, y);
>> +  printf("Py : %s\n", str);
>> +  mpz_clear(x);
>> +  mpz_clear(y);
>> +}
>> +
>> +void
>> +test_get_order (void)
>> +{
>> +  int ret = 0;
>> +  mpz_t r, R;
>> +
>> +  mpz_init(r);
>> +  mpz_init_set_str(R, order, 16);
>> +
>> +  sm2_get_order(r);
>> +
>> +  ret = mpz_cmp(r, R);
>> +  ASSERT(ret == 0);
>> +
>> +  mpz_clear(r);
>> +  mpz_clear(R);
>> +}
>> +
>> +void
>> +test_get_order_NULL (void)
>> +{
>> +  mpz_t r;
>> +
>> +  mpz_init(r);
>> +
>> +  r->_mp_d = NULL;
>> +  sm2_get_order(r);
>> +
>> +  mpz_clear(r);
>> +}
>> +
>> +void
>> +test_add (void)
>> +{
>> +  int ret = 0;
>> +  const struct ecc_curve *ecc = nettle_get_sm2();
>> +  struct ecc_point pointp, pointq, Res;
>> +  mpz_t x, y;
>> +
>> +  ecc_point_init (&pointp, ecc);
>> +  ecc_point_init (&pointq, ecc);
>> +  ecc_point_init (&Res, ecc);
>> +  mpz_init (x);
>> +  mpz_init (y);
>> +  mpz_set_str(x, Px, 16);
>> +  mpz_set_str(y, Py, 16);
>> +  sm2_point_set(&pointp, x, y);
>> +  mpz_set_str(x, Qx, 16);
>> +  mpz_set_str(y, Qy, 16);
>> +  sm2_point_set(&pointq, x, y);
>> +
>> +  sm2_add(&Res, &pointp, &pointq);
>> +
>> +  if (verbose)
>> +    sm2_point_print (&Res);
>> +
>> +  mpz_set_str(x, Rx, 16);
>> +  mpz_set_str(y, Ry, 16);
>> +  sm2_point_set(&pointq, x, y);
>> +
>> +  ret = mpn_cmp(Res.p, pointq.p, SM2_LIMB_BYTES);  ASSERT(ret == 0);
>> +
>> +  ecc_point_clear(&pointp);
>> +  ecc_point_clear(&pointq);
>> +  ecc_point_clear(&Res);
>> +  mpz_clear (x);
>> +  mpz_clear (y);
>> +}
>> +
>> +void
>> +test_mul (void)
>> +{
>> +  int ret = 0;
>> +  const struct ecc_curve *ecc = nettle_get_sm2();
>> +  struct ecc_point pub, pr, Res;
>> +  struct ecc_scalar key;
>> +  mpz_t x, y;
>> +
>> +  ecc_point_init (&pub, ecc);
>> +  ecc_point_init (&pr, ecc);
>> +  ecc_point_init (&Res, ecc);
>> +  ecc_scalar_init (&key, ecc);
>> +  mpz_init (x);
>> +  mpz_init (y);
>> +
>> +  mpz_set_str(x, pkey, 16);
>> +  ecc_scalar_set(&key, x);
>> +  mpz_set_str(x, xG, 16);
>> +  mpz_set_str(y, yG, 16);
>> +  sm2_point_set(&pub, x, y);
>> +
>> +  sm2_mul(&pr, &key, &pub);
>> +
>> +  if (verbose)
>> +    sm2_point_print (&pr);
>> +
>> +  mpz_set_str(x, xR, 16);
>> +  mpz_set_str(y, yR, 16);
>> +  sm2_point_set(&Res, x, y);
>> +
>> +  ret = mpn_cmp(Res.p, pr.p, SM2_LIMB_BYTES);  ASSERT(ret == 0);
>> +
>> +  ecc_point_clear(&pub);
>> +  ecc_point_clear(&pr);
>> +  ecc_point_clear(&Res);
>> +  ecc_scalar_clear(&key);
>> +  mpz_clear (x);
>> +  mpz_clear (y);
>> +}
>> +
>> +void
>> +test_main (void)
>> +{
>> +  test_get_order();
>> +  test_get_order_NULL();
>> +  test_add();
>> +  test_mul();
>> +}
>> diff --git a/testsuite/testutils.h b/testsuite/testutils.h index
>> 3e23978..c2cf5e1 100644
>> --- a/testsuite/testutils.h
>> +++ b/testsuite/testutils.h
>> @@ -22,6 +22,8 @@
>>  # include "ecc.h"
>>  # include "ecc-internal.h"
>>  # include "ecdsa.h"
>> +# include "sm2.h"
>> +# include "sm2-internal.h"
>>  # include "gmp-glue.h"
>>  # if NETTLE_USE_MINI_GMP
>>  #  include "knuth-lfib.h"
>
>--
>Niels Möller. PGP key CB4962D070D77D7FCB8BA36271D8F1FF368C6677.
>Internet email is subject to wholesale government surveillance.
>
>
_______________________________________________
nettle-bugs mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to