mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-07 00:46:17 +08:00
Add ECDSA with curve P-256
for TLS testing
This commit is contained in:
@@ -54,6 +54,8 @@ option(ENABLE_SM4_CBC_MAC "Enable SM4-CBC-MAC" ON)
|
||||
|
||||
option(ENABLE_SM2_EXTS "Enable SM2 Extensions" OFF)
|
||||
|
||||
option(ENABLE_SECP256R1 "Enable ECDH/ECDSA on curve secp256r1" ON)
|
||||
|
||||
option(ENABLE_LMS "Enable LMS/HSS signature" ON)
|
||||
option(ENABLE_XMSS "Enable XMSS/XMSS^MT signature" ON)
|
||||
option(ENABLE_SPHINCS "Enable SPHINCS+ signature" ON)
|
||||
@@ -108,6 +110,7 @@ set(src
|
||||
src/sm4_cbc_sm3_hmac.c
|
||||
src/sm4_ctr_sm3_hmac.c
|
||||
src/pkcs8.c
|
||||
src/bn.c
|
||||
src/ec.c
|
||||
src/rsa.c
|
||||
src/asn1.c
|
||||
@@ -128,6 +131,7 @@ set(src
|
||||
src/tls_trace.c
|
||||
src/tlcp.c
|
||||
src/tls12.c
|
||||
src/tls12_handshake.c
|
||||
src/tls13.c
|
||||
src/file.c
|
||||
src/file.c
|
||||
@@ -203,6 +207,7 @@ set(tests
|
||||
gf128
|
||||
ghash
|
||||
pkcs8
|
||||
bn
|
||||
ec
|
||||
asn1
|
||||
hex
|
||||
@@ -419,6 +424,14 @@ if (ENABLE_SM2_EXTS)
|
||||
endif()
|
||||
|
||||
|
||||
if (ENABLE_SECP256R1)
|
||||
message(STATUS "ENABLE_SECP256R1 is ON")
|
||||
add_definitions(-DENABLE_SECP256R1)
|
||||
list(APPEND src src/secp256r1.c src/secp256r1_key.c src/ecdsa.c)
|
||||
list(APPEND tests secp256r1 secp256r1_key ecdsa)
|
||||
endif()
|
||||
|
||||
|
||||
if (ENABLE_LMS)
|
||||
message(STATUS "ENABLE_LMS is ON")
|
||||
add_definitions(-DENABLE_LMS)
|
||||
|
||||
86
include/gmssl/bn.h
Normal file
86
include/gmssl/bn.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef GMSSL_BN_H
|
||||
#define GMSSL_BN_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
void bn_set_word(uint32_t *r, uint32_t a, size_t k);
|
||||
void bn_copy(uint32_t *r, const uint32_t *a, size_t k);
|
||||
int bn_cmp(const uint32_t *a, const uint32_t *b, size_t k);
|
||||
int bn_is_zero(const uint32_t *a, size_t k);
|
||||
int bn_is_one(const uint32_t *a, size_t k);
|
||||
int bn_add(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k);
|
||||
int bn_sub(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k);
|
||||
void bn_mul(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k);
|
||||
void bn_mul_lo(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k);
|
||||
void bn_to_bytes(const uint32_t *a, size_t k, uint8_t *out);
|
||||
void bn_from_bytes(uint32_t *a, size_t k, const uint8_t *in);
|
||||
int bn_print(FILE *fp, int fmt, int ind, const char *label, const uint32_t *a, size_t k);
|
||||
|
||||
void bn_mod_add(uint32_t *r, const uint32_t *a, const uint32_t *b, const uint32_t *p, size_t k);
|
||||
void bn_mod_sub(uint32_t *r, const uint32_t *a, const uint32_t *b, const uint32_t *p, size_t k);
|
||||
void bn_mod_neg(uint32_t *r, const uint32_t *a, const uint32_t *p, size_t k);
|
||||
|
||||
// multiplication with barrett reduction, need caller prepare temp values
|
||||
// u = floor(2^512 / p) for bn256
|
||||
void bn_barrett_mod_mul(uint32_t *r, const uint32_t *a, const uint32_t *b, const uint32_t *p,
|
||||
const uint32_t *u, // uint32_t u[k + 1]
|
||||
uint32_t *tmp, // uint32_t tmp[6*k + 4]
|
||||
size_t k);
|
||||
void bn_barrett_mod_sqr(uint32_t *r, const uint32_t *a, const uint32_t *p,
|
||||
const uint32_t *u, // uint32_t u[k + 1]
|
||||
uint32_t *tmp, // uint32_t tmp[6*k + 4]
|
||||
size_t k);
|
||||
void bn_barrett_mod_exp(uint32_t *r, const uint32_t *a, const uint32_t *e, const uint32_t *p,
|
||||
const uint32_t *u, // uint32_t u[k + 1]
|
||||
uint32_t *tmp, // uint32_t tmp[7*k + 4]
|
||||
size_t k);
|
||||
void bn_barrett_mod_inv(uint32_t *r, const uint32_t *a, const uint32_t *p,
|
||||
const uint32_t *u, // uint32_t u[k + 1]
|
||||
uint32_t *tmp, // uint32_t tmp[8*k + 4]
|
||||
size_t k);
|
||||
|
||||
// montgomery multiplication, all values in montgomery format, need caller prepare temp values
|
||||
void bn_mont_mod_mul(uint32_t *r, const uint32_t *a, const uint32_t *b, const uint32_t *p, const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k);
|
||||
void bn_mont_mod_sqr(uint32_t *r, const uint32_t *a, const uint32_t *p, const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k);
|
||||
void bn_mont_mod_exp(uint32_t *r, const uint32_t *a, const uint32_t *e, const uint32_t *p, const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[6 * k]
|
||||
size_t k);
|
||||
void bn_mont_mod_inv(uint32_t *r, const uint32_t *a, const uint32_t *p, const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[7 * k]
|
||||
size_t k);
|
||||
void bn_mont_set(uint32_t *r, const uint32_t *a, const uint32_t *one_sqr, const uint32_t *p, const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k);
|
||||
void bn_mont_get(uint32_t *r, const uint32_t *a, const uint32_t *p, const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
68
include/gmssl/ecdsa.h
Normal file
68
include/gmssl/ecdsa.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GMSSL_ECDSA_H
|
||||
#define GMSSL_ECDSA_H
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/sha2.h>
|
||||
#include <gmssl/secp256r1_key.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
secp256r1_t r;
|
||||
secp256r1_t s;
|
||||
} ECDSA_SIGNATURE;
|
||||
|
||||
#define ECDSA_SIGNATURE_COMPACT_SIZE 70
|
||||
#define ECDSA_SIGNATURE_TYPICAL_SIZE 71
|
||||
#define ECDSA_SIGNATURE_MAX_SIZE 72
|
||||
|
||||
int ecdsa_signature_to_der(const ECDSA_SIGNATURE *sig, uint8_t **out, size_t *outlen);
|
||||
int ecdsa_signature_from_der(ECDSA_SIGNATURE *sig, const uint8_t **in, size_t *inlen);
|
||||
int ecdsa_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const ECDSA_SIGNATURE *sig);
|
||||
int ecdsa_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen);
|
||||
|
||||
int ecdsa_do_sign_ex(const SECP256R1_KEY *key, const secp256r1_t k, const uint8_t dgst[32], ECDSA_SIGNATURE *sig);
|
||||
int ecdsa_do_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], ECDSA_SIGNATURE *sig);
|
||||
int ecdsa_do_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const ECDSA_SIGNATURE *sig);
|
||||
int ecdsa_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen);
|
||||
int ecdsa_sign_fixlen(const SECP256R1_KEY *key, const uint8_t dgst[32], size_t siglen, uint8_t *sig);
|
||||
int ecdsa_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const uint8_t *sig, size_t siglen);
|
||||
|
||||
|
||||
typedef struct {
|
||||
SHA256_CTX sha256_ctx;
|
||||
SECP256R1_KEY key;
|
||||
ECDSA_SIGNATURE sig;
|
||||
} ECDSA_SIGN_CTX;
|
||||
|
||||
int ecdsa_sign_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key);
|
||||
int ecdsa_sign_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
|
||||
int ecdsa_sign_finish(ECDSA_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen);
|
||||
int ecdsa_sign_finish_fixlen(ECDSA_SIGN_CTX *ctx, size_t siglen, uint8_t *sig);
|
||||
int ecdsa_verify_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const uint8_t *sig, size_t siglen);
|
||||
int ecdsa_verify_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen);
|
||||
int ecdsa_verify_finish(ECDSA_SIGN_CTX *ctx);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -210,6 +210,7 @@ enum {
|
||||
|
||||
|
||||
|
||||
#define OID_secp256r1 OID_prime256v1
|
||||
|
||||
|
||||
#define oid_cnt(nodes) (sizeof(nodes)/sizeof((nodes)[0]))
|
||||
|
||||
108
include/gmssl/secp256r1.h
Normal file
108
include/gmssl/secp256r1.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef GMSSL_SECP256R1_H
|
||||
#define GMSSL_SECP256R1_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
// p = 2^256 - 2^224 + 2^192 + 2^96 - 1
|
||||
// = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
|
||||
// a = -3
|
||||
// b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
|
||||
// x = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
|
||||
// y = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
|
||||
// n = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
|
||||
// h = 1
|
||||
|
||||
|
||||
typedef uint32_t secp256r1_t[8];
|
||||
|
||||
#define SECP256R1_K (sizeof(secp256r1_t)/sizeof(uint32_t))
|
||||
|
||||
extern const secp256r1_t SECP256R1_P;
|
||||
extern const secp256r1_t SECP256R1_B;
|
||||
extern const secp256r1_t SECP256R1_N;
|
||||
extern const uint32_t SECP256R1_U_P[9];
|
||||
extern const uint32_t SECP256R1_U_N[9];
|
||||
|
||||
int secp256r1_is_zero(const secp256r1_t a);
|
||||
int secp256r1_is_one(const secp256r1_t a);
|
||||
int secp256r1_cmp(const secp256r1_t a, const secp256r1_t b);
|
||||
void secp256r1_set_zero(secp256r1_t r);
|
||||
void secp256r1_set_one(secp256r1_t r);
|
||||
void secp256r1_copy(secp256r1_t r, const secp256r1_t a);
|
||||
void secp256r1_to_32bytes(const secp256r1_t a, uint8_t out[32]);
|
||||
void secp256r1_from_32bytes(secp256r1_t r, const uint8_t in[32]);
|
||||
int secp256r1_print(FILE *fp, int fmt, int ind, const char *label, const secp256r1_t a);
|
||||
|
||||
void secp256r1_modp_add(secp256r1_t r, const secp256r1_t a, const secp256r1_t b);
|
||||
void secp256r1_modp_dbl(secp256r1_t r, const secp256r1_t a);
|
||||
void secp256r1_modp_tri(secp256r1_t r, const secp256r1_t a);
|
||||
void secp256r1_modp_sub(secp256r1_t r, const secp256r1_t a, const secp256r1_t b);
|
||||
void secp256r1_modp_neg(secp256r1_t r, const secp256r1_t a);
|
||||
void secp256r1_modp_haf(secp256r1_t r, const secp256r1_t a);
|
||||
void secp256r1_modp_mul(secp256r1_t r, const secp256r1_t a, const secp256r1_t b);
|
||||
void secp256r1_modp_sqr(secp256r1_t r, const secp256r1_t a);
|
||||
void secp256r1_modp_exp(secp256r1_t r, const secp256r1_t a, const secp256r1_t e);
|
||||
void secp256r1_modp_inv(secp256r1_t r, const secp256r1_t a);
|
||||
|
||||
void secp256r1_modn(secp256r1_t r, const secp256r1_t a);
|
||||
void secp256r1_modn_add(secp256r1_t r, const secp256r1_t a, const secp256r1_t b);
|
||||
void secp256r1_modn_dbl(secp256r1_t r, const secp256r1_t a);
|
||||
void secp256r1_modn_tri(secp256r1_t r, const secp256r1_t a);
|
||||
void secp256r1_modn_sub(secp256r1_t r, const secp256r1_t a, const secp256r1_t b);
|
||||
void secp256r1_modn_neg(secp256r1_t r, const secp256r1_t a);
|
||||
void secp256r1_modn_mul(secp256r1_t r, const secp256r1_t a, const secp256r1_t b);
|
||||
void secp256r1_modn_sqr(secp256r1_t r, const secp256r1_t a);
|
||||
void secp256r1_modn_exp(secp256r1_t r, const secp256r1_t a, const secp256r1_t e);
|
||||
void secp256r1_modn_inv(secp256r1_t r, const secp256r1_t a);
|
||||
|
||||
|
||||
typedef struct {
|
||||
secp256r1_t X;
|
||||
secp256r1_t Y;
|
||||
secp256r1_t Z;
|
||||
} SECP256R1_POINT;
|
||||
|
||||
extern const SECP256R1_POINT SECP256R1_POINT_G;
|
||||
|
||||
void secp256r1_point_set_infinity(SECP256R1_POINT *R);
|
||||
int secp256r1_point_is_at_infinity(const SECP256R1_POINT *P);
|
||||
int secp256r1_point_is_on_curve(const SECP256R1_POINT *P);
|
||||
int secp256r1_point_equ(const SECP256R1_POINT *P, const SECP256R1_POINT *Q);
|
||||
int secp256r1_point_set_xy(SECP256R1_POINT *R, const secp256r1_t x, const secp256r1_t y);
|
||||
int secp256r1_point_get_xy(const SECP256R1_POINT *P, secp256r1_t x, secp256r1_t y);
|
||||
void secp256r1_point_copy(SECP256R1_POINT *R, const SECP256R1_POINT *P);
|
||||
void secp256r1_point_dbl(SECP256R1_POINT *R, const SECP256R1_POINT *P);
|
||||
void secp256r1_point_add(SECP256R1_POINT *R, const SECP256R1_POINT *P, const SECP256R1_POINT *Q);
|
||||
void secp256r1_point_neg(SECP256R1_POINT *R, const SECP256R1_POINT *P);
|
||||
void secp256r1_point_sub(SECP256R1_POINT *R, const SECP256R1_POINT *P, const SECP256R1_POINT *Q);
|
||||
void secp256r1_point_mul(SECP256R1_POINT *R, const secp256r1_t k, const SECP256R1_POINT *P);
|
||||
void secp256r1_point_mul_generator(SECP256R1_POINT *R, const secp256r1_t k);
|
||||
int secp256r1_point_print(FILE *fp, int fmt, int ind, const char *label, const SECP256R1_POINT *P);
|
||||
int secp256r1_point_to_uncompressed_octets(const SECP256R1_POINT *P, uint8_t octets[65]);
|
||||
int secp256r1_point_from_uncompressed_octets(SECP256R1_POINT *P, const uint8_t octets[65]);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
56
include/gmssl/secp256r1_key.h
Normal file
56
include/gmssl/secp256r1_key.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
#ifndef GMSSL_SECP256R1_KEY_H
|
||||
#define GMSSL_SECP256R1_KEY_H
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/secp256r1.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
SECP256R1_POINT public_key;
|
||||
secp256r1_t private_key;
|
||||
} SECP256R1_KEY;
|
||||
|
||||
int secp256r1_key_generate(SECP256R1_KEY *key);
|
||||
int secp256r1_key_set_private_key(SECP256R1_KEY *key, const secp256r1_t private_key);
|
||||
int secp256r1_public_key_equ(const SECP256R1_KEY *key, const SECP256R1_KEY *pub);
|
||||
void secp256r1_key_cleanup(SECP256R1_KEY *key);
|
||||
|
||||
int secp256r1_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SECP256R1_KEY *key);
|
||||
int secp256r1_private_key_print(FILE *fp, int fmt, int ind, const char *label, const SECP256R1_KEY *key);
|
||||
|
||||
int secp256r1_public_key_to_bytes(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen);
|
||||
int secp256r1_public_key_from_bytes(SECP256R1_KEY *key, const uint8_t **in, size_t *inlen);
|
||||
int secp256r1_public_key_to_der(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen);
|
||||
int secp256r1_public_key_from_der(SECP256R1_KEY *key, const uint8_t **in, size_t *inlen);
|
||||
int secp256r1_private_key_to_der(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen);
|
||||
int secp256r1_private_key_from_der(SECP256R1_KEY *key, const uint8_t **in, size_t *inlen);
|
||||
int secp256r1_private_key_info_to_der(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen);
|
||||
int secp256r1_private_key_info_from_der(SECP256R1_KEY *key, const uint8_t **attrs, size_t *attrslen,
|
||||
const uint8_t **in, size_t *inlen);
|
||||
int secp256r1_private_key_info_encrypt_to_der(const SECP256R1_KEY *ec_key, const char *pass,
|
||||
uint8_t **out, size_t *outlen);
|
||||
int secp256r1_private_key_info_decrypt_from_der(SECP256R1_KEY *ec_key,
|
||||
const uint8_t **attrs, size_t *attrs_len,
|
||||
const char *pass, const uint8_t **in, size_t *inlen);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -752,6 +752,11 @@ typedef struct {
|
||||
BLOCK_CIPHER_KEY server_write_key;
|
||||
|
||||
int quiet;
|
||||
|
||||
// handshake state for state machine
|
||||
int state;
|
||||
SM3_CTX sm3_ctx;
|
||||
SM2_SIGN_CTX sign_ctx;
|
||||
} TLS_CONNECT;
|
||||
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <gmssl/oid.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/secp256r1_key.h>
|
||||
#include <gmssl/ecdsa.h>
|
||||
#include <gmssl/lms.h>
|
||||
#include <gmssl/xmss.h>
|
||||
#include <gmssl/sphincs.h>
|
||||
@@ -51,11 +53,13 @@ typedef struct {
|
||||
XMSS_KEY xmss_key;
|
||||
XMSSMT_KEY xmssmt_key;
|
||||
SPHINCS_KEY sphincs_key;
|
||||
SECP256R1_KEY secp256r1_key;
|
||||
} u;
|
||||
} X509_KEY;
|
||||
|
||||
|
||||
int x509_key_set_sm2_key(X509_KEY *x509_key, const SM2_KEY *sm2_key);
|
||||
int x509_key_set_secp256r1_key(X509_KEY *x509_key, const SECP256R1_KEY *secp256r1_key);
|
||||
int x509_key_set_lms_key(X509_KEY *x509_key, const LMS_KEY *lms_key);
|
||||
int x509_key_set_hss_key(X509_KEY *x509_key, const HSS_KEY *hss_key);
|
||||
int x509_key_set_xmss_key(X509_KEY *x509_key, const XMSS_KEY *xmss_key);
|
||||
@@ -107,6 +111,7 @@ typedef union {
|
||||
typedef struct {
|
||||
union {
|
||||
SM2_SIGN_CTX sm2_sign_ctx;
|
||||
ECDSA_SIGN_CTX ecdsa_sign_ctx;
|
||||
SM2_VERIFY_CTX sm2_verify_ctx;
|
||||
HSS_SIGN_CTX hss_sign_ctx;
|
||||
XMSS_SIGN_CTX xmss_sign_ctx;
|
||||
|
||||
379
src/bn.c
Normal file
379
src/bn.c
Normal file
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <gmssl/endian.h>
|
||||
|
||||
|
||||
void bn_set_word(uint32_t *r, uint32_t a, size_t k)
|
||||
{
|
||||
r[0] = a;
|
||||
while (k-- > 1) {
|
||||
r[k] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void bn_copy(uint32_t *r, const uint32_t *a, size_t k)
|
||||
{
|
||||
while (k-- > 0) {
|
||||
r[k] = a[k];
|
||||
}
|
||||
}
|
||||
|
||||
int bn_cmp(const uint32_t *a, const uint32_t *b, size_t k)
|
||||
{
|
||||
while (k-- > 0) {
|
||||
if (a[k] > b[k]) return 1;
|
||||
else if (a[k] < b[k]) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bn_is_zero(const uint32_t *a, size_t k)
|
||||
{
|
||||
while (k-- > 0) {
|
||||
if (a[k]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bn_is_one(const uint32_t *a, size_t k)
|
||||
{
|
||||
if (a[0] != 1) {
|
||||
return 0;
|
||||
}
|
||||
while (k-- > 1) {
|
||||
if (a[k]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bn_add(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k)
|
||||
{
|
||||
uint64_t w = 0;
|
||||
size_t i;
|
||||
for (i = 0; i < k; i++) {
|
||||
w += (uint64_t)a[i] + (uint64_t)b[i];
|
||||
r[i] = w & 0xffffffff;
|
||||
w >>= 32;
|
||||
}
|
||||
return (int)w;
|
||||
}
|
||||
|
||||
int bn_sub(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k)
|
||||
{
|
||||
int64_t w = 0;
|
||||
size_t i;
|
||||
for (i = 0; i < k; i++) {
|
||||
w += (int64_t)a[i] - (int64_t)b[i];
|
||||
r[i] = w & 0xffffffff;
|
||||
w >>= 32;
|
||||
}
|
||||
return (int)w;
|
||||
}
|
||||
|
||||
void bn_mul(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k)
|
||||
{
|
||||
uint64_t w;
|
||||
size_t i, j;
|
||||
for (i = 0; i < k; i++) {
|
||||
r[i] = 0;
|
||||
}
|
||||
for (i = 0; i < k; i++) {
|
||||
w = 0;
|
||||
for (j = 0; j < k; j++) {
|
||||
w += (uint64_t)r[i + j] + (uint64_t)a[i] * (uint64_t)b[j];
|
||||
r[i + j] = w & 0xffffffff;
|
||||
w >>= 32;
|
||||
}
|
||||
r[i + k] = w;
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mul_lo(uint32_t *r, const uint32_t *a, const uint32_t *b, size_t k)
|
||||
{
|
||||
uint64_t w;
|
||||
size_t i, j;
|
||||
for (i = 0; i < k; i++) {
|
||||
r[i] = 0;
|
||||
}
|
||||
for (i = 0; i < k; i++) {
|
||||
w = 0;
|
||||
for (j = 0; j < k - i; j++) {
|
||||
w += (uint64_t)r[i + j] + (uint64_t)a[i] * (uint64_t)b[j];
|
||||
r[i + j] = w & 0xffffffff;
|
||||
w >>= 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bn_to_bytes(const uint32_t *a, size_t k, uint8_t *out)
|
||||
{
|
||||
while (k-- > 0) {
|
||||
PUTU32(out, a[k]);
|
||||
out += 4;
|
||||
}
|
||||
}
|
||||
|
||||
void bn_from_bytes(uint32_t *a, size_t k, const uint8_t *in)
|
||||
{
|
||||
while (k-- > 0) {
|
||||
a[k] = GETU32(in);
|
||||
in += 4;
|
||||
}
|
||||
}
|
||||
|
||||
int bn_print(FILE *fp, int fmt, int ind, const char *label, const uint32_t *a, size_t k)
|
||||
{
|
||||
fprintf(fp, "%s: ", label);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < k; i++) {
|
||||
fprintf(fp, "0x%08x, ", a[i]);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
|
||||
while (k-- > 0) {
|
||||
fprintf(fp, "%08x", a[k]);
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void bn_mod_add(uint32_t *r, const uint32_t *a, const uint32_t *b, const uint32_t *p, size_t k)
|
||||
{
|
||||
int carry;
|
||||
carry = bn_add(r, a, b, k);
|
||||
|
||||
if (carry) {
|
||||
bn_sub(r, r, p, k);
|
||||
} else if (bn_cmp(r, p, k) >= 0) {
|
||||
bn_sub(r, r, p, k);
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mod_sub(uint32_t *r, const uint32_t *a, const uint32_t *b, const uint32_t *p, size_t k)
|
||||
{
|
||||
if (bn_cmp(a, b, k) >= 0) {
|
||||
bn_sub(r, a, b, k);
|
||||
} else {
|
||||
bn_sub(r, b, a, k);
|
||||
bn_sub(r, p, r, k);
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mod_neg(uint32_t *r, const uint32_t *a, const uint32_t *p, size_t k)
|
||||
{
|
||||
bn_sub(r, p, a, k);
|
||||
}
|
||||
|
||||
void bn_barrett_mod_mul(uint32_t *r, // uint32_t r[k] = a * b mod p
|
||||
const uint32_t *a, // uint32_t a[k]
|
||||
const uint32_t *b, // uint32_t b[k]
|
||||
const uint32_t *p, // uint32_t p[k]
|
||||
const uint32_t *u, // uint32_t u[k + 1] = floor((2^32)^(2*k) / p)
|
||||
uint32_t *tmp, // uint32_t tmp[6*k + 4]
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *p_; // uint32_t p_[k + 1];
|
||||
uint32_t *z; // uint32_t z[2 * k];
|
||||
uint32_t *q; // uint32_t q[2 * (k + 1)];
|
||||
uint32_t *t_; // uint32_t t_[k + 1];
|
||||
size_t i;
|
||||
|
||||
p_ = tmp; tmp += k + 1;
|
||||
z = tmp; tmp += 2 * k;
|
||||
q = tmp; tmp += 2 * (k + 1);
|
||||
t_ = tmp; tmp += k + 1;
|
||||
|
||||
for (i = 0; i < k; i++) {
|
||||
p_[i] = p[i];
|
||||
}
|
||||
p_[k] = 0;
|
||||
|
||||
bn_mul(z, a, b, k);
|
||||
bn_mul(q, z + k - 1, u, k + 1);
|
||||
bn_mul_lo(t_, q + k + 1, p_, k + 1);
|
||||
bn_sub(t_, z, t_, k + 1);
|
||||
|
||||
// reduce at most twice
|
||||
if (bn_cmp(t_, p_, k + 1) >= 0) {
|
||||
bn_sub(t_, t_, p_, k + 1);
|
||||
}
|
||||
if (bn_cmp(t_, p_, k) >= 0) {
|
||||
bn_sub(t_, t_, p_, k);
|
||||
}
|
||||
bn_copy(r, t_, k);
|
||||
}
|
||||
|
||||
void bn_barrett_mod_sqr(uint32_t *r, const uint32_t *a, const uint32_t *p,
|
||||
const uint32_t *u, // uint32_t u[k + 1]
|
||||
uint32_t *tmp, // uint32_t tmp[6*k + 4]
|
||||
size_t k)
|
||||
{
|
||||
bn_barrett_mod_mul(r, a, a, p, u, tmp, k);
|
||||
}
|
||||
|
||||
void bn_barrett_mod_exp(uint32_t *r, const uint32_t *a, const uint32_t *e, const uint32_t *p,
|
||||
const uint32_t *u, //
|
||||
uint32_t *tmp, // uint32_t tmp[7*k + 4]
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *t; // uint32_t t[k];
|
||||
uint32_t w;
|
||||
int i, j;
|
||||
|
||||
// t = 1
|
||||
t = tmp; tmp += k;
|
||||
bn_set_word(t, 1, k);
|
||||
|
||||
for (i = k - 1; i >= 0; i--) {
|
||||
w = e[i];
|
||||
for (j = 0; j < 32; j++) {
|
||||
bn_barrett_mod_sqr(t, t, p, u, tmp, k);
|
||||
if (w & 0x80000000) {
|
||||
bn_barrett_mod_mul(t, t, a, p, u, tmp, k);
|
||||
}
|
||||
w <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
bn_copy(r, t, k);
|
||||
}
|
||||
|
||||
// FIXME: 如果 a = 0 (mod p) 会发生什么
|
||||
void bn_barrett_mod_inv(uint32_t *r, const uint32_t *a, const uint32_t *p, const uint32_t *u,
|
||||
uint32_t *tmp, // uint32_t tmp[8*k + 4]
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *e; // uint32_t e[k];
|
||||
|
||||
// e = p - 2
|
||||
e = tmp; tmp += k;
|
||||
bn_set_word(e, 2, k);
|
||||
bn_sub(e, p, e, k);
|
||||
|
||||
// a^-1 = a^(p - 2) (mod p)
|
||||
bn_barrett_mod_exp(r, a, e, p, u, tmp, k);
|
||||
}
|
||||
|
||||
// mont(aR, bR) = aR * bR * R^-1 = abR (mod p)
|
||||
void bn_mont_mod_mul(uint32_t *r, const uint32_t *a, const uint32_t *b, const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *z; // uint32_t z[k * 2];
|
||||
uint32_t *c; // uint32_t c[k * 2];
|
||||
uint32_t *t; // uint32_t t[k];
|
||||
|
||||
z = tmp; tmp += 2 * k;
|
||||
c = tmp; tmp += 2 * k;
|
||||
t = tmp; tmp += k;
|
||||
|
||||
bn_mul(z, a, b, k);
|
||||
bn_mul_lo(t, z, p_inv_neg, k);
|
||||
bn_mul(c, t, p, k);
|
||||
bn_add(c, c, z, k * 2);
|
||||
if (bn_cmp(c + k, p, k) >= 0) {
|
||||
bn_sub(c + k, c + k, p, k);
|
||||
}
|
||||
|
||||
bn_copy(r, c + k, k);
|
||||
}
|
||||
|
||||
void bn_mont_mod_sqr(uint32_t *r, const uint32_t *a, const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k)
|
||||
{
|
||||
bn_mont_mod_mul(r, a, a, p, p_inv_neg, tmp, k);
|
||||
}
|
||||
|
||||
void bn_mont_mod_exp(
|
||||
uint32_t *r,
|
||||
const uint32_t *a,
|
||||
const uint32_t *e,
|
||||
const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[6 * k];
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *t; // uint32_t t[k];
|
||||
uint32_t w;
|
||||
int i, j;
|
||||
|
||||
// t = 1
|
||||
t = tmp; tmp += k;
|
||||
bn_set_word(t, 1, k);
|
||||
|
||||
for (i = k - 1; i >= 0; i--) {
|
||||
w = e[i];
|
||||
for (j = 0; j < 32; j++) {
|
||||
bn_mont_mod_sqr(t, t, p, p_inv_neg, tmp, k);
|
||||
if (w & 0x80000000) {
|
||||
bn_mont_mod_mul(t, t, a, p, p_inv_neg, tmp, k);
|
||||
}
|
||||
w <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
bn_copy(r, t, k);
|
||||
}
|
||||
|
||||
// FIXME: 如果 a = 0 (mod p) 会发生什么
|
||||
void bn_mont_mod_inv(uint32_t *r, const uint32_t *a, const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[7 * k];
|
||||
size_t k)
|
||||
{
|
||||
uint32_t *e; // uint32_t e[k];
|
||||
|
||||
// e = p - 2
|
||||
e = tmp; tmp += k;
|
||||
bn_set_word(e, 2, k);
|
||||
bn_sub(e, p, e, k);
|
||||
|
||||
// a^-1 = a^(p - 2) (mod p)
|
||||
bn_mont_mod_exp(r, a, e, p, p_inv_neg, tmp, k);
|
||||
}
|
||||
|
||||
// mont(a, R^2) = a * R^2 * R^-1 = a * R mod p
|
||||
void bn_mont_set(uint32_t *r,
|
||||
const uint32_t *a,
|
||||
const uint32_t *R_sqr,
|
||||
const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k)
|
||||
{
|
||||
bn_mont_mod_mul(r, a, R_sqr, p, p_inv_neg, tmp, k);
|
||||
}
|
||||
|
||||
// mont(aR, 1) = aR * 1 * R^-1 = a (mod p)
|
||||
void bn_mont_get(uint32_t *r,
|
||||
const uint32_t *a,
|
||||
const uint32_t *p,
|
||||
const uint32_t *p_inv_neg,
|
||||
uint32_t *tmp, // uint32_t tmp[5 * k]
|
||||
size_t k)
|
||||
{
|
||||
uint32_t one[k];
|
||||
bn_set_word(one, 1, k);
|
||||
bn_mont_mod_mul(r, a, one, p, p_inv_neg, tmp, k);
|
||||
}
|
||||
|
||||
12
src/ecdh.c
Normal file
12
src/ecdh.c
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
387
src/ecdsa.c
Normal file
387
src/ecdsa.c
Normal file
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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/asn1.h>
|
||||
#include <gmssl/sha2.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/ecdsa.h>
|
||||
#include <gmssl/bn.h>
|
||||
#include <gmssl/sm2.h>
|
||||
|
||||
|
||||
int ecdsa_signature_print_ex(FILE *fp, int fmt, int ind, const char *label, const ECDSA_SIGNATURE *sig)
|
||||
{
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
secp256r1_print(fp, fmt, ind, "r", sig->r);
|
||||
secp256r1_print(fp, fmt, ind, "s", sig->s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sigbuf, size_t siglen)
|
||||
{
|
||||
ECDSA_SIGNATURE sig;
|
||||
|
||||
if (ecdsa_signature_from_der(&sig, &sigbuf, &siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ecdsa_signature_print_ex(fp, fmt, ind, label, &sig);
|
||||
if (siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_do_sign_ex(const SECP256R1_KEY *key, const secp256r1_t k, const uint8_t dgst[32], ECDSA_SIGNATURE *sig)
|
||||
{
|
||||
secp256r1_t e;
|
||||
secp256r1_t x1;
|
||||
secp256r1_t y1;
|
||||
secp256r1_t k_inv;
|
||||
SECP256R1_POINT P;
|
||||
|
||||
// e = hash(m)
|
||||
secp256r1_from_32bytes(e, dgst);
|
||||
secp256r1_modn(e, e);
|
||||
|
||||
// (x1, y1) = k*G
|
||||
secp256r1_point_mul_generator(&P, k);
|
||||
secp256r1_point_get_xy(&P, x1, y1);
|
||||
|
||||
// r = x1 mod n
|
||||
secp256r1_modn(sig->r, x1);
|
||||
|
||||
// s = k^-1 * (e + d * r) mod n
|
||||
secp256r1_modn_inv(k_inv, k);
|
||||
secp256r1_modn_mul(sig->s, key->private_key, sig->r);
|
||||
secp256r1_modn_add(sig->s, sig->s, e);
|
||||
secp256r1_modn_mul(sig->s, sig->s, k_inv);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_do_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], ECDSA_SIGNATURE *sig)
|
||||
{
|
||||
secp256r1_t k;
|
||||
|
||||
// rand k in [1, n-1]
|
||||
do {
|
||||
if (rand_bytes((uint8_t *)k, sizeof(k)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (secp256r1_is_zero(k) || secp256r1_cmp(k, SECP256R1_N) >= 0);
|
||||
|
||||
if (ecdsa_do_sign_ex(key, k, dgst, sig) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ecdsa_do_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const ECDSA_SIGNATURE *sig)
|
||||
{
|
||||
secp256r1_t e;
|
||||
secp256r1_t w;
|
||||
secp256r1_t u1;
|
||||
secp256r1_t u2;
|
||||
secp256r1_t x1;
|
||||
secp256r1_t y1;
|
||||
SECP256R1_POINT P;
|
||||
SECP256R1_POINT Q;
|
||||
SECP256R1_POINT R;
|
||||
|
||||
// check r, s in [1, n-1]
|
||||
if (secp256r1_is_zero(sig->r)
|
||||
|| secp256r1_cmp(sig->r, SECP256R1_N) >= 0
|
||||
|| secp256r1_is_zero(sig->s)
|
||||
|| secp256r1_cmp(sig->s, SECP256R1_N) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// e = hash(m)
|
||||
secp256r1_from_32bytes(e, dgst);
|
||||
secp256r1_modn(e, e);
|
||||
|
||||
// w = s^-1 (mod n)
|
||||
secp256r1_modn_inv(w, sig->s);
|
||||
|
||||
// u1 = e * w (mod n)
|
||||
secp256r1_modn_mul(u1, e, w);
|
||||
|
||||
// u2 = r * w (mod n)
|
||||
secp256r1_modn_mul(u2, sig->r, w);
|
||||
|
||||
// (x1, y1) = u1*G + u2*Q
|
||||
secp256r1_point_mul_generator(&P, u1);
|
||||
secp256r1_point_mul(&Q, u2, &key->public_key);
|
||||
secp256r1_point_add(&R, &P, &Q);
|
||||
secp256r1_point_get_xy(&R, x1, y1);
|
||||
|
||||
// x1 = x1 mod n
|
||||
secp256r1_modn(x1, x1);
|
||||
|
||||
if (secp256r1_cmp(x1, sig->r) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_signature_to_der(const ECDSA_SIGNATURE *sig, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
size_t len = 0;
|
||||
uint8_t r[32];
|
||||
uint8_t s[32];
|
||||
|
||||
if (!sig) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
secp256r1_to_32bytes(sig->r, r);
|
||||
secp256r1_to_32bytes(sig->s, s);
|
||||
|
||||
if (asn1_integer_to_der(r, 32, NULL, &len) != 1
|
||||
|| asn1_integer_to_der(s, 32, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_integer_to_der(r, 32, out, outlen) != 1
|
||||
|| asn1_integer_to_der(s, 32, out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_signature_from_der(ECDSA_SIGNATURE *sig, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
const uint8_t *r;
|
||||
const uint8_t *s;
|
||||
size_t dlen, rlen, slen;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (asn1_integer_from_der(&r, &rlen, &d, &dlen) != 1
|
||||
|| asn1_integer_from_der(&s, &slen, &d, &dlen) != 1
|
||||
|| asn1_length_le(rlen, 32) != 1
|
||||
|| asn1_length_le(slen, 32) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_from_32bytes(sig->r, r);
|
||||
secp256r1_from_32bytes(sig->s, s);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_sign(const SECP256R1_KEY *key, const uint8_t dgst[32], uint8_t *sigbuf, size_t *siglen)
|
||||
{
|
||||
ECDSA_SIGNATURE sig;
|
||||
|
||||
if (ecdsa_do_sign(key, dgst, &sig) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*siglen = 0;
|
||||
if (ecdsa_signature_to_der(&sig, &sigbuf, siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_sign_fixlen(const SECP256R1_KEY *key, const uint8_t dgst[32], size_t siglen, uint8_t *sig)
|
||||
{
|
||||
unsigned int trys = 200;
|
||||
uint8_t buf[ECDSA_SIGNATURE_MAX_SIZE];
|
||||
size_t len;
|
||||
|
||||
switch (siglen) {
|
||||
case ECDSA_SIGNATURE_COMPACT_SIZE:
|
||||
case ECDSA_SIGNATURE_TYPICAL_SIZE:
|
||||
case ECDSA_SIGNATURE_MAX_SIZE:
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (trys--) {
|
||||
if (ecdsa_sign(key, dgst, buf, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (len == siglen) {
|
||||
memcpy(sig, buf, len);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// might caused by bad randomness
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int ecdsa_verify(const SECP256R1_KEY *key, const uint8_t dgst[32], const uint8_t *sigbuf, size_t siglen)
|
||||
{
|
||||
int ret;
|
||||
ECDSA_SIGNATURE sig;
|
||||
|
||||
if (ecdsa_signature_from_der(&sig, &sigbuf, &siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if ((ret = ecdsa_do_verify(key, dgst, &sig)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ecdsa_sign_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key)
|
||||
{
|
||||
if (!ctx || !key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(ctx, 0, sizeof(ECDSA_SIGN_CTX));
|
||||
|
||||
ctx->key = *key;
|
||||
|
||||
sha256_init(&ctx->sha256_ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_sign_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
||||
{
|
||||
if (!ctx) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (data && datalen) {
|
||||
sha256_update(&ctx->sha256_ctx, data, datalen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_sign_finish(ECDSA_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen)
|
||||
{
|
||||
uint8_t dgst[32];
|
||||
|
||||
if (!ctx || !sig || !siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sha256_finish(&ctx->sha256_ctx, dgst);
|
||||
|
||||
if (ecdsa_sign(&ctx->key, dgst, sig, siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ecdsa_sign_finish_fixlen(ECDSA_SIGN_CTX *ctx, size_t siglen, uint8_t *sig)
|
||||
{
|
||||
uint8_t dgst[32];
|
||||
|
||||
if (!ctx || !sig || !siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sha256_finish(&ctx->sha256_ctx, dgst);
|
||||
|
||||
if (ecdsa_sign_fixlen(&ctx->key, dgst, siglen, sig) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int ecdsa_verify_init(ECDSA_SIGN_CTX *ctx, const SECP256R1_KEY *key, const uint8_t *sig, size_t siglen)
|
||||
{
|
||||
if (!ctx || !key || !sig || !siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ecdsa_signature_from_der(&ctx->sig, &sig, &siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->key = *key;
|
||||
|
||||
sha256_init(&ctx->sha256_ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ecdsa_verify_update(ECDSA_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
||||
{
|
||||
if (!ctx) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (data && datalen) {
|
||||
sha256_update(&ctx->sha256_ctx, data, datalen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ecdsa_verify_finish(ECDSA_SIGN_CTX *ctx)
|
||||
{
|
||||
uint8_t dgst[32];
|
||||
int ret;
|
||||
|
||||
if (!ctx) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sha256_finish(&ctx->sha256_ctx, dgst);
|
||||
|
||||
if ((ret = ecdsa_do_verify(&ctx->key, dgst, &ctx->sig)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
593
src/secp256r1.c
Normal file
593
src/secp256r1.c
Normal file
@@ -0,0 +1,593 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <gmssl/bn.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/secp256r1.h>
|
||||
|
||||
|
||||
const secp256r1_t SECP256R1_P = {
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000001, 0xffffffff,
|
||||
};
|
||||
|
||||
const secp256r1_t SECP256R1_B = {
|
||||
0x27d2604b, 0x3bce3c3e, 0xcc53b0f6, 0x651d06b0,
|
||||
0x769886bc, 0xb3ebbd55, 0xaa3a93e7, 0x5ac635d8,
|
||||
};
|
||||
|
||||
const secp256r1_t SECP256R1_N = {
|
||||
0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad,
|
||||
0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
|
||||
};
|
||||
|
||||
const uint32_t SECP256R1_U_P[9] = {
|
||||
0x00000003, 0x00000000, 0xffffffff, 0xfffffffe,
|
||||
0xfffffffe, 0xfffffffe, 0xffffffff, 0x00000000,
|
||||
0x00000001,
|
||||
};
|
||||
|
||||
const uint32_t SECP256R1_U_N[9] = {
|
||||
0xeedf9bfe, 0x012ffd85, 0xdf1a6c21, 0x43190552,
|
||||
0xffffffff, 0xfffffffe, 0xffffffff, 0x00000000,
|
||||
0x00000001,
|
||||
};
|
||||
|
||||
int secp256r1_is_zero(const secp256r1_t a) {
|
||||
return bn_is_zero(a, SECP256R1_K);
|
||||
}
|
||||
|
||||
int secp256r1_is_one(const secp256r1_t a) {
|
||||
return bn_is_one(a, SECP256R1_K);
|
||||
}
|
||||
|
||||
int secp256r1_cmp(const secp256r1_t a, const secp256r1_t b) {
|
||||
return bn_cmp(a, b, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_set_zero(secp256r1_t r) {
|
||||
bn_set_word(r, 0, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_set_one(secp256r1_t r) {
|
||||
bn_set_word(r, 1, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_copy(secp256r1_t r, const secp256r1_t a) {
|
||||
bn_copy(r, a, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_to_32bytes(const secp256r1_t a, uint8_t out[32]) {
|
||||
bn_to_bytes(a, SECP256R1_K, out);
|
||||
}
|
||||
|
||||
void secp256r1_from_32bytes(secp256r1_t r, const uint8_t in[32]) {
|
||||
bn_from_bytes(r, SECP256R1_K, in);
|
||||
}
|
||||
|
||||
int secp256r1_print(FILE *fp, int fmt, int ind, const char *label, const secp256r1_t a) {
|
||||
uint8_t bytes[32];
|
||||
secp256r1_to_32bytes(a, bytes);
|
||||
format_bytes(fp, fmt, ind, label, bytes, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void secp256r1_modp_add(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
bn_mod_add(r, a, b, SECP256R1_P, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_dbl(secp256r1_t r, const secp256r1_t a) {
|
||||
bn_mod_add(r, a, a, SECP256R1_P, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_tri(secp256r1_t r, const secp256r1_t a) {
|
||||
secp256r1_t tmp;
|
||||
|
||||
// 这里就出错了,真是太奇怪了!
|
||||
bn_mod_add(tmp, a, a, SECP256R1_P, SECP256R1_K);
|
||||
bn_mod_add(r, tmp, a, SECP256R1_P, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_sub(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
bn_mod_sub(r, a, b, SECP256R1_P, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_neg(secp256r1_t r, const secp256r1_t a) {
|
||||
bn_mod_neg(r, a, SECP256R1_P, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_haf(secp256r1_t r, const secp256r1_t a) {
|
||||
int c = 0;
|
||||
if (a[0] & 1) {
|
||||
c = bn_add(r, a, SECP256R1_P, SECP256R1_K);
|
||||
} else {
|
||||
bn_copy(r, a, SECP256R1_K);
|
||||
}
|
||||
|
||||
r[0] = (r[0] >> 1) | ((r[1] & 1) << 31);
|
||||
r[1] = (r[1] >> 1) | ((r[2] & 1) << 31);
|
||||
r[2] = (r[2] >> 1) | ((r[3] & 1) << 31);
|
||||
r[3] = (r[3] >> 1) | ((r[4] & 1) << 31);
|
||||
r[4] = (r[4] >> 1) | ((r[5] & 1) << 31);
|
||||
r[5] = (r[5] >> 1) | ((r[6] & 1) << 31);
|
||||
r[6] = (r[6] >> 1) | ((r[7] & 1) << 31);
|
||||
r[7] = (r[7] >> 1) | ((c & 1) << 31);
|
||||
}
|
||||
|
||||
void secp256r1_modp_mul(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
uint32_t tmp[6*8 + 4];
|
||||
bn_barrett_mod_mul(r, a, b, SECP256R1_P, SECP256R1_U_P, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_sqr(secp256r1_t r, const secp256r1_t a) {
|
||||
uint32_t tmp[6*8 + 4];
|
||||
bn_barrett_mod_mul(r, a, a, SECP256R1_P, SECP256R1_U_P, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modp_exp(secp256r1_t r, const secp256r1_t a, const secp256r1_t e) {
|
||||
uint32_t tmp[7*8 + 4];
|
||||
bn_barrett_mod_exp(r, a, e, SECP256R1_P, SECP256R1_U_P, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
// FIXME: 如果 a = 0 (mod p) 会发生什么
|
||||
void secp256r1_modp_inv(secp256r1_t r, const secp256r1_t a) {
|
||||
uint32_t tmp[8*8 + 4];
|
||||
bn_barrett_mod_inv(r, a, SECP256R1_P, SECP256R1_U_P, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
|
||||
void secp256r1_modn(secp256r1_t r, const secp256r1_t a) {
|
||||
if (bn_cmp(a, SECP256R1_N, SECP256R1_K) >= 0) {
|
||||
bn_sub(r, a, SECP256R1_N, SECP256R1_K);
|
||||
} else {
|
||||
bn_copy(r, a, SECP256R1_K);
|
||||
}
|
||||
}
|
||||
|
||||
void secp256r1_modn_add(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
bn_mod_add(r, a, b, SECP256R1_N, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_dbl(secp256r1_t r, const secp256r1_t a) {
|
||||
bn_mod_add(r, a, a, SECP256R1_N, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_tri(secp256r1_t r, const secp256r1_t a) {
|
||||
secp256r1_t tmp;
|
||||
bn_mod_add(tmp, a, a, SECP256R1_N, SECP256R1_K);
|
||||
bn_mod_add(r, tmp, a, SECP256R1_N, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_sub(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
bn_mod_sub(r, a, b, SECP256R1_N, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_neg(secp256r1_t r, const secp256r1_t a) {
|
||||
bn_mod_neg(r, a, SECP256R1_N, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_mul(secp256r1_t r, const secp256r1_t a, const secp256r1_t b) {
|
||||
uint32_t tmp[6*8 + 4];
|
||||
bn_barrett_mod_mul(r, a, b, SECP256R1_N, SECP256R1_U_N, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_sqr(secp256r1_t r, const secp256r1_t a) {
|
||||
uint32_t tmp[6*8 + 4];
|
||||
bn_barrett_mod_mul(r, a, a, SECP256R1_N, SECP256R1_U_N, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
void secp256r1_modn_exp(secp256r1_t r, const secp256r1_t a, const secp256r1_t e) {
|
||||
uint32_t tmp[7*8 + 4];
|
||||
bn_barrett_mod_exp(r, a, e, SECP256R1_N, SECP256R1_U_N, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
// FIXME: 如果 a = 0 (mod p) 会发生什么
|
||||
void secp256r1_modn_inv(secp256r1_t r, const secp256r1_t a) {
|
||||
uint32_t tmp[8*8 + 4];
|
||||
bn_barrett_mod_inv(r, a, SECP256R1_N, SECP256R1_U_N, tmp, SECP256R1_K);
|
||||
}
|
||||
|
||||
|
||||
const SECP256R1_POINT SECP256R1_POINT_G = {
|
||||
{ 0xd898c296, 0xf4a13945, 0x2deb33a0, 0x77037d81,
|
||||
0x63a440f2, 0xf8bce6e5, 0xe12c4247, 0x6b17d1f2, },
|
||||
{ 0x37bf51f5, 0xcbb64068, 0x6b315ece, 0x2bce3357,
|
||||
0x7c0f9e16, 0x8ee7eb4a, 0xfe1a7f9b, 0x4fe342e2, },
|
||||
{ 1,0,0,0,0,0,0,0, },
|
||||
};
|
||||
|
||||
void secp256r1_point_set_infinity(SECP256R1_POINT *R)
|
||||
{
|
||||
secp256r1_set_one(R->X);
|
||||
secp256r1_set_one(R->Y);
|
||||
secp256r1_set_zero(R->Z);
|
||||
}
|
||||
|
||||
int secp256r1_point_is_at_infinity(const SECP256R1_POINT *P)
|
||||
{
|
||||
if (secp256r1_is_zero(P->Z)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int secp256r1_point_is_on_curve(const SECP256R1_POINT *P)
|
||||
{
|
||||
secp256r1_t t0;
|
||||
secp256r1_t t1;
|
||||
secp256r1_t t2;
|
||||
|
||||
if (secp256r1_point_is_at_infinity(P)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check Y^2 + 3 * X * Z^4 == X^3 + b * Z^6
|
||||
|
||||
// t0 = Y^2
|
||||
secp256r1_modp_sqr(t0, P->Y);
|
||||
|
||||
// t1 = Z^2
|
||||
secp256r1_modp_sqr(t1, P->Z);
|
||||
|
||||
// t2 = Z^4
|
||||
secp256r1_modp_sqr(t2, t1);
|
||||
|
||||
// t1 = Z^6
|
||||
secp256r1_modp_mul(t1, t1, t2);
|
||||
|
||||
// t1 = b * Z^6
|
||||
secp256r1_modp_mul(t1, t1, SECP256R1_B);
|
||||
|
||||
// t2 = X * Z^4
|
||||
secp256r1_modp_mul(t2, t2, P->X);
|
||||
|
||||
// t0 = Y^2 + 3 * X * Z^4
|
||||
secp256r1_modp_add(t0, t0, t2);
|
||||
secp256r1_modp_add(t0, t0, t2);
|
||||
secp256r1_modp_add(t0, t0, t2);
|
||||
|
||||
// t2 = X^2
|
||||
secp256r1_modp_sqr(t2, P->X);
|
||||
|
||||
// t2 = X^3
|
||||
secp256r1_modp_mul(t2, t2, P->X);
|
||||
|
||||
// t1 = b * Z^6 + X^3
|
||||
secp256r1_modp_add(t1, t1, t2);
|
||||
|
||||
if (secp256r1_cmp(t0, t1) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void secp256r1_point_copy(SECP256R1_POINT *R, const SECP256R1_POINT *P)
|
||||
{
|
||||
secp256r1_copy(R->X, P->X);
|
||||
secp256r1_copy(R->Y, P->Y);
|
||||
secp256r1_copy(R->Z, P->Z);
|
||||
}
|
||||
|
||||
int secp256r1_point_set_xy(SECP256R1_POINT *R, const secp256r1_t x, const secp256r1_t y)
|
||||
{
|
||||
if (secp256r1_cmp(x, SECP256R1_P) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_cmp(y, SECP256R1_P) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
secp256r1_copy(R->X, x);
|
||||
secp256r1_copy(R->Y, y);
|
||||
secp256r1_set_one(R->Z);
|
||||
|
||||
|
||||
if (!secp256r1_point_is_on_curve(R)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_point_get_xy(const SECP256R1_POINT *P, secp256r1_t x, secp256r1_t y)
|
||||
{
|
||||
secp256r1_t Z_inv;
|
||||
|
||||
if (secp256r1_point_is_at_infinity(P)) {
|
||||
return 0;
|
||||
}
|
||||
secp256r1_modp_inv(Z_inv, P->Z);
|
||||
secp256r1_modp_mul(y, P->Y, Z_inv);
|
||||
secp256r1_modp_sqr(Z_inv, Z_inv);
|
||||
secp256r1_modp_mul(x, P->X, Z_inv);
|
||||
secp256r1_modp_mul(y, y, Z_inv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void secp256r1_point_dbl(SECP256R1_POINT *R, const SECP256R1_POINT *P)
|
||||
{
|
||||
/*
|
||||
secp256r1_t T_0;
|
||||
secp256r1_t T_1;
|
||||
secp256r1_t T_2;
|
||||
secp256r1_t T_3;
|
||||
secp256r1_t T_4;
|
||||
|
||||
if (secp256r1_point_is_at_infinity(P)) {
|
||||
secp256r1_point_set_infinity(R);
|
||||
return;
|
||||
}
|
||||
|
||||
secp256r1_modp_sqr(T_0, P->X);
|
||||
secp256r1_modp_tri(T_0, T_0);
|
||||
secp256r1_modp_sqr(T_1, T_0);
|
||||
secp256r1_modp_sqr(T_2, P->Y);
|
||||
secp256r1_modp_mul(T_3, P->X, T_2);
|
||||
secp256r1_modp_dbl(T_3, T_3);
|
||||
secp256r1_modp_dbl(T_3, T_3);
|
||||
secp256r1_modp_dbl(T_4, T_3);
|
||||
secp256r1_modp_sub(T_1, T_1, T_4);
|
||||
secp256r1_modp_sub(T_3, T_3, T_1);
|
||||
secp256r1_modp_mul(T_0, T_0, T_3);
|
||||
secp256r1_modp_dbl(T_2, T_2);
|
||||
secp256r1_modp_sqr(T_2, T_2);
|
||||
secp256r1_modp_dbl(T_2, T_2);
|
||||
secp256r1_modp_sub(T_0, T_0, T_2);
|
||||
secp256r1_modp_mul(T_2, P->Y, P->Z);
|
||||
secp256r1_modp_dbl(T_2, T_2);
|
||||
|
||||
secp256r1_copy(R->X, T_1);
|
||||
secp256r1_copy(R->Y, T_0);
|
||||
secp256r1_copy(R->Z, T_2);
|
||||
*/
|
||||
|
||||
const uint32_t *X1 = P->X;
|
||||
const uint32_t *Y1 = P->Y;
|
||||
const uint32_t *Z1 = P->Z;
|
||||
uint32_t *X3 = R->X;
|
||||
uint32_t *Y3 = R->Y;
|
||||
uint32_t *Z3 = R->Z;
|
||||
secp256r1_t S;
|
||||
secp256r1_t M;
|
||||
secp256r1_t Zsqr;
|
||||
secp256r1_t tmp0;
|
||||
|
||||
// 1. S = 2Y
|
||||
secp256r1_modp_dbl(S, Y1);
|
||||
|
||||
// 2. Zsqr = Z^2
|
||||
secp256r1_modp_sqr(Zsqr, Z1);
|
||||
|
||||
// 3. S = S^2 = 4Y^2
|
||||
secp256r1_modp_sqr(S, S);
|
||||
|
||||
// 4. Z = Z*Y
|
||||
secp256r1_modp_mul(Z3, Z1, Y1);
|
||||
|
||||
// 5. Z = 2*Z = 2*Y*Z ===> Z3
|
||||
secp256r1_modp_dbl(Z3, Z3);
|
||||
|
||||
// 6. M = X + Zsqr = X + Z^2
|
||||
secp256r1_modp_add(M, X1, Zsqr);
|
||||
|
||||
// 7. Zsqr = X - Zsqr = X - Z^2
|
||||
secp256r1_modp_sub(Zsqr, X1, Zsqr);
|
||||
|
||||
// 8. Y = S^2 = 16Y^4
|
||||
secp256r1_modp_sqr(Y3, S);
|
||||
|
||||
// 9. Y = Y/2 = 8Y^4
|
||||
secp256r1_modp_haf(Y3, Y3);
|
||||
|
||||
// 10. M = M * Zsqr = (X + Z^2)*(X - Z^2) = X^2 - Z^4
|
||||
secp256r1_modp_mul(M, M, Zsqr);
|
||||
|
||||
// 11. M = 3M = 3X^2 - 3Z^4
|
||||
secp256r1_modp_tri(M, M);
|
||||
|
||||
// 12. S = S * X = 4X*Y^2
|
||||
secp256r1_modp_mul(S, S, X1);
|
||||
|
||||
// 13. tmp0 = 2 * S = 8X*Y^2
|
||||
secp256r1_modp_dbl(tmp0, S);
|
||||
|
||||
// 14. X = M^2 = (3X^2 - 3Z^4)^2
|
||||
secp256r1_modp_sqr(X3, M);
|
||||
|
||||
// 15. X = X - tmp0 = (3X^2 - 3Z^4)^2 - 8X*Y^2 ===> X3
|
||||
secp256r1_modp_sub(X3, X3, tmp0);
|
||||
|
||||
// 16. S = S - X3 = 4X*Y^2 - X3
|
||||
secp256r1_modp_sub(S, S, X3);
|
||||
|
||||
// 17. S = S * M = (3X^2 - 3Z^4)*(4X*Y^2 - X3)
|
||||
secp256r1_modp_mul(S, S, M);
|
||||
|
||||
// 18. Y = S - Y = (3X^2 - 3Z^4)*(4X*Y^2 - X3) - 8Y^4 ===> Y3
|
||||
secp256r1_modp_sub(Y3, S, Y3);
|
||||
}
|
||||
|
||||
void secp256r1_point_add(SECP256R1_POINT *R, const SECP256R1_POINT *P, const SECP256R1_POINT *Q)
|
||||
{
|
||||
secp256r1_t T_1;
|
||||
secp256r1_t T_2;
|
||||
secp256r1_t T_3;
|
||||
secp256r1_t T_4;
|
||||
secp256r1_t T_5;
|
||||
secp256r1_t T_6;
|
||||
secp256r1_t T_7;
|
||||
secp256r1_t T_8;
|
||||
|
||||
if (secp256r1_point_is_at_infinity(P)) {
|
||||
*R = *Q;
|
||||
return;
|
||||
}
|
||||
if (secp256r1_point_is_at_infinity(Q)) {
|
||||
*R = *P;
|
||||
return;
|
||||
}
|
||||
|
||||
// 这里的代码是来自zkrypt的,不确定是否有问题
|
||||
secp256r1_modp_sqr(T_1, P->Z); // T_1 = Z_1^2
|
||||
secp256r1_modp_sqr(T_2, Q->Z); // T_2 = Z_2^2
|
||||
secp256r1_modp_mul(T_3, Q->X, T_1); // T_3 = X_2 * Z_1^2
|
||||
secp256r1_modp_mul(T_4, P->X, T_2); // T_4 = X_1 * Z_2^2
|
||||
secp256r1_modp_add(T_5, T_3, T_4); // T_5 = X_2 * Z_1^2 + X_1 * Z_2^2 = C
|
||||
secp256r1_modp_sub(T_3, T_3, T_4); // T_3 = X_2 * Z_1^2 - X_1 * Z_2^2 = B
|
||||
secp256r1_modp_mul(T_1, T_1, P->Z); // T_1 = Z_1^3
|
||||
secp256r1_modp_mul(T_1, T_1, Q->Y); // T_1 = Y_2 * Z_1^3
|
||||
secp256r1_modp_mul(T_2, T_2, Q->Z); // T_2 = Z_2^3
|
||||
secp256r1_modp_mul(T_2, T_2, P->Y); // T_2 = Y_1 * Z_2^3
|
||||
secp256r1_modp_add(T_6, T_1, T_2); // T_6 = Y_2 * Z_1^3 + Y_1 * Z_2^3 = D
|
||||
secp256r1_modp_sub(T_1, T_1, T_2); // T_1 = Y_2 * Z_1^3 - Y_1 * Z_2^3 = A
|
||||
|
||||
if (secp256r1_is_zero(T_1) && secp256r1_is_zero(T_3)) {
|
||||
secp256r1_point_dbl(R, P);
|
||||
return;
|
||||
}
|
||||
|
||||
if (secp256r1_is_one(T_1) && secp256r1_is_zero(T_6)) {
|
||||
secp256r1_point_set_infinity(R);
|
||||
return;
|
||||
}
|
||||
|
||||
secp256r1_modp_sqr(T_6, T_1); // T_6 = A^2
|
||||
secp256r1_modp_mul(T_7, T_3, P->Z); // T_7 = B * Z_1
|
||||
secp256r1_modp_mul(T_7, T_7, Q->Z); // T_7 = B * Z_1 * Z_2 = Z_3
|
||||
secp256r1_modp_sqr(T_8, T_3); // T_8 = B^2
|
||||
secp256r1_modp_mul(T_5, T_5, T_8); // T_5 = B^2 * C
|
||||
secp256r1_modp_mul(T_3, T_3, T_8); // T_3 = B^3
|
||||
secp256r1_modp_mul(T_4, T_4, T_8); // T_4 = B^2 * X_1 * Z_2^2
|
||||
secp256r1_modp_sub(T_6, T_6, T_5); // T_6 = A^2 - B^2 * C = X_3
|
||||
secp256r1_modp_sub(T_4, T_4, T_6); // T_4 = B^2 * X_1 * Z_2^2 - X_3
|
||||
secp256r1_modp_mul(T_1, T_1, T_4); // T_1 = A * (B^2 * X_1 * Z_2^2 - X_3)
|
||||
secp256r1_modp_mul(T_2, T_2, T_3); // T_2 = B^3 * Y_1 * Z_1^3
|
||||
secp256r1_modp_sub(T_1, T_1, T_2); // T_1 = A * (B^2 * X_1 * Z_2^2 - X_3) - B^3 * Y_1 * Z_1^3 = Y_3
|
||||
|
||||
secp256r1_copy(R->X, T_6);
|
||||
secp256r1_copy(R->Y, T_1);
|
||||
secp256r1_copy(R->Z, T_7);
|
||||
}
|
||||
|
||||
void secp256r1_point_neg(SECP256R1_POINT *R, const SECP256R1_POINT *P)
|
||||
{
|
||||
if (secp256r1_point_is_at_infinity(P)) {
|
||||
secp256r1_point_set_infinity(R);
|
||||
return;
|
||||
}
|
||||
secp256r1_copy(R->X, P->X);
|
||||
secp256r1_modp_neg(R->Y, P->Y);
|
||||
secp256r1_copy(R->Z, P->Z);
|
||||
}
|
||||
|
||||
void secp256r1_point_sub(SECP256R1_POINT *R, const SECP256R1_POINT *P, const SECP256R1_POINT *Q)
|
||||
{
|
||||
SECP256R1_POINT T;
|
||||
secp256r1_point_neg(&T, Q);
|
||||
secp256r1_point_add(R, P, &T);
|
||||
}
|
||||
|
||||
void secp256r1_point_mul(SECP256R1_POINT *R, const secp256r1_t k, const SECP256R1_POINT *P)
|
||||
{
|
||||
uint32_t bits;
|
||||
int nbits;
|
||||
int i;
|
||||
|
||||
secp256r1_point_set_infinity(R);
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
bits = k[i];
|
||||
nbits = 32;
|
||||
while (nbits-- > 0) {
|
||||
secp256r1_point_dbl(R, R);
|
||||
if (bits & 0x80000000) {
|
||||
secp256r1_point_add(R, R, P);
|
||||
}
|
||||
bits <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void secp256r1_point_mul_generator(SECP256R1_POINT *R, const secp256r1_t k)
|
||||
{
|
||||
secp256r1_point_mul(R, k, &SECP256R1_POINT_G);
|
||||
}
|
||||
|
||||
int secp256r1_point_print(FILE *fp, int fmt, int ind, const char *label, const SECP256R1_POINT *P)
|
||||
{
|
||||
uint8_t bytes[32];
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
secp256r1_to_32bytes(P->X, bytes);
|
||||
format_bytes(fp, fmt, ind, "X", bytes, 32);
|
||||
secp256r1_to_32bytes(P->Y, bytes);
|
||||
format_bytes(fp, fmt, ind, "Y", bytes, 32);
|
||||
secp256r1_to_32bytes(P->Z, bytes);
|
||||
format_bytes(fp, fmt, ind, "Z", bytes, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_point_to_uncompressed_octets(const SECP256R1_POINT *P, uint8_t octets[65])
|
||||
{
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
|
||||
if (secp256r1_point_get_xy(P, x, y) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
octets[0] = 0x04;
|
||||
secp256r1_to_32bytes(x, octets + 1);
|
||||
secp256r1_to_32bytes(y, octets + 33);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_point_from_uncompressed_octets(SECP256R1_POINT *P, const uint8_t octets[65])
|
||||
{
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
|
||||
if (octets[0] != 0x04) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
secp256r1_from_32bytes(x, octets + 1);
|
||||
secp256r1_from_32bytes(y, octets + 33);
|
||||
|
||||
if (secp256r1_point_set_xy(P, x, y) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_point_equ(const SECP256R1_POINT *P, const SECP256R1_POINT *Q)
|
||||
{
|
||||
uint8_t p_octets[65];
|
||||
uint8_t q_octets[65];
|
||||
|
||||
(void)secp256r1_point_to_uncompressed_octets(P, p_octets);
|
||||
(void)secp256r1_point_to_uncompressed_octets(Q, q_octets);
|
||||
|
||||
if (memcmp(p_octets, q_octets, 65) == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
506
src/secp256r1_key.c
Normal file
506
src/secp256r1_key.c
Normal file
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <gmssl/bn.h>
|
||||
#include <gmssl/ec.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/oid.h>
|
||||
#include <gmssl/sm4.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/pkcs8.h>
|
||||
#include <gmssl/x509_alg.h>
|
||||
#include <gmssl/secp256r1_key.h>
|
||||
|
||||
|
||||
int secp256r1_key_generate(SECP256R1_KEY *key)
|
||||
{
|
||||
do {
|
||||
if (rand_bytes((uint8_t *)key->private_key, sizeof(secp256r1_t)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} while (secp256r1_is_zero(key->private_key) || secp256r1_cmp(key->private_key, SECP256R1_N) >= 0);
|
||||
|
||||
secp256r1_point_mul_generator(&key->public_key, key->private_key);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_key_set_private_key(SECP256R1_KEY *key, const secp256r1_t private_key)
|
||||
{
|
||||
if (!key || !private_key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_is_zero(private_key) || secp256r1_cmp(private_key, SECP256R1_N) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(key, 0, sizeof(SECP256R1_KEY));
|
||||
|
||||
secp256r1_copy(key->private_key, private_key);
|
||||
secp256r1_point_mul_generator(&key->public_key, key->private_key);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_public_key_equ(const SECP256R1_KEY *key, const SECP256R1_KEY *pub)
|
||||
{
|
||||
if (secp256r1_point_equ(&key->public_key, &pub->public_key) == 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void secp256r1_key_cleanup(SECP256R1_KEY *key)
|
||||
{
|
||||
if (key) {
|
||||
gmssl_secure_clear(key->private_key, sizeof(secp256r1_t));
|
||||
memset(key, 0, sizeof(SECP256R1_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// SM2将这个命名为_to_octets,应该更准确一些
|
||||
int secp256r1_public_key_to_bytes(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
if (!key || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (out && *out) {
|
||||
if (secp256r1_point_to_uncompressed_octets(&key->public_key, *out) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*out += 65;
|
||||
}
|
||||
*outlen += 65;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_public_key_from_bytes(SECP256R1_KEY *key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
|
||||
if (!key || !in || !(*in) || !inlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (*inlen < 65) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(key, 0, sizeof(SECP256R1_KEY));
|
||||
|
||||
if (secp256r1_point_from_uncompressed_octets(&key->public_key, *in) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*in += 65;
|
||||
*inlen -= 65;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SECP256R1_KEY *key)
|
||||
{
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
|
||||
secp256r1_print(fp, fmt, ind, "X", key->public_key.X);
|
||||
secp256r1_print(fp, fmt, ind, "Y", key->public_key.Y);
|
||||
secp256r1_print(fp, fmt, ind, "Z", key->public_key.Z);
|
||||
|
||||
secp256r1_point_get_xy(&key->public_key, x, y);
|
||||
secp256r1_print(fp, fmt, ind, "x", x);
|
||||
secp256r1_print(fp, fmt, ind, "y", y);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_print(FILE *fp, int fmt, int ind, const char *label, const SECP256R1_KEY *key)
|
||||
{
|
||||
uint8_t buf[32];
|
||||
|
||||
secp256r1_to_32bytes(key->private_key, buf);
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
if (secp256r1_public_key_print(fp, fmt, ind, "public_key", key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_bytes(fp, fmt, ind, "private_key", buf, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_public_key_to_der(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
uint8_t octets[65];
|
||||
uint8_t *p = octets;
|
||||
size_t len = 0;
|
||||
|
||||
if (!key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// different from SM2
|
||||
if (out && *out) {
|
||||
if (secp256r1_public_key_to_bytes(key, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (asn1_bit_octets_to_der(octets, sizeof(octets), out, outlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_public_key_from_der(SECP256R1_KEY *key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
|
||||
if ((ret = asn1_bit_octets_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (secp256r1_public_key_from_bytes(key, &d, &dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (dlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int secp256r1_private_key_to_der(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
int curve = OID_secp256r1;
|
||||
uint8_t params[64];
|
||||
uint8_t pubkey[128];
|
||||
uint8_t *params_ptr = params;
|
||||
uint8_t *pubkey_ptr = pubkey;
|
||||
size_t params_len = 0;
|
||||
size_t pubkey_len = 0;
|
||||
uint8_t prikey[32];
|
||||
size_t len = 0;
|
||||
|
||||
if (!key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ec_named_curve_to_der(curve, ¶ms_ptr, ¶ms_len) != 1
|
||||
|| secp256r1_public_key_to_der(key, &pubkey_ptr, &pubkey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
// fprintf(stderr, "%s %d: params_len = %zu\n", params_len);
|
||||
// fprintf(stderr, "%s %d: pubkey_len = %zu\n", pubkey_len);
|
||||
secp256r1_to_32bytes(key->private_key, prikey);
|
||||
if (asn1_int_to_der(EC_private_key_version, NULL, &len) != 1
|
||||
|| asn1_octet_string_to_der(prikey, 32, NULL, &len) != 1
|
||||
|| asn1_explicit_to_der(0, params, params_len, NULL, &len) != 1
|
||||
|| asn1_explicit_to_der(1, pubkey, pubkey_len, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_int_to_der(EC_private_key_version, out, outlen) != 1
|
||||
|| asn1_octet_string_to_der(prikey, 32, out, outlen) != 1
|
||||
|| asn1_explicit_to_der(0, params, params_len, out, outlen) != 1
|
||||
|| asn1_explicit_to_der(1, pubkey, pubkey_len, out, outlen) != 1) {
|
||||
gmssl_secure_clear(prikey, 32);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
gmssl_secure_clear(prikey, 32);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_from_der(SECP256R1_KEY *key, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
int ver;
|
||||
const uint8_t *prikey;
|
||||
const uint8_t *params;
|
||||
const uint8_t *pubkey;
|
||||
size_t prikey_len, params_len, pubkey_len;
|
||||
int curve;
|
||||
SECP256R1_KEY tmp_key;
|
||||
secp256r1_t private_key;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (asn1_int_from_der(&ver, &d, &dlen) != 1
|
||||
|| asn1_octet_string_from_der(&prikey, &prikey_len, &d, &dlen) != 1
|
||||
|| asn1_explicit_from_der(0, ¶ms, ¶ms_len, &d, &dlen) != 1
|
||||
|| asn1_explicit_from_der(1, &pubkey, &pubkey_len, &d, &dlen) != 1
|
||||
|| asn1_check(ver == EC_private_key_version) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!params || !pubkey) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// public_key
|
||||
if (ec_named_curve_from_der(&curve, ¶ms, ¶ms_len) != 1
|
||||
|| asn1_check(curve == OID_secp256r1) != 1
|
||||
|| asn1_length_is_zero(params_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_public_key_from_der(&tmp_key, &pubkey, &pubkey_len) != 1
|
||||
|| asn1_length_is_zero(pubkey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// private_key
|
||||
if (!prikey || prikey_len != 32) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
secp256r1_from_32bytes(private_key, prikey);
|
||||
if (secp256r1_key_set_private_key(key, private_key) != 1) {
|
||||
gmssl_secure_clear(private_key, 32);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
gmssl_secure_clear(private_key, 32);
|
||||
|
||||
// check
|
||||
if (secp256r1_public_key_equ(key, &tmp_key) != 1) {
|
||||
secp256r1_key_cleanup(key);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_info_to_der(const SECP256R1_KEY *key, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
int algor = OID_ec_public_key;
|
||||
int algor_param = OID_secp256r1;
|
||||
size_t len = 0;
|
||||
uint8_t prikey[256];
|
||||
uint8_t *p = prikey;
|
||||
size_t prikey_len = 0;
|
||||
|
||||
if (secp256r1_private_key_to_der(key, &p, &prikey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
//fprintf(stderr, "%s %d: prikey_len = %zu\n", __FILE__, __LINE__, prikey_len);
|
||||
|
||||
if (asn1_int_to_der(PKCS8_private_key_info_version, NULL, &len) != 1
|
||||
|| x509_public_key_algor_to_der(algor, algor_param, NULL, &len) != 1
|
||||
|| asn1_octet_string_to_der(prikey, prikey_len, NULL, &len) != 1
|
||||
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|
||||
|| asn1_int_to_der(PKCS8_private_key_info_version, out, outlen) != 1
|
||||
|| x509_public_key_algor_to_der(algor, algor_param, out, outlen) != 1
|
||||
|| asn1_octet_string_to_der(prikey, prikey_len, out, outlen) != 1) {
|
||||
memset(prikey, 0, sizeof(prikey));
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(prikey, 0, sizeof(prikey));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_info_from_der(SECP256R1_KEY *key, const uint8_t **attrs, size_t *attrslen,
|
||||
const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
int version;
|
||||
int algor;
|
||||
int algor_param;
|
||||
const uint8_t *prikey;
|
||||
size_t prikey_len;
|
||||
|
||||
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
|
||||
if (ret < 0) error_print();
|
||||
return ret;
|
||||
}
|
||||
if (asn1_int_from_der(&version, &d, &dlen) != 1
|
||||
|| x509_public_key_algor_from_der(&algor, &algor_param, &d, &dlen) != 1
|
||||
|| asn1_octet_string_from_der(&prikey, &prikey_len, &d, &dlen) != 1
|
||||
|| asn1_implicit_set_from_der(0, attrs, attrslen, &d, &dlen) < 0
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_check(version == PKCS8_private_key_info_version) != 1
|
||||
|| asn1_check(algor == OID_ec_public_key) != 1
|
||||
|| asn1_check(algor_param == OID_secp256r1) != 1
|
||||
|| secp256r1_private_key_from_der(key, &prikey, &prikey_len) != 1
|
||||
|| asn1_length_is_zero(prikey_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_info_encrypt_to_der(const SECP256R1_KEY *ec_key, const char *pass,
|
||||
uint8_t **out, size_t *outlen)
|
||||
{
|
||||
int ret = -1;
|
||||
uint8_t pkey_info[512];
|
||||
uint8_t *p = pkey_info;
|
||||
size_t pkey_info_len = 0;
|
||||
uint8_t salt[16];
|
||||
int iter = 65536;
|
||||
uint8_t iv[16];
|
||||
uint8_t key[16];
|
||||
SM4_KEY sm4_key;
|
||||
uint8_t enced_pkey_info[sizeof(pkey_info) + 32];
|
||||
size_t enced_pkey_info_len;
|
||||
|
||||
if (!ec_key || !pass || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_private_key_info_to_der(ec_key, &p, &pkey_info_len) != 1
|
||||
|| rand_bytes(salt, sizeof(salt)) != 1
|
||||
|| rand_bytes(iv, sizeof(iv)) != 1
|
||||
|| sm3_pbkdf2(pass, strlen(pass), salt, sizeof(salt), iter, sizeof(key), key) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
/*
|
||||
if (pkey_info_len != sizeof(pkey_info)) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
*/
|
||||
sm4_set_encrypt_key(&sm4_key, key);
|
||||
if (sm4_cbc_padding_encrypt(
|
||||
&sm4_key, iv, pkey_info, pkey_info_len,
|
||||
enced_pkey_info, &enced_pkey_info_len) != 1
|
||||
|| pkcs8_enced_private_key_info_to_der(
|
||||
salt, sizeof(salt), iter, sizeof(key), OID_hmac_sm3,
|
||||
OID_sm4_cbc, iv, sizeof(iv),
|
||||
enced_pkey_info, enced_pkey_info_len, out, outlen) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
gmssl_secure_clear(pkey_info, sizeof(pkey_info));
|
||||
gmssl_secure_clear(key, sizeof(key));
|
||||
gmssl_secure_clear(&sm4_key, sizeof(sm4_key));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int secp256r1_private_key_info_decrypt_from_der(SECP256R1_KEY *ec_key,
|
||||
const uint8_t **attrs, size_t *attrs_len,
|
||||
const char *pass, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
int ret = -1;
|
||||
const uint8_t *salt;
|
||||
size_t saltlen;
|
||||
int iter;
|
||||
int keylen;
|
||||
int prf;
|
||||
int cipher;
|
||||
const uint8_t *iv;
|
||||
size_t ivlen;
|
||||
uint8_t key[16];
|
||||
SM4_KEY sm4_key;
|
||||
const uint8_t *enced_pkey_info;
|
||||
size_t enced_pkey_info_len;
|
||||
uint8_t pkey_info[256];
|
||||
const uint8_t *cp = pkey_info;
|
||||
size_t pkey_info_len;
|
||||
|
||||
if (!ec_key || !attrs || !attrs_len || !pass || !in || !(*in) || !inlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (pkcs8_enced_private_key_info_from_der(&salt, &saltlen, &iter, &keylen, &prf,
|
||||
&cipher, &iv, &ivlen, &enced_pkey_info, &enced_pkey_info_len, in, inlen) != 1
|
||||
|| asn1_check(keylen == -1 || keylen == 16) != 1
|
||||
|| asn1_check(prf == - 1 || prf == OID_hmac_sm3) != 1
|
||||
|| asn1_check(cipher == OID_sm4_cbc) != 1
|
||||
|| asn1_check(ivlen == 16) != 1
|
||||
|| asn1_length_le(enced_pkey_info_len, sizeof(pkey_info)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm3_pbkdf2(pass, strlen(pass), salt, saltlen, iter, sizeof(key), key) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
sm4_set_decrypt_key(&sm4_key, key);
|
||||
if (sm4_cbc_padding_decrypt(&sm4_key, iv, enced_pkey_info, enced_pkey_info_len,
|
||||
pkey_info, &pkey_info_len) != 1
|
||||
|| secp256r1_private_key_info_from_der(ec_key, attrs, attrs_len, &cp, &pkey_info_len) != 1
|
||||
|| asn1_length_is_zero(pkey_info_len) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
gmssl_secure_clear(&sm4_key, sizeof(sm4_key));
|
||||
gmssl_secure_clear(key, sizeof(key));
|
||||
gmssl_secure_clear(pkey_info, sizeof(pkey_info));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
|
||||
309
src/tls12_handshake.c
Normal file
309
src/tls12_handshake.c
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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 <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/x509.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/sm3.h>
|
||||
#include <gmssl/sm4.h>
|
||||
#include <gmssl/pem.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/tls.h>
|
||||
|
||||
|
||||
enum {
|
||||
TLS_state_client_hello,
|
||||
TLS_state_server_hello,
|
||||
TLS_state_server_certificate,
|
||||
TLS_state_server_key_exchange,
|
||||
TLS_state_server_certificate_request,
|
||||
TLS_state_server_hello_done,
|
||||
TLS_state_client_certificate,
|
||||
TLS_state_client_key_exchange,
|
||||
TLS_state_client_certificate_verify,
|
||||
TLS_state_client_change_cipher_spec,
|
||||
TLS_state_client_finished,
|
||||
TLS_state_server_change_cipher_spec,
|
||||
TLS_state_server_finished,
|
||||
};
|
||||
|
||||
static const int tls12_ciphers[] = {
|
||||
TLS_cipher_ecdhe_sm4_cbc_sm3,
|
||||
};
|
||||
|
||||
int tls_send_client_hello(TLS_CONNECT *conn)
|
||||
{
|
||||
const int ec_point_formats[] = { TLS_point_uncompressed };
|
||||
size_t ec_point_formats_cnt = sizeof(ec_point_formats)/sizeof(ec_point_formats[0]);
|
||||
const int supported_groups[] = { TLS_curve_sm2p256v1 };
|
||||
size_t supported_groups_cnt = sizeof(supported_groups)/sizeof(supported_groups[0]);
|
||||
const int signature_algors[] = { TLS_sig_sm2sig_sm3 };
|
||||
size_t signature_algors_cnt = sizeof(signature_algors)/sizeof(signature_algors[0]);
|
||||
|
||||
uint8_t *record;
|
||||
size_t recordlen;
|
||||
uint8_t client_random[32];
|
||||
uint8_t client_exts[TLS_MAX_EXTENSIONS_SIZE];
|
||||
size_t client_exts_len;
|
||||
uint8_t *p;
|
||||
|
||||
record = conn->record;
|
||||
|
||||
tls_record_set_protocol(record, TLS_protocol_tls1);
|
||||
|
||||
sm3_init(&conn->sm3_ctx);
|
||||
if (conn->client_certs_len)
|
||||
sm2_sign_init(&conn->sign_ctx, &conn->sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH);
|
||||
|
||||
|
||||
tls_random_generate(client_random);
|
||||
|
||||
p = client_exts;
|
||||
client_exts_len = 0;
|
||||
tls_ec_point_formats_ext_to_bytes(ec_point_formats, ec_point_formats_cnt, &p, &client_exts_len);
|
||||
tls_supported_groups_ext_to_bytes(supported_groups, supported_groups_cnt, &p, &client_exts_len);
|
||||
tls_signature_algorithms_ext_to_bytes(signature_algors, signature_algors_cnt, &p, &client_exts_len);
|
||||
|
||||
if (tls_record_set_handshake_client_hello(conn->record, &recordlen,
|
||||
conn->protocol, client_random, NULL, 0,
|
||||
tls12_ciphers, sizeof(tls12_ciphers)/sizeof(tls12_ciphers[0]),
|
||||
client_exts, client_exts_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_trace("send ClientHello\n");
|
||||
tls12_record_trace(stderr, record, recordlen, 0, 0);
|
||||
if (tls_record_send(record, recordlen, conn->sock) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
sm3_update(&conn->sm3_ctx, record + 5, recordlen - 5);
|
||||
if (conn->client_certs_len) {
|
||||
sm2_sign_update(&conn->sign_ctx, record + 5, recordlen - 5);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_hello(TLS_CONNECT *conn)
|
||||
{
|
||||
uint8_t *record = conn->record;
|
||||
size_t recordlen;
|
||||
|
||||
tls_trace("recv ServerHello\n");
|
||||
if (tls_record_recv(record, &recordlen, conn->sock) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
tls12_record_trace(stderr, record, recordlen, 0, 0);
|
||||
if (tls_record_protocol(record) != conn->protocol) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_protocol_version);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 这些值要放在哪儿呢?是否放在CONNECT中
|
||||
int protocol;
|
||||
int cipher_suite;
|
||||
uint8_t server_random[32];
|
||||
const uint8_t *random;
|
||||
const uint8_t *session_id;
|
||||
size_t session_id_len;
|
||||
const uint8_t *server_exts;
|
||||
size_t server_exts_len;
|
||||
|
||||
// 扩展的协商结果,-1 表示服务器不支持该扩展(未给出响应)
|
||||
int ec_point_format = -1;
|
||||
int supported_group = -1;
|
||||
int signature_algor = -1;
|
||||
|
||||
if (tls_record_get_handshake_server_hello(record,
|
||||
&protocol, &random, &session_id, &session_id_len, &cipher_suite,
|
||||
&server_exts, &server_exts_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
if (protocol != conn->protocol) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_protocol_version);
|
||||
return -1;
|
||||
}
|
||||
// tls12_ciphers 应该改为conn的内部变量
|
||||
if (tls_cipher_suite_in_list(cipher_suite, tls12_ciphers, sizeof(tls12_ciphers)/sizeof(tls12_ciphers[0])) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_handshake_failure);
|
||||
return -1;
|
||||
}
|
||||
if (!server_exts) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
if (tls_process_server_hello_exts(server_exts, server_exts_len, &ec_point_format, &supported_group, &signature_algor) != 1
|
||||
|| ec_point_format < 0
|
||||
|| supported_group < 0
|
||||
|| signature_algor < 0) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(server_random, random, 32);
|
||||
memcpy(conn->session_id, session_id, session_id_len);
|
||||
conn->cipher_suite = cipher_suite;
|
||||
sm3_update(&conn->sm3_ctx, record + 5, recordlen - 5);
|
||||
if (conn->client_certs_len) {
|
||||
sm2_sign_update(&conn->sign_ctx, record + 5, recordlen - 5);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_certificate(TLS_CONNECT *conn)
|
||||
{
|
||||
const int depth = 5;
|
||||
uint8_t *record = conn->record;
|
||||
size_t recordlen;
|
||||
int verify_result;
|
||||
|
||||
// recv ServerCertificate
|
||||
tls_trace("recv ServerCertificate\n");
|
||||
if (tls_record_recv(record, &recordlen, conn->sock) != 1
|
||||
|| tls_record_protocol(record) != conn->protocol) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
tls12_record_trace(stderr, record, recordlen, 0, 0);
|
||||
|
||||
if (tls_record_get_handshake_certificate(record,
|
||||
conn->server_certs, &conn->server_certs_len) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_unexpected_message);
|
||||
return -1;
|
||||
}
|
||||
sm3_update(&conn->sm3_ctx, record + 5, recordlen - 5);
|
||||
if (conn->client_certs_len)
|
||||
sm2_sign_update(&conn->sign_ctx, record + 5, recordlen - 5);
|
||||
|
||||
// verify ServerCertificate
|
||||
if (x509_certs_verify(conn->server_certs, conn->server_certs_len, X509_cert_chain_server,
|
||||
conn->ca_certs, conn->ca_certs_len, depth, &verify_result) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_key_exchange(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_certificate_request(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_hello_done(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_send_client_certificate(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_send_client_key_exchange(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_send_certificate_verify(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_send_client_finished(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_change_cipher_spec(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_recv_server_finished(TLS_CONNECT *conn)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int tls12_client_handshake(TLS_CONNECT *conn)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (conn->state) {
|
||||
case TLS_state_client_hello:
|
||||
ret = tls_send_client_hello(conn);
|
||||
break;
|
||||
case TLS_state_server_hello:
|
||||
ret = tls_recv_server_hello(conn);
|
||||
break;
|
||||
case TLS_state_server_certificate:
|
||||
ret = tls_recv_server_certificate(conn);
|
||||
break;
|
||||
case TLS_state_server_key_exchange:
|
||||
ret = tls_recv_server_key_exchange(conn);
|
||||
break;
|
||||
case TLS_state_server_certificate_request:
|
||||
ret = tls_recv_server_certificate_request(conn);
|
||||
break;
|
||||
case TLS_state_server_hello_done:
|
||||
ret = tls_recv_server_hello_done(conn);
|
||||
break;
|
||||
case TLS_state_client_certificate:
|
||||
ret = tls_send_client_certificate(conn);
|
||||
break;
|
||||
case TLS_state_client_key_exchange:
|
||||
ret = tls_send_client_key_exchange(conn);
|
||||
break;
|
||||
case TLS_state_client_certificate_verify:
|
||||
ret = tls_send_certificate_verify(conn);
|
||||
case TLS_state_client_change_cipher_spec:
|
||||
break;
|
||||
case TLS_state_client_finished:
|
||||
ret = tls_send_client_finished(conn);
|
||||
break;
|
||||
case TLS_state_server_change_cipher_spec:
|
||||
ret = tls_recv_server_change_cipher_spec(conn);
|
||||
break;
|
||||
case TLS_state_server_finished:
|
||||
ret = tls_recv_server_finished(conn);
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
171
src/x509_key.c
171
src/x509_key.c
@@ -14,7 +14,6 @@
|
||||
#include <gmssl/ec.h>
|
||||
#include <gmssl/oid.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/x509_alg.h>
|
||||
@@ -79,13 +78,16 @@ int x509_key_generate(X509_KEY *key, int algor, int algor_param)
|
||||
|
||||
switch (algor) {
|
||||
case OID_ec_public_key:
|
||||
if (algor_param != OID_sm2) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_key_generate(&key->u.sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
if (algor_param == OID_sm2) {
|
||||
if (sm2_key_generate(&key->u.sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else if (algor_param == OID_secp256r1) {
|
||||
if (secp256r1_key_generate(&key->u.secp256r1_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OID_lms_hashsig:
|
||||
@@ -156,7 +158,17 @@ int x509_public_key_print(FILE *fp, int fmt, int ind, const char *label, const X
|
||||
{
|
||||
switch (key->algor) {
|
||||
case OID_ec_public_key:
|
||||
if (sm2_public_key_print(fp, fmt, ind, label, &key->u.sm2_key) != 1) {
|
||||
if (key->algor_param == OID_sm2) {
|
||||
if (sm2_public_key_print(fp, fmt, ind, label, &key->u.sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
if (secp256r1_public_key_print(fp, fmt, ind, label, &key->u.secp256r1_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -208,6 +220,15 @@ int x509_key_set_sm2_key(X509_KEY *x509_key, const SM2_KEY *sm2_key)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_key_set_secp256r1_key(X509_KEY *x509_key, const SECP256R1_KEY *secp256r1_key)
|
||||
{
|
||||
memset(x509_key, 0, sizeof(X509_KEY));
|
||||
x509_key->algor = OID_ec_public_key;
|
||||
x509_key->algor_param = OID_secp256r1;
|
||||
x509_key->u.secp256r1_key = *secp256r1_key;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_key_set_lms_key(X509_KEY *x509_key, const LMS_KEY *lms_key)
|
||||
{
|
||||
memset(x509_key, 0, sizeof(X509_KEY));
|
||||
@@ -288,11 +309,21 @@ int x509_public_key_digest(const X509_KEY *key, uint8_t dgst[32])
|
||||
|
||||
switch (key->algor) {
|
||||
case OID_ec_public_key:
|
||||
if (sm2_z256_point_to_uncompressed_octets(&key->u.sm2_key.public_key, bits) != 1) {
|
||||
if (key->algor_param == OID_sm2) {
|
||||
if (sm2_z256_point_to_uncompressed_octets(&key->u.sm2_key.public_key, bits) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
len = 65;
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
if (secp256r1_public_key_to_bytes(&key->u.secp256r1_key, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
len = 65;
|
||||
break;
|
||||
case OID_hss_lms_hashsig:
|
||||
if (hss_public_key_to_bytes(&key->u.hss_key, &p, &len) != 1) {
|
||||
@@ -340,7 +371,17 @@ int x509_public_key_equ(const X509_KEY *key, const X509_KEY *pub)
|
||||
}
|
||||
switch (key->algor) {
|
||||
case OID_ec_public_key:
|
||||
if (sm2_public_key_equ(&key->u.sm2_key, &pub->u.sm2_key) != 1) {
|
||||
if (key->algor_param == OID_sm2) {
|
||||
if (sm2_public_key_equ(&key->u.sm2_key, &pub->u.sm2_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
if (secp256r1_public_key_equ(&key->u.secp256r1_key, &pub->u.secp256r1_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -456,11 +497,22 @@ int x509_sign_init(X509_SIGN_CTX *ctx, X509_KEY *key, const char *signer_id, siz
|
||||
ctx->sign_algor = key->algor;
|
||||
break;
|
||||
case OID_ec_public_key:
|
||||
if (sm2_sign_init(&ctx->u.sm2_sign_ctx, &key->u.sm2_key, signer_id, signer_idlen) != 1) {
|
||||
if (key->algor_param == OID_sm2) {
|
||||
if (sm2_sign_init(&ctx->u.sm2_sign_ctx, &key->u.sm2_key, signer_id, signer_idlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_sm2sign_with_sm3;
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
if (ecdsa_sign_init(&ctx->u.ecdsa_sign_ctx, &key->u.secp256r1_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_ecdsa_with_sha256;
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_sm2sign_with_sm3;
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
@@ -497,6 +549,12 @@ int x509_sign_update(X509_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OID_ecdsa_with_sha256:
|
||||
if (ecdsa_sign_update(&ctx->u.ecdsa_sign_ctx, data, datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -536,6 +594,13 @@ int x509_sign_finish(X509_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OID_ecdsa_with_sha256:
|
||||
*siglen = ECDSA_SIGNATURE_TYPICAL_SIZE;
|
||||
if (ecdsa_sign_finish_fixlen(&ctx->u.ecdsa_sign_ctx, *siglen, sig) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -574,17 +639,28 @@ int x509_verify_init(X509_SIGN_CTX *ctx, const X509_KEY *key, const char *signer
|
||||
ctx->sign_algor = key->algor;
|
||||
break;
|
||||
case OID_ec_public_key:
|
||||
if (sm2_verify_init(&ctx->u.sm2_verify_ctx, &key->u.sm2_key, signer_id, signer_idlen) != 1) {
|
||||
if (key->algor_param == OID_sm2) {
|
||||
if (sm2_verify_init(&ctx->u.sm2_verify_ctx, &key->u.sm2_key, signer_id, signer_idlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_sm2sign_with_sm3;
|
||||
if (siglen > sizeof(ctx->sig)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memcpy(ctx->sig, sig, siglen);
|
||||
ctx->siglen = siglen;
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
if (ecdsa_verify_init(&ctx->u.ecdsa_sign_ctx, &key->u.secp256r1_key, sig, siglen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_ecdsa_with_sha256;
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->sign_algor = OID_sm2sign_with_sm3;
|
||||
if (siglen > sizeof(ctx->sig)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memcpy(ctx->sig, sig, siglen);
|
||||
ctx->siglen = siglen;
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
@@ -620,6 +696,12 @@ int x509_verify_update(X509_SIGN_CTX *ctx, const uint8_t *data, size_t datalen)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OID_ecdsa_with_sha256:
|
||||
if (ecdsa_verify_update(&ctx->u.ecdsa_sign_ctx, data, datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -652,7 +734,13 @@ int x509_verify_finish(X509_SIGN_CTX *ctx)
|
||||
}
|
||||
break;
|
||||
case OID_sm2sign_with_sm3:
|
||||
if ((ret = sm2_verify_update(&ctx->u.sm2_verify_ctx, ctx->sig, ctx->siglen)) < 0) {
|
||||
if ((ret = sm2_verify_finish(&ctx->u.sm2_verify_ctx, ctx->sig, ctx->siglen)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case OID_ecdsa_with_sha256:
|
||||
if ((ret = ecdsa_verify_finish(&ctx->u.ecdsa_sign_ctx)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -698,8 +786,15 @@ int x509_public_key_info_to_der(const X509_KEY *x509_key, uint8_t **out, size_t
|
||||
}
|
||||
break;
|
||||
case OID_ec_public_key:
|
||||
sm2_z256_point_to_uncompressed_octets(&x509_key->u.sm2_key.public_key, p);
|
||||
keylen = 65;
|
||||
if (x509_key->algor_param == OID_sm2) {
|
||||
sm2_z256_point_to_uncompressed_octets(&x509_key->u.sm2_key.public_key, p);
|
||||
keylen = 65;
|
||||
} else if (x509_key->algor_param == OID_secp256r1) {
|
||||
if (secp256r1_public_key_to_bytes(&x509_key->u.secp256r1_key, &p, &keylen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
@@ -758,15 +853,25 @@ int x509_public_key_info_from_der(X509_KEY *x509_key, const uint8_t **in, size_t
|
||||
|
||||
switch (algor) {
|
||||
case OID_ec_public_key:
|
||||
if (algor_param != OID_sm2) {
|
||||
if (publen != 65) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sm2_z256_point_from_octets(&x509_key->u.sm2_key.public_key, pub, publen) != 1) {
|
||||
if (algor_param == OID_sm2) {
|
||||
if (sm2_z256_point_from_octets(&x509_key->u.sm2_key.public_key, pub, publen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
publen = 0;
|
||||
} else if (algor_param == OID_secp256r1) {
|
||||
if (secp256r1_public_key_from_bytes(&x509_key->u.secp256r1_key, &pub, &publen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
publen = 0;
|
||||
break;
|
||||
case OID_hss_lms_hashsig:
|
||||
if (hss_public_key_from_bytes(&x509_key->u.hss_key, &pub, &publen) != 1) {
|
||||
@@ -806,6 +911,7 @@ int x509_public_key_info_from_der(X509_KEY *x509_key, const uint8_t **in, size_t
|
||||
return 1;
|
||||
}
|
||||
|
||||
// FIXME: this function can not parse depends on algor_param
|
||||
int x509_private_key_from_file(X509_KEY *key, int algor, const char *pass, FILE *fp)
|
||||
{
|
||||
if (!key || !fp) {
|
||||
@@ -821,6 +927,7 @@ int x509_private_key_from_file(X509_KEY *key, int algor, const char *pass, FILE
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
// FIXME: secp256r1
|
||||
if (sm2_private_key_info_decrypt_from_pem(&key->u.sm2_key, pass, fp) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -901,8 +1008,12 @@ void x509_key_cleanup(X509_KEY *key)
|
||||
if (key) {
|
||||
switch (key->algor) {
|
||||
case OID_ec_public_key:
|
||||
//sm2_key_cleanup(&key->u.sm2_key);
|
||||
gmssl_secure_clear(&key->u.sm2_key, sizeof(SM2_KEY));
|
||||
if (key->algor_param == OID_sm2) {
|
||||
//sm2_key_cleanup(&key->u.sm2_key);
|
||||
gmssl_secure_clear(&key->u.sm2_key, sizeof(SM2_KEY));
|
||||
} else if (key->algor_param == OID_secp256r1) {
|
||||
secp256r1_key_cleanup(&key->u.secp256r1_key);
|
||||
}
|
||||
break;
|
||||
case OID_lms_hashsig:
|
||||
lms_key_cleanup(&key->u.lms_key);
|
||||
|
||||
128
tests/bntest.c
Normal file
128
tests/bntest.c
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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 <stdint.h>
|
||||
#include <gmssl/hex.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/bn.h>
|
||||
|
||||
|
||||
static int test_print_consts(void)
|
||||
{
|
||||
// secp256r1 parameters
|
||||
char *p = "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF";
|
||||
char *b = "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b";
|
||||
char *x = "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296";
|
||||
char *y = "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5";
|
||||
char *n = "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551";
|
||||
char *u_p = "0000000100000000fffffffffffffffefffffffefffffffeffffffff0000000000000003"; // floor(2^512/p)
|
||||
char *u_n = "0000000100000000fffffffffffffffeffffffff43190552df1a6c21012ffd85eedf9bfe"; // floor(2^512/n)
|
||||
|
||||
int k = 8;
|
||||
uint32_t bn[9];
|
||||
uint8_t buf[36];
|
||||
size_t len;
|
||||
|
||||
hex_to_bytes(p, 64, buf, &len);
|
||||
bn_from_bytes(bn, k, buf);
|
||||
bn_print(stderr, 0, 4, "p", bn, k);
|
||||
|
||||
hex_to_bytes(b, 64, buf, &len);
|
||||
bn_from_bytes(bn, k, buf);
|
||||
bn_print(stderr, 0, 4, "a", bn, k);
|
||||
|
||||
hex_to_bytes(x, 64, buf, &len);
|
||||
bn_from_bytes(bn, k, buf);
|
||||
bn_print(stderr, 0, 4, "x", bn, k);
|
||||
|
||||
hex_to_bytes(y, 64, buf, &len);
|
||||
bn_from_bytes(bn, k, buf);
|
||||
bn_print(stderr, 0, 4, "y", bn, k);
|
||||
|
||||
hex_to_bytes(n, 64, buf, &len);
|
||||
bn_from_bytes(bn, k, buf);
|
||||
bn_print(stderr, 0, 4, "n", bn, k);
|
||||
|
||||
hex_to_bytes(u_p, 72, buf, &len);
|
||||
bn_from_bytes(bn, k + 1, buf);
|
||||
bn_print(stderr, 0, 4, "u_p = 2^512//p", bn, k + 1);
|
||||
|
||||
hex_to_bytes(u_n, 72, buf, &len);
|
||||
bn_from_bytes(bn, k + 1, buf);
|
||||
bn_print(stderr, 0, 4, "u_n = 2^512//n", bn, k + 1);
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_secp256r1(void)
|
||||
{
|
||||
char *x_hex = "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296";
|
||||
char *p_hex = "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF";
|
||||
|
||||
int c;
|
||||
|
||||
uint32_t a[8];
|
||||
uint32_t r[8];
|
||||
uint8_t buf[32];
|
||||
size_t len;
|
||||
|
||||
hex_to_bytes(x_hex, 64, buf, &len);
|
||||
|
||||
bn_from_bytes(a, 8, buf);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bn_add(r, a, a, 8);
|
||||
bn_add(r, r, a, 8);
|
||||
|
||||
bn_print(stderr, 0, 4, "3*x", a, 8);
|
||||
|
||||
uint32_t p[8];
|
||||
|
||||
hex_to_bytes(p_hex, 64, buf, &len);
|
||||
bn_from_bytes(p, 8, buf);
|
||||
|
||||
|
||||
c = bn_sub(r, a, p, 8);
|
||||
printf("carray = %d\n", c);
|
||||
|
||||
|
||||
// 我知道了,这里有一个进位被忽略了
|
||||
if (bn_cmp(a, p, 8) >= 0) {
|
||||
error_print();
|
||||
} else {
|
||||
error_print();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (test_print_consts() != 1) goto err;
|
||||
if (test_secp256r1() != 1) goto err;
|
||||
|
||||
printf("%s all tests passed\n", __FILE__);
|
||||
return 0;
|
||||
err:
|
||||
error_print();
|
||||
return 1;
|
||||
}
|
||||
92
tests/ecdsatest.c
Normal file
92
tests/ecdsatest.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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 <stdint.h>
|
||||
#include <gmssl/bn.h>
|
||||
#include <gmssl/hex.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/ecdsa.h>
|
||||
|
||||
/*
|
||||
d 0x5
|
||||
xP 0x51590b7a515140d2d784c85608668fdfef8c82fd1f5be52421554a0dc3d033ed
|
||||
yP 0xe0c17da8904a727d8ae1bf36bf8a79260d012f00d4d80888d1d0bb44fda16da4
|
||||
x1 0x5ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c
|
||||
r 0x5ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c
|
||||
s 0x48a928086a55111cf99d39f886293cff41a8dda957c43b0851846697f76199ef
|
||||
x1 0x5ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c
|
||||
v 0x5ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c
|
||||
*/
|
||||
|
||||
// 这个签名是没有问题的,看来验证签名是有问题的
|
||||
static int test_ecdsa(void)
|
||||
{
|
||||
SECP256R1_KEY key;
|
||||
ECDSA_SIGNATURE sig;
|
||||
uint8_t dgst[32];
|
||||
secp256r1_t d;
|
||||
secp256r1_t k;
|
||||
|
||||
// d = 5
|
||||
bn_set_word(d, 5, 8);
|
||||
secp256r1_key_set_private_key(&key, d);
|
||||
|
||||
secp256r1_key_generate(&key);
|
||||
|
||||
secp256r1_private_key_print(stderr, 0, 0, "private_key", &key);
|
||||
|
||||
// k = 3
|
||||
bn_set_word(k, 3, 8);
|
||||
|
||||
// e = 2
|
||||
memset(dgst, 0, 31);
|
||||
dgst[31] = 2;
|
||||
|
||||
/*
|
||||
if (ecdsa_do_sign_ex(&key, k, dgst, &sig) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
if (ecdsa_do_sign(&key, dgst, &sig) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
secp256r1_print(stderr, 0, 0, "r", sig.r);
|
||||
secp256r1_print(stderr, 0, 0, "s", sig.s);
|
||||
|
||||
|
||||
if (ecdsa_do_verify(&key, dgst, &sig) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (test_ecdsa() != 1) goto err;
|
||||
|
||||
printf("%s all tests passed\n", __FILE__);
|
||||
return 0;
|
||||
err:
|
||||
error_print();
|
||||
return 1;
|
||||
}
|
||||
292
tests/secp256r1_keytest.c
Normal file
292
tests/secp256r1_keytest.c
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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 <stdint.h>
|
||||
#include <gmssl/hex.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/secp256r1_key.h>
|
||||
|
||||
|
||||
static int test_secp256r1_key_generate(void)
|
||||
{
|
||||
SECP256R1_KEY key;
|
||||
|
||||
if (secp256r1_key_generate(&key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
secp256r1_public_key_print(stderr, 0, 4, "public_key", &key);
|
||||
secp256r1_private_key_print(stderr, 0, 4, "private_key", &key);
|
||||
secp256r1_key_cleanup(&key);
|
||||
secp256r1_private_key_print(stderr, 0, 4, "private_key", &key);
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_secp256r1_key_set_private_key(void)
|
||||
{
|
||||
SECP256R1_KEY key;
|
||||
secp256r1_t private_key;
|
||||
uint8_t bytes[32];
|
||||
size_t len;
|
||||
|
||||
// key = 1
|
||||
memset(bytes, 0, sizeof(bytes));
|
||||
bytes[31] = 1;
|
||||
secp256r1_from_32bytes(private_key, bytes);
|
||||
if (secp256r1_key_set_private_key(&key, private_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
secp256r1_private_key_print(stderr, 0, 4, "private_key = 1", &key);
|
||||
|
||||
|
||||
// key = n-1
|
||||
hex_to_bytes("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550", 64, bytes, &len);
|
||||
secp256r1_from_32bytes(private_key, bytes);
|
||||
if (secp256r1_key_set_private_key(&key, private_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// key = 0, should fail
|
||||
memset(bytes, 0, sizeof(bytes));
|
||||
secp256r1_from_32bytes(private_key, bytes);
|
||||
if (secp256r1_key_set_private_key(&key, private_key) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// key = n, should fail
|
||||
hex_to_bytes("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 64, bytes, &len);
|
||||
secp256r1_from_32bytes(private_key, bytes);
|
||||
if (secp256r1_key_set_private_key(&key, private_key) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// key = 0xff..f, should fail
|
||||
memset(bytes, 0xff, sizeof(bytes));
|
||||
secp256r1_from_32bytes(private_key, bytes);
|
||||
if (secp256r1_key_set_private_key(&key, private_key) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_secp256r1_public_key_to_bytes(void)
|
||||
{
|
||||
SECP256R1_KEY key;
|
||||
SECP256R1_KEY key1;
|
||||
uint8_t bytes[512];
|
||||
uint8_t *p = bytes;
|
||||
const uint8_t *cp = bytes;
|
||||
size_t len = 0;
|
||||
|
||||
if (secp256r1_key_generate(&key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_public_key_to_bytes(&key, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_public_key_from_bytes(&key1, &cp, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_public_key_equ(&key, &key1) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_secp256r1_public_key_to_der(void)
|
||||
{
|
||||
SECP256R1_KEY key;
|
||||
SECP256R1_KEY key1;
|
||||
uint8_t bytes[512];
|
||||
uint8_t *p = bytes;
|
||||
const uint8_t *cp = bytes;
|
||||
size_t len = 0;
|
||||
|
||||
if (secp256r1_key_generate(&key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_public_key_to_der(&key, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_public_key_from_der(&key1, &cp, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_public_key_equ(&key, &key1) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_secp256r1_private_key_to_der(void)
|
||||
{
|
||||
SECP256R1_KEY key;
|
||||
SECP256R1_KEY key1;
|
||||
uint8_t bytes[512];
|
||||
uint8_t *p = bytes;
|
||||
const uint8_t *cp = bytes;
|
||||
size_t len = 0;
|
||||
|
||||
if (secp256r1_key_generate(&key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_private_key_to_der(&key, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_private_key_from_der(&key1, &cp, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_public_key_equ(&key, &key1) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_secp256r1_private_key_info_to_der(void)
|
||||
{
|
||||
SECP256R1_KEY key;
|
||||
SECP256R1_KEY key1;
|
||||
uint8_t bytes[512];
|
||||
uint8_t *p = bytes;
|
||||
const uint8_t *cp = bytes;
|
||||
size_t len = 0;
|
||||
const uint8_t *attrs;
|
||||
size_t attrslen;
|
||||
|
||||
if (secp256r1_key_generate(&key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_private_key_info_to_der(&key, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_private_key_info_from_der(&key1, &attrs, &attrslen, &cp, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_public_key_equ(&key, &key1) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_secp256r1_private_key_info_encrypt_to_der(void)
|
||||
{
|
||||
SECP256R1_KEY key;
|
||||
SECP256R1_KEY key1;
|
||||
uint8_t bytes[512];
|
||||
uint8_t *p = bytes;
|
||||
const uint8_t *cp = bytes;
|
||||
size_t len = 0;
|
||||
char *pass = "password";
|
||||
const uint8_t *attrs;
|
||||
size_t attrslen;
|
||||
|
||||
if (secp256r1_key_generate(&key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_private_key_info_encrypt_to_der(&key, pass, &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_private_key_info_decrypt_from_der(&key1, &attrs, &attrslen, pass, &cp, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_public_key_equ(&key, &key1) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (test_secp256r1_key_generate() != 1) goto err;
|
||||
// if (test_secp256r1_key_set_private_key() != 1) goto err;
|
||||
if (test_secp256r1_public_key_to_bytes() != 1) goto err;
|
||||
if (test_secp256r1_public_key_to_der() != 1) goto err;
|
||||
if (test_secp256r1_private_key_to_der() != 1) goto err;
|
||||
if (test_secp256r1_private_key_info_to_der() != 1) goto err;
|
||||
if (test_secp256r1_private_key_info_encrypt_to_der() != 1) goto err;
|
||||
|
||||
printf("%s all tests passed\n", __FILE__);
|
||||
return 0;
|
||||
err:
|
||||
error_print();
|
||||
return 1;
|
||||
}
|
||||
|
||||
481
tests/secp256r1test.c
Normal file
481
tests/secp256r1test.c
Normal file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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 <stdint.h>
|
||||
#include <gmssl/hex.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/secp256r1.h>
|
||||
|
||||
|
||||
static const char *secp256r1_p = "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF";
|
||||
static const char *secp256r1_b = "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b";
|
||||
static const char *secp256r1_x = "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296";
|
||||
static const char *secp256r1_y = "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5";
|
||||
static const char *secp256r1_n = "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551";
|
||||
|
||||
static int test_secp256r1(void)
|
||||
{
|
||||
secp256r1_t a;
|
||||
secp256r1_t b;
|
||||
secp256r1_t r;
|
||||
uint8_t buf[32];
|
||||
|
||||
secp256r1_set_zero(a);
|
||||
if (!secp256r1_is_zero(a)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
secp256r1_to_32bytes(a, buf);
|
||||
format_bytes(stderr, 0, 4, "0", buf, sizeof(buf));
|
||||
|
||||
secp256r1_set_one(b);
|
||||
if (!secp256r1_is_one(b)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
secp256r1_to_32bytes(b, buf);
|
||||
format_bytes(stderr, 0, 4, "1", buf, sizeof(buf));
|
||||
|
||||
if (secp256r1_cmp(a, b) >= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// 这个测试是有问题的,mod_add很多情况下是引发进位和借位的!
|
||||
static int test_secp256r1_modp(void)
|
||||
{
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
secp256r1_t r;
|
||||
secp256r1_t v;
|
||||
uint8_t buf[32];
|
||||
size_t len;
|
||||
|
||||
hex_to_bytes("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 64, buf, &len);
|
||||
secp256r1_from_32bytes(x, buf);
|
||||
|
||||
hex_to_bytes("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 64, buf, &len);
|
||||
secp256r1_from_32bytes(y, buf);
|
||||
|
||||
secp256r1_modp_add(r, x, y);
|
||||
hex_to_bytes("bafb14d5df46c1e387a4d22fdfb3df08a2d1b0d8991c926fc05779ae1058148b", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modp_dbl(r, x);
|
||||
hex_to_bytes("d62fa3e5c258848ff179cdcac74881e4ee06fb025bd66741e942728bb131852c", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modp_tri(r, x);
|
||||
hex_to_bytes("414775d9a384c6d6ea36b4b02aecc2d7650a788289c19ae2dde3abd189ca47c3", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modp_sub(r, x, y);
|
||||
hex_to_bytes("1b348f0fe311c2ac69d4fb9ae794a2dc4b354a29c2b9d4d228eaf8dda0d970a1", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modp_sub(r, y, x);
|
||||
hex_to_bytes("e4cb70ef1cee3d54962b0465186b5d23b4cab5d73d462b2dd71507225f268f5e", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modp_neg(r, x);
|
||||
hex_to_bytes("94e82e0c1ed3bdb90743191a9c5bbf0d88fc827fd214cc5f0b5ec6ba27673d69", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modp_mul(r, x, y);
|
||||
hex_to_bytes("823cd15f6dd3c71933565064513a6b2bd183e554c6a08622f713ebbbface98be", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modp_sqr(r, x);
|
||||
hex_to_bytes("98f6b84d29bef2b281819a5e0e3690d833b699495d694dd1002ae56c426b3f8c", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modp_exp(r, x, y);
|
||||
hex_to_bytes("2f3db69bc9d93323c351f3e768d332806ad3a7652ea632e89e23312f7b5f9f96", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modp_inv(r, x);
|
||||
hex_to_bytes("e060cbb088706d5d24936933b69b16ab707d656273744b65664c49e577f35238", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modp_inv(r, y);
|
||||
hex_to_bytes("fa27a3da2c00618a828f8cd65c1a919effc67bf68b4dbb05bbdaa775c45d4034", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int test_secp256r1_modn(void)
|
||||
{
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
secp256r1_t r;
|
||||
secp256r1_t v;
|
||||
uint8_t buf[32];
|
||||
size_t len;
|
||||
|
||||
hex_to_bytes("d62fa3e5c258848ff179cdcac74881e4ee06fb025bd66741e942728bb131852c", 64, buf, &len);
|
||||
secp256r1_from_32bytes(x, buf);
|
||||
|
||||
hex_to_bytes("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 64, buf, &len);
|
||||
secp256r1_from_32bytes(y, buf);
|
||||
|
||||
secp256r1_modn_add(r, x, y);
|
||||
hex_to_bytes("2612e6c9c073042a8061b91543581ffb5cee33ac1ff0278bc13ee830ec8db1d0", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modn_dbl(r, x);
|
||||
hex_to_bytes("ac5f47cc84b1091ee2f39b958e9103ca1f26fb5710952ffedecb1a5465ffe507", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modn_tri(r, x);
|
||||
hex_to_bytes("828eebb347098dadd46d696055d985af5046fbabc553f8bbd453c21d1ace44e2", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modn_sub(r, x, y);
|
||||
hex_to_bytes("864c6102c43e04f46291e2804b38e3cec238c7aaf0a508731d8c322379723337", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modn_sub(r, y, x);
|
||||
hex_to_bytes("79b39efc3bc1fb0c9d6e1d7fb4c71c30faae3302b6729611d62d989f82f0f21a", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modn_neg(r, x);
|
||||
hex_to_bytes("29d05c193da77b710e86323538b77e1acedfffab4b4137430a7758374b31a025", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modn_mul(r, x, y);
|
||||
hex_to_bytes("2a876a4e5df28cd6c2f3951aa6b65c55e2d6eb1883b463aee5d95035999c9a30", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modn_mul(r, y, x);
|
||||
hex_to_bytes("2a876a4e5df28cd6c2f3951aa6b65c55e2d6eb1883b463aee5d95035999c9a30", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modn_sqr(r, x);
|
||||
hex_to_bytes("22f25cab8043b82c9a5a6f0ca72c2122700737b557a11ba95ee80bddf671471f", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modn_exp(r, x, y);
|
||||
hex_to_bytes("31e8d728b341541057e09242800bcd7321b523284104340f3ac3bedb55b516c7", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_modn_inv(r, x);
|
||||
hex_to_bytes("a546ddb0e12a46eedab8425e77558aa3e56b7fec1d73fd94c03235e2f2298172", 64, buf, &len);
|
||||
secp256r1_from_32bytes(v, buf);
|
||||
if (secp256r1_cmp(r, v) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int test_secp256r1_point_at_infinity(void)
|
||||
{
|
||||
SECP256R1_POINT P;
|
||||
secp256r1_point_set_infinity(&P);
|
||||
|
||||
if (!secp256r1_point_is_at_infinity(&P)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
secp256r1_point_print(stderr, 0, 4, "point_at_infinity", &P);
|
||||
|
||||
if (!secp256r1_point_is_on_curve(&P)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_secp256r1_point_set_xy(void)
|
||||
{
|
||||
SECP256R1_POINT P;
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
secp256r1_t x1;
|
||||
secp256r1_t y1;
|
||||
uint8_t bytes[32];
|
||||
size_t len;
|
||||
|
||||
hex_to_bytes(secp256r1_x, 64, bytes, &len);
|
||||
secp256r1_from_32bytes(x, bytes);
|
||||
|
||||
hex_to_bytes(secp256r1_y, 64, bytes, &len);
|
||||
secp256r1_from_32bytes(y, bytes);
|
||||
|
||||
if (secp256r1_point_set_xy(&P, x, y) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
secp256r1_point_get_xy(&P, x1, y1);
|
||||
|
||||
if (secp256r1_cmp(x, x1) != 0
|
||||
|| secp256r1_cmp(y, y1) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_secp256r1_point_is_on_curve(void)
|
||||
{
|
||||
if (secp256r1_point_is_on_curve(&SECP256R1_POINT_G) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// 这两个计算是应该分开的!
|
||||
static int test_secp256r1_point_dbl_add(void)
|
||||
{
|
||||
SECP256R1_POINT P;
|
||||
SECP256R1_POINT Q;
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
secp256r1_t x1;
|
||||
secp256r1_t y1;
|
||||
uint8_t bytes[32];
|
||||
size_t len;
|
||||
|
||||
// test 2*G
|
||||
secp256r1_point_dbl(&P, &SECP256R1_POINT_G);
|
||||
secp256r1_point_get_xy(&P, x, y);
|
||||
|
||||
secp256r1_point_print(stderr, 0, 4, "2*G", &P);
|
||||
|
||||
hex_to_bytes("7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978", 64, bytes, &len);
|
||||
secp256r1_from_32bytes(x1, bytes);
|
||||
hex_to_bytes("07775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d1", 64, bytes, &len);
|
||||
secp256r1_from_32bytes(y1, bytes);
|
||||
|
||||
if (secp256r1_cmp(x, x1) != 0 || secp256r1_cmp(y, y1) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// test 2*G + G
|
||||
secp256r1_point_add(&Q, &P, &SECP256R1_POINT_G);
|
||||
secp256r1_point_get_xy(&Q, x, y);
|
||||
|
||||
hex_to_bytes("5ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c", 64, bytes, &len);
|
||||
secp256r1_from_32bytes(x1, bytes);
|
||||
hex_to_bytes("8734640c4998ff7e374b06ce1a64a2ecd82ab036384fb83d9a79b127a27d5032", 64, bytes, &len);
|
||||
secp256r1_from_32bytes(y1, bytes);
|
||||
|
||||
if (secp256r1_cmp(x, x1) != 0 || secp256r1_cmp(y, y1) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char *secp256r1_x_2G = "7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978";
|
||||
static const char *secp256r1_y_2G = "07775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d1";
|
||||
static const char *secp256r1_x_3G = "5ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c";
|
||||
static const char *secp256r1_y_3G = "8734640c4998ff7e374b06ce1a64a2ecd82ab036384fb83d9a79b127a27d5032";
|
||||
|
||||
|
||||
static int test_secp256r1_point_mul(void)
|
||||
{
|
||||
SECP256R1_POINT P;
|
||||
secp256r1_t x;
|
||||
secp256r1_t y;
|
||||
secp256r1_t x1;
|
||||
secp256r1_t y1;
|
||||
secp256r1_t k;
|
||||
uint8_t bytes[32] = {0};
|
||||
size_t len;
|
||||
|
||||
// k = 3
|
||||
bytes[31] = 3;
|
||||
secp256r1_from_32bytes(k, bytes);
|
||||
|
||||
secp256r1_point_mul_generator(&P, k);
|
||||
secp256r1_point_get_xy(&P, x, y); // 这个必须返回错误啊,否则没办法判断是否为无穷远点呢!
|
||||
|
||||
hex_to_bytes(secp256r1_x_3G, 64, bytes, &len);
|
||||
secp256r1_from_32bytes(x1, bytes);
|
||||
hex_to_bytes(secp256r1_y_3G, 64, bytes, &len);
|
||||
secp256r1_from_32bytes(y1, bytes);
|
||||
|
||||
if (secp256r1_cmp(x, x1) != 0 || secp256r1_cmp(y, y1) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// k = n
|
||||
hex_to_bytes(secp256r1_n, 64, bytes, &len);
|
||||
secp256r1_from_32bytes(k, bytes);
|
||||
|
||||
secp256r1_point_mul_generator(&P, k);
|
||||
|
||||
if (secp256r1_point_is_at_infinity(&P) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_secp256r1_point_to_uncompressed_octets(void)
|
||||
{
|
||||
SECP256R1_POINT P;
|
||||
uint8_t octets[65];
|
||||
|
||||
|
||||
secp256r1_point_copy(&P, &SECP256R1_POINT_G);
|
||||
|
||||
if (secp256r1_point_to_uncompressed_octets(&P, octets) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (secp256r1_point_from_uncompressed_octets(&P, octets) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (test_secp256r1() != 1) goto err;
|
||||
if (test_secp256r1_modp() != 1) goto err;
|
||||
if (test_secp256r1_modn() != 1) goto err;
|
||||
if (test_secp256r1_point_at_infinity() != 1) goto err;
|
||||
if (test_secp256r1_point_is_on_curve() != 1) goto err;
|
||||
if (test_secp256r1_point_set_xy() != 1) goto err;
|
||||
if (test_secp256r1_point_dbl_add() != 1) goto err;
|
||||
if (test_secp256r1_point_mul() != 1) goto err;
|
||||
if (test_secp256r1_point_to_uncompressed_octets() != 1) goto err;
|
||||
|
||||
|
||||
printf("%s all tests passed\n", __FILE__);
|
||||
return 0;
|
||||
err:
|
||||
error_print();
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user