TLS v1.3 Interop changes

Added Curve25519 for TLS v1.3 only. Curve25519 won't work with older
protocol versions.
Always send signature algorithm extension in TLS v1.3 for server
certificates. If only doing PSK doesn't need to be sent though.
This commit is contained in:
Sean Parkinson
2017-05-10 12:59:22 +10:00
parent dea092fa0a
commit df3abee72c
2 changed files with 313 additions and 17 deletions

329
src/tls.c
View File

@@ -40,6 +40,10 @@
#include <wolfcrypt/src/misc.c>
#endif
#ifdef HAVE_CURVE25519
#include <wolfssl/wolfcrypt/curve25519.h>
#endif
#ifdef HAVE_NTRU
#include "libntruencrypt/ntru_crypto.h"
#include <wolfssl/wolfcrypt/random.h>
@@ -4304,9 +4308,9 @@ static word16 TLSX_SupportedVersions_Write(byte* data, byte* output)
/* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */
if (pv.minor - i == TLSv1_3_MINOR) {
/* The TLS draft major number. */
*(output++) = 0x7f;
*(output++) = TLS_DRAFT_MAJOR;
/* Version of draft supported. */
*(output++) = 18;
*(output++) = TLS_DRAFT_MINOR;
continue;
}
@@ -4347,7 +4351,8 @@ static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input,
/* Find first match. */
for (i = 0; i < len; i += OPAQUE16_LEN) {
/* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */
if (input[i] == 0x7f && input[i + OPAQUE8_LEN] == 18) {
if (input[i] == TLS_DRAFT_MAJOR &&
input[i + OPAQUE8_LEN] == TLS_DRAFT_MINOR) {
ssl->version.minor = TLSv1_3_MINOR;
ssl->options.tls1_3 = 1;
TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, input,
@@ -4411,6 +4416,174 @@ static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data,
#endif /* WOLFSSL_TLS13 */
/******************************************************************************/
/* Sugnature Algorithms */
/******************************************************************************/
#ifdef WOLFSSL_TLS13
/* Return the size of the SignatureAlgorithms extension's data.
*
* data Unused
* returns the length of data that will be in the extension.
*/
static word16 TLSX_SignatureAlgorithms_GetSize(byte* data)
{
int cnt = 0;
(void)data;
#ifndef NO_RSA
#ifndef NO_SHA1
cnt++;
#endif
#ifndef NO_SHA256
cnt++;
#endif
#ifdef HAVE_SHA384
cnt++;
#endif
#ifdef HAVE_SHA512
cnt++;
#endif
#endif
#ifdef HAVE_ECC
#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
cnt++;
#endif
#endif
#if !defined(NO_ECC384) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
cnt++;
#endif
#endif
#if !defined(NO_ECC521) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
cnt++;
#endif
#endif
#endif
return OPAQUE16_LEN + cnt * OPAQUE16_LEN;
}
/* Writes the SignatureAlgorithms extension into the buffer.
*
* data Unused
* output The buffer to write the extension into.
* returns the length of data that was written.
*/
static word16 TLSX_SignatureAlgorithms_Write(byte* data, byte* output)
{
int idx = OPAQUE16_LEN;
(void)data;
#ifndef NO_RSA
#ifndef NO_SHA1
output[idx++] = 0x02;
output[idx++] = 0x01;
#endif
#ifndef NO_SHA256
output[idx++] = 0x04;
output[idx++] = 0x01;
#endif
#ifdef HAVE_SHA384
output[idx++] = 0x05;
output[idx++] = 0x01;
#endif
#ifdef HAVE_SHA512
output[idx++] = 0x06;
output[idx++] = 0x01;
#endif
#endif
#ifdef HAVE_ECC
#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
output[idx++] = 0x04;
output[idx++] = 0x03;
#endif
#endif
#if !defined(NO_ECC384) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
output[idx++] = 0x05;
output[idx++] = 0x03;
#endif
#endif
#if !defined(NO_ECC521) || defined(HAVE_ALL_CURVES)
#ifndef NO_ECC_SECP
output[idx++] = 0x06;
output[idx++] = 0x03;
#endif
#endif
#endif
output[0] = (idx - OPAQUE16_LEN) >> 8;
output[1] = idx - OPAQUE16_LEN;
return idx;
}
/* Parse the SignatureAlgorithms extension.
*
* ssl The SSL/TLS object.
* input The buffer with the extension data.
* length The length of the extension data.
* returns 0 on success, otherwise failure.
*/
static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input,
word16 length)
{
int ret = 0;
word16 len;
(void)ssl;
/* Must contain a length and at least algorithm. */
if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0)
return BUFFER_ERROR;
ato16(input, &len);
/* Algorithm array must fill rest of data. */
if (length != OPAQUE16_LEN + len)
return BUFFER_ERROR;
/* Ignore for now. */
return ret;
}
/* Sets a new SupportedVersions extension into the extension list.
*
* extensions The list of extensions.
* data The extensions specific data.
* heap The heap used for allocation.
* returns 0 on success, otherwise failure.
*/
static int TLSX_SetSignatureAlgorithms(TLSX** extensions, const void* data,
void* heap)
{
if (extensions == NULL)
return BAD_FUNC_ARG;
return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, (void *)data, heap);
}
#define SA_GET_SIZE TLSX_SignatureAlgorithms_GetSize
#define SA_WRITE TLSX_SignatureAlgorithms_Write
#define SA_PARSE TLSX_SignatureAlgorithms_Parse
#else
#define SA_GET_SIZE(a) 0
#define SA_WRITE(a, b) 0
#define SA_PARSE(a, b, c) 0
#endif
/******************************************************************************/
/* Key Share */
/******************************************************************************/
@@ -4588,9 +4761,52 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
#endif
#ifdef HAVE_CURVE25519
case WOLFSSL_ECC_X25519:
curveId = ECC_X25519;
dataSize = keySize = 32;
break;
{
curve25519_key* key;
/* Allocate an ECC key to hold private key. */
key = (curve25519_key*)XMALLOC(sizeof(curve25519_key),
ssl->heap, DYNAMIC_TYPE_TLSX);
if (key == NULL) {
WOLFSSL_MSG("EccTempKey Memory error");
return MEMORY_E;
}
dataSize = keySize = 32;
/* Make an ECC key. */
ret = wc_curve25519_init(key);
if (ret != 0)
goto end;
ret = wc_curve25519_make_key(ssl->rng, keySize, key);
if (ret != 0)
goto end;
/* Allocate space for the public key. */
keyData = XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_TLSX);
if (keyData == NULL) {
WOLFSSL_MSG("Key data Memory error");
ret = MEMORY_E;
goto end;
}
/* Export public key. */
if (wc_curve25519_export_public_ex(key, keyData, &dataSize,
EC25519_LITTLE_ENDIAN) != 0) {
ret = ECC_EXPORT_ERROR;
goto end;
}
kse->ke = keyData;
kse->keLen = dataSize;
kse->key = key;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Public ECC Key");
WOLFSSL_BUFFER(keyData, dataSize);
#endif
goto end;
}
#endif
#ifdef HAVE_X448
case WOLFSSL_ECC_X448:
@@ -4922,8 +5138,42 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
#endif
#ifdef HAVE_CURVE25519
case WOLFSSL_ECC_X25519:
curveId = ECC_X25519;
break;
{
curve25519_key* key = (curve25519_key*)keyShareEntry->key;
curve25519_key* peerEccKey;
if (ssl->peerEccKey != NULL)
wc_ecc_free(ssl->peerEccKey);
peerEccKey = (curve25519_key*)XMALLOC(sizeof(curve25519_key),
ssl->heap, DYNAMIC_TYPE_TLSX);
if (peerEccKey == NULL) {
WOLFSSL_MSG("PeerEccKey Memory error");
return MEMORY_ERROR;
}
ret = wc_curve25519_init(peerEccKey);
if (ret != 0)
return ret;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Peer ECC Key");
WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
#endif
/* Point is validated by import function. */
if (wc_curve25519_import_public_ex(keyShareEntry->ke,
keyShareEntry->keLen, peerEccKey,
EC25519_LITTLE_ENDIAN) != 0) {
return ECC_PEERKEY_ERROR;
}
ssl->arrays->preMasterSz = ENCRYPT_LEN;
ret = wc_curve25519_shared_secret_ex(key, peerEccKey,
ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz,
EC25519_LITTLE_ENDIAN);
wc_curve25519_free(peerEccKey);
XFREE(peerEccKey, ssl->heap, DYNAMIC_TYPE_TLSX);
return ret;
}
#endif
#ifdef HAVE_X448
case WOLFSSL_ECC_X448:
@@ -6136,6 +6386,9 @@ void TLSX_FreeAll(TLSX* list, void* heap)
ALPN_FREE_ALL((ALPN*)extension->data, heap);
break;
case TLSX_SIGNATURE_ALGORITHMS:
break;
#ifdef WOLFSSL_TLS13
case TLSX_SUPPORTED_VERSIONS:
break;
@@ -6237,6 +6490,12 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType)
length += ALPN_GET_SIZE((ALPN*)extension->data);
break;
case TLSX_SIGNATURE_ALGORITHMS:
#ifdef WOLFSSL_TLS13
length += SA_GET_SIZE(extension->data);
#endif
break;
#ifdef WOLFSSL_TLS13
case TLSX_SUPPORTED_VERSIONS:
length += SV_GET_SIZE(extension->data);
@@ -6355,6 +6614,13 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
offset += ALPN_WRITE((ALPN*)extension->data, output + offset);
break;
case TLSX_SIGNATURE_ALGORITHMS:
#ifdef WOLFSSL_TLS13
WOLFSSL_MSG("Signature Algorithms extension to write");
offset += SA_WRITE(extension->data, output + offset);
#endif
break;
#ifdef WOLFSSL_TLS13
case TLSX_SUPPORTED_VERSIONS:
WOLFSSL_MSG("Supported Versions extension to write");
@@ -6760,6 +7026,15 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
if (ret != SSL_SUCCESS) return ret;
#endif
#endif
#ifdef WOLFSSL_TLS13
#if defined(HAVE_CURVE25519)
#ifndef NO_ECC_SECP
ret = TLSX_UseSupportedCurve(&ssl->extensions,
WOLFSSL_ECC_X25519, ssl->heap);
if (ret != SSL_SUCCESS) return ret;
#endif
#endif
#endif
}
#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */
} /* is not server */
@@ -6771,6 +7046,11 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
if ((ret = TLSX_SetSupportedVersions(&ssl->extensions, ssl,
ssl->heap)) != 0)
return ret;
/* Add TLS v1.3 extension: signature algorithms */
WOLFSSL_MSG("Adding signature algorithms extension");
if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, NULL,
ssl->heap)) != 0)
return ret;
/* Add FFDHE supported groups. */
#ifdef HAVE_FFDHE_2048
@@ -6898,6 +7178,7 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl)
#if defined(WOLFSSL_TLS13)
if (!IsAtLeastTLSv1_3(ssl->version)) {
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
#ifndef NO_PSK
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
@@ -6914,9 +7195,11 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl)
client_hello);
}
#ifndef WOLFSSL_TLS13
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz)
length += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ
length += HELLO_EXT_SZ + OPAQUE16_LEN +
+ ssl->suites->hashSigAlgoSz;
#endif
#ifdef HAVE_EXTENDED_MASTER
if (ssl->options.haveEMS)
@@ -6946,6 +7229,7 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output)
#if defined(WOLFSSL_TLS13)
if (!IsAtLeastTLSv1_3(ssl->version)) {
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS));
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
#ifndef NO_PSK
TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
@@ -6964,10 +7248,11 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output)
offset += TLSX_Write(ssl->ctx->extensions, output + offset,
semaphore, client_hello);
#ifndef WOLFSSL_TLS13
if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) {
int i;
/* extension type */
c16toa(HELLO_EXT_SIG_ALGO, output + offset);
c16toa(TLSX_SIGNATURE_ALGORITHMS, output + offset);
offset += HELLO_EXT_TYPE_SZ;
/* extension data length */
@@ -6983,6 +7268,7 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output)
for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, offset++)
output[offset] = ssl->suites->hashSigAlgo[i];
}
#endif
#ifdef HAVE_EXTENDED_MASTER
if (ssl->options.haveEMS) {
@@ -7285,16 +7571,11 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType,
ret = ALPN_PARSE(ssl, input + offset, size, isRequest);
break;
case HELLO_EXT_SIG_ALGO:
#ifndef WOLFSSL_TLS13
case TLSX_SIGNATURE_ALGORITHMS:
WOLFSSL_MSG("Extended signature algorithm extension received");
if (isRequest) {
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(ssl->version) &&
msgType != client_hello) {
return EXT_NOT_ALLOWED;
}
#endif
/* do not mess with offset inside the switch! */
if (IsAtLeastTLSv1_2(ssl)) {
ato16(input + offset, &suites->hashSigAlgoSz);
@@ -7312,6 +7593,7 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType,
}
break;
#endif
#ifdef WOLFSSL_TLS13
case TLSX_SUPPORTED_VERSIONS:
@@ -7327,6 +7609,19 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType,
ret = SV_PARSE(ssl, input + offset, size);
break;
case TLSX_SIGNATURE_ALGORITHMS:
WOLFSSL_MSG("Signature Algorithms extension received");
if (!IsAtLeastTLSv1_3(ssl->version))
break;
if (IsAtLeastTLSv1_3(ssl->version) &&
msgType != client_hello) {
return EXT_NOT_ALLOWED;
}
ret = SA_PARSE(ssl, input + offset, size);
break;
case TLSX_KEY_SHARE:
WOLFSSL_MSG("Key Share extension received");

View File

@@ -1747,6 +1747,7 @@ typedef enum {
TLSX_TRUNCATED_HMAC = 0x0004,
TLSX_STATUS_REQUEST = 0x0005, /* a.k.a. OCSP stapling */
TLSX_SUPPORTED_GROUPS = 0x000a, /* a.k.a. Supported Curves */
TLSX_SIGNATURE_ALGORITHMS = 0x000d,
TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */
TLSX_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stapling v2 */
TLSX_QUANTUM_SAFE_HYBRID = 0x0018, /* a.k.a. QSH */