diff --git a/.github/workflows/wolfsm.yml b/.github/workflows/wolfsm.yml index 1cc94ab7e1..bfab84475b 100644 --- a/.github/workflows/wolfsm.yml +++ b/.github/workflows/wolfsm.yml @@ -84,18 +84,23 @@ jobs: run: | cat > "$RUNNER_TEMP/wolfsm-configs.json" <<'EOF' [ - {"name": "all-sm", "minutes": 3, + {"name": "all-sm", "minutes": 5.8, "configure": ["--enable-all", "--enable-sm2", "--enable-sm3", "--enable-sm4-ecb", "--enable-sm4-cbc", "--enable-sm4-ctr", "--enable-sm4-gcm", "--enable-sm4-ccm"]}, - {"name": "sm-tls-suites", "minutes": 1.5, + {"name": "sm-cryptocb", "minutes": 3.0, + "comment": "SM2/SM3/SM4 through the crypto callback. The SM dispatch needs a wolfsm that defines WOLFSSL_SM_CRYPTOCB; cryptocb_test() then checks each op reached the device.", + "configure": ["--enable-sm2", "--enable-sm3", "--enable-sm4-ecb", + "--enable-sm4-cbc", "--enable-sm4-ctr", "--enable-sm4-gcm", + "--enable-sm4-ccm", "--enable-sha3", "--enable-cryptocb"]}, + {"name": "sm-tls-suites", "minutes": 2.9, "configure": ["--enable-sm2", "--enable-sm3", "--enable-sm4-gcm", "--enable-sm4-ccm", "--enable-sha3"]}, - {"name": "sm4-all-modes", "minutes": 1.5, + {"name": "sm4-all-modes", "minutes": 2.9, "configure": ["--enable-sm2", "--enable-sm3", "--enable-sm4-ecb", "--enable-sm4-cbc", "--enable-sm4-ctr", "--enable-sm4-gcm", "--enable-sm4-ccm", "--enable-sha3"]}, - {"name": "sm-faultharden", "minutes": 1.5, + {"name": "sm-faultharden", "minutes": 1.8, "comment": "The only config that compiles the SM2 signature-fault check with HAVE_PK_CALLBACKS. sm4-cbc is required: the sole TLS 1.2 SM2 client-auth case in tests/test-sm2.conf is ECDHE-ECDSA-SM4-CBC-SM3.", "configure": ["--enable-sm2", "--enable-sm3", "--enable-sm4-ecb", "--enable-sm4-cbc", "--enable-sm4-ctr", "--enable-sm4-gcm", diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 5edebd83ef..d0d8b4617d 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -1070,6 +1070,7 @@ WOLFSSL_SHUTDOWNONCE WOLFSSL_SILABS_TRNG WOLFSSL_SLHDSA_FULL_HASH WOLFSSL_SLHDSA_NO_VERIFY_ONLY +WOLFSSL_SM_CRYPTOCB WOLFSSL_SNIFFER_NO_RECOVERY WOLFSSL_SP_ARM32_UDIV WOLFSSL_SP_FAST_NCT_EXPTMOD diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index 569a68e01a..8e3090bec5 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -173,10 +173,15 @@ static const char* GetPkTypeStr(int pk) case WC_PK_TYPE_ED25519_CHECK_KEY: return "ED25519 CheckKey"; case WC_PK_TYPE_CURVE25519_MAKE_PUB: return "CURVE25519 MakePub"; case WC_PK_TYPE_CURVE25519_GENERIC: return "CURVE25519 Generic"; +#ifdef WOLFSSL_SM2 + case WC_PK_TYPE_SM2_SIGN: return "SM2-Sign"; + case WC_PK_TYPE_SM2_VERIFY: return "SM2-Verify"; + case WC_PK_TYPE_SM2_SHARED_SECRET: return "SM2-SharedSecret"; +#endif } return NULL; } -#if !defined(NO_AES) || !defined(NO_DES3) +#if !defined(NO_AES) || !defined(NO_DES3) || defined(WOLFSSL_SM4) static const char* GetCipherTypeStr(int cipher) { switch (cipher) { @@ -191,10 +196,17 @@ static const char* GetCipherTypeStr(int cipher) case WC_CIPHER_DES3: return "DES3"; case WC_CIPHER_DES: return "DES"; case WC_CIPHER_CHACHA: return "ChaCha20"; +#ifdef WOLFSSL_SM4 + case WC_CIPHER_SM4_ECB: return "SM4 ECB"; + case WC_CIPHER_SM4_CBC: return "SM4 CBC"; + case WC_CIPHER_SM4_CTR: return "SM4 CTR"; + case WC_CIPHER_SM4_GCM: return "SM4 GCM"; + case WC_CIPHER_SM4_CCM: return "SM4 CCM"; +#endif } return NULL; } -#endif /* !NO_AES || !NO_DES3 */ +#endif /* !NO_AES || !NO_DES3 || WOLFSSL_SM4 */ static const char* GetHashTypeStr(int hash) { switch (hash) { @@ -213,6 +225,7 @@ static const char* GetHashTypeStr(int hash) case WC_HASH_TYPE_SHA3_512: return "SHA3-512"; case WC_HASH_TYPE_BLAKE2B: return "Blake2B"; case WC_HASH_TYPE_BLAKE2S: return "Blake2S"; + case WC_HASH_TYPE_SM3: return "SM3"; } return NULL; } @@ -290,16 +303,17 @@ void wc_CryptoCb_InfoString(wc_CryptoInfo* info) GetPkTypeStr(info->pk.type), info->pk.type); } } -#if !defined(NO_AES) || !defined(NO_DES3) +#if !defined(NO_AES) || !defined(NO_DES3) || defined(WOLFSSL_SM4) else if (info->algo_type == WC_ALGO_TYPE_CIPHER) { printf("Crypto CB: %s %s (%d) (%p ctx)\n", GetAlgoTypeStr(info->algo_type), GetCipherTypeStr(info->cipher.type), info->cipher.type, (void*)info->cipher.ctx); } -#endif /* !NO_AES || !NO_DES3 */ +#endif /* !NO_AES || !NO_DES3 || WOLFSSL_SM4 */ #if !defined(NO_SHA) || !defined(NO_SHA256) || \ - defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA3) + defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) || \ + defined(WOLFSSL_SHA3) || defined(WOLFSSL_SM3) else if (info->algo_type == WC_ALGO_TYPE_HASH) { printf("Crypto CB: %s %s (%d) (%p ctx) %s\n", GetAlgoTypeStr(info->algo_type), @@ -1172,6 +1186,93 @@ int wc_CryptoCb_EciesDecrypt(ecc_key* privKey, ecc_key* pubKey, #endif /* HAVE_ECC_ENCRYPT */ #endif /* HAVE_ECC */ +#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM_CRYPTOCB) +int wc_CryptoCb_Sm2Sign(const byte* in, word32 inlen, byte* out, + word32* outlen, WC_RNG* rng, ecc_key* key) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_SM2_SIGN; + cryptoInfo.pk.sm2sign.in = in; + cryptoInfo.pk.sm2sign.inlen = inlen; + cryptoInfo.pk.sm2sign.out = out; + cryptoInfo.pk.sm2sign.outlen = outlen; + cryptoInfo.pk.sm2sign.rng = rng; + cryptoInfo.pk.sm2sign.key = key; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_Sm2Verify(const byte* sig, word32 siglen, + const byte* hash, word32 hashlen, int* res, ecc_key* key) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_SM2_VERIFY; + cryptoInfo.pk.sm2verify.sig = sig; + cryptoInfo.pk.sm2verify.siglen = siglen; + cryptoInfo.pk.sm2verify.hash = hash; + cryptoInfo.pk.sm2verify.hashlen = hashlen; + cryptoInfo.pk.sm2verify.res = res; + cryptoInfo.pk.sm2verify.key = key; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_Sm2SharedSecret(ecc_key* private_key, ecc_key* public_key, + byte* out, word32* outlen) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + if (private_key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(private_key->devId, WC_ALGO_TYPE_PK); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_SM2_SHARED_SECRET; + cryptoInfo.pk.sm2dh.private_key = private_key; + cryptoInfo.pk.sm2dh.public_key = public_key; + cryptoInfo.pk.sm2dh.out = out; + cryptoInfo.pk.sm2dh.outlen = outlen; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLFSSL_SM2 && WOLFSSL_SM_CRYPTOCB */ + #ifdef HAVE_CURVE25519 int wc_CryptoCb_Curve25519Gen(WC_RNG* rng, int keySize, curve25519_key* key) @@ -2605,6 +2706,342 @@ int wc_CryptoCb_Des3Decrypt(Des3* des3, byte* out, } #endif /* !NO_DES3 */ +#if defined(WOLFSSL_SM4) && defined(WOLFSSL_SM_CRYPTOCB) +#ifdef WOLFSSL_SM4_GCM +int wc_CryptoCb_Sm4GcmEncrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (sm4) { + dev = wc_CryptoCb_FindDevice(sm4->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_SM4_GCM; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.sm4gcm_enc.sm4 = sm4; + cryptoInfo.cipher.sm4gcm_enc.out = out; + cryptoInfo.cipher.sm4gcm_enc.in = in; + cryptoInfo.cipher.sm4gcm_enc.sz = sz; + cryptoInfo.cipher.sm4gcm_enc.nonce = nonce; + cryptoInfo.cipher.sm4gcm_enc.nonceSz = nonceSz; + cryptoInfo.cipher.sm4gcm_enc.authTag = authTag; + cryptoInfo.cipher.sm4gcm_enc.authTagSz = authTagSz; + cryptoInfo.cipher.sm4gcm_enc.authIn = authIn; + cryptoInfo.cipher.sm4gcm_enc.authInSz = authInSz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_Sm4GcmDecrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (sm4) { + dev = wc_CryptoCb_FindDevice(sm4->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_SM4_GCM; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.sm4gcm_dec.sm4 = sm4; + cryptoInfo.cipher.sm4gcm_dec.out = out; + cryptoInfo.cipher.sm4gcm_dec.in = in; + cryptoInfo.cipher.sm4gcm_dec.sz = sz; + cryptoInfo.cipher.sm4gcm_dec.nonce = nonce; + cryptoInfo.cipher.sm4gcm_dec.nonceSz = nonceSz; + cryptoInfo.cipher.sm4gcm_dec.authTag = authTag; + cryptoInfo.cipher.sm4gcm_dec.authTagSz = authTagSz; + cryptoInfo.cipher.sm4gcm_dec.authIn = authIn; + cryptoInfo.cipher.sm4gcm_dec.authInSz = authInSz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLFSSL_SM4_GCM */ + +#ifdef WOLFSSL_SM4_CCM +int wc_CryptoCb_Sm4CcmEncrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (sm4) { + dev = wc_CryptoCb_FindDevice(sm4->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_SM4_CCM; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.sm4ccm_enc.sm4 = sm4; + cryptoInfo.cipher.sm4ccm_enc.out = out; + cryptoInfo.cipher.sm4ccm_enc.in = in; + cryptoInfo.cipher.sm4ccm_enc.sz = sz; + cryptoInfo.cipher.sm4ccm_enc.nonce = nonce; + cryptoInfo.cipher.sm4ccm_enc.nonceSz = nonceSz; + cryptoInfo.cipher.sm4ccm_enc.authTag = authTag; + cryptoInfo.cipher.sm4ccm_enc.authTagSz = authTagSz; + cryptoInfo.cipher.sm4ccm_enc.authIn = authIn; + cryptoInfo.cipher.sm4ccm_enc.authInSz = authInSz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_Sm4CcmDecrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (sm4) { + dev = wc_CryptoCb_FindDevice(sm4->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_SM4_CCM; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.sm4ccm_dec.sm4 = sm4; + cryptoInfo.cipher.sm4ccm_dec.out = out; + cryptoInfo.cipher.sm4ccm_dec.in = in; + cryptoInfo.cipher.sm4ccm_dec.sz = sz; + cryptoInfo.cipher.sm4ccm_dec.nonce = nonce; + cryptoInfo.cipher.sm4ccm_dec.nonceSz = nonceSz; + cryptoInfo.cipher.sm4ccm_dec.authTag = authTag; + cryptoInfo.cipher.sm4ccm_dec.authTagSz = authTagSz; + cryptoInfo.cipher.sm4ccm_dec.authIn = authIn; + cryptoInfo.cipher.sm4ccm_dec.authInSz = authInSz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLFSSL_SM4_CCM */ + +#ifdef WOLFSSL_SM4_CBC +int wc_CryptoCb_Sm4CbcEncrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (sm4) { + dev = wc_CryptoCb_FindDevice(sm4->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_SM4_CBC; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.sm4cbc.sm4 = sm4; + cryptoInfo.cipher.sm4cbc.out = out; + cryptoInfo.cipher.sm4cbc.in = in; + cryptoInfo.cipher.sm4cbc.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_Sm4CbcDecrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (sm4) { + dev = wc_CryptoCb_FindDevice(sm4->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_SM4_CBC; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.sm4cbc.sm4 = sm4; + cryptoInfo.cipher.sm4cbc.out = out; + cryptoInfo.cipher.sm4cbc.in = in; + cryptoInfo.cipher.sm4cbc.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLFSSL_SM4_CBC */ + +#ifdef WOLFSSL_SM4_CTR +int wc_CryptoCb_Sm4CtrEncrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (sm4) { + dev = wc_CryptoCb_FindDevice(sm4->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_SM4_CTR; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.sm4ctr.sm4 = sm4; + cryptoInfo.cipher.sm4ctr.out = out; + cryptoInfo.cipher.sm4ctr.in = in; + cryptoInfo.cipher.sm4ctr.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLFSSL_SM4_CTR */ + +#ifdef WOLFSSL_SM4_ECB +int wc_CryptoCb_Sm4EcbEncrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (sm4) { + dev = wc_CryptoCb_FindDevice(sm4->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_SM4_ECB; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.sm4ecb.sm4 = sm4; + cryptoInfo.cipher.sm4ecb.out = out; + cryptoInfo.cipher.sm4ecb.in = in; + cryptoInfo.cipher.sm4ecb.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_Sm4EcbDecrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (sm4) { + dev = wc_CryptoCb_FindDevice(sm4->devId, WC_ALGO_TYPE_CIPHER); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_SM4_ECB; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.sm4ecb.sm4 = sm4; + cryptoInfo.cipher.sm4ecb.out = out; + cryptoInfo.cipher.sm4ecb.in = in; + cryptoInfo.cipher.sm4ecb.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLFSSL_SM4_ECB */ +#endif /* WOLFSSL_SM4 && WOLFSSL_SM_CRYPTOCB */ + #ifndef NO_SHA int wc_CryptoCb_ShaHash(wc_Sha* sha, const byte* in, word32 inSz, byte* digest) @@ -2955,6 +3392,39 @@ int wc_CryptoCb_Shake(wc_Sha3* shake, int type, const byte* in, #endif /* WOLFSSL_SHAKE128 || WOLFSSL_SHAKE256 */ #endif /* WOLFSSL_SHA3 && (!HAVE_FIPS || FIPS_VERSION_GE(6, 0)) */ +#if defined(WOLFSSL_SM3) && defined(WOLFSSL_SM_CRYPTOCB) +int wc_CryptoCb_Sm3Hash(wc_Sm3* sm3, const byte* in, + word32 inSz, byte* digest) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (sm3) { + dev = wc_CryptoCb_FindDevice(sm3->devId, WC_ALGO_TYPE_HASH); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_HASH; + cryptoInfo.hash.type = WC_HASH_TYPE_SM3; + cryptoInfo.hash.sm3 = sm3; + cryptoInfo.hash.in = in; + cryptoInfo.hash.inSz = inSz; + cryptoInfo.hash.digest = digest; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLFSSL_SM3 && WOLFSSL_SM_CRYPTOCB */ + #ifndef NO_HMAC int wc_CryptoCb_Hmac(Hmac* hmac, int macType, const byte* in, word32 inSz, byte* digest) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 0556fd5351..ada43e7dc6 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -79259,6 +79259,25 @@ typedef struct { #if defined(WC_RSA_PSS) && defined(WOLF_CRYPTO_CB_RSA_PAD) int rsaPssVerifyCount; /* RSA-PSS verify callback invocations */ #endif +#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM_CRYPTOCB) + int sm2SignCount; /* SM2 sign callback invocations */ + int sm2VerifyCount; /* SM2 verify callback invocations */ + int sm2SecretCount; /* SM2 shared secret callback invocations */ +#endif +#if defined(WOLFSSL_SM3) && defined(WOLFSSL_SM_CRYPTOCB) + int sm3Count; /* SM3 hash callback invocations */ +#endif +#if defined(WOLFSSL_SM4) && defined(WOLFSSL_SM_CRYPTOCB) + /* Counted per direction ([0] decrypt, [1] encrypt) so a decrypt entry + * point that was never wired up cannot hide behind the encrypt one. + * Counter mode has a single entry point for both directions, so it keeps + * one counter. */ + int sm4EcbCount[2]; /* SM4-ECB callback invocations */ + int sm4CbcCount[2]; /* SM4-CBC callback invocations */ + int sm4CtrCount; /* SM4-CTR callback invocations */ + int sm4GcmCount[2]; /* SM4-GCM callback invocations */ + int sm4CcmCount[2]; /* SM4-CCM callback invocations */ +#endif } myCryptoDevCtx; #ifdef WOLF_CRYPTO_CB_ONLY_RSA @@ -80594,6 +80613,55 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) } #endif #endif /* HAVE_ECC */ + #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM_CRYPTOCB) + if (info->pk.type == WC_PK_TYPE_SM2_SIGN) { + #ifdef HAVE_ECC_SIGN + myCtx->sm2SignCount++; + + /* set devId to invalid, so software is used */ + info->pk.sm2sign.key->devId = INVALID_DEVID; + + ret = wc_ecc_sm2_sign_hash( + info->pk.sm2sign.in, info->pk.sm2sign.inlen, + info->pk.sm2sign.out, info->pk.sm2sign.outlen, + info->pk.sm2sign.rng, info->pk.sm2sign.key); + + /* reset devId */ + info->pk.sm2sign.key->devId = devIdArg; + #endif + } + else if (info->pk.type == WC_PK_TYPE_SM2_VERIFY) { + #ifdef HAVE_ECC_VERIFY + myCtx->sm2VerifyCount++; + + /* set devId to invalid, so software is used */ + info->pk.sm2verify.key->devId = INVALID_DEVID; + + ret = wc_ecc_sm2_verify_hash( + info->pk.sm2verify.sig, info->pk.sm2verify.siglen, + info->pk.sm2verify.hash, info->pk.sm2verify.hashlen, + info->pk.sm2verify.res, info->pk.sm2verify.key); + + /* reset devId */ + info->pk.sm2verify.key->devId = devIdArg; + #endif + } + else if (info->pk.type == WC_PK_TYPE_SM2_SHARED_SECRET) { + #ifdef HAVE_ECC_DHE + myCtx->sm2SecretCount++; + + /* set devId to invalid, so software is used */ + info->pk.sm2dh.private_key->devId = INVALID_DEVID; + + ret = wc_ecc_sm2_shared_secret( + info->pk.sm2dh.private_key, info->pk.sm2dh.public_key, + info->pk.sm2dh.out, info->pk.sm2dh.outlen); + + /* reset devId */ + info->pk.sm2dh.private_key->devId = devIdArg; + #endif + } + #endif /* WOLFSSL_SM2 && WOLFSSL_SM_CRYPTOCB */ #ifdef HAVE_CURVE25519 if (info->pk.type == WC_PK_TYPE_CURVE25519_KEYGEN) { /* set devId to invalid, so software is used */ @@ -81463,9 +81531,193 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) } #endif /* !NO_DES3 */ #endif /* !NO_AES || !NO_DES3 */ +#if defined(WOLFSSL_SM4) && defined(WOLFSSL_SM_CRYPTOCB) + #ifdef WOLFSSL_SM4_ECB + if (info->cipher.type == WC_CIPHER_SM4_ECB) { + if (info->cipher.sm4ecb.sm4 == NULL) + return NOT_COMPILED_IN; + + myCtx->sm4EcbCount[info->cipher.enc ? 1 : 0]++; + + /* set devId to invalid, so software is used */ + info->cipher.sm4ecb.sm4->devId = INVALID_DEVID; + + if (info->cipher.enc) { + ret = wc_Sm4EcbEncrypt( + info->cipher.sm4ecb.sm4, + info->cipher.sm4ecb.out, + info->cipher.sm4ecb.in, + info->cipher.sm4ecb.sz); + } + else { + ret = wc_Sm4EcbDecrypt( + info->cipher.sm4ecb.sm4, + info->cipher.sm4ecb.out, + info->cipher.sm4ecb.in, + info->cipher.sm4ecb.sz); + } + + /* reset devId */ + info->cipher.sm4ecb.sm4->devId = devIdArg; + } + #endif /* WOLFSSL_SM4_ECB */ + #ifdef WOLFSSL_SM4_CBC + if (info->cipher.type == WC_CIPHER_SM4_CBC) { + if (info->cipher.sm4cbc.sm4 == NULL) + return NOT_COMPILED_IN; + + myCtx->sm4CbcCount[info->cipher.enc ? 1 : 0]++; + + /* set devId to invalid, so software is used */ + info->cipher.sm4cbc.sm4->devId = INVALID_DEVID; + + if (info->cipher.enc) { + ret = wc_Sm4CbcEncrypt( + info->cipher.sm4cbc.sm4, + info->cipher.sm4cbc.out, + info->cipher.sm4cbc.in, + info->cipher.sm4cbc.sz); + } + else { + ret = wc_Sm4CbcDecrypt( + info->cipher.sm4cbc.sm4, + info->cipher.sm4cbc.out, + info->cipher.sm4cbc.in, + info->cipher.sm4cbc.sz); + } + + /* reset devId */ + info->cipher.sm4cbc.sm4->devId = devIdArg; + } + #endif /* WOLFSSL_SM4_CBC */ + #ifdef WOLFSSL_SM4_CTR + if (info->cipher.type == WC_CIPHER_SM4_CTR) { + if (info->cipher.sm4ctr.sm4 == NULL) + return NOT_COMPILED_IN; + + myCtx->sm4CtrCount++; + + /* set devId to invalid, so software is used */ + info->cipher.sm4ctr.sm4->devId = INVALID_DEVID; + + /* counter mode is its own inverse */ + ret = wc_Sm4CtrEncrypt( + info->cipher.sm4ctr.sm4, + info->cipher.sm4ctr.out, + info->cipher.sm4ctr.in, + info->cipher.sm4ctr.sz); + + /* reset devId */ + info->cipher.sm4ctr.sm4->devId = devIdArg; + } + #endif /* WOLFSSL_SM4_CTR */ + #ifdef WOLFSSL_SM4_GCM + if (info->cipher.type == WC_CIPHER_SM4_GCM) { + if (((info->cipher.enc != 0) && + (info->cipher.sm4gcm_enc.sm4 == NULL)) || + ((info->cipher.enc == 0) && + (info->cipher.sm4gcm_dec.sm4 == NULL))) { + return NOT_COMPILED_IN; + } + + myCtx->sm4GcmCount[info->cipher.enc ? 1 : 0]++; + + if (info->cipher.enc) { + /* set devId to invalid, so software is used */ + info->cipher.sm4gcm_enc.sm4->devId = INVALID_DEVID; + + ret = wc_Sm4GcmEncrypt( + info->cipher.sm4gcm_enc.sm4, + info->cipher.sm4gcm_enc.out, + info->cipher.sm4gcm_enc.in, + info->cipher.sm4gcm_enc.sz, + info->cipher.sm4gcm_enc.nonce, + info->cipher.sm4gcm_enc.nonceSz, + info->cipher.sm4gcm_enc.authTag, + info->cipher.sm4gcm_enc.authTagSz, + info->cipher.sm4gcm_enc.authIn, + info->cipher.sm4gcm_enc.authInSz); + + /* reset devId */ + info->cipher.sm4gcm_enc.sm4->devId = devIdArg; + } + else { + /* set devId to invalid, so software is used */ + info->cipher.sm4gcm_dec.sm4->devId = INVALID_DEVID; + + ret = wc_Sm4GcmDecrypt( + info->cipher.sm4gcm_dec.sm4, + info->cipher.sm4gcm_dec.out, + info->cipher.sm4gcm_dec.in, + info->cipher.sm4gcm_dec.sz, + info->cipher.sm4gcm_dec.nonce, + info->cipher.sm4gcm_dec.nonceSz, + info->cipher.sm4gcm_dec.authTag, + info->cipher.sm4gcm_dec.authTagSz, + info->cipher.sm4gcm_dec.authIn, + info->cipher.sm4gcm_dec.authInSz); + + /* reset devId */ + info->cipher.sm4gcm_dec.sm4->devId = devIdArg; + } + } + #endif /* WOLFSSL_SM4_GCM */ + #ifdef WOLFSSL_SM4_CCM + if (info->cipher.type == WC_CIPHER_SM4_CCM) { + if (((info->cipher.enc != 0) && + (info->cipher.sm4ccm_enc.sm4 == NULL)) || + ((info->cipher.enc == 0) && + (info->cipher.sm4ccm_dec.sm4 == NULL))) { + return NOT_COMPILED_IN; + } + + myCtx->sm4CcmCount[info->cipher.enc ? 1 : 0]++; + + if (info->cipher.enc) { + /* set devId to invalid, so software is used */ + info->cipher.sm4ccm_enc.sm4->devId = INVALID_DEVID; + + ret = wc_Sm4CcmEncrypt( + info->cipher.sm4ccm_enc.sm4, + info->cipher.sm4ccm_enc.out, + info->cipher.sm4ccm_enc.in, + info->cipher.sm4ccm_enc.sz, + info->cipher.sm4ccm_enc.nonce, + info->cipher.sm4ccm_enc.nonceSz, + info->cipher.sm4ccm_enc.authTag, + info->cipher.sm4ccm_enc.authTagSz, + info->cipher.sm4ccm_enc.authIn, + info->cipher.sm4ccm_enc.authInSz); + + /* reset devId */ + info->cipher.sm4ccm_enc.sm4->devId = devIdArg; + } + else { + /* set devId to invalid, so software is used */ + info->cipher.sm4ccm_dec.sm4->devId = INVALID_DEVID; + + ret = wc_Sm4CcmDecrypt( + info->cipher.sm4ccm_dec.sm4, + info->cipher.sm4ccm_dec.out, + info->cipher.sm4ccm_dec.in, + info->cipher.sm4ccm_dec.sz, + info->cipher.sm4ccm_dec.nonce, + info->cipher.sm4ccm_dec.nonceSz, + info->cipher.sm4ccm_dec.authTag, + info->cipher.sm4ccm_dec.authTagSz, + info->cipher.sm4ccm_dec.authIn, + info->cipher.sm4ccm_dec.authInSz); + + /* reset devId */ + info->cipher.sm4ccm_dec.sm4->devId = devIdArg; + } + } + #endif /* WOLFSSL_SM4_CCM */ +#endif /* WOLFSSL_SM4 && WOLFSSL_SM_CRYPTOCB */ } #if !defined(NO_SHA) || !defined(NO_SHA256) || \ - defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) + defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) || \ + defined(WOLFSSL_SM3) else if (info->algo_type == WC_ALGO_TYPE_HASH) { #if !defined(NO_SHA) if (info->hash.type == WC_HASH_TYPE_SHA) { @@ -81777,10 +82029,37 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) #endif /* WOLFSSL_SHAKE256 */ else #endif + #if defined(WOLFSSL_SM3) && defined(WOLFSSL_SM_CRYPTOCB) + if (info->hash.type == WC_HASH_TYPE_SM3) { + if (info->hash.sm3 == NULL) + return NOT_COMPILED_IN; + + myCtx->sm3Count++; + + /* set devId to invalid, so software is used */ + info->hash.sm3->devId = INVALID_DEVID; + + if (info->hash.in != NULL) { + ret = wc_Sm3Update( + info->hash.sm3, + info->hash.in, + info->hash.inSz); + } + if (info->hash.digest != NULL) { + ret = wc_Sm3Final( + info->hash.sm3, + info->hash.digest); + } + + /* reset devId */ + info->hash.sm3->devId = devIdArg; + } + else + #endif /* WOLFSSL_SM3 && WOLFSSL_SM_CRYPTOCB */ { } } -#endif /* !NO_SHA || !NO_SHA256 */ +#endif /* !NO_SHA || !NO_SHA256 || SM3 */ #ifdef WOLF_CRYPTO_CB_COPY else if (info->algo_type == WC_ALGO_TYPE_COPY) { #ifdef DEBUG_WOLFSSL @@ -82766,6 +83045,21 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) #if defined(WC_RSA_PSS) && defined(WOLF_CRYPTO_CB_RSA_PAD) myCtx.rsaPssVerifyCount = 0; #endif +#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM_CRYPTOCB) + myCtx.sm2SignCount = 0; + myCtx.sm2VerifyCount = 0; + myCtx.sm2SecretCount = 0; +#endif +#if defined(WOLFSSL_SM3) && defined(WOLFSSL_SM_CRYPTOCB) + myCtx.sm3Count = 0; +#endif +#if defined(WOLFSSL_SM4) && defined(WOLFSSL_SM_CRYPTOCB) + XMEMSET(myCtx.sm4EcbCount, 0, sizeof(myCtx.sm4EcbCount)); + XMEMSET(myCtx.sm4CbcCount, 0, sizeof(myCtx.sm4CbcCount)); + myCtx.sm4CtrCount = 0; + XMEMSET(myCtx.sm4GcmCount, 0, sizeof(myCtx.sm4GcmCount)); + XMEMSET(myCtx.sm4CcmCount, 0, sizeof(myCtx.sm4CcmCount)); +#endif /* set devId to something other than INVALID_DEVID */ devId = 1; @@ -83154,6 +83448,39 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) if (ret == 0) ret = des3_test(); #endif /* !NO_DES3 */ +#ifdef WOLFSSL_SM4 + if (ret == 0) + ret = sm4_test(); + /* Confirm every configured SM4 mode was routed through myCryptoDevCb and + * not handled in software behind the callback's back. */ + #ifdef WOLFSSL_SM_CRYPTOCB + #ifdef WOLFSSL_SM4_ECB + if (ret == 0 && ((myCtx.sm4EcbCount[0] == 0) || + (myCtx.sm4EcbCount[1] == 0))) + ret = WC_TEST_RET_ENC_NC; + #endif + #ifdef WOLFSSL_SM4_CBC + if (ret == 0 && ((myCtx.sm4CbcCount[0] == 0) || + (myCtx.sm4CbcCount[1] == 0))) + ret = WC_TEST_RET_ENC_NC; + #endif + #ifdef WOLFSSL_SM4_CTR + /* Counter mode encrypts in both directions, so there is only one hook. */ + if (ret == 0 && myCtx.sm4CtrCount == 0) + ret = WC_TEST_RET_ENC_NC; + #endif + #ifdef WOLFSSL_SM4_GCM + if (ret == 0 && ((myCtx.sm4GcmCount[0] == 0) || + (myCtx.sm4GcmCount[1] == 0))) + ret = WC_TEST_RET_ENC_NC; + #endif + #ifdef WOLFSSL_SM4_CCM + if (ret == 0 && ((myCtx.sm4CcmCount[0] == 0) || + (myCtx.sm4CcmCount[1] == 0))) + ret = WC_TEST_RET_ENC_NC; + #endif + #endif /* WOLFSSL_SM_CRYPTOCB */ +#endif /* WOLFSSL_SM4 */ #ifndef NO_SHA if (ret == 0) ret = sha_test(); @@ -83206,6 +83533,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) #endif #endif #endif +#ifdef WOLFSSL_SM3 + if (ret == 0) + ret = sm3_test(); + #ifdef WOLFSSL_SM_CRYPTOCB + if (ret == 0 && myCtx.sm3Count == 0) + ret = WC_TEST_RET_ENC_NC; + #endif +#endif /* WOLFSSL_SM3 */ #ifndef NO_HMAC #ifndef NO_SHA if (ret == 0) @@ -83307,6 +83642,168 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void) } #endif /* HAVE_ED448 */ +#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM_CRYPTOCB) && \ + defined(HAVE_ECC_SIGN) && defined(HAVE_ECC_VERIFY) && !defined(WC_NO_RNG) + if (ret == 0) { + WC_RNG sm2Rng; + int sm2RngInit = 0; + int sm2KeyAInit = 0; + int sm2KeyBInit = 0; + int sm2Skip = 0; + int sm2Verify = 0; + word32 sm2SigLen = ECC_SIG_SIZE; + byte sm2Digest[ECC_DIGEST_SIZE]; + WC_DECLARE_VAR(sm2KeyA, ecc_key, 1, HEAP_HINT); + WC_DECLARE_VAR(sm2KeyB, ecc_key, 1, HEAP_HINT); + WC_DECLARE_VAR(sm2Sig, byte, ECC_SIG_SIZE, HEAP_HINT); + + WC_ALLOC_VAR_EX(sm2KeyA, ecc_key, 1, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, ret = WC_TEST_RET_ENC_EC(MEMORY_E)); + if (ret == 0) + WC_ALLOC_VAR_EX(sm2KeyB, ecc_key, 1, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, ret = WC_TEST_RET_ENC_EC(MEMORY_E)); + if (ret == 0) + WC_ALLOC_VAR_EX(sm2Sig, byte, ECC_SIG_SIZE, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, ret = WC_TEST_RET_ENC_EC(MEMORY_E)); + + XMEMSET(sm2Digest, 0x5a, sizeof(sm2Digest)); + myCtx.sm2SignCount = 0; + myCtx.sm2VerifyCount = 0; + myCtx.sm2SecretCount = 0; + + if (ret == 0) { + ret = wc_InitRng_ex(&sm2Rng, HEAP_HINT, devId); + if (ret == 0) + sm2RngInit = 1; + else + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_ecc_init_ex(sm2KeyA, HEAP_HINT, devId); + if (ret == 0) + sm2KeyAInit = 1; + else + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_ecc_init_ex(sm2KeyB, HEAP_HINT, devId); + if (ret == 0) + sm2KeyBInit = 1; + else + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_ecc_sm2_make_key(&sm2Rng, sm2KeyA, WC_ECC_FLAG_NONE); + if (ret == WC_NO_ERR_TRACE(ECC_CURVE_OID_E)) { + sm2Skip = 1; /* curve not available in this build */ + ret = 0; + } + else if (ret != 0) { + ret = WC_TEST_RET_ENC_EC(ret); + } + } + if (ret == 0 && !sm2Skip) { + ret = wc_ecc_sm2_make_key(&sm2Rng, sm2KeyB, WC_ECC_FLAG_NONE); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0 && !sm2Skip) { + ret = wc_ecc_sm2_sign_hash(sm2Digest, (word32)sizeof(sm2Digest), + sm2Sig, &sm2SigLen, &sm2Rng, sm2KeyA); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0 && !sm2Skip && myCtx.sm2SignCount == 0) + ret = WC_TEST_RET_ENC_NC; + if (ret == 0 && !sm2Skip) { + ret = wc_ecc_sm2_verify_hash(sm2Sig, sm2SigLen, sm2Digest, + (word32)sizeof(sm2Digest), &sm2Verify, sm2KeyA); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0 && !sm2Skip && + (myCtx.sm2VerifyCount == 0 || sm2Verify != 1)) { + ret = WC_TEST_RET_ENC_NC; + } + /* A corrupted signature must come back rejected through the + * callback, not errored. Flip a bit in s, leaving the DER framing + * intact so the failure is the math and not a parse. */ + if (ret == 0 && !sm2Skip) { + int sm2VerifyCnt = myCtx.sm2VerifyCount; + + sm2Verify = 1; + sm2Sig[sm2SigLen - 1] ^= 0x01; + ret = wc_ecc_sm2_verify_hash(sm2Sig, sm2SigLen, sm2Digest, + (word32)sizeof(sm2Digest), &sm2Verify, sm2KeyA); + sm2Sig[sm2SigLen - 1] ^= 0x01; + if (ret != 0) { + ret = WC_TEST_RET_ENC_EC(ret); + } + else if ((sm2Verify == 1) || + (myCtx.sm2VerifyCount == sm2VerifyCnt)) { + ret = WC_TEST_RET_ENC_NC; + } + } + #if defined(HAVE_ECC_DHE) && defined(ECC_TIMING_RESISTANT) + /* blinding needs an RNG on the key before the shared secret */ + if (ret == 0 && !sm2Skip) { + ret = wc_ecc_set_rng(sm2KeyA, &sm2Rng); + if (ret == 0) + ret = wc_ecc_set_rng(sm2KeyB, &sm2Rng); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + #endif + #ifdef HAVE_ECC_DHE + if (ret == 0 && !sm2Skip) { + WC_DECLARE_VAR(sharedA, byte, ECC_SHARED_SIZE, HEAP_HINT); + WC_DECLARE_VAR(sharedB, byte, ECC_SHARED_SIZE, HEAP_HINT); + word32 sharedASz = ECC_SHARED_SIZE; + word32 sharedBSz = ECC_SHARED_SIZE; + + WC_ALLOC_VAR_EX(sharedA, byte, ECC_SHARED_SIZE, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, ret = WC_TEST_RET_ENC_EC(MEMORY_E)); + if (ret == 0) + WC_ALLOC_VAR_EX(sharedB, byte, ECC_SHARED_SIZE, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER, + ret = WC_TEST_RET_ENC_EC(MEMORY_E)); + + if (ret == 0) { + ret = wc_ecc_sm2_shared_secret(sm2KeyA, sm2KeyB, sharedA, + &sharedASz); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + if (ret == 0) { + ret = wc_ecc_sm2_shared_secret(sm2KeyB, sm2KeyA, sharedB, + &sharedBSz); + if (ret != 0) + ret = WC_TEST_RET_ENC_EC(ret); + } + /* both sides go through the device and agree on the secret */ + if (ret == 0 && (myCtx.sm2SecretCount == 0 || + sharedASz != sharedBSz || + XMEMCMP(sharedA, sharedB, sharedASz) != 0)) { + ret = WC_TEST_RET_ENC_NC; + } + + WC_FREE_VAR_EX(sharedB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(sharedA, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } + #endif /* HAVE_ECC_DHE */ + + if (sm2KeyBInit) + wc_ecc_free(sm2KeyB); + if (sm2KeyAInit) + wc_ecc_free(sm2KeyA); + if (sm2RngInit) + wc_FreeRng(&sm2Rng); + WC_FREE_VAR_EX(sm2Sig, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(sm2KeyB, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(sm2KeyA, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif /* WOLFSSL_SM2 && WOLFSSL_SM_CRYPTOCB */ + #if defined(WOLFSSL_CMAC) && defined(WOLF_CRYPTO_CB_FREE) && \ !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT) if (ret == 0) { diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index d3028e91e9..49c3b0948b 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -101,6 +101,15 @@ #if defined(WOLFSSL_HAVE_XMSS) #include #endif +#ifdef WOLFSSL_SM2 + #include +#endif +#ifdef WOLFSSL_SM3 + #include +#endif +#ifdef WOLFSSL_SM4 + #include +#endif #ifdef WOLF_CRYPTO_CB_CMD @@ -147,6 +156,35 @@ typedef struct { } wc_CryptoCb_AesAuthDec; #endif +#if defined(WOLFSSL_SM4) && defined(WOLFSSL_SM_CRYPTOCB) && \ + (defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM)) +/* GCM and CCM both pass the IV through nonce/nonceSz. */ +typedef struct { + wc_Sm4* sm4; + byte* out; + const byte* in; + word32 sz; + const byte* nonce; + word32 nonceSz; + byte* authTag; + word32 authTagSz; + const byte* authIn; + word32 authInSz; +} wc_CryptoCb_Sm4AuthEnc; +typedef struct { + wc_Sm4* sm4; + byte* out; + const byte* in; + word32 sz; + const byte* nonce; + word32 nonceSz; + const byte* authTag; + word32 authTagSz; + const byte* authIn; + word32 authInSz; +} wc_CryptoCb_Sm4AuthDec; +#endif + #ifdef WOLF_CRYPTO_CB_SETKEY enum wc_SetKeyType { WC_SETKEY_NONE = 0, @@ -311,6 +349,30 @@ typedef struct wc_CryptoInfo { } eciesdecrypt; #endif /* HAVE_ECC_ENCRYPT */ #endif /* HAVE_ECC */ + #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM_CRYPTOCB) + struct { + const byte* in; + word32 inlen; + byte* out; + word32* outlen; + WC_RNG* rng; + ecc_key* key; + } sm2sign; + struct { + const byte* sig; + word32 siglen; + const byte* hash; + word32 hashlen; + int* res; + ecc_key* key; + } sm2verify; + struct { + ecc_key* private_key; + ecc_key* public_key; + byte* out; + word32* outlen; + } sm2dh; + #endif /* WOLFSSL_SM2 && WOLFSSL_SM_CRYPTOCB */ #ifdef HAVE_CURVE25519 struct { WC_RNG* rng; @@ -502,7 +564,7 @@ typedef struct wc_CryptoInfo { }; #endif } pk; -#if !defined(NO_AES) || !defined(NO_DES3) +#if !defined(NO_AES) || !defined(NO_DES3) || defined(WOLFSSL_SM4) struct { int type; /* enum wc_CipherType */ int enc; @@ -585,14 +647,49 @@ typedef struct wc_CryptoInfo { int pad; /* 1 = RFC 5649 padded, 0 = RFC 3394 */ } aeskeywrap; #endif + #if defined(WOLFSSL_SM4) && defined(WOLFSSL_SM_CRYPTOCB) + #ifdef WOLFSSL_SM4_GCM + wc_CryptoCb_Sm4AuthEnc sm4gcm_enc; + wc_CryptoCb_Sm4AuthDec sm4gcm_dec; + #endif /* WOLFSSL_SM4_GCM */ + #ifdef WOLFSSL_SM4_CCM + wc_CryptoCb_Sm4AuthEnc sm4ccm_enc; + wc_CryptoCb_Sm4AuthDec sm4ccm_dec; + #endif /* WOLFSSL_SM4_CCM */ + #ifdef WOLFSSL_SM4_CBC + struct { + wc_Sm4* sm4; + byte* out; + const byte* in; + word32 sz; + } sm4cbc; + #endif /* WOLFSSL_SM4_CBC */ + #ifdef WOLFSSL_SM4_CTR + struct { + wc_Sm4* sm4; + byte* out; + const byte* in; + word32 sz; + } sm4ctr; + #endif /* WOLFSSL_SM4_CTR */ + #ifdef WOLFSSL_SM4_ECB + struct { + wc_Sm4* sm4; + byte* out; + const byte* in; + word32 sz; + } sm4ecb; + #endif /* WOLFSSL_SM4_ECB */ + #endif /* WOLFSSL_SM4 && WOLFSSL_SM_CRYPTOCB */ void* ctx; #ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES }; #endif } cipher; -#endif /* !NO_AES || !NO_DES3 */ +#endif /* !NO_AES || !NO_DES3 || WOLFSSL_SM4 */ #if !defined(NO_SHA) || !defined(NO_SHA256) || \ - defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA3) + defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) || \ + defined(WOLFSSL_SHA3) || defined(WOLFSSL_SM3) struct { int type; /* enum wc_HashType */ const byte* in; @@ -619,13 +716,16 @@ typedef struct wc_CryptoInfo { #endif #ifdef WOLFSSL_SHA3 wc_Sha3* sha3; + #endif + #if defined(WOLFSSL_SM3) && defined(WOLFSSL_SM_CRYPTOCB) + wc_Sm3* sm3; #endif void* ctx; #ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES }; #endif } hash; -#endif /* !NO_SHA || !NO_SHA256 */ +#endif /* !NO_SHA || !NO_SHA256 || SHA384 || SHA512 || SHA3 || SM3 */ #ifndef NO_HMAC struct { int macType; /* enum wc_HashType */ @@ -923,6 +1023,17 @@ WOLFSSL_LOCAL int wc_CryptoCb_EciesDecrypt(ecc_key* privKey, ecc_key* pubKey, #endif #endif /* HAVE_ECC */ +#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM_CRYPTOCB) +WOLFSSL_LOCAL int wc_CryptoCb_Sm2Sign(const byte* in, word32 inlen, byte* out, + word32* outlen, WC_RNG* rng, ecc_key* key); + +WOLFSSL_LOCAL int wc_CryptoCb_Sm2Verify(const byte* sig, word32 siglen, + const byte* hash, word32 hashlen, int* res, ecc_key* key); + +WOLFSSL_LOCAL int wc_CryptoCb_Sm2SharedSecret(ecc_key* private_key, + ecc_key* public_key, byte* out, word32* outlen); +#endif /* WOLFSSL_SM2 && WOLFSSL_SM_CRYPTOCB */ + #ifdef HAVE_CURVE25519 WOLFSSL_LOCAL int wc_CryptoCb_Curve25519Gen(WC_RNG* rng, int keySize, curve25519_key* key); @@ -1080,6 +1191,51 @@ WOLFSSL_LOCAL int wc_CryptoCb_Des3Decrypt(Des3* des3, byte* out, const byte* in, word32 sz); #endif /* !NO_DES3 */ +#if defined(WOLFSSL_SM4) && defined(WOLFSSL_SM_CRYPTOCB) +#ifdef WOLFSSL_SM4_GCM +WOLFSSL_LOCAL int wc_CryptoCb_Sm4GcmEncrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + +WOLFSSL_LOCAL int wc_CryptoCb_Sm4GcmDecrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#endif /* WOLFSSL_SM4_GCM */ +#ifdef WOLFSSL_SM4_CCM +WOLFSSL_LOCAL int wc_CryptoCb_Sm4CcmEncrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + +WOLFSSL_LOCAL int wc_CryptoCb_Sm4CcmDecrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#endif /* WOLFSSL_SM4_CCM */ +#ifdef WOLFSSL_SM4_CBC +WOLFSSL_LOCAL int wc_CryptoCb_Sm4CbcEncrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz); +WOLFSSL_LOCAL int wc_CryptoCb_Sm4CbcDecrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz); +#endif /* WOLFSSL_SM4_CBC */ +#ifdef WOLFSSL_SM4_CTR +WOLFSSL_LOCAL int wc_CryptoCb_Sm4CtrEncrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz); +#endif /* WOLFSSL_SM4_CTR */ +#ifdef WOLFSSL_SM4_ECB +WOLFSSL_LOCAL int wc_CryptoCb_Sm4EcbEncrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz); +WOLFSSL_LOCAL int wc_CryptoCb_Sm4EcbDecrypt(wc_Sm4* sm4, byte* out, + const byte* in, word32 sz); +#endif /* WOLFSSL_SM4_ECB */ +#endif /* WOLFSSL_SM4 && WOLFSSL_SM_CRYPTOCB */ + #ifndef NO_SHA WOLFSSL_LOCAL int wc_CryptoCb_ShaHash(wc_Sha* sha, const byte* in, word32 inSz, byte* digest); @@ -1117,6 +1273,11 @@ WOLFSSL_LOCAL int wc_CryptoCb_Shake(wc_Sha3* shake, int type, const byte* in, #endif #endif +#if defined(WOLFSSL_SM3) && defined(WOLFSSL_SM_CRYPTOCB) +WOLFSSL_LOCAL int wc_CryptoCb_Sm3Hash(wc_Sm3* sm3, const byte* in, + word32 inSz, byte* digest); +#endif /* WOLFSSL_SM3 && WOLFSSL_SM_CRYPTOCB */ + #ifndef NO_HMAC WOLFSSL_LOCAL int wc_CryptoCb_Hmac(Hmac* hmac, int macType, const byte* in, word32 inSz, byte* digest); diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 3cce9b4c70..864a8bd3bf 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1630,8 +1630,18 @@ enum wc_CipherType { WC_CIPHER_DES3 = 7, WC_CIPHER_DES = 8, WC_CIPHER_CHACHA = 9, - - WC_CIPHER_MAX = WC_CIPHER_AES_CCM + #define _WC_CIPHER_MAX WC_CIPHER_AES_KEYWRAP +#ifdef WOLFSSL_SM4 + WC_CIPHER_SM4_ECB = 16, + WC_CIPHER_SM4_CBC = 17, + WC_CIPHER_SM4_CTR = 18, + WC_CIPHER_SM4_GCM = 19, + WC_CIPHER_SM4_CCM = 20, + #undef _WC_CIPHER_MAX + #define _WC_CIPHER_MAX WC_CIPHER_SM4_CCM +#endif + + WC_CIPHER_MAX = _WC_CIPHER_MAX }; /* PK=public key (asymmetric) based algorithms */ @@ -1705,6 +1715,13 @@ enum wc_PkType { WC_PK_TYPE_ED448_VERIFY = 43, #undef _WC_PK_TYPE_MAX #define _WC_PK_TYPE_MAX WC_PK_TYPE_ED448_VERIFY +#ifdef WOLFSSL_SM2 + WC_PK_TYPE_SM2_SIGN = 44, + WC_PK_TYPE_SM2_VERIFY = 45, + WC_PK_TYPE_SM2_SHARED_SECRET = 46, + #undef _WC_PK_TYPE_MAX + #define _WC_PK_TYPE_MAX WC_PK_TYPE_SM2_SHARED_SECRET +#endif WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX };