MatrixSSL 4.0.1

This commit is contained in:
Janne Johansson
2018-11-15 10:12:51 +02:00
parent d0a51a7e43
commit 5a72845b65
95 changed files with 6521 additions and 4845 deletions

View File

@@ -49,7 +49,7 @@
int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end)
{
unsigned char *suiteStart, *suiteEnd;
unsigned char compLen, serverHighestMinor;
unsigned char compLen;
uint32 suiteLen;
uint32 resumptionOnTrack, cipher = 0;
int32 rc, i;
@@ -79,12 +79,12 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end)
return MATRIXSSL_ERROR;
}
ssl->reqMajVer = *c; c++;
ssl->reqMinVer = *c; c++;
psTracePrintProtocolVersion(INDENT_HS_MSG,
ssl->peerHelloVersion = psVerFromEncodingMajMin(*c, *(c+1));
c += 2;
psTracePrintProtocolVersionNew(INDENT_HS_MSG,
"client_version",
ssl->reqMajVer, ssl->reqMinVer, 1);
ssl->peerHelloVersion,
PS_TRUE);
/*
Check whether we can support ClientHello.client_version.
@@ -96,12 +96,11 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end)
So we store the check result and use it only if
no supported_versions extension is found.
*/
versionCheckResult = checkClientHelloVersion(ssl,
&serverHighestMinor);
versionCheckResult = checkClientHelloVersion(ssl);
if (ssl->rec.majVer > SSL2_MAJ_VER)
{
/* Next is a 32 bytes of random data for key generation
/* Next is a 32 bytes of random data for key generation
and a single byte with the session ID length */
if (end - c < SSL_HS_RANDOM_SIZE + 1)
{
@@ -143,13 +142,13 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end)
}
psTracePrintHex(INDENT_HS_MSG,
"session_id",
ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE,
ssl->sessionId,
ssl->sessionIdLen,
PS_TRUE);
# ifdef USE_DTLS
/* If DTLS is enabled, make sure we received a valid cookie in the
CLIENT_HELLO message. */
if (ssl->flags & SSL_FLAGS_DTLS)
if (ACTV_VER(ssl, v_dtls_any))
{
psSize_t cookie_len;
/* Next field is the cookie length */
@@ -292,7 +291,7 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end)
@see https://tools.ietf.org/html/rfc7507#section-3.*/
if (cipher == TLS_FALLBACK_SCSV)
{
if (ssl->reqMinVer < serverHighestMinor)
if (ssl->peerHelloVersion < psVerGetHighestTls(GET_SUPP_VER(ssl)))
{
ssl->err = SSL_ALERT_INAPPROPRIATE_FALLBACK;
psTraceErrr("Inappropriate version fallback\n");
@@ -497,7 +496,10 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end)
rc = checkSupportedVersions(ssl);
if (rc < 0)
{
psTraceErrr("Can't support client's SSL version\n");
psTraceErrr("No shared protocol version: " \
"supported_versions check failed\n");
/* Encode the alert using the highest version we support.*/
SET_ACTV_VER(ssl, psVerGetHighestTls(ssl->supportedVersions));
return rc;
}
}
@@ -510,7 +512,10 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end)
{
/* If no supported_versions extensions was present, and the
ClientHello.client_version check failed, send the alert now. */
psTraceErrr("Can't support client's SSL version\n");
psTraceErrr("No shared protocol version: " \
"ClientHello.client_version check failed\n");
/* Encode the alert using the highest version we support.*/
SET_ACTV_VER(ssl, psVerGetHighestTls(ssl->supportedVersions));
return versionCheckResult;
}
}
@@ -558,7 +563,7 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end)
else
{
ssl->flags &= ~SSL_FLAGS_RESUMED;
if (!NEGOTIATED_TLS_1_3(ssl))
if (!NGTD_VER(ssl, v_tls_1_3_any))
{
# ifdef USE_STATELESS_SESSION_TICKETS
/*
@@ -598,7 +603,7 @@ int32 parseClientHello(ssl_t *ssl, unsigned char **cp, unsigned char *end)
matrixsslUpdateStat(ssl, FAILED_RESUMPTIONS_STAT, 1);
# endif
# endif
} /* !NEGOTIATED_TLS_1_3(ssl) */
} /* !NGTD_VER(ssl, v_tls_1_3_any) */
}
}
@@ -685,7 +690,7 @@ SKIP_STANDARD_RESUMPTION:
# ifdef USE_ECC_CIPHER_SUITE
if (ssl->flags & SSL_FLAGS_ECC_CIPHER &&
!NEGOTIATED_TLS_1_3(ssl))
!NGTD_VER(ssl, v_tls_1_3_any))
{
/* If ecCurveId is zero and we received the extension, then
we really couldn't match and can't continue. */
@@ -844,7 +849,7 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp,
pubKeyLen = hsLen;
# ifdef USE_TLS
/* TLS - Two byte length is explicit. */
if (ssl->majVer >= TLS_MAJ_VER && ssl->minVer >= TLS_MIN_VER)
if (NGTD_VER(ssl, v_tls_any | v_dtls_any))
{
if (end - c < 2)
{
@@ -877,7 +882,7 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp,
# ifdef USE_DHE_CIPHER_SUITE
if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH)
{
if (ssl->majVer == SSL3_MAJ_VER && ssl->minVer == SSL3_MIN_VER)
if (NGTD_VER(ssl, v_ssl_3_0))
{
# ifdef USE_ECC_CIPHER_SUITE
/* Support ECC ciphers in SSLv3. This isn't really a desirable
@@ -956,6 +961,10 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp,
ssl->err = SSL_ALERT_DECODE_ERROR;
return MATRIXSSL_ERROR;
}
# ifdef USE_SSL_INFORMATIONAL_TRACE
ssl->peerKeyExKeyType = PS_ECC;
ssl->peerKeyExKeyNBits = ssl->sec.eccKeyPriv->curve->size * 8;
# endif
/* BUG FIX after 3.8.1a release. This increment is done later
in the function. So in cases where multiple handshake messages
were put in a single record, we are moving pubKeyLen farther
@@ -998,6 +1007,10 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp,
ssl->sec.dhKeyPub = NULL;
return MATRIXSSL_ERROR;
}
# ifdef USE_SSL_INFORMATIONAL_TRACE
ssl->peerKeyExKeyType = PS_DH;
ssl->peerKeyExKeyNBits = pubKeyLen * 8;
# endif
/*
Now know the premaster details. Create it.
@@ -1081,7 +1094,7 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp,
if (ssl->flags & SSL_FLAGS_PSK_CIPHER)
{
if (ssl->majVer == SSL3_MAJ_VER && ssl->minVer == SSL3_MIN_VER)
if (NGTD_VER(ssl, v_ssl_3_0))
{
/* SSLv3 for basic PSK suites will not have read off
pubKeyLen at this point */
@@ -1118,8 +1131,7 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp,
ssl->cipher->type == CS_ECDH_RSA)
{
psEccKey_t *ecc = &ssl->chosenIdentity->privKey.key.ecc;
if (ssl->majVer == SSL3_MAJ_VER &&
ssl->minVer == SSL3_MIN_VER)
if (NGTD_VER(ssl, v_ssl_3_0))
{
/* Support ECC ciphers in SSLv3. This isn't really a
desirable combination and it's a fuzzy area in the
@@ -1203,7 +1215,7 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp,
must be taken to avoid leaking the information to an attacker
(through, e.g., timing, log files, or other channels.)"
*/
# ifdef USE_IDENTITY_CERTIFICATES
# if defined(USE_IDENTITY_CERTIFICATES) && defined(USE_RSA)
rc = psRsaDecryptPriv(ckepkiPool, &ssl->chosenIdentity->privKey.key.rsa, c,
pubKeyLen, ssl->sec.premaster, ssl->sec.premasterSize,
pkiData);
@@ -1239,8 +1251,8 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp,
SSL_OP_TLS_ROLLBACK_BUG. MatrixSSL doesn't support these
incorrect implementations.
*/
ssl->sec.premaster[0] = ssl->reqMajVer;
ssl->sec.premaster[1] = ssl->reqMinVer;
ssl->sec.premaster[0] = psEncodeVersionMaj(ssl->peerHelloVersion);
ssl->sec.premaster[1] = psEncodeVersionMin(ssl->peerHelloVersion);
if (rc < 0)
{
Memcpy(ssl->sec.premaster + 2, R, sizeof(R));
@@ -1268,6 +1280,12 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp,
}
# endif /* USE_DHE_CIPHER_SUITE */
# ifdef DEBUG_TLS_PREMASTER
psTraceBytes("server premaster_secret",
ssl->sec.premaster,
SSL_HS_RSA_PREMASTER_SIZE);
# endif
/* Now that we've got the premaster secret, derive the various
symmetric keys using it and the client and server random values.
Update the cached session (if found) with the masterSecret and
@@ -1341,6 +1359,7 @@ int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp,
*cp = c;
ssl->decState = SSL_HS_CLIENT_KEY_EXCHANGE;
return PS_SUCCESS;
}
@@ -1369,7 +1388,7 @@ int32 parseCertificateVerify(ssl_t *ssl,
PS_VARIABLE_SET_BUT_UNUSED(rc); /* Note: Only used ifdef USE_ECC. */
# ifdef USE_TLS_1_2
if (ssl->flags & SSL_FLAGS_TLS_1_2)
if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
uint32_t hashSigAlg;
@@ -1461,7 +1480,7 @@ int32 parseCertificateVerify(ssl_t *ssl,
rc = 0;
# ifdef USE_TLS_1_2
if (ssl->flags & SSL_FLAGS_TLS_1_2)
if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
i = psEccDsaVerify(cvpkiPool,
&ssl->sec.cert->publicKey.key.ecc,
@@ -1517,7 +1536,7 @@ int32 parseCertificateVerify(ssl_t *ssl,
# ifdef USE_RSA
# ifdef USE_TLS_1_2
if (ssl->flags & SSL_FLAGS_TLS_1_2)
if (NGTD_VER(ssl, v_tls_with_pkcs15_auth))
{
i = pubRsaDecryptSignedElement(cvpkiPool,
&ssl->sec.cert->publicKey.key.rsa,
@@ -1618,13 +1637,12 @@ int32 parseServerHello(ssl_t *ssl, int32 hsLen, unsigned char **cp,
psTraceErrr("Invalid ssl header version length\n");
return MATRIXSSL_ERROR;
}
ssl->reqMajVer = *c; c++;
ssl->reqMinVer = *c; c++;
psTracePrintProtocolVersion(INDENT_HS_MSG,
ssl->peerHelloVersion = psVerFromEncodingMajMin(*c, *(c+1));
c += 2;
psTracePrintProtocolVersionNew(INDENT_HS_MSG,
"server_version",
ssl->reqMajVer,
ssl->reqMinVer,
1);
ssl->peerHelloVersion,
PS_TRUE);
rc = checkServerHelloVersion(ssl);
if (rc < 0)
@@ -1850,7 +1868,7 @@ int32 parseServerHello(ssl_t *ssl, int32 hsLen, unsigned char **cp,
return rc;
}
# ifdef USE_TLS_1_3
if (!NEGOTIATED_TLS_1_3(ssl))
if (!NGTD_VER(ssl, v_tls_1_3_any))
{
rc = performTls13DowngradeCheck(ssl);
if (rc < 0)
@@ -1858,7 +1876,6 @@ int32 parseServerHello(ssl_t *ssl, int32 hsLen, unsigned char **cp,
return rc;
}
}
# endif /* USE_TLS_1_3 */
}
@@ -1915,38 +1932,6 @@ int32 parseServerHello(ssl_t *ssl, int32 hsLen, unsigned char **cp,
}
# endif /* USE_STATELESS_SESSION_TICKETS */
# if 0 /* TODO moved to extDecode:parseServerHelloExtensions */
# ifdef ENABLE_SECURE_REHANDSHAKES
if (renegotiationExt == 0)
{
# ifdef REQUIRE_SECURE_REHANDSHAKES
ssl->err = SSL_ALERT_HANDSHAKE_FAILURE;
psTraceErrr("Srv doesn't support renegotiationInfo\n");
return MATRIXSSL_ERROR;
# else
if (ssl->secureRenegotiationFlag == PS_TRUE)
{
ssl->err = SSL_ALERT_HANDSHAKE_FAILURE;
psTraceErrr("Srv didn't send renegotiationInfo on re-hndshk\n");
return MATRIXSSL_ERROR;
}
# ifndef ENABLE_INSECURE_REHANDSHAKES
/* This case can only be hit if ENABLE_SECURE is on because otherwise
we wouldn't even have got this far because both would be off. */
if (ssl->secureRenegotiationFlag == PS_FALSE &&
ssl->myVerifyDataLen > 0)
{
ssl->err = SSL_ALERT_HANDSHAKE_FAILURE;
psTraceErrr("Srv attempting insecure renegotiation\n");
return MATRIXSSL_ERROR;
}
# endif /* !ENABLE_SECURE_REHANDSHAKES */
# endif /* REQUIRE_SECURE_REHANDSHAKES */
}
# endif /* ENABLE_SECURE_REHANDSHAKES */
# endif
if (ssl->flags & SSL_FLAGS_RESUMED)
{
if (sslCreateKeys(ssl) < 0)
@@ -1989,24 +1974,11 @@ int32 parseServerKeyExchange(ssl_t *ssl,
unsigned char *c;
# ifdef USE_DHE_CIPHER_SUITE
int32 i;
uint32 pubDhLen, hashSize;
psPool_t *skepkiPool = NULL;
void *pkiData = ssl->userPtr;
int32_t rc, i;
uint32 pubDhLen;
# ifndef USE_ONLY_PSK_CIPHER_SUITE
psDigestContext_t digestCtx;
unsigned char *sigStart = NULL, *sigStop = NULL;
# endif /* USE_ONLY_PSK_CIPHER_SUITE */
# ifdef USE_TLS_1_2
uint32 skeHashSigAlg;
# endif
# if defined(USE_ECC_CIPHER_SUITE)
int32 res;
# endif
# if defined(USE_RSA_CIPHER_SUITE)
unsigned char sigOut[MAX_HASH_SIZE];
# endif
# ifdef USE_ECC_CIPHER_SUITE
const psEccCurve_t *curve;
# endif
@@ -2098,6 +2070,17 @@ int32 parseServerKeyExchange(ssl_t *ssl,
psTraceIntInfo("Error: Could not match EC curve: %d\n", i);
return MATRIXSSL_ERROR;
}
# ifdef USE_SEC_CONFIG
rc = matrixSslCallSecurityCallback(ssl,
secop_ecdh_import_pub,
curve->size * 8,
NULL);
if (rc != PS_SUCCESS)
{
ssl->err = SSL_ALERT_HANDSHAKE_FAILURE;
return rc;
}
# endif /* USE_SEC_CONFIG */
/*
struct {
opaque point <1..2^8-1>;
@@ -2128,6 +2111,11 @@ int32 parseServerKeyExchange(ssl_t *ssl,
ssl->err = SSL_ALERT_DECODE_ERROR;
return MATRIXSSL_ERROR;
}
# ifdef USE_SSL_INFORMATIONAL_TRACE
ssl->peerKeyExKeyType = PS_ECC;
ssl->peerKeyExKeyNBits = curve->size * 8;
# endif
c += i;
sigStop = c;
@@ -2162,7 +2150,17 @@ int32 parseServerKeyExchange(ssl_t *ssl,
psTraceIntInfo("Our minimum: %hu\n", ssl->minDhBits);
return MATRIXSSL_ERROR;
}
# ifdef USE_SEC_CONFIG
rc = matrixSslCallSecurityCallback(ssl,
secop_dh_import_pub,
ssl->sec.dhPLen * 8,
NULL);
if (rc != PS_SUCCESS)
{
ssl->err = SSL_ALERT_HANDSHAKE_FAILURE;
return rc;
}
# endif /* USE_SEC_CONFIG */
ssl->sec.dhP = psMalloc(ssl->hsPool, ssl->sec.dhPLen);
if (ssl->sec.dhP == NULL)
{
@@ -2196,10 +2194,10 @@ int32 parseServerKeyExchange(ssl_t *ssl,
psTraceErrr("Invalid ServerKeyExchange message\n");
return MATRIXSSL_ERROR;
}
/*
/*
The next bit on the wire is the public key. Assign to
the session in structure format
*/
*/
if ((ssl->sec.dhKeyPub = psMalloc(ssl->hsPool, sizeof(psDhKey_t))) == NULL)
{
return MATRIXSSL_ERROR;
@@ -2211,26 +2209,30 @@ int32 parseServerKeyExchange(ssl_t *ssl,
ssl->sec.dhKeyPub = NULL;
return MATRIXSSL_ERROR;
}
# ifdef USE_SSL_INFORMATIONAL_TRACE
ssl->peerKeyExKeyType = PS_DH;
ssl->peerKeyExKeyNBits = ssl->sec.dhPLen * 8;
# endif
c += pubDhLen;
# ifndef USE_ONLY_PSK_CIPHER_SUITE
sigStop = c;
# endif
/*
/*
Key size is now known for premaster storage. The extra byte
is to account for the cases where the pubkey length ends
up being a byte less than the premaster. The premaster size
is adjusted accordingly when the actual secret is generated.
*/
*/
ssl->sec.premasterSize = ssl->sec.dhPLen;
# ifdef USE_PSK_CIPHER_SUITE
if (ssl->flags & SSL_FLAGS_PSK_CIPHER)
{
/*
/*
In the PSK case, the true premaster size is still unknown
but didn't want to change the allocation logic so just
make sure the size is large enough for the additional
PSK and length bytes
*/
*/
ssl->sec.premasterSize += SSL_PSK_MAX_KEY_SIZE + 4;
}
# endif /* USE_PSK_CIPHER_SUITE */
@@ -2242,9 +2244,9 @@ int32 parseServerKeyExchange(ssl_t *ssl,
# ifdef USE_ANON_DH_CIPHER_SUITE
if (ssl->flags & SSL_FLAGS_ANON_CIPHER)
{
/*
/*
In the anonymous case, there is no signature to follow
*/
*/
ssl->hsState = SSL_HS_SERVER_HELLO_DONE;
*cp = c;
ssl->decState = SSL_HS_SERVER_KEY_EXCHANGE;
@@ -2253,342 +2255,33 @@ int32 parseServerKeyExchange(ssl_t *ssl,
# endif /* USE_ANON_DH_CIPHER_SUITE */
# endif /* REQUIRE_DH_PARAMS */
# ifdef USE_ECC_CIPHER_SUITE
}
# endif /* USE_ECC_CIPHER_SUITE */
/*
This layer of authentation is at the key exchange level.
The server has sent a signature of the key material that
the client can validate here.
*/
if ((end - c) < 2)
{
ssl->err = SSL_ALERT_DECODE_ERROR;
psTraceErrr("Invalid ServerKeyExchange message\n");
return MATRIXSSL_ERROR;
}
# ifdef USE_TLS_1_2
hashSize = 0;
if (ssl->flags & SSL_FLAGS_TLS_1_2)
{
skeHashSigAlg = *c << 8; c++;
skeHashSigAlg += *c; c++;
if ((skeHashSigAlg >> 8) == 0x4)
{
hashSize = SHA256_HASH_SIZE;
}
else if ((skeHashSigAlg >> 8) == 0x5)
{
hashSize = SHA384_HASH_SIZE;
}
else if ((skeHashSigAlg >> 8) == 0x6)
{
hashSize = SHA512_HASH_SIZE;
}
else if ((skeHashSigAlg >> 8) == 0x2)
{
hashSize = SHA1_HASH_SIZE;
}
else
{
psTraceIntInfo("Unsupported hashAlg SKE parse: %d\n",
skeHashSigAlg);
return MATRIXSSL_ERROR;
}
}
# endif /* USE_TLS_1_2 */
pubDhLen = *c << 8; c++; /* Reusing variable */
pubDhLen |= *c; c++;
if ((uint32) (end - c) < pubDhLen)
{
ssl->err = SSL_ALERT_DECODE_ERROR;
psTraceErrr("Invalid ServerKeyExchange message\n");
return MATRIXSSL_ERROR;
}
# ifdef USE_RSA_CIPHER_SUITE
if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA)
{
/*
We are using the public key provided by the server during the
CERTIFICATE message. That cert has already been authenticated
by this point so this signature is to ensure that entity is also
the one negotiating keys with us.
*/
# ifdef USE_TLS_1_2
/* TLS 1.2 uses single hashes everywhere */
if (ssl->flags & SSL_FLAGS_TLS_1_2)
{
if (hashSize == SHA256_HASH_SIZE)
{
psSha256PreInit(&digestCtx.sha256);
psSha256Init(&digestCtx.sha256);
psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
psSha256Update(&digestCtx.sha256, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
psSha256Update(&digestCtx.sha256, sigStart,
(uint32) (sigStop - sigStart));
psSha256Final(&digestCtx.sha256, hsMsgHash);
# ifdef USE_SHA384
}
else if (hashSize == SHA384_HASH_SIZE)
{
psSha384PreInit(&digestCtx.sha384);
psSha384Init(&digestCtx.sha384);
psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
psSha384Update(&digestCtx.sha384, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
psSha384Update(&digestCtx.sha384, sigStart,
(uint32) (sigStop - sigStart));
psSha384Final(&digestCtx.sha384, hsMsgHash);
# endif /* USE_SHA384 */
# ifdef USE_SHA512
}
else if (hashSize == SHA512_HASH_SIZE)
{
psSha512PreInit(&digestCtx.sha512);
psSha512Init(&digestCtx.sha512);
psSha512Update(&digestCtx.sha512, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
psSha512Update(&digestCtx.sha512, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
psSha512Update(&digestCtx.sha512, sigStart,
(uint32) (sigStop - sigStart));
psSha512Final(&digestCtx.sha512, hsMsgHash);
# endif /* USE_SHA512 */
# ifdef USE_SHA1
}
else if (hashSize == SHA1_HASH_SIZE)
{
psSha1PreInit(&digestCtx.sha1);
psSha1Init(&digestCtx.sha1);
psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
psSha1Update(&digestCtx.sha1, sigStart,
(uint32) (sigStop - sigStart));
psSha1Final(&digestCtx.sha1, hsMsgHash);
# endif
}
else
{
return MATRIXSSL_ERROR;
}
}
else
{
# ifdef USE_MD5SHA1
psMd5Sha1PreInit(&digestCtx.md5sha1);
psMd5Sha1Init(&digestCtx.md5sha1);
psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
psMd5Sha1Update(&digestCtx.md5sha1, sigStart,
(uint32) (sigStop - sigStart));
psMd5Sha1Final(&digestCtx.md5sha1, hsMsgHash);
# else /* USE_MD5SHA1 */
psTraceErrr("USE_MD5SHA1 required\n");
return MATRIXSSL_ERROR;
# endif /* USE_MD5SHA1 */
}
# else /* USE_TLS_1_2 */
/*
The signature portion is an MD5 and SHA1 concat of the randoms
and the contents of this server key exchange message.
*/
# ifdef USE_MD5SHA1
psMd5Sha1PreInit(&digestCtx.md5sha1);
psMd5Sha1Init(&digestCtx.md5sha1);
psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
psMd5Sha1Update(&digestCtx.md5sha1, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
psMd5Sha1Update(&digestCtx.md5sha1, sigStart,
(uint32) (c - sigStart));
psMd5Sha1Final(&digestCtx.md5sha1, hsMsgHash);
# else
psTraceErrr("USE_MD5SHA1 required\n");
return MATRIXSSL_ERROR;
# endif /* USE_MD5SHA1 */
# endif /* USE_TLS_1_2 */
# ifdef USE_TLS_1_2
if (ssl->flags & SSL_FLAGS_TLS_1_2)
{
/* TLS 1.2 doesn't just sign the straight hash so we can't
pass it through the normal public decryption becuase
that expects an output length of a known size. These
signatures are done on elements with some ASN.1
wrapping so a special decryption with parse is needed */
if ((i = pubRsaDecryptSignedElement(skepkiPool,
&ssl->sec.cert->publicKey.key.rsa, c, pubDhLen, sigOut,
hashSize, pkiData)) < 0)
{
psTraceErrr("Can't decrypt serverKeyExchange sig\n");
ssl->err = SSL_ALERT_BAD_CERTIFICATE;
return MATRIXSSL_ERROR;
}
}
else
{
hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE;
if ((i = psRsaDecryptPub(skepkiPool,
&ssl->sec.cert->publicKey.key.rsa, c, pubDhLen, sigOut,
hashSize, pkiData)) < 0)
{
psTraceErrr("Can't decrypt server key exchange sig\n");
ssl->err = SSL_ALERT_BAD_CERTIFICATE;
return MATRIXSSL_ERROR;
}
}
# else /* ! USE_TLS_1_2 */
hashSize = MD5_HASH_SIZE + SHA1_HASH_SIZE;
if ((i = psRsaDecryptPub(skepkiPool, &ssl->sec.cert->publicKey.key.rsa,
c, pubDhLen, sigOut, hashSize, pkiData)) < 0)
{
psTraceErrr("Unable to decrypt server key exchange sig\n");
ssl->err = SSL_ALERT_BAD_CERTIFICATE;
return MATRIXSSL_ERROR;
}
# endif /* USE_TLS_1_2 */
/* Now have hash from the server. Create ours and check match */
c += pubDhLen;
if (memcmpct(sigOut, hsMsgHash, hashSize) != 0)
{
psTraceErrr("Fail to verify serverKeyExchange sig\n");
ssl->err = SSL_ALERT_BAD_CERTIFICATE;
return MATRIXSSL_ERROR;
}
}
# endif /* USE_RSA_CIPHER_SUITE */
# ifdef USE_ECC_CIPHER_SUITE
if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA)
{
/*
RFC4492: The default hash function is SHA-1, and sha_size is 20.
*/
# ifdef USE_TLS_1_2
if (ssl->flags & SSL_FLAGS_TLS_1_2 &&
(hashSize == SHA256_HASH_SIZE))
{
psSha256PreInit(&digestCtx.sha256);
psSha256Init(&digestCtx.sha256);
psSha256Update(&digestCtx.sha256, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
psSha256Update(&digestCtx.sha256, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
psSha256Update(&digestCtx.sha256, sigStart,
(int32) (sigStop - sigStart));
psSha256Final(&digestCtx.sha256, hsMsgHash);
# ifdef USE_SHA384
}
else if (ssl->flags & SSL_FLAGS_TLS_1_2 &&
(hashSize == SHA384_HASH_SIZE))
{
psSha384PreInit(&digestCtx.sha384);
psSha384Init(&digestCtx.sha384);
psSha384Update(&digestCtx.sha384, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
psSha384Update(&digestCtx.sha384, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
psSha384Update(&digestCtx.sha384, sigStart,
(int32) (sigStop - sigStart));
psSha384Final(&digestCtx.sha384, hsMsgHash);
# endif
# ifdef USE_SHA512
}
else if (hashSize == SHA512_HASH_SIZE)
{
psSha512PreInit(&digestCtx.sha512);
psSha512Init(&digestCtx.sha512);
psSha512Update(&digestCtx.sha512, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
psSha512Update(&digestCtx.sha512, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
psSha512Update(&digestCtx.sha512, sigStart,
(uint32) (sigStop - sigStart));
psSha512Final(&digestCtx.sha512, hsMsgHash);
# endif /* USE_SHA512 */
# ifdef USE_SHA1
}
else if (ssl->minVer < TLS_1_2_MIN_VER ||
# ifdef USE_DTLS
ssl->minVer == DTLS_MIN_VER ||
# endif
((ssl->flags & SSL_FLAGS_TLS_1_2) &&
(hashSize == SHA1_HASH_SIZE)))
{
hashSize = SHA1_HASH_SIZE;
psSha1PreInit(&digestCtx.sha1);
psSha1Init(&digestCtx.sha1);
psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
psSha1Update(&digestCtx.sha1, sigStart,
(int32) (sigStop - sigStart));
psSha1Final(&digestCtx.sha1, hsMsgHash);
# endif
}
else
{
return MATRIXSSL_ERROR;
}
# else /* USE_TLS_1_2 */
hashSize = SHA1_HASH_SIZE;
psSha1Init(&digestCtx.sha1);
psSha1Update(&digestCtx.sha1, ssl->sec.clientRandom,
SSL_HS_RANDOM_SIZE);
psSha1Update(&digestCtx.sha1, ssl->sec.serverRandom,
SSL_HS_RANDOM_SIZE);
psSha1Update(&digestCtx.sha1, sigStart,
(int32) (sigStop - sigStart));
psSha1Final(&digestCtx.sha1, hsMsgHash);
# endif /* USE_TLS_1_2 */
i = 0;
res = psEccDsaVerify(skepkiPool,
&ssl->sec.cert->publicKey.key.ecc,
hsMsgHash, hashSize,
c, pubDhLen,
&i, pkiData);
if (res != PS_SUCCESS)
{
psTraceErrr("ECDSA signature validation failed\n");
ssl->err = SSL_ALERT_BAD_CERTIFICATE;
return MATRIXSSL_ERROR;
}
c += pubDhLen;
/*
The validation code comes out of the final parameter
*/
if (i != 1)
{
psTraceErrr("Can't verify serverKeyExchange sig\n");
ssl->err = SSL_ALERT_BAD_CERTIFICATE;
return MATRIXSSL_ERROR;
}
}
# endif /* USE_ECC_CIPHER_SUITE */
/* We are still within if (ssl->flags & SSL_FLAGS_DHE_KEY_EX). */
/*
This layer of authentation is at the key exchange level.
The server has sent a signature of the key material that
the client can validate here.
*/
rc = tlsVerify(ssl,
sigStart,
sigStop - sigStart,
c,
end,
&ssl->sec.cert->publicKey,
NULL);
if (rc < 0)
{
return rc;
}
/* Signature OK. */
c += rc; /* tlsVerify returns number of consumed octets. */
ssl->hsState = SSL_HS_SERVER_HELLO_DONE;
}
} /* endif (ssl->flags & SSL_FLAGS_DHE_KEY_EX) */
# endif /* USE_DHE_CIPHER_SUITE */
# ifdef USE_PSK_CIPHER_SUITE
/*
Entry point for basic PSK ciphers (not DHE or RSA) parsing SKE message
@@ -2858,7 +2551,7 @@ int32 parseCertificateRequest(ssl_t *ssl,
#define GETSHORT(buf) (unsigned short)((buf)[0] << 8) | ((buf)[1])
/* TLS 1.2 specifies signature algorithms */
if (ssl->flags & SSL_FLAGS_TLS_1_2)
if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
size_t len, nSigAlg = 0;
/* supported_signature_algorithms field
@@ -3006,7 +2699,7 @@ int32 parseFinished(ssl_t *ssl, int32 hsLen,
Compare the message to the value we calculated at the beginning of
this function. */
#ifdef USE_TLS
if (ssl->flags & SSL_FLAGS_TLS)
if (!NGTD_VER(ssl, v_ssl_3_0))
{
if (hsLen != TLS_HS_FINISHED_SIZE)
{
@@ -3116,7 +2809,7 @@ int32 parseFinished(ssl_t *ssl, int32 hsLen,
#endif /* !USE_ONLY_PSK_CIPHER_SUITE */
#ifdef USE_DTLS
if (ssl->flags & SSL_FLAGS_DTLS)
if (ACTV_VER(ssl, v_dtls_any))
{
/* A successful parse of the FINISHED message means the record sequence
numbers have been reset so we need to clear out our replay detector */
@@ -3216,7 +2909,7 @@ int32 parseCertificate(ssl_t *ssl, unsigned char **cp, unsigned char *end)
goto STRAIGHT_TO_USER_CALLBACK;
}
# endif
if (ssl->majVer == SSL3_MAJ_VER && ssl->minVer == SSL3_MIN_VER)
if (NGTD_VER(ssl, v_ssl_3_0))
{
ssl->err = SSL_ALERT_NO_CERTIFICATE;
}
@@ -3494,6 +3187,21 @@ RESUME_VALIDATE_CERTS:
cert = cert->next;
}
# ifdef USE_SSL_INFORMATIONAL_TRACE
/* The peer cert will be freed as soon as it is no longer needed,
so store information about the public key, to be logged
later in matrixSslPrintHSDetails. */
ssl->peerAuthKeyType = ssl->sec.cert->publicKey.type;
if (ssl->peerAuthKeyType == PS_RSA)
{
ssl->peerAuthKeyNBits = ssl->sec.cert->publicKey.keysize * 8;
}
else
{
ssl->peerAuthKeyNBits = ssl->sec.cert->publicKey.key.ecc.curve->size * 8;
}
# endif /* USE_SSL_INFORMATIONAL_TRACE */
/* The last thing we want to check before passing the certificates to
the user callback is the case in which we don't have any
CA files loaded but we were passed a valid chain that was