liboqs integration using keyshare/supported_groups extensions in TLS 1.3

This commit is contained in:
Kareem
2021-04-28 10:28:35 -07:00
committed by Anthony Hu
parent e7ef48d2b7
commit 9a438ce289
9 changed files with 773 additions and 37 deletions

47
INSTALL
View File

@ -136,3 +136,50 @@
2) Run the Visual Studio batch to setup command line variables, e.g. C:\Program Files (x86)\Microsoft Visual 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 Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat
3) Follow steps in "Unix-based Platforms" above. 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.

View File

@ -3736,6 +3736,52 @@ then
fi 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/common.h>]], [[ 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/common.h>]], [[ 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 # Whitewood netRandom client library
ENABLED_WNR="no" ENABLED_WNR="no"
trywnrdir="" trywnrdir=""
@ -3937,11 +3983,12 @@ then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_REQUIRE_FFDHE" AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_REQUIRE_FFDHE"
fi 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" && \ if test "x$ENABLED_PSK" = "xno" && test "x$ENABLED_ECC" = "xno" && \
(test "x$ENABLED_RSA" = "xno" || test "x$ENABLED_DH" = "xno") && \ (test "x$ENABLED_RSA" = "xno" || test "x$ENABLED_DH" = "xno") && \
(test "x$ENABLED_CURVE25519" = "xno" || test "x$ENABLED_ED25519" = "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 then
# disable TLS 1.3 # disable TLS 1.3
ENABLED_TLS13=no ENABLED_TLS13=no
@ -6749,6 +6796,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_RSA],[test "x$ENABLED_USER_RSA" = "xyes"] )
AM_CONDITIONAL([BUILD_USER_CRYPTO],[test "x$ENABLED_USER_CRYPTO" = "xyes"]) AM_CONDITIONAL([BUILD_USER_CRYPTO],[test "x$ENABLED_USER_CRYPTO" = "xyes"])
AM_CONDITIONAL([BUILD_NTRU],[test "x$ENABLED_NTRU" = "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_WNR],[test "x$ENABLED_WNR" = "xyes"])
AM_CONDITIONAL([BUILD_SRP],[test "x$ENABLED_SRP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_SRP],[test "x$ENABLED_SRP" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
AM_CONDITIONAL([USE_VALGRIND],[test "x$ENABLED_VALGRIND" = "xyes"]) AM_CONDITIONAL([USE_VALGRIND],[test "x$ENABLED_VALGRIND" = "xyes"])
@ -7109,6 +7157,7 @@ echo " * Atomic User Record Layer: $ENABLED_ATOMICUSER"
echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS" echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS"
echo " * NTRU: $ENABLED_NTRU" echo " * NTRU: $ENABLED_NTRU"
echo " * QSH: $ENABLED_QSH" echo " * QSH: $ENABLED_QSH"
echo " * liboqs: $ENABLED_LIBOQS"
echo " * Whitewood netRandom: $ENABLED_WNR" echo " * Whitewood netRandom: $ENABLED_WNR"
echo " * Server Name Indication: $ENABLED_SNI" echo " * Server Name Indication: $ENABLED_SNI"
echo " * ALPN: $ENABLED_ALPN" echo " * ALPN: $ENABLED_ALPN"

View File

@ -284,7 +284,7 @@ static void ShowVersions(void)
#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
#define MAX_GROUP_NUMBER 4 #define MAX_GROUP_NUMBER 4
static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
int useX448, int setGroups) int useX448, int useLibOqs, char* oqsAlg, int setGroups)
{ {
int ret; int ret;
int groups[MAX_GROUP_NUMBER] = {0}; int groups[MAX_GROUP_NUMBER] = {0};
@ -292,6 +292,8 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
(void)useX25519; (void)useX25519;
(void)useX448; (void)useX448;
(void)useLibOqs;
(void)oqsAlg;
WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
if (onlyKeyShare == 0 || onlyKeyShare == 2) { if (onlyKeyShare == 0 || onlyKeyShare == 2) {
@ -358,6 +360,72 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
} while (ret == WC_PENDING_E); } while (ret == WC_PENDING_E);
#endif #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) if (count >= MAX_GROUP_NUMBER)
err_sys("example group array size error"); err_sys("example group array size error");
if (setGroups && count > 0) { 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, static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port,
int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession, int useX25519, 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 */ /* time passed in number of connects give average */
int times = benchmark, skip = times * 0.1; int times = benchmark, skip = times * 0.1;
@ -455,6 +524,8 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port,
(void)resumeSession; (void)resumeSession;
(void)useX25519; (void)useX25519;
(void)useX448; (void)useX448;
(void)useLibOqs;
(void)oqsAlg;
(void)helloRetry; (void)helloRetry;
(void)onlyKeyShare; (void)onlyKeyShare;
(void)version; (void)version;
@ -484,7 +555,8 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port,
#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
else if (version >= 4) { else if (version >= 4) {
if (!helloRetry) if (!helloRetry)
SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 1); SetKeyShare(ssl, onlyKeyShare, useX25519, useX448,
useLibOqs, oqsAlg, 1);
else else
wolfSSL_NoKeyShares(ssl); 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 */ /* Measures throughput in mbps. Throughput = number of bytes */
static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port,
int dtlsUDP, int dtlsSCTP, int block, size_t throughput, int useX25519, 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; double start, conn_time = 0, tx_time = 0, rx_time = 0;
SOCKET_T sockfd; SOCKET_T sockfd;
@ -587,11 +660,14 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port,
(void)useX25519; (void)useX25519;
(void)useX448; (void)useX448;
(void)useLibOqs;
(void)oqsAlg;
(void)version; (void)version;
(void)onlyKeyShare; (void)onlyKeyShare;
#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
if (version >= 4) { if (version >= 4) {
SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 1); SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, useLibOqs,
oqsAlg, 1);
} }
#endif #endif
@ -1171,10 +1247,16 @@ static const char* client_usage_msg[][70] = {
" SSLv3(0) - TLS1.2(3)\n", " SSLv3(0) - TLS1.2(3)\n",
#else #else
"-7 Set minimum downgrade protocol version [0-4] " "-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 <alg> 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 #endif
"For simpler wolfSSL TLS client examples, visit\n" "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, NULL,
}, },
#ifndef NO_MULTIBYTE_PRINT #ifndef NO_MULTIBYTE_PRINT
@ -1371,10 +1453,16 @@ static const char* client_usage_msg[][70] = {
" SSLv3(0) - TLS1.2(3)\n", " SSLv3(0) - TLS1.2(3)\n",
#else #else
"-7 最小ダウングレード可能なプロトコルバージョンを設定します [0-4] " "-7 最小ダウングレード可能なプロトコルバージョンを設定します [0-4] "
" SSLv3(0) - TLS1.3(4)\n\n", /* 69 */ " SSLv3(0) - TLS1.3(4)\n", /* 69 */
#endif
#ifdef HAVE_LIBOQS
"--oqs <alg> 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 #endif
"For simpler wolfSSL TLS client examples, visit\n" "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, NULL,
}, },
#endif #endif
@ -1559,6 +1647,12 @@ static void Usage(void)
#endif #endif
printf("%s", msg[++msgid]); /* -7 */ printf("%s", msg[++msgid]); /* -7 */
printf("%s", msg[++msgid]); /* Examples repo link */ 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) THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
@ -1597,6 +1691,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#endif #endif
{ "help", 0, 257 }, { "help", 0, 257 },
{ "ヘルプ", 0, 258 }, { "ヘルプ", 0, 258 },
#if defined(HAVE_LIBOQS)
{ "oqs", 1, 259 },
#endif
{ 0, 0, 0 } { 0, 0, 0 }
}; };
#endif #endif
@ -1701,6 +1798,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#endif #endif
int useX25519 = 0; int useX25519 = 0;
int useX448 = 0; int useX448 = 0;
int useLibOqs = 0;
char* oqsAlg = NULL;
int exitWithRet = 0; int exitWithRet = 0;
int loadCertKeyIntoSSLObj = 0; int loadCertKeyIntoSSLObj = 0;
@ -1789,7 +1888,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
(void)onlyKeyShare; (void)onlyKeyShare;
(void)useSupCurve; (void)useSupCurve;
(void)loadCertKeyIntoSSLObj; (void)loadCertKeyIntoSSLObj;
(void)useLibOqs;
(void)oqsAlg;
StackTrap(); StackTrap();
/* Reinitialize the global myVerifyAction. */ /* Reinitialize the global myVerifyAction. */
@ -2277,6 +2377,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
nonBlocking = 1; nonBlocking = 1;
simulateWantWrite = 1; simulateWantWrite = 1;
break; break;
case '7' : case '7' :
minVersion = atoi(myoptarg); minVersion = atoi(myoptarg);
if (minVersion < 0 || minVersion > 4) { if (minVersion < 0 || minVersion > 4) {
@ -2284,6 +2385,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
XEXIT_T(MY_EX_USAGE); XEXIT_T(MY_EX_USAGE);
} }
break; break;
case '8' : case '8' :
#ifdef HAVE_CURVE448 #ifdef HAVE_CURVE448
useX448 = 1; useX448 = 1;
@ -2345,6 +2447,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
break; break;
#endif #endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) && \
defined(HAVE_LIBOQS)
case 259:
useLibOqs = 1;
onlyKeyShare = 3;
oqsAlg = myoptarg;
break;
#endif
default: default:
Usage(); Usage();
XEXIT_T(MY_EX_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"); err_sys("can't load whitewood net random config file");
#endif #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) { switch (version) {
#ifndef NO_OLD_TLS #ifndef NO_OLD_TLS
#ifdef WOLFSSL_ALLOW_SSLV3 #ifdef WOLFSSL_ALLOW_SSLV3
@ -2993,8 +3114,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
((func_args*)args)->return_code = ((func_args*)args)->return_code =
ClientBenchmarkConnections(ctx, host, port, dtlsUDP, dtlsSCTP, ClientBenchmarkConnections(ctx, host, port, dtlsUDP, dtlsSCTP,
benchmark, resumeSession, useX25519, benchmark, resumeSession, useX25519,
useX448, helloRetry, onlyKeyShare, useX448, useLibOqs, oqsAlg, helloRetry,
version, earlyData); onlyKeyShare, version, earlyData);
wolfSSL_CTX_free(ctx); ctx = NULL; wolfSSL_CTX_free(ctx); ctx = NULL;
XEXIT_T(EXIT_SUCCESS); XEXIT_T(EXIT_SUCCESS);
} }
@ -3003,7 +3124,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
((func_args*)args)->return_code = ((func_args*)args)->return_code =
ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP, ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP,
block, throughput, useX25519, useX448, block, throughput, useX25519, useX448,
exitWithRet, version, onlyKeyShare); useLibOqs, oqsAlg, exitWithRet, version,
onlyKeyShare);
wolfSSL_CTX_free(ctx); ctx = NULL; wolfSSL_CTX_free(ctx); ctx = NULL;
if (!exitWithRet) if (!exitWithRet)
XEXIT_T(EXIT_SUCCESS); 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 defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
if (!helloRetry && version >= 4) { if (!helloRetry && version >= 4) {
SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 0); SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, useLibOqs,
oqsAlg, 0);
} }
else { else {
wolfSSL_NoKeyShares(ssl); wolfSSL_NoKeyShares(ssl);

View File

@ -225,7 +225,6 @@ static WC_INLINE int PeekSeq(const char* buf, word32* seq)
return 0; return 0;
} }
/* The send embedded callback /* The send embedded callback
* return : nb bytes sent, or error * 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) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
#define MAX_GROUP_NUMBER 4 #define MAX_GROUP_NUMBER 4
static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
int useX448) int useX448, int useLibOqs, char* oqsAlg)
{ {
int ret; int ret;
int groups[MAX_GROUP_NUMBER] = {0}; int groups[MAX_GROUP_NUMBER] = {0};
@ -595,6 +594,8 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
(void)useX25519; (void)useX25519;
(void)useX448; (void)useX448;
(void)useLibOqs;
(void)oqsAlg;
WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
if (onlyKeyShare == 2) { if (onlyKeyShare == 2) {
@ -626,6 +627,76 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
else else
err_sys("unable to use curve x448"); err_sys("unable to use curve x448");
} while (ret == WC_PENDING_E); } 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 #endif
} }
else { else {
@ -818,16 +889,21 @@ static const char* server_usage_msg[][60] = {
"--wolfsentry-config <file> Path for JSON wolfSentry config\n", "--wolfsentry-config <file> Path for JSON wolfSentry config\n",
/* 58 */ /* 58 */
#endif #endif
#ifndef WOLFSSL_TLS13 #ifndef WOLFSSL_TLS13
"-7 Set minimum downgrade protocol version [0-3] " "-7 Set minimum downgrade protocol version [0-3] "
" SSLv3(0) - TLS1.2(3)\n", " SSLv3(0) - TLS1.2(3)\n",
#else #else
"-7 Set minimum downgrade protocol version [0-4] " "-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 <alg> 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 #endif
"For simpler wolfSSL TLS server examples, visit\n" "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, NULL,
}, },
#ifndef NO_MULTIBYTE_PRINT #ifndef NO_MULTIBYTE_PRINT
@ -981,10 +1057,16 @@ static const char* server_usage_msg[][60] = {
" SSLv3(0) - TLS1.2(3)\n", " SSLv3(0) - TLS1.2(3)\n",
#else #else
"-7 最小ダウングレード可能なプロトコルバージョンを設定します [0-4] " "-7 最小ダウングレード可能なプロトコルバージョンを設定します [0-4] "
" SSLv3(0) - TLS1.3(4)\n\n", /* 59 */ " SSLv3(0) - TLS1.3(4)\n", /* 59 */
#endif
#ifdef HAVE_LIBOQS
"--oqs <alg> 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 #endif
"For simpler wolfSSL TLS server examples, visit\n" "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, NULL,
}, },
#endif #endif
@ -1127,6 +1209,12 @@ static void Usage(void)
#endif #endif
printf("%s", msg[++msgId]); /* -7 */ printf("%s", msg[++msgId]); /* -7 */
printf("%s", msg[++msgId]); /* Examples repo link */ 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) THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
@ -1154,6 +1242,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#endif #endif
{ "help", 0, 257 }, { "help", 0, 257 },
{ "ヘルプ", 0, 258 }, { "ヘルプ", 0, 258 },
#if defined(HAVE_LIBOQS)
{ "oqs", 1, 259 },
#endif
{ 0, 0, 0 } { 0, 0, 0 }
}; };
#endif #endif
@ -1296,6 +1387,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#endif #endif
int useX25519 = 0; int useX25519 = 0;
int useX448 = 0; int useX448 = 0;
int useLibOqs = 0;
char* oqsAlg = NULL;
int exitWithRet = 0; int exitWithRet = 0;
int loadCertKeyIntoSSLObj = 0; int loadCertKeyIntoSSLObj = 0;
@ -1356,6 +1449,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
(void)mcastID; (void)mcastID;
(void)loadCertKeyIntoSSLObj; (void)loadCertKeyIntoSSLObj;
(void)nonBlocking; (void)nonBlocking;
(void)oqsAlg;
(void)useLibOqs;
#ifdef WOLFSSL_TIRTOS #ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self()); fdOpenSession(Task_self());
@ -1872,6 +1967,14 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
break; break;
#endif #endif
#ifdef HAVE_LIBOQS
case 259:
useLibOqs = 1;
onlyKeyShare = 2;
oqsAlg = myoptarg;
break;
#endif
default: default:
Usage(); Usage();
XEXIT_T(MY_EX_USAGE); XEXIT_T(MY_EX_USAGE);
@ -1912,6 +2015,18 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
"file"); "file");
#endif #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) { switch (version) {
#ifndef NO_OLD_TLS #ifndef NO_OLD_TLS
#ifdef WOLFSSL_ALLOW_SSLV3 #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 defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
if (version >= 4) { if (version >= 4) {
SetKeyShare(ssl, onlyKeyShare, useX25519, useX448); SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, useLibOqs,
oqsAlg);
} }
#endif #endif

