Merge branch 'master' of github.com:cyassl/cyassl

This commit is contained in:
toddouska 2014-02-25 14:37:00 -08:00
commit c4fd159860
5 changed files with 169 additions and 97 deletions

View File

@ -599,7 +599,9 @@ enum Misc {
COOKIE_SZ = 20, /* use a 20 byte cookie */
SUITE_LEN = 2, /* cipher suite sz length */
ENUM_LEN = 1, /* always a byte */
OPAQUE16_LEN = 2, /* always 2 bytes */
OPAQUE8_LEN = 1, /* 1 byte */
OPAQUE16_LEN = 2, /* 2 bytes */
OPAQUE24_LEN = 3, /* 3 bytes */
COMP_LEN = 1, /* compression length */
CURVE_LEN = 2, /* ecc named curve length */
SERVER_ID_LEN = 20, /* server session id length */

View File

@ -133,7 +133,7 @@ static void Usage(void)
#ifdef HAVE_SNI
printf("-S <str> Use Host Name Indication\n");
#endif
#ifdef HAVE_MAXFRAGMENT
#ifdef HAVE_MAX_FRAGMENT
printf("-L <num> Use Maximum Fragment Length [1-5]\n");
#endif
#ifdef HAVE_TRUNCATED_HMAC

View File

@ -117,7 +117,7 @@
AX_APPEND_COMPILE_FLAGS([-Wno-pragmas],,[$ax_append_compile_cflags_extra])
AX_APPEND_COMPILE_FLAGS([-Wall],,[$ax_append_compile_cflags_extra])
AX_APPEND_COMPILE_FLAGS([-Wno-strict-aliasing],,,[$ax_append_compile_cflags_extra])
AX_APPEND_COMPILE_FLAGS([-Wno-strict-aliasing],,[$ax_append_compile_cflags_extra])
AX_APPEND_COMPILE_FLAGS([-Wextra],,[$ax_append_compile_cflags_extra])
AX_APPEND_COMPILE_FLAGS([-Wunknown-pragmas],,[$ax_append_compile_cflags_extra])
AX_APPEND_COMPILE_FLAGS([-Wthis-test-should-fail],,[$ax_append_compile_cflags_extra])
@ -187,7 +187,7 @@
])
AX_APPEND_COMPILE_FLAGS([-Wall],,[$ax_append_compile_cxxflags_extra])
AX_APPEND_COMPILE_FLAGS([-Wno-strict-aliasing],,,[$ax_append_compile_cxxflags_extra])
AX_APPEND_COMPILE_FLAGS([-Wno-strict-aliasing],,[$ax_append_compile_cxxflags_extra])
AX_APPEND_COMPILE_FLAGS([-Wextra],,[$ax_append_compile_cxxflags_extra])
AX_APPEND_COMPILE_FLAGS([-Wunknown-pragmas],,[$ax_append_compile_cxxflags_extra])
AX_APPEND_COMPILE_FLAGS([-Wthis-test-should-fail],,[$ax_append_compile_cxxflags_extra])

View File

