mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-28 03:06:24 +08:00
SM2 KAP (Key Agreement Protocol), not tested
This commit is contained in:
@@ -17,9 +17,9 @@ TEST=sm2test.c
|
||||
APPS=
|
||||
|
||||
LIB=$(TOP)/libcrypto.a
|
||||
LIBSRC= sm2_lib.c sm2_err.c sm2_sign.c sm2_enc.c
|
||||
LIBSRC= sm2_lib.c sm2_err.c sm2_sign.c sm2_enc.c sm2_kap.c
|
||||
|
||||
LIBOBJ= sm2_lib.o sm2_err.o sm2_sign.o sm2_enc.o
|
||||
LIBOBJ= sm2_lib.o sm2_err.o sm2_sign.o sm2_enc.o sm2_kap.o
|
||||
|
||||
SRC= $(LIBSRC)
|
||||
|
||||
|
||||
@@ -83,7 +83,8 @@ typedef struct sm2_ciphertext_value_st {
|
||||
char *SM2_get_id(EC_KEY *ec_key);
|
||||
int SM2_set_id(EC_KEY *ec_key, const char *id);
|
||||
int SM2_compute_id_digest(unsigned char *dgst, unsigned int *dgstlen,
|
||||
const EVP_MD *md, const void *id, size_t idlen, EC_KEY *ec_key);
|
||||
const EVP_MD *md, EC_KEY *ec_key);
|
||||
|
||||
|
||||
int SM2_CIPHERTEXT_VALUE_size(const EC_GROUP *ec_group,
|
||||
point_conversion_form_t point_form, size_t mlen,
|
||||
@@ -128,6 +129,55 @@ int SM2_sign(int type, const unsigned char *dgst, int dgstlen,
|
||||
int SM2_verify(int type, const unsigned char *dgst, int dgstlen,
|
||||
const unsigned char *sig, int siglen, EC_KEY *ec_key);
|
||||
|
||||
|
||||
|
||||
typedef struct sm2_kap_ctx_st {
|
||||
|
||||
const EVP_MD *id_dgst_md;
|
||||
const EVP_MD *kdf_md;
|
||||
const EVP_MD *checksum_md;
|
||||
point_conversion_form_t point_form;
|
||||
KDF_FUNC kdf;
|
||||
|
||||
int is_initiator;
|
||||
int do_checksum;
|
||||
|
||||
EC_KEY *ec_key;
|
||||
unsigned char id_dgst[EVP_MAX_MD_SIZE];
|
||||
unsigned int id_dgstlen;
|
||||
|
||||
EC_KEY *remote_pubkey;
|
||||
unsigned char remote_id_dgst[EVP_MAX_MD_SIZE];
|
||||
unsigned int remote_id_dgstlen;
|
||||
|
||||
const EC_GROUP *group;
|
||||
BN_CTX *bn_ctx;
|
||||
BIGNUM *order;
|
||||
BIGNUM *two_pow_w;
|
||||
|
||||
BIGNUM *t;
|
||||
EC_POINT *point;
|
||||
unsigned char pt_buf[1 + (OPENSSL_ECC_MAX_FIELD_BITS+7)/4];
|
||||
unsigned char checksum[EVP_MAX_MD_SIZE];
|
||||
|
||||
} SM2_KAP_CTX;
|
||||
|
||||
|
||||
|
||||
int SM2_KAP_CTX_init_ex(SM2_KAP_CTX *ctx, EC_KEY *ec_key,
|
||||
EC_KEY *remote_pubkey, int is_initiator, int do_checksum);
|
||||
void SM2_KAP_CTX_cleanup(SM2_KAP_CTX *ctx);
|
||||
int SM2_KAP_prepare(SM2_KAP_CTX *ctx, unsigned char *ephem_point,
|
||||
size_t ephem_point_len);
|
||||
int SM2_KAP_compute_key(SM2_KAP_CTX *ctx, const unsigned char *remote_ephem_point,
|
||||
size_t remote_ephem_point_len, unsigned char *key, size_t *keylen,
|
||||
unsigned char *checksum, size_t *checksumlen);
|
||||
int SM2_KAP_final_check(SM2_KAP_CTX *ctx, const unsigned char *checksum,
|
||||
size_t checksumlen);
|
||||
|
||||
|
||||
|
||||
|
||||
void ERR_load_SM2_strings(void);
|
||||
|
||||
/* Function codes. */
|
||||
@@ -143,14 +193,20 @@ void ERR_load_SM2_strings(void);
|
||||
#define SM2_F_SM2_DO_DECRYPT 109
|
||||
#define SM2_F_SM2_ENCRYPT 110
|
||||
#define SM2_F_SM2_DECRYPT 111
|
||||
#define SM2_SIGNATURE_SIZE 112
|
||||
#define SM2_SIGN_SETUP 113
|
||||
#define SM2_DO_SIGN_EX 114
|
||||
#define SM2_DO_SIGN 115
|
||||
#define SM2_DO_VERIFY 116
|
||||
#define SM2_SIGN_EX 117
|
||||
#define SM2_SIGN 118
|
||||
#define SM2_VERIFY 119
|
||||
#define SM2_F_SM2_SIGNATURE_SIZE 112
|
||||
#define SM2_F_SM2_SIGN_SETUP 113
|
||||
#define SM2_F_SM2_DO_SIGN_EX 114
|
||||
#define SM2_F_SM2_DO_SIGN 115
|
||||
#define SM2_F_SM2_DO_VERIFY 116
|
||||
#define SM2_F_SM2_SIGN_EX 117
|
||||
#define SM2_F_SM2_SIGN 118
|
||||
#define SM2_F_SM2_VERIFY 119
|
||||
#define SM2_F_SM2_KAP_CTX_INIT 120
|
||||
#define SM2_F_SM2_KAP_CTX_CLEANUP 121
|
||||
#define SM2_F_SM2_KAP_PREPARE 122
|
||||
#define SM2_F_SM2_KAP_COMPUTE_KEY 123
|
||||
#define SM2_F_SM2_KAP_FINAL_CHECK 124
|
||||
|
||||
|
||||
/* Reason codes. */
|
||||
#define SM2_R_BAD_DATA 100
|
||||
@@ -162,6 +218,8 @@ void ERR_load_SM2_strings(void);
|
||||
#define SM2_R_VERIFY_MAC_FAILED 106
|
||||
#define SM2_R_ECDH_FAILED 107
|
||||
#define SM2_R_BUFFER_TOO_SMALL 108
|
||||
#define SM2_R_SM2_KAP_NOT_INITED 109
|
||||
#define SM2_R_RANDOM_NUMBER_GENERATION_FAILED 110
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
37
crypto/sm2/sm2_asn1.c
Normal file
37
crypto/sm2/sm2_asn1.c
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* from GM/T 0009-2012
|
||||
* "SM2 Cryptography Algorithm Application Specification"
|
||||
*
|
||||
SM2PrivateKey ::= INTEGER
|
||||
|
||||
SM2PublicKey ::= BIT STRING
|
||||
|
||||
SM2CiphertextValue ::= SEQUENCE {
|
||||
XCoordinate INTEGER,
|
||||
YCoordinate INTEGER,
|
||||
Hash OCTET STRING SIZE(32),
|
||||
Ciphertext OCTET STRING
|
||||
}
|
||||
|
||||
SM2Signature ::= SEQUENCE {
|
||||
R INTEGER,
|
||||
S INTEGER,
|
||||
}
|
||||
|
||||
SM2EnvelopedKey ::= SEQUENCE {
|
||||
symAlgID AlgorithmIdentifier,
|
||||
symEncryptedKey SM2CiphertextValue,
|
||||
sm2PublicKey SM2PublicKey,
|
||||
sm2EncryptedPrivateKey BIT STRING
|
||||
}
|
||||
|
||||
ZID = SM3(nbits(ID)||ID||a||b||xG||yG||xA||yA)
|
||||
|
||||
Default ID = "1234567812345678"
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -60,42 +60,6 @@
|
||||
#define ERR_REASON(reason) ERR_PACK(ERR_LIB_ECIES,0,reason)
|
||||
|
||||
|
||||
#define SM2_F_SM2_SET_ID 100
|
||||
#define SM2_F_SM2_GET_ID 101
|
||||
#define SM2_F_SM2_COMPUTE_ID_DIGEST 102
|
||||
#define SM2_F_SM2_CIPHERTEXT_VALUE_SIZE 103
|
||||
#define SM2_F_SM2_CIPHERTEXT_VALUE_FREE 104
|
||||
#define SM2_F_SM2_CIPHERTEXT_VALUE_ENCODE 105
|
||||
#define SM2_F_SM2_CIPHERTEXT_VALUE_DECODE 106
|
||||
#define SM2_F_SM2_CIPHERTEXT_VALUE_PRINT 107
|
||||
#define SM2_F_SM2_DO_ENCRYPT 108
|
||||
#define SM2_F_SM2_DO_DECRYPT 109
|
||||
#define SM2_F_SM2_ENCRYPT 110
|
||||
#define SM2_F_SM2_DECRYPT 111
|
||||
#define SM2_SIGNATURE_SIZE 112
|
||||
#define SM2_SIGN_SETUP 113
|
||||
#define SM2_DO_SIGN_EX 114
|
||||
#define SM2_DO_SIGN 115
|
||||
#define SM2_DO_VERIFY 116
|
||||
#define SM2_SIGN_EX 117
|
||||
#define SM2_SIGN 118
|
||||
#define SM2_VERIFY 119
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static ERR_STRING_DATA SM2_str_functs[] = {
|
||||
{ERR_FUNC(SM2_F_SM2_SET_ID), "SM2_SET_ID"},
|
||||
{ERR_FUNC(SM2_F_SM2_GET_ID), "SM2_F_SM2_GET_ID"},
|
||||
@@ -109,27 +73,34 @@ static ERR_STRING_DATA SM2_str_functs[] = {
|
||||
{ERR_FUNC(SM2_F_SM2_DO_DECRYPT), "SM2_do_decrypt"},
|
||||
{ERR_FUNC(SM2_F_SM2_ENCRYPT), "SM2_encrypt"},
|
||||
{ERR_FUNC(SM2_F_SM2_DECRYPT), "SM2_decrypt"},
|
||||
{ERR_FUNC(SM2_SIGNATURE_SIZE), "SM2_signature_size"},
|
||||
{ERR_FUNC(SM2_SIGN_SETUP), "SM2_sign_setup"},
|
||||
{ERR_FUNC(SM2_DO_SIGN_EX), "SM2_do_sign_ex"},
|
||||
{ERR_FUNC(SM2_DO_SIGN), "SM2_do_sign"},
|
||||
{ERR_FUNC(SM2_DO_VERIFY), "SM2_do_verify"},
|
||||
{ERR_FUNC(SM2_SIGN_EX), "SM2_sign_ex"},
|
||||
{ERR_FUNC(SM2_SIGN), "SM2_sign"},
|
||||
{ERR_FUNC(SM2_VERIFY), "SM2_verify"},
|
||||
{ERR_FUNC(SM2_F_SM2_SIGNATURE_SIZE), "SM2_signature_size"},
|
||||
{ERR_FUNC(SM2_F_SM2_SIGN_SETUP), "SM2_sign_setup"},
|
||||
{ERR_FUNC(SM2_F_SM2_DO_SIGN_EX), "SM2_do_sign_ex"},
|
||||
{ERR_FUNC(SM2_F_SM2_DO_SIGN), "SM2_do_sign"},
|
||||
{ERR_FUNC(SM2_F_SM2_DO_VERIFY), "SM2_do_verify"},
|
||||
{ERR_FUNC(SM2_F_SM2_SIGN_EX), "SM2_sign_ex"},
|
||||
{ERR_FUNC(SM2_F_SM2_SIGN), "SM2_sign"},
|
||||
{ERR_FUNC(SM2_F_SM2_VERIFY), "SM2_verify"},
|
||||
{ERR_FUNC(SM2_F_SM2_KAP_CTX_INIT), "SM2_KAP_CTX_init"},
|
||||
{ERR_FUNC(SM2_F_SM2_KAP_CTX_CLEANUP), "SM2_KAP_CTX_cleanup"},
|
||||
{ERR_FUNC(SM2_F_SM2_KAP_PREPARE), "SM2_KAP_prepare"},
|
||||
{ERR_FUNC(SM2_F_SM2_KAP_COMPUTE_KEY), "SM2_KAP_compute_key"},
|
||||
{ERR_FUNC(SM2_F_SM2_KAP_FINAL_CHECK), "SM2_KAP_final_check"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
static ERR_STRING_DATA SM2_str_reasons[] = {
|
||||
{ERR_REASON(SM2_R_BAD_DATA), "bad data"},
|
||||
{ERR_REASON(SM2_R_UNKNOWN_CIPHER_TYPE),"unknown cipher type"},
|
||||
{ERR_REASON(SM2_R_UNKNOWN_CIPHER_TYPE), "unknown cipher type"},
|
||||
{ERR_REASON(SM2_R_ENCRYPT_FAILED), "encrypt failed"},
|
||||
{ERR_REASON(SM2_R_DECRYPT_FAILED), "decrypt failed"},
|
||||
{ERR_REASON(SM2_R_UNKNOWN_MAC_TYPE), "unknown MAC type"},
|
||||
{ERR_REASON(SM2_R_GEN_MAC_FAILED), "MAC generation failed"},
|
||||
{ERR_REASON(SM2_R_VERIFY_MAC_FAILED), "MAC verification failed"},
|
||||
{ERR_REASON(SM2_R_ECDH_FAILED), "ECDH failed"},
|
||||
{ERR_REASON(SM2_R_ECDH_FAILED), "ECDH failed"},
|
||||
{ERR_REASON(SM2_R_BUFFER_TOO_SMALL), "buffer too small"},
|
||||
{ERR_REASON(SM2_R_SM2_KAP_NOT_INITED), "KAP not inited"},
|
||||
{ERR_REASON(SM2_R_RANDOM_NUMBER_GENERATION_FAILED), "random number generation failed"},
|
||||
{0,NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -48,3 +48,504 @@
|
||||
* ====================================================================
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include "sm2.h"
|
||||
|
||||
int SM2_KAP_CTX_init_ex(SM2_KAP_CTX *ctx, EC_KEY *ec_key,
|
||||
EC_KEY *remote_pubkey, int is_initiator, int do_checksum)
|
||||
{
|
||||
int ret = 0;
|
||||
int w;
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
ctx->id_dgst_md = EVP_sm3();
|
||||
ctx->kdf_md = EVP_sm3();
|
||||
ctx->checksum_md = EVP_sm3();
|
||||
ctx->point_form = POINT_CONVERSION_COMPRESSED;
|
||||
|
||||
if (!(ctx->kdf = KDF_get_x9_63(ctx->kdf_md))) {
|
||||
SM2err(SM2_F_SM2_KAP_CTX_INIT, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ctx->is_initiator = is_initiator;
|
||||
ctx->do_checksum = do_checksum;
|
||||
|
||||
if (EC_GROUP_cmp(EC_KEY_get0_group(ec_key),
|
||||
EC_KEY_get0_group(remote_pubkey), NULL) != 0) {
|
||||
SM2err(SM2_F_SM2_KAP_CTX_INIT, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!SM2_compute_id_digest(ctx->id_dgst, &ctx->id_dgstlen,
|
||||
ctx->id_dgst_md, ec_key)) {
|
||||
SM2err(SM2_F_SM2_KAP_CTX_INIT, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(ctx->ec_key = EC_KEY_dup(ec_key))) {
|
||||
SM2err(SM2_F_SM2_KAP_CTX_INIT, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!SM2_compute_id_digest(ctx->remote_id_dgst, &ctx->remote_id_dgstlen,
|
||||
ctx->id_dgst_md, remote_pubkey)) {
|
||||
SM2err(SM2_F_SM2_KAP_CTX_INIT, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(ctx->remote_pubkey = EC_KEY_dup(remote_pubkey))) {
|
||||
SM2err(SM2_F_SM2_KAP_CTX_INIT, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ctx->group = EC_KEY_get0_group(ec_key);
|
||||
ctx->bn_ctx = BN_CTX_new();
|
||||
ctx->order = BN_new();
|
||||
ctx->two_pow_w = BN_new();
|
||||
ctx->t = BN_new();
|
||||
|
||||
if (!ctx->bn_ctx || !ctx->order || !ctx->two_pow_w || !ctx->t) {
|
||||
SM2err(SM2_F_SM2_KAP_CTX_INIT, ERR_R_BN_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!EC_GROUP_get_order(EC_KEY_get0_group(ec_key), ctx->order, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_CTX_INIT, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
w = (EC_GROUP_get_degree(ctx->group) + 1)/2 - 1;
|
||||
|
||||
if (!BN_one(ctx->two_pow_w)) {
|
||||
SM2err(SM2_F_SM2_KAP_CTX_INIT, ERR_R_BN_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!BN_lshift(ctx->two_pow_w, ctx->two_pow_w, w)) {
|
||||
SM2err(SM2_F_SM2_KAP_CTX_INIT, ERR_R_BN_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(ctx->point = EC_POINT_new(ctx->group))) {
|
||||
SM2err(SM2_F_SM2_KAP_CTX_INIT, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
if (!ret) SM2_KAP_CTX_cleanup(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SM2_KAP_CTX_cleanup(SM2_KAP_CTX *ctx)
|
||||
{
|
||||
if (ctx->ec_key) EC_KEY_free(ctx->ec_key);
|
||||
if (ctx->remote_pubkey) EC_KEY_free(ctx->remote_pubkey);
|
||||
if (ctx->bn_ctx) BN_CTX_free(ctx->bn_ctx);
|
||||
if (ctx->two_pow_w) BN_free(ctx->two_pow_w);
|
||||
if (ctx->order) BN_free(ctx->order);
|
||||
if (ctx->point) EC_POINT_free(ctx->point);
|
||||
if (ctx->t) BN_free(ctx->t);
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
int SM2_KAP_prepare(SM2_KAP_CTX *ctx, unsigned char *ephem_point,
|
||||
size_t ephem_point_len)
|
||||
{
|
||||
int ret = 0;
|
||||
const BIGNUM *prikey;
|
||||
BIGNUM *h = NULL;
|
||||
BIGNUM *r = NULL;
|
||||
BIGNUM *x = NULL;
|
||||
|
||||
if (!(prikey = EC_KEY_get0_private_key(ctx->ec_key))) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, SM2_R_SM2_KAP_NOT_INITED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
h = BN_new();
|
||||
r = BN_new();
|
||||
x = BN_new();
|
||||
|
||||
if (!h || !r || !x) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* r = rand(1, n)
|
||||
* R = rG = (x, y)
|
||||
*/
|
||||
|
||||
do {
|
||||
if (!BN_rand_range(r, ctx->order)) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, SM2_R_RANDOM_NUMBER_GENERATION_FAILED);
|
||||
goto end;
|
||||
}
|
||||
|
||||
} while (BN_is_zero(r));
|
||||
|
||||
if (!EC_POINT_mul(ctx->group, ctx->point, r, NULL, NULL, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (EC_METHOD_get_field_type(EC_GROUP_method_of(ctx->group)) == NID_X9_62_prime_field) {
|
||||
if (!EC_POINT_get_affine_coordinates_GFp(ctx->group, ctx->point, x, NULL, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(ctx->group, ctx->point, x, NULL, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* w = ceil(keybits / 2) - 1
|
||||
* x = 2^w + (x and (2^w - 1)) = 2^w + (x mod 2^w)
|
||||
* t = (d + x * r) mod n
|
||||
* t = (h * t) mod n
|
||||
*/
|
||||
|
||||
if (!ctx->t) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, SM2_R_SM2_KAP_NOT_INITED);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!BN_nnmod(x, x, ctx->two_pow_w, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, ERR_R_BN_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!BN_add(x, x, ctx->two_pow_w)) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, ERR_R_BN_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!BN_mod_mul(ctx->t, x, r, ctx->order, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, ERR_R_BN_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!BN_mod_add(ctx->t, ctx->t, prikey, ctx->order, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, ERR_R_BN_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!EC_GROUP_get_cofactor(ctx->group, h, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!BN_mul(ctx->t, ctx->t, h, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_PREPARE, ERR_R_BN_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* encode R = (x, y) for output and local buffer */
|
||||
|
||||
ret = EC_POINT_point2oct(ctx->group, ctx->point, ctx->point_form,
|
||||
ephem_point, ephem_point_len, ctx->bn_ctx);
|
||||
|
||||
memcpy(ctx->pt_buf, ephem_point, ret);
|
||||
|
||||
|
||||
end:
|
||||
if (h) BN_free(h);
|
||||
if (r) BN_free(r);
|
||||
if (x) BN_free(x);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SM2_KAP_compute_key(SM2_KAP_CTX *ctx, const unsigned char *remote_point,
|
||||
size_t remote_point_len, unsigned char *key, size_t *keylen,
|
||||
unsigned char *checksum, size_t *checksumlen)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
EVP_MD_CTX md_ctx;
|
||||
BIGNUM *x = NULL;
|
||||
unsigned char share_pt_buf[1 + (OPENSSL_ECC_MAX_FIELD_BITS+7)/4 + EVP_MAX_MD_SIZE * 2];
|
||||
unsigned char remote_pt_buf[1 + (OPENSSL_ECC_MAX_FIELD_BITS+7)/4];
|
||||
unsigned char dgst[EVP_MAX_MD_SIZE];
|
||||
unsigned int dgstlen;
|
||||
unsigned int len, bnlen;
|
||||
|
||||
EVP_MD_CTX_init(&md_ctx);
|
||||
|
||||
if (!(x = BN_new())) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* decode point R = (x, y), encode (x, y)
|
||||
* x = 2^w + (x and (2^w - 1)) = 2^w + (x mod 2^w), w = ceil(keybits / 2) - 1
|
||||
* U = ht * (P + x * R)
|
||||
* check U != O
|
||||
*/
|
||||
|
||||
if (!EC_POINT_oct2point(ctx->group, ctx->point,
|
||||
remote_point, remote_point_len, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(len = EC_POINT_point2oct(ctx->group, ctx->point, POINT_CONVERSION_UNCOMPRESSED,
|
||||
remote_pt_buf, sizeof(remote_pt_buf), ctx->bn_ctx))) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (EC_METHOD_get_field_type(EC_GROUP_method_of(ctx->group)) == NID_X9_62_prime_field) {
|
||||
if (!EC_POINT_get_affine_coordinates_GFp(ctx->group, ctx->point, x, NULL, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (!EC_POINT_get_affine_coordinates_GF2m(ctx->group, ctx->point, x, NULL, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* x = 2^w + (x and (2^w - 1)) = 2^w + (x mod 2^w) */
|
||||
|
||||
if (!BN_nnmod(x, x, ctx->two_pow_w, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_BN_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!BN_add(x, x, ctx->two_pow_w)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_BN_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!BN_mod_mul(x, x, ctx->t, ctx->order, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_BN_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* U = ht * (P + x * R), check U != O */
|
||||
|
||||
if (!EC_POINT_mul(ctx->group, ctx->point, NULL, ctx->point, x, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!EC_POINT_add(ctx->group, ctx->point, ctx->point,
|
||||
EC_KEY_get0_public_key(ctx->remote_pubkey), ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!EC_POINT_mul(ctx->group, ctx->point, NULL, ctx->point, ctx->t, ctx->bn_ctx)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EC_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!EC_POINT_is_at_infinity(ctx->group, ctx->point)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* encode U, append with ZA, ZB */
|
||||
|
||||
if (!(len = EC_POINT_point2oct(ctx->group, ctx->point, POINT_CONVERSION_UNCOMPRESSED,
|
||||
share_pt_buf, sizeof(share_pt_buf), ctx->bn_ctx))) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ctx->is_initiator) {
|
||||
memcpy(share_pt_buf + len, ctx->id_dgst, ctx->id_dgstlen);
|
||||
len += ctx->id_dgstlen;
|
||||
memcpy(share_pt_buf + len, ctx->remote_id_dgst, ctx->remote_id_dgstlen);
|
||||
len += ctx->remote_id_dgstlen;
|
||||
} else {
|
||||
memcpy(share_pt_buf + len, ctx->remote_id_dgst, ctx->remote_id_dgstlen);
|
||||
len += ctx->remote_id_dgstlen;
|
||||
memcpy(share_pt_buf + len, ctx->id_dgst, ctx->id_dgstlen);
|
||||
len += ctx->id_dgstlen;
|
||||
}
|
||||
|
||||
/* key = KDF(xu, yu, ZA, ZB) */
|
||||
|
||||
if (!ctx->kdf(share_pt_buf, len, key, keylen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!ctx->do_checksum) {
|
||||
|
||||
/* generate checksum S1 or SB start with 0x02
|
||||
* S1 = SB = Hash(0x02, yu, Hash(xu, ZA, ZB, x1, y1, x2, y2))
|
||||
*/
|
||||
if (!EVP_DigestInit_ex(&md_ctx, ctx->checksum_md, NULL)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
bnlen = BN_num_bytes(ctx->order);
|
||||
|
||||
if (!EVP_DigestUpdate(&md_ctx, share_pt_buf + 1, bnlen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ctx->is_initiator) {
|
||||
|
||||
if (!EVP_DigestUpdate(&md_ctx, ctx->id_dgst, ctx->id_dgstlen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
if (!EVP_DigestUpdate(&md_ctx, ctx->remote_id_dgst, ctx->remote_id_dgstlen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
if (!EVP_DigestUpdate(&md_ctx, ctx->pt_buf + 1, bnlen * 2)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
if (!EVP_DigestUpdate(&md_ctx, remote_pt_buf + 1, bnlen * 2)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!EVP_DigestUpdate(&md_ctx, ctx->remote_id_dgst, ctx->remote_id_dgstlen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
if (!EVP_DigestUpdate(&md_ctx, ctx->id_dgst, ctx->id_dgstlen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
if (!EVP_DigestUpdate(&md_ctx, remote_pt_buf + 1, bnlen * 2)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
if (!EVP_DigestUpdate(&md_ctx, ctx->pt_buf + 1, bnlen * 2)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EVP_DigestFinal_ex(&md_ctx, dgst, &dgstlen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* S1 = SB = Hash(0x02, yu, dgst) */
|
||||
|
||||
if (!EVP_DigestInit_ex(&md_ctx, ctx->checksum_md, NULL)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!EVP_DigestUpdate(&md_ctx, "\0x02", 1)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!EVP_DigestUpdate(&md_ctx, share_pt_buf + 1 + bnlen, bnlen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!EVP_DigestUpdate(&md_ctx, dgst, dgstlen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* output S1 to local buffer or SB to output */
|
||||
if (ctx->is_initiator) {
|
||||
if (!EVP_DigestFinal_ex(&md_ctx, ctx->checksum, &len)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (!EVP_DigestFinal_ex(&md_ctx, checksum, &len)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
*checksumlen = len;
|
||||
}
|
||||
|
||||
/* generate checksum SA or S2 start with 0x03
|
||||
* SA = S2 = Hash(0x03, yu, dgst)
|
||||
*/
|
||||
|
||||
if (!EVP_DigestInit_ex(&md_ctx, ctx->checksum_md, NULL)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!EVP_DigestUpdate(&md_ctx, "\0x03", 1)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!EVP_DigestUpdate(&md_ctx, share_pt_buf + 1 + bnlen, bnlen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!EVP_DigestUpdate(&md_ctx, dgst, dgstlen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ctx->is_initiator) {
|
||||
if (!EVP_DigestFinal_ex(&md_ctx, checksum, &len)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
*checksumlen = len;
|
||||
|
||||
} else {
|
||||
if (!EVP_DigestFinal_ex(&md_ctx, ctx->checksum, &len)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EVP_LIB);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
if (x) BN_free(x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SM2_KAP_final_check(SM2_KAP_CTX *ctx, const unsigned char *checksum,
|
||||
size_t checksumlen)
|
||||
{
|
||||
if (ctx->do_checksum) {
|
||||
|
||||
if (checksumlen != EVP_MD_size(ctx->checksum_md)) {
|
||||
SM2err(SM2_F_SM2_KAP_FINAL_CHECK, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp(ctx->checksum, checksum, checksumlen)) {
|
||||
SM2err(SM2_F_SM2_KAP_COMPUTE_KEY, ERR_R_EC_LIB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -185,18 +185,25 @@ err:
|
||||
}
|
||||
|
||||
int SM2_compute_id_digest(unsigned char *dgst, unsigned int *dgstlen,
|
||||
const EVP_MD *md, const void *id, size_t idlen, EC_KEY *ec_key)
|
||||
const EVP_MD *md, EC_KEY *ec_key)
|
||||
{
|
||||
int ret = 0;
|
||||
EVP_MD_CTX *md_ctx = NULL;
|
||||
unsigned char pkdata[EC_MAX_NBYTES * 6];
|
||||
uint16_t idbits = idlen * 8;
|
||||
uint16_t idbits;
|
||||
int pkdatalen;
|
||||
char *id = NULL;
|
||||
|
||||
if ((pkdatalen = sm2_get_public_key_data(pkdata, ec_key)) < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(id = SM2_get_id(ec_key))) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
idbits = strlen(id) * 8;
|
||||
|
||||
if (!(md_ctx = EVP_MD_CTX_create())) {
|
||||
goto err;
|
||||
}
|
||||
@@ -206,7 +213,7 @@ int SM2_compute_id_digest(unsigned char *dgst, unsigned int *dgstlen,
|
||||
if (!EVP_DigestUpdate(md_ctx, &idbits, sizeof(idbits))) {
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_DigestUpdate(md_ctx, id, idlen)) {
|
||||
if (!EVP_DigestUpdate(md_ctx, id, strlen(id))) {
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_DigestUpdate(md_ctx, pkdata, pkdatalen)) {
|
||||
|
||||
@@ -88,6 +88,58 @@ static int test_sm2_enc(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_sm2_kap(void)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
int curve_name = NID_sm2p256v1;
|
||||
EC_KEY *eckey1 = NULL;
|
||||
EC_KEY *eckey2 = NULL;
|
||||
SM2_KAP_CTX ctx1;
|
||||
SM2_KAP_CTX ctx2;
|
||||
|
||||
eckey1 = EC_KEY_new_by_curve_name(curve_name);
|
||||
OPENSSL_assert(eckey1 != NULL);
|
||||
|
||||
eckey2 = EC_KEY_new_by_curve_name(curve_name);
|
||||
OPENSSL_assert(eckey2 != NULL);
|
||||
|
||||
rv = EC_KEY_generate_key(eckey1);
|
||||
OPENSSL_assert(rv == 1);
|
||||
|
||||
rv = EC_KEY_generate_key(eckey2);
|
||||
OPENSSL_assert(rv == 1);
|
||||
|
||||
rv = SM2_set_id(eckey1, "Alice");
|
||||
OPENSSL_assert(rv == 1);
|
||||
|
||||
rv = SM2_set_id(eckey2, "Bob");
|
||||
OPENSSL_assert(rv == 1);
|
||||
|
||||
|
||||
rv = SM2_KAP_init();
|
||||
OPENSSL_assert(rv == 1);
|
||||
|
||||
rv = SM2_KAP_prepare(&ctx1);
|
||||
OPENSSL_assert(rv == 1);
|
||||
|
||||
rv = SM2_KAP_prepare(&ctx2);
|
||||
OPENSSL_assert(rv == 1);
|
||||
|
||||
rv = SM2_KAP_compute_key(&ctx1);
|
||||
OPENSSL_assert(rv == 1);
|
||||
|
||||
rv = SM2_KAP_compute_key(&ctx2);
|
||||
OPENSSL_assert(rv == 1);
|
||||
|
||||
rv = SM2_KAP_final_check(&ctx1);
|
||||
OPENSSL_assert(rv == 1);
|
||||
|
||||
rv = SM2_KAP_final_check(&ctx2);
|
||||
OPENSSL_assert(rv == 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user