Hybridizing the OQS groups with NIST ECC groups.

This commit is contained in:
Anthony Hu
2021-09-08 16:49:34 -04:00
parent 5a5bc9c571
commit fb733b4662
5 changed files with 580 additions and 93 deletions

View File

@ -415,6 +415,58 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
else if (XSTRNCMP(oqsAlg, "KYBER90S1024", else if (XSTRNCMP(oqsAlg, "KYBER90S1024",
XSTRLEN("KYBER90S1024")) == 0) { XSTRLEN("KYBER90S1024")) == 0) {
group = WOLFSSL_KYBER90S1024; group = WOLFSSL_KYBER90S1024;
}
else if (XSTRNCMP(oqsAlg, "P256_NTRUHPS2048509",
XSTRLEN("P256_NTRUHPS2048509")) == 0) {
group = WOLFSSL_P256_NTRU_HPS2048509;
}
else if (XSTRNCMP(oqsAlg, "P384_NTRUHPS2048677",
XSTRLEN("P384_NTRUHPS2048677")) == 0) {
group = WOLFSSL_P384_NTRU_HPS2048677;
}
else if (XSTRNCMP(oqsAlg, "P521_NTRUHPS4096821",
XSTRLEN("P521_NTRUHPS4096821")) == 0) {
group = WOLFSSL_P521_NTRU_HPS4096821;
}
else if (XSTRNCMP(oqsAlg, "P384_NTRUHRSS701",
XSTRLEN("P384_NTRUHRSS701")) == 0) {
group = WOLFSSL_P384_NTRU_HRSS701;
}
else if (XSTRNCMP(oqsAlg, "P256_LIGHTSABER",
XSTRLEN("P256_LIGHTSABER")) == 0) {
group = WOLFSSL_P256_LIGHTSABER;
}
else if (XSTRNCMP(oqsAlg, "P384_SABER",
XSTRLEN("P384_SABER")) == 0) {
group = WOLFSSL_P384_SABER;
}
else if (XSTRNCMP(oqsAlg, "P521_FIRESABER",
XSTRLEN("P521_FIRESABER")) == 0) {
group = WOLFSSL_P521_FIRESABER;
}
else if (XSTRNCMP(oqsAlg, "P256_KYBER512",
XSTRLEN("P256_KYBER512")) == 0) {
group = WOLFSSL_P256_KYBER512;
}
else if (XSTRNCMP(oqsAlg, "P384_KYBER768",
XSTRLEN("P384_KYBER768")) == 0) {
group = WOLFSSL_P384_KYBER768;
}
else if (XSTRNCMP(oqsAlg, "P521_KYBER1024",
XSTRLEN("P521_KYBER1024")) == 0) {
group = WOLFSSL_P521_KYBER1024;
}
else if (XSTRNCMP(oqsAlg, "P256_KYBER90S512",
XSTRLEN("P256_KYBER90S512")) == 0) {
group = WOLFSSL_P256_KYBER90S512;
}
else if (XSTRNCMP(oqsAlg, "P384_KYBER90S768",
XSTRLEN("P384_KYBER90S768")) == 0) {
group = WOLFSSL_P384_KYBER90S768;
}
else if (XSTRNCMP(oqsAlg, "P521_KYBER90S1024",
XSTRLEN("P521_KYBER90S1024")) == 0) {
group = WOLFSSL_P521_KYBER90S1024;
} else { } else {
err_sys("invalid OQS KEM specified"); err_sys("invalid OQS KEM specified");
} }
@ -1253,7 +1305,11 @@ static const char* client_usage_msg[][70] = {
"--oqs <alg> Key Share with specified liboqs algorithm only\n", "--oqs <alg> Key Share with specified liboqs algorithm only\n",
"[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n", "[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n",
" NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n", " NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n",
" LIGHTSABER, SABER, FIRESABER]\n\n", /* 70 */ " LIGHTSABER, SABER, FIRESABER, P256_NTRUHPS2048509,\n"
" P384_NTRUHPS2048677, P521_NTRUHPS4096821, P384_NTRUHRSS701,\n"
" P256_LIGHTSABER, P384_SABER, P521_FIRESABER, P256_KYBER512,\n"
" P384_KYBER768, P521_KYBER1024, P256_KYBER90S512, P384_KYBER90S768,\n"
" P521_KYBER90S1024]\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", /* 71 */ "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 71 */
@ -1459,7 +1515,11 @@ static const char* client_usage_msg[][70] = {
"--oqs <alg> liboqs 名前付きグループとの鍵共有のみ\n", "--oqs <alg> liboqs 名前付きグループとの鍵共有のみ\n",
"[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n", "[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n",
" NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n", " NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n",
" LIGHTSABER, SABER, FIRESABER]\n\n", /* 70 */ " LIGHTSABER, SABER, FIRESABER, P256_NTRUHPS2048509,\n"
" P384_NTRUHPS2048677, P521_NTRUHPS4096821, P384_NTRUHRSS701,\n"
" P256_LIGHTSABER, P384_SABER, P521_FIRESABER, P256_KYBER512,\n"
" P384_KYBER768, P521_KYBER1024, P256_KYBER90S512, P384_KYBER90S768,\n"
" P521_KYBER90S1024]\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", /* 71 */ "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 71 */

View File

@ -683,6 +683,58 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
XSTRLEN("KYBER90S1024")) == 0) { XSTRLEN("KYBER90S1024")) == 0) {
groups[count] = WOLFSSL_KYBER90S1024; groups[count] = WOLFSSL_KYBER90S1024;
} }
else if (XSTRNCMP(oqsAlg, "P256_NTRUHPS2048509",
XSTRLEN("P256_NTRUHPS2048509")) == 0) {
groups[count] = WOLFSSL_P256_NTRU_HPS2048509;
}
else if (XSTRNCMP(oqsAlg, "P384_NTRUHPS2048677",
XSTRLEN("P384_NTRUHPS2048677")) == 0) {
groups[count] = WOLFSSL_P384_NTRU_HPS2048677;
}
else if (XSTRNCMP(oqsAlg, "P521_NTRUHPS4096821",
XSTRLEN("P521_NTRUHPS4096821")) == 0) {
groups[count] = WOLFSSL_P521_NTRU_HPS4096821;
}
else if (XSTRNCMP(oqsAlg, "P384_NTRUHRSS701",
XSTRLEN("P384_NTRUHRSS701")) == 0) {
groups[count] = WOLFSSL_P384_NTRU_HRSS701;
}
else if (XSTRNCMP(oqsAlg, "P256_LIGHTSABER",
XSTRLEN("P256_LIGHTSABER")) == 0) {
groups[count] = WOLFSSL_P256_LIGHTSABER;
}
else if (XSTRNCMP(oqsAlg, "P384_SABER",
XSTRLEN("P384_SABER")) == 0) {
groups[count] = WOLFSSL_P384_SABER;
}
else if (XSTRNCMP(oqsAlg, "P521_FIRESABER",
XSTRLEN("P521_FIRESABER")) == 0) {
groups[count] = WOLFSSL_P521_FIRESABER;
}
else if (XSTRNCMP(oqsAlg, "P256_KYBER512",
XSTRLEN("P256_KYBER512")) == 0) {
groups[count] = WOLFSSL_P256_KYBER512;
}
else if (XSTRNCMP(oqsAlg, "P384_KYBER768",
XSTRLEN("P384_KYBER768")) == 0) {
groups[count] = WOLFSSL_P384_KYBER768;
}
else if (XSTRNCMP(oqsAlg, "P521_KYBER1024",
XSTRLEN("P521_KYBER1024")) == 0) {
groups[count] = WOLFSSL_P521_KYBER1024;
}
else if (XSTRNCMP(oqsAlg, "P256_KYBER90S512",
XSTRLEN("P256_KYBER90S512")) == 0) {
groups[count] = WOLFSSL_P256_KYBER90S512;
}
else if (XSTRNCMP(oqsAlg, "P384_KYBER90S768",
XSTRLEN("P384_KYBER90S768")) == 0) {
groups[count] = WOLFSSL_P384_KYBER90S768;
}
else if (XSTRNCMP(oqsAlg, "P521_KYBER90S1024",
XSTRLEN("P521_KYBER90S1024")) == 0) {
groups[count] = WOLFSSL_P521_KYBER90S1024;
}
if (groups[count] == 0) { if (groups[count] == 0) {
err_sys("invalid OQS KEM specified"); err_sys("invalid OQS KEM specified");
@ -900,7 +952,11 @@ static const char* server_usage_msg[][60] = {
"--oqs <alg> Key Share with specified liboqs algorithm only\n", "--oqs <alg> Key Share with specified liboqs algorithm only\n",
"[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n", "[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n",
" NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n", " NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n",
" LIGHTSABER, SABER, FIRESABER]\n\n", /* 60 */ " LIGHTSABER, SABER, FIRESABER, P256_NTRUHPS2048509,\n"
" P384_NTRUHPS2048677, P521_NTRUHPS4096821, P384_NTRUHRSS701,\n"
" P256_LIGHTSABER, P384_SABER, P521_FIRESABER, P256_KYBER512,\n"
" P384_KYBER768, P521_KYBER1024, P256_KYBER90S512, P384_KYBER90S768,\n"
" P521_KYBER90S1024]\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", /* 61 */ "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 61 */
@ -1063,7 +1119,11 @@ static const char* server_usage_msg[][60] = {
"--oqs <alg> liboqs 名前付きグループとの鍵共有のみ\n", "--oqs <alg> liboqs 名前付きグループとの鍵共有のみ\n",
"[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n", "[KYBER512, KYBER768, KYBER1024, KYBER90S512, KYBER90S768, KYBER90S1024,\n",
" NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n", " NTRU_HPS2048509, NTRU_HPS2048677, NTRU_HPS4096821, NTRU_HRSS701,\n",
" LIGHTSABER, SABER, FIRESABER]\n\n", /* 60 */ " LIGHTSABER, SABER, FIRESABER, P256_NTRUHPS2048509,\n"
" P384_NTRUHPS2048677, P521_NTRUHPS4096821, P384_NTRUHRSS701,\n"
" P256_LIGHTSABER, P384_SABER, P521_FIRESABER, P256_KYBER512,\n"
" P384_KYBER768, P521_KYBER1024, P256_KYBER90S512, P384_KYBER90S768,\n"
" P521_KYBER90S1024]\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", /* 61 */ "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 61 */

View File

@ -2540,6 +2540,19 @@ static int isValidCurveGroup(word16 name)
case WOLFSSL_KYBER90S512: case WOLFSSL_KYBER90S512:
case WOLFSSL_KYBER90S768: case WOLFSSL_KYBER90S768:
case WOLFSSL_KYBER90S1024: case WOLFSSL_KYBER90S1024:
case WOLFSSL_P256_NTRU_HPS2048509:
case WOLFSSL_P384_NTRU_HPS2048677:
case WOLFSSL_P521_NTRU_HPS4096821:
case WOLFSSL_P384_NTRU_HRSS701:
case WOLFSSL_P256_LIGHTSABER:
case WOLFSSL_P384_SABER:
case WOLFSSL_P521_FIRESABER:
case WOLFSSL_P256_KYBER512:
case WOLFSSL_P384_KYBER768:
case WOLFSSL_P521_KYBER1024:
case WOLFSSL_P256_KYBER90S512:
case WOLFSSL_P384_KYBER90S768:
case WOLFSSL_P521_KYBER90S1024:
#endif #endif
return 1; return 1;

478
src/tls.c
View File

@ -70,6 +70,7 @@ static int TLSX_KeyShare_IsSupported(int namedGroup);
static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions); static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions);
#endif #endif
static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap);
#ifndef NO_TLS #ifndef NO_TLS
@ -7151,6 +7152,72 @@ static const char* OQS_ID2name(int id)
} }
return NULL; return NULL;
} }
typedef struct OqsHybridMapping {
int hybrid;
int ecc;
int oqs;
} OqsHybridMapping;
static OqsHybridMapping oqs_hybrid_mapping[] = {
{.hybrid = WOLFSSL_P256_NTRU_HPS2048509, .ecc = WOLFSSL_ECC_SECP256R1,
.oqs = WOLFSSL_NTRU_HPS2048509},
{.hybrid = WOLFSSL_P384_NTRU_HPS2048677, .ecc = WOLFSSL_ECC_SECP384R1,
.oqs = WOLFSSL_NTRU_HPS2048677},
{.hybrid = WOLFSSL_P521_NTRU_HPS4096821, .ecc = WOLFSSL_ECC_SECP521R1,
.oqs = WOLFSSL_NTRU_HPS4096821},
{.hybrid = WOLFSSL_P384_NTRU_HRSS701, .ecc = WOLFSSL_ECC_SECP384R1,
.oqs = WOLFSSL_NTRU_HRSS701},
{.hybrid = WOLFSSL_P256_LIGHTSABER, .ecc = WOLFSSL_ECC_SECP256R1,
.oqs = WOLFSSL_LIGHTSABER},
{.hybrid = WOLFSSL_P384_SABER, .ecc = WOLFSSL_ECC_SECP384R1,
.oqs = WOLFSSL_SABER},
{.hybrid = WOLFSSL_P521_FIRESABER, .ecc = WOLFSSL_ECC_SECP521R1,
.oqs = WOLFSSL_FIRESABER},
{.hybrid = WOLFSSL_P256_KYBER512, .ecc = WOLFSSL_ECC_SECP256R1,
.oqs = WOLFSSL_KYBER512},
{.hybrid = WOLFSSL_P384_KYBER768, .ecc = WOLFSSL_ECC_SECP384R1,
.oqs = WOLFSSL_KYBER768},
{.hybrid = WOLFSSL_P521_KYBER1024, .ecc = WOLFSSL_ECC_SECP521R1,
.oqs = WOLFSSL_KYBER1024},
{.hybrid = WOLFSSL_P256_KYBER90S512, .ecc = WOLFSSL_ECC_SECP256R1,
.oqs = WOLFSSL_KYBER90S512},
{.hybrid = WOLFSSL_P384_KYBER90S768, .ecc = WOLFSSL_ECC_SECP384R1,
.oqs = WOLFSSL_KYBER90S768},
{.hybrid = WOLFSSL_P521_KYBER90S1024, .ecc = WOLFSSL_ECC_SECP521R1,
.oqs = WOLFSSL_KYBER90S1024},
{.hybrid = 0, .ecc = 0, .oqs = 0}
};
/* This will map an ecc-oqs hybrid group into its ecc group and oqs group.
* If it cannot find a mapping then *oqs is set to group. ecc is optional. */
static void findEccOqs(int *ecc, int *oqs, int group) {
int i;
if (oqs == NULL) {
return;
}
*oqs = 0;
if (ecc != NULL) {
*ecc = 0;
}
for (i = 0; oqs_hybrid_mapping[i].hybrid != 0; i++) {
if (oqs_hybrid_mapping[i].hybrid == group) {
*oqs = oqs_hybrid_mapping[i].oqs;
if (ecc != NULL) {
*ecc = oqs_hybrid_mapping[i].ecc;
}
break;
}
}
if (*oqs == 0) {
/* It is not a hybrid, so maybe its simple. */
*oqs = group;
}
}
/* Create a key share entry using liboqs parameters group. /* Create a key share entry using liboqs parameters group.
* Generates a key pair. * Generates a key pair.
* *
@ -7160,13 +7227,17 @@ static const char* OQS_ID2name(int id)
*/ */
static int TLSX_KeyShare_GenOqsKey(WOLFSSL *ssl, KeyShareEntry* kse) static int TLSX_KeyShare_GenOqsKey(WOLFSSL *ssl, KeyShareEntry* kse)
{ {
int ret = -1; int ret = 0;
const char* algName = NULL; const char* algName = NULL;
OQS_KEM* kem = NULL; OQS_KEM* kem = NULL;
byte* pubKey = NULL; byte* pubKey = NULL;
byte* privKey = NULL; byte* privKey = NULL;
KeyShareEntry *ecc_kse = NULL;
int oqs_group;
int ecc_group;
algName = OQS_ID2name(kse->group); findEccOqs(&ecc_group, &oqs_group, kse->group);
algName = OQS_ID2name(oqs_group);
if (algName == NULL) { if (algName == NULL) {
WOLFSSL_MSG("Invalid OQS algorithm specified."); WOLFSSL_MSG("Invalid OQS algorithm specified.");
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
@ -7179,35 +7250,77 @@ static int TLSX_KeyShare_GenOqsKey(WOLFSSL *ssl, KeyShareEntry* kse)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
pubKey = (byte*)XMALLOC(kem->length_public_key, ssl->heap, ecc_kse = XMALLOC(sizeof(*ecc_kse), ssl->heap, DYNAMIC_TYPE_TLSX);
DYNAMIC_TYPE_PUBLIC_KEY); if (ecc_kse == NULL) {
privKey = (byte*)XMALLOC(kem->length_secret_key, ssl->heap, WOLFSSL_MSG("ecc_kse memory allocation failure");
DYNAMIC_TYPE_PRIVATE_KEY);
if (pubKey == NULL || privKey == NULL) {
WOLFSSL_MSG("memory allocation failure");
ret = MEMORY_ERROR; 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; if (ret == 0) {
kse->keyLen = (word32) kem->length_secret_key; XMEMSET(ecc_kse, 0, sizeof(*ecc_kse));
privKey = NULL;
ret = 0;
} }
else {
WOLFSSL_MSG("liboqs keygen failure"); if (ret == 0 && ecc_group != 0) {
ret = BAD_FUNC_ARG; ecc_kse->group = ecc_group;
ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse);
if (ret != 0) {
/* No message, TLSX_KeyShare_GenEccKey() will do it. */
return ret;
}
}
if (ret == 0) {
pubKey = (byte*)XMALLOC(ecc_kse->pubKeyLen + kem->length_public_key,
ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (pubKey == NULL) {
WOLFSSL_MSG("pubkey memory allocation failure");
ret = MEMORY_ERROR;
}
}
if (ret == 0) {
privKey = (byte*)XMALLOC(kem->length_secret_key,
ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
if (privKey == NULL) {
WOLFSSL_MSG("privkey memory allocation failure");
ret = MEMORY_ERROR;
}
}
if (ret == 0) {
if (OQS_KEM_keypair(kem, pubKey + ecc_kse->pubKeyLen, privKey) ==
OQS_SUCCESS) {
XMEMCPY(pubKey, ecc_kse->pubKey, ecc_kse->pubKeyLen);
kse->pubKey = pubKey;
kse->pubKeyLen = ecc_kse->pubKeyLen +
(word32) kem->length_public_key;
pubKey = NULL;
/* Note we are saving the OQS private key and ECC private key
* separately. That's because the ECC private key is not simply a
* buffer. Its is an ecc_key struct.
*/
kse->privKey = privKey;
privKey = NULL;
kse->key = ecc_kse->key;
ecc_kse->key = NULL;
ret = 0;
}
else {
WOLFSSL_MSG("liboqs keygen failure");
ret = BAD_FUNC_ARG;
}
} }
#ifdef WOLFSSL_DEBUG_TLS #ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Public liboqs Key"); WOLFSSL_MSG("Public liboqs Key");
WOLFSSL_BUFFER(pubKey, kem->length_public_key); WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen );
#endif #endif
OQS_KEM_free(kem); OQS_KEM_free(kem);
TLSX_KeyShare_FreeAll(ecc_kse, ssl->heap);
if (pubKey != NULL) if (pubKey != NULL)
XFREE(pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); XFREE(pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (privKey != NULL) if (privKey != NULL)
@ -7788,20 +7901,24 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
*/ */
static int TLSX_KeyShare_ProcessOqs(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) static int TLSX_KeyShare_ProcessOqs(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
{ {
int ret = -1; int ret = 0;
const char* algName = NULL; const char* algName = NULL;
OQS_KEM* kem = NULL; OQS_KEM* kem = NULL;
byte* sharedSecret = NULL; byte* sharedSecret = NULL;
word32 sharedSecretLen = 0;
int oqs_group;
int ecc_group;
ecc_key eccpubkey;
word32 outlen = 0;
if (keyShareEntry->ke == NULL) {
WOLFSSL_MSG("Invalid OQS algorithm specified.");
return BAD_FUNC_ARG;
}
if (ssl->options.side == WOLFSSL_SERVER_END) { if (ssl->options.side == WOLFSSL_SERVER_END) {
if (keyShareEntry->ke == NULL) { /* I am the server, the shared secret has already been generated and
WOLFSSL_MSG("Invalid OQS algorithm specified."); * is in keyShareEntry->ke; transfer ownership of the buffer. */
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) if (ssl->arrays->preMasterSecret != NULL)
XFREE(ssl->arrays->preMasterSecret, ssl->heap, XFREE(ssl->arrays->preMasterSecret, ssl->heap,
DYNAMIC_TYPE_SECRET); DYNAMIC_TYPE_SECRET);
@ -7812,7 +7929,10 @@ static int TLSX_KeyShare_ProcessOqs(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
return 0; return 0;
} }
algName = OQS_ID2name(keyShareEntry->group); /* I am the client, the ciphertext is in keyShareEntry->ke */
findEccOqs(&ecc_group, &oqs_group, keyShareEntry->group);
algName = OQS_ID2name(oqs_group);
if (algName == NULL) { if (algName == NULL) {
WOLFSSL_MSG("Invalid OQS algorithm specified."); WOLFSSL_MSG("Invalid OQS algorithm specified.");
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
@ -7825,22 +7945,88 @@ static int TLSX_KeyShare_ProcessOqs(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
return MEMORY_E; return MEMORY_E;
} }
sharedSecret = (byte*)XMALLOC(kem->length_shared_secret, sharedSecretLen = (word32)kem->length_shared_secret;
ssl->heap, DYNAMIC_TYPE_TLSX); switch (ecc_group) {
if (sharedSecret == NULL) { case WOLFSSL_ECC_SECP256R1:
OQS_KEM_free(kem); sharedSecretLen += 32;
outlen = 32;
break;
case WOLFSSL_ECC_SECP384R1:
sharedSecretLen += 48;
outlen = 48;
break;
case WOLFSSL_ECC_SECP521R1:
sharedSecretLen += 66;
outlen = 66;
break;
default:
break;
}
ret = wc_ecc_init_ex(&eccpubkey, ssl->heap, ssl->devId);
if (ret != 0) {
WOLFSSL_MSG("Memory allocation error.");
return MEMORY_E; return MEMORY_E;
} }
if (OQS_KEM_decaps(kem, sharedSecret, keyShareEntry->ke, sharedSecret = (byte*)XMALLOC(sharedSecretLen, ssl->heap,
keyShareEntry->key) == OQS_SUCCESS) { DYNAMIC_TYPE_TLSX);
if (sharedSecret == NULL) {
WOLFSSL_MSG("Memory allocation error.");
ret = MEMORY_E;
}
if (ret == 0 && OQS_KEM_decaps(kem, sharedSecret + outlen,
keyShareEntry->ke + keyShareEntry->keLen -
kem->length_ciphertext,
keyShareEntry->privKey) != OQS_SUCCESS) {
WOLFSSL_MSG("Liboqs decapsulation failure.");
ret = BAD_FUNC_ARG;
}
if (ecc_group != 0) {
if (ret == 0) {
/* Point is validated by import function. */
ret = wc_ecc_import_x963(keyShareEntry->ke,
keyShareEntry->keLen -
(word32)kem->length_ciphertext,
&eccpubkey);
if (ret != 0) {
WOLFSSL_MSG("ECC Public key import error.");
}
}
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
!defined(HAVE_SELFTEST)
if (ret == 0) {
ret = wc_ecc_set_rng(keyShareEntry->key, ssl->rng);
if (ret != 0) {
WOLFSSL_MSG("Failure to set the ECC private key RNG.");
}
}
#endif
if (ret == 0) {
ret = wc_ecc_shared_secret(keyShareEntry->key, &eccpubkey, sharedSecret, &outlen);
if (outlen != sharedSecretLen - kem->length_shared_secret) {
WOLFSSL_MSG("ECC shared secret derivation error.");
ret = BAD_FUNC_ARG;
}
}
}
if (ret == 0) {
ssl->arrays->preMasterSecret = sharedSecret; ssl->arrays->preMasterSecret = sharedSecret;
ssl->arrays->preMasterSz = (word32) kem->length_shared_secret; ssl->arrays->preMasterSz = (word32) sharedSecretLen;
ret = 0; sharedSecret = NULL;
} else { }
if (sharedSecret != NULL) {
XFREE(sharedSecret, ssl->heap, DYNAMIC_TYPE_TLSX); XFREE(sharedSecret, ssl->heap, DYNAMIC_TYPE_TLSX);
} }
wc_ecc_free(&eccpubkey);
OQS_KEM_free(kem); OQS_KEM_free(kem);
return ret; return ret;
} }
@ -8162,50 +8348,117 @@ static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap,
static int server_generate_oqs_ciphertext(WOLFSSL* ssl, static int server_generate_oqs_ciphertext(WOLFSSL* ssl,
KeyShareEntry* keyShareEntry, KeyShareEntry* keyShareEntry,
byte* data, word16 len) { byte* data, word16 len) {
/* if this is a kem group and I am the server, the data is the /* I am the server. The data parameter is the client's public key. I need
* client's public key. I need to generate the public information * to generate the public information (AKA ciphertext) and shared secret
* (AKA ciphertext) and shared secret here. Note the "public * here. Note the "public information" is equivalent to a the public key in
* information" is equivalent to a the public key in key exchange * key exchange parlance. That's why it is being assigned to pubKey.
* parlance. That's why it is being assigned to pubKey.
*/ */
const char* algName = NULL; const char* algName = NULL;
OQS_KEM* kem = NULL; OQS_KEM* kem = NULL;
byte* sharedSecret = NULL; byte* sharedSecret = NULL;
byte* ciphertext = NULL; byte* ciphertext = NULL;
int ret = 0; int ret = 0;
int oqs_group;
int ecc_group;
KeyShareEntry *ecc_kse = NULL;
ecc_key eccpubkey;
word32 outlen = 0;
algName = OQS_ID2name(keyShareEntry->group); findEccOqs(&ecc_group, &oqs_group, keyShareEntry->group);
algName = OQS_ID2name(oqs_group);
if (algName == NULL) { if (algName == NULL) {
WOLFSSL_MSG("Invalid OQS algorithm specified."); WOLFSSL_MSG("Invalid OQS algorithm specified.");
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
kem = OQS_KEM_new(algName); ret = wc_ecc_init_ex(&eccpubkey, ssl->heap, ssl->devId);
if (kem == NULL) { if (ret != 0) {
WOLFSSL_MSG("Error creating OQS KEM, ensure algorithm support " WOLFSSL_MSG("Could not do ECC public key initialization.");
"was enabled in liboqs.");
return MEMORY_E; return MEMORY_E;
} }
if (len != kem->length_public_key) { ecc_kse = XMALLOC(sizeof(*ecc_kse), ssl->heap, DYNAMIC_TYPE_TLSX);
OQS_KEM_free(kem); if (ecc_kse == NULL) {
WOLFSSL_MSG("ecc_kse memory allocation failure");
ret = MEMORY_ERROR;
}
if (ret == 0) {
XMEMSET(ecc_kse, 0, sizeof(*ecc_kse));
}
if (ret == 0 && ecc_group != 0) {
ecc_kse->group = ecc_group;
ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse);
if (ret != 0) {
/* No message, TLSX_KeyShare_GenEccKey() will do it. */
return ret;
}
ret = 0;
}
if (ret == 0) {
kem = OQS_KEM_new(algName);
if (kem == NULL) {
WOLFSSL_MSG("Error creating OQS KEM, ensure algorithm support "
"was enabled in liboqs.");
ret = MEMORY_E;
}
}
if (ret == 0 && len != kem->length_public_key + ecc_kse->pubKeyLen) {
WOLFSSL_MSG("Invalid public key."); WOLFSSL_MSG("Invalid public key.");
ret = BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
} }
sharedSecret = (byte*)XMALLOC(kem->length_shared_secret, if (ret == 0) {
ssl->heap, DYNAMIC_TYPE_TLSX); sharedSecret = (byte*)XMALLOC(ecc_kse->keyLen +
ciphertext = (byte*)XMALLOC(kem->length_ciphertext, kem->length_shared_secret,
ssl->heap, DYNAMIC_TYPE_TLSX); ssl->heap, DYNAMIC_TYPE_TLSX);
ciphertext = (byte*)XMALLOC(ecc_kse->pubKeyLen + kem->length_ciphertext,
ssl->heap, DYNAMIC_TYPE_TLSX);
if (sharedSecret == NULL || ciphertext == NULL) { if (sharedSecret == NULL || ciphertext == NULL) {
ret = MEMORY_E; WOLFSSL_MSG("Ciphertext/shared secret memory allocation failure.");
ret = MEMORY_E;
}
}
if (ecc_group != 0) {
if (ret == 0) {
/* Point is validated by import function. */
ret = wc_ecc_import_x963(data, len - (word32)kem->length_public_key,
&eccpubkey);
if (ret != 0) {
WOLFSSL_MSG("Bad ECC public key.");
}
}
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
!defined(HAVE_SELFTEST)
if (ret == 0) {
ret = wc_ecc_set_rng(ecc_kse->key, ssl->rng);
}
#endif
if (ret == 0) {
outlen = ecc_kse->keyLen;
ret = wc_ecc_shared_secret(ecc_kse->key, &eccpubkey,
sharedSecret,
&outlen);
if (outlen != ecc_kse->keyLen) {
WOLFSSL_MSG("Data length mismatch.");
ret = BAD_FUNC_ARG;
}
}
} }
if (ret == 0 && if (ret == 0 &&
OQS_KEM_encaps(kem, ciphertext, sharedSecret, data) OQS_KEM_encaps(kem, ciphertext + ecc_kse->pubKeyLen,
!= OQS_SUCCESS) { sharedSecret + outlen,
WOLFSSL_MSG("Encapsulation failure."); data + ecc_kse->pubKeyLen) != OQS_SUCCESS) {
WOLFSSL_MSG("OQS Encapsulation failure.");
ret = BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
} }
@ -8214,20 +8467,24 @@ static int server_generate_oqs_ciphertext(WOLFSSL* ssl,
XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
} }
keyShareEntry->pubKey = ciphertext;
keyShareEntry->pubKeyLen = (word32) kem->length_ciphertext;
ciphertext = NULL;
keyShareEntry->ke = sharedSecret; keyShareEntry->ke = sharedSecret;
keyShareEntry->keLen = (word32) kem->length_shared_secret; keyShareEntry->keLen = outlen + (word32)kem->length_shared_secret;
sharedSecret = NULL; sharedSecret = NULL;
XMEMCPY(ciphertext, ecc_kse->pubKey, ecc_kse->pubKeyLen);
keyShareEntry->pubKey = ciphertext;
keyShareEntry->pubKeyLen = (word32) ecc_kse->pubKeyLen +
kem->length_ciphertext;
ciphertext = NULL;
} }
OQS_KEM_free(kem); TLSX_KeyShare_FreeAll(ecc_kse, ssl->heap);
if (sharedSecret == NULL) if (sharedSecret != NULL)
XFREE(sharedSecret, ssl->heap, DYNAMIC_TYPE_TLSX); XFREE(sharedSecret, ssl->heap, DYNAMIC_TYPE_TLSX);
if (ciphertext == NULL) if (ciphertext != NULL)
XFREE(ciphertext, ssl->heap, DYNAMIC_TYPE_TLSX); XFREE(ciphertext, ssl->heap, DYNAMIC_TYPE_TLSX);
wc_ecc_free(&eccpubkey);
OQS_KEM_free(kem);
return ret; return ret;
} }
#endif #endif
@ -8455,6 +8712,20 @@ static int TLSX_KeyShare_IsSupported(int namedGroup)
case WOLFSSL_KYBER90S512: case WOLFSSL_KYBER90S512:
case WOLFSSL_KYBER90S768: case WOLFSSL_KYBER90S768:
case WOLFSSL_KYBER90S1024: case WOLFSSL_KYBER90S1024:
case WOLFSSL_P256_NTRU_HPS2048509:
case WOLFSSL_P384_NTRU_HPS2048677:
case WOLFSSL_P521_NTRU_HPS4096821:
case WOLFSSL_P384_NTRU_HRSS701:
case WOLFSSL_P256_LIGHTSABER:
case WOLFSSL_P384_SABER:
case WOLFSSL_P521_FIRESABER:
case WOLFSSL_P256_KYBER512:
case WOLFSSL_P384_KYBER768:
case WOLFSSL_P521_KYBER1024:
case WOLFSSL_P256_KYBER90S512:
case WOLFSSL_P384_KYBER90S768:
case WOLFSSL_P521_KYBER90S1024:
findEccOqs(NULL, &namedGroup, namedGroup);
if (! OQS_KEM_alg_is_enabled(OQS_ID2name(namedGroup))) { if (! OQS_KEM_alg_is_enabled(OQS_ID2name(namedGroup))) {
return 0; return 0;
} }
@ -8555,6 +8826,32 @@ static int TLSX_KeyShare_GroupRank(WOLFSSL* ssl, int group)
ssl->group[ssl->numGroups++] = WOLFSSL_KYBER90S768; ssl->group[ssl->numGroups++] = WOLFSSL_KYBER90S768;
if (TLSX_KeyShare_IsSupported(WOLFSSL_KYBER90S1024)) if (TLSX_KeyShare_IsSupported(WOLFSSL_KYBER90S1024))
ssl->group[ssl->numGroups++] = WOLFSSL_KYBER90S1024; ssl->group[ssl->numGroups++] = WOLFSSL_KYBER90S1024;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P256_NTRU_HPS2048509))
ssl->group[ssl->numGroups++] = WOLFSSL_P256_NTRU_HPS2048509;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P384_NTRU_HPS2048677))
ssl->group[ssl->numGroups++] = WOLFSSL_P384_NTRU_HPS2048677;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P521_NTRU_HPS4096821))
ssl->group[ssl->numGroups++] = WOLFSSL_P521_NTRU_HPS4096821;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P384_NTRU_HRSS701))
ssl->group[ssl->numGroups++] = WOLFSSL_P384_NTRU_HRSS701;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P256_LIGHTSABER))
ssl->group[ssl->numGroups++] = WOLFSSL_P256_LIGHTSABER;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P384_SABER))
ssl->group[ssl->numGroups++] = WOLFSSL_P384_SABER;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P521_FIRESABER))
ssl->group[ssl->numGroups++] = WOLFSSL_P521_FIRESABER;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P256_KYBER512))
ssl->group[ssl->numGroups++] = WOLFSSL_P256_KYBER512;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P384_KYBER768))
ssl->group[ssl->numGroups++] = WOLFSSL_P384_KYBER768;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P521_KYBER1024))
ssl->group[ssl->numGroups++] = WOLFSSL_P521_KYBER1024;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P256_KYBER90S512))
ssl->group[ssl->numGroups++] = WOLFSSL_P256_KYBER90S512;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P384_KYBER90S768))
ssl->group[ssl->numGroups++] = WOLFSSL_P384_KYBER90S768;
if (TLSX_KeyShare_IsSupported(WOLFSSL_P521_KYBER90S1024))
ssl->group[ssl->numGroups++] = WOLFSSL_P521_KYBER90S1024;
#endif #endif
} }
@ -10619,6 +10916,45 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions)
if (ret == WOLFSSL_SUCCESS) if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER90S1024, ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER90S1024,
ssl->heap); ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_NTRU_HPS2048509,
ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_NTRU_HPS2048677,
ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_NTRU_HPS4096821,
ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_NTRU_HRSS701,
ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_LIGHTSABER,
ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_SABER, ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_FIRESABER,
ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER512,
ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_KYBER768,
ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_KYBER1024,
ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER90S512,
ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_KYBER90S768,
ssl->heap);
if (ret == WOLFSSL_SUCCESS)
ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_KYBER90S1024,
ssl->heap);
#endif /* HAVE_LIBOQS */ #endif /* HAVE_LIBOQS */
(void)ssl; (void)ssl;

