From b47fca5760ca220e4afee024c109633735b7700b Mon Sep 17 00:00:00 2001 From: jrblixt Date: Fri, 19 May 2017 13:22:42 -0600 Subject: [PATCH 1/6] Patched and Clean up for PR. --- tests/api.c | 297 +++++++++++++++++++++++++++++++++++++++++++ wolfcrypt/src/des3.c | 15 +++ 2 files changed, 312 insertions(+) diff --git a/tests/api.c b/tests/api.c index 13b709e42..72251a6a9 100644 --- a/tests/api.c +++ b/tests/api.c @@ -64,6 +64,10 @@ #ifdef WOLFSSL_RIPEMD #include #endif +#ifndef NO_DES3 + #include + #include +#endif #ifdef OPENSSL_EXTRA #include @@ -3728,6 +3732,294 @@ static int test_wc_Sha224Final (void) } /* END test_wc_Sha224Final */ +/* + * unit test for wc_Des3_SetIV() + */ +static int test_wc_Des3_SetIV (void) +{ +#ifndef NO_DES3 + Des3 des; + int ret; + const byte key[] = + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + }; + + const byte iv[] = + { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 + }; + + printf(testingFmt, "wc_Des3_SetIV()"); + + /* DES_ENCRYPTION or DES_DECRYPTION */ + ret = wc_Des3_SetKey(&des, key, iv, DES_ENCRYPTION); + + AssertIntEQ(XMEMCMP(iv, des.reg, DES_BLOCK_SIZE), 0); + + /* Test explicitly wc_Des3_SetIV() */ + if (ret == 0) { + ret = wc_Des3_SetIV(NULL, iv); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_SetIV(&des, NULL); + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Des3_SetIV */ + +/* + * unit test for wc_Des3_SetKey() + */ +static int test_wc_Des3_SetKey (void) +{ +#ifndef NO_DES3 + Des3 des; + int ret; + const byte key[] = + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + }; + + const byte iv[] = + { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 + }; + + printf(testingFmt, "wc_Des3_SetKey()"); + + /* DES_ENCRYPTION or DES_DECRYPTION */ + ret = wc_Des3_SetKey(&des, key, iv, DES_ENCRYPTION); + + AssertIntEQ(XMEMCMP(iv, des.reg, DES_BLOCK_SIZE), 0); + + /* Test bad args. */ + if (ret == 0) { + ret = wc_Des3_SetKey(NULL, key, iv, DES_ENCRYPTION); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_SetKey(&des, NULL, iv, DES_ENCRYPTION); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_SetKey(&des, key, iv, -1); + } + if (ret == BAD_FUNC_ARG) { + /* Default case. Should return 0. */ + ret = wc_Des3_SetKey(&des, key, NULL, DES_ENCRYPTION); + } + } /* END if ret != 0 */ + + printf(resultFmt, ret == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Des3_SetKey */ + +/* + * Test function for wc_Des3_CbcEncrypt and wc_Des3_CbcDecrypt + */ +static int test_wc_Des3_CbcEncryptDecrypt (void) +{ +#ifndef NO_DES3 + Des3 des; + + #ifndef WOLFSSL_SMALL_STACK + byte cipher[24]; + byte plain[24]; + #elif defined(WOLFSSL_SMALL_STACK) + byte* cipher = (byte*) malloc(sizeof(byte) * 24); + byte* plain = (byte*) malloc(sizeof(byte) * 24); + #endif + + int ret; + + const byte key[] = + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + }; + + const byte iv[] = + { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 + }; + + const byte vector[] = { /* "Now is the time for all " w/o trailing 0 */ + 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, + 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, + 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 + }; + + printf(testingFmt, "wc_Des3_CbcEncrypt()"); + + AssertIntEQ(wc_Des3_SetKey(&des, key, iv, DES_ENCRYPTION), 0); + + ret = wc_Des3_CbcEncrypt(&des, cipher, vector, 24); + + AssertIntEQ(wc_Des3_SetKey(&des, key, iv, DES_DECRYPTION), 0); + + if (ret == 0) { + ret = wc_Des3_CbcDecrypt(&des, plain, cipher, 24); + } + + AssertIntEQ(XMEMCMP(plain, vector, 24), 0); + + /* Pass in bad args. */ + if (ret == 0) { + ret = wc_Des3_CbcEncrypt(NULL, cipher, vector, 24); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcEncrypt(&des, NULL, vector, 24); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcEncrypt(&des, cipher, NULL, sizeof(vector)); + } + if (ret != BAD_FUNC_ARG) { + printf("\nReturn code: %d\n", ret); + ret = SSL_FAILURE; + } else { + ret = 0; + } + } + + if (ret == 0) { + ret = wc_Des3_CbcDecrypt(NULL, plain, cipher, 24); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcDecrypt(&des, NULL, cipher, 24); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcDecrypt(&des, plain, NULL, 24); + } + if (ret != BAD_FUNC_ARG) { + printf("\nReturn code: %d\n", ret); + ret = SSL_FAILURE; + } else { + ret = 0; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(plain, NULL, DYNAMIC_TYPE_NONE); + XFREE(cipher, NULL, DYNAMIC_TYPE_CIPHER); + #endif +#endif + return 0; + +} /* END wc_Des3_CbcEncrypt */ + +/* + * Unit test for wc_Des3_CbcEncryptWithKey and wc_Des3_CbcDecryptWithKey + */ +static int test_wc_Des3_CbcEncryptDecryptWithKey (void) +{ +#ifndef NO_DES3 + + word32 vectorSz, cipherSz; + int ret; + + #ifndef WOLFSSL_SMALL_STACK + byte cipher[24]; + byte plain[24]; + #elif defined(WOLFSSL_SMALL_STACK) + byte* cipher = (byte*) malloc(sizeof(byte) * 24); + byte* plain = (byte*) malloc(sizeof(byte) * 24); + #endif + + byte vector[] = /* Now is the time for all w/o trailing 0 */ + { + 0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, + 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, + 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 + }; + + byte key[] = + { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + }; + + byte iv[] = + { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 + }; + + vectorSz = sizeof(byte) * 24; + cipherSz = sizeof(byte) * 24; + + printf(testingFmt, "wc_Des3_CbcEncryptWithKey()"); + + ret = wc_Des3_CbcEncryptWithKey(cipher, vector, vectorSz, key, iv); + if (ret == 0) { + ret = wc_Des3_CbcDecryptWithKey(plain, cipher, cipherSz, key, iv); + AssertIntEQ(XMEMCMP(plain, vector, 24), 0); + } + + /* pass in bad args. */ + if (ret == 0) { + ret = wc_Des3_CbcEncryptWithKey(NULL, vector, vectorSz, key, iv); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcEncryptWithKey(cipher, NULL, vectorSz, key, iv); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcEncryptWithKey(cipher, vector, vectorSz, NULL, iv); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcEncryptWithKey(cipher, vector, vectorSz, + key, NULL); + } else { + /* Return code catch. */ + printf("\nReturn code: %d\n", ret); + ret = SSL_FAILURE; + } + } + + if (ret == 0) { + ret = wc_Des3_CbcDecryptWithKey(NULL, cipher, cipherSz, key, iv); + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcDecryptWithKey(plain, NULL, cipherSz, key, iv); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcDecryptWithKey(plain, cipher, cipherSz, NULL, iv); + } + if (ret == BAD_FUNC_ARG) { + ret = wc_Des3_CbcDecryptWithKey(plain, cipher, cipherSz, key, NULL); + } else { + printf("\nReturn code: %d\n", ret); + ret = SSL_FAILURE; + } + } + + printf(resultFmt, ret == 0 ? passed : failed); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(plain, NULL, DYNAMIC_TYPE_NONE); + XFREE(cipher, NULL, DYNAMIC_TYPE_CIPHER); + #endif + +#endif + return 0; +} /* END test_wc_Des3_CbcEncryptDecryptWithKey */ + + /*----------------------------------------------------------------------------* | Compatibility Tests *----------------------------------------------------------------------------*/ @@ -4986,6 +5278,11 @@ void ApiTest(void) AssertFalse(test_wc_InitRipeMd()); AssertFalse(test_wc_RipeMdUpdate()); AssertFalse(test_wc_RipeMdFinal()); + + AssertIntEQ(test_wc_Des3_SetIV(), 0); + AssertIntEQ(test_wc_Des3_SetKey(), 0); + AssertIntEQ(test_wc_Des3_CbcEncryptDecrypt(), 0); + AssertIntEQ(test_wc_Des3_CbcEncryptDecryptWithKey(), 0); printf(" End API Tests\n"); } diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c index 739fb62d6..24c170e7d 100755 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -1395,6 +1395,10 @@ { int ret; + if (des == NULL || key == NULL || dir < 0) { + return BAD_FUNC_ARG; + } + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { /* key_raw holds orignal key copy */ @@ -1535,6 +1539,10 @@ { word32 blocks; + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES && sz >= WC_ASYNC_THRESH_DES3_CBC) { @@ -1574,6 +1582,10 @@ { word32 blocks; + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + #if defined(WOLFSSL_ASYNC_CRYPT) if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES && sz >= WC_ASYNC_THRESH_DES3_CBC) { @@ -1661,6 +1673,9 @@ void wc_Des_SetIV(Des* des, const byte* iv) int wc_Des3_SetIV(Des3* des, const byte* iv) { + if (des == NULL) { + return BAD_FUNC_ARG; + } if (des && iv) XMEMCPY(des->reg, iv, DES_BLOCK_SIZE); else if (des) From 4d458831b77798805147d39c70b77d18e450343b Mon Sep 17 00:00:00 2001 From: jrblixt Date: Fri, 19 May 2017 16:15:13 -0600 Subject: [PATCH 2/6] Jenkins fixes. --- wolfcrypt/src/des3.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c index 24c170e7d..534f59d9a 100755 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -25,6 +25,8 @@ #endif #include +#include +#include #ifndef NO_DES3 @@ -39,6 +41,10 @@ } int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) { + if (des == NULL || key == NULL || dir < 0) { + return BAD_FUNC_ARG; + } + return Des3_SetKey_fips(des, key, iv, dir); } int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) @@ -51,10 +57,16 @@ } int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) { + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } return Des3_CbcEncrypt_fips(des, out, in, sz); } int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) { + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } return Des3_CbcDecrypt_fips(des, out, in, sz); } @@ -102,8 +114,6 @@ #include #else -#include -#include #ifdef NO_INLINE #include From edddd0522694dd560652f2c8d69278fca12db475 Mon Sep 17 00:00:00 2001 From: jrblixt Date: Mon, 22 May 2017 14:31:12 -0600 Subject: [PATCH 3/6] Changes per Chris. --- tests/api.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/api.c b/tests/api.c index 72251a6a9..87479951f 100644 --- a/tests/api.c +++ b/tests/api.c @@ -3839,8 +3839,10 @@ static int test_wc_Des3_CbcEncryptDecrypt (void) byte cipher[24]; byte plain[24]; #elif defined(WOLFSSL_SMALL_STACK) - byte* cipher = (byte*) malloc(sizeof(byte) * 24); - byte* plain = (byte*) malloc(sizeof(byte) * 24); + byte* cipher = (byte*) XMALLOC(sizeof(byte) * 24, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + byte* plain = (byte*) XMALLOC(sizeof(byte) * 24, NULL, + DYNAMIC_TYPE_TMP_BUFFER); #endif int ret; @@ -3889,10 +3891,9 @@ static int test_wc_Des3_CbcEncryptDecrypt (void) ret = wc_Des3_CbcEncrypt(&des, cipher, NULL, sizeof(vector)); } if (ret != BAD_FUNC_ARG) { - printf("\nReturn code: %d\n", ret); - ret = SSL_FAILURE; + ret = SSL_FATAL_ERROR;; } else { - ret = 0; + ret = 0; } } @@ -3905,8 +3906,7 @@ static int test_wc_Des3_CbcEncryptDecrypt (void) ret = wc_Des3_CbcDecrypt(&des, plain, NULL, 24); } if (ret != BAD_FUNC_ARG) { - printf("\nReturn code: %d\n", ret); - ret = SSL_FAILURE; + ret = SSL_FATAL_ERROR; } else { ret = 0; } @@ -3915,8 +3915,8 @@ static int test_wc_Des3_CbcEncryptDecrypt (void) printf(resultFmt, ret == 0 ? passed : failed); #ifdef WOLFSSL_SMALL_STACK - XFREE(plain, NULL, DYNAMIC_TYPE_NONE); - XFREE(cipher, NULL, DYNAMIC_TYPE_CIPHER); + XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cipher, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif #endif return 0; @@ -3937,8 +3937,10 @@ static int test_wc_Des3_CbcEncryptDecryptWithKey (void) byte cipher[24]; byte plain[24]; #elif defined(WOLFSSL_SMALL_STACK) - byte* cipher = (byte*) malloc(sizeof(byte) * 24); - byte* plain = (byte*) malloc(sizeof(byte) * 24); + byte* cipher = (byte*) XMALLOC(sizeof(byte) * 24, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + byte* plain = (byte*) XMALLOC(sizeof(byte) * 24, NULL, + DYNAMIC_TYPE_TMP_BUFFER); #endif byte vector[] = /* Now is the time for all w/o trailing 0 */ @@ -3987,7 +3989,6 @@ static int test_wc_Des3_CbcEncryptDecryptWithKey (void) key, NULL); } else { /* Return code catch. */ - printf("\nReturn code: %d\n", ret); ret = SSL_FAILURE; } } @@ -4003,7 +4004,6 @@ static int test_wc_Des3_CbcEncryptDecryptWithKey (void) if (ret == BAD_FUNC_ARG) { ret = wc_Des3_CbcDecryptWithKey(plain, cipher, cipherSz, key, NULL); } else { - printf("\nReturn code: %d\n", ret); ret = SSL_FAILURE; } } @@ -4011,8 +4011,8 @@ static int test_wc_Des3_CbcEncryptDecryptWithKey (void) printf(resultFmt, ret == 0 ? passed : failed); #ifdef WOLFSSL_SMALL_STACK - XFREE(plain, NULL, DYNAMIC_TYPE_NONE); - XFREE(cipher, NULL, DYNAMIC_TYPE_CIPHER); + XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cipher, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif #endif From 1c0006882a448bbc7326b90ff8f2973e472342c6 Mon Sep 17 00:00:00 2001 From: jrblixt Date: Fri, 26 May 2017 09:44:12 -0600 Subject: [PATCH 4/6] Remove AssertIntEq from within function. --- tests/api.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/tests/api.c b/tests/api.c index 87479951f..6b7787971 100644 --- a/tests/api.c +++ b/tests/api.c @@ -3759,7 +3759,11 @@ static int test_wc_Des3_SetIV (void) /* DES_ENCRYPTION or DES_DECRYPTION */ ret = wc_Des3_SetKey(&des, key, iv, DES_ENCRYPTION); - AssertIntEQ(XMEMCMP(iv, des.reg, DES_BLOCK_SIZE), 0); + if (ret == 0) { + if (XMEMCMP(iv, des.reg, DES_BLOCK_SIZE) != 0) { + ret = SSL_FATAL_ERROR; + } + } /* Test explicitly wc_Des3_SetIV() */ if (ret == 0) { @@ -3803,7 +3807,11 @@ static int test_wc_Des3_SetKey (void) /* DES_ENCRYPTION or DES_DECRYPTION */ ret = wc_Des3_SetKey(&des, key, iv, DES_ENCRYPTION); - AssertIntEQ(XMEMCMP(iv, des.reg, DES_BLOCK_SIZE), 0); + if (ret == 0) { + if (XMEMCMP(iv, des.reg, DES_BLOCK_SIZE) != 0) { + ret = SSL_FATAL_ERROR; + } + } /* Test bad args. */ if (ret == 0) { @@ -3869,17 +3877,24 @@ static int test_wc_Des3_CbcEncryptDecrypt (void) printf(testingFmt, "wc_Des3_CbcEncrypt()"); - AssertIntEQ(wc_Des3_SetKey(&des, key, iv, DES_ENCRYPTION), 0); - - ret = wc_Des3_CbcEncrypt(&des, cipher, vector, 24); - - AssertIntEQ(wc_Des3_SetKey(&des, key, iv, DES_DECRYPTION), 0); + ret = wc_Des3_SetKey(&des, key, iv, DES_ENCRYPTION); if (ret == 0) { - ret = wc_Des3_CbcDecrypt(&des, plain, cipher, 24); + ret = wc_Des3_CbcEncrypt(&des, cipher, vector, 24); + + if (ret == 0) { + ret = wc_Des3_SetKey(&des, key, iv, DES_DECRYPTION); + } + if (ret == 0) { + ret = wc_Des3_CbcDecrypt(&des, plain, cipher, 24); + } } - AssertIntEQ(XMEMCMP(plain, vector, 24), 0); + if (ret == 0) { + if (XMEMCMP(plain, vector, 24) != 0) { + ret = SSL_FATAL_ERROR; + } + } /* Pass in bad args. */ if (ret == 0) { @@ -3972,7 +3987,11 @@ static int test_wc_Des3_CbcEncryptDecryptWithKey (void) ret = wc_Des3_CbcEncryptWithKey(cipher, vector, vectorSz, key, iv); if (ret == 0) { ret = wc_Des3_CbcDecryptWithKey(plain, cipher, cipherSz, key, iv); - AssertIntEQ(XMEMCMP(plain, vector, 24), 0); + if (ret == 0) { + if (XMEMCMP(plain, vector, 24) != 0) { + ret = SSL_FATAL_ERROR; + } + } } /* pass in bad args. */ From e345471b21cf95cc4e36e3b3c22b937e81654eb2 Mon Sep 17 00:00:00 2001 From: jrblixt Date: Fri, 26 May 2017 13:27:27 -0600 Subject: [PATCH 5/6] Logical error fix. --- tests/api.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/api.c b/tests/api.c index 6b7787971..f5a3f5186 100644 --- a/tests/api.c +++ b/tests/api.c @@ -3770,6 +3770,8 @@ static int test_wc_Des3_SetIV (void) ret = wc_Des3_SetIV(NULL, iv); if (ret == BAD_FUNC_ARG) { ret = wc_Des3_SetIV(&des, NULL); + } else if (ret == 0) { + ret = SSL_FATAL_ERROR; } } @@ -3826,6 +3828,9 @@ static int test_wc_Des3_SetKey (void) /* Default case. Should return 0. */ ret = wc_Des3_SetKey(&des, key, NULL, DES_ENCRYPTION); } + if (ret == 0) { + ret = SSL_FATAL_ERROR; + } } /* END if ret != 0 */ printf(resultFmt, ret == 0 ? passed : failed); From 0ef1129f1850edbf1ed1e7e62e6a80334c2b25f8 Mon Sep 17 00:00:00 2001 From: jrblixt Date: Tue, 13 Jun 2017 09:53:37 -0600 Subject: [PATCH 6/6] Changes WRT small stack. --- 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 + certs/include.am | 17 + configure.ac | 33 + examples/client/client.c | 59 +- examples/server/server.c | 17 +- src/crl.c | 5 +- src/include.am | 11 +- src/internal.c | 717 +++++- src/io.c | 4 +- src/keys.c | 8 +- src/ocsp.c | 3 + src/ssl.c | 291 ++- src/tls.c | 225 +- src/tls13.c | 1226 ++++++--- tests/api.c | 1111 ++++++++- tests/suites.c | 10 + tests/test-ed25519.conf | 56 + tests/test-psk-no-id.conf | 10 + tests/test-tls13.conf | 12 + tests/test.conf | 12 + wolfcrypt/benchmark/benchmark.c | 333 +++ wolfcrypt/src/asn.c | 1001 ++++++-- wolfcrypt/src/ed25519.c | 29 +- wolfcrypt/src/fe_low_mem.c | 2 +- wolfcrypt/src/hmac.c | 26 +- wolfcrypt/src/include.am | 3 +- wolfcrypt/src/sha3.c | 941 +++++++ wolfcrypt/src/sha3_long.i | 2343 ++++++++++++++++++ wolfcrypt/src/wc_port.c | 3 +- wolfcrypt/test/test.c | 495 +++- wolfssl/certs_test.h | 153 ++ wolfssl/internal.h | 96 +- wolfssl/ssl.h | 25 + wolfssl/test.h | 70 +- wolfssl/wolfcrypt/asn.h | 22 +- wolfssl/wolfcrypt/asn_public.h | 44 +- wolfssl/wolfcrypt/curve25519.h | 10 +- wolfssl/wolfcrypt/ed25519.h | 24 +- wolfssl/wolfcrypt/include.am | 3 +- wolfssl/wolfcrypt/sha3.h | 117 + wolfssl/wolfcrypt/types.h | 1 + wrapper/python/wolfcrypt/docs/symmetric.rst | 2 - wrapper/python/wolfcrypt/wolfcrypt/random.py | 6 +- 58 files changed, 8751 insertions(+), 916 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 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/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 zcmXpAVq#=4U}a<0PAy qU8uyO;K=@_lqaJ|$cCkfJx?s(!7+D9KgXv>bC)|GQqh=Ew*~;`5+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..e21c1100c --- /dev/null +++ b/certs/ed25519/ca-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN EDDSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEIE3EyZVR/gbofvUgIsCeuA3yZ9E7DbTQxW7HMDYQhbxl +oSIEIEEH7HUMaHISPASCB24Wb0BBbaSPCPLinadDwiQomH6s +-----END EDDSA 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-hTfTe+{ktI~Xpm8qgzJPk0g@?)65$0lA`9TXB z+{}s$j_hwrc`}NGY*?Du^ThHU9CMfSb9{OCDd1;h{LjM5%*1$%0p=J-1|?}W@dJV-@+lV=f2(F=km3&L zd%ZDvlIyNJj}B&tDD&j$Otsl4BdI_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*D6oK~fvJ%tRA5N>Lkk+{%!&+Vwt@4u9G;l4 z!HRQ7d(=`^{^;PRDdKhoJ9*QDmOT9!xH#A#&_I@rIaHR9MT|vc+4O?RF`1LKry0q$ zSDWpcJWDhDqk%j~TA4+{K&%0~0)CJJen!UsEUe5-YzG)%);lsxSzLDe;p}hwtWCcC zd}P(7z|eSbnw_rYEm`&7S8EjmC4X5OnjN)VCpd%q=4AV6_wxiNNOMd-QZwlwZ}qv` H>J0nmFdR`2M;#+keMb0T<;rR&FPUy-|z%OB2gLrXp&%V|&S(;bqjo9?Tu4*&p@dmqLC 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..2db2a669e --- /dev/null +++ b/certs/ed25519/root-ed25519-key.pem @@ -0,0 +1,4 @@ +-----BEGIN EDDSA PRIVATE KEY----- +MFICAQAwBQYDK2VwBCIEIFwOftlJ9QL4yEBIBh9UmTRwCu+A6puPK9OFmVk0A19P +oSIEIKZgKbt92EfL1B7QbQ9XANgqH1BqQrxd5bgZZbLfJK9Q +-----END EDDSA 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%)?(^UakjHS6rN<*rz)rQ#ajLSs$=C(IDP{hmAQ@R+xp=fSHl;zkw`>$HyYZBGPt1 z{pGx0tq1=;&i@kT!G;0` zd>{@754&%EUP)qJB20vxhutZ^Dm6DT52k^IhsoIyCe6jeUY?(m798vY6XE7zcXcr` zH8r#}lrRtj8OqGVUtV6W2U1sDoTHbVpKB;@Aj`(7)#lOmotKf5QA{8+FD>5zNr8cq z1iz7ip}B#nk%f`5k(rTY6j;F0z|_bRDqzq!ALb(~MguMRWW-rn1Ujs4)7`<~GZ1c1pM5 p2FdL5nce^YFqyG(XPUPsmEH=_(Txq7V$U#F!ZqJqsPD@Y1_0$yoErcD literal 0 HcmV?d00001 diff --git a/certs/ed25519/server-ed25519.pem b/certs/ed25519/server-ed25519.pem new file mode 100644 index 000000000..cafd77a99 --- /dev/null +++ b/certs/ed25519/server-ed25519.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIICSzCCAf2gAwIBAgIIAdCSEGpaRlcwBQYDK2VwMIGdMQswCQYDVQQGEwJVUzEQ +MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjELMAkGA1UEBAwCQ0Ex +EDAOBgNVBAoMB3dvbGZTU0wxEDAOBgNVBAsMB0VEMjU1MTkxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTAi +GA8yMDE3MDUyODIzMjYyOVoYDzIwMTkwNTI5MjMyNjI5WjCBnzELMAkGA1UEBhMC +VVMxEDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xDTALBgNVBAQM +BExlYWYxEDAOBgNVBAoMB3dvbGZTU0wxEDAOBgNVBAsMB0VEMjU1MTkxGDAWBgNV +BAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns +LmNvbTAqMAUGAytlcAMhABowiBhHL5faBPSk471sDBa5SMHRQteOkoSgdCpDng4p +o1MwUTAdBgNVHQ4EFgQU9rKEGpW0cDJT/tnrmymAS9a18cAwHwYDVR0jBBgwFoAU +ktUL2vEEi7mhiwMCn1gANTYHeskwDwYDVR0PAQH/BAUDAgbAADAFBgMrZXADQQAS +VncMlkKY2skVbE5IlQUd0Hgy+IZGmkabZIsxsBlrd5mL//wCNgULaTeHYnXaUCwt +XVKUPwCdGEVvNxKO9OQA +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICWTCCAgugAwIBAgIIAfbhPrx5oYUwBQYDK2VwMIGfMQswCQYDVQQGEwJVUzEQ +MA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjENMAsGA1UEBAwEUm9v +dDEQMA4GA1UECgwHd29sZlNTTDEQMA4GA1UECwwHRUQyNTUxOTEYMBYGA1UEAwwP +d3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MCIYDzIwMTcwNTI4MjMyNjI5WhgPMjAxOTA1MjkyMzI2MjlaMIGdMQswCQYDVQQG +EwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjELMAkGA1UE +BAwCQ0ExEDAOBgNVBAoMB3dvbGZTU0wxEDAOBgNVBAsMB0VEMjU1MTkxGDAWBgNV +BAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns +LmNvbTAqMAUGAytlcAMhAEEH7HUMaHISPASCB24Wb0BBbaSPCPLinadDwiQomH6s +o2EwXzAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBSS1Qva8QSLuaGLAwKfWAA1Ngd6 +yTAfBgNVHSMEGDAWgBSGwCfpnvqFwf3jb/xUWXI3xzOSuzAPBgNVHQ8BAf8EBQMC +AcYAMAUGAytlcANBACIbBhfAEXQfZNGj9nsGABoLUI7rsWOSRbrc4sFoFCMMbiyV +PLEcGSeYUD5VUczESVivuUZP7ZxXOAQp1KkS/gg= +-----END CERTIFICATE----- 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/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/examples/client/client.c b/examples/client/client.c index 8d5039236..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(); @@ -1280,13 +1302,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); @@ -1474,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); } @@ -1482,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); } @@ -1520,12 +1547,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 +1979,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 +1995,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/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/crl.c b/src/crl.c index 532282a2f..e632dbf10 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 = WANT_READ; + } + else if (ret >= 0) { /* try again */ ret = CheckCertCRLList(crl, cert, &foundEntry); } diff --git a/src/include.am b/src/include.am index b8dd4951d..22bb8edfe 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 \ @@ -262,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 a634f9210..3bdf53e60 100755 --- a/src/internal.c +++ b/src/internal.c @@ -127,21 +127,12 @@ 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] = { + 0x44, 0x4f, 0x47, 0x4e, 0x47, 0x52, 0x44 }; +#define TLS13_DOWNGRADE_SZ sizeof(tls13Downgrade) #ifndef NO_OLD_TLS @@ -1717,6 +1708,10 @@ static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, suites->hashSigAlgo[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) { @@ -2646,17 +2641,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]; @@ -2822,6 +2824,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: @@ -2836,7 +2844,6 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) break; #endif #endif - /* ED25519: 0x0807 */ /* ED448: 0x0808 */ } } @@ -2897,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: @@ -3083,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 @@ -3340,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; @@ -3358,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 */ @@ -3414,6 +3430,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 @@ -4173,6 +4291,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); @@ -4210,26 +4333,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; } @@ -4256,6 +4384,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); @@ -4297,6 +4431,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); @@ -4441,6 +4581,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); @@ -5408,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); @@ -7634,6 +7781,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 @@ -7692,6 +7850,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 + /* non-blocking socket re-entry requires async */ + if (ret == WANT_READ) { + goto exit_ppc; + } + #endif doCrlLookup = (ret == OCSP_CERT_UNKNOWN); if (ret != 0) { doCrlLookup = 0; @@ -7706,6 +7870,12 @@ 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 + /* non-blocking socket re-entry requires async */ + if (ret == WANT_READ) { + goto exit_ppc; + } + #endif if (ret != 0) { WOLFSSL_MSG("\tCRL check not ok"); } @@ -7845,8 +8015,14 @@ 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 + /* non-blocking socket re-entry requires async */ + if (ret == WANT_READ) { + goto exit_ppc; + } + #endif doLookup = (ret == OCSP_CERT_UNKNOWN); if (ret != 0) { WOLFSSL_MSG("\tOCSP Lookup not ok"); @@ -7862,6 +8038,12 @@ 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 + /* non-blocking socket re-entry requires async */ + if (ret == WANT_READ) { + goto exit_ppc; + } + #endif if (ret != 0) { WOLFSSL_MSG("\tCRL check not ok"); args->fatal = 0; @@ -8068,7 +8250,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); @@ -8082,7 +8263,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 */ } @@ -8096,6 +8276,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; @@ -8268,8 +8498,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; @@ -9075,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) { @@ -9343,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; @@ -9362,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; @@ -9977,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 @@ -11724,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"); @@ -11741,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 @@ -11755,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) { @@ -12957,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 @@ -15148,6 +15399,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) { @@ -15741,6 +16003,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++]; @@ -16002,6 +16291,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 */ @@ -16700,15 +16994,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); @@ -16717,12 +17002,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) @@ -16749,6 +17047,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; @@ -16852,6 +17159,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; @@ -16960,6 +17287,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; @@ -17608,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) { @@ -17620,7 +17952,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) if (ssl->ctx->EccSharedSecretCb != NULL) { break; } - #endif + #endif /* HAVE_PK_CALLBACKS */ #ifdef HAVE_CURVE25519 if (ssl->peerX25519KeyPresent) { @@ -17948,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; @@ -18366,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 */ @@ -18526,22 +18854,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: @@ -18690,7 +19057,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 @@ -18699,6 +19066,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, @@ -18765,6 +19134,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; @@ -18811,6 +19198,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; @@ -19049,7 +19446,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 +19534,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; @@ -19918,6 +20332,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) */ @@ -20018,20 +20464,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; @@ -20078,6 +20528,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; @@ -20248,20 +20701,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; @@ -20385,6 +20842,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; } @@ -20516,6 +20994,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) */ @@ -21641,6 +22132,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); @@ -21681,6 +22176,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/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/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/ocsp.c b/src/ocsp.c index ae45322ed..4554b24b0 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 = WANT_READ; + } XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); diff --git a/src/ssl.c b/src/ssl.c index 5f3da6c8b..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) @@ -3635,6 +3656,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"); @@ -4026,16 +4056,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 */ @@ -4052,6 +4094,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; } @@ -4237,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 @@ -4375,10 +4419,11 @@ 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); - 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 @@ -4574,7 +4619,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,52 +4683,96 @@ 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; + } + } + else + eccKey = 0; + + 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 */ + /* check for minimum 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; - if (ssl) { - ssl->options.haveStaticECC = 1; - } - else if (ctx) { - ctx->haveStaticECC = 1; - } + wc_ed25519_free(&key); + ed25519Key = 1; if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { 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 +4819,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 +4838,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 +4853,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 +4883,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 +4901,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"); @@ -4862,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, 0); + der->length, SSL_FILETYPE_ASN1); FreeDer(&der); used += info.consumed; continue; @@ -5422,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; @@ -8096,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; @@ -8171,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)) { @@ -8219,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) { @@ -8234,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); @@ -8517,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; @@ -8531,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) { @@ -8555,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); @@ -9128,7 +9275,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 +9425,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; @@ -22022,6 +22169,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 +22241,6 @@ void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl) return NULL; } #endif -#endif /* HAVE_ECC */ #ifndef NO_RSA @@ -22365,6 +22559,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 a25afd141..0fb7f249b 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. @@ -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 || @@ -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; @@ -4769,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 @@ -5124,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 @@ -5207,7 +5213,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 +5440,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 +5627,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 +5705,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 +5932,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 +6000,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 +6010,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 +6159,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 +6380,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; @@ -6395,7 +6407,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; @@ -6474,7 +6487,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; @@ -6501,7 +6514,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; @@ -6600,7 +6614,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, @@ -6824,6 +6838,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; @@ -6958,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 @@ -7017,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)) && \ @@ -7082,11 +7101,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; @@ -7101,6 +7119,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) @@ -7112,7 +7161,6 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) return ret; } #endif - /* TODO: [TLS13] Add PSKs */ } #endif @@ -7150,7 +7198,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 @@ -7198,11 +7246,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 @@ -7225,8 +7273,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, @@ -7258,7 +7306,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 } @@ -7266,8 +7314,14 @@ 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; + #ifndef NO_CERTS + case certificate_request: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); #endif #endif break; @@ -7313,7 +7367,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 } @@ -7321,8 +7375,15 @@ 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; + #ifndef NO_CERTS + case certificate_request: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, + TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); #endif #endif break; @@ -7357,7 +7418,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 +7585,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); @@ -7557,7 +7620,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 cb1879019..c3ac01cf9 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 @@ -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. * @@ -455,12 +462,20 @@ 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 /* 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. @@ -474,12 +489,22 @@ 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 /* 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. @@ -493,14 +518,22 @@ 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 /* 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 +549,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 +578,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 +605,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 +632,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 +659,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 +687,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. @@ -634,12 +715,20 @@ 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 /* 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 +762,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. @@ -699,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); @@ -709,17 +806,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 +850,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. @@ -936,7 +1075,7 @@ end: return ret; } -#if defined(HAVE_SESSION_TICKET) +#ifdef HAVE_SESSION_TICKET #if defined(USER_TICKS) #if 0 word32 TimeNowInMilliseconds(void) @@ -1137,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. * @@ -1153,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); @@ -1186,6 +1329,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. @@ -1198,9 +1390,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; @@ -1334,7 +1526,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; @@ -1402,64 +1594,139 @@ 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, - 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: - 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: - 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: - 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; } @@ -1475,7 +1742,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) { @@ -1532,64 +1799,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: - 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: - ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input, dataSz, - nonce, AESCCM_NONCE_SZ, input + dataSz, macSz, NULL, 0); - break; + 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(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: - 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. * @@ -1601,96 +1964,165 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) * 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, - 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 -#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 @@ -1708,7 +2140,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. * @@ -1742,6 +2176,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 @@ -1762,12 +2197,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) @@ -1777,6 +2217,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); @@ -1817,7 +2263,9 @@ int SendTls13ClientHello(WOLFSSL* ssl) int sendSz; int ret; -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) + WOLFSSL_ENTER("SendTls13ClientHello"); + +#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)) { @@ -1894,11 +2342,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 @@ -1940,13 +2388,15 @@ 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); #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. */ @@ -1956,6 +2406,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; @@ -1978,7 +2436,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. @@ -2000,6 +2458,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); @@ -2027,7 +2487,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++]; @@ -2063,9 +2522,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; @@ -2104,6 +2563,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); @@ -2129,7 +2590,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. @@ -2148,12 +2609,15 @@ 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", - &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; @@ -2172,41 +2636,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,21 +2644,25 @@ 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. */ *inOutIdx += ssl->keys.padSz; - return 0; + return ret; } #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. @@ -2240,7 +2673,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; @@ -2277,13 +2710,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; @@ -2314,15 +2749,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) @@ -2332,6 +2777,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, @@ -2422,6 +2875,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); @@ -2450,7 +2905,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) { @@ -2520,21 +2974,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); @@ -2548,6 +3006,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; @@ -2555,7 +3017,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 @@ -2565,7 +3027,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; @@ -2574,14 +3036,16 @@ 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. */ 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. */ @@ -2606,6 +3070,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; @@ -2618,6 +3086,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; @@ -2644,6 +3116,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); @@ -2671,7 +3145,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) @@ -2721,7 +3194,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; @@ -2729,11 +3202,10 @@ int SendTls13EncryptedExtensions(WOLFSSL *ssl) word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; int sendSz; + WOLFSSL_ENTER("SendTls13EncryptedExtensions"); + 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. */ @@ -2777,7 +3249,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; @@ -2801,20 +3273,23 @@ int SendTls13EncryptedExtensions(WOLFSSL *ssl) */ int SendTls13CertificateRequest(WOLFSSL* ssl) { - byte *output; + byte* output; int ret; int sendSz; int reqCtxLen = 0; - word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + word32 i; + int reqSz; - int reqSz = OPAQUE8_LEN + reqCtxLen + REQ_HEADER_SZ + REQ_HEADER_SZ; - - reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz; + 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; @@ -2835,25 +3310,12 @@ 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, - i - RECORD_HEADER_SZ, handshake, 1, 0); + i - RECORD_HEADER_SZ, handshake, 1, 0, 0); if (sendSz < 0) return sendSz; @@ -2889,6 +3351,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: @@ -2903,7 +3372,6 @@ static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) break; #endif #endif - /* ED25519: 0x0807 */ /* ED448: 0x0808 */ } } @@ -2917,17 +3385,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]; @@ -2941,26 +3416,33 @@ 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) { + 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. */ @@ -2988,11 +3470,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); @@ -3012,7 +3495,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 @@ -3184,63 +3674,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) { - int hashType = WC_HASH_TYPE_NONE; + 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; } @@ -3321,6 +3801,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. @@ -3472,7 +3953,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; @@ -3619,7 +4100,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 @@ -3627,6 +4108,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. */ @@ -3636,7 +4119,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) { @@ -3671,6 +4156,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; @@ -3694,10 +4185,23 @@ 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 */ - args->verify = &args->output[args->idx]; ret = RsaSign(ssl, sig->buffer, sig->length, args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen, @@ -3729,9 +4233,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) { @@ -3771,17 +4272,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 */ @@ -3789,6 +4279,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); @@ -3956,6 +4461,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"); @@ -3984,7 +4495,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) @@ -3993,6 +4506,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; @@ -4002,7 +4529,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"); @@ -4039,6 +4566,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) { @@ -4255,7 +4799,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; @@ -4300,7 +4844,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 } @@ -4347,7 +4891,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; @@ -4591,7 +5135,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; @@ -4880,6 +5424,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); @@ -4919,7 +5468,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 @@ -5134,7 +5683,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; @@ -5372,7 +5922,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; @@ -5502,7 +6052,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; @@ -5515,7 +6065,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/api.c b/tests/api.c index f5a3f5186..322f4cef0 100644 --- a/tests/api.c +++ b/tests/api.c @@ -69,6 +69,10 @@ #include #endif +#ifndef NO_HMAC + #include +#endif + #ifdef OPENSSL_EXTRA #include #include @@ -3732,6 +3736,1052 @@ 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; + } + } + +#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 + 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; + } + } + +#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 + 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; + } + } + +#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 + 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; + } + } + +#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 + 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; + } + } +#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 + return 0; +} /* END test_wc_Sha384HmacFinal */ + + + /* * unit test for wc_Des3_SetIV() */ @@ -3808,7 +4858,6 @@ static int test_wc_Des3_SetKey (void) /* DES_ENCRYPTION or DES_DECRYPTION */ ret = wc_Des3_SetKey(&des, key, iv, DES_ENCRYPTION); - if (ret == 0) { if (XMEMCMP(iv, des.reg, DES_BLOCK_SIZE) != 0) { ret = SSL_FATAL_ERROR; @@ -3828,9 +4877,6 @@ static int test_wc_Des3_SetKey (void) /* Default case. Should return 0. */ ret = wc_Des3_SetKey(&des, key, NULL, DES_ENCRYPTION); } - if (ret == 0) { - ret = SSL_FATAL_ERROR; - } } /* END if ret != 0 */ printf(resultFmt, ret == 0 ? passed : failed); @@ -3847,17 +4893,8 @@ static int test_wc_Des3_CbcEncryptDecrypt (void) { #ifndef NO_DES3 Des3 des; - - #ifndef WOLFSSL_SMALL_STACK - byte cipher[24]; - byte plain[24]; - #elif defined(WOLFSSL_SMALL_STACK) - byte* cipher = (byte*) XMALLOC(sizeof(byte) * 24, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - byte* plain = (byte*) XMALLOC(sizeof(byte) * 24, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - #endif - + byte cipher[24]; + byte plain[24]; int ret; const byte key[] = @@ -3934,10 +4971,6 @@ static int test_wc_Des3_CbcEncryptDecrypt (void) printf(resultFmt, ret == 0 ? passed : failed); - #ifdef WOLFSSL_SMALL_STACK - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cipher, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif #endif return 0; @@ -3951,17 +4984,8 @@ static int test_wc_Des3_CbcEncryptDecryptWithKey (void) #ifndef NO_DES3 word32 vectorSz, cipherSz; - int ret; - - #ifndef WOLFSSL_SMALL_STACK - byte cipher[24]; - byte plain[24]; - #elif defined(WOLFSSL_SMALL_STACK) - byte* cipher = (byte*) XMALLOC(sizeof(byte) * 24, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - byte* plain = (byte*) XMALLOC(sizeof(byte) * 24, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - #endif + byte cipher[24]; + byte plain[24]; byte vector[] = /* Now is the time for all w/o trailing 0 */ { @@ -3984,6 +5008,8 @@ static int test_wc_Des3_CbcEncryptDecryptWithKey (void) 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 }; + int ret; + vectorSz = sizeof(byte) * 24; cipherSz = sizeof(byte) * 24; @@ -4034,11 +5060,6 @@ static int test_wc_Des3_CbcEncryptDecryptWithKey (void) printf(resultFmt, ret == 0 ? passed : failed); - #ifdef WOLFSSL_SMALL_STACK - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cipher, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #endif return 0; } /* END test_wc_Des3_CbcEncryptDecryptWithKey */ @@ -4352,7 +5373,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; @@ -5303,6 +6325,23 @@ void ApiTest(void) 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()); + + AssertIntEQ(test_wc_Des3_SetIV(), 0); AssertIntEQ(test_wc_Des3_SetKey(), 0); AssertIntEQ(test_wc_Des3_CbcEncryptDecrypt(), 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-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/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/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 27e605c7a..2700772a8 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) { @@ -3084,9 +3411,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; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 17c986369..08afa3b62 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 @@ -86,6 +87,10 @@ ASN Options: #include #endif +#ifdef HAVE_ED25519 + #include +#endif + #ifndef NO_RSA #include #endif @@ -1112,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 @@ -1126,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 @@ -1291,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; } @@ -1322,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; } @@ -2050,97 +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 */ - /* no match found */ - return 0; + #ifdef HAVE_ED25519 + if (der->keyOID == ED25519k) { + word32 keyIdx = 0; + ed25519_key key_pair; + + 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; + } + + return ret; } #ifndef NO_PWDBASED @@ -2389,6 +2422,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; @@ -2440,6 +2476,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 */ @@ -3347,6 +3400,31 @@ 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; + + cert->pkCurveOID = ED25519k; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1, NULL); if (ret != 0) @@ -3364,7 +3442,7 @@ static int GetKey(DecodedCert* cert) return 0; } - #endif /* HAVE_ECC */ + #endif /* HAVE_ED25519 */ default: return ASN_UNKNOWN_OID_E; } @@ -4109,10 +4187,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) @@ -4317,7 +4395,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); @@ -4435,6 +4514,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) */ @@ -4445,6 +4530,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 ret; +} + /* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */ static int ConfirmSignature(SignatureCtx* sigCtx, const byte* buf, word32 bufSz, @@ -4480,74 +4652,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; } @@ -4617,6 +4723,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; @@ -4658,6 +4786,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) */ @@ -4723,6 +4863,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) */ @@ -5682,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; } @@ -6066,7 +6219,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); } @@ -6077,7 +6230,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; } } } @@ -6121,7 +6275,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, @@ -6151,6 +6305,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; @@ -6367,6 +6525,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) @@ -6442,6 +6602,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) { @@ -7100,6 +7269,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) @@ -7860,13 +8133,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; @@ -7910,6 +8185,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; @@ -8168,8 +8453,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; @@ -8181,6 +8466,7 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, (void)sigSz; (void)rsaKey; (void)eccKey; + (void)ed25519Key; (void)rng; switch (certSignCtx->state) { @@ -8194,65 +8480,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) { @@ -8298,6 +8527,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; } @@ -8351,7 +8590,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 @@ -8360,7 +8600,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); @@ -8368,7 +8609,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; @@ -8384,11 +8626,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); } @@ -8477,10 +8738,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; @@ -8516,6 +8778,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; @@ -8651,8 +8923,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 @@ -8661,7 +8933,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); @@ -8669,7 +8941,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) @@ -8685,11 +8957,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; @@ -8705,16 +9000,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 @@ -8731,7 +9034,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; @@ -8748,6 +9051,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) @@ -8767,7 +9094,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; @@ -8776,7 +9104,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) || @@ -8806,6 +9136,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; @@ -8843,10 +9178,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 @@ -8854,14 +9206,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); } @@ -9076,7 +9446,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); @@ -9841,6 +10213,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 */ @@ -10219,8 +10762,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); @@ -10264,6 +10807,8 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, WOLFSSL_MSG("\tOCSP Confirm signature failed"); return ASN_OCSP_CONFIRM_E; } + + (void)noVerify; } *ioIndex = idx; 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/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/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 0dc745361..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,6 +522,10 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) { int ret = 0; + if (hmac == 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 +597,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); 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..de203660d --- /dev/null +++ b/wolfcrypt/src/sha3.c @@ -0,0 +1,941 @@ +/* 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. + * + * 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. */ +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 +}; + +/* Indeces used in swap and rotate operation. */ +#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 + +/* 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 +#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. + * + * s The state. + * t1 Temporary value. + * t2 Second temporary value. + * 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. + * + * 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 \ +{ \ + 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. + * + * 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 \ +{ \ + 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) + * + * 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 \ +{ \ + 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. + * + * 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 + +/* 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) +{ +#ifdef BIG_ENDIAN_ORDER + word64 n = 0; + int i; + + for (i = 0; i < 8; i++) + n |= (word64)a[i] << (8 * i); + + return n; +#else + 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; + + for (i = 0; i < 25; i++) + sha3->s[i] = 0; + sha3->i = 0; + + 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; + 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; +} + +/* 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[p * 8 - 1] = 0x00; + sha3->t[ sha3->i] = 0x06; + sha3->t[p * 8 - 1] |= 0x80; + for (i=sha3->i + 1; i < p * 8 - 1; i++) + sha3->t[i] = 0; + for (i = 0; i < p; 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; +} + +/* 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; + + 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; +} + +/* 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; + + 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; +} + +/* 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; + + 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 */ +} + +/* 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; + +#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 */ + +/* 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; + + 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; +} + +/* 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; + + if (sha3 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha3Copy(sha3, &tmpSha3); + if (ret == 0) { + 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); +} + +#endif /* WOLFSSL_SHA3 */ diff --git a/wolfcrypt/src/sha3_long.i b/wolfcrypt/src/sha3_long.i new file mode 100644 index 000000000..eaa4c7502 --- /dev/null +++ b/wolfcrypt/src/sha3_long.i @@ -0,0 +1,2343 @@ +/* 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. + * + * 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. + * + * 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/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 db6ce9fbc..426ac14a8 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 @@ -125,7 +128,9 @@ #endif #ifdef OPENSSL_EXTRA + #ifndef WOLFCRYPT_ONLY #include + #endif #include #include #include @@ -209,6 +214,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); @@ -245,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); @@ -479,6 +487,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 @@ -740,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 @@ -1760,6 +1775,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; @@ -5462,6 +5716,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 @@ -7739,6 +8001,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; } @@ -8177,7 +8442,7 @@ int srp_test(void) #endif /* WOLFCRYPT_HAVE_SRP */ -#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) int openssl_test(void) { @@ -8868,12 +9133,11 @@ int openssl_test(void) } #endif /* ifndef NO_AES */ - return 0; } -#endif /* OPENSSL_EXTRA */ +#endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY */ #ifndef NO_PWDBASED @@ -8943,6 +9207,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) @@ -8958,6 +9224,7 @@ int scrypt_test(void) if (XMEMCMP(derived, verify4, sizeof(verify4)) != 0) return -6007; #endif +#endif /* !BENCH_EMBEDDED */ return 0; } @@ -11186,6 +11453,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; @@ -11615,6 +12089,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 */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 5b63d2bc9..42d6376ab 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, @@ -924,7 +927,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, @@ -1089,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 */ @@ -1767,11 +1780,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 @@ -2059,7 +2072,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 */ @@ -2088,7 +2101,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 { @@ -2199,12 +2212,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 */ @@ -2259,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; @@ -2370,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 }; @@ -2523,7 +2543,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) */ @@ -2633,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 */ @@ -2649,12 +2672,30 @@ 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; 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 @@ -2763,7 +2804,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]; @@ -3003,7 +3044,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 { @@ -3128,6 +3169,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; @@ -3235,6 +3280,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 @@ -3376,6 +3425,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 */ }; @@ -3434,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, @@ -3465,6 +3518,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 @@ -3539,7 +3601,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); @@ -3594,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 9ae8cd9f5..59608670b 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, @@ -1680,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 aab51b4e6..a22a8af37 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 */ @@ -1800,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); @@ -1821,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); @@ -1828,6 +1842,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 +2181,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 a6ef14fa2..1b732fa55 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 }; @@ -286,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, @@ -434,10 +436,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; @@ -655,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 @@ -814,7 +821,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..0b4a8653b 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,9 @@ enum CertType { PUBLICKEY_TYPE, RSA_PUBLICKEY_TYPE, ECC_PUBLICKEY_TYPE, - TRUSTED_PEER_TYPE + TRUSTED_PEER_TYPE, + EDDSA_PRIVATEKEY_TYPE, + ED25519_TYPE }; @@ -79,7 +85,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 +181,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 +209,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 +285,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/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 { diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index ea88603a3..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 @@ -54,8 +58,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 +73,10 @@ 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; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +}; WOLFSSL_API @@ -72,7 +85,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 +94,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 +110,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/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..28f5af7a7 --- /dev/null +++ b/wolfssl/wolfcrypt/sha3.h @@ -0,0 +1,117 @@ +/* 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 + */ + + +#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 */ + 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 */ 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 ------- 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):