From d3d7446a24a573310e7ed28da65ed087c4a2ef08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Sat, 21 Jan 2017 15:31:26 -0200 Subject: [PATCH 01/34] removes 3DES from docs --- wrapper/python/wolfcrypt/docs/symmetric.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/wrapper/python/wolfcrypt/docs/symmetric.rst b/wrapper/python/wolfcrypt/docs/symmetric.rst index 0535080b0..a4939838d 100644 --- a/wrapper/python/wolfcrypt/docs/symmetric.rst +++ b/wrapper/python/wolfcrypt/docs/symmetric.rst @@ -26,8 +26,6 @@ Classes .. autoclass:: Aes -.. autoclass:: Des3 - Example ------- From bf12e4eccac8e35c81f77906364b1283fab69487 Mon Sep 17 00:00:00 2001 From: Erik Bray Date: Thu, 2 Feb 2017 16:51:41 +0100 Subject: [PATCH 02/34] wolfcrypt Python: work around minor issue in Random.__del__ During interpreter shutdown, depending on the order in which things happen, a module can be unloaded before all instances of classes defined in that module are garbage collected. In particular, this means that any global variables (including imported modules) become `None` by the time the instances `__del__` is called, resulting in ``` AttributeError: 'NoneType' object has no attribute 'wc_FreeRng' ``` being displayed while the process exits. This can be avoided simply by catching and ignoring the `AttributeError` in this case, since the process is shutting down anyways. --- wrapper/python/wolfcrypt/wolfcrypt/random.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/wrapper/python/wolfcrypt/wolfcrypt/random.py b/wrapper/python/wolfcrypt/wolfcrypt/random.py index e034f5c58..640dee8fc 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/random.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/random.py @@ -39,7 +39,11 @@ class Random(object): def __del__(self): if self.native_object: - _lib.wc_FreeRng(self.native_object) + try: + _lib.wc_FreeRng(self.native_object) + except AttributeError: + # Can occur during interpreter shutdown + pass def byte(self): From 1cf35301242aabb34d3faaf3f3d8bda201622d5f Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 19 May 2017 09:59:03 -0700 Subject: [PATCH 03/34] Fix for building with WOLFSSL_NO_OCSP_OPTIONAL_CERTS defined. --- wolfcrypt/src/asn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 04ae0c5be..db7421767 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -10234,6 +10234,8 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, WOLFSSL_MSG("\tOCSP Confirm signature failed"); return ASN_OCSP_CONFIRM_E; } + + (void)noVerify; } *ioIndex = idx; From 18806772320dfa7e6f842d4f0c4d6295be8f746b Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 11 May 2017 16:18:19 -0700 Subject: [PATCH 04/34] Disable wc_scrypt tests that use high memory for BENCH_EMBEDDED. --- wolfcrypt/test/test.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index fbed19234..97788b7a1 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -8932,6 +8932,8 @@ int scrypt_test(void) if (XMEMCMP(derived, verify2, sizeof(verify2)) != 0) return -6003; + /* Don't run these test on embedded, since they use large mallocs */ +#ifndef BENCH_EMBEDDED ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, (byte*)"SodiumChloride", 14, 14, 8, 1, sizeof(verify3)); if (ret != 0) @@ -8947,6 +8949,7 @@ int scrypt_test(void) if (XMEMCMP(derived, verify4, sizeof(verify4)) != 0) return -6007; #endif +#endif /* !BENCH_EMBEDDED */ return 0; } From 720f3fdad200d08db09e0a28899bbc8eac1e2be6 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 23 May 2017 15:00:55 -0700 Subject: [PATCH 05/34] Fixed a few minor build errors with async enabled. --- wolfssl/internal.h | 2 +- wolfssl/wolfcrypt/curve25519.h | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 568fb7e86..e17d8840b 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2999,7 +2999,7 @@ typedef struct HS_Hashes { #ifdef WOLFSSL_ASYNC_CRYPT - #define MAX_ASYNC_ARGS 16 + #define MAX_ASYNC_ARGS 18 typedef void (*FreeArgsCb)(struct WOLFSSL* ssl, void* pArgs); struct WOLFSSL_ASYNC { diff --git a/wolfssl/wolfcrypt/curve25519.h b/wolfssl/wolfcrypt/curve25519.h index fb4a96c29..85b036d14 100644 --- a/wolfssl/wolfcrypt/curve25519.h +++ b/wolfssl/wolfcrypt/curve25519.h @@ -30,6 +30,10 @@ #include #include +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -50,7 +54,7 @@ typedef struct { #ifdef FREESCALE_LTC_ECC byte pointY[CURVE25519_KEYSIZE]; #endif -}ECPoint; +} ECPoint; /* A CURVE25519 Key */ typedef struct curve25519_key { @@ -61,6 +65,10 @@ typedef struct curve25519_key { curves (idx >= 0) or user supplied */ ECPoint p; /* public key */ ECPoint k; /* private key */ + +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif } curve25519_key; enum { From 64de29f277f6129b0f9a0395fcb766859759ddeb Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 23 May 2017 15:23:58 -0700 Subject: [PATCH 06/34] Fix for wolfCrypt test with enable-all and asynccrypt. --- wolfcrypt/test/test.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 97788b7a1..535a60fab 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -7728,6 +7728,9 @@ static int dh_generate_test(WC_RNG *rng) /* Use API. */ ret = wc_DhGenerateKeyPair(&smallKey, rng, priv, &privSz, pub, &pubSz); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &smallKey.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (ret != 0) { ret = -5707; } From c1664bd1a03b79a77853d418238c899ae1963e04 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 23 May 2017 15:41:42 -0700 Subject: [PATCH 07/34] Fixes for async with benchmark tool. --- wolfcrypt/benchmark/benchmark.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 3ca221509..faed120ce 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -3072,9 +3072,15 @@ void bench_eccEncrypt(void) } ret = wc_ecc_make_key(&rng, keySize, &userA); +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (ret != 0) goto exit; ret = wc_ecc_make_key(&rng, keySize, &userB); +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (ret != 0) goto exit; From 47b0a62c88ccbd6535b0d3001b122244b84dcfcd Mon Sep 17 00:00:00 2001 From: jrblixt Date: Fri, 19 May 2017 09:44:40 -0600 Subject: [PATCH 08/34] Hmac unit test functions ready for PR. --- tests/api.c | 1063 ++++++++++++++++++++++++++++++++++++++++++ wolfcrypt/src/hmac.c | 8 + 2 files changed, 1071 insertions(+) diff --git a/tests/api.c b/tests/api.c index 13b709e42..9476503fa 100644 --- a/tests/api.c +++ b/tests/api.c @@ -65,6 +65,10 @@ #include #endif +#ifndef NO_HMAC + #include +#endif + #ifdef OPENSSL_EXTRA #include #include @@ -3728,6 +3732,1048 @@ static int test_wc_Sha224Final (void) } /* END test_wc_Sha224Final */ +/* + * Test function for wc_HmacSetKey + */ +static int test_wc_Md5HmacSetKey (void) +{ +#if !defined(NO_HMAC) && !defined(NO_MD5) + Hmac hmac; + int ret, flag, times, itr; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + "Jefe", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + }; + + times = sizeof(keys) / sizeof(char*); + flag = 0; + + printf(testingFmt, "wc_HmacSetKey() with MD5"); + + for (itr = 0; itr < times; itr++) { + ret = wc_HmacSetKey(&hmac, MD5, (byte*)keys[itr], + (word32)XSTRLEN(keys[itr])); + if (ret != 0) { + flag = ret; + } + } + + /* Bad args. */ + if (!flag) { + ret = wc_HmacSetKey(NULL, MD5, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, MD5, NULL, (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, 20, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, MD5, (byte*)keys[0], 0); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Md5HmacSetKey */ + + +/* + * testing wc_HmacSetKey() on Sha hash. + */ +static int test_wc_ShaHmacSetKey (void) +{ + +#if !defined(NO_HMAC) && !defined(NO_SHA) + Hmac hmac; + int ret, flag, times, itr; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "Jefe", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" + }; + + times = sizeof(keys) / sizeof(char*); + flag = 0; + + printf(testingFmt, "wc_HmacSetKey() with SHA"); + + for (itr = 0; itr < times; itr++) { + ret = wc_HmacSetKey(&hmac, SHA, (byte*)keys[itr], + (word32)XSTRLEN(keys[itr])); + if (ret != 0) { + flag = ret; + } + } + + /* Bad args. */ + if (!flag) { + ret = wc_HmacSetKey(NULL, SHA, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, SHA, NULL, (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, 20, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, SHA, (byte*)keys[0], 0); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_ShaHmacSetKey() */ + +/* + * testing wc_HmacSetKey() on Sha224 hash. + */ +static int test_wc_Sha224HmacSetKey (void) +{ + +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA224) + Hmac hmac; + int ret, flag, times, itr; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "Jefe", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" + }; + + times = sizeof(keys) / sizeof(char*); + flag = 0; + + printf(testingFmt, "wc_HmacSetKey() with SHA 224"); + + for (itr = 0; itr < times; itr++) { + ret = wc_HmacSetKey(&hmac, SHA224, (byte*)keys[itr], + (word32)XSTRLEN(keys[itr])); + if (ret != 0) { + flag = ret; + } + } + + /* Bad args. */ + if (!flag) { + ret = wc_HmacSetKey(NULL, SHA224, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, SHA224, NULL, (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, 20, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, SHA224, (byte*)keys[0], 0); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha224HmacSetKey() */ + + /* + * testing wc_HmacSetKey() on Sha256 hash + */ +static int test_wc_Sha256HmacSetKey (void) +{ + +#if !defined(NO_HMAC) && !defined(NO_SHA256) + Hmac hmac; + int ret, flag, times, itr; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "Jefe", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" + }; + + times = sizeof(keys) / sizeof(char*); + flag = 0; + + printf(testingFmt, "wc_HmacSetKey() with SHA256"); + + for (itr = 0; itr < times; itr++) { + ret = wc_HmacSetKey(&hmac, SHA256, (byte*)keys[itr], + (word32)XSTRLEN(keys[itr])); + if (ret != 0) { + flag = ret; + } + } + + /* Bad args. */ + if (!flag) { + ret = wc_HmacSetKey(NULL, SHA256, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, SHA256, NULL, (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, 20, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, SHA256, (byte*)keys[0], 0); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha256HmacSetKey() */ + + +/* + * testing wc_HmacSetKey on Sha384 hash. + */ +static int test_wc_Sha384HmacSetKey (void) +{ +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA384) + Hmac hmac; + int ret, flag, times, itr; + + const char* keys[]= + { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "Jefe", + "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" + "\xAA\xAA\xAA" + }; + + times = sizeof(keys) / sizeof(char*); + flag = 0; + + printf(testingFmt, "wc_HmacSetKey() with SHA384"); + + for (itr = 0; itr < times; itr++) { + ret = wc_HmacSetKey(&hmac, SHA384, (byte*)keys[itr], + (word32)XSTRLEN(keys[itr])); + if (ret != 0) { + flag = ret; + } + } + + /* Bad args. */ + if (!flag) { + ret = wc_HmacSetKey(NULL, SHA384, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, SHA384, NULL, (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, 20, (byte*)keys[0], + (word32)XSTRLEN(keys[0])); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacSetKey(&hmac, SHA384, (byte*)keys[0], 0); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha384HmacSetKey() */ + + +/* + * testing wc_HmacUpdate on Md5 hash. + */ +static int test_wc_Md5HmacUpdate (void) +{ +#if !defined(NO_HMAC) && !defined(NO_MD5) + Hmac hmac; + testVector a, b; + int ret, flag; + const char* keys = "Jefe"; + + a.input = "what do ya want for nothing?"; + a.inLen = XSTRLEN(a.input); + + b.input = "Hi There"; + b.inLen = XSTRLEN(b.input); + + flag = 0; + + printf(testingFmt, "wc_HmacUpdate() with MD5"); + + ret = wc_HmacSetKey(&hmac, MD5, (byte*)keys, (word32)XSTRLEN(keys)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + /* Update Hmac. */ + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_HmacUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, NULL, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Md5HmacUpdate */ + +/* + * testing wc_HmacUpdate on SHA hash. + */ +static int test_wc_ShaHmacUpdate (void) +{ +#if !defined(NO_HMAC) && !defined(NO_SHA) + Hmac hmac; + testVector a, b; + int ret, flag; + const char* keys = "Jefe"; + + a.input = "what do ya want for nothing?"; + a.inLen = XSTRLEN(a.input); + + b.input = "Hi There"; + b.inLen = XSTRLEN(b.input); + + flag = 0; + + printf(testingFmt, "wc_HmacUpdate() with SHA"); + + ret = wc_HmacSetKey(&hmac, SHA, (byte*)keys, (word32)XSTRLEN(keys)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + /* Update Hmac. */ + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_HmacUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, NULL, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_ShaHmacUpdate */ + +/* + * testing wc_HmacUpdate on SHA224 hash. + */ +static int test_wc_Sha224HmacUpdate (void) +{ +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA224) + Hmac hmac; + testVector a, b; + int ret, flag; + const char* keys = "Jefe"; + + a.input = "what do ya want for nothing?"; + a.inLen = XSTRLEN(a.input); + + b.input = "Hi There"; + b.inLen = XSTRLEN(b.input); + + flag = 0; + + printf(testingFmt, "wc_HmacUpdate() with SHA224"); + + ret = wc_HmacSetKey(&hmac, SHA224, (byte*)keys, (word32)XSTRLEN(keys)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + /* Update Hmac. */ + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_HmacUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, NULL, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha224HmacUpdate */ + +/* + * testing wc_HmacUpdate on SHA256 hash. + */ +static int test_wc_Sha256HmacUpdate (void) +{ +#if !defined(NO_HMAC) && !defined(NO_SHA256) + Hmac hmac; + testVector a, b; + int ret, flag; + const char* keys = "Jefe"; + + a.input = "what do ya want for nothing?"; + a.inLen = XSTRLEN(a.input); + + b.input = "Hi There"; + b.inLen = XSTRLEN(b.input); + + flag = 0; + + printf(testingFmt, "wc_HmacUpdate() with SHA256"); + + ret = wc_HmacSetKey(&hmac, SHA256, (byte*)keys, (word32)XSTRLEN(keys)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + /* Update Hmac. */ + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_HmacUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, NULL, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha256HmacUpdate */ + +/* + * testing wc_HmacUpdate on SHA384 hash. + */ +static int test_wc_Sha384HmacUpdate (void) +{ +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA384) + Hmac hmac; + testVector a, b; + int ret, flag; + const char* keys = "Jefe"; + + a.input = "what do ya want for nothing?"; + a.inLen = XSTRLEN(a.input); + + b.input = "Hi There"; + b.inLen = XSTRLEN(b.input); + + flag = 0; + + printf(testingFmt, "wc_HmacUpdate() with SHA384"); + + ret = wc_HmacSetKey(&hmac, SHA384, (byte*)keys, (word32)XSTRLEN(keys)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + /* Update Hmac. */ + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_HmacUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, NULL, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, 0); + if (ret != 0) { + flag = ret; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha384HmacUpdate */ + +/* + * Testing wc_HmacFinal() with MD5 + */ + +static int test_wc_Md5HmacFinal (void) +{ +#if !defined(NO_HMAC) && !defined(NO_MD5) + Hmac hmac; + byte hash[MD5_DIGEST_SIZE]; + testVector a; + int ret, flag; + const char* key; + + key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; + a.input = "Hi There"; + a.output = "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc" + "\x9d"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + flag = 0; + + printf(testingFmt, "wc_HmacFinal() with MD5"); + + ret = wc_HmacSetKey(&hmac, MD5, (byte*)key, (word32)XSTRLEN(key)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, MD5_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Try bad parameters. */ + if (!flag) { + ret = wc_HmacFinal(NULL, hash); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Md5HmacFinal */ + +/* + * Testing wc_HmacFinal() with SHA + */ +static int test_wc_ShaHmacFinal (void) +{ +#if !defined(NO_HMAC) && !defined(NO_SHA) + Hmac hmac; + byte hash[SHA_DIGEST_SIZE]; + testVector a; + int ret, flag; + const char* key; + + key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b"; + a.input = "Hi There"; + a.output = "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c" + "\x8e\xf1\x46\xbe\x00"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + flag = 0; + + printf(testingFmt, "wc_HmacFinal() with SHA"); + + ret = wc_HmacSetKey(&hmac, SHA, (byte*)key, (word32)XSTRLEN(key)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Try bad parameters. */ + if (!flag) { + ret = wc_HmacFinal(NULL, hash); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_ShaHmacFinal */ + + +/* + * Testing wc_HmacFinal() with SHA224 + */ +static int test_wc_Sha224HmacFinal (void) +{ +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA224) + Hmac hmac; + byte hash[SHA224_DIGEST_SIZE]; + testVector a; + int ret, flag; + const char* key; + + key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b"; + a.input = "Hi There"; + a.output = "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3" + "\x3f\x47\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + flag = 0; + + printf(testingFmt, "wc_HmacFinal() with SHA224"); + + ret = wc_HmacSetKey(&hmac, SHA224, (byte*)key, (word32)XSTRLEN(key)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA224_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Try bad parameters. */ + if (!flag) { + ret = wc_HmacFinal(NULL, hash); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha224HmacFinal */ + +/* + * Testing wc_HmacFinal() with SHA256 + */ +static int test_wc_Sha256HmacFinal (void) +{ +#if !defined(NO_HMAC) && !defined(NO_SHA256) + Hmac hmac; + byte hash[SHA256_DIGEST_SIZE]; + testVector a; + int ret, flag; + const char* key; + + key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b"; + a.input = "Hi There"; + a.output = "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1" + "\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32" + "\xcf\xf7"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + flag = 0; + + printf(testingFmt, "wc_HmacFinal() with SHA256"); + + ret = wc_HmacSetKey(&hmac, SHA256, (byte*)key, (word32)XSTRLEN(key)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA256_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Try bad parameters. */ + if (!flag) { + ret = wc_HmacFinal(NULL, hash); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha256HmacFinal */ + +/* + * Testing wc_HmacFinal() with SHA384 + */ +static int test_wc_Sha384HmacFinal (void) +{ +#if !defined(NO_HMAC) && defined(WOLFSSL_SHA384) + Hmac hmac; + byte hash[SHA384_DIGEST_SIZE]; + testVector a; + int ret, flag; + const char* key; + + key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b"; + a.input = "Hi There"; + a.output = "\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90" + "\x7f\x15\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb" + "\xc5\x9c\xfa\xea\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2" + "\xfa\x9c\xb6"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + flag = 0; + + printf(testingFmt, "wc_HmacFinal() with SHA384"); + + ret = wc_HmacSetKey(&hmac, SHA384, (byte*)key, (word32)XSTRLEN(key)); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + ret = wc_HmacUpdate(&hmac, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA384_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Try bad parameters. */ + if (!flag) { + ret = wc_HmacFinal(NULL, hash); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_HmacFinal(&hmac, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha384HmacFinal */ + + + /*----------------------------------------------------------------------------* | Compatibility Tests *----------------------------------------------------------------------------*/ @@ -4986,6 +6032,23 @@ void ApiTest(void) AssertFalse(test_wc_InitRipeMd()); AssertFalse(test_wc_RipeMdUpdate()); AssertFalse(test_wc_RipeMdFinal()); + + AssertFalse(test_wc_Md5HmacSetKey()); + AssertFalse(test_wc_Md5HmacUpdate()); + AssertFalse(test_wc_Md5HmacFinal()); + AssertFalse(test_wc_ShaHmacSetKey()); + AssertFalse(test_wc_ShaHmacUpdate()); + AssertFalse(test_wc_ShaHmacFinal()); + AssertFalse(test_wc_Sha224HmacSetKey()); + AssertFalse(test_wc_Sha224HmacUpdate()); + AssertFalse(test_wc_Sha224HmacFinal()); + AssertFalse(test_wc_Sha256HmacSetKey()); + AssertFalse(test_wc_Sha256HmacUpdate()); + AssertFalse(test_wc_Sha256HmacFinal()); + AssertFalse(test_wc_Sha384HmacSetKey()); + AssertFalse(test_wc_Sha384HmacUpdate()); + AssertFalse(test_wc_Sha384HmacFinal()); + printf(" End API Tests\n"); } diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 0dc745361..4ece69def 100755 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -510,6 +510,10 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) { int ret = 0; + if (hmac == NULL || msg == NULL) { + return BAD_FUNC_ARG; + } + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { #if defined(HAVE_CAVIUM) @@ -581,6 +585,10 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) { int ret; + if (hmac == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { int hashLen = wc_HmacSizeByType(hmac->macType); From 0e22752af45862f9c67aba30f6b3c61a2018f220 Mon Sep 17 00:00:00 2001 From: jrblixt Date: Fri, 19 May 2017 14:37:51 -0600 Subject: [PATCH 09/34] Jenkins fixes. --- tests/api.c | 16 ++++++++++------ wolfcrypt/src/hmac.c | 20 ++++++++++++++++---- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/tests/api.c b/tests/api.c index 9476503fa..6fe82d56d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -4473,13 +4473,14 @@ static int test_wc_Md5HmacFinal (void) } } +#ifndef HAVE_FIPS if (!flag) { ret = wc_HmacFinal(&hmac, NULL); if (ret != BAD_FUNC_ARG) { flag = SSL_FATAL_ERROR; } } - +#endif printf(resultFmt, flag == 0 ? passed : failed); #endif @@ -4544,13 +4545,14 @@ static int test_wc_ShaHmacFinal (void) } } +#ifndef HAVE_FIPS if (!flag) { ret = wc_HmacFinal(&hmac, NULL); if (ret != BAD_FUNC_ARG) { flag = SSL_FATAL_ERROR; } } - +#endif printf(resultFmt, flag == 0 ? passed : failed); #endif @@ -4616,13 +4618,14 @@ static int test_wc_Sha224HmacFinal (void) } } +#ifndef HAVE_FIPS if (!flag) { ret = wc_HmacFinal(&hmac, NULL); if (ret != BAD_FUNC_ARG) { flag = SSL_FATAL_ERROR; } } - +#endif printf(resultFmt, flag == 0 ? passed : failed); #endif @@ -4687,13 +4690,14 @@ static int test_wc_Sha256HmacFinal (void) } } +#ifndef HAVE_FIPS if (!flag) { ret = wc_HmacFinal(&hmac, NULL); if (ret != BAD_FUNC_ARG) { flag = SSL_FATAL_ERROR; } } - +#endif printf(resultFmt, flag == 0 ? passed : failed); #endif @@ -4758,14 +4762,14 @@ static int test_wc_Sha384HmacFinal (void) flag = SSL_FATAL_ERROR; } } - +#ifndef HAVE_FIPS if (!flag) { ret = wc_HmacFinal(&hmac, NULL); if (ret != BAD_FUNC_ARG) { flag = SSL_FATAL_ERROR; } } - +#endif printf(resultFmt, flag == 0 ? passed : failed); #endif diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 4ece69def..97fa2e2e0 100755 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -25,6 +25,7 @@ #endif #include +#include #ifndef NO_HMAC @@ -43,14 +44,28 @@ /* does init */ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz) { + if (hmac == NULL || (key == NULL && keySz != 0) || + !(type == MD5 || type == SHA || type == SHA256 || type == SHA384 + || type == SHA512 || type == BLAKE2B_ID)) { + return BAD_FUNC_ARG; + } + return HmacSetKey_fips(hmac, type, key, keySz); } int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz) { + if (hmac == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + return HmacUpdate_fips(hmac, in, sz); } int wc_HmacFinal(Hmac* hmac, byte* out) { + if (hmac == NULL) { + return BAD_FUNC_ARG; + } + return HmacFinal_fips(hmac, out); } int wolfSSL_GetHmacMaxSize(void) @@ -88,9 +103,6 @@ #else /* else build without fips */ -#include - - #ifdef WOLFSSL_PIC32MZ_HASH #define wc_InitMd5 wc_InitMd5_sw #define wc_Md5Update wc_Md5Update_sw @@ -510,7 +522,7 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) { int ret = 0; - if (hmac == NULL || msg == NULL) { + if (hmac == NULL) { return BAD_FUNC_ARG; } From 4134073c8d082effb40a88ae820eb1b3a1e9a7ab Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Tue, 23 May 2017 13:50:49 +1000 Subject: [PATCH 10/34] Initial revision of SHA-3 --- configure.ac | 33 + src/include.am | 4 + wolfcrypt/benchmark/benchmark.c | 327 +++++ wolfcrypt/src/include.am | 3 +- wolfcrypt/src/sha3.c | 710 ++++++++++ wolfcrypt/src/sha3_long.i | 2345 +++++++++++++++++++++++++++++++ wolfcrypt/test/test.c | 250 ++++ wolfssl/wolfcrypt/include.am | 3 +- wolfssl/wolfcrypt/sha3.h | 119 ++ 9 files changed, 3792 insertions(+), 2 deletions(-) create mode 100755 wolfcrypt/src/sha3.c create mode 100644 wolfcrypt/src/sha3_long.i create mode 100644 wolfssl/wolfcrypt/sha3.h diff --git a/configure.ac b/configure.ac index 22d95c05e..981ae79fa 100644 --- a/configure.ac +++ b/configure.ac @@ -167,6 +167,7 @@ then enable_ripemd=yes enable_sha512=yes enable_sha224=yes + enable_sha3=yes enable_sessioncerts=yes enable_keygen=yes enable_certgen=yes @@ -1758,6 +1759,37 @@ fi AM_CONDITIONAL([BUILD_SHA224], [test "x$ENABLED_SHA224" = "xyes"]) +# set sha3 default +SHA3_DEFAULT=no +if test "$host_cpu" = "x86_64" +then + if test "x$ENABLED_FIPS" = "xno" + then + SHA3_DEFAULT=yes + fi +fi + +# SHA3 +AC_ARG_ENABLE([sha3], + [AS_HELP_STRING([--enable-sha3],[Enable wolfSSL SHA-3 support (default: enabled on x86_64)])], + [ ENABLED_SHA3=$enableval ], + [ ENABLED_SHA3=$SHA3_DEFAULT ] + ) + +if test "$ENABLED_SHA3" = "small" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3_SMALL" + ENABLED_SHA3="yes" +fi + +if test "$ENABLED_SHA3" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3" +fi + +AM_CONDITIONAL([BUILD_SHA3], [test "x$ENABLED_SHA3" = "xyes"]) + + # set POLY1305 default POLY1305_DEFAULT=yes @@ -3658,6 +3690,7 @@ echo " * RIPEMD: $ENABLED_RIPEMD" echo " * SHA: $ENABLED_SHA" echo " * SHA-224: $ENABLED_SHA224" echo " * SHA-512: $ENABLED_SHA512" +echo " * SHA3: $ENABLED_SHA3" echo " * BLAKE2: $ENABLED_BLAKE2" echo " * CMAC: $ENABLED_CMAC" echo " * keygen: $ENABLED_KEYGEN" diff --git a/src/include.am b/src/include.am index b8dd4951d..be2e6ac9b 100644 --- a/src/include.am +++ b/src/include.am @@ -115,6 +115,10 @@ if BUILD_SHA512 src_libwolfssl_la_SOURCES += wolfcrypt/src/sha512.c endif +if BUILD_SHA3 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha3.c +endif + src_libwolfssl_la_SOURCES += \ wolfcrypt/src/logging.c \ wolfcrypt/src/wc_encrypt.c \ diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 27e605c7a..ea5c35cf1 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -76,6 +76,7 @@ #include #include #include +#include #include #include #include @@ -208,6 +209,10 @@ void bench_sha224(int); void bench_sha256(int); void bench_sha384(int); void bench_sha512(int); +void bench_sha3_224(int); +void bench_sha3_256(int); +void bench_sha3_384(int); +void bench_sha3_512(int); int bench_ripemd(void); void bench_cmac(void); void bench_scrypt(void); @@ -824,6 +829,32 @@ static void* benchmarks_do(void* args) bench_sha512(1); #endif #endif +#ifdef WOLFSSL_SHA3 + #ifndef NO_SW_BENCH + bench_sha3_224(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + bench_sha3_224(1); + #endif + #ifndef NO_SW_BENCH + bench_sha3_256(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + bench_sha3_256(1); + #endif + #ifndef NO_SW_BENCH + bench_sha3_384(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + bench_sha3_384(1); + #endif + #ifndef NO_SW_BENCH + bench_sha3_512(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + bench_sha3_512(1); + #endif +#endif #ifdef WOLFSSL_RIPEMD bench_ripemd(); #endif @@ -2084,6 +2115,302 @@ exit: } #endif + +#ifdef WOLFSSL_SHA3 +void bench_sha3_224(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA224_DIGEST_SIZE, HEAP_HINT); + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_224(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_224 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* 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, ×, numBlocks)) { + ret = wc_Sha3_224_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_224; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_224_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_224; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha3_224: + bench_stats_sym_finish("SHA3-224", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha3_224 failed: %d\n", ret); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_224_Free(&hash[i]); + } +#endif + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); +} + +void bench_sha3_256(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA3_256_DIGEST_SIZE, HEAP_HINT); + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_256(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_256 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* 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, ×, numBlocks)) { + ret = wc_Sha3_256_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_256; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_256_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_256; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha3_256: + bench_stats_sym_finish("SHA3-256", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha3_256 failed: %d\n", ret); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_256_Free(&hash[i]); + } +#endif + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); +} + +void bench_sha3_384(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA3_384_DIGEST_SIZE, HEAP_HINT); + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_384(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_384 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* 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, ×, numBlocks)) { + ret = wc_Sha3_384_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_384; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_384_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_384; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha3_384: + bench_stats_sym_finish("SHA3-384", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha3_384 failed: %d\n", ret); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_384_Free(&hash[i]); + } +#endif + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); +} + +void bench_sha3_512(int doAsync) +{ + Sha3 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA3_512_DIGEST_SIZE, HEAP_HINT); + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha3_512(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha3_512 failed, ret = %d\n", ret); + goto exit; + } + } + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* 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, ×, numBlocks)) { + ret = wc_Sha3_512_Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_512; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha3_512_Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha3_512; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha3_512: + bench_stats_sym_finish("SHA3-512", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha3_512 failed: %d\n", ret); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha3_512_Free(&hash[i]); + } +#endif + + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); +} +#endif + + #ifdef WOLFSSL_RIPEMD int bench_ripemd(void) { diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 3b895934b..fd5c3ca47 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -40,7 +40,8 @@ EXTRA_DIST += \ wolfcrypt/src/fp_sqr_comba_8.i \ wolfcrypt/src/fp_sqr_comba_9.i \ wolfcrypt/src/fp_sqr_comba_small_set.i \ - wolfcrypt/src/fe_x25519_128.i + wolfcrypt/src/fe_x25519_128.i \ + wolfcrypt/src/sha3_long.i EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/ti/ti-des3.c \ diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c new file mode 100755 index 000000000..584f3ce99 --- /dev/null +++ b/wolfcrypt/src/sha3.c @@ -0,0 +1,710 @@ +/* sha3.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_SHA3 + +#include +#include + +/* fips wrapper calls, user can call direct */ +#ifdef HAVE_FIPS + + int wc_InitSha3_224(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_224_fips(sha); + } + int wc_Sha3_224_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_224_Update_fips(sha, data, len); + } + int wc_Sha3_224_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_224_Final_fips(sha, out); + } + void wc_Sha3_224_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + + int wc_InitSha3_256(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_256_fips(sha); + } + int wc_Sha3_256_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_256_Update_fips(sha, data, len); + } + int wc_Sha3_256_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_256_Final_fips(sha, out); + } + void wc_Sha3_256_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + + int wc_InitSha3_384(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_384_fips(sha); + } + int wc_Sha3_384_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_384_Update_fips(sha, data, len); + } + int wc_Sha3_384_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_384_Final_fips(sha, out); + } + void wc_Sha3_384_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + + int wc_InitSha3_512(Sha3* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha3_512_fips(sha); + } + int wc_Sha3_512_Update(Sha3* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha3_512_Update_fips(sha, data, len); + } + int wc_Sha3_512_Final(Sha3* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha3_512_Final_fips(sha, out); + } + void wc_Sha3_512_Free(Sha3* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + +#else /* else build without fips */ + + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifdef WOLFSSL_SHA3_SMALL +/** + * Rotate a 64-bit value left. + * + * @param [in] a The number to rotate left. + * @param [in] r The number od bits to rotate left. + * @return The rotated number. + */ +#define ROTL64(a, n) (((a)<<(n))|((a)>>(64-(n)))) + +/** An array of values to XOR for block operation. */ +static const word64 hash_keccak_r[24] = +{ + 0x0000000000000001UL, 0x0000000000008082UL, + 0x800000000000808aUL, 0x8000000080008000UL, + 0x000000000000808bUL, 0x0000000080000001UL, + 0x8000000080008081UL, 0x8000000000008009UL, + 0x000000000000008aUL, 0x0000000000000088UL, + 0x0000000080008009UL, 0x000000008000000aUL, + 0x000000008000808bUL, 0x800000000000008bUL, + 0x8000000000008089UL, 0x8000000000008003UL, + 0x8000000000008002UL, 0x8000000000000080UL, + 0x000000000000800aUL, 0x800000008000000aUL, + 0x8000000080008081UL, 0x8000000000008080UL, + 0x0000000080000001UL, 0x8000000080008008UL +}; + +#define K_I_0 10 +#define K_I_1 7 +#define K_I_2 11 +#define K_I_3 17 +#define K_I_4 18 +#define K_I_5 3 +#define K_I_6 5 +#define K_I_7 16 +#define K_I_8 8 +#define K_I_9 21 +#define K_I_10 24 +#define K_I_11 4 +#define K_I_12 15 +#define K_I_13 23 +#define K_I_14 19 +#define K_I_15 13 +#define K_I_16 12 +#define K_I_17 2 +#define K_I_18 20 +#define K_I_19 14 +#define K_I_20 22 +#define K_I_21 9 +#define K_I_22 6 +#define K_I_23 1 + +#define K_R_0 1 +#define K_R_1 3 +#define K_R_2 6 +#define K_R_3 10 +#define K_R_4 15 +#define K_R_5 21 +#define K_R_6 28 +#define K_R_7 36 +#define K_R_8 45 +#define K_R_9 55 +#define K_R_10 2 +#define K_R_11 14 +#define K_R_12 27 +#define K_R_13 41 +#define K_R_14 56 +#define K_R_15 8 +#define K_R_16 25 +#define K_R_17 43 +#define K_R_18 62 +#define K_R_19 18 +#define K_R_20 39 +#define K_R_21 61 +#define K_R_22 20 +#define K_R_23 44 + +/** + * Swap and rotate left operation. + * + * @param [in] s The state. + * @param [in] t1 Temporary value. + * @param [in] t2 Second temporary value. + * @param [in] i The index of the loop. + */ +#define SWAP_ROTL(s, t1, t2, i) \ +do \ +{ \ + t2 = s[K_I_##i]; s[K_I_##i] = ROTL64(t1, K_R_##i); \ +} \ +while (0) + +/** + * Mix the XOR of the column's values into each number by column. + * + * @param [in] s The state. + * @param [in] b Temporary array of XORed column values. + * @param [in] x The index of the column. + * @param [in] t Temporary variable. + */ +#define COL_MIX(s, b, x, t) \ +do \ +{ \ + for (x = 0; x < 5; x++) \ + b[x] = s[x + 0] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20]; \ + for (x = 0; x < 5; x++) \ + { \ + t = b[(x + 4) % 5] ^ ROTL64(b[(x + 1) % 5], 1); \ + s[x + 0] ^= t; \ + s[x + 5] ^= t; \ + s[x + 10] ^= t; \ + s[x + 15] ^= t; \ + s[x + 20] ^= t; \ + } \ +} \ +while (0) + +#ifdef SHA3_BY_SPEC +/** + * Mix the row values. + * BMI1 has ANDN instruction ((~a) & b) - Haswell and above. + * + * @param [in] s The state. + * @param [in] b Temporary array of XORed row values. + * @param [in] y The index of the row to work on. + * @param [in] x The index of the column. + * @param [in] t0 Temporary variable. + * @param [in] t1 Temporary variable. + */ +#define ROW_MIX(s, b, y, x, t0, t1) \ +do \ +{ \ + for (y = 0; y < 5; y++) \ + { \ + for (x = 0; x < 5; x++) \ + b[x] = s[y * 5 + x]; \ + for (x = 0; x < 5; x++) \ + s[y * 5 + x] = b[x] ^ (~b[(x + 1) % 5] & b[(x + 2) % 5]); \ + } \ +} \ +while (0) +#else +/** + * Mix the row values. + * a ^ (~b & c) == a ^ (c & (b ^ c)) == (a ^ b) ^ (b | c) + * + * @param [in] s The state. + * @param [in] b Temporary array of XORed row values. + * @param [in] y The index of the row to work on. + * @param [in] x The index of the column. + * @param [in] t0 Temporary variable. + * @param [in] t1 Temporary variable. + */ +#define ROW_MIX(s, b, y, x, t12, t34) \ +do \ +{ \ + for (y = 0; y < 5; y++) \ + { \ + for (x = 0; x < 5; x++) \ + b[x] = s[y * 5 + x]; \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s[y * 5 + 0] = b[0] ^ (b[2] & t12); \ + s[y * 5 + 1] = t12 ^ (b[2] | b[3]); \ + s[y * 5 + 2] = b[2] ^ (b[4] & t34); \ + s[y * 5 + 3] = t34 ^ (b[4] | b[0]); \ + s[y * 5 + 4] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + } \ +} \ +while (0) +#endif + +/** + * The block operation performed on the state. + * + * @param [in] s The state. + */ +static void BlockSha3(word64 *s) +{ + byte i, x, y; + word64 t0, t1; + word64 b[5]; + + for (i = 0; i < 24; i++) + { + COL_MIX(s, b, x, t0); + + t0 = s[1]; + SWAP_ROTL(s, t0, t1, 0); + SWAP_ROTL(s, t1, t0, 1); + SWAP_ROTL(s, t0, t1, 2); + SWAP_ROTL(s, t1, t0, 3); + SWAP_ROTL(s, t0, t1, 4); + SWAP_ROTL(s, t1, t0, 5); + SWAP_ROTL(s, t0, t1, 6); + SWAP_ROTL(s, t1, t0, 7); + SWAP_ROTL(s, t0, t1, 8); + SWAP_ROTL(s, t1, t0, 9); + SWAP_ROTL(s, t0, t1, 10); + SWAP_ROTL(s, t1, t0, 11); + SWAP_ROTL(s, t0, t1, 12); + SWAP_ROTL(s, t1, t0, 13); + SWAP_ROTL(s, t0, t1, 14); + SWAP_ROTL(s, t1, t0, 15); + SWAP_ROTL(s, t0, t1, 16); + SWAP_ROTL(s, t1, t0, 17); + SWAP_ROTL(s, t0, t1, 18); + SWAP_ROTL(s, t1, t0, 19); + SWAP_ROTL(s, t0, t1, 20); + SWAP_ROTL(s, t1, t0, 21); + SWAP_ROTL(s, t0, t1, 22); + SWAP_ROTL(s, t1, t0, 23); + + ROW_MIX(s, b, y, x, t0, t1); + + s[0] ^= hash_keccak_r[i]; + } +} +#else +#include "sha3_long.i" +#endif + +static word64 Load64BitBigEndian(const byte* x) +{ +#if defined(BIG_ENDIAN_ORDER) + word64 r = 0; + int i; + + for (i = 0; i < 8; i++) + r |= (word64)x[i] << (8 * i); + + return r; +#else + return *(word64*)x; +#endif +} + +static int InitSha3(Sha3* sha3) +{ + int i; + + for (i = 0; i < 25; i++) + sha3->s[i] = 0; + sha3->i = 0; + + return 0; +} + +static int Sha3Update(Sha3* sha3, const byte* data, word32 len, byte p) +{ + byte i; + byte l; + byte *t; + + if (sha3->i > 0) + { + l = p * 8 - sha3->i; + if (l > len) + l = len; + + t = &sha3->t[sha3->i]; + for (i = 0; i < l; i++) + t[i] = data[i]; + data += i; + len -= i; + sha3->i += i; + + if (sha3->i == p * 8) + { + for (i = 0; i < p; i++) + sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); + BlockSha3(sha3->s); + sha3->i = 0; + } + } + while (len >= p * 8) + { + for (i = 0; i < p; i++) + sha3->s[i] ^= Load64BitBigEndian(data + 8 * i); + BlockSha3(sha3->s); + len -= p * 8; + data += p * 8; + } + for (i = 0; i < len; i++) + sha3->t[i] = data[i]; + sha3->i += i; + + return 0; +} + +static int Sha3Final(Sha3* sha3, byte* hash, byte r, byte l) +{ + byte i; + byte *s8 = (byte *)sha3->s; + + sha3->t[r * 8 - 1] = 0x00; + sha3->t[ sha3->i] = 0x06; + sha3->t[r * 8 - 1] |= 0x80; + for (i=sha3->i + 1; i < r * 8 - 1; i++) + sha3->t[i] = 0; + for (i = 0; i < r; i++) + sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); + BlockSha3(sha3->s); + for (i = 0; i < l; i++) + hash[i] = s8[i]; +#if defined(BIG_ENDIAN_ORDER) + ByteReverseWords64((word64*)hash, (word64*)hash, l); +#endif + + return 0; +} + +static int wc_InitSha3(Sha3* sha3, void* heap, int devId) +{ + int ret = 0; + + if (sha3 == NULL) + return BAD_FUNC_ARG; + + sha3->heap = heap; + ret = InitSha3(sha3); + if (ret != 0) + return ret; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + ret = wolfAsync_DevCtxInit(&sha3->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA3, sha3->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +static int wc_Sha3Update(Sha3* sha3, const byte* data, word32 len, byte p) +{ + int ret = 0; + + if (sha3 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha3(&sha3->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + Sha3Update(sha3, data, len, p); + + return ret; +} + +static int wc_Sha3Final(Sha3* sha3, byte* hash, byte p, byte len) +{ + int ret; + + if (sha3 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha3(&sha3->asyncDev, hash, NULL, + SHA3_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha3Final(sha3, hash, p, len); + if (ret != 0) + return ret; + + return InitSha3(sha3); /* reset state */ +} + +static void wc_Sha3Free(Sha3* sha3) +{ + (void)sha3; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3 == NULL) + return; + + wolfAsync_DevCtxFree(&sha3->asyncDev, WOLFSSL_ASYNC_MARKER_SHA3); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} +#endif /* HAVE_FIPS */ + +static int wc_Sha3Copy(Sha3* src, Sha3* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(Sha3)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif + + return ret; +} + +static int wc_Sha3GetHash(Sha3* sha3, byte* hash, byte p, byte l) +{ + int ret; + Sha3 tmpSha3; + + if (sha3 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha3Copy(sha3, &tmpSha3); + if (ret == 0) { + ret = wc_Sha3Final(&tmpSha3, hash, p, l); + } + return ret; +} + + +WOLFSSL_API int wc_InitSha3_224(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +WOLFSSL_API int wc_Sha3_224_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_224_COUNT); +} + +WOLFSSL_API int wc_Sha3_224_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_224_COUNT, SHA3_224_DIGEST_SIZE); +} + +WOLFSSL_API void wc_Sha3_224_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +WOLFSSL_API int wc_Sha3_224_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_224_COUNT, SHA3_224_DIGEST_SIZE); +} + +WOLFSSL_API int wc_Sha3_224_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +WOLFSSL_API int wc_InitSha3_256(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +WOLFSSL_API int wc_Sha3_256_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_256_COUNT); +} + +WOLFSSL_API int wc_Sha3_256_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_256_COUNT, SHA3_256_DIGEST_SIZE); +} + +WOLFSSL_API void wc_Sha3_256_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +WOLFSSL_API int wc_Sha3_256_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_256_COUNT, SHA3_256_DIGEST_SIZE); +} + +WOLFSSL_API int wc_Sha3_256_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +WOLFSSL_API int wc_InitSha3_384(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +WOLFSSL_API int wc_Sha3_384_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_384_COUNT); +} + +WOLFSSL_API int wc_Sha3_384_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_384_COUNT, SHA3_384_DIGEST_SIZE); +} + +WOLFSSL_API void wc_Sha3_384_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +WOLFSSL_API int wc_Sha3_384_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_384_COUNT, SHA3_384_DIGEST_SIZE); +} + +WOLFSSL_API int wc_Sha3_384_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +WOLFSSL_API int wc_InitSha3_512(Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +WOLFSSL_API int wc_Sha3_512_Update(Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, SHA3_512_COUNT); +} + +WOLFSSL_API int wc_Sha3_512_Final(Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, SHA3_512_COUNT, SHA3_512_DIGEST_SIZE); +} + +WOLFSSL_API void wc_Sha3_512_Free(Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +WOLFSSL_API int wc_Sha3_512_GetHash(Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, SHA3_512_COUNT, SHA3_512_DIGEST_SIZE); +} + +WOLFSSL_API int wc_Sha3_512_Copy(Sha3* src, Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + +#endif /* WOLFSSL_SHA3 */ diff --git a/wolfcrypt/src/sha3_long.i b/wolfcrypt/src/sha3_long.i new file mode 100644 index 000000000..bcf6c91ae --- /dev/null +++ b/wolfcrypt/src/sha3_long.i @@ -0,0 +1,2345 @@ +/* sha_long.i + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/** + * Rotate a 64-bit value left. + * + * @param [in] a The number to rotate left. + * @param [in] r The number od bits to rotate left. + * @return The rotated number. + */ +#define ROTL64(a, n) (((a)<<(n))|((a)>>(64-(n)))) + +/** + * The block operation performed on the state. + * + * @param [in] s The state. + */ +static void BlockSha3(word64 *s) +{ + word64 b[5], t; + + /* Round 0. */ + /* Col Mix */ + b[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; + b[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; + b[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; + b[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; + b[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[5]^=t; s[10]^=t; s[15]^=t; s[20]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[1]^=t; s[6]^=t; s[11]^=t; s[16]^=t; s[21]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[2]^=t; s[7]^=t; s[12]^=t; s[17]^=t; s[22]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[3]^=t; s[8]^=t; s[13]^=t; s[18]^=t; s[23]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[4]^=t; s[9]^=t; s[14]^=t; s[19]^=t; s[24]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[6], 44); + b[2] = ROTL64(s[12], 43); + b[3] = ROTL64(s[18], 21); + b[4] = ROTL64(s[24], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[6] = t12 ^ (b[2] | b[3]); + s[12] = b[2] ^ (b[4] & t34); + s[18] = t34 ^ (b[4] | b[0]); + s[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[3], 28); + b[1] = ROTL64(s[9], 20); + b[2] = ROTL64(s[10], 3); + b[3] = ROTL64(s[16], 45); + b[4] = ROTL64(s[22], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[3] = b[0] ^ (b[2] & t12); + s[9] = t12 ^ (b[2] | b[3]); + s[10] = b[2] ^ (b[4] & t34); + s[16] = t34 ^ (b[4] | b[0]); + s[22] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[1], 1); + b[1] = ROTL64(s[7], 6); + b[2] = ROTL64(s[13], 25); + b[3] = ROTL64(s[19], 8); + b[4] = ROTL64(s[20], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[1] = b[0] ^ (b[2] & t12); + s[7] = t12 ^ (b[2] | b[3]); + s[13] = b[2] ^ (b[4] & t34); + s[19] = t34 ^ (b[4] | b[0]); + s[20] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[4], 27); + b[1] = ROTL64(s[5], 36); + b[2] = ROTL64(s[11], 10); + b[3] = ROTL64(s[17], 15); + b[4] = ROTL64(s[23], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[4] = b[0] ^ (b[2] & t12); + s[5] = t12 ^ (b[2] | b[3]); + s[11] = b[2] ^ (b[4] & t34); + s[17] = t34 ^ (b[4] | b[0]); + s[23] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[2], 62); + b[1] = ROTL64(s[8], 55); + b[2] = ROTL64(s[14], 39); + b[3] = ROTL64(s[15], 41); + b[4] = ROTL64(s[21], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[2] = b[0] ^ (b[2] & t12); + s[8] = t12 ^ (b[2] | b[3]); + s[14] = b[2] ^ (b[4] & t34); + s[15] = t34 ^ (b[4] | b[0]); + s[21] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x1UL; + + /* Round 1. */ + /* Col Mix */ + b[0] = s[0] ^ s[1] ^ s[2] ^ s[3] ^ s[4]; + b[1] = s[5] ^ s[6] ^ s[7] ^ s[8] ^ s[9]; + b[2] = s[10] ^ s[11] ^ s[12] ^ s[13] ^ s[14]; + b[3] = s[15] ^ s[16] ^ s[17] ^ s[18] ^ s[19]; + b[4] = s[20] ^ s[21] ^ s[22] ^ s[23] ^ s[24]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[1]^=t; s[2]^=t; s[3]^=t; s[4]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[5]^=t; s[6]^=t; s[7]^=t; s[8]^=t; s[9]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[10]^=t; s[11]^=t; s[12]^=t; s[13]^=t; s[14]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[15]^=t; s[16]^=t; s[17]^=t; s[18]^=t; s[19]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[20]^=t; s[21]^=t; s[22]^=t; s[23]^=t; s[24]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[9], 44); + b[2] = ROTL64(s[13], 43); + b[3] = ROTL64(s[17], 21); + b[4] = ROTL64(s[21], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[9] = t12 ^ (b[2] | b[3]); + s[13] = b[2] ^ (b[4] & t34); + s[17] = t34 ^ (b[4] | b[0]); + s[21] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[18], 28); + b[1] = ROTL64(s[22], 20); + b[2] = ROTL64(s[1], 3); + b[3] = ROTL64(s[5], 45); + b[4] = ROTL64(s[14], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[18] = b[0] ^ (b[2] & t12); + s[22] = t12 ^ (b[2] | b[3]); + s[1] = b[2] ^ (b[4] & t34); + s[5] = t34 ^ (b[4] | b[0]); + s[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[6], 1); + b[1] = ROTL64(s[10], 6); + b[2] = ROTL64(s[19], 25); + b[3] = ROTL64(s[23], 8); + b[4] = ROTL64(s[2], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[6] = b[0] ^ (b[2] & t12); + s[10] = t12 ^ (b[2] | b[3]); + s[19] = b[2] ^ (b[4] & t34); + s[23] = t34 ^ (b[4] | b[0]); + s[2] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[24], 27); + b[1] = ROTL64(s[3], 36); + b[2] = ROTL64(s[7], 10); + b[3] = ROTL64(s[11], 15); + b[4] = ROTL64(s[15], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[24] = b[0] ^ (b[2] & t12); + s[3] = t12 ^ (b[2] | b[3]); + s[7] = b[2] ^ (b[4] & t34); + s[11] = t34 ^ (b[4] | b[0]); + s[15] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[12], 62); + b[1] = ROTL64(s[16], 55); + b[2] = ROTL64(s[20], 39); + b[3] = ROTL64(s[4], 41); + b[4] = ROTL64(s[8], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[12] = b[0] ^ (b[2] & t12); + s[16] = t12 ^ (b[2] | b[3]); + s[20] = b[2] ^ (b[4] & t34); + s[4] = t34 ^ (b[4] | b[0]); + s[8] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8082UL; + + /* Round 2. */ + /* Col Mix */ + b[0] = s[0] ^ s[6] ^ s[12] ^ s[18] ^ s[24]; + b[1] = s[3] ^ s[9] ^ s[10] ^ s[16] ^ s[22]; + b[2] = s[1] ^ s[7] ^ s[13] ^ s[19] ^ s[20]; + b[3] = s[4] ^ s[5] ^ s[11] ^ s[17] ^ s[23]; + b[4] = s[2] ^ s[8] ^ s[14] ^ s[15] ^ s[21]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[6]^=t; s[12]^=t; s[18]^=t; s[24]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[3]^=t; s[9]^=t; s[10]^=t; s[16]^=t; s[22]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[1]^=t; s[7]^=t; s[13]^=t; s[19]^=t; s[20]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[4]^=t; s[5]^=t; s[11]^=t; s[17]^=t; s[23]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[2]^=t; s[8]^=t; s[14]^=t; s[15]^=t; s[21]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[22], 44); + b[2] = ROTL64(s[19], 43); + b[3] = ROTL64(s[11], 21); + b[4] = ROTL64(s[8], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[22] = t12 ^ (b[2] | b[3]); + s[19] = b[2] ^ (b[4] & t34); + s[11] = t34 ^ (b[4] | b[0]); + s[8] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[17], 28); + b[1] = ROTL64(s[14], 20); + b[2] = ROTL64(s[6], 3); + b[3] = ROTL64(s[3], 45); + b[4] = ROTL64(s[20], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[17] = b[0] ^ (b[2] & t12); + s[14] = t12 ^ (b[2] | b[3]); + s[6] = b[2] ^ (b[4] & t34); + s[3] = t34 ^ (b[4] | b[0]); + s[20] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[9], 1); + b[1] = ROTL64(s[1], 6); + b[2] = ROTL64(s[23], 25); + b[3] = ROTL64(s[15], 8); + b[4] = ROTL64(s[12], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[9] = b[0] ^ (b[2] & t12); + s[1] = t12 ^ (b[2] | b[3]); + s[23] = b[2] ^ (b[4] & t34); + s[15] = t34 ^ (b[4] | b[0]); + s[12] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[21], 27); + b[1] = ROTL64(s[18], 36); + b[2] = ROTL64(s[10], 10); + b[3] = ROTL64(s[7], 15); + b[4] = ROTL64(s[4], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[21] = b[0] ^ (b[2] & t12); + s[18] = t12 ^ (b[2] | b[3]); + s[10] = b[2] ^ (b[4] & t34); + s[7] = t34 ^ (b[4] | b[0]); + s[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[13], 62); + b[1] = ROTL64(s[5], 55); + b[2] = ROTL64(s[2], 39); + b[3] = ROTL64(s[24], 41); + b[4] = ROTL64(s[16], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[13] = b[0] ^ (b[2] & t12); + s[5] = t12 ^ (b[2] | b[3]); + s[2] = b[2] ^ (b[4] & t34); + s[24] = t34 ^ (b[4] | b[0]); + s[16] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x800000000000808aUL; + + /* Round 3. */ + /* Col Mix */ + b[0] = s[0] ^ s[9] ^ s[13] ^ s[17] ^ s[21]; + b[1] = s[1] ^ s[5] ^ s[14] ^ s[18] ^ s[22]; + b[2] = s[2] ^ s[6] ^ s[10] ^ s[19] ^ s[23]; + b[3] = s[3] ^ s[7] ^ s[11] ^ s[15] ^ s[24]; + b[4] = s[4] ^ s[8] ^ s[12] ^ s[16] ^ s[20]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[9]^=t; s[13]^=t; s[17]^=t; s[21]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[1]^=t; s[5]^=t; s[14]^=t; s[18]^=t; s[22]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[2]^=t; s[6]^=t; s[10]^=t; s[19]^=t; s[23]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[3]^=t; s[7]^=t; s[11]^=t; s[15]^=t; s[24]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[4]^=t; s[8]^=t; s[12]^=t; s[16]^=t; s[20]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[14], 44); + b[2] = ROTL64(s[23], 43); + b[3] = ROTL64(s[7], 21); + b[4] = ROTL64(s[16], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[14] = t12 ^ (b[2] | b[3]); + s[23] = b[2] ^ (b[4] & t34); + s[7] = t34 ^ (b[4] | b[0]); + s[16] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[11], 28); + b[1] = ROTL64(s[20], 20); + b[2] = ROTL64(s[9], 3); + b[3] = ROTL64(s[18], 45); + b[4] = ROTL64(s[2], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[11] = b[0] ^ (b[2] & t12); + s[20] = t12 ^ (b[2] | b[3]); + s[9] = b[2] ^ (b[4] & t34); + s[18] = t34 ^ (b[4] | b[0]); + s[2] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[22], 1); + b[1] = ROTL64(s[6], 6); + b[2] = ROTL64(s[15], 25); + b[3] = ROTL64(s[4], 8); + b[4] = ROTL64(s[13], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[22] = b[0] ^ (b[2] & t12); + s[6] = t12 ^ (b[2] | b[3]); + s[15] = b[2] ^ (b[4] & t34); + s[4] = t34 ^ (b[4] | b[0]); + s[13] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[8], 27); + b[1] = ROTL64(s[17], 36); + b[2] = ROTL64(s[1], 10); + b[3] = ROTL64(s[10], 15); + b[4] = ROTL64(s[24], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[8] = b[0] ^ (b[2] & t12); + s[17] = t12 ^ (b[2] | b[3]); + s[1] = b[2] ^ (b[4] & t34); + s[10] = t34 ^ (b[4] | b[0]); + s[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[19], 62); + b[1] = ROTL64(s[3], 55); + b[2] = ROTL64(s[12], 39); + b[3] = ROTL64(s[21], 41); + b[4] = ROTL64(s[5], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[19] = b[0] ^ (b[2] & t12); + s[3] = t12 ^ (b[2] | b[3]); + s[12] = b[2] ^ (b[4] & t34); + s[21] = t34 ^ (b[4] | b[0]); + s[5] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000080008000UL; + + /* Round 4. */ + /* Col Mix */ + b[0] = s[0] ^ s[8] ^ s[11] ^ s[19] ^ s[22]; + b[1] = s[3] ^ s[6] ^ s[14] ^ s[17] ^ s[20]; + b[2] = s[1] ^ s[9] ^ s[12] ^ s[15] ^ s[23]; + b[3] = s[4] ^ s[7] ^ s[10] ^ s[18] ^ s[21]; + b[4] = s[2] ^ s[5] ^ s[13] ^ s[16] ^ s[24]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[8]^=t; s[11]^=t; s[19]^=t; s[22]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[3]^=t; s[6]^=t; s[14]^=t; s[17]^=t; s[20]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[1]^=t; s[9]^=t; s[12]^=t; s[15]^=t; s[23]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[4]^=t; s[7]^=t; s[10]^=t; s[18]^=t; s[21]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[2]^=t; s[5]^=t; s[13]^=t; s[16]^=t; s[24]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[20], 44); + b[2] = ROTL64(s[15], 43); + b[3] = ROTL64(s[10], 21); + b[4] = ROTL64(s[5], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[20] = t12 ^ (b[2] | b[3]); + s[15] = b[2] ^ (b[4] & t34); + s[10] = t34 ^ (b[4] | b[0]); + s[5] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[7], 28); + b[1] = ROTL64(s[2], 20); + b[2] = ROTL64(s[22], 3); + b[3] = ROTL64(s[17], 45); + b[4] = ROTL64(s[12], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[7] = b[0] ^ (b[2] & t12); + s[2] = t12 ^ (b[2] | b[3]); + s[22] = b[2] ^ (b[4] & t34); + s[17] = t34 ^ (b[4] | b[0]); + s[12] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[14], 1); + b[1] = ROTL64(s[9], 6); + b[2] = ROTL64(s[4], 25); + b[3] = ROTL64(s[24], 8); + b[4] = ROTL64(s[19], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[14] = b[0] ^ (b[2] & t12); + s[9] = t12 ^ (b[2] | b[3]); + s[4] = b[2] ^ (b[4] & t34); + s[24] = t34 ^ (b[4] | b[0]); + s[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[16], 27); + b[1] = ROTL64(s[11], 36); + b[2] = ROTL64(s[6], 10); + b[3] = ROTL64(s[1], 15); + b[4] = ROTL64(s[21], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[16] = b[0] ^ (b[2] & t12); + s[11] = t12 ^ (b[2] | b[3]); + s[6] = b[2] ^ (b[4] & t34); + s[1] = t34 ^ (b[4] | b[0]); + s[21] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[23], 62); + b[1] = ROTL64(s[18], 55); + b[2] = ROTL64(s[13], 39); + b[3] = ROTL64(s[8], 41); + b[4] = ROTL64(s[3], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[23] = b[0] ^ (b[2] & t12); + s[18] = t12 ^ (b[2] | b[3]); + s[13] = b[2] ^ (b[4] & t34); + s[8] = t34 ^ (b[4] | b[0]); + s[3] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x808bUL; + + /* Round 5. */ + /* Col Mix */ + b[0] = s[0] ^ s[7] ^ s[14] ^ s[16] ^ s[23]; + b[1] = s[2] ^ s[9] ^ s[11] ^ s[18] ^ s[20]; + b[2] = s[4] ^ s[6] ^ s[13] ^ s[15] ^ s[22]; + b[3] = s[1] ^ s[8] ^ s[10] ^ s[17] ^ s[24]; + b[4] = s[3] ^ s[5] ^ s[12] ^ s[19] ^ s[21]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[7]^=t; s[14]^=t; s[16]^=t; s[23]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[2]^=t; s[9]^=t; s[11]^=t; s[18]^=t; s[20]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[4]^=t; s[6]^=t; s[13]^=t; s[15]^=t; s[22]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[1]^=t; s[8]^=t; s[10]^=t; s[17]^=t; s[24]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[3]^=t; s[5]^=t; s[12]^=t; s[19]^=t; s[21]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[2], 44); + b[2] = ROTL64(s[4], 43); + b[3] = ROTL64(s[1], 21); + b[4] = ROTL64(s[3], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[2] = t12 ^ (b[2] | b[3]); + s[4] = b[2] ^ (b[4] & t34); + s[1] = t34 ^ (b[4] | b[0]); + s[3] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[10], 28); + b[1] = ROTL64(s[12], 20); + b[2] = ROTL64(s[14], 3); + b[3] = ROTL64(s[11], 45); + b[4] = ROTL64(s[13], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[10] = b[0] ^ (b[2] & t12); + s[12] = t12 ^ (b[2] | b[3]); + s[14] = b[2] ^ (b[4] & t34); + s[11] = t34 ^ (b[4] | b[0]); + s[13] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[20], 1); + b[1] = ROTL64(s[22], 6); + b[2] = ROTL64(s[24], 25); + b[3] = ROTL64(s[21], 8); + b[4] = ROTL64(s[23], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[20] = b[0] ^ (b[2] & t12); + s[22] = t12 ^ (b[2] | b[3]); + s[24] = b[2] ^ (b[4] & t34); + s[21] = t34 ^ (b[4] | b[0]); + s[23] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[5], 27); + b[1] = ROTL64(s[7], 36); + b[2] = ROTL64(s[9], 10); + b[3] = ROTL64(s[6], 15); + b[4] = ROTL64(s[8], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[5] = b[0] ^ (b[2] & t12); + s[7] = t12 ^ (b[2] | b[3]); + s[9] = b[2] ^ (b[4] & t34); + s[6] = t34 ^ (b[4] | b[0]); + s[8] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[15], 62); + b[1] = ROTL64(s[17], 55); + b[2] = ROTL64(s[19], 39); + b[3] = ROTL64(s[16], 41); + b[4] = ROTL64(s[18], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[15] = b[0] ^ (b[2] & t12); + s[17] = t12 ^ (b[2] | b[3]); + s[19] = b[2] ^ (b[4] & t34); + s[16] = t34 ^ (b[4] | b[0]); + s[18] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x80000001UL; + + /* Round 6. */ + /* Col Mix */ + b[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; + b[1] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; + b[2] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; + b[3] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; + b[4] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[5]^=t; s[10]^=t; s[15]^=t; s[20]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[2]^=t; s[7]^=t; s[12]^=t; s[17]^=t; s[22]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[4]^=t; s[9]^=t; s[14]^=t; s[19]^=t; s[24]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[1]^=t; s[6]^=t; s[11]^=t; s[16]^=t; s[21]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[3]^=t; s[8]^=t; s[13]^=t; s[18]^=t; s[23]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[12], 44); + b[2] = ROTL64(s[24], 43); + b[3] = ROTL64(s[6], 21); + b[4] = ROTL64(s[18], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[12] = t12 ^ (b[2] | b[3]); + s[24] = b[2] ^ (b[4] & t34); + s[6] = t34 ^ (b[4] | b[0]); + s[18] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[1], 28); + b[1] = ROTL64(s[13], 20); + b[2] = ROTL64(s[20], 3); + b[3] = ROTL64(s[7], 45); + b[4] = ROTL64(s[19], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[1] = b[0] ^ (b[2] & t12); + s[13] = t12 ^ (b[2] | b[3]); + s[20] = b[2] ^ (b[4] & t34); + s[7] = t34 ^ (b[4] | b[0]); + s[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[2], 1); + b[1] = ROTL64(s[14], 6); + b[2] = ROTL64(s[21], 25); + b[3] = ROTL64(s[8], 8); + b[4] = ROTL64(s[15], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[2] = b[0] ^ (b[2] & t12); + s[14] = t12 ^ (b[2] | b[3]); + s[21] = b[2] ^ (b[4] & t34); + s[8] = t34 ^ (b[4] | b[0]); + s[15] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[3], 27); + b[1] = ROTL64(s[10], 36); + b[2] = ROTL64(s[22], 10); + b[3] = ROTL64(s[9], 15); + b[4] = ROTL64(s[16], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[3] = b[0] ^ (b[2] & t12); + s[10] = t12 ^ (b[2] | b[3]); + s[22] = b[2] ^ (b[4] & t34); + s[9] = t34 ^ (b[4] | b[0]); + s[16] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[4], 62); + b[1] = ROTL64(s[11], 55); + b[2] = ROTL64(s[23], 39); + b[3] = ROTL64(s[5], 41); + b[4] = ROTL64(s[17], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[4] = b[0] ^ (b[2] & t12); + s[11] = t12 ^ (b[2] | b[3]); + s[23] = b[2] ^ (b[4] & t34); + s[5] = t34 ^ (b[4] | b[0]); + s[17] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000080008081UL; + + /* Round 7. */ + /* Col Mix */ + b[0] = s[0] ^ s[1] ^ s[2] ^ s[3] ^ s[4]; + b[1] = s[10] ^ s[11] ^ s[12] ^ s[13] ^ s[14]; + b[2] = s[20] ^ s[21] ^ s[22] ^ s[23] ^ s[24]; + b[3] = s[5] ^ s[6] ^ s[7] ^ s[8] ^ s[9]; + b[4] = s[15] ^ s[16] ^ s[17] ^ s[18] ^ s[19]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[1]^=t; s[2]^=t; s[3]^=t; s[4]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[10]^=t; s[11]^=t; s[12]^=t; s[13]^=t; s[14]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[20]^=t; s[21]^=t; s[22]^=t; s[23]^=t; s[24]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[5]^=t; s[6]^=t; s[7]^=t; s[8]^=t; s[9]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[15]^=t; s[16]^=t; s[17]^=t; s[18]^=t; s[19]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[13], 44); + b[2] = ROTL64(s[21], 43); + b[3] = ROTL64(s[9], 21); + b[4] = ROTL64(s[17], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[13] = t12 ^ (b[2] | b[3]); + s[21] = b[2] ^ (b[4] & t34); + s[9] = t34 ^ (b[4] | b[0]); + s[17] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[6], 28); + b[1] = ROTL64(s[19], 20); + b[2] = ROTL64(s[2], 3); + b[3] = ROTL64(s[10], 45); + b[4] = ROTL64(s[23], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[6] = b[0] ^ (b[2] & t12); + s[19] = t12 ^ (b[2] | b[3]); + s[2] = b[2] ^ (b[4] & t34); + s[10] = t34 ^ (b[4] | b[0]); + s[23] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[12], 1); + b[1] = ROTL64(s[20], 6); + b[2] = ROTL64(s[8], 25); + b[3] = ROTL64(s[16], 8); + b[4] = ROTL64(s[4], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[12] = b[0] ^ (b[2] & t12); + s[20] = t12 ^ (b[2] | b[3]); + s[8] = b[2] ^ (b[4] & t34); + s[16] = t34 ^ (b[4] | b[0]); + s[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[18], 27); + b[1] = ROTL64(s[1], 36); + b[2] = ROTL64(s[14], 10); + b[3] = ROTL64(s[22], 15); + b[4] = ROTL64(s[5], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[18] = b[0] ^ (b[2] & t12); + s[1] = t12 ^ (b[2] | b[3]); + s[14] = b[2] ^ (b[4] & t34); + s[22] = t34 ^ (b[4] | b[0]); + s[5] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[24], 62); + b[1] = ROTL64(s[7], 55); + b[2] = ROTL64(s[15], 39); + b[3] = ROTL64(s[3], 41); + b[4] = ROTL64(s[11], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[24] = b[0] ^ (b[2] & t12); + s[7] = t12 ^ (b[2] | b[3]); + s[15] = b[2] ^ (b[4] & t34); + s[3] = t34 ^ (b[4] | b[0]); + s[11] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000008009UL; + + /* Round 8. */ + /* Col Mix */ + b[0] = s[0] ^ s[6] ^ s[12] ^ s[18] ^ s[24]; + b[1] = s[1] ^ s[7] ^ s[13] ^ s[19] ^ s[20]; + b[2] = s[2] ^ s[8] ^ s[14] ^ s[15] ^ s[21]; + b[3] = s[3] ^ s[9] ^ s[10] ^ s[16] ^ s[22]; + b[4] = s[4] ^ s[5] ^ s[11] ^ s[17] ^ s[23]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[6]^=t; s[12]^=t; s[18]^=t; s[24]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[1]^=t; s[7]^=t; s[13]^=t; s[19]^=t; s[20]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[2]^=t; s[8]^=t; s[14]^=t; s[15]^=t; s[21]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[3]^=t; s[9]^=t; s[10]^=t; s[16]^=t; s[22]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[4]^=t; s[5]^=t; s[11]^=t; s[17]^=t; s[23]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[19], 44); + b[2] = ROTL64(s[8], 43); + b[3] = ROTL64(s[22], 21); + b[4] = ROTL64(s[11], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[19] = t12 ^ (b[2] | b[3]); + s[8] = b[2] ^ (b[4] & t34); + s[22] = t34 ^ (b[4] | b[0]); + s[11] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[9], 28); + b[1] = ROTL64(s[23], 20); + b[2] = ROTL64(s[12], 3); + b[3] = ROTL64(s[1], 45); + b[4] = ROTL64(s[15], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[9] = b[0] ^ (b[2] & t12); + s[23] = t12 ^ (b[2] | b[3]); + s[12] = b[2] ^ (b[4] & t34); + s[1] = t34 ^ (b[4] | b[0]); + s[15] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[13], 1); + b[1] = ROTL64(s[2], 6); + b[2] = ROTL64(s[16], 25); + b[3] = ROTL64(s[5], 8); + b[4] = ROTL64(s[24], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[13] = b[0] ^ (b[2] & t12); + s[2] = t12 ^ (b[2] | b[3]); + s[16] = b[2] ^ (b[4] & t34); + s[5] = t34 ^ (b[4] | b[0]); + s[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[17], 27); + b[1] = ROTL64(s[6], 36); + b[2] = ROTL64(s[20], 10); + b[3] = ROTL64(s[14], 15); + b[4] = ROTL64(s[3], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[17] = b[0] ^ (b[2] & t12); + s[6] = t12 ^ (b[2] | b[3]); + s[20] = b[2] ^ (b[4] & t34); + s[14] = t34 ^ (b[4] | b[0]); + s[3] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[21], 62); + b[1] = ROTL64(s[10], 55); + b[2] = ROTL64(s[4], 39); + b[3] = ROTL64(s[18], 41); + b[4] = ROTL64(s[7], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[21] = b[0] ^ (b[2] & t12); + s[10] = t12 ^ (b[2] | b[3]); + s[4] = b[2] ^ (b[4] & t34); + s[18] = t34 ^ (b[4] | b[0]); + s[7] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8aUL; + + /* Round 9. */ + /* Col Mix */ + b[0] = s[0] ^ s[9] ^ s[13] ^ s[17] ^ s[21]; + b[1] = s[2] ^ s[6] ^ s[10] ^ s[19] ^ s[23]; + b[2] = s[4] ^ s[8] ^ s[12] ^ s[16] ^ s[20]; + b[3] = s[1] ^ s[5] ^ s[14] ^ s[18] ^ s[22]; + b[4] = s[3] ^ s[7] ^ s[11] ^ s[15] ^ s[24]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[9]^=t; s[13]^=t; s[17]^=t; s[21]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[2]^=t; s[6]^=t; s[10]^=t; s[19]^=t; s[23]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[4]^=t; s[8]^=t; s[12]^=t; s[16]^=t; s[20]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[1]^=t; s[5]^=t; s[14]^=t; s[18]^=t; s[22]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[3]^=t; s[7]^=t; s[11]^=t; s[15]^=t; s[24]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[23], 44); + b[2] = ROTL64(s[16], 43); + b[3] = ROTL64(s[14], 21); + b[4] = ROTL64(s[7], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[23] = t12 ^ (b[2] | b[3]); + s[16] = b[2] ^ (b[4] & t34); + s[14] = t34 ^ (b[4] | b[0]); + s[7] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[22], 28); + b[1] = ROTL64(s[15], 20); + b[2] = ROTL64(s[13], 3); + b[3] = ROTL64(s[6], 45); + b[4] = ROTL64(s[4], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[22] = b[0] ^ (b[2] & t12); + s[15] = t12 ^ (b[2] | b[3]); + s[13] = b[2] ^ (b[4] & t34); + s[6] = t34 ^ (b[4] | b[0]); + s[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[19], 1); + b[1] = ROTL64(s[12], 6); + b[2] = ROTL64(s[5], 25); + b[3] = ROTL64(s[3], 8); + b[4] = ROTL64(s[21], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[19] = b[0] ^ (b[2] & t12); + s[12] = t12 ^ (b[2] | b[3]); + s[5] = b[2] ^ (b[4] & t34); + s[3] = t34 ^ (b[4] | b[0]); + s[21] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[11], 27); + b[1] = ROTL64(s[9], 36); + b[2] = ROTL64(s[2], 10); + b[3] = ROTL64(s[20], 15); + b[4] = ROTL64(s[18], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[11] = b[0] ^ (b[2] & t12); + s[9] = t12 ^ (b[2] | b[3]); + s[2] = b[2] ^ (b[4] & t34); + s[20] = t34 ^ (b[4] | b[0]); + s[18] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[8], 62); + b[1] = ROTL64(s[1], 55); + b[2] = ROTL64(s[24], 39); + b[3] = ROTL64(s[17], 41); + b[4] = ROTL64(s[10], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[8] = b[0] ^ (b[2] & t12); + s[1] = t12 ^ (b[2] | b[3]); + s[24] = b[2] ^ (b[4] & t34); + s[17] = t34 ^ (b[4] | b[0]); + s[10] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x88UL; + + /* Round 10. */ + /* Col Mix */ + b[0] = s[0] ^ s[8] ^ s[11] ^ s[19] ^ s[22]; + b[1] = s[1] ^ s[9] ^ s[12] ^ s[15] ^ s[23]; + b[2] = s[2] ^ s[5] ^ s[13] ^ s[16] ^ s[24]; + b[3] = s[3] ^ s[6] ^ s[14] ^ s[17] ^ s[20]; + b[4] = s[4] ^ s[7] ^ s[10] ^ s[18] ^ s[21]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[8]^=t; s[11]^=t; s[19]^=t; s[22]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[1]^=t; s[9]^=t; s[12]^=t; s[15]^=t; s[23]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[2]^=t; s[5]^=t; s[13]^=t; s[16]^=t; s[24]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[3]^=t; s[6]^=t; s[14]^=t; s[17]^=t; s[20]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[4]^=t; s[7]^=t; s[10]^=t; s[18]^=t; s[21]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[15], 44); + b[2] = ROTL64(s[5], 43); + b[3] = ROTL64(s[20], 21); + b[4] = ROTL64(s[10], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[15] = t12 ^ (b[2] | b[3]); + s[5] = b[2] ^ (b[4] & t34); + s[20] = t34 ^ (b[4] | b[0]); + s[10] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[14], 28); + b[1] = ROTL64(s[4], 20); + b[2] = ROTL64(s[19], 3); + b[3] = ROTL64(s[9], 45); + b[4] = ROTL64(s[24], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[14] = b[0] ^ (b[2] & t12); + s[4] = t12 ^ (b[2] | b[3]); + s[19] = b[2] ^ (b[4] & t34); + s[9] = t34 ^ (b[4] | b[0]); + s[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[23], 1); + b[1] = ROTL64(s[13], 6); + b[2] = ROTL64(s[3], 25); + b[3] = ROTL64(s[18], 8); + b[4] = ROTL64(s[8], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[23] = b[0] ^ (b[2] & t12); + s[13] = t12 ^ (b[2] | b[3]); + s[3] = b[2] ^ (b[4] & t34); + s[18] = t34 ^ (b[4] | b[0]); + s[8] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[7], 27); + b[1] = ROTL64(s[22], 36); + b[2] = ROTL64(s[12], 10); + b[3] = ROTL64(s[2], 15); + b[4] = ROTL64(s[17], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[7] = b[0] ^ (b[2] & t12); + s[22] = t12 ^ (b[2] | b[3]); + s[12] = b[2] ^ (b[4] & t34); + s[2] = t34 ^ (b[4] | b[0]); + s[17] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[16], 62); + b[1] = ROTL64(s[6], 55); + b[2] = ROTL64(s[21], 39); + b[3] = ROTL64(s[11], 41); + b[4] = ROTL64(s[1], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[16] = b[0] ^ (b[2] & t12); + s[6] = t12 ^ (b[2] | b[3]); + s[21] = b[2] ^ (b[4] & t34); + s[11] = t34 ^ (b[4] | b[0]); + s[1] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x80008009UL; + + /* Round 11. */ + /* Col Mix */ + b[0] = s[0] ^ s[7] ^ s[14] ^ s[16] ^ s[23]; + b[1] = s[4] ^ s[6] ^ s[13] ^ s[15] ^ s[22]; + b[2] = s[3] ^ s[5] ^ s[12] ^ s[19] ^ s[21]; + b[3] = s[2] ^ s[9] ^ s[11] ^ s[18] ^ s[20]; + b[4] = s[1] ^ s[8] ^ s[10] ^ s[17] ^ s[24]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[7]^=t; s[14]^=t; s[16]^=t; s[23]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[4]^=t; s[6]^=t; s[13]^=t; s[15]^=t; s[22]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[3]^=t; s[5]^=t; s[12]^=t; s[19]^=t; s[21]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[2]^=t; s[9]^=t; s[11]^=t; s[18]^=t; s[20]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[1]^=t; s[8]^=t; s[10]^=t; s[17]^=t; s[24]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[4], 44); + b[2] = ROTL64(s[3], 43); + b[3] = ROTL64(s[2], 21); + b[4] = ROTL64(s[1], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[4] = t12 ^ (b[2] | b[3]); + s[3] = b[2] ^ (b[4] & t34); + s[2] = t34 ^ (b[4] | b[0]); + s[1] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[20], 28); + b[1] = ROTL64(s[24], 20); + b[2] = ROTL64(s[23], 3); + b[3] = ROTL64(s[22], 45); + b[4] = ROTL64(s[21], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[20] = b[0] ^ (b[2] & t12); + s[24] = t12 ^ (b[2] | b[3]); + s[23] = b[2] ^ (b[4] & t34); + s[22] = t34 ^ (b[4] | b[0]); + s[21] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[15], 1); + b[1] = ROTL64(s[19], 6); + b[2] = ROTL64(s[18], 25); + b[3] = ROTL64(s[17], 8); + b[4] = ROTL64(s[16], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[15] = b[0] ^ (b[2] & t12); + s[19] = t12 ^ (b[2] | b[3]); + s[18] = b[2] ^ (b[4] & t34); + s[17] = t34 ^ (b[4] | b[0]); + s[16] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[10], 27); + b[1] = ROTL64(s[14], 36); + b[2] = ROTL64(s[13], 10); + b[3] = ROTL64(s[12], 15); + b[4] = ROTL64(s[11], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[10] = b[0] ^ (b[2] & t12); + s[14] = t12 ^ (b[2] | b[3]); + s[13] = b[2] ^ (b[4] & t34); + s[12] = t34 ^ (b[4] | b[0]); + s[11] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[5], 62); + b[1] = ROTL64(s[9], 55); + b[2] = ROTL64(s[8], 39); + b[3] = ROTL64(s[7], 41); + b[4] = ROTL64(s[6], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[5] = b[0] ^ (b[2] & t12); + s[9] = t12 ^ (b[2] | b[3]); + s[8] = b[2] ^ (b[4] & t34); + s[7] = t34 ^ (b[4] | b[0]); + s[6] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000aUL; + + /* Round 12. */ + /* Col Mix */ + b[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; + b[1] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; + b[2] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; + b[3] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; + b[4] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[5]^=t; s[10]^=t; s[15]^=t; s[20]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[4]^=t; s[9]^=t; s[14]^=t; s[19]^=t; s[24]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[3]^=t; s[8]^=t; s[13]^=t; s[18]^=t; s[23]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[2]^=t; s[7]^=t; s[12]^=t; s[17]^=t; s[22]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[1]^=t; s[6]^=t; s[11]^=t; s[16]^=t; s[21]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[24], 44); + b[2] = ROTL64(s[18], 43); + b[3] = ROTL64(s[12], 21); + b[4] = ROTL64(s[6], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[24] = t12 ^ (b[2] | b[3]); + s[18] = b[2] ^ (b[4] & t34); + s[12] = t34 ^ (b[4] | b[0]); + s[6] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[2], 28); + b[1] = ROTL64(s[21], 20); + b[2] = ROTL64(s[15], 3); + b[3] = ROTL64(s[14], 45); + b[4] = ROTL64(s[8], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[2] = b[0] ^ (b[2] & t12); + s[21] = t12 ^ (b[2] | b[3]); + s[15] = b[2] ^ (b[4] & t34); + s[14] = t34 ^ (b[4] | b[0]); + s[8] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[4], 1); + b[1] = ROTL64(s[23], 6); + b[2] = ROTL64(s[17], 25); + b[3] = ROTL64(s[11], 8); + b[4] = ROTL64(s[5], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[4] = b[0] ^ (b[2] & t12); + s[23] = t12 ^ (b[2] | b[3]); + s[17] = b[2] ^ (b[4] & t34); + s[11] = t34 ^ (b[4] | b[0]); + s[5] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[1], 27); + b[1] = ROTL64(s[20], 36); + b[2] = ROTL64(s[19], 10); + b[3] = ROTL64(s[13], 15); + b[4] = ROTL64(s[7], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[1] = b[0] ^ (b[2] & t12); + s[20] = t12 ^ (b[2] | b[3]); + s[19] = b[2] ^ (b[4] & t34); + s[13] = t34 ^ (b[4] | b[0]); + s[7] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[3], 62); + b[1] = ROTL64(s[22], 55); + b[2] = ROTL64(s[16], 39); + b[3] = ROTL64(s[10], 41); + b[4] = ROTL64(s[9], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[3] = b[0] ^ (b[2] & t12); + s[22] = t12 ^ (b[2] | b[3]); + s[16] = b[2] ^ (b[4] & t34); + s[10] = t34 ^ (b[4] | b[0]); + s[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000808bUL; + + /* Round 13. */ + /* Col Mix */ + b[0] = s[0] ^ s[1] ^ s[2] ^ s[3] ^ s[4]; + b[1] = s[20] ^ s[21] ^ s[22] ^ s[23] ^ s[24]; + b[2] = s[15] ^ s[16] ^ s[17] ^ s[18] ^ s[19]; + b[3] = s[10] ^ s[11] ^ s[12] ^ s[13] ^ s[14]; + b[4] = s[5] ^ s[6] ^ s[7] ^ s[8] ^ s[9]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[1]^=t; s[2]^=t; s[3]^=t; s[4]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[20]^=t; s[21]^=t; s[22]^=t; s[23]^=t; s[24]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[15]^=t; s[16]^=t; s[17]^=t; s[18]^=t; s[19]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[10]^=t; s[11]^=t; s[12]^=t; s[13]^=t; s[14]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[5]^=t; s[6]^=t; s[7]^=t; s[8]^=t; s[9]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[21], 44); + b[2] = ROTL64(s[17], 43); + b[3] = ROTL64(s[13], 21); + b[4] = ROTL64(s[9], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[21] = t12 ^ (b[2] | b[3]); + s[17] = b[2] ^ (b[4] & t34); + s[13] = t34 ^ (b[4] | b[0]); + s[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[12], 28); + b[1] = ROTL64(s[8], 20); + b[2] = ROTL64(s[4], 3); + b[3] = ROTL64(s[20], 45); + b[4] = ROTL64(s[16], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[12] = b[0] ^ (b[2] & t12); + s[8] = t12 ^ (b[2] | b[3]); + s[4] = b[2] ^ (b[4] & t34); + s[20] = t34 ^ (b[4] | b[0]); + s[16] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[24], 1); + b[1] = ROTL64(s[15], 6); + b[2] = ROTL64(s[11], 25); + b[3] = ROTL64(s[7], 8); + b[4] = ROTL64(s[3], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[24] = b[0] ^ (b[2] & t12); + s[15] = t12 ^ (b[2] | b[3]); + s[11] = b[2] ^ (b[4] & t34); + s[7] = t34 ^ (b[4] | b[0]); + s[3] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[6], 27); + b[1] = ROTL64(s[2], 36); + b[2] = ROTL64(s[23], 10); + b[3] = ROTL64(s[19], 15); + b[4] = ROTL64(s[10], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[6] = b[0] ^ (b[2] & t12); + s[2] = t12 ^ (b[2] | b[3]); + s[23] = b[2] ^ (b[4] & t34); + s[19] = t34 ^ (b[4] | b[0]); + s[10] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[18], 62); + b[1] = ROTL64(s[14], 55); + b[2] = ROTL64(s[5], 39); + b[3] = ROTL64(s[1], 41); + b[4] = ROTL64(s[22], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[18] = b[0] ^ (b[2] & t12); + s[14] = t12 ^ (b[2] | b[3]); + s[5] = b[2] ^ (b[4] & t34); + s[1] = t34 ^ (b[4] | b[0]); + s[22] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x800000000000008bUL; + + /* Round 14. */ + /* Col Mix */ + b[0] = s[0] ^ s[6] ^ s[12] ^ s[18] ^ s[24]; + b[1] = s[2] ^ s[8] ^ s[14] ^ s[15] ^ s[21]; + b[2] = s[4] ^ s[5] ^ s[11] ^ s[17] ^ s[23]; + b[3] = s[1] ^ s[7] ^ s[13] ^ s[19] ^ s[20]; + b[4] = s[3] ^ s[9] ^ s[10] ^ s[16] ^ s[22]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[6]^=t; s[12]^=t; s[18]^=t; s[24]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[2]^=t; s[8]^=t; s[14]^=t; s[15]^=t; s[21]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[4]^=t; s[5]^=t; s[11]^=t; s[17]^=t; s[23]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[1]^=t; s[7]^=t; s[13]^=t; s[19]^=t; s[20]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[3]^=t; s[9]^=t; s[10]^=t; s[16]^=t; s[22]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[8], 44); + b[2] = ROTL64(s[11], 43); + b[3] = ROTL64(s[19], 21); + b[4] = ROTL64(s[22], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[8] = t12 ^ (b[2] | b[3]); + s[11] = b[2] ^ (b[4] & t34); + s[19] = t34 ^ (b[4] | b[0]); + s[22] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[13], 28); + b[1] = ROTL64(s[16], 20); + b[2] = ROTL64(s[24], 3); + b[3] = ROTL64(s[2], 45); + b[4] = ROTL64(s[5], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[13] = b[0] ^ (b[2] & t12); + s[16] = t12 ^ (b[2] | b[3]); + s[24] = b[2] ^ (b[4] & t34); + s[2] = t34 ^ (b[4] | b[0]); + s[5] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[21], 1); + b[1] = ROTL64(s[4], 6); + b[2] = ROTL64(s[7], 25); + b[3] = ROTL64(s[10], 8); + b[4] = ROTL64(s[18], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[21] = b[0] ^ (b[2] & t12); + s[4] = t12 ^ (b[2] | b[3]); + s[7] = b[2] ^ (b[4] & t34); + s[10] = t34 ^ (b[4] | b[0]); + s[18] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[9], 27); + b[1] = ROTL64(s[12], 36); + b[2] = ROTL64(s[15], 10); + b[3] = ROTL64(s[23], 15); + b[4] = ROTL64(s[1], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[9] = b[0] ^ (b[2] & t12); + s[12] = t12 ^ (b[2] | b[3]); + s[15] = b[2] ^ (b[4] & t34); + s[23] = t34 ^ (b[4] | b[0]); + s[1] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[17], 62); + b[1] = ROTL64(s[20], 55); + b[2] = ROTL64(s[3], 39); + b[3] = ROTL64(s[6], 41); + b[4] = ROTL64(s[14], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[17] = b[0] ^ (b[2] & t12); + s[20] = t12 ^ (b[2] | b[3]); + s[3] = b[2] ^ (b[4] & t34); + s[6] = t34 ^ (b[4] | b[0]); + s[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000008089UL; + + /* Round 15. */ + /* Col Mix */ + b[0] = s[0] ^ s[9] ^ s[13] ^ s[17] ^ s[21]; + b[1] = s[4] ^ s[8] ^ s[12] ^ s[16] ^ s[20]; + b[2] = s[3] ^ s[7] ^ s[11] ^ s[15] ^ s[24]; + b[3] = s[2] ^ s[6] ^ s[10] ^ s[19] ^ s[23]; + b[4] = s[1] ^ s[5] ^ s[14] ^ s[18] ^ s[22]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[9]^=t; s[13]^=t; s[17]^=t; s[21]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[4]^=t; s[8]^=t; s[12]^=t; s[16]^=t; s[20]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[3]^=t; s[7]^=t; s[11]^=t; s[15]^=t; s[24]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[2]^=t; s[6]^=t; s[10]^=t; s[19]^=t; s[23]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[1]^=t; s[5]^=t; s[14]^=t; s[18]^=t; s[22]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[16], 44); + b[2] = ROTL64(s[7], 43); + b[3] = ROTL64(s[23], 21); + b[4] = ROTL64(s[14], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[16] = t12 ^ (b[2] | b[3]); + s[7] = b[2] ^ (b[4] & t34); + s[23] = t34 ^ (b[4] | b[0]); + s[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[19], 28); + b[1] = ROTL64(s[5], 20); + b[2] = ROTL64(s[21], 3); + b[3] = ROTL64(s[12], 45); + b[4] = ROTL64(s[3], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[19] = b[0] ^ (b[2] & t12); + s[5] = t12 ^ (b[2] | b[3]); + s[21] = b[2] ^ (b[4] & t34); + s[12] = t34 ^ (b[4] | b[0]); + s[3] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[8], 1); + b[1] = ROTL64(s[24], 6); + b[2] = ROTL64(s[10], 25); + b[3] = ROTL64(s[1], 8); + b[4] = ROTL64(s[17], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[8] = b[0] ^ (b[2] & t12); + s[24] = t12 ^ (b[2] | b[3]); + s[10] = b[2] ^ (b[4] & t34); + s[1] = t34 ^ (b[4] | b[0]); + s[17] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[22], 27); + b[1] = ROTL64(s[13], 36); + b[2] = ROTL64(s[4], 10); + b[3] = ROTL64(s[15], 15); + b[4] = ROTL64(s[6], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[22] = b[0] ^ (b[2] & t12); + s[13] = t12 ^ (b[2] | b[3]); + s[4] = b[2] ^ (b[4] & t34); + s[15] = t34 ^ (b[4] | b[0]); + s[6] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[11], 62); + b[1] = ROTL64(s[2], 55); + b[2] = ROTL64(s[18], 39); + b[3] = ROTL64(s[9], 41); + b[4] = ROTL64(s[20], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[11] = b[0] ^ (b[2] & t12); + s[2] = t12 ^ (b[2] | b[3]); + s[18] = b[2] ^ (b[4] & t34); + s[9] = t34 ^ (b[4] | b[0]); + s[20] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000008003UL; + + /* Round 16. */ + /* Col Mix */ + b[0] = s[0] ^ s[8] ^ s[11] ^ s[19] ^ s[22]; + b[1] = s[2] ^ s[5] ^ s[13] ^ s[16] ^ s[24]; + b[2] = s[4] ^ s[7] ^ s[10] ^ s[18] ^ s[21]; + b[3] = s[1] ^ s[9] ^ s[12] ^ s[15] ^ s[23]; + b[4] = s[3] ^ s[6] ^ s[14] ^ s[17] ^ s[20]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[8]^=t; s[11]^=t; s[19]^=t; s[22]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[2]^=t; s[5]^=t; s[13]^=t; s[16]^=t; s[24]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[4]^=t; s[7]^=t; s[10]^=t; s[18]^=t; s[21]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[1]^=t; s[9]^=t; s[12]^=t; s[15]^=t; s[23]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[3]^=t; s[6]^=t; s[14]^=t; s[17]^=t; s[20]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[5], 44); + b[2] = ROTL64(s[10], 43); + b[3] = ROTL64(s[15], 21); + b[4] = ROTL64(s[20], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[5] = t12 ^ (b[2] | b[3]); + s[10] = b[2] ^ (b[4] & t34); + s[15] = t34 ^ (b[4] | b[0]); + s[20] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[23], 28); + b[1] = ROTL64(s[3], 20); + b[2] = ROTL64(s[8], 3); + b[3] = ROTL64(s[13], 45); + b[4] = ROTL64(s[18], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[23] = b[0] ^ (b[2] & t12); + s[3] = t12 ^ (b[2] | b[3]); + s[8] = b[2] ^ (b[4] & t34); + s[13] = t34 ^ (b[4] | b[0]); + s[18] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[16], 1); + b[1] = ROTL64(s[21], 6); + b[2] = ROTL64(s[1], 25); + b[3] = ROTL64(s[6], 8); + b[4] = ROTL64(s[11], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[16] = b[0] ^ (b[2] & t12); + s[21] = t12 ^ (b[2] | b[3]); + s[1] = b[2] ^ (b[4] & t34); + s[6] = t34 ^ (b[4] | b[0]); + s[11] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[14], 27); + b[1] = ROTL64(s[19], 36); + b[2] = ROTL64(s[24], 10); + b[3] = ROTL64(s[4], 15); + b[4] = ROTL64(s[9], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[14] = b[0] ^ (b[2] & t12); + s[19] = t12 ^ (b[2] | b[3]); + s[24] = b[2] ^ (b[4] & t34); + s[4] = t34 ^ (b[4] | b[0]); + s[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[7], 62); + b[1] = ROTL64(s[12], 55); + b[2] = ROTL64(s[17], 39); + b[3] = ROTL64(s[22], 41); + b[4] = ROTL64(s[2], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[7] = b[0] ^ (b[2] & t12); + s[12] = t12 ^ (b[2] | b[3]); + s[17] = b[2] ^ (b[4] & t34); + s[22] = t34 ^ (b[4] | b[0]); + s[2] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000008002UL; + + /* Round 17. */ + /* Col Mix */ + b[0] = s[0] ^ s[7] ^ s[14] ^ s[16] ^ s[23]; + b[1] = s[3] ^ s[5] ^ s[12] ^ s[19] ^ s[21]; + b[2] = s[1] ^ s[8] ^ s[10] ^ s[17] ^ s[24]; + b[3] = s[4] ^ s[6] ^ s[13] ^ s[15] ^ s[22]; + b[4] = s[2] ^ s[9] ^ s[11] ^ s[18] ^ s[20]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[7]^=t; s[14]^=t; s[16]^=t; s[23]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[3]^=t; s[5]^=t; s[12]^=t; s[19]^=t; s[21]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[1]^=t; s[8]^=t; s[10]^=t; s[17]^=t; s[24]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[4]^=t; s[6]^=t; s[13]^=t; s[15]^=t; s[22]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[2]^=t; s[9]^=t; s[11]^=t; s[18]^=t; s[20]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[3], 44); + b[2] = ROTL64(s[1], 43); + b[3] = ROTL64(s[4], 21); + b[4] = ROTL64(s[2], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[3] = t12 ^ (b[2] | b[3]); + s[1] = b[2] ^ (b[4] & t34); + s[4] = t34 ^ (b[4] | b[0]); + s[2] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[15], 28); + b[1] = ROTL64(s[18], 20); + b[2] = ROTL64(s[16], 3); + b[3] = ROTL64(s[19], 45); + b[4] = ROTL64(s[17], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[15] = b[0] ^ (b[2] & t12); + s[18] = t12 ^ (b[2] | b[3]); + s[16] = b[2] ^ (b[4] & t34); + s[19] = t34 ^ (b[4] | b[0]); + s[17] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[5], 1); + b[1] = ROTL64(s[8], 6); + b[2] = ROTL64(s[6], 25); + b[3] = ROTL64(s[9], 8); + b[4] = ROTL64(s[7], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[5] = b[0] ^ (b[2] & t12); + s[8] = t12 ^ (b[2] | b[3]); + s[6] = b[2] ^ (b[4] & t34); + s[9] = t34 ^ (b[4] | b[0]); + s[7] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[20], 27); + b[1] = ROTL64(s[23], 36); + b[2] = ROTL64(s[21], 10); + b[3] = ROTL64(s[24], 15); + b[4] = ROTL64(s[22], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[20] = b[0] ^ (b[2] & t12); + s[23] = t12 ^ (b[2] | b[3]); + s[21] = b[2] ^ (b[4] & t34); + s[24] = t34 ^ (b[4] | b[0]); + s[22] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[10], 62); + b[1] = ROTL64(s[13], 55); + b[2] = ROTL64(s[11], 39); + b[3] = ROTL64(s[14], 41); + b[4] = ROTL64(s[12], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[10] = b[0] ^ (b[2] & t12); + s[13] = t12 ^ (b[2] | b[3]); + s[11] = b[2] ^ (b[4] & t34); + s[14] = t34 ^ (b[4] | b[0]); + s[12] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000000080UL; + + /* Round 18. */ + /* Col Mix */ + b[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; + b[1] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; + b[2] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; + b[3] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; + b[4] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[5]^=t; s[10]^=t; s[15]^=t; s[20]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[3]^=t; s[8]^=t; s[13]^=t; s[18]^=t; s[23]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[1]^=t; s[6]^=t; s[11]^=t; s[16]^=t; s[21]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[4]^=t; s[9]^=t; s[14]^=t; s[19]^=t; s[24]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[2]^=t; s[7]^=t; s[12]^=t; s[17]^=t; s[22]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[18], 44); + b[2] = ROTL64(s[6], 43); + b[3] = ROTL64(s[24], 21); + b[4] = ROTL64(s[12], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[18] = t12 ^ (b[2] | b[3]); + s[6] = b[2] ^ (b[4] & t34); + s[24] = t34 ^ (b[4] | b[0]); + s[12] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[4], 28); + b[1] = ROTL64(s[17], 20); + b[2] = ROTL64(s[5], 3); + b[3] = ROTL64(s[23], 45); + b[4] = ROTL64(s[11], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[4] = b[0] ^ (b[2] & t12); + s[17] = t12 ^ (b[2] | b[3]); + s[5] = b[2] ^ (b[4] & t34); + s[23] = t34 ^ (b[4] | b[0]); + s[11] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[3], 1); + b[1] = ROTL64(s[16], 6); + b[2] = ROTL64(s[9], 25); + b[3] = ROTL64(s[22], 8); + b[4] = ROTL64(s[10], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[3] = b[0] ^ (b[2] & t12); + s[16] = t12 ^ (b[2] | b[3]); + s[9] = b[2] ^ (b[4] & t34); + s[22] = t34 ^ (b[4] | b[0]); + s[10] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[2], 27); + b[1] = ROTL64(s[15], 36); + b[2] = ROTL64(s[8], 10); + b[3] = ROTL64(s[21], 15); + b[4] = ROTL64(s[14], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[2] = b[0] ^ (b[2] & t12); + s[15] = t12 ^ (b[2] | b[3]); + s[8] = b[2] ^ (b[4] & t34); + s[21] = t34 ^ (b[4] | b[0]); + s[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[1], 62); + b[1] = ROTL64(s[19], 55); + b[2] = ROTL64(s[7], 39); + b[3] = ROTL64(s[20], 41); + b[4] = ROTL64(s[13], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[1] = b[0] ^ (b[2] & t12); + s[19] = t12 ^ (b[2] | b[3]); + s[7] = b[2] ^ (b[4] & t34); + s[20] = t34 ^ (b[4] | b[0]); + s[13] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x800aUL; + + /* Round 19. */ + /* Col Mix */ + b[0] = s[0] ^ s[1] ^ s[2] ^ s[3] ^ s[4]; + b[1] = s[15] ^ s[16] ^ s[17] ^ s[18] ^ s[19]; + b[2] = s[5] ^ s[6] ^ s[7] ^ s[8] ^ s[9]; + b[3] = s[20] ^ s[21] ^ s[22] ^ s[23] ^ s[24]; + b[4] = s[10] ^ s[11] ^ s[12] ^ s[13] ^ s[14]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[1]^=t; s[2]^=t; s[3]^=t; s[4]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[15]^=t; s[16]^=t; s[17]^=t; s[18]^=t; s[19]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[5]^=t; s[6]^=t; s[7]^=t; s[8]^=t; s[9]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[20]^=t; s[21]^=t; s[22]^=t; s[23]^=t; s[24]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[10]^=t; s[11]^=t; s[12]^=t; s[13]^=t; s[14]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[17], 44); + b[2] = ROTL64(s[9], 43); + b[3] = ROTL64(s[21], 21); + b[4] = ROTL64(s[13], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[17] = t12 ^ (b[2] | b[3]); + s[9] = b[2] ^ (b[4] & t34); + s[21] = t34 ^ (b[4] | b[0]); + s[13] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[24], 28); + b[1] = ROTL64(s[11], 20); + b[2] = ROTL64(s[3], 3); + b[3] = ROTL64(s[15], 45); + b[4] = ROTL64(s[7], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[24] = b[0] ^ (b[2] & t12); + s[11] = t12 ^ (b[2] | b[3]); + s[3] = b[2] ^ (b[4] & t34); + s[15] = t34 ^ (b[4] | b[0]); + s[7] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[18], 1); + b[1] = ROTL64(s[5], 6); + b[2] = ROTL64(s[22], 25); + b[3] = ROTL64(s[14], 8); + b[4] = ROTL64(s[1], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[18] = b[0] ^ (b[2] & t12); + s[5] = t12 ^ (b[2] | b[3]); + s[22] = b[2] ^ (b[4] & t34); + s[14] = t34 ^ (b[4] | b[0]); + s[1] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[12], 27); + b[1] = ROTL64(s[4], 36); + b[2] = ROTL64(s[16], 10); + b[3] = ROTL64(s[8], 15); + b[4] = ROTL64(s[20], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[12] = b[0] ^ (b[2] & t12); + s[4] = t12 ^ (b[2] | b[3]); + s[16] = b[2] ^ (b[4] & t34); + s[8] = t34 ^ (b[4] | b[0]); + s[20] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[6], 62); + b[1] = ROTL64(s[23], 55); + b[2] = ROTL64(s[10], 39); + b[3] = ROTL64(s[2], 41); + b[4] = ROTL64(s[19], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[6] = b[0] ^ (b[2] & t12); + s[23] = t12 ^ (b[2] | b[3]); + s[10] = b[2] ^ (b[4] & t34); + s[2] = t34 ^ (b[4] | b[0]); + s[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x800000008000000aUL; + + /* Round 20. */ + /* Col Mix */ + b[0] = s[0] ^ s[6] ^ s[12] ^ s[18] ^ s[24]; + b[1] = s[4] ^ s[5] ^ s[11] ^ s[17] ^ s[23]; + b[2] = s[3] ^ s[9] ^ s[10] ^ s[16] ^ s[22]; + b[3] = s[2] ^ s[8] ^ s[14] ^ s[15] ^ s[21]; + b[4] = s[1] ^ s[7] ^ s[13] ^ s[19] ^ s[20]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[6]^=t; s[12]^=t; s[18]^=t; s[24]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[4]^=t; s[5]^=t; s[11]^=t; s[17]^=t; s[23]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[3]^=t; s[9]^=t; s[10]^=t; s[16]^=t; s[22]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[2]^=t; s[8]^=t; s[14]^=t; s[15]^=t; s[21]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[1]^=t; s[7]^=t; s[13]^=t; s[19]^=t; s[20]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[11], 44); + b[2] = ROTL64(s[22], 43); + b[3] = ROTL64(s[8], 21); + b[4] = ROTL64(s[19], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[11] = t12 ^ (b[2] | b[3]); + s[22] = b[2] ^ (b[4] & t34); + s[8] = t34 ^ (b[4] | b[0]); + s[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[21], 28); + b[1] = ROTL64(s[7], 20); + b[2] = ROTL64(s[18], 3); + b[3] = ROTL64(s[4], 45); + b[4] = ROTL64(s[10], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[21] = b[0] ^ (b[2] & t12); + s[7] = t12 ^ (b[2] | b[3]); + s[18] = b[2] ^ (b[4] & t34); + s[4] = t34 ^ (b[4] | b[0]); + s[10] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[17], 1); + b[1] = ROTL64(s[3], 6); + b[2] = ROTL64(s[14], 25); + b[3] = ROTL64(s[20], 8); + b[4] = ROTL64(s[6], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[17] = b[0] ^ (b[2] & t12); + s[3] = t12 ^ (b[2] | b[3]); + s[14] = b[2] ^ (b[4] & t34); + s[20] = t34 ^ (b[4] | b[0]); + s[6] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[13], 27); + b[1] = ROTL64(s[24], 36); + b[2] = ROTL64(s[5], 10); + b[3] = ROTL64(s[16], 15); + b[4] = ROTL64(s[2], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[13] = b[0] ^ (b[2] & t12); + s[24] = t12 ^ (b[2] | b[3]); + s[5] = b[2] ^ (b[4] & t34); + s[16] = t34 ^ (b[4] | b[0]); + s[2] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[9], 62); + b[1] = ROTL64(s[15], 55); + b[2] = ROTL64(s[1], 39); + b[3] = ROTL64(s[12], 41); + b[4] = ROTL64(s[23], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[9] = b[0] ^ (b[2] & t12); + s[15] = t12 ^ (b[2] | b[3]); + s[1] = b[2] ^ (b[4] & t34); + s[12] = t34 ^ (b[4] | b[0]); + s[23] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000080008081UL; + + /* Round 21. */ + /* Col Mix */ + b[0] = s[0] ^ s[9] ^ s[13] ^ s[17] ^ s[21]; + b[1] = s[3] ^ s[7] ^ s[11] ^ s[15] ^ s[24]; + b[2] = s[1] ^ s[5] ^ s[14] ^ s[18] ^ s[22]; + b[3] = s[4] ^ s[8] ^ s[12] ^ s[16] ^ s[20]; + b[4] = s[2] ^ s[6] ^ s[10] ^ s[19] ^ s[23]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[9]^=t; s[13]^=t; s[17]^=t; s[21]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[3]^=t; s[7]^=t; s[11]^=t; s[15]^=t; s[24]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[1]^=t; s[5]^=t; s[14]^=t; s[18]^=t; s[22]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[4]^=t; s[8]^=t; s[12]^=t; s[16]^=t; s[20]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[2]^=t; s[6]^=t; s[10]^=t; s[19]^=t; s[23]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[7], 44); + b[2] = ROTL64(s[14], 43); + b[3] = ROTL64(s[16], 21); + b[4] = ROTL64(s[23], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[7] = t12 ^ (b[2] | b[3]); + s[14] = b[2] ^ (b[4] & t34); + s[16] = t34 ^ (b[4] | b[0]); + s[23] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[8], 28); + b[1] = ROTL64(s[10], 20); + b[2] = ROTL64(s[17], 3); + b[3] = ROTL64(s[24], 45); + b[4] = ROTL64(s[1], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[8] = b[0] ^ (b[2] & t12); + s[10] = t12 ^ (b[2] | b[3]); + s[17] = b[2] ^ (b[4] & t34); + s[24] = t34 ^ (b[4] | b[0]); + s[1] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[11], 1); + b[1] = ROTL64(s[18], 6); + b[2] = ROTL64(s[20], 25); + b[3] = ROTL64(s[2], 8); + b[4] = ROTL64(s[9], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[11] = b[0] ^ (b[2] & t12); + s[18] = t12 ^ (b[2] | b[3]); + s[20] = b[2] ^ (b[4] & t34); + s[2] = t34 ^ (b[4] | b[0]); + s[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[19], 27); + b[1] = ROTL64(s[21], 36); + b[2] = ROTL64(s[3], 10); + b[3] = ROTL64(s[5], 15); + b[4] = ROTL64(s[12], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[19] = b[0] ^ (b[2] & t12); + s[21] = t12 ^ (b[2] | b[3]); + s[3] = b[2] ^ (b[4] & t34); + s[5] = t34 ^ (b[4] | b[0]); + s[12] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[22], 62); + b[1] = ROTL64(s[4], 55); + b[2] = ROTL64(s[6], 39); + b[3] = ROTL64(s[13], 41); + b[4] = ROTL64(s[15], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[22] = b[0] ^ (b[2] & t12); + s[4] = t12 ^ (b[2] | b[3]); + s[6] = b[2] ^ (b[4] & t34); + s[13] = t34 ^ (b[4] | b[0]); + s[15] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000000008080UL; + + /* Round 22. */ + /* Col Mix */ + b[0] = s[0] ^ s[8] ^ s[11] ^ s[19] ^ s[22]; + b[1] = s[4] ^ s[7] ^ s[10] ^ s[18] ^ s[21]; + b[2] = s[3] ^ s[6] ^ s[14] ^ s[17] ^ s[20]; + b[3] = s[2] ^ s[5] ^ s[13] ^ s[16] ^ s[24]; + b[4] = s[1] ^ s[9] ^ s[12] ^ s[15] ^ s[23]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[8]^=t; s[11]^=t; s[19]^=t; s[22]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[4]^=t; s[7]^=t; s[10]^=t; s[18]^=t; s[21]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[3]^=t; s[6]^=t; s[14]^=t; s[17]^=t; s[20]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[2]^=t; s[5]^=t; s[13]^=t; s[16]^=t; s[24]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[1]^=t; s[9]^=t; s[12]^=t; s[15]^=t; s[23]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[10], 44); + b[2] = ROTL64(s[20], 43); + b[3] = ROTL64(s[5], 21); + b[4] = ROTL64(s[15], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[10] = t12 ^ (b[2] | b[3]); + s[20] = b[2] ^ (b[4] & t34); + s[5] = t34 ^ (b[4] | b[0]); + s[15] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[16], 28); + b[1] = ROTL64(s[1], 20); + b[2] = ROTL64(s[11], 3); + b[3] = ROTL64(s[21], 45); + b[4] = ROTL64(s[6], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[16] = b[0] ^ (b[2] & t12); + s[1] = t12 ^ (b[2] | b[3]); + s[11] = b[2] ^ (b[4] & t34); + s[21] = t34 ^ (b[4] | b[0]); + s[6] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[7], 1); + b[1] = ROTL64(s[17], 6); + b[2] = ROTL64(s[2], 25); + b[3] = ROTL64(s[12], 8); + b[4] = ROTL64(s[22], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[7] = b[0] ^ (b[2] & t12); + s[17] = t12 ^ (b[2] | b[3]); + s[2] = b[2] ^ (b[4] & t34); + s[12] = t34 ^ (b[4] | b[0]); + s[22] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[23], 27); + b[1] = ROTL64(s[8], 36); + b[2] = ROTL64(s[18], 10); + b[3] = ROTL64(s[3], 15); + b[4] = ROTL64(s[13], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[23] = b[0] ^ (b[2] & t12); + s[8] = t12 ^ (b[2] | b[3]); + s[18] = b[2] ^ (b[4] & t34); + s[3] = t34 ^ (b[4] | b[0]); + s[13] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[14], 62); + b[1] = ROTL64(s[24], 55); + b[2] = ROTL64(s[9], 39); + b[3] = ROTL64(s[19], 41); + b[4] = ROTL64(s[4], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[14] = b[0] ^ (b[2] & t12); + s[24] = t12 ^ (b[2] | b[3]); + s[9] = b[2] ^ (b[4] & t34); + s[19] = t34 ^ (b[4] | b[0]); + s[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x80000001UL; + + /* Round 23. */ + /* Col Mix */ + b[0] = s[0] ^ s[7] ^ s[14] ^ s[16] ^ s[23]; + b[1] = s[1] ^ s[8] ^ s[10] ^ s[17] ^ s[24]; + b[2] = s[2] ^ s[9] ^ s[11] ^ s[18] ^ s[20]; + b[3] = s[3] ^ s[5] ^ s[12] ^ s[19] ^ s[21]; + b[4] = s[4] ^ s[6] ^ s[13] ^ s[15] ^ s[22]; + t = b[4] ^ ROTL64(b[1], 1); + s[0]^=t; s[7]^=t; s[14]^=t; s[16]^=t; s[23]^=t; + t = b[0] ^ ROTL64(b[2], 1); + s[1]^=t; s[8]^=t; s[10]^=t; s[17]^=t; s[24]^=t; + t = b[1] ^ ROTL64(b[3], 1); + s[2]^=t; s[9]^=t; s[11]^=t; s[18]^=t; s[20]^=t; + t = b[2] ^ ROTL64(b[4], 1); + s[3]^=t; s[5]^=t; s[12]^=t; s[19]^=t; s[21]^=t; + t = b[3] ^ ROTL64(b[0], 1); + s[4]^=t; s[6]^=t; s[13]^=t; s[15]^=t; s[22]^=t; + /* Row Mix */ + b[0] = s[0]; + b[1] = ROTL64(s[1], 44); + b[2] = ROTL64(s[2], 43); + b[3] = ROTL64(s[3], 21); + b[4] = ROTL64(s[4], 14); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[0] = b[0] ^ (b[2] & t12); + s[1] = t12 ^ (b[2] | b[3]); + s[2] = b[2] ^ (b[4] & t34); + s[3] = t34 ^ (b[4] | b[0]); + s[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[5], 28); + b[1] = ROTL64(s[6], 20); + b[2] = ROTL64(s[7], 3); + b[3] = ROTL64(s[8], 45); + b[4] = ROTL64(s[9], 61); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[5] = b[0] ^ (b[2] & t12); + s[6] = t12 ^ (b[2] | b[3]); + s[7] = b[2] ^ (b[4] & t34); + s[8] = t34 ^ (b[4] | b[0]); + s[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[10], 1); + b[1] = ROTL64(s[11], 6); + b[2] = ROTL64(s[12], 25); + b[3] = ROTL64(s[13], 8); + b[4] = ROTL64(s[14], 18); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[10] = b[0] ^ (b[2] & t12); + s[11] = t12 ^ (b[2] | b[3]); + s[12] = b[2] ^ (b[4] & t34); + s[13] = t34 ^ (b[4] | b[0]); + s[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[15], 27); + b[1] = ROTL64(s[16], 36); + b[2] = ROTL64(s[17], 10); + b[3] = ROTL64(s[18], 15); + b[4] = ROTL64(s[19], 56); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[15] = b[0] ^ (b[2] & t12); + s[16] = t12 ^ (b[2] | b[3]); + s[17] = b[2] ^ (b[4] & t34); + s[18] = t34 ^ (b[4] | b[0]); + s[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + b[0] = ROTL64(s[20], 62); + b[1] = ROTL64(s[21], 55); + b[2] = ROTL64(s[22], 39); + b[3] = ROTL64(s[23], 41); + b[4] = ROTL64(s[24], 2); + { + word64 t12, t34; + + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); + s[20] = b[0] ^ (b[2] & t12); + s[21] = t12 ^ (b[2] | b[3]); + s[22] = b[2] ^ (b[4] & t34); + s[23] = t34 ^ (b[4] | b[0]); + s[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); + } + /* XOR in constant. */ + s[0] ^= 0x8000000080008008UL; +} + diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index db6ce9fbc..7739f4245 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -95,6 +95,9 @@ #ifdef HAVE_BLAKE2 #include #endif +#ifdef WOLFSSL_SHA3 + #include +#endif #ifdef HAVE_LIBZ #include #endif @@ -209,6 +212,7 @@ int sha224_test(void); int sha256_test(void); int sha512_test(void); int sha384_test(void); +int sha3_test(void); int hash_test(void); int hmac_md5_test(void); int hmac_sha_test(void); @@ -479,6 +483,13 @@ int wolfcrypt_test(void* args) printf( "SHA-512 test passed!\n"); #endif +#ifdef WOLFSSL_SHA3 + if ( (ret = sha3_test()) != 0) + return err_sys("SHA-3 test failed!\n", ret); + else + printf( "SHA-3 test passed!\n"); +#endif + if ( (ret = hash_test()) != 0) return err_sys("Hash test failed!\n", ret); else @@ -1760,6 +1771,245 @@ int sha384_test(void) } #endif /* WOLFSSL_SHA384 */ +#ifdef WOLFSSL_SHA3 +static int sha3_224_test(void) +{ + Sha3 sha; + byte hash[SHA3_224_DIGEST_SIZE]; + byte hashcopy[SHA3_224_DIGEST_SIZE]; + + testVector a, b; + testVector test_sha[2]; + int ret; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = "abc"; + a.output = "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76" + "\x6f\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_224_DIGEST_SIZE; + + b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + b.output = "\x8a\x24\x10\x8b\x15\x4a\xda\x21\xc9\xfd\x55\x74\x49\x44\x79" + "\xba\x5c\x7e\x7a\xb7\x6e\xf2\x64\xea\xd0\xfc\xce\x33"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_224_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + + ret = wc_InitSha3_224(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2000; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_224_Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + if (ret != 0) + return -2010 - i; + ret = wc_Sha3_224_GetHash(&sha, hashcopy); + if (ret != 0) + return -2020 - i; + ret = wc_Sha3_224_Final(&sha, hash); + if (ret != 0) + return -2030 - i; + + if (XMEMCMP(hash, test_sha[i].output, SHA3_224_DIGEST_SIZE) != 0) + return -2040 - i; + + if (XMEMCMP(hash, hashcopy, SHA3_224_DIGEST_SIZE) != 0) + return -2050 - i; + } + wc_Sha3_224_Free(&sha); + + return 0; +} + +static int sha3_256_test(void) +{ + Sha3 sha; + byte hash[SHA3_256_DIGEST_SIZE]; + byte hashcopy[SHA3_256_DIGEST_SIZE]; + + testVector a, b; + testVector test_sha[2]; + int ret; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = "abc"; + a.output = "\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90" + "\xbd\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43" + "\x15\x32"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_256_DIGEST_SIZE; + + b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + b.output = "\x41\xc0\xdb\xa2\xa9\xd6\x24\x08\x49\x10\x03\x76\xa8\x23\x5e" + "\x2c\x82\xe1\xb9\x99\x8a\x99\x9e\x21\xdb\x32\xdd\x97\x49\x6d" + "\x33\x76"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_256_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + + ret = wc_InitSha3_256(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2100; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_256_Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + if (ret != 0) + return -2110 - i; + ret = wc_Sha3_256_GetHash(&sha, hashcopy); + if (ret != 0) + return -2120 - i; + ret = wc_Sha3_256_Final(&sha, hash); + if (ret != 0) + return -2130 - i; + + if (XMEMCMP(hash, test_sha[i].output, SHA3_256_DIGEST_SIZE) != 0) + return -2140 - i; + + if (XMEMCMP(hash, hashcopy, SHA3_256_DIGEST_SIZE) != 0) + return -2150 - i; + } + wc_Sha3_256_Free(&sha); + + return 0; +} + +static int sha3_384_test(void) +{ + Sha3 sha; + byte hash[SHA3_384_DIGEST_SIZE]; + byte hashcopy[SHA3_384_DIGEST_SIZE]; + + testVector a, b; + testVector test_sha[2]; + int ret; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = "abc"; + a.output = "\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad" + "\x8d\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b" + "\xe4\xb2\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28" + "\x37\x6d\x25"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_384_DIGEST_SIZE; + + b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + b.output = "\x99\x1c\x66\x57\x55\xeb\x3a\x4b\x6b\xbd\xfb\x75\xc7\x8a\x49" + "\x2e\x8c\x56\xa2\x2c\x5c\x4d\x7e\x42\x9b\xfd\xbc\x32\xb9\xd4" + "\xad\x5a\xa0\x4a\x1f\x07\x6e\x62\xfe\xa1\x9e\xef\x51\xac\xd0" + "\x65\x7c\x22"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_384_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + + ret = wc_InitSha3_384(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2200; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_384_Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + if (ret != 0) + return -2210 - i; + ret = wc_Sha3_384_GetHash(&sha, hashcopy); + if (ret != 0) + return -2220 - i; + ret = wc_Sha3_384_Final(&sha, hash); + if (ret != 0) + return -2230 - i; + + if (XMEMCMP(hash, test_sha[i].output, SHA3_384_DIGEST_SIZE) != 0) + return -2240 - i; + + if (XMEMCMP(hash, hashcopy, SHA3_384_DIGEST_SIZE) != 0) + return -2250 - i; + } + wc_Sha3_384_Free(&sha); + + return 0; +} + +static int sha3_512_test(void) +{ + Sha3 sha; + byte hash[SHA3_512_DIGEST_SIZE]; + byte hashcopy[SHA3_512_DIGEST_SIZE]; + + testVector a, b; + testVector test_sha[2]; + int ret; + int times = sizeof(test_sha) / sizeof(struct testVector), i; + + a.input = "abc"; + a.output = "\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09" + "\x6e\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2" + "\x71\x2e\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47" + "\xe3\x93\x40\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27" + "\x4e\xec\x53\xf0"; + a.inLen = XSTRLEN(a.input); + a.outLen = SHA3_512_DIGEST_SIZE; + + b.input = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + b.output = "\x04\xa3\x71\xe8\x4e\xcf\xb5\xb8\xb7\x7c\xb4\x86\x10\xfc\xa8" + "\x18\x2d\xd4\x57\xce\x6f\x32\x6a\x0f\xd3\xd7\xec\x2f\x1e\x91" + "\x63\x6d\xee\x69\x1f\xbe\x0c\x98\x53\x02\xba\x1b\x0d\x8d\xc7" + "\x8c\x08\x63\x46\xb5\x33\xb4\x9c\x03\x0d\x99\xa2\x7d\xaf\x11" + "\x39\xd6\xe7\x5e"; + b.inLen = XSTRLEN(b.input); + b.outLen = SHA3_512_DIGEST_SIZE; + + test_sha[0] = a; + test_sha[1] = b; + + ret = wc_InitSha3_512(&sha, HEAP_HINT, devId); + if (ret != 0) + return -2300; + + for (i = 0; i < times; ++i) { + ret = wc_Sha3_512_Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); + if (ret != 0) + return -2310 - i; + ret = wc_Sha3_512_GetHash(&sha, hashcopy); + if (ret != 0) + return -2320 - i; + ret = wc_Sha3_512_Final(&sha, hash); + if (ret != 0) + return -2330 - i; + + if (XMEMCMP(hash, test_sha[i].output, SHA3_512_DIGEST_SIZE) != 0) + return -2340 - i; + + if (XMEMCMP(hash, hashcopy, SHA3_512_DIGEST_SIZE) != 0) + return -2350 - i; + } + wc_Sha3_512_Free(&sha); + + return 0; +} + +int sha3_test(void) +{ + int ret; + + if ((ret = sha3_224_test()) != 0) + return ret; + if ((ret = sha3_256_test()) != 0) + return ret; + if ((ret = sha3_384_test()) != 0) + return ret; + if ((ret = sha3_512_test()) != 0) + return ret; + + return 0; +} +#endif + + int hash_test(void) { wc_HashAlg hash; diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 92307a2b8..66115c932 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -59,7 +59,8 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/mem_track.h \ wolfssl/wolfcrypt/wolfevent.h \ wolfssl/wolfcrypt/pkcs12.h \ - wolfssl/wolfcrypt/wolfmath.h + wolfssl/wolfcrypt/wolfmath.h \ + wolfssl/wolfcrypt/sha3.h noinst_HEADERS+= \ wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ diff --git a/wolfssl/wolfcrypt/sha3.h b/wolfssl/wolfcrypt/sha3.h new file mode 100644 index 000000000..09d1b161f --- /dev/null +++ b/wolfssl/wolfcrypt/sha3.h @@ -0,0 +1,119 @@ +/* sha3.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* code submitted by raphael.huck@efixo.com */ + +#ifndef WOLF_CRYPT_SHA3_H +#define WOLF_CRYPT_SHA3_H + +#include + +#ifdef WOLFSSL_SHA3 + +#ifdef HAVE_FIPS + /* for fips @wc_fips */ + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef HAVE_FIPS /* avoid redefinition of structs */ + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +/* in bytes */ +enum { + SHA3_224 = 10, /* hash type unique */ + SHA3_224_DIGEST_SIZE = 28, + SHA3_224_COUNT = 18, + + SHA3_256 = 11, /* hash type unique */ + SHA3_256_DIGEST_SIZE = 32, + SHA3_256_COUNT = 17, + + SHA3_384 = 12, /* hash type unique */ + SHA3_384_DIGEST_SIZE = 48, + SHA3_384_COUNT = 13, + + SHA3_512 = 13, /* hash type unique */ + SHA3_512_DIGEST_SIZE = 64, + SHA3_512_COUNT = 9 +}; + + +/* Sha3 digest */ +typedef struct Sha3 { + /* State data that is processed for each block. */ + word64 s[25]; + /* Unprocessed message data. */ + byte t[200]; + /* Index into unprocessed data to place next message byte. */ + byte i; + + void* heap; + +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +} Sha3; + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha3_224(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_224_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_224_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_224_Free(Sha3*); +WOLFSSL_API int wc_Sha3_224_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_224_Copy(Sha3* src, Sha3* dst); + +WOLFSSL_API int wc_InitSha3_256(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_256_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_256_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_256_Free(Sha3*); +WOLFSSL_API int wc_Sha3_256_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_256_Copy(Sha3* src, Sha3* dst); + +WOLFSSL_API int wc_InitSha3_384(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_384_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_384_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_384_Free(Sha3*); +WOLFSSL_API int wc_Sha3_384_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_384_Copy(Sha3* src, Sha3* dst); + +WOLFSSL_API int wc_InitSha3_512(Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_512_Update(Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_512_Final(Sha3*, byte*); +WOLFSSL_API void wc_Sha3_512_Free(Sha3*); +WOLFSSL_API int wc_Sha3_512_GetHash(Sha3*, byte*); +WOLFSSL_API int wc_Sha3_512_Copy(Sha3* src, Sha3* dst); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_SHA3 */ +#endif /* WOLF_CRYPT_SHA3_H */ + From 7ef5aeaf13e997e1306ce3688d49a11a2ee88544 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Wed, 24 May 2017 09:27:01 +1000 Subject: [PATCH 11/34] Fixes from review and tidy up code. --- wolfcrypt/src/sha3.c | 331 ++++++++++++++++++++++++++++++++------ wolfcrypt/src/sha3_long.i | 14 +- wolfssl/wolfcrypt/sha3.h | 2 - 3 files changed, 287 insertions(+), 60 deletions(-) diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c index 584f3ce99..de203660d 100755 --- a/wolfcrypt/src/sha3.c +++ b/wolfcrypt/src/sha3.c @@ -162,16 +162,15 @@ #ifdef WOLFSSL_SHA3_SMALL -/** - * Rotate a 64-bit value left. +/* Rotate a 64-bit value left. * - * @param [in] a The number to rotate left. - * @param [in] r The number od bits to rotate left. - * @return The rotated number. + * a Number to rotate left. + * r Number od bits to rotate left. + * returns the rotated number. */ #define ROTL64(a, n) (((a)<<(n))|((a)>>(64-(n)))) -/** An array of values to XOR for block operation. */ +/* An array of values to XOR for block operation. */ static const word64 hash_keccak_r[24] = { 0x0000000000000001UL, 0x0000000000008082UL, @@ -188,6 +187,7 @@ static const word64 hash_keccak_r[24] = 0x0000000080000001UL, 0x8000000080008008UL }; +/* Indeces used in swap and rotate operation. */ #define K_I_0 10 #define K_I_1 7 #define K_I_2 11 @@ -213,6 +213,7 @@ static const word64 hash_keccak_r[24] = #define K_I_22 6 #define K_I_23 1 +/* Number of bits to rotate in swap and rotate operation. */ #define K_R_0 1 #define K_R_1 3 #define K_R_2 6 @@ -238,13 +239,12 @@ static const word64 hash_keccak_r[24] = #define K_R_22 20 #define K_R_23 44 -/** - * Swap and rotate left operation. +/* Swap and rotate left operation. * - * @param [in] s The state. - * @param [in] t1 Temporary value. - * @param [in] t2 Second temporary value. - * @param [in] i The index of the loop. + * s The state. + * t1 Temporary value. + * t2 Second temporary value. + * i The index of the loop. */ #define SWAP_ROTL(s, t1, t2, i) \ do \ @@ -253,13 +253,12 @@ do \ } \ while (0) -/** - * Mix the XOR of the column's values into each number by column. +/* Mix the XOR of the column's values into each number by column. * - * @param [in] s The state. - * @param [in] b Temporary array of XORed column values. - * @param [in] x The index of the column. - * @param [in] t Temporary variable. + * s The state. + * b Temporary array of XORed column values. + * x The index of the column. + * t Temporary variable. */ #define COL_MIX(s, b, x, t) \ do \ @@ -279,16 +278,15 @@ do \ while (0) #ifdef SHA3_BY_SPEC -/** - * Mix the row values. +/* Mix the row values. * BMI1 has ANDN instruction ((~a) & b) - Haswell and above. * - * @param [in] s The state. - * @param [in] b Temporary array of XORed row values. - * @param [in] y The index of the row to work on. - * @param [in] x The index of the column. - * @param [in] t0 Temporary variable. - * @param [in] t1 Temporary variable. + * s The state. + * b Temporary array of XORed row values. + * y The index of the row to work on. + * x The index of the column. + * t0 Temporary variable. + * t1 Temporary variable. */ #define ROW_MIX(s, b, y, x, t0, t1) \ do \ @@ -303,16 +301,15 @@ do \ } \ while (0) #else -/** - * Mix the row values. +/* Mix the row values. * a ^ (~b & c) == a ^ (c & (b ^ c)) == (a ^ b) ^ (b | c) * - * @param [in] s The state. - * @param [in] b Temporary array of XORed row values. - * @param [in] y The index of the row to work on. - * @param [in] x The index of the column. - * @param [in] t0 Temporary variable. - * @param [in] t1 Temporary variable. + * s The state. + * b Temporary array of XORed row values. + * y The index of the row to work on. + * x The index of the column. + * t0 Temporary variable. + * t1 Temporary variable. */ #define ROW_MIX(s, b, y, x, t12, t34) \ do \ @@ -332,10 +329,9 @@ do \ while (0) #endif -/** - * The block operation performed on the state. +/* The block operation performed on the state. * - * @param [in] s The state. + * s The state. */ static void BlockSha3(word64 *s) { @@ -382,21 +378,31 @@ static void BlockSha3(word64 *s) #include "sha3_long.i" #endif -static word64 Load64BitBigEndian(const byte* x) +/* Convert the array of bytes, in little-endian order, to a 64-bit integer. + * + * a Array of bytes. + * returns a 64-bit integer. + */ +static word64 Load64BitBigEndian(const byte* a) { -#if defined(BIG_ENDIAN_ORDER) - word64 r = 0; +#ifdef BIG_ENDIAN_ORDER + word64 n = 0; int i; for (i = 0; i < 8; i++) - r |= (word64)x[i] << (8 * i); + n |= (word64)a[i] << (8 * i); - return r; + return n; #else - return *(word64*)x; + return *(word64*)a; #endif } +/* Initialize the state for a SHA3-224 hash operation. + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ static int InitSha3(Sha3* sha3) { int i; @@ -408,6 +414,14 @@ static int InitSha3(Sha3* sha3) return 0; } +/* Update the SHA-3 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * p Number of 64-bit numbers in a block of data to process. + * returns 0 on success. + */ static int Sha3Update(Sha3* sha3, const byte* data, word32 len, byte p) { byte i; @@ -450,17 +464,25 @@ static int Sha3Update(Sha3* sha3, const byte* data, word32 len, byte p) return 0; } -static int Sha3Final(Sha3* sha3, byte* hash, byte r, byte l) +/* Calculate the SHA-3 hash based on all the message data seen. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. + * p Number of 64-bit numbers in a block of data to process. + * len Number of bytes in output. + * returns 0 on success. + */ +static int Sha3Final(Sha3* sha3, byte* hash, byte p, byte l) { byte i; byte *s8 = (byte *)sha3->s; - sha3->t[r * 8 - 1] = 0x00; + sha3->t[p * 8 - 1] = 0x00; sha3->t[ sha3->i] = 0x06; - sha3->t[r * 8 - 1] |= 0x80; - for (i=sha3->i + 1; i < r * 8 - 1; i++) + sha3->t[p * 8 - 1] |= 0x80; + for (i=sha3->i + 1; i < p * 8 - 1; i++) sha3->t[i] = 0; - for (i = 0; i < r; i++) + for (i = 0; i < p; i++) sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); BlockSha3(sha3->s); for (i = 0; i < l; i++) @@ -472,6 +494,13 @@ static int Sha3Final(Sha3* sha3, byte* hash, byte r, byte l) return 0; } +/* Initialize the state for a SHA-3 hash operation. + * + * sha3 Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ static int wc_InitSha3(Sha3* sha3, void* heap, int devId) { int ret = 0; @@ -494,6 +523,14 @@ static int wc_InitSha3(Sha3* sha3, void* heap, int devId) return ret; } +/* Update the SHA-3 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * p Number of 64-bit numbers in a block of data to process. + * returns 0 on success. + */ static int wc_Sha3Update(Sha3* sha3, const byte* data, word32 len, byte p) { int ret = 0; @@ -515,6 +552,14 @@ static int wc_Sha3Update(Sha3* sha3, const byte* data, word32 len, byte p) return ret; } +/* Calculate the SHA-3 hash based on all the message data seen. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. + * p Number of 64-bit numbers in a block of data to process. + * len Number of bytes in output. + * returns 0 on success. + */ static int wc_Sha3Final(Sha3* sha3, byte* hash, byte p, byte len) { int ret; @@ -539,6 +584,12 @@ static int wc_Sha3Final(Sha3* sha3, byte* hash, byte p, byte len) return InitSha3(sha3); /* reset state */ } +/* Dispose of any dynamically allocated data from the SHA3-384 operation. + * (Required for async ops.) + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ static void wc_Sha3Free(Sha3* sha3) { (void)sha3; @@ -552,6 +603,12 @@ static void wc_Sha3Free(Sha3* sha3) } #endif /* HAVE_FIPS */ +/* Copy the state of the SHA3 operation. + * + * src Sha3 object holding state top copy. + * dst Sha3 object to copy into. + * returns 0 on success. + */ static int wc_Sha3Copy(Sha3* src, Sha3* dst) { int ret = 0; @@ -568,7 +625,17 @@ static int wc_Sha3Copy(Sha3* src, Sha3* dst) return ret; } -static int wc_Sha3GetHash(Sha3* sha3, byte* hash, byte p, byte l) +/* Calculate the SHA3-224 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 28 bytes. + * p Number of 64-bit numbers in a block of data to process. + * len Number of bytes in output. + * returns 0 on success. + */ +static int wc_Sha3GetHash(Sha3* sha3, byte* hash, byte p, byte len) { int ret; Sha3 tmpSha3; @@ -578,130 +645,294 @@ static int wc_Sha3GetHash(Sha3* sha3, byte* hash, byte p, byte l) ret = wc_Sha3Copy(sha3, &tmpSha3); if (ret == 0) { - ret = wc_Sha3Final(&tmpSha3, hash, p, l); + ret = wc_Sha3Final(&tmpSha3, hash, p, len); } return ret; } +/* Initialize the state for a SHA3-224 hash operation. + * + * sha3 Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ WOLFSSL_API int wc_InitSha3_224(Sha3* sha3, void* heap, int devId) { return wc_InitSha3(sha3, heap, devId); } +/* Update the SHA3-224 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_224_Update(Sha3* sha3, const byte* data, word32 len) { return wc_Sha3Update(sha3, data, len, SHA3_224_COUNT); } +/* Calculate the SHA3-224 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 28 bytes. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_224_Final(Sha3* sha3, byte* hash) { return wc_Sha3Final(sha3, hash, SHA3_224_COUNT, SHA3_224_DIGEST_SIZE); } +/* Dispose of any dynamically allocated data from the SHA3-224 operation. + * (Required for async ops.) + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ WOLFSSL_API void wc_Sha3_224_Free(Sha3* sha3) { wc_Sha3Free(sha3); } +/* Calculate the SHA3-224 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 28 bytes. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_224_GetHash(Sha3* sha3, byte* hash) { return wc_Sha3GetHash(sha3, hash, SHA3_224_COUNT, SHA3_224_DIGEST_SIZE); } +/* Copy the state of the SHA3-224 operation. + * + * src Sha3 object holding state top copy. + * dst Sha3 object to copy into. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_224_Copy(Sha3* src, Sha3* dst) { return wc_Sha3Copy(src, dst); } +/* Initialize the state for a SHA3-256 hash operation. + * + * sha3 Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ WOLFSSL_API int wc_InitSha3_256(Sha3* sha3, void* heap, int devId) { return wc_InitSha3(sha3, heap, devId); } +/* Update the SHA3-256 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_256_Update(Sha3* sha3, const byte* data, word32 len) { return wc_Sha3Update(sha3, data, len, SHA3_256_COUNT); } +/* Calculate the SHA3-256 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 32 bytes. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_256_Final(Sha3* sha3, byte* hash) { return wc_Sha3Final(sha3, hash, SHA3_256_COUNT, SHA3_256_DIGEST_SIZE); } +/* Dispose of any dynamically allocated data from the SHA3-256 operation. + * (Required for async ops.) + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ WOLFSSL_API void wc_Sha3_256_Free(Sha3* sha3) { wc_Sha3Free(sha3); } +/* Calculate the SHA3-256 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 32 bytes. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_256_GetHash(Sha3* sha3, byte* hash) { return wc_Sha3GetHash(sha3, hash, SHA3_256_COUNT, SHA3_256_DIGEST_SIZE); } +/* Copy the state of the SHA3-256 operation. + * + * src Sha3 object holding state top copy. + * dst Sha3 object to copy into. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_256_Copy(Sha3* src, Sha3* dst) { return wc_Sha3Copy(src, dst); } +/* Initialize the state for a SHA3-384 hash operation. + * + * sha3 Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ WOLFSSL_API int wc_InitSha3_384(Sha3* sha3, void* heap, int devId) { return wc_InitSha3(sha3, heap, devId); } +/* Update the SHA3-384 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_384_Update(Sha3* sha3, const byte* data, word32 len) { return wc_Sha3Update(sha3, data, len, SHA3_384_COUNT); } +/* Calculate the SHA3-384 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 48 bytes. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_384_Final(Sha3* sha3, byte* hash) { return wc_Sha3Final(sha3, hash, SHA3_384_COUNT, SHA3_384_DIGEST_SIZE); } +/* Dispose of any dynamically allocated data from the SHA3-384 operation. + * (Required for async ops.) + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ WOLFSSL_API void wc_Sha3_384_Free(Sha3* sha3) { wc_Sha3Free(sha3); } +/* Calculate the SHA3-384 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 48 bytes. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_384_GetHash(Sha3* sha3, byte* hash) { return wc_Sha3GetHash(sha3, hash, SHA3_384_COUNT, SHA3_384_DIGEST_SIZE); } +/* Copy the state of the SHA3-384 operation. + * + * src Sha3 object holding state top copy. + * dst Sha3 object to copy into. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_384_Copy(Sha3* src, Sha3* dst) { return wc_Sha3Copy(src, dst); } +/* Initialize the state for a SHA3-512 hash operation. + * + * sha3 Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ WOLFSSL_API int wc_InitSha3_512(Sha3* sha3, void* heap, int devId) { return wc_InitSha3(sha3, heap, devId); } +/* Update the SHA3-512 hash state with message data. + * + * sha3 Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_512_Update(Sha3* sha3, const byte* data, word32 len) { return wc_Sha3Update(sha3, data, len, SHA3_512_COUNT); } +/* Calculate the SHA3-512 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 64 bytes. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_512_Final(Sha3* sha3, byte* hash) { return wc_Sha3Final(sha3, hash, SHA3_512_COUNT, SHA3_512_DIGEST_SIZE); } +/* Dispose of any dynamically allocated data from the SHA3-512 operation. + * (Required for async ops.) + * + * sha3 Sha3 object holding state. + * returns 0 on success. + */ WOLFSSL_API void wc_Sha3_512_Free(Sha3* sha3) { wc_Sha3Free(sha3); } +/* Calculate the SHA3-512 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 64 bytes. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_512_GetHash(Sha3* sha3, byte* hash) { return wc_Sha3GetHash(sha3, hash, SHA3_512_COUNT, SHA3_512_DIGEST_SIZE); } +/* Copy the state of the SHA3-512 operation. + * + * src Sha3 object holding state top copy. + * dst Sha3 object to copy into. + * returns 0 on success. + */ WOLFSSL_API int wc_Sha3_512_Copy(Sha3* src, Sha3* dst) { return wc_Sha3Copy(src, dst); diff --git a/wolfcrypt/src/sha3_long.i b/wolfcrypt/src/sha3_long.i index bcf6c91ae..eaa4c7502 100644 --- a/wolfcrypt/src/sha3_long.i +++ b/wolfcrypt/src/sha3_long.i @@ -20,19 +20,17 @@ */ -/** - * Rotate a 64-bit value left. +/* Rotate a 64-bit value left. * - * @param [in] a The number to rotate left. - * @param [in] r The number od bits to rotate left. - * @return The rotated number. + * a The number to rotate left. + * r The number od bits to rotate left. + * returns the rotated number. */ #define ROTL64(a, n) (((a)<<(n))|((a)>>(64-(n)))) -/** - * The block operation performed on the state. +/* The block operation performed on the state. * - * @param [in] s The state. + * s The state. */ static void BlockSha3(word64 *s) { diff --git a/wolfssl/wolfcrypt/sha3.h b/wolfssl/wolfcrypt/sha3.h index 09d1b161f..28f5af7a7 100644 --- a/wolfssl/wolfcrypt/sha3.h +++ b/wolfssl/wolfcrypt/sha3.h @@ -20,8 +20,6 @@ */ -/* code submitted by raphael.huck@efixo.com */ - #ifndef WOLF_CRYPT_SHA3_H #define WOLF_CRYPT_SHA3_H From 53021a5df7fe3b6c4d5ddfdf4b93fe4540f96649 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 26 May 2017 10:01:42 -0700 Subject: [PATCH 12/34] Increased security for `WOLFSSL_NO_TRUSTED_CERTS_VERIFY` workaround so it only applies to OCSP. Fix for the workaround to still return date or parsing errors. --- wolfcrypt/src/asn.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index db7421767..c7f5a3f74 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -39,6 +39,7 @@ ASN Options: * WOLFSSL_NO_TRUSTED_CERTS_VERIFY: Workaround for sitatuon where entire cert chain is not loaded. This only matches on subject and public key and does not perform a PKI validation, so it is not a secure solution. + Only enabled for OCSP. */ #ifndef NO_ASN @@ -4109,10 +4110,10 @@ static int GetValidity(DecodedCert* cert, int verify) if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) return ASN_PARSE_E; - if (GetDate(cert, BEFORE) < 0 && verify) + if (GetDate(cert, BEFORE) < 0 && verify != NO_VERIFY) badDate = ASN_BEFORE_DATE_E; /* continue parsing */ - if (GetDate(cert, AFTER) < 0 && verify) + if (GetDate(cert, AFTER) < 0 && verify != NO_VERIFY) return ASN_AFTER_DATE_E; if (badDate != 0) @@ -6036,7 +6037,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) /* alternate lookup method using subject and match on public key */ #ifdef WOLFSSL_NO_TRUSTED_CERTS_VERIFY - if (cert->ca == NULL) { + if (cert->ca == NULL && verify == VERIFY_OCSP) { if (cert->extSubjKeyIdSet) { cert->ca = GetCA(cm, cert->extSubjKeyId); } @@ -6047,7 +6048,8 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) if ((cert->ca->pubKeySize == cert->pubKeySize) && (XMEMCMP(cert->ca->publicKey, cert->publicKey, cert->ca->pubKeySize) == 0)) { - return 0; + ret = 0; /* success */ + goto exit_pcr; } } } @@ -6091,7 +6093,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { if (cert->ca) { - if (verify == VERIFY) { + if (verify == VERIFY || verify == VERIFY_OCSP) { /* try to confirm/verify signature */ if ((ret = ConfirmSignature(&cert->sigCtx, cert->source + cert->certBegin, @@ -6121,6 +6123,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) } } +exit_pcr: if (badDate != 0) return badDate; @@ -10189,8 +10192,8 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, InitDecodedCert(&cert, resp->cert, resp->certSz, heap); /* Don't verify if we don't have access to Cert Manager. */ - ret = ParseCertRelative(&cert, CERT_TYPE, noVerify ? NO_VERIFY : VERIFY, - cm); + ret = ParseCertRelative(&cert, CERT_TYPE, + noVerify ? NO_VERIFY : VERIFY_OCSP, cm); if (ret < 0) { WOLFSSL_MSG("\tOCSP Responder certificate parsing failed"); FreeDecodedCert(&cert); From a0345f6ba9800340c4c0794ba80167e685190a1b Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 26 May 2017 10:53:42 -0700 Subject: [PATCH 13/34] Fix for building without WOLFSSL_NO_TRUSTED_CERTS_VERIFY. --- wolfcrypt/src/asn.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index c7f5a3f74..85d22b98e 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -6123,7 +6123,10 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) } } +#ifdef WOLFSSL_NO_TRUSTED_CERTS_VERIFY exit_pcr: +#endif + if (badDate != 0) return badDate; From 6b34a9458913dac3f6851e2f2ac778b1ab016d6c Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Thu, 1 Jun 2017 11:56:53 +1000 Subject: [PATCH 14/34] Fix NO_DH build issue --- tests/api.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/api.c b/tests/api.c index 13b709e42..1c74e8518 100644 --- a/tests/api.c +++ b/tests/api.c @@ -4036,7 +4036,8 @@ static void test_wolfSSL_PEM_PrivateKey(void) static void test_wolfSSL_tmp_dh(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ - !defined(NO_FILESYSTEM) && !defined(NO_DSA) && !defined(NO_RSA) + !defined(NO_FILESYSTEM) && !defined(NO_DSA) && !defined(NO_RSA) && \ + !defined(NO_DH) byte buffer[5300]; char file[] = "./certs/dsaparams.pem"; FILE *f; From 0b32d0368f315b9c295b63d38e08be63b136706c Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Tue, 23 May 2017 15:56:52 +1000 Subject: [PATCH 15/34] Updates for Draft 20 of TLS v1.3 --- examples/client/client.c | 10 +- src/tls.c | 25 ++++- src/tls13.c | 200 ++++++++++++++++++++++++++++----------- wolfssl/internal.h | 4 + 4 files changed, 179 insertions(+), 60 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 8d5039236..a86b5681e 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1520,12 +1520,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef WOLFSSL_TLS13 if (!helloRetry) { if (onlyKeyShare == 0 || onlyKeyShare == 2) { + #ifdef HAVE_CURVE25519 if (useX25519) { if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != SSL_SUCCESS) { err_sys("unable to use curve secp256r1"); } } + #endif if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) != SSL_SUCCESS) { err_sys("unable to use curve secp256r1"); @@ -1950,12 +1952,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void*)"resumed session"); #endif - #ifdef WOLFSSL_TLS13 +#ifdef WOLFSSL_TLS13 + #ifdef HAVE_CURVE25519 if (useX25519) { if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != SSL_SUCCESS) { err_sys("unable to use curve secp256r1"); } } + #endif if (wolfSSL_UseKeyShare(sslResume, WOLFSSL_ECC_SECP256R1) != SSL_SUCCESS) { err_sys("unable to use curve secp256r1"); @@ -1964,12 +1968,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) WOLFSSL_ECC_SECP384R1) != SSL_SUCCESS) { err_sys("unable to use curve secp384r1"); } - #ifdef HAVE_FFDHE_2048 + #ifdef HAVE_FFDHE_2048 if (wolfSSL_UseKeyShare(sslResume, WOLFSSL_FFDHE_2048) != SSL_SUCCESS) { err_sys("unable to use DH 2048-bit parameters"); } - #endif #endif +#endif #ifndef WOLFSSL_CALLBACKS if (nonBlocking) { diff --git a/src/tls.c b/src/tls.c index a25afd141..6399bb808 100755 --- a/src/tls.c +++ b/src/tls.c @@ -6395,7 +6395,8 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType) { TLSX* extension; word16 length = 0; - byte isRequest = (msgType == client_hello); + byte isRequest = (msgType == client_hello || + msgType == certificate_request); while ((extension = list)) { list = extension->next; @@ -6501,7 +6502,8 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, TLSX* extension; word16 offset = 0; word16 length_offset = 0; - byte isRequest = (msgType == client_hello); + byte isRequest = (msgType == client_hello || + msgType == certificate_request); while ((extension = list)) { list = extension->next; @@ -7268,6 +7270,12 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); #ifndef NO_PSK TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + break; + #ifndef NO_CERTS + case certificate_request: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); #endif #endif break; @@ -7323,6 +7331,13 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); #ifndef NO_PSK TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + break; + #ifndef NO_CERTS + case certificate_request: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, + TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); #endif #endif break; @@ -7357,7 +7372,8 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, { int ret = 0; word16 offset = 0; - byte isRequest = (msgType == client_hello); + byte isRequest = (msgType == client_hello || + msgType == certificate_request); #ifdef HAVE_EXTENDED_MASTER byte pendingEMS = 0; #endif @@ -7523,7 +7539,8 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, break; if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello) { + msgType != client_hello && + msgType != certificate_request) { return EXT_NOT_ALLOWED; } ret = SA_PARSE(ssl, input + offset, size, suites); diff --git a/src/tls13.c b/src/tls13.c index cb1879019..539df7d73 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -286,10 +286,17 @@ static int HKDF_Expand_Label(byte* okm, word32 okmLen, return ret; } +#ifdef WOLFSSL_TLS13_DRAFT_18 /* Size of the TLS v1.3 label use when deriving keys. */ #define TLS13_PROTOCOL_LABEL_SZ 9 /* The protocol label for TLS v1.3. */ static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "TLS 1.3, "; +#else +/* Size of the TLS v1.3 label use when deriving keys. */ +#define TLS13_PROTOCOL_LABEL_SZ 6 +/* The protocol label for TLS v1.3. */ +static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 "; +#endif /* Derive a key from a message. * @@ -456,11 +463,19 @@ static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen, #if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +#ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the binder key label. */ #define BINDER_KEY_LABEL_SZ 23 /* The binder key label. */ static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] = "external psk binder key"; +#else +/* The length of the binder key label. */ +#define BINDER_KEY_LABEL_SZ 10 +/* The binder key label. */ +static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] = + "ext binder"; +#endif /* Derive the binder key. * * ssl The SSL/TLS object. @@ -475,11 +490,19 @@ static int DeriveBinderKey(WOLFSSL* ssl, byte* key) NULL, 0, ssl->specs.mac_algorithm); } +#ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the binder key resume label. */ #define BINDER_KEY_RESUME_LABEL_SZ 25 /* The binder key resume label. */ static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] = "resumption psk binder key"; +#else +/* The length of the binder key resume label. */ +#define BINDER_KEY_RESUME_LABEL_SZ 10 +/* The binder key resume label. */ +static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] = + "res binder"; +#endif /* Derive the binder resumption key. * * ssl The SSL/TLS object. @@ -496,11 +519,19 @@ static int DeriveBinderKeyResume(WOLFSSL* ssl, byte* key) #endif #ifdef TLS13_SUPPORTS_0RTT +#ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the early traffic label. */ #define EARLY_TRAFFIC_LABEL_SZ 27 /* The early traffic label. */ static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] = "client early traffic secret"; +#else +/* The length of the early traffic label. */ +#define EARLY_TRAFFIC_LABEL_SZ 11 +/* The early traffic label. */ +static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] = + "c e traffic"; +#endif /* Derive the early traffic key. * * ssl The SSL/TLS object. @@ -516,11 +547,19 @@ static int DeriveEarlyTrafficSecret(WOLFSSL* ssl, byte* key) } #ifdef TLS13_SUPPORTS_EXPORTERS +#ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the early exporter label. */ #define EARLY_EXPORTER_LABEL_SZ 28 /* The early exporter label. */ static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] = "early exporter master secret"; +#else +/* The length of the early exporter label. */ +#define EARLY_EXPORTER_LABEL_SZ 12 +/* The early exporter label. */ +static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] = + "e exp master"; +#endif /* Derive the early exporter key. * * ssl The SSL/TLS object. @@ -537,11 +576,19 @@ static int DeriveEarlyExporterSecret(WOLFSSL* ssl, byte* key) #endif #endif +#ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the client hanshake label. */ #define CLIENT_HANDSHAKE_LABEL_SZ 31 /* The client hanshake label. */ static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] = "client handshake traffic secret"; +#else +/* The length of the client hanshake label. */ +#define CLIENT_HANDSHAKE_LABEL_SZ 12 +/* The client hanshake label. */ +static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] = + "c hs traffic"; +#endif /* Derive the client handshake key. * * ssl The SSL/TLS object. @@ -556,11 +603,19 @@ static int DeriveClientHandshakeSecret(WOLFSSL* ssl, byte* key) ssl->specs.mac_algorithm, 1); } +#ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the server handshake label. */ #define SERVER_HANDSHAKE_LABEL_SZ 31 /* The server handshake label. */ static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] = "server handshake traffic secret"; +#else +/* The length of the server handshake label. */ +#define SERVER_HANDSHAKE_LABEL_SZ 12 +/* The server handshake label. */ +static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] = + "s hs traffic"; +#endif /* Derive the server handshake key. * * ssl The SSL/TLS object. @@ -575,11 +630,19 @@ static int DeriveServerHandshakeSecret(WOLFSSL* ssl, byte* key) ssl->specs.mac_algorithm, 1); } +#ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the client application traffic label. */ #define CLIENT_APP_LABEL_SZ 33 /* The client application traffic label. */ static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] = "client application traffic secret"; +#else +/* The length of the client application traffic label. */ +#define CLIENT_APP_LABEL_SZ 12 +/* The client application traffic label. */ +static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] = + "c ap traffic"; +#endif /* Derive the client application traffic key. * * ssl The SSL/TLS object. @@ -594,11 +657,19 @@ static int DeriveClientTrafficSecret(WOLFSSL* ssl, byte* key) ssl->specs.mac_algorithm, 1); } +#ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the server application traffic label. */ #define SERVER_APP_LABEL_SZ 33 /* The server application traffic label. */ static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] = "server application traffic secret"; +#else +/* The length of the server application traffic label. */ +#define SERVER_APP_LABEL_SZ 12 +/* The server application traffic label. */ +static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] = + "s ap traffic"; +#endif /* Derive the server application traffic key. * * ssl The SSL/TLS object. @@ -614,11 +685,19 @@ static int DeriveServerTrafficSecret(WOLFSSL* ssl, byte* key) } #ifdef TLS13_SUPPORTS_EXPORTERS +#ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the exporter master secret label. */ #define EXPORTER_MASTER_LABEL_SZ 22 /* The exporter master secret label. */ static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] = "exporter master secret"; +#else +/* The length of the exporter master secret label. */ +#define EXPORTER_MASTER_LABEL_SZ 10 +/* The exporter master secret label. */ +static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] = + "exp master"; +#endif /* Derive the exporter secret. * * ssl The SSL/TLS object. @@ -635,11 +714,19 @@ static int DeriveExporterSecret(WOLFSSL* ssl, byte* key) #endif #ifndef NO_PSK +#ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the resumption master secret label. */ #define RESUME_MASTER_LABEL_SZ 24 /* The resumption master secret label. */ static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] = "resumption master secret"; +#else +/* The length of the resumption master secret label. */ +#define RESUME_MASTER_LABEL_SZ 10 +/* The resumption master secret label. */ +static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] = + "res master"; +#endif /* Derive the resumption secret. * * ssl The SSL/TLS object. @@ -673,11 +760,19 @@ static int DeriveFinishedSecret(WOLFSSL* ssl, byte* key, byte* secret) ssl->specs.mac_algorithm, 0); } +#ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the application traffic label. */ #define APP_TRAFFIC_LABEL_SZ 26 /* The application traffic label. */ static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] = "application traffic secret"; +#else +/* The length of the application traffic label. */ +#define APP_TRAFFIC_LABEL_SZ 11 +/* The application traffic label. */ +static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] = + "traffic upd"; +#endif /* Update the traffic secret. * * ssl The SSL/TLS object. @@ -709,17 +804,42 @@ static int DeriveEarlySecret(WOLFSSL* ssl) #endif } +#ifndef WOLFSSL_TLS13_DRAFT_18 +/* The length of the derived label. */ +#define DERIVED_LABEL_SZ 7 +/* The derived label. */ +static const byte derivedLabel[DERIVED_LABEL_SZ + 1] = + "derived"; +#endif /* Derive the handshake secret using HKDF Extract. * * ssl The SSL/TLS object. */ static int DeriveHandshakeSecret(WOLFSSL* ssl) { +#ifdef WOLFSSL_TLS13_DRAFT_18 WOLFSSL_MSG("Derive Handshake Secret"); return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret, ssl->arrays->secret, ssl->specs.hash_size, ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, ssl->specs.mac_algorithm); +#else + byte key[WC_MAX_DIGEST_SIZE]; + int ret; + + WOLFSSL_MSG("Derive Handshake Secret"); + + ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, + derivedLabel, DERIVED_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); + if (ret != 0) + return ret; + + return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret, + key, ssl->specs.hash_size, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + ssl->specs.mac_algorithm); +#endif } /* Derive the master secret using HKDF Extract. @@ -728,10 +848,27 @@ static int DeriveHandshakeSecret(WOLFSSL* ssl) */ static int DeriveMasterSecret(WOLFSSL* ssl) { +#ifdef WOLFSSL_TLS13_DRAFT_18 WOLFSSL_MSG("Derive Master Secret"); return Tls13_HKDF_Extract(ssl->arrays->masterSecret, ssl->arrays->preMasterSecret, ssl->specs.hash_size, ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +#else + byte key[WC_MAX_DIGEST_SIZE]; + int ret; + + WOLFSSL_MSG("Derive Master Secret"); + + ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->preMasterSecret, + derivedLabel, DERIVED_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); + if (ret != 0) + return ret; + + return Tls13_HKDF_Extract(ssl->arrays->masterSecret, + key, ssl->specs.hash_size, + ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +#endif } /* Calculate the HMAC of message data to this point. @@ -2148,6 +2285,8 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, { word16 len; word32 begin = *inOutIdx; + int ret; + Suites peerSuites; #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("CertificateRequest", @@ -2172,41 +2311,6 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, */ *inOutIdx += len; - /* Signature and hash algorithms. */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - ato16(input + *inOutIdx, &len); - *inOutIdx += OPAQUE16_LEN; - if ((*inOutIdx - begin) + len > size) - return BUFFER_ERROR; - PickHashSigAlgo(ssl, input + *inOutIdx, len); - *inOutIdx += len; - - /* Length of certificate authority data. */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - ato16(input + *inOutIdx, &len); - *inOutIdx += OPAQUE16_LEN; - if ((*inOutIdx - begin) + len > size) - return BUFFER_ERROR; - - /* Certificate authorities. */ - while (len) { - word16 dnSz; - - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &dnSz); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + dnSz > size) - return BUFFER_ERROR; - - *inOutIdx += dnSz; - len -= OPAQUE16_LEN + dnSz; - } - /* TODO: [TLS13] Add extension handling. */ /* Certificate extensions */ if ((*inOutIdx - begin) + OPAQUE16_LEN > size) @@ -2215,9 +2319,13 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, *inOutIdx += OPAQUE16_LEN; if ((*inOutIdx - begin) + len > size) return BUFFER_ERROR; - /* Skip over extensions for now. */ + if ((ret = TLSX_Parse(ssl, (byte *)(input + *inOutIdx), len, + certificate_request, &peerSuites))) + return ret; *inOutIdx += len; + PickHashSigAlgo(ssl, peerSuites.hashSigAlgo, peerSuites.hashSigAlgoSz); + ssl->options.sendVerify = SEND_CERT; /* This message is always encrypted so add encryption padding. */ @@ -2807,9 +2915,8 @@ int SendTls13CertificateRequest(WOLFSSL* ssl) int reqCtxLen = 0; word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - int reqSz = OPAQUE8_LEN + reqCtxLen + REQ_HEADER_SZ + REQ_HEADER_SZ; - - reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz; + int reqSz = OPAQUE8_LEN + reqCtxLen + + TLSX_GetResponseSize(ssl, certificate_request); if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) return 0; /* not needed */ @@ -2835,21 +2942,8 @@ int SendTls13CertificateRequest(WOLFSSL* ssl) */ output[i++] = reqCtxLen; - /* supported hash/sig */ - c16toa(ssl->suites->hashSigAlgoSz, &output[i]); - i += LENGTH_SZ; - - XMEMCPY(&output[i], ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz); - i += ssl->suites->hashSigAlgoSz; - - /* Certificate authorities not supported yet - empty buffer. */ - c16toa(0, &output[i]); - i += REQ_HEADER_SZ; - /* Certificate extensions. */ - /* TODO: [TLS13] Add extension handling. */ - c16toa(0, &output[i]); /* auth's */ - i += REQ_HEADER_SZ; + i += TLSX_WriteResponse(ssl, output + i, certificate_request); /* Always encrypted. */ sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 59329eca2..493870135 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -924,7 +924,11 @@ enum Misc { TLSv1_2_MINOR = 3, /* TLSv1_2 minor version number */ TLSv1_3_MINOR = 4, /* TLSv1_3 minor version number */ TLS_DRAFT_MAJOR = 0x7f, /* Draft TLS major version number */ +#ifdef WOLFSSL_TLS13_DRAFT_18 TLS_DRAFT_MINOR = 0x12, /* Minor version number of TLS draft */ +#else + TLS_DRAFT_MINOR = 0x14, /* Minor version number of TLS draft */ +#endif OLD_HELLO_ID = 0x01, /* SSLv2 Client Hello Indicator */ INVALID_BYTE = 0xff, /* Used to initialize cipher specs values */ NO_COMPRESSION = 0, From b3a85bc2c711bb1d8e85f1be7a0cedc475c310f1 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 2 Jun 2017 09:36:35 -0700 Subject: [PATCH 16/34] Fixes for OCSP and CRL with non-blocking sockets. Fix for OCSP and CRL file descriptor check to allow 0. --- src/crl.c | 5 ++++- src/internal.c | 25 +++++++++++++++++++++++-- src/io.c | 4 ++-- src/ocsp.c | 3 +++ 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/crl.c b/src/crl.c index 532282a2f..7743a1797 100755 --- a/src/crl.c +++ b/src/crl.c @@ -349,7 +349,10 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) if (crl->crlIOCb) { ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo, cert->extCrlInfoSz); - if (ret >= 0) { + if (ret == WOLFSSL_CBIO_ERR_WANT_READ) { + ret = WC_PENDING_E; + } + else if (ret >= 0) { /* try again */ ret = CheckCertCRLList(crl, cert, &foundEntry); } diff --git a/src/internal.c b/src/internal.c index a634f9210..946d58f17 100755 --- a/src/internal.c +++ b/src/internal.c @@ -7692,6 +7692,12 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz WOLFSSL_MSG("Doing Non Leaf OCSP check"); ret = CheckCertOCSP(ssl->ctx->cm->ocsp, args->dCert, NULL); + #ifdef WOLFSSL_ASYNC_CRYPT + /* Handle WC_PENDING_E */ + if (ret == WC_PENDING_E) { + goto exit_ppc; + } + #endif doCrlLookup = (ret == OCSP_CERT_UNKNOWN); if (ret != 0) { doCrlLookup = 0; @@ -7706,6 +7712,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz ssl->ctx->cm->crlCheckAll) { WOLFSSL_MSG("Doing Non Leaf CRL check"); ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + goto exit_ppc; + } + #endif if (ret != 0) { WOLFSSL_MSG("\tCRL check not ok"); } @@ -7845,8 +7856,13 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz #ifdef HAVE_OCSP if (doLookup && ssl->ctx->cm->ocspEnabled) { WOLFSSL_MSG("Doing Leaf OCSP check"); - ret = CheckCertOCSP(ssl->ctx->cm->ocsp, - args->dCert, NULL); + ret = CheckCertOCSP(ssl->ctx->cm->ocsp, args->dCert, + NULL); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + goto exit_ppc; + } + #endif doLookup = (ret == OCSP_CERT_UNKNOWN); if (ret != 0) { WOLFSSL_MSG("\tOCSP Lookup not ok"); @@ -7862,6 +7878,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz if (doLookup && ssl->ctx->cm->crlEnabled) { WOLFSSL_MSG("Doing Leaf CRL check"); ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + goto exit_ppc; + } + #endif if (ret != 0) { WOLFSSL_MSG("\tCRL check not ok"); args->fatal = 0; diff --git a/src/io.c b/src/io.c index 8b9a9b960..7dc7c6584 100644 --- a/src/io.c +++ b/src/io.c @@ -1168,7 +1168,7 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, httpBuf, httpBufSz); ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); - if ((ret != 0) || (sfd <= 0)) { + if ((ret != 0) || (sfd < 0)) { WOLFSSL_MSG("OCSP Responder connection failed"); } else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) != @@ -1267,7 +1267,7 @@ int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz) httpBuf, httpBufSz); ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); - if ((ret != 0) || (sfd <= 0)) { + if ((ret != 0) || (sfd < 0)) { WOLFSSL_MSG("CRL connection failed"); } else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) diff --git a/src/ocsp.c b/src/ocsp.c index ae45322ed..7f34a5615 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -445,6 +445,9 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, responseSz = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, request, requestSz, &response); } + if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) { + ret = WC_PENDING_E; + } XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); From c55575665f20494eaca82b25a13e1381a02d3692 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 2 Jun 2017 10:35:26 -0700 Subject: [PATCH 17/34] Cleanup to use `WANT_READ` instead of async `WC_PENDING_E` for non-blocking OCSP and CRL. --- src/crl.c | 2 +- src/internal.c | 16 +++++++++------- src/ocsp.c | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/crl.c b/src/crl.c index 7743a1797..e632dbf10 100755 --- a/src/crl.c +++ b/src/crl.c @@ -350,7 +350,7 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo, cert->extCrlInfoSz); if (ret == WOLFSSL_CBIO_ERR_WANT_READ) { - ret = WC_PENDING_E; + ret = WANT_READ; } else if (ret >= 0) { /* try again */ diff --git a/src/internal.c b/src/internal.c index 946d58f17..eab408824 100755 --- a/src/internal.c +++ b/src/internal.c @@ -7693,8 +7693,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz ret = CheckCertOCSP(ssl->ctx->cm->ocsp, args->dCert, NULL); #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ - if (ret == WC_PENDING_E) { + /* non-blocking socket re-entry requires async */ + if (ret == WANT_READ) { goto exit_ppc; } #endif @@ -7713,7 +7713,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz WOLFSSL_MSG("Doing Non Leaf CRL check"); ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + /* non-blocking socket re-entry requires async */ + if (ret == WANT_READ) { goto exit_ppc; } #endif @@ -7859,7 +7860,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz ret = CheckCertOCSP(ssl->ctx->cm->ocsp, args->dCert, NULL); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + /* non-blocking socket re-entry requires async */ + if (ret == WANT_READ) { goto exit_ppc; } #endif @@ -7879,7 +7881,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz WOLFSSL_MSG("Doing Leaf CRL check"); ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + /* non-blocking socket re-entry requires async */ + if (ret == WANT_READ) { goto exit_ppc; } #endif @@ -8289,8 +8292,7 @@ exit_ppc: WOLFSSL_LEAVE("ProcessPeerCerts", ret); #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ - if (ret == WC_PENDING_E) { + if (ret == WC_PENDING_E || ret == WANT_READ) { /* Mark message as not recevied so it can process again */ ssl->msgsReceived.got_certificate = 0; diff --git a/src/ocsp.c b/src/ocsp.c index 7f34a5615..4554b24b0 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -446,7 +446,7 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, request, requestSz, &response); } if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) { - ret = WC_PENDING_E; + ret = WANT_READ; } XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); From 642795db1b907bde3df2a453734721def90177b6 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 2 Jun 2017 14:05:47 +1000 Subject: [PATCH 18/34] Implement TLS v1.3 specified downgrade protection mechanism TLS v1.2 implementations whould implement the downgrade protection mechanism too and so is included. --- examples/client/client.c | 10 +++++--- src/internal.c | 52 +++++++++++++++++++++++++++++++++++++++- src/tls13.c | 2 -- 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 8d5039236..a86b5681e 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1520,12 +1520,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef WOLFSSL_TLS13 if (!helloRetry) { if (onlyKeyShare == 0 || onlyKeyShare == 2) { + #ifdef HAVE_CURVE25519 if (useX25519) { if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != SSL_SUCCESS) { err_sys("unable to use curve secp256r1"); } } + #endif if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) != SSL_SUCCESS) { err_sys("unable to use curve secp256r1"); @@ -1950,12 +1952,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void*)"resumed session"); #endif - #ifdef WOLFSSL_TLS13 +#ifdef WOLFSSL_TLS13 + #ifdef HAVE_CURVE25519 if (useX25519) { if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != SSL_SUCCESS) { err_sys("unable to use curve secp256r1"); } } + #endif if (wolfSSL_UseKeyShare(sslResume, WOLFSSL_ECC_SECP256R1) != SSL_SUCCESS) { err_sys("unable to use curve secp256r1"); @@ -1964,12 +1968,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) WOLFSSL_ECC_SECP384R1) != SSL_SUCCESS) { err_sys("unable to use curve secp384r1"); } - #ifdef HAVE_FFDHE_2048 + #ifdef HAVE_FFDHE_2048 if (wolfSSL_UseKeyShare(sslResume, WOLFSSL_FFDHE_2048) != SSL_SUCCESS) { err_sys("unable to use DH 2048-bit parameters"); } - #endif #endif +#endif #ifndef WOLFSSL_CALLBACKS if (nonBlocking) { diff --git a/src/internal.c b/src/internal.c index a634f9210..6689dc207 100755 --- a/src/internal.c +++ b/src/internal.c @@ -143,6 +143,12 @@ enum cipherState { CIPHER_STATE_END, }; +/* Server random bytes for TLS v1.3 described downgrade protection mechanism. */ +static const byte tls13Downgrade[7] = { + 0x44, 0x4f, 0x47, 0x4e, 0x47, 0x52, 0x44 +}; +#define TLS13_DOWNGRADE_SZ sizeof(tls13Downgrade) + #ifndef NO_OLD_TLS static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, @@ -15741,6 +15747,33 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); i += RAN_LEN; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) { + /* TLS v1.3 capable client not allowed to downgrade when connecting + * to TLS v1.3 capable server. + */ + if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + (*(input + i - 1) == 0 || *(input + i - 1) == 1)) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return VERSION_ERROR; + } + } + else +#endif + if (ssl->ctx->method->version.major == SSLv3_MAJOR && + ssl->ctx->method->version.minor == TLSv1_2_MINOR) { + /* TLS v1.2 capable client not allowed to downgrade when connecting + * to TLS v1.2 capable server. + */ + if (XMEMCMP(input + i - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + *(input + i - 1) == 0) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return VERSION_ERROR; + } + } + /* session id */ ssl->arrays->sessionIDSz = input[i++]; @@ -19049,7 +19082,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* NO_WOLFSSL_CLIENT */ - #ifndef NO_WOLFSSL_SERVER int SendServerHello(WOLFSSL* ssl) @@ -19138,6 +19170,24 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) { + /* TLS v1.3 capable server downgraded. */ + XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ); + output[idx + RAN_LEN - 1] = IsAtLeastTLSv1_2(ssl); + } + else +#endif + if (ssl->ctx->method->version.major == SSLv3_MAJOR && + ssl->ctx->method->version.minor == TLSv1_2_MINOR && + !IsAtLeastTLSv1_2(ssl)) { + /* TLS v1.2 capable server downgraded. */ + XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ); + output[idx + RAN_LEN - 1] = 0; + } + /* store info in SSL for later */ XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN); idx += RAN_LEN; diff --git a/src/tls13.c b/src/tls13.c index cb1879019..14458457c 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -2027,7 +2027,6 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Server random - keep for debugging. */ XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); i += RAN_LEN; - /* TODO: [TLS13] Check last 8 bytes. */ /* Set the cipher suite from the message. */ ssl->options.cipherSuite0 = input[i++]; @@ -2671,7 +2670,6 @@ int SendTls13ServerHello(WOLFSSL* ssl) output[idx++] = TLS_DRAFT_MAJOR; output[idx++] = TLS_DRAFT_MINOR; - /* TODO: [TLS13] Last 8 bytes have special meaning. */ /* Generate server random. */ ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); if (ret != 0) From 63c85f72d25cda523ea9bbe833621c90b6cfcf71 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 5 Jun 2017 15:21:34 -0600 Subject: [PATCH 19/34] sanity check on build with ECC or RSA --- wolfcrypt/src/asn.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index f615728d8..cc4d036be 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8711,16 +8711,24 @@ int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, /* locate ctx */ if (rsaKey) { + #ifndef NO_RSA #ifdef WOLFSSL_ASYNC_CRYPT certSignCtx = &rsaKey->certSignCtx; #endif heap = rsaKey->heap; + #else + return NOT_COMPILED_IN; + #endif /* NO_RSA */ } else if (eccKey) { + #ifdef HAVE_ECC #ifdef WOLFSSL_ASYNC_CRYPT certSignCtx = &eccKey->certSignCtx; #endif heap = eccKey->heap; + #else + return NOT_COMPILED_IN; + #endif /* HAVE_ECC */ } #ifdef WOLFSSL_ASYNC_CRYPT From 5d5ff56336b4379936a4486be5b3fc0b5e504373 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Wed, 7 Jun 2017 08:29:08 +1000 Subject: [PATCH 20/34] External PSK working in TLS13 --- examples/client/client.c | 15 ++- examples/server/server.c | 17 +-- src/ssl.c | 6 +- src/tls.c | 82 +++++++++++---- src/tls13.c | 216 ++++++++++++++++++++++++++++---------- tests/test-psk-no-id.conf | 10 ++ wolfssl/internal.h | 23 ++-- 7 files changed, 268 insertions(+), 101 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index a86b5681e..6b81d3430 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1280,13 +1280,18 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb); if (cipherList == NULL) { const char *defaultCipherList; - #if defined(HAVE_AESGCM) && !defined(NO_DH) - defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; - #elif defined(HAVE_NULL_CIPHER) - defaultCipherList = "PSK-NULL-SHA256"; + #if defined(HAVE_AESGCM) && !defined(NO_DH) + #ifdef WOLFSSL_TLS13 + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256:" + "TLS13-AES128-GCM-SHA256"; #else - defaultCipherList = "PSK-AES128-CBC-SHA256"; + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; #endif + #elif defined(HAVE_NULL_CIPHER) + defaultCipherList = "PSK-NULL-SHA256"; + #else + defaultCipherList = "PSK-AES128-CBC-SHA256"; + #endif if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList) !=SSL_SUCCESS) { wolfSSL_CTX_free(ctx); diff --git a/examples/server/server.c b/examples/server/server.c index 7eb1bb287..766f1ea2f 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -866,14 +866,19 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (cipherList == NULL && !usePskPlus) { const char *defaultCipherList; - #if defined(HAVE_AESGCM) && !defined(NO_DH) - defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; - needDH = 1; - #elif defined(HAVE_NULL_CIPHER) - defaultCipherList = "PSK-NULL-SHA256"; + #if defined(HAVE_AESGCM) && !defined(NO_DH) + #ifdef WOLFSSL_TLS13 + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256:" + "TLS13-AES128-GCM-SHA256"; #else - defaultCipherList = "PSK-AES128-CBC-SHA256"; + defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; #endif + needDH = 1; + #elif defined(HAVE_NULL_CIPHER) + defaultCipherList = "PSK-NULL-SHA256"; + #else + defaultCipherList = "PSK-AES128-CBC-SHA256"; + #endif if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) != SSL_SUCCESS) err_sys("server can't set cipher list 2"); } diff --git a/src/ssl.c b/src/ssl.c index 5f3da6c8b..eceafd442 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -9128,7 +9128,7 @@ int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) ssl->options.resuming = 1; #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ - defined(HAVE_SESSION_TICKET) && !defined(NO_PSK)) + defined(HAVE_SESSION_TICKET)) ssl->version = session->version; ssl->options.cipherSuite0 = session->cipherSuite0; ssl->options.cipherSuite = session->cipherSuite; @@ -9278,13 +9278,13 @@ int AddSession(WOLFSSL* ssl) } #endif /* SESSION_CERTS */ #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ - defined(HAVE_SESSION_TICKET) && !defined(NO_PSK)) + defined(HAVE_SESSION_TICKET)) if (error == 0) { session->version = ssl->version; session->cipherSuite0 = ssl->options.cipherSuite0; session->cipherSuite = ssl->options.cipherSuite; } -#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & !NO_PSK) */ +#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */ #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) if (error == 0) { session->namedGroup = ssl->session.namedGroup; diff --git a/src/tls.c b/src/tls.c index 6399bb808..5e5c47148 100755 --- a/src/tls.c +++ b/src/tls.c @@ -673,7 +673,7 @@ static INLINE void c24to32(const word24 u24, word32* u32) } #endif -#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) /* Convert opaque data to a 32-bit unsigned integer. * * c The opaque data holding a 32-bit integer. @@ -5207,7 +5207,7 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) { int ret; -#ifdef HAVE_SESSION_TICKET +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) ssl->session.namedGroup = keyShareEntry->group; #endif /* Use Key Share Data from server. */ @@ -5434,6 +5434,7 @@ int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, if (extension == NULL) return MEMORY_E; } + extension->resp = 0; /* Try to find the key share entry with this group. */ keyShareEntry = (KeyShareEntry*)extension->data; @@ -5620,6 +5621,9 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) if (extension != NULL) list = (KeyShareEntry*)extension->data; + if (extension && extension->resp == 1) + return 0; + /* TODO: [TLS13] Server's preference and sending back SupportedGroups */ /* Use client's preference. */ for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) { @@ -5695,7 +5699,7 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) /* Pre-Shared Key */ /******************************************************************************/ -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) /* Free the pre-shared key dynamic data. * * list The linked list of key share entry objects. @@ -5922,8 +5926,8 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, ato32(input + idx, &age); idx += OPAQUE32_LEN; - ret = TLSX_PreSharedKey_Use(ssl, identity, identityLen, age, 0, 1, - NULL); + ret = TLSX_PreSharedKey_Use(ssl, identity, identityLen, age, no_mac, + 1, NULL); if (ret != 0) return ret; @@ -5990,6 +5994,7 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, return PSK_KEY_ERROR; list->chosen = 1; + #ifdef HAVE_SESSION_TICKET if (list->resumption) { /* Check that the session's details are the same as the server's. */ if (ssl->options.cipherSuite0 != ssl->session.cipherSuite0 || @@ -5999,6 +6004,7 @@ static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, return PSK_KEY_ERROR; } } + #endif /* TODO: [TLS13] More checks of consistency. * the "key_share", and "signature_algorithms" extensions are * consistent with the indicated ke_modes and auth_modes values @@ -6147,7 +6153,7 @@ int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, word16 len, word32 age, /* PSK Key Exchange Modes */ /******************************************************************************/ -#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) /* Get the size of the encoded PSK KE modes extension. * Only in ClientHello. * @@ -6368,7 +6374,7 @@ void TLSX_FreeAll(TLSX* list, void* heap) KS_FREE_ALL((KeyShareEntry*)extension->data, heap); break; - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) case TLSX_PRE_SHARED_KEY: PSK_FREE_ALL((PreSharedKey*)extension->data, heap); break; @@ -6475,7 +6481,7 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType) length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType); break; - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) case TLSX_PRE_SHARED_KEY: length += PSK_GET_SIZE((PreSharedKey*)extension->data, msgType); break; @@ -6602,7 +6608,7 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, output + offset, msgType); break; - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) case TLSX_PRE_SHARED_KEY: WOLFSSL_MSG("Pre-Shared Key extension to write"); offset += PSK_WRITE((PreSharedKey*)extension->data, @@ -6826,6 +6832,9 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) int ret = 0; byte* public_key = NULL; word16 public_key_len = 0; +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) + int usingPSK = 0; +#endif #ifdef HAVE_QSH TLSX* extension; QSHScheme* qsh; @@ -7084,11 +7093,10 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) return ret; } - #if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) + #if defined(HAVE_SESSION_TICKET) if (ssl->options.resuming) { WOLFSSL_SESSION* sess = &ssl->session; word32 milli; - byte modes; /* Determine the MAC algorithm for the cipher suite used. */ ssl->options.cipherSuite0 = sess->cipherSuite0; @@ -7103,6 +7111,37 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) if (ret != 0) return ret; + usingPSK = 1; + } + #endif + #ifndef NO_PSK + if (ssl->options.client_psk_cb != NULL) { + byte mac = sha256_mac; + + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + ssl->arrays->server_hint, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + return PSK_KEY_ERROR; + } + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; + /* Hash algorithm defaults to SHA-256 unless cb specifies. */ + + ret = TLSX_PreSharedKey_Use(ssl, + (byte*)ssl->arrays->client_identity, + XSTRLEN(ssl->arrays->client_identity), + 0, mac, 0, NULL); + if (ret != 0) + return ret; + + usingPSK = 1; + } + #endif + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (usingPSK) { + byte modes; + /* Pre-shared key modes: mandatory extension for resumption. */ modes = 1 << PSK_KE; #if !defined(NO_DH) || defined(HAVE_ECC) @@ -7114,7 +7153,6 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) return ret; } #endif - /* TODO: [TLS13] Add PSKs */ } #endif @@ -7152,7 +7190,7 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl) if (!IsAtLeastTLSv1_3(ssl->version)) { TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES)); #endif @@ -7200,11 +7238,11 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) if (!IsAtLeastTLSv1_3(ssl->version)) { TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES)); #endif } - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); #endif #endif @@ -7227,8 +7265,8 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) #endif #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version) && ssl->options.resuming) { - #ifndef NO_PSK + if (IsAtLeastTLSv1_3(ssl->version)) { + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); #endif offset += TLSX_Write(ssl->extensions, output + offset, semaphore, @@ -7260,7 +7298,7 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType) if (ssl->options.tls1_3) { XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); #endif } @@ -7268,7 +7306,7 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType) case encrypted_extensions: TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); #endif break; @@ -7321,7 +7359,7 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType) if (ssl->options.tls1_3) { XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); #endif } @@ -7329,7 +7367,7 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType) case encrypted_extensions: TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); #endif break; @@ -7574,7 +7612,7 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, ret = KS_PARSE(ssl, input + offset, size, msgType); break; - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) case TLSX_PRE_SHARED_KEY: WOLFSSL_MSG("Pre-Shared Key extension received"); diff --git a/src/tls13.c b/src/tls13.c index b5beff8d7..852b30f80 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -26,8 +26,8 @@ #endif #ifdef WOLFSSL_TLS13 -#if defined(HAVE_SESSION_TICKET) -#include +#ifdef HAVE_SESSION_TICKET + #include #endif #include @@ -462,7 +462,7 @@ static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen, } -#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +#ifndef NO_PSK #ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the binder key label. */ #define BINDER_KEY_LABEL_SZ 23 @@ -489,7 +489,9 @@ static int DeriveBinderKey(WOLFSSL* ssl, byte* key) binderKeyLabel, BINDER_KEY_LABEL_SZ, NULL, 0, ssl->specs.mac_algorithm); } +#endif /* !NO_PSK */ +#ifdef HAVE_SESSION_TICKET #ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the binder key resume label. */ #define BINDER_KEY_RESUME_LABEL_SZ 25 @@ -516,7 +518,7 @@ static int DeriveBinderKeyResume(WOLFSSL* ssl, byte* key) binderKeyResumeLabel, BINDER_KEY_RESUME_LABEL_SZ, NULL, 0, ssl->specs.mac_algorithm); } -#endif +#endif /* HAVE_SESSION_TICKET */ #ifdef TLS13_SUPPORTS_0RTT #ifdef WOLFSSL_TLS13_DRAFT_18 @@ -713,7 +715,7 @@ static int DeriveExporterSecret(WOLFSSL* ssl, byte* key) } #endif -#ifndef NO_PSK +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) #ifdef WOLFSSL_TLS13_DRAFT_18 /* The length of the resumption master secret label. */ #define RESUME_MASTER_LABEL_SZ 24 @@ -794,7 +796,7 @@ static int DeriveTrafficSecret(WOLFSSL* ssl, byte* secret) static int DeriveEarlySecret(WOLFSSL* ssl) { WOLFSSL_MSG("Derive Early Secret"); -#ifndef NO_PSK +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0, ssl->arrays->psk_key, ssl->arrays->psk_keySz, ssl->specs.mac_algorithm); @@ -1073,7 +1075,7 @@ end: return ret; } -#if defined(HAVE_SESSION_TICKET) +#ifdef HAVE_SESSION_TICKET #if defined(USER_TICKS) #if 0 word32 TimeNowInMilliseconds(void) @@ -1274,10 +1276,10 @@ end: return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000); } #endif -#endif /* HAVE_SESSION_TICKET */ +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ -#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_SESSION_TICKET) && \ +#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_SESSION_TICKET) || \ !defined(NO_PSK)) /* Add input to all handshake hashes. * @@ -1323,6 +1325,55 @@ static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz) } #endif +/* Restart the Hanshake hash with a hash of the previous messages. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int RestartHandshakeHash(WOLFSSL* ssl) +{ + int ret; + Hashes hashes; + byte header[] = { message_hash, 0, 0, 0 }; + byte* hash = NULL; + + ret = BuildCertHashes(ssl, &hashes); + if (ret != 0) + return ret; + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + header[3] = SHA256_DIGEST_SIZE; + hash = hashes.sha256; + break; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + header[3] = SHA384_DIGEST_SIZE; + hash = hashes.sha384; + break; + #endif + #ifdef WOLFSSL_SHA512 + case sha512_mac: + header[3] = SHA512_DIGEST_SIZE; + hash = hashes.sha512; + break; + #endif + } + + WOLFSSL_MSG("Restart Hash"); + WOLFSSL_BUFFER(hash, header[3]); + + ret = HashOutputRaw(ssl, header, sizeof(header)); + if (ret != 0) + return ret; + return HashOutputRaw(ssl, hash, header[3]); +} + + /* Extract the handshake header information. * * ssl The SSL/TLS object. @@ -1335,9 +1386,9 @@ static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz) * returns BUFFER_E if there is not enough input data and 0 on success. */ static int GetHandshakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, - byte *type, word32 *size, word32 totalSz) + byte* type, word32* size, word32 totalSz) { - const byte *ptr = input + *inOutIdx; + const byte* ptr = input + *inOutIdx; (void)ssl; *inOutIdx += HANDSHAKE_HEADER_SZ; @@ -1471,7 +1522,7 @@ static INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) * iv The derived IV. * order The side on which the message is to be or was sent. */ -static INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte *nonce, const byte* iv, +static INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte* nonce, const byte* iv, int order) { int i; @@ -1612,7 +1663,7 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, * tagIn The authentication tag data from packet. * returns 0 on success, otherwise failure. */ -static int ChaCha20Poly1305_Decrypt(WOLFSSL *ssl, byte* output, +static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, byte* nonce, const byte* tagIn) { @@ -1821,13 +1872,13 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, } #ifndef NO_WOLFSSL_CLIENT -#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +#ifdef HAVE_SESSION_TICKET /* Get the size of the message hash. * * ssl The SSL/TLS object. * returns the length of the hash. */ -static int GetMsgHashSize(WOLFSSL *ssl) +static int GetMsgHashSize(WOLFSSL* ssl) { switch (ssl->specs.mac_algorithm) { #ifndef NO_SHA256 @@ -1845,7 +1896,9 @@ static int GetMsgHashSize(WOLFSSL *ssl) } return 0; } +#endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Derive and write the binders into the ClientHello in space left when * writing the Pre-Shared Key extension. * @@ -1879,6 +1932,7 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) /* Calculate the binder for each identity based on previous handshake data. */ while (current != NULL) { + #ifdef HAVE_SESSION_TICKET if (current->resumption) { /* Set the HMAC to use based on the one for the session (set into * the extension data at the start of this function based on the @@ -1899,12 +1953,17 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) if (ret != 0) return ret; } - else { - /* TODO: [TLS13] Support non-ticket PSK. */ + else + #endif + #ifndef NO_PSK + if (!current->resumption) { /* Get the pre-shared key. */ ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, (char *)current->identity, ssl->arrays->client_identity, MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + /* TODO: Forcing cipher suite to use SHA256 with PSK. */ + /* Default to SHA-256 if cb doesn't specify. */ + ssl->specs.mac_algorithm = sha256_mac; /* Derive the early secret using the PSK. */ ret = DeriveEarlySecret(ssl); if (ret != 0) @@ -1914,6 +1973,12 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) if (ret != 0) return ret; } + else + #endif + { + current = current->next; + continue; + } /* Derive the Finished message secret. */ ret = DeriveFinishedSecret(ssl, binderKey, ssl->keys.client_write_MAC_secret); @@ -1954,7 +2019,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) int sendSz; int ret; -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) if (ssl->options.resuming && (ssl->session.version.major != ssl->version.major || ssl->session.version.minor != ssl->version.minor)) { @@ -2031,11 +2096,11 @@ int SendTls13ClientHello(WOLFSSL* ssl) /* Write out extensions for a request. */ idx += TLSX_WriteRequest(ssl, output + idx); -#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Resumption has a specific set of extensions and binder is calculated * for each identity. */ - if (ssl->options.resuming) + if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY)) ret = WritePSKBinders(ssl, output, idx); else #endif @@ -2083,7 +2148,7 @@ static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input, #endif /* Version info and length field of extension data. */ - if (totalSz < i - begin + OPAQUE16_LEN + OPAQUE16_LEN) + if (totalSz < i - begin + OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN) return BUFFER_ERROR; /* Protocol version. */ @@ -2093,6 +2158,14 @@ static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input, if (ret != 0) return ret; + /* Set the cipher suite from the message. */ + ssl->options.cipherSuite0 = input[i++]; + ssl->options.cipherSuite = input[i++]; + + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + /* Length of extension data. */ ato16(&input[i], &totalExtSz); i += OPAQUE16_LEN; @@ -2115,7 +2188,7 @@ static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input, ssl->options.tls1_3 = 1; ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST; - return 0; + return RestartHandshakeHash(ssl); } /* Handle the ServerHello message from the server. @@ -2199,9 +2272,9 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; -#ifndef NO_PSK +#ifdef HAVE_SESSION_TICKET if (ssl->options.resuming) { - PreSharedKey *psk = NULL; + PreSharedKey* psk = NULL; TLSX* ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); if (ext != NULL) psk = (PreSharedKey*)ext->data; @@ -2336,7 +2409,7 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, #endif /* !NO_WOLFSSL_CLIENT */ #ifndef NO_WOLFSSL_SERVER -#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Handle any Pre-Shared Key (PSK) extension. * Must do this in ClientHello as it requires a hash of the truncated message. * Don't know size of binders until Pre-Shared Key extension has been parsed. @@ -2347,7 +2420,7 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, * usingPSK Indicates handshake is using Pre-Shared Keys. * returns 0 on success and otherwise failure. */ -static int DoPreSharedKeys(WOLFSSL *ssl, const byte* input, word32 helloSz, +static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, int* usingPSK) { int ret; @@ -2384,13 +2457,15 @@ static int DoPreSharedKeys(WOLFSSL *ssl, const byte* input, word32 helloSz, /* Look through all client's pre-shared keys for a match. */ current = (PreSharedKey*)ext->data; while (current != NULL) { - /* TODO: [TLS13] Support non-ticket PSK. */ - /* Decode the identity. */ - ret = DoClientTicket(ssl, current->identity, current->identityLen); - if (ret != WOLFSSL_TICKET_RET_OK) - continue; + #ifndef NO_PSK + XMEMCPY(ssl->arrays->client_identity, current->identity, + current->identityLen); + ssl->arrays->client_identity[current->identityLen] = '\0'; + #endif - if (current->resumption) { + #ifdef HAVE_SESSION_TICKET + /* Decode the identity. */ + if ((ret = DoClientTicket(ssl, current->identity, current->identityLen)) == WOLFSSL_TICKET_RET_OK) { /* Check the ticket isn't too old or new. */ int diff = TimeNowInMilliseconds() - ssl->session.ticketSeen; diff -= current->ticketAge - ssl->session.ticketAdd; @@ -2421,15 +2496,25 @@ static int DoPreSharedKeys(WOLFSSL *ssl, const byte* input, word32 helloSz, if (ret != 0) return ret; } - else { + else + #endif + #ifndef NO_PSK + if ((ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN)) != 0) { + if (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) + return PSK_KEY_ERROR; + + ssl->options.resuming = 0; + /* PSK age is always zero. */ if (current->ticketAge != ssl->session.ticketAdd) return PSK_KEY_ERROR; - /* Get the pre-shared key. */ - ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, - (char*)current->identity, ssl->arrays->client_identity, - MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + /* TODO: Forcing cipher suite to use SHA256 with PSK. */ + /* Default to SHA-256 if cb doesn't specify. */ + ssl->specs.mac_algorithm = sha256_mac; + /* Derive the early secret using the PSK. */ ret = DeriveEarlySecret(ssl); if (ret != 0) @@ -2439,6 +2524,14 @@ static int DoPreSharedKeys(WOLFSSL *ssl, const byte* input, word32 helloSz, if (ret != 0) return ret; } + else + #endif + { + current = current->next; + continue; + } + + ssl->options.sendVerify = 0; /* Derive the Finished message secret. */ ret = DeriveFinishedSecret(ssl, binderKey, @@ -2627,21 +2720,25 @@ static int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) == NULL) ssl->version.minor = pv.minor; -#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) + ssl->options.sendVerify = SEND_CERT; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Process the Pre-Shared Key extension if present. */ ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK); if (ret != 0) return ret; #endif - if (!usingPSK) { + if (!usingPSK || !ssl->options.resuming) { ret = MatchSuite(ssl, &clSuites); if (ret < 0) { WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); return ret; } + } -#ifndef NO_PSK + if (!usingPSK) { +#ifdef HAVE_SESSION_TICKET if (ssl->options.resuming) { ssl->options.resuming = 0; XMEMSET(ssl->arrays->psk_key, 0, ssl->specs.hash_size); @@ -2655,6 +2752,10 @@ static int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = HashInput(ssl, input + begin, helloSz); if (ret != 0) return ret; + + /* Derive early secret for handshake secret. */ + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; } i += totalExtSz; @@ -2672,7 +2773,7 @@ static int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, * ssl The SSL/TLS object. * returns 0 on success, otherwise failure. */ -int SendTls13HelloRetryRequest(WOLFSSL *ssl) +int SendTls13HelloRetryRequest(WOLFSSL* ssl) { int ret; byte* output; @@ -2687,8 +2788,8 @@ int SendTls13HelloRetryRequest(WOLFSSL *ssl) if (len == 0) return MISSING_HANDSHAKE_DATA; - /* Protocol version + Extensions */ - length = OPAQUE16_LEN + len; + /* Protocol version + CipherSuite + Extensions */ + length = OPAQUE16_LEN + OPAQUE16_LEN + len; sendSz = idx + length; /* Check buffers are big enough and grow if needed. */ @@ -2713,6 +2814,10 @@ int SendTls13HelloRetryRequest(WOLFSSL *ssl) output[idx++] = TLS_DRAFT_MAJOR; output[idx++] = TLS_DRAFT_MINOR; + /* Chosen cipher suite */ + output[idx++] = ssl->options.cipherSuite0; + output[idx++] = ssl->options.cipherSuite; + /* Add TLS extensions. */ TLSX_WriteResponse(ssl, output + idx, hello_retry_request); idx += len; @@ -2725,6 +2830,10 @@ int SendTls13HelloRetryRequest(WOLFSSL *ssl) ssl->heap); #endif + ret = RestartHandshakeHash(ssl); + if (ret < 0) + return ret; + ret = HashOutput(ssl, output, idx, 0); if (ret != 0) return ret; @@ -2827,7 +2936,7 @@ int SendTls13ServerHello(WOLFSSL* ssl) * ssl The SSL/TLS object. * returns 0 on success, otherwise failure. */ -int SendTls13EncryptedExtensions(WOLFSSL *ssl) +int SendTls13EncryptedExtensions(WOLFSSL* ssl) { int ret; byte* output; @@ -2837,9 +2946,6 @@ int SendTls13EncryptedExtensions(WOLFSSL *ssl) ssl->keys.encryptionOn = 1; - /* Derive early secret for handshake secret. */ - if ((ret = DeriveEarlySecret(ssl)) != 0) - return ret; /* Derive the handshake secret now that we are at first message to be * encrypted under the keys. */ @@ -2907,7 +3013,7 @@ int SendTls13EncryptedExtensions(WOLFSSL *ssl) */ int SendTls13CertificateRequest(WOLFSSL* ssl) { - byte *output; + byte* output; int ret; int sendSz; int reqCtxLen = 0; @@ -3033,7 +3139,7 @@ static INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType) * hash The buffer to write the hash to. * returns the length of the hash. */ -static INLINE int GetMsgHash(WOLFSSL *ssl, byte* hash) +static INLINE int GetMsgHash(WOLFSSL* ssl, byte* hash) { switch (ssl->specs.mac_algorithm) { #ifndef NO_SHA256 @@ -3279,7 +3385,7 @@ static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo, CreateSigData(ssl, sigData, &sigDataSz, 1); #ifdef WC_RSA_PSS if (sigAlgo == rsa_pss_sa_algo) { - int hashType = WC_HASH_TYPE_NONE; + enum wc_HashType hashType = WC_HASH_TYPE_NONE; switch (hashAlgo) { case sha512_mac: @@ -4392,7 +4498,7 @@ int SendTls13Finished(WOLFSSL* ssl) if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) return ret; -#ifndef NO_PSK +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); #endif } @@ -5011,7 +5117,7 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, return ret; } -#ifndef NO_PSK +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) if (type == finished && ssl->options.side == WOLFSSL_SERVER_END) DeriveResumptionSecret(ssl, ssl->session.masterSecret); #endif @@ -5464,7 +5570,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) errno = 0; #endif -#ifndef NO_PSK +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) havePSK = ssl->options.havePSK; #endif (void)havePSK; @@ -5594,7 +5700,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) case CERT_REQ_SENT : ssl->options.acceptState = KEY_EXCHANGE_SENT; #ifndef NO_CERTS - if (!ssl->options.resuming) { + if (!ssl->options.resuming && ssl->options.sendVerify) { if ((ssl->error = SendTls13Certificate(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; @@ -5607,7 +5713,7 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) case CERT_SENT : #ifndef NO_CERTS - if (!ssl->options.resuming) { + if (!ssl->options.resuming && ssl->options.sendVerify) { if ((ssl->error = SendTls13CertificateVerify(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; diff --git a/tests/test-psk-no-id.conf b/tests/test-psk-no-id.conf index 40f63af36..f3a997e25 100644 --- a/tests/test-psk-no-id.conf +++ b/tests/test-psk-no-id.conf @@ -251,3 +251,13 @@ -v 3 -l PSK-AES256-GCM-SHA384 +# server TLSv1.3 AES128-GCM-SHA256 +-s +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# client TLSv1.3 AES128-GCM-SHA256 +-s +-v 4 +-l TLS13-AES128-GCM-SHA256 + diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 493870135..9487a7947 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1771,11 +1771,11 @@ typedef enum { TLSX_SESSION_TICKET = 0x0023, #ifdef WOLFSSL_TLS13 TLSX_KEY_SHARE = 0x0028, - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TLSX_PRE_SHARED_KEY = 0x0029, #endif TLSX_SUPPORTED_VERSIONS = 0x002b, - #ifndef NO_PSK + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TLSX_PSK_KEY_EXCHANGE_MODES = 0x002d, #endif #endif @@ -2063,7 +2063,7 @@ WOLFSSL_LOCAL int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl); WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl); -#ifndef NO_PSK +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* The PreSharedKey extension information - entry in a linked list. */ typedef struct PreSharedKey { word16 identityLen; /* Length of identity */ @@ -2092,7 +2092,7 @@ enum PskKeyExchangeMode { }; WOLFSSL_LOCAL int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes); -#endif /* NO_PSK */ +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ /* The types of keys to derive for. */ enum DeriveKeyType { @@ -2203,12 +2203,12 @@ struct WOLFSSL_CTX { word32 ecdhCurveOID; /* curve Ecc_Sum */ word32 pkCurveOID; /* curve Ecc_Sum */ #endif -#ifndef NO_PSK +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) byte havePSK; /* psk key set by user */ wc_psk_client_callback client_psk_cb; /* client callback */ wc_psk_server_callback server_psk_cb; /* server callback */ char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; -#endif /* NO_PSK */ +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ #ifdef HAVE_ANON byte haveAnon; /* User wants to allow Anon suites */ #endif /* HAVE_ANON */ @@ -2527,7 +2527,7 @@ struct WOLFSSL_SESSION { word16 idLen; /* serverID length */ byte serverID[SERVER_ID_LEN]; /* for easier client lookup */ #endif -#ifdef HAVE_SESSION_TICKET +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) #ifdef WOLFSSL_TLS13 byte namedGroup; word32 ticketSeen; /* Time ticket seen (ms) */ @@ -2657,8 +2657,10 @@ typedef struct Options { #ifndef NO_PSK wc_psk_client_callback client_psk_cb; wc_psk_server_callback server_psk_cb; - word16 havePSK:1; /* psk key set by user */ #endif /* NO_PSK */ +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + word16 havePSK:1; /* psk key set by user */ +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ #ifdef OPENSSL_EXTRA unsigned long mask; /* store SSL_OP_ flags */ #endif @@ -2767,7 +2769,7 @@ typedef struct Arrays { word32 preMasterSz; /* differs for DH, actual size */ word32 pendingMsgSz; /* defrag buffer size */ word32 pendingMsgOffset; /* current offset into defrag buffer */ -#ifndef NO_PSK +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) word32 psk_keySz; /* actual size */ char client_identity[MAX_PSK_ID_LEN + NULL_TERM_LEN]; char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; @@ -3380,6 +3382,7 @@ enum HandShakeType { change_cipher_hs = 55, /* simulate unique handshake type for sanity checks. record layer change_cipher conflicts with handshake finished */ + message_hash = 254, /* synthetic message type for TLS v1.3 */ no_shake = 255 /* used to initialize the DtlsMsg record */ }; @@ -3543,7 +3546,7 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); #endif /* NO_TLS */ -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) WOLFSSL_LOCAL word32 TimeNowInMilliseconds(void); #endif WOLFSSL_LOCAL word32 LowResTimer(void); From 2c84eee2df3cc64c137e57a3d8be650de27b0ec6 Mon Sep 17 00:00:00 2001 From: John Blixt Date: Wed, 7 Jun 2017 11:55:55 -0600 Subject: [PATCH 21/34] Fix wc_SetKeyUsage() value error. --- wolfcrypt/src/asn.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index f615728d8..7669fda90 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -9082,7 +9082,9 @@ int wc_SetKeyUsage(Cert *cert, const char *value) XSTRNCPY(str, value, XSTRLEN(value)); /* parse value, and set corresponding Key Usage value */ - token = XSTRTOK(str, ",", &ptr); + if ((token = XSTRTOK(str, ",", &ptr)) == NULL) { + return KEYUSAGE_E; + } while (token != NULL) { len = (word32)XSTRLEN(token); From 4beda52dcd83543e6363f96305961203231219ce Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Thu, 25 May 2017 09:04:05 +1000 Subject: [PATCH 22/34] Ed25519 Certificates --- wolfcrypt/src/asn.c | 839 +++++++++++++++++++++++++++------ wolfcrypt/src/ed25519.c | 29 +- wolfssl/wolfcrypt/asn.h | 19 +- wolfssl/wolfcrypt/asn_public.h | 43 +- wolfssl/wolfcrypt/ed25519.h | 17 +- wolfssl/wolfcrypt/types.h | 1 + 6 files changed, 783 insertions(+), 165 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index f615728d8..e3e647e07 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -87,6 +87,10 @@ ASN Options: #include #endif +#ifdef HAVE_ED25519 + #include +#endif + #ifndef NO_RSA #include #endif @@ -1113,6 +1117,9 @@ static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; static const byte sigSha384wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 3}; static const byte sigSha512wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 4}; #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + static const byte sigEd25519Oid[] = {43, 101, 112}; +#endif /* HAVE_ED25519 */ /* keyType */ #ifndef NO_DSA @@ -1127,6 +1134,9 @@ static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; #ifdef HAVE_ECC static const byte keyEcdsaOid[] = {42, 134, 72, 206, 61, 2, 1}; #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + static const byte keyEd25519Oid[] = {43, 101, 112}; +#endif /* HAVE_ED25519 */ /* curveType */ #ifdef HAVE_ECC @@ -1292,6 +1302,12 @@ static const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(sigSha512wEcdsaOid); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case CTC_ED25519: + oid = sigEd25519Oid; + *oidSz = sizeof(sigEd25519Oid); + break; + #endif default: break; } @@ -1323,6 +1339,12 @@ static const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(keyEcdsaOid); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + oid = keyEd25519Oid; + *oidSz = sizeof(keyEd25519Oid); + break; + #endif /* HAVE_ED25519 */ default: break; } @@ -2140,6 +2162,41 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + { + int ret = 0; + word32 keyIdx = 0; + ed25519_key key_pair; + + if (der->keyOID == ED25519k) { + if ((ret = wc_ed25519_init(&key_pair)) == 0 && + wc_Ed25519PrivateKeyDecode(key, &keyIdx, &key_pair, keySz) + == 0) { + WOLFSSL_MSG("Checking ED25519 key pair"); + keyIdx = 0; + if ((ret = wc_ed25519_import_public(der->publicKey, + der->pubKeySize, &key_pair)) == 0) { + /* public and private extracted successfuly no check if is + * a pair and also do sanity checks on key. wc_ecc_check_key + * checks that private * base generator equals pubkey */ + if ((ret = wc_ed25519_check_key(&key_pair)) == 0) { + /* found a match */ + wc_ed25519_free(&key_pair); + return 1; + } + + } + } + wc_ed25519_free(&key_pair); + } + + /* error on attempt to match */ + if (ret != 0) { + return ret; + } + } + #endif + /* no match found */ return 0; } @@ -2390,6 +2447,9 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, #ifndef NO_RSA RsaKey rsa; #endif +#ifdef HAVE_ED25519 + ed25519_key ed25519; +#endif if (algoID == NULL) { return BAD_FUNC_ARG; @@ -2441,6 +2501,23 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, } } #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + if (*algoID != RSAk && *algoId != ECDSAk) { + if (wc_ed25519_init(&ed25519) == 0) { + if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, &ed25519, keySz) + == 0) { + *algoID = ED25519k; + } + else { + WOLFSSL_MSG("Not ED25519 DER key"); + } + wc_ed25519_free(&ed25519); + } + else { + WOLFSSL_MSG("GetKeyOID wc_ed25519_init failed"); + } + } +#endif /* if flag is not set then is neither RSA or ECC key that could be * found */ @@ -3348,6 +3425,29 @@ static int GetKey(DecodedCert* cert) return ECC_CURVE_OID_E; /* key header */ + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; + + cert->publicKey = (byte*)XMALLOC(length, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (cert->publicKey == NULL) + return MEMORY_E; + XMEMCPY(cert->publicKey, &cert->source[cert->srcIdx], length); + cert->pubKeyStored = 1; + cert->pubKeySize = length; + + cert->srcIdx += length; + + return 0; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + int ret; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1, NULL); if (ret != 0) @@ -3365,7 +3465,7 @@ static int GetKey(DecodedCert* cert) return 0; } - #endif /* HAVE_ECC */ + #endif /* HAVE_ED25519 */ default: return ASN_UNKNOWN_OID_E; } @@ -4318,7 +4418,8 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ tagSz = (type == oidHashType || - (type == oidSigType && !IsSigAlgoECDSA(algoOID)) || + (type == oidSigType && !IsSigAlgoECDSA(algoOID) && + algoOID != ED25519k) || (type == oidKeyType && algoOID == RSAk)) ? 2 : 0; algoName = OidFromId(algoOID, type, &algoSz); @@ -4436,6 +4537,12 @@ void FreeSignatureCtx(SignatureCtx* sigCtx) XFREE(sigCtx->key.ecc, sigCtx->heap, DYNAMIC_TYPE_ECC); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + wc_ed25519_free(sigCtx->key.ed25519); + XFREE(sigCtx->key.ed25519, sigCtx->heap, DYNAMIC_TYPE_ED25519); + break; + #endif /* HAVE_ED25519 */ default: break; } /* switch (keyOID) */ @@ -4446,6 +4553,93 @@ void FreeSignatureCtx(SignatureCtx* sigCtx) sigCtx->state = SIG_STATE_BEGIN; } +static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, + byte* digest, int* typeH, int* digestSz, int verify) +{ + int ret = 0; + + (void)verify; + + switch (sigOID) { + #if defined(WOLFSSL_MD2) + case CTC_MD2wRSA: + if (!verify) { + ret = HASH_TYPE_E; + WOLFSSL_MSG("MD2 not supported for signing"); + } + else if ((ret = wc_Md2Hash(buf, bufSz, digest)) == 0) { + *typeH = MD2h; + *digestSz = MD2_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_MD5 + case CTC_MD5wRSA: + if ((ret = wc_Md5Hash(buf, bufSz, digest)) == 0) { + *typeH = MD5h; + *digestSz = MD5_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + case CTC_SHAwDSA: + case CTC_SHAwECDSA: + if ((ret = wc_ShaHash(buf, bufSz, digest)) == 0) { + *typeH = SHAh; + *digestSz = SHA_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wRSA: + case CTC_SHA224wECDSA: + if ((ret = wc_Sha224Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA224h; + *digestSz = SHA224_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + case CTC_SHA256wECDSA: + if ((ret = wc_Sha256Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA256h; + *digestSz = SHA256_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + case CTC_SHA384wECDSA: + if ((ret = wc_Sha384Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA384h; + *digestSz = SHA384_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + case CTC_SHA512wECDSA: + if ((ret = wc_Sha512Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA512h; + *digestSz = SHA512_DIGEST_SIZE; + } + break; + #endif + case CTC_ED25519: + /* Hashes done in signing operation. + * Two dependent hashes with prefixes performed. + */ + break; + default: + ret = HASH_TYPE_E; + WOLFSSL_MSG("Hash for Signature has unsupported type"); + } + + return 0; +} + /* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */ static int ConfirmSignature(SignatureCtx* sigCtx, const byte* buf, word32 bufSz, @@ -4481,74 +4675,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx, case SIG_STATE_HASH: { - switch (sigOID) { - #ifndef NO_MD5 - case CTC_MD5wRSA: - if ((ret = wc_Md5Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = MD5h; - sigCtx->digestSz = MD5_DIGEST_SIZE; - } - break; - #endif - #if defined(WOLFSSL_MD2) - case CTC_MD2wRSA: - if ((ret = wc_Md2Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = MD2h; - sigCtx->digestSz = MD2_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA - case CTC_SHAwRSA: - case CTC_SHAwDSA: - case CTC_SHAwECDSA: - if ((ret = wc_ShaHash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = SHAh; - sigCtx->digestSz = SHA_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA224 - case CTC_SHA224wRSA: - case CTC_SHA224wECDSA: - if ((ret = wc_Sha224Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = SHA224h; - sigCtx->digestSz = SHA224_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA256 - case CTC_SHA256wRSA: - case CTC_SHA256wECDSA: - if ((ret = wc_Sha256Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = SHA256h; - sigCtx->digestSz = SHA256_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA512 - case CTC_SHA512wRSA: - case CTC_SHA512wECDSA: - if ((ret = wc_Sha512Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = SHA512h; - sigCtx->digestSz = SHA512_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA384 - case CTC_SHA384wRSA: - case CTC_SHA384wECDSA: - if ((ret = wc_Sha384Hash(buf, bufSz, sigCtx->digest)) == 0) { - sigCtx->typeH = SHA384h; - sigCtx->digestSz = SHA384_DIGEST_SIZE; - } - break; - #endif - default: - ret = HASH_TYPE_E; - WOLFSSL_MSG("Verify Signature has unsupported type"); - } - + ret = HashForSignature(buf, bufSz, sigOID, sigCtx->digest, + &sigCtx->typeH, &sigCtx->digestSz, 1); if (ret != 0) { goto exit_cs; } @@ -4618,6 +4746,28 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + sigCtx->verify = 0; + sigCtx->key.ed25519 = (ed25519_key*)XMALLOC( + sizeof(ed25519_key), sigCtx->heap, + DYNAMIC_TYPE_ED25519); + if (sigCtx->key.ed25519 == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + + if ((ret = wc_ed25519_init(sigCtx->key.ed25519)) < 0) { + goto exit_cs; + } + if ((ret = wc_ed25519_import_public(key, keySz, + sigCtx->key.ed25519)) < 0) { + WOLFSSL_MSG("ASN Key import error ED25519"); + goto exit_cs; + } + break; + } + #endif default: WOLFSSL_MSG("Verify Key type unknown"); ret = ASN_UNKNOWN_OID_E; @@ -4659,6 +4809,18 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + ret = wc_ed25519_verify_msg(sig, sigSz, buf, bufSz, + &sigCtx->verify, sigCtx->key.ed25519); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + sigCtx->asyncDev = &sigCtx->key.ecc->asyncDev; + #endif + break; + } + #endif default: break; } /* switch (keyOID) */ @@ -4724,6 +4886,19 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("ED25519 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + #endif /* HAVE_ED25519 */ default: break; } /* switch (keyOID) */ @@ -7106,6 +7281,110 @@ int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen, return SetEccPublicKey(output, key, with_AlgCurve); } #endif /* HAVE_ECC && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */ +#if defined(HAVE_ED25519) && (defined(WOLFSSL_CERT_GEN) || \ + defined(WOLFSSL_KEY_GEN)) + +/* Write a public ECC key to output */ +static int SetEd25519PublicKey(byte* output, ed25519_key* key, int with_header) +{ + byte bitString[1 + MAX_LENGTH_SZ + 1]; + int algoSz; + int bitStringSz; + int idx; + word32 pubSz = ED25519_PUB_KEY_SIZE; +#ifdef WOLFSSL_SMALL_STACK + byte* algo = NULL; + byte* pub = NULL; +#else + byte algo[MAX_ALGO_SZ]; + byte pub[ED25519_PUB_KEY_SIZE]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) + return MEMORY_E; +#endif + + int ret = wc_ed25519_export_public(key, pub, &pubSz); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* headers */ + if (with_header) { +#ifdef WOLFSSL_SMALL_STACK + algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + algoSz = SetAlgoID(ED25519k, algo, oidKeyType, 0); + + bitStringSz = SetBitString(pubSz, 0, bitString); + + idx = SetSequence(pubSz + bitStringSz + algoSz, output); + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* bit string */ + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; + } + else + idx = 0; + + /* pub */ + XMEMCPY(output + idx, pub, pubSz); + idx += pubSz; + +#ifdef WOLFSSL_SMALL_STACK + if (with_header) { + XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + +int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, word32 inLen, + int withAlg) +{ + word32 infoSz = 0; + word32 keySz = 0; + int ret; + + if (output == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if (withAlg) { + /* buffer space for algorithm */ + infoSz += MAX_SEQ_SZ; + infoSz += MAX_ALGO_SZ; + + /* buffer space for public key sequence */ + infoSz += MAX_SEQ_SZ; + infoSz += TRAILING_ZERO; + } + + if ((ret = wc_ed25519_export_public(key, output, &keySz)) != BUFFER_E) { + WOLFSSL_MSG("Error in getting ECC public key size"); + return ret; + } + + if (inLen < keySz + infoSz) { + return BUFFER_E; + } + + return SetEd25519PublicKey(output, key, withAlg); +} +#endif /* HAVE_ED25519 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */ #if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) static INLINE byte itob(int number) @@ -7866,13 +8145,15 @@ int SetName(byte* output, word32 outputSz, CertName* name) /* encode info from cert into DER encoded format */ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, - WC_RNG* rng, const byte* ntruKey, word16 ntruSz) + WC_RNG* rng, const byte* ntruKey, word16 ntruSz, + ed25519_key* ed25519Key) { int ret; (void)eccKey; (void)ntruKey; (void)ntruSz; + (void)ed25519Key; if (cert == NULL || der == NULL || rng == NULL) return BAD_FUNC_ARG; @@ -7916,6 +8197,16 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, } #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + if (cert->keyType == ED25519_KEY) { + if (ed25519Key == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1); + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + } +#endif + #ifdef HAVE_NTRU if (cert->keyType == NTRU_KEY) { word32 rc; @@ -8174,8 +8465,8 @@ static int WriteCertBody(DerCert* der, byte* buffer) /* Make RSA signature from buffer (sz), write to sig (sigSz) */ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, - byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, - int sigAlgoType, void* heap) + byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey, + ed25519_key* ed25519Key, WC_RNG* rng, int sigAlgoType, void* heap) { int digestSz = 0, typeH = 0, ret = 0; @@ -8187,6 +8478,7 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, (void)sigSz; (void)rsaKey; (void)eccKey; + (void)ed25519Key; (void)rng; switch (certSignCtx->state) { @@ -8200,65 +8492,8 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, ret = MEMORY_E; goto exit_ms; } - switch (sigAlgoType) { - #ifndef NO_MD5 - case CTC_MD5wRSA: - if ((ret = wc_Md5Hash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = MD5h; - digestSz = MD5_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA - case CTC_SHAwRSA: - case CTC_SHAwECDSA: - if ((ret = wc_ShaHash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA224 - case CTC_SHA224wRSA: - case CTC_SHA224wECDSA: - if ((ret = wc_Sha224Hash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = SHA224h; - digestSz = SHA224_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA256 - case CTC_SHA256wRSA: - case CTC_SHA256wECDSA: - if ((ret = wc_Sha256Hash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA384 - case CTC_SHA384wRSA: - case CTC_SHA384wECDSA: - if ((ret = wc_Sha384Hash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA512 - case CTC_SHA512wRSA: - case CTC_SHA512wECDSA: - if ((ret = wc_Sha512Hash(buffer, sz, certSignCtx->digest)) == 0) { - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - } - break; - #endif - default: - WOLFSSL_MSG("MakeSignautre called with unsupported type"); - ret = ALGO_ID_E; - } - + ret = HashForSignature(buffer, sz, sigAlgoType, certSignCtx->digest, + &typeH, &digestSz, 0); /* set next state, since WC_PENDING rentry for these are not "call again" */ certSignCtx->state = CERTSIGN_STATE_ENCODE; if (ret != 0) { @@ -8304,6 +8539,16 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, ret = outSz; } #endif /* HAVE_ECC */ + + #ifdef HAVE_ED25519 + if (!rsaKey && !eccKey && ed25519Key) { + word32 outSz = sigSz; + + ret = wc_ed25519_sign_msg(buffer, sz, sig, &outSz, ed25519Key); + if (ret == 0) + ret = outSz; + } + #endif /* HAVE_ECC */ break; } @@ -8357,7 +8602,8 @@ static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz, /* Make an x509 Certificate v3 any key type from cert input, write to buffer */ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, - const byte* ntruKey, word16 ntruSz) + const byte* ntruKey, word16 ntruSz, + ed25519_key* ed25519Key) { int ret; #ifdef WOLFSSL_SMALL_STACK @@ -8366,7 +8612,8 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, DerCert der[1]; #endif - cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : NTRU_KEY); + cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : + (ed25519Key ? ED25519_KEY : NTRU_KEY)); #ifdef WOLFSSL_SMALL_STACK der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -8374,7 +8621,8 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, return MEMORY_E; #endif - ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz); + ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz, + ed25519Key); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) ret = BUFFER_E; @@ -8390,11 +8638,30 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, } +/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */ +int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, + void* key, WC_RNG* rng) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0, + ed25519Key); +} /* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */ int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) { - return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0); + return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0, + NULL); } @@ -8483,10 +8750,11 @@ static int SetReqAttrib(byte* output, char* pw, int extSz) /* encode info from cert into DER encoded format */ -static int EncodeCertReq(Cert* cert, DerCert* der, - RsaKey* rsaKey, ecc_key* eccKey) +static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, + ecc_key* eccKey, ed25519_key* ed25519Key) { (void)eccKey; + (void)ed25519Key; if (cert == NULL || der == NULL) return BAD_FUNC_ARG; @@ -8522,6 +8790,16 @@ static int EncodeCertReq(Cert* cert, DerCert* der, } #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + if (cert->keyType == ED25519_KEY) { + if (ed25519Key == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1); + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + } +#endif /* HAVE_ED25519 */ + /* set the extensions */ der->extensionsSz = 0; @@ -8657,8 +8935,8 @@ static int WriteCertReqBody(DerCert* der, byte* buffer) } -int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, - RsaKey* rsaKey, ecc_key* eccKey) +static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, + RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key) { int ret; #ifdef WOLFSSL_SMALL_STACK @@ -8667,7 +8945,7 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, DerCert der[1]; #endif - cert->keyType = eccKey ? ECC_KEY : RSA_KEY; + cert->keyType = eccKey ? ECC_KEY : (ed25519Key ? ED25519_KEY : RSA_KEY); #ifdef WOLFSSL_SMALL_STACK der = (DerCert*)XMALLOC(sizeof(DerCert), NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -8675,7 +8953,7 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, return MEMORY_E; #endif - ret = EncodeCertReq(cert, der, rsaKey, eccKey); + ret = EncodeCertReq(cert, der, rsaKey, eccKey, ed25519Key); if (ret == 0) { if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) @@ -8691,11 +8969,34 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, return ret; } +int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, + void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, ed25519Key); +} + +int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, + RsaKey* rsaKey, ecc_key* eccKey) +{ + return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, NULL); +} #endif /* WOLFSSL_CERT_REQ */ -int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, - RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) +static int SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, + RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key, + WC_RNG* rng) { int sigSz = 0; void* heap = NULL; @@ -8737,7 +9038,7 @@ int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, } sigSz = MakeSignature(certSignCtx, buffer, requestSz, certSignCtx->sig, - MAX_ENCODED_SIG_SZ, rsaKey, eccKey, rng, sType, heap); + MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, rng, sType, heap); if (sigSz == WC_PENDING_E) return sigSz; @@ -8754,6 +9055,30 @@ int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, return sigSz; } +int wc_SignCert_ex(int requestSz, int sType, byte* buffer, word32 buffSz, + int keyType, void* key, WC_RNG* rng) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SignCert(requestSz, sType, buffer, buffSz, rsaKey, eccKey, + ed25519Key, rng); +} + +int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, + RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) +{ + return SignCert(requestSz, sType, buffer, buffSz, rsaKey, eccKey, NULL, + rng); +} int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, RsaKey* key, WC_RNG* rng) @@ -8773,7 +9098,8 @@ int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, /* Set KID from RSA or ECC public key */ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, - byte *ntruKey, word16 ntruKeySz, int kid_type) + byte *ntruKey, word16 ntruKeySz, + ed25519_key* ed25519Key, int kid_type) { byte *buffer; int bufferSz, ret; @@ -8782,7 +9108,9 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, (void)ntruKeySz; #endif - if (cert == NULL || (rsakey == NULL && eckey == NULL && ntruKey == NULL) || + if (cert == NULL || + (rsakey == NULL && eckey == NULL && ntruKey == NULL && + ed25519Key == NULL) || (rsakey != NULL && eckey != NULL) || (rsakey != NULL && ntruKey != NULL) || (ntruKey != NULL && eckey != NULL) || @@ -8812,6 +9140,11 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, bufferSz = -1; } #endif +#ifdef HAVE_ED25519 + /* ED25519 public key */ + else if (ed25519Key != NULL) + bufferSz = SetEd25519PublicKey(buffer, ed25519Key, 0); +#endif /* HAVE_ECC */ else bufferSz = -1; @@ -8849,10 +9182,27 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, return ret; } +int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key, + SKID_TYPE); +} + /* Set SKID from RSA or ECC public key */ int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) { - return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, SKID_TYPE); + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, SKID_TYPE); } #ifdef HAVE_NTRU @@ -8860,14 +9210,32 @@ int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey, word16 ntruKeySz) { - return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, SKID_TYPE); + return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, NULL, + SKID_TYPE); } #endif +int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key, + AKID_TYPE); +} + /* Set SKID from RSA or ECC public key */ int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) { - return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, AKID_TYPE); + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, AKID_TYPE); } @@ -9847,6 +10215,177 @@ int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + +int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, + ed25519_key* key, word32 inSz) +{ + word32 oid; + int ret, version, length, endKeyIdx, privSz, pubSz; + const byte* priv; + const byte* pub; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + endKeyIdx = *inOutIdx + length; + + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) + return ASN_PARSE_E; + if (version != 0) { + WOLFSSL_MSG("Unrecognized version of ED25519 private key"); + return ASN_PARSE_E; + } + + if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) + return ASN_PARSE_E; + if (oid != ED25519k) + return ASN_PARSE_E; + + if (GetOctetString(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) + return ASN_PARSE_E; + priv = input + *inOutIdx; + *inOutIdx += privSz; + + if (endKeyIdx == (int)*inOutIdx) { + ret = wc_ed25519_import_private_only(priv, privSz, key); + } + else { + if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1, + inOutIdx, &length, inSz) < 0) { + return ASN_PARSE_E; + } + if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0) + return ASN_PARSE_E; + pub = input + *inOutIdx; + *inOutIdx += pubSz; + + ret = wc_ed25519_import_private_key(priv, privSz, pub, pubSz, key); + } + if (ret == 0 && endKeyIdx != (int)*inOutIdx) + return ASN_PARSE_E; + + return ret; +} + + +int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx, + ed25519_key* key, word32 inSz) +{ + int length; + int ret; +#ifdef ECC_CHECK_PUBLIC_KEY_OID + word32 oidSum; +#endif + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + ret = SkipObjectId(input, inOutIdx, inSz); + if (ret != 0) + return ret; + + /* key header */ + ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + if (ret != 0) + return ret; + + /* This is the raw point data compressed or uncompressed. */ + if (wc_ed25519_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0) + return ASN_ECC_KEY_E; + + return 0; +} + + +#ifdef WOLFSSL_KEY_GEN + +/* build DER formatted ED25519 key, + * return length on success, negative on error */ +static int wc_BuildEd25519KeyDer(ed25519_key* key, byte* output, word32 inLen, + int pubOut) +{ + byte algoArray[MAX_ALGO_SZ]; + byte ver[MAX_VERSION_SZ]; + byte seq[MAX_SEQ_SZ]; + int ret; + word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0; + + if (key == NULL || output == NULL || inLen == 0) + return BAD_FUNC_ARG; + + if (pubOut) + pubSz = 2 + 2 + ED25519_PUB_KEY_SIZE; + privSz = 2 + 2 + ED25519_KEY_SIZE; + algoSz = SetAlgoID(ED25519k, algoArray, oidKeyType, 0); + verSz = SetMyVersion(0, ver, FALSE); + seqSz = SetSequence(verSz + algoSz + privSz + pubSz, seq); + + if (seqSz + verSz + algoSz + privSz + pubSz > inLen) + return BAD_FUNC_ARG; + + /* write out */ + /* seq */ + XMEMCPY(output + idx, seq, seqSz); + idx = seqSz; + /* ver */ + XMEMCPY(output + idx, ver, verSz); + idx += verSz; + /* algo */ + XMEMCPY(output + idx, algoArray, algoSz); + idx += algoSz; + /* privKey */ + idx += SetOctetString(2 + ED25519_KEY_SIZE, output + idx); + idx += SetOctetString(ED25519_KEY_SIZE, output + idx); + ret = wc_ed25519_export_private_only(key, output + idx, &privSz); + if (ret != 0) + return ret; + idx += privSz; + /* pubKey */ + if (pubOut) { + idx += SetExplicit(1, 2 + ED25519_PUB_KEY_SIZE, output + idx); + idx += SetOctetString(ED25519_KEY_SIZE, output + idx); + ret = wc_ed25519_export_public(key, output + idx, &pubSz); + if (ret != 0) + return ret; + idx += pubSz; + } + + return idx; +} + +/* Write a Private ecc key, including public to DER format, + * length on success else < 0 */ +int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, word32 inLen) +{ + return wc_BuildEd25519KeyDer(key, output, inLen, 1); +} + + + +/* Write only private ecc key to DER format, + * length on success else < 0 */ +int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, word32 inLen) +{ + return wc_BuildEd25519KeyDer(key, output, inLen, 0); +} + +#endif /* WOLFSSL_KEY_GEN */ + +#endif /* HAVE_ED25519 */ + + #if defined(HAVE_OCSP) || defined(HAVE_CRL) /* Get raw Date only, no processing, 0 on success */ diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 258631b00..22ced3d1b 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -210,7 +210,7 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, res will be 1 on successful verify and 0 on unsuccessful return 0 and res of 1 on success */ -int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, +int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg, word32 msglen, int* res, ed25519_key* key) { byte rcheck[ED25519_KEY_SIZE]; @@ -407,6 +407,25 @@ int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key) } +/* + For importing a private key. + */ +int wc_ed25519_import_private_only(const byte* priv, word32 privSz, + ed25519_key* key) +{ + /* sanity check on arguments */ + if (priv == NULL || key == NULL) + return BAD_FUNC_ARG; + + /* key size check */ + if (privSz < ED25519_KEY_SIZE) + return BAD_FUNC_ARG; + + XMEMCPY(key->k, priv, ED25519_KEY_SIZE); + + return 0; +} + /* For importing a private key and its associated public key. */ @@ -508,6 +527,14 @@ int wc_ed25519_export_key(ed25519_key* key, #endif /* HAVE_ED25519_KEY_EXPORT */ +/* check the private and public keys match */ +int wc_ed25519_check_key(ed25519_key* key) +{ + /* TODO: Perform check of private and public key */ + (void)key; + + return 0; +} /* returns the private key size (secret only) in bytes */ int wc_ed25519_size(ed25519_key* key) diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index a6ef14fa2..42be1f71c 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -239,10 +239,11 @@ enum Block_Sum { enum Key_Sum { - DSAk = 515, - RSAk = 645, - NTRUk = 274, - ECDSAk = 518 + DSAk = 515, + RSAk = 645, + NTRUk = 274, + ECDSAk = 518, + ED25519k = 256 }; @@ -434,10 +435,13 @@ struct SignatureCtx { #endif union { #ifndef NO_RSA - struct RsaKey* rsa; + struct RsaKey* rsa; #endif #ifdef HAVE_ECC - struct ecc_key* ecc; + struct ecc_key* ecc; + #endif + #ifdef HAVE_ED25519 + struct ed25519_key* ed25519; #endif void* ptr; } key; @@ -814,7 +818,8 @@ enum cert_enums { EMAIL_JOINT_LEN = 9, RSA_KEY = 10, NTRU_KEY = 11, - ECC_KEY = 12 + ECC_KEY = 12, + ED25519_KEY = 13 }; #ifndef WOLFSSL_PEMCERT_TODER_DEFINED diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 1fdfa61ef..9adf13cf5 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -35,6 +35,10 @@ typedef struct ecc_key ecc_key; #define WC_ECCKEY_TYPE_DEFINED #endif +#ifndef WC_ED25519KEY_TYPE_DEFINED + typedef struct ed25519_key ed25519_key; + #define WC_ED25519KEY_TYPE_DEFINED +#endif #ifndef WC_RSAKEY_TYPE_DEFINED typedef struct RsaKey RsaKey; #define WC_RSAKEY_TYPE_DEFINED @@ -61,7 +65,8 @@ enum CertType { PUBLICKEY_TYPE, RSA_PUBLICKEY_TYPE, ECC_PUBLICKEY_TYPE, - TRUSTED_PEER_TYPE + TRUSTED_PEER_TYPE, + ED25519_TYPE }; @@ -79,7 +84,8 @@ enum Ctc_SigType { CTC_SHA384wRSA = 656, CTC_SHA384wECDSA = 525, CTC_SHA512wRSA = 657, - CTC_SHA512wECDSA = 526 + CTC_SHA512wECDSA = 526, + CTC_ED25519 = 256 }; enum Ctc_Encoding { @@ -174,14 +180,21 @@ typedef struct Cert { keyType = RSA_KEY (default) */ WOLFSSL_API void wc_InitCert(Cert*); +WOLFSSL_API int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, + int keyType, void* key, WC_RNG* rng); WOLFSSL_API int wc_MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, - ecc_key*, WC_RNG*); + ecc_key*, WC_RNG*); #ifdef WOLFSSL_CERT_REQ + WOLFSSL_API int wc_MakeCertReq_ex(Cert*, byte* derBuffer, word32 derSz, + int, void*); WOLFSSL_API int wc_MakeCertReq(Cert*, byte* derBuffer, word32 derSz, RsaKey*, ecc_key*); #endif +WOLFSSL_API int wc_SignCert_ex(int requestSz, int sType, byte* buffer, + word32 buffSz, int keyType, void* key, + WC_RNG* rng); WOLFSSL_API int wc_SignCert(int requestSz, int sigType, byte* derBuffer, - word32 derSz, RsaKey*, ecc_key*, WC_RNG*); + word32 derSz, RsaKey*, ecc_key*, WC_RNG*); WOLFSSL_API int wc_MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, WC_RNG*); WOLFSSL_API int wc_SetIssuer(Cert*, const char*); @@ -195,10 +208,14 @@ WOLFSSL_API int wc_SetAltNamesBuffer(Cert*, const byte*, int); WOLFSSL_API int wc_SetDatesBuffer(Cert*, const byte*, int); #ifdef WOLFSSL_CERT_EXT +WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, + void* key); WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey); WOLFSSL_API int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz); WOLFSSL_API int wc_SetAuthKeyId(Cert *cert, const char* file); +WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, + void* key); WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey); WOLFSSL_API int wc_SetSubjectKeyId(Cert *cert, const char* file); @@ -267,6 +284,24 @@ WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); #endif #endif +#ifdef HAVE_ED25519 + /* private key helpers */ + WOLFSSL_API int wc_Ed25519PrivateKeyDecode(const byte*, word32*, + ed25519_key*, word32); + WOLFSSL_API int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, + word32 inLen); + WOLFSSL_API int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, + word32 inLen); + + /* public key helper */ + WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte*, word32*, + ed25519_key*, word32); + #if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) + WOLFSSL_API int wc_Ed25519PublicKeyToDer(ed25519_key*, byte* output, + word32 inLen, int with_AlgCurve); + #endif +#endif + /* DER encode signature */ WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID); diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index ea88603a3..f806785aa 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -54,8 +54,14 @@ /* both private and public key */ #define ED25519_PRV_KEY_SIZE (ED25519_PUB_KEY_SIZE+ED25519_KEY_SIZE) + +#ifndef WC_ED25519KEY_TYPE_DEFINED + typedef struct ed25519_key ed25519_key; + #define WC_ED25519KEY_TYPE_DEFINED +#endif + /* An ED25519 Key */ -typedef struct { +struct ed25519_key { byte p[ED25519_PUB_KEY_SIZE]; /* compressed public key */ byte k[ED25519_PRV_KEY_SIZE]; /* private key : 32 secret -- 32 public */ #ifdef FREESCALE_LTC_ECC @@ -63,7 +69,7 @@ typedef struct { byte pointX[ED25519_KEY_SIZE]; /* recovered X coordinate */ byte pointY[ED25519_KEY_SIZE]; /* Y coordinate is the public key with The most significant bit of the final octet always zero. */ #endif -} ed25519_key; +}; WOLFSSL_API @@ -72,7 +78,7 @@ WOLFSSL_API int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, word32 *outlen, ed25519_key* key); WOLFSSL_API -int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, +int wc_ed25519_verify_msg(const byte* sig, word32 siglen, const byte* msg, word32 msglen, int* stat, ed25519_key* key); WOLFSSL_API int wc_ed25519_init(ed25519_key* key); @@ -81,6 +87,9 @@ void wc_ed25519_free(ed25519_key* key); WOLFSSL_API int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key); WOLFSSL_API +int wc_ed25519_import_private_only(const byte* priv, word32 privSz, + ed25519_key* key); +WOLFSSL_API int wc_ed25519_import_private_key(const byte* priv, word32 privSz, const byte* pub, word32 pubSz, ed25519_key* key); WOLFSSL_API @@ -94,6 +103,8 @@ int wc_ed25519_export_key(ed25519_key* key, byte* priv, word32 *privSz, byte* pub, word32 *pubSz); +int wc_ed25519_check_key(ed25519_key* key); + /* size helper */ WOLFSSL_API int wc_ed25519_size(ed25519_key* key); diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 044fcfd06..5b23efeb2 100755 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -416,6 +416,7 @@ DYNAMIC_TYPE_ASYNC_NUMA = 67, DYNAMIC_TYPE_ASYNC_NUMA64 = 68, DYNAMIC_TYPE_CURVE25519 = 69, + DYNAMIC_TYPE_ED25519 = 70, }; /* max error buffer string size */ From 613d30bcae2734ea802701f34bcee36a45198a16 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Tue, 30 May 2017 16:04:24 +1000 Subject: [PATCH 23/34] ED25519 TLS support --- certs/ed25519/ca-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/ca-ed25519-key.pem | 4 + certs/ed25519/ca-ed25519.der | Bin 0 -> 605 bytes certs/ed25519/ca-ed25519.pem | 15 + certs/ed25519/client-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/client-ed25519-key.pem | 4 + certs/ed25519/client-ed25519.der | Bin 0 -> 597 bytes certs/ed25519/client-ed25519.pem | 15 + certs/ed25519/root-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/root-ed25519-key.pem | 4 + certs/ed25519/root-ed25519.der | Bin 0 -> 607 bytes certs/ed25519/root-ed25519.pem | 15 + certs/ed25519/server-ed25519-key.der | Bin 0 -> 84 bytes certs/ed25519/server-ed25519-key.pem | 4 + certs/ed25519/server-ed25519.der | Bin 0 -> 591 bytes certs/ed25519/server-ed25519.pem | 30 ++ src/internal.c | 546 +++++++++++++++++++++++---- src/ssl.c | 179 ++++++++- src/tls.c | 112 +++--- src/tls13.c | 91 ++++- tests/suites.c | 10 + tests/test-ed25519.conf | 56 +++ tests/test-tls13.conf | 12 + tests/test.conf | 12 + wolfcrypt/src/asn.c | 15 +- wolfssl/internal.h | 40 +- wolfssl/ssl.h | 21 ++ wolfssl/test.h | 59 ++- wolfssl/wolfcrypt/asn.h | 1 + 29 files changed, 1091 insertions(+), 154 deletions(-) create mode 100644 certs/ed25519/ca-ed25519-key.der create mode 100644 certs/ed25519/ca-ed25519-key.pem create mode 100644 certs/ed25519/ca-ed25519.der create mode 100644 certs/ed25519/ca-ed25519.pem create mode 100644 certs/ed25519/client-ed25519-key.der create mode 100644 certs/ed25519/client-ed25519-key.pem create mode 100644 certs/ed25519/client-ed25519.der create mode 100644 certs/ed25519/client-ed25519.pem create mode 100644 certs/ed25519/root-ed25519-key.der create mode 100644 certs/ed25519/root-ed25519-key.pem create mode 100644 certs/ed25519/root-ed25519.der create mode 100644 certs/ed25519/root-ed25519.pem create mode 100644 certs/ed25519/server-ed25519-key.der create mode 100644 certs/ed25519/server-ed25519-key.pem create mode 100644 certs/ed25519/server-ed25519.der create mode 100644 certs/ed25519/server-ed25519.pem create mode 100644 tests/test-ed25519.conf diff --git a/certs/ed25519/ca-ed25519-key.der b/certs/ed25519/ca-ed25519-key.der new file mode 100644 index 0000000000000000000000000000000000000000..01156fec2949fb7c50ca359e52a69a5386fd10bf GIT binary patch literal 84 zcmV-a0IUBnQUU=0Fa-t!D`jv5A_O2!#L1OW{s!oN^&ld^p12M2XVE(iw9v(F$1pY! qg}h~d7ZKRI~^5UJRL&78|n0~D15+F7J literal 0 HcmV?d00001 diff --git a/certs/ed25519/ca-ed25519-key.pem b/certs/ed25519/ca-ed25519-key.pem new file mode 100644 index 000000000..a78c396f7 --- /dev/null +++ b/certs/ed25519/ca-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN RSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEIE3EyZVR/gbofvUgIsCeuA3yZ9E7DbTQxW7HMDYQhbxl +oSIEIEEH7HUMaHISPASCB24Wb0BBbaSPCPLinadDwiQomH6s +-----END RSA PRIVATE KEY----- diff --git a/certs/ed25519/ca-ed25519.der b/certs/ed25519/ca-ed25519.der new file mode 100644 index 0000000000000000000000000000000000000000..fd6f31d1d8517b5f991fd05ce1de26065becfb5a GIT binary patch literal 605 zcmXqLVv00qV&Y!F%*4pV#KHLOq1~R!g{=mxY|PrJ1qO}t4Y>_C*_cCF*o2uvgAD}? z_&^*E9(LdSypqJcM3@LW54%%-RcdZxo*}ORH%JW&4@*#fehEwg7Y}=Reok6&un$ax zn}^-i#mLmu(9%%CKn$dXnTNl;yj%~YuDCcyFF8NgP~Je6jZ>@5qwPB{BPXMnKxSTA zz5|j110@N5BLhQo15+alBV!{oBg-hTfF)4C5-MQOIG1!^K)ubv!{qD;b1|*_pal(X zW<>@^_BW+G8AU=iEKTfrV)+h^xl8&vK0TVd-1(4-#*Df(ixUmv4S0ZoB`eIrYQW6M z_#YTRKpr297>mfHtK7FfvUKlU*v-r|KZ3#3jJ@ilfjmfBnFScc4I*s^)L+i~)q3#n z_C*_cCF*o2uvgAD}? z_&^*E9(LdSypqJcM3@LW54%%-RcdZxo*};hFGvjw4_k6hW@=suObHhcdwG6NT5zxr zOoW?<-POg&)YQ<@P{KeAq=}h_zr4I$52UWRI7crzKi5#+K$eYDtIebBJ1-+AqnJQu zURu5bk^%!I34S93LvsUDBMT#ABQqn*D6oJfP{0x@FeLn;1r2m&MFun5z3>M~4Sw0pq7LjGs3ns^8PS&1gB-dVT zwrlb%&G3%~@*rtt7GS_OU{}BoQozs1_@9N9nThQH1I&6yhAE57Za5A5dySyj|tE8D+BHB(G4DdmqLC literal 0 HcmV?d00001 diff --git a/certs/ed25519/root-ed25519-key.pem b/certs/ed25519/root-ed25519-key.pem new file mode 100644 index 000000000..be922d961 --- /dev/null +++ b/certs/ed25519/root-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN RSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEIFwOftlJ9QL4yEBIBh9UmTRwCu+A6puPK9OFmVk0A19P +oSIEIKZgKbt92EfL1B7QbQ9XANgqH1BqQrxd5bgZZbLfJK9Q +-----END RSA PRIVATE KEY----- diff --git a/certs/ed25519/root-ed25519.der b/certs/ed25519/root-ed25519.der new file mode 100644 index 0000000000000000000000000000000000000000..f4da216c4f44dcba10db9f1767a80bb3ffce814a GIT binary patch literal 607 zcmXqLVv06sV&YxE%*4pV#KCyf@ZAev3poQ;HfHVA0)xi+hTI06Y|No7Y{E>T!G;0` zd>{@754&%EUP)qJB20vxhutZ^Dm6DT&yd%E8>EJXhb1UKzXYa$i-)~DKPN3X*as%U z&BN~MVq|J+XlW>6AO_OH%)?(^UakjHS6rNPUy-|z z%OB2gLrXp&%V|&S(;bqjo9?Tu4_KUN5O2T(3@%w=7FGjhM#lfZAOiCESj1RF+776{ zocF8s;NQpje?lUQ%#RyS+HD{Yl2&E`266*-1^gfd{6LdfSb@pl7z4~Pjto+^WnbJY zW|nVu>~3Q@bFV3Q?Vjk*cfI;`1Sh-n**2}(aQka|SnJRGsrjuh-<;5Ta{qVWv=^lZ OPTrg2qB{5Feog@FP_5Gd literal 0 HcmV?d00001 diff --git a/certs/ed25519/root-ed25519.pem b/certs/ed25519/root-ed25519.pem new file mode 100644 index 000000000..1356b21cc --- /dev/null +++ b/certs/ed25519/root-ed25519.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICWzCCAg2gAwIBAgIIAcUx7uhNOB4wBQYDK2VwMIGfMQswCQYDVQQGEwJVUzEQ +MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjENMAsGA1UEBAwEUm9v +dDEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYGA1UEAwwP +d3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MCIYDzIwMTcwNTI4MjMyNjI5WhgPMjAxOTA1MjkyMzI2MjlaMIGfMQswCQYDVQQG +EwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjENMAsGA1UE +BAwEUm9vdDEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYG +A1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZz +c2wuY29tMCowBQYDK2VwAyEApmApu33YR8vUHtBtD1cA2CofUGpCvF3luBllst8k +r1CjYTBfMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFIbAJ+me+oXB/eNv/FRZcjfH +M5K7MB8GA1UdIwQYMBaAFIbAJ+me+oXB/eNv/FRZcjfHM5K7MA8GA1UdDwEB/wQF +AwIBxgAwBQYDK2VwA0EAGj129Ed4mXezQYuGBMzeglOtvFvz3UqPLBGTRI49gqqw +2/VnVoX532VvhensyCrk3/tRluh1wMnenEQlncm/CQ== +-----END CERTIFICATE----- diff --git a/certs/ed25519/server-ed25519-key.der b/certs/ed25519/server-ed25519-key.der new file mode 100644 index 0000000000000000000000000000000000000000..3c966a31b58677514764749a87ddc9a60e39283e GIT binary patch literal 84 zcmV-a0IUBnQUU=0Fa-t!D`jv5A_O4V>2|U|ANPoL_1*Y-#z`=4>7UD;9xK2Y@4I!0 q=67eIA_O2BFo+mOFPGW`^rYjxYz!8;NWsxU*N&2epmZujo(?I5QX}60 literal 0 HcmV?d00001 diff --git a/certs/ed25519/server-ed25519-key.pem b/certs/ed25519/server-ed25519-key.pem new file mode 100644 index 000000000..5699e0a7c --- /dev/null +++ b/certs/ed25519/server-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN RSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEINjpdrI/H/eIdfXd+HrGSTBu6Z/LnR4rwBjvu3WJ5ndn +oSIEIBowiBhHL5faBPSk471sDBa5SMHRQteOkoSgdCpDng4p +-----END RSA PRIVATE KEY----- diff --git a/certs/ed25519/server-ed25519.der b/certs/ed25519/server-ed25519.der new file mode 100644 index 0000000000000000000000000000000000000000..9dc76898affb4b6c704ab2f524b9310a53c0885a GIT binary patch literal 591 zcmXqLV)8aT!G;0` zd>{@754&%EUP)qJB20vxhutZ^Dm6DT52k^IhsoIyCe6jeUY?(m798vY6XE7zcXcr` zH8r#}lrRtj8OqGVUtV6W2U1sDoTHbVpKB;@Aj`(7)#lOmotKf5QA{8+FD>5zNr8cq z1iz7ip}B#nk%f`5k(rTY6j;C#C}0T{Fld|)a}x1>;5Fa|If;db#V0i}4d!NA`9cdC z+{}s$QU)Co?)uYjv3yzbcyA7m*iMgw7oD#6O=?+CqUAh~PjhjwK_D4AusbNmsdVePrq0xv-m=X?_HQsTq6K zNdtb60)9ru|17M`Ol$`jVAeY_2!)mNOmmuX>!fIopT|^I*$Wj$Kib@8xy?@LHrybY nT|Tq>{~snZR_;vm_N3BV0Xn*|K~wA*=1REcn+x@QdBOkyhashSigAlgo[idx++] = sha_mac; suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; #endif + #ifdef HAVE_ED25519 + suites->hashSigAlgo[idx++] = ED25519_SA_MAJOR; + suites->hashSigAlgo[idx++] = ED25519_SA_MINOR; + #endif } if (haveRSAsig) { @@ -2652,17 +2656,24 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, static INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType) { switch (input[0]) { + case NEW_SA_MAJOR: #ifdef WC_RSA_PSS - case rsa_pss_sa_algo: - /* PSS signatures: 0x080[4-6] */ - if (input[1] <= sha512_mac) { - *hsType = input[0]; - *hashAlgo = input[1]; - } - break; + /* PSS signatures: 0x080[4-6] */ + if (input[1] <= sha512_mac) { + *hsType = input[0]; + *hashAlgo = input[1]; + } #endif - /* ED25519: 0x0807 */ - /* ED448: 0x0808 */ + #ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + if (input[1] == ED25519_SA_MINOR) { + *hsType = ed25519_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + #endif + /* ED448: 0x0808 */ + break; default: *hashAlgo = input[0]; *hsType = input[1]; @@ -2828,6 +2839,12 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) output[0] = hashAlgo; output[1] = ecc_dsa_sa_algo; break; + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + output[0] = ED25519_SA_MAJOR; + output[1] = ED25519_SA_MINOR; + break; + #endif #endif #ifndef NO_RSA case rsa_sa_algo: @@ -2842,7 +2859,6 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) break; #endif #endif - /* ED25519: 0x0807 */ /* ED448: 0x0808 */ } } @@ -3420,6 +3436,108 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) return ret; } +#ifdef HAVE_ED25519 +/* Sign the data using EdDSA and key using X25519. + * + * ssl SSL object. + * in Data or message to sign. + * inSz Length of the data. + * out Buffer to hold signature. + * outSz On entry, size of the buffer. On exit, the size of the signature. + * key The private X25519 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on succes, otherwise the valus is an error. + */ +int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, ed25519_key* key, byte* keyBuf, word32 keySz, + void* ctx) +{ + int ret; + + (void)ssl; + (void)keyBuf; + (void)keySz; + (void)ctx; + + WOLFSSL_ENTER("Ed25519Sign"); + +#if defined(HAVE_PK_CALLBACKS) + if (ssl->ctx->Ed25519SignCb) { + ret = ssl->ctx->Ed25519SignCb(ssl, in, inSz, out, outSz, keyBuf, + keySz, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ed25519_sign_msg(in, inSz, out, outSz, key); + } + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("Ed25519Sign", ret); + + return ret; +} + +/* Verify the data using EdDSA and key using X25519. + * + * ssl SSL object. + * in Signature data. + * inSz Length of the signature data in bytes. + * msg Message to verify. + * outSz Length of message in bytes. + * key The public X25519 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on succes, otherwise the valus is an error. + */ +int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, + word32 msgSz, ed25519_key* key, byte* keyBuf, word32 keySz, + void* ctx) +{ + int ret; + + (void)ssl; + (void)keyBuf; + (void)keySz; + (void)ctx; + + WOLFSSL_ENTER("Ed25519Verify"); + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->Ed25519VerifyCb) { + ret = ssl->ctx->Ed25519VerifyCb(ssl, in, inSz, msg, msgSz, keyBuf, + keySz, &ssl->eccVerifyRes, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ed25519_verify_msg(in, inSz, msg, msgSz, + &ssl->eccVerifyRes, key); + } + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + } + else +#endif /* WOLFSSL_ASYNC_CRYPT */ + { + ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0; + } + + WOLFSSL_LEAVE("Ed25519Verify", ret); + + return ret; +} +#endif /* HAVE_ED25519 */ #ifdef HAVE_CURVE25519 #ifdef HAVE_PK_CALLBACKS @@ -4179,6 +4297,11 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey) wc_ecc_free((ecc_key*)*pKey); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_free((ed25519_key*)*pKey); + break; + #endif /* HAVE_CURVE25519 */ #ifdef HAVE_CURVE25519 case DYNAMIC_TYPE_CURVE25519: wc_curve25519_free((curve25519_key*)*pKey); @@ -4216,26 +4339,31 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) /* Determine size */ switch (type) { - #ifndef NO_RSA + #ifndef NO_RSA case DYNAMIC_TYPE_RSA: sz = sizeof(RsaKey); break; - #endif /* ! NO_RSA */ - #ifdef HAVE_ECC + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC case DYNAMIC_TYPE_ECC: sz = sizeof(ecc_key); break; - #endif /* HAVE_ECC */ - #ifdef HAVE_CURVE25519 + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + sz = sizeof(ed25519_key); + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_CURVE25519 case DYNAMIC_TYPE_CURVE25519: sz = sizeof(curve25519_key); break; - #endif /* HAVE_CURVE25519 */ - #ifndef NO_DH + #endif /* HAVE_CURVE25519 */ + #ifndef NO_DH case DYNAMIC_TYPE_DH: sz = sizeof(DhKey); break; - #endif /* !NO_DH */ + #endif /* !NO_DH */ default: return BAD_FUNC_ARG; } @@ -4262,6 +4390,12 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) ret = wc_ecc_init_ex((ecc_key*)*pKey, ssl->heap, ssl->devId); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_init((ed25519_key*)*pKey); + ret = 0; + break; + #endif /* HAVE_CURVE25519 */ #ifdef HAVE_CURVE25519 case DYNAMIC_TYPE_CURVE25519: wc_curve25519_init((curve25519_key*)*pKey); @@ -4303,6 +4437,12 @@ static int ReuseKey(WOLFSSL* ssl, int type, void* pKey) ret = wc_ecc_init_ex((ecc_key*)pKey, ssl->heap, ssl->devId); break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_free((ed25519_key*)pKey); + wc_ed25519_init((ed25519_key*)pKey); + break; + #endif /* HAVE_CURVE25519 */ #ifdef HAVE_CURVE25519 case DYNAMIC_TYPE_CURVE25519: wc_curve25519_free((curve25519_key*)pKey); @@ -4447,6 +4587,10 @@ void SSL_ResourceFree(WOLFSSL* ssl) ssl->peerX25519KeyPresent = 0; #endif #endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; +#endif #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC); @@ -7640,6 +7784,17 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz } break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (ssl->options.minEccKeySz < 0 || + ED25519_KEY_SIZE < + (word16)ssl->options.minEccKeySz) { + WOLFSSL_MSG( + "ECC key size in cert chain error"); + ret = ECC_KEY_SIZE_E; + } + break; + #endif /* HAVE_ED25519 */ default: WOLFSSL_MSG("Key size not checked"); /* key not being checked for size if not in @@ -8098,7 +8253,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz else { ssl->peerEccDsaKeyPresent = 1; #ifdef HAVE_PK_CALLBACKS - #ifdef HAVE_ECC ssl->buffers.peerEccDsaKey.buffer = (byte*)XMALLOC(args->dCert->pubKeySize, ssl->heap, DYNAMIC_TYPE_ECC); @@ -8112,7 +8266,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz ssl->buffers.peerEccDsaKey.length = args->dCert->pubKeySize; } - #endif /* HAVE_ECC */ #endif /*HAVE_PK_CALLBACKS */ } @@ -8126,6 +8279,56 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz } break; } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + int keyRet = 0; + if (ssl->peerEd25519Key == NULL) { + /* alloc/init on demand */ + keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEd25519Key); + } else if (ssl->peerEd25519KeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ECC, + ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; + } + + if (keyRet != 0 || + wc_ed25519_import_public(args->dCert->publicKey, + args->dCert->pubKeySize, + ssl->peerEd25519Key) + != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerEd25519KeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEd25519Key.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->buffers.peerEd25519Key.buffer == NULL) { + ERROR_OUT(MEMORY_ERROR, exit_ppc); + } + else { + XMEMCPY(ssl->buffers.peerEd25519Key.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerEd25519Key.length = + args->dCert->pubKeySize; + } + #endif /*HAVE_PK_CALLBACKS */ + } + + /* check size of peer ECC key */ + if (ret == 0 && ssl->peerEd25519KeyPresent && + !ssl->options.verifyNone && + ED25519_KEY_SIZE < ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Peer ECC key is too small"); + } + break; + } #endif /* HAVE_ECC */ default: break; @@ -15177,6 +15380,17 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, byte hashAlgo = 0, sigAlgo = 0; DecodeSigAlg(&hashSigAlgo[i], &hashAlgo, &sigAlgo); + #ifdef HAVE_ECC + if (ssl->pkCurveOID == ECC_ED25519_OID && sigAlgo != ed25519_sa_algo) + continue; + + if (sigAlgo == ed25519_sa_algo && + ssl->specs.sig_algo == ecc_dsa_sa_algo) { + ssl->suites->sigAlgo = sigAlgo; + ssl->suites->hashAlgo = sha512_mac; + break; + } + #endif if (sigAlgo == ssl->specs.sig_algo || (sigAlgo == rsa_pss_sa_algo && ssl->specs.sig_algo == rsa_sa_algo)) { if (hashAlgo == sha_mac) { @@ -16756,15 +16970,6 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } ssl->buffers.sig.length = SEED_LEN + verifySz; - /* buffer for hash */ - ssl->buffers.digest.length = wc_HashGetDigestSize(hashType); - ssl->buffers.digest.buffer = (byte*)XMALLOC( - ssl->buffers.digest.length, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (ssl->buffers.digest.buffer == NULL) { - ERROR_OUT(MEMORY_E, exit_dske); - } - /* build message to hash */ XMEMCPY(ssl->buffers.sig.buffer, ssl->arrays->clientRandom, RAN_LEN); @@ -16773,12 +16978,25 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN * 2], input + args->begin, verifySz); /* message */ - /* Perform hash */ - ret = wc_Hash(hashType, - ssl->buffers.sig.buffer, ssl->buffers.sig.length, - ssl->buffers.digest.buffer, ssl->buffers.digest.length); - if (ret != 0) { - goto exit_dske; + if (args->sigAlgo != ed25519_sa_algo) { + /* buffer for hash */ + ssl->buffers.digest.length = + wc_HashGetDigestSize(hashType); + ssl->buffers.digest.buffer = (byte*)XMALLOC( + ssl->buffers.digest.length, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->buffers.digest.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + + /* Perform hash */ + ret = wc_Hash(hashType, ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length); + if (ret != 0) { + goto exit_dske; + } } switch (args->sigAlgo) @@ -16805,6 +17023,15 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, break; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + if (!ssl->peerEd25519KeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* HAVE_ECC */ default: ret = ALGO_ID_E; @@ -16908,6 +17135,26 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, break; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + ret = Ed25519Verify(ssl, + args->verifySig, args->verifySigSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->peerEd25519Key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEccDsaKey.buffer, + ssl->buffers.peerEccDsaKey.length, + ssl->Ed25519VerifyCtx + #else + NULL, 0, NULL + #endif + ); + + break; + } + #endif /* HAVE_ECC */ default: ret = ALGO_ID_E; @@ -17016,6 +17263,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case ecc_dsa_sa_algo: /* Nothing to do in this algo */ break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + /* Nothing to do in this algo */ + break; #endif /* HAVE_ECC */ default: ret = ALGO_ID_E; @@ -18582,22 +18834,61 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, (ecc_key*)ssl->hsKey, ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using ECC private key"); + + /* Check it meets the minimum ECC key size requirements. */ + keySz = wc_ecc_size((ecc_key*)ssl->hsKey); + if (keySz < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ECC key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = wc_ecc_sig_size((ecc_key*)ssl->hsKey); + + goto exit_dpk; + } +#endif +#ifdef HAVE_ED25519 +#if !defined(NO_RSA) || defined(HAVE_ECC) + FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey); +#endif + + ssl->hsType = DYNAMIC_TYPE_ED25519; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { - WOLFSSL_MSG("Bad client cert type"); goto exit_dpk; } - WOLFSSL_MSG("Using ECC private key"); +#ifdef HAVE_ECC + WOLFSSL_MSG("Trying ED25519 private key, ECC didn't work"); +#elif !defined(NO_RSA) + WOLFSSL_MSG("Trying ED25519 private key, RSA didn't work"); +#else + WOLFSSL_MSG("Trying ED25519 private key"); +#endif - /* Check it meets the minimum ECC key size requirements. */ - keySz = wc_ecc_size((ecc_key*)ssl->hsKey); - if (keySz < ssl->options.minEccKeySz) { - WOLFSSL_MSG("ECC key size too small"); - ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an ED25519 private key. */ + ret = wc_Ed25519PrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (ed25519_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using ED25519 private key"); + + /* Check it meets the minimum ECC key size requirements. */ + if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ED25519 key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = ED25519_SIG_SIZE; + + goto exit_dpk; } - - /* Return the maximum signature length. */ - *length = wc_ecc_sig_size((ecc_key*)ssl->hsKey); #endif exit_dpk: @@ -18755,6 +19046,8 @@ int SendCertificateVerify(WOLFSSL* ssl) } else if (ssl->hsType == DYNAMIC_TYPE_ECC) args->sigAlgo = ecc_dsa_sa_algo; + else if (ssl->hsType == DYNAMIC_TYPE_ED25519) + args->sigAlgo = ed25519_sa_algo; if (IsAtLeastTLSv1_2(ssl)) { EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, @@ -18821,6 +19114,24 @@ int SendCertificateVerify(WOLFSSL* ssl) ); } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + ed25519_key* key = (ed25519_key*)ssl->hsKey; + + ret = Ed25519Sign(ssl, + ssl->buffers.digest.buffer, ssl->buffers.digest.length, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + key, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->Ed25519SignCtx + #else + NULL, 0, NULL + #endif + ); + } + #endif /* HAVE_ECC */ #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { RsaKey* key = (RsaKey*)ssl->hsKey; @@ -18867,6 +19178,16 @@ int SendCertificateVerify(WOLFSSL* ssl) ssl->buffers.sig.buffer, ssl->buffers.sig.length); } #endif /* HAVE_ECC */ + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + args->length = ssl->buffers.sig.length; + /* prepend hdr */ + c16toa((word16)ssl->buffers.sig.length, args->verify + + args->extraSz); + XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER, + ssl->buffers.sig.buffer, ssl->buffers.sig.length); + } + #endif /* HAVE_ECC */ #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { RsaKey* key = (RsaKey*)ssl->hsKey; @@ -19991,6 +20312,38 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } break; } + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + word32 i = 0; + + ssl->hsType = DYNAMIC_TYPE_ED25519; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_sske; + } + + ret = wc_Ed25519PrivateKeyDecode( + ssl->buffers.key->buffer, + &i, + (ed25519_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret != 0) { + goto exit_sske; + } + /* worst case estimate */ + args->tmpSigSz = ED25519_SIG_SIZE; + + /* check the minimum ECC key size */ + if (ED25519_KEY_SIZE < + ssl->options.minEccKeySz) { + WOLFSSL_MSG("Ed25519 key size too small"); + ret = ECC_KEY_SIZE_E; + goto exit_sske; + } + break; + } + #endif default: ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */ } /* switch(ssl->specs.sig_algo) */ @@ -20091,20 +20444,24 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, args->output + preSigIdx, preSigSz); - ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); - ssl->buffers.sig.buffer = (byte*)XMALLOC( + if (ssl->suites->sigAlgo != ed25519_sa_algo) { + ssl->buffers.sig.length = + wc_HashGetDigestSize(hashType); + ssl->buffers.sig.buffer = (byte*)XMALLOC( ssl->buffers.sig.length, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (ssl->buffers.sig.buffer == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } - /* Perform hash */ - ret = wc_Hash(hashType, - args->sigDataBuf, args->sigDataSz, - ssl->buffers.sig.buffer, ssl->buffers.sig.length); - if (ret != 0) { - goto exit_sske; + /* Perform hash */ + ret = wc_Hash(hashType, args->sigDataBuf, + args->sigDataSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length); + if (ret != 0) { + goto exit_sske; + } } args->sigSz = args->tmpSigSz; @@ -20151,6 +20508,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, break; #endif #endif /* !NO_RSA */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + #endif case ecc_dsa_sa_algo: { break; @@ -20321,20 +20681,24 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, args->output + preSigIdx, preSigSz); - ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); - ssl->buffers.sig.buffer = (byte*)XMALLOC( + if (ssl->suites->sigAlgo != ed25519_sa_algo) { + ssl->buffers.sig.length = + wc_HashGetDigestSize(hashType); + ssl->buffers.sig.buffer = (byte*)XMALLOC( ssl->buffers.sig.length, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (ssl->buffers.sig.buffer == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } - /* Perform hash */ - ret = wc_Hash(hashType, - args->sigDataBuf, args->sigDataSz, - ssl->buffers.sig.buffer, ssl->buffers.sig.length); - if (ret != 0) { - goto exit_sske; + /* Perform hash */ + ret = wc_Hash(hashType, args->sigDataBuf, + args->sigDataSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length); + if (ret != 0) { + goto exit_sske; + } } args->sigSz = args->tmpSigSz; @@ -20458,6 +20822,27 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ); break; } + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + ed25519_key* key = (ed25519_key*)ssl->hsKey; + + ret = Ed25519Sign(ssl, + args->sigDataBuf, args->sigDataSz, + args->output + LENGTH_SZ + args->idx, + &args->sigSz, + key, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->Ed25519SignCtx + #else + NULL, 0, NULL + #endif + ); + break; + } + #endif } /* switch(ssl->specs.sig_algo) */ break; } @@ -20589,6 +20974,19 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args->sendSz += args->sigSz - args->tmpSigSz; break; } + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + /* Now that we know the real sig size, write it. */ + c16toa((word16)args->sigSz, + args->output + args->idx); + + /* And adjust length and sendSz from estimates */ + args->length += args->sigSz - args->tmpSigSz; + args->sendSz += args->sigSz - args->tmpSigSz; + break; + } + #endif default: ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */ } /* switch(ssl->specs.sig_algo) */ @@ -21714,6 +22112,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, else if (ssl->peerEccDsaKeyPresent) args->sigAlgo = ecc_dsa_sa_algo; #endif + #ifdef HAVE_ED25519 + else if (ssl->peerEd25519KeyPresent) + args->sigAlgo = ed25519_sa_algo; + #endif if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcv); @@ -21754,6 +22156,16 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + if (IsAtLeastTLSv1_2(ssl) && + args->sigAlgo != ed25519_sa_algo) { + WOLFSSL_MSG( + "Oops, peer sent ED25519 key but not in verify"); + } + } + #endif /* HAVE_ED25519 */ /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_DO; diff --git a/src/ssl.c b/src/ssl.c index eceafd442..59a18ec42 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -3635,6 +3635,15 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) } break; #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (cm->minEccKeySz < 0 || + ED25519_KEY_SIZE < (word16)cm->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ECC key size error"); + } + break; + #endif /* HAVE_ED25519 */ default: WOLFSSL_MSG("\tNo key size check done on CA"); @@ -4375,6 +4384,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */ int ret = 0; int eccKey = 0; + int ed25519Key = 0; int rsaKey = 0; int resetSuites = 0; void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); @@ -4574,7 +4584,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (type == PRIVATEKEY_TYPE && format != SSL_FILETYPE_RAW) { #ifndef NO_RSA - if (!eccKey) { + if (!eccKey && !ed25519Key) { /* make sure RSA key can be used */ word32 idx = 0; #ifdef WOLFSSL_SMALL_STACK @@ -4638,40 +4648,83 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #endif #ifdef HAVE_ECC - if (!rsaKey) { + if (!rsaKey && !ed25519Key) { /* make sure ECC key can be used */ word32 idx = 0; ecc_key key; - ret = wc_ecc_init_ex(&key, heap, devId); + if (wc_ecc_init_ex(&key, heap, devId) == 0) { + if (wc_EccPrivateKeyDecode(der->buffer, &idx, &key, + der->length) == 0) { + + /* check for minimum ECC key size and then free */ + if (ssl) { + if (wc_ecc_size(&key) < ssl->options.minEccKeySz) { + wc_ecc_free(&key); + WOLFSSL_MSG("ECC private key too small"); + return ECC_KEY_SIZE_E; + } + } + else if (ctx) { + if (wc_ecc_size(&key) < ctx->minEccKeySz) { + wc_ecc_free(&key); + WOLFSSL_MSG("ECC private key too small"); + return ECC_KEY_SIZE_E; + } + } + + eccKey = 1; + if (ssl) { + ssl->options.haveStaticECC = 1; + } + else if (ctx) { + ctx->haveStaticECC = 1; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } + } + + wc_ecc_free(&key); + } + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (!rsaKey && !eccKey) { + /* make sure Ed25519 key can be used */ + word32 idx = 0; + ed25519_key key; + + ret = wc_ed25519_init(&key); if (ret != 0) { return ret; } - if (wc_EccPrivateKeyDecode(der->buffer, &idx, &key, - der->length) != 0) { - wc_ecc_free(&key); + if (wc_Ed25519PrivateKeyDecode(der->buffer, &idx, &key, + der->length) != 0) { + wc_ed25519_free(&key); return SSL_BAD_FILE; } /* check for minimum ECC key size and then free */ if (ssl) { - if (wc_ecc_size(&key) < ssl->options.minEccKeySz) { - wc_ecc_free(&key); - WOLFSSL_MSG("ECC private key too small"); + if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) { + wc_ed25519_free(&key); + WOLFSSL_MSG("ED25519 private key too small"); return ECC_KEY_SIZE_E; } } else if (ctx) { - if (wc_ecc_size(&key) < ctx->minEccKeySz) { - wc_ecc_free(&key); - WOLFSSL_MSG("ECC private key too small"); + if (ED25519_KEY_SIZE < ctx->minEccKeySz) { + wc_ed25519_free(&key); + WOLFSSL_MSG("ED25519 private key too small"); return ECC_KEY_SIZE_E; } } - wc_ecc_free(&key); - eccKey = 1; + wc_ed25519_free(&key); + ed25519Key = 1; if (ssl) { ssl->options.haveStaticECC = 1; } @@ -4683,7 +4736,12 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, resetSuites = 1; } } - #endif /* HAVE_ECC */ + #endif + + if (!rsaKey && !eccKey && !ed25519Key) + return SSL_BAD_FILE; + + (void)ed25519Key; } else if (type == CERT_TYPE) { #ifdef WOLFSSL_SMALL_STACK @@ -4730,6 +4788,13 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, else if (ctx) ctx->haveECDSAsig = 1; break; + case CTC_ED25519: + WOLFSSL_MSG("ED25519 cert signature"); + if (ssl) + ssl->options.haveECDSAsig = 1; + else if (ctx) + ctx->haveECDSAsig = 1; + break; default: WOLFSSL_MSG("Not ECDSA cert signature"); break; @@ -4742,6 +4807,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (cert->keyOID == ECDSAk) { ssl->options.haveECC = 1; } + #ifdef HAVE_ED25519 + else if (cert->keyOID == ED25519k) { + ssl->options.haveECC = 1; + } + #endif #else ssl->options.haveECC = ssl->options.haveECDSAsig; #endif @@ -4752,6 +4822,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (cert->keyOID == ECDSAk) { ctx->haveECC = 1; } + #ifdef HAVE_ED25519 + else if (cert->keyOID == ED25519k) { + ctx->haveECC = 1; + } + #endif #else ctx->haveECC = ctx->haveECDSAsig; #endif @@ -4777,7 +4852,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } } break; - #endif /* !NO_RSA */ + #endif /* !NO_RSA */ #ifdef HAVE_ECC case ECDSAk: if (ssl && !ssl->options.verifyNone) { @@ -4795,7 +4870,25 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } } break; - #endif /* HAVE_ECC */ + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minEccKeySz < 0 || + ED25519_KEY_SIZE < (word16)ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate Ed key size error"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minEccKeySz < 0 || + ED25519_KEY_SIZE < (word16)ctx->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate ECC key size error"); + } + } + break; + #endif /* HAVE_ED25519 */ default: WOLFSSL_MSG("No key size check done on certificate"); @@ -22022,6 +22115,54 @@ void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl) return NULL; } +#endif /* HAVE_ECC */ + +#ifdef HAVE_ED25519 +void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb) +{ + if (ctx) + ctx->Ed25519SignCb = cb; +} + + +void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed25519SignCtx = ctx; +} + + +void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed25519SignCtx; + + return NULL; +} + + +void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb) +{ + if (ctx) + ctx->Ed25519VerifyCb = cb; +} + + +void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed25519VerifyCtx = ctx; +} + + +void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed25519VerifyCtx; + + return NULL; +} +#endif #ifdef HAVE_CURVE25519 void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx, @@ -22046,7 +22187,6 @@ void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl) return NULL; } #endif -#endif /* HAVE_ECC */ #ifndef NO_RSA @@ -22365,6 +22505,9 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) case RSAk: ctx->haveRSA = 1; break; + #ifdef HAVE_ED25519 + case ED25519k: + #endif case ECDSAk: ctx->haveECC = 1; ctx->pkCurveOID = x->pkCurveOID; diff --git a/src/tls.c b/src/tls.c index 5e5c47148..4a713d0c9 100755 --- a/src/tls.c +++ b/src/tls.c @@ -2985,6 +2985,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { : NULL; EllipticCurve* curve = NULL; word32 oid = 0; + word32 pkOid = 0; word32 defOid = 0; word32 defSz = 80; /* Maximum known curve size is 66. */ word32 nextOid = 0; @@ -3009,19 +3010,19 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP160R1: - oid = ECC_SECP160R1_OID; + pkOid = oid = ECC_SECP160R1_OID; octets = 20; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_SECPR2 case WOLFSSL_ECC_SECP160R2: - oid = ECC_SECP160R2_OID; + pkOid = oid = ECC_SECP160R2_OID; octets = 20; break; #endif /* HAVE_ECC_SECPR2 */ #ifdef HAVE_ECC_KOBLITZ case WOLFSSL_ECC_SECP160K1: - oid = ECC_SECP160K1_OID; + pkOid = oid = ECC_SECP160K1_OID; octets = 20; break; #endif /* HAVE_ECC_KOBLITZ */ @@ -3029,13 +3030,13 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP192R1: - oid = ECC_SECP192R1_OID; + pkOid = oid = ECC_SECP192R1_OID; octets = 24; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ case WOLFSSL_ECC_SECP192K1: - oid = ECC_SECP192K1_OID; + pkOid = oid = ECC_SECP192K1_OID; octets = 24; break; #endif /* HAVE_ECC_KOBLITZ */ @@ -3043,13 +3044,13 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP224R1: - oid = ECC_SECP224R1_OID; + pkOid = oid = ECC_SECP224R1_OID; octets = 28; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ case WOLFSSL_ECC_SECP224K1: - oid = ECC_SECP224K1_OID; + pkOid = oid = ECC_SECP224K1_OID; octets = 28; break; #endif /* HAVE_ECC_KOBLITZ */ @@ -3057,25 +3058,30 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP256R1: - oid = ECC_SECP256R1_OID; + pkOid = oid = ECC_SECP256R1_OID; octets = 32; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_CURVE25519 case WOLFSSL_ECC_X25519: oid = ECC_X25519_OID; + #ifdef HAVE_ED25519 + pkOid = ECC_ED25519_OID; + #else + pkOid = ECC_X25519_OID; + #endif octets = 32; break; #endif /* HAVE_CURVE25519 */ #ifdef HAVE_ECC_KOBLITZ case WOLFSSL_ECC_SECP256K1: - oid = ECC_SECP256K1_OID; + pkOid = oid = ECC_SECP256K1_OID; octets = 32; break; #endif /* HAVE_ECC_KOBLITZ */ #ifdef HAVE_ECC_BRAINPOOL case WOLFSSL_ECC_BRAINPOOLP256R1: - oid = ECC_BRAINPOOLP256R1_OID; + pkOid = oid = ECC_BRAINPOOLP256R1_OID; octets = 32; break; #endif /* HAVE_ECC_BRAINPOOL */ @@ -3083,13 +3089,13 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP384R1: - oid = ECC_SECP384R1_OID; + pkOid = oid = ECC_SECP384R1_OID; octets = 48; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_BRAINPOOL case WOLFSSL_ECC_BRAINPOOLP384R1: - oid = ECC_BRAINPOOLP384R1_OID; + pkOid = oid = ECC_BRAINPOOLP384R1_OID; octets = 48; break; #endif /* HAVE_ECC_BRAINPOOL */ @@ -3097,7 +3103,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) #ifdef HAVE_ECC_BRAINPOOL case WOLFSSL_ECC_BRAINPOOLP512R1: - oid = ECC_BRAINPOOLP512R1_OID; + pkOid = oid = ECC_BRAINPOOLP512R1_OID; octets = 64; break; #endif /* HAVE_ECC_BRAINPOOL */ @@ -3105,7 +3111,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP521R1: - oid = ECC_SECP521R1_OID; + pkOid = oid = ECC_SECP521R1_OID; octets = 66; break; #endif /* !NO_ECC_SECP */ @@ -3139,7 +3145,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - sig |= ssl->pkCurveOID == oid; + sig |= ssl->pkCurveOID == pkOid; key |= ssl->ecdhCurveOID == oid; ephmSuite = 1; break; @@ -3158,7 +3164,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { defOid = 0; defSz = 80; } - sig |= ssl->pkCurveOID == oid; + sig |= ssl->pkCurveOID == pkOid; key |= ssl->pkCurveOID == oid; break; #endif /* WOLFSSL_STATIC_DH */ @@ -3192,7 +3198,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { defSz = 80; } sig = 1; - key |= ssl->pkCurveOID == oid; + key |= ssl->pkCurveOID == pkOid; break; #endif /* WOLFSSL_STATIC_DH */ #endif @@ -3214,7 +3220,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { /* ECDHE_ECDSA */ case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : - sig |= ssl->pkCurveOID == oid; + sig |= ssl->pkCurveOID == pkOid; key |= ssl->ecdhCurveOID == oid; ephmSuite = 1; break; @@ -6969,9 +6975,9 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) WOLFSSL_ECC_SECP256R1, ssl->heap); if (ret != SSL_SUCCESS) return ret; #endif - #ifdef HAVE_CURVE25519 + #if defined(HAVE_CURVE25519) ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_ECC_X25519, ssl->heap); + WOLFSSL_ECC_X25519, ssl->heap); if (ret != SSL_SUCCESS) return ret; #endif #ifdef HAVE_ECC_KOBLITZ @@ -7028,38 +7034,40 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) ssl->heap)) != 0) return ret; - /* Add FFDHE supported groups. */ - #ifdef HAVE_FFDHE_2048 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_2048, ssl->heap); - if (ret != SSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_3072 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_3072, ssl->heap); - if (ret != SSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_4096 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_4096, ssl->heap); - if (ret != SSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_6144 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_6144, ssl->heap); - if (ret != SSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_8192 - ret = TLSX_UseSupportedCurve(&ssl->extensions, - WOLFSSL_FFDHE_8192, ssl->heap); - if (ret != SSL_SUCCESS) - return ret; - #endif - ret = 0; + if (!ssl->options.userCurves && !ssl->ctx->userCurves) { + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_2048 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_2048, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_3072 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_3072, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_4096 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_4096, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_6144 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_6144, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_8192 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_8192, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + ret = 0; + } if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \ diff --git a/src/tls13.c b/src/tls13.c index 852b30f80..3679c06d0 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3087,6 +3087,13 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) output[0] = hashAlgo; output[1] = ecc_dsa_sa_algo; break; + #ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + case ed25519_sa_algo: + output[0] = ED25519_SA_MAJOR; + output[1] = ED25519_SA_MINOR; + break; + #endif #endif #ifndef NO_RSA case rsa_sa_algo: @@ -3101,7 +3108,6 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) break; #endif #endif - /* ED25519: 0x0807 */ /* ED448: 0x0808 */ } } @@ -3115,17 +3121,24 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) static INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType) { switch (input[0]) { + case NEW_SA_MAJOR: #ifdef WC_RSA_PSS - case 0x08: - /* PSS signatures: 0x080[4-6] */ - if (input[1] <= 0x06) { - *hsType = input[0]; - *hashAlgo = input[1]; - } - break; + /* PSS signatures: 0x080[4-6] */ + if (input[1] <= sha512_mac) { + *hsType = input[0]; + *hashAlgo = input[1]; + } #endif - /* ED25519: 0x0807 */ - /* ED448: 0x0808 */ + #ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + if (input[1] == ED25519_SA_MINOR) { + *hsType = ed25519_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + #endif + /* ED448: 0x0808 */ + break; default: *hashAlgo = input[0]; *hsType = input[1]; @@ -3825,6 +3838,8 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) } else if (ssl->hsType == DYNAMIC_TYPE_ECC) args->sigAlgo = ecc_dsa_sa_algo; + else if (ssl->hsType == DYNAMIC_TYPE_ED25519) + args->sigAlgo = ed25519_sa_algo; EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, args->verify); /* Create the data to be signed. */ @@ -3869,6 +3884,12 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) ret = 0; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + /* Nothing to do */ + sig->length = ED25519_SIG_SIZE; + } + #endif /* HAVE_ECC */ /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_DO; @@ -3892,6 +3913,21 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) args->length = sig->length; } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + ret = Ed25519Sign(ssl, args->sigData, args->sigDataSz, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + &sig->length, (ed25519_key*)ssl->hsKey, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, ssl->buffers.key->length, + ssl->Ed25519SignCtx + #else + NULL, 0, NULL + #endif + ); + args->length = sig->length; + } + #endif #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { /* restore verify pointer */ @@ -4154,6 +4190,10 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } /* Check for public key of required type. */ + if (args->sigAlgo == ed25519_sa_algo && + !ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Oops, peer sent ED25519 key but not in verify"); + } if (args->sigAlgo == ecc_dsa_sa_algo && !ssl->peerEccDsaKeyPresent) { WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); @@ -4191,6 +4231,20 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, ret = 0; } #endif + #ifdef HAVE_ED25519 + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + + CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + ret = 0; + } + #endif /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_DO; @@ -4237,6 +4291,23 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, ); } #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + + ret = Ed25519Verify(ssl, input + args->idx, args->sz, + args->sigData, args->sigDataSz, + ssl->peerEd25519Key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEd25519Key.buffer, + ssl->buffers.peerEd25519Key.length, + ssl->Ed25519VerifyCtx + #else + NULL, 0, NULL + #endif + ); + } + #endif /* Check for error */ if (ret != 0) { diff --git a/tests/suites.c b/tests/suites.c index 289c5ef46..cb37e203f 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -574,6 +574,16 @@ int SuiteTest(void) exit(EXIT_FAILURE); } #endif +#if defined(HAVE_CURVE25519) && defined(HAVE_ED25519) + /* add ED25519 certificate cipher suite tests */ + strcpy(argv0[1], "tests/test-ed25519.conf"); + printf("starting ED25519 extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + exit(EXIT_FAILURE); + } +#endif #ifdef WOLFSSL_DTLS /* add dtls extra suites */ strcpy(argv0[1], "tests/test-dtls.conf"); diff --git a/tests/test-ed25519.conf b/tests/test-ed25519.conf new file mode 100644 index 000000000..cdd3ade35 --- /dev/null +++ b/tests/test-ed25519.conf @@ -0,0 +1,56 @@ +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/ed25519/server-ed25519.pem +-k ./certs/ed25519/server-ed25519-key.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ed25519/root-ed25519.pem +-C + +# Enable when CRL for ED25519 certificates available. +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +#-v 3 +#-l ECDHE-ECDSA-AES128-GCM-SHA256 +#-c ./certs/ed25519/server-ed25519.pem +#-k ./certs/ed25519/server-ed25519-key.pem +#-A ./certs/ed25519/client-ed25519.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +#-v 3 +#-l ECDHE-ECDSA-AES128-GCM-SHA256 +#-c ./certs/ed25519/client-ed25519.pem +#-k ./certs/ed25519/client-ed25519-key.pem +#-A ./certs/ed25519/root-ed25519.pem +#-C + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/ed25519/server-ed25519.pem +-k ./certs/ed25519/server-ed25519-key.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/ed25519/root-ed25519.pem +-C + +# Enable when CRL for ED25519 certificates available. +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +#-v 4 +#-l TLS13-AES128-GCM-SHA256 +#-c ./certs/ed25519/server-ed25519.pem +#-k ./certs/ed25519/server-ed25519-key.pem +#-A ./certs/ed25519/client-ed25519.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +#-v 4 +#-l TLS13-AES128-GCM-SHA256 +#-c ./certs/ed25519/client-ed25519.pem +#-k ./certs/ed25519/client-ed25519-key.pem +#-A ./certs/ed25519/root-ed25519.pem +#-C + diff --git a/tests/test-tls13.conf b/tests/test-tls13.conf index cf1e9f7f9..b0c2aa92f 100644 --- a/tests/test-tls13.conf +++ b/tests/test-tls13.conf @@ -93,3 +93,15 @@ -l TLS13-AES128-CCM-8-SHA256 -A ./certs/server-ecc.pem +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/server-ecc.pem +-t + diff --git a/tests/test.conf b/tests/test.conf index 933d001fd..e8223797e 100644 --- a/tests/test.conf +++ b/tests/test.conf @@ -2178,3 +2178,15 @@ -l ECDHE-RSA-AES128-SHA256 -j +# server TLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305 +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/server-ecc.pem +-t + diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index e3e647e07..51df86d6b 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2502,7 +2502,7 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, } #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 - if (*algoID != RSAk && *algoId != ECDSAk) { + if (*algoID != RSAk && *algoID != ECDSAk) { if (wc_ed25519_init(&ed25519) == 0) { if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, &ed25519, keySz) == 0) { @@ -3448,6 +3448,8 @@ static int GetKey(DecodedCert* cert) { int ret; + cert->pkCurveOID = ED25519k; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1, NULL); if (ret != 0) @@ -4637,7 +4639,7 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, WOLFSSL_MSG("Hash for Signature has unsupported type"); } - return 0; + return ret; } /* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */ @@ -10228,6 +10230,15 @@ int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; + if (GetOctetString(input, inOutIdx, &privSz, inSz) >= 0) { + priv = input + *inOutIdx; + *inOutIdx += privSz; + + if (*inOutIdx != inSz) + return ASN_PARSE_E; + return wc_ed25519_import_private_only(priv, privSz, key); + } + if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; endKeyIdx = *inOutIdx + length; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9487a7947..4293dd873 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -72,6 +72,9 @@ #ifdef HAVE_ECC #include #endif +#ifdef HAVE_ED25519 + #include +#endif #ifdef HAVE_CURVE25519 #include #endif @@ -909,7 +912,7 @@ enum Misc { ECC_BYTE = 0xC0, /* ECC first cipher suite byte */ QSH_BYTE = 0xD0, /* Quantum-safe Handshake cipher suite */ CHACHA_BYTE = 0xCC, /* ChaCha first cipher suite */ - TLS13_BYTE = 0x13, /* TLS v.13 first byte of cipher suite */ + TLS13_BYTE = 0x13, /* TLS v1.3 first byte of cipher suite */ SEND_CERT = 1, SEND_BLANK_CERT = 2, @@ -1093,6 +1096,12 @@ enum Misc { ECDHE_SIZE = 32, /* ECHDE server size defaults to 256 bit */ MAX_EXPORT_ECC_SZ = 256, /* Export ANS X9.62 max future size */ + NEW_SA_MAJOR = 8, /* Most signicant byte used with new sig algos */ + ED25519_SA_MAJOR = 8, /* Most significant byte for ED25519 */ + 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 */ + #ifdef HAVE_QSH /* qsh handshake sends 600+ size keys over hello extensions */ MAX_HELLO_SZ = 2048, /* max client or server hello */ @@ -2263,6 +2272,12 @@ struct WOLFSSL_CTX { CallbackEccSign EccSignCb; /* User EccSign Callback handler */ CallbackEccVerify EccVerifyCb; /* User EccVerify Callback handler */ CallbackEccSharedSecret EccSharedSecretCb; /* User EccVerify Callback handler */ + #ifdef HAVE_ED25519 + /* User Ed25519Sign Callback handler */ + CallbackEd25519Sign Ed25519SignCb; + /* User Ed25519Verify Callback handler */ + CallbackEd25519Verify Ed25519VerifyCb; + #endif #ifdef HAVE_CURVE25519 /* User EccSharedSecret Callback handler */ CallbackX25519SharedSecret X25519SharedSecretCb; @@ -2374,7 +2389,8 @@ enum SignatureAlgorithm { rsa_sa_algo = 1, dsa_sa_algo = 2, ecc_dsa_sa_algo = 3, - rsa_pss_sa_algo = 8 + rsa_pss_sa_algo = 8, + ed25519_sa_algo = 9 }; @@ -2637,6 +2653,9 @@ typedef struct Buffers { #ifdef HAVE_ECC buffer peerEccDsaKey; /* we own for Ecc Verify Callbacks */ #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + buffer peerEd25519Key; /* for Ed25519 Verify Callbacks */ + #endif /* HAVE_ED25519 */ #ifndef NO_RSA buffer peerRsaKey; /* we own for Rsa Verify Callbacks */ #endif /* NO_RSA */ @@ -3134,6 +3153,10 @@ struct WOLFSSL { byte peerEccKeyPresent; byte peerEccDsaKeyPresent; byte eccTempKeyPresent; +#ifdef HAVE_ED25519 + ed25519_key* peerEd25519Key; + byte peerEd25519KeyPresent; +#endif #ifdef HAVE_CURVE25519 curve25519_key* peerX25519Key; byte peerX25519KeyPresent; @@ -3241,6 +3264,10 @@ struct WOLFSSL { void* EccSignCtx; /* Ecc Sign Callback Context */ void* EccVerifyCtx; /* Ecc Verify Callback Context */ void* EccSharedSecretCtx; /* Ecc Pms Callback Context */ + #ifdef HAVE_ED25519 + void* Ed25519SignCtx; /* ED25519 Sign Callback Context */ + void* Ed25519VerifyCtx; /* ED25519 Verify Callback Context */ + #endif #ifdef HAVE_CURVE25519 void* X25519SharedSecretCtx; /* X25519 Pms Callback Context */ #endif @@ -3472,6 +3499,15 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); ecc_key* pub_key, byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen, int side, void* ctx); #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + WOLFSSL_LOCAL int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, ed25519_key* key, byte* keyBuf, + word32 keySz, void* ctx); + WOLFSSL_LOCAL int Ed25519Verify(WOLFSSL* ssl, const byte* in, + word32 inSz, const byte* msg, word32 msgSz, ed25519_key* key, + byte* keyBuf, word32 keySz, void* ctx); + #endif /* HAVE_ED25519 */ + #ifdef WOLFSSL_TRUST_PEER_CERT diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 9ae8cd9f5..7e573a398 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1506,6 +1506,27 @@ WOLFSSL_API void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX*, CallbackEccShar WOLFSSL_API void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl); +struct ed25519_key; +typedef int (*CallbackEd25519Sign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX*, + CallbackEd25519Sign); +WOLFSSL_API void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl); + +typedef int (*CallbackEd25519Verify)(WOLFSSL* ssl, + const unsigned char* sig, unsigned int sigSz, + const unsigned char* msg, unsigned int msgSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX*, + CallbackEd25519Verify); +WOLFSSL_API void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl); + struct curve25519_key; typedef int (*CallbackX25519SharedSecret)(WOLFSSL* ssl, struct curve25519_key* otherKey, diff --git a/wolfssl/test.h b/wolfssl/test.h index aab51b4e6..7535465af 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -24,6 +24,9 @@ #ifdef HAVE_ECC #include #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + #include + #endif /* HAVE_ED25519 */ #ifdef HAVE_CURVE25519 #include #endif /* HAVE_ECC */ @@ -1828,6 +1831,52 @@ static INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, return ret; } +#ifdef HAVE_ED25519 +static INLINE int myEd25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + ed25519_key myKey; + + (void)ssl; + (void)ctx; + + ret = wc_ed25519_init(&myKey); + if (ret == 0) { + ret = wc_Ed25519PrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_ed25519_sign_msg(in, inSz, out, outSz, &myKey); + wc_ed25519_free(&myKey); + } + + return ret; +} + + +static INLINE int myEd25519Verify(WOLFSSL* ssl, const byte* sig, word32 sigSz, + const byte* msg, word32 msgSz, const byte* key, word32 keySz, + int* result, void* ctx) +{ + int ret; + ed25519_key myKey; + + (void)ssl; + (void)ctx; + + ret = wc_ed25519_init(&myKey); + if (ret == 0) { + ret = wc_ed25519_import_public(key, keySz, &myKey); + if (ret == 0) { + ret = wc_ed25519_verify_msg(sig, sigSz, msg, msgSz, result, &myKey); + } + wc_ed25519_free(&myKey); + } + + return ret; +} +#endif /* HAVE_ED25519 */ + #ifdef HAVE_CURVE25519 static INLINE int myX25519SharedSecret(WOLFSSL* ssl, curve25519_key* otherKey, unsigned char* pubKeyDer, unsigned int* pubKeySz, @@ -2121,10 +2170,14 @@ static INLINE void SetupPkCallbacks(WOLFSSL_CTX* ctx, WOLFSSL* ssl) wolfSSL_CTX_SetEccSignCb(ctx, myEccSign); wolfSSL_CTX_SetEccVerifyCb(ctx, myEccVerify); wolfSSL_CTX_SetEccSharedSecretCb(ctx, myEccSharedSecret); - #ifdef HAVE_CURVE25519 - wolfSSL_CTX_SetX25519SharedSecretCb(ctx, myX25519SharedSecret); - #endif #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + wolfSSL_CTX_SetEd25519SignCb(ctx, myEd25519Sign); + wolfSSL_CTX_SetEd25519VerifyCb(ctx, myEd25519Verify); + #endif + #ifdef HAVE_CURVE25519 + wolfSSL_CTX_SetX25519SharedSecretCb(ctx, myX25519SharedSecret); + #endif #ifndef NO_RSA wolfSSL_CTX_SetRsaSignCb(ctx, myRsaSign); wolfSSL_CTX_SetRsaVerifyCb(ctx, myRsaVerify); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 42be1f71c..f2c5c9aa5 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -287,6 +287,7 @@ enum Ecc_Sum { ECC_SECP256K1_OID = 186, ECC_BRAINPOOLP256R1_OID = 104, ECC_X25519_OID = 365, + ECC_ED25519_OID = 256, ECC_BRAINPOOLP320R1_OID = 106, ECC_SECP384R1_OID = 210, ECC_BRAINPOOLP384R1_OID = 108, From 1bc862ae249b0a8b25bd96be19fdbf0a0c1b8dfb Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Wed, 31 May 2017 10:35:55 +1000 Subject: [PATCH 24/34] Ed25519 testing in test.c --- wolfcrypt/test/test.c | 226 ++++++++++++++++++++++++++++++++++++++++++ wolfssl/certs_test.h | 153 ++++++++++++++++++++++++++++ 2 files changed, 379 insertions(+) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 4bf48891b..86d1e3b01 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -5712,6 +5712,14 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) static const char* eccCaKeyPubFile = CERT_ROOT "ecc-keyPub.der"; #endif #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + #ifdef WOLFSSL_TEST_CERT + static const char* serverEd25519Cert = + CERT_ROOT "ed25519/server-ed25519.der"; + static const char* caEd25519Cert = + CERT_ROOT "ed25519/ca-ed25519.der"; + #endif + #endif #endif /* !USE_CERT_BUFFER_* */ #ifndef NO_WRITE_TEMP_FILES @@ -11442,6 +11450,213 @@ int curve25519_test(void) #ifdef HAVE_ED25519 +#ifdef WOLFSSL_TEST_CERT +static int ed25519_test_cert(void) +{ + DecodedCert cert[2]; + DecodedCert* serverCert = NULL; + DecodedCert* caCert = NULL; +#ifdef HAVE_ED25519_VERIFY + ed25519_key key; + ed25519_key* pubKey = NULL; + int verify; +#endif /* HAVE_ED25519_VERIFY */ + int ret; + byte* tmp; + int bytes; + FILE* file; + + tmp = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ret = -7200; + goto done; + } + +#ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, ca_ed25519_cert, sizeof_ca_ed25519_cert); + bytes = sizeof_ca_ed25519_cert; +#elif !defined(NO_FILESYSTEM) + file = fopen(caEd25519Cert, "rb"); + if (file == NULL) { + ret = -7201; + goto done; + } + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); +#else + /* No certificate to use. */ + ret = -7202; + goto done; +#endif + + InitDecodedCert(&cert[0], tmp, (word32)bytes, 0); + caCert = &cert[0]; + ret = ParseCert(caCert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ret = -7203; + goto done; + } + +#ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, server_ed25519_cert, sizeof_server_ed25519_cert); + bytes = sizeof_server_ed25519_cert; +#elif !defined(NO_FILESYSTEM) + file = fopen(serverEd25519Cert, "rb"); + if (file == NULL) { + ret = -7204; + goto done; + } + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); +#else + /* No certificate to use. */ + ret = -7205; + goto done; +#endif + + InitDecodedCert(&cert[1], tmp, (word32)bytes, 0); + serverCert = &cert[1]; + ret = ParseCert(serverCert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ret = -7206; + goto done; + } + +#ifdef HAVE_ED25519_VERIFY + ret = wc_ed25519_init(&key); + if (ret < 0) { + ret = -7207; + goto done; + } + pubKey = &key; + ret = wc_ed25519_import_public(caCert->publicKey, caCert->pubKeySize, + pubKey); + if (ret < 0) { + ret = -7208; + goto done; + } + + if (wc_ed25519_verify_msg(serverCert->signature, serverCert->sigLength, + serverCert->source + serverCert->certBegin, + serverCert->sigIndex - serverCert->certBegin, + &verify, pubKey) < 0 || verify != 1) { + ret = -7209; + goto done; + } +#endif /* HAVE_ED25519_VERIFY */ + +done: + if (tmp != NULL) + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef HAVE_ED25519_VERIFY + wc_ed25519_free(pubKey); +#endif /* HAVE_ED25519_VERIFY */ + if (caCert != NULL) + FreeDecodedCert(caCert); + if (serverCert != NULL) + FreeDecodedCert(serverCert); + + return ret; +} + +#ifdef WOLFSSL_CERT_GEN +static const CertName defaultName = { + "US", CTC_PRINTABLE, + "Montana", CTC_UTF8, + "Bozeman", CTC_UTF8, + "Test", CTC_UTF8, + "wolfSSL", CTC_UTF8, + "ED25519", CTC_UTF8, + "www.wolfssl.com", CTC_UTF8, + "info@wolfssl.com" +}; +#ifdef WOLFSSL_CERT_EXT +static const char leafKeyUsage[] = "digitalSignature,nonRepudiation"; +#endif + +static int ed25519_test_make_cert(void) +{ + WC_RNG rng; + Cert cert; + DecodedCert decode; + ed25519_key key; + ed25519_key* privKey = NULL; + int ret = 0; + byte* tmp = NULL; + + wc_InitCert(&cert); + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -7220; + + wc_ed25519_init(&key); + privKey = &key; + wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, privKey); + + cert.daysValid = 365 * 2; + cert.selfSigned = 1; + XMEMCPY(&cert.issuer, &defaultName, sizeof(CertName)); + XMEMCPY(&cert.subject, &defaultName, sizeof(CertName)); + cert.isCA = 0; +#ifdef WOLFSSL_CERT_EXT + ret = wc_SetKeyUsage(&cert, leafKeyUsage); + if (ret < 0) { + ret = -7221; + goto done; + } + ret = wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, privKey); + if (ret < 0) { + ret = -7222; + goto done; + } + ret = wc_SetAuthKeyIdFromPublicKey_ex(&cert, ED25519_TYPE, privKey); + if (ret < 0) { + ret = -7223; + goto done; + } +#endif + tmp = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + ret = -7224; + goto done; + } + + cert.sigType = CTC_ED25519; + ret = wc_MakeCert_ex(&cert, tmp, FOURK_BUF, ED25519_TYPE, privKey, &rng); + if (ret < 0) { + ret = -7225; + goto done; + } + ret = wc_SignCert_ex(cert.bodySz, cert.sigType, tmp, FOURK_BUF, + ED25519_TYPE, privKey, &rng); + if (ret < 0) { + ret = -7226; + goto done; + } + + InitDecodedCert(&decode, tmp, ret, HEAP_HINT); + ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); + FreeDecodedCert(&decode); + if (ret != 0) { + ret = -7227; + goto done; + } + +done: + if (tmp != NULL) + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_ed25519_free(privKey); + wc_FreeRng(&rng); + return ret; +} +#endif /* WOLFSSL_CERT_GEN */ +#endif /* WOLFSSL_TEST_CERT */ + int ed25519_test(void) { WC_RNG rng; @@ -11871,6 +12086,17 @@ int ed25519_test(void) (void)keySz; (void)sigSz; +#ifdef WOLFSSL_TEST_CERT + ret = ed25519_test_cert(); + if (ret < 0) + return ret; +#ifdef WOLFSSL_CERT_GEN + ret = ed25519_test_make_cert(); + if (ret < 0) + return ret; +#endif /* WOLFSSL_CERT_GEN */ +#endif /* WOLFSSL_TEST_CERT */ + return 0; } #endif /* HAVE_ED25519 */ diff --git a/wolfssl/certs_test.h b/wolfssl/certs_test.h index 64d10e50d..621936c00 100644 --- a/wolfssl/certs_test.h +++ b/wolfssl/certs_test.h @@ -2183,5 +2183,158 @@ static const unsigned char dh_g[] = 0x02, }; +#ifdef HAVE_ED25519 +/* + * Subject: /C=US/ST=Montana/L=Bozeman/SN=Leaf/O=wolfSSL/OU=ED25519/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + * Issuer: /C=US/ST=Montana/L=Bozeman/SN=CA/O=wolfSSL/OU=ED25519/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + */ +static const unsigned char server_ed25519_pkey[44] = { + 0x30, 0x2A, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, + 0x21, 0x00, 0x1A, 0x30, 0x88, 0x18, 0x47, 0x2F, 0x97, 0xDA, + 0x04, 0xF4, 0xA4, 0xE3, 0xBD, 0x6C, 0x0C, 0x16, 0xB9, 0x48, + 0xC1, 0xD1, 0x42, 0xD7, 0x8E, 0x92, 0x84, 0xA0, 0x74, 0x2A, + 0x43, 0x9E, 0x0E, 0x29 +}; +static const int sizeof_server_ed25519_pkey = sizeof(server_ed25519_pkey); + +static const unsigned char server_ed25519_cert[591] = { + 0x30, 0x82, 0x02, 0x4B, 0x30, 0x82, 0x01, 0xFD, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x08, 0x01, 0xD0, 0x92, 0x10, 0x6A, + 0x5A, 0x46, 0x57, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, + 0x30, 0x81, 0x9D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, + 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, + 0x61, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x04, 0x0C, 0x02, 0x43, 0x41, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, + 0x53, 0x53, 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, + 0x39, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, 0x30, 0x35, + 0x32, 0x38, 0x32, 0x33, 0x32, 0x36, 0x32, 0x39, 0x5A, 0x18, + 0x0F, 0x32, 0x30, 0x31, 0x39, 0x30, 0x35, 0x32, 0x39, 0x32, + 0x33, 0x32, 0x36, 0x32, 0x39, 0x5A, 0x30, 0x81, 0x9F, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, + 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x0D, + 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, 0x04, 0x4C, + 0x65, 0x61, 0x66, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, + 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, + 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, + 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x2A, + 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x21, 0x00, + 0x1A, 0x30, 0x88, 0x18, 0x47, 0x2F, 0x97, 0xDA, 0x04, 0xF4, + 0xA4, 0xE3, 0xBD, 0x6C, 0x0C, 0x16, 0xB9, 0x48, 0xC1, 0xD1, + 0x42, 0xD7, 0x8E, 0x92, 0x84, 0xA0, 0x74, 0x2A, 0x43, 0x9E, + 0x0E, 0x29, 0xA3, 0x53, 0x30, 0x51, 0x30, 0x1D, 0x06, 0x03, + 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xF6, 0xB2, 0x84, + 0x1A, 0x95, 0xB4, 0x70, 0x32, 0x53, 0xFE, 0xD9, 0xEB, 0x9B, + 0x29, 0x80, 0x4B, 0xD6, 0xB5, 0xF1, 0xC0, 0x30, 0x1F, 0x06, + 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x92, 0xD5, 0x0B, 0xDA, 0xF1, 0x04, 0x8B, 0xB9, 0xA1, 0x8B, + 0x03, 0x02, 0x9F, 0x58, 0x00, 0x35, 0x36, 0x07, 0x7A, 0xC9, + 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, + 0x04, 0x05, 0x03, 0x02, 0x06, 0xC0, 0x00, 0x30, 0x05, 0x06, + 0x03, 0x2B, 0x65, 0x70, 0x03, 0x41, 0x00, 0x12, 0x56, 0x77, + 0x0C, 0x96, 0x42, 0x98, 0xDA, 0xC9, 0x15, 0x6C, 0x4E, 0x48, + 0x95, 0x05, 0x1D, 0xD0, 0x78, 0x32, 0xF8, 0x86, 0x46, 0x9A, + 0x46, 0x9B, 0x64, 0x8B, 0x31, 0xB0, 0x19, 0x6B, 0x77, 0x99, + 0x8B, 0xFF, 0xFC, 0x02, 0x36, 0x05, 0x0B, 0x69, 0x37, 0x87, + 0x62, 0x75, 0xDA, 0x50, 0x2C, 0x2D, 0x5D, 0x52, 0x94, 0x3F, + 0x00, 0x9D, 0x18, 0x45, 0x6F, 0x37, 0x12, 0x8E, 0xF4, 0xE4, + 0x00 +}; +static const int sizeof_server_ed25519_cert = sizeof(server_ed25519_cert); + +static const unsigned char ca_ed25519_pkey[44] = { + 0x30, 0x2A, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, + 0x21, 0x00, 0x41, 0x07, 0xEC, 0x75, 0x0C, 0x68, 0x72, 0x12, + 0x3C, 0x04, 0x82, 0x07, 0x6E, 0x16, 0x6F, 0x40, 0x41, 0x6D, + 0xA4, 0x8F, 0x08, 0xF2, 0xE2, 0x9D, 0xA7, 0x43, 0xC2, 0x24, + 0x28, 0x98, 0x7E, 0xAC +}; +static const int sizeof_ca_ed25519_pkey = sizeof(ca_ed25519_pkey); + +static const unsigned char ca_ed25519_cert[605] = { + 0x30, 0x82, 0x02, 0x59, 0x30, 0x82, 0x02, 0x0B, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x08, 0x01, 0xF6, 0xE1, 0x3E, 0xBC, + 0x79, 0xA1, 0x85, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, + 0x30, 0x81, 0x9F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, + 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, + 0x61, 0x6E, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x04, 0x0C, 0x04, 0x52, 0x6F, 0x6F, 0x74, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, + 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, + 0x35, 0x31, 0x39, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, + 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x37, + 0x30, 0x35, 0x32, 0x38, 0x32, 0x33, 0x32, 0x36, 0x32, 0x39, + 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x39, 0x30, 0x35, 0x32, + 0x39, 0x32, 0x33, 0x32, 0x36, 0x32, 0x39, 0x5A, 0x30, 0x81, + 0x9D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, + 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, + 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, + 0x02, 0x43, 0x41, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, + 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, + 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, + 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x2A, + 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x21, 0x00, + 0x41, 0x07, 0xEC, 0x75, 0x0C, 0x68, 0x72, 0x12, 0x3C, 0x04, + 0x82, 0x07, 0x6E, 0x16, 0x6F, 0x40, 0x41, 0x6D, 0xA4, 0x8F, + 0x08, 0xF2, 0xE2, 0x9D, 0xA7, 0x43, 0xC2, 0x24, 0x28, 0x98, + 0x7E, 0xAC, 0xA3, 0x61, 0x30, 0x5F, 0x30, 0x0C, 0x06, 0x03, + 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0x92, 0xD5, 0x0B, 0xDA, 0xF1, 0x04, 0x8B, 0xB9, 0xA1, + 0x8B, 0x03, 0x02, 0x9F, 0x58, 0x00, 0x35, 0x36, 0x07, 0x7A, + 0xC9, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0x86, 0xC0, 0x27, 0xE9, 0x9E, 0xFA, + 0x85, 0xC1, 0xFD, 0xE3, 0x6F, 0xFC, 0x54, 0x59, 0x72, 0x37, + 0xC7, 0x33, 0x92, 0xBB, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, + 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x03, 0x02, 0x01, 0xC6, + 0x00, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x41, + 0x00, 0x22, 0x1B, 0x06, 0x17, 0xC0, 0x11, 0x74, 0x1F, 0x64, + 0xD1, 0xA3, 0xF6, 0x7B, 0x06, 0x00, 0x1A, 0x0B, 0x50, 0x8E, + 0xEB, 0xB1, 0x63, 0x92, 0x45, 0xBA, 0xDC, 0xE2, 0xC1, 0x68, + 0x14, 0x23, 0x0C, 0x6E, 0x2C, 0x95, 0x3C, 0xB1, 0x1C, 0x19, + 0x27, 0x98, 0x50, 0x3E, 0x55, 0x51, 0xCC, 0xC4, 0x49, 0x58, + 0xAF, 0xB9, 0x46, 0x4F, 0xED, 0x9C, 0x57, 0x38, 0x04, 0x29, + 0xD4, 0xA9, 0x12, 0xFE, 0x08 +}; +static const int sizeof_ca_ed25519_cert = sizeof(ca_ed25519_cert); +#endif + #endif /* WOLFSSL_CERTS_TEST_H */ From a30e8eb4ade7aa67ff83db519b1dd0eef72fba28 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Wed, 31 May 2017 11:44:43 +1000 Subject: [PATCH 25/34] Fix for benchmarking X25519 --- examples/client/client.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 6b81d3430..284f21e83 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -156,7 +156,7 @@ static void ShowVersions(void) /* Measures average time to create, connect and disconnect a connection (TPS). Benchmark = number of connections. */ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, - int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession) + int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession, int useX25519) { /* time passed in number of connects give average */ int times = benchmark; @@ -171,6 +171,7 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, #endif (void)resumeSession; + (void)useX25519; while (loops--) { #ifndef NO_SESSION_CACHE @@ -190,6 +191,16 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, #ifndef NO_SESSION_CACHE if (benchResume) wolfSSL_set_session(ssl, benchSession); + #endif + #ifdef WOLFSSL_TLS13 + #ifdef HAVE_CURVE25519 + else if (useX25519) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) + != SSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); + } + } + #endif #endif if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { err_sys("error in setting fd"); @@ -247,7 +258,7 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, /* Measures throughput in kbps. Throughput = number of bytes */ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, - int dtlsUDP, int dtlsSCTP, int throughput) + int dtlsUDP, int dtlsSCTP, int throughput, int useX25519) { double start, conn_time = 0, tx_time = 0, rx_time = 0; SOCKET_T sockfd; @@ -264,6 +275,18 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, err_sys("error in setting fd"); } + (void)useX25519; + #ifdef WOLFSSL_TLS13 + #ifdef HAVE_CURVE25519 + if (useX25519) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) + != SSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); + } + } + #endif + #endif + do { err = 0; /* reset error */ ret = wolfSSL_connect(ssl); @@ -735,9 +758,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int useOcsp = 0; char* ocspUrl = NULL; #endif -#ifdef HAVE_CURVE25519 int useX25519 = 0; -#endif #ifdef HAVE_WNR const char* wnrConfigFile = wnrConfig; @@ -771,6 +792,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void)alpnList; (void)alpn_opt; (void)updateKeysIVs; + (void)useX25519; StackTrap(); @@ -1479,7 +1501,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (benchmark) { ((func_args*)args)->return_code = ClientBenchmarkConnections(ctx, host, port, dtlsUDP, dtlsSCTP, - benchmark, resumeSession); + benchmark, resumeSession, useX25519); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } @@ -1487,7 +1509,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if(throughput) { ((func_args*)args)->return_code = ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP, - throughput); + throughput, useX25519); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } From 1db52f0c0448d1d7afeb564d49ad6eb4d9320aae Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Tue, 6 Jun 2017 10:52:48 +1000 Subject: [PATCH 26/34] Fix to use different PEM header for EDDSA keys Include new cert and key files in distribution Fix compile issue when only doing TLS13. --- certs/ed25519/ca-ed25519-key.pem | 4 +-- certs/ed25519/client-ed25519-key.pem | 4 +-- certs/ed25519/root-ed25519-key.pem | 4 +-- certs/ed25519/server-ed25519-key.pem | 4 +-- certs/include.am | 17 +++++++++++ src/ssl.c | 44 +++++++++++++++++----------- src/tls13.c | 2 ++ wolfcrypt/src/asn.c | 20 +++++++------ wolfssl/wolfcrypt/asn.h | 2 ++ wolfssl/wolfcrypt/asn_public.h | 1 + 10 files changed, 68 insertions(+), 34 deletions(-) diff --git a/certs/ed25519/ca-ed25519-key.pem b/certs/ed25519/ca-ed25519-key.pem index a78c396f7..e21c1100c 100644 --- a/certs/ed25519/ca-ed25519-key.pem +++ b/certs/ed25519/ca-ed25519-key.pem @@ -1,4 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- +-----BEGIN EDDSA PRIVATE KEY----- MFICAQAwBQYDK2VwBCIEIE3EyZVR/gbofvUgIsCeuA3yZ9E7DbTQxW7HMDYQhbxl oSIEIEEH7HUMaHISPASCB24Wb0BBbaSPCPLinadDwiQomH6s ------END RSA PRIVATE KEY----- +-----END EDDSA PRIVATE KEY----- diff --git a/certs/ed25519/client-ed25519-key.pem b/certs/ed25519/client-ed25519-key.pem index b35d30898..fc4eef62f 100644 --- a/certs/ed25519/client-ed25519-key.pem +++ b/certs/ed25519/client-ed25519-key.pem @@ -1,4 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- +-----BEGIN EDDSA PRIVATE KEY----- MFICAQAwBQYDK2VwBCIEIBGdNYxa3ommO8aYO1oGaGSRQBqDYB0sKOdR3bqejqIQ oSIEIDY9UZ60w5FgsDoJuIdapQUPW1PlZBc+cLkNZhKk5fFR ------END RSA PRIVATE KEY----- +-----END EDDSA PRIVATE KEY----- diff --git a/certs/ed25519/root-ed25519-key.pem b/certs/ed25519/root-ed25519-key.pem index be922d961..2db2a669e 100644 --- a/certs/ed25519/root-ed25519-key.pem +++ b/certs/ed25519/root-ed25519-key.pem @@ -1,4 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- +-----BEGIN EDDSA PRIVATE KEY----- MFICAQAwBQYDK2VwBCIEIFwOftlJ9QL4yEBIBh9UmTRwCu+A6puPK9OFmVk0A19P oSIEIKZgKbt92EfL1B7QbQ9XANgqH1BqQrxd5bgZZbLfJK9Q ------END RSA PRIVATE KEY----- +-----END EDDSA PRIVATE KEY----- diff --git a/certs/ed25519/server-ed25519-key.pem b/certs/ed25519/server-ed25519-key.pem index 5699e0a7c..1f1e769ce 100644 --- a/certs/ed25519/server-ed25519-key.pem +++ b/certs/ed25519/server-ed25519-key.pem @@ -1,4 +1,4 @@ ------BEGIN RSA PRIVATE KEY----- +-----BEGIN EDDSA PRIVATE KEY----- MFICAQAwBQYDK2VwBCIEINjpdrI/H/eIdfXd+HrGSTBu6Z/LnR4rwBjvu3WJ5ndn oSIEIBowiBhHL5faBPSk471sDBa5SMHRQteOkoSgdCpDng4p ------END RSA PRIVATE KEY----- +-----END EDDSA PRIVATE KEY----- diff --git a/certs/include.am b/certs/include.am index e9b8e5c5d..72ef15232 100644 --- a/certs/include.am +++ b/certs/include.am @@ -55,6 +55,23 @@ EXTRA_DIST += \ certs/server-ecc.der \ certs/server-ecc-rsa.der \ certs/server-cert-chain.der +EXTRA_DIST += \ + certs/ed25519/ca-ed25519.der \ + certs/ed25519/ca-ed25519-key.der \ + certs/ed25519/ca-ed25519-key.pem \ + certs/ed25519/ca-ed25519.pem \ + certs/ed25519/client-ed25519.der \ + certs/ed25519/client-ed25519-key.der \ + certs/ed25519/client-ed25519-key.pem \ + certs/ed25519/client-ed25519.pem \ + certs/ed25519/root-ed25519.der \ + certs/ed25519/root-ed25519-key.der \ + certs/ed25519/root-ed25519-key.pem \ + certs/ed25519/root-ed25519.pem \ + certs/ed25519/server-ed25519.der \ + certs/ed25519/server-ed25519-key.der \ + certs/ed25519/server-ed25519-key.pem \ + certs/ed25519/server-ed25519.pem dist_doc_DATA+= certs/taoCert.txt diff --git a/src/ssl.c b/src/ssl.c index 59a18ec42..23d7bce00 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -4035,16 +4035,28 @@ int PemToDer(const unsigned char* buff, long longSz, int type, switch (type) { case CA_TYPE: /* same as below */ case TRUSTED_PEER_TYPE: - case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; break; - case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; break; - case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; break; - case DSA_PARAM_TYPE: header=BEGIN_DSA_PARAM; footer=END_DSA_PARAM; break; - case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ; break; - case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; break; - case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV; break; - case RSA_TYPE: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; - case PUBLICKEY_TYPE: header=BEGIN_PUB_KEY; footer=END_PUB_KEY; break; - default: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; break; + case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; + break; + case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; + break; + case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; + break; + case DSA_PARAM_TYPE: header=BEGIN_DSA_PARAM; footer=END_DSA_PARAM; + break; + case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ; + break; + case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; + break; + case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV; + break; + case RSA_TYPE: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; + break; + case ED25519_TYPE: header=BEGIN_EDDSA_PRIV; footer=END_EDDSA_PRIV; + break; + case PUBLICKEY_TYPE: header=BEGIN_PUB_KEY; footer=END_PUB_KEY; + break; + default: header=BEGIN_RSA_PRIV; footer=END_RSA_PRIV; + break; } /* find header */ @@ -4061,6 +4073,8 @@ int PemToDer(const unsigned char* buff, long longSz, int type, header = BEGIN_EC_PRIV; footer = END_EC_PRIV; } else if (header == BEGIN_EC_PRIV) { header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV; + } else if (header == BEGIN_DSA_PRIV) { + header = BEGIN_EDDSA_PRIV; footer = END_EDDSA_PRIV; } else break; } @@ -4685,6 +4699,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, resetSuites = 1; } } + else + eccKey = 0; wc_ecc_free(&key); } @@ -4707,7 +4723,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, return SSL_BAD_FILE; } - /* check for minimum ECC key size and then free */ + /* check for minimum key size and then free */ if (ssl) { if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) { wc_ed25519_free(&key); @@ -4725,12 +4741,6 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, wc_ed25519_free(&key); ed25519Key = 1; - if (ssl) { - ssl->options.haveStaticECC = 1; - } - else if (ctx) { - ctx->haveStaticECC = 1; - } if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { resetSuites = 1; diff --git a/src/tls13.c b/src/tls13.c index 3679c06d0..e649bc467 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -4190,10 +4190,12 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } /* Check for public key of required type. */ + #ifdef HAVE_ED25519 if (args->sigAlgo == ed25519_sa_algo && !ssl->peerEd25519KeyPresent) { WOLFSSL_MSG("Oops, peer sent ED25519 key but not in verify"); } + #endif if (args->sigAlgo == ecc_dsa_sa_algo && !ssl->peerEccDsaKeyPresent) { WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 51df86d6b..180179eff 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -6550,6 +6550,8 @@ const char* BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----"; const char* END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; const char* BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; const char* END_PUB_KEY = "-----END PUBLIC KEY-----"; +const char* BEGIN_EDDSA_PRIV = "-----BEGIN EDDSA PRIVATE KEY-----"; +const char* END_EDDSA_PRIV = "-----END EDDSA PRIVATE KEY-----"; #if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA) @@ -6625,6 +6627,15 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, XSTRNCAT(footer, "\n", 1); } #endif +#ifdef HAVE_ED25519 + else if (type == EDDSA_PRIVATEKEY_TYPE) { + XSTRNCPY(header, BEGIN_EDDSA_PRIV, headerLen); + XSTRNCAT(header, "\n", 1); + + XSTRNCPY(footer, END_EDDSA_PRIV, footerLen); + XSTRNCAT(footer, "\n", 1); + } +#endif #ifdef WOLFSSL_CERT_REQ else if (type == CERTREQ_TYPE) { @@ -10230,15 +10241,6 @@ int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; - if (GetOctetString(input, inOutIdx, &privSz, inSz) >= 0) { - priv = input + *inOutIdx; - *inOutIdx += privSz; - - if (*inOutIdx != inSz) - return ASN_PARSE_E; - return wc_ed25519_import_private_only(priv, privSz, key); - } - if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; endKeyIdx = *inOutIdx + length; diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index f2c5c9aa5..1b732fa55 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -660,6 +660,8 @@ extern const char* BEGIN_DSA_PRIV; extern const char* END_DSA_PRIV; extern const char* BEGIN_PUB_KEY; extern const char* END_PUB_KEY; +extern const char* BEGIN_EDDSA_PRIV; +extern const char* END_EDDSA_PRIV; #ifdef NO_SHA #define SIGNER_DIGEST_SIZE SHA256_DIGEST_SIZE diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 9adf13cf5..0b4a8653b 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -66,6 +66,7 @@ enum CertType { RSA_PUBLICKEY_TYPE, ECC_PUBLICKEY_TYPE, TRUSTED_PEER_TYPE, + EDDSA_PRIVATEKEY_TYPE, ED25519_TYPE }; From 3429b5a3b5bd736f302b89d93528de5464aa106b Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Thu, 8 Jun 2017 09:24:39 +1000 Subject: [PATCH 27/34] Rework CheckPrivateKey --- wolfcrypt/src/asn.c | 163 +++++++++++++++++++------------------------- 1 file changed, 69 insertions(+), 94 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 180179eff..1863c2b81 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2073,132 +2073,107 @@ int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, * der : a initialized and parsed DecodedCert holding a certificate */ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) { + int ret; + if (key == NULL || der == NULL) { return BAD_FUNC_ARG; } #if !defined(NO_RSA) - { + /* test if RSA key */ + if (der->keyOID == RSAk) { RsaKey a, b; word32 keyIdx = 0; - int ret = 0; - /* test if RSA key */ - if (der->keyOID == RSAk) { - if (wc_InitRsaKey(&a, NULL) == 0 && - wc_RsaPrivateKeyDecode(key, &keyIdx, &a, keySz) == 0) { - WOLFSSL_MSG("Checking RSA key pair"); - keyIdx = 0; /* reset to 0 for parsing public key */ - - if (wc_InitRsaKey(&b, NULL) == 0) { - if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, - &b, der->pubKeySize)) == 0) { - /* limit for user RSA crypto because of RsaKey - * dereference. */ - #if defined(HAVE_USER_RSA) - WOLFSSL_MSG("Cannot verify RSA pair with user RSA"); - wc_FreeRsaKey(&b); - wc_FreeRsaKey(&a); - return 1; /* return first RSA cert as match */ - #else - /* both keys extracted successfully now check n and e - * values are the same. This is dereferencing RsaKey */ - if (mp_cmp(&(a.n), &(b.n)) != MP_EQ || - mp_cmp(&(a.e), &(b.e)) != MP_EQ) { - ret = MP_CMP_E; - } - else { - /* match found, free keys and return success */ - wc_FreeRsaKey(&b); - wc_FreeRsaKey(&a); - return 1; - } - #endif - } - wc_FreeRsaKey(&b); - } - } + if ((ret = wc_InitRsaKey(&a, NULL)) < 0) + return ret; + if ((ret = wc_InitRsaKey(&b, NULL)) < 0) { wc_FreeRsaKey(&a); - } - - /* if ret is not 0 then there was a failed comparision attempt */ - if (ret != 0) { return ret; } + if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, &a, keySz)) == 0) { + WOLFSSL_MSG("Checking RSA key pair"); + keyIdx = 0; /* reset to 0 for parsing public key */ + + if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, &b, + der->pubKeySize)) == 0) { + /* limit for user RSA crypto because of RsaKey + * dereference. */ + #if defined(HAVE_USER_RSA) + WOLFSSL_MSG("Cannot verify RSA pair with user RSA"); + ret = 1; /* return first RSA cert as match */ + #else + /* both keys extracted successfully now check n and e + * values are the same. This is dereferencing RsaKey */ + if (mp_cmp(&(a.n), &(b.n)) != MP_EQ || + mp_cmp(&(a.e), &(b.e)) != MP_EQ) { + ret = MP_CMP_E; + } + else + ret = 1; + #endif + } + } + wc_FreeRsaKey(&b); + wc_FreeRsaKey(&a); } + else #endif /* NO_RSA */ #ifdef HAVE_ECC - { - int ret = 0; + if (der->keyOID == ECDSAk) { word32 keyIdx = 0; ecc_key key_pair; - if (der->keyOID == ECDSAk) { - if ((ret = wc_ecc_init(&key_pair)) == 0 && - wc_EccPrivateKeyDecode(key, &keyIdx, &key_pair, keySz) == 0) { - WOLFSSL_MSG("Checking ECC key pair"); - keyIdx = 0; - if ((ret = wc_ecc_import_x963(der->publicKey, der->pubKeySize, - &key_pair)) == 0) { - /* public and private extracted successfuly no check if is - * a pair and also do sanity checks on key. wc_ecc_check_key - * checks that private * base generator equals pubkey */ - if ((ret = wc_ecc_check_key(&key_pair)) == 0) { - /* found a match */ - wc_ecc_free(&key_pair); - return 1; - } - - } - } - wc_ecc_free(&key_pair); - } - - /* error on attempt to match */ - if (ret != 0) { + if ((ret = wc_ecc_init(&key_pair)) < 0) return ret; + if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, &key_pair, + keySz)) == 0) { + WOLFSSL_MSG("Checking ECC key pair"); + keyIdx = 0; + if ((ret = wc_ecc_import_x963(der->publicKey, der->pubKeySize, + &key_pair)) == 0) { + /* public and private extracted successfuly no check if is + * a pair and also do sanity checks on key. wc_ecc_check_key + * checks that private * base generator equals pubkey */ + if ((ret = wc_ecc_check_key(&key_pair)) == 0) + ret = 1; + } } + wc_ecc_free(&key_pair); } + else #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 - { - int ret = 0; + if (der->keyOID == ED25519k) { word32 keyIdx = 0; ed25519_key key_pair; - if (der->keyOID == ED25519k) { - if ((ret = wc_ed25519_init(&key_pair)) == 0 && - wc_Ed25519PrivateKeyDecode(key, &keyIdx, &key_pair, keySz) - == 0) { - WOLFSSL_MSG("Checking ED25519 key pair"); - keyIdx = 0; - if ((ret = wc_ed25519_import_public(der->publicKey, - der->pubKeySize, &key_pair)) == 0) { - /* public and private extracted successfuly no check if is - * a pair and also do sanity checks on key. wc_ecc_check_key - * checks that private * base generator equals pubkey */ - if ((ret = wc_ed25519_check_key(&key_pair)) == 0) { - /* found a match */ - wc_ed25519_free(&key_pair); - return 1; - } - - } - } - wc_ed25519_free(&key_pair); - } - - /* error on attempt to match */ - if (ret != 0) { + if ((ret = wc_ed25519_init(&key_pair)) < 0) return ret; + if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, &key_pair, + keySz)) == 0) { + WOLFSSL_MSG("Checking ED25519 key pair"); + keyIdx = 0; + if ((ret = wc_ed25519_import_public(der->publicKey, der->pubKeySize, + &key_pair)) == 0) { + /* public and private extracted successfuly no check if is + * a pair and also do sanity checks on key. wc_ecc_check_key + * checks that private * base generator equals pubkey */ + if ((ret = wc_ed25519_check_key(&key_pair)) == 0) + ret = 1; + } } + wc_ed25519_free(&key_pair); } + else #endif + { + ret = 0; + } - /* no match found */ - return 0; + return ret; } #ifndef NO_PWDBASED From a00165768cb582b93fdebc6032f2691fd8fcff08 Mon Sep 17 00:00:00 2001 From: kaleb-himes Date: Thu, 8 Jun 2017 13:34:44 -0600 Subject: [PATCH 28/34] Fix compile error, too many args with --enabl-wpas --- src/ssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ssl.c b/src/ssl.c index eceafd442..1e90b71fa 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -4862,7 +4862,7 @@ static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, NULL) == 0) { WOLFSSL_MSG(" Proccessed a CRL"); wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer, - der->length,SSL_FILETYPE_ASN1, 0); + der->length,SSL_FILETYPE_ASN1); FreeDer(&der); used += info.consumed; continue; From 86809cca74be095fe6d9f4f52699836103e3dd6a Mon Sep 17 00:00:00 2001 From: kaleb-himes Date: Thu, 8 Jun 2017 20:14:15 -0600 Subject: [PATCH 29/34] Fix compile time warning with openssl extra and cryptonly --- wolfcrypt/src/wc_port.c | 3 ++- wolfcrypt/test/test.c | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 5478b9692..2104ace74 100755 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -131,7 +131,8 @@ int wolfCrypt_Init(void) WOLFSSL_MSG("Using ARM hardware acceleration"); #endif - #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + #if !defined(WOLFCRYPT_ONLY) && \ + ( defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) ) wolfSSL_EVP_init(); #endif diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 4bf48891b..9bc637df4 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -128,7 +128,9 @@ #endif #ifdef OPENSSL_EXTRA + #ifndef WOLFCRYPT_ONLY #include + #endif #include #include #include @@ -249,7 +251,9 @@ int random_test(void); #endif /* WC_NO_RNG */ int pwdbased_test(void); int ripemd_test(void); -int openssl_test(void); /* test mini api */ +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) + int openssl_test(void); /* test mini api */ +#endif int pbkdf1_test(void); int pkcs12_test(void); int pbkdf2_test(void); @@ -751,7 +755,7 @@ int wolfcrypt_test(void* args) printf( "PWDBASED test passed!\n"); #endif -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) if ( (ret = openssl_test()) != 0) return err_sys("OPENSSL test failed!\n", ret); else @@ -8430,7 +8434,7 @@ int srp_test(void) #endif /* WOLFCRYPT_HAVE_SRP */ -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) int openssl_test(void) { @@ -9121,12 +9125,11 @@ int openssl_test(void) } #endif /* ifndef NO_AES */ - return 0; } -#endif /* OPENSSL_EXTRA */ +#endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY */ #ifndef NO_PWDBASED From fdcf25b6d181fb3911a3bc02340cf913c530eb8b Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Mon, 12 Jun 2017 09:05:32 +1000 Subject: [PATCH 30/34] Fix check for PSS availability in peer --- src/internal.c | 7 ++++++- src/tls13.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/internal.c b/src/internal.c index 8a3e89b70..3db69c74d 100755 --- a/src/internal.c +++ b/src/internal.c @@ -16058,6 +16058,11 @@ void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, PickHashSigAlgo(ssl, input + *inOutIdx, len); *inOutIdx += len; + #ifdef WC_RSA_PSS + ssl->pssAlgo = 0; + if (ssl->suites->sigAlgo == rsa_pss_sa_algo) + ssl->pssAlgo |= 1 << ssl->suites->hashAlgo; + #endif } /* authorities */ @@ -18746,7 +18751,7 @@ int SendCertificateVerify(WOLFSSL* ssl) if (ssl->hsType == DYNAMIC_TYPE_RSA) { #ifdef WC_RSA_PSS if (IsAtLeastTLSv1_2(ssl) && - (ssl->pssAlgo | (1 << ssl->suites->hashAlgo))) { + (ssl->pssAlgo & (1 << ssl->suites->hashAlgo))) { args->sigAlgo = rsa_pss_sa_algo; } else diff --git a/src/tls13.c b/src/tls13.c index 852b30f80..5b313842c 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -3817,7 +3817,7 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) /* Add signature algorithm. */ if (ssl->hsType == DYNAMIC_TYPE_RSA) { #ifdef WC_RSA_PSS - if (ssl->pssAlgo | (1 << ssl->suites->hashAlgo)) + if (ssl->pssAlgo & (1 << ssl->suites->hashAlgo)) args->sigAlgo = rsa_pss_sa_algo; else #endif From 044417ba01de1b72624e779b9372fe102d58454a Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Mon, 12 Jun 2017 09:46:50 +1000 Subject: [PATCH 31/34] Fix for cache only SNI and TLS v1.3 --- src/tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tls.c b/src/tls.c index 5e5c47148..a818539c3 100755 --- a/src/tls.c +++ b/src/tls.c @@ -1595,7 +1595,7 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, /* Don't process the second ClientHello SNI extension if there * was problems with the first. */ - if (sni->status != 0) + if (!cacheOnly && sni->status != 0) break; #endif byte matched = cacheOnly || From 8dbd9a88eef51547f4736a817e91b1021e572a32 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Mon, 12 Jun 2017 14:21:43 +1000 Subject: [PATCH 32/34] Fix for CCM - TLS v1.3 needs all nonce/IV bytes --- src/keys.c | 8 ++++---- src/tls13.c | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/keys.c b/src/keys.c index 92b03d651..3a22073b0 100644 --- a/src/keys.c +++ b/src/keys.c @@ -2640,7 +2640,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, return CcmRet; } XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } if (dec) { CcmRet = wc_AesCcmSetKey(dec->aes, keys->server_write_key, @@ -2649,7 +2649,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, return CcmRet; } XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } else { @@ -2660,7 +2660,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, return CcmRet; } XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } if (dec) { CcmRet = wc_AesCcmSetKey(dec->aes, keys->client_write_key, @@ -2669,7 +2669,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, return CcmRet; } XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } if (enc) diff --git a/src/tls13.c b/src/tls13.c index 5b313842c..80c62eb08 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1616,6 +1616,10 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, switch (ssl->specs.bulk_cipher_algorithm) { #ifdef BUILD_AESGCM case wolfssl_aes_gcm: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(nonce, AESGCM_NONCE_SZ); +#endif ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input, dataSz, nonce, AESGCM_NONCE_SZ, output + dataSz, macSz, NULL, 0); break; @@ -1623,6 +1627,10 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, #ifdef HAVE_AESCCM case wolfssl_aes_ccm: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(nonce, AESCCM_NONCE_SZ); +#endif ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input, dataSz, nonce, AESCCM_NONCE_SZ, output + dataSz, macSz, NULL, 0); break; @@ -1630,6 +1638,10 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) case wolfssl_chacha: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(nonce, CHACHA_IV_BYTES); +#endif ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz, nonce, output + dataSz); break; @@ -1740,6 +1752,10 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) switch (ssl->specs.bulk_cipher_algorithm) { #ifdef BUILD_AESGCM case wolfssl_aes_gcm: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(nonce, AESGCM_NONCE_SZ); +#endif ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input, dataSz, nonce, AESGCM_NONCE_SZ, input + dataSz, macSz, NULL, 0); break; @@ -1747,6 +1763,10 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) #ifdef HAVE_AESCCM case wolfssl_aes_ccm: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(nonce, AESCCM_NONCE_SZ); +#endif ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input, dataSz, nonce, AESCCM_NONCE_SZ, input + dataSz, macSz, NULL, 0); break; @@ -1754,6 +1774,10 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) case wolfssl_chacha: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(nonce, CHACHA_IV_BYTES); +#endif ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz, nonce, input + dataSz); break; From ce231e0cbc12e80d5e9e2d08fd22597cd55475f8 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 8 Jun 2017 14:55:28 -0700 Subject: [PATCH 33/34] Fixes for asynchronous TLS 1.3. Fixes for PK_CALLBACKS with async. New helper API's for `wolfSSL_CTX_GetDevId` and `wolfSSL_CTX_GetHeap`. Fix for build to not include tls13.c if not enabled to suppress empty object file warning. Fix typo in fe_low_mem.c. General cleanup. Extra tls13.c debug messages. --- src/include.am | 7 +- src/internal.c | 85 +++-- src/ssl.c | 62 ++- src/tls.c | 4 +- src/tls13.c | 737 ++++++++++++++++++++++++------------ wolfcrypt/src/asn.c | 4 +- wolfcrypt/src/fe_low_mem.c | 2 +- wolfssl/internal.h | 27 +- wolfssl/ssl.h | 4 + wolfssl/test.h | 11 + wolfssl/wolfcrypt/ed25519.h | 7 + 11 files changed, 653 insertions(+), 297 deletions(-) diff --git a/src/include.am b/src/include.am index be2e6ac9b..22bb8edfe 100644 --- a/src/include.am +++ b/src/include.am @@ -266,8 +266,11 @@ src_libwolfssl_la_SOURCES += \ src/io.c \ src/keys.c \ src/ssl.c \ - src/tls.c \ - src/tls13.c + src/tls.c + +if BUILD_TLS13 +src_libwolfssl_la_SOURCES += src/tls13.c +endif if BUILD_OCSP src_libwolfssl_la_SOURCES += src/ocsp.c diff --git a/src/internal.c b/src/internal.c index a78a3a114..3bdf53e60 100755 --- a/src/internal.c +++ b/src/internal.c @@ -127,21 +127,6 @@ enum processReply { runProcessingOneMessage }; -/* sub-states for build message */ -enum buildMsgState { - BUILD_MSG_BEGIN = 0, - BUILD_MSG_SIZE, - BUILD_MSG_HASH, - BUILD_MSG_VERIFY_MAC, - BUILD_MSG_ENCRYPT, -}; - -/* sub-states for cipher operations */ -enum cipherState { - CIPHER_STATE_BEGIN = 0, - CIPHER_STATE_DO, - CIPHER_STATE_END, -}; /* Server random bytes for TLS v1.3 described downgrade protection mechanism. */ static const byte tls13Downgrade[7] = { @@ -2919,7 +2904,8 @@ static int TypeHash(int hashAlgo) } #if defined(WC_RSA_PSS) -static int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf) { +int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf) +{ switch (hashAlgo) { #ifdef WOLFSSL_SHA512 case sha512_mac: @@ -3105,10 +3091,11 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, return ret; ret = wc_RsaPSS_VerifyInline(verifySig, sigSz, &out, hashType, mgf, key); - if (ret > 0) + if (ret > 0) { ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, hashType); if (ret != 0) ret = VERIFY_CERT_ERROR; + } } else #endif @@ -3362,7 +3349,9 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, int side, void* ctx) { int ret; - +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev; +#endif (void)ssl; (void)pubKeyDer; (void)pubKeySz; @@ -3380,18 +3369,23 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer, pubKeySz, out, outlen, side, ctx); } + #ifdef WOLFSSL_ASYNC_CRYPT + asyncDev = &otherKey->asyncDev; + #endif } else #endif { ret = wc_ecc_shared_secret(priv_key, pub_key, out, outlen); + #ifdef WOLFSSL_ASYNC_CRYPT + asyncDev = &priv_key->asyncDev; + #endif } /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) if (ret == WC_PENDING_E) { - ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev, - WC_ASYNC_FLAG_CALL_AGAIN); + ret = wolfSSL_AsyncPush(ssl, asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -5558,6 +5552,9 @@ int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) (void)output; (void)sz; + if (ssl->hsHashes == NULL) + return BAD_FUNC_ARG; + #ifdef HAVE_FUZZER if (ssl->fuzzerCb) ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx); @@ -9307,7 +9304,7 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef WOLFSSL_ASYNC_CRYPT /* if async, offset index so this msg will be processed again */ - if (ret == WC_PENDING_E) { + if (ret == WC_PENDING_E && *inOutIdx > 0) { *inOutIdx -= HANDSHAKE_HEADER_SZ; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { @@ -9575,6 +9572,10 @@ static int DtlsMsgDrain(WOLFSSL* ssl) ssl->keys.dtls_expected_peer_handshake_number++; ret = DoHandShakeMsgType(ssl, item->msg, &idx, item->type, item->sz, item->sz); + if (ret == WC_PENDING_E) { + ssl->keys.dtls_expected_peer_handshake_number--; + break; + } ssl->dtls_rx_msg_list = item->next; DtlsMsgDelete(item, ssl->heap); item = ssl->dtls_rx_msg_list; @@ -9594,10 +9595,24 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, int ret = 0; WOLFSSL_ENTER("DoDtlsHandShakeMsg()"); + + /* process any pending DTLS messages - this flow can happen with async */ + if (ssl->dtls_rx_msg_list != NULL) { + ret = DtlsMsgDrain(ssl); + if (ret != 0) + return ret; + + /* if done processing fragment exit with success */ + if (totalSz == *inOutIdx) + return ret; + } + + /* parse header */ if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type, &size, &fragOffset, &fragSz, totalSz) != 0) return PARSE_ERROR; + /* check that we have complete fragment */ if (*inOutIdx + fragSz > totalSz) return INCOMPLETE_DATA; @@ -10209,7 +10224,7 @@ static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz, int ret = 0; #ifdef WOLFSSL_ASYNC_CRYPT - if (asyncOkay && ssl->error == WC_PENDING_E) { + if (ssl->error == WC_PENDING_E) { ssl->error = 0; /* clear async */ } #endif @@ -11956,12 +11971,12 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay) { int ret = 0; + BuildMsgArgs* args; + BuildMsgArgs lcl_args; #ifdef WOLFSSL_ASYNC_CRYPT - BuildMsgArgs* args = (BuildMsgArgs*)ssl->async.args; + args = (BuildMsgArgs*)ssl->async.args; typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; (void)sizeof(args_test); -#else - BuildMsgArgs args[1]; #endif WOLFSSL_ENTER("BuildMessage"); @@ -11973,7 +11988,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #ifdef WOLFSSL_TLS13 if (ssl->options.tls1_3) { return BuildTls13Message(ssl, output, outSz, input, inSz, type, - hashOutput, sizeOnly); + hashOutput, sizeOnly, asyncOkay); } #endif @@ -11987,7 +12002,11 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, goto exit_buildmsg; } } + else #endif + { + args = &lcl_args; + } /* Reset state */ if (ret == WC_NOT_PENDING_E) { @@ -13189,7 +13208,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) else { #ifdef WOLFSSL_TLS13 sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz, - application_data, 0, 0); + application_data, 0, 0, 1); #else sendSz = BUFFER_ERROR; #endif @@ -17921,7 +17940,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) { ecc_key* peerKey; - #ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ #ifdef HAVE_CURVE25519 if (ssl->ecdhCurveOID == ECC_X25519_OID) { @@ -17933,7 +17952,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) if (ssl->ctx->EccSharedSecretCb != NULL) { break; } - #endif + #endif /* HAVE_PK_CALLBACKS */ #ifdef HAVE_CURVE25519 if (ssl->peerX25519KeyPresent) { @@ -18261,7 +18280,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) break; } #endif - #ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { break; @@ -18679,11 +18698,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) { if (IsEncryptionOn(ssl, 1)) { ret = BuildMessage(ssl, args->output, args->sendSz, - args->input, args->inputSz, handshake, 1, 0, 1); - #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) - goto exit_scke; - #endif + args->input, args->inputSz, handshake, 1, 0, 0); XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); args->input = NULL; /* make sure its not double free'd on cleanup */ diff --git a/src/ssl.c b/src/ssl.c index a589d2a32..a67836d15 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -1439,6 +1439,27 @@ int wolfSSL_CTX_UseAsync(WOLFSSL_CTX* ctx, int devId) #endif /* WOLFSSL_ASYNC_CRYPT */ +/* helpers to get device id and heap */ +int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + int devId = INVALID_DEVID; + if (ctx != NULL) + devId = ctx->devId; + else if (ssl != NULL) + devId = ssl->devId; + return devId; +} +void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + void* heap = NULL; + if (ctx != NULL) + heap = ctx->heap; + else if (ssl != NULL) + heap = ssl->heap; + return heap; +} + + #ifdef HAVE_SNI int wolfSSL_UseSNI(WOLFSSL* ssl, byte type, const void* data, word16 size) @@ -4260,7 +4281,7 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, long* used, EncryptedInfo* info) { int ret = 0; - void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); + void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); #ifdef WOLFSSL_TLS13 int cnt = 0; #endif @@ -4401,8 +4422,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, int ed25519Key = 0; int rsaKey = 0; int resetSuites = 0; - void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); - int devId = ctx ? ctx->devId : ((ssl) ? ssl->devId : INVALID_DEVID); + void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); + int devId = wolfSSL_CTX_GetDevId(ctx, ssl); #ifdef WOLFSSL_SMALL_STACK EncryptedInfo* info = NULL; #else @@ -4965,7 +4986,7 @@ static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, NULL) == 0) { WOLFSSL_MSG(" Proccessed a CRL"); wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer, - der->length,SSL_FILETYPE_ASN1); + der->length, SSL_FILETYPE_ASN1); FreeDer(&der); used += info.consumed; continue; @@ -5525,7 +5546,7 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, int ret; long sz = 0; XFILE file; - void* heapHint = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); + void* heapHint = wolfSSL_CTX_GetHeap(ctx, ssl); (void)crl; (void)heapHint; @@ -8199,6 +8220,11 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, return SSL_FATAL_ERROR; } + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + #ifdef WOLFSSL_DTLS if (ssl->version.major == DTLS_MAJOR) { ssl->options.dtls = 1; @@ -8274,10 +8300,10 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, if (ssl->options.certOnly) return SSL_SUCCESS; -#ifdef WOLFSSL_TLS13 + #ifdef WOLFSSL_TLS13 if (ssl->options.tls1_3) return wolfSSL_connect_TLSv13(ssl); -#endif + #endif #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { @@ -8322,6 +8348,10 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, FALL_THROUGH; case FIRST_REPLY_DONE : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif #ifndef NO_CERTS if (ssl->options.sendVerify) { if ( (ssl->error = SendCertificate(ssl)) != 0) { @@ -8337,6 +8367,10 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, FALL_THROUGH; case FIRST_REPLY_FIRST : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif if (!ssl->options.resuming) { if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); @@ -8620,11 +8654,11 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, FALL_THROUGH; case ACCEPT_FIRST_REPLY_DONE : -#ifdef WOLFSSL_TLS13 + #ifdef WOLFSSL_TLS13 if (ssl->options.tls1_3) { return wolfSSL_accept_TLSv13(ssl); } -#endif + #endif if ( (ssl->error = SendServerHello(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; @@ -8634,6 +8668,11 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, FALL_THROUGH; case SERVER_HELLO_SENT : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } + #endif #ifndef NO_CERTS if (!ssl->options.resuming) if ( (ssl->error = SendCertificate(ssl)) != 0) { @@ -8658,6 +8697,11 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, FALL_THROUGH; case CERT_STATUS_SENT : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } + #endif if (!ssl->options.resuming) if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); diff --git a/src/tls.c b/src/tls.c index a06f0fb5d..0fb7f249b 100755 --- a/src/tls.c +++ b/src/tls.c @@ -4775,7 +4775,7 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) kse->key = key; #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Public ECC Key"); + WOLFSSL_MSG("Public Curve25519 Key"); WOLFSSL_BUFFER(keyData, dataSize); #endif @@ -5130,7 +5130,7 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) if (ret != 0) return ret; #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Peer ECC Key"); + WOLFSSL_MSG("Peer Curve25519 Key"); WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); #endif diff --git a/src/tls13.c b/src/tls13.c index f8cf9d2bb..6bbd1d05f 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1292,6 +1292,10 @@ static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz) { int ret = BAD_FUNC_ARG; + if (ssl->hsHashes == NULL) { + return BAD_FUNC_ARG; + } + #ifndef NO_OLD_TLS #ifndef NO_SHA ret = wc_ShaUpdate(&ssl->hsHashes->hashSha, input, sz); @@ -1593,73 +1597,135 @@ static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output, * returns 0 on success, otherwise failure. */ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, - word16 sz) + word16 sz, int asyncOkay) { int ret = 0; word16 dataSz = sz - ssl->specs.aead_mac_size; word16 macSz = ssl->specs.aead_mac_size; - byte nonce[AEAD_NONCE_SZ]; + word32 nonceSz = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev = NULL; + word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN; +#endif + + WOLFSSL_ENTER("EncryptTls13"); (void)output; (void)input; (void)sz; (void)dataSz; (void)macSz; + (void)asyncOkay; + (void)nonceSz; -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Data to encrypt"); - WOLFSSL_BUFFER(input, dataSz); +#ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->error == WC_PENDING_E) { + ssl->error = 0; /* clear async */ + } #endif - BuildTls13Nonce(ssl, nonce, ssl->keys.aead_enc_imp_IV, CUR_ORDER); - - switch (ssl->specs.bulk_cipher_algorithm) { - #ifdef BUILD_AESGCM - case wolfssl_aes_gcm: -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Nonce"); - WOLFSSL_BUFFER(nonce, AESGCM_NONCE_SZ); -#endif - ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input, dataSz, - nonce, AESGCM_NONCE_SZ, output + dataSz, macSz, NULL, 0); - break; + switch (ssl->encrypt.state) { + case CIPHER_STATE_BEGIN: + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Data to encrypt"); + WOLFSSL_BUFFER(input, dataSz); #endif - #ifdef HAVE_AESCCM - case wolfssl_aes_ccm: -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Nonce"); - WOLFSSL_BUFFER(nonce, AESCCM_NONCE_SZ); -#endif - ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input, dataSz, - nonce, AESCCM_NONCE_SZ, output + dataSz, macSz, NULL, 0); - break; - #endif + if (ssl->encrypt.nonce == NULL) + ssl->encrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES); + if (ssl->encrypt.nonce == NULL) + return MEMORY_E; - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case wolfssl_chacha: -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Nonce"); - WOLFSSL_BUFFER(nonce, CHACHA_IV_BYTES); -#endif - ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz, nonce, - output + dataSz); - break; - #endif + BuildTls13Nonce(ssl, ssl->encrypt.nonce, ssl->keys.aead_enc_imp_IV, + CUR_ORDER); - default: - WOLFSSL_MSG("wolfSSL Encrypt programming error"); - return ENCRYPT_ERROR; + /* Advance state and proceed */ + ssl->encrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + + case CIPHER_STATE_DO: + { + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + nonceSz = AESGCM_NONCE_SZ; + ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input, + dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, NULL, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + asyncDev = &ssl->encrypt.aes->asyncDev; + #endif + break; + #endif + + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + nonceSz = AESCCM_NONCE_SZ; + ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input, + dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, NULL, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + asyncDev = &ssl->encrypt.aes->asyncDev; + #endif + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + nonceSz = CHACHA_IV_BYTES; + ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz, + ssl->encrypt.nonce, output + dataSz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Encrypt programming error"); + return ENCRYPT_ERROR; + } + + /* Advance state */ + ssl->encrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + /* if async is not okay, then block */ + if (!asyncOkay) { + ret = wc_AsyncWait(ret, asyncDev, event_flags); + } + else { + /* If pending, then leave and return will resume below */ + ret = wolfSSL_AsyncPush(ssl, asyncDev, event_flags); + + return ret; + } + } + #endif + } + FALL_THROUGH; + + case CIPHER_STATE_END: + { + if (ssl->encrypt.nonce) + ForceZero(ssl->encrypt.nonce, AEAD_NONCE_SZ); + + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(ssl->encrypt.nonce, ssl->specs.iv_size); + WOLFSSL_MSG("Encrypted data"); + WOLFSSL_BUFFER(output, dataSz); + WOLFSSL_MSG("Authentication Tag"); + WOLFSSL_BUFFER(output + dataSz, macSz); + #endif + + break; + } } - ForceZero(nonce, AEAD_NONCE_SZ); - -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Encrypted data"); - WOLFSSL_BUFFER(output, dataSz); - WOLFSSL_MSG("Authentication Tag"); - WOLFSSL_BUFFER(output + dataSz, macSz); -#endif + /* Reset state */ + ssl->encrypt.state = CIPHER_STATE_BEGIN; return ret; } @@ -1732,76 +1798,160 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) int ret = 0; word16 dataSz = sz - ssl->specs.aead_mac_size; word16 macSz = ssl->specs.aead_mac_size; - byte nonce[AEAD_NONCE_SZ]; + word32 nonceSz = 0; + + WOLFSSL_ENTER("DecryptTls13"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state); + if (ret != WC_NOT_PENDING_E) { + /* check for still pending */ + if (ret == WC_PENDING_E) + return ret; + + ssl->error = 0; /* clear async */ + + /* let failures through so CIPHER_STATE_END logic is run */ + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->decrypt.state = CIPHER_STATE_BEGIN; + } (void)output; (void)input; (void)sz; (void)dataSz; (void)macSz; + (void)nonceSz; -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Data to decrypt"); - WOLFSSL_BUFFER(input, dataSz); - WOLFSSL_MSG("Authentication tag"); - WOLFSSL_BUFFER(input + dataSz, macSz); -#endif - - BuildTls13Nonce(ssl, nonce, ssl->keys.aead_dec_imp_IV, PEER_ORDER); - - switch (ssl->specs.bulk_cipher_algorithm) { - #ifdef BUILD_AESGCM - case wolfssl_aes_gcm: -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Nonce"); - WOLFSSL_BUFFER(nonce, AESGCM_NONCE_SZ); -#endif - ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input, dataSz, - nonce, AESGCM_NONCE_SZ, input + dataSz, macSz, NULL, 0); - break; + switch (ssl->decrypt.state) { + case CIPHER_STATE_BEGIN: + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Data to decrypt"); + WOLFSSL_BUFFER(input, dataSz); + WOLFSSL_MSG("Authentication tag"); + WOLFSSL_BUFFER(input + dataSz, macSz); #endif - #ifdef HAVE_AESCCM - case wolfssl_aes_ccm: -#ifdef WOLFSSL_DEBUG_TLS + if (ssl->decrypt.nonce == NULL) + ssl->decrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES); + if (ssl->decrypt.nonce == NULL) + return MEMORY_E; + + BuildTls13Nonce(ssl, ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + PEER_ORDER); + + /* Advance state and proceed */ + ssl->decrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + + case CIPHER_STATE_DO: + { + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + nonceSz = AESGCM_NONCE_SZ; + ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input, + dataSz, ssl->decrypt.nonce, nonceSz, + input + dataSz, macSz, NULL, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif + break; + #endif + + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + nonceSz = AESCCM_NONCE_SZ; + ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input, + dataSz, ssl->decrypt.nonce, nonceSz, + input + dataSz, macSz, NULL, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + nonceSz = CHACHA_IV_BYTES; + ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz, + ssl->decrypt.nonce, input + dataSz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Decrypt programming error"); + return DECRYPT_ERROR; + } + + /* Advance state */ + ssl->decrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* If pending, leave now */ + if (ret == WC_PENDING_E) { + return ret; + } + #endif + } + FALL_THROUGH; + + case CIPHER_STATE_END: + { + if (ssl->decrypt.nonce) + ForceZero(ssl->decrypt.nonce, AEAD_NONCE_SZ); + + #ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG("Nonce"); - WOLFSSL_BUFFER(nonce, AESCCM_NONCE_SZ); -#endif - ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input, dataSz, - nonce, AESCCM_NONCE_SZ, input + dataSz, macSz, NULL, 0); - break; + WOLFSSL_BUFFER(ssl->decrypt.nonce, ssl->specs.iv_size); + WOLFSSL_MSG("Decrypted data"); + WOLFSSL_BUFFER(output, dataSz); #endif - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case wolfssl_chacha: -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Nonce"); - WOLFSSL_BUFFER(nonce, CHACHA_IV_BYTES); -#endif - ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz, nonce, - input + dataSz); break; - #endif - - default: - WOLFSSL_MSG("wolfSSL Decrypt programming error"); - return DECRYPT_ERROR; + } } - ForceZero(nonce, AEAD_NONCE_SZ); if (ret < 0 && !ssl->options.dtls) { SendAlert(ssl, alert_fatal, bad_record_mac); ret = VERIFY_MAC_ERROR; } -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Decrypted data"); - WOLFSSL_BUFFER(output, dataSz); -#endif - return ret; } +/* Persistable BuildMessage arguments */ +typedef struct BuildMsg13Args { + word32 sz; + word32 idx; + word32 headerSz; + word16 size; +} BuildMsg13Args; + +static void FreeBuildMsg13Args(WOLFSSL* ssl, void* pArgs) +{ + BuildMsg13Args* args = (BuildMsg13Args*)pArgs; + + (void)ssl; + (void)args; + + /* no allocations in BuildTls13Message */ +} + /* Build SSL Message, encrypted. * TLS v1.3 encryption is AEAD only. * @@ -1816,83 +1966,151 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) * returns the size of the encrypted record message or negative value on error. */ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, - int inSz, int type, int hashOutput, int sizeOnly) + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay) { - word32 sz = RECORD_HEADER_SZ + inSz; - word32 idx = RECORD_HEADER_SZ; - word32 headerSz = RECORD_HEADER_SZ; - word16 size; - int ret = 0; - int atomicUser = 0; - - if (ssl == NULL) - return BAD_FUNC_ARG; - if (!sizeOnly && (output == NULL || input == NULL)) - return BAD_FUNC_ARG; - /* catch mistaken sizeOnly parameter */ - if (sizeOnly && (output || input)) { - WOLFSSL_MSG("BuildMessage with sizeOnly doesn't need input or output"); - return BAD_FUNC_ARG; - } - - /* Record layer content type at the end of record data. */ - sz++; - /* Authentication data at the end. */ - sz += ssl->specs.aead_mac_size; - - if (sizeOnly) - return sz; - - if (sz > (word32)outSz) { - WOLFSSL_MSG("Oops, want to write past output buffer size"); - return BUFFER_E; - } - - /* Record data length. */ - size = (word16)(sz - headerSz); - /* Write/update the record header with the new size. - * Always have the content type as application data for encrypted - * messages in TLS v1.3. - */ - AddTls13RecordHeader(output, size, application_data, ssl); - - /* TLS v1.3 can do in place encryption. */ - if (input != output + idx) - XMEMCPY(output + idx, input, inSz); - idx += inSz; - - if (hashOutput) { - ret = HashOutput(ssl, output, headerSz + inSz, 0); - if (ret != 0) - return ret; - } - - /* The real record content type goes at the end of the data. */ - output[idx++] = type; - -#ifdef ATOMIC_USER - if (ssl->ctx->MacEncryptCb) - atomicUser = 1; + int ret = 0; + BuildMsg13Args* args; + BuildMsg13Args lcl_args; +#ifdef WOLFSSL_ASYNC_CRYPT + args = (BuildMsg13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); #endif - if (atomicUser) { /* User Record Layer Callback handling */ -#ifdef ATOMIC_USER - byte* mac = output + idx; - output += headerSz; + WOLFSSL_ENTER("BuildTls13Message"); - if ((ret = ssl->ctx->MacEncryptCb(ssl, mac, output, inSz, type, 0, - output, output, size, ssl->MacEncryptCtx)) != 0) { - return ret; + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ret = WC_NOT_PENDING_E; +#ifdef WOLFSSL_ASYNC_CRYPT + if (asyncOkay) { + ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_buildmsg; } -#endif } - else { - output += headerSz; - if ((ret = EncryptTls13(ssl, output, output, size)) != 0) - return ret; + else +#endif + { + args = &lcl_args; } - return sz; + /* Reset state */ + if (ret == WC_NOT_PENDING_E) { + ret = 0; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + XMEMSET(args, 0, sizeof(BuildMsg13Args)); + + args->sz = RECORD_HEADER_SZ + inSz; + args->idx = RECORD_HEADER_SZ; + args->headerSz = RECORD_HEADER_SZ; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeBuildMsg13Args; + #endif + } + + switch (ssl->options.buildMsgState) { + case BUILD_MSG_BEGIN: + { + if (!sizeOnly && (output == NULL || input == NULL)) + return BAD_FUNC_ARG; + /* catch mistaken sizeOnly parameter */ + if (sizeOnly && (output || input)) { + WOLFSSL_MSG("BuildMessage with sizeOnly doesn't need input or output"); + return BAD_FUNC_ARG; + } + + /* Record layer content type at the end of record data. */ + args->sz++; + /* Authentication data at the end. */ + args->sz += ssl->specs.aead_mac_size; + + if (sizeOnly) + return args->sz; + + if (args->sz > (word32)outSz) { + WOLFSSL_MSG("Oops, want to write past output buffer size"); + return BUFFER_E; + } + + /* Record data length. */ + args->size = (word16)(args->sz - args->headerSz); + /* Write/update the record header with the new size. + * Always have the content type as application data for encrypted + * messages in TLS v1.3. + */ + AddTls13RecordHeader(output, args->size, application_data, ssl); + + /* TLS v1.3 can do in place encryption. */ + if (input != output + args->idx) + XMEMCPY(output + args->idx, input, inSz); + args->idx += inSz; + + ssl->options.buildMsgState = BUILD_MSG_HASH; + } + FALL_THROUGH; + + case BUILD_MSG_HASH: + { + if (hashOutput) { + ret = HashOutput(ssl, output, args->headerSz + inSz, 0); + if (ret != 0) + goto exit_buildmsg; + } + + ssl->options.buildMsgState = BUILD_MSG_ENCRYPT; + } + FALL_THROUGH; + + case BUILD_MSG_ENCRYPT: + { + /* The real record content type goes at the end of the data. */ + output[args->idx++] = type; + + #ifdef ATOMIC_USER + if (ssl->ctx->MacEncryptCb) { + /* User Record Layer Callback handling */ + byte* mac = output + args->idx; + output += args->headerSz; + + ret = ssl->ctx->MacEncryptCb(ssl, mac, output, inSz, type, 0, + output, output, args->size, ssl->MacEncryptCtx); + } + else + #endif + { + output += args->headerSz; + ret = EncryptTls13(ssl, output, output, args->size, asyncOkay); + } + break; + } + } + +exit_buildmsg: + + WOLFSSL_LEAVE("BuildTls13Message", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } +#endif + + /* make sure build message state is reset */ + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + + /* return sz on success */ + if (ret == 0) + ret = args->sz; + + /* Final cleanup */ + FreeBuildMsg13Args(ssl, args); + + return ret; } #ifndef NO_WOLFSSL_CLIENT @@ -2043,6 +2261,8 @@ int SendTls13ClientHello(WOLFSSL* ssl) int sendSz; int ret; + WOLFSSL_ENTER("SendTls13ClientHello"); + #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) if (ssl->options.resuming && (ssl->session.version.major != ssl->version.major || @@ -2166,6 +2386,8 @@ static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input, word16 totalExtSz; ProtocolVersion pv; + WOLFSSL_ENTER("DoTls13HelloRetryRequest"); + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("HelloRetryRequest", &ssl->handShakeInfo); if (ssl->toInfoOn) AddLateName("HelloRetryRequest", &ssl->timeoutInfo); @@ -2234,6 +2456,8 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int ret; word16 totalExtSz; + WOLFSSL_ENTER("DoTls13ServerHello"); + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); @@ -2337,6 +2561,8 @@ static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, word32 i = begin; word16 totalExtSz; + WOLFSSL_ENTER("DoTls13EncryptedExtensions"); + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("EncryptedExtensions", &ssl->handShakeInfo); @@ -2362,7 +2588,7 @@ static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, /* Always encrypted. */ *inOutIdx += ssl->keys.padSz; - return 0; + return ret; } /* Handle a TLS v1.3 CertificateRequest message. @@ -2384,11 +2610,12 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, int ret; Suites peerSuites; - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("CertificateRequest", - &ssl->handShakeInfo); - if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo); - #endif + WOLFSSL_ENTER("DoTls13CertificateRequest"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("CertificateRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo); +#endif if ((*inOutIdx - begin) + OPAQUE8_LEN > size) return BUFFER_ERROR; @@ -2427,7 +2654,7 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, /* This message is always encrypted so add encryption padding. */ *inOutIdx += ssl->keys.padSz; - return 0; + return ret; } #endif /* !NO_WOLFSSL_CLIENT */ @@ -2646,6 +2873,8 @@ static int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word16 totalExtSz; int usingPSK = 0; + WOLFSSL_ENTER("DoTls13ClientHello"); + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo); if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo); @@ -2674,7 +2903,6 @@ static int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_BUFFER(ssl->arrays->clientRandom, RAN_LEN); #endif - /* Session id - empty in TLS v1.3 */ b = input[i++]; if (b != 0) { @@ -2787,7 +3015,7 @@ static int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->options.clientState = CLIENT_HELLO_COMPLETE; - return 0; + return ret; } /* Send the HelloRetryRequest message to indicate the negotiated protocol @@ -2806,6 +3034,8 @@ int SendTls13HelloRetryRequest(WOLFSSL* ssl) word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; int sendSz; + WOLFSSL_ENTER("SendTls13HelloRetryRequest"); + /* Get the length of the extensions that will be written. */ len = TLSX_GetResponseSize(ssl, hello_retry_request); /* There must be extensions sent to indicate what client needs to do. */ @@ -2884,6 +3114,8 @@ int SendTls13ServerHello(WOLFSSL* ssl) int sendSz; int ret; + WOLFSSL_ENTER("SendTls13ServerHello"); + /* Protocol version, server random, cipher suite and extensions. */ length = VERSION_SZ + RAN_LEN + SUITE_LEN + TLSX_GetResponseSize(ssl, server_hello); @@ -2968,6 +3200,8 @@ int SendTls13EncryptedExtensions(WOLFSSL* ssl) word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; int sendSz; + WOLFSSL_ENTER("SendTls13EncryptedExtensions"); + ssl->keys.encryptionOn = 1; /* Derive the handshake secret now that we are at first message to be @@ -3013,7 +3247,7 @@ int SendTls13EncryptedExtensions(WOLFSSL* ssl) /* This handshake message is always encrypted. */ sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, - idx - RECORD_HEADER_SZ, handshake, 1, 0); + idx - RECORD_HEADER_SZ, handshake, 1, 0, 0); if (sendSz < 0) return sendSz; @@ -3041,15 +3275,19 @@ int SendTls13CertificateRequest(WOLFSSL* ssl) int ret; int sendSz; int reqCtxLen = 0; - word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + word32 i; + int reqSz; - int reqSz = OPAQUE8_LEN + reqCtxLen + - TLSX_GetResponseSize(ssl, certificate_request); + WOLFSSL_ENTER("SendTls13CertificateRequest"); if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) return 0; /* not needed */ - sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz; + i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + reqSz = OPAQUE8_LEN + reqCtxLen + + TLSX_GetResponseSize(ssl, certificate_request); + + sendSz = i + reqSz; /* Always encrypted and make room for padding. */ sendSz += MAX_MSG_EXTRA; @@ -3075,7 +3313,7 @@ int SendTls13CertificateRequest(WOLFSSL* ssl) /* Always encrypted. */ sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, - i - RECORD_HEADER_SZ, handshake, 1, 0); + i - RECORD_HEADER_SZ, handshake, 1, 0, 0); if (sendSz < 0) return sendSz; @@ -3178,24 +3416,31 @@ static INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType) */ static INLINE int GetMsgHash(WOLFSSL* ssl, byte* hash) { + int ret = 0; switch (ssl->specs.mac_algorithm) { #ifndef NO_SHA256 case sha256_mac: - wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + if (ret != 0) + break; return SHA256_DIGEST_SIZE; #endif /* !NO_SHA256 */ #ifdef WOLFSSL_SHA384 case sha384_mac: - wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + if (ret != 0) + break; return SHA384_DIGEST_SIZE; #endif /* WOLFSSL_SHA384 */ #ifdef WOLFSSL_SHA512 case sha512_mac: - wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + if (ret != 0) + break; return SHA512_DIGEST_SIZE; #endif /* WOLFSSL_SHA512 */ } - return 0; + return ret; } /* The length of the certificate verification label - client and server. */ @@ -3223,11 +3468,12 @@ static const byte clientCertVfyLabel[CERT_VFY_LABEL_SZ] = * sigDataSz The length of the signature data. * check Indicates this is a check not create. */ -static void CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz, +static int CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz, int check) { word16 idx; int side = ssl->options.side; + int ret; /* Signature Data = Prefix | Label | Handshake Hash */ XMEMSET(sigData, SIGNING_DATA_PREFIX_BYTE, SIGNING_DATA_PREFIX_SZ); @@ -3247,7 +3493,14 @@ static void CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz, #endif idx += CERT_VFY_LABEL_SZ; - *sigDataSz = idx + GetMsgHash(ssl, &sigData[idx]); + ret = GetMsgHash(ssl, &sigData[idx]); + if (ret < 0) + return ret; + + *sigDataSz = idx + ret; + ret = 0; + + return ret; } #ifndef NO_RSA @@ -3419,63 +3672,53 @@ static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo, #endif word32 sigSz; - CreateSigData(ssl, sigData, &sigDataSz, 1); + ret = CreateSigData(ssl, sigData, &sigDataSz, 1); + if (ret != 0) + return ret; + #ifdef WC_RSA_PSS if (sigAlgo == rsa_pss_sa_algo) { enum wc_HashType hashType = WC_HASH_TYPE_NONE; - switch (hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif - break; - } - - ret = sigSz = CreateRSAEncodedSig(sigData, sigData, sigDataSz, - rsa_pss_sa_algo, hashAlgo); + ret = ConvertHashPss(hashAlgo, &hashType, NULL); if (ret < 0) return ret; + /* PSS signature can be done in-pace */ + ret = CreateRSAEncodedSig(sigData, sigData, sigDataSz, + sigAlgo, hashAlgo); + if (ret < 0) + return ret; + sigSz = ret; + ret = wc_RsaPSS_CheckPadding(sigData, sigSz, decSig, decSigSz, hashType); } else #endif { -#ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (encodedSig == NULL) { - ret = MEMORY_E; - goto end; + return MEMORY_E; } -#endif + #endif + + sigSz = CreateRSAEncodedSig(encodedSig, sigData, sigDataSz, sigAlgo, + hashAlgo); - sigSz = CreateRSAEncodedSig(encodedSig, sigData, sigDataSz, - DYNAMIC_TYPE_RSA, hashAlgo); /* Check the encoded and decrypted signature data match. */ if (decSigSz != sigSz || decSig == NULL || XMEMCMP(decSig, encodedSig, sigSz) != 0) { ret = VERIFY_CERT_ERROR; } - } -#ifdef WOLFSSL_SMALL_STACK -end: - if (encodedSig != NULL) - XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif + #ifdef WOLFSSL_SMALL_STACK + if (encodedSig != NULL) + XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } return ret; } @@ -3556,6 +3799,7 @@ int SendTls13Certificate(WOLFSSL* ssl) word32 offset = OPAQUE16_LEN; byte* p = NULL; + WOLFSSL_ENTER("SendTls13Certificate"); /* TODO: [TLS13] Request context for post-handshake auth. * Taken from request if post-handshake. @@ -3707,7 +3951,7 @@ int SendTls13Certificate(WOLFSSL* ssl) /* This message is always encrypted. */ sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, - i - RECORD_HEADER_SZ, handshake, 1, 0); + i - RECORD_HEADER_SZ, handshake, 1, 0, 0); if (sendSz < 0) return sendSz; @@ -3873,7 +4117,9 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) ERROR_OUT(MEMORY_E, exit_scv); } - CreateSigData(ssl, args->sigData, &args->sigDataSz, 0); + ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 0); + if (ret != 0) + goto exit_scv; #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { @@ -3954,8 +4200,6 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) #endif #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { - /* restore verify pointer */ - args->verify = &args->output[args->idx]; ret = RsaSign(ssl, sig->buffer, sig->length, args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen, @@ -3987,9 +4231,6 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) case TLS_ASYNC_VERIFY: { - /* restore verify pointer */ - args->verify = &args->output[args->idx]; - #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { if (args->verifySig == NULL) { @@ -4029,17 +4270,6 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + args->length + HASH_SIG_SIZE + VERIFY_HEADER; - /* This message is always encrypted. */ - args->sendSz = BuildTls13Message(ssl, args->output, - MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, - args->output + RECORD_HEADER_SZ, - args->sendSz - RECORD_HEADER_SZ, handshake, - 1, 0); - if (args->sendSz < 0) { - ret = args->sendSz; - goto exit_scv; - } - /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_END; } /* case TLS_ASYNC_FINALIZE */ @@ -4047,6 +4277,21 @@ int SendTls13CertificateVerify(WOLFSSL* ssl) case TLS_ASYNC_END: { + /* This message is always encrypted. */ + ret = BuildTls13Message(ssl, args->output, + MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, + args->output + RECORD_HEADER_SZ, + args->sendSz - RECORD_HEADER_SZ, handshake, + 1, 0, 0); + + if (ret < 0) { + goto exit_scv; + } + else { + args->sendSz = ret; + ret = 0; + } + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("CertificateVerify", &ssl->handShakeInfo); @@ -4248,7 +4493,9 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, ERROR_OUT(MEMORY_E, exit_dcv); } - CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + 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) @@ -4280,7 +4527,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, case TLS_ASYNC_DO: { #ifndef NO_RSA - if (args->sigAlgo == rsa_sa_algo || + if (args->sigAlgo == rsa_sa_algo || args->sigAlgo == rsa_pss_sa_algo) { WOLFSSL_MSG("Doing RSA peer cert verify"); @@ -4550,7 +4797,7 @@ int SendTls13Finished(WOLFSSL* ssl) /* This message is always encrypted. */ sendSz = BuildTls13Message(ssl, output, outputSz, input, - headerSz + finishedSz, handshake, 1, 0); + headerSz + finishedSz, handshake, 1, 0, 0); if (sendSz < 0) return BUILD_MSG_ERROR; @@ -4642,7 +4889,7 @@ static int SendTls13KeyUpdate(WOLFSSL* ssl) /* This message is always encrypted. */ sendSz = BuildTls13Message(ssl, output, outputSz, input, - headerSz + OPAQUE8_LEN, handshake, 0, 0); + headerSz + OPAQUE8_LEN, handshake, 0, 0, 0); if (sendSz < 0) return BUILD_MSG_ERROR; @@ -4886,7 +5133,7 @@ int SendTls13NewSessionTicket(WOLFSSL* ssl) /* This message is always encrypted. */ sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, - idx - RECORD_HEADER_SZ, handshake, 0, 0); + idx - RECORD_HEADER_SZ, handshake, 0, 0, 0); if (sendSz < 0) return sendSz; @@ -5175,6 +5422,11 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, break; } + /* reset error */ + if (ret == 0 && ssl->error == WC_PENDING_E) + ssl->error = 0; + + if (ret == 0 && type != client_hello && type != session_ticket && type != key_update && ssl->error != WC_PENDING_E) { ret = HashInput(ssl, input + inIdx, size); @@ -5429,7 +5681,8 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) FALL_THROUGH; case HELLO_AGAIN_REPLY: - if (ssl->options.serverState == NULL_STATE) { + if (ssl->options.serverState == NULL_STATE || + ssl->error == WC_PENDING_E) { neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 2e853a828..08afa3b62 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -5835,8 +5835,8 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) break; #elif defined(WOLFSSL_CERT_EXT) /* decode cert policy */ - if (DecodePolicyOID(cert->extCertPolicies[cert->extCertPoliciesNb], MAX_CERTPOL_SZ, - input + idx, length) != 0) { + if (DecodePolicyOID(cert->extCertPolicies[cert->extCertPoliciesNb], + MAX_CERTPOL_SZ, input + idx, length) != 0) { WOLFSSL_MSG("\tCouldn't decode CertPolicy"); return ASN_PARSE_E; } diff --git a/wolfcrypt/src/fe_low_mem.c b/wolfcrypt/src/fe_low_mem.c index aa6a44996..0f0f1be44 100644 --- a/wolfcrypt/src/fe_low_mem.c +++ b/wolfcrypt/src/fe_low_mem.c @@ -20,7 +20,7 @@ */ -/* Based from Daniel Beer's public domain word. */ +/* Based from Daniel Beer's public domain work. */ #ifdef HAVE_CONFIG_H #include diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 4293dd873..42d6376ab 100755 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2672,6 +2672,22 @@ enum asyncState { TLS_ASYNC_END }; +/* sub-states for build message */ +enum buildMsgState { + BUILD_MSG_BEGIN = 0, + BUILD_MSG_SIZE, + BUILD_MSG_HASH, + BUILD_MSG_VERIFY_MAC, + BUILD_MSG_ENCRYPT, +}; + +/* sub-states for cipher operations */ +enum cipherState { + CIPHER_STATE_BEGIN = 0, + CIPHER_STATE_DO, + CIPHER_STATE_END, +}; + typedef struct Options { #ifndef NO_PSK wc_psk_client_callback client_psk_cb; @@ -3468,9 +3484,12 @@ WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl); WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); #ifndef NO_CERTS #ifndef NO_RSA - WOLFSSL_LOCAL int CheckRsaPssPadding(const byte* plain, word32 plainSz, - byte* out, word32 sigSz, - enum wc_HashType hashType); + #ifdef WC_RSA_PSS + WOLFSSL_LOCAL int CheckRsaPssPadding(const byte* plain, word32 plainSz, + byte* out, word32 sigSz, + enum wc_HashType hashType); + WOLFSSL_LOCAL int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf); + #endif WOLFSSL_LOCAL int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, const byte* plain, word32 plainSz, @@ -3637,7 +3656,7 @@ WOLFSSL_LOCAL int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, #ifdef WOLFSSL_TLS13 int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, - int inSz, int type, int hashOutput, int sizeOnly); + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay); #endif WOLFSSL_LOCAL int AllocKey(WOLFSSL* ssl, int type, void** pKey); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 7e573a398..59608670b 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1701,6 +1701,10 @@ WOLFSSL_API int wolfSSL_UseClientSuites(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_UseAsync(WOLFSSL*, int devId); WOLFSSL_API int wolfSSL_CTX_UseAsync(WOLFSSL_CTX*, int devId); +/* helpers to get device id and heap */ +WOLFSSL_API int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl); + /* TLS Extensions */ /* Server Name Indication */ diff --git a/wolfssl/test.h b/wolfssl/test.h index 7535465af..a22a8af37 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -1803,6 +1803,11 @@ static INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, ret = wc_InitRng(&rng); if (ret == 0) { ret = wc_ecc_make_key_ex(&rng, 0, privKey, otherKey->dp->id); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif if (ret == 0) ret = wc_ecc_export_x963(privKey, pubKeyDer, pubKeySz); wc_FreeRng(&rng); @@ -1824,6 +1829,12 @@ static INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, /* generate shared secret and return it */ if (ret == 0) { ret = wc_ecc_shared_secret(privKey, pubKey, out, outlen); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif } wc_ecc_free(&tmpKey); diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index f806785aa..049e4a61d 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -32,6 +32,10 @@ #include #include +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -69,6 +73,9 @@ struct ed25519_key { byte pointX[ED25519_KEY_SIZE]; /* recovered X coordinate */ byte pointY[ED25519_KEY_SIZE]; /* Y coordinate is the public key with The most significant bit of the final octet always zero. */ #endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif }; From af2cbcdbabe716a4addc87fa267085bfc9a37232 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 9 Jun 2017 08:57:50 -0700 Subject: [PATCH 34/34] Added new arg documentation for `asyncOkay` in doxygen style. --- src/tls13.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tls13.c b/src/tls13.c index 6bbd1d05f..c3ac01cf9 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1594,6 +1594,7 @@ static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output, * May be the same pointer as input. * input The data to encrypt. * sz The number of bytes to encrypt. + * asyncOkay If non-zero can return WC_PENDING_E, otherwise blocks on crypto * returns 0 on success, otherwise failure. */ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, @@ -1963,6 +1964,7 @@ static void FreeBuildMsg13Args(WOLFSSL* ssl, void* pArgs) * type The recorder header content type. * hashOutput Whether to hash the unencrypted record data. * sizeOnly Only want the size of the record message. + * asyncOkay If non-zero can return WC_PENDING_E, otherwise blocks on crypto * returns the size of the encrypted record message or negative value on error. */ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input,