@ -79,8 +79,7 @@ CYASSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS
#ifndef NO_CYASSL_SERVER
static int DoClientHello(CYASSL* ssl, const byte* input, word32*, word32,
word32);
static int DoClientHello(CYASSL* ssl, const byte* input, word32*, word32);
static int DoClientKeyExchange(CYASSL* ssl, byte* input, word32*, word32);
#if !defined(NO_RSA) || defined(HAVE_ECC)
static int DoCertificateVerify(CYASSL* ssl, byte*, word32*, word32);
@ -3723,7 +3722,12 @@ static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx,
CYASSL_ENTER("DoHandShakeMsgType");
/* make sure can read the message */
if (*inOutIdx + size > totalSz)
return INCOMPLETE_DATA;
HashInput(ssl, input + *inOutIdx, size);
#ifdef CYASSL_CALLBACKS
/* add name later, add on record and handshake header part back on */
if (ssl->toInfoOn) {
@ -3820,12 +3824,12 @@ static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx,
#ifndef NO_CYASSL_SERVER
case client_hello:
CYASSL_MSG("processing client hello");
ret = DoClientHello(ssl, input, inOutIdx, totalSz, size);
ret = DoClientHello(ssl, input, inOutIdx, size);
break;
case client_key_exchange:
CYASSL_MSG("processing client key exchange");
ret = DoClientKeyExchange(ssl, input, inOutIdx, totalSz);
ret = DoClientKeyExchange(ssl, input, inOutIdx, size);
break;
#if !defined(NO_RSA) || defined(HAVE_ECC)
@ -3840,6 +3844,7 @@ static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx,
default:
CYASSL_MSG("Unknown handshake message type");
ret = UNKNOWN_HANDSHAKE_TYPE;
break;
}
CYASSL_LEAVE("DoHandShakeMsgType()", ret);
@ -3850,18 +3855,15 @@ static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx,
static int DoHandShakeMsg(CYASSL* ssl, byte* input, word32* inOutIdx,
word32 totalSz)
{
byte type;
byte type;
word32 size;
int ret = 0;
int ret = 0;
CYASSL_ENTER("DoHandShakeMsg()");
if (GetHandShakeHeader(ssl, input, inOutIdx, &type, &size) != 0)
return PARSE_ERROR;
if (*inOutIdx + size > totalSz)
return INCOMPLETE_DATA;
ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
CYASSL_LEAVE("DoHandShakeMsg()", ret);
@ -7461,29 +7463,38 @@ static void PickHashSigAlgo(CYASSL* ssl,
static int DoServerHello(CYASSL* ssl, const byte* input, word32* inOutIdx,
word32 helloSz)
{
byte b;
byte compression;
byte b;
ProtocolVersion pv;
word32 i = *inOutIdx;
word32 begin = i;
byte compression;
word32 i = *inOutIdx;
word32 begin = i;
#ifdef CYASSL_CALLBACKS
if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo);
if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo);
#endif
XMEMCPY(&pv, input + i, sizeof(pv));
i += (word32)sizeof(pv);
/* protocol version, random and session id length check */
if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
/* protocol version */
XMEMCPY(&pv, input + i, OPAQUE16_LEN);
i += OPAQUE16_LEN;
if (pv.minor > ssl->version.minor) {
CYASSL_MSG("Server using higher version, fatal error");
return VERSION_ERROR;
}
else if (pv.minor < ssl->version.minor) {
CYASSL_MSG("server using lower version");
if (!ssl->options.downgrade) {
CYASSL_MSG(" no downgrade allowed, fatal error");
return VERSION_ERROR;
}
else if (pv.minor == SSLv3_MINOR) {
if (pv.minor == SSLv3_MINOR) {
/* turn off tls */
CYASSL_MSG(" downgrading to SSLv3");
ssl->options.tls = 0;
@ -7501,14 +7512,31 @@ static void PickHashSigAlgo(CYASSL* ssl,
ssl->version.minor = TLSv1_1_MINOR;
}
}
/* random */
XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN);
i += RAN_LEN;
/* session id */
b = input[i++];
if (b) {
if (b == ID_LEN) {
if ((i - begin) + ID_LEN > helloSz)
return BUFFER_ERROR;
XMEMCPY(ssl->arrays->sessionID, input + i, min(b, ID_LEN));
i += b;
i += ID_LEN;
ssl->options.haveSessionId = 1;
}
else if (b) {
CYASSL_MSG("Invalid session ID size");
return BUFFER_ERROR; /* session ID nor 0 neither 32 bytes long */
}
/* suite and compression */
if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
ssl->options.cipherSuite0 = input[i++];
ssl->options.cipherSuite = input[i++];
compression = input[i++];
@ -7519,17 +7547,23 @@ static void PickHashSigAlgo(CYASSL* ssl,
}
*inOutIdx = i;
/* tls extensions */
if ( (i - begin) < helloSz) {
#ifdef HAVE_TLS_EXTENSIONS
if (IsTLS(ssl)) {
int ret = 0;
int ret = 0;
word16 totalExtSz;
Suites clSuites; /* just for compatibility right now */
if ((i - begin) + OPAQUE16_LEN > helloSz)
return BUFFER_ERROR;
ato16(&input[i], &totalExtSz);
i += LENGTH_SZ;
if (totalExtSz > helloSz + begin - i)
return INCOMPLETE_DATA;
i += OPAQUE16_LEN;
if ((i - begin) + totalExtSz > helloSz)
return BUFFER_ERROR;
if ((ret = TLSX_Parse(ssl, (byte *) input + i,
totalExtSz, 0, &clSuites)))
@ -7540,7 +7574,7 @@ static void PickHashSigAlgo(CYASSL* ssl,
}
else
#endif
*inOutIdx = begin + helloSz; /* skip extensions */
*inOutIdx = begin + helloSz; /* skip extensions */
}
ssl->options.serverState = SERVER_HELLO_COMPLETE;
@ -7549,7 +7583,8 @@ static void PickHashSigAlgo(CYASSL* ssl,
if (ssl->options.haveSessionId && XMEMCMP(ssl->arrays->sessionID,
ssl->session.sessionID, ID_LEN) == 0) {
if (SetCipherSpecs(ssl) == 0) {
int ret = -1;
int ret = -1;
XMEMCPY(ssl->arrays->masterSecret,
ssl->session.masterSecret, SECRET_LEN);
#ifdef NO_OLD_TLS
@ -7563,6 +7598,7 @@ static void PickHashSigAlgo(CYASSL* ssl,
ret = DeriveKeys(ssl);
#endif
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
return ret;
}
else {
@ -7580,6 +7616,7 @@ static void PickHashSigAlgo(CYASSL* ssl,
DtlsPoolReset(ssl);
}
#endif
return SetCipherSpecs(ssl);
}
@ -9986,7 +10023,7 @@ static void PickHashSigAlgo(CYASSL* ssl,
static int DoClientHello(CYASSL* ssl, const byte* input, word32* inOutIdx,
word32 totalSz, word32 helloSz)
word32 helloSz)
{
byte b;
ProtocolVersion pv;
@ -9999,12 +10036,8 @@ static void PickHashSigAlgo(CYASSL* ssl,
if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo);
#endif
/* make sure can read the client hello */
if (begin + helloSz > totalSz)
return INCOMPLETE_DATA;
/* protocol version, random and session id length check */
if ((i - begin) + OPAQUE16_LEN + RAN_LEN + ENUM_LEN > helloSz)
if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
/* protocol version */
@ -10076,14 +10109,16 @@ static void PickHashSigAlgo(CYASSL* ssl,
ssl->options.resuming = 1; /* client wants to resume */
CYASSL_MSG("Client wants to resume session");
}
else if (b)
else if (b) {
CYASSL_MSG("Invalid session ID size");
return BUFFER_ERROR; /* session ID nor 0 neither 32 bytes long */
}
#ifdef CYASSL_DTLS
/* cookie */
if (ssl->options.dtls) {
if ((i - begin) + ENUM_LEN > helloSz)
if ((i - begin) + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
b = input[i++];
@ -10122,7 +10157,7 @@ static void PickHashSigAlgo(CYASSL* ssl,
i += OPAQUE16_LEN;
/* suites and compression length check */
if ((i - begin) + clSuites.suiteSz + ENUM_LEN > helloSz)
if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz)
return BUFFER_ERROR;
if (clSuites.suiteSz > MAX_SUITE_SZ)
@ -10512,18 +10547,19 @@ static void PickHashSigAlgo(CYASSL* ssl,
}
#endif
static int DoClientKeyExchange(CYASSL* ssl, byte* input,
word32* inOutIdx, word32 totalSz)
static int DoClientKeyExchange(CYASSL* ssl, byte* input, word32* inOutIdx,
word32 size)
{
int ret = 0;
word32 length = 0;
byte* out = NULL;
word32 begin = *inOutIdx;
(void)length; /* shut up compiler warnings */
(void)out;
(void)input;
(void)inOutIdx;
(void)totalSz;
(void)size;
if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) {
CYASSL_MSG("Client sending keyexchange at wrong time");
@ -10552,15 +10588,12 @@ static void PickHashSigAlgo(CYASSL* ssl,
{
word32 idx = 0;
RsaKey key;
byte* tmp = 0;
byte doUserRsa = 0;
#ifdef HAVE_PK_CALLBACKS
#ifndef NO_RSA
if (ssl->ctx->RsaDecCb)
doUserRsa = 1;
#endif /* NO_RSA */
#endif /*HAVE_PK_CALLBACKS */
if (ssl->ctx->RsaDecCb)
doUserRsa = 1;
#endif
InitRsaKey(&key, ssl->heap);
@ -10576,28 +10609,31 @@ static void PickHashSigAlgo(CYASSL* ssl,
if (ssl->options.tls) {
word16 check;
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;
ato16(input + *inOutIdx, &check);
if ((word32)check != length) {
*inOutIdx += OPAQUE16_LEN;
if ((word32) check != length) {
CYASSL_MSG("RSA explicit size doesn't match");
FreeRsaKey(&key);
return RSA_PRIVATE_ERROR;
}
(*inOutIdx) += 2;
}
tmp = input + *inOutIdx;
*inOutIdx += length;
if (*inOutIdx > totalSz) {
if ((*inOutIdx - begin) + length > size) {
CYASSL_MSG("RSA message too big");
FreeRsaKey(&key);
return INCOMPLETE_DATA;
return BUFFER_ERROR;
}
if (doUserRsa) {
#ifdef HAVE_PK_CALLBACKS
#ifndef NO_RSA
ret = ssl->ctx->RsaDecCb(ssl,
tmp, length, &out,
input + *inOutIdx, length, &out,
ssl->buffers.key.buffer,
ssl->buffers.key.length,
ssl->RsaDecCtx);
@ -10605,9 +10641,12 @@ static void PickHashSigAlgo(CYASSL* ssl,
#endif /*HAVE_PK_CALLBACKS */
}
else {
ret = RsaPrivateDecryptInline(tmp, length, &out, &key);
ret = RsaPrivateDecryptInline(input + *inOutIdx, length,
&out, &key);
}
*inOutIdx += length;
if (ret == SECRET_LEN) {
XMEMCPY(ssl->arrays->preMasterSecret, out, SECRET_LEN);
if (ssl->arrays->preMasterSecret[0] !=
@ -10633,36 +10672,46 @@ static void PickHashSigAlgo(CYASSL* ssl,
byte* pms = ssl->arrays->preMasterSecret;
word16 ci_sz;
ato16(&input[*inOutIdx], &ci_sz);
*inOutIdx += LENGTH_SZ;
if (ci_sz > MAX_PSK_ID_LEN) return CLIENT_ID_ERROR;
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;
XMEMCPY(ssl->arrays->client_identity, &input[*inOutIdx], ci_sz);
ato16(input + *inOutIdx, &ci_sz);
*inOutIdx += OPAQUE16_LEN;
if (ci_sz > MAX_PSK_ID_LEN)
return CLIENT_ID_ERROR;
if ((*inOutIdx - begin) + ci_sz > size)
return BUFFER_ERROR;
XMEMCPY(ssl->arrays->client_identity, input + *inOutIdx, ci_sz);
*inOutIdx += ci_sz;
if (ci_sz < MAX_PSK_ID_LEN)
ssl->arrays->client_identity[ci_sz] = 0;
else
ssl->arrays->client_identity[MAX_PSK_ID_LEN-1] = 0;
ssl->arrays->client_identity[min(ci_sz, MAX_PSK_ID_LEN-1)] = 0;
ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl,
ssl->arrays->client_identity, ssl->arrays->psk_key,
MAX_PSK_KEY_LEN);
if (ssl->arrays->psk_keySz == 0 ||
ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN)
ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN)
return PSK_KEY_ERROR;
/* make psk pre master secret */
/* length of key + length 0s + length of key + key */
c16toa((word16)ssl->arrays->psk_keySz, pms);
pms += 2;
c16toa((word16) ssl->arrays->psk_keySz, pms);
pms += OPAQUE16_LEN;
XMEMSET(pms, 0, ssl->arrays->psk_keySz);
pms += ssl->arrays->psk_keySz;
c16toa((word16)ssl->arrays->psk_keySz, pms);
pms += 2;
c16toa((word16) ssl->arrays->psk_keySz, pms);
pms += OPAQUE16_LEN;
XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz);
ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4;
ret = MakeMasterSecret(ssl);
/* No further need for PSK */
XMEMSET(ssl->arrays->psk_key, 0, ssl->arrays->psk_keySz);
ssl->arrays->psk_keySz = 0;
@ -10672,26 +10721,34 @@ static void PickHashSigAlgo(CYASSL* ssl,
#ifdef HAVE_NTRU
case ntru_kea:
{
word32 rc;
word16 cipherLen;
word16 plainLen = sizeof(ssl->arrays->preMasterSecret);
byte* tmp;
if (!ssl->buffers.key.buffer)
return NO_PRIVATE_KEY;
ato16(&input[*inOutIdx], &cipherLen);
*inOutIdx += LENGTH_SZ;
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;
ato16(input + *inOutIdx, &cipherLen);
*inOutIdx += OPAQUE16_LEN;
if (cipherLen > MAX_NTRU_ENCRYPT_SZ)
return NTRU_KEY_ERROR;
tmp = input + *inOutIdx;
rc = crypto_ntru_decrypt((word16)ssl->buffers.key.length,
ssl->buffers.key.buffer, cipherLen, tmp, &plainLen,
ssl->arrays->preMasterSecret);
if ((*inOutIdx - begin) + cipherLen > size)
return BUFFER_ERROR;
if (rc != NTRU_OK || plainLen != SECRET_LEN)
if (NTRU_OK != crypto_ntru_decrypt(
(word16) ssl->buffers.key.length,
ssl->buffers.key.buffer, cipherLen,
input + *inOutIdx, &plainLen,
ssl->arrays->preMasterSecret))
return NTRU_DECRYPT_ERROR;
if (plainLen != SECRET_LEN)
return NTRU_DECRYPT_ERROR;
*inOutIdx += cipherLen;
ssl->arrays->preMasterSz = plainLen;
@ -10702,18 +10759,23 @@ static void PickHashSigAlgo(CYASSL* ssl,
#ifdef HAVE_ECC
case ecc_diffie_hellman_kea:
{
word32 size;
word32 bLength = input[*inOutIdx]; /* one byte length */
*inOutIdx += 1;
if ((*inOutIdx - begin) + OPAQUE8_LEN > size)
return BUFFER_ERROR;
ret = ecc_import_x963(&input[*inOutIdx],
bLength, ssl->peerEccKey);
if (ret != 0)
length = input[*inOutIdx];
*inOutIdx += OPAQUE8_LEN;
if ((*inOutIdx - begin) + length > size)
return BUFFER_ERROR;
if (ecc_import_x963(input + *inOutIdx, length, ssl->peerEccKey))
return ECC_PEERKEY_ERROR;
*inOutIdx += bLength;
*inOutIdx += length;
ssl->peerEccKeyPresent = 1;
size = sizeof(ssl->arrays->preMasterSecret);
length = sizeof(ssl->arrays->preMasterSecret);
if (ssl->specs.static_ecdh) {
ecc_key staticKey;
word32 i = 0;
@ -10721,17 +10783,21 @@ static void PickHashSigAlgo(CYASSL* ssl,
ecc_init(&staticKey);
ret = EccPrivateKeyDecode(ssl->buffers.key.buffer, &i,
&staticKey, ssl->buffers.key.length);
if (ret == 0)
ret = ecc_shared_secret(&staticKey, ssl->peerEccKey,
ssl->arrays->preMasterSecret, &size);
ssl->arrays->preMasterSecret, &length);
ecc_free(&staticKey);
}
else
else
ret = ecc_shared_secret(ssl->eccTempKey, ssl->peerEccKey,
ssl->arrays->preMasterSecret, &size);
ssl->arrays->preMasterSecret, &length);
if (ret != 0)
return ECC_SHARED_ERROR;
ssl->arrays->preMasterSz = size;
ssl->arrays->preMasterSz = length;
ret = MakeMasterSecret(ssl);
}
break;
@ -10739,15 +10805,17 @@ static void PickHashSigAlgo(CYASSL* ssl,
#ifdef OPENSSL_EXTRA
case diffie_hellman_kea:
{
byte* clientPub;
word16 clientPubSz;
DhKey dhKey;
ato16(&input[*inOutIdx], &clientPubSz);
*inOutIdx += LENGTH_SZ;
if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
return BUFFER_ERROR;
clientPub = &input[*inOutIdx];
*inOutIdx += clientPubSz;
ato16(input + *inOutIdx, &clientPubSz);
*inOutIdx += OPAQUE16_LEN;
if ((*inOutIdx - begin) + clientPubSz > size)
return BUFFER_ERROR;
InitDhKey(&dhKey);
ret = DhSetKey(&dhKey, ssl->buffers.serverDH_P.buffer,
@ -10759,8 +10827,11 @@ static void PickHashSigAlgo(CYASSL* ssl,
&ssl->arrays->preMasterSz,
ssl->buffers.serverDH_Priv.buffer,
ssl->buffers.serverDH_Priv.length,
clientPub, clientPubSz);
input + *inOutIdx, clientPubSz);
FreeDhKey(&dhKey);
*inOutIdx += clientPubSz;
if (ret == 0)
ret = MakeMasterSecret(ssl);
}
@ -10773,6 +10844,7 @@ static void PickHashSigAlgo(CYASSL* ssl,
}
break;
}
/* No further need for PMS */
XMEMSET(ssl->arrays->preMasterSecret, 0, ssl->arrays->preMasterSz);
ssl->arrays->preMasterSz = 0;
@ -10789,5 +10861,3 @@ static void PickHashSigAlgo(CYASSL* ssl,
}
#endif /* NO_CYASSL_SERVER */

View File

@ -1782,7 +1782,7 @@ static int DoOldHello(SnifferSession* session, const byte* sslFrame,
ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
*rhSize);
if (ret < 0) {
if (ret < 0 && ret != MATCH_SUITE_ERROR) {
SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
return -1;
}