Browse Source

SM2/SM3/SM4: Chinese cipher support

Add support for:
 - SM2 elliptic curve and SM2 sign/verify
 - SM3 digest
 - SM4 cipher with modes ECB/CBC/CTR/GCM/CCM

Add APIs for SM3 and SM4.
Add SM2 sign and verify APIs.
Add support for SM3 in wc_Hash and wc_Hmac API.
Add support for SM3 and SM4 through EVP layer.
Add support for SM2-SM3 certificates. Support key ID and name hash being
with SHA-1/256 or SM3.
Add support for TLS 1.3 cipher suites: TLS-SM4-GCM-SM3, TLS-SM4-CCM-SM3
Add support for TLS 1.2 SM cipher suite: ECDHE-ECDSA-SM4-CBC-SM3
Add support for SM3 in wc_PRF_TLS.
Add SM2-SM3 certificates and keys. Generated with GmSSL-3.0.0 and
OpenSSL.
Sean Parkinson 1 year ago
parent
commit
e2424e6744
90 changed files with 7639 additions and 1769 deletions
  1. 1 0
      certs/include.am
  2. BIN
      certs/sm2/ca-sm2-key.der
  3. 4 0
      certs/sm2/ca-sm2-key.pem
  4. BIN
      certs/sm2/ca-sm2-priv.der
  5. 5 0
      certs/sm2/ca-sm2-priv.pem
  6. BIN
      certs/sm2/ca-sm2.der
  7. 51 0
      certs/sm2/ca-sm2.pem
  8. BIN
      certs/sm2/client-sm2-key.der
  9. 4 0
      certs/sm2/client-sm2-key.pem
  10. BIN
      certs/sm2/client-sm2-priv.der
  11. 5 0
      certs/sm2/client-sm2-priv.pem
  12. BIN
      certs/sm2/client-sm2.der
  13. 63 0
      certs/sm2/client-sm2.pem
  14. 105 0
      certs/sm2/gen-sm2-certs.sh
  15. 16 0
      certs/sm2/gen-sm2-keys.sh
  16. 37 0
      certs/sm2/include.am
  17. BIN
      certs/sm2/root-sm2-key.der
  18. 4 0
      certs/sm2/root-sm2-key.pem
  19. BIN
      certs/sm2/root-sm2-priv.der
  20. 5 0
      certs/sm2/root-sm2-priv.pem
  21. BIN
      certs/sm2/root-sm2.der
  22. 52 0
      certs/sm2/root-sm2.pem
  23. 13 0
      certs/sm2/self-sm2-cert.pem
  24. 4 0
      certs/sm2/self-sm2-key.pem
  25. 6 0
      certs/sm2/self-sm2-priv.pem
  26. 57 0
      certs/sm2/server-sm2-cert.pem
  27. BIN
      certs/sm2/server-sm2-key.der
  28. 4 0
      certs/sm2/server-sm2-key.pem
  29. BIN
      certs/sm2/server-sm2-priv.der
  30. 5 0
      certs/sm2/server-sm2-priv.pem
  31. BIN
      certs/sm2/server-sm2.der
  32. 108 0
      certs/sm2/server-sm2.pem
  33. 174 3
      configure.ac
  34. 13 0
      examples/client/client.c
  35. 2 2
      mcapi/crypto.h
  36. 2 2
      src/dtls.c
  37. 21 0
      src/include.am
  38. 748 483
      src/internal.c
  39. 379 0
      src/keys.c
  40. 4 0
      src/pk.c
  41. 5 0
      src/sniffer.c
  42. 150 3
      src/ssl.c
  43. 143 7
      src/tls.c
  44. 292 47
      src/tls13.c
  45. 963 5
      tests/api.c
  46. 1 0
      tests/include.am
  47. 12 0
      tests/suites.c
  48. 189 0
      tests/test-sm2.conf
  49. 4 4
      tests/unit.h
  50. 594 0
      wolfcrypt/benchmark/benchmark.c
  51. 5 0
      wolfcrypt/benchmark/benchmark.h
  52. 127 123
      wolfcrypt/src/aes.c
  53. 297 62
      wolfcrypt/src/asn.c
  54. 228 44
      wolfcrypt/src/ecc.c
  55. 6 0
      wolfcrypt/src/error.c
  56. 561 162
      wolfcrypt/src/evp.c
  57. 109 1
      wolfcrypt/src/hash.c
  58. 74 0
      wolfcrypt/src/hmac.c
  59. 9 0
      wolfcrypt/src/integer.c
  60. 14 0
      wolfcrypt/src/kdf.c
  61. 4 4
      wolfcrypt/src/misc.c
  62. 85 27
      wolfcrypt/src/pkcs7.c
  63. 50 45
      wolfcrypt/src/port/arm/armv8-aes.c
  64. 3 0
      wolfcrypt/src/rsa.c
  65. 13 0
      wolfcrypt/src/sm2.c
  66. 13 0
      wolfcrypt/src/sm3.c
  67. 3 0
      wolfcrypt/src/sm3_asm.S
  68. 13 0
      wolfcrypt/src/sm4.c
  69. 48 31
      wolfcrypt/src/sp_int.c
  70. 27 13
      wolfcrypt/src/tfm.c
  71. 1324 615
      wolfcrypt/test/test.c
  72. 115 6
      wolfssl/internal.h
  73. 105 50
      wolfssl/openssl/evp.h
  74. 8 3
      wolfssl/ssl.h
  75. 28 18
      wolfssl/wolfcrypt/aes.h
  76. 23 4
      wolfssl/wolfcrypt/asn.h
  77. 3 0
      wolfssl/wolfcrypt/asn_public.h
  78. 3 0
      wolfssl/wolfcrypt/ecc.h
  79. 4 1
      wolfssl/wolfcrypt/error-crypt.h
  80. 15 1
      wolfssl/wolfcrypt/hash.h
  81. 3 0
      wolfssl/wolfcrypt/hmac.h
  82. 4 1
      wolfssl/wolfcrypt/include.am
  83. 2 0
      wolfssl/wolfcrypt/integer.h
  84. 7 0
      wolfssl/wolfcrypt/sm2.h
  85. 7 0
      wolfssl/wolfcrypt/sm3.h
  86. 7 0
      wolfssl/wolfcrypt/sm4.h
  87. 33 0
      wolfssl/wolfcrypt/sp.h
  88. 3 0
      wolfssl/wolfcrypt/sp_int.h
  89. 2 1
      wolfssl/wolfcrypt/tfm.h
  90. 9 1
      wolfssl/wolfcrypt/types.h

+ 1 - 0
certs/include.am

@@ -129,6 +129,7 @@ include certs/ecc/include.am
 include certs/ed25519/include.am
 include certs/ed448/include.am
 include certs/p521/include.am
+include certs/sm2/include.am
 include certs/external/include.am
 include certs/ocsp/include.am
 include certs/statickeys/include.am

BIN
certs/sm2/ca-sm2-key.der


+ 4 - 0
certs/sm2/ca-sm2-key.pem

@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFowFAYIKoEcz1UBgi0GCCqBHM9VAYItA0IABCGS98sk32RNuqtme4N1qSnn/2Rj
+ttVCgCC94uICEjuOtACVCYDLVu1Lyo1X5q4F03YnY3E5ibdp5kiArtGpSBI=
+-----END PUBLIC KEY-----

BIN
certs/sm2/ca-sm2-priv.der


+ 5 - 0
certs/sm2/ca-sm2-priv.pem

@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGIAgEAMBQGCCqBHM9VAYItBggqgRzPVQGCLQRtMGsCAQEEII+5uEAZDiE56+gI
+fP3YoQWTpDUs0YDjv35IR+QFDQlBoUQDQgAEIZL3yyTfZE26q2Z7g3WpKef/ZGO2
+1UKAIL3i4gISO460AJUJgMtW7UvKjVfmrgXTdidjcTmJt2nmSICu0alIEg==
+-----END PRIVATE KEY-----

BIN
certs/sm2/ca-sm2.der


+ 51 - 0
certs/sm2/ca-sm2.pem

@@ -0,0 +1,51 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: SM2-with-SM3
+        Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_SM2, OU = Root-SM2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com
+        Validity
+            Not Before: Feb 15 06:23:07 2023 GMT
+            Not After : Nov 11 06:23:07 2025 GMT
+        Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_sm2, OU = CA-sm2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com, UID = wolfSSL
+        Subject Public Key Info:
+            Public Key Algorithm: sm2
+                Public-Key: (256 bit)
+                pub:
+                    04:21:92:f7:cb:24:df:64:4d:ba:ab:66:7b:83:75:
+                    a9:29:e7:ff:64:63:b6:d5:42:80:20:bd:e2:e2:02:
+                    12:3b:8e:b4:00:95:09:80:cb:56:ed:4b:ca:8d:57:
+                    e6:ae:05:d3:76:27:63:71:39:89:b7:69:e6:48:80:
+                    ae:d1:a9:48:12
+                ASN1 OID: SM2
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                47:0A:48:7E:BB:02:A8:5A:26:57:2B:19:A9:7B:61:8B:7F:5D:99:6E
+            X509v3 Authority Key Identifier: 
+                34:1D:79:44:15:79:A1:B1:63:99:E3:ED:65:7C:64:89:80:FF:B8:EC
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+    Signature Algorithm: SM2-with-SM3
+    Signature Value:
+        30:45:02:20:47:4e:00:03:ab:34:a1:af:59:39:8f:60:36:bf:
+        89:88:42:41:27:c1:dd:57:c9:79:cb:1f:56:5c:16:b5:28:bd:
+        02:21:00:8b:2e:25:eb:21:9b:a9:2b:a6:6a:5b:db:a7:c7:2b:
+        11:df:73:15:ad:e4:c5:c3:c2:f3:b4:b4:67:af:d7:51:1c
+-----BEGIN CERTIFICATE-----
+MIICljCCAjygAwIBAgIBATAKBggqgRzPVQGDdTCBlTELMAkGA1UEBhMCVVMxEDAO
+BgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFDASBgNVBAoMC3dvbGZT
+U0xfU00yMREwDwYDVQQLDAhSb290LVNNMjEYMBYGA1UEAwwPd3d3LndvbGZzc2wu
+Y29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIzMDIxNTA2
+MjMwN1oXDTI1MTExMTA2MjMwN1owgawxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdN
+b250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYDVQQKDAt3b2xmU1NMX3NtMjEP
+MA0GA1UECwwGQ0Etc20yMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkq
+hkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20xFzAVBgoJkiaJk/IsZAEBDAd3b2xm
+U1NMMFowFAYIKoEcz1UBgi0GCCqBHM9VAYItA0IABCGS98sk32RNuqtme4N1qSnn
+/2RjttVCgCC94uICEjuOtACVCYDLVu1Lyo1X5q4F03YnY3E5ibdp5kiArtGpSBKj
+YzBhMB0GA1UdDgQWBBRHCkh+uwKoWiZXKxmpe2GLf12ZbjAfBgNVHSMEGDAWgBQ0
+HXlEFXmhsWOZ4+1lfGSJgP+47DAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBhjAKBggqgRzPVQGDdQNIADBFAiBHTgADqzShr1k5j2A2v4mIQkEnwd1XyXnL
+H1ZcFrUovQIhAIsuJeshm6krpmpb26fHKxHfcxWt5MXDwvO0tGev11Ec
+-----END CERTIFICATE-----

BIN
certs/sm2/client-sm2-key.der


+ 4 - 0
certs/sm2/client-sm2-key.pem

@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFowFAYIKoEcz1UBgi0GCCqBHM9VAYItA0IABDod6MtL0y4/Swc/sCH+xZ7ZyjqT
+k5V2HTDZC/VW7Rlg7QFM9mcd8ayodA2yd8hJOOT/TO+NbYf2Tsf4OXRwcLU=
+-----END PUBLIC KEY-----

BIN
certs/sm2/client-sm2-priv.der


+ 5 - 0
certs/sm2/client-sm2-priv.pem

@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGIAgEAMBQGCCqBHM9VAYItBggqgRzPVQGCLQRtMGsCAQEEINCi30l6Ld8Cyc63
+8jcCDd38CLjeFJN6UyZJ1f4C2fNxoUQDQgAEOh3oy0vTLj9LBz+wIf7FntnKOpOT
+lXYdMNkL9VbtGWDtAUz2Zx3xrKh0DbJ3yEk45P9M741th/ZOx/g5dHBwtQ==
+-----END PRIVATE KEY-----

BIN
certs/sm2/client-sm2.der


+ 63 - 0
certs/sm2/client-sm2.pem

@@ -0,0 +1,63 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            60:a0:4a:0b:36:eb:7d:e1:3f:74:29:a9:29:b4:05:6c:17:f7:a6:d4
+        Signature Algorithm: SM2-with-SM3
+        Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_sm2, OU = Client-sm2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com, UID = wolfSSL
+        Validity
+            Not Before: Feb 15 06:23:07 2023 GMT
+            Not After : Nov 11 06:23:07 2025 GMT
+        Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_sm2, OU = Client-sm2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com, UID = wolfSSL
+        Subject Public Key Info:
+            Public Key Algorithm: sm2
+                Public-Key: (256 bit)
+                pub:
+                    04:3a:1d:e8:cb:4b:d3:2e:3f:4b:07:3f:b0:21:fe:
+                    c5:9e:d9:ca:3a:93:93:95:76:1d:30:d9:0b:f5:56:
+                    ed:19:60:ed:01:4c:f6:67:1d:f1:ac:a8:74:0d:b2:
+                    77:c8:49:38:e4:ff:4c:ef:8d:6d:87:f6:4e:c7:f8:
+                    39:74:70:70:b5
+                ASN1 OID: SM2
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                E4:21:B2:C5:E5:D4:9E:82:CA:F8:67:F2:28:99:F6:85:E8:F1:55:EF
+            X509v3 Authority Key Identifier: 
+                keyid:E4:21:B2:C5:E5:D4:9E:82:CA:F8:67:F2:28:99:F6:85:E8:F1:55:EF
+                DirName:/C=US/ST=Montana/L=Bozeman/O=wolfSSL_sm2/OU=Client-sm2/CN=www.wolfssl.com/emailAddress=info@wolfssl.com/UID=wolfSSL
+                serial:60:A0:4A:0B:36:EB:7D:E1:3F:74:29:A9:29:B4:05:6C:17:F7:A6:D4
+            X509v3 Basic Constraints: 
+                CA:TRUE
+            X509v3 Subject Alternative Name: 
+                DNS:example.com, IP Address:127.0.0.1
+            X509v3 Extended Key Usage: 
+                TLS Web Server Authentication, TLS Web Client Authentication
+    Signature Algorithm: SM2-with-SM3
+    Signature Value:
+        30:46:02:21:00:8f:b2:b5:95:8f:79:f6:5e:75:e5:c5:e9:9a:
+        12:d2:0f:78:9f:c0:1d:8d:1c:be:6b:0c:f1:f5:57:60:db:91:
+        4f:02:21:00:87:5e:7d:e4:d6:3a:bb:7b:98:27:85:de:7a:f0:
+        21:e2:66:a1:9f:26:e0:dd:86:23:b4:c8:c0:46:5a:f2:49:8d
+-----BEGIN CERTIFICATE-----
+MIIDyTCCA26gAwIBAgIUYKBKCzbrfeE/dCmpKbQFbBf3ptQwCgYIKoEcz1UBg3Uw
+gbAxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3pl
+bWFuMRQwEgYDVQQKDAt3b2xmU1NMX3NtMjETMBEGA1UECwwKQ2xpZW50LXNtMjEY
+MBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv
+bGZzc2wuY29tMRcwFQYKCZImiZPyLGQBAQwHd29sZlNTTDAeFw0yMzAyMTUwNjIz
+MDdaFw0yNTExMTEwNjIzMDdaMIGwMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9u
+dGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIGA1UECgwLd29sZlNTTF9zbTIxEzAR
+BgNVBAsMCkNsaWVudC1zbTIxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0G
+CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTEXMBUGCgmSJomT8ixkAQEMB3dv
+bGZTU0wwWjAUBggqgRzPVQGCLQYIKoEcz1UBgi0DQgAEOh3oy0vTLj9LBz+wIf7F
+ntnKOpOTlXYdMNkL9VbtGWDtAUz2Zx3xrKh0DbJ3yEk45P9M741th/ZOx/g5dHBw
+taOCAWEwggFdMB0GA1UdDgQWBBTkIbLF5dSegsr4Z/IomfaF6PFV7zCB8AYDVR0j
+BIHoMIHlgBTkIbLF5dSegsr4Z/IomfaF6PFV76GBtqSBszCBsDELMAkGA1UEBhMC
+VVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFDASBgNVBAoM
+C3dvbGZTU0xfc20yMRMwEQYDVQQLDApDbGllbnQtc20yMRgwFgYDVQQDDA93d3cu
+d29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20xFzAV
+BgoJkiaJk/IsZAEBDAd3b2xmU1NMghRgoEoLNut94T90KakptAVsF/em1DAMBgNV
+HRMEBTADAQH/MBwGA1UdEQQVMBOCC2V4YW1wbGUuY29thwR/AAABMB0GA1UdJQQW
+MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAKBggqgRzPVQGDdQNJADBGAiEAj7K1lY95
+9l515cXpmhLSD3ifwB2NHL5rDPH1V2DbkU8CIQCHXn3k1jq7e5gnhd568CHiZqGf
+JuDdhiO0yMBGWvJJjQ==
+-----END CERTIFICATE-----

+ 105 - 0
certs/sm2/gen-sm2-certs.sh

@@ -0,0 +1,105 @@
+#!/bin/bash
+
+check_result(){
+    if [ $1 -ne 0 ]; then
+        echo "Failed at \"$2\", Abort"
+        exit 1
+    else
+        echo "Step Succeeded!"
+    fi
+}
+
+openssl pkey -in root-sm2-priv.pem -noout >/dev/null 2>&1
+if [ $? -ne 0 ]; then
+    echo "OpenSSL does not support SM2"
+    echo "Skipping SM2 certificate renewal"
+    exit 0
+fi
+
+############################################################
+###### update the self-signed root-sm2.pem #############
+############################################################
+echo "Updating root-sm2.pem"
+echo ""
+#pipe the following arguments to openssl req...
+echo -e "US\\nMontana\\nBozeman\\nwolfSSL_SM2\\nRoot-SM2\\nwww.wolfssl.com\\ninfo@wolfssl.com\\n.\\n.\\n" | \
+openssl req -new -key root-sm2-priv.pem -config ../renewcerts/wolfssl.cnf -nodes -out root-sm2.csr
+check_result $? "Generate request"
+
+openssl x509 -req -in root-sm2.csr -days 1000 -extfile ../renewcerts/wolfssl.cnf -extensions ca_ecc_cert -signkey root-sm2-priv.pem -out root-sm2.pem
+check_result $? "Generate certificate"
+rm root-sm2.csr
+
+openssl x509 -in root-sm2.pem -outform DER > root-sm2.der
+check_result $? "Convert to DER"
+openssl x509 -in root-sm2.pem -text > tmp.pem
+check_result $? "Add text"
+mv tmp.pem root-sm2.pem
+echo "End of section"
+echo "---------------------------------------------------------------------"
+
+############################################################
+###### update ca-sm2.pem signed by root ################
+############################################################
+echo "Updating ca-sm2.pem"
+echo ""
+#pipe the following arguments to openssl req...
+echo -e "US\\nMontana\\nBozeman\\nwolfSSL_sm2\\nCA-sm2\\nwww.wolfssl.com\\ninfo@wolfssl.com\\n\\n\\n\\n" | openssl req -new -key ca-sm2-priv.pem -config ../renewcerts/wolfssl.cnf -nodes -out ca-sm2.csr
+check_result $? "Generate request"
+
+openssl x509 -req -in ca-sm2.csr -days 1000 -extfile ../renewcerts/wolfssl.cnf -extensions ca_ecc_cert -CA root-sm2.pem -CAkey root-sm2-priv.pem -set_serial 01 -out ca-sm2.pem
+check_result $? "Generate certificate"
+rm ca-sm2.csr
+
+openssl x509 -in ca-sm2.pem -outform DER > ca-sm2.der
+check_result $? "Convert to DER"
+openssl x509 -in ca-sm2.pem -text > tmp.pem
+check_result $? "Add text"
+mv tmp.pem ca-sm2.pem
+echo "End of section"
+echo "---------------------------------------------------------------------"
+
+############################################################
+###### update server-sm2.pem signed by ca ##############
+############################################################
+echo "Updating server-sm2.pem"
+echo ""
+#pipe the following arguments to openssl req...
+echo -e "US\\nMontana\\nBozeman\\nwolfSSL_sm2\\nServer-sm2\\nwww.wolfssl.com\\ninfo@wolfssl.com\\n\\n\\n\\n" | openssl req -new -key server-sm2-priv.pem -config ../renewcerts/wolfssl.cnf -nodes -out server-sm2.csr
+check_result $? "Generate request"
+
+openssl x509 -req -in server-sm2.csr -days 1000 -extfile ../renewcerts/wolfssl.cnf -extensions server_ecc -CA ca-sm2.pem -CAkey ca-sm2-priv.pem -set_serial 01 -out server-sm2-cert.pem
+check_result $? "Generate certificate"
+rm server-sm2.csr
+
+openssl x509 -in server-sm2-cert.pem -outform DER > server-sm2.der
+check_result $? "Convert to DER"
+openssl x509 -in server-sm2-cert.pem -text > tmp.pem
+check_result $? "Add text"
+mv tmp.pem server-sm2-cert.pem
+cat server-sm2-cert.pem ca-sm2.pem > server-sm2.pem
+check_result $? "Add CA into server cert"
+echo "End of section"
+echo "---------------------------------------------------------------------"
+
+############################################################
+###### update the self-signed client-sm2.pem ###########
+############################################################
+echo "Updating client-sm2.pem"
+echo ""
+#pipe the following arguments to openssl req...
+echo -e "US\\nMontana\\nBozeman\\nwolfSSL_sm2\\nClient-sm2\\nwww.wolfssl.com\\ninfo@wolfssl.com\\n\\n\\n\\n" | openssl req -new -key client-sm2-priv.pem -config ../renewcerts/wolfssl.cnf -nodes -out client-sm2.csr
+check_result $? "Generate request"
+
+openssl x509 -req -in client-sm2.csr -days 1000 -extfile ../renewcerts/wolfssl.cnf -extensions wolfssl_opts -signkey client-sm2-priv.pem -out client-sm2.pem
+check_result $? "Generate certificate"
+rm client-sm2.csr
+
+openssl x509 -in client-sm2.pem -outform DER > client-sm2.der
+check_result $? "Convert to DER"
+openssl x509 -in client-sm2.pem -text > tmp.pem
+check_result $? "Add text"
+mv tmp.pem client-sm2.pem
+echo "End of section"
+echo "---------------------------------------------------------------------"
+

+ 16 - 0
certs/sm2/gen-sm2-keys.sh

@@ -0,0 +1,16 @@
+#!/bin/sh
+
+for key in root ca server client
+do
+
+  openssl genpkey -algorithm sm2 > ${key}-sm2-priv.pem
+
+  openssl pkey -in ${key}-sm2-priv.pem -outform DER -out ${key}-sm2-priv.der
+
+  openssl pkey -in ${key}-sm2-priv.pem -outform PEM -pubout -out ${key}-sm2-key.pem
+
+  openssl pkey -in ${key}-sm2-priv.pem -outform DER -pubout -out ${key}-sm2-key.der
+
+done
+
+

+ 37 - 0
certs/sm2/include.am

@@ -0,0 +1,37 @@
+# vim:ft=automake
+# All paths should be given relative to the root
+#
+
+EXTRA_DIST += \
+         certs/sm2/ca-sm2.der \
+         certs/sm2/ca-sm2.pem \
+         certs/sm2/ca-sm2-key.der \
+         certs/sm2/ca-sm2-key.pem \
+         certs/sm2/ca-sm2-priv.der \
+         certs/sm2/ca-sm2-priv.pem \
+         certs/sm2/client-sm2.der \
+         certs/sm2/client-sm2.pem \
+         certs/sm2/client-sm2-key.der \
+         certs/sm2/client-sm2-key.pem \
+         certs/sm2/client-sm2-priv.der \
+         certs/sm2/client-sm2-priv.pem \
+         certs/sm2/root-sm2.der \
+         certs/sm2/root-sm2.pem \
+         certs/sm2/root-sm2-key.der \
+         certs/sm2/root-sm2-key.pem \
+         certs/sm2/root-sm2-priv.der \
+         certs/sm2/root-sm2-priv.pem \
+         certs/sm2/server-sm2.der \
+         certs/sm2/server-sm2.pem \
+         certs/sm2/server-sm2-cert.pem \
+         certs/sm2/server-sm2-key.der \
+         certs/sm2/server-sm2-key.pem \
+         certs/sm2/server-sm2-priv.der \
+         certs/sm2/server-sm2-priv.pem \
+         certs/sm2/self-sm2-cert.pem \
+         certs/sm2/self-sm2-key.pem \
+         certs/sm2/self-sm2-priv.pem
+
+EXTRA_DIST += \
+         certs/sm2/gen-sm2-certs.sh \
+         certs/sm2/gen-sm2-keys.sh

BIN
certs/sm2/root-sm2-key.der


+ 4 - 0
certs/sm2/root-sm2-key.pem

@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFowFAYIKoEcz1UBgi0GCCqBHM9VAYItA0IABLucdYz3F/hIq/f22w2ajZ/C0UeX
+lQtO5lfsxfhXVHE5PHnhQD+2Uel8x9ot79LoeYF7q6NfaypslxpejtnQzAQ=
+-----END PUBLIC KEY-----

BIN
certs/sm2/root-sm2-priv.der


+ 5 - 0
certs/sm2/root-sm2-priv.pem

@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGIAgEAMBQGCCqBHM9VAYItBggqgRzPVQGCLQRtMGsCAQEEIMZrNEwzN1tkFlp/
+BPn8hzDRFbpYeO4HmCAm4QaNUYoooUQDQgAEu5x1jPcX+Eir9/bbDZqNn8LRR5eV
+C07mV+zF+FdUcTk8eeFAP7ZR6XzH2i3v0uh5gXuro19rKmyXGl6O2dDMBA==
+-----END PRIVATE KEY-----

BIN
certs/sm2/root-sm2.der


+ 52 - 0
certs/sm2/root-sm2.pem

@@ -0,0 +1,52 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            74:9c:dd:a4:b2:67:26:57:29:fb:e9:13:54:e0:34:08:03:2b:70:a9
+        Signature Algorithm: SM2-with-SM3
+        Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_SM2, OU = Root-SM2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com
+        Validity
+            Not Before: Feb 15 06:23:07 2023 GMT
+            Not After : Nov 11 06:23:07 2025 GMT
+        Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_SM2, OU = Root-SM2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com
+        Subject Public Key Info:
+            Public Key Algorithm: sm2
+                Public-Key: (256 bit)
+                pub:
+                    04:bb:9c:75:8c:f7:17:f8:48:ab:f7:f6:db:0d:9a:
+                    8d:9f:c2:d1:47:97:95:0b:4e:e6:57:ec:c5:f8:57:
+                    54:71:39:3c:79:e1:40:3f:b6:51:e9:7c:c7:da:2d:
+                    ef:d2:e8:79:81:7b:ab:a3:5f:6b:2a:6c:97:1a:5e:
+                    8e:d9:d0:cc:04
+                ASN1 OID: SM2
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                34:1D:79:44:15:79:A1:B1:63:99:E3:ED:65:7C:64:89:80:FF:B8:EC
+            X509v3 Authority Key Identifier: 
+                34:1D:79:44:15:79:A1:B1:63:99:E3:ED:65:7C:64:89:80:FF:B8:EC
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+    Signature Algorithm: SM2-with-SM3
+    Signature Value:
+        30:44:02:20:03:27:29:f0:ef:78:26:a1:1a:6a:1e:88:81:e7:
+        83:72:5f:3e:e6:08:e8:14:68:bf:4b:0f:68:52:92:aa:8f:a1:
+        02:20:0b:fe:1b:14:ba:51:82:65:06:bb:22:d8:1a:a7:9f:54:
+        62:eb:8d:b2:d5:13:b3:b8:a2:f3:14:44:b2:a0:21:d0
+-----BEGIN CERTIFICATE-----
+MIICkTCCAjigAwIBAgIUdJzdpLJnJlcp++kTVOA0CAMrcKkwCgYIKoEcz1UBg3Uw
+gZUxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3pl
+bWFuMRQwEgYDVQQKDAt3b2xmU1NMX1NNMjERMA8GA1UECwwIUm9vdC1TTTIxGDAW
+BgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm
+c3NsLmNvbTAeFw0yMzAyMTUwNjIzMDdaFw0yNTExMTEwNjIzMDdaMIGVMQswCQYD
+VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEUMBIG
+A1UECgwLd29sZlNTTF9TTTIxETAPBgNVBAsMCFJvb3QtU00yMRgwFgYDVQQDDA93
+d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20w
+WjAUBggqgRzPVQGCLQYIKoEcz1UBgi0DQgAEu5x1jPcX+Eir9/bbDZqNn8LRR5eV
+C07mV+zF+FdUcTk8eeFAP7ZR6XzH2i3v0uh5gXuro19rKmyXGl6O2dDMBKNjMGEw
+HQYDVR0OBBYEFDQdeUQVeaGxY5nj7WV8ZImA/7jsMB8GA1UdIwQYMBaAFDQdeUQV
+eaGxY5nj7WV8ZImA/7jsMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGG
+MAoGCCqBHM9VAYN1A0cAMEQCIAMnKfDveCahGmoeiIHng3JfPuYI6BRov0sPaFKS
+qo+hAiAL/hsUulGCZQa7Itgap59UYuuNstUTs7ii8xREsqAh0A==
+-----END CERTIFICATE-----

+ 13 - 0
certs/sm2/self-sm2-cert.pem

@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIICATCCAaSgAwIBAgIMGSJGj94zOf2VJ8V7MAwGCCqBHM9VAYN1BQAwWTELMAkG
+A1UEBhMCQVUxDDAKBgNVBAgTA1FMRDEQMA4GA1UEChMHd29sZlNTTDEQMA4GA1UE
+CxMHVGVzdGluZzEYMBYGA1UEAxMPd29sZnNzbC1kZXYtc20yMB4XDTIzMDIxNDAz
+NDYyMFoXDTI0MDIxMzE3NDYyMFowWTELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM
+RDEQMA4GA1UEChMHd29sZlNTTDEQMA4GA1UECxMHVGVzdGluZzEYMBYGA1UEAxMP
+d29sZnNzbC1kZXYtc20yMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE2MSh8QuL
+jcR93NRluaVVTvusM6ubQ5RMSEAbM9kbzDHBglY/sMBrlUBR/YgCAbGwlGwG66fa
+ju5wtuW7tB7ntKNQME4wDgYDVR0PAQH/BAQDAgKEMA8GA1UdEwEB/wQFMAMBAf8w
+KwYDVR0jBCQwIoAg58sNBkW7bGpWBXDo6zbHrieKTvcwnKWSidVvnSzhPkIwDAYI
+KoEcz1UBg3UFAANJADBGAiEAm/cByfeknMZJ4NF/a0gu/RqeG/tFouvXKKtbYzqN
+8/8CIQCJV/RNKQkp8zKZU+sMOGvGk7c3otMNy4B4OOJorD00rw==
+-----END CERTIFICATE-----

+ 4 - 0
certs/sm2/self-sm2-key.pem

@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE2MSh8QuLjcR93NRluaVVTvusM6ub
+Q5RMSEAbM9kbzDHBglY/sMBrlUBR/YgCAbGwlGwG66faju5wtuW7tB7ntA==
+-----END PUBLIC KEY-----

+ 6 - 0
certs/sm2/self-sm2-priv.pem

@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg0JwoWhXWJQ22X9Gh
+AW60DtA2+hX8qQTlF6HQLynW/mqgCgYIKoEcz1UBgi2hRANCAATYxKHxC4uNxH3c
+1GW5pVVO+6wzq5tDlExIQBsz2RvMMcGCVj+wwGuVQFH9iAIBsbCUbAbrp9qO7nC2
+5bu0Hue0
+-----END PRIVATE KEY-----

+ 57 - 0
certs/sm2/server-sm2-cert.pem

@@ -0,0 +1,57 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: SM2-with-SM3
+        Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_sm2, OU = CA-sm2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com, UID = wolfSSL
+        Validity
+            Not Before: Feb 15 06:23:07 2023 GMT
+            Not After : Nov 11 06:23:07 2025 GMT
+        Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_sm2, OU = Server-sm2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com, UID = wolfSSL
+        Subject Public Key Info:
+            Public Key Algorithm: sm2
+                Public-Key: (256 bit)
+                pub:
+                    04:94:70:2b:46:e4:5e:0f:41:fb:8f:2d:34:0a:41:
+                    40:19:5e:fb:d4:1d:11:ac:fa:f5:93:37:c6:fa:87:
+                    08:f7:16:1f:2c:ce:30:40:9d:4f:a6:2a:0a:a1:d6:
+                    95:33:c3:a6:03:98:e6:8d:05:34:b0:97:0c:de:a4:
+                    c7:cf:53:8f:d1
+                ASN1 OID: SM2
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                67:AE:60:FF:7E:1B:0F:95:AE:1F:82:59:F2:6C:56:2D:93:EF:17:32
+            X509v3 Authority Key Identifier: 
+                47:0A:48:7E:BB:02:A8:5A:26:57:2B:19:A9:7B:61:8B:7F:5D:99:6E
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Key Usage: critical
+                Digital Signature, Key Encipherment, Key Agreement
+            X509v3 Extended Key Usage: 
+                TLS Web Server Authentication
+            Netscape Cert Type: 
+                SSL Server
+    Signature Algorithm: SM2-with-SM3
+    Signature Value:
+        30:45:02:20:1b:ca:94:28:7f:f6:b2:0d:31:43:50:e1:d5:34:
+        17:dd:af:3a:de:81:06:67:9a:b3:06:22:7e:64:ec:fd:0e:b9:
+        02:21:00:a1:48:a8:32:d1:05:09:6b:1c:eb:89:12:66:d8:38:
+        a1:c4:5c:89:09:0f:fd:e9:c0:3b:1d:fb:cd:b5:4c:31:68
+-----BEGIN CERTIFICATE-----
+MIIC2DCCAn6gAwIBAgIBATAKBggqgRzPVQGDdTCBrDELMAkGA1UEBhMCVVMxEDAO
+BgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFDASBgNVBAoMC3dvbGZT
+U0xfc20yMQ8wDQYDVQQLDAZDQS1zbTIxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNv
+bTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTEXMBUGCgmSJomT8ixk
+AQEMB3dvbGZTU0wwHhcNMjMwMjE1MDYyMzA3WhcNMjUxMTExMDYyMzA3WjCBsDEL
+MAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4x
+FDASBgNVBAoMC3dvbGZTU0xfc20yMRMwEQYDVQQLDApTZXJ2ZXItc20yMRgwFgYD
+VQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz
+bC5jb20xFzAVBgoJkiaJk/IsZAEBDAd3b2xmU1NMMFowFAYIKoEcz1UBgi0GCCqB
+HM9VAYItA0IABJRwK0bkXg9B+48tNApBQBle+9QdEaz69ZM3xvqHCPcWHyzOMECd
+T6YqCqHWlTPDpgOY5o0FNLCXDN6kx89Tj9GjgYkwgYYwHQYDVR0OBBYEFGeuYP9+
+Gw+Vrh+CWfJsVi2T7xcyMB8GA1UdIwQYMBaAFEcKSH67AqhaJlcrGal7YYt/XZlu
+MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUF
+BwMBMBEGCWCGSAGG+EIBAQQEAwIGQDAKBggqgRzPVQGDdQNIADBFAiAbypQof/ay
+DTFDUOHVNBfdrzregQZnmrMGIn5k7P0OuQIhAKFIqDLRBQlrHOuJEmbYOKHEXIkJ
+D/3pwDsd+821TDFo
+-----END CERTIFICATE-----

BIN
certs/sm2/server-sm2-key.der


+ 4 - 0
certs/sm2/server-sm2-key.pem

@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFowFAYIKoEcz1UBgi0GCCqBHM9VAYItA0IABJRwK0bkXg9B+48tNApBQBle+9Qd
+Eaz69ZM3xvqHCPcWHyzOMECdT6YqCqHWlTPDpgOY5o0FNLCXDN6kx89Tj9E=
+-----END PUBLIC KEY-----

BIN
certs/sm2/server-sm2-priv.der


+ 5 - 0
certs/sm2/server-sm2-priv.pem

@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGIAgEAMBQGCCqBHM9VAYItBggqgRzPVQGCLQRtMGsCAQEEINczwaFxmNpDgQ1w
+Qohj0Ex+D4qbLdoVqg5a+u13OkOooUQDQgAElHArRuReD0H7jy00CkFAGV771B0R
+rPr1kzfG+ocI9xYfLM4wQJ1PpioKodaVM8OmA5jmjQU0sJcM3qTHz1OP0Q==
+-----END PRIVATE KEY-----

BIN
certs/sm2/server-sm2.der


+ 108 - 0
certs/sm2/server-sm2.pem

@@ -0,0 +1,108 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: SM2-with-SM3
+        Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_sm2, OU = CA-sm2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com, UID = wolfSSL
+        Validity
+            Not Before: Feb 15 06:23:07 2023 GMT
+            Not After : Nov 11 06:23:07 2025 GMT
+        Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_sm2, OU = Server-sm2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com, UID = wolfSSL
+        Subject Public Key Info:
+            Public Key Algorithm: sm2
+                Public-Key: (256 bit)
+                pub:
+                    04:94:70:2b:46:e4:5e:0f:41:fb:8f:2d:34:0a:41:
+                    40:19:5e:fb:d4:1d:11:ac:fa:f5:93:37:c6:fa:87:
+                    08:f7:16:1f:2c:ce:30:40:9d:4f:a6:2a:0a:a1:d6:
+                    95:33:c3:a6:03:98:e6:8d:05:34:b0:97:0c:de:a4:
+                    c7:cf:53:8f:d1
+                ASN1 OID: SM2
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                67:AE:60:FF:7E:1B:0F:95:AE:1F:82:59:F2:6C:56:2D:93:EF:17:32
+            X509v3 Authority Key Identifier: 
+                47:0A:48:7E:BB:02:A8:5A:26:57:2B:19:A9:7B:61:8B:7F:5D:99:6E
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Key Usage: critical
+                Digital Signature, Key Encipherment, Key Agreement
+            X509v3 Extended Key Usage: 
+                TLS Web Server Authentication
+            Netscape Cert Type: 
+                SSL Server
+    Signature Algorithm: SM2-with-SM3
+    Signature Value:
+        30:45:02:20:1b:ca:94:28:7f:f6:b2:0d:31:43:50:e1:d5:34:
+        17:dd:af:3a:de:81:06:67:9a:b3:06:22:7e:64:ec:fd:0e:b9:
+        02:21:00:a1:48:a8:32:d1:05:09:6b:1c:eb:89:12:66:d8:38:
+        a1:c4:5c:89:09:0f:fd:e9:c0:3b:1d:fb:cd:b5:4c:31:68
+-----BEGIN CERTIFICATE-----
+MIIC2DCCAn6gAwIBAgIBATAKBggqgRzPVQGDdTCBrDELMAkGA1UEBhMCVVMxEDAO
+BgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFDASBgNVBAoMC3dvbGZT
+U0xfc20yMQ8wDQYDVQQLDAZDQS1zbTIxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNv
+bTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTEXMBUGCgmSJomT8ixk
+AQEMB3dvbGZTU0wwHhcNMjMwMjE1MDYyMzA3WhcNMjUxMTExMDYyMzA3WjCBsDEL
+MAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4x
+FDASBgNVBAoMC3dvbGZTU0xfc20yMRMwEQYDVQQLDApTZXJ2ZXItc20yMRgwFgYD
+VQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz
+bC5jb20xFzAVBgoJkiaJk/IsZAEBDAd3b2xmU1NMMFowFAYIKoEcz1UBgi0GCCqB
+HM9VAYItA0IABJRwK0bkXg9B+48tNApBQBle+9QdEaz69ZM3xvqHCPcWHyzOMECd
+T6YqCqHWlTPDpgOY5o0FNLCXDN6kx89Tj9GjgYkwgYYwHQYDVR0OBBYEFGeuYP9+
+Gw+Vrh+CWfJsVi2T7xcyMB8GA1UdIwQYMBaAFEcKSH67AqhaJlcrGal7YYt/XZlu
+MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgOoMBMGA1UdJQQMMAoGCCsGAQUF
+BwMBMBEGCWCGSAGG+EIBAQQEAwIGQDAKBggqgRzPVQGDdQNIADBFAiAbypQof/ay
+DTFDUOHVNBfdrzregQZnmrMGIn5k7P0OuQIhAKFIqDLRBQlrHOuJEmbYOKHEXIkJ
+D/3pwDsd+821TDFo
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: SM2-with-SM3
+        Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_SM2, OU = Root-SM2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com
+        Validity
+            Not Before: Feb 15 06:23:07 2023 GMT
+            Not After : Nov 11 06:23:07 2025 GMT
+        Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_sm2, OU = CA-sm2, CN = www.wolfssl.com, emailAddress = info@wolfssl.com, UID = wolfSSL
+        Subject Public Key Info:
+            Public Key Algorithm: sm2
+                Public-Key: (256 bit)
+                pub:
+                    04:21:92:f7:cb:24:df:64:4d:ba:ab:66:7b:83:75:
+                    a9:29:e7:ff:64:63:b6:d5:42:80:20:bd:e2:e2:02:
+                    12:3b:8e:b4:00:95:09:80:cb:56:ed:4b:ca:8d:57:
+                    e6:ae:05:d3:76:27:63:71:39:89:b7:69:e6:48:80:
+                    ae:d1:a9:48:12
+                ASN1 OID: SM2
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                47:0A:48:7E:BB:02:A8:5A:26:57:2B:19:A9:7B:61:8B:7F:5D:99:6E
+            X509v3 Authority Key Identifier: 
+                34:1D:79:44:15:79:A1:B1:63:99:E3:ED:65:7C:64:89:80:FF:B8:EC
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+    Signature Algorithm: SM2-with-SM3
+    Signature Value:
+        30:45:02:20:47:4e:00:03:ab:34:a1:af:59:39:8f:60:36:bf:
+        89:88:42:41:27:c1:dd:57:c9:79:cb:1f:56:5c:16:b5:28:bd:
+        02:21:00:8b:2e:25:eb:21:9b:a9:2b:a6:6a:5b:db:a7:c7:2b:
+        11:df:73:15:ad:e4:c5:c3:c2:f3:b4:b4:67:af:d7:51:1c
+-----BEGIN CERTIFICATE-----
+MIICljCCAjygAwIBAgIBATAKBggqgRzPVQGDdTCBlTELMAkGA1UEBhMCVVMxEDAO
+BgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFDASBgNVBAoMC3dvbGZT
+U0xfU00yMREwDwYDVQQLDAhSb290LVNNMjEYMBYGA1UEAwwPd3d3LndvbGZzc2wu
+Y29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIzMDIxNTA2
+MjMwN1oXDTI1MTExMTA2MjMwN1owgawxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdN
+b250YW5hMRAwDgYDVQQHDAdCb3plbWFuMRQwEgYDVQQKDAt3b2xmU1NMX3NtMjEP
+MA0GA1UECwwGQ0Etc20yMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkq
+hkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20xFzAVBgoJkiaJk/IsZAEBDAd3b2xm
+U1NMMFowFAYIKoEcz1UBgi0GCCqBHM9VAYItA0IABCGS98sk32RNuqtme4N1qSnn
+/2RjttVCgCC94uICEjuOtACVCYDLVu1Lyo1X5q4F03YnY3E5ibdp5kiArtGpSBKj
+YzBhMB0GA1UdDgQWBBRHCkh+uwKoWiZXKxmpe2GLf12ZbjAfBgNVHSMEGDAWgBQ0
+HXlEFXmhsWOZ4+1lfGSJgP+47DAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBhjAKBggqgRzPVQGDdQNIADBFAiBHTgADqzShr1k5j2A2v4mIQkEnwd1XyXnL
+H1ZcFrUovQIhAIsuJeshm6krpmpb26fHKxHfcxWt5MXDwvO0tGev11Ec
+-----END CERTIFICATE-----

+ 174 - 3
configure.ac

@@ -184,7 +184,6 @@ AS_IF([test "$ax_enable_debug" = "yes"],
       [AM_CCASFLAGS="$DEBUG_CFLAGS $AM_CCASFLAGS"],
       [AM_CCASFLAGS="$AM_CCASFLAGS -DNDEBUG"])
 
-
 # Start without certificates enabled and enable if a certificate algorithm is
 # enabled
 ENABLED_CERTS="no"
@@ -2255,8 +2254,97 @@ then
 fi
 
 
+# SM4
+ENABLED_SM4="no"
+AC_ARG_ENABLE([sm4-ecb],
+    [AS_HELP_STRING([--enable-sm4-ecb],[Enable wolfSSL SM4-ECB support (default: disabled)])],
+    [ ENABLED_SM4_ECB=$enableval ],
+    [ ENABLED_SM4_ECB=no ]
+    )
+
+if test "$ENABLED_SM4_ECB" = "small"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM4_SMALL"
+fi
+if test "$ENABLED_SM4_ECB" != "no"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM4_ECB"
+    ENABLED_SM4="yes"
+fi
+
+AC_ARG_ENABLE([sm4-cbc],
+    [AS_HELP_STRING([--enable-sm4-cbc],[Enable wolfSSL SM4-CBC support (default: disabled)])],
+    [ ENABLED_SM4_CBC=$enableval ],
+    [ ENABLED_SM4_CBC=no ]
+    )
+
+if test "$ENABLED_SM4_CBC" = "small"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM4_SMALL"
+fi
+if test "$ENABLED_SM4_CBC" != "no"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM4_CBC"
+    ENABLED_SM4="yes"
+fi
+
+AC_ARG_ENABLE([sm4-ctr],
+    [AS_HELP_STRING([--enable-sm4-ctr],[Enable wolfSSL SM4-CTR support (default: disabled)])],
+    [ ENABLED_SM4_CTR=$enableval ],
+    [ ENABLED_SM4_CTR=no ]
+    )
+
+if test "$ENABLED_SM4_CTR" = "small"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM4_SMALL"
+fi
+if test "$ENABLED_SM4_CTR" != "no"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM4_CTR"
+    ENABLED_SM4="yes"
+fi
+
+AC_ARG_ENABLE([sm4-gcm],
+    [AS_HELP_STRING([--enable-sm4-gcm],[Enable wolfSSL SM4-GCM support (default: enabled)])],
+    [ ENABLED_SM4_GCM=$enableval ],
+    [ ENABLED_SM4_GCM=no ]
+    )
+
+if test "$ENABLED_SM4_GCM" = "small"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM4_SMALL"
+fi
+if test "$ENABLED_SM4_GCM" != "no"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM4_GCM"
+    ENABLED_SM4="yes"
+fi
+
+AC_ARG_ENABLE([sm4-ccm],
+    [AS_HELP_STRING([--enable-sm4-ccm],[Enable wolfSSL SM4-CCM support (default: enabled)])],
+    [ ENABLED_SM4_CCM=$enableval ],
+    [ ENABLED_SM4_CCM=no ]
+    )
+
+if test "$ENABLED_SM4_CCM" = "small"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM4_SMALL"
+fi
+if test "$ENABLED_SM4_CCM" != "no"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM4_CCM"
+    ENABLED_SM4="yes"
+fi
+
+if test "$ENABLED_SM4" = "yes"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM4"
+fi
+
+
 ENABLED_ARMASM_INLINE="no"
 ENABLED_ARMASM_SHA3="no"
+ENABLED_ARMASM_CRYPTO_SM4="no"
 # ARM Assembly
 # Both SHA3 and SHA512 instructions available with ARMV8.2-a
 AC_ARG_ENABLE([armasm],
@@ -2284,6 +2372,33 @@ then
                 break;;
             esac
             ENABLED_ARMASM_SHA3=yes
+            ENABLED_ARMASM_PLUS=yes
+            ;;
+        sm4)
+            case $host_cpu in
+            *aarch64*)
+                ;;
+            *)
+                AC_MSG_ERROR([SM4 instructions only available on Aarch64 CPU.])
+                break;;
+            esac
+            ENABLED_ARMASM_SM4=yes
+            # gcc requires -march=...+sm4 to enable SM4 instructions
+            ENABLED_ARMASM_CRYPTO_SM4=yes
+            ENABLED_ARMASM_PLUS=yes
+            ;;
+        sm3)
+            case $host_cpu in
+            *aarch64*)
+                ;;
+            *)
+                AC_MSG_ERROR([SM3 instructions only available on Aarch64 CPU.])
+                break;;
+            esac
+            ENABLED_ARMASM_SM3=yes
+            # gcc requires -march=...+sm4 to enable SM3 instructions
+            ENABLED_ARMASM_CRYPTO_SM4=yes
+            ENABLED_ARMASM_PLUS=yes
             ;;
         *)
             AC_MSG_ERROR([Invalid choice of ARM asm inclusions (yes, sha512-crypto, sha3-crypto): $ENABLED_ARMASM.])
@@ -2308,8 +2423,14 @@ then
                 ;;
             *)
                 # +crypto needed for hardware acceleration
-                if test "$ENABLED_ARMASM_SHA3" = "yes"; then
-                    AM_CPPFLAGS="$AM_CPPFLAGS -march=armv8.2-a+crypto+sha3"
+                if test "$ENABLED_ARMASM_PLUS" = "yes"; then
+                    AM_CPPFLAGS="$AM_CPPFLAGS -march=armv8.2-a+crypto"
+                    if test "$ENABLED_ARMASM_SHA3" = "yes"; then
+                        AM_CPPFLAGS="$AM_CPPFLAGS+sha3"
+                    fi
+                    if test "$ENABLED_ARMASM_CRYPTO_SM4" = "yes"; then
+                        AM_CPPFLAGS="$AM_CPPFLAGS+sm4"
+                    fi
                 else
                     AM_CPPFLAGS="$AM_CPPFLAGS -mcpu=generic+crypto"
                 fi
@@ -2359,6 +2480,12 @@ if test "$ENABLED_ARMASM_SHA3" = "yes"; then
     AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ARMASM_CRYPTO_SHA512 -DWOLFSSL_ARMASM_CRYPTO_SHA3"
     AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_ARMASM_CRYPTO_SHA512 -DWOLFSSL_ARMASM_CRYPTO_SHA3"
 fi
+if test "$ENABLED_ARMASM_SM3" = "yes"; then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ARMASM_CRYPTO_SM3"
+fi
+if test "$ENABLED_ARMASM_SM4" = "yes"; then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ARMASM_CRYPTO_SM4"
+fi
 
 # Xilinx hardened crypto
 AC_ARG_ENABLE([xilinx],
@@ -2957,6 +3084,22 @@ then
 fi
 
 
+# SM3
+AC_ARG_ENABLE([sm3],
+    [AS_HELP_STRING([--enable-sm3],[Enable wolfSSL SM3 support (default: disabled)])],
+    [ ENABLED_SM3=$enableval ],
+    [ ENABLED_SM3=no ]
+    )
+
+if test "$ENABLED_SM3" = "small"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM3_SMALL"
+fi
+if test "$ENABLED_SM3" != "no"
+then
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM3"
+fi
+
 # SESSION CERTS
 AC_ARG_ENABLE([sessioncerts],
     [AS_HELP_STRING([--enable-sessioncerts],[Enable session cert storing (default: disabled)])],
@@ -3170,6 +3313,24 @@ then
 fi
 
 
+# SM2
+AC_ARG_ENABLE([sm2],
+    [AS_HELP_STRING([--enable-sm2],[Enable wolfSSL SM2 support (default: disabled)])],
+    [ ENABLED_SM2=$enableval ],
+    [ ENABLED_SM2=no ]
+    )
+
+if test "$ENABLED_SM2" = "yes"
+then
+    if test "$ENABLED_ECC" = "no"
+    then
+        AC_MSG_ERROR([Cannot enable SM2 without enabling ecc.])
+    fi
+
+    AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SM2 -DWOLFSSL_BASE16"
+fi
+
+
 # ECC Custom Curves
 AC_ARG_ENABLE([ecccustcurves],
     [AS_HELP_STRING([--enable-ecccustcurves],[Enable ECC custom curves (default: disabled)])],
@@ -8532,6 +8693,9 @@ AM_CONDITIONAL([BUILD_SHA3],[test "x$ENABLED_SHA3" != "xno" || test "x$ENABLED_U
 AM_CONDITIONAL([BUILD_POLY1305],[test "x$ENABLED_POLY1305" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
 AM_CONDITIONAL([BUILD_CHACHA],[test "x$ENABLED_CHACHA" = "xyes" || test "x$ENABLED_CHACHA" = "xnoasm" || test "x$ENABLED_USERSETTINGS" = "xyes"])
 AM_CONDITIONAL([BUILD_XCHACHA],[test "x$ENABLED_XCHACHA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
+AM_CONDITIONAL([BUILD_SM2],[test "x$ENABLED_SM2" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"])
+AM_CONDITIONAL([BUILD_SM3],[test "x$ENABLED_SM3" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"])
+AM_CONDITIONAL([BUILD_SM4],[test "x$ENABLED_SM4" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"])
 AM_CONDITIONAL([BUILD_INLINE],[test "x$ENABLED_INLINE" = "xyes"])
 AM_CONDITIONAL([BUILD_OCSP],[test "x$ENABLED_OCSP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
 AM_CONDITIONAL([BUILD_OCSP_STAPLING],[test "x$ENABLED_CERTIFICATE_STATUS_REQUEST" = "xyes"])
@@ -8927,6 +9091,11 @@ echo "   * AES-OFB:                    $ENABLED_AESOFB"
 echo "   * AES-SIV:                    $ENABLED_AESSIV"
 echo "   * DES3:                       $ENABLED_DES3"
 echo "   * Camellia:                   $ENABLED_CAMELLIA"
+echo "   * SM4-ECB:                    $ENABLED_SM4_ECB"
+echo "   * SM4-CBC:                    $ENABLED_SM4_CBC"
+echo "   * SM4-CTR:                    $ENABLED_SM4_CTR"
+echo "   * SM4-GCM:                    $ENABLED_SM4_GCM"
+echo "   * SM4-CCM:                    $ENABLED_SM4_CCM"
 echo "   * NULL Cipher:                $ENABLED_NULL_CIPHER"
 echo "   * MD2:                        $ENABLED_MD2"
 echo "   * MD4:                        $ENABLED_MD4"
@@ -8939,6 +9108,7 @@ echo "   * SHA-512:                    $ENABLED_SHA512"
 echo "   * SHA3:                       $ENABLED_SHA3"
 echo "   * SHAKE128:                   $ENABLED_SHAKE128"
 echo "   * SHAKE256:                   $ENABLED_SHAKE256"
+echo "   * SM3:                        $ENABLED_SM3"
 echo "   * BLAKE2:                     $ENABLED_BLAKE2"
 echo "   * BLAKE2S:                    $ENABLED_BLAKE2S"
 echo "   * SipHash:                    $ENABLED_SIPHASH"
@@ -9081,6 +9251,7 @@ then
 fi
 echo "   * ARM ASM:                    $ENABLED_ARMASM"
 echo "   * ARM ASM SHA512/SHA3 Crypto  $ENABLED_ARMASM_SHA3"
+echo "   * ARM ASM SM3/SM4 Crypto      $ENABLED_ARMASM_CRYPTO_SM4"
 echo "   * AES Key Wrap:               $ENABLED_AESKEYWRAP"
 echo "   * Write duplicate:            $ENABLED_WRITEDUP"
 echo "   * Xilinx Hardware Acc.:       $ENABLED_XILINX"

+ 13 - 0
examples/client/client.c

@@ -350,6 +350,19 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
                     err_sys("unable to use curve secp256r1");
             } while (ret == WC_PENDING_E);
         #endif
+        #ifdef WOLFSSL_SM2
+            do {
+                ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SM2P256V1);
+                if (ret == WOLFSSL_SUCCESS)
+                    groups[count++] = WOLFSSL_ECC_SM2P256V1;
+            #ifdef WOLFSSL_ASYNC_CRYPT
+                else if (ret == WC_PENDING_E)
+                    wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
+            #endif
+                else
+                    err_sys("unable to use curve sm2p256v1");
+            } while (ret == WC_PENDING_E);
+        #endif
     #endif
         }
     }

+ 2 - 2
mcapi/crypto.h

@@ -173,9 +173,9 @@ enum {
 typedef struct CRYPT_AES_CTX {
     /* big enough to hold internal, but check on init */
     #ifdef WOLF_PRIVATE_KEY_ID
-    int holder[108];
+    int holder[110];
     #else
-    int holder[90];
+    int holder[92];
     #endif
 } CRYPT_AES_CTX;
 

+ 2 - 2
src/dtls.c

@@ -718,8 +718,8 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch)
 #ifdef HAVE_SUPPORTED_CURVES
         if (doKE) {
             byte searched = 0;
-            ret = TLSX_KeyShare_Choose(ssl, parsedExts, &cs.clientKSE,
-                    &searched);
+            ret = TLSX_KeyShare_Choose(ssl, parsedExts, cs.cipherSuite0,
+                    cs.cipherSuite, &cs.clientKSE, &searched);
             if (ret != 0)
                 goto dtls13_cleanup;
             if (cs.clientKSE == NULL && searched)

+ 21 - 0
src/include.am

@@ -473,6 +473,27 @@ endif
 endif
 endif !BUILD_FIPS_CURRENT
 
+if !BUILD_FIPS_CURRENT
+if BUILD_SM2
+src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sm2.c
+endif BUILD_SM2
+endif !BUILD_FIPS_CURRENT
+
+if !BUILD_FIPS_CURRENT
+if BUILD_SM3
+src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sm3.c
+if BUILD_INTELASM
+src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sm3_asm.S
+endif
+endif BUILD_SM3
+endif !BUILD_FIPS_CURRENT
+
+if !BUILD_FIPS_CURRENT
+if BUILD_SM4
+src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sm4.c
+endif BUILD_SM4
+endif !BUILD_FIPS_CURRENT
+
 endif !BUILD_FIPS_RAND
 
 if BUILD_SIPHASH

File diff suppressed because it is too large
+ 748 - 483
src/internal.c


+ 379 - 0
src/keys.c

@@ -1354,13 +1354,114 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite,
     }
     }
 
+    if (cipherSuite0 == SM_BYTE) {
+
+    switch (cipherSuite) {
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
+    case TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3 :
+        specs->bulk_cipher_algorithm = wolfssl_sm4_cbc;
+        specs->cipher_type           = block;
+        specs->mac_algorithm         = sm3_mac;
+        specs->kea                   = ecc_diffie_hellman_kea;
+        specs->sig_algo              = sm2_sa_algo;
+        specs->hash_size             = WC_SM3_DIGEST_SIZE;
+        specs->pad_size              = PAD_SHA;
+        specs->static_ecdh           = 0;
+        specs->key_size              = SM4_KEY_SIZE;
+        specs->iv_size               = SM4_IV_SIZE;
+        specs->block_size            = SM4_BLOCK_SIZE;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_GCM_SM3
+    case TLS_ECDHE_ECDSA_WITH_SM4_GCM_SM3 :
+        specs->bulk_cipher_algorithm = wolfssl_sm4_gcm;
+        specs->cipher_type           = aead;
+        specs->mac_algorithm         = sm3_mac;
+        specs->kea                   = ecc_diffie_hellman_kea;
+        specs->sig_algo              = sm2_sa_algo;
+        specs->hash_size             = WC_SM3_DIGEST_SIZE;
+        specs->pad_size              = PAD_SHA;
+        specs->static_ecdh           = 0;
+        specs->key_size              = SM4_KEY_SIZE;
+        specs->block_size            = SM4_BLOCK_SIZE;
+        specs->iv_size               = GCM_IMP_IV_SZ;
+        specs->aead_mac_size         = SM4_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CCM_SM3
+    case TLS_ECDHE_ECDSA_WITH_SM4_CCM_SM3 :
+        specs->bulk_cipher_algorithm = wolfssl_sm4_ccm;
+        specs->cipher_type           = aead;
+        specs->mac_algorithm         = sm3_mac;
+        specs->kea                   = ecc_diffie_hellman_kea;
+        specs->sig_algo              = sm2_sa_algo;
+        specs->hash_size             = WC_SM3_DIGEST_SIZE;
+        specs->pad_size              = PAD_SHA;
+        specs->static_ecdh           = 0;
+        specs->key_size              = SM4_KEY_SIZE;
+        specs->block_size            = SM4_BLOCK_SIZE;
+        specs->iv_size               = GCM_IMP_IV_SZ;
+        specs->aead_mac_size         = SM4_CCM_AUTH_SZ;
+
+        break;
+#endif
+
+    default:
+        break;
+    }
+    }
 
     if (cipherSuite0 != ECC_BYTE &&
         cipherSuite0 != ECDHE_PSK_BYTE &&
         cipherSuite0 != CHACHA_BYTE &&
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) && \
+    (defined(WOLFSSL_SM4_CBC) || defined(WOLFSSL_SM4_GCM) || \
+     defined(WOLFSSL_SM4_CCM))
+        cipherSuite0 != SM_BYTE &&
+#endif
         cipherSuite0 != TLS13_BYTE) {   /* normal suites */
     switch (cipherSuite) {
 
+#ifdef BUILD_TLS_SM4_GCM_SM3
+    case TLS_SM4_GCM_SM3 :
+        specs->bulk_cipher_algorithm = wolfssl_sm4_gcm;
+        specs->cipher_type           = aead;
+        specs->mac_algorithm         = sm3_mac;
+        specs->kea                   = 0;
+        specs->sig_algo              = 0;
+        specs->hash_size             = WC_SM3_DIGEST_SIZE;
+        specs->pad_size              = PAD_SHA;
+        specs->static_ecdh           = 0;
+        specs->key_size              = SM4_KEY_SIZE;
+        specs->block_size            = SM4_BLOCK_SIZE;
+        specs->iv_size               = SM4_GCM_NONCE_SZ;
+        specs->aead_mac_size         = SM4_GCM_AUTH_SZ;
+
+        break;
+#endif
+
+#ifdef BUILD_TLS_SM4_CCM_SM3
+    case TLS_SM4_CCM_SM3 :
+        specs->bulk_cipher_algorithm = wolfssl_sm4_ccm;
+        specs->cipher_type           = aead;
+        specs->mac_algorithm         = sm3_mac;
+        specs->kea                   = 0;
+        specs->sig_algo              = 0;
+        specs->hash_size             = WC_SM3_DIGEST_SIZE;
+        specs->pad_size              = PAD_SHA;
+        specs->static_ecdh           = 0;
+        specs->key_size              = SM4_KEY_SIZE;
+        specs->block_size            = SM4_BLOCK_SIZE;
+        specs->iv_size               = SM4_CCM_NONCE_SZ;
+        specs->aead_mac_size         = SM4_CCM_AUTH_SZ;
+
+        break;
+#endif
+
 #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA
     case SSL_RSA_WITH_RC4_128_SHA :
         specs->bulk_cipher_algorithm = wolfssl_rc4;
@@ -2780,6 +2881,284 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs,
     }
 #endif /* HAVE_CAMELLIA */
 
+#ifdef WOLFSSL_SM4_CBC
+    /* check that buffer sizes are sufficient */
+    #if (MAX_WRITE_IV_SZ < 16) /* AES_IV_SIZE */
+        #error MAX_WRITE_IV_SZ too small for SM4_CBC
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_sm4_cbc) {
+        int sm4Ret = 0;
+
+        if (enc) {
+            if (enc->sm4 == NULL) {
+                enc->sm4 = (wc_Sm4*)XMALLOC(sizeof(wc_Sm4), heap,
+                    DYNAMIC_TYPE_CIPHER);
+                if (enc->sm4 == NULL)
+                    return MEMORY_E;
+            }
+            else {
+                wc_Sm4Free(enc->sm4);
+            }
+
+            XMEMSET(enc->sm4, 0, sizeof(wc_Sm4));
+        }
+        if (dec) {
+            if (dec->sm4 == NULL) {
+                dec->sm4 = (wc_Sm4*)XMALLOC(sizeof(wc_Sm4), heap,
+                    DYNAMIC_TYPE_CIPHER);
+                if (dec->sm4 == NULL)
+                    return MEMORY_E;
+            }
+            else {
+                wc_Sm4Free(dec->sm4);
+            }
+
+            XMEMSET(dec->sm4, 0, sizeof(wc_Sm4));
+        }
+        if (enc) {
+            if (wc_Sm4Init(enc->sm4, heap, devId) != 0) {
+                WOLFSSL_MSG("Sm4Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_Sm4Init(dec->sm4, heap, devId) != 0) {
+                WOLFSSL_MSG("Sm4Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                sm4Ret = wc_Sm4SetKey(enc->sm4, keys->client_write_key,
+                    specs->key_size);
+                if (sm4Ret != 0) return sm4Ret;
+                sm4Ret = wc_Sm4SetIV(enc->sm4, keys->client_write_IV);
+                if (sm4Ret != 0) return sm4Ret;
+            }
+            if (dec) {
+                sm4Ret = wc_Sm4SetKey(dec->sm4, keys->server_write_key,
+                    specs->key_size);
+                if (sm4Ret != 0) return sm4Ret;
+                sm4Ret = wc_Sm4SetIV(dec->sm4, keys->server_write_IV);
+                if (sm4Ret != 0) return sm4Ret;
+            }
+        }
+        else {
+            if (enc) {
+                sm4Ret = wc_Sm4SetKey(enc->sm4, keys->server_write_key,
+                    specs->key_size);
+                if (sm4Ret != 0) return sm4Ret;
+                sm4Ret = wc_Sm4SetIV(enc->sm4, keys->server_write_IV);
+                if (sm4Ret != 0) return sm4Ret;
+            }
+            if (dec) {
+                sm4Ret = wc_Sm4SetKey(dec->sm4, keys->client_write_key,
+                    specs->key_size);
+                if (sm4Ret != 0) return sm4Ret;
+                sm4Ret = wc_Sm4SetIV(dec->sm4, keys->client_write_IV);
+                if (sm4Ret != 0) return sm4Ret;
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* WOLFSSL_SM4_CBC */
+
+#ifdef WOLFSSL_SM4_GCM
+    /* check that buffer sizes are sufficient */
+    #if (AEAD_MAX_IMP_SZ < 4) /* SM4-GCM_IMP_IV_SZ */
+        #error AEAD_MAX_IMP_SZ too small for SM4-GCM
+    #endif
+    #if (AEAD_MAX_EXP_SZ < 8) /* SM4-GCM_EXP_IV_SZ */
+        #error AEAD_MAX_EXP_SZ too small for SM4-GCM
+    #endif
+    #if (MAX_WRITE_IV_SZ < 4) /* SM4-GCM_IMP_IV_SZ */
+        #error MAX_WRITE_IV_SZ too small for SM4-GCM
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_sm4_gcm) {
+        int gcmRet;
+
+        if (enc) {
+            if (enc->sm4 == NULL) {
+                enc->sm4 = (wc_Sm4*)XMALLOC(sizeof(wc_Sm4), heap,
+                                            DYNAMIC_TYPE_CIPHER);
+                if (enc->sm4 == NULL)
+                    return MEMORY_E;
+            } else {
+                wc_Sm4Free(enc->sm4);
+            }
+
+            XMEMSET(enc->sm4, 0, sizeof(wc_Sm4));
+        }
+        if (dec) {
+            if (dec->sm4 == NULL) {
+                dec->sm4 = (wc_Sm4*)XMALLOC(sizeof(wc_Sm4), heap,
+                                            DYNAMIC_TYPE_CIPHER);
+                if (dec->sm4 == NULL)
+                    return MEMORY_E;
+            } else {
+                wc_Sm4Free(dec->sm4);
+            }
+
+            XMEMSET(dec->sm4, 0, sizeof(wc_Sm4));
+        }
+
+        if (enc) {
+            if (wc_Sm4Init(enc->sm4, heap, devId) != 0) {
+                WOLFSSL_MSG("Sm4Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_Sm4Init(dec->sm4, heap, devId) != 0) {
+                WOLFSSL_MSG("Sm4Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                gcmRet = wc_Sm4GcmSetKey(enc->sm4, keys->client_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+            if (dec) {
+                gcmRet = wc_Sm4GcmSetKey(dec->sm4, keys->server_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        else {
+            if (enc) {
+                gcmRet = wc_Sm4GcmSetKey(enc->sm4, keys->server_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+            if (dec) {
+                gcmRet = wc_Sm4GcmSetKey(dec->sm4, keys->client_write_key,
+                                      specs->key_size);
+                if (gcmRet != 0) return gcmRet;
+                XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* WOLFSSL_SM4_GCM */
+
+#ifdef WOLFSSL_SM4_CCM
+    /* check that buffer sizes are sufficient (CCM is same size as GCM) */
+    #if (AEAD_MAX_IMP_SZ < 4) /* SM4-CCM_IMP_IV_SZ */
+        #error AEAD_MAX_IMP_SZ too small for SM4-CCM
+    #endif
+    #if (AEAD_MAX_EXP_SZ < 8) /* SM4-CCM_EXP_IV_SZ */
+        #error AEAD_MAX_EXP_SZ too small for SM4-CCM
+    #endif
+    #if (MAX_WRITE_IV_SZ < 4) /* SM4-CCM_IMP_IV_SZ */
+        #error MAX_WRITE_IV_SZ too small for SM4-CCM
+    #endif
+
+    if (specs->bulk_cipher_algorithm == wolfssl_sm4_ccm) {
+        int CcmRet;
+
+        if (enc) {
+            if (enc->sm4 == NULL) {
+                enc->sm4 = (wc_Sm4*)XMALLOC(sizeof(wc_Sm4), heap,
+                                            DYNAMIC_TYPE_CIPHER);
+                if (enc->sm4 == NULL)
+                    return MEMORY_E;
+            } else {
+                wc_Sm4Free(enc->sm4);
+            }
+
+            XMEMSET(enc->sm4, 0, sizeof(wc_Sm4));
+        }
+        if (dec) {
+            if (dec->sm4 == NULL) {
+                dec->sm4 = (wc_Sm4*)XMALLOC(sizeof(wc_Sm4), heap,
+                                            DYNAMIC_TYPE_CIPHER);
+                if (dec->sm4 == NULL)
+                return MEMORY_E;
+            } else {
+                wc_Sm4Free(dec->sm4);
+            }
+            XMEMSET(dec->sm4, 0, sizeof(wc_Sm4));
+        }
+
+        if (enc) {
+            if (wc_Sm4Init(enc->sm4, heap, devId) != 0) {
+                WOLFSSL_MSG("Sm4Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+        if (dec) {
+            if (wc_Sm4Init(dec->sm4, heap, devId) != 0) {
+                WOLFSSL_MSG("Sm4Init failed in SetKeys");
+                return ASYNC_INIT_E;
+            }
+        }
+
+        if (side == WOLFSSL_CLIENT_END) {
+            if (enc) {
+                CcmRet = wc_Sm4SetKey(enc->sm4, keys->client_write_key,
+                                      specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+            if (dec) {
+                CcmRet = wc_Sm4SetKey(dec->sm4, keys->server_write_key,
+                                      specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        else {
+            if (enc) {
+                CcmRet = wc_Sm4SetKey(enc->sm4, keys->server_write_key,
+                                      specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+            if (dec) {
+                CcmRet = wc_Sm4SetKey(dec->sm4, keys->client_write_key,
+                                      specs->key_size);
+                if (CcmRet != 0) {
+                    return CcmRet;
+                }
+                XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV,
+                        AEAD_MAX_IMP_SZ);
+            }
+        }
+        if (enc)
+            enc->setup = 1;
+        if (dec)
+            dec->setup = 1;
+    }
+#endif /* WOLFSSL_SM4_CCM */
+
 #ifdef HAVE_NULL_CIPHER
     if (specs->bulk_cipher_algorithm == wolfssl_cipher_null) {
     #ifdef WOLFSSL_TLS13

+ 4 - 0
src/pk.c

@@ -8815,6 +8815,10 @@ int EccEnumToNID(int n)
             return NID_brainpoolP384r1;
         case ECC_BRAINPOOLP512R1:
             return NID_brainpoolP512r1;
+    #ifdef WOLFSSL_SM2
+        case ECC_SM2P256V1:
+            return NID_sm2;
+    #endif
         default:
             WOLFSSL_MSG("NID not found");
             return -1;

+ 5 - 0
src/sniffer.c

@@ -3267,6 +3267,11 @@ static int ProcessKeyShare(KeyShareInfo* info, const byte* input, int len,
                 info->curve_id = ECC_SECP256R1;
                 break;
             #endif /* !NO_ECC_SECP */
+            #ifdef WOLFSSL_SM2
+            case WOLFSSL_ECC_SM2P256V1:
+                info->curve_id = ECC_SM2P256V1;
+                break;
+            #endif /* WOLFSSL_SM2 */
         #endif
         #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
             #ifndef NO_ECC_SECP

+ 150 - 3
src/ssl.c

@@ -448,6 +448,9 @@ const WOLF_EC_NIST_NAME kNistCurves[] = {
     {XSTR_SIZEOF("P384_KYBER_LEVEL3"), "P384_KYBER_LEVEL3", WOLFSSL_P384_KYBER_LEVEL3},
     {XSTR_SIZEOF("P521_KYBER_LEVEL5"), "P521_KYBER_LEVEL5", WOLFSSL_P521_KYBER_LEVEL5},
 #endif
+#endif
+#ifdef WOLFSSL_SM2
+    {XSTR_SIZEOF("SM2"),     "SM2",     NID_sm2},
 #endif
     {0, NULL, 0},
 };
@@ -2647,6 +2650,9 @@ int wolfSSL_GetObjectSize(void)
 #endif
 #ifdef HAVE_CHACHA
     printf("\tsizeof chacha       = %lu\n", (unsigned long)sizeof(ChaCha));
+#endif
+#ifdef WOLFSSL_SM4
+    printf("\tsizeof sm4          = %lu\n", (unsigned long)sizeof(Sm4));
 #endif
     printf("sizeof cipher specs     = %lu\n", (unsigned long)sizeof(CipherSpecs));
     printf("sizeof keys             = %lu\n", (unsigned long)sizeof(Keys));
@@ -2668,6 +2674,9 @@ int wolfSSL_GetObjectSize(void)
 #endif
 #ifdef WOLFSSL_SHA384
     printf("\tsizeof SHA512       = %lu\n", (unsigned long)sizeof(wc_Sha512));
+#endif
+#ifdef WOLFSSL_SM3
+    printf("\tsizeof sm3          = %lu\n", (unsigned long)sizeof(Sm3));
 #endif
     printf("sizeof Buffers          = %lu\n", (unsigned long)sizeof(Buffers));
     printf("sizeof Options          = %lu\n", (unsigned long)sizeof(Options));
@@ -3692,6 +3701,7 @@ static int isValidCurveGroup(word16 name)
         case WOLFSSL_ECC_BRAINPOOLP256R1:
         case WOLFSSL_ECC_BRAINPOOLP384R1:
         case WOLFSSL_ECC_BRAINPOOLP512R1:
+        case WOLFSSL_ECC_SM2P256V1:
         case WOLFSSL_ECC_X25519:
         case WOLFSSL_ECC_X448:
 
@@ -6127,8 +6137,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
         XMEMCPY(signer->subjectNameHash, cert->subjectHash,
                 SIGNER_DIGEST_SIZE);
     #ifdef HAVE_OCSP
-        XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash,
-                KEYID_SIZE);
+        XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash, KEYID_SIZE);
     #endif
         signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage
                                                 : 0xFFFF;
@@ -6874,11 +6883,23 @@ static int ProcessBufferTryDecodeEcc(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
             if (ssl) {
                 ssl->options.haveStaticECC = 1;
                 ssl->buffers.keyType = ecc_dsa_sa_algo;
+            #ifdef WOLFSSL_SM2
+                if (key->dp->id == ECC_SM2P256V1)
+                    ssl->buffers.keyType = sm2_sa_algo;
+                else
+            #endif
+                    ssl->buffers.keyType = ecc_dsa_sa_algo;
                 ssl->buffers.keySz = *keySz;
             }
             else {
                 ctx->haveStaticECC = 1;
                 ctx->privateKeyType = ecc_dsa_sa_algo;
+            #ifdef WOLFSSL_SM2
+                if (key->dp->id == ECC_SM2P256V1)
+                    ctx->privateKeyType = sm2_sa_algo;
+                else
+            #endif
+                    ctx->privateKeyType = ecc_dsa_sa_algo;
                 ctx->privateKeySz = *keySz;
             }
 
@@ -7233,7 +7254,11 @@ static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
     }
 #endif
 #ifdef HAVE_ECC
-    if ((*keyFormat == 0 || *keyFormat == ECDSAk)) {
+    if ((*keyFormat == 0) || (*keyFormat == ECDSAk)
+    #ifdef WOLFSSL_SM2
+        || (*keyFormat == SM2k)
+    #endif
+        ) {
         ret = ProcessBufferTryDecodeEcc(ctx, ssl, der, keySz, idx, resetSuites,
             keyFormat, heap, devId);
         if (ret != 0)
@@ -7628,6 +7653,9 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
             case CTC_SHA512wECDSA:
             case CTC_ED25519:
             case CTC_ED448:
+        #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+            case CTC_SM3wSM2:
+        #endif
                 WOLFSSL_MSG("ECDSA/ED25519/ED448 cert signature");
                 if (ssl)
                     ssl->options.haveECDSAsig = 1;
@@ -7677,6 +7705,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
             }
             #endif
             #endif
+            #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                else if (cert->keyOID == SM2k) {
+                    ssl->options.haveECC = 1;
+                }
+            #endif
             #ifdef HAVE_ED25519
                 else if (cert->keyOID == ED25519k) {
                     ssl->options.haveECC = 1;
@@ -7724,6 +7757,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
             }
             #endif
             #endif
+            #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+            else if (cert->keyOID == SM2k) {
+                ctx->haveECC = 1;
+            }
+            #endif
             #ifdef HAVE_ED25519
                 else if (cert->keyOID == ED25519k) {
                     ctx->haveECC = 1;
@@ -7815,6 +7853,30 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
                 }
                 break;
         #endif /* HAVE_ECC */
+        #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+            case SM2k:
+            #ifdef WOLF_PRIVATE_KEY_ID
+                keyType = sm2_sa_algo;
+            #endif
+                /* Determine ECC key size based on curve */
+                keySz = wc_ecc_get_curve_size_from_id(
+                    wc_ecc_get_oid(cert->pkCurveOID, NULL, NULL));
+                if (ssl && !ssl->options.verifyNone) {
+                    if (ssl->options.minEccKeySz < 0 ||
+                          keySz < (int)ssl->options.minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate Ed key size error");
+                    }
+                }
+                else if (ctx && !ctx->verifyNone) {
+                    if (ctx->minEccKeySz < 0 ||
+                                  keySz < (int)ctx->minEccKeySz) {
+                        ret = ECC_KEY_SIZE_E;
+                        WOLFSSL_MSG("Certificate ECC key size error");
+                    }
+                }
+                break;
+        #endif /* HAVE_ED25519 */
         #ifdef HAVE_ED25519
             case ED25519k:
             #ifdef WOLF_PRIVATE_KEY_ID
@@ -10005,6 +10067,11 @@ WOLFSSL_EVP_PKEY* wolfSSL_CTX_get0_privatekey(const WOLFSSL_CTX* ctx)
         case ecc_dsa_sa_algo:
             type = EVP_PKEY_EC;
             break;
+#endif
+#ifdef WOLFSSL_SM2
+        case sm2_sa_algo:
+            type = EVP_PKEY_EC;
+            break;
 #endif
         default:
             /* Other key types not supported either as ssl private keys
@@ -22528,6 +22595,11 @@ static WC_INLINE const char* wolfssl_sigalg_to_string(int sig_algo)
             authStr = "ECDSA";
             break;
 #endif
+#ifdef WOLFSSL_SM2
+        case sm2_sa_algo:
+            authStr = "SM2";
+            break;
+#endif
 #ifdef HAVE_ED25519
         case ed25519_sa_algo:
             authStr = "Ed25519";
@@ -26218,6 +26290,9 @@ const WOLFSSL_ObjectInfo wolfssl_object_info[] = {
         { NID_sha3_512, SHA3_512h, oidHashType, "SHA3-512", "sha3-512"},
         #endif
     #endif /* WOLFSSL_SHA3 */
+    #ifdef WOLFSSL_SM3
+        { NID_sm3, SM3h, oidHashType, "SM3", "sm3"},
+    #endif
         /* oidSigType */
     #ifndef NO_DSA
         #ifndef NO_SHA
@@ -26390,6 +26465,10 @@ const WOLFSSL_ObjectInfo wolfssl_object_info[] = {
         { NID_brainpoolP320r1, ECC_BRAINPOOLP320R1_OID,  oidCurveType, "brainpoolP320r1", "brainpoolP320r1"},
         { NID_brainpoolP384r1, ECC_BRAINPOOLP384R1_OID,  oidCurveType, "brainpoolP384r1", "brainpoolP384r1"},
         { NID_brainpoolP512r1, ECC_BRAINPOOLP512R1_OID,  oidCurveType, "brainpoolP512r1", "brainpoolP512r1"},
+
+    #ifdef WOLFSSL_SM2
+        { NID_sm2, ECC_SM2P256V1_OID, oidCurveType, "sm2", "sm2"},
+    #endif
     #endif /* HAVE_ECC */
 
         /* oidBlkType */
@@ -27662,6 +27741,9 @@ struct WOLFSSL_HashSigInfo {
         { sha_mac,    ecc_dsa_sa_algo, CTC_SHAwECDSA },
     #endif
 #endif
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    { sm3_mac, sm2_sa_algo, CTC_SM3wSM2 },
+#endif
 #ifdef HAVE_ED25519
     { no_mac, ed25519_sa_algo, CTC_ED25519 },
 #endif
@@ -33594,6 +33676,13 @@ static int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, const char* names)
         {
             curve = WOLFSSL_ECC_SECP521R1;
         }
+    #ifdef WOLFSSL_SM2
+        else if ((XSTRNCMP(name, "sm2p256v1", len) == 0) ||
+                 (XSTRNCMP(name, "SM2", len) == 0))
+        {
+            curve = WOLFSSL_ECC_SECP521R1;
+        }
+    #endif
     #ifdef HAVE_CURVE25519
         else if (XSTRNCMP(name, "X25519", len) == 0)
         {
@@ -36530,6 +36619,35 @@ int wolfSSL_RAND_poll(void)
                 break;
 #endif
 
+#ifdef WOLFSSL_SM4_ECB
+            case SM4_ECB_TYPE:
+                break;
+#endif
+#ifdef WOLFSSL_SM4_CBC
+            case SM4_CBC_TYPE:
+                WOLFSSL_MSG("SM4 CBC");
+                XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE);
+                break;
+#endif
+#ifdef WOLFSSL_SM4_CTR
+            case SM4_CTR_TYPE:
+                WOLFSSL_MSG("SM4 CTR");
+                XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE);
+                break;
+#endif
+#ifdef WOLFSSL_SM4_GCM
+            case SM4_GCM_TYPE:
+                WOLFSSL_MSG("SM4 GCM");
+                XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE);
+                break;
+#endif
+#ifdef WOLFSSL_SM4_CCM
+            case SM4_CCM_TYPE:
+                WOLFSSL_MSG("SM4 CCM");
+                XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE);
+                break;
+#endif
+
             case NULL_CIPHER_TYPE :
                 WOLFSSL_MSG("NULL");
                 break;
@@ -36624,6 +36742,35 @@ int wolfSSL_RAND_poll(void)
                 break;
 #endif
 
+#ifdef WOLFSSL_SM4_ECB
+            case SM4_ECB_TYPE:
+                break;
+#endif
+#ifdef WOLFSSL_SM4_CBC
+            case SM4_CBC_TYPE:
+                WOLFSSL_MSG("SM4 CBC");
+                XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz);
+                break;
+#endif
+#ifdef WOLFSSL_SM4_CTR
+            case SM4_CTR_TYPE:
+                WOLFSSL_MSG("SM4 CTR");
+                XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz);
+                break;
+#endif
+#ifdef WOLFSSL_SM4_GCM
+            case SM4_GCM_TYPE:
+                WOLFSSL_MSG("SM4 GCM");
+                XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz);
+                break;
+#endif
+#ifdef WOLFSSL_SM4_CCM
+            case SM4_CCM_TYPE:
+                WOLFSSL_MSG("SM4 CCM");
+                XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz);
+                break;
+#endif
+
             case NULL_CIPHER_TYPE :
                 WOLFSSL_MSG("NULL");
                 break;

+ 143 - 7
src/tls.c

@@ -156,6 +156,12 @@ int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen)
             ret |= wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
             hashSz = WC_SHA384_DIGEST_SIZE;
         }
+#endif
+#ifdef WOLFSSL_SM3
+        if (ssl->specs.mac_algorithm == sm3_mac) {
+            ret |= wc_Sm3GetHash(&ssl->hsHashes->hashSm3, hash);
+            hashSz = WC_SM3_DIGEST_SIZE;
+        }
 #endif
     }
 
@@ -686,7 +692,12 @@ int wolfSSL_GetHmacType_ex(CipherSpecs* specs)
         {
             return WC_SHA384;
         }
-
+        #endif
+        #ifdef WOLFSSL_SM3
+        case sm3_mac:
+        {
+            return WC_SM3;
+        }
         #endif
         #ifndef NO_SHA
         case sha_mac:
@@ -775,6 +786,12 @@ static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz)
             break;
     #endif /* WOLFSSL_SHA512 */
 
+    #ifdef WOLFSSL_SM3
+        case WC_SM3:
+            ret = wc_Sm3Update(&hmac->hash.sm3, data, sz);
+            break;
+    #endif /* WOLFSSL_SM3 */
+
         default:
             break;
     }
@@ -817,6 +834,12 @@ static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash)
             break;
     #endif /* WOLFSSL_SHA512 */
 
+    #ifdef WOLFSSL_SM3
+        case WC_SM3:
+            ret = wc_Sm3FinalRaw(&hmac->hash.sm3, hash);
+            break;
+    #endif /* WOLFSSL_SM3 */
+
         default:
             break;
     }
@@ -913,6 +936,14 @@ static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in,
             break;
     #endif /* WOLFSSL_SHA512 */
 
+    #ifdef WOLFSSL_SM3
+        case WC_SM3:
+            blockSz = WC_SM3_BLOCK_SIZE;
+            blockBits = 6;
+            padSz = WC_SM3_BLOCK_SIZE - WC_SM3_PAD_SIZE + 1;
+            break;
+    #endif /* WOLFSSL_SM3 */
+
         default:
             return BAD_FUNC_ARG;
     }
@@ -3860,7 +3891,7 @@ int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type,
                        && !defined(HAVE_FFDHE) && !defined(HAVE_PQC)
 #error Elliptic Curves Extension requires Elliptic Curve Cryptography or liboqs groups. \
        Use --enable-ecc and/or --enable-liboqs in the configure script or \
-       define HAVE_ECC. Alternatively use FFDHE for DH ciphersuites.
+       define HAVE_ECC. Alternatively use FFDHE for DH cipher suites.
 #endif
 
 static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name,
@@ -3987,6 +4018,21 @@ static void TLSX_SupportedCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
     for (i = 0; i < suites->suiteSz; i += 2) {
         if (suites->suites[i] == TLS13_BYTE)
             return;
+    #ifdef BUILD_TLS_SM4_GCM_SM3
+        if ((suites->suites[i] == CIPHER_BYTE) &&
+            (suites->suites[i+1] == TLS_SM4_GCM_SM3))
+            return;
+    #endif
+    #ifdef BUILD_TLS_SM4_CCM_SM3
+        if ((suites->suites[i] == CIPHER_BYTE) &&
+            (suites->suites[i+1] == TLS_SM4_CCM_SM3))
+            return;
+    #endif
+    #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
+        if ((suites->suites[i] == SM_BYTE) &&
+            (suites->suites[i+1] == TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3))
+            return;
+    #endif
         if ((suites->suites[i] == ECC_BYTE) ||
             (suites->suites[i] == ECDHE_PSK_BYTE) ||
             (suites->suites[i] == CHACHA_BYTE)) {
@@ -4024,6 +4070,21 @@ static void TLSX_PointFormat_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
     for (i = 0; i < suites->suiteSz; i += 2) {
         if (suites->suites[i] == TLS13_BYTE)
             return;
+    #ifdef BUILD_TLS_SM4_GCM_SM3
+        if ((suites->suites[i] == CIPHER_BYTE) &&
+            (suites->suites[i+1] == TLS_SM4_GCM_SM3))
+            return;
+    #endif
+    #ifdef BUILD_TLS_SM4_CCM_SM3
+        if ((suites->suites[i] == CIPHER_BYTE) &&
+            (suites->suites[i+1] == TLS_SM4_CCM_SM3))
+            return;
+    #endif
+    #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
+        if ((suites->suites[i] == SM_BYTE) &&
+            (suites->suites[i+1] == TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3))
+            return;
+    #endif
         if ((suites->suites[i] == ECC_BYTE) ||
             (suites->suites[i] == ECDHE_PSK_BYTE) ||
             (suites->suites[i] == CHACHA_BYTE)) {
@@ -4051,6 +4112,21 @@ static void TLSX_PointFormat_ValidateResponse(WOLFSSL* ssl, byte* semaphore)
 
     if (ssl->options.cipherSuite0 == TLS13_BYTE)
         return;
+#ifdef BUILD_TLS_SM4_GCM_SM3
+    if ((ssl->options.cipherSuite0 == CIPHER_BYTE) &&
+        (ssl->options.cipherSuite == TLS_SM4_GCM_SM3))
+        return;
+#endif
+#ifdef BUILD_TLS_SM4_CCM_SM3
+    if ((ssl->options.cipherSuite0 == CIPHER_BYTE) &&
+        (ssl->options.cipherSuite == TLS_SM4_CCM_SM3))
+        return;
+#endif
+#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
+    if ((ssl->options.cipherSuite0 == SM_BYTE) &&
+        (ssl->options.cipherSuite == TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3))
+        return;
+#endif
 #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
     if (ssl->options.cipherSuite0 == ECC_BYTE ||
         ssl->options.cipherSuite0 == ECDHE_PSK_BYTE ||
@@ -4671,6 +4747,12 @@ int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, byte second,
                 octets = 32;
                 break;
         #endif /* HAVE_ECC_BRAINPOOL */
+        #ifdef WOLFSSL_SM2
+            case WOLFSSL_ECC_SM2P256V1:
+                oid = ECC_SM2P256V1_OID;
+                octets = 32;
+                break;
+        #endif /* WOLFSSL_SM2 */
     #endif
     #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
         #ifndef NO_ECC_SECP
@@ -7098,6 +7180,12 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
             keySize = 32;
             break;
         #endif /* !NO_ECC_SECP */
+        #ifdef WOLFSSL_SM2
+        case WOLFSSL_ECC_SM2P256V1:
+            curveId = ECC_SM2P256V1;
+            keySize = 32;
+            break;
+        #endif /* !NO_ECC_SECP */
     #endif
     #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
         #ifndef NO_ECC_SECP
@@ -7888,6 +7976,11 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
             curveId = ECC_SECP256R1;
             break;
         #endif /* !NO_ECC_SECP */
+        #ifdef WOLFSSL_SM2
+        case WOLFSSL_ECC_SM2P256V1:
+            curveId = ECC_SM2P256V1;
+            break;
+        #endif
     #endif
     #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384
         #ifndef NO_ECC_SECP
@@ -8834,6 +8927,10 @@ static int TLSX_KeyShare_IsSupported(int namedGroup)
         case WOLFSSL_ECC_BRAINPOOLP256R1:
             break;
         #endif
+        #ifdef WOLFSSL_SM2
+        case WOLFSSL_ECC_SM2P256V1:
+            break;
+        #endif /* WOLFSSL_SM2 */
     #endif
     #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
         case WOLFSSL_ECC_X25519:
@@ -8949,6 +9046,9 @@ static const word16 preferredGroup[] = {
 #if defined(HAVE_ECC) && (!defined(NO_ECC256) || \
     defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 256
     WOLFSSL_ECC_SECP256R1,
+#if !defined(HAVE_FIPS) && defined(WOLFSSL_SM2)
+    WOLFSSL_ECC_SM2P256V1,
+#endif
 #endif
 #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
     WOLFSSL_ECC_X25519,
@@ -9124,7 +9224,7 @@ int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, TLSX** extensions)
 
 /* Server side KSE processing */
 int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions,
-                         KeyShareEntry** kse, byte* searched)
+    byte cipherSuite0, byte cipherSuite, KeyShareEntry** kse, byte* searched)
 {
     TLSX*          extension;
     KeyShareEntry* clientKSE = NULL;
@@ -9133,6 +9233,9 @@ int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions,
     int preferredRank = WOLFSSL_MAX_GROUP_COUNT;
     int rank;
 
+    (void)cipherSuite0;
+    (void)cipherSuite;
+
     if (ssl == NULL || ssl->options.side != WOLFSSL_SERVER_END)
         return BAD_FUNC_ARG;
 
@@ -9163,6 +9266,19 @@ int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions,
         if (clientKSE->ke == NULL)
             continue;
 
+#ifdef WOLFSSL_SM2
+        if ((cipherSuite0 == CIPHER_BYTE) &&
+            ((cipherSuite == TLS_SM4_GCM_SM3) ||
+             (cipherSuite == TLS_SM4_CCM_SM3))) {
+           if (clientKSE->group != WOLFSSL_ECC_SM2P256V1) {
+               continue;
+           }
+        }
+        else if (clientKSE->group == WOLFSSL_ECC_SM2P256V1) {
+           continue;
+        }
+#endif
+
         /* Check consistency now - extensions in any order. */
         if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group, extensions))
             continue;
@@ -9298,7 +9414,8 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry)
 
     *doHelloRetry = 0;
 
-    ret = TLSX_KeyShare_Choose(ssl, ssl->extensions, &clientKSE, &searched);
+    ret = TLSX_KeyShare_Choose(ssl, ssl->extensions, ssl->cipher.cipherSuite0,
+        ssl->cipher.cipherSuite, &clientKSE, &searched);
     if (ret != 0 || !searched)
         return ret;
 
@@ -9780,6 +9897,10 @@ static WC_INLINE byte GetHmacLength(int hmac)
         case sha512_mac:
             return WC_SHA512_DIGEST_SIZE;
     #endif
+    #ifdef WOLFSSL_SM3
+        case sm3_mac:
+            return WC_SM3_DIGEST_SIZE;
+    #endif
     }
     return 0;
 }
@@ -9791,8 +9912,8 @@ static WC_INLINE byte GetHmacLength(int hmac)
  * len           The length of the identity data.
  * age           The age of the identity.
  * hmac          The HMAC algorithm.
- * ciphersuite0  The first byte of the ciphersuite to use.
- * ciphersuite   The second byte of the ciphersuite to use.
+ * cipherSuite0  The first byte of the cipher suite to use.
+ * cipherSuite   The second byte of the cipher suite to use.
  * resumption    The PSK is for resumption of a session.
  * preSharedKey  The new pre-shared key object.
  * returns 0 on success and other values indicate failure.
@@ -11738,6 +11859,11 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions)
                                         WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap);
                 if (ret != WOLFSSL_SUCCESS) return ret;
             #endif
+            #ifdef WOLFSSL_SM2
+                ret = TLSX_UseSupportedCurve(extensions,
+                                              WOLFSSL_ECC_SM2P256V1, ssl->heap);
+                if (ret != WOLFSSL_SUCCESS) return ret;
+            #endif
         #endif
 #endif /* HAVE_ECC */
 
@@ -12135,6 +12261,16 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
                         }
                     }
                     else
+                #endif
+                #if (defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)) && \
+                    defined(WOLFSSL_SM3)
+                    if (cipherSuite0 == CIPHER_BYTE) {
+                        if ((cipherSuite != TLS_SM4_GCM_SM3) &&
+                            (cipherSuite != TLS_SM4_CCM_SM3)) {
+                            continue;
+                        }
+                    }
+                    else
                 #endif
                     if (cipherSuite0 != TLS13_BYTE)
                         continue;
@@ -12175,7 +12311,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
         #endif
             if (ssl->options.client_psk_cb != NULL ||
                                      ssl->options.client_psk_tls13_cb != NULL) {
-                /* Default ciphersuite. */
+                /* Default cipher suite. */
                 byte cipherSuite0 = TLS13_BYTE;
                 byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER;
                 int cipherSuiteFlags = WOLFSSL_CIPHER_SUITE_FLAG_NONE;

+ 292 - 47
src/tls13.c

@@ -338,6 +338,19 @@ static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen,
             hashSz = WC_SHA512_DIGEST_SIZE;
             digestAlg = WC_SHA512;
             break;
+#endif
+#ifdef WOLFSSL_SM3
+        case sm3_mac:
+            ret = wc_InitSm3(&digest.sm3, ssl->heap, INVALID_DEVID);
+            if (ret == 0) {
+                ret = wc_Sm3Update(&digest.sm3, msg, msgLen);
+                if (ret == 0)
+                    ret = wc_Sm3Final(&digest.sm3, hash);
+                wc_Sm3Free(&digest.sm3);
+            }
+            hashSz = WC_SM3_DIGEST_SIZE;
+            digestAlg = WC_SM3;
+            break;
 #endif
         default:
             digestAlg = -1;
@@ -429,6 +442,15 @@ int Tls13DeriveKey(WOLFSSL* ssl, byte* output, int outputLen,
             break;
     #endif
 
+    #ifdef WOLFSSL_SM3
+        case sm3_mac:
+            hashSz    = WC_SM3_DIGEST_SIZE;
+            digestAlg = WC_SM3;
+            if (includeMsgs)
+                ret = wc_Sm3GetHash(&ssl->hsHashes->hashSm3, hash);
+            break;
+    #endif
+
         default:
             ret = HASH_TYPE_E;
             break;
@@ -502,6 +524,13 @@ static WC_INLINE int mac2hash(int mac)
             hash = WC_SHA512;
             break;
         #endif
+
+        #ifdef WOLFSSL_SM3
+        case sm3_mac:
+            hash = WC_SM3;
+            break;
+        #endif
+
     default:
         hash = WC_HASH_TYPE_NONE;
     }
@@ -1202,6 +1231,12 @@ int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret)
             break;
         #endif
 
+        #ifdef WOLFSSL_SM3
+        case sm3_mac:
+            digestAlg = WC_SM3;
+            break;
+        #endif
+
         default:
             return BAD_FUNC_ARG;
     }
@@ -1271,6 +1306,13 @@ static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash,
             ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash);
             break;
     #endif /* WOLFSSL_TLS13_SHA512 */
+    #ifdef WOLFSSL_SM3
+        case sm3_mac:
+            hashType = WC_SM3;
+            hashSz = WC_SM3_DIGEST_SIZE;
+            ret = wc_Sm3GetHash(&ssl->hsHashes->hashSm3, hash);
+            break;
+    #endif /* WOLFSSL_SM3 */
         default:
             break;
     }
@@ -2596,6 +2638,24 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
                     break;
             #endif
 
+            #ifdef WOLFSSL_SM4_GCM
+                case wolfssl_sm4_gcm:
+                    nonceSz = SM4_GCM_NONCE_SZ;
+                    ret = wc_Sm4GcmEncrypt(ssl->encrypt.sm4, output, input,
+                        dataSz, ssl->encrypt.nonce, nonceSz, output + dataSz,
+                        macSz, aad, aadSz);
+                    break;
+            #endif
+
+            #ifdef WOLFSSL_SM4_CCM
+                case wolfssl_sm4_ccm:
+                    nonceSz = SM4_CCM_NONCE_SZ;
+                    ret = wc_Sm4CcmEncrypt(ssl->encrypt.sm4, output, input,
+                        dataSz, ssl->encrypt.nonce, nonceSz, output + dataSz,
+                        macSz, aad, aadSz);
+                    break;
+            #endif
+
             #ifdef HAVE_NULL_CIPHER
                 case wolfssl_cipher_null:
                     ret = Tls13IntegrityOnly_Encrypt(ssl, output, input, dataSz,
@@ -2972,6 +3032,24 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz,
                     break;
             #endif
 
+            #ifdef WOLFSSL_SM4_GCM
+                case wolfssl_sm4_gcm:
+                    nonceSz = SM4_GCM_NONCE_SZ;
+                    ret = wc_Sm4GcmDecrypt(ssl->decrypt.sm4, output, input,
+                        dataSz, ssl->decrypt.nonce, nonceSz, output + dataSz,
+                        macSz, aad, aadSz);
+                    break;
+            #endif
+
+            #ifdef WOLFSSL_SM4_CCM
+                case wolfssl_sm4_ccm:
+                    nonceSz = SM4_CCM_NONCE_SZ;
+                    ret = wc_Sm4CcmDecrypt(ssl->decrypt.sm4, output, input,
+                        dataSz, ssl->decrypt.nonce, nonceSz, output + dataSz,
+                        macSz, aad, aadSz);
+                    break;
+            #endif
+
             #ifdef HAVE_NULL_CIPHER
                 case wolfssl_cipher_null:
                     ret = Tls13IntegrityOnly_Decrypt(ssl, output, input, dataSz,
@@ -3339,6 +3417,25 @@ byte SuiteMac(const byte* suite)
                 break;
         }
     }
+#if (defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)) && \
+     defined(WOLFSSL_SM3)
+    else if (suite[0] == CIPHER_BYTE) {
+        switch (suite[1]) {
+        #ifdef BUILD_TLS_SM4_GCM_SM3
+            case TLS_SM4_GCM_SM3:
+                mac = sm3_mac;
+                break;
+        #endif
+        #ifdef BUILD_TLS_SM4_CCM_SM3
+            case TLS_SM4_CCM_SM3:
+                mac = sm3_mac;
+                break;
+        #endif
+            default:
+                break;
+        }
+    }
+#endif
 #ifdef HAVE_NULL_CIPHER
     else if (suite[0] == ECC_BYTE) {
         switch (suite[1]) {
@@ -3472,6 +3569,11 @@ static int CreateCookie(const WOLFSSL* ssl, byte** hash, byte* hashSz,
             *hash = hashes->sha512;
             break;
     #endif
+    #ifdef WOLFSSL_SM3
+        case sm3_mac:
+            *hash = hashes->sm3;
+            break;
+    #endif
     }
     *hashSz = ssl->specs.hash_size;
 
@@ -4587,6 +4689,12 @@ static int EchCheckAcceptance(WOLFSSL* ssl, const byte* input,
                 digestSize = WC_SHA512_DIGEST_SIZE;
                 break;
 #endif /* WOLFSSL_TLS13_SHA512 */
+#ifdef WOLFSSL_SM3
+            case sm3_mac:
+                digestType = WC_SM3;
+                digestSize = WC_SM3_DIGEST_SIZE;
+                break;
+#endif /* WOLFSSL_SM3 */
             default:
                 ret = -1;
                 break;
@@ -4717,6 +4825,12 @@ static int EchWriteAcceptance(WOLFSSL* ssl, byte* output,
                 digestSize = WC_SHA512_DIGEST_SIZE;
                 break;
 #endif /* WOLFSSL_TLS13_SHA512 */
+#ifdef WOLFSSL_SM3
+            case sm3_mac:
+                digestType = WC_SM3;
+                digestSize = WC_SM3_DIGEST_SIZE;
+                break;
+#endif /* WOLFSSL_SM3 */
             default:
                 ret = -1;
                 break;
@@ -5228,6 +5342,20 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
         ;
     }
     else
+#endif
+#if defined(WOLFSSL_SM4_GCM) && defined(WOLFSSL_SM3)
+    if (ssl->options.cipherSuite0 == CIPHER_BYTE &&
+            ssl->options.cipherSuite == TLS_SM4_GCM_SM3) {
+        ; /* Do nothing. */
+    }
+    else
+#endif
+#if defined(WOLFSSL_SM4_CCM) && defined(WOLFSSL_SM3)
+    if (ssl->options.cipherSuite0 == CIPHER_BYTE &&
+            ssl->options.cipherSuite == TLS_SM4_CCM_SM3) {
+        ; /* Do nothing. */
+    }
+    else
 #endif
     /* Check that the negotiated ciphersuite matches protocol version. */
     if (ssl->options.cipherSuite0 != TLS13_BYTE) {
@@ -6812,6 +6940,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
 
     if (!args->usingPSK) {
 #ifndef NO_CERTS
+        /* Check that the negotiated ciphersuite matches protocol version. */
     #ifdef HAVE_NULL_CIPHER
         if (ssl->options.cipherSuite0 == ECC_BYTE &&
                               (ssl->options.cipherSuite == TLS_SHA256_SHA256 ||
@@ -6820,7 +6949,20 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
         }
         else
     #endif
-        /* Check that the negotiated ciphersuite matches protocol version. */
+    #if defined(WOLFSSL_SM4_GCM) && defined(WOLFSSL_SM3)
+        if (ssl->options.cipherSuite0 == CIPHER_BYTE &&
+                ssl->options.cipherSuite == TLS_SM4_GCM_SM3) {
+            ; /* Do nothing. */
+        }
+        else
+    #endif
+    #if defined(WOLFSSL_SM4_CCM) && defined(WOLFSSL_SM3)
+        if (ssl->options.cipherSuite0 == CIPHER_BYTE &&
+                ssl->options.cipherSuite == TLS_SM4_CCM_SM3) {
+            ; /* Do nothing. */
+        }
+        else
+    #endif
         if (ssl->options.cipherSuite0 != TLS13_BYTE) {
             WOLFSSL_MSG("Negotiated ciphersuite from lesser version than "
                         "TLS v1.3");
@@ -7287,6 +7429,10 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
     word16 reqSz;
     word16 hashSigAlgoSz = 0;
     SignatureAlgorithms* sa;
+    int haveSig = SIG_RSA | SIG_ECDSA | SIG_FALCON | SIG_DILITHIUM;
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    haveSig |= SIG_SM2;
+#endif
 
     WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND);
     WOLFSSL_ENTER("SendTls13CertificateRequest");
@@ -7297,13 +7443,13 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx,
         return SIDE_ERROR;
 
     /* Get the length of the hashSigAlgo buffer */
-    InitSuitesHashSigAlgo_ex(NULL, 1, 1, 1, 1, 0, 1, ssl->buffers.keySz,
-                             &hashSigAlgoSz);
+    InitSuitesHashSigAlgo_ex2(NULL, haveSig, 1, ssl->buffers.keySz,
+        &hashSigAlgoSz);
     sa = TLSX_SignatureAlgorithms_New(ssl, hashSigAlgoSz, ssl->heap);
     if (sa == NULL)
         return MEMORY_ERROR;
-    InitSuitesHashSigAlgo_ex(sa->hashSigAlgo, 1, 1, 1, 1, 0, 1,
-                             ssl->buffers.keySz, &sa->hashSigAlgoSz);
+    InitSuitesHashSigAlgo_ex2(sa->hashSigAlgo, haveSig, 1, ssl->buffers.keySz,
+        &hashSigAlgoSz);
     ret = TLSX_Push(&ssl->extensions, TLSX_SIGNATURE_ALGORITHMS, sa, ssl->heap);
     if (ret != 0) {
         TLSX_SignatureAlgorithms_FreeAll(sa, ssl->heap);
@@ -7412,6 +7558,12 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output)
             output[1] = ecc_dsa_sa_algo;
             break;
 #endif
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+        case sm2_sa_algo:
+            output[0] = SM2_SA_MAJOR;
+            output[1] = SM2_SA_MINOR;
+            break;
+#endif
 #ifdef HAVE_ED25519
         /* ED25519: 0x0807 */
         case ed25519_sa_algo:
@@ -7479,6 +7631,16 @@ static WC_INLINE int DecodeTls13SigAlg(byte* input, byte* hashAlgo,
     int ret = 0;
 
     switch (input[0]) {
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+        case SM2_SA_MAJOR:
+            if (input[1] == SM2_SA_MINOR) {
+                *hsType = sm2_sa_algo;
+                *hashAlgo = sm3_mac;
+            }
+            else
+                ret = INVALID_PARAMETER;
+            break;
+    #endif
         case NEW_SA_MAJOR:
             /* PSS signatures: 0x080[4-6] */
             if (input[1] >= sha256_mac && input[1] <= sha512_mac) {
@@ -7579,6 +7741,13 @@ static WC_INLINE int GetMsgHash(WOLFSSL* ssl, byte* hash)
                 ret = WC_SHA512_DIGEST_SIZE;
             break;
     #endif /* WOLFSSL_TLS13_SHA512 */
+    #ifdef WOLFSSL_SM3
+        case sm3_mac:
+            ret = wc_Sm3GetHash(&ssl->hsHashes->hashSm3, hash);
+            if (ret == 0)
+                ret = WC_SM3_DIGEST_SIZE;
+            break;
+    #endif /* WOLFSSL_SM3 */
         default:
             break;
     }
@@ -8358,8 +8527,17 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl)
             if (ssl->hsType == DYNAMIC_TYPE_RSA)
                 args->sigAlgo = rsa_pss_sa_algo;
         #ifdef HAVE_ECC
-            else if (ssl->hsType == DYNAMIC_TYPE_ECC)
-                args->sigAlgo = ecc_dsa_sa_algo;
+            else if (ssl->hsType == DYNAMIC_TYPE_ECC) {
+        #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                if (ssl->buffers.keyType == sm2_sa_algo) {
+                    args->sigAlgo = sm2_sa_algo;
+                }
+                else
+        #endif
+                {
+                    args->sigAlgo = ecc_dsa_sa_algo;
+                }
+            }
         #endif
         #ifdef HAVE_ED25519
             else if (ssl->hsType == DYNAMIC_TYPE_ED25519)
@@ -8460,12 +8638,17 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl)
             if (ssl->hsType == DYNAMIC_TYPE_ECC) {
                 sig->length = args->sendSz - args->idx - HASH_SIG_SIZE -
                               VERIFY_HEADER;
-                ret = CreateECCEncodedSig(args->sigData,
-                    args->sigDataSz, ssl->options.hashAlgo);
-                if (ret < 0)
-                    goto exit_scv;
-                args->sigDataSz = (word16)ret;
-                ret = 0;
+            #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                if (ssl->buffers.keyType != sm2_sa_algo)
+            #endif
+                {
+                    ret = CreateECCEncodedSig(args->sigData,
+                        args->sigDataSz, ssl->options.hashAlgo);
+                    if (ret < 0)
+                        goto exit_scv;
+                    args->sigDataSz = (word16)ret;
+                    ret = 0;
+                }
             }
         #endif /* HAVE_ECC */
         #ifdef HAVE_ED25519
@@ -8507,16 +8690,27 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl)
         case TLS_ASYNC_DO:
         {
         #ifdef HAVE_ECC
-           if (ssl->hsType == DYNAMIC_TYPE_ECC) {
-                ret = EccSign(ssl, args->sigData, args->sigDataSz,
-                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
-                    (word32*)&sig->length, (ecc_key*)ssl->hsKey,
-            #ifdef HAVE_PK_CALLBACKS
-                    ssl->buffers.key
-            #else
-                    NULL
+            if (ssl->hsType == DYNAMIC_TYPE_ECC) {
+            #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                if (ssl->buffers.keyType == sm2_sa_algo) {
+                    ret = Sm2wSm3Sign(ssl, TLS13_SM2_SIG_ID,
+                        TLS13_SM2_SIG_ID_SZ, args->sigData, args->sigDataSz,
+                        args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
+                        (word32*)&sig->length, (ecc_key*)ssl->hsKey, NULL);
+                }
+                else
             #endif
-                );
+                {
+                    ret = EccSign(ssl, args->sigData, args->sigDataSz,
+                        args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
+                        (word32*)&sig->length, (ecc_key*)ssl->hsKey,
+                #ifdef HAVE_PK_CALLBACKS
+                        ssl->buffers.key
+                #else
+                        NULL
+                #endif
+                    );
+                }
                 args->length = (word16)sig->length;
             }
         #endif /* HAVE_ECC */
@@ -8612,17 +8806,29 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl)
             }
         #endif /* !NO_RSA */
         #if defined(HAVE_ECC) && defined(WOLFSSL_CHECK_SIG_FAULTS)
-           if (ssl->hsType == DYNAMIC_TYPE_ECC) {
-                ret = EccVerify(ssl,
-                    args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
-                    sig->length, args->sigData, args->sigDataSz,
-                    (ecc_key*)ssl->hsKey,
-            #ifdef HAVE_PK_CALLBACKS
-                    ssl->buffers.key
-            #else
-                    NULL
+            if (ssl->hsType == DYNAMIC_TYPE_ECC) {
+            #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                if (ssl->buffers.keyType == sm2_sa_algo) {
+                    ret = Sm2wSm3Verify(ssl, TLS13_SM2_SIG_ID,
+                        TLS13_SM2_SIG_ID_SZ,
+                        args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
+                        sig->length, args->sigData, args->sigDataSz,
+                        (ecc_key*)ssl->hsKey, NULL);
+                }
+                else
             #endif
-                );
+                {
+                    ret = EccVerify(ssl,
+                        args->verify + HASH_SIG_SIZE + VERIFY_HEADER,
+                        sig->length, args->sigData, args->sigDataSz,
+                        (ecc_key*)ssl->hsKey,
+                #ifdef HAVE_PK_CALLBACKS
+                        ssl->buffers.key
+                #else
+                        NULL
+                #endif
+                    );
+                }
             }
         #endif
 
@@ -8948,6 +9154,13 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
                                                       ssl->peerEccDsaKeyPresent;
             }
         #endif
+        #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+            if (args->sigAlgo == sm2_sa_algo) {
+                WOLFSSL_MSG("Peer sent SM2 sig");
+                validSigAlgo = (ssl->peerEccDsaKey != NULL) &&
+                                                      ssl->peerEccDsaKeyPresent;
+            }
+        #endif
         #ifdef HAVE_PQC
             if (args->sigAlgo == falcon_level1_sa_algo) {
                 WOLFSSL_MSG("Peer sent Falcon Level 1 sig");
@@ -9012,12 +9225,17 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
                 ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 1);
                 if (ret != 0)
                     goto exit_dcv;
-                ret = CreateECCEncodedSig(args->sigData,
-                    args->sigDataSz, args->hashAlgo);
-                if (ret < 0)
-                    goto exit_dcv;
-                args->sigDataSz = (word16)ret;
-                ret = 0;
+            #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                if (args->sigAlgo != sm2_sa_algo)
+            #endif
+                {
+                    ret = CreateECCEncodedSig(args->sigData,
+                        args->sigDataSz, args->hashAlgo);
+                    if (ret < 0)
+                        goto exit_dcv;
+                    args->sigDataSz = (word16)ret;
+                    ret = 0;
+                }
             }
         #endif
         #ifdef HAVE_ED25519
@@ -9101,15 +9319,26 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input,
         #endif /* !NO_RSA */
         #ifdef HAVE_ECC
             if (ssl->peerEccDsaKeyPresent) {
-                ret = EccVerify(ssl, input + args->idx, args->sz,
-                    args->sigData, args->sigDataSz,
-                    ssl->peerEccDsaKey,
-                #ifdef HAVE_PK_CALLBACKS
-                    &ssl->buffers.peerEccDsaKey
-                #else
-                    NULL
-                #endif
-                );
+            #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                if (args->sigAlgo == sm2_sa_algo) {
+                    ret = Sm2wSm3Verify(ssl, TLS13_SM2_SIG_ID,
+                        TLS13_SM2_SIG_ID_SZ, input + args->idx, args->sz,
+                        args->sigData, args->sigDataSz,
+                        ssl->peerEccDsaKey, NULL);
+                }
+                else
+            #endif
+                {
+                    ret = EccVerify(ssl, input + args->idx, args->sz,
+                        args->sigData, args->sigDataSz,
+                        ssl->peerEccDsaKey,
+                    #ifdef HAVE_PK_CALLBACKS
+                        &ssl->buffers.peerEccDsaKey
+                    #else
+                        NULL
+                    #endif
+                    );
+                }
 
                 if (ret >= 0) {
                     /* CLIENT/SERVER: data verified with public key from
@@ -10254,6 +10483,13 @@ static int ExpectedResumptionSecret(WOLFSSL* ssl)
                 return ret;
             break;
     #endif
+    #ifdef WOLFSSL_SM3
+        case sm3_mac:
+            ret = wc_Sm3Copy(&ssl->hsHashes->hashSm3, &digest.sm3);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
     }
 
     /* Generate the Client's Finished message and hash it. */
@@ -10307,6 +10543,15 @@ static int ExpectedResumptionSecret(WOLFSSL* ssl)
                 return ret;
             break;
     #endif
+    #ifdef WOLFSSL_SM3
+        case sm3_mac:
+            wc_Sm3Free(&ssl->hsHashes->hashSm3);
+            ret = wc_Sm3Copy(&digest.sm3, &ssl->hsHashes->hashSm3);
+            wc_Sm3Free(&digest.sm3);
+            if (ret != 0)
+                return ret;
+            break;
+    #endif
     }
 
     return ret;

File diff suppressed because it is too large
+ 963 - 5
tests/api.c


+ 1 - 0
tests/include.am

@@ -66,6 +66,7 @@ EXTRA_DIST += tests/unit.h \
               tests/test-dhprime.conf \
               tests/test-p521.conf \
               tests/test-ecc-cust-curves.conf \
+              tests/test-sm2.conf \
               tests/NCONF_test.cnf \
               tests/test-tls-downgrade.conf \
               tests/TXT_DB.txt

+ 12 - 0
tests/suites.c

@@ -1275,6 +1275,18 @@ int SuiteTest(int argc, char** argv)
     }
 #endif /* HAVE_RSA and HAVE_ECC */
 #endif /* !WC_STRICT_SIG */
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) && \
+    (defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM))
+    /* add SM2/SM3/SM4 test suites */
+    XSTRLCPY(argv0[1], "tests/test-sm2.conf", sizeof(argv0[1]));
+    printf("starting SM2/SM3/SM4 cipher suite tests\n");
+    test_harness(&args);
+    if (args.return_code != 0) {
+        printf("error from script %d\n", args.return_code);
+        args.return_code = EXIT_FAILURE;
+        goto exit;
+    }
+#endif
 #ifndef NO_PSK
     #ifndef WOLFSSL_NO_TLS12
         #if !defined(NO_RSA) || defined(HAVE_ECC)

+ 189 - 0
tests/test-sm2.conf

@@ -0,0 +1,189 @@
+# server TLSv1.2 ECDHE-ECDSA-SM4-CBC-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CBC-SM3
+-c ./certs/sm2/server-sm2.pem
+-k ./certs/sm2/server-sm2-priv.pem
+-d
+
+# client TLSv1.2 ECDHE-ECDSA-SM4-CBC-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CBC-SM3
+-A ./certs/sm2/root-sm2.pem
+-C
+
+# server TLSv1.2 ECDHE-ECDSA-SM4-CBC-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CBC-SM3
+-c ./certs/sm2/server-sm2.pem
+-k ./certs/sm2/server-sm2-priv.pem
+-d
+
+# client TLSv1.2 ECDHE-ECDSA-SM4-CBC-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CBC-SM3
+-A ./certs/sm2/root-sm2.pem
+-C
+
+# server TLSv1.2 ECDHE-ECDSA-SM4-CBC-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CBC-SM3
+-c ./certs/sm2/server-sm2.pem
+-k ./certs/sm2/server-sm2-priv.pem
+-A ./certs/sm2/client-sm2.pem
+-V
+# Remove -V when CRL for SM2 certificates available.
+
+# client TLSv1.2 ECDHE-ECDSA-SM4-CBC-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CBC-SM3
+-c ./certs/sm2/client-sm2.pem
+-k ./certs/sm2/client-sm2-priv.pem
+-A ./certs/sm2/root-sm2.pem
+-C
+
+# server TLSv1.2 ECDHE-ECDSA-SM4-GCM-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-GCM-SM3
+-c ./certs/sm2/server-sm2.pem
+-k ./certs/sm2/server-sm2-priv.pem
+-d
+
+# client TLSv1.2 ECDHE-ECDSA-SM4-GCM-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-GCM-SM3
+-A ./certs/sm2/root-sm2.pem
+-C
+
+# server TLSv1.2 ECDHE-ECDSA-SM4-CCM-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CCM-SM3
+-c ./certs/sm2/server-sm2.pem
+-k ./certs/sm2/server-sm2-priv.pem
+-d
+
+# client TLSv1.2 ECDHE-ECDSA-SM4-CCM-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CCM-SM3
+-A ./certs/sm2/root-sm2.pem
+-C
+
+# server TLSv1.3 TLS13-SM4-GCM-SM3
+-v 4
+-l TLS13-SM4-GCM-SM3
+-c ./certs/sm2/server-sm2.pem
+-k ./certs/sm2/server-sm2-priv.pem
+-d
+
+# client TLSv1.3 TLS13-SM4-GCM-SM3
+-v 4
+-l TLS13-SM4-GCM-SM3
+-A ./certs/sm2/root-sm2.pem
+-C
+
+# server TLSv1.3 TLS13-SM4-CCM-SM3
+-v 4
+-l TLS13-SM4-CCM-SM3
+-c ./certs/sm2/server-sm2.pem
+-k ./certs/sm2/server-sm2-priv.pem
+-d
+
+# client TLSv1.3 TLS13-SM4-CCM-SM3
+-v 4
+-l TLS13-SM4-CCM-SM3
+-A ./certs/sm2/root-sm2.pem
+-C
+
+# Enable when CRL for SM2 certificates available.
+# server TLSv1.3 TLS13-SM4-GCM-SM3
+-v 4
+-l TLS13-SM4-GCM-SM3
+-c ./certs/sm2/server-sm2.pem
+-k ./certs/sm2/server-sm2-priv.pem
+-A ./certs/sm2/client-sm2.pem
+-V
+# Remove -V when CRL for SM2 certificates available.
+
+# client TLSv1.3 TLS13-SM4-GCM-SM3
+-v 4
+-l TLS13-SM4-GCM-SM3
+-c ./certs/sm2/client-sm2.pem
+-k ./certs/sm2/client-sm2-priv.pem
+-A ./certs/sm2/root-sm2.pem
+-C
+
+# Enable when CRL for SM2 certificates available.
+# server TLSv1.3 TLS13-SM4-CCM-SM3
+-v 4
+-l TLS13-SM4-CCM-SM3
+-c ./certs/sm2/server-sm2.pem
+-k ./certs/sm2/server-sm2-priv.pem
+-A ./certs/sm2/client-sm2.pem
+-V
+# Remove -V when CRL for SM2 certificates available.
+
+# client TLSv1.3 TLS13-SM4-CCM-SM3
+-v 4
+-l TLS13-SM4-CCM-SM3
+-c ./certs/sm2/client-sm2.pem
+-k ./certs/sm2/client-sm2-priv.pem
+-A ./certs/sm2/root-sm2.pem
+-C
+
+# GmSSL certificates and keys
+# server TLSv1.2 ECDHE-ECDSA-SM4-CBC-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CBC-SM3
+-c ./certs/sm2/self-sm2-cert.pem
+-k ./certs/sm2/self-sm2-priv.pem
+-d
+
+# client TLSv1.2 ECDHE-ECDSA-SM4-CBC-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CBC-SM3
+-A ./certs/sm2/self-sm2-cert.pem
+-C
+
+# server TLSv1.2 ECDHE-ECDSA-SM4-CBC-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CBC-SM3
+-c ./certs/sm2/self-sm2-cert.pem
+-k ./certs/sm2/self-sm2-priv.pem
+-A ./certs/sm2/self-sm2-cert.pem
+-V
+
+# client TLSv1.2 ECDHE-ECDSA-SM4-CBC-SM3
+-v 3
+-l ECDHE-ECDSA-SM4-CBC-SM3
+-A ./certs/sm2/self-sm2-cert.pem
+-c ./certs/sm2/self-sm2-cert.pem
+-k ./certs/sm2/self-sm2-priv.pem
+-C
+
+# server TLSv1.3 TLS13-SM4-GCM-SM3
+-v 4
+-l TLS13-SM4-GCM-SM3
+-c ./certs/sm2/self-sm2-cert.pem
+-k ./certs/sm2/self-sm2-priv.pem
+-d
+
+# client TLSv1.3 TLS13-SM4-GCM-SM3
+-v 4
+-l TLS13-SM4-GCM-SM3
+-A ./certs/sm2/self-sm2-cert.pem
+-C
+
+# server TLSv1.3 TLS13-SM4-GCM-SM3
+-v 4
+-l TLS13-SM4-GCM-SM3
+-c ./certs/sm2/self-sm2-cert.pem
+-k ./certs/sm2/self-sm2-priv.pem
+-A ./certs/sm2/self-sm2-cert.pem
+-V
+
+# client TLSv1.3 TLS13-SM4-GCM-SM3
+-v 4
+-l TLS13-SM4-GCM-SM3
+-A ./certs/sm2/self-sm2-cert.pem
+-c ./certs/sm2/self-sm2-cert.pem
+-k ./certs/sm2/self-sm2-priv.pem
+-C

+ 4 - 4
tests/unit.h

@@ -189,17 +189,17 @@
 
 #define ExpectPtr(x, y, op, er) do {                                           \
     if (_ret != TEST_FAIL) {                                                   \
-        PRAGMA_DIAG_PUSH;                                                      \
+        PRAGMA_GCC_DIAG_PUSH;                                                  \
           /* remarkably, without this inhibition, */                           \
           /* the _Pragma()s make the declarations warn. */                     \
-        PRAGMA("GCC diagnostic ignored \"-Wdeclaration-after-statement\"");    \
+        PRAGMA_GCC("GCC diagnostic ignored \"-Wdeclaration-after-statement\"");\
           /* inhibit "ISO C forbids conversion of function pointer */          \
           /* to object pointer type [-Werror=pedantic]" */                     \
-        PRAGMA("GCC diagnostic ignored \"-Wpedantic\"");                       \
+        PRAGMA_GCC("GCC diagnostic ignored \"-Wpedantic\"");                   \
         void* _x = (void*)(x);                                                 \
         void* _y = (void*)(y);                                                 \
         Expect(_x op _y, ("%s " #op " %s", #x, #y), ("%p " #er " %p", _x, _y));\
-        PRAGMA_DIAG_POP;                                                       \
+        PRAGMA_GCC_DIAG_POP;                                                   \
     }                                                                          \
 } while(0)
 

+ 594 - 0
wolfcrypt/benchmark/benchmark.c

@@ -79,6 +79,9 @@
 #ifdef HAVE_CAMELLIA
     #include <wolfssl/wolfcrypt/camellia.h>
 #endif
+#ifdef WOLFSSL_SM4
+    #include <wolfssl/wolfcrypt/sm4.h>
+#endif
 #ifndef NO_MD5
     #include <wolfssl/wolfcrypt/md5.h>
 #endif
@@ -94,6 +97,9 @@
 #ifdef WOLFSSL_SHA3
     #include <wolfssl/wolfcrypt/sha3.h>
 #endif
+#ifdef WOLFSSL_SM3
+     #include <wolfssl/wolfcrypt/sm3.h>
+#endif
 #ifndef NO_RSA
     #include <wolfssl/wolfcrypt/rsa.h>
 #endif
@@ -124,6 +130,9 @@
 #ifdef HAVE_ECC
     #include <wolfssl/wolfcrypt/ecc.h>
 #endif
+#ifdef WOLFSSL_SM2
+    #include <wolfssl/wolfcrypt/sm2.h>
+#endif
 #ifdef HAVE_CURVE25519
     #include <wolfssl/wolfcrypt/curve25519.h>
 #endif
@@ -472,6 +481,10 @@
 #define BENCH_AES_CFB            0x00010000
 #define BENCH_AES_OFB            0x00020000
 #define BENCH_AES_SIV            0x00040000
+#define BENCH_SM4_CBC            0x00080000
+#define BENCH_SM4_GCM            0x00100000
+#define BENCH_SM4_CCM            0x00200000
+#define BENCH_SM4                (BENCH_SM4_CBC | BENCH_SM4_GCM | BENCH_SM4_CCM)
 /* Digest algorithms. */
 #define BENCH_MD5                0x00000001
 #define BENCH_POLY1305           0x00000002
@@ -494,6 +507,7 @@
 #define BENCH_RIPEMD             0x00004000
 #define BENCH_BLAKE2B            0x00008000
 #define BENCH_BLAKE2S            0x00010000
+#define BENCH_SM3                0x00020000
 
 /* MAC algorithms. */
 #define BENCH_CMAC               0x00000001
@@ -530,6 +544,7 @@
 #define BENCH_ECC_P256           0x01000000
 #define BENCH_ECC_P384           0x02000000
 #define BENCH_ECC_P521           0x04000000
+#define BENCH_SM2                0x08000000
 #define BENCH_ECCSI_KEYGEN       0x00000020
 #define BENCH_ECCSI_PAIRGEN      0x00000040
 #define BENCH_ECCSI_VALIDATE     0x00000080
@@ -646,6 +661,18 @@ static const bench_alg bench_cipher_opt[] = {
 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
     { "-chacha20-poly1305",  BENCH_CHACHA20_POLY1305 },
 #endif
+#ifdef WOLFSSL_SM4_CBC
+    { "-sm4-cbc",            BENCH_SM4_CBC           },
+#endif
+#ifdef WOLFSSL_SM4_GCM
+    { "-sm4-gcm",            BENCH_SM4_GCM           },
+#endif
+#ifdef WOLFSSL_SM4_CCM
+    { "-sm4-ccm",            BENCH_SM4_CCM           },
+#endif
+#ifdef WOLFSSL_SM4
+    { "-sm4",                BENCH_SM4               },
+#endif
 #ifndef NO_DES3
     { "-des",                BENCH_DES               },
 #endif
@@ -704,6 +731,9 @@ static const bench_alg bench_digest_opt[] = {
     { "-shake256",           BENCH_SHAKE256          },
     #endif
 #endif
+#ifdef WOLFSSL_SM3
+    { "-sm3",                BENCH_SM3               },
+#endif
 #ifdef WOLFSSL_RIPEMD
     { "-ripemd",             BENCH_RIPEMD            },
 #endif
@@ -776,6 +806,9 @@ static const bench_alg bench_asym_opt[] = {
     #endif
     { "-ecc-all",            BENCH_ECC_ALL           },
 #endif
+#ifdef WOLFSSL_SM2
+    { "-sm2",                BENCH_SM2               },
+#endif
 #ifdef HAVE_CURVE25519
     { "-curve25519-kg",      BENCH_CURVE25519_KEYGEN },
     #ifdef HAVE_CURVE25519_SHARED_SECRET
@@ -2401,6 +2434,18 @@ static void* benchmarks_do(void* args)
     if (bench_all || (bench_cipher_algs & BENCH_CAMELLIA))
         bench_camellia();
 #endif
+#ifdef WOLFSSL_SM4_CBC
+    if (bench_all || (bench_cipher_algs & BENCH_SM4_CBC))
+        bench_sm4_cbc();
+#endif
+#ifdef WOLFSSL_SM4_GCM
+    if (bench_all || (bench_cipher_algs & BENCH_SM4_GCM))
+        bench_sm4_gcm();
+#endif
+#ifdef WOLFSSL_SM4_CCM
+    if (bench_all || (bench_cipher_algs & BENCH_SM4_CCM))
+        bench_sm4_ccm();
+#endif
 #ifndef NO_RC4
     if (bench_all || (bench_cipher_algs & BENCH_ARC4)) {
     #ifndef NO_SW_BENCH
@@ -2580,6 +2625,16 @@ static void* benchmarks_do(void* args)
     }
     #endif /* WOLFSSL_SHAKE256 */
 #endif
+#ifdef WOLFSSL_SM3
+    if (bench_all || (bench_digest_algs & BENCH_SM3)) {
+    #ifndef NO_SW_BENCH
+        bench_sm3(0);
+    #endif
+    #ifdef BENCH_DEVID
+        bench_sm3(1);
+    #endif
+    }
+#endif
 #ifdef WOLFSSL_RIPEMD
     if (bench_all || (bench_digest_algs & BENCH_RIPEMD))
         bench_ripemd();
@@ -2810,6 +2865,11 @@ static void* benchmarks_do(void* args)
         }
     }
 #endif
+#ifdef WOLFSSL_SM2
+    if (bench_all || (bench_asym_algs & BENCH_SM2)) {
+        bench_sm2(0);
+    }
+#endif
 
 #ifdef HAVE_CURVE25519
     if (bench_all || (bench_asym_algs & BENCH_CURVE25519_KEYGEN)) {
@@ -4284,7 +4344,171 @@ void bench_camellia(void)
 }
 #endif
 
+#ifdef WOLFSSL_SM4_CBC
+void bench_sm4_cbc(void)
+{
+    wc_Sm4 sm4;
+    double start;
+    int    ret;
+    int    i;
+    int    count;
+
+    ret = wc_Sm4SetKey(&sm4, bench_key, SM4_KEY_SIZE);
+    if (ret != 0) {
+        printf("Sm4SetKey failed, ret = %d\n", ret);
+        return;
+    }
+    ret = wc_Sm4SetIV(&sm4, bench_iv);
+    if (ret != 0) {
+        printf("Sm4SetIV failed, ret = %d\n", ret);
+        return;
+    }
+
+    bench_stats_start(&count, &start);
+    do {
+        for (i = 0; i < numBlocks; i++) {
+            ret = wc_Sm4CbcEncrypt(&sm4, bench_cipher, bench_plain, bench_size);
+            if (ret < 0) {
+                printf("Sm4CbcEncrypt failed: %d\n", ret);
+                return;
+            }
+        }
+        count += i;
+    } while (bench_stats_check(start));
+    bench_stats_sym_finish("SM4-CBC-enc", 0, count, bench_size, start, ret);
+
+    bench_stats_start(&count, &start);
+    do {
+        for (i = 0; i < numBlocks; i++) {
+            ret = wc_Sm4CbcDecrypt(&sm4, bench_plain, bench_cipher, bench_size);
+            if (ret < 0) {
+                printf("Sm4CbcDecrypt failed: %d\n", ret);
+                return;
+            }
+        }
+        count += i;
+    } while (bench_stats_check(start));
+    bench_stats_sym_finish("SM4-CBC-dec", 0, count, bench_size, start, ret);
+}
+#endif
+
+#ifdef WOLFSSL_SM4_GCM
+void bench_sm4_gcm(void)
+{
+    wc_Sm4 sm4;
+    double start;
+    int    ret;
+    int    i;
+    int    count;
+
+    WC_DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT);
+    WC_DECLARE_VAR(bench_tag, byte, AES_AUTH_TAG_SZ, HEAP_HINT);
+#ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC
+    if (bench_additional == NULL || bench_tag == NULL) {
+        printf("bench_aesgcm_internal malloc failed\n");
+        return;
+    }
+#endif
+
+    ret = wc_Sm4GcmSetKey(&sm4, bench_key, SM4_KEY_SIZE);
+    if (ret != 0) {
+        printf("Sm4GcmSetKey failed, ret = %d\n", ret);
+        return;
+    }
+
+    bench_stats_start(&count, &start);
+    do {
+        for (i = 0; i < numBlocks; i++) {
+            ret = wc_Sm4GcmEncrypt(&sm4, bench_cipher, bench_plain, bench_size,
+                bench_iv, GCM_NONCE_MID_SZ, bench_tag, SM4_BLOCK_SIZE,
+                bench_additional, aesAuthAddSz);
+            if (ret < 0) {
+                printf("Sm4GcmEncrypt failed: %d\n", ret);
+                return;
+            }
+        }
+        count += i;
+    } while (bench_stats_check(start));
+    bench_stats_sym_finish("SM4-GCM-enc", 0, count, bench_size, start, ret);
+
+    bench_stats_start(&count, &start);
+    do {
+        for (i = 0; i < numBlocks; i++) {
+            ret = wc_Sm4GcmDecrypt(&sm4, bench_plain, bench_cipher, bench_size,
+                bench_iv, GCM_NONCE_MID_SZ, bench_tag, SM4_BLOCK_SIZE,
+                bench_additional, aesAuthAddSz);
+            if (ret < 0) {
+                printf("Sm4GcmDecrypt failed: %d\n", ret);
+                return;
+            }
+        }
+        count += i;
+    } while (bench_stats_check(start));
+    bench_stats_sym_finish("SM4-GCM-dec", 0, count, bench_size, start, ret);
+}
+#endif
+
+#ifdef WOLFSSL_SM4_CCM
+void bench_sm4_ccm()
+{
+    wc_Sm4 enc;
+    double start;
+    int    ret, i, count;
+
+    WC_DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT);
+    WC_DECLARE_VAR(bench_tag, byte, AES_AUTH_TAG_SZ, HEAP_HINT);
+
+#ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC
+    if (bench_additional == NULL || bench_tag == NULL) {
+        printf("bench_aesccm malloc failed\n");
+        goto exit;
+    }
+#endif
+
+    XMEMSET(bench_tag, 0, AES_AUTH_TAG_SZ);
+    XMEMSET(bench_additional, 0, AES_AUTH_ADD_SZ);
 
+    if ((ret = wc_Sm4SetKey(&enc, bench_key, 16)) != 0) {
+        printf("wc_Sm4SetKey failed, ret = %d\n", ret);
+        goto exit;
+    }
+
+    bench_stats_start(&count, &start);
+    do {
+        for (i = 0; i < numBlocks; i++) {
+            ret |= wc_Sm4CcmEncrypt(&enc, bench_cipher, bench_plain, bench_size,
+                bench_iv, 12, bench_tag, AES_AUTH_TAG_SZ,
+                bench_additional, 0);
+        }
+        count += i;
+    } while (bench_stats_check(start));
+    bench_stats_sym_finish("SM4-CCM-enc", 0, count, bench_size, start, ret);
+    if (ret != 0) {
+        printf("wc_Sm4Encrypt failed, ret = %d\n", ret);
+        goto exit;
+    }
+
+    bench_stats_start(&count, &start);
+    do {
+        for (i = 0; i < numBlocks; i++) {
+            ret |= wc_Sm4CcmDecrypt(&enc, bench_plain, bench_cipher, bench_size,
+                bench_iv, 12, bench_tag, AES_AUTH_TAG_SZ,
+                bench_additional, 0);
+        }
+        count += i;
+    } while (bench_stats_check(start));
+    bench_stats_sym_finish("SM4-CCM-dec", 0, count, bench_size, start, ret);
+    if (ret != 0) {
+        printf("wc_Sm4Decrypt failed, ret = %d\n", ret);
+        goto exit;
+    }
+
+  exit:
+
+    WC_FREE_VAR(bench_additional, HEAP_HINT);
+    WC_FREE_VAR(bench_tag, HEAP_HINT);
+}
+#endif /* HAVE_AESCCM */
 #ifndef NO_DES3
 void bench_des(int useDeviceID)
 {
@@ -5771,6 +5995,96 @@ exit:
 #endif /* WOLFSSL_SHAKE256 */
 #endif
 
+#ifdef WOLFSSL_SM3
+void bench_sm3(int useDeviceID)
+{
+    wc_Sm3 hash[BENCH_MAX_PENDING];
+    double start;
+    int    ret = 0, i, count = 0, times, pending = 0;
+    WC_DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SM3_DIGEST_SIZE,
+        HEAP_HINT);
+    WC_INIT_ARRAY(digest, byte, BENCH_MAX_PENDING, WC_SM3_DIGEST_SIZE,
+        HEAP_HINT);
+
+    /* clear for done cleanup */
+    XMEMSET(hash, 0, sizeof(hash));
+
+    if (digest_stream) {
+        /* init keys */
+        for (i = 0; i < BENCH_MAX_PENDING; i++) {
+            ret = wc_InitSm3(&hash[i], HEAP_HINT,
+                useDeviceID ? devId: INVALID_DEVID);
+            if (ret != 0) {
+                printf("InitSm3 failed, ret = %d\n", ret);
+                goto exit;
+            }
+        }
+
+        bench_stats_start(&count, &start);
+        do {
+            for (times = 0; times < numBlocks || pending > 0; ) {
+                bench_async_poll(&pending);
+
+                /* while free pending slots in queue, submit ops */
+                for (i = 0; i < BENCH_MAX_PENDING; i++) {
+                    if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]),
+                                              0, &times, numBlocks, &pending)) {
+                        ret = wc_Sm3Update(&hash[i], bench_plain,
+                            bench_size);
+                        if (!bench_async_handle(&ret,
+                            BENCH_ASYNC_GET_DEV(&hash[i]), 0, &times, &pending)) {
+                            goto exit_sm3;
+                        }
+                    }
+                } /* for i */
+            } /* for times */
+            count += times;
+
+            times = 0;
+            do {
+                bench_async_poll(&pending);
+                for (i = 0; i < BENCH_MAX_PENDING; i++) {
+                    if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]),
+                                              0, &times, numBlocks, &pending)) {
+                        ret = wc_Sm3Final(&hash[i], digest[i]);
+                        if (!bench_async_handle(&ret,
+                            BENCH_ASYNC_GET_DEV(&hash[i]), 0, &times, &pending)) {
+                            goto exit_sm3;
+                        }
+                    }
+                } /* for i */
+            } while (pending > 0);
+        } while (bench_stats_check(start));
+    }
+    else {
+        bench_stats_start(&count, &start);
+        do {
+            for (times = 0; times < numBlocks; times++) {
+                ret = wc_InitSm3(hash, HEAP_HINT,
+                    useDeviceID ? devId: INVALID_DEVID);
+                if (ret == 0)
+                    ret = wc_Sm3Update(hash, bench_plain, bench_size);
+                if (ret == 0)
+                    ret = wc_Sm3Final(hash, digest[0]);
+                if (ret != 0)
+                    goto exit_sm3;
+            } /* for times */
+            count += times;
+        } while (bench_stats_check(start));
+    }
+exit_sm3:
+    bench_stats_sym_finish("SM3", useDeviceID, count, bench_size, start, ret);
+
+exit:
+
+    for (i = 0; i < BENCH_MAX_PENDING; i++) {
+        wc_Sm3Free(&hash[i]);
+    }
+
+    WC_FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT);
+}
+#endif
+
 
 #ifdef WOLFSSL_RIPEMD
 void bench_ripemd(void)
@@ -7836,6 +8150,286 @@ exit:
 #endif
 }
 #endif
+
+#ifdef WOLFSSL_SM2
+static void bench_sm2_MakeKey(int useDeviceID)
+{
+    int ret = 0, i, times, count, pending = 0;
+    int deviceID;
+    int keySize;
+    ecc_key genKey[BENCH_MAX_PENDING];
+    char name[BENCH_ECC_NAME_SZ];
+    double start;
+    const char**desc = bench_desc_words[lng_index];
+
+    deviceID = useDeviceID ? devId : INVALID_DEVID;
+    keySize = wc_ecc_get_curve_size_from_id(ECC_SM2P256V1);
+
+    /* clear for done cleanup */
+    XMEMSET(&genKey, 0, sizeof(genKey));
+
+    /* ECC Make Key */
+    bench_stats_start(&count, &start);
+    do {
+        /* while free pending slots in queue, submit ops */
+        for (times = 0; times < agreeTimes || pending > 0; ) {
+            bench_async_poll(&pending);
+
+            for (i = 0; i < BENCH_MAX_PENDING; i++) {
+                if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0,
+                            &times, agreeTimes, &pending)) {
+
+                    wc_ecc_free(&genKey[i]);
+                    ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, deviceID);
+                    if (ret < 0) {
+                        goto exit;
+                    }
+
+                    ret = wc_ecc_sm2_make_key(&gRng, &genKey[i],
+                        WC_ECC_FLAG_NONE);
+                    if (!bench_async_handle(&ret,
+                                BENCH_ASYNC_GET_DEV(&genKey[i]), 0, &times,
+                                &pending)) {
+                        goto exit;
+                    }
+                }
+            } /* for i */
+        } /* for times */
+        count += times;
+    } while (bench_stats_check(start));
+exit:
+    (void)XSNPRINTF(name, BENCH_ECC_NAME_SZ, "ECC   [%15s]",
+            wc_ecc_get_name(ECC_SM2P256V1));
+    bench_stats_asym_finish(name, keySize * 8, desc[2], useDeviceID, count, start,
+            ret);
+
+    /* cleanup */
+    for (i = 0; i < BENCH_MAX_PENDING; i++) {
+        wc_ecc_free(&genKey[i]);
+    }
+}
+
+
+void bench_sm2(int useDeviceID)
+{
+    int ret = 0, i, times, count, pending = 0;
+    int deviceID;
+    int  keySize;
+    char name[BENCH_ECC_NAME_SZ];
+    ecc_key genKey[BENCH_MAX_PENDING];
+#ifdef HAVE_ECC_DHE
+    ecc_key genKey2[BENCH_MAX_PENDING];
+#endif
+#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN)
+#ifdef HAVE_ECC_VERIFY
+    int    verify[BENCH_MAX_PENDING];
+#endif
+#endif
+    word32 x[BENCH_MAX_PENDING];
+    double start = 0;
+    const char**desc = bench_desc_words[lng_index];
+
+#ifdef HAVE_ECC_DHE
+    WC_DECLARE_ARRAY(shared, byte, BENCH_MAX_PENDING, MAX_ECC_BYTES, HEAP_HINT);
+#endif
+#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN)
+    WC_DECLARE_ARRAY(sig, byte, BENCH_MAX_PENDING, ECC_MAX_SIG_SIZE, HEAP_HINT);
+    WC_DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, MAX_ECC_BYTES, HEAP_HINT);
+#endif
+
+#ifdef HAVE_ECC_DHE
+    WC_INIT_ARRAY(shared, byte, BENCH_MAX_PENDING, MAX_ECC_BYTES, HEAP_HINT);
+#endif
+#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN)
+    WC_INIT_ARRAY(sig, byte, BENCH_MAX_PENDING, ECC_MAX_SIG_SIZE, HEAP_HINT);
+    WC_INIT_ARRAY(digest, byte, BENCH_MAX_PENDING, MAX_ECC_BYTES, HEAP_HINT);
+#endif
+    deviceID = useDeviceID ? devId : INVALID_DEVID;
+
+    bench_sm2_MakeKey(useDeviceID);
+
+    /* clear for done cleanup */
+    XMEMSET(&genKey, 0, sizeof(genKey));
+#ifdef HAVE_ECC_DHE
+    XMEMSET(&genKey2, 0, sizeof(genKey2));
+#endif
+    keySize = wc_ecc_get_curve_size_from_id(ECC_SM2P256V1);
+
+    /* init keys */
+    for (i = 0; i < BENCH_MAX_PENDING; i++) {
+        /* setup an context for each key */
+        if ((ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, deviceID)) < 0) {
+            goto exit;
+        }
+        ret = wc_ecc_sm2_make_key(&gRng, &genKey[i], WC_ECC_FLAG_NONE);
+    #ifdef WOLFSSL_ASYNC_CRYPT
+        ret = wc_AsyncWait(ret, &genKey[i].asyncDev, WC_ASYNC_FLAG_NONE);
+    #endif
+        if (ret < 0) {
+            goto exit;
+        }
+
+    #ifdef HAVE_ECC_DHE
+        if ((ret = wc_ecc_init_ex(&genKey2[i], HEAP_HINT, deviceID)) < 0) {
+            goto exit;
+        }
+        if ((ret = wc_ecc_sm2_make_key(&gRng, &genKey2[i],
+                WC_ECC_FLAG_NONE)) > 0) {
+            goto exit;
+        }
+    #endif
+    }
+
+#ifdef HAVE_ECC_DHE
+#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
+    (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
+    !defined(HAVE_SELFTEST)
+    for (i = 0; i < BENCH_MAX_PENDING; i++) {
+        (void)wc_ecc_set_rng(&genKey[i], &gRng);
+    }
+#endif
+
+    /* ECC Shared Secret */
+    bench_stats_start(&count, &start);
+    PRIVATE_KEY_UNLOCK();
+    do {
+        for (times = 0; times < agreeTimes || pending > 0; ) {
+            bench_async_poll(&pending);
+
+            /* while free pending slots in queue, submit ops */
+            for (i = 0; i < BENCH_MAX_PENDING; i++) {
+                if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1,
+                            &times, agreeTimes, &pending)) {
+                    x[i] = (word32)keySize;
+                    ret = wc_ecc_sm2_shared_secret(&genKey[i], &genKey2[i],
+                            shared[i], &x[i]);
+                    if (!bench_async_handle(&ret,
+                                BENCH_ASYNC_GET_DEV(&genKey[i]), 1, &times,
+                                &pending)) {
+                        goto exit_ecdhe;
+                    }
+                }
+            } /* for i */
+        } /* for times */
+        count += times;
+    } while (bench_stats_check(start));
+    PRIVATE_KEY_UNLOCK();
+exit_ecdhe:
+    (void)XSNPRINTF(name, BENCH_ECC_NAME_SZ, "ECDHE [%15s]", wc_ecc_get_name(ECC_SM2P256V1));
+
+    bench_stats_asym_finish(name, keySize * 8, desc[3], useDeviceID, count, start,
+            ret);
+
+    if (ret < 0) {
+        goto exit;
+    }
+#endif /* HAVE_ECC_DHE */
+
+#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN)
+
+    /* Init digest to sign */
+    for (i = 0; i < BENCH_MAX_PENDING; i++) {
+        for (count = 0; count < keySize; count++) {
+            digest[i][count] = (byte)count;
+        }
+    }
+
+    /* ECC Sign */
+    bench_stats_start(&count, &start);
+    do {
+        for (times = 0; times < agreeTimes || pending > 0; ) {
+            bench_async_poll(&pending);
+
+            /* while free pending slots in queue, submit ops */
+            for (i = 0; i < BENCH_MAX_PENDING; i++) {
+                if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1,
+                            &times, agreeTimes, &pending)) {
+                    if (genKey[i].state == 0)
+                        x[i] = ECC_MAX_SIG_SIZE;
+                    ret = wc_ecc_sm2_sign_hash(digest[i], (word32)keySize,
+                            sig[i], &x[i], &gRng, &genKey[i]);
+                    if (!bench_async_handle(&ret,
+                                BENCH_ASYNC_GET_DEV(&genKey[i]), 1, &times,
+                                &pending)) {
+                        goto exit_ecdsa_sign;
+                    }
+                }
+            } /* for i */
+        } /* for times */
+        count += times;
+    } while (bench_stats_check(start));
+exit_ecdsa_sign:
+    (void)XSNPRINTF(name, BENCH_ECC_NAME_SZ, "ECDSA [%15s]", wc_ecc_get_name(ECC_SM2P256V1));
+
+    bench_stats_asym_finish(name, keySize * 8, desc[4], useDeviceID, count, start,
+            ret);
+
+    if (ret < 0) {
+        goto exit;
+    }
+
+#ifdef HAVE_ECC_VERIFY
+
+    /* ECC Verify */
+    bench_stats_start(&count, &start);
+    do {
+        for (times = 0; times < agreeTimes || pending > 0; ) {
+            bench_async_poll(&pending);
+
+            /* while free pending slots in queue, submit ops */
+            for (i = 0; i < BENCH_MAX_PENDING; i++) {
+                if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1,
+                            &times, agreeTimes, &pending)) {
+                    if (genKey[i].state == 0)
+                        verify[i] = 0;
+                    ret = wc_ecc_sm2_verify_hash(sig[i], x[i], digest[i],
+                                       (word32)keySize, &verify[i], &genKey[i]);
+                    if (!bench_async_handle(&ret,
+                                BENCH_ASYNC_GET_DEV(&genKey[i]), 1, &times,
+                                &pending)) {
+                        goto exit_ecdsa_verify;
+                    }
+                }
+            } /* for i */
+        } /* for times */
+        count += times;
+    } while (bench_stats_check(start));
+exit_ecdsa_verify:
+    (void)XSNPRINTF(name, BENCH_ECC_NAME_SZ, "ECDSA [%15s]", wc_ecc_get_name(ECC_SM2P256V1));
+
+    bench_stats_asym_finish(name, keySize * 8, desc[5], useDeviceID, count, start,
+            ret);
+#endif /* HAVE_ECC_VERIFY */
+#endif /* !NO_ASN && HAVE_ECC_SIGN */
+
+exit:
+
+    /* cleanup */
+    for (i = 0; i < BENCH_MAX_PENDING; i++) {
+        wc_ecc_free(&genKey[i]);
+    #ifdef HAVE_ECC_DHE
+        wc_ecc_free(&genKey2[i]);
+    #endif
+    }
+
+#ifdef HAVE_ECC_DHE
+    WC_FREE_ARRAY(shared, BENCH_MAX_PENDING, HEAP_HINT);
+#endif
+#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN)
+    WC_FREE_ARRAY(sig, BENCH_MAX_PENDING, HEAP_HINT);
+    WC_FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT);
+#endif
+
+    (void)useDeviceID;
+    (void)pending;
+    (void)x;
+    (void)count;
+    (void)times;
+    (void)desc;
+    (void)start;
+    (void)name;
+}
+#endif /* WOLFSSL_SM2 */
 #endif /* HAVE_ECC */
 
 #ifdef HAVE_CURVE25519

+ 5 - 0
wolfcrypt/benchmark/benchmark.h

@@ -61,6 +61,9 @@ void bench_aesofb(void);
 void bench_aessiv(void);
 void bench_poly1305(void);
 void bench_camellia(void);
+void bench_sm4_cbc(void);
+void bench_sm4_gcm(void);
+void bench_sm4_ccm(void);
 void bench_md5(int useDeviceID);
 void bench_sha(int useDeviceID);
 void bench_sha224(int useDeviceID);
@@ -81,6 +84,7 @@ void bench_sha3_384(int useDeviceID);
 void bench_sha3_512(int useDeviceID);
 void bench_shake128(int useDeviceID);
 void bench_shake256(int useDeviceID);
+void bench_sm3(int useDeviceID);
 void bench_ripemd(void);
 void bench_cmac(int useDeviceID);
 void bench_scrypt(void);
@@ -101,6 +105,7 @@ void bench_ecc_curve(int curveId);
 void bench_eccMakeKey(int useDeviceID, int curveId);
 void bench_ecc(int useDeviceID, int curveId);
 void bench_eccEncrypt(int curveId);
+void bench_sm2(int useDeviceID);
 void bench_curve25519KeyGen(int useDeviceID);
 void bench_curve25519KeyAgree(int useDeviceID);
 void bench_ed25519KeyGen(void);

+ 127 - 123
wolfcrypt/src/aes.c

@@ -4890,12 +4890,12 @@ static WC_INLINE void RIGHTSHIFTX(byte* x)
 
 #ifdef GCM_TABLE
 
-static void GenerateM0(Aes* aes)
+void GenerateM0(Gcm* gcm)
 {
     int i, j;
-    byte (*m)[AES_BLOCK_SIZE] = aes->M0;
+    byte (*m)[AES_BLOCK_SIZE] = gcm->M0;
 
-    XMEMCPY(m[128], aes->H, AES_BLOCK_SIZE);
+    XMEMCPY(m[128], gcm->H, AES_BLOCK_SIZE);
 
     for (i = 64; i > 0; i /= 2) {
         XMEMCPY(m[i], m[i*2], AES_BLOCK_SIZE);
@@ -4924,17 +4924,17 @@ static WC_INLINE void Shift4_M0(byte *r8, byte *z8)
 }
 #endif
 
-static void GenerateM0(Aes* aes)
+void GenerateM0(Gcm* gcm)
 {
 #if !defined(BIG_ENDIAN_ORDER) && !defined(WC_16BIT_CPU)
     int i;
 #endif
-    byte (*m)[AES_BLOCK_SIZE] = aes->M0;
+    byte (*m)[AES_BLOCK_SIZE] = gcm->M0;
 
     /* 0 times -> 0x0 */
     XMEMSET(m[0x0], 0, AES_BLOCK_SIZE);
     /* 1 times -> 0x8 */
-    XMEMCPY(m[0x8], aes->H, AES_BLOCK_SIZE);
+    XMEMCPY(m[0x8], gcm->H, AES_BLOCK_SIZE);
     /* 2 times -> 0x4 */
     XMEMCPY(m[0x4], m[0x8], AES_BLOCK_SIZE);
     RIGHTSHIFTX(m[0x4]);
@@ -5015,8 +5015,8 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
     }
 
 #ifdef OPENSSL_EXTRA
-    XMEMSET(aes->aadH, 0, sizeof(aes->aadH));
-    aes->aadLen = 0;
+    XMEMSET(aes->gcm.aadH, 0, sizeof(aes->gcm.aadH));
+    aes->gcm.aadLen = 0;
 #endif
     XMEMSET(iv, 0, AES_BLOCK_SIZE);
     ret = wc_AesSetKey(aes, key, len, iv, AES_ENCRYPTION);
@@ -5037,10 +5037,10 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
 
 #if !defined(FREESCALE_LTC_AES_GCM)
     if (ret == 0)
-        ret = wc_AesEncrypt(aes, iv, aes->H);
+        ret = wc_AesEncrypt(aes, iv, aes->gcm.H);
     if (ret == 0) {
     #if defined(GCM_TABLE) || defined(GCM_TABLE_4BIT)
-        GenerateM0(aes);
+        GenerateM0(&aes->gcm);
     #endif /* GCM_TABLE */
     }
 #endif /* FREESCALE_LTC_AES_GCM */
@@ -5147,7 +5147,7 @@ static void GMULT(byte* X, byte* Y)
 }
 
 
-void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
+void GHASH(Gcm* gcm, const byte* a, word32 aSz, const byte* c,
     word32 cSz, byte* s, word32 sSz)
 {
     byte x[AES_BLOCK_SIZE];
@@ -5155,11 +5155,11 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
     word32 blocks, partial;
     byte* h;
 
-    if (aes == NULL) {
+    if (gcm == NULL) {
         return;
     }
 
-    h = aes->H;
+    h = gcm->H;
     XMEMSET(x, 0, AES_BLOCK_SIZE);
 
     /* Hash in A, the Additional Authentication Data */
@@ -5223,7 +5223,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
 #define GHASH_ONE_BLOCK(aes, block)                     \
     do {                                                \
         xorbuf(AES_TAG(aes), block, AES_BLOCK_SIZE);    \
-        GMULT(AES_TAG(aes), aes->H);                    \
+        GMULT(AES_TAG(aes), aes->gcm.H);                \
     }                                                   \
     while (0)
 #endif /* WOLFSSL_AESGCM_STREAM */
@@ -5350,14 +5350,14 @@ static void GMULT(byte *x, byte m[256][AES_BLOCK_SIZE])
 #endif
 }
 
-void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
+void GHASH(Gcm* gcm, const byte* a, word32 aSz, const byte* c,
     word32 cSz, byte* s, word32 sSz)
 {
     byte x[AES_BLOCK_SIZE];
     byte scratch[AES_BLOCK_SIZE];
     word32 blocks, partial;
 
-    if (aes == NULL) {
+    if (gcm == NULL) {
         return;
     }
 
@@ -5369,14 +5369,14 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
         partial = aSz % AES_BLOCK_SIZE;
         while (blocks--) {
             xorbuf(x, a, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
+            GMULT(x, gcm->M0);
             a += AES_BLOCK_SIZE;
         }
         if (partial != 0) {
             XMEMSET(scratch, 0, AES_BLOCK_SIZE);
             XMEMCPY(scratch, a, partial);
             xorbuf(x, scratch, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
+            GMULT(x, gcm->M0);
         }
     }
 
@@ -5386,14 +5386,14 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
         partial = cSz % AES_BLOCK_SIZE;
         while (blocks--) {
             xorbuf(x, c, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
+            GMULT(x, gcm->M0);
             c += AES_BLOCK_SIZE;
         }
         if (partial != 0) {
             XMEMSET(scratch, 0, AES_BLOCK_SIZE);
             XMEMCPY(scratch, c, partial);
             xorbuf(x, scratch, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
+            GMULT(x, gcm->M0);
         }
     }
 
@@ -5401,7 +5401,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
     FlattenSzInBits(&scratch[0], aSz);
     FlattenSzInBits(&scratch[8], cSz);
     xorbuf(x, scratch, AES_BLOCK_SIZE);
-    GMULT(x, aes->M0);
+    GMULT(x, gcm->M0);
 
     /* Copy the result into s. */
     XMEMCPY(s, x, sSz);
@@ -5424,7 +5424,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
 #define GHASH_ONE_BLOCK(aes, block)                     \
     do {                                                \
         xorbuf(AES_TAG(aes), block, AES_BLOCK_SIZE);    \
-        GMULT(AES_TAG(aes), aes->M0);                   \
+        GMULT(AES_TAG(aes), aes->gcm.M0);               \
     }                                                   \
     while (0)
 #endif /* WOLFSSL_AESGCM_STREAM */
@@ -5650,14 +5650,14 @@ static WC_INLINE void GMULT(byte *x, byte m[32][AES_BLOCK_SIZE])
 }
 #endif
 
-void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
+void GHASH(Gcm* gcm, const byte* a, word32 aSz, const byte* c,
     word32 cSz, byte* s, word32 sSz)
 {
     byte x[AES_BLOCK_SIZE];
     byte scratch[AES_BLOCK_SIZE];
     word32 blocks, partial;
 
-    if (aes == NULL) {
+    if (gcm == NULL) {
         return;
     }
 
@@ -5669,14 +5669,14 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
         partial = aSz % AES_BLOCK_SIZE;
         while (blocks--) {
             xorbuf(x, a, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
+            GMULT(x, gcm->M0);
             a += AES_BLOCK_SIZE;
         }
         if (partial != 0) {
             XMEMSET(scratch, 0, AES_BLOCK_SIZE);
             XMEMCPY(scratch, a, partial);
             xorbuf(x, scratch, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
+            GMULT(x, gcm->M0);
         }
     }
 
@@ -5686,14 +5686,14 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
         partial = cSz % AES_BLOCK_SIZE;
         while (blocks--) {
             xorbuf(x, c, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
+            GMULT(x, gcm->M0);
             c += AES_BLOCK_SIZE;
         }
         if (partial != 0) {
             XMEMSET(scratch, 0, AES_BLOCK_SIZE);
             XMEMCPY(scratch, c, partial);
             xorbuf(x, scratch, AES_BLOCK_SIZE);
-            GMULT(x, aes->M0);
+            GMULT(x, gcm->M0);
         }
     }
 
@@ -5701,7 +5701,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
     FlattenSzInBits(&scratch[0], aSz);
     FlattenSzInBits(&scratch[8], cSz);
     xorbuf(x, scratch, AES_BLOCK_SIZE);
-    GMULT(x, aes->M0);
+    GMULT(x, gcm->M0);
 
     /* Copy the result into s. */
     XMEMCPY(s, x, sSz);
@@ -5724,7 +5724,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
 #define GHASH_ONE_BLOCK(aes, block)                     \
     do {                                                \
         xorbuf(AES_TAG(aes), block, AES_BLOCK_SIZE);    \
-        GMULT(AES_TAG(aes), (aes)->M0);                 \
+        GMULT(AES_TAG(aes), (aes)->gcm.M0);             \
     }                                                   \
     while (0)
 #endif /* WOLFSSL_AESGCM_STREAM */
@@ -5768,18 +5768,18 @@ static void GMULT(word64* X, word64* Y)
 }
 
 
-void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
+void GHASH(Gcm* gcm, const byte* a, word32 aSz, const byte* c,
     word32 cSz, byte* s, word32 sSz)
 {
     word64 x[2] = {0,0};
     word32 blocks, partial;
     word64 bigH[2];
 
-    if (aes == NULL) {
+    if (gcm == NULL) {
         return;
     }
 
-    XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE);
+    XMEMCPY(bigH, gcm->H, AES_BLOCK_SIZE);
     #ifdef LITTLE_ENDIAN_ORDER
         ByteReverseWords64(bigH, bigH, AES_BLOCK_SIZE);
     #endif
@@ -5811,10 +5811,10 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
         }
 #ifdef OPENSSL_EXTRA
         /* store AAD partial tag for next call */
-        aes->aadH[0] = (word32)((x[0] & 0xFFFFFFFF00000000ULL) >> 32);
-        aes->aadH[1] = (word32)(x[0] & 0xFFFFFFFF);
-        aes->aadH[2] = (word32)((x[1] & 0xFFFFFFFF00000000ULL) >> 32);
-        aes->aadH[3] = (word32)(x[1] & 0xFFFFFFFF);
+        gcm->aadH[0] = (word32)((x[0] & 0xFFFFFFFF00000000ULL) >> 32);
+        gcm->aadH[1] = (word32)(x[0] & 0xFFFFFFFF);
+        gcm->aadH[2] = (word32)((x[1] & 0xFFFFFFFF00000000ULL) >> 32);
+        gcm->aadH[3] = (word32)(x[1] & 0xFFFFFFFF);
 #endif
     }
 
@@ -5825,9 +5825,9 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
         partial = cSz % AES_BLOCK_SIZE;
 #ifdef OPENSSL_EXTRA
         /* Start from last AAD partial tag */
-        if(aes->aadLen) {
-            x[0] = ((word64)aes->aadH[0]) << 32 | aes->aadH[1];
-            x[1] = ((word64)aes->aadH[2]) << 32 | aes->aadH[3];
+        if(gcm->aadLen) {
+            x[0] = ((word64)gcm->aadH[0]) << 32 | gcm->aadH[1];
+            x[1] = ((word64)gcm->aadH[2]) << 32 | gcm->aadH[3];
          }
 #endif
         while (blocks--) {
@@ -5857,8 +5857,8 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
         word64 len[2];
         len[0] = aSz; len[1] = cSz;
 #ifdef OPENSSL_EXTRA
-        if (aes->aadLen)
-            len[0] = (word64)aes->aadLen;
+        if (gcm->aadLen)
+            len[0] = (word64)gcm->aadLen;
 #endif
         /* Lengths are in bytes. Convert to bits. */
         len[0] *= 8;
@@ -5884,7 +5884,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
  * @param [in] aes  AES GCM object.
  */
 #define GHASH_INIT_EXTRA(aes)                                               \
-    ByteReverseWords64((word64*)aes->H, (word64*)aes->H, AES_BLOCK_SIZE)
+    ByteReverseWords64((word64*)aes->gcm.H, (word64*)aes->gcm.H, AES_BLOCK_SIZE)
 
 /* GHASH one block of data..
  *
@@ -5896,7 +5896,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
 #define GHASH_ONE_BLOCK(aes, block)                             \
     do {                                                        \
         word64* x = (word64*)AES_TAG(aes);                      \
-        word64* h = (word64*)aes->H;                            \
+        word64* h = (word64*)aes->gcm.H;                        \
         word64 block64[2];                                      \
         XMEMCPY(block64, block, AES_BLOCK_SIZE);                \
         ByteReverseWords64(block64, block64, AES_BLOCK_SIZE);   \
@@ -5916,11 +5916,11 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
 #define GHASH_LEN_BLOCK(aes)                            \
     do {                                                \
         word64* x = (word64*)AES_TAG(aes);              \
-        word64* h = (word64*)aes->H;                    \
+        word64* h = (word64*)aes->gcm.H;                \
         word64 len[2];                                  \
         len[0] = aes->aSz; len[1] = aes->cSz;           \
-        if (aes->aadLen)                                \
-            len[0] = (word64)aes->aadLen;               \
+        if (aes->gcm.aadLen)                            \
+            len[0] = (word64)aes->gcm.aadLen;           \
         /* Lengths are in bytes. Convert to bits. */    \
         len[0] *= 8;                                    \
         len[1] *= 8;                                    \
@@ -5941,7 +5941,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
 #define GHASH_LEN_BLOCK(aes)                            \
     do {                                                \
         word64* x = (word64*)AES_TAG(aes);              \
-        word64* h = (word64*)aes->H;                    \
+        word64* h = (word64*)aes->gcm.H;                \
         word64 len[2];                                  \
         len[0] = aes->aSz; len[1] = aes->cSz;           \
         /* Lengths are in bytes. Convert to bits. */    \
@@ -5974,7 +5974,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
 #define GHASH_ONE_BLOCK(aes, block)                     \
     do {                                                \
         word64* x = (word64*)AES_TAG(aes);              \
-        word64* h = (word64*)aes->H;                    \
+        word64* h = (word64*)aes->gcm.H;                \
         word64 block64[2];                              \
         XMEMCPY(block64, block, AES_BLOCK_SIZE);        \
         x[0] ^= block64[0];                             \
@@ -5993,11 +5993,11 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
 #define GHASH_LEN_BLOCK(aes)                            \
     do {                                                \
         word64* x = (word64*)AES_TAG(aes);              \
-        word64* h = (word64*)aes->H;                    \
+        word64* h = (word64*)aes->gcm.H;                \
         word64 len[2];                                  \
         len[0] = aes->aSz; len[1] = aes->cSz;           \
-        if (aes->aadLen)                                \
-            len[0] = (word64)aes->aadLen;               \
+        if (aes->gcm.aadLen)                            \
+            len[0] = (word64)aes->gcm.aadLen;           \
         /* Lengths are in bytes. Convert to bits. */    \
         len[0] *= 8;                                    \
         len[1] *= 8;                                    \
@@ -6017,7 +6017,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
 #define GHASH_LEN_BLOCK(aes)                            \
     do {                                                \
         word64* x = (word64*)AES_TAG(aes);              \
-        word64* h = (word64*)aes->H;                    \
+        word64* h = (word64*)aes->gcm.H;                \
         word64 len[2];                                  \
         len[0] = aes->aSz; len[1] = aes->cSz;           \
         /* Lengths are in bytes. Convert to bits. */    \
@@ -6085,18 +6085,18 @@ static void GMULT(word32* X, word32* Y)
 }
 
 
-void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
+void GHASH(Gcm* gcm, const byte* a, word32 aSz, const byte* c,
     word32 cSz, byte* s, word32 sSz)
 {
     word32 x[4] = {0,0,0,0};
     word32 blocks, partial;
     word32 bigH[4];
 
-    if (aes == NULL) {
+    if (gcm == NULL) {
         return;
     }
 
-    XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE);
+    XMEMCPY(bigH, gcm->H, AES_BLOCK_SIZE);
     #ifdef LITTLE_ENDIAN_ORDER
         ByteReverseWords(bigH, bigH, AES_BLOCK_SIZE);
     #endif
@@ -6194,7 +6194,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
  * @param [in, out] aes  AES GCM object.
  */
 #define GHASH_INIT_EXTRA(aes) \
-    ByteReverseWords((word32*)aes->H, (word32*)aes->H, AES_BLOCK_SIZE)
+    ByteReverseWords((word32*)aes->gcm.H, (word32*)aes->gcm.H, AES_BLOCK_SIZE)
 
 /* GHASH one block of data..
  *
@@ -6206,7 +6206,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
 #define GHASH_ONE_BLOCK(aes, block)                         \
     do {                                                    \
         word32* x = (word32*)AES_TAG(aes);                  \
-        word32* h = (word32*)aes->H;                        \
+        word32* h = (word32*)aes->gcm.H;                    \
         word32 bigEnd[4];                                   \
         XMEMCPY(bigEnd, block, AES_BLOCK_SIZE);             \
         ByteReverseWords(bigEnd, bigEnd, AES_BLOCK_SIZE);   \
@@ -6228,7 +6228,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
     do {                                                    \
         word32 len[4];                                      \
         word32* x = (word32*)AES_TAG(aes);                  \
-        word32* h = (word32*)aes->H;                        \
+        word32* h = (word32*)aes->gcm.H;                    \
         len[0] = (aes->aSz >> (8*sizeof(aes->aSz) - 3));    \
         len[1] = aes->aSz << 3;                             \
         len[2] = (aes->cSz >> (8*sizeof(aes->cSz) - 3));    \
@@ -6258,7 +6258,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
 #define GHASH_ONE_BLOCK(aes, block)                         \
     do {                                                    \
         word32* x = (word32*)AES_TAG(aes);                  \
-        word32* h = (word32*)aes->H;                        \
+        word32* h = (word32*)aes->gcm.H;                    \
         word32 block32[4];                                  \
         XMEMCPY(block32, block, AES_BLOCK_SIZE);            \
         x[0] ^= block32[0];                                 \
@@ -6277,7 +6277,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
     do {                                                    \
         word32 len[4];                                      \
         word32* x = (word32*)AES_TAG(aes);                  \
-        word32* h = (word32*)aes->H;                        \
+        word32* h = (word32*)aes->gcm.H;                    \
         len[0] = (aes->aSz >> (8*sizeof(aes->aSz) - 3));    \
         len[1] = aes->aSz << 3;                             \
         len[2] = (aes->cSz >> (8*sizeof(aes->cSz) - 3));    \
@@ -6547,7 +6547,7 @@ static WARN_UNUSED_RESULT int wc_AesGcmEncrypt_STM32(
         pCtr[AES_BLOCK_SIZE - 1] = 1;
     }
     else {
-        GHASH(aes, NULL, 0, iv, ivSz, (byte*)ctr, AES_BLOCK_SIZE);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, (byte*)ctr, AES_BLOCK_SIZE);
     }
     XMEMCPY(ctrInit, ctr, sizeof(ctr)); /* save off initial counter for GMAC */
 
@@ -6721,7 +6721,7 @@ static WARN_UNUSED_RESULT int wc_AesGcmEncrypt_STM32(
         /* return authTag */
         if (authTag) {
             if (useSwGhash) {
-                GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
+                GHASH(&aes->gcm, authIn, authInSz, out, sz, authTag, authTagSz);
                 ret = wc_AesEncrypt(aes, (byte*)ctrInit, (byte*)tag);
                 if (ret == 0) {
                     xorbuf(authTag, tag, authTagSz);
@@ -6779,12 +6779,12 @@ WARN_UNUSED_RESULT int AES_GCM_encrypt_C(
     else {
         /* Counter is GHASH of IV. */
 #ifdef OPENSSL_EXTRA
-        word32 aadTemp = aes->aadLen;
-        aes->aadLen = 0;
+        word32 aadTemp = aes->gcm.aadLen;
+        aes->gcm.aadLen = 0;
 #endif
-        GHASH(aes, NULL, 0, iv, ivSz, counter, AES_BLOCK_SIZE);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, counter, AES_BLOCK_SIZE);
 #ifdef OPENSSL_EXTRA
-        aes->aadLen = aadTemp;
+        aes->gcm.aadLen = aadTemp;
 #endif
     }
     XMEMCPY(initialCounter, counter, AES_BLOCK_SIZE);
@@ -6844,7 +6844,7 @@ WARN_UNUSED_RESULT int AES_GCM_encrypt_C(
         xorbufout(c, scratch, p, partial);
     }
     if (authTag) {
-        GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
+        GHASH(&aes->gcm, authIn, authInSz, out, sz, authTag, authTagSz);
         ret = wc_AesEncrypt(aes, initialCounter, scratch);
         if (ret != 0)
             return ret;
@@ -6852,7 +6852,7 @@ WARN_UNUSED_RESULT int AES_GCM_encrypt_C(
 #ifdef OPENSSL_EXTRA
         if (!in && !sz)
             /* store AAD size for next call */
-            aes->aadLen = authInSz;
+            aes->gcm.aadLen = authInSz;
 #endif
     }
 
@@ -7060,7 +7060,7 @@ static WARN_UNUSED_RESULT int wc_AesGcmDecrypt_STM32(
         pCtr[AES_BLOCK_SIZE - 1] = 1;
     }
     else {
-        GHASH(aes, NULL, 0, iv, ivSz, (byte*)ctr, AES_BLOCK_SIZE);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, (byte*)ctr, AES_BLOCK_SIZE);
     }
 
     /* Make copy of expected authTag, which could get corrupted in some
@@ -7089,7 +7089,7 @@ static WARN_UNUSED_RESULT int wc_AesGcmDecrypt_STM32(
         || authPadSz != authInSz
     #endif
     ) {
-        GHASH(aes, authIn, authInSz, in, sz, (byte*)tag, sizeof(tag));
+        GHASH(&aes->gcm, authIn, authInSz, in, sz, (byte*)tag, sizeof(tag));
         ret = wc_AesEncrypt(aes, (byte*)ctr, (byte*)partialBlock);
         if (ret != 0)
             return ret;
@@ -7304,17 +7304,17 @@ int WARN_UNUSED_RESULT AES_GCM_decrypt_C(
     else {
         /* Counter is GHASH of IV. */
 #ifdef OPENSSL_EXTRA
-        word32 aadTemp = aes->aadLen;
-        aes->aadLen = 0;
+        word32 aadTemp = aes->gcm.aadLen;
+        aes->gcm.aadLen = 0;
 #endif
-        GHASH(aes, NULL, 0, iv, ivSz, counter, AES_BLOCK_SIZE);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, counter, AES_BLOCK_SIZE);
 #ifdef OPENSSL_EXTRA
-        aes->aadLen = aadTemp;
+        aes->gcm.aadLen = aadTemp;
 #endif
     }
 
     /* Calc the authTag again using received auth data and the cipher text */
-    GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime));
+    GHASH(&aes->gcm, authIn, authInSz, in, sz, Tprime, sizeof(Tprime));
     ret = wc_AesEncrypt(aes, counter, EKY0);
     if (ret != 0)
         return ret;
@@ -7337,7 +7337,7 @@ int WARN_UNUSED_RESULT AES_GCM_decrypt_C(
     if (!out) {
         /* authenticated, non-confidential data */
         /* store AAD size for next call */
-        aes->aadLen = authInSz;
+        aes->gcm.aadLen = authInSz;
     }
 #endif
 
@@ -7563,12 +7563,12 @@ static WARN_UNUSED_RESULT int AesGcmInit_C(Aes* aes, const byte* iv, word32 ivSz
     else {
         /* Counter is GHASH of IV. */
     #ifdef OPENSSL_EXTRA
-        word32 aadTemp = aes->aadLen;
-        aes->aadLen = 0;
+        word32 aadTemp = aes->gcm.aadLen;
+        aes->gcm.aadLen = 0;
     #endif
-        GHASH(aes, NULL, 0, iv, ivSz, counter, AES_BLOCK_SIZE);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, counter, AES_BLOCK_SIZE);
     #ifdef OPENSSL_EXTRA
-        aes->aadLen = aadTemp;
+        aes->gcm.aadLen = aadTemp;
     #endif
     }
 
@@ -7695,7 +7695,7 @@ static WARN_UNUSED_RESULT int AesGcmFinal_C(
     xorbuf(authTag, AES_INITCTR(aes), authTagSz);
 #ifdef OPENSSL_EXTRA
     /* store AAD size for next call */
-    aes->aadLen = aes->aSz;
+    aes->gcm.aadLen = aes->aSz;
 #endif
     /* Zeroize last block to protect sensitive data. */
     ForceZero(AES_LASTBLOCK(aes), AES_BLOCK_SIZE);
@@ -7788,8 +7788,8 @@ static WARN_UNUSED_RESULT int AesGcmInit_aesni(
 #ifdef HAVE_INTEL_AVX2
     if (IS_INTEL_AVX2(intel_flags)) {
         SAVE_VECTOR_REGISTERS(return _svr_ret;);
-        AES_GCM_init_avx2((byte*)aes->key, (int)aes->rounds, iv, ivSz, aes->H,
-                          AES_COUNTER(aes), AES_INITCTR(aes));
+        AES_GCM_init_avx2((byte*)aes->key, (int)aes->rounds, iv, ivSz,
+            aes->gcm.H, AES_COUNTER(aes), AES_INITCTR(aes));
         RESTORE_VECTOR_REGISTERS();
     }
     else
@@ -7797,16 +7797,16 @@ static WARN_UNUSED_RESULT int AesGcmInit_aesni(
 #ifdef HAVE_INTEL_AVX1
     if (IS_INTEL_AVX1(intel_flags)) {
         SAVE_VECTOR_REGISTERS(return _svr_ret;);
-        AES_GCM_init_avx1((byte*)aes->key, (int)aes->rounds, iv, ivSz, aes->H,
-                          AES_COUNTER(aes), AES_INITCTR(aes));
+        AES_GCM_init_avx1((byte*)aes->key, (int)aes->rounds, iv, ivSz,
+            aes->gcm.H, AES_COUNTER(aes), AES_INITCTR(aes));
         RESTORE_VECTOR_REGISTERS();
     }
     else
 #endif
     {
         SAVE_VECTOR_REGISTERS(return _svr_ret;);
-        AES_GCM_init_aesni((byte*)aes->key, (int)aes->rounds, iv, ivSz, aes->H,
-                           AES_COUNTER(aes), AES_INITCTR(aes));
+        AES_GCM_init_aesni((byte*)aes->key, (int)aes->rounds, iv, ivSz,
+            aes->gcm.H, AES_COUNTER(aes), AES_INITCTR(aes));
         RESTORE_VECTOR_REGISTERS();
     }
     return 0;
@@ -7847,20 +7847,20 @@ static WARN_UNUSED_RESULT int AesGcmAadUpdate_aesni(
             #ifdef HAVE_INTEL_AVX2
                 if (IS_INTEL_AVX2(intel_flags)) {
                     AES_GCM_ghash_block_avx2(AES_LASTGBLOCK(aes), AES_TAG(aes),
-                                             aes->H);
+                                             aes->gcm.H);
                 }
                 else
             #endif
             #ifdef HAVE_INTEL_AVX1
                 if (IS_INTEL_AVX1(intel_flags)) {
                     AES_GCM_ghash_block_avx1(AES_LASTGBLOCK(aes), AES_TAG(aes),
-                                             aes->H);
+                                             aes->gcm.H);
                 }
                 else
             #endif
                 {
                     AES_GCM_ghash_block_aesni(AES_LASTGBLOCK(aes), AES_TAG(aes),
-                                              aes->H);
+                                              aes->gcm.H);
                 }
                 /* Reset count. */
                 aes->aOver = 0;
@@ -7878,20 +7878,20 @@ static WARN_UNUSED_RESULT int AesGcmAadUpdate_aesni(
         #ifdef HAVE_INTEL_AVX2
             if (IS_INTEL_AVX2(intel_flags)) {
                 AES_GCM_aad_update_avx2(a, blocks * AES_BLOCK_SIZE,
-                                        AES_TAG(aes), aes->H);
+                                        AES_TAG(aes), aes->gcm.H);
             }
             else
         #endif
         #ifdef HAVE_INTEL_AVX1
             if (IS_INTEL_AVX1(intel_flags)) {
                 AES_GCM_aad_update_avx1(a, blocks * AES_BLOCK_SIZE,
-                                        AES_TAG(aes), aes->H);
+                                        AES_TAG(aes), aes->gcm.H);
             }
             else
         #endif
             {
                 AES_GCM_aad_update_aesni(a, blocks * AES_BLOCK_SIZE,
-                                         AES_TAG(aes), aes->H);
+                                         AES_TAG(aes), aes->gcm.H);
             }
             /* Skip over to end of AAD blocks. */
             a += blocks * AES_BLOCK_SIZE;
@@ -7910,19 +7910,21 @@ static WARN_UNUSED_RESULT int AesGcmAadUpdate_aesni(
         /* GHASH last AAD block. */
     #ifdef HAVE_INTEL_AVX2
         if (IS_INTEL_AVX2(intel_flags)) {
-            AES_GCM_ghash_block_avx2(AES_LASTGBLOCK(aes), AES_TAG(aes), aes->H);
+            AES_GCM_ghash_block_avx2(AES_LASTGBLOCK(aes), AES_TAG(aes),
+                                     aes->gcm.H);
         }
         else
     #endif
     #ifdef HAVE_INTEL_AVX1
         if (IS_INTEL_AVX1(intel_flags)) {
-            AES_GCM_ghash_block_avx1(AES_LASTGBLOCK(aes), AES_TAG(aes), aes->H);
+            AES_GCM_ghash_block_avx1(AES_LASTGBLOCK(aes), AES_TAG(aes),
+                                     aes->gcm.H);
         }
         else
     #endif
         {
             AES_GCM_ghash_block_aesni(AES_LASTGBLOCK(aes), AES_TAG(aes),
-                                      aes->H);
+                                      aes->gcm.H);
         }
         /* Clear partial count for next time through. */
         aes->aOver = 0;
@@ -7975,20 +7977,20 @@ static WARN_UNUSED_RESULT int AesGcmEncryptUpdate_aesni(
             #ifdef HAVE_INTEL_AVX2
                 if (IS_INTEL_AVX2(intel_flags)) {
                     AES_GCM_ghash_block_avx2(AES_LASTGBLOCK(aes), AES_TAG(aes),
-                                             aes->H);
+                                             aes->gcm.H);
                 }
                 else
             #endif
             #ifdef HAVE_INTEL_AVX1
                 if (IS_INTEL_AVX1(intel_flags)) {
                     AES_GCM_ghash_block_avx1(AES_LASTGBLOCK(aes), AES_TAG(aes),
-                                             aes->H);
+                                             aes->gcm.H);
                 }
                 else
             #endif
                 {
                     AES_GCM_ghash_block_aesni(AES_LASTGBLOCK(aes), AES_TAG(aes),
-                                              aes->H);
+                                              aes->gcm.H);
                 }
                 /* Reset count. */
                 aes->cOver = 0;
@@ -8007,7 +8009,7 @@ static WARN_UNUSED_RESULT int AesGcmEncryptUpdate_aesni(
         #ifdef HAVE_INTEL_AVX2
             if (IS_INTEL_AVX2(intel_flags)) {
                 AES_GCM_encrypt_update_avx2((byte*)aes->key, (int)aes->rounds,
-                    c, p, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H,
+                    c, p, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->gcm.H,
                     AES_COUNTER(aes));
             }
             else
@@ -8015,14 +8017,14 @@ static WARN_UNUSED_RESULT int AesGcmEncryptUpdate_aesni(
         #ifdef HAVE_INTEL_AVX1
             if (IS_INTEL_AVX1(intel_flags)) {
                 AES_GCM_encrypt_update_avx1((byte*)aes->key, (int)aes->rounds,
-                    c, p, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H,
+                    c, p, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->gcm.H,
                     AES_COUNTER(aes));
             }
             else
         #endif
             {
                 AES_GCM_encrypt_update_aesni((byte*)aes->key, (int)aes->rounds,
-                    c, p, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H,
+                    c, p, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->gcm.H,
                     AES_COUNTER(aes));
             }
             /* Skip over to end of blocks. */
@@ -8089,39 +8091,41 @@ static WARN_UNUSED_RESULT int AesGcmEncryptFinal_aesni(
         /* GHASH last cipher block. */
     #ifdef HAVE_INTEL_AVX2
         if (IS_INTEL_AVX2(intel_flags)) {
-            AES_GCM_ghash_block_avx2(AES_LASTGBLOCK(aes), AES_TAG(aes), aes->H);
+            AES_GCM_ghash_block_avx2(AES_LASTGBLOCK(aes), AES_TAG(aes),
+                                     aes->gcm.H);
         }
         else
     #endif
     #ifdef HAVE_INTEL_AVX1
         if (IS_INTEL_AVX1(intel_flags)) {
-            AES_GCM_ghash_block_avx1(AES_LASTGBLOCK(aes), AES_TAG(aes), aes->H);
+            AES_GCM_ghash_block_avx1(AES_LASTGBLOCK(aes), AES_TAG(aes),
+                                     aes->gcm.H);
         }
         else
     #endif
         {
             AES_GCM_ghash_block_aesni(AES_LASTGBLOCK(aes), AES_TAG(aes),
-                                      aes->H);
+                                      aes->gcm.H);
         }
     }
     /* Calculate the authentication tag. */
 #ifdef HAVE_INTEL_AVX2
     if (IS_INTEL_AVX2(intel_flags)) {
         AES_GCM_encrypt_final_avx2(AES_TAG(aes), authTag, authTagSz, aes->cSz,
-            aes->aSz, aes->H, AES_INITCTR(aes));
+            aes->aSz, aes->gcm.H, AES_INITCTR(aes));
     }
     else
 #endif
 #ifdef HAVE_INTEL_AVX1
     if (IS_INTEL_AVX1(intel_flags)) {
         AES_GCM_encrypt_final_avx1(AES_TAG(aes), authTag, authTagSz, aes->cSz,
-            aes->aSz, aes->H, AES_INITCTR(aes));
+            aes->aSz, aes->gcm.H, AES_INITCTR(aes));
     }
     else
 #endif
     {
         AES_GCM_encrypt_final_aesni(AES_TAG(aes), authTag, authTagSz, aes->cSz,
-            aes->aSz, aes->H, AES_INITCTR(aes));
+            aes->aSz, aes->gcm.H, AES_INITCTR(aes));
     }
     RESTORE_VECTOR_REGISTERS();
     return 0;
@@ -8205,20 +8209,20 @@ static WARN_UNUSED_RESULT int AesGcmDecryptUpdate_aesni(
             #ifdef HAVE_INTEL_AVX2
                 if (IS_INTEL_AVX2(intel_flags)) {
                     AES_GCM_ghash_block_avx2(AES_LASTBLOCK(aes), AES_TAG(aes),
-                                             aes->H);
+                                             aes->gcm.H);
                 }
                 else
             #endif
             #ifdef HAVE_INTEL_AVX1
                 if (IS_INTEL_AVX1(intel_flags)) {
                     AES_GCM_ghash_block_avx1(AES_LASTBLOCK(aes), AES_TAG(aes),
-                                             aes->H);
+                                             aes->gcm.H);
                 }
                 else
             #endif
                 {
                     AES_GCM_ghash_block_aesni(AES_LASTBLOCK(aes), AES_TAG(aes),
-                                              aes->H);
+                                              aes->gcm.H);
                 }
                 /* Reset count. */
                 aes->cOver = 0;
@@ -8237,7 +8241,7 @@ static WARN_UNUSED_RESULT int AesGcmDecryptUpdate_aesni(
         #ifdef HAVE_INTEL_AVX2
             if (IS_INTEL_AVX2(intel_flags)) {
                 AES_GCM_decrypt_update_avx2((byte*)aes->key, (int)aes->rounds,
-                    p, c, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H,
+                    p, c, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->gcm.H,
                     AES_COUNTER(aes));
             }
             else
@@ -8245,14 +8249,14 @@ static WARN_UNUSED_RESULT int AesGcmDecryptUpdate_aesni(
         #ifdef HAVE_INTEL_AVX1
             if (IS_INTEL_AVX1(intel_flags)) {
                 AES_GCM_decrypt_update_avx1((byte*)aes->key, (int)aes->rounds,
-                    p, c, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H,
+                    p, c, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->gcm.H,
                     AES_COUNTER(aes));
             }
             else
         #endif
             {
                 AES_GCM_decrypt_update_aesni((byte*)aes->key, (int)aes->rounds,
-                    p, c, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->H,
+                    p, c, blocks * AES_BLOCK_SIZE, AES_TAG(aes), aes->gcm.H,
                     AES_COUNTER(aes));
             }
             /* Skip over to end of blocks. */
@@ -8325,38 +8329,38 @@ static WARN_UNUSED_RESULT int AesGcmDecryptFinal_aesni(
         /* Hash the last block of cipher text. */
     #ifdef HAVE_INTEL_AVX2
         if (IS_INTEL_AVX2(intel_flags)) {
-            AES_GCM_ghash_block_avx2(lastBlock, AES_TAG(aes), aes->H);
+            AES_GCM_ghash_block_avx2(lastBlock, AES_TAG(aes), aes->gcm.H);
         }
         else
     #endif
     #ifdef HAVE_INTEL_AVX1
         if (IS_INTEL_AVX1(intel_flags)) {
-            AES_GCM_ghash_block_avx1(lastBlock, AES_TAG(aes), aes->H);
+            AES_GCM_ghash_block_avx1(lastBlock, AES_TAG(aes), aes->gcm.H);
         }
         else
     #endif
         {
-            AES_GCM_ghash_block_aesni(lastBlock, AES_TAG(aes), aes->H);
+            AES_GCM_ghash_block_aesni(lastBlock, AES_TAG(aes), aes->gcm.H);
         }
     }
     /* Calculate and compare the authentication tag. */
 #ifdef HAVE_INTEL_AVX2
     if (IS_INTEL_AVX2(intel_flags)) {
         AES_GCM_decrypt_final_avx2(AES_TAG(aes), authTag, authTagSz, aes->cSz,
-            aes->aSz, aes->H, AES_INITCTR(aes), &res);
+            aes->aSz, aes->gcm.H, AES_INITCTR(aes), &res);
     }
     else
 #endif
 #ifdef HAVE_INTEL_AVX1
     if (IS_INTEL_AVX1(intel_flags)) {
         AES_GCM_decrypt_final_avx1(AES_TAG(aes), authTag, authTagSz, aes->cSz,
-            aes->aSz, aes->H, AES_INITCTR(aes), &res);
+            aes->aSz, aes->gcm.H, AES_INITCTR(aes), &res);
     }
     else
 #endif
     {
         AES_GCM_decrypt_final_aesni(AES_TAG(aes), authTag, authTagSz, aes->cSz,
-            aes->aSz, aes->H, AES_INITCTR(aes), &res);
+            aes->aSz, aes->gcm.H, AES_INITCTR(aes), &res);
     }
     RESTORE_VECTOR_REGISTERS();
     /* Return error code when calculated doesn't match input. */
@@ -9818,8 +9822,8 @@ int wc_AesInit(Aes* aes, void* heap, int devId)
 
 #ifdef HAVE_AESGCM
 #ifdef OPENSSL_EXTRA
-    XMEMSET(aes->aadH, 0, sizeof(aes->aadH));
-    aes->aadLen = 0;
+    XMEMSET(aes->gcm.aadH, 0, sizeof(aes->gcm.aadH));
+    aes->gcm.aadLen = 0;
 #endif
 #endif
 

+ 297 - 62
wolfcrypt/src/asn.c

@@ -142,6 +142,10 @@ ASN Options:
     #include <wolfssl/wolfcrypt/ecc.h>
 #endif
 
+#ifdef WOLFSSL_SM2
+    #include <wolfssl/wolfcrypt/sm2.h>
+#endif
+
 #ifdef HAVE_ED25519
     #include <wolfssl/wolfcrypt/ed25519.h>
 #endif
@@ -4028,6 +4032,10 @@ static word32 SetBitString16Bit(word16 val, byte* output)
     static const byte sigSha3_512wEcdsaOid[] = {96, 134, 72, 1, 101, 3, 4, 3, 12};
     #endif
     #endif
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    /* 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x83, 0x75 */
+    static const byte sigSm3wSm2Oid[] = {42, 129, 28, 207, 85, 1, 131, 117};
+    #endif
 #endif /* HAVE_ECC */
 #ifdef HAVE_ED25519
     static const byte sigEd25519Oid[] = {43, 101, 112};
@@ -4646,6 +4654,12 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz)
                     break;
                 #endif
                 #endif
+                #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                case CTC_SM3wSM2:
+                    oid = sigSm3wSm2Oid;
+                    *oidSz = sizeof(sigSm3wSm2Oid);
+                    break;
+                #endif
                 #endif /* HAVE_ECC */
                 #ifdef HAVE_ED25519
                 case CTC_ED25519:
@@ -11322,8 +11336,8 @@ static int StoreKey(DecodedCert* cert, const byte* source, word32* srcIdx,
     ret = CheckBitString(source, srcIdx, &length, maxIdx, 1, NULL);
     if (ret == 0) {
     #ifdef HAVE_OCSP
-        ret = CalcHashId(source + *srcIdx, (word32)length,
-                         cert->subjectKeyHash);
+        ret = CalcHashId_ex(source + *srcIdx, (word32)length,
+            cert->subjectKeyHash, HashIdAlg(cert->signatureOID));
     }
     if (ret == 0) {
     #endif
@@ -11926,7 +11940,8 @@ static int StoreRsaKey(DecodedCert* cert, const byte* source, word32* srcIdx,
     *srcIdx += (word32)length;
 
 #ifdef HAVE_OCSP
-    return CalcHashId(cert->publicKey, cert->pubKeySize, cert->subjectKeyHash);
+    return CalcHashId_ex(cert->publicKey, cert->pubKeySize,
+        cert->subjectKeyHash, HashIdAlg(cert->signatureOID));
 #else
     return 0;
 #endif
@@ -11956,8 +11971,8 @@ static int StoreRsaKey(DecodedCert* cert, const byte* source, word32* srcIdx,
     #endif
     #ifdef HAVE_OCSP
         /* Calculate the hash of the public key for OCSP. */
-        ret = CalcHashId(cert->publicKey, cert->pubKeySize,
-                         cert->subjectKeyHash);
+        ret = CalcHashId_ex(cert->publicKey, cert->pubKeySize,
+                         cert->subjectKeyHash, HashIdAlg(cert->signatureOID));
     #endif
     }
 
@@ -12058,8 +12073,8 @@ static int StoreEccKey(DecodedCert* cert, const byte* source, word32* srcIdx,
     #endif
 
     #ifdef HAVE_OCSP
-        ret = CalcHashId(source + *srcIdx, (word32)length,
-                         cert->subjectKeyHash);
+        ret = CalcHashId_ex(source + *srcIdx, (word32)length,
+            cert->subjectKeyHash, HashIdAlg(cert->signatureOID));
         if (ret != 0)
             return ret;
     #endif
@@ -12108,9 +12123,9 @@ static int StoreEccKey(DecodedCert* cert, const byte* source, word32* srcIdx,
 
     #ifdef HAVE_OCSP
         /* Calculate the hash of the subject public key for OCSP. */
-        ret = CalcHashId(dataASN[ECCCERTKEYASN_IDX_SUBJPUBKEY].data.ref.data,
+        ret = CalcHashId_ex(dataASN[ECCCERTKEYASN_IDX_SUBJPUBKEY].data.ref.data,
                          dataASN[ECCCERTKEYASN_IDX_SUBJPUBKEY].data.ref.length,
-                         cert->subjectKeyHash);
+                         cert->subjectKeyHash, HashIdAlg(cert->signatureOID));
     }
     if (ret == 0) {
     #endif
@@ -12336,6 +12351,9 @@ static int GetCertKey(DecodedCert* cert, const byte* source, word32* inOutIdx,
             break;
 #endif /* NO_RSA */
     #ifdef HAVE_ECC
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+        case SM2k:
+    #endif
         case ECDSAk:
             ret = StoreEccKey(cert, source, &srcIdx, maxIdx, source + pubIdx,
                               (word32)pubLen);
@@ -12426,6 +12444,30 @@ static int GetCertKey(DecodedCert* cert, const byte* source, word32* inOutIdx,
 }
 #endif
 
+/* Return the hash algorithm to use with the signature algorithm.
+ *
+ * @param [in] oidSum  Signature id.
+ * @return  Hash algorithm id.
+ */
+int HashIdAlg(int oidSum)
+{
+    (void)oidSum;
+
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    if (oidSum == CTC_SM3wSM2) {
+        return WC_SM3;
+    }
+    if (oidSum == SM2k) {
+        return WC_SM3;
+    }
+#endif
+#if defined(NO_SHA) || (!defined(NO_SHA256) && defined(WC_ASN_HASH_SHA256))
+    return WC_SHA256;
+#else
+    return WC_SHA;
+#endif
+}
+
 /* Calculate hash of the id using the SHA-1 or SHA-256.
  *
  * @param [in]  data  Data to hash.
@@ -12435,19 +12477,56 @@ static int GetCertKey(DecodedCert* cert, const byte* source, word32* inOutIdx,
  * @return  MEMORY_E when dynamic memory allocation fails.
  */
 int CalcHashId(const byte* data, word32 len, byte* hash)
+{
+    /* Use default hash algorithm. */
+    return CalcHashId_ex(data, len, hash,
+#if defined(NO_SHA) || (!defined(NO_SHA256) && defined(WC_ASN_HASH_SHA256))
+        WC_SHA256
+#else
+        WC_SHA
+#endif
+        );
+}
+
+/* Calculate hash of the id using the SHA-1 or SHA-256.
+ *
+ * @param [in]  data  Data to hash.
+ * @param [in]  len   Length of data to hash.
+ * @param [out] hash  Buffer to hold hash.
+ * @return  0 on success.
+ * @return  MEMORY_E when dynamic memory allocation fails.
+ */
+int CalcHashId_ex(const byte* data, word32 len, byte* hash, int hashAlg)
 {
     int ret;
 
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    if (hashAlg == WC_SM3) {
+        ret = wc_Sm3Hash(data, len, hash);
+    }
+    else
+#endif
 #if defined(NO_SHA) || (!defined(NO_SHA256) && defined(WC_ASN_HASH_SHA256))
-    ret = wc_Sha256Hash(data, len, hash);
+    if (hashAlg == WC_SHA256) {
+        ret = wc_Sha256Hash(data, len, hash);
+    }
+    else
 #elif !defined(NO_SHA)
-    ret = wc_ShaHash(data, len, hash);
+    if (hashAlg == WC_SHA) {
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+        XMEMSET(hash + WC_SHA_DIGEST_SIZE, 0, KEYID_SIZE - WC_SHA_DIGEST_SIZE);
+    #endif
+        ret = wc_ShaHash(data, len, hash);
+    }
+    else
 #else
-    ret = NOT_COMPILED_IN;
     (void)data;
     (void)len;
     (void)hash;
 #endif
+    {
+        ret = NOT_COMPILED_IN;
+    }
 
     return ret;
 }
@@ -12463,16 +12542,24 @@ int CalcHashId(const byte* data, word32 len, byte* hash)
  * @return  0 on success.
  * @return  MEMORY_E when dynamic memory allocation fails.
  */
-static int GetHashId(const byte* id, int length, byte* hash)
+static int GetHashId(const byte* id, int length, byte* hash, int hashAlg)
 {
     int ret;
 
-    if (length == KEYID_SIZE) {
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    if (length == wc_HashGetDigestSize(wc_HashTypeConvert(hashAlg)))
+#else
+    if (length == KEYID_SIZE)
+#endif
+    {
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+        XMEMSET(hash + length, 0, KEYID_SIZE - length);
+    #endif
         XMEMCPY(hash, id, (size_t)length);
         ret = 0;
     }
     else {
-        ret = CalcHashId(id, (word32)length, hash);
+        ret = CalcHashId_ex(id, (word32)length, hash, hashAlg);
     }
 
     return ret;
@@ -13205,8 +13292,10 @@ static int GetCertName(DecodedCert* cert, char* full, byte* hash, int nameType,
     /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be
      * calculated over the entire DER encoding of the Name field, including
      * the tag and length. */
-    if (CalcHashId(input + *inOutIdx, maxIdx - *inOutIdx, hash) != 0)
+    if (CalcHashId_ex(input + *inOutIdx, maxIdx - *inOutIdx, hash,
+            HashIdAlg(cert->signatureOID)) != 0) {
         return ASN_PARSE_E;
+    }
 
 #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
     !defined(WOLFCRYPT_ONLY)
@@ -13858,7 +13947,8 @@ static int GetCertName(DecodedCert* cert, char* full, byte* hash, int nameType,
     /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be
      * calculated over the entire DER encoding of the Name field, including
      * the tag and length. */
-    if (CalcHashId(input + srcIdx, maxIdx - srcIdx, hash) != 0) {
+    if (CalcHashId_ex(input + srcIdx, maxIdx - srcIdx, hash,
+            HashIdAlg(cert->signatureOID)) != 0) {
         ret = ASN_PARSE_E;
     }
 
@@ -14939,9 +15029,8 @@ int DecodeToKey(DecodedCert* cert, int verify)
     else
 #endif
     {
-        cert->selfSigned = XMEMCMP(cert->issuerHash,
-                                   cert->subjectHash,
-                                   KEYID_SIZE) == 0 ? 1 : 0;
+        cert->selfSigned = XMEMCMP(cert->issuerHash, cert->subjectHash,
+            KEYID_SIZE) == 0 ? 1 : 0;
     }
 
     ret = GetCertKey(cert, cert->source, &cert->srcIdx, cert->maxIdx);
@@ -15214,6 +15303,9 @@ static WC_INLINE int IsSigAlgoECC(word32 algoOID)
         #ifdef HAVE_ECC
               || IsSigAlgoECDSA(algoOID)
         #endif
+        #ifdef WOLFSSL_SM2
+              || (algoOID == SM2k)
+        #endif
         #ifdef HAVE_ED25519
               || (algoOID == ED25519k)
         #endif
@@ -15532,6 +15624,9 @@ void FreeSignatureCtx(SignatureCtx* sigCtx)
         #endif
         #ifdef HAVE_ECC
             case ECDSAk:
+        #ifdef WOLFSSL_SM2
+            case SM2k:
+        #endif
             #if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
                 defined(WC_ASYNC_ENABLE_ECC)
                 if (sigCtx->key.ecc->nb_ctx != NULL) {
@@ -15716,6 +15811,14 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID,
             break;
     #endif
     #endif
+    #if defined(WOLFSSL_SM2) & defined(WOLFSSL_SM3)
+        case CTC_SM3wSM2:
+            if ((ret = wc_Sm3Hash(buf, bufSz, digest)) == 0) {
+                *typeH    = SM3h;
+                *digestSz = WC_SM3_DIGEST_SIZE;
+            }
+            break;
+    #endif
     #ifdef HAVE_ED25519
         case CTC_ED25519:
             /* Hashes done in signing operation.
@@ -15858,6 +15961,12 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
                 }
             }
             else
+        #endif
+        #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+            if (sigOID == CTC_SM3wSM2) {
+                ; /* SM2 hash requires public key. Done later. */
+            }
+            else
         #endif
             {
                 ret = HashForSignature(buf, bufSz, sigOID, sigCtx->digest,
@@ -16027,6 +16136,9 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
                 }
             #endif /* !NO_DSA && !HAVE_SELFTEST */
             #ifdef HAVE_ECC
+            #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                case SM2k:
+            #endif
                 case ECDSAk:
                 {
                     word32 idx = 0;
@@ -16478,9 +16590,50 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
                     break;
                 }
             #endif /* !NO_DSA && !HAVE_SELFTEST */
+            #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                case SM2k:
+                {
+                    /* OpenSSL creates signature without CERT_SIG_ID. */
+                    ret = wc_ecc_sm2_create_digest(CERT_SIG_ID, 0, buf, bufSz,
+                        WC_HASH_TYPE_SM3, sigCtx->digest, WC_SM3_DIGEST_SIZE,
+                        sigCtx->key.ecc);
+                    if (ret == 0) {
+                        sigCtx->typeH    = SM3h;
+                        sigCtx->digestSz = WC_SM3_DIGEST_SIZE;
+                    }
+                    else {
+                        WOLFSSL_MSG("SM2wSM3 create digest failed");
+                        WOLFSSL_ERROR_VERBOSE(ret);
+                        goto exit_cs;
+                    }
+                    ret = wc_ecc_sm2_verify_hash(sig, sigSz, sigCtx->digest,
+                        sigCtx->digestSz, &sigCtx->verify, sigCtx->key.ecc);
+                    break;
+                }
+            #endif
             #if defined(HAVE_ECC) && defined(HAVE_ECC_VERIFY)
                 case ECDSAk:
                 {
+                #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                    if (sigOID == CTC_SM3wSM2) {
+                        ret = wc_ecc_sm2_create_digest(CERT_SIG_ID,
+                            CERT_SIG_ID_SZ, buf, bufSz, WC_HASH_TYPE_SM3,
+                            sigCtx->digest, WC_SM3_DIGEST_SIZE,
+                            sigCtx->key.ecc);
+                        if (ret == 0) {
+                            sigCtx->typeH    = SM3h;
+                            sigCtx->digestSz = WC_SM3_DIGEST_SIZE;
+                        }
+                        else {
+                            WOLFSSL_MSG("SM2wSM3 create digest failed");
+                            WOLFSSL_ERROR_VERBOSE(ret);
+                            goto exit_cs;
+                        }
+                        ret = wc_ecc_sm2_verify_hash(sig, sigSz, sigCtx->digest,
+                            sigCtx->digestSz, &sigCtx->verify, sigCtx->key.ecc);
+                    }
+                    else
+                #endif
                 #if defined(HAVE_PK_CALLBACKS)
                     if (sigCtx->pkCbEcc) {
                         ret = sigCtx->pkCbEcc(
@@ -16666,6 +16819,9 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
                 }
             #endif /* !NO_DSA && !HAVE_SELFTEST */
             #ifdef HAVE_ECC
+            #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+                case SM2k:
+            #endif
                 case ECDSAk:
                 {
                     if (sigCtx->verify == 1) {
@@ -18682,7 +18838,8 @@ static int DecodeAuthKeyId(const byte* input, word32 sz, DecodedCert* cert)
     cert->extAuthKeyIdSz = length;
 #endif /* OPENSSL_EXTRA */
 
-    return GetHashId(input + idx, length, cert->extAuthKeyId);
+    return GetHashId(input + idx, length, cert->extAuthKeyId,
+        HashIdAlg(cert->signatureOID));
 #else
     DECL_ASNGETDATA(dataASN, authKeyIdASN_Length);
     int ret = 0;
@@ -18716,7 +18873,7 @@ static int DecodeAuthKeyId(const byte* input, word32 sz, DecodedCert* cert)
             /* Get the hash or hash of the hash if wrong size. */
             ret = GetHashId(dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.data,
                         (int)dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.length,
-                        cert->extAuthKeyId);
+                        cert->extAuthKeyId, HashIdAlg(cert->signatureOID));
         }
     }
 
@@ -18753,7 +18910,8 @@ static int DecodeSubjKeyId(const byte* input, word32 sz, DecodedCert* cert)
     #endif /* OPENSSL_EXTRA */
 
         /* Get the hash or hash of the hash if wrong size. */
-        ret = GetHashId(input + idx, length, cert->extSubjKeyId);
+        ret = GetHashId(input + idx, length, cert->extSubjKeyId,
+            HashIdAlg(cert->signatureOID));
     }
 
     return ret;
@@ -21322,6 +21480,7 @@ static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm)
  *
  * @param [in]  input   Input data.
  * @param [in]  maxIdx  Maximum index for data.
+ * @param [in]  sigOID  Signature OID for determining hash algorithm.
  * @param [out] hash    Hash of AKI.
  * @param [out] set     Whether the hash buffer was set.
  * @param [in]  heap    Dynamic memory allocation hint.
@@ -21330,8 +21489,8 @@ static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm)
  *          is invalid.
  * @return  MEMORY_E on dynamic memory allocation failure.
  */
-static int GetAKIHash(const byte* input, word32 maxIdx, byte* hash, int* set,
-                      void* heap)
+static int GetAKIHash(const byte* input, word32 maxIdx, int sigOID,
+                      byte* hash, int* set, void* heap)
 {
     /* AKI and Certificate Extenion ASN.1 templates are the same length. */
     DECL_ASNGETDATA(dataASN, certExtASN_Length);
@@ -21381,7 +21540,7 @@ static int GetAKIHash(const byte* input, word32 maxIdx, byte* hash, int* set,
                     ret = GetHashId(
                             dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.data,
                             dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.length,
-                            hash);
+                            hash, sigOID);
                 }
                 break;
             }
@@ -21646,7 +21805,7 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
                                     /* Get the hash or hash of the hash if wrong
                                      * size. */
                                     ret = GetHashId(cert + extIdx, extLen,
-                                                    hash);
+                                        hash, HashIdAlg(signatureOID));
                                 }
                             }
                             break;
@@ -21668,14 +21827,16 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
         if (extAuthKeyIdSet)
             ca = GetCA(cm, hash);
         if (ca == NULL) {
-            ret = CalcHashId(cert + issuerIdx, issuerSz, hash);
+            ret = CalcHashId_ex(cert + issuerIdx, issuerSz, hash,
+                HashIdAlg(signatureOID));
             if (ret == 0)
                 ca = GetCAByName(cm, hash);
         }
     }
 #else
     if (ret == 0 && pubKey == NULL) {
-        ret = CalcHashId(cert + issuerIdx, issuerSz, hash);
+        ret = CalcHashId_ex(cert + issuerIdx, issuerSz, hash,
+            HashIdAlg(signatureOID));
         if (ret == 0)
             ca = GetCA(cm, hash);
     }
@@ -21904,7 +22065,8 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
         /* Find the AKI extension in list of extensions and get hash. */
         if ((!req) && (akiData != NULL)) {
             /* TODO: test case */
-            ret = GetAKIHash(akiData, akiLen, hash, &extAuthKeyIdSet, heap);
+            ret = GetAKIHash(akiData, akiLen, sigOID, hash, &extAuthKeyIdSet,
+                heap);
         }
 
         /* Get the CA by hash one was found. */
@@ -21915,7 +22077,7 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
 #endif
         {
             /* Try hash of issuer name. */
-            ret = CalcHashId(caName, caNameLen, hash);
+            ret = CalcHashId_ex(caName, caNameLen, hash, HashIdAlg(sigOID));
             if (ret == 0) {
                 ca = GetCAByName(cm, hash);
             }
@@ -22391,8 +22553,16 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
     #ifndef NO_SKID
         if (cert->extSubjKeyIdSet == 0 && cert->publicKey != NULL &&
                                                          cert->pubKeySize > 0) {
-            ret = CalcHashId(cert->publicKey, cert->pubKeySize,
-                                                            cert->extSubjKeyId);
+            if (cert->signatureOID == CTC_SM3wSM2) {
+                /* TODO: GmSSL creates IDs this way but whole public key info
+                 * block should be hashed. */
+                ret = CalcHashId_ex(cert->publicKey + cert->pubKeySize - 65, 65,
+                    cert->extSubjKeyId, HashIdAlg(cert->signatureOID));
+            }
+            else {
+                ret = CalcHashId_ex(cert->publicKey, cert->pubKeySize,
+                    cert->extSubjKeyId, HashIdAlg(cert->signatureOID));
+            }
             if (ret != 0) {
                 WOLFSSL_ERROR_VERBOSE(ret);
                 return ret;
@@ -22412,7 +22582,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
                 cert->ca = GetCA(cm, cert->extSubjKeyId);
             }
             if (cert->ca != NULL && XMEMCMP(cert->issuerHash,
-                                  cert->ca->subjectNameHash, KEYID_SIZE) != 0) {
+                    cert->ca->subjectNameHash, KEYID_SIZE) != 0) {
                 cert->ca = NULL;
             }
             if (cert->ca == NULL) {
@@ -22541,7 +22711,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
             if (cert->ca) {
                 /* Need the CA's public key hash for OCSP */
                 XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash,
-                                                                KEYID_SIZE);
+                    KEYID_SIZE);
             }
         }
         #endif /* HAVE_OCSP */
@@ -22560,7 +22730,8 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
             return ret;
         }
         cert->sigCtx.CertAtt.certBegin = cert->certBegin;
-    } else if (cert->keyOID == ECDSAk) {
+    }
+    else if (cert->keyOID == ECDSAk) {
         cert->sigCtx.CertAtt.certBegin = cert->certBegin;
     }
     /* check if we can use TSIP for cert verification */
@@ -29992,12 +30163,22 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey,
 
     /* Compute SKID by hashing public key */
     if (kid_type == SKID_TYPE) {
-        ret = CalcHashId(buf, (word32)bufferSz, cert->skid);
+        int hashId = HashIdAlg(cert->sigType);
+        ret = CalcHashId_ex(buf, (word32)bufferSz, cert->skid, hashId);
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+        cert->skidSz = wc_HashGetDigestSize(wc_HashTypeConvert(hashId));
+    #else
         cert->skidSz = KEYID_SIZE;
+    #endif
     }
     else if (kid_type == AKID_TYPE) {
-        ret = CalcHashId(buf, (word32)bufferSz, cert->akid);
+        int hashId = HashIdAlg(cert->sigType);
+        ret = CalcHashId_ex(buf, (word32)bufferSz, cert->akid, hashId);
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+        cert->akidSz = wc_HashGetDigestSize(wc_HashTypeConvert(hashId));
+    #else
         cert->akidSz = KEYID_SIZE;
+    #endif
     }
     else
         ret = BAD_FUNC_ARG;
@@ -30231,9 +30412,14 @@ static int SetAuthKeyIdFromDcert(Cert* cert, DecodedCert* decoded)
     }
 
     else {
-        /* Put the SKID of CA to AKID of certificate */
-        XMEMCPY(cert->akid, decoded->extSubjKeyId, KEYID_SIZE);
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+        cert->akidSz = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
+            cert->sigType)));
+    #else
         cert->akidSz = KEYID_SIZE;
+    #endif
+        /* Put the SKID of CA to AKID of certificate */
+        XMEMCPY(cert->akid, decoded->extSubjKeyId, cert->akidSz);
     }
 
     return ret;
@@ -31835,6 +32021,9 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
     if (ToTraditionalInline_ex(input, inOutIdx, inSz, &algId) < 0) {
         /* ignore error, did not have pkcs8 header */
     }
+    else {
+        curve_id = wc_ecc_get_oid(algId, NULL, NULL);
+    }
 
     if (GetSequence(input, inOutIdx, &length, inSz) < 0)
         return ASN_PARSE_E;
@@ -31944,7 +32133,7 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
     byte version;
     int ret = 0;
     int curve_id = ECC_CURVE_DEF;
-#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) || defined(SM2)
     word32 algId = 0;
 #endif
 
@@ -31953,11 +32142,14 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
         ret = BAD_FUNC_ARG;
     }
 
-#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12)
+#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) || defined(SM2)
     /* if has pkcs8 header skip it */
     if (ToTraditionalInline_ex(input, inOutIdx, inSz, &algId) < 0) {
         /* ignore error, did not have pkcs8 header */
     }
+    else {
+        curve_id = wc_ecc_get_oid(algId, NULL, NULL);
+    }
 #endif
 
     CALLOC_ASNGETDATA(dataASN, eccKeyASN_Length, ret, key->heap);
@@ -32372,10 +32564,14 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
     if (ret == 0) {
         /* Clear dynamic data for ECC public key. */
         XMEMSET(dataASN, 0, sizeof(*dataASN) * eccPublicKeyASN_Length);
+#if !defined(WOLFSSL_SM2) || !defined(WOLFSSL_SM3)
         /* Set required ECDSA OID and ignore the curve OID type. */
         GetASN_ExpBuffer(&dataASN[ECCPUBLICKEYASN_IDX_ALGOID_OID], keyEcdsaOid,
                 sizeof(keyEcdsaOid));
-        GetASN_OID(&dataASN[oidIdx], oidIgnoreType);
+#else
+        GetASN_OID(&dataASN[ECCPUBLICKEYASN_IDX_ALGOID_OID], oidKeyType);
+#endif
+        GetASN_OID(&dataASN[oidIdx], oidCurveType);
         /* Decode the public ECC key. */
         ret = GetASN_Items(eccPublicKeyASN, dataASN, eccPublicKeyASN_Length, 1,
                            input, inOutIdx, inSz);
@@ -32389,7 +32585,7 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
             /* Clear dynamic data for ECC private key. */
             XMEMSET(dataASN, 0, sizeof(*dataASN) * eccKeyASN_Length);
             /* Check named curve OID type. */
-            GetASN_OID(&dataASN[oidIdx], oidIgnoreType);
+            GetASN_OID(&dataASN[oidIdx], oidCurveType);
             /* Try private key format .*/
             ret = GetASN_Items(eccKeyASN, dataASN, eccKeyASN_Length, 1, input,
                                inOutIdx, inSz);
@@ -32399,6 +32595,14 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
         }
     }
 
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    if ((ret == 0) && (oidIdx == ECCPUBLICKEYASN_IDX_ALGOID_CURVEID)) {
+        int oidSum = dataASN[ECCPUBLICKEYASN_IDX_ALGOID_OID].data.oid.sum;
+        if ((oidSum != ECDSAk) && (oidSum != SM2k)) {
+            ret = ASN_PARSE_E;
+        }
+    }
+#endif
     if (ret == 0) {
         if (dataASN[oidIdx].tag != 0) {
             /* Named curve - check and get id. */
@@ -33872,6 +34076,7 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
 #else
     DECL_ASNGETDATA(dataASN, singleResponseASN_Length);
     int ret = 0;
+    word32 ocspDigestSize = OCSP_DIGEST_SIZE;
     CertStatus* cs = NULL;
     word32 serialSz;
     word32 issuerHashLen;
@@ -33918,12 +34123,18 @@ static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
         ret = GetASN_Items(singleResponseASN, dataASN, singleResponseASN_Length,
                 1, source, ioIndex, size);
     }
+    if (ret == 0) {
+        single->hashAlgoOID =
+            dataASN[SINGLERESPONSEASN_IDX_CID_HASHALGO_OID].data.oid.sum;
+        ocspDigestSize = wc_HashGetDigestSize(
+            wc_OidGetHash(single->hashAlgoOID));
+    }
     /* Validate the issuer hash length is the size required. */
-    if ((ret == 0) && (issuerHashLen != OCSP_DIGEST_SIZE)) {
+    if ((ret == 0) && (issuerHashLen != ocspDigestSize)) {
         ret = ASN_PARSE_E;
     }
     /* Validate the issuer key hash length is the size required. */
-    if ((ret == 0) && (issuerKeyHashLen != OCSP_DIGEST_SIZE)) {
+    if ((ret == 0) && (issuerKeyHashLen != ocspDigestSize)) {
         ret = ASN_PARSE_E;
     }
     if (ret == 0) {
@@ -35147,17 +35358,20 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
     byte extArray[MAX_OCSP_EXT_SZ];
     word32 seqSz[5], algoSz, issuerSz, issuerKeySz, extSz, totalSz;
     int i, snSz;
+    int keyIdSz;
 
     WOLFSSL_ENTER("EncodeOcspRequest");
 
 #ifdef NO_SHA
     algoSz = SetAlgoID(SHA256h, algoArray, oidHashType, 0);
+    keyIdSz = WC_SHA256_DIGEST_SIZE;
 #else
     algoSz = SetAlgoID(SHAh, algoArray, oidHashType, 0);
+    keyIdSz = WC_SHA_DIGEST_SIZE;
 #endif
 
-    issuerSz    = SetDigest(req->issuerHash,    KEYID_SIZE,    issuerArray);
-    issuerKeySz = SetDigest(req->issuerKeyHash, KEYID_SIZE,    issuerKeyArray);
+    issuerSz    = SetDigest(req->issuerHash,    keyIdSz,    issuerArray);
+    issuerKeySz = SetDigest(req->issuerKeyHash, keyIdSz,    issuerKeyArray);
     snSz        = SetSerialNumber(req->serial,  req->serialSz, snArray,
                                                           MAX_SN_SZ, MAX_SN_SZ);
     extSz       = 0;
@@ -35215,6 +35429,7 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
     word32 extSz = 0;
     int sz = 0;
     int ret = 0;
+    int keyIdSz;
 
     WOLFSSL_ENTER("EncodeOcspRequest");
 
@@ -35225,16 +35440,18 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size)
     #ifdef NO_SHA
         SetASN_OID(&dataASN[OCSPREQUESTASN_IDX_TBS_REQ_HASH_OID], SHA256h,
                 oidHashType);
+        keyIdSz = WC_SHA256_DIGEST_SIZE;
     #else
         SetASN_OID(&dataASN[OCSPREQUESTASN_IDX_TBS_REQ_HASH_OID], SHAh,
                 oidHashType);
+        keyIdSz = WC_SHA_DIGEST_SIZE;
     #endif
         /* Set issuer, issuer key hash and serial number of certificate being
          * checked. */
         SetASN_Buffer(&dataASN[OCSPREQUESTASN_IDX_TBS_REQ_ISSUER],
-                req->issuerHash, KEYID_SIZE);
+                req->issuerHash, keyIdSz);
         SetASN_Buffer(&dataASN[OCSPREQUESTASN_IDX_TBS_REQ_ISSUERKEY],
-                req->issuerKeyHash, KEYID_SIZE);
+                req->issuerKeyHash, keyIdSz);
         SetASN_Buffer(&dataASN[OCSPREQUESTASN_IDX_TBS_REQ_SERIAL],
                 req->serial, req->serialSz);
         /* Only extension to write is nonce - check if one to encode. */
@@ -35377,6 +35594,7 @@ void FreeOcspRequest(OcspRequest* req)
 int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
 {
     int cmp = -1; /* default as not matching, cmp gets set on each check */
+    int ocspDigestSize;
     OcspEntry *single, *next, *prev = NULL, *top;
 
     WOLFSSL_ENTER("CompareOcspReqResp");
@@ -35412,11 +35630,17 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
 
     /* match based on found status and return */
     for (single = resp->single; single; single = next) {
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+        ocspDigestSize = wc_HashGetDigestSize(
+            wc_OidGetHash(single->hashAlgoOID));
+    #else
+        ocspDigestSize = OCSP_DIGEST_SIZE;
+    #endif
         cmp = req->serialSz - single->status->serialSz;
         if (cmp == 0) {
             cmp = XMEMCMP(req->serial, single->status->serial, req->serialSz)
-               || XMEMCMP(req->issuerHash, single->issuerHash, OCSP_DIGEST_SIZE)
-               || XMEMCMP(req->issuerKeyHash, single->issuerKeyHash, OCSP_DIGEST_SIZE);
+               || XMEMCMP(req->issuerHash, single->issuerHash, ocspDigestSize)
+               || XMEMCMP(req->issuerKeyHash, single->issuerKeyHash, ocspDigestSize);
             if (cmp == 0) {
                 /* match found */
                 if (resp->single != single && prev) {
@@ -35461,6 +35685,14 @@ enum {
 
 /* store WC_SHA hash of NAME */
 int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx)
+{
+    /* Use summy signature OID. */
+    return GetNameHash_ex(source, idx, hash, maxIdx, 0);
+}
+
+/* store WC_SHA hash of NAME */
+int GetNameHash_ex(const byte* source, word32* idx, byte* hash, int maxIdx,
+    int sigOID)
 {
 #ifndef WOLFSSL_ASN_TEMPLATE
     int    length;  /* length of all distinguished names */
@@ -35489,7 +35721,8 @@ int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx)
     if (GetSequence(source, idx, &length, (word32)maxIdx) < 0)
         return ASN_PARSE_E;
 
-    ret = CalcHashId(source + dummy, (word32)length + *idx - dummy, hash);
+    ret = CalcHashId_ex(source + dummy, (word32)length + *idx - dummy, hash,
+        HashIdAlg(sigOID));
 
     *idx += (word32)length;
 
@@ -35509,10 +35742,10 @@ int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx)
          * calculated over the entire DER encoding of the Name field, including
          * the tag and length. */
         /* Calculate hash of complete name including SEQUENCE. */
-        ret = CalcHashId(
+        ret = CalcHashId_ex(
                 GetASNItem_Addr(dataASN[NAMEHASHASN_IDX_NAME], source),
                 GetASNItem_Length(dataASN[NAMEHASHASN_IDX_NAME], source),
-                hash);
+                hash, HashIdAlg(sigOID));
     }
 
     return ret;
@@ -35827,7 +36060,7 @@ static int PaseCRL_CheckSignature(DecodedCRL* dcrl, const byte* buff, void* cm)
     }
     /* Check issuerHash matched CA's subjectNameHash. */
     if ((ca != NULL) && (XMEMCMP(dcrl->issuerHash, ca->subjectNameHash,
-                                 KEYID_SIZE) != 0)) {
+            KEYID_SIZE) != 0)) {
         ca = NULL;
     }
     if (ca == NULL) {
@@ -35899,7 +36132,7 @@ static int ParseCRL_CertList(RevokedCert* rcert, DecodedCRL* dcrl,
     dcrl->issuer   = (byte*)GetNameFromDer(buf + idx, (int)dcrl->issuerSz);
 #endif
 
-    if (GetNameHash(buf, &idx, dcrl->issuerHash, sz) < 0)
+    if (GetNameHash_ex(buf, &idx, dcrl->issuerHash, sz, oid) < 0)
         return ASN_PARSE_E;
 
     if (GetBasicDate(buf, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0)
@@ -35989,7 +36222,8 @@ static int ParseCRL_AuthKeyIdExt(const byte* input, int sz, DecodedCRL* dcrl)
 
     dcrl->extAuthKeyIdSet = 1;
     /* Get the hash or hash of the hash if wrong size. */
-    ret = GetHashId(input + idx, length, dcrl->extAuthKeyId);
+    ret = GetHashId(input + idx, length, dcrl->extAuthKeyId,
+        HashIdAlg(dcrl->signatureOID));
 
     return ret;
 #else
@@ -36015,7 +36249,7 @@ static int ParseCRL_AuthKeyIdExt(const byte* input, int sz, DecodedCRL* dcrl)
             /* Get the hash or hash of the hash if wrong size. */
             ret = GetHashId(dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.data,
                 dataASN[AUTHKEYIDASN_IDX_KEYID].data.ref.length,
-                dcrl->extAuthKeyId);
+                dcrl->extAuthKeyId, HashIdAlg(dcrl->signatureOID));
         }
     }
 
@@ -36348,7 +36582,7 @@ int ParseCRL(RevokedCert* rcert, DecodedCRL* dcrl, const byte* buff, word32 sz,
         ca = GetCA(cm, dcrl->extAuthKeyId); /* more unique than issuerHash */
     }
     if (ca != NULL && XMEMCMP(dcrl->issuerHash, ca->subjectNameHash,
-                KEYID_SIZE) != 0) {
+            KEYID_SIZE) != 0) {
         ca = NULL;
     }
     if (ca == NULL) {
@@ -36474,9 +36708,10 @@ end:
                             (int)dcrl->issuerSz);
     #endif
         /* Calculate the Hash id from the issuer name. */
-        ret = CalcHashId(GetASNItem_Addr(dataASN[CRLASN_IDX_TBS_ISSUER], buff),
+        ret = CalcHashId_ex(
+                GetASNItem_Addr(dataASN[CRLASN_IDX_TBS_ISSUER], buff),
                 GetASNItem_Length(dataASN[CRLASN_IDX_TBS_ISSUER], buff),
-                dcrl->issuerHash);
+                dcrl->issuerHash, HashIdAlg(dcrl->signatureOID));
         if (ret < 0) {
             ret = ASN_PARSE_E;
         }

+ 228 - 44
wolfcrypt/src/ecc.c

@@ -101,6 +101,7 @@ ECC Curve Types:
  * HAVE_ECC_SECPR3      Enables SECP R3 curves                  default: off
  * HAVE_ECC_BRAINPOOL   Enables Brainpool curves                default: off
  * HAVE_ECC_KOBLITZ     Enables Koblitz curves                  default: off
+ * WOLFSSL_SM2          Enables SM2 curves                      default: off
  */
 
 /*
@@ -648,6 +649,21 @@ enum {
         #endif
         #define ecc_oid_brainpoolp256r1_sz CODED_BRAINPOOLP256R1_SZ
     #endif /* HAVE_ECC_BRAINPOOL */
+    #ifdef WOLFSSL_SM2
+        #ifdef HAVE_OID_ENCODING
+            #define CODED_SM2P256V1    {1,2,156,10197,1,301}
+            #define CODED_SM2P256V1_SZ 6
+        #else
+            #define CODED_SM2P256V1 {0x2A,0x81,0x1C,0xCF,0x55,0x01,0x82,0x2d}
+            #define CODED_SM2P256V1_SZ 8
+        #endif
+        #ifndef WOLFSSL_ECC_CURVE_STATIC
+            static const ecc_oid_t ecc_oid_sm2p256v1[] = CODED_SM2P256V1;
+        #else
+            #define ecc_oid_sm2p256v1 CODED_SM2P256V1
+        #endif
+        #define ecc_oid_sm2p256v1_sz CODED_SM2P256V1_SZ
+    #endif /* WOLFSSL_SM2 */
 #endif /* ECC256 */
 #ifdef ECC320
     #ifdef HAVE_ECC_BRAINPOOL
@@ -1128,6 +1144,25 @@ const ecc_set_type ecc_sets[] = {
         1,                                                                  /* cofactor   */
     },
     #endif /* HAVE_ECC_BRAINPOOL */
+    #ifdef WOLFSSL_SM2
+    {
+        32,                                                     /* size/bytes */
+        ECC_SM2P256V1,                                          /* ID         */
+        "SM2P256V1",                                            /* curve name */
+
+        /* bottom of draft-shen-sm2-ecdsa-02, recommended values */
+        "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", /* prime */
+        "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", /* A */
+        "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", /* B */
+        "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", /* order */
+        "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", /* Gx */
+        "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", /* Gy */
+        ecc_oid_sm2p256v1,                                      /* oid/oidSz  */
+        ecc_oid_sm2p256v1_sz,
+        ECC_SM2P256V1_OID,                                      /* oid sum    */
+        1,                                                      /* cofactor   */
+    },
+    #endif /* WOLFSSL_SM2 */
 #endif /* ECC256 */
 #ifdef ECC320
     #ifdef HAVE_ECC_BRAINPOOL
@@ -2109,6 +2144,12 @@ done:
 
 #ifndef WOLFSSL_SP_NO_256
     if (modBits == 256) {
+    #ifdef WOLFSSL_SM2
+        if (!mp_is_bit_set(modulus, 224)) {
+           return sp_ecc_proj_add_point_sm2_256(P->x, P->y, P->z, Q->x, Q->y,
+                                                Q->z, R->x, R->y, R->z);
+        }
+    #endif
         return sp_ecc_proj_add_point_256(P->x, P->y, P->z, Q->x, Q->y, Q->z,
                                          R->x, R->y, R->z);
     }
@@ -2473,6 +2514,12 @@ static int _ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a,
 
 #ifndef WOLFSSL_SP_NO_256
     if (modBits == 256) {
+    #ifdef WOLFSSL_SM2
+        if (!mp_is_bit_set(modulus, 224)) {
+           return sp_ecc_proj_dbl_point_sm2_256(P->x, P->y, P->z, R->x, R->y,
+                                                R->z);
+        }
+    #endif
         return sp_ecc_proj_dbl_point_256(P->x, P->y, P->z, R->x, R->y, R->z);
     }
 #endif
@@ -2725,6 +2772,11 @@ done:
 
 #ifndef WOLFSSL_SP_NO_256
    if (mp_count_bits(modulus) == 256) {
+    #ifdef WOLFSSL_SM2
+        if (!mp_is_bit_set(modulus, 224)) {
+           return sp_ecc_map_sm2_256(P->x, P->y, P->z);
+        }
+    #endif
        return sp_ecc_map_256(P->x, P->y, P->z);
    }
 #endif
@@ -2906,21 +2958,11 @@ static int ecc_mulmod(const mp_int* k, ecc_point* tG, ecc_point* R,
 #else
 
 static int wc_ecc_gen_z(WC_RNG* rng, int size, ecc_point* p, mp_int* modulus,
-    mp_digit mp, mp_int* tx, mp_int* ty)
+    mp_digit mp, mp_int* tx, mp_int* ty, mp_int* mu)
 {
     int err = MP_OKAY;
-    DECL_MP_INT_SIZE_DYN(mu, mp_bitsused(modulus), MAX_ECC_BITS_USE);
 
-    NEW_MP_INT_SIZE(mu, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC);
-#ifdef MP_INT_SIZE_CHECK_NULL
-    if (mu == NULL)
-        err = MEMORY_E;
-#endif
-
-    if (err == MP_OKAY)
-        err = INIT_MP_INT_SIZE(mu, mp_bitsused(modulus));
-    if (err == MP_OKAY)
-        err = mp_montgomery_calc_normalization(mu, modulus);
+    err = mp_montgomery_calc_normalization(mu, modulus);
     /* Generate random value to multiply into p->z. */
     if (err == MP_OKAY)
         err = wc_ecc_gen_k(rng, size, ty, modulus);
@@ -2953,9 +2995,6 @@ static int wc_ecc_gen_z(WC_RNG* rng, int size, ecc_point* p, mp_int* modulus,
     if (err == MP_OKAY)
         err = mp_montgomery_reduce(p->y, modulus, mp);
 
-    mp_clear(mu);
-    FREE_MP_INT_SIZE(mu, NULL, DYNAMIC_TYPE_ECC);
-
     return err;
 }
 
@@ -2993,9 +3032,23 @@ static int ecc_mulmod(const mp_int* k, ecc_point* P, ecc_point* Q,
 #ifndef WC_NO_CACHE_RESISTANT
     /* First bit always 1 (fix at end) and swap equals first bit */
     int      swap = 1;
+#ifdef WOLFSSL_SMALL_STACK
+    mp_int*  tmp = NULL;
+#else
+    mp_int   tmp[1];
+#endif
 #endif
     int      infinity;
 
+#ifdef WOLFSSL_SMALL_STACK
+    tmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
+    if (tmp == NULL) {
+        err = MEMORY_E;
+    }
+#endif
+    if (err == MP_OKAY)
+        err = mp_init(tmp);
+
     /* Step 1: R[0] = P; R[1] = P */
     /* R[0] = P */
     if (err == MP_OKAY)
@@ -3015,9 +3068,9 @@ static int ecc_mulmod(const mp_int* k, ecc_point* P, ecc_point* Q,
 
     /* Randomize z ordinates to obfuscate timing. */
     if ((err == MP_OKAY) && (rng != NULL))
-        err = wc_ecc_gen_z(rng, bytes, R[0], modulus, mp, R[2]->x, R[2]->y);
+        err = wc_ecc_gen_z(rng, bytes, R[0], modulus, mp, R[2]->x, R[2]->y, kt);
     if ((err == MP_OKAY) && (rng != NULL))
-        err = wc_ecc_gen_z(rng, bytes, R[1], modulus, mp, R[2]->x, R[2]->y);
+        err = wc_ecc_gen_z(rng, bytes, R[1], modulus, mp, R[2]->x, R[2]->y, kt);
 
     if (err == MP_OKAY) {
         /* Order could be one greater than the size of the modulus. */
@@ -3050,12 +3103,18 @@ static int ecc_mulmod(const mp_int* k, ecc_point* P, ecc_point* Q,
 #else
         /* Swap R[0] and R[1] if other index is needed. */
         swap ^= (int)b;
-        if (err == MP_OKAY)
-            err = mp_cond_swap_ct(R[0]->x, R[1]->x, (int)modulus->used, swap);
-        if (err == MP_OKAY)
-            err = mp_cond_swap_ct(R[0]->y, R[1]->y, (int)modulus->used, swap);
-        if (err == MP_OKAY)
-            err = mp_cond_swap_ct(R[0]->z, R[1]->z, (int)modulus->used, swap);
+        if (err == MP_OKAY) {
+            err = mp_cond_swap_ct_ex(R[0]->x, R[1]->x, (int)modulus->used, swap,
+                tmp);
+        }
+        if (err == MP_OKAY) {
+            err = mp_cond_swap_ct_ex(R[0]->y, R[1]->y, (int)modulus->used, swap,
+                tmp);
+        }
+        if (err == MP_OKAY) {
+            err = mp_cond_swap_ct_ex(R[0]->z, R[1]->z, (int)modulus->used, swap,
+                tmp);
+        }
         swap = (int)b;
 
         if (err == MP_OKAY)
@@ -3070,12 +3129,18 @@ static int ecc_mulmod(const mp_int* k, ecc_point* P, ecc_point* Q,
 #ifndef WC_NO_CACHE_RESISTANT
     /* Swap back if last bit is 0. */
     swap ^= 1;
-    if (err == MP_OKAY)
-        err = mp_cond_swap_ct(R[0]->x, R[1]->x, (int)modulus->used, swap);
-    if (err == MP_OKAY)
-        err = mp_cond_swap_ct(R[0]->y, R[1]->y, (int)modulus->used, swap);
-    if (err == MP_OKAY)
-        err = mp_cond_swap_ct(R[0]->z, R[1]->z, (int)modulus->used, swap);
+    if (err == MP_OKAY) {
+        err = mp_cond_swap_ct_ex(R[0]->x, R[1]->x, (int)modulus->used, swap,
+            tmp);
+    }
+    if (err == MP_OKAY) {
+        err = mp_cond_swap_ct_ex(R[0]->y, R[1]->y, (int)modulus->used, swap,
+            tmp);
+    }
+    if (err == MP_OKAY) {
+        err = mp_cond_swap_ct_ex(R[0]->z, R[1]->z, (int)modulus->used, swap,
+            tmp);
+    }
 #endif
 
     /* Step 5: b = k[0]; R[b] = R[b] - P */
@@ -3094,21 +3159,32 @@ static int ecc_mulmod(const mp_int* k, ecc_point* P, ecc_point* Q,
                                                                      &infinity);
 #else
         /* Swap R[0] and R[1], if necessary, to operate on the one we want. */
-        err = mp_cond_swap_ct(R[0]->x, R[1]->x, (int)modulus->used, (int)b);
-        if (err == MP_OKAY)
-            err = mp_cond_swap_ct(R[0]->y, R[1]->y, (int)modulus->used, (int)b);
-        if (err == MP_OKAY)
-            err = mp_cond_swap_ct(R[0]->z, R[1]->z, (int)modulus->used, (int)b);
+        err = mp_cond_swap_ct_ex(R[0]->x, R[1]->x, (int)modulus->used, (int)b,
+            tmp);
+        if (err == MP_OKAY) {
+            err = mp_cond_swap_ct_ex(R[0]->y, R[1]->y, (int)modulus->used,
+                (int)b, tmp);
+        }
+        if (err == MP_OKAY) {
+            err = mp_cond_swap_ct_ex(R[0]->z, R[1]->z, (int)modulus->used,
+                (int)b, tmp);
+        }
         if (err == MP_OKAY)
             err = ecc_projective_add_point_safe(R[0], R[2], R[0], a, modulus,
                                                                  mp, &infinity);
         /* Swap back if necessary. */
-        if (err == MP_OKAY)
-            err = mp_cond_swap_ct(R[0]->x, R[1]->x, (int)modulus->used, (int)b);
-        if (err == MP_OKAY)
-            err = mp_cond_swap_ct(R[0]->y, R[1]->y, (int)modulus->used, (int)b);
-        if (err == MP_OKAY)
-            err = mp_cond_swap_ct(R[0]->z, R[1]->z, (int)modulus->used, (int)b);
+        if (err == MP_OKAY) {
+            err = mp_cond_swap_ct_ex(R[0]->x, R[1]->x, (int)modulus->used,
+                (int)b, tmp);
+        }
+        if (err == MP_OKAY) {
+            err = mp_cond_swap_ct_ex(R[0]->y, R[1]->y, (int)modulus->used,
+                (int)b, tmp);
+        }
+        if (err == MP_OKAY) {
+            err = mp_cond_swap_ct_ex(R[0]->z, R[1]->z, (int)modulus->used,
+                (int)b, tmp);
+        }
 #endif
     }
 
@@ -3120,6 +3196,10 @@ static int ecc_mulmod(const mp_int* k, ecc_point* P, ecc_point* Q,
     if (err == MP_OKAY)
         err = mp_copy(R[0]->z, Q->z);
 
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
+#endif
+
     return err;
 }
 
@@ -3211,10 +3291,10 @@ static int ecc_mulmod(const mp_int* k, ecc_point* P, ecc_point* Q,
     /* Randomize z ordinates to obfuscate timing. */
     if ((err == MP_OKAY) && (rng != NULL))
         err = wc_ecc_gen_z(rng, bytes, R[0], modulus, mp, R[TMP_IDX]->x,
-                           R[TMP_IDX]->y);
+                           R[TMP_IDX]->y, kt);
     if ((err == MP_OKAY) && (rng != NULL))
         err = wc_ecc_gen_z(rng, bytes, R[1], modulus, mp, R[TMP_IDX]->x,
-                           R[TMP_IDX]->y);
+                           R[TMP_IDX]->y, kt);
 
     if (err == MP_OKAY) {
         /* Order could be one greater than the size of the modulus. */
@@ -3597,6 +3677,11 @@ exit:
 #ifdef WOLFSSL_HAVE_SP_ECC
 #ifndef WOLFSSL_SP_NO_256
    if (mp_count_bits(modulus) == 256) {
+   #ifdef WOLFSSL_SM2
+       if (!mp_is_bit_set(modulus, 224)) {
+           return sp_ecc_mulmod_sm2_256(k, G, R, map, heap);
+       }
+   #endif
        return sp_ecc_mulmod_256(k, G, R, map, heap);
    }
 #endif
@@ -4585,6 +4670,14 @@ int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point,
     #endif /* !WC_ECC_NONBLOCK */
     }
     else
+#ifdef WOLFSSL_SM2
+    if (private_key->idx != ECC_CUSTOM_IDX &&
+                               ecc_sets[private_key->idx].id == ECC_SM2P256V1) {
+        err = sp_ecc_secret_gen_sm2_256(k, point, out, outlen,
+                                                             private_key->heap);
+    }
+    else
+#endif
 #endif /* ! WOLFSSL_SP_NO_256 */
 #ifdef WOLFSSL_SP_384
     if (private_key->idx != ECC_CUSTOM_IDX &&
@@ -5169,7 +5262,13 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve,
         err = sp_ecc_mulmod_base_256(key->k, pub, 1, key->heap);
     }
     else
+#ifdef WOLFSSL_SM2
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SM2P256V1) {
+        err = sp_ecc_mulmod_base_sm2_256(&key->k, pub, 1, key->heap);
+    }
+    else
 #endif
+#endif /* WOLFSSL_SP_NO_256 */
 #ifdef WOLFSSL_SP_384
     if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
         err = sp_ecc_mulmod_base_384(key->k, pub, 1, key->heap);
@@ -5545,6 +5644,15 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key,
         }
     }
     else
+#ifdef WOLFSSL_SM2
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SM2P256V1) {
+        err = sp_ecc_make_key_sm2_256(rng, &key->k, &key->pubkey, key->heap);
+        if (err == MP_OKAY) {
+            key->type = ECC_PRIVATEKEY;
+        }
+    }
+    else
+#endif
 #endif /* !WOLFSSL_SP_NO_256 */
 #ifdef WOLFSSL_SP_384
     if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
@@ -6753,6 +6861,12 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng,
             }
         #endif
         }
+        #ifdef WOLFSSL_SM2
+        if (ecc_sets[key->idx].id == ECC_SM2P256V1) {
+            return sp_ecc_sign_sm2_256(in, inlen, rng, &key->k, r, s, sign_k,
+                key->heap);
+        }
+        #endif
     #endif
     #ifdef WOLFSSL_SP_384
         if (ecc_sets[key->idx].id == ECC_SECP384R1) {
@@ -8319,6 +8433,21 @@ static int ecc_verify_hash_sp(mp_int *r, mp_int *s, const byte* hash,
             }
         #endif
         }
+        #ifdef WOLFSSL_SM2
+        if (ecc_sets[key->idx].id == ECC_SM2P256V1) {
+            #if defined(FP_ECC_CONTROL) && !defined(WOLFSSL_DSP_BUILD)
+            return sp_ecc_cache_verify_sm2_256(hash, hashlen, key->pubkey.x,
+                key->pubkey.y, key->pubkey.z, r, s, res,
+                sp_ecc_get_cache_entry_256(&(key->pubkey), ECC_SM2P256V1,
+                                          key->fpIdx, key->fpBuild, key->heap),
+                key->heap);
+            #endif
+            #if !defined(FP_ECC_CONTROL)
+            return sp_ecc_verify_sm2_256(hash, hashlen, key->pubkey.x,
+                key->pubkey.y, key->pubkey.z, r, s, res, key->heap);
+            #endif
+        }
+        #endif
     #endif
     #ifdef WOLFSSL_SP_384
         if (ecc_sets[key->idx].id == ECC_SECP384R1) {
@@ -8942,6 +9071,13 @@ int wc_ecc_import_point_der_ex(const byte* in, word32 inLen,
             err = sp_ecc_uncompress_256(point->x, pointType, point->y);
         }
         else
+        #ifdef WOLFSSL_SM2
+        if (curve_idx != ECC_CUSTOM_IDX &&
+                                 ecc_sets[curve_idx->idx].id == ECC_SM2P256V1) {
+            sp_ecc_uncompress_sm2_256(point->x, pointType, point->y);
+        }
+        else
+        #endif
         #endif
         #ifdef WOLFSSL_SP_384
         if (curve_idx != ECC_CUSTOM_IDX &&
@@ -9490,6 +9626,11 @@ static int _ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime)
 #ifdef WOLFSSL_HAVE_SP_ECC
 #ifndef WOLFSSL_SP_NO_256
    if (mp_count_bits(prime) == 256) {
+   #ifdef WOLFSSL_SM2
+       if (!mp_is_bit_set(prime, 224)) {
+           return sp_ecc_is_point_sm2_256(ecp->x, ecp->y);
+       }
+   #endif
        return sp_ecc_is_point_256(ecp->x, ecp->y);
    }
 #endif
@@ -9582,6 +9723,14 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime)
         }
     }
     else
+    #ifdef WOLFSSL_SM2
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SM2P256V1) {
+        if (err == MP_OKAY) {
+            err = sp_ecc_mulmod_base_sm2_256(&key->k, res, 1, key->heap);
+        }
+    }
+    else
+    #endif
 #endif
 #ifdef WOLFSSL_SP_384
     if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
@@ -9815,6 +9964,13 @@ static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a,
             err = sp_ecc_mulmod_256(order, pubkey, inf, 1, key->heap);
         }
         else
+    #ifdef WOLFSSL_SM2
+        if (key->idx != ECC_CUSTOM_IDX &&
+                                       ecc_sets[key->idx].id == ECC_SM2P256V1) {
+            err = sp_ecc_mulmod_sm2_256(order, pubkey, inf, 1, key->heap);
+        }
+        else
+    #endif
 #endif
 #ifdef WOLFSSL_SP_384
         if (key->idx != ECC_CUSTOM_IDX &&
@@ -9920,6 +10076,12 @@ static int _ecc_validate_public_key(ecc_key* key, int partial, int priv)
         return sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y,
             key->type == ECC_PRIVATEKEY ? key->k : NULL, key->heap);
     }
+#ifdef WOLFSSL_SM2
+    if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SM2P256V1) {
+        return sp_ecc_check_key_sm2_256(key->pubkey.x, key->pubkey.y
+            key->type == ECC_PRIVATEKEY ? &key->k : NULL, key->heap);
+    }
+#endif
 #endif
 #ifdef WOLFSSL_SP_384
     if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) {
@@ -10300,6 +10462,12 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key,
                 key->pubkey.y);
         }
         else
+        #ifdef WOLFSSL_SM2
+        if (key->dp->id == ECC_SM2P256V1) {
+            sp_ecc_uncompress_sm2_256(key->pubkey.x, pointType, key->pubkey.y);
+        }
+        else
+        #endif
     #endif
     #ifdef WOLFSSL_SP_384
         if (key->dp->id == ECC_SECP384R1) {
@@ -12861,7 +13029,15 @@ int wc_ecc_mulmod_ex(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
     if (mp_count_bits(modulus) == 256) {
         int ret;
         SAVE_VECTOR_REGISTERS(return _svr_ret);
-        ret = sp_ecc_mulmod_256(k, G, R, map, heap);
+     #ifdef WOLFSSL_SM2
+        if (!mp_is_bit_set(modulus, 224)) {
+            ret = sp_ecc_mulmod_sm2_256(k, G, R, map, heap);
+        }
+        else
+     #endif
+        {
+            ret = sp_ecc_mulmod_256(k, G, R, map, heap);
+        }
         RESTORE_VECTOR_REGISTERS();
         return ret;
     }
@@ -13030,7 +13206,15 @@ int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
     if (mp_count_bits(modulus) == 256) {
         int ret;
         SAVE_VECTOR_REGISTERS(return _svr_ret);
-        ret = sp_ecc_mulmod_256(k, G, R, map, heap);
+    #ifdef WOLFSSL_SM2
+        if (!mp_is_bit_set(modulus, 224)) {
+            ret = sp_ecc_mulmod_sm2_256(k, G, R, map, heap);
+        }
+        else
+    #endif
+        {
+            ret = sp_ecc_mulmod_256(k, G, R, map, heap);
+        }
         RESTORE_VECTOR_REGISTERS();
         return ret;
     }

+ 6 - 0
wolfcrypt/src/error.c

@@ -589,6 +589,12 @@ const char* wc_GetErrorString(int error)
     case ASN_LEN_E:
         return "ASN.1 length invalid";
 
+    case SM4_GCM_AUTH_E:
+        return "SM4-GCM Authentication check fail";
+
+    case SM4_CCM_AUTH_E:
+        return "SM4-CCM Authentication check fail";
+
     default:
         return "unknown error number";
 

File diff suppressed because it is too large
+ 561 - 162
wolfcrypt/src/evp.c


+ 109 - 1
wolfcrypt/src/hash.c

@@ -59,7 +59,8 @@ enum Hash_Sum  {
     SHA3_384h = 422,
     SHA3_512h = 423,
     SHAKE128h = 424,
-    SHAKE256h = 425
+    SHAKE256h = 425,
+    SM3h      = 640     /* 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x11 */
 };
 #endif /* !NO_ASN */
 
@@ -121,6 +122,11 @@ enum wc_HashType wc_HashTypeConvert(int hashType)
             eHashType = WC_HASH_TYPE_SHA3_512;
             break;
     #endif /* WOLFSSL_SHA3 */
+    #ifdef WOLFSSL_SM3
+        case WC_SM3:
+            eHashType = WC_HASH_TYPE_SM3;
+            break;
+    #endif
         default:
             eHashType = WC_HASH_TYPE_NONE;
             break;
@@ -222,6 +228,11 @@ int wc_HashGetOID(enum wc_HashType hash_type)
             oid = SHAKE256h;
             break;
     #endif
+    #ifdef WOLFSSL_SM3
+        case WC_HASH_TYPE_SM3:
+            oid = SM3h;
+            break;
+    #endif
 
         /* Not Supported */
         case WC_HASH_TYPE_MD4:
@@ -289,6 +300,11 @@ enum wc_HashType wc_OidGetHash(int oid)
             hash_type = WC_HASH_TYPE_SHA3_512;
             break;
     #endif /* WOLFSSL_SHA3 */
+    #ifdef WOLFSSL_SM3
+        case SM3h:
+            hash_type = WC_HASH_TYPE_SM3;
+    #endif
+            break;
         default:
             break;
     }
@@ -395,6 +411,12 @@ int wc_HashGetDigestSize(enum wc_HashType hash_type)
         #endif
             break;
 
+    #ifdef WOLFSSL_SM3
+        case WC_HASH_TYPE_SM3:
+            dig_size = WC_SM3_DIGEST_SIZE;
+            break;
+    #endif
+
         /* Not Supported */
     #if defined(WOLFSSL_SHA3) && defined(WOLFSSL_SHAKE128)
         case WC_HASH_TYPE_SHAKE128:
@@ -508,6 +530,12 @@ int wc_HashGetBlockSize(enum wc_HashType hash_type)
         #endif
             break;
 
+    #ifdef WOLFSSL_SM3
+        case WC_HASH_TYPE_SM3:
+            block_size = WC_SM3_BLOCK_SIZE;
+            break;
+    #endif
+
         /* Not Supported */
     #if defined(WOLFSSL_SHA3) && defined(WOLFSSL_SHAKE128)
         case WC_HASH_TYPE_SHAKE128:
@@ -626,6 +654,12 @@ int wc_Hash(enum wc_HashType hash_type, const byte* data,
 #endif
             break;
 
+    #ifdef WOLFSSL_SM3
+        case WC_HASH_TYPE_SM3:
+            ret = wc_Sm3Hash(data, data_len, hash);
+            break;
+    #endif
+
         /* Not Supported */
         case WC_HASH_TYPE_MD2:
         case WC_HASH_TYPE_MD4:
@@ -723,6 +757,12 @@ int wc_HashInit_ex(wc_HashAlg* hash, enum wc_HashType type, void* heap,
 #endif
             break;
 
+    #ifdef WOLFSSL_SM3
+        case WC_HASH_TYPE_SM3:
+            ret = wc_InitSm3(&hash->sm3, heap, devId);
+            break;
+    #endif
+
         /* not supported */
         case WC_HASH_TYPE_MD5_SHA:
         case WC_HASH_TYPE_MD2:
@@ -829,6 +869,12 @@ int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data,
 #endif
             break;
 
+    #ifdef WOLFSSL_SM3
+        case WC_HASH_TYPE_SM3:
+            ret = wc_Sm3Update(&hash->sm3, data, dataSz);
+            break;
+    #endif
+
         /* not supported */
         case WC_HASH_TYPE_MD5_SHA:
         case WC_HASH_TYPE_MD2:
@@ -926,6 +972,12 @@ int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out)
 #endif
             break;
 
+    #ifdef WOLFSSL_SM3
+        case WC_HASH_TYPE_SM3:
+            ret = wc_Sm3Final(&hash->sm3, out);
+            break;
+    #endif
+
         /* not supported */
         case WC_HASH_TYPE_MD5_SHA:
         case WC_HASH_TYPE_MD2:
@@ -1035,6 +1087,13 @@ int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type)
 #endif
             break;
 
+    #ifdef WOLFSSL_SM3
+        case WC_HASH_TYPE_SM3:
+            wc_Sm3Free(&hash->sm3);
+            ret = 0;
+            break;
+    #endif
+
         /* not supported */
         case WC_HASH_TYPE_MD5_SHA:
         case WC_HASH_TYPE_MD2:
@@ -1110,6 +1169,12 @@ int wc_HashSetFlags(wc_HashAlg* hash, enum wc_HashType type, word32 flags)
 #endif
             break;
 
+    #ifdef WOLFSSL_SM3
+        case WC_HASH_TYPE_SM3:
+            ret = wc_Sm3SetFlags(&hash->sm3, flags);
+    #endif
+            break;
+
         /* not supported */
         case WC_HASH_TYPE_MD5_SHA:
         case WC_HASH_TYPE_MD2:
@@ -1183,6 +1248,12 @@ int wc_HashGetFlags(wc_HashAlg* hash, enum wc_HashType type, word32* flags)
 #endif
             break;
 
+    #ifdef WOLFSSL_SM3
+        case WC_HASH_TYPE_SM3:
+            ret = wc_Sm3GetFlags(&hash->sm3, flags);
+            break;
+    #endif
+
         /* not supported */
         case WC_HASH_TYPE_MD5_SHA:
         case WC_HASH_TYPE_MD2:
@@ -1763,6 +1834,43 @@ int wc_HashGetFlags(wc_HashAlg* hash, enum wc_HashType type, word32* flags)
 #endif /* WOLFSSL_SHAKE_256 */
 #endif /* WOLFSSL_SHA3 */
 
+#ifdef WOLFSSL_SM3
+    int wc_Sm3Hash(const byte* data, word32 len, byte* hash)
+    {
+        int ret = 0;
+    #ifdef WOLFSSL_SMALL_STACK
+        wc_Sm3* sm3;
+    #else
+        wc_Sm3 sm3[1];
+    #endif
+
+    #ifdef WOLFSSL_SMALL_STACK
+        sm3 = (wc_Sm3*)XMALLOC(sizeof(wc_Sm3), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        if (sm3 == NULL)
+            return MEMORY_E;
+    #endif
+
+        if ((ret = wc_InitSm3(sm3, NULL, INVALID_DEVID)) != 0) {
+            WOLFSSL_MSG("InitSm3 failed");
+        }
+        else {
+            if ((ret = wc_Sm3Update(sm3, data, len)) != 0) {
+                WOLFSSL_MSG("Sm3Update failed");
+            }
+            else if ((ret = wc_Sm3Final(sm3, hash)) != 0) {
+                WOLFSSL_MSG("Sm3Final failed");
+            }
+            wc_Sm3Free(sm3);
+        }
+
+    #ifdef WOLFSSL_SMALL_STACK
+        XFREE(sm3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
+
+        return ret;
+    }
+#endif /* !WOLFSSL_NOSHA3_224 */
+
 #endif /* !NO_HASH_WRAPPER */
 
 #ifdef WOLFSSL_HASH_KEEP

+ 74 - 0
wolfcrypt/src/hmac.c

@@ -141,6 +141,9 @@ int wc_HmacSizeByType(int type)
     int ret;
 
     if (!(type == WC_MD5 || type == WC_SHA ||
+    #ifdef WOLFSSL_SM3
+            type == WC_SM3 ||
+    #endif
             type == WC_SHA224 || type == WC_SHA256 ||
             type == WC_SHA384 || type == WC_SHA512 ||
             type == WC_SHA3_224 || type == WC_SHA3_256 ||
@@ -200,7 +203,12 @@ int wc_HmacSizeByType(int type)
         case WC_SHA3_512:
             ret = WC_SHA3_512_DIGEST_SIZE;
             break;
+    #endif /* WOLFSSL_SHA3 */
 
+    #ifdef WOLFSSL_SM3
+        case WC_SM3:
+            ret = WC_SM3_DIGEST_SIZE;
+            break;
     #endif
 
         default:
@@ -278,6 +286,12 @@ int _InitHmac(Hmac* hmac, int type, void* heap)
     #endif
     #endif
 
+    #ifdef WOLFSSL_SM3
+        case WC_SM3:
+            ret = wc_InitSm3(&hmac->hash.sm3, heap, devId);
+            break;
+    #endif
+
         default:
             ret = BAD_FUNC_ARG;
             break;
@@ -306,6 +320,9 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
 
     if (hmac == NULL || (key == NULL && length != 0) ||
        !(type == WC_MD5 || type == WC_SHA ||
+    #ifdef WOLFSSL_SM3
+            type == WC_SM3 ||
+    #endif
             type == WC_SHA224 || type == WC_SHA256 ||
             type == WC_SHA384 || type == WC_SHA512 ||
             type == WC_SHA3_224 || type == WC_SHA3_256 ||
@@ -558,6 +575,27 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length)
     #endif
     #endif /* WOLFSSL_SHA3 */
 
+    #ifdef WOLFSSL_SM3
+        case WC_SM3:
+            hmac_block_size = WC_SM3_BLOCK_SIZE;
+            if (length <= WC_SM3_BLOCK_SIZE) {
+                if (key != NULL) {
+                    XMEMCPY(ip, key, length);
+                }
+            }
+            else {
+                ret = wc_Sm3Update(&hmac->hash.sm3, key, length);
+                if (ret != 0)
+                    break;
+                ret = wc_Sm3Final(&hmac->hash.sm3, ip);
+                if (ret != 0)
+                    break;
+
+                length = WC_SM3_DIGEST_SIZE;
+            }
+            break;
+    #endif
+
         default:
             return BAD_FUNC_ARG;
     }
@@ -670,6 +708,13 @@ static int HmacKeyInnerHash(Hmac* hmac)
     #endif
     #endif /* WOLFSSL_SHA3 */
 
+    #ifdef WOLFSSL_SM3
+        case WC_SM3:
+            ret = wc_Sm3Update(&hmac->hash.sm3, (byte*)hmac->ipad,
+                                                             WC_SM3_BLOCK_SIZE);
+            break;
+    #endif
+
         default:
             break;
     }
@@ -776,6 +821,12 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
     #endif
     #endif /* WOLFSSL_SHA3 */
 
+    #ifdef WOLFSSL_SM3
+        case WC_SM3:
+            ret = wc_Sm3Update(&hmac->hash.sm3, msg, length);
+            break;
+    #endif
+
         default:
             break;
     }
@@ -993,6 +1044,23 @@ int wc_HmacFinal(Hmac* hmac, byte* hash)
     #endif
     #endif /* WOLFSSL_SHA3 */
 
+    #ifdef WOLFSSL_SM3
+        case WC_SM3:
+            ret = wc_Sm3Final(&hmac->hash.sm3, (byte*)hmac->innerHash);
+            if (ret != 0)
+                break;
+            ret = wc_Sm3Update(&hmac->hash.sm3, (byte*)hmac->opad,
+                                                             WC_SM3_BLOCK_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sm3Update(&hmac->hash.sm3, (byte*)hmac->innerHash,
+                                                            WC_SM3_DIGEST_SIZE);
+            if (ret != 0)
+                break;
+            ret = wc_Sm3Final(&hmac->hash.sm3, hash);
+            break;
+    #endif
+
         default:
             ret = BAD_FUNC_ARG;
             break;
@@ -1167,6 +1235,12 @@ void wc_HmacFree(Hmac* hmac)
     #endif
     #endif /* WOLFSSL_SHA3 */
 
+    #ifdef WOLFSSL_SM3
+        case WC_SM3:
+            wc_Sm3Free(&hmac->hash.sm3);
+            break;
+    #endif
+
         default:
             break;
     }

+ 9 - 0
wolfcrypt/src/integer.c

@@ -553,6 +553,15 @@ int mp_exch (mp_int * a, mp_int * b)
   return MP_OKAY;
 }
 
+int mp_cond_swap_ct_ex (mp_int * a, mp_int * b, int c, int m, mp_int * t)
+{
+    (void)c;
+    (void)t;
+    if (m == 1)
+        mp_exch(a, b);
+    return MP_OKAY;
+}
+
 int mp_cond_swap_ct (mp_int * a, mp_int * b, int c, int m)
 {
     (void)c;

+ 14 - 0
wolfcrypt/src/kdf.c

@@ -113,6 +113,13 @@ int wc_PRF(byte* result, word32 resLen, const byte* secret,
         break;
     #endif
 
+    #ifdef WOLFSSL_SM3
+        case sm3_mac:
+            hash = WC_SM3;
+            len  = WC_SM3_DIGEST_SIZE;
+        break;
+    #endif
+
     #ifndef NO_SHA
         case sha_mac:
             hash = WC_SHA;
@@ -376,6 +383,13 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen,
                 len = WC_SHA512_DIGEST_SIZE;
                 break;
             #endif
+
+            #ifdef WOLFSSL_SM3
+            case WC_SM3:
+                len = WC_SM3_DIGEST_SIZE;
+                break;
+            #endif
+
             default:
                 return BAD_FUNC_ARG;
         }

+ 4 - 4
wolfcrypt/src/misc.c

@@ -104,13 +104,13 @@ masking and clearing memory logic.
 
     WC_MISC_STATIC WC_INLINE word32 rotlFixed(word32 x, word32 y)
     {
-        return (x << y) | (x >> (sizeof(y) * 8 - y));
+        return (x << y) | (x >> (sizeof(x) * 8 - y));
     }
 
 /* This routine performs a right circular arithmetic shift of <x> by <y> value. */
     WC_MISC_STATIC WC_INLINE word32 rotrFixed(word32 x, word32 y)
     {
-        return (x >> y) | (x << (sizeof(y) * 8 - y));
+        return (x >> y) | (x << (sizeof(x) * 8 - y));
     }
 
 #endif
@@ -120,14 +120,14 @@ masking and clearing memory logic.
 /* This routine performs a left circular arithmetic shift of <x> by <y> value */
 WC_MISC_STATIC WC_INLINE word16 rotlFixed16(word16 x, word16 y)
 {
-    return (x << y) | (x >> (sizeof(y) * 8 - y));
+    return (x << y) | (x >> (sizeof(x) * 8 - y));
 }
 
 
 /* This routine performs a right circular arithmetic shift of <x> by <y> value */
 WC_MISC_STATIC WC_INLINE word16 rotrFixed16(word16 x, word16 y)
 {
-    return (x >> y) | (x << (sizeof(y) * 8 - y));
+    return (x >> y) | (x << (sizeof(x) * 8 - y));
 }
 
 #endif /* WC_RC2 */

+ 85 - 27
wolfcrypt/src/pkcs7.c

@@ -2374,6 +2374,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
     word32 totalSz, total2Sz;
     int idx = 0, ret = 0;
     int digEncAlgoId, digEncAlgoType;
+    int keyIdSize;
     byte* flatSignedAttribs = NULL;
     word32 flatSignedAttribsSz = 0;
 
@@ -2392,6 +2393,13 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
         return BAD_FUNC_ARG;
     }
 
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
+           pkcs7->publicKeyOID)));
+#else
+    keyIdSize = KEYID_SIZE;
+#endif
+
 #ifdef WOLFSSL_SMALL_STACK
     signedDataOid = (byte *)XMALLOC(MAX_OID_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
     if (signedDataOid == NULL) {
@@ -2485,11 +2493,10 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
 
     } else if (pkcs7->sidType == CMS_SKID) {
         /* SubjectKeyIdentifier */
-        esd->issuerSKIDSz = SetOctetString(KEYID_SIZE, esd->issuerSKID);
-        esd->issuerSKIDSeqSz = SetExplicit(0, esd->issuerSKIDSz + KEYID_SIZE,
+        esd->issuerSKIDSz = SetOctetString(keyIdSize, esd->issuerSKID);
+        esd->issuerSKIDSeqSz = SetExplicit(0, esd->issuerSKIDSz + keyIdSize,
                                            esd->issuerSKIDSeq);
-        signerInfoSz += (esd->issuerSKIDSz + esd->issuerSKIDSeqSz +
-                         KEYID_SIZE);
+        signerInfoSz += (esd->issuerSKIDSz + esd->issuerSKIDSeqSz + keyIdSize);
 
         /* version MUST be 3 */
         esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0);
@@ -2723,8 +2730,8 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
         idx += esd->issuerSKIDSeqSz;
         XMEMCPY(output2 + idx, esd->issuerSKID, esd->issuerSKIDSz);
         idx += esd->issuerSKIDSz;
-        XMEMCPY(output2 + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE);
-        idx += KEYID_SIZE;
+        XMEMCPY(output2 + idx, pkcs7->issuerSubjKeyId, keyIdSize);
+        idx += keyIdSize;
     } else if (pkcs7->sidType == DEGENERATE_SID) {
         /* no signer infos in degenerate case */
     } else {
@@ -6118,6 +6125,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
     int ret = 0;
     int keySz, direction = 0;
     int blockKeySz = 0;
+    int keyIdSize;
 
     /* ASN.1 layout */
     int totalSz = 0;
@@ -6169,6 +6177,13 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
     byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
 #endif
 
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
+           pkcs7->publicKeyOID)));
+#else
+    keyIdSize = KEYID_SIZE;
+#endif
+
     /* allocate and init memory for recipient */
     recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap,
                                  DYNAMIC_TYPE_PKCS7);
@@ -6294,12 +6309,12 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
     totalSz += (encryptedKeyOctetSz + encryptedKeySz);
 
     /* SubjectKeyIdentifier */
-    subjKeyIdOctetSz = SetOctetString(KEYID_SIZE, subjKeyIdOctet);
-    totalSz += (subjKeyIdOctetSz + KEYID_SIZE);
+    subjKeyIdOctetSz = SetOctetString(keyIdSize, subjKeyIdOctet);
+    totalSz += (subjKeyIdOctetSz + keyIdSize);
 
     /* RecipientKeyIdentifier IMPLICIT [0] */
     recipKeyIdSeqSz = SetImplicit(ASN_SEQUENCE, 0, subjKeyIdOctetSz +
-                                  KEYID_SIZE, recipKeyIdSeq);
+                                  keyIdSize, recipKeyIdSeq);
     totalSz += recipKeyIdSeqSz;
 
     /* RecipientEncryptedKey */
@@ -6423,8 +6438,8 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
     XMEMCPY(recip->recip + idx, subjKeyIdOctet, subjKeyIdOctetSz);
     idx += subjKeyIdOctetSz;
     /* subject key id */
-    XMEMCPY(recip->recip + idx, kari->decoded->extSubjKeyId, KEYID_SIZE);
-    idx += KEYID_SIZE;
+    XMEMCPY(recip->recip + idx, kari->decoded->extSubjKeyId, keyIdSize);
+    idx += keyIdSize;
     XMEMCPY(recip->recip + idx, encryptedKeyOctet, encryptedKeyOctetSz);
     idx += encryptedKeyOctetSz;
     /* encrypted CEK */
@@ -6473,6 +6488,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz,
     WC_RNG rng;
     word32 idx = 0;
     word32 encryptedKeySz = 0;
+    int keyIdSize;
 
     int ret = 0, blockKeySz;
     int verSz = 0, issuerSz = 0, snSz = 0, keyEncAlgSz = 0;
@@ -6599,6 +6615,13 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz,
         return ret;
     }
 
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
+           decoded->signatureOID)));
+#else
+    keyIdSize = KEYID_SIZE;
+#endif
+
     if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) {
 
         /* version, must be 0 for IssuerAndSerialNumber */
@@ -6655,7 +6678,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz,
         verSz = SetMyVersion(2, ver, 0);
         recip->recipVersion = 2;
 
-        issuerSKIDSz = SetLength(KEYID_SIZE, issuerSKID);
+        issuerSKIDSz = SetLength(keyIdSize, issuerSKID);
     } else {
         FreeDecodedCert(decoded);
 #ifdef WOLFSSL_SMALL_STACK
@@ -6815,10 +6838,10 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz,
 
     } else {
         recipSeqSz = SetSequence(verSz + ASN_TAG_SZ + issuerSKIDSz +
-                                 KEYID_SIZE + keyEncAlgSz + encKeyOctetStrSz +
+                                 keyIdSize + keyEncAlgSz + encKeyOctetStrSz +
                                  encryptedKeySz, recipSeq);
 
-        if (recipSeqSz + verSz + ASN_TAG_SZ + issuerSKIDSz + KEYID_SIZE +
+        if (recipSeqSz + verSz + ASN_TAG_SZ + issuerSKIDSz + keyIdSize +
             keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) {
             WOLFSSL_MSG("RecipientInfo output buffer too small");
             FreeDecodedCert(decoded);
@@ -6852,8 +6875,8 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz,
         idx += ASN_TAG_SZ;
         XMEMCPY(recip->recip + idx, issuerSKID, issuerSKIDSz);
         idx += issuerSKIDSz;
-        XMEMCPY(recip->recip + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE);
-        idx += KEYID_SIZE;
+        XMEMCPY(recip->recip + idx, pkcs7->issuerSubjKeyId, keyIdSize);
+        idx += keyIdSize;
     }
     XMEMCPY(recip->recip + idx, keyAlgArray, keyEncAlgSz);
     idx += keyEncAlgSz;
@@ -8567,6 +8590,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz,
 {
     int length, encryptedKeySz = 0, ret = 0;
     int keySz, version, sidType = 0;
+    int keyIdSize;
     word32 encOID = 0;
     word32 keyIdx;
     byte   issuerHash[KEYID_SIZE];
@@ -8593,6 +8617,13 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz,
     RsaKey privKey[1];
 #endif
 
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
+           pkcs7->publicKeyOID)));
+#else
+    keyIdSize = KEYID_SIZE;
+#endif
+
     switch (pkcs7->state) {
         case WC_PKCS7_DECRYPT_KTRI:
         #ifndef NO_PKCS7_STREAM
@@ -8680,11 +8711,12 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz,
                 if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
                     return ASN_PARSE_E;
 
-                if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0)
+                if (GetNameHash_ex(pkiMsg, idx, issuerHash, pkiMsgSz,
+                                   pkcs7->publicKeyOID) < 0)
                     return ASN_PARSE_E;
 
                 /* if we found correct recipient, issuer hashes will match */
-                if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) {
+                if (XMEMCMP(issuerHash, pkcs7->issuerHash, keyIdSize) == 0) {
                     *recipFound = 1;
                 }
 
@@ -8732,15 +8764,15 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz,
                 if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
                     return ASN_PARSE_E;
 
-                if (KEYID_SIZE > pkiMsgSz - (*idx))
+                if ((word32)keyIdSize > pkiMsgSz - (*idx))
                     return BUFFER_E;
 
                 /* if we found correct recipient, SKID will match */
                 if (XMEMCMP(pkiMsg + (*idx), pkcs7->issuerSubjKeyId,
-                            KEYID_SIZE) == 0) {
+                            keyIdSize) == 0) {
                     *recipFound = 1;
                 }
-                (*idx) += KEYID_SIZE;
+                (*idx) += keyIdSize;
             }
 
             if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0)
@@ -9149,11 +9181,19 @@ static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari,
 {
     int length;
     byte tag;
+    int keyIdSize;
 
     if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL ||
             rid == NULL)
         return BAD_FUNC_ARG;
 
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
+           kari->decoded->signatureOID)));
+#else
+    keyIdSize = KEYID_SIZE;
+#endif
+
     /* remove RecipientKeyIdentifier IMPLICIT [0] */
     if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) {
         return ASN_PARSE_E;
@@ -9178,14 +9218,14 @@ static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari,
     if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0)
         return ASN_PARSE_E;
 
-    if (length != KEYID_SIZE)
+    if (length != keyIdSize)
         return ASN_PARSE_E;
 
-    XMEMCPY(rid, pkiMsg + (*idx), KEYID_SIZE);
+    XMEMCPY(rid, pkiMsg + (*idx), keyIdSize);
     (*idx) += length;
 
     /* subject key id should match if recipient found */
-    if (XMEMCMP(rid, kari->decoded->extSubjKeyId, KEYID_SIZE) == 0) {
+    if (XMEMCMP(rid, kari->decoded->extSubjKeyId, keyIdSize) == 0) {
         *recipFound = 1;
     }
 
@@ -9200,6 +9240,7 @@ static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari,
                         int* recipFound, byte* rid)
 {
     int length, ret;
+    int keyIdSize;
 #ifdef WOLFSSL_SMALL_STACK
     mp_int* serial;
     mp_int* recipSerial;
@@ -9212,15 +9253,24 @@ static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari,
         return BAD_FUNC_ARG;
     }
 
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
+           kari->decoded->signatureOID)));
+#else
+    keyIdSize = KEYID_SIZE;
+#endif
+
     /* remove IssuerAndSerialNumber */
     if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0)
         return ASN_PARSE_E;
 
-    if (GetNameHash(pkiMsg, idx, rid, pkiMsgSz) < 0)
+    if (GetNameHash_ex(pkiMsg, idx, rid, pkiMsgSz,
+                       kari->decoded->signatureOID) < 0) {
         return ASN_PARSE_E;
+    }
 
     /* if we found correct recipient, issuer hashes will match */
-    if (XMEMCMP(rid, kari->decoded->issuerHash, KEYID_SIZE) == 0) {
+    if (XMEMCMP(rid, kari->decoded->issuerHash, keyIdSize) == 0) {
         *recipFound = 1;
     }
 
@@ -9876,6 +9926,7 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz,
     int ret, keySz;
     int encryptedKeySz;
     int direction = 0;
+    int keyIdSize;
     word32 keyAgreeOID, keyWrapOID;
     byte rid[KEYID_SIZE];
 
@@ -9899,6 +9950,13 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz,
         return BAD_FUNC_ARG;
     }
 
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    keyIdSize = wc_HashGetDigestSize(wc_HashTypeConvert(HashIdAlg(
+           pkcs7->publicKeyOID)));
+#else
+    keyIdSize = KEYID_SIZE;
+#endif
+
     switch (pkcs7->state) {
         case WC_PKCS7_DECRYPT_KARI: {
             WC_PKCS7_KARI* kari;
@@ -10054,7 +10112,7 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz,
                 tmpKeySz = (word32)ret;
 
                 keySz = pkcs7->wrapCEKCb(pkcs7, encryptedKey, encryptedKeySz,
-                        rid, KEYID_SIZE, tmpKeyDer, tmpKeySz,
+                        rid, keyIdSize, tmpKeyDer, tmpKeySz,
                         decryptedKey, *decryptedKeySz,
                         keyWrapOID, (int)PKCS7_KARI, direction);
                 XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);

+ 50 - 45
wolfcrypt/src/port/arm/armv8-aes.c

@@ -1462,7 +1462,7 @@ int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
 
 /* PMULL and RBIT only with AArch64 */
 /* Use ARM hardware for polynomial multiply */
-static void GMULT(byte* X, byte* Y)
+void GMULT(byte* X, byte* Y)
 {
     __asm__ volatile (
         "LD1 {v0.16b}, [%[inX]] \n"
@@ -1511,14 +1511,19 @@ static void GMULT(byte* X, byte* Y)
 }
 
 
-void GHASH(Aes* aes, const byte* a, word32 aSz,
-                                const byte* c, word32 cSz, byte* s, word32 sSz)
+void GHASH(Gcm* gcm, const byte* a, word32 aSz, const byte* c,
+    word32 cSz, byte* s, word32 sSz)
 {
     byte x[AES_BLOCK_SIZE];
     byte scratch[AES_BLOCK_SIZE];
     word32 blocks, partial;
-    byte* h = aes->H;
+    byte* h;
+
+    if (gcm == NULL) {
+        return;
+    }
 
+    h = gcm->H;
     XMEMSET(x, 0, AES_BLOCK_SIZE);
 
     /* Hash in A, the Additional Authentication Data */
@@ -1597,8 +1602,8 @@ static int Aes128GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         initialCounter[AES_BLOCK_SIZE - 1] = 1;
     }
     else {
-        GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
-        GMULT(initialCounter, aes->H);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
+        GMULT(initialCounter, aes->gcm.H);
     }
     XMEMCPY(counter, initialCounter, AES_BLOCK_SIZE);
 
@@ -1611,14 +1616,14 @@ static int Aes128GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         /* do as many blocks as possible */
         while (blocks--) {
             xorbuf(x, authIn, AES_BLOCK_SIZE);
-            GMULT(x, aes->H);
+            GMULT(x, aes->gcm.H);
             authIn += AES_BLOCK_SIZE;
         }
         if (partial != 0) {
             XMEMSET(scratch, 0, AES_BLOCK_SIZE);
             XMEMCPY(scratch, authIn, partial);
             xorbuf(x, scratch, AES_BLOCK_SIZE);
-            GMULT(x, aes->H);
+            GMULT(x, aes->gcm.H);
         }
     }
 
@@ -1777,10 +1782,10 @@ static int Aes128GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
             "STR q17, [%[xOut]] \n" /* GHASH x value for partial blocks */
 
             :[out] "=r" (out), "=r" (keyPt), [ctrOut] "=r" (ctr), "=r" (in)
-            ,[xOut] "=r" (xPt),"=m" (aes->H)
+            ,[xOut] "=r" (xPt),"=m" (aes->gcm.H)
             :"0" (out), [Key] "1" (keyPt), [ctr] "2" (ctr), [blocks] "r" (blocks),
              [input] "3" (in)
-            ,[inX] "4" (xPt), [inY] "m" (aes->H)
+            ,[inX] "4" (xPt), [inY] "m" (aes->gcm.H)
             : "cc", "w11", "v0", "v1", "v2", "v3", "v4", "v5",
             "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14"
             ,"v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", "v24"
@@ -1797,7 +1802,7 @@ static int Aes128GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         XMEMSET(scratch, 0, AES_BLOCK_SIZE);
         XMEMCPY(scratch, out, partial);
         xorbuf(x, scratch, AES_BLOCK_SIZE);
-        GMULT(x, aes->H);
+        GMULT(x, aes->gcm.H);
     }
 
     /* Hash in the lengths of A and C in bits */
@@ -1866,7 +1871,7 @@ static int Aes128GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
 
         :[out] "=r" (sPt), "=r" (keyPt), "=r" (iCtr)
         :[tag] "0" (sPt), [Key] "1" (keyPt),
-        [ctr] "2" (iCtr) , [h] "m" (aes->H)
+        [ctr] "2" (iCtr) , [h] "m" (aes->gcm.H)
         : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5",
         "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14",
         "v15", "v16", "v17","v18", "v19", "v20","v21","v22","v23","v24"
@@ -1915,8 +1920,8 @@ static int Aes192GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         initialCounter[AES_BLOCK_SIZE - 1] = 1;
     }
     else {
-        GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
-        GMULT(initialCounter, aes->H);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
+        GMULT(initialCounter, aes->gcm.H);
     }
     XMEMCPY(counter, initialCounter, AES_BLOCK_SIZE);
 
@@ -1929,14 +1934,14 @@ static int Aes192GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         /* do as many blocks as possible */
         while (blocks--) {
             xorbuf(x, authIn, AES_BLOCK_SIZE);
-            GMULT(x, aes->H);
+            GMULT(x, aes->gcm.H);
             authIn += AES_BLOCK_SIZE;
         }
         if (partial != 0) {
             XMEMSET(scratch, 0, AES_BLOCK_SIZE);
             XMEMCPY(scratch, authIn, partial);
             xorbuf(x, scratch, AES_BLOCK_SIZE);
-            GMULT(x, aes->H);
+            GMULT(x, aes->gcm.H);
         }
     }
 
@@ -2103,10 +2108,10 @@ static int Aes192GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
             "STR q17, [%[xOut]] \n" /* GHASH x value for partial blocks */
 
             :[out] "=r" (out), "=r" (keyPt), [ctrOut] "=r" (ctr), "=r" (in)
-            ,[xOut] "=r" (xPt),"=m" (aes->H)
+            ,[xOut] "=r" (xPt),"=m" (aes->gcm.H)
             :"0" (out), [Key] "1" (keyPt), [ctr] "2" (ctr), [blocks] "r" (blocks),
              [input] "3" (in)
-            ,[inX] "4" (xPt), [inY] "m" (aes->H)
+            ,[inX] "4" (xPt), [inY] "m" (aes->gcm.H)
             : "cc", "w11", "v0", "v1", "v2", "v3", "v4", "v5",
             "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14"
             ,"v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
@@ -2124,7 +2129,7 @@ static int Aes192GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         XMEMSET(scratch, 0, AES_BLOCK_SIZE);
         XMEMCPY(scratch, out, partial);
         xorbuf(x, scratch, AES_BLOCK_SIZE);
-        GMULT(x, aes->H);
+        GMULT(x, aes->gcm.H);
     }
 
     /* Hash in the lengths of A and C in bits */
@@ -2198,7 +2203,7 @@ static int Aes192GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
 
         :[out] "=r" (sPt), "=r" (keyPt), "=r" (iCtr)
         :[tag] "0" (sPt), [Key] "1" (keyPt),
-        [ctr] "2" (iCtr) , [h] "m" (aes->H)
+        [ctr] "2" (iCtr) , [h] "m" (aes->gcm.H)
         : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5",
         "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14",
         "v15", "v16", "v17","v18", "v19", "v20","v21","v22","v23","v24"
@@ -2248,8 +2253,8 @@ static int Aes256GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         initialCounter[AES_BLOCK_SIZE - 1] = 1;
     }
     else {
-        GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
-        GMULT(initialCounter, aes->H);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
+        GMULT(initialCounter, aes->gcm.H);
     }
     XMEMCPY(counter, initialCounter, AES_BLOCK_SIZE);
 
@@ -2262,14 +2267,14 @@ static int Aes256GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         /* do as many blocks as possible */
         while (blocks--) {
             xorbuf(x, authIn, AES_BLOCK_SIZE);
-            GMULT(x, aes->H);
+            GMULT(x, aes->gcm.H);
             authIn += AES_BLOCK_SIZE;
         }
         if (partial != 0) {
             XMEMSET(scratch, 0, AES_BLOCK_SIZE);
             XMEMCPY(scratch, authIn, partial);
             xorbuf(x, scratch, AES_BLOCK_SIZE);
-            GMULT(x, aes->H);
+            GMULT(x, aes->gcm.H);
         }
     }
 
@@ -2444,10 +2449,10 @@ static int Aes256GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
             "STR q17, [%[xOut]] \n" /* GHASH x value for partial blocks */
 
             :[out] "=r" (out), "=r" (keyPt), [ctrOut] "=r" (ctr), "=r" (in)
-            ,[xOut] "=r" (xPt),"=m" (aes->H)
+            ,[xOut] "=r" (xPt),"=m" (aes->gcm.H)
             :"0" (out), [Key] "1" (keyPt), [ctr] "2" (ctr), [blocks] "r" (blocks),
              [input] "3" (in)
-            ,[inX] "4" (xPt), [inY] "m" (aes->H)
+            ,[inX] "4" (xPt), [inY] "m" (aes->gcm.H)
             : "cc", "w11", "v0", "v1", "v2", "v3", "v4", "v5",
             "v6", "v7", "v8", "v9", "v10", "v11", "v12", "v13", "v14"
             ,"v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", "v24"
@@ -2464,7 +2469,7 @@ static int Aes256GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         XMEMSET(scratch, 0, AES_BLOCK_SIZE);
         XMEMCPY(scratch, out, partial);
         xorbuf(x, scratch, AES_BLOCK_SIZE);
-        GMULT(x, aes->H);
+        GMULT(x, aes->gcm.H);
     }
 
     /* Hash in the lengths of A and C in bits */
@@ -2542,7 +2547,7 @@ static int Aes256GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
 
         :[out] "=r" (sPt), "=r" (keyPt), "=r" (iCtr)
         :[tag] "0" (sPt), [Key] "1" (keyPt),
-        [ctr] "2" (iCtr) , [h] "m" (aes->H)
+        [ctr] "2" (iCtr) , [h] "m" (aes->gcm.H)
         : "cc", "memory", "v0", "v1", "v2", "v3", "v4", "v5",
         "v6", "v7", "v8", "v9", "v10","v11","v12","v13","v14",
         "v15", "v16", "v17","v18", "v19", "v20","v21","v22","v23",
@@ -2670,8 +2675,8 @@ int  wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         initialCounter[AES_BLOCK_SIZE - 1] = 1;
     }
     else {
-        GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
-        GMULT(initialCounter, aes->H);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
+        GMULT(initialCounter, aes->gcm.H);
     }
     XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE);
 
@@ -2681,8 +2686,8 @@ int  wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         byte Tprime[AES_BLOCK_SIZE];
         byte EKY0[AES_BLOCK_SIZE];
 
-        GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime));
-        GMULT(Tprime, aes->H);
+        GHASH(&aes->gcm, authIn, authInSz, in, sz, Tprime, sizeof(Tprime));
+        GMULT(Tprime, aes->gcm.H);
         wc_AesEncrypt(aes, ctr, EKY0);
         xorbuf(Tprime, EKY0, sizeof(Tprime));
 
@@ -4280,7 +4285,7 @@ void GHASH(Aes* aes, const byte* a, word32 aSz,
     byte x[AES_BLOCK_SIZE];
     byte scratch[AES_BLOCK_SIZE];
     word32 blocks, partial;
-    byte* h = aes->H;
+    byte* h = aes->gcm.H;
 
     XMEMSET(x, 0, AES_BLOCK_SIZE);
 
@@ -4377,7 +4382,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         initialCounter[AES_BLOCK_SIZE - 1] = 1;
     }
     else {
-        GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
     }
     XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE);
 
@@ -4398,7 +4403,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz,
 
     }
 
-    GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
+    GHASH(&aes->gcm, authIn, authInSz, out, sz, authTag, authTagSz);
     wc_AesEncrypt(aes, initialCounter, scratch);
     if (authTagSz > AES_BLOCK_SIZE) {
         xorbuf(authTag, scratch, AES_BLOCK_SIZE);
@@ -4454,7 +4459,7 @@ int  wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         initialCounter[AES_BLOCK_SIZE - 1] = 1;
     }
     else {
-        GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE);
     }
     XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE);
 
@@ -4464,7 +4469,7 @@ int  wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
         byte Tprime[AES_BLOCK_SIZE];
         byte EKY0[AES_BLOCK_SIZE];
 
-        GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime));
+        GHASH(&aes->gcm, authIn, authInSz, in, sz, Tprime, sizeof(Tprime));
         wc_AesEncrypt(aes, ctr, EKY0);
         xorbuf(Tprime, EKY0, sizeof(Tprime));
 
@@ -4523,7 +4528,7 @@ int  wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz,
 #define GHASH_ONE_BLOCK(aes, block)                     \
     do {                                                \
         xorbuf(AES_TAG(aes), block, AES_BLOCK_SIZE);    \
-        GMULT(AES_TAG(aes), aes->H);                    \
+        GMULT(AES_TAG(aes), aes->gcm.H);                \
     }                                                   \
     while (0)
 
@@ -4719,8 +4724,8 @@ static void AesGcmInit_C(Aes* aes, const byte* iv, word32 ivSz)
         word32 aadTemp = aes->aadLen;
         aes->aadLen = 0;
     #endif
-        GHASH(aes, NULL, 0, iv, ivSz, counter, AES_BLOCK_SIZE);
-        GMULT(counter, aes->H);
+        GHASH(&aes->gcm, NULL, 0, iv, ivSz, counter, AES_BLOCK_SIZE);
+        GMULT(counter, aes->gcm.H);
     #ifdef OPENSSL_EXTRA
         aes->aadLen = aadTemp;
     #endif
@@ -5401,10 +5406,10 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
         aes->gcmKeySet = 1;
 #endif
 
-        wc_AesEncrypt(aes, iv, aes->H);
+        wc_AesEncrypt(aes, iv, aes->gcm.H);
     #if defined(__aarch64__)
         {
-            word32* pt = (word32*)aes->H;
+            word32* pt = (word32*)aes->gcm.H;
             __asm__ volatile (
                 "LD1 {v0.16b}, [%[h]] \n"
                 "RBIT v0.16b, v0.16b \n"
@@ -5416,7 +5421,7 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
         }
     #else
         {
-            word32* pt = (word32*)aes->H;
+            word32* pt = (word32*)aes->gcm.H;
             __asm__ volatile (
                 "VLD1.32 {q0}, [%[h]] \n"
                 "VREV64.8 q0, q0 \n"
@@ -5970,7 +5975,7 @@ static void GenerateM0(Aes* aes)
     /* 0 times -> 0x0 */
     XMEMSET(m[0x0], 0, AES_BLOCK_SIZE);
     /* 1 times -> 0x8 */
-    XMEMCPY(m[0x8], aes->H, AES_BLOCK_SIZE);
+    XMEMCPY(m[0x8], aes->gcm.H, AES_BLOCK_SIZE);
     /* 2 times -> 0x4 */
     XMEMCPY(m[0x4], m[0x8], AES_BLOCK_SIZE);
     RIGHTSHIFTX(m[0x4]);
@@ -6035,7 +6040,7 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len)
     ret = wc_AesSetKey(aes, key, len, iv, AES_ENCRYPTION);
     
     if (ret == 0) {
-        AES_ECB_encrypt(iv, aes->H, AES_BLOCK_SIZE,
+        AES_ECB_encrypt(iv, aes->gcm.H, AES_BLOCK_SIZE,
             (const unsigned char*)aes->key, aes->rounds);
         GenerateM0(aes);
     }

+ 3 - 0
wolfcrypt/src/rsa.c

@@ -2085,6 +2085,9 @@ int wc_hash2mgf(enum wc_HashType hType)
     case WC_HASH_TYPE_SHA3_512:
     case WC_HASH_TYPE_BLAKE2B:
     case WC_HASH_TYPE_BLAKE2S:
+#ifdef WOLFSSL_SM3
+    case WC_HASH_TYPE_SM3:
+#endif
     #ifdef WOLFSSL_SHAKE128
         case WC_HASH_TYPE_SHAKE128:
     #endif

+ 13 - 0
wolfcrypt/src/sm2.c

@@ -0,0 +1,13 @@
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_SM2
+
+#error "Contact wolfSSL to get the implementation of this file"
+
+#endif
+

+ 13 - 0
wolfcrypt/src/sm3.c

@@ -0,0 +1,13 @@
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_SM3
+
+#error "Contact wolfSSL to get the implementation of this file"
+
+#endif
+

+ 3 - 0
wolfcrypt/src/sm3_asm.S

@@ -0,0 +1,3 @@
+
+#error "Contact wolfSSL to get the implementation of this file"
+

+ 13 - 0
wolfcrypt/src/sm4.c

@@ -0,0 +1,13 @@
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifdef WOLFSSL_SM4
+
+#error "Contact wolfSSL to get the implementation of this file"
+
+#endif
+

+ 48 - 31
wolfcrypt/src/sp_int.c

@@ -5233,49 +5233,66 @@ int sp_exch(sp_int* a, sp_int* b)
  * @param [in]  b     Second SP int to conditionally swap.
  * @param [in]  cnt   Count of words to copy.
  * @param [in]  swap  When value is 1 then swap.
+ * @param [in]  t     Temporary SP int to use in swap.
  * @return  MP_OKAY on success.
  * @return  MP_MEM when dynamic memory allocation fails.
  */
-int sp_cond_swap_ct(sp_int* a, sp_int* b, int cnt, int swap)
+int sp_cond_swap_ct_ex(sp_int* a, sp_int* b, int cnt, int swap, sp_int* t)
 {
     unsigned int i;
-    int err = MP_OKAY;
     sp_int_digit mask = (sp_int_digit)0 - (sp_int_digit)swap;
-    DECL_SP_INT(t, (size_t)cnt);
 
-    /* Allocate temporary to hold masked xor of a and b. */
-    ALLOC_SP_INT(t, cnt, err, NULL);
-    if (err == MP_OKAY) {
-        /* XOR other fields in sp_int into temp - mask set when swapping. */
-        t->used = (a->used ^ b->used) & (unsigned int)mask;
-    #ifdef WOLFSSL_SP_INT_NEGATIVE
-        t->sign = (a->sign ^ b->sign) & (unsigned int)mask;
-    #endif
+    /* XOR other fields in sp_int into temp - mask set when swapping. */
+    t->used = (a->used ^ b->used) & (unsigned int)mask;
+#ifdef WOLFSSL_SP_INT_NEGATIVE
+    t->sign = (a->sign ^ b->sign) & (unsigned int)mask;
+#endif
 
-        /* XOR requested words into temp - mask set when swapping. */
-        for (i = 0; i < (unsigned int)cnt; i++) {
-            t->dp[i] = (a->dp[i] ^ b->dp[i]) & mask;
-        }
+    /* XOR requested words into temp - mask set when swapping. */
+    for (i = 0; i < (unsigned int)cnt; i++) {
+        t->dp[i] = (a->dp[i] ^ b->dp[i]) & mask;
+    }
 
-        /* XOR temporary - when mask set then result will be b. */
-        a->used ^= t->used;
-    #ifdef WOLFSSL_SP_INT_NEGATIVE
-        a->sign ^= t->sign;
-    #endif
-        for (i = 0; i < (unsigned int)cnt; i++) {
-            a->dp[i] ^= t->dp[i];
-        }
+    /* XOR temporary - when mask set then result will be b. */
+    a->used ^= t->used;
+#ifdef WOLFSSL_SP_INT_NEGATIVE
+    a->sign ^= t->sign;
+#endif
+    for (i = 0; i < (unsigned int)cnt; i++) {
+        a->dp[i] ^= t->dp[i];
+    }
 
-        /* XOR temporary - when mask set then result will be a. */
-        b->used ^= t->used;
-    #ifdef WOLFSSL_SP_INT_NEGATIVE
-        b->sign ^= b->sign;
-    #endif
-        for (i = 0; i < (unsigned int)cnt; i++) {
-            b->dp[i] ^= t->dp[i];
-        }
+    /* XOR temporary - when mask set then result will be a. */
+    b->used ^= t->used;
+#ifdef WOLFSSL_SP_INT_NEGATIVE
+    b->sign ^= b->sign;
+#endif
+    for (i = 0; i < (unsigned int)cnt; i++) {
+        b->dp[i] ^= t->dp[i];
     }
 
+    return MP_OKAY;
+}
+
+/* Conditional swap of SP int values in constant time.
+ *
+ * @param [in]  a     First SP int to conditionally swap.
+ * @param [in]  b     Second SP int to conditionally swap.
+ * @param [in]  cnt   Count of words to copy.
+ * @param [in]  swap  When value is 1 then swap.
+ * @return  MP_OKAY on success.
+ * @return  MP_MEM when dynamic memory allocation fails.
+ */
+int sp_cond_swap_ct(sp_int* a, sp_int* b, int cnt, int swap)
+{
+    int err = MP_OKAY;
+    DECL_SP_INT(t, (size_t)cnt);
+
+    /* Allocate temporary to hold masked xor of a and b. */
+    ALLOC_SP_INT(t, cnt, err, NULL);
+
+    err = sp_cond_swap_ct_ex(a, b, cnt, swap, t);
+
     FREE_SP_INT(t, NULL);
     return err;
 }

+ 27 - 13
wolfcrypt/src/tfm.c

@@ -4807,21 +4807,10 @@ int mp_montgomery_calc_normalization(mp_int *a, mp_int *b)
 
 #endif /* WOLFSSL_KEY_GEN || HAVE_ECC */
 
-static int fp_cond_swap_ct (mp_int * a, mp_int * b, int c, int m)
+static int fp_cond_swap_ct_ex(mp_int* a, mp_int* b, int c, int m, mp_int* t)
 {
     int i;
     mp_digit mask = (mp_digit)0 - m;
-#ifndef WOLFSSL_SMALL_STACK
-    fp_int  t[1];
-#else
-    fp_int* t;
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
-   t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
-   if (t == NULL)
-       return FP_MEM;
-#endif
 
     t->used = (a->used ^ b->used) & mask;
     for (i = 0; i < c; i++) {
@@ -4836,6 +4825,26 @@ static int fp_cond_swap_ct (mp_int * a, mp_int * b, int c, int m)
         b->dp[i] ^= t->dp[i];
     }
 
+    return FP_OKAY;
+}
+
+
+static int fp_cond_swap_ct(mp_int* a, mp_int* b, int c, int m)
+{
+#ifndef WOLFSSL_SMALL_STACK
+    fp_int  t[1];
+#else
+    fp_int* t;
+#endif
+
+#ifdef WOLFSSL_SMALL_STACK
+   t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT);
+   if (t == NULL)
+       return FP_MEM;
+#endif
+
+   fp_cond_swap_ct_ex(a, b, c, m, t);
+
 #ifdef WOLFSSL_SMALL_STACK
     XFREE(t, NULL, DYNAMIC_TYPE_BIGINT);
 #endif
@@ -5426,7 +5435,12 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng)
 #endif /* !NO_RSA || !NO_DSA || !NO_DH || WOLFSSL_KEY_GEN */
 
 
-int mp_cond_swap_ct(mp_int * a, mp_int * b, int c, int m)
+int mp_cond_swap_ct_ex(mp_int* a, mp_int* b, int c, int m, mp_int* t)
+{
+    return fp_cond_swap_ct_ex(a, b, c, m, t);
+}
+
+int mp_cond_swap_ct(mp_int* a, mp_int* b, int c, int m)
 {
     return fp_cond_swap_ct(a, b, c, m);
 }

File diff suppressed because it is too large
+ 1324 - 615
wolfcrypt/test/test.c


+ 115 - 6
wolfssl/internal.h

@@ -58,6 +58,9 @@
 #ifdef HAVE_CAMELLIA
     #include <wolfssl/wolfcrypt/camellia.h>
 #endif
+#ifdef WOLFSSL_SM4
+    #include <wolfssl/wolfcrypt/sm4.h>
+#endif
 #include <wolfssl/wolfcrypt/logging.h>
 #ifndef NO_HMAC
     #include <wolfssl/wolfcrypt/hmac.h>
@@ -83,6 +86,9 @@
 #ifdef WOLFSSL_SHA512
     #include <wolfssl/wolfcrypt/sha512.h>
 #endif
+#ifdef WOLFSSL_SM3
+    #include <wolfssl/wolfcrypt/sm3.h>
+#endif
 #ifdef HAVE_AESGCM
     #include <wolfssl/wolfcrypt/sha512.h>
 #endif
@@ -95,6 +101,9 @@
 #ifdef HAVE_ECC
     #include <wolfssl/wolfcrypt/ecc.h>
 #endif
+#ifdef WOLFSSL_SM2
+    #include <wolfssl/wolfcrypt/sm2.h>
+#endif
 #ifndef NO_DH
     #include <wolfssl/wolfcrypt/dh.h>
 #endif
@@ -840,6 +849,17 @@
     #endif
 #endif
 
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+        #ifdef WOLFSSL_SM4_CBC
+            #define BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3
+        #endif
+        #ifdef WOLFSSL_SM4_GCM
+            #define BUILD_TLS_ECDHE_ECDSA_WITH_SM4_GCM_SM3
+        #endif
+        #ifdef WOLFSSL_SM4_CCM
+            #define BUILD_TLS_ECDHE_ECDSA_WITH_SM4_CCM_SM3
+        #endif
+    #endif
 #endif
 
 #if defined(WOLFSSL_TLS13)
@@ -872,6 +892,16 @@
             #define BUILD_TLS_SHA384_SHA384
         #endif
     #endif
+
+    #ifdef WOLFSSL_SM3
+        #ifdef WOLFSSL_SM4_GCM
+            #define BUILD_TLS_SM4_GCM_SM3
+        #endif
+
+        #ifdef WOLFSSL_SM4_CCM
+            #define BUILD_TLS_SM4_CCM_SM3
+        #endif
+    #endif
 #endif
 
 #if !defined(WOLFCRYPT_ONLY) && defined(NO_PSK) && \
@@ -971,6 +1001,7 @@
      defined(HAVE_AESCCM) || \
     (defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \
      !defined(NO_CHAPOL_AEAD)) || \
+    defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM) || \
     (defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER))
 
     #define HAVE_AEAD
@@ -1140,6 +1171,15 @@ enum {
     TLS_SHA256_SHA256            = 0xB4,
     TLS_SHA384_SHA384            = 0xB5,
 
+    /* TLS v1.3 SM cipher suites - 0x00 (CIPHER_BYTE) is first byte */
+    TLS_SM4_GCM_SM3              = 0xC6,
+    TLS_SM4_CCM_SM3              = 0xC7,
+
+    /* TLS v1.2 SM cipher suites - 0xE0 (SM_BYTE) is first byte */
+    TLS_ECDHE_ECDSA_WITH_SM4_CBC_SM3 = 0x11,
+    TLS_ECDHE_ECDSA_WITH_SM4_GCM_SM3 = 0x51,
+    TLS_ECDHE_ECDSA_WITH_SM4_CCM_SM3 = 0x52,
+
     /* Fallback SCSV (Signaling Cipher Suite Value) */
     TLS_FALLBACK_SCSV                        = 0x56,
     /* Renegotiation Indication Extension Special Suite */
@@ -1395,6 +1435,15 @@ enum {
 #define DTLS_AEAD_AES_CCM_FAIL_LIMIT             w64From32(0x00B5, 0x04F3)
 #define DTLS_AEAD_AES_CCM_FAIL_KU_LIMIT          w64From32(0x005A, 0x8279)
 
+/* Limit is (2^22 - 1) full messages [2^36 - 31 octets]
+ * https://www.rfc-editor.org/rfc/rfc8998.html#name-aead_sm4_gcm
+ */
+#define AEAD_SM4_GCM_LIMIT                       w64From32(0, (1 << 22) - 1)
+/* Limit is (2^10 - 1) full messages [2^24 - 1 octets]
+ * https://www.rfc-editor.org/rfc/rfc8998.html#name-aead_sm4_ccm
+ */
+#define AEAD_SM4_CCM_LIMIT                       w64From32(0, (1 << 10) - 1)
+
 #if defined(WOLFSSL_TLS13) || !defined(NO_PSK)
 
 #define TLS13_TICKET_NONCE_MAX_SZ 255
@@ -1432,6 +1481,7 @@ enum Misc {
     CHACHA_BYTE    = 0xCC,         /* ChaCha first cipher suite */
     TLS13_BYTE     = 0x13,         /* TLS v1.3 first byte of cipher suite */
     ECDHE_PSK_BYTE = 0xD0,         /* RFC 8442 */
+    SM_BYTE        = 0xE0,         /* SM first byte - private range */
 
     SEND_CERT       = 1,
     SEND_BLANK_CERT = 2,
@@ -1651,6 +1701,9 @@ enum Misc {
     AESGCM_IMP_IV_SZ    = 4,   /* Size of GCM/CCM AEAD implicit IV */
     AESGCM_EXP_IV_SZ    = 8,   /* Size of GCM/CCM AEAD explicit IV */
     AESGCM_NONCE_SZ     = AESGCM_EXP_IV_SZ + AESGCM_IMP_IV_SZ,
+    GCM_IMP_IV_SZ       = 4,   /* Size of GCM/CCM AEAD implicit IV */
+    GCM_EXP_IV_SZ       = 8,   /* Size of GCM/CCM AEAD explicit IV */
+    GCM_NONCE_SZ        = GCM_EXP_IV_SZ + GCM_IMP_IV_SZ,
 
     CHACHA20_IMP_IV_SZ  = 12,  /* Size of ChaCha20 AEAD implicit IV */
     CHACHA20_NONCE_SZ   = 12,  /* Size of ChacCha20 nonce           */
@@ -1663,6 +1716,11 @@ enum Misc {
     AES_CCM_8_AUTH_SZ   = 8,  /* AES-CCM-8 Auth Tag Length  */
     AESCCM_NONCE_SZ     = 12,
 
+    SM4_GCM_AUTH_SZ     = 16, /* SM4-GCM Auth Tag length    */
+    SM4_GCM_NONCE_SZ    = 12, /* SM4 GCM Nonce length       */
+    SM4_CCM_AUTH_SZ     = 16, /* SM4-CCM Auth Tag length    */
+    SM4_CCM_NONCE_SZ    = 12, /* SM4 CCM Nonce length       */
+
     CAMELLIA_128_KEY_SIZE = 16, /* for 128 bit */
     CAMELLIA_192_KEY_SIZE = 24, /* for 192 bit */
     CAMELLIA_256_KEY_SIZE = 32, /* for 256 bit */
@@ -1689,6 +1747,8 @@ enum Misc {
     ED25519_SA_MINOR    = 7,   /* Least significant byte for ED25519 */
     ED448_SA_MAJOR      = 8,   /* Most significant byte for ED448 */
     ED448_SA_MINOR      = 8,   /* Least significant byte for ED448 */
+    SM2_SA_MAJOR        = 7,   /* Most significant byte for SM2 with SM3 */
+    SM2_SA_MINOR        = 8,   /* Least significant byte for SM2 with SM3 */
 
     PQC_SA_MAJOR        = 0xFE,/* Most significant byte used with PQC sig algs */
 
@@ -2252,6 +2312,9 @@ WOLFSSL_LOCAL void InitSuitesHashSigAlgo_ex(byte* hashSigAlgo, int haveECDSAsig,
                                             int haveRSAsig, int haveFalconSig,
                                             int haveDilithiumSig, int haveAnon,
                                             int tls1_2, int keySz, word16* len);
+WOLFSSL_LOCAL void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int have,
+                                             int tls1_2, int keySz,
+                                             word16* len);
 WOLFSSL_LOCAL int AllocateCtxSuites(WOLFSSL_CTX* ctx);
 WOLFSSL_LOCAL int AllocateSuites(WOLFSSL* ssl);
 WOLFSSL_LOCAL void InitSuites(Suites* suites, ProtocolVersion pv, int keySz,
@@ -2341,7 +2404,9 @@ struct WOLFSSL_OCSP {
 
 typedef struct CRL_Entry CRL_Entry;
 
-#ifdef NO_SHA
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    #define CRL_DIGEST_SIZE WC_SM3_DIGEST_SIZE
+#elif defined(NO_SHA)
     #define CRL_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
 #else
     #define CRL_DIGEST_SIZE WC_SHA_DIGEST_SIZE
@@ -3195,10 +3260,11 @@ WOLFSSL_LOCAL int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group,
         word16 len, byte* data, KeyShareEntry **kse, TLSX** extensions);
 WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl);
 WOLFSSL_LOCAL int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl,
-                                             TLSX** extensions);
+        TLSX** extensions);
 WOLFSSL_LOCAL int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse);
 WOLFSSL_LOCAL int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions,
-                                       KeyShareEntry** kse, byte* searched);
+        byte cipherSuite0, byte cipherSuite, KeyShareEntry** kse,
+        byte* searched);
 WOLFSSL_LOCAL int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE);
 WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl, int* doHelloRetry);
 WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(WOLFSSL* sclientKSEclientKSEsl);
@@ -3825,6 +3891,14 @@ enum KeyExchangeAlgorithm {
     ecc_static_diffie_hellman_kea       /* for verify suite only */
 };
 
+/* Used with InitSuitesHashSigAlgo_ex2 */
+#define SIG_ECDSA       0x01
+#define SIG_RSA         0x02
+#define SIG_SM2         0x04
+#define SIG_FALCON      0x08
+#define SIG_DILITHIUM   0x10
+#define SIG_ANON        0x20
+
 /* Supported Authentication Schemes */
 enum SignatureAlgorithm {
     anonymous_sa_algo            = 0,
@@ -3840,6 +3914,7 @@ enum SignatureAlgorithm {
     dilithium_level2_sa_algo     = 14,
     dilithium_level3_sa_algo     = 15,
     dilithium_level5_sa_algo     = 16,
+    sm2_sa_algo                  = 17,
     invalid_sa_algo              = 255
 };
 
@@ -3855,6 +3930,18 @@ enum SigAlgRsaPss {
     pss_sha512  = 0x0b,
 };
 
+#ifdef WOLFSSL_SM2
+    /* Default SM2 signature ID. */
+    #define TLS12_SM2_SIG_ID        ((byte*)"1234567812345678")
+    /* Length of default SM2 signature ID. */
+    #define TLS12_SM2_SIG_ID_SZ     16
+
+    /* https://www.rfc-editor.org/rfc/rfc8998.html#name-sm2-signature-scheme */
+    /* ID to use when signing/verifying TLS v1.3 data. */
+    #define TLS13_SM2_SIG_ID        ((byte*)"TLSv1.3+GM+Cipher+Suite")
+    /* Length of ID to use when signing/verifying TLS v1.3 data. */
+    #define TLS13_SM2_SIG_ID_SZ     23
+#endif
 
 /* Supported ECC Curve Types */
 enum EccCurves {
@@ -3930,6 +4017,9 @@ typedef struct Ciphers {
 #ifdef HAVE_CHACHA
     ChaCha*   chacha;
 #endif
+#ifdef WOLFSSL_SM4
+    wc_Sm4*   sm4;
+#endif
 #if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER) && !defined(NO_HMAC)
     Hmac* hmac;
 #endif
@@ -3988,6 +4078,9 @@ typedef struct Hashes {
     #ifdef WOLFSSL_SHA512
         byte sha512[WC_SHA512_DIGEST_SIZE];
     #endif
+    #ifdef WOLFSSL_SM3
+        byte sm3[WC_SM3_DIGEST_SIZE];
+    #endif
 } Hashes;
 
 WOLFSSL_LOCAL int BuildCertHashes(const WOLFSSL* ssl, Hashes* hashes);
@@ -4003,6 +4096,9 @@ typedef union Digest {
 #ifdef WOLFSSL_SHA512
     wc_Sha512 sha512;
 #endif
+#ifdef WOLFSSL_SM3
+    wc_Sm3    sm3;
+#endif
 } Digest;
 #endif
 
@@ -4498,7 +4594,8 @@ struct Options {
     word16            sentChangeCipher:1; /* Change Cipher Spec sent */
 #endif
 #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
-               ((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
+               ((defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)) || \
+                (defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
                 (defined(HAVE_ED448) && !defined(NO_ED448_CLIENT_AUTH)))
     word16            cacheMessages:1;    /* Cache messages for sign/verify */
 #endif
@@ -4977,8 +5074,12 @@ typedef struct HS_Hashes {
 #ifdef WOLFSSL_SHA512
     wc_Sha512       hashSha512;         /* sha512 hash of handshake msgs */
 #endif
-#if (defined(HAVE_ED25519) || defined(HAVE_ED448)) && \
-                                                !defined(WOLFSSL_NO_CLIENT_AUTH)
+#ifdef WOLFSSL_SM3
+    wc_Sm3          hashSm3;            /* sm3 hash of handshake msgs */
+#endif
+#if (defined(HAVE_ED25519) || defined(HAVE_ED448) || \
+     (defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3))) && \
+    !defined(WOLFSSL_NO_CLIENT_AUTH)
     byte*           messages;           /* handshake messages */
     int             length;             /* length of handshake messages' data */
     int             prevLen;            /* length of messages but last */
@@ -5921,6 +6022,14 @@ WOLFSSL_LOCAL WC_RNG* WOLFSSL_RSA_GetRNG(WOLFSSL_RSA *rsa, WC_RNG **tmpRNG,
             ecc_key* pub_key, byte* pubKeyDer, word32* pubKeySz, byte* out,
             word32* outlen, int side);
     #endif /* HAVE_ECC */
+    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+        WOLFSSL_LOCAL int Sm2wSm3Sign(WOLFSSL* ssl, const byte* id, word32 idSz,
+            const byte* in, word32 inSz, byte* out, word32* outSz, ecc_key* key,
+            DerBuffer* keyBufInfo);
+        WOLFSSL_LOCAL int Sm2wSm3Verify(WOLFSSL* ssl, const byte* id,
+            word32 idSz, const byte* in, word32 inSz, const byte* out,
+            word32 outSz, ecc_key* key, buffer* keyBufInfo);
+    #endif /* WOLFSSL_SM2 && WOLFSSL_SM3 */
     #ifdef HAVE_ED25519
         WOLFSSL_LOCAL int Ed25519CheckPubKey(WOLFSSL* ssl);
         WOLFSSL_LOCAL int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz,

+ 105 - 50
wolfssl/openssl/evp.h

@@ -57,6 +57,12 @@
 #include <wolfssl/wolfcrypt/chacha20_poly1305.h>
 #include <wolfssl/wolfcrypt/hmac.h>
 #include <wolfssl/wolfcrypt/pwdbased.h>
+#ifdef WOLFSSL_SM3
+    #include <wolfssl/wolfcrypt/sm3.h>
+#endif
+#ifdef WOLFSSL_SM4
+    #include <wolfssl/wolfcrypt/sm4.h>
+#endif
 
 #if defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE)
 #include <wolfssl/wolfcrypt/coding.h>
@@ -91,6 +97,8 @@ WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_256(void);
 WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_384(void);
 WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha3_512(void);
 
+WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sm3(void);
+
 WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void);
 WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void);
 WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void);
@@ -149,7 +157,21 @@ WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_chacha20_poly1305(void);
 #define WOLFSSL_EVP_CHACHA_IV_BYTES     (CHACHA_IV_BYTES + sizeof(word32))
 WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_chacha20(void);
 #endif
-
+#ifdef WOLFSSL_SM4_ECB
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_sm4_ecb(void);
+#endif
+#ifdef WOLFSSL_SM4_CBC
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_sm4_cbc(void);
+#endif
+#ifdef WOLFSSL_SM4_CTR
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_sm4_ctr(void);
+#endif
+#ifdef WOLFSSL_SM4_GCM
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_sm4_gcm(void);
+#endif
+#ifdef WOLFSSL_SM4_CCM
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_sm4_ccm(void);
+#endif
 
 typedef union {
     #ifndef NO_MD4
@@ -186,6 +208,9 @@ typedef union {
     #ifndef WOLFSSL_NOSHA3_512
         WOLFSSL_SHA3_512_CTX sha3_512;
     #endif
+    #ifdef WOLFSSL_SM3
+        wc_Sm3               sm3;
+    #endif
 } WOLFSSL_Hasher;
 
 
@@ -225,6 +250,9 @@ typedef union {
 #ifdef HAVE_CHACHA
     ChaCha chacha;
 #endif
+#ifdef WOLFSSL_SM4
+    wc_Sm4 sm4;
+#endif
 } WOLFSSL_Cipher;
 
 #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
@@ -266,6 +294,11 @@ typedef union {
 #define NID_camellia_256_cbc            753
 #define NID_chacha20_poly1305           1018
 #define NID_chacha20                    1019
+#define NID_sm4_ecb                     1133
+#define NID_sm4_cbc                     1134
+#define NID_sm4_ctr                     1139
+#define NID_sm4_gcm                     1248
+#define NID_sm4_ccm                     1249
 #define NID_md5WithRSA                  104
 #define NID_md2WithRSAEncryption        9
 #define NID_md5WithRSAEncryption        99
@@ -303,6 +336,7 @@ typedef union {
 #define NID_shake256                    1101
 #define NID_sha1                        64
 #define NID_sha224                      675
+#define NID_sm3                         1143
 #define NID_md2                         77
 #define NID_md4                         257
 #define NID_md5                         40
@@ -346,6 +380,8 @@ typedef union {
 #define NID_auth_srp                    1052
 #define NID_auth_null                   1054
 #define NID_auth_any                    1055
+/* Curve */
+#define NID_sm2                         1172
 
 #define NID_X9_62_id_ecPublicKey EVP_PKEY_EC
 #define NID_rsaEncryption        EVP_PKEY_RSA
@@ -360,52 +396,57 @@ typedef union {
 #define EVP_PKEY_PRINT_INDENT_MAX    128
 
 enum {
-    AES_128_CBC_TYPE  = 1,
-    AES_192_CBC_TYPE  = 2,
-    AES_256_CBC_TYPE  = 3,
-    AES_128_CTR_TYPE  = 4,
-    AES_192_CTR_TYPE  = 5,
-    AES_256_CTR_TYPE  = 6,
-    AES_128_ECB_TYPE  = 7,
-    AES_192_ECB_TYPE  = 8,
-    AES_256_ECB_TYPE  = 9,
-    DES_CBC_TYPE      = 10,
-    DES_ECB_TYPE      = 11,
-    DES_EDE3_CBC_TYPE = 12,
-    DES_EDE3_ECB_TYPE = 13,
-    ARC4_TYPE         = 14,
-    NULL_CIPHER_TYPE  = 15,
-    EVP_PKEY_RSA      = 16,
-    EVP_PKEY_DSA      = 17,
-    EVP_PKEY_EC       = 18,
-    AES_128_GCM_TYPE  = 21,
-    AES_192_GCM_TYPE  = 22,
-    AES_256_GCM_TYPE  = 23,
-    EVP_PKEY_DH       = NID_dhKeyAgreement,
-    EVP_PKEY_HMAC     = NID_hmac,
-    EVP_PKEY_CMAC     = NID_cmac,
-    EVP_PKEY_HKDF     = NID_hkdf,
-    EVP_PKEY_FALCON   = 300, /* Randomly picked value. */
-    EVP_PKEY_DILITHIUM= 301, /* Randomly picked value. */
-    AES_128_CFB1_TYPE = 24,
-    AES_192_CFB1_TYPE = 25,
-    AES_256_CFB1_TYPE = 26,
-    AES_128_CFB8_TYPE = 27,
-    AES_192_CFB8_TYPE = 28,
-    AES_256_CFB8_TYPE = 29,
-    AES_128_CFB128_TYPE = 30,
-    AES_192_CFB128_TYPE = 31,
-    AES_256_CFB128_TYPE = 32,
-    AES_128_OFB_TYPE = 33,
-    AES_192_OFB_TYPE = 34,
-    AES_256_OFB_TYPE = 35,
-    AES_128_XTS_TYPE = 36,
-    AES_256_XTS_TYPE = 37,
+    AES_128_CBC_TYPE       = 1,
+    AES_192_CBC_TYPE       = 2,
+    AES_256_CBC_TYPE       = 3,
+    AES_128_CTR_TYPE       = 4,
+    AES_192_CTR_TYPE       = 5,
+    AES_256_CTR_TYPE       = 6,
+    AES_128_ECB_TYPE       = 7,
+    AES_192_ECB_TYPE       = 8,
+    AES_256_ECB_TYPE       = 9,
+    DES_CBC_TYPE           = 10,
+    DES_ECB_TYPE           = 11,
+    DES_EDE3_CBC_TYPE      = 12,
+    DES_EDE3_ECB_TYPE      = 13,
+    ARC4_TYPE              = 14,
+    NULL_CIPHER_TYPE       = 15,
+    EVP_PKEY_RSA           = 16,
+    EVP_PKEY_DSA           = 17,
+    EVP_PKEY_EC            = 18,
+    AES_128_GCM_TYPE       = 21,
+    AES_192_GCM_TYPE       = 22,
+    AES_256_GCM_TYPE       = 23,
+    EVP_PKEY_DH            = NID_dhKeyAgreement,
+    EVP_PKEY_HMAC          = NID_hmac,
+    EVP_PKEY_CMAC          = NID_cmac,
+    EVP_PKEY_HKDF          = NID_hkdf,
+    EVP_PKEY_FALCON        = 300, /* Randomly picked value. */
+    EVP_PKEY_DILITHIUM     = 301, /* Randomly picked value. */
+    AES_128_CFB1_TYPE      = 24,
+    AES_192_CFB1_TYPE      = 25,
+    AES_256_CFB1_TYPE      = 26,
+    AES_128_CFB8_TYPE      = 27,
+    AES_192_CFB8_TYPE      = 28,
+    AES_256_CFB8_TYPE      = 29,
+    AES_128_CFB128_TYPE    = 30,
+    AES_192_CFB128_TYPE    = 31,
+    AES_256_CFB128_TYPE    = 32,
+    AES_128_OFB_TYPE       = 33,
+    AES_192_OFB_TYPE       = 34,
+    AES_256_OFB_TYPE       = 35,
+    AES_128_XTS_TYPE       = 36,
+    AES_256_XTS_TYPE       = 37,
     CHACHA20_POLY1305_TYPE = 38,
-    CHACHA20_TYPE    = 39,
-    AES_128_CCM_TYPE  = 40,
-    AES_192_CCM_TYPE  = 41,
-    AES_256_CCM_TYPE  = 42
+    CHACHA20_TYPE          = 39,
+    AES_128_CCM_TYPE       = 40,
+    AES_192_CCM_TYPE       = 41,
+    AES_256_CCM_TYPE       = 42,
+    SM4_ECB_TYPE           = 43,
+    SM4_CBC_TYPE           = 44,
+    SM4_CTR_TYPE           = 45,
+    SM4_GCM_TYPE           = 46,
+    SM4_CCM_TYPE           = 47
 };
 
 #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
@@ -421,6 +462,8 @@ struct WOLFSSL_EVP_CIPHER_CTX {
 #if !defined(NO_AES)
     /* working iv pointer into cipher */
     ALIGN16 unsigned char  iv[AES_BLOCK_SIZE];
+#elif defined(WOLFSSL_SM4)
+    ALIGN16 unsigned char  iv[SM4_BLOCK_SIZE];
 #elif defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
     ALIGN16 unsigned char  iv[CHACHA20_POLY1305_AEAD_IV_SIZE];
 #elif !defined(NO_DES3)
@@ -433,10 +476,12 @@ struct WOLFSSL_EVP_CIPHER_CTX {
     int  lastUsed;
 #if !defined(NO_AES) || !defined(NO_DES3) || defined(HAVE_AESGCM) || \
     defined (WOLFSSL_AES_XTS) || (defined(HAVE_CHACHA) || \
-    defined(HAVE_POLY1305) || defined(HAVE_AESCCM))
+    defined(HAVE_POLY1305) || defined(HAVE_AESCCM)) || \
+    defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)
 #define HAVE_WOLFSSL_EVP_CIPHER_CTX_IV
     int    ivSz;
-#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
+#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) || \
+    defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)
     byte*   authBuffer;
     int     authBufferLen;
     byte*   authIn;
@@ -446,15 +491,19 @@ struct WOLFSSL_EVP_CIPHER_CTX {
     byte*   key;                 /* used in partial Init()s */
 #endif
 #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) || \
-        (defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
+    defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM) || \
+    (defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
 #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
     ALIGN16 unsigned char authTag[AES_BLOCK_SIZE];
+#elif defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)
+    ALIGN16 unsigned char authTag[SM4_BLOCK_SIZE];
 #else
     ALIGN16 unsigned char authTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
 #endif
     int     authTagSz;
 #endif
-#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
+#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) || \
+    defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)
     byte    authIvGenEnable:1;
     byte    authIncIv:1;
 #endif
@@ -877,6 +926,7 @@ WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx,
 #define EVP_ripemd160     wolfSSL_EVP_ripemd160
 #define EVP_shake128      wolfSSL_EVP_shake128
 #define EVP_shake256      wolfSSL_EVP_shake256
+#define EVP_sm3           wolfSSL_EVP_sm3
 #define EVP_set_pw_prompt wolfSSL_EVP_set_pw_prompt
 
 #define EVP_sha3_224    wolfSSL_EVP_sha3_224
@@ -923,6 +973,11 @@ WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx,
 #define EVP_rc4               wolfSSL_EVP_rc4
 #define EVP_chacha20          wolfSSL_EVP_chacha20
 #define EVP_chacha20_poly1305 wolfSSL_EVP_chacha20_poly1305
+#define EVP_sm4_ecb           wolfSSL_EVP_sm4_ecb
+#define EVP_sm4_cbc           wolfSSL_EVP_sm4_cbc
+#define EVP_sm4_ctr           wolfSSL_EVP_sm4_ctr
+#define EVP_sm4_gcm           wolfSSL_EVP_sm4_gcm
+#define EVP_sm4_ccm           wolfSSL_EVP_sm4_ccm
 #define EVP_enc_null          wolfSSL_EVP_enc_null
 
 #define EVP_MD_size             wolfSSL_EVP_MD_size

+ 8 - 3
wolfssl/ssl.h

@@ -3227,7 +3227,10 @@ enum BulkCipherAlgorithm {
     wolfssl_aes_gcm     = 7,
     wolfssl_aes_ccm     = 8,
     wolfssl_chacha      = 9,
-    wolfssl_camellia    = 10
+    wolfssl_camellia    = 10,
+    wolfssl_sm4_cbc     = 11,
+    wolfssl_sm4_gcm     = 12,
+    wolfssl_sm4_ccm     = 13
 };
 
 
@@ -3235,7 +3238,8 @@ enum BulkCipherAlgorithm {
 enum KDF_MacAlgorithm {
     wolfssl_sha256 = 4,     /* needs to match hash.h wc_MACAlgorithm */
     wolfssl_sha384,
-    wolfssl_sha512
+    wolfssl_sha512,
+    wolfssl_sm3 = 9
 };
 
 
@@ -3895,7 +3899,8 @@ enum {
     WOLFSSL_ECC_BRAINPOOLP512R1 = 28,
     WOLFSSL_ECC_X25519    = 29,
     WOLFSSL_ECC_X448      = 30,
-    WOLFSSL_ECC_MAX       = 30,
+    WOLFSSL_ECC_SM2P256V1 = 41,
+    WOLFSSL_ECC_MAX       = 41,
 
     WOLFSSL_FFDHE_2048    = 256,
     WOLFSSL_FFDHE_3072    = 257,

+ 28 - 18
wolfssl/wolfcrypt/aes.h

@@ -36,6 +36,33 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits
 
 #include <wolfssl/wolfcrypt/types.h>
 
+#if !defined(NO_AES) || defined(WOLFSSL_SM4)
+typedef struct Gcm {
+    ALIGN16 byte H[16];
+#ifdef OPENSSL_EXTRA
+    word32 aadH[4]; /* additional authenticated data GHASH */
+    word32 aadLen;  /* additional authenticated data len */
+#endif
+#ifdef GCM_TABLE
+    /* key-based fast multiplication table. */
+    ALIGN16 byte M0[256][16];
+#elif defined(GCM_TABLE_4BIT)
+    #if defined(BIG_ENDIAN_ORDER) || defined(WC_16BIT_CPU)
+        ALIGN16 byte M0[16][16];
+    #else
+        ALIGN16 byte M0[32][16];
+    #endif
+#endif /* GCM_TABLE */
+} Gcm;
+
+WOLFSSL_LOCAL void GenerateM0(Gcm* gcm);
+#ifdef WOLFSSL_ARMASM
+WOLFSSL_LOCAL void GMULT(byte* X, byte* Y);
+#endif
+WOLFSSL_LOCAL void GHASH(Gcm* gcm, const byte* a, word32 aSz, const byte* c,
+                         word32 cSz, byte* s, word32 sSz);
+#endif
+
 #ifndef NO_AES
 
 #if defined(HAVE_FIPS) && \
@@ -184,7 +211,6 @@ enum {
     WOLF_ENUM_DUMMY_LAST_ELEMENT(AES)
 };
 
-
 struct Aes {
     /* AESNI needs key first, rounds 2nd, not sure why yet */
     ALIGN16 word32 key[60];
@@ -199,11 +225,7 @@ struct Aes {
     word32 nonceSz;
 #endif
 #ifdef HAVE_AESGCM
-    ALIGN16 byte H[AES_BLOCK_SIZE];
-#ifdef OPENSSL_EXTRA
-    word32 aadH[4]; /* additional authenticated data GHASH */
-    word32 aadLen;  /* additional authenticated data len */
-#endif
+    Gcm gcm;
 
 #ifdef WOLFSSL_SE050
     sss_symmetric_t aes_ctx; /* used as the function context */
@@ -212,16 +234,6 @@ struct Aes {
     byte   keyIdSet;
     byte   useSWCrypt; /* Use SW crypt instead of SE050, before SCP03 auth */
 #endif
-#ifdef GCM_TABLE
-    /* key-based fast multiplication table. */
-    ALIGN16 byte M0[256][AES_BLOCK_SIZE];
-#elif defined(GCM_TABLE_4BIT)
-    #if defined(BIG_ENDIAN_ORDER) || defined(WC_16BIT_CPU)
-        ALIGN16 byte M0[16][AES_BLOCK_SIZE];
-    #else
-        ALIGN16 byte M0[32][AES_BLOCK_SIZE];
-    #endif
-#endif /* GCM_TABLE */
 #ifdef HAVE_CAVIUM_OCTEON_SYNC
     word32 y0;
 #endif
@@ -505,8 +517,6 @@ WOLFSSL_API int wc_AesGcmDecryptFinal(Aes* aes, const byte* authTag,
                                const byte* authIn, word32 authInSz,
                                const byte* authTag, word32 authTagSz);
 #endif /* WC_NO_RNG */
- WOLFSSL_LOCAL void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c,
-                               word32 cSz, byte* s, word32 sSz);
 #endif /* HAVE_AESGCM */
 #ifdef HAVE_AESCCM
  WOLFSSL_LOCAL int wc_AesCcmCheckTagSize(int sz);

+ 23 - 4
wolfssl/wolfcrypt/asn.h

@@ -64,6 +64,9 @@ that can be serialized and deserialized in a cross-platform way.
     #include <wolfssl/wolfcrypt/md5.h>
 #endif
 #include <wolfssl/wolfcrypt/sha256.h>
+#ifdef WOLFSSL_SM3
+    #include <wolfssl/wolfcrypt/sm3.h>
+#endif
 #include <wolfssl/wolfcrypt/asn_public.h>   /* public interface */
 
 #if defined(NO_SHA) && defined(NO_SHA256)
@@ -903,7 +906,9 @@ enum Misc_ASN {
     ASN_BOOL_SIZE       =   2,     /* including type */
     ASN_ECC_HEADER_SZ   =   2,     /* String type + 1 byte len */
     ASN_ECC_CONTEXT_SZ  =   2,     /* Content specific type + 1 byte len */
-#if defined(NO_SHA) || (!defined(NO_SHA256) && defined(WC_ASN_HASH_SHA256))
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    KEYID_SIZE          = WC_SM3_DIGEST_SIZE,
+#elif defined(NO_SHA) || (!defined(NO_SHA256) && defined(WC_ASN_HASH_SHA256))
     KEYID_SIZE          = WC_SHA256_DIGEST_SIZE,
 #else
     KEYID_SIZE          = WC_SHA_DIGEST_SIZE,
@@ -1085,7 +1090,8 @@ enum Hash_Sum  {
     SHA3_384h = 422,
     SHA3_512h = 423,
     SHAKE128h = 424,
-    SHAKE256h = 425
+    SHAKE256h = 425,
+    SM3h      = 640
 };
 
 #if !defined(NO_DES3) || !defined(NO_AES)
@@ -1119,6 +1125,7 @@ enum Key_Sum {
     RSAPSSk           = 654,
     RSAESOAEPk        = 651, /* 1.2.840.113549.1.1.7 */
     ECDSAk            = 518,
+    SM2k              = 667,
     ED25519k          = 256, /* 1.3.101.112 */
     X25519k           = 254, /* 1.3.101.110 */
     ED448k            = 257, /* 1.3.101.113 */
@@ -1913,7 +1920,9 @@ struct DecodedCert {
 #endif
 };
 
-#ifdef NO_SHA
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    #define SIGNER_DIGEST_SIZE WC_SM3_DIGEST_SIZE
+#elif defined(NO_SHA)
     #define SIGNER_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
 #else
     #define SIGNER_DIGEST_SIZE WC_SHA_DIGEST_SIZE
@@ -2021,7 +2030,10 @@ typedef enum MimeStatus
 #endif /* HAVE_SMIME */
 
 
+WOLFSSL_LOCAL int HashIdAlg(int oidSum);
 WOLFSSL_LOCAL int CalcHashId(const byte* data, word32 len, byte* hash);
+WOLFSSL_LOCAL int CalcHashId_ex(const byte* data, word32 len, byte* hash,
+    int hashAlg);
 WOLFSSL_LOCAL int GetName(DecodedCert* cert, int nameType, int maxIdx);
 
 WOLFSSL_ASN_API int wc_BerToDer(const byte* ber, word32 berSz, byte* der,
@@ -2207,6 +2219,8 @@ WOLFSSL_LOCAL int wc_GetSerialNumber(const byte* input, word32* inOutIdx,
 #endif
 WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
                               int maxIdx);
+WOLFSSL_LOCAL int GetNameHash_ex(const byte* source, word32* idx, byte* hash,
+                                 int maxIdx, int sigOID);
 WOLFSSL_LOCAL int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der);
 WOLFSSL_LOCAL int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz,
                                      const byte* pubKey, word32 pubKeySz, enum Key_Sum ks);
@@ -2364,7 +2378,9 @@ struct CertStatus {
 
 typedef struct OcspEntry OcspEntry;
 
-#ifdef NO_SHA
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+#define OCSP_DIGEST_SIZE WC_SM3_DIGEST_SIZE
+#elif defined(NO_SHA)
 #define OCSP_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
 #else
 #define OCSP_DIGEST_SIZE WC_SHA_DIGEST_SIZE
@@ -2427,6 +2443,9 @@ struct OcspResponse {
 struct OcspRequest {
     byte   issuerHash[KEYID_SIZE];
     byte   issuerKeyHash[KEYID_SIZE];
+#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
+    int    hashSz;
+#endif
     byte*  serial;   /* copy of the serial number in source cert */
     int    serialSz;
 #ifdef OPENSSL_EXTRA

+ 3 - 0
wolfssl/wolfcrypt/asn_public.h

@@ -104,6 +104,7 @@ enum Ecc_Sum {
     ECC_SECP256R1_OID = 526,
     ECC_SECP256K1_OID = 186,
     ECC_BRAINPOOLP256R1_OID = 104,
+    ECC_SM2P256V1_OID = 667,
     ECC_X25519_OID = 365,
     ECC_ED25519_OID = 256,
     ECC_BRAINPOOLP320R1_OID = 106,
@@ -207,6 +208,8 @@ enum Ctc_SigType {
 
     CTC_RSASSAPSS    = 654,
 
+    CTC_SM3wSM2      = 740, /* 1.2.156.10197.1.501 */
+
     CTC_ED25519      = 256,
     CTC_ED448        = 257,
 

+ 3 - 0
wolfssl/wolfcrypt/ecc.h

@@ -243,6 +243,9 @@ typedef enum ecc_curve_id {
     ECC_BRAINPOOLP384R1,
     ECC_BRAINPOOLP512R1,
 
+    /* SM2 */
+    ECC_SM2P256V1,
+
     /* Twisted Edwards Curves */
 #ifdef HAVE_CURVE25519
     ECC_X25519,

+ 4 - 1
wolfssl/wolfcrypt/error-crypt.h

@@ -260,7 +260,10 @@ enum {
     ASN_DEPTH_E         = -296,  /* Invalid ASN.1 - depth check */
     ASN_LEN_E           = -297,  /* ASN.1 length invalid */
 
-    WC_LAST_E           = -297,  /* Update this to indicate last error */
+    SM4_GCM_AUTH_E      = -298,  /* SM4-GCM Authentication check failure */
+    SM4_CCM_AUTH_E      = -299,  /* SM4-CCM Authentication check failure */
+
+    WC_LAST_E           = -299,  /* Update this to indicate last error */
     MIN_CODE_E          = -300   /* errors -101 - -299 */
 
     /* add new companion error id strings for any new error codes

+ 15 - 1
wolfssl/wolfcrypt/hash.h

@@ -55,6 +55,9 @@
 #if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S)
     #include <wolfssl/wolfcrypt/blake2.h>
 #endif
+#ifdef WOLFSSL_SM3
+    #include <wolfssl/wolfcrypt/sm3.h>
+#endif
 
 
 #ifdef __cplusplus
@@ -76,7 +79,8 @@ enum wc_MACAlgorithm {
     sha384_mac,
     sha512_mac,
     rmd_mac,
-    blake2b_mac
+    blake2b_mac,
+    sm3_mac,
 };
 
 enum wc_HashFlags {
@@ -112,6 +116,9 @@ typedef union {
     #ifdef WOLFSSL_SHA3
         wc_Sha3 sha3;
     #endif
+    #ifdef WOLFSSL_SM3
+        wc_Sm3 sm3;
+    #endif
 } wc_HashAlg;
 #endif /* !NO_HASH_WRAPPER */
 
@@ -132,6 +139,9 @@ typedef union {
 #elif !defined(NO_SHA256)
     #define WC_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
     #define WC_MAX_BLOCK_SIZE  WC_SHA256_BLOCK_SIZE
+#elif defined(WOLFSSL_SM3)
+    #define WC_MAX_DIGEST_SIZE WC_SM3_DIGEST_SIZE
+    #define WC_MAX_BLOCK_SIZE  WC_SM3_BLOCK_SIZE
 #elif defined(WOLFSSL_SHA224)
     #define WC_MAX_DIGEST_SIZE WC_SHA224_DIGEST_SIZE
     #define WC_MAX_BLOCK_SIZE  WC_SHA224_BLOCK_SIZE
@@ -226,6 +236,10 @@ WOLFSSL_API int wc_Shake256Hash(const byte* data, word32 len, byte* hash,
 #endif
 #endif /* WOLFSSL_SHA3 */
 
+#ifdef WOLFSSL_SM3
+WOLFSSL_API int wc_Sm3Hash(const byte* data, word32 len, byte* hash);
+#endif
+
 #endif /* !NO_HASH_WRAPPER */
 
 #if defined(WOLFSSL_HASH_KEEP)

+ 3 - 0
wolfssl/wolfcrypt/hmac.h

@@ -144,6 +144,9 @@ typedef union {
 #ifdef WOLFSSL_SHA3
     wc_Sha3 sha3;
 #endif
+#ifdef WOLFSSL_SM3
+    wc_Sm3 sm3;
+#endif
 } wc_HmacHash;
 
 /* Hmac digest */

+ 4 - 1
wolfssl/wolfcrypt/include.am

@@ -75,7 +75,10 @@ nobase_include_HEADERS+= \
                          wolfssl/wolfcrypt/cryptocb.h \
                          wolfssl/wolfcrypt/kyber.h \
                          wolfssl/wolfcrypt/wc_kyber.h \
-                         wolfssl/wolfcrypt/ext_kyber.h
+                         wolfssl/wolfcrypt/ext_kyber.h \
+                         wolfssl/wolfcrypt/sm2.h \
+                         wolfssl/wolfcrypt/sm3.h \
+                         wolfssl/wolfcrypt/sm4.h
 
 noinst_HEADERS+= \
                          wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \

+ 2 - 0
wolfssl/wolfcrypt/integer.h

@@ -329,6 +329,8 @@ MP_API int  mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d);
 MP_API void mp_zero (mp_int * a);
 MP_API void mp_clamp (mp_int * a);
 MP_API int  mp_exch (mp_int * a, mp_int * b);
+MP_API int  mp_cond_swap_ct_ex (mp_int * a, mp_int * b, int c, int m,
+                                mp_int * t);
 MP_API int  mp_cond_swap_ct (mp_int * a, mp_int * b, int c, int m);
 MP_API void mp_rshd (mp_int * a, int b);
 MP_API void mp_rshb (mp_int * a, int b);

+ 7 - 0
wolfssl/wolfcrypt/sm2.h

@@ -0,0 +1,7 @@
+
+#ifdef WOLFSSL_SM2
+
+#error "Contact wolfSSL to get the implementation of this file"
+
+#endif
+

+ 7 - 0
wolfssl/wolfcrypt/sm3.h

@@ -0,0 +1,7 @@
+
+#ifdef WOLFSSL_SM3
+
+#error "Contact wolfSSL to get the implementation of this file"
+
+#endif
+

+ 7 - 0
wolfssl/wolfcrypt/sm4.h

@@ -0,0 +1,7 @@
+
+#ifdef WOLFSSL_SM4
+
+#error "Contact wolfSSL to get the implementation of this file"
+
+#endif
+

+ 33 - 0
wolfssl/wolfcrypt/sp.h

@@ -366,6 +366,39 @@ WOLFSSL_LOCAL int sp_ecc_verify_521_nb(sp_ecc_ctx_t* ctx, const byte* hash,
     const mp_int* r, const mp_int* sm, int* res, void* heap);
 #endif /* WOLFSSL_SP_NONBLOCK */
 
+#ifdef HAVE_ECC_SM2
+
+WOLFSSL_LOCAL int sp_ecc_mulmod_sm2_256(mp_int* km, ecc_point* gm,
+    ecc_point* rm, int map, void* heap);
+WOLFSSL_LOCAL int sp_ecc_mulmod_base_sm2_256(mp_int* km, ecc_point* rm, int map,
+    void* heap);
+
+WOLFSSL_LOCAL int sp_ecc_make_key_sm2_256(WC_RNG* rng, mp_int* priv,
+    ecc_point* pub, void* heap);
+WOLFSSL_LOCAL int sp_ecc_secret_gen_sm2_256(mp_int* priv, ecc_point* pub,
+    byte* out, word32* outlen, void* heap);
+
+WOLFSSL_LOCAL int sp_ecc_sign_sm2_256(const byte* hash, word32 hashLen,
+    WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap);
+WOLFSSL_LOCAL int sp_ecc_verify_sm2_256(const byte* hash, word32 hashLen,
+    mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res,
+    void* heap);
+
+WOLFSSL_LOCAL int sp_ecc_is_point_sm2_256(mp_int* pX, mp_int* pY);
+WOLFSSL_LOCAL int sp_ecc_check_key_sm2_256(mp_int* pX, mp_int* pY,
+    mp_int* privm, void* heap);
+
+WOLFSSL_LOCAL int sp_ecc_proj_add_point_sm2_256(mp_int* pX, mp_int* pY,
+    mp_int* pZ, mp_int* qX, mp_int* qY, mp_int* qZ, mp_int* rX, mp_int* rY,
+    mp_int* rZ);
+WOLFSSL_LOCAL int sp_ecc_proj_dbl_point_sm2_256(mp_int* pX, mp_int* pY,
+    mp_int* pZ, mp_int* rX, mp_int* rY, mp_int* rZ);
+WOLFSSL_LOCAL int sp_ecc_map_sm2_256(mp_int* pX, mp_int* pY, mp_int* pZ);
+WOLFSSL_LOCAL int sp_ecc_uncompress_sm2_256(mp_int* xm, int odd, mp_int* ym);
+
+#endif
+
+
 #endif /* WOLFSSL_HAVE_SP_ECC */
 
 

+ 3 - 0
wolfssl/wolfcrypt/sp_int.h

@@ -924,6 +924,8 @@ MP_API int sp_init_copy (sp_int* r, const sp_int* a);
 MP_API int sp_copy(const sp_int* a, sp_int* r);
 MP_API int sp_exch(sp_int* a, sp_int* b);
 MP_API int sp_cond_swap_ct(sp_int* a, sp_int* b, int cnt, int swap);
+MP_API int sp_cond_swap_ct_ex(sp_int* a, sp_int* b, int cnt, int swap,
+    sp_int* t);
 
 #ifdef WOLFSSL_SP_INT_NEGATIVE
 MP_API int sp_abs(const sp_int* a, sp_int* r);
@@ -1100,6 +1102,7 @@ WOLFSSL_LOCAL void sp_memzero_check(sp_int* sp);
 #define mp_init_copy                        sp_init_copy
 #define mp_exch                             sp_exch
 #define mp_cond_swap_ct                     sp_cond_swap_ct
+#define mp_cond_swap_ct_ex                  sp_cond_swap_ct_ex
 #define mp_cmp_mag                          sp_cmp_mag
 #define mp_cmp                              sp_cmp
 #define mp_count_bits                       sp_count_bits

+ 2 - 1
wolfssl/wolfcrypt/tfm.h

@@ -899,7 +899,8 @@ MP_API int  mp_lcm(fp_int *a, fp_int *b, fp_int *c);
 MP_API int  mp_rand_prime(mp_int* a, int len, WC_RNG* rng, void* heap);
 MP_API int  mp_exch(mp_int *a, mp_int *b);
 #endif /* WOLFSSL_KEY_GEN */
-MP_API int  mp_cond_swap_ct (mp_int * a, mp_int * b, int c, int m);
+MP_API int  mp_cond_swap_ct_ex(mp_int* a, mp_int* b, int c, int m, mp_int* t);
+MP_API int  mp_cond_swap_ct(mp_int* a, mp_int* b, int c, int m);
 
 MP_API int  mp_cnt_lsb(fp_int *a);
 MP_API int  mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d);

+ 9 - 1
wolfssl/wolfcrypt/types.h

@@ -1009,6 +1009,7 @@ typedef struct w64wrapper {
         DYNAMIC_TYPE_SESSION      = 96,
         DYNAMIC_TYPE_DILITHIUM    = 97,
         DYNAMIC_TYPE_SPHINCS      = 98,
+        DYNAMIC_TYPE_SM4_BUFFER   = 99,
         DYNAMIC_TYPE_SNIFFER_SERVER     = 1000,
         DYNAMIC_TYPE_SNIFFER_SESSION    = 1001,
         DYNAMIC_TYPE_SNIFFER_PB         = 1002,
@@ -1067,7 +1068,7 @@ typedef struct w64wrapper {
         WC_HASH_TYPE_SHA3_512 = 13,
         WC_HASH_TYPE_BLAKE2B = 14,
         WC_HASH_TYPE_BLAKE2S = 19,
-        WC_HASH_TYPE_MAX = WC_HASH_TYPE_BLAKE2S
+        WC_HASH_TYPE_MAX = WC_HASH_TYPE_BLAKE2S,
         #ifndef WOLFSSL_NOSHA512_224
             #define WOLFSSL_NOSHA512_224
         #endif
@@ -1104,12 +1105,19 @@ typedef struct w64wrapper {
         #endif
         #ifdef WOLFSSL_SHAKE128
             WC_HASH_TYPE_SHAKE128 = 18,
+            #undef _WC_HASH_TYPE_MAX
+            #define _WC_HASH_TYPE_MAX WC_HASH_TYPE_SHAKE128
         #endif
         #ifdef WOLFSSL_SHAKE256
             WC_HASH_TYPE_SHAKE256 = 19,
             #undef _WC_HASH_TYPE_MAX
             #define _WC_HASH_TYPE_MAX WC_HASH_TYPE_SHAKE256
         #endif
+        #ifdef WOLFSSL_SM3
+            WC_HASH_TYPE_SM3     = 20,
+            #undef _WC_HASH_TYPE_MAX
+            #define _WC_HASH_TYPE_MAX WC_HASH_TYPE_SM3
+        #endif
         WC_HASH_TYPE_MAX = _WC_HASH_TYPE_MAX
         #undef _WC_HASH_TYPE_MAX
 

Some files were not shown because too many files changed in this diff