From 4e3992d3f0ab8e7ff74b47c4a1b7d8bae5cb59b9 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sun, 15 May 2022 14:06:29 +0800 Subject: [PATCH] Update SM9 --- include/gmssl/sm9.h | 76 ++++++++++-- src/sm9_alg.c | 36 +++--- src/sm9_key.c | 294 ++++++++++++++++++++++++++++++++++++++++++++ src/sm9_lib.c | 253 +++++++++++++++++++++++++++++++++----- 4 files changed, 604 insertions(+), 55 deletions(-) diff --git a/include/gmssl/sm9.h b/include/gmssl/sm9.h index dba22138..e687f661 100644 --- a/include/gmssl/sm9.h +++ b/include/gmssl/sm9.h @@ -312,9 +312,12 @@ int sm9_point_from_bytes(sm9_point_t *P, const uint8_t in[32 * 2]); int sm9_twist_point_to_bytes(const sm9_twist_point_t *P, uint8_t out[32 * 2]); int sm9_twist_point_from_bytes(sm9_twist_point_t *P, const uint8_t in[32 * 2]); - - - +void sm9_fn_to_bytes(const sm9_fn_t a, uint8_t out[32]); +int sm9_fn_from_bytes(sm9_fn_t a, const uint8_t in[32]); +int sm9_point_to_uncompressed_octets(const sm9_point_t *P, uint8_t octets[65]); +int sm9_point_from_uncompressed_octets(sm9_point_t *P, const uint8_t octets[65]); +int sm9_twist_point_to_uncompressed_octets(const sm9_twist_point_t *P, uint8_t octets[129]); +int sm9_twist_point_from_uncompressed_octets(sm9_twist_point_t *P, const uint8_t octets[129]); // set the same value as sm2 @@ -331,20 +334,48 @@ typedef struct { uint8_t y[64]; } SM9_TWIST_POINT; + +/* +SM9SignMasterKey ::= SEQUENCE { + ks INTEGER, + Ppubs BIT STRING, -- uncompressed octets of twisted point +} +*/ typedef struct { sm9_twist_point_t Ppubs; // Ppubs = ks * P2 sm9_fn_t ks; } SM9_SIGN_MASTER_KEY; +int sm9_sign_master_key_to_der(const SM9_SIGN_MASTER_KEY *msk, uint8_t **out, size_t *outlen); +int sm9_sign_master_key_from_der(SM9_SIGN_MASTER_KEY *msk, const uint8_t **in, size_t *inlen); +int sm9_sign_master_public_key_to_der(const SM9_SIGN_MASTER_KEY *mpk, uint8_t **out, size_t *outlen); +int sm9_sign_master_public_key_from_der(SM9_SIGN_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen); + +/* +SM9SignPrivateKey ::= SEQUENCE { + ds BIT STRING, -- uncompressed octets of ECPoint + Ppubs BIT STRING -- uncompressed octets of twisted point +} +*/ typedef struct { sm9_twist_point_t Ppubs; sm9_point_t ds; } SM9_SIGN_KEY; +int sm9_sign_key_to_der(const SM9_SIGN_KEY *key, uint8_t **out, size_t *outlen); +int sm9_sign_key_from_der(SM9_SIGN_KEY *key, const uint8_t **in, size_t *inlen); + + int sm9_sign_master_key_generate(SM9_SIGN_MASTER_KEY *master); int sm9_sign_master_key_extract_key(SM9_SIGN_MASTER_KEY *master, const char *id, size_t idlen, SM9_SIGN_KEY *key); +/* +from GM/T 0080-2020 SM9 Cryptographic Alagorithm Application Specification +SM9Signature ::= SEQUENCE { + h OCTET STRING, + S BIT STRING, -- uncompressed octets of ECPoint } +*/ typedef struct { sm9_fn_t h; sm9_point_t S; @@ -353,6 +384,8 @@ typedef struct { int sm9_do_sign(const SM9_SIGN_KEY *key, const SM3_CTX *sm3_ctx, SM9_SIGNATURE *sig); int sm9_do_verify(const SM9_SIGN_MASTER_KEY *mpk, const char *id, size_t idlen, const SM3_CTX *sm3_ctx, const SM9_SIGNATURE *sig); +int sm9_signature_to_der(const SM9_SIGNATURE *sig, uint8_t **out, size_t *outlen); +int sm9_signature_from_der(SM9_SIGNATURE *sig, const uint8_t **in, size_t *inlen); typedef struct { @@ -368,26 +401,53 @@ int sm9_verify_update(SM9_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); int sm9_verify_finish(SM9_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen, const SM9_SIGN_MASTER_KEY *mpk, const char *id, size_t idlen); - typedef struct { sm9_point_t Ppube; // Ppube = ke * P1 sm9_fn_t ke; } SM9_ENC_MASTER_KEY; +int sm9_enc_master_key_to_der(const SM9_ENC_MASTER_KEY *msk, uint8_t **out, size_t *outlen); +int sm9_enc_master_key_from_der(SM9_ENC_MASTER_KEY *msk, const uint8_t **in, size_t *inlen); +int sm9_enc_master_public_key_to_der(const SM9_ENC_MASTER_KEY *mpk, uint8_t **out, size_t *outlen); +int sm9_enc_master_public_key_from_der(SM9_ENC_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen); + +/* +SM9EncPrivateKey ::= SEQUENCE { + de BIT STRING, -- uncompressed octets of twisted point + Ppube BIT STRING -- uncompressed octets of ECPoint +} +*/ typedef struct { sm9_point_t Ppube; sm9_twist_point_t de; } SM9_ENC_KEY; +int sm9_enc_key_to_der(const SM9_ENC_KEY *key, uint8_t **out, size_t *outlen); +int sm9_enc_key_from_der(SM9_ENC_KEY *key, const uint8_t **in, size_t *inlen); + int sm9_enc_master_key_generate(SM9_ENC_MASTER_KEY *master); int sm9_enc_master_key_extract_key(SM9_ENC_MASTER_KEY *master, const char *id, size_t idlen, SM9_ENC_KEY *key); -int sm9_kem_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, size_t klen, uint8_t *kbuf, uint8_t cbuf[64]); -int sm9_kem_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, const uint8_t cbuf[64], size_t klen, uint8_t *kbuf); +/* +from GM/T 0080-2020 SM9 Cryptographic Alagorithm Application Specification +SM9Cipher ::= SEQUENCE { + EnType INTEGER, -- 0 for XOR + C1 BIT STRING, -- uncompressed octets of ECPoint + C3 OCTET STRING, -- 32 bytes HMAC-SM3 tag + CipherText OCTET STRING, +} +*/ +int sm9_ciphertext_to_der(const sm9_point_t *C1, const uint8_t *c2, size_t c2len, + const uint8_t c3[SM3_HMAC_SIZE], uint8_t **out, size_t *outlen); +int sm9_ciphertext_from_der(sm9_point_t *C1, const uint8_t **c2, size_t *c2len, + const uint8_t *c3[SM3_HMAC_SIZE], const uint8_t **in, size_t *inlen); + +int sm9_kem_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, size_t klen, uint8_t *kbuf, sm9_point_t *C); +int sm9_kem_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, const sm9_point_t *C, size_t klen, uint8_t *kbuf); int sm9_do_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, - const uint8_t *in, size_t inlen, uint8_t C1[64], uint8_t *C2, uint8_t C3[32]); + const uint8_t *in, size_t inlen, sm9_point_t *C1, uint8_t *c2, uint8_t c3[SM3_HMAC_SIZE]); int sm9_do_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, - const uint8_t C1[64], const uint8_t *C2, size_t C2len, const uint8_t C3[32], uint8_t *out); + const sm9_point_t *C1, const uint8_t *c2, size_t c2len, const uint8_t c3[SM3_HMAC_SIZE], uint8_t *out); # ifdef __cplusplus } diff --git a/src/sm9_alg.c b/src/sm9_alg.c index 4cd05e12..c5ba8b2f 100644 --- a/src/sm9_alg.c +++ b/src/sm9_alg.c @@ -2092,35 +2092,35 @@ void sm9_fp12_to_bytes(const sm9_fp12_t a, uint8_t buf[32 * 12]) // FIXME: add impl } -int sm9_point_to_bytes(const sm9_point_t *P, uint8_t out[32 * 2]) +void sm9_fn_to_bytes(const sm9_fn_t a, uint8_t out[32]) { - // FIXME - return 1; } -int sm9_point_from_bytes(sm9_point_t *P, const uint8_t in[32 * 2]) +int sm9_fn_from_bytes(sm9_fn_t a, const uint8_t in[32]) { - // FIXME - return 1; + // FIXME: impl + return -1; } -int sm9_twist_point_to_bytes(const sm9_twist_point_t *P, uint8_t out[32 * 2]) +int sm9_point_to_uncompressed_octets(const sm9_point_t *P, uint8_t octets[65]) { - // FIXME - return 1; + //FIXME: impl + return -1; } -int sm9_twist_point_from_bytes(sm9_twist_point_t *P, const uint8_t in[32 * 2]) +int sm9_point_from_uncompressed_octets(sm9_point_t *P, const uint8_t octets[65]) { - // FIXME - return 1; + //FIXME: impl + return -1; } +int sm9_twist_point_to_uncompressed_octets(const sm9_twist_point_t *P, uint8_t octets[129]) +{ + return -1; +} - - - - - - +int sm9_twist_point_from_uncompressed_octets(sm9_twist_point_t *P, const uint8_t octets[129]) +{ + return -1; +} diff --git a/src/sm9_key.c b/src/sm9_key.c index 01891781..1a25231b 100644 --- a/src/sm9_key.c +++ b/src/sm9_key.c @@ -51,6 +51,8 @@ #include #include #include +#include +#include #include @@ -81,6 +83,298 @@ int sm9_hash1(sm9_bn_t h1, const char *id, size_t idlen, uint8_t hid) return 1; } +int sm9_sign_master_key_to_der(const SM9_SIGN_MASTER_KEY *msk, uint8_t **out, size_t *outlen) +{ + uint8_t ks[32]; + uint8_t Ppubs[1 + 32 * 4]; + size_t len = 0; + + sm9_fn_to_bytes(msk->ks, ks); + sm9_twist_point_to_uncompressed_octets(&msk->Ppubs, Ppubs); + + if (asn1_integer_to_der(ks, sizeof(ks), NULL, &len) != 1 + || asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(ks, sizeof(ks), out, outlen) != 1 + || asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), out, outlen) != 1) { + gmssl_secure_clear(ks, sizeof(ks)); + error_print(); + return -1; + } + gmssl_secure_clear(ks, sizeof(ks)); + return 1; +} + +int sm9_sign_master_key_from_der(SM9_SIGN_MASTER_KEY *msk, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *ks; + size_t kslen; + const uint8_t *Ppubs; + size_t Ppubslen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(&ks, &kslen, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&Ppubs, &Ppubslen, &d, &dlen) != 1 + || asn1_check(kslen == 32) != 1 + || asn1_check(Ppubslen == 1 + 32 * 4) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(msk, 0, sizeof(*msk)); + if (sm9_fn_from_bytes(msk->ks, ks) != 1 + || sm9_twist_point_from_uncompressed_octets(&msk->Ppubs, Ppubs) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_master_public_key_to_der(const SM9_SIGN_MASTER_KEY *mpk, uint8_t **out, size_t *outlen) +{ + uint8_t Ppubs[1 + 32 * 4]; + size_t len = 0; + + sm9_twist_point_to_uncompressed_octets(&mpk->Ppubs, Ppubs); + if (asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_master_public_key_from_der(SM9_SIGN_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *Ppubs; + size_t Ppubslen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_bit_octets_from_der(&Ppubs, &Ppubslen, &d, &dlen) != 1 + || asn1_check(Ppubslen == 1 + 32 * 4) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(mpk, 0, sizeof(*mpk)); + if (sm9_twist_point_from_uncompressed_octets(&mpk->Ppubs, Ppubs) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_sign_key_to_der(const SM9_SIGN_KEY *key, uint8_t **out, size_t *outlen) +{ + uint8_t ds[32]; + uint8_t Ppubs[129]; + size_t len = 0; + + sm9_point_to_uncompressed_octets(&key->ds, ds); + sm9_twist_point_to_uncompressed_octets(&key->Ppubs, Ppubs); + if (asn1_bit_octets_to_der(ds, sizeof(ds), NULL, &len) != 1 + || asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_bit_octets_to_der(ds, sizeof(ds), out, outlen) != 1 + || asn1_bit_octets_to_der(Ppubs, sizeof(Ppubs), out, outlen) != 1) { + gmssl_secure_clear(ds, sizeof(ds)); + error_print(); + return -1; + } + gmssl_secure_clear(ds, sizeof(ds)); + return 1; +} + +int sm9_sign_key_from_der(SM9_SIGN_KEY *key, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *ds; + size_t dslen; + const uint8_t *Ppubs; + size_t Ppubslen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_bit_octets_from_der(&ds, &dslen, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&Ppubs, &Ppubslen, &d, &dlen) != 1 + || asn1_check(dslen == 65) != 1 + || asn1_check(Ppubslen == 129) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(key, 0, sizeof(*key)); + if (sm9_point_from_uncompressed_octets(&key->ds, ds) != 1 + || sm9_twist_point_from_uncompressed_octets(&key->Ppubs, Ppubs) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_master_key_to_der(const SM9_ENC_MASTER_KEY *msk, uint8_t **out, size_t *outlen) +{ + uint8_t ke[32]; + uint8_t Ppube[1 + 32 * 2]; + size_t len = 0; + + sm9_fn_to_bytes(msk->ke, ke); + sm9_point_to_uncompressed_octets(&msk->Ppube, Ppube); + + if (asn1_integer_to_der(ke, sizeof(ke), NULL, &len) != 1 + || asn1_bit_octets_to_der(Ppube, sizeof(Ppube), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(ke, sizeof(ke), out, outlen) != 1 + || asn1_bit_octets_to_der(Ppube, sizeof(Ppube), out, outlen) != 1) { + gmssl_secure_clear(ke, sizeof(ke)); + error_print(); + return -1; + } + gmssl_secure_clear(ke, sizeof(ke)); + return 1; +} + +int sm9_enc_master_key_from_der(SM9_ENC_MASTER_KEY *msk, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *ke; + size_t kelen; + const uint8_t *Ppube; + size_t Ppubelen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(&ke, &kelen, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&Ppube, &Ppubelen, &d, &dlen) != 1 + || asn1_check(kelen == 32) != 1 + || asn1_check(Ppubelen == 1 + 32 * 2) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(msk, 0, sizeof(*msk)); + if (sm9_fn_from_bytes(msk->ke, ke) != 1 + || sm9_point_from_uncompressed_octets(&msk->Ppube, Ppube) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_master_public_key_to_der(const SM9_ENC_MASTER_KEY *mpk, uint8_t **out, size_t *outlen) +{ + uint8_t Ppube[1 + 32 * 2]; + size_t len = 0; + + sm9_point_to_uncompressed_octets(&mpk->Ppube, Ppube); + if (asn1_bit_octets_to_der(Ppube, sizeof(Ppube), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_bit_octets_to_der(Ppube, sizeof(Ppube), out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_master_public_key_from_der(SM9_ENC_MASTER_KEY *mpk, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *Ppube; + size_t Ppubelen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_bit_octets_from_der(&Ppube, &Ppubelen, &d, &dlen) != 1 + || asn1_check(Ppubelen == 1 + 32 * 2) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(mpk, 0, sizeof(*mpk)); + if (sm9_point_from_uncompressed_octets(&mpk->Ppube, Ppube) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_enc_key_to_der(const SM9_ENC_KEY *key, uint8_t **out, size_t *outlen) +{ + uint8_t de[129]; + uint8_t Ppube[65]; + size_t len = 0; + + sm9_twist_point_to_uncompressed_octets(&key->de, de); + sm9_point_to_uncompressed_octets(&key->Ppube, Ppube); + if (asn1_bit_octets_to_der(de, sizeof(de), NULL, &len) != 1 + || asn1_bit_octets_to_der(Ppube, sizeof(Ppube), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_bit_octets_to_der(de, sizeof(de), out, outlen) != 1 + || asn1_bit_octets_to_der(Ppube, sizeof(Ppube), out, outlen) != 1) { + gmssl_secure_clear(de, sizeof(de)); + error_print(); + return -1; + } + gmssl_secure_clear(de, sizeof(de)); + return 1; +} + +int sm9_enc_key_from_der(SM9_ENC_KEY *key, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *de; + size_t delen; + const uint8_t *Ppube; + size_t Ppubelen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_bit_octets_from_der(&de, &delen, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&Ppube, &Ppubelen, &d, &dlen) != 1 + || asn1_check(delen == 129) != 1 + || asn1_check(Ppubelen == 65) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + memset(key, 0, sizeof(*key)); + if (sm9_twist_point_from_uncompressed_octets(&key->de, de) != 1 + || sm9_point_from_uncompressed_octets(&key->Ppube, Ppube) != 1) { + error_print(); + return -1; + } + return 1; +} + int sm9_sign_master_key_generate(SM9_SIGN_MASTER_KEY *msk) { // k = rand(1, n-1) diff --git a/src/sm9_lib.c b/src/sm9_lib.c index 086ea94c..1fa958c1 100644 --- a/src/sm9_lib.c +++ b/src/sm9_lib.c @@ -53,9 +53,62 @@ #include #include #include +#include #include + + +int sm9_signature_to_der(const SM9_SIGNATURE *sig, uint8_t **out, size_t *outlen) +{ + uint8_t hbuf[32]; + uint8_t Sbuf[65]; + size_t len = 0; + + sm9_fn_to_bytes(sig->h, hbuf); + sm9_point_to_uncompressed_octets(&sig->S, Sbuf); + + if (asn1_integer_to_der(hbuf, sizeof(hbuf), NULL, &len) != 1 + || asn1_bit_octets_to_der(Sbuf, sizeof(Sbuf), NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(hbuf, sizeof(hbuf), out, outlen) != 1 + || asn1_bit_octets_to_der(Sbuf, sizeof(Sbuf), out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_signature_from_der(SM9_SIGNATURE *sig, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *h; + size_t hlen; + const uint8_t *S; + size_t Slen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(&h, &hlen, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&S, &Slen, &d, &dlen) != 1 + || asn1_check(hlen == 32) != 1 + || asn1_check(Slen == 65) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (sm9_fn_from_bytes(sig->h, h) != 1 + || sm9_point_from_uncompressed_octets(&sig->S, S) != 1) { + error_print(); + return -1; + } + return 1; +} + int sm9_sign_init(SM9_SIGN_CTX *ctx) { const uint8_t prefix[1] = {0x02}; @@ -72,7 +125,18 @@ int sm9_sign_update(SM9_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) int sm9_sign_finish(SM9_SIGN_CTX *ctx, const SM9_SIGN_KEY *key, uint8_t *sig, size_t *siglen) { - return -1; + SM9_SIGNATURE signature; + + if (sm9_do_sign(key, &ctx->sm3_ctx, &signature) != 1) { + error_print(); + return -1; + } + *siglen = 0; + if (sm9_signature_to_der(&signature, &sig, siglen) != 1) { + error_print(); + return -1; + } + return 1; } int sm9_do_sign(const SM9_SIGN_KEY *key, const SM3_CTX *sm3_ctx, SM9_SIGNATURE *sig) @@ -140,7 +204,20 @@ int sm9_verify_update(SM9_SIGN_CTX *ctx, const uint8_t *data, size_t datalen) int sm9_verify_finish(SM9_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen, const SM9_SIGN_MASTER_KEY *mpk, const char *id, size_t idlen) { - return -1; + int ret; + SM9_SIGNATURE signature; + + if (sm9_signature_from_der(&signature, &sig, &siglen) != 1 + || asn1_length_is_zero(siglen) != 1) { + error_print(); + return -1; + } + + if ((ret = sm9_do_verify(mpk, id, idlen, &ctx->sm3_ctx, &signature)) < 0) { + error_print(); + return -1; + } + return ret; } int sm9_do_verify(const SM9_SIGN_MASTER_KEY *mpk, const char *id, size_t idlen, @@ -200,26 +277,26 @@ int sm9_do_verify(const SM9_SIGN_MASTER_KEY *mpk, const char *id, size_t idlen, } int sm9_kem_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, - size_t klen, uint8_t *kbuf, uint8_t cbuf[64]) + size_t klen, uint8_t *kbuf, sm9_point_t *C) { sm9_fn_t r; sm9_fp12_t w; - sm9_point_t C; uint8_t wbuf[32 * 12]; + uint8_t cbuf[65]; SM3_KDF_CTX kdf_ctx; // A1: Q = H1(ID||hid,N) * P1 + Ppube sm9_hash1(r, id, idlen, SM9_HID_EXCH); - sm9_point_mul(&C, r, SM9_P1); - sm9_point_add(&C, &C, &mpk->Ppube); + sm9_point_mul(C, r, SM9_P1); + sm9_point_add(C, C, &mpk->Ppube); do { // A2: rand r in [1, N-1] sm9_fn_rand(r); // A3: C1 = r * Q - sm9_point_mul(&C, r, &C); - sm9_point_to_bytes(&C, cbuf); + sm9_point_mul(C, r, C); + sm9_point_to_uncompressed_octets(C, cbuf); // A4: g = e(Ppube, P2) sm9_pairing(w, SM9_P2, &mpk->Ppube); @@ -230,7 +307,7 @@ int sm9_kem_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, // A6: K = KDF(C || w || ID_B, klen), if K == 0, goto A2 sm3_kdf_init(&kdf_ctx, klen); - sm3_kdf_update(&kdf_ctx, cbuf, 64); + sm3_kdf_update(&kdf_ctx, cbuf + 1, 64); sm3_kdf_update(&kdf_ctx, wbuf, sizeof(wbuf)); sm3_kdf_update(&kdf_ctx, (uint8_t *)id, idlen); sm3_kdf_finish(&kdf_ctx, kbuf); @@ -239,7 +316,6 @@ int sm9_kem_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, gmssl_secure_clear(&r, sizeof(r)); gmssl_secure_clear(&w, sizeof(w)); - gmssl_secure_clear(&C, sizeof(C)); gmssl_secure_clear(wbuf, sizeof(wbuf)); gmssl_secure_clear(&kdf_ctx, sizeof(kdf_ctx)); @@ -247,26 +323,23 @@ int sm9_kem_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, return 1; } -int sm9_kem_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, const uint8_t cbuf[64], +int sm9_kem_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, const sm9_point_t *C, size_t klen, uint8_t *kbuf) { sm9_fp12_t w; - sm9_point_t C; uint8_t wbuf[32 * 12]; + uint8_t cbuf[65]; SM3_KDF_CTX kdf_ctx; // B1: check C in G1 - if (sm9_point_from_bytes(&C, cbuf) != 1) { - error_print(); - return -1; - } + sm9_point_to_uncompressed_octets(C, cbuf + 1); // B2: w = e(C, de); - sm9_pairing(w, &key->de, &C); + sm9_pairing(w, &key->de, C); // B3: K = KDF(C || w || ID, klen) sm3_kdf_init(&kdf_ctx, klen); - sm3_kdf_update(&kdf_ctx, cbuf, 64); + sm3_kdf_update(&kdf_ctx, cbuf + 1, 64); sm3_kdf_update(&kdf_ctx, wbuf, sizeof(wbuf)); sm3_kdf_update(&kdf_ctx, (uint8_t *)id, idlen); sm3_kdf_finish(&kdf_ctx, kbuf); @@ -277,7 +350,6 @@ int sm9_kem_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, const } gmssl_secure_clear(&w, sizeof(w)); - gmssl_secure_clear(&C, sizeof(C)); gmssl_secure_clear(wbuf, sizeof(wbuf)); gmssl_secure_clear(&kdf_ctx, sizeof(kdf_ctx)); @@ -287,30 +359,153 @@ int sm9_kem_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, const int sm9_do_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, const uint8_t *in, size_t inlen, - uint8_t C1[64], uint8_t *C2, uint8_t C3[32]) + sm9_point_t *C1, uint8_t *c2, uint8_t c3[SM3_HMAC_SIZE]) { uint8_t K[inlen + 32]; sm9_kem_encrypt(mpk, id, idlen, sizeof(K), K, C1); - gmssl_memxor(C2, K, in, inlen); - sm3_hmac(K + inlen, 32, C2, inlen, C3); + gmssl_memxor(c2, K, in, inlen); + sm3_hmac(K + inlen, 32, c2, inlen, c3); return 1; } int sm9_do_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, - const uint8_t C1[64], const uint8_t *C2, size_t C2len, const uint8_t C3[32], + const sm9_point_t *C1, const uint8_t *c2, size_t c2len, const uint8_t c3[SM3_HMAC_SIZE], uint8_t *out) { - uint8_t K[C2len + 32]; - uint8_t mac[32]; + uint8_t k[c2len + SM3_HMAC_SIZE]; + uint8_t mac[SM3_HMAC_SIZE]; - sm9_kem_decrypt(key, id, idlen, C1, sizeof(K), K); - sm3_hmac(K + C2len, 32, C2, C2len, mac); - if (gmssl_secure_memcmp(C3, mac, sizeof(mac)) != 0) { + sm9_kem_decrypt(key, id, idlen, C1, sizeof(k), k); + sm3_hmac(k + c2len, SM3_HMAC_SIZE, c2, c2len, mac); + if (gmssl_secure_memcmp(c3, mac, sizeof(mac)) != 0) { + error_print(); + return -1; + } + gmssl_memxor(out, k, c2, c2len); + return 1; +} + +#define SM9_ENC_TYPE_XOR 0 +#define SM9_ENC_TYPE_ECB 1 +#define SM9_ENC_TYPE_CBC 2 +#define SM9_ENC_TYPE_OFB 4 +#define SM9_ENC_TYPE_CFB 8 + +/* +SM9Cipher ::= SEQUENCE { + EnType INTEGER, -- 0 for XOR + C1 BIT STRING, -- uncompressed octets of ECPoint + C3 OCTET STRING, -- 32 bytes HMAC-SM3 tag + CipherText OCTET STRING, +} +*/ +int sm9_ciphertext_to_der(const sm9_point_t *C1, const uint8_t *c2, size_t c2len, + const uint8_t c3[SM3_HMAC_SIZE], uint8_t **out, size_t *outlen) +{ + int en_type = SM9_ENC_TYPE_XOR; + uint8_t c1[65]; + size_t len = 0; + + sm9_point_to_uncompressed_octets(C1, c1); + if (asn1_int_to_der(en_type, NULL, &len) != 1 + || asn1_bit_octets_to_der(c1, sizeof(c1), NULL, &len) != 1 + || asn1_octet_string_to_der(c3, SM3_HMAC_SIZE, NULL, &len) != 1 + || asn1_octet_string_to_der(c2, c2len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(en_type, out, outlen) != 1 + || asn1_bit_octets_to_der(c1, sizeof(c1), out, outlen) != 1 + || asn1_octet_string_to_der(c3, SM3_HMAC_SIZE, out, outlen) != 1 + || asn1_octet_string_to_der(c2, c2len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_ciphertext_from_der( + sm9_point_t *C1, const uint8_t **c2, size_t *c2len, const uint8_t **c3, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + int en_type; + const uint8_t *c1; + size_t c1len; + size_t c3len; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(&en_type, &d, &dlen) != 1 + || asn1_bit_octets_from_der(&c1, &c1len, &d, &dlen) != 1 + || asn1_octet_string_from_der(c3, &c3len, &d, &dlen) != 1 + || asn1_octet_string_from_der(c2, c2len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (en_type != SM9_ENC_TYPE_XOR) { + error_print(); + return -1; + } + if (c1len != 65) { + error_print(); + return -1; + } + if (c3len != SM3_HMAC_SIZE) { + error_print(); + return -1; + } + if (sm9_point_from_uncompressed_octets(C1, c1) != 1) { + error_print(); + return -1; + } + return 1; +} + +int sm9_encrypt(const SM9_ENC_MASTER_KEY *mpk, const char *id, size_t idlen, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + sm9_point_t C1; + uint8_t c2[inlen]; + uint8_t c3[SM3_HMAC_SIZE]; + + if (sm9_do_encrypt(mpk, id, idlen, in, inlen, &C1, c2, c3) != 1) { + error_print(); + return -1; + } + *outlen = 0; + if (sm9_ciphertext_to_der(&C1, c2, inlen, c3, &out, outlen) != 1) { // FIXME: when out == NULL + error_print(); + return -1; + } + return 1; +} + +int sm9_decrypt(const SM9_ENC_KEY *key, const char *id, size_t idlen, + const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) +{ + sm9_point_t C1; + const uint8_t *c2; + size_t c2len; + const uint8_t *c3; + + if (sm9_ciphertext_from_der(&C1, &c2, &c2len, &c3, &in, &inlen) != 1 + || asn1_length_is_zero(inlen) != 1) { + error_print(); + return -1; + } + if (!out) { + *outlen = c2len; + return 1; + } + if (sm9_do_decrypt(key, id, idlen, &C1, c2, c2len, c3, out) != 1) { error_print(); return -1; } - gmssl_memxor(out, K, C2, C2len); return 1; }