View File

@ -776,7 +776,7 @@ enum SNICbReturn {
#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 #ifdef HAVE_LIBOQS
#define WOLFSSL_MAX_GROUP_COUNT 23 #define WOLFSSL_MAX_GROUP_COUNT 36
#else #else
#define WOLFSSL_MAX_GROUP_COUNT 10 #define WOLFSSL_MAX_GROUP_COUNT 10
#endif #endif
@ -3510,23 +3510,41 @@ enum {
#ifdef HAVE_LIBOQS #ifdef HAVE_LIBOQS
/* These group numbers were taken from liboqs' openssl fork, see: /* These group numbers were taken from liboqs' openssl fork, see:
https://github.com/open-quantum-safe/openssl/blob/OQS-OpenSSL_1_1_1-stable/ * https://github.com/open-quantum-safe/openssl/blob/OQS-OpenSSL_1_1_1-stable/
oqs-template/oqs-kem-info.md */ * oqs-template/oqs-kem-info.md */
WOLFSSL_OQS_MIN = 532, WOLFSSL_OQS_MIN = 532,
WOLFSSL_NTRU_HPS2048509 = 532, WOLFSSL_OQS_SIMPLE_MIN = 532,
WOLFSSL_NTRU_HPS2048677 = 533, WOLFSSL_NTRU_HPS2048509 = 532,
WOLFSSL_NTRU_HPS4096821 = 534, WOLFSSL_NTRU_HPS2048677 = 533,
WOLFSSL_NTRU_HRSS701 = 535, WOLFSSL_NTRU_HPS4096821 = 534,
WOLFSSL_LIGHTSABER = 536, WOLFSSL_NTRU_HRSS701 = 535,
WOLFSSL_SABER = 537, WOLFSSL_LIGHTSABER = 536,
WOLFSSL_FIRESABER = 538, WOLFSSL_SABER = 537,
WOLFSSL_KYBER512 = 570, WOLFSSL_FIRESABER = 538,
WOLFSSL_KYBER768 = 572, WOLFSSL_KYBER512 = 570,
WOLFSSL_KYBER1024 = 573, WOLFSSL_KYBER768 = 572,
WOLFSSL_KYBER90S512 = 574, WOLFSSL_KYBER1024 = 573,
WOLFSSL_KYBER90S768 = 575, WOLFSSL_KYBER90S512 = 574,
WOLFSSL_KYBER90S1024 = 576, WOLFSSL_KYBER90S768 = 575,
WOLFSSL_OQS_MAX = 576, WOLFSSL_KYBER90S1024 = 576,
WOLFSSL_OQS_SIMPLE_MAX = 576,
WOLFSSL_OQS_HYBRID_MIN = 12052,
WOLFSSL_P256_NTRU_HPS2048509 = 12052,
WOLFSSL_P384_NTRU_HPS2048677 = 12053,
WOLFSSL_P521_NTRU_HPS4096821 = 12054,
WOLFSSL_P384_NTRU_HRSS701 = 12055,
WOLFSSL_P256_LIGHTSABER = 12056,
WOLFSSL_P384_SABER = 12057,
WOLFSSL_P521_FIRESABER = 12058,
WOLFSSL_P256_KYBER512 = 12090,
WOLFSSL_P384_KYBER768 = 12092,
WOLFSSL_P521_KYBER1024 = 12093,
WOLFSSL_P256_KYBER90S512 = 12094,
WOLFSSL_P384_KYBER90S768 = 12095,
WOLFSSL_P521_KYBER90S1024 = 12096,
WOLFSSL_OQS_HYBRID_MAX = 12096,
WOLFSSL_OQS_MAX = 12096,
#endif #endif
}; };