summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Lloyd <jack.lloyd@ribose.com>2017-10-25 13:19:02 -0400
committerRonald Tse <ronald.tse@ribose.com>2017-11-06 07:21:11 +0800
commita0c3e4fa9089f571ff4b406cb914d0a504847b10 (patch)
tree46bc0fccfcc317d2572145d3a13acf029523973d
parentcf72c7579201086cee303eadcb60bd28eff78dd9 (diff)
downloadopenssl-new-a0c3e4fa9089f571ff4b406cb914d0a504847b10.tar.gz
SM3: Add SM3 hash function
SM3 is a secure hash function which is part of the Chinese "Commercial Cryptography" suite of algorithms which use is required for certain commercial applications in China. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/4616)
-rw-r--r--CHANGES5
-rwxr-xr-xConfigure3
-rw-r--r--INSTALL6
-rwxr-xr-xconfig2
-rw-r--r--crypto/evp/build.info2
-rw-r--r--crypto/evp/c_alld.c3
-rw-r--r--crypto/evp/m_sm3.c55
-rw-r--r--crypto/objects/obj_dat.h20
-rw-r--r--crypto/objects/obj_mac.num2
-rw-r--r--crypto/objects/objects.txt3
-rw-r--r--crypto/sm3/build.info2
-rw-r--r--crypto/sm3/sm3.c215
-rw-r--r--crypto/sm3/sm3_locl.h79
-rw-r--r--doc/man3/SM3.pod76
-rw-r--r--include/openssl/evp.h3
-rw-r--r--include/openssl/obj_mac.h10
-rw-r--r--include/openssl/sm3.h47
-rw-r--r--test/recipes/30-test_evp_data/evpdigest.txt39
-rw-r--r--util/libcrypto.num5
-rwxr-xr-xutil/mkdef.pl2
20 files changed, 567 insertions, 12 deletions
diff --git a/CHANGES b/CHANGES
index 71c700c2fd..c35990e2af 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,11 @@
Changes between 1.1.0f and 1.1.1 [xx XXX xxxx]
+ *) Add SM3 implemented according to GB/T 32905-2016
+ [ Jack Lloyd <jack.lloyd@ribose.com>,
+ Ronald Tse <ronald.tse@ribose.com>,
+ Erick Borsboom <erick.borsboom@ribose.com> ]
+
*) Add 'Maximum Fragment Length' TLS extension negotiation and support
as documented in RFC6066.
Based on a patch from Tomasz Moń
diff --git a/Configure b/Configure
index 247f276de4..3821741183 100755
--- a/Configure
+++ b/Configure
@@ -307,7 +307,7 @@ $config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "
# crypto/ subdirectories to build
$config{sdirs} = [
"objects",
- "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash",
+ "md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash", "sm3",
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "sm4", "chacha", "modes",
"bn", "ec", "rsa", "dsa", "dh", "dso", "engine",
"buffer", "bio", "stack", "lhash", "rand", "err",
@@ -394,6 +394,7 @@ my @disablables = (
"seed",
"shared",
"siphash",
+ "sm3",
"sm4",
"sock",
"srp",
diff --git a/INSTALL b/INSTALL
index c4fcc05329..4e954e34c2 100644
--- a/INSTALL
+++ b/INSTALL
@@ -512,9 +512,9 @@
Build without support for the specified algorithm, where
<alg> is one of: bf, blake2, camellia, cast, chacha, cmac,
des, dh, dsa, ecdh, ecdsa, idea, md4, mdc2, ocb, poly1305,
- rc2, rc4, rmd160, scrypt, seed, siphash, sm4 or whirlpool.
- The "ripemd" algorithm is deprecated and if used is
- synonymous with rmd160.
+ rc2, rc4, rmd160, scrypt, seed, siphash, sm3, sm4 or
+ whirlpool. The "ripemd" algorithm is deprecated and if used
+ is synonymous with rmd160.
-Dxxx, lxxx, -Lxxx, -Wl, -rpath, -R, -framework, -static
These system specific options will be recognised and
diff --git a/config b/config
index 14d735c618..a341af2d61 100755
--- a/config
+++ b/config
@@ -848,7 +848,7 @@ case "$GUESSOS" in
i386-*) options="$options 386" ;;
esac
-for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sm4 sha
+for i in aes aria bf camellia cast des dh dsa ec hmac idea md2 md5 mdc2 rc2 rc4 rc5 ripemd rsa seed sha sm3 sm4
do
if [ ! -d $THERE/crypto/$i ]
then
diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index 0305738011..96b44efbfb 100644
--- a/crypto/evp/build.info
+++ b/crypto/evp/build.info
@@ -5,7 +5,7 @@ SOURCE[../../libcrypto]=\
e_rc4.c e_aes.c names.c e_seed.c e_aria.c e_sm4.c \
e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c \
m_null.c m_md2.c m_md4.c m_md5.c m_sha1.c m_wp.c \
- m_md5_sha1.c m_mdc2.c m_ripemd.c m_sha3.c \
+ m_md5_sha1.c m_mdc2.c m_ripemd.c m_sha3.c m_sm3.c \
p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \
bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
c_allc.c c_alld.c evp_lib.c bio_ok.c \
diff --git a/crypto/evp/c_alld.c b/crypto/evp/c_alld.c
index 088f65cd80..257d405ba7 100644
--- a/crypto/evp/c_alld.c
+++ b/crypto/evp/c_alld.c
@@ -42,6 +42,9 @@ void openssl_add_all_digests_int(void)
#ifndef OPENSSL_NO_WHIRLPOOL
EVP_add_digest(EVP_whirlpool());
#endif
+#ifndef OPENSSL_NO_SM3
+ EVP_add_digest(EVP_sm3());
+#endif
#ifndef OPENSSL_NO_BLAKE2
EVP_add_digest(EVP_blake2b512());
EVP_add_digest(EVP_blake2s256());
diff --git a/crypto/evp/m_sm3.c b/crypto/evp/m_sm3.c
new file mode 100644
index 0000000000..21ee1de136
--- /dev/null
+++ b/crypto/evp/m_sm3.c
@@ -0,0 +1,55 @@
+/*
+ * 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 <stdio.h>
+#include "internal/cryptlib.h"
+
+#ifndef OPENSSL_NO_SM3
+
+# include <openssl/evp.h>
+# include <openssl/objects.h>
+# include <openssl/sm3.h>
+# include "internal/evp_int.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,
+ SM3_CBLOCK,
+ sizeof(EVP_MD *) + sizeof(SM3_CTX),
+};
+
+const EVP_MD *EVP_sm3(void)
+{
+ return &sm3_md;
+}
+#endif
+
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index 866fa34cc1..535d315037 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -10,7 +10,7 @@
*/
/* Serialized OID's */
-static const unsigned char so[7308] = {
+static const unsigned char so[7324] = {
0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */
@@ -1028,9 +1028,11 @@ static const unsigned char so[7308] = {
0x2A,0x81,0x1C, /* [ 7293] OBJ_ISO_CN */
0x2A,0x81,0x1C,0xCF,0x55, /* [ 7296] OBJ_oscca */
0x2A,0x81,0x1C,0xCF,0x55,0x01, /* [ 7301] OBJ_sm_scheme */
+ 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x11, /* [ 7307] OBJ_sm3 */
+ 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x78, /* [ 7315] OBJ_sm3WithRSAEncryption */
};
-#define NUM_NID 1143
+#define NUM_NID 1145
static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"UNDEF", "undefined", NID_undef},
{"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@@ -2175,9 +2177,11 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"ISO-CN", "ISO CN Member Body", NID_ISO_CN, 3, &so[7293]},
{"oscca", "oscca", NID_oscca, 5, &so[7296]},
{"sm-scheme", "sm-scheme", NID_sm_scheme, 6, &so[7301]},
+ {"SM3", "sm3", NID_sm3, 8, &so[7307]},
+ {"RSA-SM3", "sm3WithRSAEncryption", NID_sm3WithRSAEncryption, 8, &so[7315]},
};
-#define NUM_SN 1134
+#define NUM_SN 1136
static const unsigned int sn_objs[NUM_SN] = {
364, /* "AD_DVCS" */
419, /* "AES-128-CBC" */
@@ -2418,6 +2422,7 @@ static const unsigned int sn_objs[NUM_SN] = {
668, /* "RSA-SHA256" */
669, /* "RSA-SHA384" */
670, /* "RSA-SHA512" */
+ 1144, /* "RSA-SM3" */
919, /* "RSAES-OAEP" */
912, /* "RSASSA-PSS" */
777, /* "SEED-CBC" */
@@ -2438,6 +2443,7 @@ static const unsigned int sn_objs[NUM_SN] = {
1095, /* "SHA512-256" */
1100, /* "SHAKE128" */
1101, /* "SHAKE256" */
+ 1143, /* "SM3" */
1134, /* "SM4-CBC" */
1137, /* "SM4-CFB" */
1136, /* "SM4-CFB1" */
@@ -3315,7 +3321,7 @@ static const unsigned int sn_objs[NUM_SN] = {
1093, /* "x509ExtAdmission" */
};
-#define NUM_LN 1134
+#define NUM_LN 1136
static const unsigned int ln_objs[NUM_LN] = {
363, /* "AD Time Stamping" */
405, /* "ANSI X9.62" */
@@ -4399,6 +4405,8 @@ static const unsigned int ln_objs[NUM_LN] = {
496, /* "singleLevelQuality" */
1062, /* "siphash" */
1142, /* "sm-scheme" */
+ 1143, /* "sm3" */
+ 1144, /* "sm3WithRSAEncryption" */
1134, /* "sm4-cbc" */
1137, /* "sm4-cfb" */
1136, /* "sm4-cfb1" */
@@ -4453,7 +4461,7 @@ static const unsigned int ln_objs[NUM_LN] = {
125, /* "zlib compression" */
};
-#define NUM_OBJ 1023
+#define NUM_OBJ 1025
static const unsigned int obj_objs[NUM_OBJ] = {
0, /* OBJ_undef 0 */
181, /* OBJ_iso 1 */
@@ -4915,6 +4923,8 @@ static const unsigned int obj_objs[NUM_OBJ] = {
1136, /* OBJ_sm4_cfb1 1 2 156 10197 1 104 5 */
1138, /* OBJ_sm4_cfb8 1 2 156 10197 1 104 6 */
1139, /* OBJ_sm4_ctr 1 2 156 10197 1 104 7 */
+ 1143, /* OBJ_sm3 1 2 156 10197 1 401 */
+ 1144, /* OBJ_sm3WithRSAEncryption 1 2 156 10197 1 504 */
776, /* OBJ_seed_ecb 1 2 410 200004 1 3 */
777, /* OBJ_seed_cbc 1 2 410 200004 1 4 */
779, /* OBJ_seed_cfb128 1 2 410 200004 1 5 */
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index 4e5f702c29..83641c451e 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -1140,3 +1140,5 @@ sm4_ctr 1139
ISO_CN 1140
oscca 1141
sm_scheme 1142
+sm3 1143
+sm3WithRSAEncryption 1144
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index 22e69b8f1c..bbef44e6aa 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -371,6 +371,9 @@ rsadsi 2 5 : MD5 : md5
rsadsi 2 6 : : hmacWithMD5
rsadsi 2 7 : : hmacWithSHA1
+member-body 156 10197 1 401 : SM3 : sm3
+member-body 156 10197 1 504 : RSA-SM3 : sm3WithRSAEncryption
+
# From RFC4231
rsadsi 2 8 : : hmacWithSHA224
rsadsi 2 9 : : hmacWithSHA256
diff --git a/crypto/sm3/build.info b/crypto/sm3/build.info
new file mode 100644
index 0000000000..239ac8755e
--- /dev/null
+++ b/crypto/sm3/build.info
@@ -0,0 +1,2 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]=sm3.c
diff --git a/crypto/sm3/sm3.c b/crypto/sm3/sm3.c
new file mode 100644
index 0000000000..615fcb21cd
--- /dev/null
+++ b/crypto/sm3/sm3.c
@@ -0,0 +1,215 @@
+/*
+ * 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 <stdio.h>
+
+#ifndef OPENSSL_NO_SM3
+
+#include "sm3_locl.h"
+#include <openssl/opensslv.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;
+}
+
+unsigned char *SM3(const unsigned char *d, size_t n, unsigned char *md)
+{
+ SM3_CTX c;
+ static unsigned char m[SM3_DIGEST_LENGTH];
+
+ if (md == NULL)
+ md = m;
+ if (!SM3_Init(&c))
+ return NULL;
+ SM3_Update(&c, d, n);
+ SM3_Final(md, &c);
+ OPENSSL_cleanse(&c, sizeof(c)); /* security consideration */
+ return md;
+}
+
+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;
+ }
+}
+#endif
diff --git a/crypto/sm3/sm3_locl.h b/crypto/sm3/sm3_locl.h
new file mode 100644
index 0000000000..598c80aa1d
--- /dev/null
+++ b/crypto/sm3/sm3_locl.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 <stdlib.h>
+#include <string.h>
+#include <openssl/e_os2.h>
+#include <openssl/sm3.h>
+
+void sm3_block_data_order(SM3_CTX *c, const void *p, size_t num);
+
+#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
+
+#include "internal/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
diff --git a/doc/man3/SM3.pod b/doc/man3/SM3.pod
new file mode 100644
index 0000000000..afa7082618
--- /dev/null
+++ b/doc/man3/SM3.pod
@@ -0,0 +1,76 @@
+=pod
+
+=head1 NAME
+
+SM3_Init,
+SM3_Update,
+SM3_Final
+
+=head1 SYNOPSIS
+
+ #include <openssl/sm3.h>
+
+ unsigned char *SM3(const unsigned char *d, size_t n, unsigned char *md);
+
+ 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);
+
+=head1 DESCRIPTION
+
+SM3 is a cryptographic hash function with a 256-bit output, defined in GB/T
+32905-2016.
+
+SM3() computes the SM3 message digest of the B<n> bytes at B<d> and places it
+in B<md> (which must have space for SM3_DIGEST_LENGTH == 32 bytes of output).
+If B<md> is NULL, the digest is placed in a static array.
+
+The following functions may be used if the message is not completely stored in
+memory:
+
+SM3_Init() initializes a B<SM3_CTX> structure.
+
+SM3_Update() can be called repeatedly with chunks of the message to be hashed
+(B<len> bytes at B<data>).
+
+SM3_Final() places the message digest in B<md>, which must have space for
+B<SM3_DIGEST_LENGTH> == 32 bytes of output, and erases the B<SM3_CTX>.
+
+=head1 RETURN VALUES
+
+=over 4
+
+=item SM3()
+
+Returns pointers to the hash value.
+
+=item SM3_Init(), SM3_Update(), SM3_Final()
+
+Returns 1 for success, 0 otherwise.
+
+=back
+
+=head1 NOTE
+
+Applications should use the higher level functions such as L<EVP_DigestInit(3)>
+instead of calling these functions directly.
+
+=head1 CONFORMING TO
+
+GB/T 32905-2016 and GM/T 0004-2012.
+
+=head1 SEE ALSO
+
+L<EVP_DigestInit(3)>
+
+=head1 COPYRIGHT
+
+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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 3a98e1da9e..e002d63d24 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -717,6 +717,9 @@ const EVP_MD *EVP_ripemd160(void);
# ifndef OPENSSL_NO_WHIRLPOOL
const EVP_MD *EVP_whirlpool(void);
# endif
+# ifndef OPENSSL_NO_SM3
+const EVP_MD *EVP_sm3(void);
+# endif
const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */
# ifndef OPENSSL_NO_DES
const EVP_CIPHER *EVP_des_ecb(void);
diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h
index 02447dcd50..8a9e25284c 100644
--- a/include/openssl/obj_mac.h
+++ b/include/openssl/obj_mac.h
@@ -1132,6 +1132,16 @@
#define NID_hmacWithSHA1 163
#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L
+#define SN_sm3 "SM3"
+#define LN_sm3 "sm3"
+#define NID_sm3 1143
+#define OBJ_sm3 OBJ_member_body,156L,10197L,1L,401L
+
+#define SN_sm3WithRSAEncryption "RSA-SM3"
+#define LN_sm3WithRSAEncryption "sm3WithRSAEncryption"
+#define NID_sm3WithRSAEncryption 1144
+#define OBJ_sm3WithRSAEncryption OBJ_member_body,156L,10197L,1L,504L
+
#define LN_hmacWithSHA224 "hmacWithSHA224"
#define NID_hmacWithSHA224 798
#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L
diff --git a/include/openssl/sm3.h b/include/openssl/sm3.h
new file mode 100644
index 0000000000..84f8570235
--- /dev/null
+++ b/include/openssl/sm3.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017 [Ribose Inc.](https://www.ribose.com). 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_SM3_H
+# define HEADER_SM3_H
+
+# include <openssl/opensslconf.h>
+
+# ifdef OPENSSL_NO_SM3
+# error SM3 is disabled.
+# endif
+
+# ifdef __cplusplus
+extern "C" {
+# 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_Transform(SM3_CTX *c, const unsigned char *data);
+unsigned char *SM3(const unsigned char *d, size_t n, unsigned char *md);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/test/recipes/30-test_evp_data/evpdigest.txt b/test/recipes/30-test_evp_data/evpdigest.txt
index 456358eaa2..d01ff6481a 100644
--- a/test/recipes/30-test_evp_data/evpdigest.txt
+++ b/test/recipes/30-test_evp_data/evpdigest.txt
@@ -431,3 +431,42 @@ Output = b9b92544fb25cfe4ec6fe437d8da2bbe00f7bdaface3de97b8775a44d753c3adca3f7c6
Digest = SHAKE256
Input = 8d8001e2c096f1b88e7c9224a086efd4797fbf74a8033a2d422a2b6b8f6747e4
Output = 2e975f6a8a14f0704d51b13667d8195c219f71e6345696c49fa4b9d08e9225d3d39393425152c97e71dd24601c11abcfa0f12f53c680bd3ae757b8134a9c10d429615869217fdd5885c4db174985703a6d6de94a667eac3023443a8337ae1bc601b76d7d38ec3c34463105f0d3949d78e562a039e4469548b609395de5a4fd43c46ca9fd6ee29ada5efc07d84d553249450dab4a49c483ded250c9338f85cd937ae66bb436f3b4026e859fda1ca571432f3bfc09e7c03ca4d183b741111ca0483d0edabc03feb23b17ee48e844ba2408d9dcfd0139d2e8c7310125aee801c61ab7900d1efc47c078281766f361c5e6111346235e1dc38325666c
+
+Title = SM3 Tests
+
+# From https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02
+
+Digest = SM3
+Input = 0090414C494345313233405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A20AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857
+Output = F4A38489E32B45B6F876E3AC2168CA392362DC8F23459C1D1146FC3DBFB7BC9A
+
+# From https://tools.ietf.org/html/draft-shen-sm3-hash-01
+Digest = SM3
+Input = 616263
+Output = 66C7F0F462EEEDD9D1F2D46BDC10E4E24167C4875CF2F7A2297DA02B8F4BA8E0
+
+Digest = SM3
+Input = 61626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364
+Output = DEBE9FF92275B8A138604889C18E5A4D6FDB70E5387E5765293dCbA39C0C5732
+
+# From GmSSL test suite
+
+Digest = SM3
+Input = 0090414C494345313233405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A20AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857
+Output = F4A38489E32B45B6F876E3AC2168CA392362DC8F23459C1D1146FC3DBFB7BC9A
+
+Digest = SM3
+Input = 0090414C494345313233405941484F4F2E434F4D00000000000000000000000000000000000000000000000000000000000000000000E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E0165961645281A8626607B917F657D7E9382F1EA5CD931F40F6627F357542653B201686522130D590FB8DE635D8FCA715CC6BF3D05BEF3F75DA5D543454448166612
+Output = 26352AF82EC19F207BBC6F9474E11E90CE0F7DDACE03B27F801817E897A81FD5
+
+Digest = SM3
+Input = 0090414C494345313233405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A23099093BF3C137D8FCBBCDF4A2AE50F3B0F216C3122D79425FE03A45DBFE16553DF79E8DAC1CF0ECBAA2F2B49D51A4B387F2EFAF482339086A27A8E05BAED98B
+Output = E4D1D0C3CA4C7F11BC8FF8CB3F4C02A78F108FA098E51A668487240F75E20F31
+
+Digest = SM3
+Input = 008842494C4C343536405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2245493D446C38D8CC0F118374690E7DF633A8A4BFB3329B5ECE604B2B4F37F4353C0869F4B9E17773DE68FEC45E14904E0DEA45BF6CECF9918C85EA047C60A4C
+Output = 6B4B6D0E276691BD4A11BF72F4FB501AE309FDACB72FA6CC336E6656119ABD67
+
+Digest = SM3
+Input = 4D38D2958CA7FD2CFAE3AF04486959CF92C8EF48E8B83A05C112E739D5F181D03082020CA003020102020900AF28725D98D33143300C06082A811CCF550183750500307D310B300906035504060C02636E310B300906035504080C02626A310B300906035504070C02626A310F300D060355040A0C06746F70736563310F300D060355040B0C06746F707365633111300F06035504030C08546F707365634341311F301D06092A864886F70D0109010C10626A40746F707365632E636F6D2E636E301E170D3132303632343037353433395A170D3332303632303037353433395A307D310B300906035504060C02636E310B300906035504080C02626A310B300906035504070C02626A310F300D060355040A0C06746F70736563310F300D060355040B0C06746F707365633111300F06035504030C08546F707365634341311F301D06092A864886F70D0109010C10626A40746F707365632E636F6D2E636E3059301306072A8648CE3D020106082A811CCF5501822D03420004D69C2F1EEC3BFB6B95B30C28085C77B125D77A9C39525D8190768F37D6B205B589DCD316BBE7D89A9DC21917F17799E698531F5E6E3E10BD31370B259C3F81C3A3733071300F0603551D130101FF040530030101FF301D0603551D0E041604148E5D90347858BAAAD870D8BDFBA6A85E7B563B64301F0603551D230418301680148E5D90347858BAAAD870D8BDFBA6A85E7B563B64300B0603551D0F040403020106301106096086480186F8420101040403020057
+Output = C3B02E500A8B60B77DEDCF6F4C11BEF8D56E5CDE708C72065654FD7B2167915A
diff --git a/util/libcrypto.num b/util/libcrypto.num
index bbaa50bf1d..cf7575de5f 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4425,3 +4425,8 @@ EVP_sm4_cbc 4369 1_1_1 EXIST::FUNCTION:SM4
EVP_sm4_ofb 4370 1_1_1 EXIST::FUNCTION:SM4
EVP_sm4_ecb 4371 1_1_1 EXIST::FUNCTION:SM4
EVP_sm4_cfb128 4372 1_1_1 EXIST::FUNCTION:SM4
+EVP_sm3 4373 1_1_1 EXIST::FUNCTION:SM3
+SM3_Update 4374 1_1_1 EXIST::FUNCTION:SM3
+SM3 4375 1_1_1 EXIST::FUNCTION:SM3
+SM3_Init 4376 1_1_1 EXIST::FUNCTION:SM3
+SM3_Final 4377 1_1_1 EXIST::FUNCTION:SM3
diff --git a/util/mkdef.pl b/util/mkdef.pl
index 1ca1112d04..20af2e8cd0 100755
--- a/util/mkdef.pl
+++ b/util/mkdef.pl
@@ -85,7 +85,7 @@ my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
"MDC2", "WHIRLPOOL", "RSA", "DSA", "DH", "EC", "EC2M",
"HMAC", "AES", "CAMELLIA", "SEED", "GOST", "ARIA", "SM4",
"SCRYPT", "CHACHA", "POLY1305", "BLAKE2",
- "SIPHASH",
+ "SIPHASH", "SM3",
# EC_NISTP_64_GCC_128
"EC_NISTP_64_GCC_128",
# Envelope "algorithms"