View File

@ -2527,6 +2527,22 @@ static int isValidCurveGroup(word16 name)
case WOLFSSL_FFDHE_4096: case WOLFSSL_FFDHE_4096:
case WOLFSSL_FFDHE_6144: case WOLFSSL_FFDHE_6144:
case WOLFSSL_FFDHE_8192: 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; return 1;
default: default:
@ -22683,7 +22699,6 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b)
return id; return id;
} }
byte* wolfSSL_X509_get_subjectKeyID(WOLFSSL_X509* x509, byte* wolfSSL_X509_get_subjectKeyID(WOLFSSL_X509* x509,
byte* dst, int* dstLen) byte* dst, int* dstLen)
{ {

371
src/tls.c
View File

@ -50,6 +50,9 @@
#include "libntruencrypt/ntru_crypto.h" #include "libntruencrypt/ntru_crypto.h"
#include <wolfssl/wolfcrypt/random.h> #include <wolfssl/wolfcrypt/random.h>
#endif #endif
#ifdef HAVE_LIBOQS
#include <oqs/kem.h>
#endif
#ifdef HAVE_QSH #ifdef HAVE_QSH
static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key); static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key);
@ -3768,10 +3771,10 @@ int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type,
#ifdef HAVE_SUPPORTED_CURVES #ifdef HAVE_SUPPORTED_CURVES
#if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) \ #if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) \
&& !defined(HAVE_FFDHE) && !defined(HAVE_FFDHE) && !defined(HAVE_LIBOQS)
#error Elliptic Curves Extension requires Elliptic Curve Cryptography. \ #error Elliptic Curves Extension requires Elliptic Curve Cryptography or liboqs groups. \
Use --enable-ecc in the configure script or define HAVE_ECC. \ Use --enable-ecc and/or --enable-liboqs in the configure script or \
Alternatively use FFDHE for DH ciphersuites. define HAVE_ECC. Alternatively use FFDHE for DH ciphersuites.
#endif #endif
static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name, static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name,
@ -7130,6 +7133,94 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
return ret; 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. /* Generate a secret/key using the key share entry.
* *
* ssl The SSL/TLS object. * ssl The SSL/TLS object.
@ -7145,6 +7236,10 @@ static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse)
ret = TLSX_KeyShare_GenX25519Key(ssl, kse); ret = TLSX_KeyShare_GenX25519Key(ssl, kse);
else if (kse->group == WOLFSSL_ECC_X448) else if (kse->group == WOLFSSL_ECC_X448)
ret = TLSX_KeyShare_GenX448Key(ssl, kse); 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 else
ret = TLSX_KeyShare_GenEccKey(ssl, kse); ret = TLSX_KeyShare_GenEccKey(ssl, kse);
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
@ -7179,6 +7274,13 @@ static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap)
wc_curve448_free((curve448_key*)current->key); wc_curve448_free((curve448_key*)current->key);
#endif #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 { else {
#ifdef HAVE_ECC #ifdef HAVE_ECC
wc_ecc_free((ecc_key*)current->key); wc_ecc_free((ecc_key*)current->key);
@ -7680,6 +7782,73 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
return ret; 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. /* Process the key share extension on the client side.
* *
* ssl The SSL/TLS object. * ssl The SSL/TLS object.
@ -7700,6 +7869,11 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
ret = TLSX_KeyShare_ProcessX25519(ssl, keyShareEntry); ret = TLSX_KeyShare_ProcessX25519(ssl, keyShareEntry);
else if (keyShareEntry->group == WOLFSSL_ECC_X448) else if (keyShareEntry->group == WOLFSSL_ECC_X448)
ret = TLSX_KeyShare_ProcessX448(ssl, keyShareEntry); 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 else
ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry); ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry);
@ -7986,6 +8160,80 @@ static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap,
return 0; 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. /* Use the data to create a new key share object in the extensions.
* *
* ssl The SSL/TLS object. * 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 (data != NULL) {
if (keyShareEntry->ke != NULL) { #ifdef HAVE_LIBOQS
XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); 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 { else {
/* Generate a key pair. */ /* Generate a key pair. */
@ -8129,6 +8390,22 @@ static int TLSX_KeyShare_IsSupported(int namedGroup)
case WOLFSSL_ECC_SECP521R1: case WOLFSSL_ECC_SECP521R1:
break; break;
#endif /* !NO_ECC_SECP */ #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 #endif
default: default:
return 0; return 0;
@ -8195,6 +8472,22 @@ static int TLSX_KeyShare_GroupRank(WOLFSSL* ssl, int group)
#ifdef HAVE_FFDHE_8192 #ifdef HAVE_FFDHE_8192
ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_8192; ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_8192;
#endif #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++) 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) { if ((clientKSE->group & NAMED_DH_MASK) == 0) {
/* Check max value supported. */ /* Check max value supported. */
if (clientKSE->group > WOLFSSL_ECC_MAX) { 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 #ifdef OPENSSL_EXTRA
/* Check if server supports group. */ /* Check if server supports group. */
@ -8349,13 +8646,30 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry)
} }
list = NULL; 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); ret = TLSX_KeyShare_New(&list, clientKSE->group, ssl->heap, &serverKSE);
if (ret != 0) if (ret != 0)
return ret; return ret;
if (clientKSE->key == NULL) { 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 */ /* for async do setup of serverKSE below, but return WC_PENDING_E */
if (ret != 0 if (ret != 0
#ifdef WOLFSSL_ASYNC_CRYPT #ifdef WOLFSSL_ASYNC_CRYPT
@ -10203,6 +10517,41 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions)
#endif #endif
#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)ssl;
(void)extensions; (void)extensions;

View File

@ -8667,6 +8667,19 @@ int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group)
} }
#endif #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); ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL);
if (ret != 0) if (ret != 0)
return ret; return ret;

