From 62d73c2dd0cc4b2a80186d55de5ffd4298462a83 Mon Sep 17 00:00:00 2001
From: Huaxin Lu <luhuaxin1@huawei.com>
Date: Mon, 7 Nov 2022 11:44:18 +0800
Subject: [PATCH 3/5] shim openssl add sm2 and sm3 support

Co-authored-by: Yusong Gao <gaoyusong2@huawei.com>
Signed-off-by: Yusong Gao <gaoyusong2@huawei.com>
Signed-off-by: Huaxin Lu <luhuaxin1@huawei.com>
---
 Cryptlib/Include/openssl/sm2.h          |  79 ++++++
 Cryptlib/Include/openssl/sm2err.h       |  65 +++++
 Cryptlib/Include/openssl/sm3.h          |  39 +++
 Cryptlib/OpenSSL/crypto/sm2/sm2_err.c   |  71 ++++++
 Cryptlib/OpenSSL/crypto/sm2/sm2_pmeth.c | 292 +++++++++++++++++++++
 Cryptlib/OpenSSL/crypto/sm2/sm2_sign.c  | 325 ++++++++++++++++++++++++
 Cryptlib/OpenSSL/crypto/sm3/m_sm3.c     |  52 ++++
 Cryptlib/OpenSSL/crypto/sm3/sm3.c       | 196 ++++++++++++++
 Cryptlib/OpenSSL/crypto/sm3/sm3_local.h |  79 ++++++
 9 files changed, 1198 insertions(+)
 create mode 100644 Cryptlib/Include/openssl/sm2.h
 create mode 100644 Cryptlib/Include/openssl/sm2err.h
 create mode 100644 Cryptlib/Include/openssl/sm3.h
 create mode 100644 Cryptlib/OpenSSL/crypto/sm2/sm2_err.c
 create mode 100644 Cryptlib/OpenSSL/crypto/sm2/sm2_pmeth.c
 create mode 100644 Cryptlib/OpenSSL/crypto/sm2/sm2_sign.c
 create mode 100644 Cryptlib/OpenSSL/crypto/sm3/m_sm3.c
 create mode 100644 Cryptlib/OpenSSL/crypto/sm3/sm3.c
 create mode 100644 Cryptlib/OpenSSL/crypto/sm3/sm3_local.h

