2 * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
12 * SM2 low level APIs are deprecated for public use, but still ok for
15 #include "internal/deprecated.h"
18 #include <openssl/err.h>
19 #include "crypto/bn.h"
21 #include "internal/common.h"
22 #include "internal/constant_time.h"
24 #define P256_LIMBS (256 / BN_BITS2)
26 #if !defined(OPENSSL_NO_SM2_PRECOMP)
27 extern const BN_ULONG ecp_sm2p256_precomputed
[8 * 32 * 256];
31 BN_ULONG X
[P256_LIMBS
];
32 BN_ULONG Y
[P256_LIMBS
];
33 BN_ULONG Z
[P256_LIMBS
];
37 BN_ULONG X
[P256_LIMBS
];
38 BN_ULONG Y
[P256_LIMBS
];
41 #if !defined(OPENSSL_NO_SM2_PRECOMP)
42 /* Coordinates of G, for which we have precomputed tables */
43 ALIGN32
static const BN_ULONG def_xG
[P256_LIMBS
] = {
44 0x715a4589334c74c7, 0x8fe30bbff2660be1,
45 0x5f9904466a39c994, 0x32c4ae2c1f198119
48 ALIGN32
static const BN_ULONG def_yG
[P256_LIMBS
] = {
49 0x02df32e52139f0a0, 0xd0a9877cc62a4740,
50 0x59bdcee36b692153, 0xbc3736a2f4f6779c,
54 /* p and order for SM2 according to GB/T 32918.5-2017 */
55 ALIGN32
static const BN_ULONG def_p
[P256_LIMBS
] = {
56 0xffffffffffffffff, 0xffffffff00000000,
57 0xffffffffffffffff, 0xfffffffeffffffff
59 ALIGN32
static const BN_ULONG def_ord
[P256_LIMBS
] = {
60 0x53bbf40939d54123, 0x7203df6b21c6052b,
61 0xffffffffffffffff, 0xfffffffeffffffff
64 ALIGN32
static const BN_ULONG ONE
[P256_LIMBS
] = {1, 0, 0, 0};
66 /* Functions implemented in assembly */
68 * Most of below mentioned functions *preserve* the property of inputs
69 * being fully reduced, i.e. being in [0, modulus) range. Simply put if
70 * inputs are fully reduced, then output is too.
72 /* Right shift: a >> 1 */
73 void bn_rshift1(BN_ULONG
*a
);
75 void bn_sub(BN_ULONG
*r
, const BN_ULONG
*a
, const BN_ULONG
*b
);
76 /* Modular div by 2: r = a / 2 mod p */
77 void ecp_sm2p256_div_by_2(BN_ULONG
*r
, const BN_ULONG
*a
);
78 /* Modular div by 2: r = a / 2 mod n, where n = ord(p) */
79 void ecp_sm2p256_div_by_2_mod_ord(BN_ULONG
*r
, const BN_ULONG
*a
);
80 /* Modular add: r = a + b mod p */
81 void ecp_sm2p256_add(BN_ULONG
*r
, const BN_ULONG
*a
, const BN_ULONG
*b
);
82 /* Modular sub: r = a - b mod p */
83 void ecp_sm2p256_sub(BN_ULONG
*r
, const BN_ULONG
*a
, const BN_ULONG
*b
);
84 /* Modular sub: r = a - b mod n, where n = ord(p) */
85 void ecp_sm2p256_sub_mod_ord(BN_ULONG
*r
, const BN_ULONG
*a
, const BN_ULONG
*b
);
86 /* Modular mul by 3: out = 3 * a mod p */
87 void ecp_sm2p256_mul_by_3(BN_ULONG
*r
, const BN_ULONG
*a
);
88 /* Modular mul: r = a * b mod p */
89 void ecp_sm2p256_mul(BN_ULONG
*r
, const BN_ULONG
*a
, const BN_ULONG
*b
);
90 /* Modular sqr: r = a ^ 2 mod p */
91 void ecp_sm2p256_sqr(BN_ULONG
*r
, const BN_ULONG
*a
);
93 static ossl_inline BN_ULONG
is_zeros(const BN_ULONG
*a
)
97 res
= a
[0] | a
[1] | a
[2] | a
[3];
99 return constant_time_is_zero_64(res
);
102 static ossl_inline
int is_equal(const BN_ULONG
*a
, const BN_ULONG
*b
)
111 return constant_time_is_zero_64(res
);
114 static ossl_inline
int is_greater(const BN_ULONG
*a
, const BN_ULONG
*b
)
118 for (i
= P256_LIMBS
- 1; i
>= 0; --i
) {
128 #define is_one(a) is_equal(a, ONE)
129 #define is_even(a) !(a[0] & 1)
130 #define is_point_equal(a, b) \
131 is_equal(a->X, b->X) && \
132 is_equal(a->Y, b->Y) && \
135 /* Bignum and field elements conversion */
136 #define ecp_sm2p256_bignum_field_elem(out, in) \
137 bn_copy_words(out, in, P256_LIMBS)
139 /* Binary algorithm for inversion in Fp */
140 #define BN_MOD_INV(out, in, mod_div, mod_sub, mod) \
142 ALIGN32 BN_ULONG u[4]; \
143 ALIGN32 BN_ULONG v[4]; \
144 ALIGN32 BN_ULONG x1[4] = {1, 0, 0, 0}; \
145 ALIGN32 BN_ULONG x2[4] = {0}; \
150 memcpy(v, mod, 32); \
151 while (!is_one(u) && !is_one(v)) { \
152 while (is_even(u)) { \
156 while (is_even(v)) { \
160 if (is_greater(u, v) == 1) { \
162 mod_sub(x1, x1, x2); \
165 mod_sub(x2, x2, x1); \
169 memcpy(out, x1, 32); \
171 memcpy(out, x2, 32); \
174 /* Modular inverse |out| = |in|^(-1) mod |p|. */
175 static ossl_inline
void ecp_sm2p256_mod_inverse(BN_ULONG
* out
,
176 const BN_ULONG
* in
) {
177 BN_MOD_INV(out
, in
, ecp_sm2p256_div_by_2
, ecp_sm2p256_sub
, def_p
);
180 /* Modular inverse mod order |out| = |in|^(-1) % |ord|. */
181 static ossl_inline
void ecp_sm2p256_mod_ord_inverse(BN_ULONG
* out
,
182 const BN_ULONG
* in
) {
183 BN_MOD_INV(out
, in
, ecp_sm2p256_div_by_2_mod_ord
, ecp_sm2p256_sub_mod_ord
,
187 /* Point double: R <- P + P */
188 static void ecp_sm2p256_point_double(P256_POINT
*R
, const P256_POINT
*P
)
191 ALIGN32 BN_ULONG tmp0
[P256_LIMBS
];
192 ALIGN32 BN_ULONG tmp1
[P256_LIMBS
];
193 ALIGN32 BN_ULONG tmp2
[P256_LIMBS
];
195 /* zero-check P->Z */
196 if (is_zeros(P
->Z
)) {
197 for (i
= 0; i
< P256_LIMBS
; ++i
)
203 ecp_sm2p256_sqr(tmp0
, P
->Z
);
204 ecp_sm2p256_sub(tmp1
, P
->X
, tmp0
);
205 ecp_sm2p256_add(tmp0
, P
->X
, tmp0
);
206 ecp_sm2p256_mul(tmp1
, tmp1
, tmp0
);
207 ecp_sm2p256_mul_by_3(tmp1
, tmp1
);
208 ecp_sm2p256_add(R
->Y
, P
->Y
, P
->Y
);
209 ecp_sm2p256_mul(R
->Z
, R
->Y
, P
->Z
);
210 ecp_sm2p256_sqr(R
->Y
, R
->Y
);
211 ecp_sm2p256_mul(tmp2
, R
->Y
, P
->X
);
212 ecp_sm2p256_sqr(R
->Y
, R
->Y
);
213 ecp_sm2p256_div_by_2(R
->Y
, R
->Y
);
214 ecp_sm2p256_sqr(R
->X
, tmp1
);
215 ecp_sm2p256_add(tmp0
, tmp2
, tmp2
);
216 ecp_sm2p256_sub(R
->X
, R
->X
, tmp0
);
217 ecp_sm2p256_sub(tmp0
, tmp2
, R
->X
);
218 ecp_sm2p256_mul(tmp0
, tmp0
, tmp1
);
219 ecp_sm2p256_sub(tmp1
, tmp0
, R
->Y
);
220 memcpy(R
->Y
, tmp1
, 32);
223 /* Point add affine: R <- P + Q */
224 static void ecp_sm2p256_point_add_affine(P256_POINT
*R
, const P256_POINT
*P
,
225 const P256_POINT_AFFINE
*Q
)
228 ALIGN32 BN_ULONG tmp0
[P256_LIMBS
] = {0};
229 ALIGN32 BN_ULONG tmp1
[P256_LIMBS
] = {0};
230 ALIGN32 BN_ULONG tmp2
[P256_LIMBS
] = {0};
231 ALIGN32 BN_ULONG tmp3
[P256_LIMBS
] = {0};
233 /* zero-check P->Z */
234 if (is_zeros(P
->Z
)) {
235 for (i
= 0; i
< P256_LIMBS
; ++i
) {
245 ecp_sm2p256_sqr(tmp0
, P
->Z
);
246 ecp_sm2p256_mul(tmp1
, tmp0
, P
->Z
);
247 ecp_sm2p256_mul(tmp0
, tmp0
, Q
->X
);
248 ecp_sm2p256_mul(tmp1
, tmp1
, Q
->Y
);
249 ecp_sm2p256_sub(tmp0
, tmp0
, P
->X
);
250 ecp_sm2p256_sub(tmp1
, tmp1
, P
->Y
);
252 /* zero-check tmp0, tmp1 */
253 if (is_zeros(tmp0
)) {
254 if (is_zeros(tmp1
)) {
257 for (i
= 0; i
< P256_LIMBS
; ++i
) {
263 ecp_sm2p256_point_double(R
, &K
);
265 for (i
= 0; i
< P256_LIMBS
; ++i
)
272 ecp_sm2p256_mul(R
->Z
, P
->Z
, tmp0
);
273 ecp_sm2p256_sqr(tmp2
, tmp0
);
274 ecp_sm2p256_mul(tmp3
, tmp2
, tmp0
);
275 ecp_sm2p256_mul(tmp2
, tmp2
, P
->X
);
276 ecp_sm2p256_add(tmp0
, tmp2
, tmp2
);
277 ecp_sm2p256_sqr(R
->X
, tmp1
);
278 ecp_sm2p256_sub(R
->X
, R
->X
, tmp0
);
279 ecp_sm2p256_sub(R
->X
, R
->X
, tmp3
);
280 ecp_sm2p256_sub(tmp2
, tmp2
, R
->X
);
281 ecp_sm2p256_mul(tmp2
, tmp2
, tmp1
);
282 ecp_sm2p256_mul(tmp3
, tmp3
, P
->Y
);
283 ecp_sm2p256_sub(R
->Y
, tmp2
, tmp3
);
286 /* Point add: R <- P + Q */
287 static void ecp_sm2p256_point_add(P256_POINT
*R
, const P256_POINT
*P
,
291 ALIGN32 BN_ULONG tmp0
[P256_LIMBS
] = {0};
292 ALIGN32 BN_ULONG tmp1
[P256_LIMBS
] = {0};
293 ALIGN32 BN_ULONG tmp2
[P256_LIMBS
] = {0};
295 /* zero-check P | Q ->Z */
296 if (is_zeros(P
->Z
)) {
297 for (i
= 0; i
< P256_LIMBS
; ++i
) {
304 } else if (is_zeros(Q
->Z
)) {
305 for (i
= 0; i
< P256_LIMBS
; ++i
) {
312 } else if (is_point_equal(P
, Q
)) {
313 ecp_sm2p256_point_double(R
, Q
);
318 ecp_sm2p256_sqr(tmp0
, P
->Z
);
319 ecp_sm2p256_mul(tmp1
, tmp0
, P
->Z
);
320 ecp_sm2p256_mul(tmp0
, tmp0
, Q
->X
);
321 ecp_sm2p256_mul(tmp1
, tmp1
, Q
->Y
);
322 ecp_sm2p256_mul(R
->Y
, P
->Y
, Q
->Z
);
323 ecp_sm2p256_mul(R
->Z
, Q
->Z
, P
->Z
);
324 ecp_sm2p256_sqr(tmp2
, Q
->Z
);
325 ecp_sm2p256_mul(R
->Y
, tmp2
, R
->Y
);
326 ecp_sm2p256_mul(R
->X
, tmp2
, P
->X
);
327 ecp_sm2p256_sub(tmp0
, tmp0
, R
->X
);
328 ecp_sm2p256_mul(R
->Z
, tmp0
, R
->Z
);
329 ecp_sm2p256_sub(tmp1
, tmp1
, R
->Y
);
330 ecp_sm2p256_sqr(tmp2
, tmp0
);
331 ecp_sm2p256_mul(tmp0
, tmp0
, tmp2
);
332 ecp_sm2p256_mul(tmp2
, tmp2
, R
->X
);
333 ecp_sm2p256_sqr(R
->X
, tmp1
);
334 ecp_sm2p256_sub(R
->X
, R
->X
, tmp2
);
335 ecp_sm2p256_sub(R
->X
, R
->X
, tmp2
);
336 ecp_sm2p256_sub(R
->X
, R
->X
, tmp0
);
337 ecp_sm2p256_sub(tmp2
, tmp2
, R
->X
);
338 ecp_sm2p256_mul(tmp2
, tmp1
, tmp2
);
339 ecp_sm2p256_mul(tmp0
, tmp0
, R
->Y
);
340 ecp_sm2p256_sub(R
->Y
, tmp2
, tmp0
);
343 #if !defined(OPENSSL_NO_SM2_PRECOMP)
344 /* Base point mul by scalar: k - scalar, G - base point */
345 static void ecp_sm2p256_point_G_mul_by_scalar(P256_POINT
*R
, const BN_ULONG
*k
)
347 unsigned int i
, index
, mask
= 0xff;
350 memset(R
, 0, sizeof(P256_POINT
));
358 memcpy(R
->X
, ecp_sm2p256_precomputed
+ index
, 32);
359 memcpy(R
->Y
, ecp_sm2p256_precomputed
+ index
+ P256_LIMBS
, 32);
363 for (i
= 1; i
< 32; ++i
) {
364 index
= (k
[i
/ 8] >> (8 * (i
% 8))) & mask
;
367 index
= index
+ i
* 256;
369 memcpy(Q
.X
, ecp_sm2p256_precomputed
+ index
, 32);
370 memcpy(Q
.Y
, ecp_sm2p256_precomputed
+ index
+ P256_LIMBS
, 32);
371 ecp_sm2p256_point_add_affine(R
, R
, &Q
);
378 * Affine point mul by scalar: k - scalar, P - affine point
380 static void ecp_sm2p256_point_P_mul_by_scalar(P256_POINT
*R
, const BN_ULONG
*k
,
384 unsigned int index
, mask
= 0x0f;
385 ALIGN64 P256_POINT precomputed
[16];
387 memset(R
, 0, sizeof(P256_POINT
));
392 /* The first value of the precomputed table is P. */
393 memcpy(precomputed
[1].X
, P
.X
, 32);
394 memcpy(precomputed
[1].Y
, P
.Y
, 32);
395 precomputed
[1].Z
[0] = 1;
396 precomputed
[1].Z
[1] = 0;
397 precomputed
[1].Z
[2] = 0;
398 precomputed
[1].Z
[3] = 0;
400 /* The second value of the precomputed table is 2P. */
401 ecp_sm2p256_point_double(&precomputed
[2], &precomputed
[1]);
403 /* The subsequent elements are 3P, 4P, and so on. */
404 for (i
= 3; i
< 16; ++i
)
405 ecp_sm2p256_point_add_affine(&precomputed
[i
], &precomputed
[i
- 1], &P
);
407 for (i
= 64 - 1; i
>= 0; --i
) {
408 index
= (k
[i
/ 16] >> (4 * (i
% 16))) & mask
;
412 memcpy(R
, &precomputed
[index
], sizeof(P256_POINT
));
416 ecp_sm2p256_point_double(R
, R
);
417 ecp_sm2p256_point_double(R
, R
);
418 ecp_sm2p256_point_double(R
, R
);
419 ecp_sm2p256_point_double(R
, R
);
421 ecp_sm2p256_point_add(R
, R
, &precomputed
[index
]);
426 /* Get affine point */
427 static void ecp_sm2p256_point_get_affine(P256_POINT_AFFINE
*R
,
430 ALIGN32 BN_ULONG z_inv3
[P256_LIMBS
] = {0};
431 ALIGN32 BN_ULONG z_inv2
[P256_LIMBS
] = {0};
434 memcpy(R
->X
, P
->X
, 32);
435 memcpy(R
->Y
, P
->Y
, 32);
439 ecp_sm2p256_mod_inverse(z_inv3
, P
->Z
);
440 ecp_sm2p256_sqr(z_inv2
, z_inv3
);
441 ecp_sm2p256_mul(R
->X
, P
->X
, z_inv2
);
442 ecp_sm2p256_mul(z_inv3
, z_inv3
, z_inv2
);
443 ecp_sm2p256_mul(R
->Y
, P
->Y
, z_inv3
);
446 #if !defined(OPENSSL_NO_SM2_PRECOMP)
447 static int ecp_sm2p256_is_affine_G(const EC_POINT
*generator
)
449 return (bn_get_top(generator
->X
) == P256_LIMBS
)
450 && (bn_get_top(generator
->Y
) == P256_LIMBS
)
451 && is_equal(bn_get_words(generator
->X
), def_xG
)
452 && is_equal(bn_get_words(generator
->Y
), def_yG
)
453 && (generator
->Z_is_one
== 1);
458 * Convert Jacobian coordinate point into affine coordinate (x,y)
460 static int ecp_sm2p256_get_affine(const EC_GROUP
*group
,
461 const EC_POINT
*point
,
462 BIGNUM
*x
, BIGNUM
*y
, BN_CTX
*ctx
)
464 ALIGN32 BN_ULONG z_inv2
[P256_LIMBS
] = {0};
465 ALIGN32 BN_ULONG z_inv3
[P256_LIMBS
] = {0};
466 ALIGN32 BN_ULONG x_aff
[P256_LIMBS
] = {0};
467 ALIGN32 BN_ULONG y_aff
[P256_LIMBS
] = {0};
468 ALIGN32 BN_ULONG point_x
[P256_LIMBS
] = {0};
469 ALIGN32 BN_ULONG point_y
[P256_LIMBS
] = {0};
470 ALIGN32 BN_ULONG point_z
[P256_LIMBS
] = {0};
472 if (EC_POINT_is_at_infinity(group
, point
)) {
473 ECerr(ERR_LIB_EC
, EC_R_POINT_AT_INFINITY
);
477 if (ecp_sm2p256_bignum_field_elem(point_x
, point
->X
) <= 0
478 || ecp_sm2p256_bignum_field_elem(point_y
, point
->Y
) <= 0
479 || ecp_sm2p256_bignum_field_elem(point_z
, point
->Z
) <= 0) {
480 ECerr(ERR_LIB_EC
, EC_R_COORDINATES_OUT_OF_RANGE
);
484 ecp_sm2p256_mod_inverse(z_inv3
, point_z
);
485 ecp_sm2p256_sqr(z_inv2
, z_inv3
);
488 ecp_sm2p256_mul(x_aff
, point_x
, z_inv2
);
489 if (!bn_set_words(x
, x_aff
, P256_LIMBS
))
494 ecp_sm2p256_mul(z_inv3
, z_inv3
, z_inv2
);
495 ecp_sm2p256_mul(y_aff
, point_y
, z_inv3
);
496 if (!bn_set_words(y
, y_aff
, P256_LIMBS
))
503 /* r = sum(scalar[i]*point[i]) */
504 static int ecp_sm2p256_windowed_mul(const EC_GROUP
*group
,
506 const BIGNUM
**scalar
,
507 const EC_POINT
**point
,
508 size_t num
, BN_CTX
*ctx
)
512 const BIGNUM
**scalars
= NULL
;
513 ALIGN32 BN_ULONG k
[P256_LIMBS
] = {0};
520 if (num
> OPENSSL_MALLOC_MAX_NELEMS(P256_POINT
)
521 || (scalars
= OPENSSL_malloc(num
* sizeof(BIGNUM
*))) == NULL
) {
522 ECerr(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
526 memset(r
, 0, sizeof(P256_POINT
));
528 for (i
= 0; i
< num
; i
++) {
529 if (EC_POINT_is_at_infinity(group
, point
[i
]))
532 if ((BN_num_bits(scalar
[i
]) > 256) || BN_is_negative(scalar
[i
])) {
535 if ((tmp
= BN_CTX_get(ctx
)) == NULL
)
537 if (!BN_nnmod(tmp
, scalar
[i
], group
->order
, ctx
)) {
538 ECerr(ERR_LIB_EC
, ERR_R_BN_LIB
);
543 scalars
[i
] = scalar
[i
];
546 if (ecp_sm2p256_bignum_field_elem(k
, scalars
[i
]) <= 0
547 || ecp_sm2p256_bignum_field_elem(p
.p
.X
, point
[i
]->X
) <= 0
548 || ecp_sm2p256_bignum_field_elem(p
.p
.Y
, point
[i
]->Y
) <= 0
549 || ecp_sm2p256_bignum_field_elem(p
.p
.Z
, point
[i
]->Z
) <= 0) {
550 ECerr(ERR_LIB_EC
, EC_R_COORDINATES_OUT_OF_RANGE
);
554 ecp_sm2p256_point_get_affine(&t
.a
, &p
.p
);
555 ecp_sm2p256_point_P_mul_by_scalar(&kP
, k
, t
.a
);
556 ecp_sm2p256_point_add(r
, r
, &kP
);
561 OPENSSL_free(scalars
);
565 /* r = scalar*G + sum(scalars[i]*points[i]) */
566 static int ecp_sm2p256_points_mul(const EC_GROUP
*group
,
568 const BIGNUM
*scalar
,
570 const EC_POINT
*points
[],
571 const BIGNUM
*scalars
[], BN_CTX
*ctx
)
573 int ret
= 0, p_is_infinity
= 0;
574 const EC_POINT
*generator
= NULL
;
575 ALIGN32 BN_ULONG k
[P256_LIMBS
] = {0};
581 if ((num
+ 1) == 0 || (num
+ 1) > OPENSSL_MALLOC_MAX_NELEMS(void *)) {
582 ECerr(ERR_LIB_EC
, ERR_R_MALLOC_FAILURE
);
589 generator
= EC_GROUP_get0_generator(group
);
590 if (generator
== NULL
) {
591 ECerr(ERR_LIB_EC
, EC_R_UNDEFINED_GENERATOR
);
595 if (!ecp_sm2p256_bignum_field_elem(k
, scalar
)) {
596 ECerr(ERR_LIB_EC
, EC_R_COORDINATES_OUT_OF_RANGE
);
599 #if !defined(OPENSSL_NO_SM2_PRECOMP)
600 if (ecp_sm2p256_is_affine_G(generator
)) {
601 ecp_sm2p256_point_G_mul_by_scalar(&p
.p
, k
);
605 /* if no precomputed table */
606 const EC_POINT
*new_generator
[1];
607 const BIGNUM
*g_scalars
[1];
609 new_generator
[0] = generator
;
610 g_scalars
[0] = scalar
;
612 if (!ecp_sm2p256_windowed_mul(group
, &p
.p
, g_scalars
, new_generator
,
613 (new_generator
[0] != NULL
614 && g_scalars
[0] != NULL
), ctx
))
621 P256_POINT
*out
= &t
.p
;
626 if (!ecp_sm2p256_windowed_mul(group
, out
, scalars
, points
, num
, ctx
))
630 ecp_sm2p256_point_add(&p
.p
, &p
.p
, out
);
633 /* Not constant-time, but we're only operating on the public output. */
634 if (!bn_set_words(r
->X
, p
.p
.X
, P256_LIMBS
)
635 || !bn_set_words(r
->Y
, p
.p
.Y
, P256_LIMBS
)
636 || !bn_set_words(r
->Z
, p
.p
.Z
, P256_LIMBS
))
638 r
->Z_is_one
= is_equal(bn_get_words(r
->Z
), ONE
) & 1;
646 static int ecp_sm2p256_field_mul(const EC_GROUP
*group
, BIGNUM
*r
,
647 const BIGNUM
*a
, const BIGNUM
*b
, BN_CTX
*ctx
)
649 ALIGN32 BN_ULONG a_fe
[P256_LIMBS
] = {0};
650 ALIGN32 BN_ULONG b_fe
[P256_LIMBS
] = {0};
651 ALIGN32 BN_ULONG r_fe
[P256_LIMBS
] = {0};
653 if (a
== NULL
|| b
== NULL
|| r
== NULL
)
656 if (!ecp_sm2p256_bignum_field_elem(a_fe
, a
)
657 || !ecp_sm2p256_bignum_field_elem(b_fe
, b
)) {
658 ECerr(ERR_LIB_EC
, EC_R_COORDINATES_OUT_OF_RANGE
);
662 ecp_sm2p256_mul(r_fe
, a_fe
, b_fe
);
664 if (!bn_set_words(r
, r_fe
, P256_LIMBS
))
670 static int ecp_sm2p256_field_sqr(const EC_GROUP
*group
, BIGNUM
*r
,
671 const BIGNUM
*a
, BN_CTX
*ctx
)
673 ALIGN32 BN_ULONG a_fe
[P256_LIMBS
] = {0};
674 ALIGN32 BN_ULONG r_fe
[P256_LIMBS
] = {0};
676 if (a
== NULL
|| r
== NULL
)
679 if (!ecp_sm2p256_bignum_field_elem(a_fe
, a
)) {
680 ECerr(ERR_LIB_EC
, EC_R_COORDINATES_OUT_OF_RANGE
);
684 ecp_sm2p256_sqr(r_fe
, a_fe
);
686 if (!bn_set_words(r
, r_fe
, P256_LIMBS
))
692 static int ecp_sm2p256_inv_mod_ord(const EC_GROUP
*group
, BIGNUM
*r
,
693 const BIGNUM
*x
, BN_CTX
*ctx
)
696 ALIGN32 BN_ULONG t
[P256_LIMBS
] = {0};
697 ALIGN32 BN_ULONG out
[P256_LIMBS
] = {0};
699 if (bn_wexpand(r
, P256_LIMBS
) == NULL
) {
700 ECerr(ERR_LIB_EC
, ERR_R_BN_LIB
);
704 if ((BN_num_bits(x
) > 256) || BN_is_negative(x
)) {
707 if ((tmp
= BN_CTX_get(ctx
)) == NULL
708 || !BN_nnmod(tmp
, x
, group
->order
, ctx
)) {
709 ECerr(ERR_LIB_EC
, ERR_R_BN_LIB
);
715 if (!ecp_sm2p256_bignum_field_elem(t
, x
)) {
716 ECerr(ERR_LIB_EC
, EC_R_COORDINATES_OUT_OF_RANGE
);
720 ecp_sm2p256_mod_ord_inverse(out
, t
);
722 if (!bn_set_words(r
, out
, P256_LIMBS
))
730 const EC_METHOD
*EC_GFp_sm2p256_method(void)
732 static const EC_METHOD ret
= {
733 EC_FLAGS_DEFAULT_OCT
,
734 NID_X9_62_prime_field
,
735 ossl_ec_GFp_simple_group_init
,
736 ossl_ec_GFp_simple_group_finish
,
737 ossl_ec_GFp_simple_group_clear_finish
,
738 ossl_ec_GFp_simple_group_copy
,
739 ossl_ec_GFp_simple_group_set_curve
,
740 ossl_ec_GFp_simple_group_get_curve
,
741 ossl_ec_GFp_simple_group_get_degree
,
742 ossl_ec_group_simple_order_bits
,
743 ossl_ec_GFp_simple_group_check_discriminant
,
744 ossl_ec_GFp_simple_point_init
,
745 ossl_ec_GFp_simple_point_finish
,
746 ossl_ec_GFp_simple_point_clear_finish
,
747 ossl_ec_GFp_simple_point_copy
,
748 ossl_ec_GFp_simple_point_set_to_infinity
,
749 ossl_ec_GFp_simple_point_set_affine_coordinates
,
750 ecp_sm2p256_get_affine
,
752 ossl_ec_GFp_simple_add
,
753 ossl_ec_GFp_simple_dbl
,
754 ossl_ec_GFp_simple_invert
,
755 ossl_ec_GFp_simple_is_at_infinity
,
756 ossl_ec_GFp_simple_is_on_curve
,
757 ossl_ec_GFp_simple_cmp
,
758 ossl_ec_GFp_simple_make_affine
,
759 ossl_ec_GFp_simple_points_make_affine
,
760 ecp_sm2p256_points_mul
, /* mul */
761 0 /* precompute_mult */,
762 0 /* have_precompute_mult */,
763 ecp_sm2p256_field_mul
,
764 ecp_sm2p256_field_sqr
,
767 0 /* field_encode */,
768 0 /* field_decode */,
769 0 /* field_set_to_one */,
770 ossl_ec_key_simple_priv2oct
,
771 ossl_ec_key_simple_oct2priv
,
773 ossl_ec_key_simple_generate_key
,
774 ossl_ec_key_simple_check_key
,
775 ossl_ec_key_simple_generate_public_key
,
778 ossl_ecdh_simple_compute_key
,
779 ossl_ecdsa_simple_sign_setup
,
780 ossl_ecdsa_simple_sign_sig
,
781 ossl_ecdsa_simple_verify_sig
,
782 ecp_sm2p256_inv_mod_ord
,
783 0, /* blind_coordinates */