View File

@ -24,7 +24,6 @@
#ifndef WOLFSSL_INT_H #ifndef WOLFSSL_INT_H
#define WOLFSSL_INT_H #define WOLFSSL_INT_H
#include <wolfssl/wolfcrypt/types.h> #include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/ssl.h> #include <wolfssl/ssl.h>
#ifdef HAVE_CRL #ifdef HAVE_CRL

View File

@ -775,7 +775,11 @@ enum SNICbReturn {
/* Maximum master key length (SECRET_LEN) */ /* Maximum master key length (SECRET_LEN) */
#define WOLFSSL_MAX_MASTER_KEY_LENGTH 48 #define WOLFSSL_MAX_MASTER_KEY_LENGTH 48
/* Maximum number of groups that can be set */ /* Maximum number of groups that can be set */
#ifdef HAVE_LIBOQS
#define WOLFSSL_MAX_GROUP_COUNT 23
#else
#define WOLFSSL_MAX_GROUP_COUNT 10 #define WOLFSSL_MAX_GROUP_COUNT 10
#endif
#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
enum Tls13Secret { enum Tls13Secret {
@ -3493,6 +3497,27 @@ enum {
WOLFSSL_FFDHE_4096 = 258, WOLFSSL_FFDHE_4096 = 258,
WOLFSSL_FFDHE_6144 = 259, WOLFSSL_FFDHE_6144 = 259,
WOLFSSL_FFDHE_8192 = 260, 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 { enum {