Commit 00433bad authored by Paul Yang's avatar Paul Yang
Browse files

Make SM2 ID stick to specification

parent 0a8fdef7
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -20,18 +20,28 @@
/* The default user id as specified in GM/T 0009-2012 */
#  define SM2_DEFAULT_USERID "1234567812345678"

int sm2_compute_userid_digest(uint8_t *out,
                              const EVP_MD *digest,
                              const uint8_t *id,
                              const size_t id_len,
                              const EC_KEY *key);

/*
 * SM2 signature operation. Computes ZA (user id digest) and then signs
 * H(ZA || msg) using SM2
 */
ECDSA_SIG *sm2_do_sign(const EC_KEY *key,
                       const EVP_MD *digest,
                       const char *user_id, const uint8_t *msg, size_t msg_len);
                       const uint8_t *id,
                       const size_t id_len,
                       const uint8_t *msg, size_t msg_len);

int sm2_do_verify(const EC_KEY *key,
                  const EVP_MD *digest,
                  const ECDSA_SIG *signature,
                  const char *user_id, const uint8_t *msg, size_t msg_len);
                  const uint8_t *id,
                  const size_t id_len,
                  const uint8_t *msg, size_t msg_len);

/*
 * SM2 signature generation.
+32 −1
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ typedef struct {
    EC_GROUP *gen_group;
    /* message digest */
    const EVP_MD *md;
    uint8_t *id;
    size_t id_len;
} SM2_PKEY_CTX;

static int pkey_sm2_init(EVP_PKEY_CTX *ctx)
@@ -209,6 +211,29 @@ static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx,
    return -2;
}

static int pkey_sm2_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
{
    uint8_t z[EVP_MAX_MD_SIZE];
    SM2_PKEY_CTX *sctx = ctx->data;
    EC_KEY *ec = ctx->pkey->pkey.ec;
    const EVP_MD *md = EVP_MD_CTX_md(mctx);

    if (sctx->id == NULL) {
        /* XXX:
         * currently we reject all null-ID for SM2, but this needs
         * more considerations and discussion since the specifications
         * on SM2 are not clear on null-ID
         */
        return 0;
    }

    /* get hashed prefix of tbs message */
    if (!sm2_compute_userid_digest(z, md, sctx->id, sctx->id_len, ec))
        return 0;

    return EVP_DigestUpdate(mctx, z, EVP_MD_size(md));
}

const EVP_PKEY_METHOD sm2_pkey_meth = {
    EVP_PKEY_SM2,
    0,
@@ -241,5 +266,11 @@ const EVP_PKEY_METHOD sm2_pkey_meth = {
    0,
    0,
    pkey_sm2_ctrl,
    pkey_sm2_ctrl_str
    pkey_sm2_ctrl_str,

    0, 0,

    0, 0, 0,

    pkey_sm2_digest_custom
};
+19 −15
Original line number Diff line number Diff line
@@ -18,9 +18,10 @@
#include <openssl/bn.h>
#include <string.h>

static int sm2_compute_userid_digest(uint8_t *out,
int sm2_compute_userid_digest(uint8_t *out,
                              const EVP_MD *digest,
                                     const char *user_id,
                              const uint8_t *id,
                              const size_t id_len,
                              const EC_KEY *key)
{
    int rc = 0;
@@ -36,7 +37,6 @@ static int sm2_compute_userid_digest(uint8_t *out,
    BIGNUM *yA = NULL;
    int p_bytes = 0;
    uint8_t *buf = NULL;
    size_t uid_len = 0;
    uint16_t entla = 0;
    uint8_t e_byte = 0;

@@ -67,14 +67,13 @@ static int sm2_compute_userid_digest(uint8_t *out,

    /* Z = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA) */

    uid_len = strlen(user_id);
    if (uid_len >= (UINT16_MAX / 8)) {
    if (id_len >= (UINT16_MAX / 8)) {
        /* too large */
        SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, SM2_R_USER_ID_TOO_LARGE);
        goto done;
    }

    entla = (uint16_t)(8 * uid_len);
    entla = (uint16_t)(8 * id_len);

    e_byte = entla >> 8;
    if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
@@ -83,7 +82,7 @@ static int sm2_compute_userid_digest(uint8_t *out,
    }
    e_byte = entla & 0xFF;
    if (!EVP_DigestUpdate(hash, &e_byte, 1)
            || !EVP_DigestUpdate(hash, user_id, uid_len)) {
            || !EVP_DigestUpdate(hash, id, id_len)) {
        SM2err(SM2_F_SM2_COMPUTE_USERID_DIGEST, ERR_R_EVP_LIB);
        goto done;
    }
@@ -134,7 +133,8 @@ static int sm2_compute_userid_digest(uint8_t *out,

static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,
                                    const EC_KEY *key,
                                    const char *user_id,
                                    const uint8_t *id,
                                    const size_t id_len,
                                    const uint8_t *msg, size_t msg_len)
{
    EVP_MD_CTX *hash = EVP_MD_CTX_new();
@@ -153,7 +153,7 @@ static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,
        goto done;
    }

    if (!sm2_compute_userid_digest(za, digest, user_id, key)) {
    if (!sm2_compute_userid_digest(za, digest, id, id_len, key)) {
        /* SM2err already called */
        goto done;
    }
@@ -358,12 +358,14 @@ static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig,

ECDSA_SIG *sm2_do_sign(const EC_KEY *key,
                       const EVP_MD *digest,
                       const char *user_id, const uint8_t *msg, size_t msg_len)
                       const uint8_t *id,
                       const size_t id_len,
                       const uint8_t *msg, size_t msg_len)
{
    BIGNUM *e = NULL;
    ECDSA_SIG *sig = NULL;

    e = sm2_compute_msg_hash(digest, key, user_id, msg, msg_len);
    e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len);
    if (e == NULL) {
        /* SM2err already called */
        goto done;
@@ -379,12 +381,14 @@ ECDSA_SIG *sm2_do_sign(const EC_KEY *key,
int sm2_do_verify(const EC_KEY *key,
                  const EVP_MD *digest,
                  const ECDSA_SIG *sig,
                  const char *user_id, const uint8_t *msg, size_t msg_len)
                  const uint8_t *id,
                  const size_t id_len,
                  const uint8_t *msg, size_t msg_len)
{
    BIGNUM *e = NULL;
    int ret = 0;

    e = sm2_compute_msg_hash(digest, key, user_id, msg, msg_len);
    e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len);
    if (e == NULL) {
        /* SM2err already called */
        goto done;
+4 −3
Original line number Diff line number Diff line
@@ -294,7 +294,8 @@ static int test_sm2_sign(const EC_GROUP *group,
        goto done;

    start_fake_rand(k_hex);
    sig = sm2_do_sign(key, EVP_sm3(), userid, (const uint8_t *)message, msg_len);
    sig = sm2_do_sign(key, EVP_sm3(), (const uint8_t *)userid, strlen(userid),
                      (const uint8_t *)message, msg_len);
    if (!TEST_ptr(sig)
            || !TEST_size_t_eq(fake_rand_bytes_offset, fake_rand_size)) {
        restore_rand();
@@ -310,8 +311,8 @@ static int test_sm2_sign(const EC_GROUP *group,
            || !TEST_BN_eq(s, sig_s))
        goto done;

    ok = sm2_do_verify(key, EVP_sm3(), sig, userid, (const uint8_t *)message,
                       msg_len);
    ok = sm2_do_verify(key, EVP_sm3(), sig, (const uint8_t *)userid,
                       strlen(userid), (const uint8_t *)message, msg_len);

    /* We goto done whether this passes or fails */
    TEST_true(ok);