diff --git a/INSTALL b/INSTALL index 589cb2842..df12ee1df 100644 --- a/INSTALL +++ b/INSTALL @@ -136,3 +136,50 @@ 2) Run the Visual Studio batch to setup command line variables, e.g. C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat 3) Follow steps in "Unix-based Platforms" above. + +15. Building with liboqs for TLS 1.3 KEM Groups [EXPERIMENTAL] + In order be able to use liboqs, you must have it built and installed on your + system. For example, on linux, this would be sufficient: + + $ cd liboqs + $ mkdir build + $ cd build + $ cmake -DOQS_USE_OPENSSL=0 .. + $ make all + $ sudo make install + + And then for building wolfssl, the following is sufficient: + + $ cd wolfssl + $ ./autogen.sh (Might not be necessary) + $ ./configure --with-liboqs + $ make all + + Execute the following to see the liboqs-related options near the end of the + output of these commands: + + $ ./examples/server/server -? + $ ./examples/client/client -? + + For a quick start, you can run the client and server like this: + + $ ./examples/server/server -v 4 --oqs KYBER512 + $ ./examples/client/client -v 4 --oqs KYBER512 + + Look for the following line in the output of the server and client: + + ``` + Using OQS KEM: KYBER512 + ``` + + The following NIST Competition Round 3 Finalist KEMs are supported: + - CRYSTALS-KYBER + - SABER + - NTRU + + Links to more information about these algorithms can be found here: + https://csrc.nist.gov/projects/post-quantum-cryptography/round-3-submissions + + NOTE: The quantum-safe algorithms provided by LIBOQS are unstandardized and + experimental. It is highly advised that they NOT be used in production + environments. diff --git a/configure.ac b/configure.ac index 16c2116fc..ad05f998a 100644 --- a/configure.ac +++ b/configure.ac @@ -3741,6 +3741,52 @@ then fi +# liboqs +ENABLED_LIBOQS="no" +tryliboqsdir="" +AC_ARG_WITH([liboqs], + [AS_HELP_STRING([--with-liboqs=PATH],[Path to liboqs install (default /usr/local) EXPERIMENTAL!])], + [ + AC_MSG_CHECKING([for liboqs]) + CPPFLAGS="$CPPFLAGS -DHAVE_LIBOQS -DHAVE_TLS_EXTENSIONS" + LIBS="$LIBS -loqs" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ OQS_init(); ]])], [ liboqs_linked=yes ],[ liboqs_linked=no ]) + + if test "x$liboqs_linked" = "xno" ; then + if test "x$withval" != "xno" ; then + tryliboqsdir=$withval + fi + if test "x$withval" = "xyes" ; then + tryliboqsdir="/usr/local" + fi + + LDFLAGS="$AM_LDFLAGS $LDFLAGS -L$tryliboqsdir/lib" + CPPFLAGS="$CPPFLAGS -I$tryliboqsdir/include" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ OQS_init(); ]])], [ liboqs_linked=yes ],[ liboqs_linked=no ]) + + if test "x$liboqs_linked" = "xno" ; then + AC_MSG_ERROR([liboqs isn't found. + If it's already installed, specify its path using --with-liboqs=/dir/]) + fi + AC_MSG_RESULT([yes]) + AM_LDFLAGS="$AM_LDFLAGS -L$tryliboqsdir/lib" + else + AC_MSG_RESULT([yes]) + fi + + if test "x$ENABLED_OPENSSLEXTRA" = "xno" && test "x$ENABLED_OPENSSLCOEXIST" = "xno" + then + ENABLED_OPENSSLEXTRA="yes" + AM_CFLAGS="-DOPENSSL_EXTRA $AM_CFLAGS" + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_LIBOQS -DHAVE_TLS_EXTENSIONS" + ENABLED_LIBOQS="yes" + ] +) + # Whitewood netRandom client library ENABLED_WNR="no" trywnrdir="" @@ -3942,11 +3988,12 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_REQUIRE_FFDHE" fi -# TLS 1.3 Requires either ECC or (RSA/DH), or CURVE25519/ED25519 or CURVE448/ED448 +# TLS 1.3 Requires either ECC or (RSA/DH), or CURVE25519/ED25519 or CURVE448/ED448 or libOQS if test "x$ENABLED_PSK" = "xno" && test "x$ENABLED_ECC" = "xno" && \ (test "x$ENABLED_RSA" = "xno" || test "x$ENABLED_DH" = "xno") && \ (test "x$ENABLED_CURVE25519" = "xno" || test "x$ENABLED_ED25519" = "xno") && \ - (test "x$ENABLED_CURVE448" = "xno" || test "x$ENABLED_ED448" = "xno") + (test "x$ENABLED_CURVE448" = "xno" || test "x$ENABLED_ED448" = "xno") && \ + test "x$ENABLED_LIBOQS" = "xno" then # disable TLS 1.3 ENABLED_TLS13=no @@ -6754,6 +6801,7 @@ AM_CONDITIONAL([BUILD_CRL_MONITOR],[test "x$ENABLED_CRL_MONITOR" = "xyes"]) AM_CONDITIONAL([BUILD_USER_RSA],[test "x$ENABLED_USER_RSA" = "xyes"] ) AM_CONDITIONAL([BUILD_USER_CRYPTO],[test "x$ENABLED_USER_CRYPTO" = "xyes"]) AM_CONDITIONAL([BUILD_NTRU],[test "x$ENABLED_NTRU" = "xyes"]) +AM_CONDITIONAL([BUILD_LIBOQS],[test "x$ENABLED_LIBOQS" = "xyes"]) AM_CONDITIONAL([BUILD_WNR],[test "x$ENABLED_WNR" = "xyes"]) AM_CONDITIONAL([BUILD_SRP],[test "x$ENABLED_SRP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([USE_VALGRIND],[test "x$ENABLED_VALGRIND" = "xyes"]) @@ -7114,6 +7162,7 @@ echo " * Atomic User Record Layer: $ENABLED_ATOMICUSER" echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS" echo " * NTRU: $ENABLED_NTRU" echo " * QSH: $ENABLED_QSH" +echo " * liboqs: $ENABLED_LIBOQS" echo " * Whitewood netRandom: $ENABLED_WNR" echo " * Server Name Indication: $ENABLED_SNI" echo " * ALPN: $ENABLED_ALPN" diff --git a/examples/client/client.c b/examples/client/client.c index c137a0206..948095545 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -284,7 +284,7 @@ static void ShowVersions(void) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) #define MAX_GROUP_NUMBER 4 static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, - int useX448, int setGroups) + int useX448, int useLibOqs, char* oqsAlg, int setGroups) { int ret; int groups[MAX_GROUP_NUMBER] = {0}; @@ -292,6 +292,8 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, (void)useX25519; (void)useX448; + (void)useLibOqs; + (void)oqsAlg; WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); if (onlyKeyShare == 0 || onlyKeyShare == 2) { @@ -358,6 +360,72 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, } while (ret == WC_PENDING_E); #endif } + #ifdef HAVE_LIBOQS + if (onlyKeyShare == 0 || onlyKeyShare == 3) { + if (useLibOqs) { + int group = 0; + + if (XSTRNCMP(oqsAlg, "KYBER512", XSTRLEN("KYBER512")) == 0) { + group = WOLFSSL_KYBER512; + } + else if (XSTRNCMP(oqsAlg, "KYBER768", + XSTRLEN("KYBER768")) == 0) { + group = WOLFSSL_KYBER768; + } + else if (XSTRNCMP(oqsAlg, "KYBER1024", + XSTRLEN("KYBER1024")) == 0) { + group = WOLFSSL_KYBER1024; + } + else if (XSTRNCMP(oqsAlg, "NTRU_HPS2048509", + XSTRLEN("NTRU_HPS2048509")) == 0) { + group = WOLFSSL_NTRU_HPS2048509; + } + else if (XSTRNCMP(oqsAlg, "NTRU_HPS2048677", + XSTRLEN("NTRU_HPS2048677")) == 0) { + group = WOLFSSL_NTRU_HPS2048677; + } + else if (XSTRNCMP(oqsAlg, "NTRU_HPS4096821", + XSTRLEN("NTRU_HPS4096821")) == 0) { + group = WOLFSSL_NTRU_HPS4096821; + } + else if (XSTRNCMP(oqsAlg, "NTRU_HRSS701", + XSTRLEN("NTRU_HRSS701")) == 0) { + group = WOLFSSL_NTRU_HRSS701; + } + else if (XSTRNCMP(oqsAlg, "LIGHTSABER", + XSTRLEN("LIGHTSABER")) == 0) { + group = WOLFSSL_LIGHTSABER; + } + else if (XSTRNCMP(oqsAlg, "SABER", + XSTRLEN("SABER")) == 0) { + group = WOLFSSL_SABER; + } + else if (XSTRNCMP(oqsAlg, "FIRESABER", + XSTRLEN("FIRESABER")) == 0) { + group = WOLFSSL_FIRESABER; + } + else if (XSTRNCMP(oqsAlg, "KYBER90S512", + XSTRLEN("KYBER90S512")) == 0) { + group = WOLFSSL_KYBER90S512; + } + else if (XSTRNCMP(oqsAlg, "KYBER90S768", + XSTRLEN("KYBER90S768")) == 0) { + group = WOLFSSL_KYBER90S768; + } + else if (XSTRNCMP(oqsAlg, "KYBER90S1024", + XSTRLEN("KYBER90S1024")) == 0) { + group = WOLFSSL_KYBER90S1024; + } else { + err_sys("invalid OQS KEM specified"); + } + + printf("Using OQS KEM: %s\n", oqsAlg); + if (wolfSSL_UseKeyShare(ssl, group) != WOLFSSL_SUCCESS) { + err_sys("unable to use oqs KEM"); + } + } + } + #endif if (count >= MAX_GROUP_NUMBER) err_sys("example group array size error"); if (setGroups && count > 0) { @@ -438,7 +506,8 @@ static const char* client_bench_conmsg[][5] = { static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession, int useX25519, - int useX448, int helloRetry, int onlyKeyShare, int version, int earlyData) + int useX448, int useLibOqs, char* oqsAlg, int helloRetry, int onlyKeyShare, + int version, int earlyData) { /* time passed in number of connects give average */ int times = benchmark, skip = times * 0.1; @@ -455,6 +524,8 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, (void)resumeSession; (void)useX25519; (void)useX448; + (void)useLibOqs; + (void)oqsAlg; (void)helloRetry; (void)onlyKeyShare; (void)version; @@ -484,7 +555,8 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) else if (version >= 4) { if (!helloRetry) - SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 1); + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, + useLibOqs, oqsAlg, 1); else wolfSSL_NoKeyShares(ssl); } @@ -568,7 +640,8 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, /* Measures throughput in mbps. Throughput = number of bytes */ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, int dtlsUDP, int dtlsSCTP, int block, size_t throughput, int useX25519, - int useX448, int exitWithRet, int version, int onlyKeyShare) + int useX448, int useLibOqs, char* oqsAlg, int exitWithRet, int version, + int onlyKeyShare) { double start, conn_time = 0, tx_time = 0, rx_time = 0; SOCKET_T sockfd; @@ -587,11 +660,14 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, (void)useX25519; (void)useX448; + (void)useLibOqs; + (void)oqsAlg; (void)version; (void)onlyKeyShare; #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) if (version >= 4) { - SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 1); + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, useLibOqs, + oqsAlg, 1); } #endif @@ -1171,10 +1247,16 @@ static const char* client_usage_msg[][70] = { " SSLv3(0) - TLS1.2(3)\n", #else "-7 Set minimum downgrade protocol version [0-4] " - " SSLv3(0) - TLS1.3(4)\n\n", /* 69 */ + " SSLv3(0) - TLS1.3(4)\n", /* 69 */ +#endif +#ifdef HAVE_LIBOQS + "--oqs Key Share with specified liboqs algorithm only\n", + "[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n", + " NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n", + " LIGHTSABER, SABER, FIRESABER]\n\n", /* 70 */ #endif "For simpler wolfSSL TLS client examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 70 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 71 */ NULL, }, #ifndef NO_MULTIBYTE_PRINT @@ -1371,10 +1453,16 @@ static const char* client_usage_msg[][70] = { " SSLv3(0) - TLS1.2(3)\n", #else "-7 最小ダウングレード可能なプロトコルバージョンを設定します [0-4] " - " SSLv3(0) - TLS1.3(4)\n\n", /* 69 */ + " SSLv3(0) - TLS1.3(4)\n", /* 69 */ +#endif +#ifdef HAVE_LIBOQS + "--oqs liboqs 名前付きグループとの鍵共有のみ\n", + "[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n", + " NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n", + " LIGHTSABER, SABER, FIRESABER]\n\n", /* 70 */ #endif "For simpler wolfSSL TLS client examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 70 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 71 */ NULL, }, #endif @@ -1559,6 +1647,12 @@ static void Usage(void) #endif printf("%s", msg[++msgid]); /* -7 */ printf("%s", msg[++msgid]); /* Examples repo link */ +#ifdef HAVE_LIBOQS + printf("%s", msg[++msgid]); /* --oqs */ + printf("%s", msg[++msgid]); /* --oqs options */ + printf("%s", msg[++msgid]); /* more --oqs options */ + printf("%s", msg[++msgid]); /* more --oqs options */ +#endif } THREAD_RETURN WOLFSSL_THREAD client_test(void* args) @@ -1597,6 +1691,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif { "help", 0, 257 }, { "ヘルプ", 0, 258 }, +#if defined(HAVE_LIBOQS) + { "oqs", 1, 259 }, +#endif { 0, 0, 0 } }; #endif @@ -1701,6 +1798,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif int useX25519 = 0; int useX448 = 0; + int useLibOqs = 0; + char* oqsAlg = NULL; int exitWithRet = 0; int loadCertKeyIntoSSLObj = 0; @@ -1789,7 +1888,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void)onlyKeyShare; (void)useSupCurve; (void)loadCertKeyIntoSSLObj; - + (void)useLibOqs; + (void)oqsAlg; StackTrap(); /* Reinitialize the global myVerifyAction. */ @@ -2277,6 +2377,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) nonBlocking = 1; simulateWantWrite = 1; break; + case '7' : minVersion = atoi(myoptarg); if (minVersion < 0 || minVersion > 4) { @@ -2284,6 +2385,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) XEXIT_T(MY_EX_USAGE); } break; + case '8' : #ifdef HAVE_CURVE448 useX448 = 1; @@ -2345,6 +2447,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) break; #endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) && \ + defined(HAVE_LIBOQS) + case 259: + useLibOqs = 1; + onlyKeyShare = 3; + oqsAlg = myoptarg; + break; +#endif default: Usage(); XEXIT_T(MY_EX_USAGE); @@ -2466,6 +2576,17 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err_sys("can't load whitewood net random config file"); #endif +#ifdef HAVE_LIBOQS + if (useLibOqs) { + if (version == CLIENT_DOWNGRADE_VERSION || + version == EITHER_DOWNGRADE_VERSION) + printf("WARNING: If a TLS 1.3 connection is not negotiated, you " + "will not be using a liboqs group.\n"); + else if (version != 4) + err_sys("can only use liboqs groups with TLS 1.3"); + } +#endif + switch (version) { #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_SSLV3 @@ -2993,8 +3114,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) ((func_args*)args)->return_code = ClientBenchmarkConnections(ctx, host, port, dtlsUDP, dtlsSCTP, benchmark, resumeSession, useX25519, - useX448, helloRetry, onlyKeyShare, - version, earlyData); + useX448, useLibOqs, oqsAlg, helloRetry, + onlyKeyShare, version, earlyData); wolfSSL_CTX_free(ctx); ctx = NULL; XEXIT_T(EXIT_SUCCESS); } @@ -3003,7 +3124,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) ((func_args*)args)->return_code = ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP, block, throughput, useX25519, useX448, - exitWithRet, version, onlyKeyShare); + useLibOqs, oqsAlg, exitWithRet, version, + onlyKeyShare); wolfSSL_CTX_free(ctx); ctx = NULL; if (!exitWithRet) XEXIT_T(EXIT_SUCCESS); @@ -3127,7 +3249,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) if (!helloRetry && version >= 4) { - SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 0); + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, useLibOqs, + oqsAlg, 0); } else { wolfSSL_NoKeyShares(ssl); diff --git a/examples/server/server.c b/examples/server/server.c index 23bc835a9..e67125318 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -225,7 +225,6 @@ static WC_INLINE int PeekSeq(const char* buf, word32* seq) return 0; } - /* The send embedded callback * return : nb bytes sent, or error */ @@ -587,7 +586,7 @@ static void ServerWrite(WOLFSSL* ssl, const char* output, int outputLen) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) #define MAX_GROUP_NUMBER 4 static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, - int useX448) + int useX448, int useLibOqs, char* oqsAlg) { int ret; int groups[MAX_GROUP_NUMBER] = {0}; @@ -595,6 +594,8 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, (void)useX25519; (void)useX448; + (void)useLibOqs; + (void)oqsAlg; WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); if (onlyKeyShare == 2) { @@ -626,6 +627,76 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, else err_sys("unable to use curve x448"); } while (ret == WC_PENDING_E); + #endif + } + else if (useLibOqs == 1) { + #ifdef HAVE_LIBOQS + groups[count] = 0; + if (XSTRNCMP(oqsAlg, "KYBER512", XSTRLEN("KYBER512")) == 0) { + groups[count] = WOLFSSL_KYBER512; + } + else if (XSTRNCMP(oqsAlg, "KYBER768", + XSTRLEN("KYBER768")) == 0) { + groups[count] = WOLFSSL_KYBER768; + } + else if (XSTRNCMP(oqsAlg, "KYBER1024", + XSTRLEN("KYBER1024")) == 0) { + groups[count] = WOLFSSL_KYBER1024; + } + else if (XSTRNCMP(oqsAlg, "NTRU_HPS2048509", + XSTRLEN("NTRU_HPS2048509")) == 0) { + groups[count] = WOLFSSL_NTRU_HPS2048509; + } + else if (XSTRNCMP(oqsAlg, "NTRU_HPS2048677", + XSTRLEN("NTRU_HPS2048677")) == 0) { + groups[count] = WOLFSSL_NTRU_HPS2048677; + } + else if (XSTRNCMP(oqsAlg, "NTRU_HPS4096821", + XSTRLEN("NTRU_HPS4096821")) == 0) { + groups[count] = WOLFSSL_NTRU_HPS4096821; + } + else if (XSTRNCMP(oqsAlg, "NTRU_HRSS701", + XSTRLEN("NTRU_HRSS701")) == 0) { + groups[count] = WOLFSSL_NTRU_HRSS701; + } + else if (XSTRNCMP(oqsAlg, "LIGHTSABER", + XSTRLEN("LIGHTSABER")) == 0) { + groups[count] = WOLFSSL_LIGHTSABER; + } + else if (XSTRNCMP(oqsAlg, "SABER", + XSTRLEN("SABER")) == 0) { + groups[count] = WOLFSSL_SABER; + } + else if (XSTRNCMP(oqsAlg, "FIRESABER", + XSTRLEN("FIRESABER")) == 0) { + groups[count] = WOLFSSL_FIRESABER; + } + else if (XSTRNCMP(oqsAlg, "KYBER90S512", + XSTRLEN("KYBER90S512")) == 0) { + groups[count] = WOLFSSL_KYBER90S512; + } + else if (XSTRNCMP(oqsAlg, "KYBER90S768", + XSTRLEN("KYBER90S768")) == 0) { + groups[count] = WOLFSSL_KYBER90S768; + } + else if (XSTRNCMP(oqsAlg, "KYBER90S1024", + XSTRLEN("KYBER90S1024")) == 0) { + groups[count] = WOLFSSL_KYBER90S1024; + } + + if (groups[count] == 0) { + err_sys("invalid OQS KEM specified"); + } + else { + if (wolfSSL_UseKeyShare(ssl, groups[count]) == WOLFSSL_SUCCESS) { + printf("Using OQS KEM: %s\n", oqsAlg); + count++; + } + else { + groups[count] = 0; + err_sys("unable to use oqs algorithm"); + } + } #endif } else { @@ -818,16 +889,21 @@ static const char* server_usage_msg[][60] = { "--wolfsentry-config Path for JSON wolfSentry config\n", /* 58 */ #endif - #ifndef WOLFSSL_TLS13 "-7 Set minimum downgrade protocol version [0-3] " " SSLv3(0) - TLS1.2(3)\n", #else "-7 Set minimum downgrade protocol version [0-4] " - " SSLv3(0) - TLS1.3(4)\n\n", /* 59 */ + " SSLv3(0) - TLS1.3(4)\n", /* 59 */ +#endif +#ifdef HAVE_LIBOQS + "--oqs Key Share with specified liboqs algorithm only\n", + "[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n", + " NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n", + " LIGHTSABER, SABER, FIRESABER]\n\n", /* 60 */ #endif "For simpler wolfSSL TLS server examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 60 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 61 */ NULL, }, #ifndef NO_MULTIBYTE_PRINT @@ -981,10 +1057,16 @@ static const char* server_usage_msg[][60] = { " SSLv3(0) - TLS1.2(3)\n", #else "-7 最小ダウングレード可能なプロトコルバージョンを設定します [0-4] " - " SSLv3(0) - TLS1.3(4)\n\n", /* 59 */ + " SSLv3(0) - TLS1.3(4)\n", /* 59 */ +#endif +#ifdef HAVE_LIBOQS + "--oqs liboqs 名前付きグループとの鍵共有のみ\n", + "[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n", + " NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n", + " LIGHTSABER, SABER, FIRESABER]\n\n", /* 60 */ #endif "For simpler wolfSSL TLS server examples, visit\n" - "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 60 */ + "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 61 */ NULL, }, #endif @@ -1127,6 +1209,12 @@ static void Usage(void) #endif printf("%s", msg[++msgId]); /* -7 */ printf("%s", msg[++msgId]); /* Examples repo link */ +#ifdef HAVE_LIBOQS + printf("%s", msg[++msgId]); /* --oqs */ + printf("%s", msg[++msgId]); /* --oqs options */ + printf("%s", msg[++msgId]); /* more --oqs options */ + printf("%s", msg[++msgId]); /* more --oqs options */ +#endif } THREAD_RETURN WOLFSSL_THREAD server_test(void* args) @@ -1154,6 +1242,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #endif { "help", 0, 257 }, { "ヘルプ", 0, 258 }, +#if defined(HAVE_LIBOQS) + { "oqs", 1, 259 }, +#endif { 0, 0, 0 } }; #endif @@ -1296,6 +1387,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #endif int useX25519 = 0; int useX448 = 0; + int useLibOqs = 0; + char* oqsAlg = NULL; int exitWithRet = 0; int loadCertKeyIntoSSLObj = 0; @@ -1356,6 +1449,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) (void)mcastID; (void)loadCertKeyIntoSSLObj; (void)nonBlocking; + (void)oqsAlg; + (void)useLibOqs; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); @@ -1872,6 +1967,14 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) break; #endif +#ifdef HAVE_LIBOQS + case 259: + useLibOqs = 1; + onlyKeyShare = 2; + oqsAlg = myoptarg; + break; +#endif + default: Usage(); XEXIT_T(MY_EX_USAGE); @@ -1912,6 +2015,18 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) "file"); #endif +#ifdef HAVE_LIBOQS + if (useLibOqs) { + if (version == SERVER_DOWNGRADE_VERSION || + version == EITHER_DOWNGRADE_VERSION) { + printf("WARNING: If a TLS 1.3 connection is not negotiated, you " + "will not be using a liboqs group.\n"); + } else if (version != 4) { + err_sys("can only use liboqs groups with TLS 1.3"); + } + } +#endif + switch (version) { #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_SSLV3 @@ -2604,7 +2719,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) if (version >= 4) { - SetKeyShare(ssl, onlyKeyShare, useX25519, useX448); + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, useLibOqs, + oqsAlg); } #endif diff --git a/src/ssl.c b/src/ssl.c index f9fa5639e..5268f70d5 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2527,6 +2527,22 @@ static int isValidCurveGroup(word16 name) case WOLFSSL_FFDHE_4096: case WOLFSSL_FFDHE_6144: case WOLFSSL_FFDHE_8192: + +#ifdef HAVE_LIBOQS + case WOLFSSL_KYBER512: + case WOLFSSL_KYBER768: + case WOLFSSL_KYBER1024: + case WOLFSSL_NTRU_HPS2048509: + case WOLFSSL_NTRU_HPS2048677: + case WOLFSSL_NTRU_HPS4096821: + case WOLFSSL_NTRU_HRSS701: + case WOLFSSL_LIGHTSABER: + case WOLFSSL_SABER: + case WOLFSSL_FIRESABER: + case WOLFSSL_KYBER90S512: + case WOLFSSL_KYBER90S768: + case WOLFSSL_KYBER90S1024: +#endif return 1; default: @@ -22792,7 +22808,6 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) return id; } - byte* wolfSSL_X509_get_subjectKeyID(WOLFSSL_X509* x509, byte* dst, int* dstLen) { diff --git a/src/tls.c b/src/tls.c index e5aa0afc8..114800e02 100644 --- a/src/tls.c +++ b/src/tls.c @@ -50,6 +50,9 @@ #include "libntruencrypt/ntru_crypto.h" #include #endif +#ifdef HAVE_LIBOQS + #include +#endif #ifdef HAVE_QSH static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key); @@ -3768,10 +3771,10 @@ int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, #ifdef HAVE_SUPPORTED_CURVES #if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) \ - && !defined(HAVE_FFDHE) -#error Elliptic Curves Extension requires Elliptic Curve Cryptography. \ - Use --enable-ecc in the configure script or define HAVE_ECC. \ - Alternatively use FFDHE for DH ciphersuites. + && !defined(HAVE_FFDHE) && !defined(HAVE_LIBOQS) +#error Elliptic Curves Extension requires Elliptic Curve Cryptography or liboqs groups. \ + Use --enable-ecc and/or --enable-liboqs in the configure script or \ + define HAVE_ECC. Alternatively use FFDHE for DH ciphersuites. #endif static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name, @@ -7130,6 +7133,94 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) return ret; } +#ifdef HAVE_LIBOQS +/* Transform a group ID into an OQS Algorithm name as a string. */ +static const char* OQS_ID2name(int id) +{ + switch (id) { + case WOLFSSL_KYBER512: return OQS_KEM_alg_kyber_512; + case WOLFSSL_KYBER768: return OQS_KEM_alg_kyber_768; + case WOLFSSL_KYBER1024: return OQS_KEM_alg_kyber_1024; + case WOLFSSL_NTRU_HPS2048509: return OQS_KEM_alg_ntru_hps2048509; + case WOLFSSL_NTRU_HPS2048677: return OQS_KEM_alg_ntru_hps2048677; + case WOLFSSL_NTRU_HPS4096821: return OQS_KEM_alg_ntru_hps4096821; + case WOLFSSL_NTRU_HRSS701: return OQS_KEM_alg_ntru_hrss701; + case WOLFSSL_LIGHTSABER: return OQS_KEM_alg_saber_lightsaber; + case WOLFSSL_SABER: return OQS_KEM_alg_saber_saber; + case WOLFSSL_FIRESABER: return OQS_KEM_alg_saber_firesaber; + case WOLFSSL_KYBER90S512: return OQS_KEM_alg_kyber_512_90s; + case WOLFSSL_KYBER90S768: return OQS_KEM_alg_kyber_768_90s; + case WOLFSSL_KYBER90S1024: return OQS_KEM_alg_kyber_1024_90s; + default: break; + } + return NULL; +} +/* Create a key share entry using liboqs parameters group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * kse The key share entry object. + * returns 0 on success, otherwise failure. + */ +static int TLSX_KeyShare_GenOqsKey(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret = -1; + const char* algName = NULL; + OQS_KEM* kem = NULL; + byte* pubKey = NULL; + byte* privKey = NULL; + + algName = OQS_ID2name(kse->group); + if (algName == NULL) { + WOLFSSL_MSG("Invalid OQS algorithm specified."); + return BAD_FUNC_ARG; + } + + kem = OQS_KEM_new(algName); + if (kem == NULL) { + WOLFSSL_MSG("Error creating OQS KEM, ensure algorithm support" + "was enabled in liboqs."); + return BAD_FUNC_ARG; + } + + pubKey = (byte*)XMALLOC(kem->length_public_key, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + privKey = (byte*)XMALLOC(kem->length_secret_key, ssl->heap, + DYNAMIC_TYPE_PRIVATE_KEY); + if (pubKey == NULL || privKey == NULL) { + WOLFSSL_MSG("memory allocation failure"); + ret = MEMORY_ERROR; + } + else if (OQS_KEM_keypair(kem, pubKey, privKey) == OQS_SUCCESS) { + kse->pubKey = pubKey; + kse->pubKeyLen = (word32) kem->length_public_key; + pubKey = NULL; + + kse->key = privKey; + kse->keyLen = (word32) kem->length_secret_key; + privKey = NULL; + ret = 0; + } + else { + WOLFSSL_MSG("liboqs keygen failure"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public liboqs Key"); + WOLFSSL_BUFFER(pubKey, kem->length_public_key); +#endif + + OQS_KEM_free(kem); + if (pubKey != NULL) + XFREE(pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (privKey != NULL) + XFREE(privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + + return ret; +} +#endif + /* Generate a secret/key using the key share entry. * * ssl The SSL/TLS object. @@ -7145,6 +7236,10 @@ static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse) ret = TLSX_KeyShare_GenX25519Key(ssl, kse); else if (kse->group == WOLFSSL_ECC_X448) ret = TLSX_KeyShare_GenX448Key(ssl, kse); +#ifdef HAVE_LIBOQS + else if (kse->group >= WOLFSSL_OQS_MIN && kse->group <= WOLFSSL_OQS_MAX) + ret = TLSX_KeyShare_GenOqsKey(ssl, kse); +#endif else ret = TLSX_KeyShare_GenEccKey(ssl, kse); #ifdef WOLFSSL_ASYNC_CRYPT @@ -7179,6 +7274,13 @@ static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap) wc_curve448_free((curve448_key*)current->key); #endif } +#ifdef HAVE_LIBOQS + else if (current->group >= WOLFSSL_OQS_MIN && + current->group <= WOLFSSL_OQS_MAX && + current->key != NULL) { + ForceZero((byte*)current->key, current->keyLen); + } +#endif else { #ifdef HAVE_ECC wc_ecc_free((ecc_key*)current->key); @@ -7680,6 +7782,73 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) return ret; } +#ifdef HAVE_LIBOQS +/* Process the liboqs key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_ProcessOqs(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ + int ret = -1; + const char* algName = NULL; + OQS_KEM* kem = NULL; + byte* sharedSecret = NULL; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (keyShareEntry->ke == NULL) { + WOLFSSL_MSG("Invalid OQS algorithm specified."); + return BAD_FUNC_ARG; + } + + /* If I'm the server, the shared secret has already been generated and + * is in keyShareEntry->ke; transfer ownership of the buffer. + */ + if (ssl->arrays->preMasterSecret != NULL) + XFREE(ssl->arrays->preMasterSecret, ssl->heap, + DYNAMIC_TYPE_SECRET); + ssl->arrays->preMasterSecret = keyShareEntry->ke; + ssl->arrays->preMasterSz = keyShareEntry->keLen; + keyShareEntry->ke = NULL; + keyShareEntry->keLen = 0; + return 0; + } + + algName = OQS_ID2name(keyShareEntry->group); + if (algName == NULL) { + WOLFSSL_MSG("Invalid OQS algorithm specified."); + return BAD_FUNC_ARG; + } + + kem = OQS_KEM_new(algName); + if (kem == NULL) { + WOLFSSL_MSG("Error creating OQS KEM, ensure algorithm support" + "was enabled in liboqs."); + return MEMORY_E; + } + + sharedSecret = (byte*)XMALLOC(kem->length_shared_secret, + ssl->heap, DYNAMIC_TYPE_TLSX); + if (sharedSecret == NULL) { + OQS_KEM_free(kem); + return MEMORY_E; + } + + if (OQS_KEM_decaps(kem, sharedSecret, keyShareEntry->ke, + keyShareEntry->key) == OQS_SUCCESS) { + ssl->arrays->preMasterSecret = sharedSecret; + ssl->arrays->preMasterSz = (word32) kem->length_shared_secret; + ret = 0; + } else { + XFREE(sharedSecret, ssl->heap, DYNAMIC_TYPE_TLSX); + } + + OQS_KEM_free(kem); + return ret; +} +#endif + /* Process the key share extension on the client side. * * ssl The SSL/TLS object. @@ -7700,6 +7869,11 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) ret = TLSX_KeyShare_ProcessX25519(ssl, keyShareEntry); else if (keyShareEntry->group == WOLFSSL_ECC_X448) ret = TLSX_KeyShare_ProcessX448(ssl, keyShareEntry); +#ifdef HAVE_LIBOQS + else if (keyShareEntry->group >= WOLFSSL_OQS_MIN && + keyShareEntry->group <= WOLFSSL_OQS_MAX) + ret = TLSX_KeyShare_ProcessOqs(ssl, keyShareEntry); +#endif else ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry); @@ -7986,6 +8160,80 @@ static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap, return 0; } +#ifdef HAVE_LIBOQS +static int server_generate_oqs_ciphertext(WOLFSSL* ssl, + KeyShareEntry* keyShareEntry, + byte* data, word16 len) { + /* if this is a kem group and I am the server, the data is the + * client's public key. I need to generate the public information + * (AKA ciphertext) and shared secret here. Note the "public + * information" is equivalent to a the public key in key exchange + * parlance. That's why it is being assigned to pubKey. + */ + const char* algName = NULL; + OQS_KEM* kem = NULL; + byte* sharedSecret = NULL; + byte* ciphertext = NULL; + int ret = 0; + + algName = OQS_ID2name(keyShareEntry->group); + if (algName == NULL) { + WOLFSSL_MSG("Invalid OQS algorithm specified."); + return BAD_FUNC_ARG; + } + + kem = OQS_KEM_new(algName); + if (kem == NULL) { + WOLFSSL_MSG("Error creating OQS KEM, ensure algorithm support " + "was enabled in liboqs."); + return MEMORY_E; + } + + if (len != kem->length_public_key) { + OQS_KEM_free(kem); + WOLFSSL_MSG("Invalid public key."); + ret = BAD_FUNC_ARG; + } + + sharedSecret = (byte*)XMALLOC(kem->length_shared_secret, + ssl->heap, DYNAMIC_TYPE_TLSX); + ciphertext = (byte*)XMALLOC(kem->length_ciphertext, + ssl->heap, DYNAMIC_TYPE_TLSX); + + if (sharedSecret == NULL || ciphertext == NULL) { + ret = MEMORY_E; + } + + if (ret == 0 && + OQS_KEM_encaps(kem, ciphertext, sharedSecret, data) + != OQS_SUCCESS) { + WOLFSSL_MSG("Encapsulation failure."); + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if (keyShareEntry->ke != NULL) { + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + + keyShareEntry->pubKey = ciphertext; + keyShareEntry->pubKeyLen = (word32) kem->length_ciphertext; + ciphertext = NULL; + + keyShareEntry->ke = sharedSecret; + keyShareEntry->keLen = (word32) kem->length_shared_secret; + sharedSecret = NULL; + } + + OQS_KEM_free(kem); + if (sharedSecret == NULL) + XFREE(sharedSecret, ssl->heap, DYNAMIC_TYPE_TLSX); + if (ciphertext == NULL) + XFREE(ciphertext, ssl->heap, DYNAMIC_TYPE_TLSX); + return ret; +} +#endif + /* Use the data to create a new key share object in the extensions. * * ssl The SSL/TLS object. @@ -8033,11 +8281,24 @@ int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, } if (data != NULL) { - if (keyShareEntry->ke != NULL) { - XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); +#ifdef HAVE_LIBOQS + if (group >= WOLFSSL_OQS_MIN && + group <= WOLFSSL_OQS_MAX && + ssl->options.side == WOLFSSL_SERVER_END) { + ret = server_generate_oqs_ciphertext(ssl, keyShareEntry, data, + len); + if (ret != 0) + return ret; + } + else +#endif + { + if (keyShareEntry->ke != NULL) { + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + keyShareEntry->ke = data; + keyShareEntry->keLen = len; } - keyShareEntry->ke = data; - keyShareEntry->keLen = len; } else { /* Generate a key pair. */ @@ -8129,6 +8390,22 @@ static int TLSX_KeyShare_IsSupported(int namedGroup) case WOLFSSL_ECC_SECP521R1: break; #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_LIBOQS + case WOLFSSL_KYBER512: + case WOLFSSL_KYBER768: + case WOLFSSL_KYBER1024: + case WOLFSSL_NTRU_HPS2048509: + case WOLFSSL_NTRU_HPS2048677: + case WOLFSSL_NTRU_HPS4096821: + case WOLFSSL_NTRU_HRSS701: + case WOLFSSL_LIGHTSABER: + case WOLFSSL_SABER: + case WOLFSSL_FIRESABER: + case WOLFSSL_KYBER90S512: + case WOLFSSL_KYBER90S768: + case WOLFSSL_KYBER90S1024: + break; #endif default: return 0; @@ -8195,6 +8472,22 @@ static int TLSX_KeyShare_GroupRank(WOLFSSL* ssl, int group) #ifdef HAVE_FFDHE_8192 ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_8192; #endif + +#ifdef HAVE_LIBOQS + ssl->group[ssl->numGroups++] = WOLFSSL_KYBER512; + ssl->group[ssl->numGroups++] = WOLFSSL_KYBER768; + ssl->group[ssl->numGroups++] = WOLFSSL_KYBER1024; + ssl->group[ssl->numGroups++] = WOLFSSL_NTRU_HPS2048509; + ssl->group[ssl->numGroups++] = WOLFSSL_NTRU_HPS2048677; + ssl->group[ssl->numGroups++] = WOLFSSL_NTRU_HPS4096821; + ssl->group[ssl->numGroups++] = WOLFSSL_NTRU_HRSS701; + ssl->group[ssl->numGroups++] = WOLFSSL_LIGHTSABER; + ssl->group[ssl->numGroups++] = WOLFSSL_SABER; + ssl->group[ssl->numGroups++] = WOLFSSL_FIRESABER; + ssl->group[ssl->numGroups++] = WOLFSSL_KYBER90S512; + ssl->group[ssl->numGroups++] = WOLFSSL_KYBER90S768; + ssl->group[ssl->numGroups++] = WOLFSSL_KYBER90S1024; +#endif } for (i = 0; i < ssl->numGroups; i++) @@ -8320,7 +8613,11 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry) if ((clientKSE->group & NAMED_DH_MASK) == 0) { /* Check max value supported. */ if (clientKSE->group > WOLFSSL_ECC_MAX) { - continue; +#ifdef HAVE_LIBOQS + if (clientKSE->group < WOLFSSL_OQS_MIN || + clientKSE->group > WOLFSSL_OQS_MAX ) +#endif + continue; } #ifdef OPENSSL_EXTRA /* Check if server supports group. */ @@ -8349,13 +8646,30 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry) } list = NULL; - /* Generate a new key pair. */ + /* Generate a new key pair except in the case of OQS KEM because we + * are going to encapsulate and that does not require us to generate a + * key pair. + */ ret = TLSX_KeyShare_New(&list, clientKSE->group, ssl->heap, &serverKSE); if (ret != 0) return ret; if (clientKSE->key == NULL) { - ret = TLSX_KeyShare_GenKey(ssl, serverKSE); +#ifdef HAVE_LIBOQS + if (clientKSE->group >= WOLFSSL_OQS_MIN && + clientKSE->group <= WOLFSSL_OQS_MAX ) { + /* Going to need the public key (AKA ciphertext). */ + serverKSE->pubKey = clientKSE->pubKey; + clientKSE->pubKey = NULL; + serverKSE->pubKeyLen = clientKSE->pubKeyLen; + clientKSE->pubKeyLen = 0; + } + else +#endif + { + ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + } + /* for async do setup of serverKSE below, but return WC_PENDING_E */ if (ret != 0 #ifdef WOLFSSL_ASYNC_CRYPT @@ -10203,6 +10517,41 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) #endif #endif +#ifdef HAVE_LIBOQS + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER512, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER768, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER1024, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_NTRU_HPS2048509, + ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_NTRU_HPS2048677, + ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_NTRU_HPS4096821, + ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_NTRU_HRSS701, + ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_LIGHTSABER, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SABER, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_FIRESABER, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER90S512, + ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER90S768, + ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER90S1024, + ssl->heap); +#endif /* HAVE_LIBOQS */ + (void)ssl; (void)extensions; diff --git a/src/tls13.c b/src/tls13.c index 39fdb351e..74d8c6399 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -8667,6 +8667,19 @@ int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) } #endif +#ifdef HAVE_LIBOQS + if (group >= WOLFSSL_OQS_MIN && + group <= WOLFSSL_OQS_MAX && + ssl->options.side == WOLFSSL_SERVER_END) { + /* If I am the server of a KEM connection, do not do keygen because I'm + * going to encapsulate with the client's public key. Note that I might + * be the client and ssl->option.side has not been properly set yet. In + * that case the KeyGen operation will be deferred to connection time. + */ + return WOLFSSL_SUCCESS; + } +#endif + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); if (ret != 0) return ret; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 2091d90ef..66020f1db 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -24,7 +24,6 @@ #ifndef WOLFSSL_INT_H #define WOLFSSL_INT_H - #include #include #ifdef HAVE_CRL diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 3e1fa2064..9269d85e6 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -775,7 +775,11 @@ enum SNICbReturn { /* Maximum master key length (SECRET_LEN) */ #define WOLFSSL_MAX_MASTER_KEY_LENGTH 48 /* Maximum number of groups that can be set */ +#ifdef HAVE_LIBOQS +#define WOLFSSL_MAX_GROUP_COUNT 23 +#else #define WOLFSSL_MAX_GROUP_COUNT 10 +#endif #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) enum Tls13Secret { @@ -3493,6 +3497,27 @@ enum { WOLFSSL_FFDHE_4096 = 258, WOLFSSL_FFDHE_6144 = 259, WOLFSSL_FFDHE_8192 = 260, + +#ifdef HAVE_LIBOQS + /* These group numbers were taken from liboqs' openssl fork, see: + https://github.com/open-quantum-safe/openssl/blob/OQS-OpenSSL_1_1_1-stable/ + oqs-template/oqs-kem-info.md */ + WOLFSSL_OQS_MIN = 532, + WOLFSSL_NTRU_HPS2048509 = 532, + WOLFSSL_NTRU_HPS2048677 = 533, + WOLFSSL_NTRU_HPS4096821 = 534, + WOLFSSL_NTRU_HRSS701 = 535, + WOLFSSL_LIGHTSABER = 536, + WOLFSSL_SABER = 537, + WOLFSSL_FIRESABER = 538, + WOLFSSL_KYBER512 = 570, + WOLFSSL_KYBER768 = 572, + WOLFSSL_KYBER1024 = 573, + WOLFSSL_KYBER90S512 = 574, + WOLFSSL_KYBER90S768 = 575, + WOLFSSL_KYBER90S1024 = 576, + WOLFSSL_OQS_MAX = 576, +#endif }; enum {