diff --git a/Cryptlib/Include/openssl/sm2.h b/Cryptlib/Include/openssl/sm2.h
new file mode 100644
index 0000000..37c67a3
--- /dev/null
+++ b/Cryptlib/Include/openssl/sm2.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017 Ribose Inc. All Rights Reserved.
+ * Ported from Ribose contributions from Botan.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_SM2_H
+# define OSSL_CRYPTO_SM2_H
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_SM2
+
+#  include <openssl/ec.h>
+#  include <openssl/ecdsa.h>
+
+/* The default user id as specified in GM/T 0009-2012 */
+#  define SM2_DEFAULT_USERID "1234567812345678"
+#  define SM2_DEFAULT_USERID_LEN 16
+
+int sm2_compute_z_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 Z and then signs H(Z || msg) using SM2
+ */
+ECDSA_SIG *sm2_do_sign(const EC_KEY *key,
+                       const EVP_MD *digest,
+                       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 uint8_t *id,
+                  const size_t id_len,
+                  const uint8_t *msg, size_t msg_len);
+
+/*
+ * SM2 signature generation.
+ */
+int sm2_sign(const unsigned char *dgst, int dgstlen,
+             unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
+
+/*
+ * SM2 signature verification.
+ */
+int sm2_verify(const unsigned char *dgst, int dgstlen,
+               const unsigned char *sig, int siglen, EC_KEY *eckey);
+
+/*
+ * SM2 encryption
+ */
+int sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len,
+                        size_t *ct_size);
+
+int sm2_plaintext_size(const unsigned char *ct, size_t ct_size, size_t *pt_size);
+
+int sm2_encrypt(const EC_KEY *key,
+                const EVP_MD *digest,
+                const uint8_t *msg,
+                size_t msg_len,
+                uint8_t *ciphertext_buf, size_t *ciphertext_len);
+
+int sm2_decrypt(const EC_KEY *key,
+                const EVP_MD *digest,
+                const uint8_t *ciphertext,
+                size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len);
+
+# endif /* OPENSSL_NO_SM2 */
+#endif
diff --git a/Cryptlib/Include/openssl/sm2err.h b/Cryptlib/Include/openssl/sm2err.h
new file mode 100644
index 0000000..251c4f9
--- /dev/null
+++ b/Cryptlib/Include/openssl/sm2err.h
@@ -0,0 +1,65 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef HEADER_SM2ERR_H
+# define HEADER_SM2ERR_H
+
+# include <openssl/symhacks.h>
+
+# include <openssl/opensslconf.h>
+
+# ifndef OPENSSL_NO_SM2
+
+#  ifdef  __cplusplus
+extern "C"
+#  endif
+int ERR_load_SM2_strings(void);
+
+/*
+ * SM2 function codes.
+ */
+#  define SM2_F_PKEY_SM2_COPY                              115
+#  define SM2_F_PKEY_SM2_CTRL                              109
+#  define SM2_F_PKEY_SM2_CTRL_STR                          110
+#  define SM2_F_PKEY_SM2_DIGEST_CUSTOM                     114
+#  define SM2_F_PKEY_SM2_INIT                              111
+#  define SM2_F_PKEY_SM2_SIGN                              112
+#  define SM2_F_SM2_COMPUTE_KEY                            116
+#  define SM2_F_SM2_COMPUTE_MSG_HASH                       100
+#  define SM2_F_SM2_COMPUTE_USERID_DIGEST                  101
+#  define SM2_F_SM2_COMPUTE_Z_DIGEST                       113
+#  define SM2_F_SM2_DECRYPT                                102
+#  define SM2_F_SM2_ENCRYPT                                103
+#  define SM2_F_SM2_PLAINTEXT_SIZE                         104
+#  define SM2_F_SM2_SIGN                                   105
+#  define SM2_F_SM2_SIG_GEN                                106
+#  define SM2_F_SM2_SIG_VERIFY                             107
+#  define SM2_F_SM2_VERIFY                                 108
+
+/*
+ * SM2 reason codes.
+ */
+#  define SM2_R_ASN1_ERROR                                 100
+#  define SM2_R_BAD_SIGNATURE                              101
+#  define SM2_R_BUFFER_TOO_SMALL                           107
+#  define SM2_R_DIST_ID_TOO_LARGE                          110
+#  define SM2_R_ID_NOT_SET                                 112
+#  define SM2_R_ID_TOO_LARGE                               111
+#  define SM2_R_INVALID_CURVE                              108
+#  define SM2_R_INVALID_DIGEST                             102
+#  define SM2_R_INVALID_DIGEST_TYPE                        103
+#  define SM2_R_INVALID_ENCODING                           104
+#  define SM2_R_INVALID_FIELD                              105
+#  define SM2_R_NO_PARAMETERS_SET                          109
+#  define SM2_R_NO_PRIVATE_VALUE                           113
+#  define SM2_R_USER_ID_TOO_LARGE                          106
+
+# endif
+#endif
diff --git a/Cryptlib/Include/openssl/sm3.h b/Cryptlib/Include/openssl/sm3.h
new file mode 100644
index 0000000..97e7460
--- /dev/null
+++ b/Cryptlib/Include/openssl/sm3.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017 Ribose Inc. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_SM3_H
+# define OSSL_CRYPTO_SM3_H
+
+# include <openssl/opensslconf.h>
+
+# ifdef OPENSSL_NO_SM3
+#  error SM3 is disabled.
+# endif
+
+# define SM3_DIGEST_LENGTH 32
+# define SM3_WORD unsigned int
+
+# define SM3_CBLOCK      64
+# define SM3_LBLOCK      (SM3_CBLOCK/4)
+
+typedef struct SM3state_st {
+   SM3_WORD A, B, C, D, E, F, G, H;
+   SM3_WORD Nl, Nh;
+   SM3_WORD data[SM3_LBLOCK];
+   unsigned int num;
+} SM3_CTX;
+
+int sm3_init(SM3_CTX *c);
+int sm3_update(SM3_CTX *c, const void *data, size_t len);
+int sm3_final(unsigned char *md, SM3_CTX *c);
+
+void sm3_block_data_order(SM3_CTX *c, const void *p, size_t num);
+
+#endif
diff --git a/Cryptlib/OpenSSL/crypto/sm2/sm2_err.c b/Cryptlib/OpenSSL/crypto/sm2/sm2_err.c
new file mode 100644
index 0000000..6e06f6a
--- /dev/null
+++ b/Cryptlib/OpenSSL/crypto/sm2/sm2_err.c
@@ -0,0 +1,71 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/sm2err.h>
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA SM2_str_functs[] = {
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_COPY, 0), "pkey_sm2_copy"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL, 0), "pkey_sm2_ctrl"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_CTRL_STR, 0), "pkey_sm2_ctrl_str"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_DIGEST_CUSTOM, 0),
+     "pkey_sm2_digest_custom"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_INIT, 0), "pkey_sm2_init"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_PKEY_SM2_SIGN, 0), "pkey_sm2_sign"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_KEY, 0), "SM2_compute_key"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_MSG_HASH, 0),
+     "sm2_compute_msg_hash"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_USERID_DIGEST, 0),
+     "sm2_compute_userid_digest"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_COMPUTE_Z_DIGEST, 0),
+     "sm2_compute_z_digest"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_DECRYPT, 0), "sm2_decrypt"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_ENCRYPT, 0), "sm2_encrypt"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_PLAINTEXT_SIZE, 0), "sm2_plaintext_size"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIGN, 0), "sm2_sign"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIG_GEN, 0), "sm2_sig_gen"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_SIG_VERIFY, 0), "sm2_sig_verify"},
+    {ERR_PACK(ERR_LIB_SM2, SM2_F_SM2_VERIFY, 0), "sm2_verify"},
+    {0, NULL}
+};
+
+static const ERR_STRING_DATA SM2_str_reasons[] = {
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ASN1_ERROR), "asn1 error"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BAD_SIGNATURE), "bad signature"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_BUFFER_TOO_SMALL), "buffer too small"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_DIST_ID_TOO_LARGE), "dist id too large"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ID_NOT_SET), "id not set"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_ID_TOO_LARGE), "id too large"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_CURVE), "invalid curve"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_DIGEST), "invalid digest"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_DIGEST_TYPE),
+    "invalid digest type"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_ENCODING), "invalid encoding"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_INVALID_FIELD), "invalid field"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PARAMETERS_SET), "no parameters set"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_NO_PRIVATE_VALUE), "no private value"},
+    {ERR_PACK(ERR_LIB_SM2, 0, SM2_R_USER_ID_TOO_LARGE), "user id too large"},
+    {0, NULL}
+};
+
+#endif
+
+int ERR_load_SM2_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+    if (ERR_func_error_string(SM2_str_functs[0].error) == NULL) {
+        ERR_load_strings_const(SM2_str_functs);
+        ERR_load_strings_const(SM2_str_reasons);
+    }
+#endif
+    return 1;
+}
diff --git a/Cryptlib/OpenSSL/crypto/sm2/sm2_pmeth.c b/Cryptlib/OpenSSL/crypto/sm2/sm2_pmeth.c
new file mode 100644
index 0000000..b0d9519
--- /dev/null
+++ b/Cryptlib/OpenSSL/crypto/sm2/sm2_pmeth.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/cryptlib.h"
+#include <openssl/asn1t.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#include "crypto/evp/evp_locl.h"
+#include <openssl/sm2.h>
+#include <openssl/sm2err.h>
+
+/* EC pkey context structure */
+
+typedef struct {
+    /* Key and paramgen group */
+    EC_GROUP *gen_group;
+    /* message digest */
+    const EVP_MD *md;
+    /* Distinguishing Identifier, ISO/IEC 15946-3 */
+    uint8_t *id;
+    size_t id_len;
+    /* id_set indicates if the 'id' field is set (1) or not (0) */
+    int id_set;
+} SM2_PKEY_CTX;
+
+static int pkey_sm2_init(EVP_PKEY_CTX *ctx)
+{
+    SM2_PKEY_CTX *smctx;
+
+    if ((smctx = OPENSSL_zalloc(sizeof(*smctx))) == NULL) {
+        SM2err(SM2_F_PKEY_SM2_INIT, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    ctx->data = smctx;
+    return 1;
+}
+
+static void pkey_sm2_cleanup(EVP_PKEY_CTX *ctx)
+{
+    SM2_PKEY_CTX *smctx = ctx->data;
+
+    if (smctx != NULL) {
+        EC_GROUP_free(smctx->gen_group);
+        OPENSSL_free(smctx->id);
+        OPENSSL_free(smctx);
+        ctx->data = NULL;
+    }
+}
+
+static int pkey_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+{
+    SM2_PKEY_CTX *dctx, *sctx;
+
+    if (!pkey_sm2_init(dst))
+        return 0;
+    sctx = src->data;
+    dctx = dst->data;
+    if (sctx->gen_group != NULL) {
+        dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
+        if (dctx->gen_group == NULL) {
+            pkey_sm2_cleanup(dst);
+            return 0;
+        }
+    }
+    if (sctx->id != NULL) {
+        dctx->id = OPENSSL_malloc(sctx->id_len);
+        if (dctx->id == NULL) {
+            SM2err(SM2_F_PKEY_SM2_COPY, ERR_R_MALLOC_FAILURE);
+            pkey_sm2_cleanup(dst);
+            return 0;
+        }
+        memcpy(dctx->id, sctx->id, sctx->id_len);
+    }
+    dctx->id_len = sctx->id_len;
+    dctx->id_set = sctx->id_set;
+    dctx->md = sctx->md;
+
+    return 1;
+}
+
+static int pkey_sm2_verify(EVP_PKEY_CTX *ctx,
+                           const unsigned char *sig, size_t siglen,
+                           const unsigned char *tbs, size_t tbslen)
+{
+    EC_KEY *ec = ctx->pkey->pkey.ec;
+
+    return sm2_verify(tbs, tbslen, sig, siglen, ec);
+}
+
+static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+    SM2_PKEY_CTX *smctx = ctx->data;
+    EC_GROUP *group;
+    uint8_t *tmp_id;
+
+    switch (type) {
+    case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
+        group = EC_GROUP_new_by_curve_name(p1);
+        if (group == NULL) {
+            SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_INVALID_CURVE);
+            return 0;
+        }
+        EC_GROUP_free(smctx->gen_group);
+        smctx->gen_group = group;
+        return 1;
+
+    case EVP_PKEY_CTRL_EC_PARAM_ENC:
+        if (smctx->gen_group == NULL) {
+            SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_NO_PARAMETERS_SET);
+            return 0;
+        }
+        EC_GROUP_set_asn1_flag(smctx->gen_group, p1);
+        return 1;
+
+    case EVP_PKEY_CTRL_MD:
+        smctx->md = p2;
+        return 1;
+
+    case EVP_PKEY_CTRL_GET_MD:
+        *(const EVP_MD **)p2 = smctx->md;
+        return 1;
+
+    case EVP_PKEY_CTRL_SET1_ID:
+        if (p1 > 0) {
+            tmp_id = OPENSSL_malloc(p1);
+            if (tmp_id == NULL) {
+                SM2err(SM2_F_PKEY_SM2_CTRL, ERR_R_MALLOC_FAILURE);
+                return 0;
+            }
+            memcpy(tmp_id, p2, p1);
+            OPENSSL_free(smctx->id);
+            smctx->id = tmp_id;
+        } else {
+            /* set null-ID */
+            OPENSSL_free(smctx->id);
+            smctx->id = NULL;
+        }
+        smctx->id_len = (size_t)p1;
+        smctx->id_set = 1;
+        return 1;
+
+    case EVP_PKEY_CTRL_GET1_ID:
+        memcpy(p2, smctx->id, smctx->id_len);
+        return 1;
+
+    case EVP_PKEY_CTRL_GET1_ID_LEN:
+        *(size_t *)p2 = smctx->id_len;
+        return 1;
+
+    case EVP_PKEY_CTRL_PKCS7_SIGN:
+    case EVP_PKEY_CTRL_DIGESTINIT:
+        /* nothing to be inited, this is to suppress the error... */
+        return 1;
+
+    default:
+        return -2;
+    }
+}
+
+static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx,
+                             const char *type, const char *value)
+{
+    uint8_t *hex_id;
+    long hex_len = 0;
+    int ret = 0;
+
+    if (strcmp(type, "ec_paramgen_curve") == 0) {
+        int nid = NID_undef;
+
+        if (((nid = EC_curve_nist2nid(value)) == NID_undef)
+            && ((nid = OBJ_sn2nid(value)) == NID_undef)
+            && ((nid = OBJ_ln2nid(value)) == NID_undef)) {
+            SM2err(SM2_F_PKEY_SM2_CTRL_STR, SM2_R_INVALID_CURVE);
+            return 0;
+        }
+        return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
+    } else if (strcmp(type, "ec_param_enc") == 0) {
+        int param_enc;
+
+        if (strcmp(value, "explicit") == 0)
+            param_enc = 0;
+        else if (strcmp(value, "named_curve") == 0)
+            param_enc = OPENSSL_EC_NAMED_CURVE;
+        else
+            return -2;
+        return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
+    } else if (strcmp(type, "sm2_id") == 0) {
+        return pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID,
+                             (int)strlen(value), (void *)value);
+    } else if (strcmp(type, "sm2_hex_id") == 0) {
+        /*
+         * TODO(3.0): reconsider the name "sm2_hex_id", OR change
+         * OSSL_PARAM_construct_from_text() / OSSL_PARAM_allocate_from_text()
+         * to handle infix "_hex_"
+         */
+        hex_id = OPENSSL_hexstr2buf((const char *)value, &hex_len);
+        if (hex_id == NULL) {
+            SM2err(SM2_F_PKEY_SM2_CTRL_STR, ERR_R_PASSED_INVALID_ARGUMENT);
+            return 0;
+        }
+        ret = pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, (int)hex_len,
+                            (void *)hex_id);
+        OPENSSL_free(hex_id);
+        return ret;
+    }
+
+    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 *smctx = ctx->data;
+    EC_KEY *ec = ctx->pkey->pkey.ec;
+    const EVP_MD *md = EVP_MD_CTX_md(mctx);
+    int mdlen = EVP_MD_size(md);
+
+#ifndef OPENSSL_NO_SM2
+    if (!smctx->id_set)
+        (void)pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, SM2_DEFAULT_USERID_LEN
+            , (void *)SM2_DEFAULT_USERID);
+#endif
+    if (!smctx->id_set) {
+        /*
+         * An ID value must be set. The specifications are not clear whether a
+         * NULL is allowed. We only allow it if set explicitly for maximum
+         * flexibility.
+         */
+        SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_ID_NOT_SET);
+        return 0;
+    }
+
+    if (mdlen < 0) {
+        SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_INVALID_DIGEST);
+        return 0;
+    }
+
+    /* get hashed prefix 'z' of tbs message */
+    if (!sm2_compute_z_digest(z, md, smctx->id, smctx->id_len, ec))
+        return 0;
+
+    return EVP_DigestUpdate(mctx, z, (size_t)mdlen);
+}
+
+const EVP_PKEY_METHOD sm2_pkey_meth = {
+    EVP_PKEY_SM2,
+    0,
+    pkey_sm2_init,
+    pkey_sm2_copy,
+    pkey_sm2_cleanup,
+
+    0,
+    0,
+
+    0,
+    0,
+
+    0,
+    0, // pkey_sm2_sign,
+
+    0,
+    pkey_sm2_verify,
+
+    0, 0,
+
+    0, 0, 0, 0,
+
+    0,
+    0, // pkey_sm2_encrypt,
+
+    0,
+    0, // pkey_sm2_decrypt,
+
+    0,
+    0,
+    pkey_sm2_ctrl,
+    pkey_sm2_ctrl_str,
+
+    0, 0,
+
+    0, 0, 0,
+
+    pkey_sm2_digest_custom
+};
diff --git a/Cryptlib/OpenSSL/crypto/sm2/sm2_sign.c b/Cryptlib/OpenSSL/crypto/sm2/sm2_sign.c
new file mode 100644
index 0000000..d206f33
--- /dev/null
+++ b/Cryptlib/OpenSSL/crypto/sm2/sm2_sign.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017 Ribose Inc. All Rights Reserved.
+ * Ported from Ribose contributions from Botan.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/sm2.h>
+#include <openssl/sm2err.h>
+#include <openssl/ec.h> /* ec_group_do_inverse_ord() */
+#include <openssl/ecdsa.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <string.h>
+
+int sm2_compute_z_digest(uint8_t *out,
+                         const EVP_MD *digest,
+                         const uint8_t *id,
+                         const size_t id_len,
+                         const EC_KEY *key)
+{
+    int rc = 0;
+    const EC_GROUP *group = EC_KEY_get0_group(key);
+    BN_CTX *ctx = NULL;
+    EVP_MD_CTX *hash = NULL;
+    BIGNUM *p = NULL;
+    BIGNUM *a = NULL;
+    BIGNUM *b = NULL;
+    BIGNUM *xG = NULL;
+    BIGNUM *yG = NULL;
+    BIGNUM *xA = NULL;
+    BIGNUM *yA = NULL;
+    int p_bytes = 0;
+    uint8_t *buf = NULL;
+    uint16_t entl = 0;
+    uint8_t e_byte = 0;
+
+    hash = EVP_MD_CTX_new();
+    ctx = BN_CTX_new();
+    if (hash == NULL || ctx == NULL) {
+        SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
+        goto done;
+    }
+
+    p = BN_CTX_get(ctx);
+    a = BN_CTX_get(ctx);
+    b = BN_CTX_get(ctx);
+    xG = BN_CTX_get(ctx);
+    yG = BN_CTX_get(ctx);
+    xA = BN_CTX_get(ctx);
+    yA = BN_CTX_get(ctx);
+
+    if (yA == NULL) {
+        SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
+        goto done;
+    }
+
+    if (!EVP_DigestInit(hash, digest)) {
+        SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
+        goto done;
+    }
+
+    /* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */
+
+    if (id_len >= (UINT16_MAX / 8)) {
+        /* too large */
+        SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, SM2_R_ID_TOO_LARGE);
+        goto done;
+    }
+
+    entl = (uint16_t)(8 * id_len);
+
+    e_byte = entl >> 8;
+    if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
+        SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
+        goto done;
+    }
+    e_byte = entl & 0xFF;
+    if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
+        SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
+        goto done;
+    }
+
+    if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) {
+        SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EVP_LIB);
+        goto done;
+    }
+
+    if (!EC_GROUP_get_curve_GFp(group, p, a, b, ctx)) {
+        SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_EC_LIB);
+        goto done;
+    }
+
+    p_bytes = BN_num_bytes(p);
+    buf = OPENSSL_zalloc(p_bytes);
+    if (buf == NULL) {
+        SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_MALLOC_FAILURE);
+        goto done;
+    }
+
+    if (BN_bn2bin(a, buf) < 0
+            || !EVP_DigestUpdate(hash, buf, p_bytes)
+            || BN_bn2bin(b, buf) < 0
+            || !EVP_DigestUpdate(hash, buf, p_bytes)
+            || !EC_POINT_get_affine_coordinates_GFp(group,
+                                                EC_GROUP_get0_generator(group),
+                                                xG, yG, ctx)
+            || BN_bn2bin(xG, buf) < 0
+            || !EVP_DigestUpdate(hash, buf, p_bytes)
+            || BN_bn2bin(yG, buf) < 0
+            || !EVP_DigestUpdate(hash, buf, p_bytes)
+            || !EC_POINT_get_affine_coordinates_GFp(group,
+                                                EC_KEY_get0_public_key(key),
+                                                xA, yA, ctx)
+            || BN_bn2bin(xA, buf) < 0
+            || !EVP_DigestUpdate(hash, buf, p_bytes)
+            || BN_bn2bin(yA, buf) < 0
+            || !EVP_DigestUpdate(hash, buf, p_bytes)
+            || !EVP_DigestFinal(hash, out, NULL)) {
+        SM2err(SM2_F_SM2_COMPUTE_Z_DIGEST, ERR_R_INTERNAL_ERROR);
+        goto done;
+    }
+
+    rc = 1;
+
+ done:
+    OPENSSL_free(buf);
+    BN_CTX_free(ctx);
+    EVP_MD_CTX_free(hash);
+    return rc;
+}
+
+static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,
+                                    const EC_KEY *key,
+                                    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();
+    const int md_size = EVP_MD_size(digest);
+    uint8_t *z = NULL;
+    BIGNUM *e = NULL;
+
+    if (md_size < 0) {
+        SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, SM2_R_INVALID_DIGEST);
+        goto done;
+    }
+
+    z = OPENSSL_zalloc(md_size);
+    if (hash == NULL || z == NULL) {
+        SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_MALLOC_FAILURE);
+        goto done;
+    }
+
+    if (!sm2_compute_z_digest(z, digest, id, id_len, key)) {
+        /* SM2err already called */
+        goto done;
+    }
+
+    if (!EVP_DigestInit(hash, digest)
+            || !EVP_DigestUpdate(hash, z, md_size)
+            || !EVP_DigestUpdate(hash, msg, msg_len)
+               /* reuse z buffer to hold H(Z || M) */
+            || !EVP_DigestFinal(hash, z, NULL)) {
+        SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_EVP_LIB);
+        goto done;
+    }
+
+    e = BN_bin2bn(z, md_size, NULL);
+    if (e == NULL)
+        SM2err(SM2_F_SM2_COMPUTE_MSG_HASH, ERR_R_INTERNAL_ERROR);
+
+ done:
+    OPENSSL_free(z);
+    EVP_MD_CTX_free(hash);
+    return e;
+}
+
+static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig,
+                          const BIGNUM *e)
+{
+    int ret = 0;
+    const EC_GROUP *group = EC_KEY_get0_group(key);
+    const BIGNUM *order = EC_GROUP_get0_order(group);
+    BN_CTX *ctx = NULL;
+    EC_POINT *pt = NULL;
+    BIGNUM *t = NULL;
+    BIGNUM *x1 = NULL;
+    const BIGNUM *r = NULL;
+    const BIGNUM *s = NULL;
+
+    ctx = BN_CTX_new();
+    pt = EC_POINT_new(group);
+    if (ctx == NULL || pt == NULL) {
+        SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_MALLOC_FAILURE);
+        goto done;
+    }
+
+    BN_CTX_start(ctx);
+    t = BN_CTX_get(ctx);
+    x1 = BN_CTX_get(ctx);
+    if (x1 == NULL) {
+        SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_MALLOC_FAILURE);
+        goto done;
+    }
+
+    /*
+     * B1: verify whether r' in [1,n-1], verification failed if not
+     * B2: verify whether s' in [1,n-1], verification failed if not
+     * B3: set M'~=ZA || M'
+     * B4: calculate e'=Hv(M'~)
+     * B5: calculate t = (r' + s') modn, verification failed if t=0
+     * B6: calculate the point (x1', y1')=[s']G + [t]PA
+     * B7: calculate R=(e'+x1') modn, verification pass if yes, otherwise failed
+     */
+
+    ECDSA_SIG_get0(sig, &r, &s);
+
+    if (BN_cmp(r, BN_value_one()) < 0
+            || BN_cmp(s, BN_value_one()) < 0
+            || BN_cmp(order, r) <= 0
+            || BN_cmp(order, s) <= 0) {
+        SM2err(SM2_F_SM2_SIG_VERIFY, SM2_R_BAD_SIGNATURE);
+        goto done;
+    }
+
+    if (!BN_mod_add(t, r, s, order, ctx)) {
+        SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_BN_LIB);
+        goto done;
+    }
+
+    if (BN_is_zero(t)) {
+        SM2err(SM2_F_SM2_SIG_VERIFY, SM2_R_BAD_SIGNATURE);
+        goto done;
+    }
+
+    if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx)
+            || !EC_POINT_get_affine_coordinates_GFp(group, pt, x1, NULL, ctx)) {
+        SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_EC_LIB);
+        goto done;
+    }
+
+    if (!BN_mod_add(t, e, x1, order, ctx)) {
+        SM2err(SM2_F_SM2_SIG_VERIFY, ERR_R_BN_LIB);
+        goto done;
+    }
+
+    if (BN_cmp(r, t) == 0)
+        ret = 1;
+
+ done:
+    EC_POINT_free(pt);
+    BN_CTX_free(ctx);
+    return ret;
+}
+
+int sm2_do_verify(const EC_KEY *key,
+                  const EVP_MD *digest,
+                  const ECDSA_SIG *sig,
+                  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, id, id_len, msg, msg_len);
+    if (e == NULL) {
+        /* SM2err already called */
+        goto done;
+    }
+
+    ret = sm2_sig_verify(key, sig, e);
+
+ done:
+    BN_free(e);
+    return ret;
+}
+
+int sm2_verify(const unsigned char *dgst, int dgstlen,
+               const unsigned char *sig, int sig_len, EC_KEY *eckey)
+{
+    ECDSA_SIG *s = NULL;
+    BIGNUM *e = NULL;
+    const unsigned char *p = sig;
+    unsigned char *der = NULL;
+    int derlen = -1;
+    int ret = -1;
+
+    s = ECDSA_SIG_new();
+    if (s == NULL) {
+        SM2err(SM2_F_SM2_VERIFY, ERR_R_MALLOC_FAILURE);
+        goto done;
+    }
+    if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) {
+        SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING);
+        goto done;
+    }
+    /* Ensure signature uses DER and doesn't have trailing garbage */
+    derlen = i2d_ECDSA_SIG(s, &der);
+    if (derlen != sig_len || memcmp(sig, der, derlen) != 0) {
+        SM2err(SM2_F_SM2_VERIFY, SM2_R_INVALID_ENCODING);
+        goto done;
+    }
+
+    e = BN_bin2bn(dgst, dgstlen, NULL);
+    if (e == NULL) {
+        SM2err(SM2_F_SM2_VERIFY, ERR_R_BN_LIB);
+        goto done;
+    }
+
+    ret = sm2_sig_verify(eckey, s, e);
+
+ done:
+    OPENSSL_free(der);
+    BN_free(e);
+    ECDSA_SIG_free(s);
+    return ret;
+}
diff --git a/Cryptlib/OpenSSL/crypto/sm3/m_sm3.c b/Cryptlib/OpenSSL/crypto/sm3/m_sm3.c
new file mode 100644
index 0000000..d429b8c
--- /dev/null
+++ b/Cryptlib/OpenSSL/crypto/sm3/m_sm3.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017 Ribose Inc. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "cryptlib.h"
+
+#ifndef OPENSSL_NO_SM3
+# include <openssl/evp.h>
+# include <openssl/sm3.h>
+
+static int init(EVP_MD_CTX *ctx)
+{
+    return sm3_init(EVP_MD_CTX_md_data(ctx));
+}
+
+static int update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+    return sm3_update(EVP_MD_CTX_md_data(ctx), data, count);
+}
+
+static int final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+    return sm3_final(md, EVP_MD_CTX_md_data(ctx));
+}
+
+static const EVP_MD sm3_md = {
+    NID_sm3,
+    NID_sm3WithRSAEncryption,
+    SM3_DIGEST_LENGTH,
+    0,
+    init,
+    update,
+    final,
+    NULL,
+    NULL,
+    EVP_PKEY_NULL_method,
+    SM3_CBLOCK,
+    sizeof(EVP_MD *) + sizeof(SM3_CTX),
+};
+
+const EVP_MD *EVP_sm3(void)
+{
+    return &sm3_md;
+}
+
+#endif
diff --git a/Cryptlib/OpenSSL/crypto/sm3/sm3.c b/Cryptlib/OpenSSL/crypto/sm3/sm3.c
new file mode 100644
index 0000000..d78292b
--- /dev/null
+++ b/Cryptlib/OpenSSL/crypto/sm3/sm3.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017 Ribose Inc. All Rights Reserved.
+ * Ported from Ribose contributions from Botan.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/e_os2.h>
+#include "sm3_local.h"
+
+int sm3_init(SM3_CTX *c)
+{
+    memset(c, 0, sizeof(*c));
+    c->A = SM3_A;
+    c->B = SM3_B;
+    c->C = SM3_C;
+    c->D = SM3_D;
+    c->E = SM3_E;
+    c->F = SM3_F;
+    c->G = SM3_G;
+    c->H = SM3_H;
+    return 1;
+}
+
+void sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num)
+{
+    const unsigned char *data = p;
+    register unsigned MD32_REG_T A, B, C, D, E, F, G, H;
+
+    unsigned MD32_REG_T W00, W01, W02, W03, W04, W05, W06, W07,
+        W08, W09, W10, W11, W12, W13, W14, W15;
+
+    for (; num--;) {
+
+        A = ctx->A;
+        B = ctx->B;
+        C = ctx->C;
+        D = ctx->D;
+        E = ctx->E;
+        F = ctx->F;
+        G = ctx->G;
+        H = ctx->H;
+
+        /*
+        * We have to load all message bytes immediately since SM3 reads
+        * them slightly out of order.
+        */
+        (void)HOST_c2l(data, W00);
+        (void)HOST_c2l(data, W01);
+        (void)HOST_c2l(data, W02);
+        (void)HOST_c2l(data, W03);
+        (void)HOST_c2l(data, W04);
+        (void)HOST_c2l(data, W05);
+        (void)HOST_c2l(data, W06);
+        (void)HOST_c2l(data, W07);
+        (void)HOST_c2l(data, W08);
+        (void)HOST_c2l(data, W09);
+        (void)HOST_c2l(data, W10);
+        (void)HOST_c2l(data, W11);
+        (void)HOST_c2l(data, W12);
+        (void)HOST_c2l(data, W13);
+        (void)HOST_c2l(data, W14);
+        (void)HOST_c2l(data, W15);
+
+        R1(A, B, C, D, E, F, G, H, 0x79CC4519, W00, W00 ^ W04);
+        W00 = EXPAND(W00, W07, W13, W03, W10);
+        R1(D, A, B, C, H, E, F, G, 0xF3988A32, W01, W01 ^ W05);
+        W01 = EXPAND(W01, W08, W14, W04, W11);
+        R1(C, D, A, B, G, H, E, F, 0xE7311465, W02, W02 ^ W06);
+        W02 = EXPAND(W02, W09, W15, W05, W12);
+        R1(B, C, D, A, F, G, H, E, 0xCE6228CB, W03, W03 ^ W07);
+        W03 = EXPAND(W03, W10, W00, W06, W13);
+        R1(A, B, C, D, E, F, G, H, 0x9CC45197, W04, W04 ^ W08);
+        W04 = EXPAND(W04, W11, W01, W07, W14);
+        R1(D, A, B, C, H, E, F, G, 0x3988A32F, W05, W05 ^ W09);
+        W05 = EXPAND(W05, W12, W02, W08, W15);
+        R1(C, D, A, B, G, H, E, F, 0x7311465E, W06, W06 ^ W10);
+        W06 = EXPAND(W06, W13, W03, W09, W00);
+        R1(B, C, D, A, F, G, H, E, 0xE6228CBC, W07, W07 ^ W11);
+        W07 = EXPAND(W07, W14, W04, W10, W01);
+        R1(A, B, C, D, E, F, G, H, 0xCC451979, W08, W08 ^ W12);
+        W08 = EXPAND(W08, W15, W05, W11, W02);
+        R1(D, A, B, C, H, E, F, G, 0x988A32F3, W09, W09 ^ W13);
+        W09 = EXPAND(W09, W00, W06, W12, W03);
+        R1(C, D, A, B, G, H, E, F, 0x311465E7, W10, W10 ^ W14);
+        W10 = EXPAND(W10, W01, W07, W13, W04);
+        R1(B, C, D, A, F, G, H, E, 0x6228CBCE, W11, W11 ^ W15);
+        W11 = EXPAND(W11, W02, W08, W14, W05);
+        R1(A, B, C, D, E, F, G, H, 0xC451979C, W12, W12 ^ W00);
+        W12 = EXPAND(W12, W03, W09, W15, W06);
+        R1(D, A, B, C, H, E, F, G, 0x88A32F39, W13, W13 ^ W01);
+        W13 = EXPAND(W13, W04, W10, W00, W07);
+        R1(C, D, A, B, G, H, E, F, 0x11465E73, W14, W14 ^ W02);
+        W14 = EXPAND(W14, W05, W11, W01, W08);
+        R1(B, C, D, A, F, G, H, E, 0x228CBCE6, W15, W15 ^ W03);
+        W15 = EXPAND(W15, W06, W12, W02, W09);
+        R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04);
+        W00 = EXPAND(W00, W07, W13, W03, W10);
+        R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05);
+        W01 = EXPAND(W01, W08, W14, W04, W11);
+        R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06);
+        W02 = EXPAND(W02, W09, W15, W05, W12);
+        R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07);
+        W03 = EXPAND(W03, W10, W00, W06, W13);
+        R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08);
+        W04 = EXPAND(W04, W11, W01, W07, W14);
+        R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09);
+        W05 = EXPAND(W05, W12, W02, W08, W15);
+        R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10);
+        W06 = EXPAND(W06, W13, W03, W09, W00);
+        R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11);
+        W07 = EXPAND(W07, W14, W04, W10, W01);
+        R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12);
+        W08 = EXPAND(W08, W15, W05, W11, W02);
+        R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13);
+        W09 = EXPAND(W09, W00, W06, W12, W03);
+        R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14);
+        W10 = EXPAND(W10, W01, W07, W13, W04);
+        R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15);
+        W11 = EXPAND(W11, W02, W08, W14, W05);
+        R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00);
+        W12 = EXPAND(W12, W03, W09, W15, W06);
+        R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01);
+        W13 = EXPAND(W13, W04, W10, W00, W07);
+        R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02);
+        W14 = EXPAND(W14, W05, W11, W01, W08);
+        R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03);
+        W15 = EXPAND(W15, W06, W12, W02, W09);
+        R2(A, B, C, D, E, F, G, H, 0x7A879D8A, W00, W00 ^ W04);
+        W00 = EXPAND(W00, W07, W13, W03, W10);
+        R2(D, A, B, C, H, E, F, G, 0xF50F3B14, W01, W01 ^ W05);
+        W01 = EXPAND(W01, W08, W14, W04, W11);
+        R2(C, D, A, B, G, H, E, F, 0xEA1E7629, W02, W02 ^ W06);
+        W02 = EXPAND(W02, W09, W15, W05, W12);
+        R2(B, C, D, A, F, G, H, E, 0xD43CEC53, W03, W03 ^ W07);
+        W03 = EXPAND(W03, W10, W00, W06, W13);
+        R2(A, B, C, D, E, F, G, H, 0xA879D8A7, W04, W04 ^ W08);
+        W04 = EXPAND(W04, W11, W01, W07, W14);
+        R2(D, A, B, C, H, E, F, G, 0x50F3B14F, W05, W05 ^ W09);
+        W05 = EXPAND(W05, W12, W02, W08, W15);
+        R2(C, D, A, B, G, H, E, F, 0xA1E7629E, W06, W06 ^ W10);
+        W06 = EXPAND(W06, W13, W03, W09, W00);
+        R2(B, C, D, A, F, G, H, E, 0x43CEC53D, W07, W07 ^ W11);
+        W07 = EXPAND(W07, W14, W04, W10, W01);
+        R2(A, B, C, D, E, F, G, H, 0x879D8A7A, W08, W08 ^ W12);
+        W08 = EXPAND(W08, W15, W05, W11, W02);
+        R2(D, A, B, C, H, E, F, G, 0x0F3B14F5, W09, W09 ^ W13);
+        W09 = EXPAND(W09, W00, W06, W12, W03);
+        R2(C, D, A, B, G, H, E, F, 0x1E7629EA, W10, W10 ^ W14);
+        W10 = EXPAND(W10, W01, W07, W13, W04);
+        R2(B, C, D, A, F, G, H, E, 0x3CEC53D4, W11, W11 ^ W15);
+        W11 = EXPAND(W11, W02, W08, W14, W05);
+        R2(A, B, C, D, E, F, G, H, 0x79D8A7A8, W12, W12 ^ W00);
+        W12 = EXPAND(W12, W03, W09, W15, W06);
+        R2(D, A, B, C, H, E, F, G, 0xF3B14F50, W13, W13 ^ W01);
+        W13 = EXPAND(W13, W04, W10, W00, W07);
+        R2(C, D, A, B, G, H, E, F, 0xE7629EA1, W14, W14 ^ W02);
+        W14 = EXPAND(W14, W05, W11, W01, W08);
+        R2(B, C, D, A, F, G, H, E, 0xCEC53D43, W15, W15 ^ W03);
+        W15 = EXPAND(W15, W06, W12, W02, W09);
+        R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04);
+        W00 = EXPAND(W00, W07, W13, W03, W10);
+        R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05);
+        W01 = EXPAND(W01, W08, W14, W04, W11);
+        R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06);
+        W02 = EXPAND(W02, W09, W15, W05, W12);
+        R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07);
+        W03 = EXPAND(W03, W10, W00, W06, W13);
+        R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08);
+        R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09);
+        R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10);
+        R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11);
+        R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12);
+        R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13);
+        R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14);
+        R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15);
+        R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00);
+        R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01);
+        R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02);
+        R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03);
+
+        ctx->A ^= A;
+        ctx->B ^= B;
+        ctx->C ^= C;
+        ctx->D ^= D;
+        ctx->E ^= E;
+        ctx->F ^= F;
+        ctx->G ^= G;
+        ctx->H ^= H;
+    }
+}
+
diff --git a/Cryptlib/OpenSSL/crypto/sm3/sm3_local.h b/Cryptlib/OpenSSL/crypto/sm3/sm3_local.h
new file mode 100644
index 0000000..dfb7bfb
--- /dev/null
+++ b/Cryptlib/OpenSSL/crypto/sm3/sm3_local.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017 Ribose Inc. All Rights Reserved.
+ * Ported from Ribose contributions from Botan.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/sm3.h>
+
+#define DATA_ORDER_IS_BIG_ENDIAN
+
+#define HASH_LONG               SM3_WORD
+#define HASH_CTX                SM3_CTX
+#define HASH_CBLOCK             SM3_CBLOCK
+#define HASH_UPDATE             sm3_update
+#define HASH_TRANSFORM          sm3_transform
+#define HASH_FINAL              sm3_final
+#define HASH_MAKE_STRING(c, s)              \
+      do {                                  \
+        unsigned long ll;                   \
+        ll=(c)->A; (void)HOST_l2c(ll, (s)); \
+        ll=(c)->B; (void)HOST_l2c(ll, (s)); \
+        ll=(c)->C; (void)HOST_l2c(ll, (s)); \
+        ll=(c)->D; (void)HOST_l2c(ll, (s)); \
+        ll=(c)->E; (void)HOST_l2c(ll, (s)); \
+        ll=(c)->F; (void)HOST_l2c(ll, (s)); \
+        ll=(c)->G; (void)HOST_l2c(ll, (s)); \
+        ll=(c)->H; (void)HOST_l2c(ll, (s)); \
+      } while (0)
+#define HASH_BLOCK_DATA_ORDER   sm3_block_data_order
+
+void sm3_transform(SM3_CTX *c, const unsigned char *data);
+
+#include "crypto/md32_common.h"
+
+#define P0(X) (X ^ ROTATE(X, 9) ^ ROTATE(X, 17))
+#define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23))
+
+#define FF0(X,Y,Z) (X ^ Y ^ Z)
+#define GG0(X,Y,Z) (X ^ Y ^ Z)
+
+#define FF1(X,Y,Z) ((X & Y) | ((X | Y) & Z))
+#define GG1(X,Y,Z) ((Z ^ (X & (Y ^ Z))))
+
+#define EXPAND(W0,W7,W13,W3,W10) \
+   (P1(W0 ^ W7 ^ ROTATE(W13, 15)) ^ ROTATE(W3, 7) ^ W10)
+
+#define RND(A, B, C, D, E, F, G, H, TJ, Wi, Wj, FF, GG)           \
+     do {                                                         \
+       const SM3_WORD A12 = ROTATE(A, 12);                        \
+       const SM3_WORD A12_SM = A12 + E + TJ;                      \
+       const SM3_WORD SS1 = ROTATE(A12_SM, 7);                    \
+       const SM3_WORD TT1 = FF(A, B, C) + D + (SS1 ^ A12) + (Wj); \
+       const SM3_WORD TT2 = GG(E, F, G) + H + SS1 + Wi;           \
+       B = ROTATE(B, 9);                                          \
+       D = TT1;                                                   \
+       F = ROTATE(F, 19);                                         \
+       H = P0(TT2);                                               \
+     } while(0)
+
+#define R1(A,B,C,D,E,F,G,H,TJ,Wi,Wj) \
+   RND(A,B,C,D,E,F,G,H,TJ,Wi,Wj,FF0,GG0)
+
+#define R2(A,B,C,D,E,F,G,H,TJ,Wi,Wj) \
+   RND(A,B,C,D,E,F,G,H,TJ,Wi,Wj,FF1,GG1)
+
+#define SM3_A 0x7380166fUL
+#define SM3_B 0x4914b2b9UL
+#define SM3_C 0x172442d7UL
+#define SM3_D 0xda8a0600UL
+#define SM3_E 0xa96f30bcUL
+#define SM3_F 0x163138aaUL
+#define SM3_G 0xe38dee4dUL
+#define SM3_H 0xb0fb0e4eUL
-- 
2.33.0

