diff --git a/README.html b/README.html
index bd8fe50..e7dfd6e 100644
--- a/README.html
+++ b/README.html
@@ -11,7 +11,8 @@
Overview
-MatrixSSL has been continuously maintained since 2002. It is the first open source small footprint SSL stack. Until recently, releases were tracked on http://freecode.com/projects/matrixssl
+MatrixSSL has been continuously maintained since 2002. It is the first open source small footprint SSL stack. Until recently, releases were tracked on http://freecode.com/projects/matrixssl
+
MatrixSSL is an embedded SSL and TLS implementation designed for small footprint IoT devices requiring low overhead per connection. It includes client and server support through TLS 1.3, mutual authentication, session resumption, and implementations of RSA, ECC, AES, SHA1, SHA-256, ChaCha20-Poly1305 and more. The source is well documented and contains portability layers for additional operating systems, cipher suites, and cryptography providers.
diff --git a/apps/dtls/dtlsClient.c b/apps/dtls/dtlsClient.c
index ef12a69..1193535 100644
--- a/apps/dtls/dtlsClient.c
+++ b/apps/dtls/dtlsClient.c
@@ -157,7 +157,7 @@ static int32 dtlsClientConnection(sslKeys_t *keys, sslSessionId_t *sid)
# endif /* DTLS_TEST_LOST_CIPHERSPEC_CHANGE_REHANDSHAKE */
Memset(&options, 0x0, sizeof(sslSessOpts_t));
- options.versionFlag = SSL_FLAGS_DTLS;
+ options.versionFlag = SSL_FLAGS_DTLS | SSL_FLAGS_TLS_1_2;
options.trustedCAindication = 1;
diff --git a/apps/dtls/dtlsServer.c b/apps/dtls/dtlsServer.c
index a7d3085..a89a850 100644
--- a/apps/dtls/dtlsServer.c
+++ b/apps/dtls/dtlsServer.c
@@ -868,6 +868,10 @@ int main(int argc, char **argv)
{
Memset(&options, 0x0, sizeof(sslSessOpts_t));
options.versionFlag = SSL_FLAGS_DTLS;
+ if (COMPILED_IN_VER(v_dtls_1_2))
+ {
+ options.versionFlag |= SSL_FLAGS_TLS_1_2;
+ }
options.truncHmac = -1;
if (matrixSslNewServerSession(&ssl, keys,
diff --git a/apps/ssl/client.c b/apps/ssl/client.c
index 3122a09..8f0275e 100644
--- a/apps/ssl/client.c
+++ b/apps/ssl/client.c
@@ -220,7 +220,7 @@ static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid,
uint16_t groups[TLS_1_3_MAX_GROUPS] = {0};
# endif
uint16_t sigAlgs[TLS_MAX_SIGNATURE_ALGORITHMS] = {0};
- int32_t supportedVersions[TLS_MAX_SUPPORTED_VERSIONS] = {0};
+ psProtocolVersion_t supportedVersions[TLS_MAX_SUPPORTED_VERSIONS] = {0};
psSize_t i;
# ifdef USE_ALPN
@@ -341,6 +341,7 @@ static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid,
while (supportedVersion)
{
supportedVersions[i] = atoi((char* )supportedVersion->item);
+ supportedVersions[i] = DIGIT_TO_VER(supportedVersions[i]);
supportedVersion = supportedVersion->next;
i++;
}
@@ -352,7 +353,6 @@ static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid,
Printf("matrixSslSessOptsSetClientTlsVersions failed\n");
goto L_CLOSE_ERR;
}
-
}
else if (g_version_range_set)
{
@@ -366,7 +366,7 @@ static int32 httpsClientConnection(sslKeys_t *keys, sslSessionId_t *sid,
}
else if (g_version != 0)
{
- options.versionFlag = tlsMinVerToVersionFlag(g_version);
+ options.versionFlag = psVerToFlag(DIGIT_TO_VER(g_version));
}
options.userPtr = keys;
@@ -962,6 +962,8 @@ static void usage(void)
" rsa (for RSA keys)\n"
" ec (for EC keys ECDSA signature)\n"
" ecrsa (for EC keys with RSA signature)\n"
+ "--psk \n"
+ " - Load test PSKs.\n"
"--groups \n"
" - Supported groups.\n"
" For example: secp256r1:secp384r1\n"
@@ -1220,8 +1222,9 @@ static int32 process_cmd_options(int32 argc, char **argv)
case 'V':
/* Single version. */
version = atoi(optarg);
- if (!matrixSslTlsVersionRangeSupported(version,
- version))
+ if (!matrixSslTlsVersionRangeSupported(
+ DIGIT_TO_VER(version),
+ DIGIT_TO_VER(version)))
{
Printf("Invalid version: %d\n", version);
return -1;
@@ -1273,10 +1276,11 @@ static int32 process_cmd_options(int32 argc, char **argv)
optarg);
return -1;
}
- g_min_version = atoi((char *)versionRangeList->item);
- g_max_version = atoi((char *)versionRangeList->next->item);
+ g_min_version = DIGIT_TO_VER(atoi((char *)versionRangeList->item));
+ g_max_version = DIGIT_TO_VER(atoi((char *)versionRangeList->next->item));
psFreeList(versionRangeList, NULL);
- if (!matrixSslTlsVersionRangeSupported(g_min_version,
+ if (!matrixSslTlsVersionRangeSupported(
+ g_min_version,
g_max_version))
{
Printf("Unsupported version range: %s\n",
diff --git a/apps/ssl/server.c b/apps/ssl/server.c
index dcc3999..059b515 100644
--- a/apps/ssl/server.c
+++ b/apps/ssl/server.c
@@ -116,8 +116,8 @@ static int g_require_client_auth;
static DLListEntry g_conns;
static int32 g_exitFlag;
static int g_port;
-static int g_min_version;
-static int g_max_version;
+static psProtocolVersion_t g_min_version;
+static psProtocolVersion_t g_max_version;
static int g_use_default_versions;
static int g_disabledCiphers;
static uint16_t g_disabledCipher[SSL_MAX_DISABLED_CIPHERS];
@@ -274,9 +274,10 @@ void SNIcallback(void *ssl, char *hostname, int32 hostnameLen,
int32 setProtocolVersions(sslSessOpts_t *options)
{
psList_t *supportedVersion;
- int32_t supportedVersions[TLS_MAX_SUPPORTED_VERSIONS] = {0};
+ psProtocolVersion_t supportedVersions[TLS_MAX_SUPPORTED_VERSIONS] = {0};
psSize_t i;
int32 rc;
+
if (g_supportedVersionsList)
{
supportedVersion = g_supportedVersionsList;
@@ -284,6 +285,7 @@ int32 setProtocolVersions(sslSessOpts_t *options)
while (supportedVersion)
{
supportedVersions[i] = atoi((char* )supportedVersion->item);
+ supportedVersions[i] = DIGIT_TO_VER(supportedVersions[i]);
supportedVersion = supportedVersion->next;
i++;
}
@@ -481,6 +483,7 @@ static int32 selectLoop(sslKeys_t *keys, SOCKET lfd)
if (rc < 0)
{
Printf("matrixSslSessOptsSetKeyExGroups failed\n");
+ close(fd);
return rc;
}
}
@@ -500,6 +503,7 @@ static int32 selectLoop(sslKeys_t *keys, SOCKET lfd)
if (rc < 0)
{
Printf("matrixSslSessOptsSetSigAlgsCert failed\n");
+ close(fd);
return rc;
}
}
@@ -514,6 +518,7 @@ static int32 selectLoop(sslKeys_t *keys, SOCKET lfd)
if (sigAlgs[i] == 0)
{
Printf("Invalid signature algorithm parameter\n");
+ close(fd);
return PS_ARG_FAIL;
}
sigAlg = sigAlg->next;
@@ -525,6 +530,7 @@ static int32 selectLoop(sslKeys_t *keys, SOCKET lfd)
if (rc < 0)
{
Printf("matrixSslSessOptsSetSigAlgs failed\n");
+ close(fd);
return rc;
}
}
@@ -1149,9 +1155,10 @@ static int32_t parse_cipher_list(char *cipherListString,
encountered OR a request for help is seen (i.e. '-h' option). */
static int32 process_cmd_options(int32 argc, char **argv)
{
- int optionChar, str_len, version, numCiphers;
+ int optionChar, str_len, numCiphers;
char *cipherListString;
psList_t *versionRangeList;
+ psProtocolVersion_t version;
/* Start with all options zeroized. */
Memset(g_keyfilePath, 0, MAX_KEYFILE_PATH);
@@ -1163,7 +1170,7 @@ static int32 process_cmd_options(int32 argc, char **argv)
Memset(g_password, 0, MAX_PASSWORD_LEN);
g_port = HTTPS_PORT;
- g_min_version = g_max_version = 3;
+ g_min_version = g_max_version = v_tls_1_2;
g_disabledCiphers = 0;
opterr = 0;
@@ -1330,7 +1337,7 @@ static int32 process_cmd_options(int32 argc, char **argv)
case 'v':
/* Single version. */
- version = atoi(optarg);
+ version = DIGIT_TO_VER(atoi(optarg));
if (!matrixSslTlsVersionRangeSupported(version,
version))
{
@@ -1346,10 +1353,11 @@ static int32 process_cmd_options(int32 argc, char **argv)
{
Printf("Invalid version range string: %s\n",
optarg);
+ psFreeList(versionRangeList, NULL);
return -1;
}
- g_min_version = atoi((char *)versionRangeList->item);
- g_max_version = atoi((char *)versionRangeList->next->item);
+ g_min_version = DIGIT_TO_VER(atoi((char *)versionRangeList->item));
+ g_max_version = DIGIT_TO_VER(atoi((char *)versionRangeList->next->item));
psFreeList(versionRangeList, NULL);
if (!matrixSslTlsVersionRangeSupported(g_min_version,
g_max_version))
@@ -1447,6 +1455,7 @@ int32 main(int32 argc, char **argv)
if (0 != process_cmd_options(argc, argv))
{
+ matrixSslDeleteKeys(keys);
usage();
return 0;
}
@@ -1467,6 +1476,7 @@ int32 main(int32 argc, char **argv)
|| psGetPrngLocked(sessTicketName, sizeof(sessTicketName), NULL) < 0)
{
psTrace("Error generating session ticket encryption key\n");
+ matrixSslDeleteKeys(keys);
return EXIT_FAILURE;
}
if (matrixSslLoadSessionTicketKeys(keys, sessTicketName,
diff --git a/configs/default/cryptoConfig.h b/configs/default/cryptoConfig.h
index aa08c14..0e0944c 100644
--- a/configs/default/cryptoConfig.h
+++ b/configs/default/cryptoConfig.h
@@ -44,7 +44,7 @@
/* #define USE_CRYPTO_TRACE */
# ifdef DEBUG
-/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
+/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
# endif
/******************************************************************************/
@@ -179,7 +179,7 @@
SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting
only with newer certificates.
*/
-/* #define USE_SHA224 *//**< @note Used only for cert signature */
+/* #define USE_SHA224 *//**< @note Used only for cert signature */
# define USE_SHA256/**< @note Required for TLS 1.2 and above */
# define USE_HMAC_SHA256
# define USE_SHA384/**< @pre USE_SHA512 */
@@ -274,7 +274,7 @@
# ifdef USE_OCSP
# define USE_OCSP_RESPONSE
# define USE_OCSP_REQUEST
-# elif defined(USE_X509) && defined(USE_SHA1)
+# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE)
/**
Enable parsing and writing of OCSP responses. This is enough
to support OCSP stapling.
@@ -298,4 +298,3 @@
#endif /* _h_PS_CRYPTOCONFIG */
/******************************************************************************/
-
diff --git a/configs/default/matrixsslConfig.h b/configs/default/matrixsslConfig.h
index 472b4b1..6c7cea3 100644
--- a/configs/default/matrixsslConfig.h
+++ b/configs/default/matrixsslConfig.h
@@ -108,6 +108,7 @@ extern "C" {
/* TLS 1.2 ciphers */
/* #define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */
/* #define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */
+/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */
/** Non-Ephemeral RSA keys/certificates */
# define USE_TLS_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHALL */
@@ -181,7 +182,7 @@ extern "C" {
Note: The RC4 cipher suites below need to disabled according to RFC 7465.
*/
/* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */
-
+
/******************************************************************************/
/**
Ephemeral key cache support.
@@ -420,7 +421,7 @@ extern "C" {
# define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
# define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
-/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
+/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
# endif
# ifdef __cplusplus
@@ -429,4 +430,3 @@ extern "C" {
#endif /* _h_MATRIXCONFIG */
/******************************************************************************/
-
diff --git a/configs/noecc/cryptoConfig.h b/configs/noecc/cryptoConfig.h
index 30dbf7e..032a814 100644
--- a/configs/noecc/cryptoConfig.h
+++ b/configs/noecc/cryptoConfig.h
@@ -44,7 +44,7 @@
/* #define USE_CRYPTO_TRACE */
# ifdef DEBUG
-/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
+/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
# endif
/******************************************************************************/
@@ -179,7 +179,7 @@
SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting
only with newer certificates.
*/
-/* #define USE_SHA224 *//**< @note Used only for cert signature */
+/* #define USE_SHA224 *//**< @note Used only for cert signature */
# define USE_SHA256/**< @note Required for TLS 1.2 and above */
# define USE_HMAC_SHA256
# define USE_SHA384/**< @pre USE_SHA512 */
@@ -274,7 +274,7 @@
# ifdef USE_OCSP
# define USE_OCSP_RESPONSE
# define USE_OCSP_REQUEST
-# elif defined(USE_X509) && defined(USE_SHA1)
+# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE)
/**
Enable parsing and writing of OCSP responses. This is enough
to support OCSP stapling.
@@ -298,4 +298,3 @@
#endif /* _h_PS_CRYPTOCONFIG */
/******************************************************************************/
-
diff --git a/configs/noecc/matrixsslConfig.h b/configs/noecc/matrixsslConfig.h
index 29e697b..1268ea1 100644
--- a/configs/noecc/matrixsslConfig.h
+++ b/configs/noecc/matrixsslConfig.h
@@ -108,6 +108,7 @@ extern "C" {
/* TLS 1.2 ciphers */
# define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
# define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */
/** Non-Ephemeral RSA keys/certificates */
# define USE_TLS_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHALL */
@@ -181,7 +182,7 @@ extern "C" {
Note: The RC4 cipher suites below need to disabled according to RFC 7465.
*/
/* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */
-
+
/******************************************************************************/
/**
Ephemeral key cache support.
@@ -420,7 +421,7 @@ extern "C" {
# define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
# define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
-/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
+/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
# endif
# ifdef __cplusplus
@@ -429,4 +430,3 @@ extern "C" {
#endif /* _h_MATRIXCONFIG */
/******************************************************************************/
-
diff --git a/configs/psk/cryptoConfig.h b/configs/psk/cryptoConfig.h
index 6f7c767..11798ec 100644
--- a/configs/psk/cryptoConfig.h
+++ b/configs/psk/cryptoConfig.h
@@ -44,7 +44,7 @@
/* #define USE_CRYPTO_TRACE */
# ifdef DEBUG
-/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
+/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
# endif
/******************************************************************************/
@@ -109,7 +109,7 @@
@see http://csrc.nist.gov/groups/ST/toolkit/documents/dss/NISTReCur.pdf
*/
# ifdef USE_ECC
-/* #define USE_SECP192R1 *//**< @security FIPS allowed for sig ver only. */
+/* #define USE_SECP192R1 *//**< @security FIPS allowed for sig ver only. */
/* #define USE_SECP224R1 */
/* #define USE_SECP256R1 *//**< @security NIST_SHALL */
/* #define USE_SECP384R1 *//**< @security NIST_SHALL */
@@ -179,10 +179,10 @@
SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting
only with newer certificates.
*/
-/* #define USE_SHA224 *//**< @note Used only for cert signature */
+/* #define USE_SHA224 *//**< @note Used only for cert signature */
# define USE_SHA256/**< @note Required for TLS 1.2 and above */
# define USE_HMAC_SHA256
-/* #define USE_SHA384 *//**< @pre USE_SHA512 */
+/* #define USE_SHA384 *//**< @pre USE_SHA512 */
/* #define USE_HMAC_SHA384 */
/* #define USE_SHA512 */
@@ -198,7 +198,7 @@
@note ENABLE_MD5_SIGNED_CERTS can additionally be configured below.
*/
/* #define USE_MD5 */
-/* #define USE_MD5SHA1 *//* Required for < TLS 1.2 Handshake */
+/* #define USE_MD5SHA1 *//* Required for < TLS 1.2 Handshake */
/* #define USE_HMAC_MD5 */
/**
@@ -274,7 +274,7 @@
# ifdef USE_OCSP
# define USE_OCSP_RESPONSE
# define USE_OCSP_REQUEST
-# elif defined(USE_X509) && defined(USE_SHA1)
+# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE)
/**
Enable parsing and writing of OCSP responses. This is enough
to support OCSP stapling.
@@ -287,15 +287,14 @@
Various PKCS standards support
*/
/* #define USE_PRIVATE_KEY_PARSING */
-/* #define USE_PKCS5 *//**< v2.0 PBKDF encrypted priv keys. @pre USE_3DES */
+/* #define USE_PKCS5 *//**< v2.0 PBKDF encrypted priv keys. @pre USE_3DES */
/**< Enable PBKDF1 in priv key PEM encryption. @pre USE_PKCS5 and @pre USE_MD5. @security Not recommended. */
/* #define USE_PBKDF1 */
-/* #define USE_PKCS8 *//* Alternative private key storage format */
-/* #define USE_PKCS12 *//**< @pre USE_PKCS8 */
-/* #define USE_PKCS1_OAEP *//* OAEP padding algorithm */
-/* #define USE_PKCS1_PSS *//* PSS padding algorithm */
+/* #define USE_PKCS8 *//* Alternative private key storage format */
+/* #define USE_PKCS12 *//**< @pre USE_PKCS8 */
+/* #define USE_PKCS1_OAEP *//* OAEP padding algorithm */
+/* #define USE_PKCS1_PSS *//* PSS padding algorithm */
#endif /* _h_PS_CRYPTOCONFIG */
/******************************************************************************/
-
diff --git a/configs/psk/matrixsslConfig.h b/configs/psk/matrixsslConfig.h
index 008677d..b7cf2ed 100644
--- a/configs/psk/matrixsslConfig.h
+++ b/configs/psk/matrixsslConfig.h
@@ -108,6 +108,7 @@ extern "C" {
/* TLS 1.2 ciphers */
/* #define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */
/* #define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */
+/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */
/** Non-Ephemeral RSA keys/certificates */
/* #define USE_TLS_RSA_WITH_AES_128_CBC_SHA *//**< @security NIST_SHALL */
@@ -181,7 +182,7 @@ extern "C" {
Note: The RC4 cipher suites below need to disabled according to RFC 7465.
*/
/* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */
-
+
/******************************************************************************/
/**
Ephemeral key cache support.
@@ -420,7 +421,7 @@ extern "C" {
# define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
# define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
-/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
+/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
# endif
# ifdef __cplusplus
@@ -429,4 +430,3 @@ extern "C" {
#endif /* _h_MATRIXCONFIG */
/******************************************************************************/
-
diff --git a/configs/rsaonly/cryptoConfig.h b/configs/rsaonly/cryptoConfig.h
index 8b4b4ba..7066a93 100644
--- a/configs/rsaonly/cryptoConfig.h
+++ b/configs/rsaonly/cryptoConfig.h
@@ -44,7 +44,7 @@
/* #define USE_CRYPTO_TRACE */
# ifdef DEBUG
-/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
+/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
# endif
/******************************************************************************/
@@ -179,7 +179,7 @@
SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting
only with newer certificates.
*/
-/* #define USE_SHA224 *//**< @note Used only for cert signature */
+/* #define USE_SHA224 *//**< @note Used only for cert signature */
# define USE_SHA256/**< @note Required for TLS 1.2 and above */
# define USE_HMAC_SHA256
# define USE_SHA384/**< @pre USE_SHA512 */
@@ -274,7 +274,7 @@
# ifdef USE_OCSP
# define USE_OCSP_RESPONSE
# define USE_OCSP_REQUEST
-# elif defined(USE_X509) && defined(USE_SHA1)
+# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE)
/**
Enable parsing and writing of OCSP responses. This is enough
to support OCSP stapling.
@@ -298,4 +298,3 @@
#endif /* _h_PS_CRYPTOCONFIG */
/******************************************************************************/
-
diff --git a/configs/rsaonly/matrixsslConfig.h b/configs/rsaonly/matrixsslConfig.h
index 9b6e612..303a1b7 100644
--- a/configs/rsaonly/matrixsslConfig.h
+++ b/configs/rsaonly/matrixsslConfig.h
@@ -108,6 +108,7 @@ extern "C" {
/* TLS 1.2 ciphers */
/* #define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */
/* #define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */
+/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */
/** Non-Ephemeral RSA keys/certificates */
# define USE_TLS_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHALL */
@@ -181,7 +182,7 @@ extern "C" {
Note: The RC4 cipher suites below need to disabled according to RFC 7465.
*/
/* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */
-
+
/******************************************************************************/
/**
Ephemeral key cache support.
@@ -420,7 +421,7 @@ extern "C" {
# define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
# define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
-/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
+/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
# endif
# ifdef __cplusplus
@@ -429,4 +430,3 @@ extern "C" {
#endif /* _h_MATRIXCONFIG */
/******************************************************************************/
-
diff --git a/configs/tls/cryptoConfig.h b/configs/tls/cryptoConfig.h
index dd3b3b7..13fee06 100644
--- a/configs/tls/cryptoConfig.h
+++ b/configs/tls/cryptoConfig.h
@@ -44,7 +44,7 @@
/* #define USE_CRYPTO_TRACE */
# ifdef DEBUG
-/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
+/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
# endif
/******************************************************************************/
@@ -179,7 +179,7 @@
SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting
only with newer certificates.
*/
-/* #define USE_SHA224 *//**< @note Used only for cert signature */
+/* #define USE_SHA224 *//**< @note Used only for cert signature */
# define USE_SHA256/**< @note Required for TLS 1.2 and above */
# define USE_HMAC_SHA256
# define USE_SHA384/**< @pre USE_SHA512 */
@@ -274,7 +274,7 @@
# ifdef USE_OCSP
# define USE_OCSP_RESPONSE
# define USE_OCSP_REQUEST
-# elif defined(USE_X509) && defined(USE_SHA1)
+# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE)
/**
Enable parsing and writing of OCSP responses. This is enough
to support OCSP stapling.
@@ -298,4 +298,3 @@
#endif /* _h_PS_CRYPTOCONFIG */
/******************************************************************************/
-
diff --git a/configs/tls/matrixsslConfig.h b/configs/tls/matrixsslConfig.h
index 472b4b1..6c7cea3 100644
--- a/configs/tls/matrixsslConfig.h
+++ b/configs/tls/matrixsslConfig.h
@@ -108,6 +108,7 @@ extern "C" {
/* TLS 1.2 ciphers */
/* #define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */
/* #define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */
+/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */
/** Non-Ephemeral RSA keys/certificates */
# define USE_TLS_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHALL */
@@ -181,7 +182,7 @@ extern "C" {
Note: The RC4 cipher suites below need to disabled according to RFC 7465.
*/
/* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */
-
+
/******************************************************************************/
/**
Ephemeral key cache support.
@@ -420,7 +421,7 @@ extern "C" {
# define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
# define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
-/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
+/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
# endif
# ifdef __cplusplus
@@ -429,4 +430,3 @@ extern "C" {
#endif /* _h_MATRIXCONFIG */
/******************************************************************************/
-
diff --git a/configs/tls13/cryptoConfig.h b/configs/tls13/cryptoConfig.h
index aa08c14..0e0944c 100644
--- a/configs/tls13/cryptoConfig.h
+++ b/configs/tls13/cryptoConfig.h
@@ -44,7 +44,7 @@
/* #define USE_CRYPTO_TRACE */
# ifdef DEBUG
-/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
+/* #define CRYPTO_ASSERT *//**< Extra sanity asserts */
# endif
/******************************************************************************/
@@ -179,7 +179,7 @@
SHA1 using TLS 1.2 and SHA2 based ciphersuites, and interacting
only with newer certificates.
*/
-/* #define USE_SHA224 *//**< @note Used only for cert signature */
+/* #define USE_SHA224 *//**< @note Used only for cert signature */
# define USE_SHA256/**< @note Required for TLS 1.2 and above */
# define USE_HMAC_SHA256
# define USE_SHA384/**< @pre USE_SHA512 */
@@ -274,7 +274,7 @@
# ifdef USE_OCSP
# define USE_OCSP_RESPONSE
# define USE_OCSP_REQUEST
-# elif defined(USE_X509) && defined(USE_SHA1)
+# elif defined(USE_X509) && defined(USE_SHA1) && defined(USE_CERT_PARSE)
/**
Enable parsing and writing of OCSP responses. This is enough
to support OCSP stapling.
@@ -298,4 +298,3 @@
#endif /* _h_PS_CRYPTOCONFIG */
/******************************************************************************/
-
diff --git a/configs/tls13/matrixsslConfig.h b/configs/tls13/matrixsslConfig.h
index 472b4b1..6c7cea3 100644
--- a/configs/tls13/matrixsslConfig.h
+++ b/configs/tls13/matrixsslConfig.h
@@ -108,6 +108,7 @@ extern "C" {
/* TLS 1.2 ciphers */
/* #define USE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 */
/* #define USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */
+/* #define USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 */
/** Non-Ephemeral RSA keys/certificates */
# define USE_TLS_RSA_WITH_AES_128_CBC_SHA/**< @security NIST_SHALL */
@@ -181,7 +182,7 @@ extern "C" {
Note: The RC4 cipher suites below need to disabled according to RFC 7465.
*/
/* #define USE_SSL_RSA_WITH_RC4_128_SHA *//**< @security NIST_SHALL_NOT */
-
+
/******************************************************************************/
/**
Ephemeral key cache support.
@@ -420,7 +421,7 @@ extern "C" {
# define SSL_DEFAULT_IN_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
# define SSL_DEFAULT_OUT_BUF_SIZE DTLS_PMTU /* See PMTU comments above */
-/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
+/* #define DTLS_SEND_RECORDS_INDIVIDUALLY *//* Max one record per datagram */
# endif
# ifdef __cplusplus
@@ -429,4 +430,3 @@ extern "C" {
#endif /* _h_MATRIXCONFIG */
/******************************************************************************/
-
diff --git a/core/makefiles/get_CCARCH.mk b/core/makefiles/get_CCARCH.mk
index 60b0a9e..5c8df9a 100644
--- a/core/makefiles/get_CCARCH.mk
+++ b/core/makefiles/get_CCARCH.mk
@@ -10,8 +10,10 @@ ifeq '$(CCARCH)' ''
# some versions of GCC)
CCARCH:=$(shell $(CLEAN_ENV) $(CC) -dumpmachine)
+ARM_ARCH ?= armv7-a
+
ifeq '$(CCARCH)' ''
-$(error Unable to determine compiler architecture.
+$(error Unable to determine compiler architecture.)
$(CC) $(CFLAGS_ARCHITECTURE_VARIANT) $(FLAGS_ARCHITECTURE_VARIANT) -print-multiarch or $(CC) -v or $(CC) -dumpmachine does not work. Please, provide CCARCH manually via an environment variable.)
endif
endif
diff --git a/core/makefiles/platform_specific.mk b/core/makefiles/platform_specific.mk
index 8d4aabc..df906c0 100644
--- a/core/makefiles/platform_specific.mk
+++ b/core/makefiles/platform_specific.mk
@@ -19,7 +19,7 @@ ifneq (,$(NEON_VARIANT))
CFLAGS_ENABLE_NEON=-march=armv7-a -mfpu=neon
else
# No neon mentioned. Request float abi to be softfp.
-CFLAGS_ENABLE_NEON=-march=armv7-a -mfloat-abi=softfp -mfpu=neon
+CFLAGS_ENABLE_NEON=$(CFLAGS_ARCHITECTURE_VARIANT) -mfloat-abi=softfp -mfpu=neon
endif
endif
diff --git a/core/osdep/include/template.h b/core/osdep/include/template.h
index 6738747..7ad1f51 100644
--- a/core/osdep/include/template.h
+++ b/core/osdep/include/template.h
@@ -9,6 +9,18 @@ __END__
* Wrapper for system header __FILENAME__
*/
+#ifdef MATRIX_COMMERCIAL
+/*****************************************************************************
+* Copyright (c) 2017 INSIDE Secure Oy. All Rights Reserved.
+*
+* This confidential and proprietary software may be used only as authorized
+* by a licensing agreement from INSIDE Secure.
+*
+* The entire notice above must be reproduced on all authorized copies that
+* may only be made to the extent permitted by a licensing agreement from
+* INSIDE Secure.
+*****************************************************************************/
+#else
/*****************************************************************************
* Copyright (c) 2017 INSIDE Secure Oy. All Rights Reserved.
*
@@ -33,6 +45,7 @@ __END__
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*****************************************************************************/
+#endif /* MATRIX_COMMERCIAL */
/* This file just includes system header __TOFILE__.
In case your system does not include all functions
diff --git a/core/src/psStat.c b/core/src/psStat.c
index a525fb6..7a01df5 100644
--- a/core/src/psStat.c
+++ b/core/src/psStat.c
@@ -143,12 +143,18 @@ psStatCompByteSeqResult_t psStatCompByteSeq(const unsigned char *a,
res.lcss_freq = num_longest_match_runs;
res.num_match_runs = num_match_runs;
- res.avg_match_run_len = (int)((double)sum_match_runs /
- (double)num_match_runs);
+ if (num_match_runs > 0)
+ res.avg_match_run_len = (int)((double)sum_match_runs /
+ (double)num_match_runs);
+ else
+ res.avg_match_run_len = 0;
res.num_diff_runs = num_diff_runs;
- res.avg_diff_run_len = (int)((double)sum_diff_runs /
- (double)num_diff_runs);
+ if (num_diff_runs > 0)
+ res.avg_diff_run_len = (int)((double)sum_diff_runs /
+ (double)num_diff_runs);
+ else
+ res.avg_diff_run_len = 0;
res.filled = 1;
diff --git a/core/src/psbuf.c b/core/src/psbuf.c
index 2610748..5267823 100644
--- a/core/src/psbuf.c
+++ b/core/src/psbuf.c
@@ -811,7 +811,10 @@ int32_t psDynBufAppendTlsVector(psDynBuf_t *db,
return PS_ARG_FAIL;
}
- target = psDynBufAppendSize(db, len + extralen);
+ if ((target = psDynBufAppendSize(db, len + extralen)) == NULL)
+ {
+ return PS_FAIL;
+ }
if (extralen == 1)
{
diff --git a/core/src/psprintf.c b/core/src/psprintf.c
index fa0105c..9e3b1b5 100644
--- a/core/src/psprintf.c
+++ b/core/src/psprintf.c
@@ -468,6 +468,7 @@ next_ch:
case 'd': l += 2;
/* fall-through. */
case 'o': l += 8;
+ /* fall-through. */
case 'c':
/* Promote "long" to "long long" on LP64 architectures. */
if (arg_size > 0 && sizeof(long) > sizeof(int))
diff --git a/core/src/sfzclcalendar.c b/core/src/sfzclcalendar.c
index 72934b8..ea2a291 100644
--- a/core/src/sfzclcalendar.c
+++ b/core/src/sfzclcalendar.c
@@ -448,7 +448,7 @@ sfzcl_make_time(SfzclCalendarTime calendar_time, SfzclTime *time_return,
{
int days_per_month;
- while (calendar_time->month > 12)
+ while (calendar_time->month > 11)
{
#ifdef DEBUG
L_DEBUG(LF_CERTLIB, "Month too large, adjusting %d",
@@ -477,7 +477,7 @@ sfzcl_make_time(SfzclCalendarTime calendar_time, SfzclTime *time_return,
#endif
if (calendar_time->month == 0)
{
- calendar_time->month = 12;
+ calendar_time->month = 11;
calendar_time->year--;
}
else
diff --git a/core/src/sfzclstr.c b/core/src/sfzclstr.c
index ac87829..8442f4c 100644
--- a/core/src/sfzclstr.c
+++ b/core/src/sfzclstr.c
@@ -118,6 +118,8 @@ sfzcl_str_realloc(SfzclStr str, size_t new_length)
L_DEBUG(LF_TOTAL_PROGRESS,
"Failed to convert charset %u (%u bit chars).",
str->charset, str->bits);
+ SPAL_Memory_Free(newp);
+ newp = NULL;
break;
}
}
diff --git a/core/testsupp/src/sfzutf/sfzutf_main_stdio.c b/core/testsupp/src/sfzutf/sfzutf_main_stdio.c
index 2e97adf..03f4e35 100644
--- a/core/testsupp/src/sfzutf/sfzutf_main_stdio.c
+++ b/core/testsupp/src/sfzutf/sfzutf_main_stdio.c
@@ -420,6 +420,8 @@ file_readArgs(
if (newArgc >= SFZUTF_FILE_MAX_ARGS)
{
error_p = "Too many arguments";
+ SFZUTF_FREE(line_p);
+ SFZUTF_FREE(newArgv);
return error_p;
}
diff --git a/core/unit_tests/test_psGetFileBuf.cc b/core/unit_tests/test_psGetFileBuf.cc
index 1710a8a..302c26d 100644
--- a/core/unit_tests/test_psGetFileBuf.cc
+++ b/core/unit_tests/test_psGetFileBuf.cc
@@ -77,7 +77,7 @@ AUTO_TEST(TEST_psGetFileBuf_empty_file)
{
return SKIPPED;
}
-
+
res = psGetFileBuf(pool, file, &buf, &len);
FAIL_IF(res != PS_SUCCESS);
FAIL_IF(buf == NULL);
@@ -100,7 +100,7 @@ AUTO_TEST(TEST_psGetFileBuf_endless_file)
{
return SKIPPED;
}
-
+
res = psGetFileBuf(pool, file, &buf, &len);
FAIL_IF(res != PS_SUCCESS);
FAIL_IF(buf == NULL);
@@ -125,7 +125,7 @@ AUTO_TEST(TEST_psGetFileBuf_4294967295_bytes_file)
take a long time. */
return SKIPPED;
}
-
+
FAIL_IF(system("rm " FILENAME) < -1);
FAIL_IF(system("fallocate -l 4294967295 " FILENAME) < -1);
if (!can_read(FILENAME))
@@ -166,7 +166,7 @@ AUTO_TEST(TEST_psGetFileBuf_4294967297_bytes_file)
take a long time. */
return SKIPPED;
}
-
+
FAIL_IF(system("rm " FILENAME) < -1);
FAIL_IF(system("fallocate -l 4294967297 " FILENAME) < -1);
if (!can_read(FILENAME))
diff --git a/crypto/Makefile b/crypto/Makefile
index 28325d5..60b4d42 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -9,6 +9,7 @@ include $(MATRIXSSL_ROOT)/common.mk
SRC:=\
common/alg_info.c \
+ common/digest_info.c \
symmetric/aes.c \
symmetric/aesCBC.c \
symmetric/aesGCM.c \
diff --git a/crypto/common/alg_info.c b/crypto/common/alg_info.c
index 4f3a0f5..0c766b1 100644
--- a/crypto/common/alg_info.c
+++ b/crypto/common/alg_info.c
@@ -95,6 +95,22 @@ psResSize_t psSigAlgToHashLen(int32_t sigAlg)
case OID_SHA512_RSA_SIG:
case OID_SHA512_ECDSA_SIG:
return SHA512_HASH_SIZE;
+# ifdef USE_PKCS1_PSS
+ /*
+ The PSS IDs are not part of the same range as the above OIDs,
+ but they do not conflict with the OIDs either. Support them here
+ for convenience. Now one can always map e.g. cert->sigAlgorithm
+ to hash length.
+ */
+ case PKCS1_SHA1_ID:
+ return SHA1_HASH_SIZE;
+ case PKCS1_SHA256_ID:
+ return SHA256_HASH_SIZE;
+ case PKCS1_SHA384_ID:
+ return SHA384_HASH_SIZE;
+ case PKCS1_SHA512_ID:
+ return SHA512_HASH_SIZE;
+# endif
default:
return PS_UNSUPPORTED_FAIL;
}
@@ -218,7 +234,10 @@ int32_t psHashLenToSigAlg(psSize_t hash_len,
/** Return PS_TRUE if sigAlg is deemed insecure.
Return PS_FALSE otherwise.
*/
-psBool_t psIsInsecureSigAlg(int32_t sigAlg, int keyAlgorithm, psSize_t keySize, psSize_t hashSize)
+psBool_t psIsInsecureSigAlg(int32_t sigAlg,
+ int keyAlgorithm,
+ psSize_t keySize,
+ psSize_t hashSize)
{
if (sigAlg == OID_MD2_RSA_SIG
|| sigAlg == OID_MD5_RSA_SIG
@@ -236,6 +255,69 @@ psBool_t psIsInsecureSigAlg(int32_t sigAlg, int keyAlgorithm, psSize_t keySize,
return PS_FALSE;
}
+/* Return PS_TRUE if hashLen is valid for sigAlg,
+ e.g. OID_SHA256_RSA_SIG requires hashLen == 32. */
+psBool_t psIsValidHashLenSigAlgCombination(psSize_t hashLen,
+ int32_t sigAlg)
+{
+ switch (sigAlg)
+ {
+# ifdef USE_MD2
+ case OID_MD2_RSA_SIG:
+ if (hashLen != MD2_HASH_SIZE)
+ {
+ return PS_FALSE;
+ }
+ break;
+# endif /* USE_MD2 */
+# ifdef USE_MD5
+ case OID_MD5_RSA_SIG:
+ if (hashLen != MD5_HASH_SIZE)
+ {
+ return PS_FALSE;
+ }
+ break;
+# endif /* USE_MD5 */
+ case OID_SHA1_RSA_SIG:
+ if (hashLen != SHA1_HASH_SIZE)
+ {
+ return PS_FALSE;
+ }
+ break;
+#ifdef USE_SHA224
+ case OID_SHA224_RSA_SIG:
+ if (hashLen != SHA224_HASH_SIZE)
+ {
+ return PS_FALSE;
+ }
+ break;
+#endif /* USE_SHA224 */
+ case OID_SHA256_RSA_SIG:
+ if (hashLen != SHA256_HASH_SIZE)
+ {
+ return PS_FALSE;
+ }
+ break;
+ case OID_SHA384_RSA_SIG:
+ if (hashLen != SHA384_HASH_SIZE)
+ {
+ return PS_FALSE;
+ }
+ break;
+ case OID_SHA512_RSA_SIG:
+ if (hashLen != SHA512_HASH_SIZE)
+ {
+ return PS_FALSE;
+ }
+ break;
+ default:
+ psTraceIntCrypto("Unsupported RSA signature alg: %d\n", sigAlg);
+ return PS_FALSE;
+ }
+
+ return PS_TRUE;
+}
+
/** Given the name of a signature algorithm (section 4.3.2 in TLS 1.3
draft #28), return its two-byte SignatureScheme identifier. */
uint16_t psGetNamedSigAlgId(const char *name)
diff --git a/crypto/common/digest_info.c b/crypto/common/digest_info.c
new file mode 100644
index 0000000..f7d9a54
--- /dev/null
+++ b/crypto/common/digest_info.c
@@ -0,0 +1,237 @@
+/**
+ * @file digest_info.c
+ * @version $Format:%h%d$
+ *
+ * Static DigestInfo prefixes and querying functions for PKCS #1.5.
+ */
+/*
+ * Copyright (c) 2018 INSIDE Secure Corporation
+ * Copyright (c) PeerSec Networks, 2002-2011
+ * All Rights Reserved
+ *
+ * The latest version of this code is available at http://www.matrixssl.org
+ *
+ * This software is open source; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This General Public License does NOT permit incorporating this software
+ * into proprietary programs. If you are unable to comply with the GPL, a
+ * commercial license for this software may be purchased from INSIDE at
+ * http://www.insidesecure.com/
+ *
+ * This program is distributed in WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "../cryptoImpl.h"
+
+# ifdef USE_RSA
+
+/*
+ ASN.1 DER encoded DigestInfos.
+ In RSA signature verification, the prefix of the RSA-decrypted message
+ should be compared against one of these. The correct one can be fetched
+ with psGetDigestInfoPrefix, which takes in as arguments the sig alg ID
+ and the length of the decrypted message. Each DigestInfo has two variants:
+ one with optional NULL parameters in the AlgorithmIdentifier, the other
+ without.
+*/
+
+# ifdef USE_MD2
+static const unsigned char PKCS1Dig_MD2[] =
+{
+ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10
+};
+static const unsigned char PKCS1Dig_MD2_ALT[] =
+{
+ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x02, 0x02, 0x04, 0x10
+};
+# endif /* USE_MD2 */
+
+# ifdef USE_MD5
+static const unsigned char PKCS1Dig_MD5[] =
+{
+ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
+};
+static const unsigned char PKCS1Dig_MD5_ALT[] =
+{
+ 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x02, 0x05, 0x04, 0x10
+};
+# endif /* USE_MD5 */
+
+# ifdef USE_SHA1
+static const unsigned char PKCS1Dig_SHA1[] =
+{
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
+ 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
+};
+static const unsigned char PKCS1Dig_SHA1_ALT[] =
+{
+ 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03,
+ 0x02, 0x1a, 0x04, 0x14
+};
+# endif /* USE_SHA1 */
+
+#ifdef USE_SHA224
+static const unsigned char PKCS1Dig_SHA224[] =
+{
+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c
+};
+static const unsigned char PKCS1Dig_SHA224_ALT[] =
+{
+ 0x30, 0x2b, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x04, 0x1c
+};
+# endif /* USE_SHA224 */
+
+# ifdef USE_SHA256
+static const unsigned char PKCS1Dig_SHA256[] =
+{
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+};
+static const unsigned char PKCS1Dig_SHA256_ALT[] =
+{
+ 0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20
+};
+# endif /* USE_SHA256 */
+
+# ifdef USE_SHA384
+static const unsigned char PKCS1Dig_SHA384[] =
+{
+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30
+};
+static const unsigned char PKCS1Dig_SHA384_ALT[] =
+{
+ 0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, 0x30
+};
+# endif /* USE_SHA384 */
+
+# ifdef USE_SHA512
+static const unsigned char PKCS1Dig_SHA512[] =
+{
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
+};
+static const unsigned char PKCS1Dig_SHA512_ALT[] =
+{
+ 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40
+};
+# endif /* USE_SHA512 */
+
+const
+unsigned char *psGetDigestInfoPrefix(int32_t len,
+ int32_t sigAlg)
+{
+ switch (sigAlg)
+ {
+# ifdef USE_MD2
+ case OID_MD2_RSA_SIG:
+ if (len == sizeof(PKCS1Dig_MD2) + MD2_HASH_SIZE)
+ {
+ return PKCS1Dig_MD2;
+ }
+ else if (len == sizeof(PKCS1Dig_MD2_ALT) + MD2_HASH_SIZE)
+ {
+ return PKCS1Dig_MD2_ALT;
+ }
+ break;
+# endif /* USE_MD2 */
+# ifdef USE_MD5
+ case OID_MD5_RSA_SIG:
+ if (len == sizeof(PKCS1Dig_MD5) + MD5_HASH_SIZE)
+ {
+ return PKCS1Dig_MD5;
+ }
+ else if (len == sizeof(PKCS1Dig_MD5_ALT) + MD5_HASH_SIZE)
+ {
+ return PKCS1Dig_MD5_ALT;
+ }
+ break;
+# endif /* USE_MD5 */
+# ifdef USE_SHA1
+ case OID_SHA1_RSA_SIG:
+ if (len == sizeof(PKCS1Dig_SHA1) + SHA1_HASH_SIZE)
+ {
+ return PKCS1Dig_SHA1;
+ }
+ else if (len == sizeof(PKCS1Dig_SHA1_ALT) + SHA1_HASH_SIZE)
+ {
+ return PKCS1Dig_SHA1_ALT;
+ }
+ break;
+# endif /* USE_SHA1 */
+# ifdef USE_SHA224
+ case OID_SHA224_RSA_SIG:
+ if (len == sizeof(PKCS1Dig_SHA224) + SHA224_HASH_SIZE)
+ {
+ return PKCS1Dig_SHA224;
+ }
+ else if (len == sizeof(PKCS1Dig_SHA224_ALT) + SHA224_HASH_SIZE)
+ {
+ return PKCS1Dig_SHA224_ALT;
+ }
+ break;
+# endif /* USE_SHA224 */
+# ifdef USE_SHA256
+ case OID_SHA256_RSA_SIG:
+ if (len == sizeof(PKCS1Dig_SHA256) + SHA256_HASH_SIZE)
+ {
+ return PKCS1Dig_SHA256;
+ }
+ else if (len == sizeof(PKCS1Dig_SHA256_ALT) + SHA256_HASH_SIZE)
+ {
+ return PKCS1Dig_SHA256_ALT;
+ }
+ break;
+# endif /* USE_SHA256 */
+# ifdef USE_SHA384
+ case OID_SHA384_RSA_SIG:
+ if (len == sizeof(PKCS1Dig_SHA384) + SHA384_HASH_SIZE)
+ {
+ return PKCS1Dig_SHA384;
+ }
+ else if (len == sizeof(PKCS1Dig_SHA384_ALT) + SHA384_HASH_SIZE)
+ {
+ return PKCS1Dig_SHA384_ALT;
+ }
+ break;
+# endif /* USE_SHA384 */
+# ifdef USE_SHA512
+ case OID_SHA512_RSA_SIG:
+ if (len == sizeof(PKCS1Dig_SHA512) + SHA512_HASH_SIZE)
+ {
+ return PKCS1Dig_SHA512;
+ }
+ else if (len == sizeof(PKCS1Dig_SHA512_ALT) + SHA512_HASH_SIZE)
+ {
+ return PKCS1Dig_SHA512_ALT;
+ }
+ break;
+# endif /* USE_SHA512 */
+ default:
+ psTraceCrypto("Unsupported RSA signature algorithm\n");
+ return NULL;
+ }
+
+ return NULL;
+}
+
+# endif /* USE_RSA */
diff --git a/crypto/cryptoApi.h b/crypto/cryptoApi.h
index c8a0151..47408e4 100644
--- a/crypto/cryptoApi.h
+++ b/crypto/cryptoApi.h
@@ -625,6 +625,57 @@ PSPUBLIC void psHmacSha384Final(psHmacSha384_t * ctx,
unsigned char hash[SHA384_HASHLEN]);
# endif
+# ifdef USE_PEM_DECODE
+typedef enum {
+ PEM_TYPE_ANY = 0,
+ PEM_TYPE_KEY,
+ PEM_TYPE_PRIVATE_KEY,
+ PEM_TYPE_PUBLIC_KEY,
+ PEM_TYPE_CERTIFICATE
+} psPemType_t;
+
+
+PSPUBLIC int32_t
+psPemFileToDer(psPool_t *pool,
+ const char *fileName,
+ const char *password,
+ psPemType_t expectedPemType,
+ unsigned char **derOut,
+ psSizeL_t *derOutLen);
+
+PSPUBLIC psBool_t
+psPemCheckOk(const unsigned char *pemBuf,
+ psSizeL_t pemBufLen,
+ psPemType_t pemType,
+ char **startp,
+ char **endp,
+ psSizeL_t *pemlen);
+
+PSPUBLIC int32_t
+psPemDecode(psPool_t *pool,
+ const unsigned char *pemBufIn,
+ psSizeL_t pemBufLen,
+ const char *password,
+ unsigned char **out,
+ psSizeL_t *outlen);
+
+PSPUBLIC psRes_t
+psPemCertBufToList(psPool_t *pool,
+ const unsigned char *buf,
+ psSizeL_t len,
+ psList_t **x509certList);
+
+PSPUBLIC int32_t
+psPemTryDecode(psPool_t *pool,
+ const unsigned char *in,
+ psSizeL_t inLen,
+ psPemType_t pemType,
+ const char *password,
+ unsigned char **out,
+ psSizeL_t *outlen);
+
+# endif /* USE_PEM_DECODE */
+
/******************************************************************************/
/*
Private Key Parsing
@@ -675,58 +726,8 @@ PSPUBLIC void psPkcs5Pbkdf2(unsigned char *password, uint32 pLen,
/*
Public Key Cryptography
*/
-# if defined(USE_RSA) || defined(USE_ECC) || defined(USE_DH)
-
-typedef enum {
- PEM_TYPE_ANY = 0,
- PEM_TYPE_KEY,
- PEM_TYPE_PRIVATE_KEY,
- PEM_TYPE_PUBLIC_KEY,
- PEM_TYPE_CERTIFICATE
-} psPemType_t;
-
-# ifdef USE_PEM_DECODE
-
-PSPUBLIC int32_t
-psPemFileToDer(psPool_t *pool,
- const char *fileName,
- const char *password,
- psPemType_t expectedPemType,
- unsigned char **derOut,
- psSizeL_t *derOutLen);
-
-PSPUBLIC psBool_t
-psPemCheckOk(const unsigned char *pemBuf,
- psSizeL_t pemBufLen,
- psPemType_t pemType,
- char **startp,
- char **endp,
- psSizeL_t *pemlen);
-
-PSPUBLIC int32_t
-psPemDecode(psPool_t *pool,
- const unsigned char *pemBufIn,
- psSizeL_t pemBufLen,
- const char *password,
- unsigned char **out,
- psSizeL_t *outlen);
-
-PSPUBLIC psRes_t
-psPemCertBufToList(psPool_t *pool,
- const unsigned char *buf,
- psSizeL_t len,
- psList_t **x509certList);
-# endif /* USE_PEM_DECODE */
-
-PSPUBLIC int32_t
-psPemTryDecode(psPool_t *pool,
- const unsigned char *in,
- psSizeL_t inLen,
- psPemType_t pemType,
- const char *password,
- unsigned char **out,
- psSizeL_t *outlen);
+# if defined(USE_RSA) || defined(USE_ECC) || defined(USE_DH) || defined(USE_X25519) || defined(USE_ED25519)
PSPUBLIC int32_t psInitPubKey(psPool_t *pool, psPubKey_t *key, uint8_t type);
PSPUBLIC void psClearPubKey(psPubKey_t *key);
PSPUBLIC int32_t psNewPubKey(psPool_t *pool, uint8_t type, psPubKey_t **key);
@@ -1190,6 +1191,17 @@ PSPUBLIC psBool_t psIsEcdheGroup(uint16_t namedGroup);
PSPUBLIC uint16_t psGetNamedGroupId(const char *name);
/** Map TLS specification's signature_algorithm name to algorithm id. */
PSPUBLIC uint16_t psGetNamedSigAlgId(const char *name);
+
+PSPUBLIC psBool_t psIsValidHashLenSigAlgCombination(psSize_t hashLen,
+ int32_t sigAlg);
+
+# ifdef USE_RSA
+/* Return the correct reference DigestInfo prefix for sigAlg,
+ when len bytes were RSA-decrypted. */
+PSPUBLIC const unsigned char *psGetDigestInfoPrefix(int32_t len,
+ int32_t sigAlg);
+# endif /* USE_RSA */
+
# ifdef USE_MD2
/******************************************************************************/
static inline void psMd2PreInit(psMd2_t *md2)
diff --git a/crypto/cryptoCheck.h b/crypto/cryptoCheck.h
index 491a706..f41859a 100644
--- a/crypto/cryptoCheck.h
+++ b/crypto/cryptoCheck.h
@@ -115,6 +115,9 @@
# ifndef USE_SHA1
# error "Enable USE_SHA1 in cryptoConfig.h for OCSP support"
# endif
+# ifndef USE_CERT_PARSE
+# errro "enable USE_CERT_PARSE for USE_OCSP_RESPONSE."
+# endif
# endif
# ifdef USE_OCSP_REQUEST
diff --git a/crypto/cryptolib.h b/crypto/cryptolib.h
index dbd175e..555e388 100644
--- a/crypto/cryptolib.h
+++ b/crypto/cryptolib.h
@@ -234,6 +234,17 @@ extern int32_t psGetPrngLocked(unsigned char *bytes, psSize_t size,
# define OID_SHA512_ECDSA_SIG 526
# define OID_SHA512_ECDSA_SIG_HEX "\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x04"
+/* The SSL 3.0, TLS 1.0/1.1 MD5-SHA1 based signature scheme for RSA.
+ Not based on an OID (because there isn't one).
+ This is a MatrixSSL internal ID. */
+# define OID_RSA_TLS_SIG_ALG 666
+/* Generic ID for PKCS #1.5 RSA signatures.
+ Hash algoritm to use must be specified in some other way. */
+# define OID_RSA_PKCS15_SIG_ALG (667 + OID_COLLISION)
+/* Generic ID for ECDSA signatures in TLS.
+ Hash algoritm to use must be specified in some other way. */
+# define OID_ECDSA_TLS_SIG_ALG (668 + OID_COLLISION)
+
/* Public key algorithms */
# define OID_RSA_KEY_ALG_STR "1.2.840.113549.1.1.1"
# define OID_RSA_KEY_ALG 645
diff --git a/crypto/digest/digest.h b/crypto/digest/digest.h
index f4d0e32..4b27647 100644
--- a/crypto/digest/digest.h
+++ b/crypto/digest/digest.h
@@ -44,6 +44,7 @@
# define SHA512_HASH_SIZE 64
# define MD2_HASH_SIZE 16
# define MD5_HASH_SIZE 16
+# define MD5SHA1_HASH_SIZE 36
# define SHA1_HASHLEN 20
# define SHA224_HASHLEN 28
@@ -53,7 +54,7 @@
# define MD2_HASHLEN 16
# define MD4_HASHLEN 16
# define MD5_HASHLEN 16
-# define MD5SHA1_HASHLEN (MD5_HASHLEN + SHA1_HASHLEN)
+# define MD5SHA1_HASHLEN 36
# if defined(USE_SHA512)
# define MAX_HASH_SIZE SHA512_HASHLEN
diff --git a/crypto/digest/hkdf.c b/crypto/digest/hkdf.c
index 5e7266a..7cc7feb 100644
--- a/crypto/digest/hkdf.c
+++ b/crypto/digest/hkdf.c
@@ -47,7 +47,7 @@ int32_t psHkdfExpand(psCipherType_e hmacAlg,
unsigned char *okm,
psSize_t okmLen)
{
- psSize_t hashLen;
+ int32_t hashLen;
unsigned char buf[MAX_HASH_SIZE + HKDF_MAX_INFO_LEN + 1] = {0};
unsigned char T[MAX_HASH_SIZE] = {0};
psSizeL_t i, L, stillNeeded;
@@ -218,11 +218,11 @@ int32_t psHkdfExpandLabel(psPool_t *pool,
rc = psDynBufAppendTlsVector(&hkdfLabelBuf,
7, 255,
vector_data, vector_data_len);
+ psFree(vector_data, pool);
if (rc < 0)
{
return rc;
}
- psFree(vector_data, pool);
psDynBufUninit(&labelBuf);
/* opaque context<0..255> = Context; */
@@ -236,11 +236,11 @@ int32_t psHkdfExpandLabel(psPool_t *pool,
rc = psDynBufAppendTlsVector(&hkdfLabelBuf,
0, 255,
vector_data, vector_data_len);
+ psFree(vector_data, pool);
if (rc < 0)
{
return rc;
}
- psFree(vector_data, pool);
psDynBufUninit(&contextBuf);
/* Fetch the final HdkfLabel */
@@ -262,6 +262,7 @@ int32_t psHkdfExpandLabel(psPool_t *pool,
length);
if (rc < 0)
{
+ psFree(hkdf_label, pool);
return rc;
}
diff --git a/crypto/keyformat/pkcs.c b/crypto/keyformat/pkcs.c
index 99a19aa..eac741f 100644
--- a/crypto/keyformat/pkcs.c
+++ b/crypto/keyformat/pkcs.c
@@ -111,14 +111,21 @@ int32_t pkcs1Pad(const unsigned char *in, psSize_t inlen,
00 00
We don't worry about v2 rollback issues because we don't support v2
+
+ If verifyUnpaddedLen is false, leave it up to the caller to check that
+ the unpadded lenght matches the expected length.
*/
-int32_t pkcs1Unpad(const unsigned char *in, psSize_t inlen,
- unsigned char *out, psSize_t outlen,
- uint8_t decryptType)
+int32_t pkcs1UnpadExt(const unsigned char *in,
+ psSize_t inlen,
+ unsigned char *out,
+ psSize_t outlen,
+ uint8_t decryptType,
+ psBool_t verifyUnpaddedLen,
+ psSize_t *unpaddedLen)
{
const unsigned char *c, *end;
- if (inlen < outlen + 10)
+ if (verifyUnpaddedLen && inlen < outlen + 10)
{
psTraceCrypto("pkcs1Unpad failure\n");
return PS_ARG_FAIL;
@@ -148,15 +155,32 @@ int32_t pkcs1Unpad(const unsigned char *in, psSize_t inlen,
c++;
}
c++;
-/*
- The length of the remaining data should be equal to what was expected
- Combined with the initial length check, there must be >= 8 bytes of pad
- ftp://ftp.rsa.com/pub/pdfs/bulletn7.pdf
- */
- if ((uint32) (end - c) != outlen)
+
+ /*
+ The length of the remaining data should be equal to what was expected
+ Combined with the initial length check, there must be >= 8 bytes of pad
+ ftp://ftp.rsa.com/pub/pdfs/bulletn7.pdf
+ */
+ if (verifyUnpaddedLen)
{
- psTraceCrypto("pkcs1Unpad verification failure\n");
- return PS_LIMIT_FAIL;
+ if ((uint32) (end - c) != outlen)
+ {
+ psTraceCrypto("pkcs1Unpad verification failure\n");
+ return PS_LIMIT_FAIL;
+ }
+ }
+ else
+ {
+ if ((uint32) (end - c) > outlen)
+ {
+ psTraceCrypto("pkcs1Unpad output buffer to small\n");
+ return PS_OUTPUT_LENGTH;
+ }
+ }
+
+ if (unpaddedLen)
+ {
+ *unpaddedLen = (psSize_t)(end - c);
}
/* Copy the value bytes to the out buffer */
@@ -165,9 +189,25 @@ int32_t pkcs1Unpad(const unsigned char *in, psSize_t inlen,
*out = *c;
out++; c++;
}
+
return PS_SUCCESS;
}
+int32_t pkcs1Unpad(const unsigned char *in,
+ psSize_t inlen,
+ unsigned char *out,
+ psSize_t outlen,
+ uint8_t decryptType)
+{
+ return pkcs1UnpadExt(in,
+ inlen,
+ out,
+ outlen,
+ decryptType,
+ PS_TRUE,
+ NULL);
+}
+
#ifdef USE_PRIVATE_KEY_PARSING
# ifdef MATRIX_USE_FILE_SYSTEM
# ifdef USE_PKCS8
diff --git a/crypto/keyformat/x509.c b/crypto/keyformat/x509.c
index 74d5f7d..5832a60 100644
--- a/crypto/keyformat/x509.c
+++ b/crypto/keyformat/x509.c
@@ -160,12 +160,6 @@ static int32_t getImplicitBitString(psPool_t *pool, const unsigned char **pp,
psSize_t len, int32_t impVal, unsigned char **bitString,
psSize_t *bitLen);
static int32_t issuedBefore(rfc_e rfc, const psX509Cert_t *cert);
-
-# ifdef USE_RSA
-static int32_t x509ConfirmSignature(const unsigned char *sigHash,
- const unsigned char *sigOut, psSize_t sigLen);
-# endif
-
# endif /* USE_CERT_PARSE */
/******************************************************************************/
@@ -273,7 +267,7 @@ psRes_t psX509ParseCertFile(psPool_t *pool, const char *fileName,
{
psFreeList(fileList, pool);
psX509FreeCert(certs);
- psFree(pool, fileBuf);
+ psFree(fileBuf, pool);
return rc;
}
psFree(fileBuf, pool);
@@ -1076,6 +1070,9 @@ static int parse_single_cert(psPool_t *pool, const unsigned char **pp,
func_rc = PS_PARSE_FAIL;
goto out;
}
+
+ cert->sigHashLen = psSigAlgToHashLen(cert->sigAlgorithm);
+
/*
Compute the hash of the cert here for CA validation
*/
@@ -5292,33 +5289,16 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert,
void *hwCtx, void *poolUserPtr)
{
psX509Cert_t *ic, *sc;
- int32 sigType, rc;
- uint32 sigLen;
- void *rsaData = NULL;
-# ifdef USE_ECC
- int32 sigStat;
-# endif /* USE_ECC */
-# ifdef USE_RSA
- unsigned char sigOut[10 + MAX_HASH_SIZE + 9]; /* Max size */
- unsigned char *tempSig = NULL;
-# endif /* USE_RSA */
- psPool_t *pkiPool = NULL;
-# if defined(USE_PKCS1_PSS) && !defined(USE_CL_RSA)
- psSize_t pssLen;
-# endif
-
- rc = 0;
- sigLen = 0;
if (subjectCert == NULL)
{
psTraceCrypto("No subject cert given to psX509AuthenticateCert\n");
return PS_ARG_FAIL;
}
-/*
- Determine what we've been passed
- */
+ /*
+ Determine what we've been passed
+ */
if (issuerCert == NULL)
{
/* reset auth flags in subjectCert chain and find first sc and ic */
@@ -5346,15 +5326,15 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert,
sc = subjectCert;
}
-/*
- Error on first problem seen and set the subject status to FAIL
- */
+ /*
+ Error on first problem seen and set the subject status to FAIL
+ */
while (ic)
{
-/*
- Certificate authority constraint only available in version 3 certs.
- Only parsing version 3 certs by default though.
- */
+ /*
+ Certificate authority constraint only available in version 3 certs.
+ Only parsing version 3 certs by default though.
+ */
if ((ic->version > 1) && (ic->extensions.bc.cA != CA_TRUE))
{
if (sc != ic)
@@ -5365,9 +5345,9 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert,
}
}
-/*
- Use sha1 hash of issuer fields computed at parse time to compare
- */
+ /*
+ Use sha1 hash of issuer fields computed at parse time to compare
+ */
if (Memcmp(sc->issuer.hash, ic->subject.hash, SHA1_HASH_SIZE) != 0)
{
#define ALLOW_INTERMEDIATES_AS_ROOTS
@@ -5427,261 +5407,54 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert,
}
# endif
-/*
- Signature confirmation
- The sigLen is the ASN.1 size in bytes for encoding the hash.
- The magic 10 is comprised of the SEQUENCE and ALGORITHM ID overhead.
- The magic 9, 8, or 5 is the OID length of the corresponding algorithm.
- */
- switch (sc->sigAlgorithm)
- {
-# ifdef USE_RSA
-# ifdef ENABLE_MD5_SIGNED_CERTS
-# ifdef USE_MD2
- case OID_MD2_RSA_SIG:
-# endif
- case OID_MD5_RSA_SIG:
- sigType = RSA_TYPE_SIG;
- sigLen = 10 + MD5_HASH_SIZE + 8;
- break;
-# endif
-# ifdef ENABLE_SHA1_SIGNED_CERTS
- case OID_SHA1_RSA_SIG:
- case OID_SHA1_RSA_SIG2:
- sigLen = 10 + SHA1_HASH_SIZE + 5;
- sigType = RSA_TYPE_SIG;
- break;
-# endif
-# ifdef USE_SHA224
- case OID_SHA224_RSA_SIG:
- sigLen = 10 + SHA224_HASH_SIZE + 9;
- sigType = RSA_TYPE_SIG;
- break;
-# endif
-# ifdef USE_SHA256
- case OID_SHA256_RSA_SIG:
- sigLen = 10 + SHA256_HASH_SIZE + 9;
- sigType = RSA_TYPE_SIG;
- break;
-# endif
-# ifdef USE_SHA384
- case OID_SHA384_RSA_SIG:
- sigLen = 10 + SHA384_HASH_SIZE + 9;
- sigType = RSA_TYPE_SIG;
- break;
-# endif
-# ifdef USE_SHA512
- case OID_SHA512_RSA_SIG:
- sigLen = 10 + SHA512_HASH_SIZE + 9;
- sigType = RSA_TYPE_SIG;
- break;
-# endif
-# endif /* USE_RSA */
-# ifdef USE_ECC
-# ifdef ENABLE_SHA1_SIGNED_CERTS
- case OID_SHA1_ECDSA_SIG:
- sigLen = SHA1_HASH_SIZE;
- sigType = ECDSA_TYPE_SIG;
- break;
-# endif
-# ifdef USE_SHA224
- case OID_SHA224_ECDSA_SIG:
- sigLen = SHA224_HASH_SIZE;
- sigType = ECDSA_TYPE_SIG;
- break;
-# endif
-# ifdef USE_SHA256
- case OID_SHA256_ECDSA_SIG:
- sigLen = SHA256_HASH_SIZE;
- sigType = ECDSA_TYPE_SIG;
- break;
-# endif
-# ifdef USE_SHA384
- case OID_SHA384_ECDSA_SIG:
- sigLen = SHA384_HASH_SIZE;
- sigType = ECDSA_TYPE_SIG;
- break;
-# endif
-# ifdef USE_SHA512
- case OID_SHA512_ECDSA_SIG:
- sigLen = SHA512_HASH_SIZE;
- sigType = ECDSA_TYPE_SIG;
- break;
-# endif
-# endif /* USE_ECC */
-# ifdef USE_ED25519
- case OID_ED25519_KEY_ALG:
- sigLen = 64;
- sigType = ED25519_TYPE_SIG;
- break;
-# endif
-# ifdef USE_PKCS1_PSS
- case OID_RSASSA_PSS:
- switch (sc->pssHash)
- {
-# ifdef ENABLE_MD5_SIGNED_CERTS
- case PKCS1_MD5_ID:
- sigLen = MD5_HASH_SIZE;
- break;
-# endif
-# ifdef ENABLE_SHA1_SIGNED_CERTS
- case PKCS1_SHA1_ID:
- sigLen = SHA1_HASH_SIZE;
- break;
-# endif
-# ifdef USE_SHA224
- case PKCS1_SHA224_ID:
- sigLen = SHA224_HASH_SIZE;
- break;
-# endif
-# ifdef USE_SHA256
- case PKCS1_SHA256_ID:
- sigLen = SHA256_HASH_SIZE;
- break;
-# endif
-# ifdef USE_SHA384
- case PKCS1_SHA384_ID:
- sigLen = SHA384_HASH_SIZE;
- break;
-# endif
-# ifdef USE_SHA512
- case PKCS1_SHA512_ID:
- sigLen = SHA512_HASH_SIZE;
- break;
-# endif
- default:
- return PS_UNSUPPORTED_FAIL;
- }
- sigType = RSAPSS_TYPE_SIG;
- break;
-# endif
- default:
- sigType = PS_UNSUPPORTED_FAIL;
- break;
- }
-
- if (sigType == PS_UNSUPPORTED_FAIL)
- {
- sc->authStatus = PS_CERT_AUTH_FAIL_SIG;
- psTraceIntCrypto("Unsupported certificate signature algorithm %d\n",
- subjectCert->sigAlgorithm);
- return sigType;
- }
-
-# ifdef USE_RSA
- if (sigType == RSA_TYPE_SIG || sigType == RSAPSS_TYPE_SIG)
- {
- }
- /* Now do the signature validation */
- if (sigType == RSA_TYPE_SIG)
- {
- psAssert(sigLen <= sizeof(sigOut));
-/*
- psRsaDecryptPub destroys the 'in' parameter so let it be a tmp
- */
- tempSig = psMalloc(pool, sc->signatureLen);
- if (tempSig == NULL)
- {
- psError("Memory allocation error: psX509AuthenticateCert\n");
- return PS_MEM_FAIL;
- }
- Memcpy(tempSig, sc->signature, sc->signatureLen);
-
- if ((rc = psRsaDecryptPub(pkiPool, &ic->publicKey.key.rsa,
- tempSig, sc->signatureLen, sigOut, sigLen, rsaData)) < 0)
- {
-
- psTraceCrypto("Unable to RSA decrypt certificate signature\n");
- sc->authStatus = PS_CERT_AUTH_FAIL_SIG;
- psFree(tempSig, pool);
- return rc;
- }
- psFree(tempSig, pool);
- rc = x509ConfirmSignature(sc->sigHash, sigOut, sigLen);
- }
-# if defined(USE_PKCS1_PSS) && !defined(USE_CL_RSA)
- if (sigType == RSAPSS_TYPE_SIG)
- {
- tempSig = psMalloc(pool, sc->signatureLen);
- if (tempSig == NULL)
- {
- psError("Memory allocation error: psX509AuthenticateCert\n");
- return PS_MEM_FAIL;
- }
- pssLen = sc->signatureLen;
- if ((rc = psRsaCrypt(pkiPool, &ic->publicKey.key.rsa,
- sc->signature, sc->signatureLen, tempSig, &pssLen,
- PS_PUBKEY, rsaData)) < 0)
- {
- psFree(tempSig, pool);
- return rc;
- }
-
- if (psPkcs1PssDecode(pkiPool, sc->sigHash, sigLen, tempSig,
- pssLen, sc->saltLen, sc->pssHash, ic->publicKey.keysize * 8,
- &rc) < 0)
- {
- psFree(tempSig, pool);
- return PS_FAILURE;
- }
- psFree(tempSig, pool);
-
- if (rc == 0)
- {
- /* This is an indication the hash did NOT match */
- rc = -1; /* The test below is looking for < 0 */
- }
- }
-# endif /* defined(USE_PKCS1_PSS) && !defined(USE_CL_RSA) */
-# endif /* USE_RSA */
-
-# ifdef USE_ECC
- if (sigType == ECDSA_TYPE_SIG)
- {
- if ((rc = psEccDsaVerify(pkiPool,
- &ic->publicKey.key.ecc,
- sc->sigHash, sigLen,
- sc->signature, sc->signatureLen,
- &sigStat, rsaData)) != 0)
- {
- psTraceCrypto("Error validating ECDSA certificate signature\n");
- sc->authStatus = PS_CERT_AUTH_FAIL_SIG;
- return rc;
- }
- if (sigStat == -1)
- {
- /* No errors, but signature didn't pass */
- psTraceCrypto("ECDSA certificate signature failed\n");
- rc = -1;
- }
- }
-# endif /* USE_ECC */
-# ifdef USE_ED25519
- if (sigType == ED25519_TYPE_SIG)
+ /*
+ Try to verify the subject cert's signature using the issuer cert's
+ public key.
+ */
{
psRes_t res;
+ const unsigned char *tbs = sc->sigHash;
+ psSizeL_t tbsLen = sc->sigHashLen;
+ psVerifyOptions_t opts;
+ psBool_t verifyResult = PS_FALSE;
- res = psEd25519Verify(sc->signature,
- sc->tbsCertStart,
- sc->tbsCertLen,
- ic->publicKey.key.ed25519.pub);
- if (res != PS_SUCCESS)
+ memset(&opts, 0, sizeof(opts));
+ opts.msgIsDigestInfo = PS_TRUE;
+
+ /* Special cases: RSASSA-PSS, Ed25519 and DSA verification
+ needs some extra information. */
+# ifdef USE_PKCS1_PSS
+ if (sc->sigAlgorithm == OID_RSASSA_PSS)
{
- psTraceCrypto("Ed25519 certificate signature failed\n");
- rc = -1;
+ opts.rsaPssHashAlg = sc->pssHash;
+ opts.rsaPssHashLen = psPssHashAlgToHashLen(sc->pssHash);
+ opts.rsaPssSaltLen = sc->saltLen;
+ opts.useRsaPss = PS_TRUE;
+ }
+# endif /* USE_PKCS1_PSS */
+# ifdef USE_ED25519
+ if (sc->sigAlgorithm == OID_ED25519_KEY_ALG)
+ {
+ tbs = sc->tbsCertStart;
+ tbsLen = sc->tbsCertLen;
+ opts.msgIsDigestInfo = PS_FALSE;
+ }
+# endif /* USE_ED25519 */
+ res = psVerifySig(NULL,
+ tbs,
+ tbsLen,
+ sc->signature,
+ sc->signatureLen,
+ &ic->publicKey,
+ sc->sigAlgorithm,
+ &verifyResult,
+ &opts);
+ if (res != PS_SUCCESS || verifyResult != PS_TRUE)
+ {
+ sc->authStatus = PS_CERT_AUTH_FAIL_SIG;
+ return PS_CERT_AUTH_FAIL_SIG;
}
}
-# endif /* USE_ED25519 */
-
-/*
- Test what happen in the signature test?
- */
- if (rc < PS_SUCCESS)
- {
- sc->authStatus = PS_CERT_AUTH_FAIL_SIG;
- return rc;
- }
-
/* X.509 extension tests. Problems below here will be collected
in flags and given to the user */
@@ -5742,6 +5515,7 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert,
will always contain the relevant information. */
if ( !(ic->extensions.keyUsageFlags & KEY_USAGE_KEY_CERT_SIGN))
{
+ int32 rc = 0;
/* @security If keyUsageFlags is zero, it may not exist at all
in the cert. This is allowed if the cert was issued before
the RFC was updated to require this field for CA certificates.
@@ -5750,10 +5524,7 @@ int32 psX509AuthenticateCert(psPool_t *pool, psX509Cert_t *subjectCert,
{
rc = issuedBefore(RFC_3280, ic);
}
- else
- {
- rc = 0; /* Awkward code to force the compare below */
- }
+
/* Iff rc == 1 we won't error */
if (!rc)
{
@@ -5813,125 +5584,6 @@ L_INTERMEDIATE_ROOT:
return PS_SUCCESS;
}
-# ifdef USE_RSA
-/******************************************************************************/
-/*
- Do the signature validation for a subject certificate against a
- known CA certificate
- */
-static int32_t x509ConfirmSignature(const unsigned char *sigHash,
- const unsigned char *sigOut, psSize_t sigLen)
-{
- const unsigned char *end;
- const unsigned char *p = sigOut;
- unsigned char hash[MAX_HASH_SIZE];
- int32_t oi;
- psSize_t len, plen;
-
- end = p + sigLen;
-/*
- DigestInfo ::= SEQUENCE {
- digestAlgorithm DigestAlgorithmIdentifier,
- digest Digest }
-
- DigestAlgorithmIdentifier ::= AlgorithmIdentifier
-
- Digest ::= OCTET STRING
- */
- if (getAsnSequence(&p, (uint32) (end - p), &len) < 0)
- {
- psTraceCrypto("Initial parse error in x509ConfirmSignature\n");
- return PS_PARSE_FAIL;
- }
-
- /* Could be MD5 or SHA1 */
- if (getAsnAlgorithmIdentifier(&p, (uint32) (end - p), &oi, &plen) < 0)
- {
- psTraceCrypto("Algorithm ID parse error in x509ConfirmSignature\n");
- return PS_PARSE_FAIL;
- }
- psAssert(plen == 0);
- if ((*p++ != ASN_OCTET_STRING) ||
- getAsnLength(&p, (uint32) (end - p), &len) < 0 ||
- (uint32) (end - p) < len)
- {
- psTraceCrypto("getAsnLength parse error in x509ConfirmSignature\n");
- return PS_PARSE_FAIL;
- }
- Memcpy(hash, p, len);
- switch (oi)
- {
-# ifdef ENABLE_MD5_SIGNED_CERTS
-# ifdef USE_MD2
- case OID_MD2_ALG:
-# endif
- case OID_MD5_ALG:
- if (len != MD5_HASH_SIZE)
- {
- psTraceCrypto("MD5_HASH_SIZE error in x509ConfirmSignature\n");
- return PS_LIMIT_FAIL;
- }
- break;
-# endif
-# ifdef ENABLE_SHA1_SIGNED_CERTS
- case OID_SHA1_ALG:
- if (len != SHA1_HASH_SIZE)
- {
- psTraceCrypto("SHA1_HASH_SIZE error in x509ConfirmSignature\n");
- return PS_LIMIT_FAIL;
- }
- break;
-# endif
-# ifdef USE_SHA224
- case OID_SHA224_ALG:
- if (len != SHA224_HASH_SIZE)
- {
- psTraceCrypto("SHA224_HASH_SIZE error in x509ConfirmSignature\n");
- return PS_LIMIT_FAIL;
- }
- break;
-# endif
-# ifdef USE_SHA256
- case OID_SHA256_ALG:
- if (len != SHA256_HASH_SIZE)
- {
- psTraceCrypto("SHA256_HASH_SIZE error in x509ConfirmSignature\n");
- return PS_LIMIT_FAIL;
- }
- break;
-# endif
-# ifdef USE_SHA384
- case OID_SHA384_ALG:
- if (len != SHA384_HASH_SIZE)
- {
- psTraceCrypto("SHA384_HASH_SIZE error in x509ConfirmSignature\n");
- return PS_LIMIT_FAIL;
- }
- break;
-# endif
-# ifdef USE_SHA512
- case OID_SHA512_ALG:
- if (len != SHA512_HASH_SIZE)
- {
- psTraceCrypto("SHA512_HASH_SIZE error in x509ConfirmSignature\n");
- return PS_LIMIT_FAIL;
- }
- break;
-# endif
- default:
- psTraceCrypto("Unsupported alg ID error in x509ConfirmSignature\n");
- return PS_UNSUPPORTED_FAIL;
- }
- /* hash should match sigHash */
- if (memcmpct(hash, sigHash, len) != 0)
- {
- psTraceCrypto("Signature failure in x509ConfirmSignature\n");
- return PS_SIGNATURE_MISMATCH;
- }
- return PS_SUCCESS;
-}
-# endif /* USE_RSA */
-
/******************************************************************************/
# endif /* USE_CERT_PARSE */
@@ -6951,7 +6603,7 @@ int32_t psOcspResponseValidate(psPool_t *pool, psX509Cert_t *trustedOCSP,
{
static psValidateOCSPResponseOptions_t vOptsDefault;
psX509Cert_t *curr, *issuer, *subject, *ocspResIssuer;
- psOcspSingleResponse_t *subjectResponse;
+ psOcspSingleResponse_t *subjectResponse = NULL;
unsigned char sigOut[MAX_HASH_SIZE];
int32 sigOutLen, sigType, index;
psPool_t *pkiPool = NULL;
@@ -7109,7 +6761,8 @@ int32_t psOcspResponseValidate(psPool_t *pool, psX509Cert_t *trustedOCSP,
while (index < MAX_OCSP_RESPONSES)
{
subjectResponse = &response->singleResponse[index];
- if ((subject->serialNumberLen == subjectResponse->certIdSerialLen) &&
+ if ((subject->serialNumberLen > 0) &&
+ (subject->serialNumberLen == subjectResponse->certIdSerialLen) &&
(Memcmp(subject->serialNumber, subjectResponse->certIdSerial,
subject->serialNumberLen) == 0))
{
diff --git a/crypto/keyformat/x509.h b/crypto/keyformat/x509.h
index a6c6d42..96ff597 100644
--- a/crypto/keyformat/x509.h
+++ b/crypto/keyformat/x509.h
@@ -657,6 +657,7 @@ typedef struct psCert
int32 revokedStatus;
# endif
unsigned char sigHash[MAX_HASH_SIZE];
+ psSize_t sigHashLen;
# endif /* USE_CERT_PARSE */
# if defined(USE_OCSP_RESPONSE) || defined(USE_OCSP_REQUEST)
unsigned char sha1KeyHash[SHA1_HASH_SIZE];
diff --git a/crypto/pubkey/dh_gen_key.c b/crypto/pubkey/dh_gen_key.c
index 412d494..ba1b3b2 100644
--- a/crypto/pubkey/dh_gen_key.c
+++ b/crypto/pubkey/dh_gen_key.c
@@ -243,7 +243,7 @@ int32_t psDhGenKeyParams(psPool_t *pool, const psDhParams_t *params,
else
{
return psDhGenKeyIntsSize(pool, params->size, ¶ms->p,
- ¶ms->g, params->x_bitlen, key, usrData);
+ ¶ms->g, params->x_bitlen/8, key, usrData);
}
}
diff --git a/crypto/pubkey/dh_params.c b/crypto/pubkey/dh_params.c
index ccc6dc3..c99a4ba 100644
--- a/crypto/pubkey/dh_params.c
+++ b/crypto/pubkey/dh_params.c
@@ -95,7 +95,10 @@ int32_t psPkcs3ParseDhParamBin(psPool_t *pool, const unsigned char *dhBin,
/* Read desired length of private key.
(Note: currently ignored by MatrixSSL). */
pstm_int bitlen;
- pstm_init_size(pool, &bitlen, 1);
+ if (pstm_init_size(pool, &bitlen, 1) < 0)
+ {
+ goto L_ERR;
+ }
if (pstm_read_asn(pool, &c, (uint16_t) (end - c), &bitlen) < 0)
{
pstm_clear(&bitlen);
diff --git a/crypto/pubkey/ecc_curve_config.c b/crypto/pubkey/ecc_curve_config.c
index 23f6a77..515c95b 100644
--- a/crypto/pubkey/ecc_curve_config.c
+++ b/crypto/pubkey/ecc_curve_config.c
@@ -72,6 +72,7 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves
const psEccCurve_t *curve;
uint8_t listLen = 0;
+# ifdef USE_SECP521R1
if (curves & IS_SECP521R1)
{
if (getEccParamById(IANA_SECP521R1, &curve) == 0)
@@ -83,6 +84,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves
}
}
}
+# endif
+# ifdef USE_BRAIN512R1
if (curves & IS_BRAIN512R1)
{
if (getEccParamById(IANA_BRAIN512R1, &curve) == 0)
@@ -94,6 +97,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves
}
}
}
+# endif
+# ifdef USE_SECP384R1
if (curves & IS_SECP384R1)
{
if (getEccParamById(IANA_SECP384R1, &curve) == 0)
@@ -105,6 +110,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves
}
}
}
+# endif
+# ifdef USE_BRAIN384R1
if (curves & IS_BRAIN384R1)
{
if (getEccParamById(IANA_BRAIN384R1, &curve) == 0)
@@ -116,6 +123,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves
}
}
}
+# endif
+# ifdef USE_SECP256R1
if (curves & IS_SECP256R1)
{
if (getEccParamById(IANA_SECP256R1, &curve) == 0)
@@ -127,6 +136,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves
}
}
}
+# endif
+# ifdef USE_BRAIN256R1
if (curves & IS_BRAIN256R1)
{
if (getEccParamById(IANA_BRAIN256R1, &curve) == 0)
@@ -138,6 +149,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves
}
}
}
+# endif
+# ifdef USE_SECP224R1
if (curves & IS_SECP224R1)
{
if (getEccParamById(IANA_SECP224R1, &curve) == 0)
@@ -149,6 +162,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves
}
}
}
+# endif
+# ifdef USE_BRAIN224R1
if (curves & IS_BRAIN224R1)
{
if (getEccParamById(IANA_BRAIN224R1, &curve) == 0)
@@ -160,6 +175,8 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves
}
}
}
+# endif
+# ifdef USE_SECP192R1
if (curves & IS_SECP192R1)
{
if (getEccParamById(IANA_SECP192R1, &curve) == 0)
@@ -171,6 +188,7 @@ void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves
}
}
}
+# endif
*len = listLen;
}
diff --git a/crypto/pubkey/ecc_priv.c b/crypto/pubkey/ecc_priv.c
index be8ffe1..943c569 100644
--- a/crypto/pubkey/ecc_priv.c
+++ b/crypto/pubkey/ecc_priv.c
@@ -201,10 +201,6 @@ int32_t psEccDsaSignCommon(psPool_t *pool, const psEccKey_t *privKey,
goto error; /* s = br (b == 1). */
}
}
- if (err != PS_SUCCESS)
- {
- goto error;
- }
if (blinding)
{
diff --git a/crypto/pubkey/pubkey.c b/crypto/pubkey/pubkey.c
index 4ac4741..806a49c 100644
--- a/crypto/pubkey/pubkey.c
+++ b/crypto/pubkey/pubkey.c
@@ -34,7 +34,7 @@
#include "../cryptoImpl.h"
-#if defined(USE_RSA) || defined(USE_ECC)
+# if defined(USE_RSA) || defined(USE_ECC) || defined(USE_DH) || defined(USE_X25519) || defined(USE_ED25519)
/******************************************************************************/
@@ -124,4 +124,3 @@ void psDeletePubKey(psPubKey_t **key)
/******************************************************************************/
#endif /* USE_RSA || USE_ECC */
-
diff --git a/crypto/pubkey/pubkey.h b/crypto/pubkey/pubkey.h
index 14020a4..d66188b 100644
--- a/crypto/pubkey/pubkey.h
+++ b/crypto/pubkey/pubkey.h
@@ -203,7 +203,7 @@ typedef struct psX25519Key
*/
typedef struct
{
-# if defined(USE_RSA) || defined(USE_ECC)
+# if defined(USE_RSA) || defined(USE_ECC) || defined(USE_DH) || defined(USE_X25519) || defined(USE_ED25519)
union
{
# ifdef USE_RSA
@@ -228,19 +228,35 @@ typedef struct
uint8_t type; /* PS_RSA, PS_ECC, PS_DH */
} psPubKey_t;
+# define PS_SIGN_OPTS_ECDSA_INCLUDE_SIZE (1ULL << 0)
+# define PS_SIGN_OPTS_USE_PREALLOCATED_OUTBUF (1ULL << 1)
+
typedef struct {
uint32_t flags;
int32_t rsaPssHashAlg;
unsigned char *rsaPssSalt;
psSize_t rsaPssSaltLen;
+ void *userData;
} psSignOpts_t;
-extern int32_t pkcs1Pad(const unsigned char *in, psSize_t inlen,
- unsigned char *out, psSize_t outlen,
- uint8_t cryptType, void *userPtr);
-extern int32_t pkcs1Unpad(const unsigned char *in, psSize_t inlen,
- unsigned char *out, psSize_t outlen,
- uint8_t decryptType);
+extern int32_t pkcs1Pad(const unsigned char *in,
+ psSize_t inlen,
+ unsigned char *out,
+ psSize_t outlen,
+ uint8_t cryptType,
+ void *userPtr);
+extern int32_t pkcs1Unpad(const unsigned char *in,
+ psSize_t inlen,
+ unsigned char *out,
+ psSize_t outlen,
+ uint8_t decryptType);
+extern int32_t pkcs1UnpadExt(const unsigned char *in,
+ psSize_t inlen,
+ unsigned char *out,
+ psSize_t outlen,
+ uint8_t decryptType,
+ psBool_t verifyUnpaddedLen,
+ psSize_t *unpaddedLen);
# if defined(USE_RSA) || defined(USE_ECC)
@@ -251,7 +267,7 @@ int32_t psHashLenToSigAlg(psSize_t hash_len,
purposes.
Compute a digest that is to be signed or whose signature is
- to be verified.
+ to be verified. Supports only single-part operation.
*/
psRes_t psComputeHashForSig(const unsigned char *dataBegin,
psSizeL_t dataLen,
@@ -260,6 +276,27 @@ psRes_t psComputeHashForSig(const unsigned char *dataBegin,
psSize_t * hashOutLen);
/** Algorithm-independent function for signing hashes.
+
+ The the signature algorithm is standard RSA (not PSS), the function
+ first wraps the input hash into a DigestInfo, unless the TLS 1.1 and
+ below signature algorithm (sigAlg == OID_RSA_TLS_SIG_ALG)
+ is used.
+
+ The supported values for sigAlg are:
+ OID_RSA_TLS_SIG_ALG (TLS 1.1 and below custom algorithm)
+ OID_SHA1_RSA_SIG (PKCS #1.5)
+ OID_SHA256_RSA_SIG (PKCS #1.5)
+ OID_SHA384_RSA_SIG (PKCS #1.5)
+ OID_RSASSA_PSS (RSASSA-PSS)
+ OID_SHA256_ECDSA_SIG (ECDSA)
+ OID_SHA384_ECDSA_SIG (ECDSA)
+ OID_SHA512_ECDSA_SIG (ECDSA)
+
+ It is also possible to use a more generic sigAlg ID.
+ In this case, psSign will deduce the hash algorithm to use
+ from inLen (e.g. inLen == 32 would imply SHA-256):
+ OID_RSA_PKCS15_SIG_ALG
+ OID_ECDSA_TLS_SIG_ALG
*/
int32_t psSignHash(psPool_t *pool,
psPubKey_t *privKey,
@@ -273,8 +310,9 @@ int32_t psSignHash(psPool_t *pool,
/** Algorithm-independent function for signing arbitrary
data.
- The data is first hashed if the signature algorithm
- is only able to sign hashes. TODO: not really. Fix.
+ This function is similar to psSignHash, expect that it also supports
+ signing arbitrary (non-hash) data with Ed25519, when sigAlg is
+ OID_ED25519_KEY_ALG.
*/
int32_t psSign(psPool_t *pool,
psPubKey_t *privKey,
diff --git a/crypto/pubkey/pubkey_parse_file.c b/crypto/pubkey/pubkey_parse_file.c
index fb35d8c..cbb01f0 100644
--- a/crypto/pubkey/pubkey_parse_file.c
+++ b/crypto/pubkey/pubkey_parse_file.c
@@ -514,10 +514,10 @@ psRes_t psPkcs8ParsePrivBin(psPool_t *pool,
#if 0
PKCS8_FAIL:
-#endif
psClearPubKey(key);
psTraceCrypto("Did not parse key in PKCS#8 parse\n");
return PS_FAILURE;
+#endif
}
# endif /* USE_PKCS8 */
diff --git a/crypto/pubkey/pubkey_sign.c b/crypto/pubkey/pubkey_sign.c
index 9dac397..d058343 100644
--- a/crypto/pubkey/pubkey_sign.c
+++ b/crypto/pubkey/pubkey_sign.c
@@ -51,25 +51,46 @@ int32_t psSignHashEcdsaInternal(psPool_t *pool,
psSize_t *outLen,
psSignOpts_t *opts)
{
- unsigned char tmp[140];
- psSize_t sigLen;
+ unsigned char tmp[142];
+ unsigned char *outBuf = tmp;
+ psSize_t sigLen = sizeof(tmp);
int32_t rc;
+ uint8_t includeSize = 0;
+ psBool_t usePreAllocatedOutBuf = PS_FALSE;
+
+ if (opts && (opts->flags & PS_SIGN_OPTS_USE_PREALLOCATED_OUTBUF))
+ {
+ usePreAllocatedOutBuf = PS_TRUE;
+ }
+ if (opts && (opts->flags & PS_SIGN_OPTS_ECDSA_INCLUDE_SIZE))
+ {
+ includeSize = 1;
+ }
sigLen = sizeof(tmp);
- rc = psEccDsaSign(pool, &privKey->key.ecc,
- in, inLen,
- tmp, &sigLen,
- 0, NULL);
+ rc = psEccDsaSign(pool,
+ &privKey->key.ecc,
+ in,
+ inLen,
+ outBuf,
+ &sigLen,
+ includeSize,
+ opts ? opts->userData : NULL);
if (rc < 0)
{
return rc;
}
- *out = psMalloc(pool, sigLen);
+ if (!usePreAllocatedOutBuf)
+ {
+ *out = psMalloc(pool, sigLen);
+ }
+ /* Check also the preallocated pointer. */
if (*out == NULL)
{
return PS_MEM_FAIL;
}
+
Memcpy(*out, tmp, sigLen);
*outLen = sigLen;
@@ -88,31 +109,71 @@ int32_t psSignHashRsa(psPool_t *pool,
psSignOpts_t *opts)
{
int32_t rc;
+ unsigned char tmp[512];
unsigned char *sig;
psSize_t sigLen;
+ psBool_t usePreAllocatedOutBuf = PS_FALSE;
- sigLen = privKey->keysize;
- sig = psMalloc(pool, sigLen);
- if (sig == NULL)
+ if (opts && (opts->flags & PS_SIGN_OPTS_USE_PREALLOCATED_OUTBUF))
{
- return PS_MEM_FAIL;
+ usePreAllocatedOutBuf = PS_TRUE;
}
- rc = psRsaEncryptPriv(pool,
- &privKey->key.rsa,
- in,
- inLen,
- sig,
- sigLen,
- NULL);
+ sigLen = privKey->keysize;
+
+ if (usePreAllocatedOutBuf)
+ {
+ sig = tmp;
+ }
+ else
+ {
+ sig = psMalloc(pool, sigLen);
+ if (sig == NULL)
+ {
+ return PS_MEM_FAIL;
+ }
+ }
+
+ if (sigAlg == OID_RSA_TLS_SIG_ALG)
+ {
+ /* TLS 1.0/1.1 style RSA signature. */
+ rc = psRsaEncryptPriv(pool,
+ &privKey->key.rsa,
+ in,
+ inLen,
+ sig,
+ sigLen,
+ opts ? opts->userData : NULL);
+ }
+ else
+ {
+ /* PKCS #1.5 signature. */
+ rc = privRsaEncryptSignedElement(pool,
+ &privKey->key.rsa,
+ in,
+ inLen,
+ sig,
+ sigLen,
+ opts ? opts->userData : NULL);
+ }
if (rc != PS_SUCCESS)
{
- psFree(sig, pool);
+ if (!usePreAllocatedOutBuf)
+ {
+ psFree(sig, pool);
+ }
return rc;
}
- *out = sig;
- *outLen = sigLen;
+ if (usePreAllocatedOutBuf)
+ {
+ Memcpy(*out, sig, sigLen);
+ }
+ else
+ {
+ *out = sig;
+ *outLen = sigLen;
+ }
return PS_SUCCESS;
}
@@ -134,24 +195,40 @@ int32_t psSignHash(psPool_t *pool,
case OID_SHA256_ECDSA_SIG:
case OID_SHA384_ECDSA_SIG:
case OID_SHA512_ECDSA_SIG:
- return psSignHashEcdsaInternal(pool, privKey, sigAlg,
+ case OID_ECDSA_TLS_SIG_ALG:
+ if (privKey->type == PS_ECC || privKey->type == PS_ED25519)
+ {
+ return psSignHashEcdsaInternal(pool, privKey, sigAlg,
in, inLen, out, outLen, opts);
+ }
+ break;
# endif /* USE_ECC */
# ifdef USE_PKCS1_PSS
case OID_RSASSA_PSS:
- return psRsaPssSignHash(pool, privKey, sigAlg,
+ if (privKey->type == PS_RSA)
+ {
+ return psRsaPssSignHash(pool, privKey, sigAlg,
in, inLen, out, outLen, opts);
+ }
+ break;
# endif /* USE_PKCS1_PSS */
# ifdef USE_RSA
case OID_SHA256_RSA_SIG:
case OID_SHA384_RSA_SIG:
case OID_SHA512_RSA_SIG:
- return psSignHashRsa(pool, privKey, sigAlg,
+ case OID_RSA_TLS_SIG_ALG:
+ case OID_RSA_PKCS15_SIG_ALG:
+ if (privKey->type == PS_RSA)
+ {
+ return psSignHashRsa(pool, privKey, sigAlg,
in, inLen, out, outLen, opts);
+ }
# endif
default:
- return PS_UNSUPPORTED_FAIL;
+ break;
}
+ psTraceCrypto("Invalid privKey type or sigAlg in psSignHash\n");
+ return PS_UNSUPPORTED_FAIL;
}
int32_t psSign(psPool_t *pool,
@@ -180,6 +257,11 @@ int32_t psSign(psPool_t *pool,
case OID_ED25519_KEY_ALG:
/* Ed25519 is used to sign arbitrary data directly without
pre-hashing. */
+ if (privKey->type != PS_ED25519)
+ {
+ psTraceCrypto("Invalid privKey type in psSign\n");
+ return PS_MEM_FAIL;
+ }
sigOut = psMalloc(pool, 64);
if (sigOut == NULL)
{
diff --git a/crypto/pubkey/pubkey_verify.c b/crypto/pubkey/pubkey_verify.c
index 8e494d9..407da2b 100644
--- a/crypto/pubkey/pubkey_verify.c
+++ b/crypto/pubkey/pubkey_verify.c
@@ -84,6 +84,7 @@ psRes_t psVerifySig(psPool_t *pool,
else
# endif /* USE_PKCS1_PSS */
{
+
if (opts && opts->msgIsDigestInfo)
{
/* RSA PKCS 1.5 verification of TLS signed elements. */
@@ -216,6 +217,26 @@ psRes_t psHashDataAndVerifySig(psPool_t *pool,
return rc;
}
+# ifdef USE_PKCS1_PSS
+static
+int32_t get_pss_hash_sig_alg(psVerifyOptions_t *opts)
+{
+ switch (opts->rsaPssHashAlg)
+ {
+ case PKCS1_SHA1_ID:
+ return OID_SHA1_RSA_SIG;
+ case PKCS1_SHA256_ID:
+ return OID_SHA256_RSA_SIG;
+ case PKCS1_SHA384_ID:
+ return OID_SHA384_RSA_SIG;
+ case PKCS1_SHA512_ID:
+ return OID_SHA512_RSA_SIG;
+ default:
+ return PS_UNSUPPORTED_FAIL;
+ }
+}
+# endif /* USE_PKCS1_PSS */
+
psRes_t psVerify(psPool_t *pool,
const unsigned char *dataBegin,
const psSizeL_t dataLen,
@@ -230,14 +251,22 @@ psRes_t psVerify(psPool_t *pool,
*verifyResult = PS_FALSE;
-# if defined (USE_PKCS1_PSS) && defined(USE_CL_RSA)
if (opts && opts->useRsaPss)
{
+# if defined (USE_PKCS1_PSS) && defined(USE_CL_RSA)
/* The crypto-cl API for RSA-PSS verification does not support
pre-hashing. */
needPreHash = PS_FALSE;
- }
# endif
+ if (needPreHash && signatureAlgorithm == OID_RSASSA_PSS)
+ {
+ /* psComputeHashForSig called by psHashDataAndVerifySig below
+ cannot operate on OID_RSASSA_PSS, since this ID does not
+ indicate the hash alg. So translate to one of the
+ OID_*_RSA_SIG IDs. */
+ signatureAlgorithm = get_pss_hash_sig_alg(opts);
+ }
+ }
# ifdef USE_ED25519
if (signatureAlgorithm == OID_ED25519_KEY_ALG)
diff --git a/crypto/pubkey/rsa_priv.c b/crypto/pubkey/rsa_priv.c
index 710ea37..3b43aa4 100644
--- a/crypto/pubkey/rsa_priv.c
+++ b/crypto/pubkey/rsa_priv.c
@@ -312,6 +312,7 @@ int32_t psRsaPssSignHash(psPool_t *pool,
sig = psMalloc(pool, modNBytes);
if (sig == NULL)
{
+ psFree(em, pool);
return PS_MEM_FAIL;
}
sigLen = modNBytes;
diff --git a/crypto/pubkey/rsa_pub.c b/crypto/pubkey/rsa_pub.c
index e91cc39..f1d57e0 100644
--- a/crypto/pubkey/rsa_pub.c
+++ b/crypto/pubkey/rsa_pub.c
@@ -37,14 +37,76 @@
/******************************************************************************/
/* TODO - the following functions are not implementation layer specific...
move to a common file?
-
- Matrix-specific starts at #ifdef USE_MATRIX_RSA
*/
+#ifdef USE_MATRIX_RSA
+
#define ASN_OVERHEAD_LEN_RSA_SHA2 19
#define ASN_OVERHEAD_LEN_RSA_SHA1 15
-#ifdef USE_MATRIX_RSA
+static
+int32_t psRsaDecryptPubExt(psPool_t *pool,
+ psRsaKey_t *key,
+ unsigned char *in,
+ psSize_t inlen,
+ unsigned char *out,
+ psSize_t *outlen,
+ psSize_t expectedLen,
+ void *data)
+{
+ int32_t err;
+ psSize_t ptLen, unpaddedLen;
+
+ if (inlen != key->size)
+ {
+ psTraceCrypto("Error on bad inlen parameter to psRsaDecryptPub\n");
+ return PS_ARG_FAIL;
+ }
+
+ ptLen = inlen;
+
+ /* Raw, in-place RSA decryption. */
+ err = psRsaCrypt(pool,
+ key,
+ in,
+ inlen,
+ in,
+ &ptLen,
+ PS_PUBKEY,
+ data);
+ if (err < PS_SUCCESS)
+ {
+ psTraceCrypto("Error performing psRsaDecryptPub\n");
+ return err;
+ }
+
+ /* In raw RSA decryption, size of the decrypted plaintext must equal
+ the size of the ciphertext. */
+ if (ptLen != inlen)
+ {
+ psTraceIntCrypto("Decrypted size error in psRsaDecryptPub %d\n", ptLen);
+ return PS_FAILURE;
+ }
+
+ /* Remove PKCS #1 padding and copy the decrypted and de-padded data
+ to out. */
+ err = pkcs1UnpadExt(in,
+ inlen,
+ out,
+ ptLen,
+ PS_PUBKEY,
+ PS_FALSE,
+ &unpaddedLen);
+ if (err < 0)
+ {
+ return err;
+ }
+
+ *outlen = unpaddedLen;
+
+ return PS_SUCCESS;
+}
+
int32_t pubRsaDecryptSignedElement(psPool_t *pool, psRsaKey_t *key,
unsigned char *in, psSize_t inlen,
unsigned char *out, psSize_t outlen,
@@ -65,121 +127,112 @@ int32_t pubRsaDecryptSignedElement(psPool_t *pool, psRsaKey_t *key,
signatureAlgorithm, data);
}
-int32_t pubRsaDecryptSignedElementExt(psPool_t *pool, psRsaKey_t *key,
- unsigned char *in, psSize_t inlen,
- unsigned char *out, psSize_t outlen,
- int32_t signatureAlgorithm, void *data)
+int32_t pubRsaDecryptSignedElementExt(psPool_t *pool,
+ psRsaKey_t *key,
+ unsigned char *in,
+ psSize_t inlen,
+ unsigned char *hashOut,
+ psSize_t hashOutLen,
+ int32_t signatureAlgorithm,
+ void *data)
{
- unsigned char *c, *front, *end;
- uint16_t outlenWithAsn, len, plen;
- int32_t oi, rc;
+ int32_t rc;
+ /* Reserve enough room for the largest supported decrypted and de-padded
+ plaintext: a SHA-512 DigestInfo (with NULL parameters). */
+ unsigned char decrypted[SHA512_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2];
+ psSize_t decryptedLen = sizeof(decrypted);
+ const unsigned char *prefix;
+ unsigned char *decPrefixStart;
+ psSize_t decPrefixLen;
- /* The issue here is that the standard RSA decryption routine requires
- the user to know the output length (usually just a hash size). With
- these "digitally signed elements" there is an algorithm
- identifier surrounding the hash so we use the known magic numbers as
- additional lengths of the wrapper since it is a defined ASN sequence,
- ASN algorithm oid, and ASN octet string */
- if (outlen == SHA256_HASH_SIZE)
+
+ /*
+ Check input arguments
+ */
+ if (key == NULL || in == NULL || hashOut == NULL)
{
- outlenWithAsn = SHA256_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2;
- }
- else if (outlen == SHA1_HASH_SIZE)
- {
- outlenWithAsn = SHA1_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA1;
- }
- else if (outlen == SHA384_HASH_SIZE)
- {
- outlenWithAsn = SHA384_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2;
- }
- else if (outlen == SHA512_HASH_SIZE)
- {
- outlenWithAsn = SHA512_HASH_SIZE + ASN_OVERHEAD_LEN_RSA_SHA2;
- }
- else
- {
- psTraceIntCrypto("Unsupported decryptSignedElement hash %d\n", outlen);
- return PS_FAILURE;
+ psTraceCrypto(
+ "ERROR: invalid argument in pubRsaDecryptSignedElement\n");
+ return PS_ARG_FAIL;
}
- front = c = psMalloc(pool, outlenWithAsn);
- if (front == NULL)
+ /*
+ Check that the hash length + signatureAlgorithm combination
+ is valid and that signatureAlgorithm is supported.
+ */
+ if (!psIsValidHashLenSigAlgCombination(hashOutLen, signatureAlgorithm))
{
- return PS_MEM_FAIL;
+ psTraceCrypto("Invalid hash length + signature alg combination: ");
+ psTraceIntCrypto("hash length: %d, ", hashOutLen);
+ psTraceIntCrypto("sig alg: %d\n", signatureAlgorithm);
+ return PS_ARG_FAIL;
}
- if ((rc = psRsaDecryptPub(pool, key, in, inlen, c, outlenWithAsn, data)) < 0)
+ /*
+ Perform RSA decryption + de-padding. After this, decryptedLen
+ becomes the length of the actual recovered DigestInfo.
+ */
+ rc = psRsaDecryptPubExt(pool,
+ key,
+ in,
+ inlen,
+ decrypted,
+ &decryptedLen,
+ hashOutLen,
+ data);
+ if (rc < 0)
{
- psFree(front, pool);
psTraceCrypto("Couldn't public decrypt signed element\n");
return rc;
}
- /* Parse it */
- end = c + outlenWithAsn;
+ /*
+ Two alternatives for verifying the decrypted RSA message
+ representative:
- /* @note Below we do a typecast to const to avoid a compiler warning,
- although it should be fine to pass a non const pointer into an
- api declaring it const, since it is just the API declaring the
- contents will not be modified within the API. */
- if (getAsnSequence((const unsigned char **) &c,
- (uint16_t) (end - c), &len) < 0)
+ - Comparison-based: directly compare the known parts of the
+ DigestInfo against a reference DigestInfo.
+ - Parsing based: parse the decrypted DigestInfo and check that
+ each component is as expected.
+
+ In both approaches, the variable part (the embedded digest itself)
+ needs to be directly compared against the reference digest. We don't
+ perform that part here; this must be done by the caller.
+
+ We use the comparison-based approach, since its safer and easier
+ to implement correctly, see e.g. Kühn et al.: "Variants of
+ Bleichenbacher's Low-Exponent Attack on PKCS#1 RSA Signatures".
+ */
+
+ /*
+ Based on the signatureAlgorithm we were given, get a reference
+ DigestInfo prefix to compare against.
+ */
+ prefix = psGetDigestInfoPrefix(decryptedLen, signatureAlgorithm);
+ if (prefix == NULL)
{
- psTraceCrypto("Couldn't parse signed element sequence\n");
- psFree(front, pool);
- return PS_FAILURE;
- }
- if (getAsnAlgorithmIdentifier((const unsigned char **) &c,
- (uint16_t) (end - c), &oi, &plen) < 0)
- {
- psTraceCrypto("Couldn't parse signed element octet string\n");
- psFree(front, pool);
- return PS_FAILURE;
+ return PS_ARG_FAIL;
}
- if (oi == OID_SHA256_ALG)
+ /*
+ Check that the decrypted DigestInfo prefix is valid.
+ If yes, copy the decrypted digest to out.
+ */
+ decPrefixStart = decrypted;
+ decPrefixLen = decryptedLen - hashOutLen;
+ if (memcmpct(prefix, decPrefixStart, decPrefixLen) == 0)
{
- psAssert(outlen == SHA256_HASH_SIZE);
+ Memcpy(hashOut, decrypted + decPrefixLen, hashOutLen);
+ rc = PS_SUCCESS;
}
- else if (oi == OID_SHA1_ALG)
- {
- psAssert(outlen == SHA1_HASH_SIZE);
- }
- else if (oi == OID_SHA384_ALG)
- {
- psAssert(outlen == SHA384_HASH_SIZE);
- }
-# ifdef USE_MD2
- else if (oi == OID_MD2_ALG)
- {
- psAssert(outlen == MD5_HASH_SIZE);
- }
-# endif /* USE_MD2 */
-# ifdef USE_MD5
- else if (oi == OID_MD5_ALG)
- {
- psAssert(outlen == MD5_HASH_SIZE);
- }
-# endif /* USE_MD5 */
else
{
- psAssert(outlen == SHA512_HASH_SIZE);
+ rc = PS_FAILURE;
}
- /* Note the last test here requires the buffer to be exactly outlen bytes */
- if ((end - c) < 1 || (*c++ != ASN_OCTET_STRING) ||
- getAsnLength((const unsigned char **) &c, (uint16_t) (end - c), &len) < 0 ||
- (uint32_t) (end - c) != outlen)
- {
+ Memset(decrypted, 0, sizeof(decrypted));
- psTraceCrypto("Couldn't parse signed element octet string\n");
- psFree(front, pool);
- return PS_FAILURE;
- }
- /* Will finally be sitting at the hash now */
- Memcpy(out, c, outlen);
- psFree(front, pool);
- return PS_SUCCESS;
+ return rc;
}
/******************************************************************************/
@@ -256,30 +309,29 @@ int32_t psRsaDecryptPub(psPool_t *pool, psRsaKey_t *key,
unsigned char *out, psSize_t outlen,
void *data)
{
- int32_t err;
+ int32_t rc;
psSize_t ptLen;
- if (inlen != key->size)
+ rc = psRsaDecryptPubExt(pool,
+ key,
+ in,
+ inlen,
+ out,
+ &ptLen,
+ outlen,
+ data);
+ if (rc != PS_SUCCESS)
{
- psTraceCrypto("Error on bad inlen parameter to psRsaDecryptPub\n");
- return PS_ARG_FAIL;
+ return rc;
}
- ptLen = inlen;
- if ((err = psRsaCrypt(pool, key, in, inlen, in, &ptLen,
- PS_PUBKEY, data)) < PS_SUCCESS)
+
+ if (ptLen != outlen)
{
- psTraceCrypto("Error performing psRsaDecryptPub\n");
- return err;
- }
- if (ptLen != inlen)
- {
- psTraceIntCrypto("Decrypted size error in psRsaDecryptPub %d\n", ptLen);
+ psTraceIntCrypto("Decrypted size error in psRsaDecryptPub %d\n",
+ ptLen);
return PS_FAILURE;
}
- if ((err = pkcs1Unpad(in, inlen, out, outlen, PS_PUBKEY)) < 0)
- {
- return err;
- }
+
return PS_SUCCESS;
}
diff --git a/crypto/test/algorithmTest.c b/crypto/test/algorithmTest.c
index 3e76217..1b092ea 100644
--- a/crypto/test/algorithmTest.c
+++ b/crypto/test/algorithmTest.c
@@ -4152,12 +4152,50 @@ static int32 psRsaKeyFormatTests(void)
unsigned char hashTbs[MAX_HASH_SIZE] = {0};
psSize_t hashTbsLen = sizeof(hashTbs);
/*
- echo -n "mytbs" \
- |openssl dgst -binary -sha256 \
- |openssl rsautl -inkey testkeys/RSA/2048_RSA_KEY.pem -sign \
+ echo -n "mytbs"
+ |openssl dgst -binary -sha256
+ |openssl pkeyutl -inkey testkeys/RSA/2048_RSA_KEY.pem -sign \
+ -pkeyopt rsa_padding_mode:pkcs1 -pkeyopt digest:sha256
|xxd -i
+
+ Note: this is a PKCS #1.5 signature (used in TLS 1.2). The hash
+ of "mytbs" is first wrapped into a DigestInfo.
*/
- unsigned char expectedSig[] =
+ unsigned char expectedSig1[] =
+ {
+ 0x7f, 0x91, 0xb1, 0x24, 0xc4, 0x85, 0x12, 0x2b, 0x06, 0xef, 0xf1, 0x20,
+ 0xbb, 0xde, 0x2b, 0x48, 0x39, 0x9b, 0x66, 0xfb, 0x1e, 0x6c, 0x8a, 0x77,
+ 0x60, 0xec, 0x96, 0x21, 0xe3, 0x8a, 0xa0, 0xcc, 0x2f, 0x0a, 0x97, 0x6d,
+ 0xa7, 0xd3, 0x6a, 0xb0, 0x89, 0xc2, 0x7a, 0xa4, 0x09, 0xbc, 0x87, 0xfa,
+ 0xe3, 0x54, 0xc2, 0xde, 0xb3, 0x7d, 0x35, 0x55, 0xda, 0xb1, 0x58, 0xc2,
+ 0x8d, 0xce, 0xfa, 0xd1, 0x5e, 0xd1, 0xd4, 0xef, 0x25, 0x22, 0x92, 0x8c,
+ 0xdc, 0x62, 0x3a, 0xdd, 0x87, 0x8b, 0xcf, 0xfc, 0xa1, 0x6c, 0xaf, 0x83,
+ 0xff, 0xbf, 0x29, 0x09, 0x05, 0xef, 0x76, 0x3a, 0xab, 0xba, 0xde, 0x3b,
+ 0x16, 0xc9, 0x8e, 0x2a, 0x54, 0xe4, 0x60, 0x27, 0x57, 0xa8, 0x8c, 0xf0,
+ 0x21, 0x05, 0xa6, 0x8e, 0x52, 0xc7, 0xe8, 0x79, 0x46, 0x46, 0x09, 0x7c,
+ 0x75, 0xca, 0x7f, 0xc6, 0x98, 0x19, 0xcf, 0x98, 0xdf, 0x31, 0x11, 0x12,
+ 0x66, 0x23, 0x56, 0xa6, 0xe9, 0x29, 0x71, 0xe4, 0x0f, 0x13, 0xb7, 0x1c,
+ 0x7e, 0xeb, 0x8b, 0x22, 0xc6, 0x98, 0x64, 0xde, 0x76, 0xfd, 0xa4, 0xbd,
+ 0x11, 0xea, 0xf5, 0x2c, 0x90, 0x12, 0xc0, 0x1c, 0xe3, 0x79, 0x19, 0xc1,
+ 0x2f, 0x07, 0x0b, 0x25, 0x94, 0xf8, 0xc8, 0xac, 0x85, 0x87, 0xae, 0xbb,
+ 0xe5, 0x24, 0xa8, 0x11, 0xeb, 0xc0, 0x46, 0x02, 0xa4, 0x39, 0xd3, 0xe6,
+ 0xe1, 0x12, 0xfc, 0x60, 0x44, 0x5f, 0x68, 0x1d, 0x06, 0x6a, 0xcb, 0x26,
+ 0x3e, 0xeb, 0xa3, 0xca, 0xba, 0x70, 0xb9, 0xd8, 0x32, 0x72, 0xf4, 0x26,
+ 0x2c, 0x5d, 0x5d, 0xee, 0x75, 0x20, 0xf7, 0x52, 0xcc, 0x9c, 0x9f, 0x50,
+ 0xf5, 0xb2, 0x2c, 0x67, 0x2e, 0x6b, 0xc1, 0xfd, 0x6c, 0xa0, 0x4b, 0x63,
+ 0x52, 0xe7, 0xb0, 0x4a, 0xcb, 0x87, 0x2c, 0x73, 0x1c, 0xfe, 0xfb, 0xc6,
+ 0xab, 0xb7, 0x81, 0x6d
+ };
+ /*
+ echo -n "mytbs" \
+ |openssl dgst -binary -sha256 \
+ |openssl rsautl -inkey testkeys/RSA/2048_RSA_KEY.pem -sign \
+ |xxd -i
+
+ Note: this is a DigestInfoless signature (like the signatures used
+ in TLS 1.1 and below, but with SHA-256 instead of MD5-SHA1.
+ */
+ unsigned char expectedSig2[] =
{
0x27, 0x05, 0x37, 0x60, 0x71, 0x8f, 0x96, 0x9c, 0xbc, 0xc7, 0x29, 0x65,
0xf5, 0xc7, 0x8e, 0xf4, 0x94, 0x8d, 0x2f, 0x23, 0xca, 0x88, 0xd1, 0x68,
@@ -4182,13 +4220,16 @@ static int32 psRsaKeyFormatTests(void)
0xb2, 0x65, 0xe1, 0x56, 0xdc, 0xfe, 0xe8, 0xfc, 0x59, 0x8e, 0x00, 0x2f,
0xac, 0x99, 0xac, 0xb4
};
- unsigned char *sig = NULL;
- psSize_t sigLen;
+ unsigned char *sig1 = NULL;
+ psSize_t sigLen1;
+ unsigned char *sig2 = NULL;
+ psSize_t sigLen2;
psPubKey_t privKey;
psPubKey_t pubKey;
int32_t rc;
psRes_t rc2;
psBool_t verifyOk;
+ psVerifyOptions_t verifyOpts = {0};
/* Hash some data and sign the hash with 2048_RSA_KEY, then parse
2048_RSA_PUB from PEM and try to verify the signature. */
@@ -4215,28 +4256,58 @@ static int32 psRsaKeyFormatTests(void)
goto out_fail;
}
+ /* OID_SHA256_RSA_SIG produces a PKCS #1.5 signature,
+ where hashTbs is first wrapped into a DigestInfo. */
rc = psSign(NULL,
&privKey,
OID_SHA256_RSA_SIG,
hashTbs,
hashTbsLen,
- &sig,
- &sigLen,
+ &sig1,
+ &sigLen1,
NULL);
if (rc != PS_SUCCESS)
{
- _psTrace("psSign failed\n");
+ _psTrace("psSign failed for sig1\n");
goto out_fail;
}
-
- if (sigLen != sizeof(expectedSig))
+ if (sigLen1 != sizeof(expectedSig1))
{
- _psTrace("psSign output sig has wrong len\n");
+ _psTrace("psSign output sig1 has wrong len\n");
goto out_fail;
}
- if (Memcmp(sig, expectedSig, sigLen))
+ if (Memcmp(sig1, expectedSig1, sigLen1))
{
- _psTrace("psSign output sig is wrong\n");
+ psTraceBytes("Got: ", sig1, sigLen1);
+ psTraceBytes("Expected: ", expectedSig1, sigLen1);
+ _psTrace("psSign output sig1 is wrong\n");
+ goto out_fail;
+ }
+ /* OID_RSA_TLS_SIG_ALG produces a TLS 1.1 style signature
+ (without DigestInfo encoding). */
+ rc = psSign(NULL,
+ &privKey,
+ OID_RSA_TLS_SIG_ALG,
+ hashTbs,
+ hashTbsLen,
+ &sig2,
+ &sigLen2,
+ NULL);
+ if (rc != PS_SUCCESS)
+ {
+ _psTrace("psSign failed for sig2\n");
+ goto out_fail;
+ }
+ if (sigLen2 != sizeof(expectedSig2))
+ {
+ _psTrace("psSign output sig2 has wrong len\n");
+ goto out_fail;
+ }
+ if (Memcmp(sig2, expectedSig2, sigLen2))
+ {
+ psTraceBytes("Got: ", sig2, sigLen2);
+ psTraceBytes("Expected: ", expectedSig2, sigLen2);
+ _psTrace("psSign output sig2 is wrong\n");
goto out_fail;
}
@@ -4254,30 +4325,67 @@ static int32 psRsaKeyFormatTests(void)
pubKey.type = PS_RSA;
+ verifyOpts.msgIsDigestInfo = PS_TRUE;
rc2 = psVerify(NULL,
tbs,
tbsLen,
- sig,
- sigLen,
+ sig1,
+ sigLen1,
&pubKey,
OID_SHA256_RSA_SIG,
&verifyOk,
- NULL);
+ &verifyOpts);
if (rc2 != PS_SUCCESS && !verifyOk)
{
- _psTrace("psVerify failed\n");
+ _psTrace("psVerify failed for sig 1\n");
+ goto out_fail;
+ }
+
+ verifyOpts.msgIsDigestInfo = PS_FALSE;
+ rc2 = psVerify(NULL,
+ tbs,
+ tbsLen,
+ sig2,
+ sigLen2,
+ &pubKey,
+ OID_SHA256_RSA_SIG,
+ &verifyOk,
+ &verifyOpts);
+ if (rc2 != PS_SUCCESS && !verifyOk)
+ {
+ _psTrace("psVerify failed for sig 2\n");
+ goto out_fail;
+ }
+
+ /* Now corrupt the sig a bit and ensure verification fails. */
+ sig2[4] = 0x0a;
+ verifyOpts.msgIsDigestInfo = PS_FALSE;
+ rc2 = psVerify(NULL,
+ tbs,
+ tbsLen,
+ sig2,
+ sigLen2,
+ &pubKey,
+ OID_SHA256_RSA_SIG,
+ &verifyOk,
+ &verifyOpts);
+ if (verifyOk || rc2 == PS_SUCCESS)
+ {
+ _psTrace("psVerify wrong result for corrupted sig 2\n");
goto out_fail;
}
psClearPubKey(&privKey);
psRsaClearKey(&pubKey.key.rsa);
- psFree(sig, NULL);
+ psFree(sig1, NULL);
+ psFree(sig2, NULL);
_psTrace(" PASSED\n");
return PS_SUCCESS;
out_fail:
- psFree(sig, NULL);
+ psFree(sig1, NULL);
+ psFree(sig2, NULL);
return PS_FAILURE;
}
# endif /* USE_PRIVATE_KEY_PARSING */
@@ -6391,6 +6499,7 @@ static int32_t psEccTestParsePriv(void)
NULL);
if (rc != PS_SUCCESS)
{
+ psEccDeleteKey(&key1);
goto fail;
}
@@ -6446,6 +6555,138 @@ fail:
return rc;
}
+static int32_t psEccTestSigVer()
+{
+ int32_t rc = PS_FAILURE;
+ psPubKey_t key_noparam, key_noparam_nopub;
+ /* This is testkeys/EC/256_EC_KEY.noparam.pem in DER form. */
+ unsigned char p256_key_noparam[] =
+ {
+ 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x5c, 0xe9, 0x89, 0xc5, 0xb1,
+ 0x53, 0xa0, 0x02, 0x3c, 0x90, 0xbe, 0x3a, 0x2a, 0x73, 0xb2, 0x08, 0x16,
+ 0xc3, 0xed, 0xbc, 0xd5, 0xd6, 0x67, 0x26, 0x10, 0x4e, 0xec, 0x79, 0x28,
+ 0x0f, 0xbf, 0xcb, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+ 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x5f, 0xad, 0x62,
+ 0x02, 0x42, 0x48, 0xba, 0xfb, 0xe2, 0x88, 0xd8, 0x7f, 0xb9, 0x72, 0xcb,
+ 0x28, 0xae, 0xc3, 0x8a, 0x1e, 0xc3, 0x0e, 0x9c, 0x7d, 0x7a, 0xa4, 0xb5,
+ 0x7f, 0xda, 0xbd, 0x46, 0x5a, 0xb9, 0x95, 0x39, 0xe0, 0x44, 0x51, 0x71,
+ 0xba, 0xe3, 0xb3, 0x40, 0xf2, 0x54, 0xfd, 0x23, 0x84, 0xb2, 0xea, 0x2a,
+ 0x84, 0xa3, 0x4f, 0xd7, 0xb0, 0x08, 0xba, 0x6e, 0x80, 0xc3, 0xeb, 0xdf,
+ 0x2f
+ };
+ /* This is testkeys/EC/256_EC_KEY.noparam.nopub.pem in DER form. */
+ unsigned char p256_key_noparam_nopub[] =
+ {
+ 0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, 0x5c, 0xe9, 0x89, 0xc5, 0xb1,
+ 0x53, 0xa0, 0x02, 0x3c, 0x90, 0xbe, 0x3a, 0x2a, 0x73, 0xb2, 0x08, 0x16,
+ 0xc3, 0xed, 0xbc, 0xd5, 0xd6, 0x67, 0x26, 0x10, 0x4e, 0xec, 0x79, 0x28,
+ 0x0f, 0xbf, 0xcb, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+ 0x03, 0x01, 0x07
+ };
+ unsigned char tbs[] = {'i', 'n', 's', 'i', 'd', 'e'};
+ unsigned char tbs_hash[64] = {0};
+ psSize_t tbs_hash_len = sizeof(tbs_hash);
+ unsigned char sig[150] = {0};
+ psSize_t sig_len = sizeof(sig);
+ int32 verifyResult = 0;
+
+ /*
+ This is a simple pairwise sign + verify test. But in addition, it
+ tests that signing is possible without a public key:
+ key_noparam and key_noparam_nopub contain the same private key,
+ but key_noparam_nopub omits the optional public key.
+ */
+
+ _psTrace(" P-256 sig ver test...");
+
+ rc = psParseUnknownPrivKeyMem(NULL,
+ p256_key_noparam,
+ sizeof(p256_key_noparam),
+ NULL,
+ &key_noparam);
+ if (rc < 0) {
+ _psTrace("psParseUnknownPrivKeyMem failed\n");
+ rc = PS_FAILURE;
+ goto out_no_key_1;
+ }
+
+ rc = psParseUnknownPrivKeyMem(NULL,
+ p256_key_noparam_nopub,
+ sizeof(p256_key_noparam_nopub),
+ NULL,
+ &key_noparam_nopub);
+ if (rc < 0) {
+ _psTrace("psParseUnknownPrivKeyMem failed\n");
+ rc = PS_FAILURE;
+ goto out_no_key_2;
+ }
+
+ rc = psComputeHashForSig(tbs,
+ sizeof(tbs),
+ OID_SHA256_ECDSA_SIG,
+ tbs_hash,
+ &tbs_hash_len);
+ if (rc != PS_SUCCESS)
+ {
+ _psTraceInt("psComputeHashForSig failed: %d\n", rc);
+ rc = PS_FAILURE;
+ goto out;
+ }
+
+ rc = psEccDsaSign(NULL,
+ &key_noparam_nopub.key.ecc,
+ tbs_hash,
+ tbs_hash_len,
+ sig,
+ &sig_len,
+ 0,
+ NULL);
+ if (rc != PS_SUCCESS)
+ {
+ _psTraceInt("psEccDsaSign failed : %d\n", rc);
+ rc = PS_FAILURE;
+ goto out;
+ }
+
+ rc = psEccDsaVerify(NULL,
+ &key_noparam.key.ecc,
+ tbs_hash,
+ tbs_hash_len,
+ sig,
+ sig_len,
+ &verifyResult,
+ NULL);
+ if (rc != PS_SUCCESS)
+ {
+ _psTraceInt("psEccDsaVerify failed : %d\n", rc);
+ rc = PS_FAILURE;
+ goto out;
+ }
+ if (verifyResult != 1)
+ {
+ _psTrace("verification failed failed\n");
+ rc = PS_FAILURE;
+ goto out;
+ }
+
+out:
+ psEccClearKey(&key_noparam_nopub.key.ecc);
+out_no_key_2:
+ psEccClearKey(&key_noparam.key.ecc);
+out_no_key_1:
+
+ if (rc == PS_SUCCESS)
+ {
+ _psTrace(" PASSED\n");
+ }
+ else
+ {
+ _psTrace(" FAILED\n");
+ }
+
+ return rc;
+}
+
static int32_t psEccTest(void)
{
int32_t rc;
@@ -6482,6 +6723,12 @@ static int32_t psEccTest(void)
return rc;
}
+ rc = psEccTestSigVer();
+ if (rc != PS_SUCCESS)
+ {
+ return rc;
+ }
+
return PS_SUCCESS;
}
#endif /* USE_ECC */
diff --git a/crypto/test/eccTest.c b/crypto/test/eccTest.c
index 7499e57..c9ae90d 100644
--- a/crypto/test/eccTest.c
+++ b/crypto/test/eccTest.c
@@ -40,7 +40,7 @@ int sign_verify_test1(psEccKey_t *privKey,
if (psEccDsaVerify(pool, pubKey,
in, sizeof(in),
buffer + 2, *buffer_size_result_p - 2,
- &validateStatus, NULL) < 0 || validateStatus != 1)
+ &validateStatus, NULL) < 0)
{
printf("Operation failed: Ecc Verify\n");
return 2;
diff --git a/doc/CHANGES_v4.0.html b/doc/CHANGES_v4.0.html
index 1e8ad36..08ce9e3 100644
--- a/doc/CHANGES_v4.0.html
+++ b/doc/CHANGES_v4.0.html
@@ -8,7 +8,25 @@
-MatrixSSL 4.0 changelog
+MatrixSSL 4.x changelog
+Changes between 4.0.0 and 4.0.1 [November 2018]
+This version improves the security of RSA PKCS #1.5 signature verification and adds better support for run-time security configuration.
+
+TLS:
+
+Added a run-time security callback feature (matrixSslRegisterSecurityCallback). The security callback can allow or deny a cryptographic operation based on the operation type and the key size. Currently only authentication and key exchange operations are supported. The default security callback supports pre-defined security profiles (matrixSslSetSecurityProfile).
+Added an example security profile: WPA3 1.0 Enterprise 192-bit mode restrictions for EAP-TLS.
+Added support for the TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ciphersuite.
+Changed the way how protocol version IDs are stored internally and rewrote most of the version negotiation code. This is almost entirely an internal code refactoring. To the API user, the only visible change is that version selection APIs now take in an argument of type psProtocolVersion_t instead of int32_t. See the API reference guide for details.
+Refactored ServerKeyExchange signature generation and verification code.
+
+Crypto:
+
+Changed from a parsing-based to a comparison-based approach in DigestInfo validation when verifying RSA PKCS #1.5 signatures. There are no known practical attacks against the old code, but the comparison-based approach is theoretically more sound. Thanks to Sze Yiu Chau from Purdue University for pointing this out.
+(MatrixSSL FIPS Edition only:) Fix DH key exchange when using DH parameter files containing optional privateValueLength argument.
+psX509AuthenticateCert now uses the common psVerifySig API for signature verification. Previously, CRLs and certificates used different code paths for signature verification.
+
+
Changes between 3.9.5 and 4.0.0 [August 2018]
This version adds support for RFC 8446 (TLS 1.3), new APIs for configuring session options as well as fixes to security vulnerabilities.
diff --git a/doc/CHANGES_v4.0.md b/doc/CHANGES_v4.0.md
index f27903d..b62b68a 100644
--- a/doc/CHANGES_v4.0.md
+++ b/doc/CHANGES_v4.0.md
@@ -1,4 +1,52 @@
-# MatrixSSL 4.0 changelog
+# MatrixSSL 4.x changelog
+
+## Changes between 4.0.0 and 4.0.1 [November 2018]
+
+This version improves the security of RSA PKCS #1.5 signature
+verification and adds better support for run-time security
+configuration.
+
+- TLS:
+
+ * Added a run-time security callback feature
+ (matrixSslRegisterSecurityCallback). The security callback can
+ allow or deny a cryptographic operation based on the operation
+ type and the key size. Currently only authentication and key
+ exchange operations are supported. The default security callback
+ supports pre-defined security profiles
+ (matrixSslSetSecurityProfile).
+
+ * Added an example security profile: WPA3 1.0 Enterprise 192-bit
+ mode restrictions for EAP-TLS.
+
+ * Added support for the TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ ciphersuite.
+
+ * Changed the way how protocol version IDs are stored internally
+ and rewrote most of the version negotiation code. This is almost
+ entirely an internal code refactoring. To the API user, the only
+ visible change is that version selection APIs now take in an
+ argument of type psProtocolVersion_t instead of int32_t. See the
+ API reference guide for details.
+
+ * Refactored ServerKeyExchange signature generation and
+ verification code.
+
+- Crypto:
+
+ * Changed from a parsing-based to a comparison-based approach in
+ DigestInfo validation when verifying RSA PKCS #1.5
+ signatures. There are no known practical attacks against the old
+ code, but the comparison-based approach is theoretically more
+ sound. Thanks to Sze Yiu Chau from Purdue University for
+ pointing this out.
+
+ * (MatrixSSL FIPS Edition only:) Fix DH key exchange when using DH
+ parameter files containing optional privateValueLength argument.
+
+ * psX509AuthenticateCert now uses the common psVerifySig API for
+ signature verification. Previously, CRLs and certificates used
+ different code paths for signature verification.
## Changes between 3.9.5 and 4.0.0 [August 2018]
diff --git a/doc/CHANGES_v4.0.txt b/doc/CHANGES_v4.0.txt
index cd3e2fd..69936c7 100644
--- a/doc/CHANGES_v4.0.txt
+++ b/doc/CHANGES_v4.0.txt
@@ -1,6 +1,55 @@
-MATRIXSSL 4.0 CHANGELOG
+MATRIXSSL 4.X CHANGELOG
+
+
+Changes between 4.0.0 and 4.0.1 [November 2018]
+
+This version improves the security of RSA PKCS #1.5 signature
+verification and adds better support for run-time security
+configuration.
+
+- TLS:
+
+ - Added a run-time security callback
+ feature (matrixSslRegisterSecurityCallback). The security
+ callback can allow or deny a cryptographic operation based on
+ the operation type and the key size. Currently only
+ authentication and key exchange operations are supported. The
+ default security callback supports pre-defined security
+ profiles (matrixSslSetSecurityProfile).
+
+ - Added an example security profile: WPA3 1.0 Enterprise 192-bit
+ mode restrictions for EAP-TLS.
+
+ - Added support for the
+ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ciphersuite.
+
+ - Changed the way how protocol version IDs are stored internally
+ and rewrote most of the version negotiation code. This is almost
+ entirely an internal code refactoring. To the API user, the only
+ visible change is that version selection APIs now take in an
+ argument of type psProtocolVersion_t instead of int32_t. See the
+ API reference guide for details.
+
+ - Refactored ServerKeyExchange signature generation and
+ verification code.
+
+- Crypto:
+
+ - Changed from a parsing-based to a comparison-based approach in
+ DigestInfo validation when verifying RSA PKCS #1.5 signatures.
+ There are no known practical attacks against the old code, but
+ the comparison-based approach is theoretically more sound.
+ Thanks to Sze Yiu Chau from Purdue University for pointing
+ this out.
+
+ - (MatrixSSL FIPS Edition only:) Fix DH key exchange when using DH
+ parameter files containing optional privateValueLength argument.
+
+ - psX509AuthenticateCert now uses the common psVerifySig API for
+ signature verification. Previously, CRLs and certificates used
+ different code paths for signature verification.
Changes between 3.9.5 and 4.0.0 [August 2018]
diff --git a/doc/MatrixSSL_API.pdf b/doc/MatrixSSL_API.pdf
index ee114eb..ef5ff6e 100644
Binary files a/doc/MatrixSSL_API.pdf and b/doc/MatrixSSL_API.pdf differ
diff --git a/matrixssl/Makefile b/matrixssl/Makefile
index 5add0aa..76fa90f 100644
--- a/matrixssl/Makefile
+++ b/matrixssl/Makefile
@@ -19,12 +19,15 @@ SRC:=\
matrixssl.c \
matrixsslKeys.c \
matrixsslApi.c \
+ matrixsslInitVer.c \
+ matrixsslSecConfig.c \
prf.c \
psk.c \
sslDecode.c \
sslEncode.c \
tlsDefaults.c \
tlsSelectKeys.c \
+ tlsSigVer.c \
tlsTrace.c \
tls13Authenticate.c \
tls13CipherSuite.c \
diff --git a/matrixssl/cipherSuite.c b/matrixssl/cipherSuite.c
index bdfa222..382c90f 100644
--- a/matrixssl/cipherSuite.c
+++ b/matrixssl/cipherSuite.c
@@ -205,7 +205,7 @@ int32 csAesGcmEncrypt(void *ssl, unsigned char *pt,
meet this uniqueness requirement can significantly degrade security.
The nonce_explicit MAY be the 64-bit sequence number. */
# ifdef USE_DTLS
- if (lssl->flags & SSL_FLAGS_DTLS)
+ if (NGTD_VER(lssl, v_dtls_any))
{
Memcpy(nonce + 4, lssl->epoch, 2);
Memcpy(nonce + 4 + 2, lssl->rsn, 6);
@@ -223,8 +223,8 @@ int32 csAesGcmEncrypt(void *ssl, unsigned char *pt,
Memcpy(aad, lssl->sec.seq, 8);
}
aad[8] = lssl->outRecType;
- aad[9] = lssl->majVer;
- aad[10] = lssl->minVer;
+ aad[9] = psEncodeVersionMaj(GET_NGTD_VER(lssl));
+ aad[10] = psEncodeVersionMin(GET_NGTD_VER(lssl));
aad[11] = ptLen >> 8 & 0xFF;
aad[12] = ptLen & 0xFF;
@@ -233,7 +233,7 @@ int32 csAesGcmEncrypt(void *ssl, unsigned char *pt,
psAesGetGCMTag(ctx, 16, ct + ptLen);
# ifdef USE_DTLS
- if (lssl->flags & SSL_FLAGS_DTLS)
+ if (NGTD_VER(lssl, v_dtls_any))
{
return len;
}
@@ -269,7 +269,7 @@ int32 csAesGcmDecrypt(void *ssl, unsigned char *ct,
len -= TLS_EXPLICIT_NONCE_LEN;
# ifdef USE_DTLS
- if (lssl->flags & SSL_FLAGS_DTLS)
+ if (NGTD_VER(lssl, v_dtls_any))
{
/* In the case of DTLS the counter is formed from the concatenation of
the 16-bit epoch with the 48-bit sequence number. */
@@ -285,8 +285,8 @@ int32 csAesGcmDecrypt(void *ssl, unsigned char *ct,
}
ctLen = len - TLS_GCM_TAG_LEN;
aad[8] = lssl->rec.type;
- aad[9] = lssl->majVer;
- aad[10] = lssl->minVer;
+ aad[9] = psEncodeVersionMaj(GET_NGTD_VER(lssl));
+ aad[10] = psEncodeVersionMin(GET_NGTD_VER(lssl));
aad[11] = ctLen >> 8 & 0xFF;
aad[12] = ctLen & 0xFF;
@@ -374,7 +374,8 @@ int32 csAesDecrypt(void *ssl, unsigned char *ct,
/******************************************************************************/
/* #define DEBUG_CHACHA20_POLY1305_IETF_CIPHER_SUITE */
-#ifdef USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE
+#if defined(USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE) || defined(USE_CHACHA20_POLY1305_IETF)
+
int32 csChacha20Poly1305IetfInit(sslSec_t *sec, int32 type, uint32 keysize)
{
psRes_t err;
@@ -450,8 +451,8 @@ int32 csChacha20Poly1305IetfEncrypt(void *ssl, unsigned char *pt,
i = TLS_AEAD_SEQNB_LEN;
aad[i++] = lssl->outRecType;
- aad[i++] = lssl->majVer;
- aad[i++] = lssl->minVer;
+ aad[i++] = psEncodeVersionMaj(GET_NGTD_VER(lssl));
+ aad[i++] = psEncodeVersionMin(GET_NGTD_VER(lssl));
aad[i++] = ptLen >> 8 & 0xFF;
aad[i++] = ptLen & 0xFF;
@@ -540,8 +541,8 @@ int32 csChacha20Poly1305IetfDecrypt(void *ssl, unsigned char *ct,
ctLen = len - TLS_CHACHA20_POLY1305_IETF_TAG_LEN;
aad[i++] = lssl->rec.type;
- aad[i++] = lssl->majVer;
- aad[i++] = lssl->minVer;
+ aad[i++] = psEncodeVersionMaj(GET_NGTD_VER(lssl));
+ aad[i++] = psEncodeVersionMin(GET_NGTD_VER(lssl));
aad[i++] = ctLen >> 8 & 0xFF;
aad[i++] = ctLen & 0xFF;
@@ -723,38 +724,39 @@ static int32 csShaGenerateMac(void *sslv, unsigned char type,
ssl_t *ssl = (ssl_t *) sslv;
unsigned char mac[MAX_HASH_SIZE];
-# ifdef USE_TLS
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (NGTD_VER(ssl, v_tls_with_hmac))
{
-# ifdef USE_SHA256
- if (ssl->nativeEnMacSize == SHA256_HASH_SIZE ||
- ssl->nativeEnMacSize == SHA384_HASH_SIZE)
+ switch (ssl->nativeEnMacSize)
{
- tlsHMACSha2(ssl, HMAC_CREATE, type, data, len, mac,
- ssl->nativeEnMacSize);
- }
- else
- {
-# endif
+# ifdef USE_SHA256
+ case SHA256_HASH_SIZE:
+# ifdef USE_SHA384
+ case SHA384_HASH_SIZE:
+# endif
+ tlsHMACSha2(ssl, HMAC_CREATE, type,
+ data, len, mac, ssl->nativeEnMacSize);
+ break;
+# endif /* USE_SHA256 */
# ifdef USE_SHA1
- tlsHMACSha1(ssl, HMAC_CREATE, type, data, len, mac);
-# endif
-# ifdef USE_SHA256
- }
-# endif
+ case SHA1_HASH_SIZE:
+ tlsHMACSha1(ssl, HMAC_CREATE, type,
+ data, len, mac);
+ break;
+# endif /* USE_SHA1 */
+ default:
+ return PS_ARG_FAIL;
+ }
}
else
{
-# endif /* USE_TLS */
-# ifndef DISABLE_SSLV3
- ssl3HMACSha1(ssl->sec.writeMAC, ssl->sec.seq, type, data,
- len, mac);
+# ifdef DISABLE_SSLV3
+ return PS_ARG_FAIL;
# else
- return PS_ARG_FAIL;
-# endif /* DISABLE_SSLV3 */
-# ifdef USE_TLS
-}
-# endif /* USE_TLS */
+ ssl3HMACSha1(ssl->sec.writeMAC, ssl->sec.seq, type,
+ data, len, mac);
+# endif
+ }
+
Memcpy(macOut, mac, ssl->enMacSize);
return ssl->enMacSize;
@@ -766,7 +768,7 @@ static int32 csShaVerifyMac(void *sslv, unsigned char type,
unsigned char buf[MAX_HASH_SIZE];
ssl_t *ssl = (ssl_t *) sslv;
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (NGTD_VER(ssl, v_tls_with_hmac))
{
switch (ssl->nativeDeMacSize)
{
@@ -814,7 +816,7 @@ static int32 csMd5GenerateMac(void *sslv, unsigned char type,
ssl_t *ssl = (ssl_t *) sslv;
# ifdef USE_TLS
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (NGTD_VER(ssl, v_tls_with_hmac))
{
tlsHMACMd5(ssl, HMAC_CREATE, type, data, len, mac);
}
@@ -841,7 +843,7 @@ static int32 csMd5VerifyMac(void *sslv, unsigned char type, unsigned char *data,
ssl_t *ssl = (ssl_t *) sslv;
# ifdef USE_TLS
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (NGTD_VER(ssl, v_tls_with_hmac))
{
tlsHMACMd5(ssl, HMAC_VERIFY, type, data, len, buf);
}
@@ -880,18 +882,20 @@ const static sslCipherSpec_t supportedCiphers[] = {
256 ciphers max.
The ordering of the ciphers is grouped and sub-grouped by the following:
- 1. Non-deprecated
- 2. Ephemeral
- 3. Authentication Method (PKI > PSK > anon)
- 4. Hash Strength (SHA384 > SHA256 > SHA > MD5)
- 5. Cipher Strength (AES256 > AES128 > 3DES > ARC4 > SEED > IDEA > NULL)
- 6. PKI Key Exchange (DHE > ECDHE > ECDH > RSA > PSK)
- 7. Cipher Mode (GCM > CBC)
- 8. PKI Authentication Method (ECDSA > RSA > PSK)
+ 1. TLS 1.3
+ 2. Non-deprecated
+ 3. Ephemeral
+ 4. Authentication Method (PKI > PSK > anon)
+ 5. Hash Strength (SHA384 > SHA256 > SHA > MD5)
+ 6. Cipher Strength (AES256 > AES128 > 3DES > ARC4 > SEED > IDEA > NULL)
+ 7. PKI Key Exchange (DHE > ECDHE > ECDH > RSA > PSK)
+ 8. Cipher Mode (GCM > CBC)
+ 9. PKI Authentication Method (ECDSA > RSA > PSK)
*/
+#ifdef USE_TLS_1_3
/* TLS 1.3 ciphersuites. */
-#ifdef USE_TLS_AES_128_GCM_SHA256
+# ifdef USE_TLS_AES_128_GCM_SHA256
{ TLS_AES_128_GCM_SHA256, /* ident */
CS_TLS13, /* type */
CRYPTO_FLAGS_AES | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA2, /* flags */
@@ -904,9 +908,9 @@ const static sslCipherSpec_t supportedCiphers[] = {
csAesGcmDecryptTls13, /* decrypt */
NULL, /* generateMac */
NULL }, /* verifyMac */
-#endif /* TLS_AES_128_GCM_SHA256 */
+# endif /* TLS_AES_128_GCM_SHA256 */
-#ifdef USE_TLS_AES_256_GCM_SHA384
+# ifdef USE_TLS_AES_256_GCM_SHA384
{ TLS_AES_256_GCM_SHA384, /* ident */
CS_TLS13, /* type */
CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA3, /* flags */
@@ -919,9 +923,9 @@ const static sslCipherSpec_t supportedCiphers[] = {
csAesGcmDecryptTls13, /* decrypt */
NULL, /* generateMac */
NULL }, /* verifyMac */
-#endif /* TLS_AES_128_GCM_SHA256 */
+# endif /* TLS_AES_128_GCM_SHA256 */
-#ifdef USE_TLS_CHACHA20_POLY1305_SHA256
+# ifdef USE_TLS_CHACHA20_POLY1305_SHA256
{ TLS_CHACHA20_POLY1305_SHA256, /* ident */
CS_TLS13, /* type */
CRYPTO_FLAGS_CHACHA | CRYPTO_FLAGS_SHA2, /* flags */
@@ -934,8 +938,8 @@ const static sslCipherSpec_t supportedCiphers[] = {
csChacha20Poly1305IetfDecryptTls13, /* decrypt */
NULL, /* generateMac */
NULL }, /* verifyMac */
-#endif /* USE_TLS_CHACHA20_POLY1305_SHA256 */
-
+# endif /* USE_TLS_CHACHA20_POLY1305_SHA256 */
+#endif /* USE_TLS_1_3 */
/* Ephemeral ciphersuites */
#ifdef USE_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
{ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, /* ident */
@@ -1027,6 +1031,21 @@ const static sslCipherSpec_t supportedCiphers[] = {
csShaVerifyMac },
#endif /* USE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 */
+#ifdef USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ { TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
+ CS_DHE_RSA,
+ CRYPTO_FLAGS_AES256 | CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_SHA3,
+ 0, /* macSize */
+ 32, /* keySize */
+ 4, /* ivSize */
+ 0, /* blocksize */
+ csAesGcmInit,
+ csAesGcmEncrypt,
+ csAesGcmDecrypt,
+ NULL,
+ NULL },
+#endif /* USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 */
+
#ifdef USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
CS_DHE_RSA,
@@ -1222,6 +1241,7 @@ const static sslCipherSpec_t supportedCiphers[] = {
csShaVerifyMac },
#endif /* USE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA */
+
#ifdef USE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
{ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
CS_ECDHE_RSA,
@@ -1976,7 +1996,7 @@ static psRes_t validateKeyForExtensions(ssl_t *ssl, const sslCipherSpec_t *spec,
}
# ifdef USE_TLS_1_3
- if (NEGOTIATED_TLS_1_3(ssl))
+ if (NGTD_VER(ssl, v_tls_1_3_any))
{
int32_t rc;
@@ -1991,7 +2011,7 @@ static psRes_t validateKeyForExtensions(ssl_t *ssl, const sslCipherSpec_t *spec,
# ifdef USE_TLS_1_2
/* hash and sig alg is a TLS 1.2 only extension */
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
/* Walk through each cert and confirm the client will be able to
deal with them based on the algorithms provided in the extension */
@@ -2146,8 +2166,9 @@ static psRes_t haveCorrectKeyAlg(sslIdentity_t *idKey,
# ifdef VALIDATE_KEY_MATERIAL
static psRes_t haveKeyForAlg(sslKeys_t *keys,
- int32 keyAlg, int32 sigType,
- int anyOrFirst)
+ int32 keyAlg,
+ int32 sigType,
+ int anyOrFirst)
{
sslIdentity_t *idKey;
@@ -2178,8 +2199,8 @@ static psRes_t haveKeyForAlg(sslKeys_t *keys,
SSL_FLAGS_SERVER test so no #else cases should be needed
*/
int32_t haveKeyMaterial(const ssl_t *ssl,
- const sslCipherSpec_t *cipher,
- short reallyTest)
+ const sslCipherSpec_t *cipher,
+ short reallyTest)
{
int32 cipherType = cipher->type;
@@ -2188,6 +2209,7 @@ int32_t haveKeyMaterial(const ssl_t *ssl,
if (cipherType == CS_TLS13)
{
psSize_t hashLen;
+
/* The only meaningful check we can make here for TLS1.3 is that
when using PSK we choose such cipher suite that matches the
chosen PSK length */
@@ -2502,10 +2524,15 @@ chooseCS(ssl_t *ssl, uint32_t *suites, psSize_t nsuites)
{
sslKeys_t *givenKey = NULL, *keys;
#ifdef USE_IDENTITY_CERTIFICATES
- sslIdentity_t *idKey, *fallbackId = NULL;
+ sslIdentity_t *idKey;
#endif
psBool_t sniUsed = PS_FALSE;
+#ifdef USE_CS_FALLBACK
+#ifdef USE_IDENTITY_CERTIFICATES
+ sslIdentity_t *fallbackId = NULL;
+#endif
const sslCipherSpec_t *fallbackSuite = NULL;
+#endif
int i;
/* prefer keys loaded using SNI */
@@ -2545,7 +2572,7 @@ chooseCS(ssl_t *ssl, uint32_t *suites, psSize_t nsuites)
When using TLS 1.3, just pick the first supported TLS 1.3 suite from
the client's list. No need to check against key material.*/
# ifdef USE_TLS_1_3
- if (NEGOTIATED_TLS_1_3(ssl) && spec->type == CS_TLS13)
+ if (NGTD_VER(ssl, v_tls_1_3_any) && spec->type == CS_TLS13)
{
ssl->cipher = spec;
# ifdef USE_IDENTITY_CERTIFICATES
@@ -2643,7 +2670,7 @@ chooseCS(ssl_t *ssl, uint32_t *suites, psSize_t nsuites)
if (spec->type == CS_ECDH_RSA || spec->type == CS_ECDH_ECDSA)
{
reqKeyAlg = OID_ECDSA_KEY_ALG;
- reqSigType = (spec->type == CS_ECDH_RSA) ? RSA_TYPE_SIG : ECDSA_TYPE_SIG;
+ reqSigType = ECDSA_TYPE_SIG;
}
else
{
@@ -2667,6 +2694,7 @@ chooseCS(ssl_t *ssl, uint32_t *suites, psSize_t nsuites)
KEY_ALG_FIRST) < 0 ||
validateKeyForExtensions(ssl, spec, idKey) < 0)
{
+#ifdef USE_CS_FALLBACK
/* This key is not suitable, but might be a good
fallback, if nothing else is found. */
if (fallbackSuite == NULL)
@@ -2674,6 +2702,7 @@ chooseCS(ssl_t *ssl, uint32_t *suites, psSize_t nsuites)
fallbackSuite = spec;
fallbackId = idKey;
}
+#endif
continue;
}
/* this suite and key suits the requirements. */
@@ -2685,6 +2714,10 @@ chooseCS(ssl_t *ssl, uint32_t *suites, psSize_t nsuites)
}
#endif /* USE_IDENTITY_CERTIFICATES */
}
+
+#ifdef USE_CS_FALLBACK
+ /* XXX: MatrixSSL 3 series used to fall back to what client proposed on
+ absense of key material. This is now gone. */
if (fallbackSuite != NULL)
{
/* maybe productive to try the fallback. */
@@ -2694,6 +2727,7 @@ chooseCS(ssl_t *ssl, uint32_t *suites, psSize_t nsuites)
#endif
goto out_ok;
}
+#endif
psTraceErrr("No matching keys for any requested cipher suite.\n");
return PS_UNSUPPORTED_FAIL; /* Server can't match anything */
@@ -2916,6 +2950,34 @@ psBool_t isAlpnSuite(const sslCipherSpec_t *spec)
return PS_FALSE;
}
+# ifdef USE_SEC_CONFIG
+static
+psBool_t ciphersuiteAllowedBySecConfig(ssl_t *ssl, const uint16_t id)
+{
+ psSize_t j;
+
+ if (ssl->supportedCiphersLen > 0)
+ {
+ /* The NULL ciphersuite is used before encryption is turned on.
+ We have to support that. */
+ if (id == SSL_NULL_WITH_NULL_NULL)
+ {
+ return PS_TRUE;
+ }
+ for (j = 0; j < ssl->supportedCiphersLen; j++)
+ {
+ if (ssl->supportedCiphers[j] == id)
+ {
+ return PS_TRUE;
+ }
+ }
+ return PS_FALSE;
+ }
+
+ return PS_TRUE;
+}
+# endif /* USE_SEC_CONFIG */
+
/******************************************************************************/
/**
Lookup and validate the given cipher spec ID.
@@ -2924,7 +2986,7 @@ psBool_t isAlpnSuite(const sslCipherSpec_t *spec)
@param[in] id The official ciphersuite id to find.
@return A pointer to the cipher suite structure, if configured in build
and appropriate for the constraints in 'ssl'.
- If not defined or apprppriate, return NULL.
+ If not defined or appropriate, return NULL.
*/
const sslCipherSpec_t *sslGetCipherSpec(const ssl_t *ssl, uint16_t id)
{
@@ -2934,6 +2996,7 @@ const sslCipherSpec_t *sslGetCipherSpec(const ssl_t *ssl, uint16_t id)
uint8_t j;
#endif /* USE_SERVER_SIDE_SSL */
+ /* Loop over the global supportedCiphers array. */
i = 0;
do
{
@@ -2974,6 +3037,18 @@ const sslCipherSpec_t *sslGetCipherSpec(const ssl_t *ssl, uint16_t id)
return NULL;
}
#endif
+
+#ifdef USE_SEC_CONFIG
+ if (!ciphersuiteAllowedBySecConfig(ssl, id))
+ {
+ psTracePrintCiphersuiteName(0,
+ "Ciphersuite not allowed by sec config",
+ id,
+ PS_TRUE);
+ psTraceErrr("Invalid ciphersuite selection\n");
+ return NULL;
+ }
+#endif /* USE_SEC_CONFIG */
#ifdef USE_SERVER_SIDE_SSL
/* Globally disabled? */
if (disabledCipherFlags[i >> 5] & (1UL << (i & 31)))
@@ -2996,66 +3071,60 @@ const sslCipherSpec_t *sslGetCipherSpec(const ssl_t *ssl, uint16_t id)
}
}
#endif /* USE_SERVER_SIDE_SSL */
+
+ /*
+ Unusable because protocol doesn't allow?
+
+ Only perform this check if we already know which versions
+ we have been configured to support. If we have been called
+ during a resumption attempt to retrieve the ciphersuite stored
+ in the sessionId_t struct, we have not initialized our list
+ of supported versions yet. TODO: better fix.
+ */
+ if (GET_SUPP_VER(ssl) != v_undefined)
+ {
#ifdef USE_TLS_1_2
- /* Unusable because protocol doesn't allow? */
-# ifdef USE_DTLS
- if (ssl->majVer == DTLS_MAJ_VER &&
- ssl->minVer != DTLS_1_2_MIN_VER)
- {
- if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 ||
- supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2)
+ if (!SUPP_VER(ssl, v_tls_sha2) || NGTD_VER(ssl, v_tls_no_sha2))
{
- psTraceIntInfo(
- "Matched cipher suite %d but only allowed in DTLS 1.2\n", id);
- return NULL;
+ if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 ||
+ supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2)
+ {
+ psTraceIntInfo("Matched cipher suite %d " \
+ "but not allowed in (D)TLS <1.2\n", id);
+ return NULL;
+ }
}
- }
- if (!(ssl->flags & SSL_FLAGS_DTLS))
- {
-# endif
# ifdef USE_TLS_1_3
- /* Reject non-TLS1.3 cipher suites if TLS1.3 has been negotiated */
- if (ssl->flags & SSL_FLAGS_TLS_1_3_NEGOTIATED)
- {
- if (supportedCiphers[i].type != CS_TLS13 &&
- supportedCiphers[i].type != CS_NULL)
+ /* Reject non-TLS1.3 cipher suites if TLS1.3 has been negotiated */
+ if (NGTD_VER(ssl, v_tls_1_3_any))
{
- return NULL;
+ if (supportedCiphers[i].type != CS_TLS13 &&
+ supportedCiphers[i].type != CS_NULL)
+ {
+ return NULL;
+ }
}
- }
- /* The server should reject TLS 1.3 cipher suites if TLS 1.3
- is not enabled. */
- if (IS_SERVER(ssl) && !USING_TLS_1_3(ssl))
- {
- if (supportedCiphers[i].type == CS_TLS13)
+ /* The server should reject TLS 1.3 cipher suites if TLS 1.3
+ is not enabled. */
+ if (IS_SERVER(ssl) && !SUPP_VER(ssl, v_tls_1_3_any))
{
- return NULL;
+ if (supportedCiphers[i].type == CS_TLS13)
+ {
+ return NULL;
+ }
}
- }
-# endif
- if (ssl->minVer < TLS_1_2_MIN_VER)
- {
- if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 ||
- supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2)
+# endif /* USE_TLS_1_3 */
+ if (NGTD_VER(ssl, v_dtls_1_2 | v_tls_1_2 | v_tls_1_3_any))
{
- psTraceIntInfo(
- "Matched cipher suite %d but not allowed in TLS <1.2\n", id);
- return NULL;
+ if (supportedCiphers[i].flags & CRYPTO_FLAGS_MD5)
+ {
+ psTraceIntInfo("Not allowing MD5 suite %d in TLS 1.2/1.3\n",
+ id);
+ return NULL;
+ }
}
- }
- if (ssl->minVer == TLS_1_2_MIN_VER || USING_TLS_1_3(ssl))
- {
- if (supportedCiphers[i].flags & CRYPTO_FLAGS_MD5)
- {
- psTraceIntInfo("Not allowing MD5 suite %d in TLS 1.2/1.3\n",
- id);
- return NULL;
- }
- }
-# ifdef USE_DTLS
- }
-# endif
#endif /* TLS_1_2 */
+ } /* if (GET_SUPP_VER(ssl) != v_undefined */
/** Check restrictions by HTTP2 (set by ALPN extension).
This should filter out all ciphersuites specified in:
@@ -3089,8 +3158,8 @@ const sslCipherSpec_t *sslGetCipherSpec(const ssl_t *ssl, uint16_t id)
}
}
- /* The suite is available. Want to reject if current key material
- does not support? */
+ /* The suite is available. Want to reject if current key material
+ does not support? */
#ifdef VALIDATE_KEY_MATERIAL
if (ssl->keys != NULL)
{
@@ -3127,20 +3196,29 @@ const sslCipherSpec_t *sslGetCipherSpec(const ssl_t *ssl, uint16_t id)
Write out a list of the supported cipher suites to the caller's buffer
First 2 bytes are the number of cipher suite bytes, the remaining bytes are
the cipher suites, as two byte, network byte order values.
+
+ If called with encodeList == PS_FALSE, only returns lengths of the list.
*/
-int32_t sslGetCipherSpecList(ssl_t *ssl, unsigned char *c, int32 len,
- int32 addScsv)
+static
+int32_t sslGetCipherSpecListExt(const ssl_t *ssl,
+ unsigned char *c,
+ int32 len,
+ int32 addScsv,
+ psBool_t encodeList)
{
unsigned char *end, *p;
unsigned short i;
int32 ignored;
- if (len < 4)
+ if (encodeList)
{
- return -1;
+ if (len < 4)
+ {
+ return -1;
+ }
+ end = c + len;
+ p = c; c += 2;
}
- end = c + len;
- p = c; c += 2;
ignored = 0;
for (i = 0; supportedCiphers[i].ident != SSL_NULL_WITH_NULL_NULL; i++)
@@ -3149,8 +3227,7 @@ int32_t sslGetCipherSpecList(ssl_t *ssl, unsigned char *c, int32 len,
/* The SHA-2 based cipher suites are TLS 1.2 only so don't send
those if the user has requested a lower protocol in
NewClientSession */
-# ifdef USE_DTLS
- if (ssl->majVer == DTLS_MAJ_VER && ssl->minVer != DTLS_1_2_MIN_VER)
+ if (!SUPP_VER(ssl, v_tls_sha2))
{
if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 ||
supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2)
@@ -3159,39 +3236,31 @@ int32_t sslGetCipherSpecList(ssl_t *ssl, unsigned char *c, int32 len,
continue;
}
}
- if (!(ssl->flags & SSL_FLAGS_DTLS))
- {
-# endif
- if (ssl->minVer != TLS_1_2_MIN_VER)
- {
- if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 ||
- supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2)
- {
- ignored += 2;
- continue;
- }
- }
-
-# ifdef USE_DTLS
- }
-# endif
#endif /* TLS_1_2 */
# ifdef USE_TLS_1_3
/* At this point remove the cipher if TLS1.3 is
the only enabled version */
- if (USING_ONLY_TLS_1_3(ssl) && supportedCiphers[i].type != CS_TLS13)
+ if (!SUPP_VER(ssl, v_tls_legacy)
+ && supportedCiphers[i].type != CS_TLS13)
{
ignored += 2;
continue;
}
/* Remove TLS1.3 ciphers in case TLS1.3 is not enabled */
- if (!(USING_TLS_1_3(ssl)) &&
- (supportedCiphers[i].type == CS_TLS13))
+ if (!SUPP_VER(ssl, v_tls_1_3_any)
+ && (supportedCiphers[i].type == CS_TLS13))
{
ignored += 2;
continue;
}
# endif /* USE_TLS_1_3 */
+# ifdef USE_SEC_CONFIG
+ if (!ciphersuiteAllowedBySecConfig(ssl, supportedCiphers[i].ident))
+ {
+ ignored += 2;
+ continue;
+ }
+# endif /* USE_SEC_CONFIG */
#ifdef VALIDATE_KEY_MATERIAL
if (haveKeyMaterial(ssl, &supportedCiphers[i], 0) != PS_SUCCESS)
{
@@ -3199,27 +3268,36 @@ int32_t sslGetCipherSpecList(ssl_t *ssl, unsigned char *c, int32 len,
continue;
}
#endif
- if (end - c < 2)
+
+ if (encodeList)
{
- return PS_MEM_FAIL;
+ if (end - c < 2)
+ {
+ return PS_MEM_FAIL;
+ }
+ *c = (unsigned char) ((supportedCiphers[i].ident & 0xFF00) >> 8); c++;
+ *c = (unsigned char) (supportedCiphers[i].ident & 0xFF); c++;
}
- *c = (unsigned char) ((supportedCiphers[i].ident & 0xFF00) >> 8); c++;
- *c = (unsigned char) (supportedCiphers[i].ident & 0xFF); c++;
}
+
i *= 2;
i -= (unsigned short) ignored;
+
#ifdef ENABLE_SECURE_REHANDSHAKES
if (addScsv == 1)
{
# ifdef USE_CLIENT_SIDE_SSL
- ssl->extFlags.req_renegotiation_info = 1;
+ ((ssl_t*)ssl)->extFlags.req_renegotiation_info = 1;
# endif
- if (end - c < 2)
+ if (encodeList)
{
- return PS_MEM_FAIL;
+ if (end - c < 2)
+ {
+ return PS_MEM_FAIL;
+ }
+ *c = ((TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xFF00) >> 8); c++;
+ *c = TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xFF; c++;
}
- *c = ((TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xFF00) >> 8); c++;
- *c = TLS_EMPTY_RENEGOTIATION_INFO_SCSV & 0xFF; c++;
i += 2;
}
#endif
@@ -3230,21 +3308,40 @@ int32_t sslGetCipherSpecList(ssl_t *ssl, unsigned char *c, int32 len,
{
/** Add the fallback signalling ciphersuite.
@see https://tools.ietf.org/html/rfc7507 */
- if (end - c < 2)
+ if (encodeList)
{
- return PS_MEM_FAIL;
+ if (end - c < 2)
+ {
+ return PS_MEM_FAIL;
+ }
+ *c = (TLS_FALLBACK_SCSV >> 8) & 0xFF; c++;
+ *c = TLS_FALLBACK_SCSV & 0xFF; c++;
}
- *c = (TLS_FALLBACK_SCSV >> 8) & 0xFF; c++;
- *c = TLS_FALLBACK_SCSV & 0xFF; c++;
i += 2;
}
#endif
- *p = (unsigned char) (i >> 8); p++;
- *p = (unsigned char) (i & 0xFF);
+ if (encodeList)
+ {
+ *p = (unsigned char) (i >> 8); p++;
+ *p = (unsigned char) (i & 0xFF);
+ }
+
return i + 2;
}
+int32_t sslGetCipherSpecList(ssl_t *ssl,
+ unsigned char *c,
+ int32 len,
+ int32 addScsv)
+{
+ return sslGetCipherSpecListExt(ssl,
+ c,
+ len,
+ addScsv,
+ PS_TRUE);
+}
+
/******************************************************************************/
/*
Return the length of the cipher spec list, including initial length bytes,
@@ -3252,65 +3349,11 @@ int32_t sslGetCipherSpecList(ssl_t *ssl, unsigned char *c, int32 len,
*/
int32_t sslGetCipherSpecListLen(const ssl_t *ssl)
{
- int32 i, ignored;
-
- ignored = 0;
- for (i = 0; supportedCiphers[i].ident != SSL_NULL_WITH_NULL_NULL; i++)
- {
-#ifdef USE_TLS_1_2
- /* The SHA-2 based cipher suites are TLS 1.2 only so don't send
- those if the user has requested a lower protocol in
- NewClientSession */
-# ifdef USE_DTLS
- if (ssl->majVer == DTLS_MAJ_VER && ssl->minVer != DTLS_1_2_MIN_VER)
- {
- if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 ||
- supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2)
- {
- ignored += 2;
- continue;
- }
- }
- if (!(ssl->flags & SSL_FLAGS_DTLS))
- {
-# endif
- if (ssl->minVer != TLS_1_2_MIN_VER)
- {
- if (supportedCiphers[i].flags & CRYPTO_FLAGS_SHA3 ||
- supportedCiphers[i].flags & CRYPTO_FLAGS_SHA2)
- {
- ignored += 2;
- continue;
- }
- }
-# ifdef USE_DTLS
- }
-# endif
-#endif /* USE_TLS_1_2 */
-# ifdef USE_TLS_1_3
- /* At this point remove the cipher if TLS1.3 is
- the only enabled version */
- if (USING_ONLY_TLS_1_3(ssl) && supportedCiphers[i].type != CS_TLS13)
- {
- ignored += 2;
- continue;
- }
- /* Remove TLS1.3 ciphers in case TLS1.3 is not enabled */
- if (!(USING_TLS_1_3(ssl)) &&
- (supportedCiphers[i].type == CS_TLS13))
- {
- ignored += 2;
- continue;
- }
-# endif /* USE_TLS_1_3 */
-#ifdef VALIDATE_KEY_MATERIAL
- if (haveKeyMaterial(ssl, &supportedCiphers[i], 0) != PS_SUCCESS)
- {
- ignored += 2;
- }
-#endif
- }
- return (i * 2) + 2 - ignored;
+ return sslGetCipherSpecListExt(ssl,
+ NULL,
+ 0,
+ 0,
+ PS_FALSE);
}
/******************************************************************************/
diff --git a/matrixssl/dtls.c b/matrixssl/dtls.c
index 8b8fb22..9abcc6e 100644
--- a/matrixssl/dtls.c
+++ b/matrixssl/dtls.c
@@ -244,7 +244,7 @@ int32 dtlsWriteCertificateRequest(psPool_t *pool, ssl_t *ssl, int32 certLen,
# endif
*tmp++ = RSA_SIGN;
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
/* RFC: "The interaction of the certificate_types and
supported_signature_algorithms fields is somewhat complicated.
diff --git a/matrixssl/extDecode.c b/matrixssl/extDecode.c
index 3315e41..be4e7a6 100644
--- a/matrixssl/extDecode.c
+++ b/matrixssl/extDecode.c
@@ -252,7 +252,7 @@ int32 parseClientHelloExtensions(ssl_t *ssl, unsigned char **cp, unsigned short
}
# if defined(USE_TLS_1_2) && defined(USE_CERT_PARSE)
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
if (!ssl->hashSigAlg)
{
@@ -348,7 +348,7 @@ static int ClientHelloExt(ssl_t *ssl,
int i;
int32_t rc;
# ifdef USE_ECC_CIPHER_SUITE
- unsigned short dataLen, curveId;
+ unsigned short dataLen;
uint32 ecFlags;
# elif defined USE_OCSP_RESPONSE
unsigned short dataLen;
@@ -714,6 +714,7 @@ static int ClientHelloExt(ssl_t *ssl,
}
ssl->extFlags.got_cookie = 1;
break;
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
case EXT_KEY_SHARE:
case EXT_KEY_SHARE_PRE_DRAFT_23:
psTracePrintExtensionParse(ssl, EXT_KEY_SHARE);
@@ -787,6 +788,7 @@ static int ClientHelloExt(ssl_t *ssl,
psSizeL_t keyExchangeLen = 0;
psSize_t n;
psBool_t foundSupportedCurve = PS_FALSE;
+ unsigned short groupName;
/* 2-byte NamedGroup ID */
if (extLen < 2)
@@ -795,23 +797,23 @@ static int ClientHelloExt(ssl_t *ssl,
ssl->err = SSL_ALERT_HANDSHAKE_FAILURE;
return MATRIXSSL_ERROR;
}
- curveId = *c << 8; c++;
- curveId += *c; c++;
+ groupName = *c << 8; c++;
+ groupName += *c; c++;
extLen -= 2;
clientSharesLen -= 2;
psTracePrintTls13NamedGroup(INDENT_EXTENSION + 1,
- NULL, curveId, PS_TRUE);
- if (tls13AddPeerKeyShareGroup(ssl, curveId) < 0)
+ NULL, groupName, PS_TRUE);
+ if (tls13AddPeerKeyShareGroup(ssl, groupName) < 0)
{
ssl->err = SSL_ALERT_INTERNAL_ERROR;
return MATRIXSSL_ERROR;
}
- if (tls13WeSupportGroup(ssl, curveId))
+ if (tls13WeSupportGroup(ssl, groupName))
{
psTracePrintTls13NamedGroup(INDENT_NEGOTIATED_PARAM,
"Found supported group",
- curveId,
+ groupName,
PS_TRUE);
foundSupportedCurve = PS_TRUE;
}
@@ -837,7 +839,7 @@ static int ClientHelloExt(ssl_t *ssl,
rc = tls13ImportPublicValue(ssl,
c,
keyExchangeLen,
- curveId);
+ groupName);
if (rc < 0)
{
return rc;
@@ -846,7 +848,7 @@ static int ClientHelloExt(ssl_t *ssl,
/* We will still iterate over the rest of the entries,
but will not try to import another public value. */
importedPeerPubValue = PS_TRUE;
- ssl->tls13NegotiatedGroup = curveId;
+ ssl->tls13NegotiatedGroup = groupName;
}
c += keyExchangeLen;
@@ -856,7 +858,7 @@ static int ClientHelloExt(ssl_t *ssl,
}
ssl->extFlags.got_key_share = 1;
break;
-
+# endif /* USE_ONLY_PSK_CIPHER_SUITE */
case EXT_SUPPORTED_VERSIONS:
/* This is defined in TLS 1.3 draft 22, but TLS 1.2 implementations
SHOULD also be able to parse this. */
@@ -902,6 +904,8 @@ static int ClientHelloExt(ssl_t *ssl,
PS_FALSE);
while (dataLen >= 2 && extLen >= 2)
{
+ unsigned short curveId;
+
curveId = *c << 8; c++;
curveId += *c; c++;
dataLen -= 2;
@@ -1551,7 +1555,7 @@ static int ServerHelloExt(ssl_t *ssl, unsigned short extType, unsigned short ext
if (rc < 0)
{
- if (ssl->minVer >= TLS_1_2_MIN_VER)
+ if (ACTV_VER(ssl, v_tls_with_unsupported_extension_alert))
{
/* This alert was added only in 1.2 */
ssl->err = SSL_ALERT_UNSUPPORTED_EXTENSION;
diff --git a/matrixssl/hsDecode.c b/matrixssl/hsDecode.c
index 00b24fd..0f39fc3 100644
--- a/matrixssl/hsDecode.c
+++ b/matrixssl/hsDecode.c
@@ -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
diff --git a/matrixssl/hsHash.c b/matrixssl/hsHash.c
index 62a4e73..73ed3c2 100644
--- a/matrixssl/hsHash.c
+++ b/matrixssl/hsHash.c
@@ -68,7 +68,7 @@
int32_t sslInitHSHash(ssl_t *ssl)
{
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* Don't allow CLIENT_HELLO message retransmit to reset hash */
if (ssl->retransmit)
@@ -138,7 +138,7 @@ int32_t sslUpdateHSHash(ssl_t *ssl, const unsigned char *in, psSize_t len)
#endif
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* Don't update handshake hashes on resends. Already been through here */
if (ssl->retransmit)
@@ -152,16 +152,13 @@ int32_t sslUpdateHSHash(ssl_t *ssl, const unsigned char *in, psSize_t len)
/* Keep a running total of each for greatest RFC support when it comes
to the CertificateVerify message. Although, trying to be smart
about MD5 and SHA-2 based on protocol version. */
- if ((ssl->majVer == 0 && ssl->minVer == 0) ||
-# ifdef USE_DTLS
- ssl->minVer == DTLS_1_2_MIN_VER ||
-# endif
- ssl->minVer == TLS_1_2_MIN_VER)
+ if (!VersionNegotiationComplete(ssl)
+ || NGTD_VER(ssl, v_tls_sha2))
{
psSha256Update(&ssl->sec.msgHashSha256, in, len);
# ifdef USE_SHA1
psSha1Update(&ssl->sec.msgHashSha1, in, len);
-# endif
+# endif /* USE_SHA1 */
# ifdef USE_SHA384
psSha384Update(&ssl->sec.msgHashSha384, in, len);
# endif
@@ -169,7 +166,7 @@ int32_t sslUpdateHSHash(ssl_t *ssl, const unsigned char *in, psSize_t len)
psSha512Update(&ssl->sec.msgHashSha512, in, len);
# endif
}
-# endif
+# endif /* USE_TLS_1_2 */
# ifndef USE_ONLY_TLS_1_2
/* Below TLS 1.2, the hash is always the md5sha1 hash. If we negotiate
@@ -285,10 +282,11 @@ static int32_t tlsGenerateFinishedHash(ssl_t *ssl,
*/
if (senderFlag >= 0)
{
- Memcpy(tmp, (senderFlag & SSL_FLAGS_SERVER) ? LABEL_SERVER : LABEL_CLIENT,
- FINISHED_LABEL_SIZE);
+ Memcpy(tmp,
+ (senderFlag & SSL_FLAGS_SERVER) ? LABEL_SERVER : LABEL_CLIENT,
+ FINISHED_LABEL_SIZE);
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (ACTV_VER(ssl, v_tls_sha2))
{
if (ssl->cipher->flags & CRYPTO_FLAGS_SHA3)
{
@@ -334,7 +332,7 @@ static int32_t tlsGenerateFinishedHash(ssl_t *ssl,
/* Overloading this function to handle the client auth needs of
handshake hashing. */
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (ACTV_VER(ssl, v_tls_sha2))
{
psSha256_t sha256_backup;
psSha256Cpy(&sha256_backup, sha256);
@@ -422,7 +420,7 @@ int32_t extMasterSecretSnapshotHSHash(ssl_t *ssl, unsigned char *out,
*outLen = 0;
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (ACTV_VER(ssl, v_tls_sha2))
{
if (ssl->cipher->flags & CRYPTO_FLAGS_SHA3)
{
@@ -472,7 +470,7 @@ int32_t sslSnapshotHSHash(ssl_t *ssl, unsigned char *out, int32 senderFlag)
int32 len = PS_FAILURE;
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* Don't allow FINISHED message retransmit to re-calc hash */
if (ssl->retransmit)
@@ -484,7 +482,7 @@ int32_t sslSnapshotHSHash(ssl_t *ssl, unsigned char *out, int32 senderFlag)
# endif /* USE_DTLS */
# ifdef USE_TLS
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (ACTV_VER(ssl, v_tls_any | v_dtls_any))
{
len = tlsGenerateFinishedHash(ssl,
# ifndef USE_ONLY_TLS_1_2
@@ -517,7 +515,7 @@ int32_t sslSnapshotHSHash(ssl_t *ssl, unsigned char *out, int32 senderFlag)
# endif /* USE_TLS */
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (len > 0)
{
diff --git a/matrixssl/hsNegotiateVersion.c b/matrixssl/hsNegotiateVersion.c
index 5d712e0..833491a 100644
--- a/matrixssl/hsNegotiateVersion.c
+++ b/matrixssl/hsNegotiateVersion.c
@@ -34,364 +34,350 @@
#include "matrixsslImpl.h"
-int32_t checkClientHelloVersion(ssl_t *ssl,
- unsigned char *serverHighestMinor)
+uint16_t psEncodeVersion(uint32_t ver)
{
- unsigned char compareMin, compareMaj;
+ ver = VER_GET_RAW(ver);
-# ifndef USE_SSL_PROTOCOL_VERSIONS_OTHER_THAN_3
- /* RFC 5246 Suggests to accept all RSA minor versions, but only
- major version 0x03 (SSLv3, TLS 1.0, TLS 1.1, TLS 1.2, TLS 1.3 etc) */
- if (ssl->reqMajVer != 0x03
-# ifdef USE_DTLS
- && ssl->reqMajVer != DTLS_MAJ_VER
-# endif /* USE_DTLS */
- )
+ switch (ver)
{
- /* Consider invalid major version protocol version error. */
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- psTraceErrr("Won't support client's SSL major version\n");
- return MATRIXSSL_ERROR;
+ case v_ssl_3_0:
+ return v_ssl_3_0_enc;
+ case v_tls_1_0:
+ return v_tls_1_0_enc;
+ case v_dtls_1_0:
+ return v_dtls_1_0_enc;
+ case v_tls_1_1:
+ return v_tls_1_1_enc;
+ case v_tls_1_2:
+ return v_tls_1_2_enc;
+ case v_dtls_1_2:
+ return v_dtls_1_2_enc;
+ case v_tls_1_3_draft_22:
+ return v_tls_1_3_draft_22_enc;
+ case v_tls_1_3_draft_23:
+ return v_tls_1_3_draft_23_enc;
+ case v_tls_1_3_draft_24:
+ return v_tls_1_3_draft_24_enc;
+ case v_tls_1_3_draft_26:
+ return v_tls_1_3_draft_26_enc;
+ case v_tls_1_3_draft_28:
+ return v_tls_1_3_draft_28_enc;
+ case v_tls_1_3:
+ return v_tls_1_3_enc;
+ default:
+ psTraceIntInfo("Tried to encode an unsupported version: %u\n", ver);
+ return 0;
}
-# endif /* USE_SSL_PROTOCOL_VERSIONS_OTHER_THAN_3 */
+}
- /* Client should always be sending highest supported protocol. Server
- will reply with a match or a lower version if enabled (or forced). */
- if (ssl->majVer != 0)
+uint8_t psEncodeVersionMin(uint32_t ver)
+{
+ uint32_t ver_enc = psEncodeVersion(ver);
+
+ return (ver_enc & 0xff);
+}
+
+uint8_t psEncodeVersionMaj(uint32_t ver)
+{
+ uint32_t ver_enc = psEncodeVersion(ver);
+
+ return ((ver_enc & 0xff00) >> 8);
+}
+
+psProtocolVersion_t psVerFromEncoding(uint16_t enc)
+{
+ switch (enc)
{
- /* If our forced server version is a later protocol than their
- request, we have to exit */
- if (ssl->reqMinVer < ssl->minVer)
- {
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- psTraceErrr("Won't support client's SSL version\n");
- return MATRIXSSL_ERROR;
- }
-# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
- {
- /* DTLS specfication somehow assigned minimum version of DTLS 1.0
- as 255 so there was nowhere to go but down in DTLS 1.1 so
- that is 253 and requires the opposite test from above */
- if (ssl->reqMinVer > ssl->minVer)
- {
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- psTraceErrr("Won't support client's DTLS version\n");
- return MATRIXSSL_ERROR;
- }
- }
-# endif
- /* Otherwise we just set our forced version to act like it was
- what the client wanted in order to move through the standard
- negotiation. */
- compareMin = ssl->minVer;
- compareMaj = ssl->majVer;
- /* Set the highest version to the version explicitly set */
- *serverHighestMinor = ssl->minVer;
+ case v_ssl_3_0_enc:
+ return v_ssl_3_0;
+ case v_tls_1_0_enc:
+ return v_tls_1_0;
+ case v_tls_1_1_enc:
+ return v_tls_1_1;
+ case v_tls_1_2_enc:
+ return v_tls_1_2;
+ case v_tls_1_3_enc:
+ return v_tls_1_3;
+ case v_tls_1_3_draft_22_enc:
+ return v_tls_1_3_draft_22;
+ case v_tls_1_3_draft_23_enc:
+ return v_tls_1_3_draft_23;
+ case v_tls_1_3_draft_24_enc:
+ return v_tls_1_3_draft_24;
+ case v_tls_1_3_draft_26_enc:
+ return v_tls_1_3_draft_26;
+ case v_tls_1_3_draft_28_enc:
+ return v_tls_1_3_draft_28;
+ case v_dtls_1_0_enc:
+ return v_dtls_1_0;
+ case v_dtls_1_2_enc:
+ return v_dtls_1_2;
+ default:
+ return v_undefined;
}
- else
+}
+
+psProtocolVersion_t psVerFromEncodingMajMin(uint8_t maj, uint8_t min)
+{
+ uint16_t ver = (maj << 8) | min;
+
+ return psVerFromEncoding(ver);
+}
+
+int32_t psVerToFlag(psProtocolVersion_t ver)
+{
+ int32_t flags = 0;
+
+ if (ver & v_ssl_3_0)
{
- compareMin = ssl->reqMinVer;
- compareMaj = ssl->reqMajVer;
- /* If no explicit version was set for the server, use the highest supported */
- *serverHighestMinor = TLS_HIGHEST_MINOR;
+ flags |= SSL_FLAGS_SSLV3;
+ }
+ else if (ver & v_tls_1_0)
+ {
+ flags |= SSL_FLAGS_TLS_1_0;
+ }
+ else if (ver & v_tls_1_1)
+ {
+ flags |= SSL_FLAGS_TLS_1_1;
+ }
+ else if (ver & v_tls_1_2)
+ {
+ flags |= SSL_FLAGS_TLS_1_2;
+ }
+ else if (ver & v_tls_1_3)
+ {
+ flags |= SSL_FLAGS_TLS_1_3;
+ }
+ else if (ver & v_tls_1_3_draft_22)
+ {
+ flags |= SSL_FLAGS_TLS_1_3_DRAFT_22;
+ }
+ else if (ver & v_tls_1_3_draft_24)
+ {
+ flags |= SSL_FLAGS_TLS_1_3_DRAFT_24;
+ }
+ else if (ver & v_tls_1_3_draft_26)
+ {
+ flags |= SSL_FLAGS_TLS_1_3_DRAFT_26;
+ }
+ else if (ver & v_tls_1_3_draft_28)
+ {
+ flags |= SSL_FLAGS_TLS_1_3_DRAFT_28;
+ }
+ else if (ver & v_dtls_1_0)
+ {
+ flags |= SSL_FLAGS_DTLS;
+ }
+ else if (ver & v_dtls_1_2)
+ {
+ flags |= SSL_FLAGS_DTLS;
+ flags |= SSL_FLAGS_TLS_1_2;
}
- if (compareMaj >= SSL3_MAJ_VER)
+ return flags;
+}
+
+psProtocolVersion_t psFlagToVer(int32_t flag)
+{
+ psProtocolVersion_t ver = v_undefined;
+
+ if (flag & SSL_FLAGS_SSLV3)
{
- ssl->majVer = compareMaj;
-# ifdef USE_TLS
- if (compareMin >= TLS_MIN_VER)
- {
-# ifndef DISABLE_TLS_1_0
- /* Allow TLS 1.0, unless specifically disabled. */
- if (tlsVersionSupported(ssl, tls_v_1_0))
- {
- ssl->minVer = TLS_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS;
- }
-# endif
-# ifdef USE_TLS_1_1 /* TLS_1_1 */
-# ifdef USE_TLS_1_1_TOGGLE
- if (tlsVersionSupported(ssl, tls_v_1_1))
- {
-# endif
- if (compareMin >= TLS_1_1_MIN_VER)
- {
-# ifndef DISABLE_TLS_1_1
- ssl->minVer = TLS_1_1_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS;
-# endif
- }
-# ifdef USE_TLS_1_1_TOGGLE
- }
-# endif
-# ifdef USE_TLS_1_2
-# ifdef USE_TLS_1_2_TOGGLE
- /* Prefer TLS 1.2, unless specifically disabled. */
- if (tlsVersionSupported(ssl, tls_v_1_2))
- {
-# endif /* USE_TLS_1_2_TOGGLE */
- if (compareMin == TLS_1_2_MIN_VER)
- {
- ssl->minVer = TLS_1_2_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_2 | SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS;
- }
-# ifdef USE_TLS_1_2_TOGGLE
- }
-# endif /* USE_TLS_1_2_TOGGLE */
-# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
- {
- if (compareMin == DTLS_1_2_MIN_VER)
- {
- ssl->minVer = DTLS_1_2_MIN_VER;
- }
- }
-# endif
-# endif /* USE_TLS_1_2 */
-# endif /* USE_TLS_1_1 */
- if (ssl->minVer == 0)
- {
- /* TLS versions are disabled. Go SSLv3 if available. */
-# ifdef DISABLE_SSLV3
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- return MATRIXSSL_ERROR;
-# else
- ssl->minVer = SSL3_MIN_VER;
-# endif
- }
- }
- else if (compareMin == 0)
- {
-# ifdef DISABLE_SSLV3
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- psTraceErrr("Client wanted to talk SSLv3 but it's disabled\n");
- return MATRIXSSL_ERROR;
-# else
- ssl->minVer = SSL3_MIN_VER;
-# endif /* DISABLE_SSLV3 */
- }
-# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
- {
- if (compareMin < DTLS_1_2_MIN_VER)
- {
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- psTraceErrr("Error: incorrect DTLS required version\n");
- return MATRIXSSL_ERROR;
- }
- ssl->minVer = DTLS_MIN_VER;
-# ifdef USE_TLS_1_2
-# ifdef USE_TLS_1_2_TOGGLE
- /* Prefer TLS 1.2, unless specifically disabled. */
- if (tlsVersionSupported(ssl, tls_v_1_2))
- {
-# endif /* USE_TLS_1_2_TOGGLE */
- if (compareMin == DTLS_1_2_MIN_VER)
- {
- ssl->flags |= SSL_FLAGS_TLS_1_2 | SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS;
- ssl->minVer = DTLS_1_2_MIN_VER;
- }
-# ifdef USE_TLS_1_2_TOGGLE
- }
-# endif /* USE_TLS_1_2_TOGGLE */
-# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
- {
- if (compareMin == DTLS_1_2_MIN_VER)
- {
- ssl->minVer = DTLS_1_2_MIN_VER;
- }
- }
-# endif /* USE_DTLS */
-# endif /* USE_TLS_1_2 */
-
- }
-# endif /* USE_DTLS */
-# else
- ssl->minVer = SSL3_MIN_VER;
-
-# endif /* USE_TLS */
-
+ ver |= v_ssl_3_0;
}
- else
+ if (flag & SSL_FLAGS_TLS_1_0)
{
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- psTraceIntInfo("Unsupported ssl version: %d\n", compareMaj);
- return MATRIXSSL_ERROR;
+ ver |= v_tls_1_0;
+ }
+ if (flag & SSL_FLAGS_TLS_1_1)
+ {
+ ver |= v_tls_1_1;
+ }
+ if (flag & SSL_FLAGS_TLS_1_2)
+ {
+ ver |= v_tls_1_2;
+ }
+ if (flag & SSL_FLAGS_TLS_1_3)
+ {
+ ver |= v_tls_1_3;
+ }
+ if (flag & SSL_FLAGS_TLS_1_3_DRAFT_22)
+ {
+ ver |= v_tls_1_3_draft_22;
+ }
+ if (flag & SSL_FLAGS_TLS_1_3_DRAFT_23)
+ {
+ ver |= v_tls_1_3_draft_23;
+ }
+ if (flag & SSL_FLAGS_TLS_1_3_DRAFT_24)
+ {
+ ver |= v_tls_1_3_draft_23;
+ }
+ if (flag & SSL_FLAGS_TLS_1_3_DRAFT_26)
+ {
+ ver |= v_tls_1_3_draft_26;
+ }
+ if (flag & SSL_FLAGS_TLS_1_3_DRAFT_28)
+ {
+ ver |= v_tls_1_3_draft_28;
+ }
+ if (flag & SSL_FLAGS_DTLS)
+ {
+ ver |= v_dtls_1_0;
+ if (flag & SSL_FLAGS_TLS_1_2)
+ {
+ ver |= v_dtls_1_2;
+ }
}
+ return ver;
+}
+
+psProtocolVersion_t psVerGetLowest(psProtocolVersion_t ver,
+ int allowDtls)
+{
+ psSize_t i;
+ psProtocolVersion_t mask = 1;
+
+ ver = VER_GET_RAW(ver);
+
+ for (i = 0; i <= VER_MAX_BIT; i++)
+ {
+ if (ver & mask)
+ {
+ if (allowDtls || (mask & v_tls_any))
+ {
+ return mask;
+ }
+ }
+ mask <<= 1;
+ }
+
+ return v_undefined;
+}
+
+psProtocolVersion_t psVerGetLowestTls(psProtocolVersion_t ver)
+{
+ return psVerGetLowest(ver, 0);
+}
+
+psProtocolVersion_t psVerGetHighest(psProtocolVersion_t ver,
+ int allowDtls)
+{
+ psSize_t i;
+ psProtocolVersion_t mask;
+
+ ver = VER_GET_RAW(ver);
+
+ mask = (1 << VER_MAX_BIT);
+ for (i = VER_MAX_BIT; i > 0; i--)
+ {
+ if (ver & mask)
+ {
+ if (allowDtls || (mask & v_tls_any))
+ {
+ return mask;
+ }
+ }
+ mask >>= 1;
+ }
+
+ return v_undefined;
+}
+
+psProtocolVersion_t psVerGetHighestTls(psProtocolVersion_t ver)
+{
+ return psVerGetHighest(ver, 0);
+}
+
+int32_t checkClientHelloVersion(ssl_t *ssl)
+{
+ psProtocolVersion_t clientHighest;
+ psProtocolVersion_t negotiatedVer;
+ psProtocolVersion_t ver;
+ psBool_t clientWantsDtls = PS_FALSE, isDtls;
+ psSize_t i;
+
+ /*
+ Check the client_version (legacy_version in TLS 1.3) field
+ and try to negotiate a common version based on the field value.
+ The semantics of this field is that it should be the highest
+ version supported by the client (in TLS 1.2 and below) or should
+ be ignored (in TLS 1.3).
+ */
+
+ clientHighest = ssl->peerHelloVersion;
+ if (SUPP_VER(ssl, clientHighest))
+ {
+ negotiatedVer = clientHighest;
+ goto out_ok;
+ }
+
+ if (clientHighest & v_dtls_any)
+ {
+ clientWantsDtls = PS_TRUE;
+ }
+
+ /* We don't support clientHighest. See if we can propose a downgrade. */
+
+ /* Loop over our supported versions in priority order and select
+ the first version lower than clientHighest. */
+ for (i = 0; i < ssl->supportedVersionsPriorityLen; i++)
+ {
+ ver = ssl->supportedVersionsPriority[i];
+ isDtls = (ver & v_dtls_any) ? PS_TRUE : PS_FALSE;
+
+ /* Don't downgrade from TLS to DTLS, or vice versa. */
+ if ((clientWantsDtls && !isDtls)
+ || (!clientWantsDtls && isDtls))
+ {
+ continue;
+ }
+ if (ver < clientHighest)
+ {
+ negotiatedVer = ver;
+ goto out_ok;
+ }
+ }
+
+ /* Legacy (TLS <1.3) version negotiation failed. However, if the
+ ClientHello contains a supported_versions extension, we shall
+ still try to negotiate based on that. */
+ ssl->err = SSL_ALERT_PROTOCOL_VERSION;
+ return MATRIXSSL_ERROR;
+
+out_ok:
+ SET_NGTD_VER(ssl, negotiatedVer);
return PS_SUCCESS;
}
-# ifndef DISABLE_SSLV3
-int32_t ssl3CheckServerHelloVersion(ssl_t *ssl)
-{
- psAssert(ssl->reqMajVer == SSL3_MAJ_VER);
-
- /* Server minVer now becomes OUR initial requested version.
- This is used during the creation of the premaster where
- this initial requested version is part of the calculation.
- The RFC actually says to use the original requested version
- but no implemenations seem to follow that and just use the
- agreed upon one. */
- ssl->reqMinVer = ssl->minVer;
- ssl->minVer = SSL3_MIN_VER;
- ssl->flags &= ~SSL_FLAGS_TLS;
-# ifdef USE_TLS_1_1
- ssl->flags &= ~SSL_FLAGS_TLS_1_1;
-# endif /* USE_TLS_1_1 */
-# ifdef USE_TLS_1_2
- ssl->flags &= ~SSL_FLAGS_TLS_1_2;
-# endif /* USE_TLS_1_2 */
-}
-# endif /* DISABLE_SSLV3 */
-
-# ifdef USE_TLS
-int32_t tlsCheckServerHelloVersion(ssl_t *ssl)
-{
- psAssert(ssl->reqMajVer == TLS_MAJ_VER);
-
- if (ssl->reqMinVer == ssl->minVer)
- {
- return MATRIXSSL_SUCCESS;
- }
- else
- {
- /* Server is trying to change (downgrade) the protocol version. */
- /* Check if the requested version is in the supported
- version list. */
- if (!tlsVersionSupported(ssl, ssl->reqMinVer))
- {
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- psTraceErrr("Error: version downgrade attempt by server" \
- " rejected:\nServerHello.server_version <" \
- " ClientHello.client_version\n");
- return MATRIXSSL_ERROR;
- }
-
- /* At this point we know that we support the requested version. */
-# ifdef USE_TLS_1_2
- if (ssl->reqMinVer == TLS_1_2_MIN_VER)
- {
- ssl->reqMinVer = ssl->minVer;
- ssl->minVer = TLS_1_2_MIN_VER;
- ssl->flags &= ~SSL_FLAGS_TLS_1_1;
- return MATRIXSSL_SUCCESS;
- }
-# endif /* USE_TLS_1_2 */
-# if defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1)
- else if (ssl->reqMinVer == TLS_1_1_MIN_VER)
- {
- ssl->reqMinVer = ssl->minVer;
- ssl->minVer = TLS_1_1_MIN_VER;
- ssl->flags &= ~SSL_FLAGS_TLS_1_2;
- return MATRIXSSL_SUCCESS;
- }
-# endif /* USE_TLS_1_1 && !DISABLE_TLS_1_1*/
-# ifndef DISABLE_TLS_1_0
- else if (ssl->reqMinVer == TLS_MIN_VER)
- {
- ssl->reqMinVer = ssl->minVer;
- ssl->minVer = TLS_MIN_VER;
- ssl->flags &= ~SSL_FLAGS_TLS_1_2;
- ssl->flags &= ~SSL_FLAGS_TLS_1_1;
- return MATRIXSSL_SUCCESS;
- }
-# endif /* DISABLE_TLS_1_0 */
- else
- {
- return MATRIXSSL_ERROR;
- }
- }
-}
-#endif /* USE_TLS */
-
-#ifdef USE_DTLS
-int32_t dtlsCheckServerHelloVersion(ssl_t *ssl)
-{
- psAssert(ssl->reqMajVer == DTLS_MAJ_VER);
-
- if (ssl->flags & SSL_FLAGS_DTLS)
- {
- if (ssl->reqMinVer == DTLS_MIN_VER &&
- ssl->minVer == DTLS_1_2_MIN_VER)
- {
- ssl->reqMinVer = ssl->minVer;
- ssl->minVer = DTLS_MIN_VER;
- ssl->flags &= ~SSL_FLAGS_TLS_1_2;
- return MATRIXSSL_SUCCESS;
- }
- }
-
- return MATRIXSSL_ERROR;
-}
-#endif /* USE_DTLS */
-
/** Check whether the protocol version selected by the server can
be supported for this handshake.
- @precond: ssl->reqMajVer, ssl->reqMinVer contains the version parsed
+ @precond: ssl->peerHelloVersion contains the version parsed
from ServerHello.server_version (called ServerHello.legacy_version
in TLS 1.3).
*/
int32_t checkServerHelloVersion(ssl_t *ssl)
{
- int32_t rc = MATRIXSSL_ERROR;
+ psProtocolVersion_t serverVer;
- /* Check that we have a common major version. For example,
- do not allow the server to select DTLS when we tried to
- connect using TLS. */
- if (ssl->reqMajVer != ssl->majVer)
- {
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- psTraceIntInfo("Unsupported ssl version: %d\n", ssl->reqMajVer);
- return MATRIXSSL_ERROR;
- }
+ serverVer = ssl->peerHelloVersion;
- /* Easy case: server chose our preferred version. */
- if (ssl->reqMinVer == ssl->minVer)
+ if (!SUPP_VER(ssl, serverVer))
{
- return MATRIXSSL_SUCCESS;
- }
-
- /* Now handle downgrades. */
- switch(ssl->reqMajVer)
- {
-# ifdef USE_TLS
- case TLS_MAJ_VER:
- rc = tlsCheckServerHelloVersion(ssl);
- break;
-# endif
-# ifdef USE_DTLS
- case DTLS_MAJ_VER:
- rc = dtlsCheckServerHelloVersion(ssl);
- break;
-# endif
- default:
- rc = MATRIXSSL_ERROR;
- }
-
- # ifndef DISABLE_SSLV3
- if (rc != MATRIXSSL_SUCCESS
- && ssl->reqMinVer == SSL3_MIN_VER
- && ssl->minVer >= TLS_MIN_VER)
- {
- rc = sslv3CheckServerHelloVersion(ssl);
- }
-# endif /* !DISABLE_SSLV3 */
-
- if (rc != MATRIXSSL_SUCCESS)
- {
- /* Wasn't able to settle on a common protocol */
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- psTracePrintProtocolVersion(INDENT_HS_MSG,
+ psTraceErrr("Cannot support ServerHello.server_version\n");
+ psTracePrintProtocolVersionNew(INDENT_HS_MSG,
"Unsupported protocol version",
- ssl->reqMajVer, ssl->reqMinVer, PS_TRUE);
+ serverVer,
+ PS_TRUE);
+ ssl->err = SSL_ALERT_PROTOCOL_VERSION;
return MATRIXSSL_ERROR;
}
+ /* Version negotiation complete for now. Result may get
+ overriden by the supported_versions check. */
+ SET_NGTD_VER(ssl, serverVer);
return MATRIXSSL_SUCCESS;
}
@@ -399,8 +385,8 @@ int32_t checkServerHelloVersion(ssl_t *ssl)
int32_t checkSupportedVersions(ssl_t *ssl)
{
int32 rc;
- uint16_t selectedVersion = 0;
- uint16_t forbiddenVer[16] = {0};
+ psProtocolVersion_t selectedVersion = 0;
+ psProtocolVersion_t forbiddenVer[16] = {0};
psSize_t forbiddenVerLen = 0;
psSize_t i = 0;
@@ -419,10 +405,10 @@ int32_t checkSupportedVersions(ssl_t *ssl)
/* Choose version from the intersection of our and the client's
version list. */
- rc = tls13IntersectionPrioritySelect(ssl->supportedVersions,
- ssl->supportedVersionsLen,
- ssl->tls13PeerSupportedVersions,
- ssl->tls13PeerSupportedVersionsLen,
+ rc = tls13IntersectionPrioritySelect(ssl->supportedVersionsPriority,
+ ssl->supportedVersionsPriorityLen,
+ ssl->peerSupportedVersionsPriority,
+ ssl->peerSupportedVersionsPriorityLen,
forbiddenVer,
forbiddenVerLen,
&selectedVersion);
@@ -433,70 +419,7 @@ int32_t checkSupportedVersions(ssl_t *ssl)
return MATRIXSSL_ERROR;
}
- switch (selectedVersion & 0xff)
- {
- case TLS_1_0_MIN_VER:
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_0_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_0;
- break;
- case TLS_1_1_MIN_VER:
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_1_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_1;
- break;
- case TLS_1_2_MIN_VER:
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_2_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_2;
- break;
- case TLS_1_3_MIN_VER:
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_2_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_3 |
- SSL_FLAGS_TLS_1_3_NEGOTIATED;
- ssl->tls13NegotiatedMinorVer = selectedVersion & 0xff;
- break;
- case TLS_1_3_DRAFT_22_MIN_VER:
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_2_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_3_DRAFT_22 |
- SSL_FLAGS_TLS_1_3_NEGOTIATED;
- ssl->tls13NegotiatedMinorVer = selectedVersion & 0xff;
- break;
- case TLS_1_3_DRAFT_23_MIN_VER:
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_2_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_3_DRAFT_23 |
- SSL_FLAGS_TLS_1_3_NEGOTIATED;
- ssl->tls13NegotiatedMinorVer = selectedVersion & 0xff;
- break;
- case TLS_1_3_DRAFT_24_MIN_VER:
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_2_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_3_DRAFT_24 |
- SSL_FLAGS_TLS_1_3_NEGOTIATED;
- ssl->tls13NegotiatedMinorVer = selectedVersion & 0xff;
- break;
- case TLS_1_3_DRAFT_26_MIN_VER:
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_2_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_3_DRAFT_26 |
- SSL_FLAGS_TLS_1_3_NEGOTIATED;
- ssl->tls13NegotiatedMinorVer = selectedVersion & 0xff;
- break;
- case TLS_1_3_DRAFT_28_MIN_VER:
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_2_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_3_DRAFT_28 |
- SSL_FLAGS_TLS_1_3_NEGOTIATED;
- ssl->tls13NegotiatedMinorVer = selectedVersion & 0xff;
- break;
- default:
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- psTraceErrr("Unsupported protocol version\n");
- return MATRIXSSL_ERROR;
- }
+ SET_NGTD_VER(ssl, selectedVersion);
return PS_SUCCESS;
}
@@ -516,7 +439,7 @@ int32_t performTls13DowngradeCheck(ssl_t *ssl)
return MATRIXSSL_ERROR;
}
- if (tlsVersionSupported(ssl, TLS_1_3_MIN_VER))
+ if (SUPP_VER(ssl, v_tls_1_3))
{
/* TLS 1.3 downgrade protection: if we support (non-draft)
TLS 1.3 and the server chose <1.3, check that the last 8
diff --git a/matrixssl/matrixssl.c b/matrixssl/matrixssl.c
index 3943104..d367f91 100644
--- a/matrixssl/matrixssl.c
+++ b/matrixssl/matrixssl.c
@@ -75,22 +75,20 @@ static void initSessionEntryChronList(void);
#endif /* USE_SERVER_SIDE_SSL */
-static int32 initSupportedVersions(ssl_t *ssl, sslSessOpts_t *options);
#ifdef USE_TLS_1_3
static int32 initSupportedGroups(ssl_t *ssl, sslSessOpts_t *options);
#endif
static int32 initSignatureAlgorithms(ssl_t *ssl, sslSessOpts_t *options);
extern int32 getDefaultSigAlgs(ssl_t *ssl);
-extern psBool_t tlsVersionSupported(ssl_t *ssl, const uint8_t minVersion);
extern psBool_t psIsSigAlgSupported(uint16_t sigAlg);
-extern int32 getClientDefaultVersions(ssl_t *ssl);
-extern int32 getServerDefaultVersions(ssl_t *ssl);
#ifdef USE_TLS_1_3
extern int32 tls13GetDefaultSigAlgsCert(ssl_t *ssl);
extern int32 tls13GetDefaultGroups(ssl_t *ssl);
#endif
+extern int32 initSupportedVersions(ssl_t *ssl, sslSessOpts_t *options);
+
/******************************************************************************/
/*
Open and close the SSL module. These routines are called once in the
@@ -208,277 +206,6 @@ void matrixSslClose(void)
*g_config = 'N';
}
-psBool_t matrixSslTlsVersionRangeSupported(int32_t low,
- int32_t high)
-{
-#ifdef USE_TLS_1_3
- /* TODO:Document/handle case where range contains legacy versions and
- draft versions for example 3 - 23. Currently not supported */
- /* Handle TLS1.3 draft versions */
- if (low >= MIN_ENABLED_TLS_1_3_DRAFT_VERSION &&
- high <= MAX_ENABLED_TLS_1_3_DRAFT_VERSION &&
- low <= high)
- {
- return PS_TRUE;
- }
-#endif
- if (low < MIN_ENABLED_TLS_VER)
- {
- psTraceIntInfo("Minimum of version range not supported " \
- "by config: %d\n", low);
- return PS_FALSE;
- }
- if (high > MAX_ENABLED_TLS_VER)
- {
- psTraceIntInfo("Maximum of version range not supported " \
- "by config: %d\n", high);
- return PS_FALSE;
- }
- if (low > high)
- {
- psTraceInfo("Invalid version range: low > high\n");
- return PS_FALSE;
- }
-
- return PS_TRUE;
-}
-
-int32 tlsMinVerToVersionFlag(int32_t minVer)
-{
- switch (minVer)
- {
- case tls_v_1_3_draft_28:
- return SSL_FLAGS_TLS_1_3_DRAFT_28;
- case tls_v_1_3_draft_26:
- return SSL_FLAGS_TLS_1_3_DRAFT_26;
- case tls_v_1_3_draft_24:
- return SSL_FLAGS_TLS_1_3_DRAFT_24;
- case tls_v_1_3_draft_23:
- return SSL_FLAGS_TLS_1_3_DRAFT_23;
- case tls_v_1_3_draft_22:
- return SSL_FLAGS_TLS_1_3_DRAFT_22;
- case tls_v_1_3:
- return SSL_FLAGS_TLS_1_3;
- case tls_v_1_2:
- return SSL_FLAGS_TLS_1_2;
- case tls_v_1_1:
- return SSL_FLAGS_TLS_1_1;
- case tls_v_1_0:
- return SSL_FLAGS_TLS_1_0;
- case 0:
- return SSL_FLAGS_SSLV3;
- default:
- psTraceIntInfo("Unsupported minor version: %d\n", minVer);
- return SSL_FLAGS_TLS_1_3;
- }
-}
-
-#ifdef USE_CLIENT_SIDE_SSL
-int32_t matrixSslSessOptsSetClientTlsVersionRange(sslSessOpts_t *options,
- int32_t low, int32_t high)
-{
- int32_t versions[TLS_MAX_SUPPORTED_VERSIONS];
- uint8_t numVersions = 0;
- uint32_t i;
-
- if (low < tls_v_1_0)
- {
- psTraceErrr("matrixSslSessOptsSetClientTlsVersionRange only " \
- "supports TLS 1.0 to TLS 1.3. SSL 3.0 is not supported\n");
- return PS_ARG_FAIL;
- }
- /* Copy the range to array for SetClientTlsVersions */
- i = 0;
- do
- {
- versions[i] = high;
- numVersions++;
- i++;
- high--;
- } while (high >= low);
- return matrixSslSessOptsSetClientTlsVersions(options,
- versions,
- numVersions);
-}
-
-PSPUBLIC int32_t matrixSslSessOptsSetClientTlsVersions(sslSessOpts_t *options,
- const int32_t versions[],
- int32_t versionsLen)
-{
- uint8_t i, k;
- int32_t highestVersion = 0;
-# ifdef USE_TLS_1_3
- psBool_t haveTls13Draft28 = PS_FALSE;
-# endif
-
- if (options == NULL)
- {
- return PS_ARG_FAIL;
- }
- if (versionsLen == 0)
- {
- psTraceErrr("Please enable at least one version.\n");
- return PS_ARG_FAIL;
- }
- if (versionsLen > TLS_MAX_SUPPORTED_VERSIONS)
- {
- psTraceErrr("Too many supported versions. Increase " \
- "TLS_MAX_SUPPORTED_VERSIONS.\n");
- return PS_ARG_FAIL;
- }
-# ifdef USE_TLS_1_3
- for (i = 0; i < versionsLen; i++)
- {
- if (versions[i] == tls_v_1_3_draft_28)
- {
- haveTls13Draft28 = PS_TRUE;
- }
- }
-# endif
-
- options->supportedVersionsLen = 0;
- for (i = 0, k = 0; i < versionsLen; i++)
- {
- if (!matrixSslTlsVersionRangeSupported(versions[i], versions[i]))
- {
- psTraceErrr("Unsupported version. Please enable more " \
- "versions in matrixsslConfig.h.\n");
- return PS_ARG_FAIL;
- }
- options->supportedVersions[k++] = versions[i];
- options->supportedVersionsLen++;
- if (versions[i] > highestVersion)
- {
- highestVersion = versions[i];
- }
-# ifdef USE_TLS_1_3
- if (versions[i] == tls_v_1_3 && !haveTls13Draft28)
- {
- /* Very little support in the wild for TLS 1.3 RFC version,
- so add draft #28 as well. TODO: remove.*/
- options->supportedVersions[k++] = tls_v_1_3_draft_28;
- options->supportedVersionsLen++;
- }
-# endif
- }
-
- /* Set the versionFlag always to highest version. Note that
- versionFlag is not the same as the legacy version field
- so it can contain also the 1.3 version.
- Note that the priority order of the versions only affects to order of
- versions in the TLS1.3 supportedVersions extension, nothing else */
- options->versionFlag = tlsMinVerToVersionFlag(highestVersion);
-
- return PS_SUCCESS;
-}
-
-#endif /* USE_CLIENT_SIDE_SSL */
-
-#ifdef USE_SERVER_SIDE_SSL
-
-int32_t matrixSslSessOptsSetServerTlsVersionRange(sslSessOpts_t *options,
- int32_t low, int32_t high)
-{
- int32_t versions[TLS_MAX_SUPPORTED_VERSIONS];
- uint8_t numVersions = 0;
- uint32_t i;
-
- if (low < tls_v_1_0)
- {
- psTraceErrr("matrixSslSessOptsSetServerTlsVersionRange only " \
- "supports TLS 1.0 to TLS 1.3. SSL 3.0 is not supported\n");
- return PS_ARG_FAIL;
- }
- /* Copy the range to array for SetClientTlsVersions */
- i = 0;
- do
- {
- versions[i] = high;
- numVersions++;
- i++;
- high--;
- } while (high >= low);
-
- return matrixSslSessOptsSetServerTlsVersions(options,
- versions,
- numVersions);
-}
-PSPUBLIC int32_t matrixSslSessOptsSetServerTlsVersions(sslSessOpts_t *options,
- const int32_t versions[],
- int32_t versionsLen)
-{
- uint8_t i, k;
-# ifdef USE_TLS_1_3
- psBool_t haveTls13Draft28 = PS_FALSE;
-# endif
-
- /*
- On the server side the version handling goes either of two
- ways:
- 1. If single version is selected it is set to versionFlag
- 2. If multiple versions are selected then the non-enabled
- versions are disabled through the disable flags and
- the versionFlag = 0
- */
- if (options == NULL)
- {
- return PS_ARG_FAIL;
- }
- if (versionsLen == 0)
- {
- psTraceErrr("Please enable at least one version.\n");
- return PS_ARG_FAIL;
- }
- if (versionsLen > TLS_MAX_SUPPORTED_VERSIONS)
- {
- psTraceErrr("Too many supported versions. Increase " \
- "TLS_MAX_SUPPORTED_VERSIONS.\n");
- return PS_ARG_FAIL;
- }
-
-# ifdef USE_TLS_1_3
- for (i = 0; i < versionsLen; i++)
- {
- if (versions[i] == tls_v_1_3_draft_28)
- {
- haveTls13Draft28 = PS_TRUE;
- }
- }
-# endif
- for (i = 0, k = 0; i < versionsLen; i++)
- {
- if (!matrixSslTlsVersionRangeSupported(versions[i], versions[i]))
- {
- psTraceErrr("Unsupported version. Please enable more " \
- "versions in matrixsslConfig.h.\n");
- return PS_ARG_FAIL;
- }
- options->supportedVersions[k++] = versions[i];
- options->supportedVersionsLen++;
-# ifdef USE_TLS_1_3
- if (versions[i] == tls_v_1_3 && !haveTls13Draft28)
- {
- /* Very little support in the wild for TLS 1.3 RFC version,
- so add draft #28 as well. TODO: remove.*/
- options->supportedVersions[k++] = tls_v_1_3_draft_28;
- options->supportedVersionsLen++;
- }
-# endif
- }
-
- if (versionsLen == 1)
- {
- /* If on the server side only one version is enabled then it
- * is handled through the versionFlag. If there are many versions
- * enabled then they are handled through the supportedVersions */
- options->versionFlag = tlsMinVerToVersionFlag(versions[0]);
- }
-
- return PS_SUCCESS;
-}
-
-#endif /* USE_SERVER_SIDE_SSL */
-
# ifdef USE_TLS_1_3
/** Set the (EC)DHE groups to support for key exchange.
@@ -684,20 +411,13 @@ int32 matrixSslNewSession(ssl_t **ssl, const sslKeys_t *keys,
{
psPool_t *pool = NULL;
ssl_t *lssl;
- int32_t specificVersion, flags, rc;
+ int32_t flags, rc;
#ifdef USE_STATELESS_SESSION_TICKETS
uint32_t i;
#endif
/* SERVER_SIDE and CLIENT_AUTH and others will have been added to
versionFlag by callers */
- /* TLS1.3 draft version handling */
- if (options->versionFlag & SSL_FLAGS_TLS_1_3)
- {
- /* Substitute TLS_1_3 flag with latest draft flag */
- options->versionFlag &= ~SSL_FLAGS_TLS_1_3;
- options->versionFlag |= SSL_FLAGS_TLS_1_3_DRAFT_28;
- }
flags = options->versionFlag;
/*
@@ -760,6 +480,45 @@ int32 matrixSslNewSession(ssl_t **ssl, const sslKeys_t *keys,
Memset(lssl, 0x0, sizeof(ssl_t));
lssl->memAllocPtr = options->memAllocPtr;
+# ifdef USE_SEC_CONFIG
+# ifdef DEFAULT_SEC_CONFIG
+ rc = matrixSslSetSecurityProfile(lssl, DEFAULT_SEC_CONFIG);
+ if (rc < 0)
+ {
+ return rc;
+ }
+ {
+ sslIdentity_t *key = keys->identity;
+ psSizeL_t nBits;
+ uint8_t type;
+ psSecOperation_t op;
+
+ /* Check whether the loaded keys fulfill the security requirements. */
+ while (key != NULL)
+ {
+ type = key->privKey.type;
+ if (type == PS_RSA)
+ {
+ nBits = key->privKey.keysize * 8;
+ op = secop_rsa_load_key;
+ }
+ else if (type == PS_ECC)
+ {
+ nBits = key->privKey.key.ecc.curve->size * 8;
+ op = secop_ecdsa_load_key;
+
+ }
+ rc = matrixSslCallSecurityCallback(lssl, op, nBits, NULL);
+ if (rc < 0)
+ {
+ return rc;
+ }
+ key = key->next;
+ }
+ }
+# endif
+# endif
+
#ifdef USE_X509
if (options->keep_peer_cert_der)
{
@@ -778,7 +537,9 @@ int32 matrixSslNewSession(ssl_t **ssl, const sslKeys_t *keys,
}
if (options->userDataPtr != NULL)
+ {
lssl->userDataPtr = options->userDataPtr;
+ }
#ifdef USE_ECC
/* If user specified EC curves they support, let's check that against
@@ -886,276 +647,21 @@ int32 matrixSslNewSession(ssl_t **ssl, const sslKeys_t *keys,
if (flags & SSL_FLAGS_SERVER)
{
lssl->flags |= SSL_FLAGS_SERVER;
-/*
- Client auth can only be requested by server, not set by client
- */
+ /*
+ Client auth can only be requested by server, not set by client
+ */
if (flags & SSL_FLAGS_CLIENT_AUTH)
{
lssl->flags |= SSL_FLAGS_CLIENT_AUTH;
}
lssl->hsState = SSL_HS_CLIENT_HELLO;
-
- /* Is caller requesting specific protocol version for this client?
- Make sure it's enabled and use specificVersion var for err */
- specificVersion = 0;
- if (flags & SSL_FLAGS_SSLV3)
- {
-#ifndef DISABLE_SSLV3
- lssl->majVer = SSL3_MAJ_VER;
- lssl->minVer = SSL3_MIN_VER;
-#else
- specificVersion = 1;
-#endif
- }
-
- if (flags & SSL_FLAGS_TLS_1_0)
- {
-#ifdef USE_TLS
-# ifndef DISABLE_TLS_1_0
- lssl->majVer = TLS_MAJ_VER;
- lssl->minVer = TLS_MIN_VER;
-# else
- specificVersion = 1; /* TLS enabled but TLS_1_0 disabled */
-# endif
-#else
- specificVersion = 1; /* TLS not even enabled */
-#endif
- }
-
- if (flags & SSL_FLAGS_TLS_1_1)
- {
-#ifdef USE_TLS_1_1
-# ifndef DISABLE_TLS_1_1
- lssl->majVer = TLS_MAJ_VER;
- lssl->minVer = TLS_1_1_MIN_VER;
-# else
- specificVersion = 1; /* TLS_1_1 enabled but TLS_1_1 disabled */
-# endif
-#else
- specificVersion = 1; /* TLS not even enabled */
-#endif
- }
-
- if (flags & SSL_FLAGS_TLS_1_2)
- {
-#ifdef USE_TLS_1_2
- lssl->majVer = TLS_MAJ_VER;
- lssl->minVer = TLS_1_2_MIN_VER;
-#else
- specificVersion = 1; /* TLS_1_2 disabled */
-#endif
- }
- if (flags & SSL_FLAGS_TLS_1_3_DRAFT_22 ||
- flags & SSL_FLAGS_TLS_1_3_DRAFT_23 ||
- flags & SSL_FLAGS_TLS_1_3_DRAFT_24 ||
- flags & SSL_FLAGS_TLS_1_3_DRAFT_26 ||
- flags & SSL_FLAGS_TLS_1_3_DRAFT_28)
- {
-#ifdef USE_TLS_1_3
- lssl->majVer = TLS_MAJ_VER;
- lssl->minVer = TLS_1_2_MIN_VER;
-#else
- specificVersion = 1; /* TLS_1_3 disabled */
-#endif
- }
- if (specificVersion)
- {
- psTraceErrr("ERROR: protocol version isn't compiled into matrix\n");
- matrixSslDeleteSession(lssl);
- return PS_ARG_FAIL;
- }
- else if (options->supportedVersionsLen == 0)
- {
- /* Caller did not specify either versionFlags or supportedVersions */
- if (getServerDefaultVersions(lssl) < 0)
- {
- psTraceErrr("ERROR: Setting default versions failed\n");
- matrixSslDeleteSession(lssl);
- return PS_ARG_FAIL;
- }
- }
-
-#ifdef USE_DTLS
- /* FLAGS_DTLS used in conjuction with specific 1.1 or 1.2 protocol */
- if (flags & SSL_FLAGS_DTLS)
- {
- if (lssl->majVer)
- {
- if (lssl->minVer == SSL3_MIN_VER || lssl->minVer == TLS_MIN_VER)
- {
- psTraceErrr("ERROR: Can't use SSLv3 or TLS1.0 with DTLS\n");
- matrixSslDeleteSession(lssl);
- return PS_ARG_FAIL;
- }
- lssl->majVer = DTLS_MAJ_VER;
- if (lssl->minVer == TLS_1_2_MIN_VER)
- {
- lssl->minVer = DTLS_1_2_MIN_VER;
- }
- else if (lssl->minVer == TLS_1_1_MIN_VER)
- {
- lssl->minVer = DTLS_MIN_VER;
- }
- else
- {
- psTraceErrr("ERROR: Protocol version parse error\n");
- matrixSslDeleteSession(lssl);
- return PS_ARG_FAIL;
- }
- }
- }
-#endif
-
}
- else
+ else /* Client. */
{
-/*
- Client is first to set protocol version information based on
- compile and/or the 'flags' parameter so header information in
- the handshake messages will be correctly set.
-
- Look for specific version first... but still have to make sure library
- has been compiled to support it
- */
- specificVersion = 0;
- if (flags & SSL_FLAGS_SSLV3)
- {
-#ifndef DISABLE_SSLV3
- lssl->majVer = SSL3_MAJ_VER;
- lssl->minVer = SSL3_MIN_VER;
- specificVersion = 1;
-#else
- specificVersion = 2;
-#endif
- }
-
- if (flags & SSL_FLAGS_TLS_1_0)
- {
-#ifdef USE_TLS
-# ifndef DISABLE_TLS_1_0
- lssl->majVer = TLS_MAJ_VER;
- lssl->minVer = TLS_MIN_VER;
- /* Set flags here if caller has not entered supportedVersions.
- Otherwise set them in initSupportedVersions */
- if (options->supportedVersionsLen == 0)
- {
- lssl->flags |= SSL_FLAGS_TLS;
- }
- specificVersion = 1;
-# else
- specificVersion = 2; /* TLS enabled but TLS_1_0 disabled */
-# endif
-#else
- specificVersion = 2; /* TLS not even enabled */
-#endif
- }
-
- if (flags & SSL_FLAGS_TLS_1_1)
- {
-#ifdef USE_TLS_1_1
-# ifndef DISABLE_TLS_1_1
- lssl->majVer = TLS_MAJ_VER;
- lssl->minVer = TLS_1_1_MIN_VER;
- /* Set flags here if caller has not entered supportedVersions.
- Otherwise set them in initSupportedVersions */
- if (options->supportedVersionsLen == 0)
- {
- lssl->flags |= SSL_FLAGS_TLS | SSL_FLAGS_TLS_1_1;
- }
- specificVersion = 1;
-# else
- specificVersion = 2; /* TLS_1_1 enabled but TLS_1_1 disabled */
-# endif
-#else
- specificVersion = 2; /* TLS not even enabled */
-#endif
- }
-
- if (flags & SSL_FLAGS_TLS_1_2)
- {
-#ifdef USE_TLS_1_2
-# ifndef DISABLE_TLS_1_2
- lssl->majVer = TLS_MAJ_VER;
- lssl->minVer = TLS_1_2_MIN_VER;
- /* Set flags here if caller has not entered supportedVersions.
- Otherwise set them in initSupportedVersions */
- if (options->supportedVersionsLen == 0)
- {
- lssl->flags |= SSL_FLAGS_TLS | SSL_FLAGS_TLS_1_1 | SSL_FLAGS_TLS_1_2;
- }
- specificVersion = 1;
-# else
- specificVersion = 2; /* TLS_1_2 disabled */
-# endif
-#else
- specificVersion = 2; /* TLS 1.2 not even enabled */
-#endif
- }
- if (flags & SSL_FLAGS_TLS_1_3 ||
- flags & SSL_FLAGS_TLS_1_3_DRAFT_22 ||
- flags & SSL_FLAGS_TLS_1_3_DRAFT_23 ||
- flags & SSL_FLAGS_TLS_1_3_DRAFT_24 ||
- flags & SSL_FLAGS_TLS_1_3_DRAFT_26 ||
- flags & SSL_FLAGS_TLS_1_3_DRAFT_28)
- {
-#ifdef USE_TLS_1_3
- /* majVer, minVer is what we are going to encode as the version
- number in record, ClientHello and ServerHello legacy_version
- fields. The TLS 1.3 spec says that we MUST use the TLS 1.2
- version number. The version flag can be used to check
- whether we are actually talking 1.3. */
- lssl->majVer = TLS_MAJ_VER;
- lssl->minVer = TLS_1_2_MIN_VER;
- specificVersion = 1;
-#else
- specificVersion = 2; /* TLS 1.3 not even enabled */
-#endif
- }
-
- if (specificVersion == 2)
- {
- psTraceErrr("ERROR: protocol version isn't compiled into matrix\n");
- matrixSslDeleteSession(lssl);
- return PS_ARG_FAIL;
- }
-
- if (specificVersion == 0)
- {
- /* Highest available if not specified (or not legal value)
- so set default values */
- if (getClientDefaultVersions(lssl) < 0)
- {
- psTraceErrr("ERROR: Setting default versions failed\n");
- matrixSslDeleteSession(lssl);
- return PS_ARG_FAIL;
- }
-
- } /* end non-specific version */
-
-#ifdef USE_DTLS
- if (flags & SSL_FLAGS_DTLS && specificVersion == 1)
- {
- lssl->majVer = DTLS_MAJ_VER;
- if (lssl->minVer == TLS_1_2_MIN_VER)
- {
- lssl->minVer = DTLS_1_2_MIN_VER;
- }
- else if (lssl->minVer == TLS_1_1_MIN_VER)
- {
- lssl->minVer = DTLS_MIN_VER;
- }
- else
- {
- psTraceErrr("ERROR: DTLS must be TLS 1.1 or TLS 1.2\n");
- matrixSslDeleteSession(lssl);
- return PS_ARG_FAIL;
- }
- }
-#endif
-
lssl->hsState = SSL_HS_SERVER_HELLO;
if (session != NULL && session->cipherId != SSL_NULL_WITH_NULL_NULL)
{
+ /* Use the cipher specified in the session ID struct. */
lssl->cipher = sslGetCipherSpec(lssl, session->cipherId);
if (lssl->cipher == NULL)
{
@@ -1241,212 +747,6 @@ int32 matrixSslNewSession(ssl_t **ssl, const sslKeys_t *keys,
return PS_SUCCESS;
}
-static void addVersion(ssl_t *ssl, uint16_t ver)
-{
-# ifdef USE_TLS_1_3
- /*
- Don't include TLS 1.3 in ClientHello supported_versions if the
- user did not enable any 1.3 suites.
-
- Without TLS 1.3 suites in ClientHello, TLS 1.3 cannot be
- negotiated. And if the server then chooses <1.3, the TLS 1.3
- downgrade protection mechanism will be triggered on the client-side,
- causing handshake failure.
-*/
- if (IS_CLIENT(ssl)
- && !ssl->tls13CiphersuitesEnabledClient
- && ver >= TLS_1_3_VER)
- {
- psTraceInfo("Warning: tried to enable TLS 1.3 without enabling " \
- "any TLS 1.3 ciphersuites. Disabling TLS 1.3 for this " \
- "connection.\n");
- return;
- }
-# endif
-
- ssl->supportedVersions[ssl->supportedVersionsLen] = ver;
- ssl->supportedVersionsLen++;
-}
-
-static void addVersionMin(ssl_t *ssl, uint8_t min)
-{
- uint16_t ver;
- uint8_t maj = TLS_MAJ_VER;
-
-# ifdef USE_TLS_1_3
- if (min >= MIN_ENABLED_TLS_1_3_DRAFT_VERSION)
- {
- maj = TLS_1_3_DRAFT_MAJ_VER;
- }
-# endif
-
- ver = (maj << 8) | min;
- addVersion(ssl, ver);
-}
-
-/*
- Convert 32-bit tls_v_1* enum values to official 2-byte version ids.
-*/
-uint16_t tlsMinVerToOfficialVer(int32_t minVer)
-{
- uint16_t val;
-
- switch (minVer)
- {
- case tls_v_1_3_draft_28:
- val = TLS_1_3_DRAFT_MAJ_VER << 8;
- val |= TLS_1_3_DRAFT_28_MIN_VER;
- break;
- case tls_v_1_3_draft_26:
- val = TLS_1_3_DRAFT_MAJ_VER << 8;
- val |= TLS_1_3_DRAFT_26_MIN_VER;
- break;
- case tls_v_1_3_draft_24:
- val = TLS_1_3_DRAFT_MAJ_VER << 8;
- val |= TLS_1_3_DRAFT_24_MIN_VER;
- break;
- case tls_v_1_3_draft_23:
- val = TLS_1_3_DRAFT_MAJ_VER << 8;
- val |= TLS_1_3_DRAFT_23_MIN_VER;
- break;
- case tls_v_1_3_draft_22:
- val = TLS_1_3_DRAFT_MAJ_VER << 8;
- val |= TLS_1_3_DRAFT_22_MIN_VER;
- break;
- case tls_v_1_3:
- val = TLS_MAJ_VER << 8;
- val |= TLS_1_3_MIN_VER;
- break;
- case tls_v_1_2:
- val = TLS_MAJ_VER << 8;
- val |= TLS_1_2_MIN_VER;
- break;
- case tls_v_1_1:
- val = TLS_MAJ_VER << 8;
- val |= TLS_1_1_MIN_VER;
- break;
- case tls_v_1_0:
- val = TLS_MAJ_VER << 8;
- val |= TLS_MIN_VER;
- break;
- case 0:
- default:
- val = SSL3_MAJ_VER << 8;
- val |= SSL3_MIN_VER;
- break;
- }
-
- return val;
-}
-
-/* Gets the supportedVersions list from options and saves it to ssl struct.
- Also makes sure the ssl->flags and supportedVersions are synced. */
-static int32 initSupportedVersions(ssl_t *ssl, sslSessOpts_t *options)
-{
- psSize_t i;
- uint32 flags;
- int32_t flag;
- uint16_t ver;
-
- for (i = 0; i < options->supportedVersionsLen; i++)
- {
- ver = tlsMinVerToOfficialVer(options->supportedVersions[i]);
- addVersion(ssl, ver);
- }
-
- /* Unfortunately API user can bypass the API and just set the
- version flags in options struct directly without settings
- supportedVersions, in which case we must do it here. */
-
- if (options->supportedVersionsLen == 0)
- {
- flags = options->versionFlag;
- if ((flags & SSL_FLAGS_TLS_1_0) &&
- !tlsVersionSupported(ssl, tls_v_1_0))
- {
- addVersionMin(ssl, TLS_1_0_MIN_VER);
- }
- if ((flags & SSL_FLAGS_TLS_1_1) &&
- !tlsVersionSupported(ssl, tls_v_1_1))
- {
- addVersionMin(ssl, TLS_1_1_MIN_VER);
- }
- if ((flags & SSL_FLAGS_TLS_1_2) &&
- !tlsVersionSupported(ssl, tls_v_1_2))
- {
- addVersionMin(ssl, TLS_1_2_MIN_VER);
- }
-#ifdef USE_TLS_1_3
- if ((flags & SSL_FLAGS_TLS_1_3) &&
- !tlsVersionSupported(ssl, tls_v_1_3))
- {
- addVersionMin(ssl, TLS_1_3_MIN_VER);
- }
- if ((flags & SSL_FLAGS_TLS_1_3_DRAFT_22) &&
- !tlsVersionSupported(ssl, tls_v_1_3_draft_22))
- {
- addVersionMin(ssl, TLS_1_3_DRAFT_22_MIN_VER);
- }
- if ((flags & SSL_FLAGS_TLS_1_3_DRAFT_23) &&
- !tlsVersionSupported(ssl, tls_v_1_3_draft_23))
- {
- addVersionMin(ssl, TLS_1_3_DRAFT_23_MIN_VER);
- }
- if ((flags & SSL_FLAGS_TLS_1_3_DRAFT_24) &&
- !tlsVersionSupported(ssl, tls_v_1_3_draft_24))
- {
- addVersionMin(ssl, TLS_1_3_DRAFT_24_MIN_VER);
- }
- if ((flags & SSL_FLAGS_TLS_1_3_DRAFT_26) &&
- !tlsVersionSupported(ssl, tls_v_1_3_draft_26))
- {
- addVersionMin(ssl, TLS_1_3_DRAFT_26_MIN_VER);
- }
- if ((flags & SSL_FLAGS_TLS_1_3_DRAFT_28) &&
- !tlsVersionSupported(ssl, tls_v_1_3_draft_28))
- {
- addVersionMin(ssl, TLS_1_3_DRAFT_28_MIN_VER);
- }
-#endif
- }
-
- /* Client and server handle the flags differently.
- One place of refactoring is to unify those */
- if (!(ssl->flags & SSL_FLAGS_SERVER))
- {
- for (i = 0; i < ssl->supportedVersionsLen; i++)
- {
- flag = tlsMinVerToVersionFlag(
- ssl->supportedVersions[i] & 0xff);
- if (flag > 0)
- {
- ssl->flags |= flag;
- }
- }
- }
-
- /* It seems the SSL_FLAGS_TLS is used as a flag for
- TLS in general. On the other hand it is the same value
- as SSL_FLAGS_TLS_1_0. TODO: Check that it does not mean
- that it is allowed to negotiate 1.0 at any time! */
- ssl->flags |= SSL_FLAGS_TLS;
-
- /* In some places, the <1.3 code expects that flags for lesser
- versions are enabled as well. TODO: the whole version flag
- mechanism is a mess. */
- if (USING_TLS_1_3(ssl))
- {
- ssl->flags |= SSL_FLAGS_TLS_1_2;
- ssl->flags |= SSL_FLAGS_TLS_1_1;
- }
- else if (ssl->flags & SSL_FLAGS_TLS_1_2)
- {
- ssl->flags |= SSL_FLAGS_TLS_1_1;
- }
-
- return MATRIXSSL_SUCCESS;
-}
-
#ifdef USE_TLS_1_3
/* Copy the supplied supportedGroups to ssl struct. Use defaults if nothing supplied */
static int32 initSupportedGroups(ssl_t *ssl, sslSessOpts_t *options)
@@ -1579,7 +879,7 @@ void matrixSslDeleteSession(ssl_t *ssl)
}
#endif
-#ifndef USE_ONLY_PSK_CIPHER_SUITE
+#if defined(USE_IDENTITY_CERTIFICATES)
psFree(ssl->sec.keySelect.caNames, ssl->sPool);
psFree(ssl->sec.keySelect.caNameLens, ssl->sPool);
# if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH)
@@ -1595,7 +895,7 @@ void matrixSslDeleteSession(ssl_t *ssl)
#ifdef USE_TLS_1_3
{
psSize_t i;
-
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
for (i = 0; i < TLS_1_3_MAX_GROUPS; i++)
{
if (ssl->sec.tls13KeyAgreeKeys[i] != NULL)
@@ -1608,7 +908,7 @@ void matrixSslDeleteSession(ssl_t *ssl)
psFree(ssl->tls13CertRequestContext, ssl->hsPool);
ssl->tls13CertRequestContext = NULL;
}
-
+# endif
tls13FreePsk(ssl->sec.tls13SessionPskList, ssl->hsPool);
if (ssl->sec.tls13CookieFromServer)
{
@@ -1823,6 +1123,13 @@ int32_t matrixSslHandshakeIsComplete(const ssl_t *ssl)
*/
psBool_t matrixSslRehandshaking(const ssl_t *ssl)
{
+# ifdef USE_TLS_1_3
+ if (NGTD_VER(ssl, v_tls_1_3_any))
+ {
+ /* TLS 1.3 does not allow re-handshakes. */
+ return PS_FALSE;
+ }
+# endif
if (ssl->flags & SSL_FLAGS_ERROR)
{
/* Fatal alerts mean the handshake is over. */
@@ -1909,7 +1216,7 @@ int32 matrixRegisterSession(ssl_t *ssl)
Don't reassign a new sessionId if we already have one or we blow the
handshake hash
*/
- if ((ssl->flags & SSL_FLAGS_DTLS) && ssl->sessionIdLen > 0)
+ if (ACTV_VER(ssl, v_dtls_any) && ssl->sessionIdLen > 0)
{
/* This is a retransmit case */
return PS_SUCCESS;
@@ -1970,8 +1277,8 @@ int32 matrixRegisterSession(ssl_t *ssl)
with same SSL version.
*/
psGetTime(&g_sessionTable[i].startTime, ssl->userPtr);
- g_sessionTable[i].majVer = ssl->majVer;
- g_sessionTable[i].minVer = ssl->minVer;
+ g_sessionTable[i].majVer = psEncodeVersionMaj(GET_NGTD_VER(ssl));
+ g_sessionTable[i].minVer = psEncodeVersionMin(GET_NGTD_VER(ssl));
g_sessionTable[i].extendedMasterSecret = ssl->extFlags.extended_master_secret;
@@ -2062,8 +1369,8 @@ int32 matrixResumeSession(ssl_t *ssl)
if ((Memcmp(g_sessionTable[i].id, id,
(uint32) min(ssl->sessionIdLen, SSL_MAX_SESSION_ID_SIZE)) != 0) ||
(psDiffMsecs(g_sessionTable[i].startTime, accessTime, ssl->userPtr) >
- SSL_SESSION_ENTRY_LIFE) || (g_sessionTable[i].majVer != ssl->majVer)
- || (g_sessionTable[i].minVer != ssl->minVer))
+ SSL_SESSION_ENTRY_LIFE) || (g_sessionTable[i].majVer != psEncodeVersionMaj(GET_NGTD_VER(ssl)))
+ || (g_sessionTable[i].minVer != psEncodeVersionMin(GET_NGTD_VER(ssl))))
{
psUnlockMutex(&g_sessionTableLock);
return PS_FAILURE;
@@ -2364,8 +1671,8 @@ int32 matrixCreateSessionTicket(ssl_t *ssl, unsigned char *out, int32 *outLen)
Memcpy(c, randno, AES_IVLEN);
c += AES_IVLEN;
enc = c; /* encrypt start */
- *c = ssl->majVer; c++;
- *c = ssl->minVer; c++;
+ *c = psEncodeVersionMaj(GET_NGTD_VER(ssl)); c++;
+ *c = psEncodeVersionMin(GET_NGTD_VER(ssl)); c++;
*c = (ssl->cipher->ident & 0xFF00) >> 8; c++;
*c = ssl->cipher->ident & 0xFF; c++;
/* Need to track if original handshake used extended master secret */
@@ -2568,8 +1875,9 @@ int32 matrixUnlockSessionTicket(ssl_t *ssl, unsigned char *in, int32 inLen)
majVer = *enc; enc++;
minVer = *enc; enc++;
- /* Match protcol version */
- if (majVer != ssl->majVer || minVer != ssl->minVer)
+ /* Match protocol version */
+ if (majVer != psEncodeVersionMaj(GET_NGTD_VER(ssl))
+ || minVer != psEncodeVersionMin(GET_NGTD_VER(ssl)))
{
psTraceErrr("Protocol check failure on session ticket\n");
return PS_FAILURE;
@@ -2851,7 +2159,7 @@ void sslResetContext(ssl_t *ssl)
state for attempting flight resends. If we are resetting context we
know a handshake phase is starting up again
*/
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
ssl->appDataExch = 0;
}
@@ -2946,6 +2254,40 @@ static int matchEmail(char *email, int32 emailLen,
return 0;
}
+static
+int32_t checkPathLenConstraint(psX509Cert_t *ic,
+ psX509Cert_t *sc,
+ int32_t pathLen)
+{
+ if (ic->extensions.bc.pathLenConstraint >= 0)
+ {
+ /*
+ Make sure the pathLen is not exceeded. If the sc and ic
+ are the same CA at this point, this means the peer
+ included the root CA in the chain it sent. It's not good
+ practice to do this but implementations seem to allow it.
+ Subtract one from pathLen in this case since one got
+ added when it was truly just self-authenticating.
+ */
+ if (sc->sigHashLen == ic->sigHashLen &&
+ memcmpct(sc->sigHash, ic->sigHash, sc->sigHashLen) == 0)
+ {
+ if (pathLen > 0)
+ {
+ pathLen--;
+ }
+ }
+ if (ic->extensions.bc.pathLenConstraint < pathLen)
+ {
+ psTraceErrr("Authentication failed due to X.509 pathLen\n");
+ sc->authStatus = PS_CERT_AUTH_FAIL_PATH_LEN;
+ return PS_CERT_AUTH_FAIL_PATH_LEN;
+ }
+ }
+
+ return PS_SUCCESS;
+}
+
/******************************************************************************/
/*
Wrapper for matrixValidateCertsExt taking in no extra options, using
@@ -3077,17 +2419,14 @@ int32 matrixValidateCertsExt(psPool_t *pool, psX509Cert_t *subjectCerts,
{
return rc;
}
- if (ic->extensions.bc.pathLenConstraint >= 0)
+
+ rc = checkPathLenConstraint(ic, sc, pathLen);
+ if (rc < 0)
{
- /* Make sure the pathLen is not exceeded */
- if (ic->extensions.bc.pathLenConstraint < pathLen)
- {
- psTraceErrr("Authentication failed due to X.509 pathLen\n");
- sc->authStatus = PS_CERT_AUTH_FAIL_PATH_LEN;
- return PS_CERT_AUTH_FAIL_PATH_LEN;
- }
+ return rc;
}
pathLen++;
+
sc = sc->next;
ic = sc->next;
}
@@ -3099,15 +2438,11 @@ int32 matrixValidateCertsExt(psPool_t *pool, psX509Cert_t *subjectCerts,
{
return rc;
}
- if (ic->extensions.bc.pathLenConstraint >= 0)
+
+ rc = checkPathLenConstraint(ic, sc, pathLen);
+ if (rc < 0)
{
- /* Make sure the pathLen is not exceeded */
- if (ic->extensions.bc.pathLenConstraint < pathLen)
- {
- psTraceErrr("Authentication failed due to X.509 pathLen\n");
- sc->authStatus = PS_CERT_AUTH_FAIL_PATH_LEN;
- return PS_CERT_AUTH_FAIL_PATH_LEN;
- }
+ return rc;
}
pathLen++;
/*
@@ -3129,29 +2464,10 @@ int32 matrixValidateCertsExt(psPool_t *pool, psX509Cert_t *subjectCerts,
if ((rc = psX509AuthenticateCert(pool, sc, ic, foundIssuer, hwCtx,
poolUserPtr)) == PS_SUCCESS)
{
- if (ic->extensions.bc.pathLenConstraint >= 0)
+ rc = checkPathLenConstraint(ic, sc, pathLen);
+ if (rc < 0)
{
- /* Make sure the pathLen is not exceeded. If the sc and ic
- are the same CA at this point, this means the peer
- included the root CA in the chain it sent. It's not good
- practice to do this but implementations seem to allow it.
- Subtract one from pathLen in this case since one got
- added when it was truly just self-authenticating */
- if (ic->signatureLen == sc->signatureLen &&
- (Memcmp(ic->signature, sc->signature,
- sc->signatureLen) == 0))
- {
- if (pathLen > 0)
- {
- pathLen--;
- }
- }
- if (ic->extensions.bc.pathLenConstraint < pathLen)
- {
- psTraceErrr("Authentication failed due to X.509 pathLen\n");
- rc = sc->authStatus = PS_CERT_AUTH_FAIL_PATH_LEN;
- return rc;
- }
+ return rc;
}
if (opts->flags & VCERTS_FLAG_REVALIDATE_DATES)
diff --git a/matrixssl/matrixsslApi.c b/matrixssl/matrixsslApi.c
index bf712ff..25acf28 100644
--- a/matrixssl/matrixsslApi.c
+++ b/matrixssl/matrixsslApi.c
@@ -972,7 +972,7 @@ int32 matrixSslGetWritebuf(ssl_t *ssl, unsigned char **buf, uint32 requestedLen)
{
/* Not a problem at all beginning in TLS 1.1 (version 3.2) and never
a problem on stream ciphers */
- if ((ssl->majVer == SSL3_MAJ_VER) && (ssl->minVer <= TLS_MIN_VER)
+ if (NGTD_VER(ssl, v_tls_need_beast_workaround)
&& (ssl->enBlockSize > 1) && (requestedLen > 1) &&
!(ssl->bFlags & BFLAG_STOP_BEAST))
{
@@ -1008,7 +1008,7 @@ int32 matrixSslGetWritebuf(ssl_t *ssl, unsigned char **buf, uint32 requestedLen)
overhead = requiredLen - requestedLen;
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
pmtu = matrixDtlsGetPmtu();
if (requiredLen > (uint32) pmtu)
@@ -1074,9 +1074,10 @@ int32 matrixSslGetWritebuf(ssl_t *ssl, unsigned char **buf, uint32 requestedLen)
that extra length here.
*/
if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) &&
- (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
+ NGTD_VER(ssl, v_tls_explicit_iv) && (ssl->enBlockSize > 1))
{
- *buf = ssl->outbuf + ssl->outlen + ssl->recordHeadLen + ssl->enBlockSize;
+ *buf = ssl->outbuf + ssl->outlen + ssl->recordHeadLen;
+ *buf += ssl->enBlockSize;
return requestedLen; /* may not be what was passed in */
}
/* GCM mode will need to save room for the nonce */
@@ -1185,7 +1186,7 @@ int32 matrixSslEncodeWritebuf(ssl_t *ssl, uint32 len)
that extra length here.
*/
if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) &&
- (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
+ ACTV_VER(ssl, v_tls_explicit_iv) && (ssl->enBlockSize > 1))
{
reserved += ssl->enBlockSize;
}
@@ -1237,7 +1238,7 @@ int32 matrixSslEncodeToOutdata(ssl_t *ssl, unsigned char *ptBuf, uint32 len)
}
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
rc = matrixSslGetEncodedSize(ssl, len);
if (rc > matrixDtlsGetPmtu())
@@ -1301,7 +1302,7 @@ static void revertToDefaultBufsize(ssl_t *ssl, uint16 inOrOut)
if (inOrOut == SSL_INBUF)
{
#ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
defaultSize = matrixDtlsGetPmtu();
}
@@ -1326,7 +1327,7 @@ static void revertToDefaultBufsize(ssl_t *ssl, uint16 inOrOut)
else
{
#ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
defaultSize = matrixDtlsGetPmtu();
}
@@ -1597,7 +1598,7 @@ DECODE_MORE:
# ifdef USE_TLS_1_1
/* Been ignoring the explicit IV up to this final return point. */
if ((ssl->flags & SSL_FLAGS_READ_SECURE) &&
- (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
+ ACTV_VER(ssl, v_tls_explicit_iv) && (ssl->enBlockSize > 1))
{
prevBuf += ssl->enBlockSize;
}
@@ -1693,7 +1694,7 @@ DECODE_MORE:
Changed and added an assert to see if these ever don't match */
psAssert(ssl->enBlockSize == ssl->deBlockSize);
if ((ssl->flags & SSL_FLAGS_READ_SECURE) &&
- (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->deBlockSize > 1))
+ ACTV_VER(ssl, v_tls_explicit_iv) && (ssl->deBlockSize > 1))
{
len -= ssl->deBlockSize;
prevBuf += ssl->deBlockSize;
@@ -1710,7 +1711,7 @@ DECODE_MORE:
know for certain we are out of the hs states. Testing HandshakeComplete
is not enough because you never know if the other side got FINISHED.
*/
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
ssl->appDataExch = 1;
}
@@ -1985,7 +1986,7 @@ int32_t matrixSslEncodeRehandshake(ssl_t *ssl, sslKeys_t *keys,
}
}
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* Resend epoch should be brought up-to-date with new epoch */
ssl->resendEpoch[0] = ssl->epoch[0];
diff --git a/matrixssl/matrixsslApi.h b/matrixssl/matrixsslApi.h
index 53f72c3..d573b3a 100644
--- a/matrixssl/matrixsslApi.h
+++ b/matrixssl/matrixsslApi.h
@@ -98,6 +98,9 @@ extern "C" {
# error Must define USE_TLS_1_x_AND_ABOVE
# endif
+/* Type used for storing protocol versions. */
+typedef uint32_t psProtocolVersion_t;
+
# if defined(USE_TLS_1_3) && defined(DISABLE_TLS_1_3)
# undef USE_TLS_1_3
# undef USE_TLS_AES_128_GCM_SHA256
@@ -158,7 +161,7 @@ extern "C" {
/* Maximum number of simultaneous TLS versions supported */
-# define TLS_MAX_SUPPORTED_VERSIONS 8
+# define TLS_MAX_SUPPORTED_VERSIONS 16
/* TLS 1.3: maximum number of algorithms in signature_algorithms extension. */
# define TLS_MAX_SIGNATURE_ALGORITHMS 32
/* TLS 1.3: maximum number of cipher suites to support in clientHello */
@@ -401,8 +404,8 @@ PSPUBLIC int32 matrixSslProcessedData(ssl_t *ssl,
PSPUBLIC int32 matrixSslEncodeClosureAlert(ssl_t *ssl);
PSPUBLIC void matrixSslDeleteSession(ssl_t *ssl);
-PSPUBLIC psBool_t matrixSslTlsVersionRangeSupported(int32_t low,
- int32_t high);
+PSPUBLIC psBool_t matrixSslTlsVersionRangeSupported(psProtocolVersion_t low,
+ psProtocolVersion_t high);
PSPUBLIC int32_t matrixSslSessOptsSetKeyExGroups(sslSessOpts_t *options,
uint16_t *namedGroups,
psSize_t namedGroupsLen,
@@ -449,6 +452,7 @@ struct sslKeySelectInfo
many elements. */
psSize_t nCas;
+# if defined(USE_IDENTITY_CERTIFICATES)
/* Array of certificate authority names, binary DER encoding, as received
from the peer. Each element caNames[N] is a binary string whose lenght
is caNameLens[N] octets.
@@ -457,6 +461,7 @@ struct sslKeySelectInfo
certificate subject/issuer names. */
const unsigned char **caNames;
psSize_t *caNameLens;
+# endif
/* Supported signature algorithm masks for transport and
certificate chains (latter for TLS1.3) */
@@ -572,9 +577,10 @@ PSPUBLIC void matrixSslDeleteHelloExtension(tlsExtension_t *extension);
PSPUBLIC int32 matrixSslCreateSNIext(psPool_t *pool, unsigned char *host,
int32 hostLen, unsigned char **extOut, int32 *extLen);
PSPUBLIC int32_t matrixSslSessOptsSetClientTlsVersionRange(sslSessOpts_t *options,
- int32_t low, int32_t high);
+ psProtocolVersion_t low,
+ psProtocolVersion_t high);
PSPUBLIC int32_t matrixSslSessOptsSetClientTlsVersions(sslSessOpts_t *options,
- const int32_t versions[],
+ const psProtocolVersion_t versions[],
int32_t versionsLen);
# ifdef USE_ALPN
@@ -784,20 +790,73 @@ typedef sslKeys_t *(*pubkeyCb_t)(struct ssl *ssl, const sslPubkeyId_t *keyId);
pskId is found. If key is not found, a negative error code shall be
returned resulting into aborted handshake. */
typedef int32_t (*pskCb_t)(struct ssl *ssl,
- const unsigned char pskId[SSL_PSK_MAX_ID_SIZE], uint8_t pskIdLen,
- unsigned char *psk[SSL_PSK_MAX_KEY_SIZE], uint8_t *pskLen);
+ const unsigned char pskId[SSL_PSK_MAX_ID_SIZE],
+ uint8_t pskIdLen,
+ unsigned char *psk[SSL_PSK_MAX_KEY_SIZE],
+ uint8_t *pskLen);
PSPUBLIC int32_t matrixSslNewServer(ssl_t **ssl,
pubkeyCb_t pubkeyCb,
pskCb_t pskCb,
sslCertCb_t certCb,
sslSessOpts_t *options);
-PSPUBLIC int32 matrixSslSetCipherSuiteEnabledStatus(ssl_t *ssl, psCipher16_t cipherId,
- uint32 status);
-PSPUBLIC int32_t matrixSslSessOptsSetServerTlsVersionRange(sslSessOpts_t *options,
- int32_t low, int32_t high);
-PSPUBLIC int32_t matrixSslSessOptsSetServerTlsVersions(sslSessOpts_t *options,
- const int32_t versions[],
+PSPUBLIC int32 matrixSslSetCipherSuiteEnabledStatus(ssl_t *ssl,
+ psCipher16_t cipherId,
+ uint32 status);
+
+# ifdef USE_SEC_CONFIG
+/** Security operation IDs. */
+typedef enum
+{
+ secop_undefined = 0,
+ secop_symmetric_encrypt,
+ secop_hmac,
+ secop_hash_for_sig,
+ secop_rsa_encrypt,
+ secop_rsa_decrypt,
+ secop_rsa_sign,
+ secop_rsa_verify,
+ secop_rsa_load_key,
+ secop_ecdsa_sign,
+ secop_ecdsa_verify,
+ secop_ecdsa_load_key,
+ secop_dh_import_pub,
+ secop_ecdh_import_pub,
+ secop_proto_version_check,
+ secop_sigalg_check,
+ secop_cipher_check
+} psSecOperation_t;
+/** Security callback.
+ This function will be called by MatrixSSL or Matrix Crypto to query
+ the permissibility of an operation. */
+typedef psRes_t (*securityCb_t)(
+ void *ctx, /* Pointer to either ssl_t or crypto_t */
+ psSecOperation_t op, /* Crypto/TLS op code, e.g. CRYPTO_OP_RSA_PKCS1_5_SIGN. */
+ psSizeL_t nbits, /* Bits to use in the operation (key size or similar.) */
+ void *extraData); /* Extra decision-making info; format depends on op. */
+/** Set the security callback to use in TLS connections using ssl_t. */
+void matrixSslRegisterSecurityCallback(
+ ssl_t *ssl,
+ securityCb_t cb);
+/** Pre-defined security profiles. */
+typedef enum
+{
+ secprofile_default = 0,
+ secprofile_wpa3_1_0_enterprise_192 = 1
+} psPreDefinedSecProfile_t;
+/** Assign one of the pre-defined security profiles to ssl struct. */
+PSPUBLIC int32_t matrixSslSetSecurityProfile(
+ ssl_t *ssl,
+ psPreDefinedSecProfile_t profile);
+# endif /* USE_SEC_CONFIG */
+
+PSPUBLIC int32_t matrixSslSessOptsSetServerTlsVersionRange(
+ sslSessOpts_t *options,
+ psProtocolVersion_t low,
+ psProtocolVersion_t high);
+PSPUBLIC int32_t matrixSslSessOptsSetServerTlsVersions(
+ sslSessOpts_t *options,
+ const psProtocolVersion_t versions[],
int32_t versionsLen);
/* Callback function of this type is called from the matrix library on the
diff --git a/matrixssl/matrixsslCheck.h b/matrixssl/matrixsslCheck.h
index bdee4fb..e4dda6e 100644
--- a/matrixssl/matrixsslCheck.h
+++ b/matrixssl/matrixsslCheck.h
@@ -53,6 +53,7 @@ extern "C" {
# endif
# define DTLS_MAJ_VER 0xFE
# define DTLS_MIN_VER 0xFF
+# define DTLS_1_0_MIN_VER DTLS_MIN_VER
# define DTLS_1_2_MIN_VER 0xFD/* DTLS 1.2 */
# endif /* USE_DTLS */
@@ -74,35 +75,6 @@ extern "C" {
# error "USE_RSA with USE_TLS_1_3 requires USE_PKCS1_PSS"
# endif
-/*
- Convenience macros for finding out minimum and maximum enabled TLS version.
-*/
-# if defined(USE_TLS_1_3) && !defined(DISABLE_TLS_1_3)
-# define MAX_ENABLED_TLS_VER TLS_1_3_MIN_VER
-# define MIN_ENABLED_TLS_1_3_DRAFT_VERSION 22
-# define MAX_ENABLED_TLS_1_3_DRAFT_VERSION 28
-# elif defined(USE_TLS_1_2) && !defined(DISABLE_TLS_1_2)
-# define MAX_ENABLED_TLS_VER TLS_1_2_MIN_VER
-# elif defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1)
-# define MAX_ENABLED_TLS_VER TLS_1_1_MIN_VER
-# elif defined(USE_TLS) && !defined(DISABLE_TLS_1_0)
-# define MAX_ENABLED_TLS_VER TLS_MIN_VER
-# elif !defined(DISABLE_SSLV3)
-# define MAX_ENABLED_TLS_VER SSL3_MIN_VER
-# endif
-
-# if !defined(DISABLE_SSLV3)
-# define MIN_ENABLED_TLS_VER SSL3_MIN_VER
-# elif defined(USE_TLS) && !defined(DISABLE_TLS_1_0)
-# define MIN_ENABLED_TLS_VER TLS_MIN_VER
-# elif defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1)
-# define MIN_ENABLED_TLS_VER TLS_1_1_MIN_VER
-# elif defined(USE_TLS_1_2) && !defined(DISABLE_TLS_1_2)
-# define MIN_ENABLED_TLS_VER TLS_1_2_MIN_VER
-# elif defined(USE_TLS_1_3) && !defined(DISABLE_TLS_1_3)
-# define MIN_ENABLED_TLS_VER TLS_1_3_LOWEST_DRAFT_MIN_VER
-# endif
-
# ifdef USE_SHARED_SESSION_CACHE
# ifndef POSIX
# error "USE_SHARED_SESSION_CACHE only implemented for POSIX platforms."
@@ -112,6 +84,12 @@ extern "C" {
# endif
# endif
+# if defined(USE_ED25519)
+# ifndef USE_CERT_PARSE
+# error "USE_ED25519 requires USE_CERT_PARSE"
+# endif
+# endif
+
# ifdef USE_EAP_FAST
/******************************************************************************/
# ifndef USE_SHA1
@@ -175,6 +153,7 @@ extern "C" {
# endif
# endif
+
/******************************************************************************/
/*
Test specific crypto features based on which cipher suites are enabled
@@ -259,6 +238,7 @@ extern "C" {
# define USE_RSA_CIPHER_SUITE
# endif
+
/******************************************************************************/
/*
Notes on DHE-related defines
@@ -289,13 +269,19 @@ extern "C" {
# if defined(USE_TLS_AES_256_GCM_SHA384) || defined(USE_TLS_AES_128_GCM_SHA256)
# define USE_DHE_CIPHER_SUITE
-# define USE_ECDSA_CIPHER_SUITE
-# define USE_ECC_CIPHER_SUITE
+# ifdef USE_RSA
+# define USE_RSA_CIPHER_SUITE
+# endif
+# ifdef USE_ECC
+# define USE_ECDSA_CIPHER_SUITE
+# define USE_ECC_CIPHER_SUITE
+# endif
# define USE_AES_CIPHER_SUITE
# define USE_TLS_1_3_CIPHER_SUITE
# endif
-# ifdef USE_TLS_CHACHA20_POLY1305_SHA256
+
+# ifdef USE_/* TLS_CHACHA20_POLY1305_SHA256 */
# define USE_DHE_CIPHER_SUITE
# define USE_ECDSA_CIPHER_SUITE
# define USE_ECC_CIPHER_SUITE
@@ -420,6 +406,7 @@ extern "C" {
# define USE_RSA_CIPHER_SUITE
# endif
+
# if defined(USE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256) || defined(USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA256)
# ifndef USE_RSA
# error "Enable USE_RSA in cryptoConfig.h for TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"
@@ -590,6 +577,7 @@ extern "C" {
# define USE_AES_CIPHER_SUITE
# endif
+
# ifdef USE_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
# ifndef USE_AES_GCM
# error "Enable USE_AES_GCM in cryptoConfig.h for TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
@@ -761,6 +749,7 @@ extern "C" {
# endif
# endif /* ! TLS_1_2 */
+
/** @note This cipher is deprecated from matrixsslConfig.h */
# ifdef USE_SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
# ifndef USE_3DES
@@ -861,6 +850,7 @@ extern "C" {
# define USE_DHE_PSK_CIPHER_SUITE
# endif
+
# ifdef USE_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
# ifndef USE_AES
# error "Enable USE_AES in cryptoConfig.h for TLS_DHE_PSK_WITH_AES_256_CBC_SHA"
@@ -1138,8 +1128,7 @@ extern "C" {
user can disable USE_X509, USE_RSA, USE_ECC, and USE_PRIVATE_KEY_PARSING in
cryptoConfig.h.
*/
-# if !defined(USE_RSA_CIPHER_SUITE) && !defined(USE_DHE_CIPHER_SUITE) && \
- !defined(USE_DH_CIPHER_SUITE)
+# if !defined(USE_RSA_CIPHER_SUITE) && !defined(USE_ECC_CIPHER_SUITE) && !defined(USE_DH_CIPHER_SUITE) && !defined(USE_DHE_PSK_CIPHER_SUITE)
# ifndef USE_ONLY_PSK_CIPHER_SUITE
# define USE_ONLY_PSK_CIPHER_SUITE
# endif
@@ -1186,6 +1175,7 @@ typedef int32 psX509Cert_t;
# endif
# endif
+
# ifdef USE_TLS_1_3_CIPHER_SUITE
# ifndef USE_TLS_1_3
# error "Need USE_TLS_1_3 for TLS 1.3 suites"
@@ -1199,8 +1189,15 @@ typedef int32 psX509Cert_t;
# ifndef USE_HKDF
# error "Need USE_HKDF for TLS 1.3"
# endif
-# define USE_ECC_CIPHER_SUITE
-# define USE_DHE_CIPHER_SUITE
+# ifdef USE_ECC
+# define USE_ECC_CIPHER_SUITE
+# endif
+# ifdef USE_DH
+# define USE_DHE_CIPHER_SUITE
+# endif
+# ifdef USE_RSA
+# define USE_RSA_CIPHER_SUITE
+# endif
# define USE_PSK_CIPHER_SUITE
# ifdef USE_DH
# define REQUIRE_DH_PARAMS
@@ -1219,6 +1216,8 @@ typedef int32 psX509Cert_t;
# endif
# endif
+#ifdef USE_RSA_CIPHER_SUITE
+#endif
/* USE_IDENTITY_CERTIFICATES maps high level "features" requiring
certificate/public key authentication into a single concrete CPP definition
used to guard code line needed to implement the features.
@@ -1243,17 +1242,6 @@ typedef int32 psX509Cert_t;
# endif
#endif
-#if defined(USE_RSA_CIPHER_SUITE) && !defined(USE_RSA)
-# define USE_RSA 1
-#endif
-
-#if defined(USE_ECC_CIPHER_SUITE) && !defined(USE_ECC)
-# define USE_ECC 1
-#endif
-
-#if defined(USE_ECDSA_CIPHER_SUITE) && !defined(USE_ECC)
-# define USE_ECC 1
-#endif
# ifdef __cplusplus
}
diff --git a/matrixssl/matrixsslInitVer.c b/matrixssl/matrixsslInitVer.c
new file mode 100644
index 0000000..a19bb4d
--- /dev/null
+++ b/matrixssl/matrixsslInitVer.c
@@ -0,0 +1,461 @@
+/**
+ * @file matrixsslInitVer.c
+ * @version $Format:%h%d$
+ *
+ * Functions for initialization protocol versions in a session.
+ */
+/*
+ * Copyright (c) 2013-2018 INSIDE Secure Corporation
+ * Copyright (c) PeerSec Networks, 2002-2011
+ * All Rights Reserved
+ *
+ * The latest version of this code is available at http://www.matrixssl.org
+ *
+ * This software is open source; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This General Public License does NOT permit incorporating this software
+ * into proprietary programs. If you are unable to comply with the GPL, a
+ * commercial license for this software may be purchased from INSIDE at
+ * http://www.insidesecure.com/
+ *
+ * This program is distributed in WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+/******************************************************************************/
+
+#include "matrixsslImpl.h"
+
+int32 initSupportedVersions(ssl_t *ssl, sslSessOpts_t *options);
+extern int32 getClientDefaultVersions(ssl_t *ssl);
+extern int32 getServerDefaultVersions(ssl_t *ssl);
+extern int32 getDefaultVersions(ssl_t *ssl);
+
+psBool_t matrixSslTlsVersionRangeSupported(psProtocolVersion_t low,
+ psProtocolVersion_t high)
+{
+ if (low > high)
+ {
+ psTraceInfo("Invalid version range: low > high\n");
+ return PS_FALSE;
+ }
+
+ if (!COMPILED_IN_VER(low) || !COMPILED_IN_VER(high))
+ {
+ return PS_FALSE;
+ }
+
+ low <<= 1;
+ while (low < high)
+ {
+ if (!COMPILED_IN_VER(low))
+ {
+ return PS_FALSE;
+ }
+ low <<= 1;
+ }
+ return PS_TRUE;
+}
+
+#ifdef USE_CLIENT_SIDE_SSL
+int32_t
+matrixSslSessOptsSetClientTlsVersionRange(sslSessOpts_t *options,
+ psProtocolVersion_t low,
+ psProtocolVersion_t high)
+{
+ psProtocolVersion_t versions[TLS_MAX_SUPPORTED_VERSIONS] = {0};
+ uint8_t numVersions = 0;
+ uint32_t i;
+
+ if (low > high)
+ {
+ return PS_ARG_FAIL;
+ }
+
+ /* Copy the range to array for SetClientTlsVersions */
+ i = 0;
+ do
+ {
+ if (COMPILED_IN_VER(high))
+ {
+ versions[i] = high;
+ }
+ numVersions++;
+ i++;
+ high >>= 1;
+ } while (high >= low);
+
+ return matrixSslSessOptsSetClientTlsVersions(options,
+ versions,
+ numVersions);
+}
+
+PSPUBLIC int32_t
+matrixSslSessOptsSetClientTlsVersions(sslSessOpts_t *options,
+ const psProtocolVersion_t versions[],
+ int32_t versionsLen)
+{
+ uint8_t i, k;
+ psProtocolVersion_t highestVersion = 0;
+# ifdef USE_TLS_1_3
+ psBool_t haveTls13Draft28 = PS_FALSE;
+# endif
+
+ if (options == NULL)
+ {
+ return PS_ARG_FAIL;
+ }
+ if (versionsLen == 0)
+ {
+ psTraceErrr("Please enable at least one version.\n");
+ return PS_ARG_FAIL;
+ }
+ if (versionsLen > TLS_MAX_SUPPORTED_VERSIONS)
+ {
+ psTraceErrr("Too many supported versions. Increase " \
+ "TLS_MAX_SUPPORTED_VERSIONS.\n");
+ return PS_ARG_FAIL;
+ }
+# ifdef USE_TLS_1_3
+ for (i = 0; i < versionsLen; i++)
+ {
+ if (versions[i] == v_tls_1_3_draft_28)
+ {
+ haveTls13Draft28 = PS_TRUE;
+ }
+ }
+# endif
+
+ options->supportedVersionsLen = 0;
+ for (i = 0, k = 0; i < versionsLen; i++)
+ {
+ if (!matrixSslTlsVersionRangeSupported(versions[i], versions[i]))
+ {
+ psTraceErrr("Unsupported version. Please enable more " \
+ "versions in matrixsslConfig.h.\n");
+ return PS_ARG_FAIL;
+ }
+ options->supportedVersions[k++] = versions[i];
+ options->supportedVersionsLen++;
+ if (versions[i] > highestVersion)
+ {
+ highestVersion = versions[i];
+ }
+# ifdef USE_TLS_1_3
+ if (versions[i] == v_tls_1_3 && !haveTls13Draft28)
+ {
+ /* Very little support in the wild for TLS 1.3 RFC version,
+ so add draft #28 as well. TODO: remove.*/
+ options->supportedVersions[k++] = v_tls_1_3_draft_28;
+ options->supportedVersionsLen++;
+ }
+# endif
+ }
+
+ /* Set the versionFlag always to highest version. Note that
+ versionFlag is not the same as the legacy version field
+ so it can contain also the 1.3 version.
+ Note that the priority order of the versions only affects to order of
+ versions in the TLS1.3 supportedVersions extension, nothing else */
+ options->versionFlag = VER_TO_FLAG(highestVersion);
+
+ return PS_SUCCESS;
+}
+
+#endif /* USE_CLIENT_SIDE_SSL */
+
+#ifdef USE_SERVER_SIDE_SSL
+
+int32_t
+matrixSslSessOptsSetServerTlsVersionRange(sslSessOpts_t *options,
+ psProtocolVersion_t low,
+ psProtocolVersion_t high)
+{
+ psProtocolVersion_t versions[TLS_MAX_SUPPORTED_VERSIONS] = {0};
+ uint8_t numVersions = 0;
+ uint32_t i;
+
+ if (low > high)
+ {
+ return PS_ARG_FAIL;
+ }
+
+ /* Copy the range to array for SetClientTlsVersions */
+ i = 0;
+ do
+ {
+ if (COMPILED_IN_VER(high))
+ {
+ versions[i] = high;
+ }
+ numVersions++;
+ i++;
+ high >>= 1;
+ } while (high >= low);
+
+ return matrixSslSessOptsSetServerTlsVersions(options,
+ versions,
+ numVersions);
+}
+
+PSPUBLIC int32_t
+matrixSslSessOptsSetServerTlsVersions(sslSessOpts_t *options,
+ const psProtocolVersion_t versions[],
+ int32_t versionsLen)
+{
+ uint8_t i, k;
+# ifdef USE_TLS_1_3
+ psBool_t haveTls13Draft28 = PS_FALSE;
+# endif
+
+ /*
+ On the server side the version handling goes either of two
+ ways:
+ 1. If single version is selected it is set to versionFlag
+ 2. If multiple versions are selected then the non-enabled
+ versions are disabled through the disable flags and
+ the versionFlag = 0
+ */
+ if (options == NULL)
+ {
+ return PS_ARG_FAIL;
+ }
+ if (versionsLen == 0)
+ {
+ psTraceErrr("Please enable at least one version.\n");
+ return PS_ARG_FAIL;
+ }
+ if (versionsLen > TLS_MAX_SUPPORTED_VERSIONS)
+ {
+ psTraceErrr("Too many supported versions. Increase " \
+ "TLS_MAX_SUPPORTED_VERSIONS.\n");
+ return PS_ARG_FAIL;
+ }
+
+# ifdef USE_TLS_1_3
+ for (i = 0; i < versionsLen; i++)
+ {
+ if (versions[i] == v_tls_1_3_draft_28)
+ {
+ haveTls13Draft28 = PS_TRUE;
+ }
+ }
+# endif
+ for (i = 0, k = 0; i < versionsLen; i++)
+ {
+ if (!matrixSslTlsVersionRangeSupported(versions[i], versions[i]))
+ {
+ psTraceErrr("Unsupported version. Please enable more " \
+ "versions in matrixsslConfig.h.\n");
+ psTracePrintProtocolVersionNew(INDENT_ERROR,
+ "unsupported version",
+ versions[i],
+ PS_TRUE);
+ return PS_ARG_FAIL;
+ }
+ options->supportedVersions[k++] = versions[i];
+ options->supportedVersionsLen++;
+# ifdef USE_TLS_1_3
+ if (versions[i] == v_tls_1_3 && !haveTls13Draft28)
+ {
+ /* Very little support in the wild for TLS 1.3 RFC version,
+ so add draft #28 as well. TODO: remove.*/
+ options->supportedVersions[k++] = v_tls_1_3_draft_28;
+ options->supportedVersionsLen++;
+ }
+# endif
+ }
+
+ if (versionsLen == 1)
+ {
+ /* If on the server side only one version is enabled then it
+ * is handled through the versionFlag. If there are many versions
+ * enabled then they are handled through the supportedVersions */
+ options->versionFlag = VER_TO_FLAG(versions[0]);
+ }
+
+ return PS_SUCCESS;
+}
+
+#endif /* USE_SERVER_SIDE_SSL */
+
+void addVersion(ssl_t *ssl, psProtocolVersion_t ver)
+{
+ /* First, make sure the version to be added is supported by our
+ build-time config. */
+ if (!VER_SUPPORTED_BY_BUILD(ver))
+ {
+ psTraceErrr("Warning: tried to add a version not supported by " \
+ "the build-time configuration\n");
+ psTracePrintProtocolVersionNew(INDENT_WARNING,
+ "Unsupported version",
+ ver,
+ PS_TRUE);
+ return;
+ }
+
+# ifdef USE_TLS_1_3
+ /*
+ Don't include TLS 1.3 in ClientHello supported_versions if the
+ user did not enable any 1.3 suites.
+
+ Without TLS 1.3 suites in ClientHello, TLS 1.3 cannot be
+ negotiated. And if the server then chooses <1.3, the TLS 1.3
+ downgrade protection mechanism will be triggered on the client-side,
+ causing handshake failure.
+ */
+ if ((ver & v_tls_1_3_any)
+ && IS_CLIENT(ssl)
+ && !ssl->tls13CiphersuitesEnabledClient)
+ {
+ psTraceInfo("Warning: tried to enable TLS 1.3 without enabling " \
+ "any TLS 1.3 ciphersuites. Disabling TLS 1.3 for this " \
+ "connection.\n");
+ return;
+ }
+# endif /* USE_TLS_1_3 */
+
+ ADD_VER(ssl->supportedVersions, ver);
+
+ psAssert(ssl->supportedVersionsPriorityLen < TLS_MAX_SUPPORTED_VERSIONS);
+ ssl->supportedVersionsPriority[ssl->supportedVersionsPriorityLen] = ver;
+ ssl->supportedVersionsPriorityLen++;
+
+ return;
+}
+
+/* Gets the supportedVersions list from options and saves it to ssl struct. */
+int32 initSupportedVersions(ssl_t *ssl, sslSessOpts_t *options)
+{
+ psSize_t i;
+ uint32 flags;
+ psBool_t userProvidedVersions = PS_FALSE;
+ psProtocolVersion_t highestSupported = v_undefined;
+
+ userProvidedVersions = PS_TRUE;
+ if (options->supportedVersionsLen == 0 &&
+ !(options->versionFlag & ANY_VERSION_FLAG))
+ {
+ userProvidedVersions = PS_FALSE;
+ }
+
+ for (i = 0; i < options->supportedVersionsLen; i++)
+ {
+ addVersion(ssl, options->supportedVersions[i]);
+ }
+
+ /* Unfortunately API user can bypass the API and just set the
+ version flags in options struct directly without settings
+ supportedVersions, in which case we must do it here. */
+
+ if (options->supportedVersionsLen == 0)
+ {
+ flags = options->versionFlag;
+ if (flags & SSL_FLAGS_DTLS)
+ {
+ addVersion(ssl, v_dtls_1_0);
+ highestSupported = v_dtls_1_0;
+ if (flags & SSL_FLAGS_TLS_1_2)
+ {
+ addVersion(ssl, v_dtls_1_2);
+ highestSupported = v_dtls_1_2;
+ }
+ }
+ else
+ {
+ if ((flags & SSL_FLAGS_TLS_1_0)
+ && !SUPP_VER(ssl, v_tls_1_0))
+ {
+ addVersion(ssl, v_tls_1_0);
+ }
+ if ((flags & SSL_FLAGS_TLS_1_1)
+ && !SUPP_VER(ssl, v_tls_1_1))
+ {
+ addVersion(ssl, v_tls_1_1);
+ }
+ if ((flags & SSL_FLAGS_TLS_1_2)
+ && !SUPP_VER(ssl, v_tls_1_2))
+ {
+ addVersion(ssl, v_tls_1_2);
+ }
+#ifdef USE_TLS_1_3
+ if ((flags & SSL_FLAGS_TLS_1_3)
+ && !SUPP_VER(ssl, v_tls_1_3))
+ {
+ addVersion(ssl, v_tls_1_3);
+ }
+ if ((flags & SSL_FLAGS_TLS_1_3_DRAFT_22)
+ && !SUPP_VER(ssl, v_tls_1_3_draft_22))
+ {
+ addVersion(ssl, v_tls_1_3_draft_22);
+ }
+ if ((flags & SSL_FLAGS_TLS_1_3_DRAFT_23) &&
+ !SUPP_VER(ssl, v_tls_1_3_draft_23))
+ {
+ addVersion(ssl, v_tls_1_3_draft_23);
+ }
+ if ((flags & SSL_FLAGS_TLS_1_3_DRAFT_24) &&
+ !SUPP_VER(ssl, v_tls_1_3_draft_24))
+ {
+ addVersion(ssl, v_tls_1_3_draft_24);
+ }
+ if ((flags & SSL_FLAGS_TLS_1_3_DRAFT_26) &&
+ !SUPP_VER(ssl, v_tls_1_3_draft_26))
+ {
+ addVersion(ssl, v_tls_1_3_draft_26);
+ }
+ if ((flags & SSL_FLAGS_TLS_1_3_DRAFT_28) &&
+ !SUPP_VER(ssl, v_tls_1_3_draft_28))
+ {
+ addVersion(ssl, v_tls_1_3_draft_28);
+ }
+#endif
+ }
+ }
+
+ if (userProvidedVersions && ssl->supportedVersions == v_undefined)
+ {
+ /* User provided some versions, but we could not enable any of
+ them, probably due to build-time configuration. */
+ psTraceErrr("Invalid version configuration\n");
+ return MATRIXSSL_ERROR;
+ }
+
+ if (!userProvidedVersions)
+ {
+ /* Get the default versions. */
+ (void)getDefaultVersions(ssl);
+ }
+
+ /*
+ We set the highest version we support as the active version.
+ This has the following implications:
+
+ - If server, we initially try to decode the first ClientHello
+ as if it were in the TLS 1.3 ClientHello format. If this
+ doesn't work, we will try with TLS 1.2 and below.
+
+ - If client, we shall encode the first ClientHello according
+ in the TLS 1.3 ClientHello format.
+ */
+ if (IS_CLIENT(ssl))
+ {
+ if (highestSupported == v_undefined)
+ {
+ highestSupported = psVerGetHighestTls(GET_SUPP_VER(ssl));
+ }
+ SET_ACTV_VER(ssl, highestSupported);
+ }
+
+ return MATRIXSSL_SUCCESS;
+}
+
+/******************************************************************************/
diff --git a/matrixssl/matrixsslKeys.c b/matrixssl/matrixsslKeys.c
index 2a8709e..1e64374 100644
--- a/matrixssl/matrixsslKeys.c
+++ b/matrixssl/matrixsslKeys.c
@@ -362,6 +362,7 @@ static psRes_t sslLoadKeyPair(psPool_t *pool,
psSizeL_t keydata_len)
{
psRes_t err = PS_SUCCESS;
+# ifdef USE_PRIVATE_KEY_PARSING
unsigned char *unarmored;
psSizeL_t unarmored_len;
int32_t rc;
@@ -371,7 +372,6 @@ static psRes_t sslLoadKeyPair(psPool_t *pool,
psTraceInfo("slLoadKeyPair(): no key material");
return PS_SUCCESS;
}
-
rc = psPemTryDecode(pool,
keydata,
keydata_len,
@@ -461,6 +461,7 @@ static psRes_t sslLoadKeyPair(psPool_t *pool,
out:
if (unarmored != keydata)
psFree(unarmored, pool);
+# endif
return err;
}
@@ -487,6 +488,7 @@ static psRes_t sslLoadCert(psPool_t *pool,
(CERT_STORE_UNPARSED_BUFFER|CERT_STORE_DN_BUFFER));
if (rc < PS_SUCCESS)
{
+ psX509FreeCert((*cert));
return rc;
}
@@ -511,7 +513,7 @@ matrixSslCreateIdentityFromData(sslKeys_t *keys,
matrixSslLoadKeysOpts_t *opts)
{
psPubKey_t idkey;
- psX509Cert_t *idcert;
+ psX509Cert_t *idcert = NULL;
int32 err;
sslIdentity_t *id;
@@ -767,7 +769,7 @@ int32 matrixSslLoadPkcs12Mem(sslKeys_t *keys,
psPool_t *pool;
int32 rc;
psX509Cert_t *cert;
- psPubKey_t idkey;
+ psPubKey_t idkey = {0};
sslIdentity_t *id;
if (keys == NULL)
@@ -969,7 +971,7 @@ int32 matrixSslLoadPkcs12(sslKeys_t *keys,
psPool_t *pool;
int32 rc;
psX509Cert_t *cert;
- psPubKey_t idkey;
+ psPubKey_t idkey = {0};
sslIdentity_t *id;
if (keys == NULL)
diff --git a/matrixssl/matrixsslSecConfig.c b/matrixssl/matrixsslSecConfig.c
new file mode 100644
index 0000000..780f305
--- /dev/null
+++ b/matrixssl/matrixsslSecConfig.c
@@ -0,0 +1,263 @@
+/**
+ * @file matrixsslSecConfig.c
+ * @version $Format:%h%d$
+ *
+ * Functions for changing MatrixSSL's security configuration.
+ */
+/*
+ * Copyright (c) 2013-2018 INSIDE Secure Corporation
+ * Copyright (c) PeerSec Networks, 2002-2011
+ * All Rights Reserved
+ *
+ * The latest version of this code is available at http://www.matrixssl.org
+ *
+ * This software is open source; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This General Public License does NOT permit incorporating this software
+ * into proprietary programs. If you are unable to comply with the GPL, a
+ * commercial license for this software may be purchased from INSIDE at
+ * http://www.insidesecure.com/
+ *
+ * This program is distributed in WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+/******************************************************************************/
+
+#include "matrixsslImpl.h"
+
+# ifdef USE_SEC_CONFIG
+
+# ifdef USE_SEC_CONFIG_WPA3_1_0
+
+/* WPA3 1.0 only allows these three ciphersuites. */
+static
+psCipher16_t cipherlist_wpa3_1_0_enterprise_192[] =
+{
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+};
+static psSize_t cipherlist_wpa3_1_0_enterprise_192_len = 3;
+static uint32_t ec_flags_wpa3_1_0_enterprise_192 = SSL_OPT_SECP384R1;
+
+/* We use the psSecConfig_t to restrict the RSA/ECDSA/DH sizes.
+ WPA3 1.0 Enterprise claims to require "192 bits" of security.
+ In reality, this is not quite true; it would need a much
+ larger RSA key in that case.
+
+ Note that we shall use this only in the TLS layer. So setting
+ min_rsa_bits to 3072 does not restrict the use of RSA sigs
+ in certificates as the X.509 lib is separate. */
+static
+psSecConfig_t secconfig_wpa3_1_0_enterprise_192 =
+{
+ .min_symmetric_key_bits = 192,
+ .min_rsa_bits = 3072,
+ .min_rsa_verify_bits = 3072,
+ .min_dh_key_bits = 3072,
+ .min_dh_group_bits = 3072,
+ .min_ec_curve_bits = 384,
+ .min_ec_verify_curve_bits = 384,
+ .min_hmac_bits = 384,
+ .min_signature_hash_bits = 0,
+ .min_signature_verify_hash_bits = 0,
+ .allow_pkcs1_sigs_in_handshake = PS_TRUE,
+ .allow_pkcs1_sigs_in_certs = PS_TRUE,
+ .allow_rsa_key_transport = PS_FALSE, /* Only (EC)DHE-RSA allowed. */
+ .require_sig_hash_group_match = PS_FALSE,
+ .min_tls_version = v_tls_1_0
+};
+# endif /* USE_SEC_CONFIG_WPA3_1_0 */
+
+psRes_t matrixSslSetSecurityProfile(ssl_t *ssl,
+ psPreDefinedSecProfile_t profile)
+{
+ psCipher16_t *cipherList = NULL;
+ psSize_t cipherListLen = 0;
+ uint32_t ecFlags = 0;
+
+# ifndef USE_SEC_CONFIG
+ psTraceErrr("Need USE_SEC_CONFIG for matrixSslSetSecurityProfile\n");
+ return PS_UNSUPPORTED_FAIL;
+# else
+ if (ssl == NULL)
+ {
+ return PS_ARG_FAIL;
+ }
+
+ switch (profile)
+ {
+ case secprofile_default:
+ break;
+# ifdef USE_SEC_CONFIG_WPA3_1_0
+ case secprofile_wpa3_1_0_enterprise_192:
+ cipherList = cipherlist_wpa3_1_0_enterprise_192;
+ cipherListLen = cipherlist_wpa3_1_0_enterprise_192_len;
+ ecFlags = ec_flags_wpa3_1_0_enterprise_192;
+ ssl->secConfig = secconfig_wpa3_1_0_enterprise_192;
+ break;
+# endif /* USE_SEC_CONFIG_WPA3_1_0 */
+ default:
+ psTraceErrr("Invalid profile in matrixSslSetSecurityProfile\n");
+ return PS_FAILURE;
+ }
+
+ if (cipherList != NULL)
+ {
+ ssl->supportedCiphers = cipherList;
+ ssl->supportedCiphersLen = cipherListLen;
+ }
+
+ ssl->ecFlagsOverride = ecFlags;
+ ssl->secProfile = profile;
+ psTraceStrInfo("Using security profile: %s\n",
+ SECPROFILE_TO_STR(profile));
+
+ return PS_SUCCESS;
+# endif /* USE_SEC_CONFIG */
+}
+
+void matrixSslRegisterSecurityCallback(
+ ssl_t *ssl,
+ securityCb_t cb)
+{
+ if (ssl == NULL)
+ {
+ return;
+ }
+ ssl->secCb = cb;
+}
+
+/** MatrixSSL's default TLS security callback.
+
+ This callback uses information in the ssl->secConfig (a struct of
+ type psSecConfig_t) to check whether an operation is allowed
+ or not. */
+static
+psRes_t defaultTlsSecCb(void *ctx,
+ psSecOperation_t op,
+ psSizeL_t nbits,
+ void *extraData)
+{
+ ssl_t *ssl = (ssl_t*)ctx;
+
+ psTraceStrInfo("Checking %s", SECOP_TO_STR(op));
+ psTraceIntInfo(" (%zu bits)", nbits);
+ psTraceInfo("...\n");
+
+ /* Check whether operation allowed or not. Key size will be
+ checked later. */
+ switch (op)
+ {
+ case secop_rsa_encrypt:
+ case secop_rsa_decrypt:
+ if (!ssl->secConfig.allow_rsa_key_transport)
+ {
+ psTraceErrr("RSA key transport not allowed by sec config\n");
+ return MATRIXSSL_ERROR;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Check that key size is over the minimum required. */
+ switch (op)
+ {
+ case secop_rsa_encrypt:
+ case secop_rsa_decrypt:
+ case secop_rsa_sign:
+ case secop_rsa_verify:
+ if (ssl->secConfig.min_rsa_bits > nbits)
+ {
+ psTraceErrr("RSA key size too low for security config\n");
+ psTraceIntInfo("Got: %zu, ", nbits);
+ psTraceIntInfo("want: >= %hu\n", ssl->secConfig.min_rsa_bits);
+ return MATRIXSSL_ERROR;
+ }
+ break;
+ case secop_ecdsa_sign:
+ case secop_ecdsa_verify:
+ if (ssl->secConfig.min_ec_curve_bits > nbits)
+ {
+ psTraceErrr("ECDSA curve size too low for security config\n");
+ psTraceInt("Got: %zu, ", nbits);
+ psTraceInt("want: >= %hu\n", ssl->secConfig.min_ec_curve_bits);
+ return MATRIXSSL_ERROR;
+ }
+ break;
+ case secop_dh_import_pub:
+ if (ssl->secConfig.min_dh_group_bits > nbits)
+ {
+ psTraceErrr("Peer DH group size too low for security config\n");
+ psTraceInt("Got: %zu, ", nbits);
+ psTraceInt("want: >= %hu\n", ssl->secConfig.min_dh_group_bits);
+ return MATRIXSSL_ERROR;
+ }
+ break;
+ case secop_ecdh_import_pub:
+ if (ssl->secConfig.min_ec_curve_bits > nbits)
+ {
+ psTraceErrr("Peer ECDH curve size too low for security config\n");
+ psTraceInt("Got: %zu, ", nbits);
+ psTraceInt("want: >= %hu\n", ssl->secConfig.min_ec_curve_bits);
+ return MATRIXSSL_ERROR;
+ }
+ break;
+
+ /* Warn if user tries to load too small keys. In the end, it is the
+ users responsibility to load the right keys, so do not issue
+ an error. */
+ case secop_rsa_load_key:
+ if (ssl->secConfig.min_rsa_bits > nbits)
+ {
+ psTraceErrr("Warning: loaded RSA key is below minimum size " \
+ "required by security config\n");
+ psTraceIntInfo("Got: %zu, ", nbits);
+ psTraceIntInfo("want: >= %hu\n", ssl->secConfig.min_rsa_bits);
+ }
+ break;
+ case secop_ecdsa_load_key:
+ if (ssl->secConfig.min_ec_curve_bits > nbits)
+ {
+ psTraceErrr("Warning: loaded EC key is below minimum size " \
+ "required by security config\n");
+ psTraceIntInfo("Got: %zu, ", nbits);
+ psTraceIntInfo("want: >= %hu\n", ssl->secConfig.min_ec_curve_bits);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* Operation deemed as permissible if we got here. */
+ psTraceInfo("OK\n");
+ return MATRIXSSL_SUCCESS;
+}
+
+psRes_t matrixSslCallSecurityCallback(ssl_t *ssl,
+ psSecOperation_t op,
+ psSizeL_t nbits,
+ void *extraData)
+{
+ if (ssl->secCb)
+ {
+ return ssl->secCb(ssl, op, nbits, extraData);
+ }
+ else
+ {
+ return defaultTlsSecCb(ssl, op, nbits, extraData);
+ }
+}
+
+
+# endif /* USE_SEC_CONFIG */
diff --git a/matrixssl/matrixssllib.h b/matrixssl/matrixssllib.h
index afce4bd..9012279 100644
--- a/matrixssl/matrixssllib.h
+++ b/matrixssl/matrixssllib.h
@@ -259,6 +259,7 @@ extern "C" {
# ifdef USE_DTLS
# define DTLS_HEADER_ADD_LEN 8
# endif
+# define DTLS_HEADER_LEN 13
# define TLS_CHACHA20_POLY1305_IETF_AAD_LEN 13
# define TLS_GCM_AAD_LEN 13
@@ -335,22 +336,12 @@ extern "C" {
# define SSL_FLAGS_INTERCEPTOR (1U << 26)
# define SSL_FLAGS_EAP_FAST (1U << 27)
-# define USING_TLS_1_2(SSL) ((SSL->flags & SSL_FLAGS_TLS_1_2) ? PS_TRUE : PS_FALSE)
# define IS_SERVER(SSL) ((SSL->flags & SSL_FLAGS_SERVER) ? PS_TRUE : PS_FALSE)
# define IS_CLIENT(SSL) !IS_SERVER(SSL)
-# define USING_TLS_1_3(SSL) ((SSL->flags & SSL_FLAGS_TLS_1_3) || \
- (SSL->flags & SSL_FLAGS_TLS_1_3_DRAFT_22) || \
- (SSL->flags & SSL_FLAGS_TLS_1_3_DRAFT_23) || \
- (SSL->flags & SSL_FLAGS_TLS_1_3_DRAFT_24) || \
- (SSL->flags & SSL_FLAGS_TLS_1_3_DRAFT_26) || \
- (SSL->flags & SSL_FLAGS_TLS_1_3_DRAFT_28) \
- ? PS_TRUE : PS_FALSE)
-# define USING_TLS_1_3_AAD(SSL) tls13UsingAad(SSL)
-# define USING_ONLY_TLS_1_3(SSL) (USING_TLS_1_3(SSL) && \
- !(SSL->flags & SSL_FLAGS_TLS_1_2) && \
- !(SSL->flags & SSL_FLAGS_TLS_1_1) ? PS_TRUE : PS_FALSE)
-# define NEGOTIATED_TLS_1_3(SSL) ((SSL->flags & SSL_FLAGS_TLS_1_3_NEGOTIATED) ? PS_TRUE : PS_FALSE)
+# include "matrixssllib_version.h"
+# include "matrixssllib_secconfig.h"
+
# define ENCRYPTING_RECORDS(SSL) ((SSL->flags & SSL_FLAGS_WRITE_SECURE) ? PS_TRUE : PS_FALSE)
# define DECRYPTING_RECORDS(SSL) ((SSL->flags & SSL_FLAGS_READ_SECURE) ? PS_TRUE : PS_FALSE)
# define RESUMED_HANDSHAKE(SSL) isResumedHandshake(SSL)
@@ -380,18 +371,6 @@ extern "C" {
# define BFLAG_KEEP_PEER_CERTS (1 << 3) /* Keep peer cert chain. */
# define BFLAG_KEEP_PEER_CERT_DER (1 << 4) /* Keep raw DER of peer certs. */
-enum PACKED
-{
- tls_v_1_0 = 1,
- tls_v_1_1 = 2,
- tls_v_1_2 = 3,
- tls_v_1_3 = 4,
- tls_v_1_3_draft_22 = 22,
- tls_v_1_3_draft_23 = 23,
- tls_v_1_3_draft_24 = 24,
- tls_v_1_3_draft_26 = 26,
- tls_v_1_3_draft_28 = 28
-};
/*
Number of bytes server must send before creating a re-handshake credit
@@ -658,6 +637,7 @@ static inline uint16_t HASH_SIG_MASK(uint8_t hash, uint8_t sig)
# define TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x0091 /* 145 */
# define TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C /* 156 */
# define TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D /* 157 */
+# define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F /* 159 */
# define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF /**< @see RFC 5746 */
# define TLS_FALLBACK_SCSV 0x5600 /**< @see RFC 7507 */
@@ -932,7 +912,7 @@ struct psTls13Psk
# endif /* USE_TLS_1_3 */
-# if defined(USE_SERVER_SIDE_SSL) && defined(USE_STATELESS_SESSION_TICKETS)
+# if defined(USE_TLS_1_3_RESUMPTION) || (defined(USE_SERVER_SIDE_SSL) && defined(USE_STATELESS_SESSION_TICKETS))
typedef int32 (*sslSessTicketCb_t)(void *keys, unsigned char[16], short);
typedef struct sessTicketKey
@@ -1010,7 +990,7 @@ struct sslKeys
sslIdentity_t *identity;
# endif
-# if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH)
+# if defined(USE_IDENTITY_CERTIFICATES) || defined(USE_CA_CERTIFICATES)
/* For a client this is the set of trust anchors used to authenticate the
server, and for the server side this is set of trusted client
certificate issuers. */
@@ -1025,7 +1005,7 @@ struct sslKeys
psTls13Psk_t *tls13PskKeys;
# endif
# endif /* USE_PSK_CIPHER_SUITE */
-# if defined(USE_SERVER_SIDE_SSL) && defined(USE_STATELESS_SESSION_TICKETS)
+# if defined(USE_TLS_1_3_RESUMPTION) || (defined(USE_SERVER_SIDE_SSL) && defined(USE_STATELESS_SESSION_TICKETS))
psSessionTicketKeys_t *sessTickets;
sslSessTicketCb_t ticket_cb;
# endif
@@ -1061,7 +1041,7 @@ struct sslSessOpts
CertificateVerify externally. */
# endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */
int32 versionFlag; /* The SSL_FLAGS_TLS_ version (+ DTLS flag here) */
- int32_t supportedVersions[TLS_MAX_SUPPORTED_VERSIONS]; /* Priority list of supported protocol versions*/
+ uint32_t supportedVersions[TLS_MAX_SUPPORTED_VERSIONS]; /* Priority list of supported protocol versions*/
psSize_t supportedVersionsLen;
# ifdef USE_TLS_1_3
uint16_t tls13SupportedSigAlgsCert[TLS_MAX_SIGNATURE_ALGORITHMS];
@@ -1224,15 +1204,14 @@ typedef struct
pubkeyCb_t pubkeyCb;
# endif
-# ifndef USE_ONLY_PSK_CIPHER_SUITE
sslKeySelectInfo_t keySelect;
+
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
sslIdentityCb_t identityCb;
-# if defined(USE_CLIENT_SIDE_SSL) || defined(USE_CLIENT_AUTH)
- /* Client side identity callback, and a pointer to client side
- identity key selectors for external certificate/key loading */
+# if defined(USE_IDENTITY_CERTIFICATES) || defined(USE_CERT_VALIDATE)
psX509Cert_t *cert;
sslCertCb_t validateCert;
-# endif /* USE_CLIENT_SIDE_SSL || USE_CLIENT_AUTH */
+# endif /* USE_IDENTITY_CERTIFICATES */
# endif /* USE_ONLY_PSK_CIPHER_SUITE */
# ifdef USE_CLIENT_SIDE_SSL
@@ -1293,11 +1272,10 @@ typedef struct
psEccKey_t *eccKeyPub; /* remote key */
psPool_t *eccDhKeyPool; /* handshake-scope pool for clients */
unsigned char *x25519KeyPub;
-# ifdef USE_TLS_1_3
- psPubKey_t *tls13KeyAgreeKeys[TLS_1_3_MAX_GROUPS];
-# endif
# endif
-
+# ifdef USE_TLS_1_3
+ psPubKey_t *tls13KeyAgreeKeys[TLS_1_3_MAX_GROUPS];
+# endif
int32 anon;
} sslSec_t;
@@ -1568,23 +1546,41 @@ struct ssl
uint8_t hsState; /* Next expected SSL_HS_ message type */
uint8_t decState; /* Most recent encoded SSL_HS_ message */
uint8_t encState; /* Most recent decoded SSL_HS_ message */
- uint8_t reqMajVer;
- uint8_t reqMinVer;
- uint8_t majVer;
- uint8_t minVer;
- uint16_t supportedVersions[TLS_MAX_SUPPORTED_VERSIONS];
- psSize_t supportedVersionsLen;
+# ifdef USE_SEC_CONFIG
+ psCipher16_t *supportedCiphers;
+ psSize_t supportedCiphersLen;
+ psPreDefinedSecProfile_t secProfile;
+ psSecConfig_t secConfig;
+ securityCb_t secCb;
+ uint32_t ecFlagsOverride;
+# endif /* USE_SEC_CONFIG */
+# ifdef USE_SSL_INFORMATIONAL_TRACE
+ /* Store information about the peer public key, to be printed
+ in matrixSslPrintHSDetails. */
+ uint8_t peerAuthKeyType;
+ uint8_t peerKeyExKeyType;
+ psSize_t peerAuthKeyNBits;
+ psSize_t peerKeyExKeyNBits;
+# endif
+ /* List of TLS spec versions supported by us. Both compile-time and
+ run-time configuration affect these. */
+ psProtocolVersion_t supportedVersions; /* TLS versions we support. */
+ psProtocolVersion_t supportedVersionsPeer; /* TLS versions the peer supports. */
+ psProtocolVersion_t ourHelloVersion; /* Version we encoded in ClientHello. */
+ psProtocolVersion_t peerHelloVersion; /* legacy_version from peer's hello msg. */
+ psProtocolVersion_t activeVersion; /* TLS spec version we are following.
+ If v_tls_negotiated flag is set,
+ this version has been succesfully
+ negotiated with the peer. */
+ /* Priority-ordering information for supported versions.*/
+ psProtocolVersion_t supportedVersionsPriority[TLS_MAX_SUPPORTED_VERSIONS];
+ psProtocolVersion_t supportedVersionsPriorityLen;
#ifdef USE_TLS_1_3
- /* The supported versions array is the client's supported
- * versions list. It is either set through the API (when MatrixSSL is
- * client) or filled when ClientHello is received (when MatrixSSL is
- * server) */
- uint8_t tls13NegotiatedMinorVer;
+ psProtocolVersion_t peerSupportedVersionsPriority[TLS_MAX_SUPPORTED_VERSIONS];
+ psSize_t peerSupportedVersionsPriorityLen;
psBool_t tls13IncorrectDheKeyShare;
- uint16_t tls13PeerSupportedVersions[TLS_MAX_SUPPORTED_VERSIONS];
- psSize_t tls13PeerSupportedVersionsLen;
psBool_t gotTls13CiphersuiteInCH; /* Does CH contain any 1.3 suites? */
uint16_t tls13SupportedSigAlgsCert[TLS_MAX_SIGNATURE_ALGORITHMS];
psSize_t tls13SupportedSigAlgsCertLen;
@@ -1736,14 +1732,15 @@ struct ssl
uint32 deny_max_fragment_len : 1;
uint32 deny_session_ticket : 1;
/* Whether the server received this extension. */
- uint32 got_key_share : 1;
- uint32 got_supported_versions : 1;
- uint32 got_pre_shared_key : 1;
uint32 got_psk_key_exchange_modes : 1;
uint32 got_cookie : 1;
- uint32 got_early_data : 1;
uint32 got_elliptic_points : 1;
# endif
+ uint32 got_supported_versions : 1; /* server only; but 1bit only */
+ uint32 got_key_share : 1; /* server only; but 1bit only */
+ uint32 got_pre_shared_key : 1; /* server only; but 1bit only */
+
+ uint32 got_early_data : 1;
/* Set if the extension was negotiated successfully */
uint32 sni : 1;
uint32 truncated_hmac : 1;
@@ -1841,35 +1838,6 @@ PSPUBLIC int32 matrixSslIsSessionCompressionOn(ssl_t *ssl);
# endif
# ifdef USE_TLS_1_3
-static inline
-psBool_t tls13UsingAad(ssl_t *ssl)
-{
- /* AAD is used from draft 26 onwards. */
- if (ssl->tls13NegotiatedMinorVer == TLS_1_3_MIN_VER ||
- ssl->tls13NegotiatedMinorVer >= TLS_1_3_DRAFT_26_MIN_VER)
- {
- return PS_TRUE;
- }
-
- /* If negotiated version is 0, we may be trying to encrypt early
- data using a PSK-derived key. The PSK may not necessarily
- have associated version information and even if it did, we
- do not store the draft version. So, when using using a PSK,
- we shall assume draft 26 if we are support it. Yes, this
- is an ugly kludge, but whole draft version mess should
- disappear once the final RFC has been approved and taken into
- use. */
- if (ssl->tls13NegotiatedMinorVer == 0 &&
- ((ssl->flags & SSL_FLAGS_TLS_1_3) ||
- (ssl->flags & SSL_FLAGS_TLS_1_3_DRAFT_26) ||
- (ssl->flags & SSL_FLAGS_TLS_1_3_DRAFT_28)))
- {
- return PS_TRUE;
- }
-
- return PS_FALSE;
-}
-
static inline
psBool_t tls13IsResumedHandshake(ssl_t *ssl)
{
@@ -1890,7 +1858,7 @@ static inline
psBool_t isResumedHandshake(ssl_t *ssl)
{
# ifdef USE_TLS_1_3
- if (NEGOTIATED_TLS_1_3(ssl))
+ if (NGTD_VER(ssl, v_tls_1_3_any))
{
return tls13IsResumedHandshake(ssl);
}
@@ -1934,8 +1902,7 @@ extern int32 parseClientHelloExtensions(ssl_t *ssl, unsigned char **cp,
unsigned short len);
extern int32 parseClientKeyExchange(ssl_t *ssl, int32 hsLen, unsigned char **cp,
unsigned char *end);
-extern int32 checkClientHelloVersion(ssl_t *ssl,
- unsigned char *serverHighestMinor);
+extern int32 checkClientHelloVersion(ssl_t *ssl);
extern int32 checkSupportedVersions(ssl_t *ssl);
# ifndef USE_ONLY_PSK_CIPHER_SUITE
# ifdef USE_CLIENT_AUTH
@@ -2004,10 +1971,8 @@ extern int32_t findFromUint16Array(const uint16_t *a,
const uint16_t b);
extern psBool_t anyTls13VersionSupported(ssl_t *ssl);
extern psBool_t anyNonTls13VersionSupported(ssl_t *ssl);
-extern psBool_t tlsVersionSupported(ssl_t *ssl, const uint8_t minVersion);
extern psBool_t peerOnlySupportsTls13(ssl_t *ssl);
extern psBool_t weOnlySupportTls13(ssl_t *ssl);
-extern int32 tlsMinVerToVersionFlag(int32_t minVer);
extern uint16_t tlsMinVerToOfficialVer(int32_t minVer);
# ifdef USE_CERT_PARSE
@@ -2016,6 +1981,31 @@ extern void matrixSslReorderCertChain(psX509Cert_t *a_cert);
# endif
# endif
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
+extern int32_t tlsVerify(ssl_t *ssl,
+ const unsigned char *tbs,
+ psSizeL_t tbsLen,
+ const unsigned char *c,
+ const unsigned char *end,
+ psPubKey_t *pubKey,
+ psVerifyOptions_t *opts);
+extern psRes_t tlsPrepareSkeSignature(ssl_t *ssl,
+ int32_t skeSigAlg,
+ unsigned char *tbsStart,
+ unsigned char *c);
+extern psRes_t tlsMakeSkeSignature(ssl_t *ssl,
+ pkaAfter_t *pka,
+ psBuf_t *out);
+extern int32_t chooseSkeSigAlg(ssl_t *ssl,
+ sslIdentity_t *id);
+extern int accountForEcdsaSizeChange(ssl_t *ssl,
+ pkaAfter_t *pka,
+ int real,
+ unsigned char *sig,
+ psBuf_t *out,
+ int hsMsg);
+# endif /* USE_ONLY_PSK_CIPHER_SUITE */
+
# ifdef USE_TLS_1_3
/* Parsing. */
extern int32 matrixSslDecodeTls13(ssl_t *ssl,
@@ -2275,9 +2265,12 @@ extern int32_t tls13ValidateSessionParams(ssl_t *ssl,
psTls13SessionParams_t *params);
/* Negotiation. */
+#ifdef USE_IDENTITY_CERTIFICATES
extern int32_t tls13TryNegotiateParams(ssl_t *ssl,
const sslCipherSpec_t *spec,
sslIdentity_t *givenKey);
+# endif
+
extern uint16_t tls13NegotiateGroup(ssl_t *ssl,
uint16_t *peerList,
psSize_t peerListLen);
@@ -2293,7 +2286,14 @@ extern int32_t tls13AddPeerSupportedGroup(ssl_t *ssl,
uint16_t namedGroup);
extern int32_t tls13AddPeerKeyShareGroup(ssl_t *ssl,
uint16_t namedGroup);
-extern int32_t tls13IntersectionPrioritySelect(const uint16_t *a,
+extern int32_t tls13IntersectionPrioritySelect(const psProtocolVersion_t *a,
+ psSize_t aLen,
+ const psProtocolVersion_t *b,
+ psSize_t bLen,
+ const psProtocolVersion_t *f,
+ psSize_t fLen,
+ psProtocolVersion_t *selectedElement);
+extern int32_t tls13IntersectionPrioritySelectU16(const uint16_t *a,
psSize_t aLen,
const uint16_t *b,
psSize_t bLen,
@@ -2635,6 +2635,8 @@ void matrixsslUpdateStat(ssl_t *ssl, int32_t type, int32_t value)
/** Pre-defined indent levels to use with psTracePrint*, etc. */
# define INDENT_CONN_ESTABLISHED 0
# define INDENT_NEGOTIATED_PARAM 0
+# define INDENT_ERROR 0
+# define INDENT_WARNING 0
# define INDENT_HS_MSG 5
# define INDENT_EXTENSION 6
@@ -2767,6 +2769,10 @@ void psPrintTls13SigAlgList(psSize_t indentLevel,
uint16_t *algs,
psSize_t numAlgs,
psBool_t addNewline);
+void psPrintProtocolVersionNew(psSize_t indentLevel,
+ const char *where,
+ psProtocolVersion_t ver,
+ psBool_t addNewline);
void psPrintProtocolVersion(psSize_t indentLevel,
const char *where,
unsigned char majVer,
@@ -2778,12 +2784,7 @@ void psPrintNegotiatedProtocolVersion(psSize_t indentLevel,
psBool_t addNewline);
void psPrintVersionsList(psSize_t indentLevel,
const char *where,
- uint16_t *list,
- psSize_t listLen,
- psBool_t addNewline);
-void psPrintVersionsList32(psSize_t indentLevel,
- const char *where,
- int32_t *list,
+ psProtocolVersion_t *list,
psSize_t listLen,
psBool_t addNewline);
void psPrintSupportedVersionsList(psSize_t indentLevel,
@@ -2851,12 +2852,12 @@ void psPrintTranscriptHashUpdate(ssl_t *ssl,
psPrintTls13SigAlgList(indentLevel, where, algs, numAlgs, addNewline)
# define psTracePrintProtocolVersion(indentLevel, where, majVer, minVer, addNewline) \
psPrintProtocolVersion(indentLevel, where, majVer, minVer, addNewline)
+# define psTracePrintProtocolVersionNew(indentLevel, where, ver, addNewline) \
+ psPrintProtocolVersionNew(indentLevel, where, ver, addNewline)
# define psTracePrintNegotiatedProtocolVersion(indentLevel, where, ssl, addNewline) \
psPrintNegotiatedProtocolVersion(indentLevel, where, ssl, addNewline)
# define psTracePrintVersionsList(indentLevel, where, list, listLen, addNewline) \
psPrintVersionsList(indentLevel, where, list, listLen, addNewline)
-# define psTracePrintVersionsList32(indentLevel, where, list, listLen, addNewline) \
- psPrintVersionsList32(indentLevel, where, list, listLen, addNewline)
# define psTracePrintSupportedVersionsList(indentLevel, where, ssl, peer, addNewline) \
psPrintSupportedVersionsList(indentLevel, where, ssl, peer, addNewline)
# define psTracePrintTls13NamedGroup(indentLevel, where, curveId, addNewline) \
@@ -2895,6 +2896,7 @@ void psPrintTranscriptHashUpdate(ssl_t *ssl,
# define psTracePrintTls13SigAlg(indentLevel, where, sigAlg, addNewline)
# define psTracePrintTls13SigAlgList(indentLevel, where, algs, numAlg, addNewline)
# define psTracePrintProtocolVersion(indentLevel, where, majVer, minVer, addNewline)
+# define psTracePrintProtocolVersionNew(indentLevel, where, ver, addNewline)
# define psTracePrintNegotiatedProtocolVersion(indentLevel, where, ssl, addNewline)
# define psTracePrintVersionsList(indentLevel, where, list, listLen, addNewline)
# define psTracePrintVersionsList32(indentLevel, where, list, listLen, addNewline)
diff --git a/matrixssl/matrixssllib_secconfig.h b/matrixssl/matrixssllib_secconfig.h
new file mode 100644
index 0000000..234f6a7
--- /dev/null
+++ b/matrixssl/matrixssllib_secconfig.h
@@ -0,0 +1,103 @@
+/**
+ * @file matrixssllib_sec_config.h
+ * @version $Format:%h%d$
+ *
+ * Internal header file used for the MatrixSSL implementation.
+ * Only modifiers of the library should be intersted in this file.
+ * This file contains run-time security configuration related macros
+ * and constants.
+ */
+/*
+ * Copyright (c) 2013-2018 INSIDE Secure Corporation
+ * Copyright (c) PeerSec Networks, 2002-2011
+ * All Rights Reserved
+ *
+ * The latest version of this code is available at http://www.matrixssl.org
+ *
+ * This software is open source; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This General Public License does NOT permit incorporating this software
+ * into proprietary programs. If you are unable to comply with the GPL, a
+ * commercial license for this software may be purchased from INSIDE at
+ * http://www.insidesecure.com/
+ *
+ * This program is distributed in WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+/******************************************************************************/
+
+#ifndef _h_MATRIXSSLLIB_SEC_CONFIG
+# define _h_MATRIXSSLLIB_SEC_CONFIG
+
+# ifdef USE_SEC_CONFIG
+
+/** Run-time security configuration parameters. This struct is used by
+ MatrixSSL's default security callback implementation. */
+typedef struct {
+ /* Minimums. */
+ psSize_t min_symmetric_key_bits;
+ psSize_t min_rsa_bits; /** Key transport + sig + ver */
+ psSize_t min_rsa_verify_bits; /** Sig ver only. */
+ psSize_t min_dh_key_bits;
+ psSize_t min_dh_group_bits;
+ psSize_t min_ec_curve_bits; /** ECDH + sig + ver. */
+ psSize_t min_ec_verify_curve_bits; /** Sig ver only. */
+ psSize_t min_hmac_bits;
+ psSize_t min_signature_hash_bits; /** Sig + ver. */
+ psSize_t min_signature_verify_hash_bits; /** Sig ver only. */
+
+ /* Allowed/disallowed operations. */
+ psBool_t allow_pkcs1_sigs_in_handshake;
+ psBool_t allow_pkcs1_sigs_in_certs;
+ psBool_t allow_rsa_key_transport;
+ /** Require that hash alg used in sig must curve size. For example,
+ SHA-256 is required with P-256. In TLS 1.3, this is always
+ required. This setting applies only to <1.3.*/
+ psBool_t require_sig_hash_group_match;
+ psProtocolVersion_t min_tls_version;
+ /* + lots more. The idea is that the user will not need
+ to touch these, but use one of the pre-defined security
+ levels below. */
+} psSecConfig_t;
+
+# define SECOP_TO_STR(op) \
+ (op == secop_undefined) ? "secop_undefined" : \
+ (op == secop_symmetric_encrypt) ? "secop_symmetric_encrypt" : \
+ (op == secop_hmac) ? "secop_hmac" : \
+ (op == secop_hash_for_sig) ? "secop_hash_for_sig" : \
+ (op == secop_rsa_encrypt) ? "secop_rsa_encrypt" : \
+ (op == secop_rsa_decrypt) ? "secop_rsa_decrypt" : \
+ (op == secop_rsa_sign) ? "secop_rsa_sign" : \
+ (op == secop_rsa_verify) ? "secop_rsa_verify" : \
+ (op == secop_rsa_load_key) ? "secop_rsa_load_key" : \
+ (op == secop_ecdsa_load_key) ? "secop_ecdsa_load_key" : \
+ (op == secop_ecdsa_sign) ? "secop_ecdsa_sign" : \
+ (op == secop_ecdsa_verify) ? "secop_ecdsa_verify" : \
+ (op == secop_dh_import_pub) ? "secop_dh_import_pub" : \
+ (op == secop_ecdh_import_pub) ? "secop_ecdh_import_pub" : \
+ (op == secop_proto_version_check) ? "secop_proto_version_check" : \
+ (op == secop_sigalg_check) ? "secop_sigalg_check" : \
+ (op == secop_cipher_check) ? "secop_cipher_check" : \
+ "Unknown/unsupported security operation"
+
+# define SECPROFILE_TO_STR(sp) \
+ (sp == secprofile_default) ? "secprofile_default" : \
+ (sp == secprofile_wpa3_1_0_enterprise_192) ? "wpa3_1_0_enterprise_192" : \
+ "Unknown/unsupported security profile"
+
+psRes_t matrixSslCallSecurityCallback(ssl_t *ssl,
+ psSecOperation_t op,
+ psSizeL_t nbits,
+ void *extraData);
+
+# endif /* USE_SEC_CONFIG */
+#endif /* _h_MATRIXSSLLIB_SEC_CONFIG */
diff --git a/matrixssl/matrixssllib_version.h b/matrixssl/matrixssllib_version.h
new file mode 100644
index 0000000..b9f14f7
--- /dev/null
+++ b/matrixssl/matrixssllib_version.h
@@ -0,0 +1,461 @@
+/**
+ * @file matrixssllib_version.h
+ * @version $Format:%h%d$
+ *
+ * Internal header file used for the MatrixSSL implementation.
+ * Only modifiers of the library should be intersted in this file.
+ * This file contains protocol version related macros and constants.
+ */
+/*
+ * Copyright (c) 2013-2018 INSIDE Secure Corporation
+ * Copyright (c) PeerSec Networks, 2002-2011
+ * All Rights Reserved
+ *
+ * The latest version of this code is available at http://www.matrixssl.org
+ *
+ * This software is open source; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This General Public License does NOT permit incorporating this software
+ * into proprietary programs. If you are unable to comply with the GPL, a
+ * commercial license for this software may be purchased from INSIDE at
+ * http://www.insidesecure.com/
+ *
+ * This program is distributed in WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+/******************************************************************************/
+
+#ifndef _h_MATRIXSSLLIB_VERSION
+# define _h_MATRIXSSLLIB_VERSION
+
+/* Official on-the-wire version identifiers. */
+enum PACKED
+{
+ v_undefined_enc = 0,
+ v_ssl_3_0_enc = 0x0300,
+ v_tls_1_0_enc = 0x0301,
+ v_tls_1_1_enc = 0x0302,
+ v_tls_1_2_enc = 0x0303,
+ v_tls_1_3_enc = 0x0304,
+ v_tls_1_3_draft_22_enc = 0x7f16,
+ v_tls_1_3_draft_23_enc = 0x7f17,
+ v_tls_1_3_draft_24_enc = 0x7f18,
+ v_tls_1_3_draft_26_enc = 0x7f1a,
+ v_tls_1_3_draft_28_enc = 0x7f1c,
+ v_dtls_1_0_enc = 0xfeff,
+ v_dtls_1_2_enc = 0xfefd
+};
+
+/** A version v can be either:
+ 1. Supported by the compile-time config
+ --> if (v & v_compiled_in)
+ 2. Supported for the current connection
+ --> if (SUPP_VER(ssl, v))
+ 3. The active version
+ --> if (ACTV_VER(ssl, v))
+ 4. The negotiated version
+ --> if (NGTD_VER(ssl, v))
+
+ An activated version is the version we are currently following.
+ This affects e.g. the format of our ClientHello, whether or not
+ to allow sending early data, and whether to expect the peer's
+ hello message to have TLS or DTLS style record headers.
+
+ An active version becomes negotiated when we have sufficient
+ information from the peer to know that it also supports the
+ version.
+*/
+
+/** Bits 0 to 23 are reserved for versions. */
+#define VER_MAX_BIT 23
+
+/** Bits 24 to 31 are reserved for version attributes. */
+#define VER_ATTRIB_MAX_BIT 31
+
+/* MatrixSSL's internal protocol version identifiers. */
+enum PACKED
+{
+ v_undefined = 0,
+
+ /** Versions. The ordering of the numeric values of the enumerators
+ MUST correspond to the chronological order in which the
+ protocol specifications were published, for example:
+ v_tls_1_1 < v_tls_1_2. This affects e.g. the default
+ priority order. */
+ v_ssl_3_0 = 1ULL << 0,
+ v_tls_1_0 = 1ULL << 1,
+ v_tls_1_1 = 1ULL << 2,
+ v_dtls_1_0 = 1ULL << 3,
+ v_tls_1_2 = 1ULL << 4,
+ v_dtls_1_2 = 1ULL << 5,
+ v_tls_1_3_draft_22 = 1ULL << 6,
+ v_tls_1_3_draft_23 = 1ULL << 7,
+ v_tls_1_3_draft_24 = 1ULL << 8,
+ v_tls_1_3_draft_26 = 1ULL << 9,
+ v_tls_1_3_draft_28 = 1ULL << 10,
+ v_tls_1_3 = 1ULL << 11,
+
+ /** Version attributes. */
+ v_tls_negotiated = 1ULL << 24, /* Version negotiation complete? */
+
+ /** Version combinations. */
+
+ /** Any supported TLS 1.3 draft version. */
+ v_tls_1_3_draft_any = (v_tls_1_3_draft_22
+ | v_tls_1_3_draft_23
+ | v_tls_1_3_draft_24
+ | v_tls_1_3_draft_26
+ | v_tls_1_3_draft_28),
+ /** Any supported TLS 1.3 version. */
+ v_tls_1_3_any = (v_tls_1_3
+ | v_tls_1_3_draft_any),
+ /** Any supported TLS version. */
+ v_tls_any = (v_tls_1_0 | v_tls_1_1 | v_tls_1_2 | v_tls_1_3_any),
+ /** Any DTLS version. */
+ v_dtls_any = (v_dtls_1_0 | v_dtls_1_2),
+ /** Any supported legacy version (TLS <1.3) */
+ v_tls_legacy = (v_tls_1_0 | v_tls_1_1 | v_tls_1_2 | v_dtls_any),
+ /** Any supported TLS 1.3 version that uses AAD in record encryption. */
+ v_tls_1_3_aad = (v_tls_1_3
+ | v_tls_1_3_draft_26
+ | v_tls_1_3_draft_28),
+ /** Any supported TLS 1.3 version that uses 51 as key_share ID */
+ v_tls_1_3_key_share_51 = (v_tls_1_3
+ | v_tls_1_3_draft_23
+ | v_tls_1_3_draft_24
+ | v_tls_1_3_draft_26
+ | v_tls_1_3_draft_28),
+ /** Any supported version that uses an explicit IV in CBC mode. */
+ v_tls_explicit_iv = (v_dtls_1_0 | v_dtls_1_2 | v_tls_1_1 | v_tls_1_2),
+ /** Any recommended TLS version. TODO: remove draft #28 once the
+ RFC version becomes widely supported enough. */
+ v_tls_recommended = (v_tls_1_2 | v_tls_1_3 | v_tls_1_3_draft_28),
+ /** Any recommended DTLS version. */
+ v_dtls_recommended = v_dtls_1_2,
+ /** Any version that allows SHA-2 based ciphersuites. */
+ v_tls_sha2 = (v_tls_1_2 | v_tls_1_3_any | v_dtls_1_2),
+ /** Any version that does NOT allow SHA-2 based ciphersuites. */
+ v_tls_no_sha2 = (v_ssl_3_0 | v_tls_1_0 | v_tls_1_1 | v_dtls_1_0),
+ /** Any version that may need the BEAST workaround. */
+ v_tls_need_beast_workaround = (v_ssl_3_0 | v_tls_1_0),
+ /** Any version that uses the unsupported_extension alert. */
+ v_tls_with_unsupported_extension_alert = (v_tls_1_2
+ | v_dtls_1_2
+ | v_tls_1_3_any),
+ /** Any version that uses HMAC instead of a custom MAC construction. */
+ v_tls_with_hmac = (v_tls_any | v_dtls_any),
+ /** Any version that supports the signature_algorithms extension. */
+ v_tls_with_signature_algorithms = (v_tls_1_2
+ | v_tls_1_3_any
+ | v_dtls_1_2),
+ /** Any version that supports PKCS #1.5 sigs in CV and SKE. */
+ v_tls_with_pkcs15_auth = (v_tls_1_2 | v_dtls_1_2),
+ /** Any version that uses the TLS 1.2 PRF. */
+ v_tls_with_tls_1_2_prf = (v_tls_1_2 | v_dtls_1_2),
+ /** Any version supported by build-time-config. */
+ v_compiled_in = (0
+# if !defined(DISABLE_SSLV3)
+ | v_ssl_3_0
+# endif
+# if defined(USE_TLS) && !defined(DISABLE_TLS_1_0)
+ | v_tls_1_0
+# endif
+# if defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1)
+ | v_tls_1_1
+# if defined(USE_DTLS)
+ | v_dtls_1_0
+# endif
+# endif
+# if defined(USE_TLS_1_2) && !defined(DISABLE_TLS_1_2)
+ | v_tls_1_2
+# if defined(USE_DTLS)
+ | v_dtls_1_2
+# endif
+# endif
+# if defined(USE_TLS_1_3) && !defined(DISABLE_TLS_1_3)
+ | v_tls_1_3_any
+# endif
+ )
+};
+
+/*
+ Note: we could store all version lists as a single variable. But
+ typically the version lists imply priority order. There is no easy
+ way to store priority order in a flag variable.
+*/
+
+/* Convert from MatrixSSL internal ID to official on-the-wire ID */
+# define ENCODE_VER(ver) ( ver ## _enc )
+# define ENCODE_MIN_VER(ver) ( ver ## _enc & 0xff )
+# define ENCODE_MAJ_VER(ver) (( ver ## _enc & 0xff00 ) >> 8)
+uint16_t psEncodeVersion(psProtocolVersion_t ver);
+uint8_t psEncodeVersionMin(psProtocolVersion_t ver);
+uint8_t psEncodeVersionMaj(psProtocolVersion_t ver);
+
+/* Convert from official on-the-wire ID to MatrixSSL internal ID. */
+psProtocolVersion_t psVerFromEncoding(uint16_t enc);
+psProtocolVersion_t psVerFromEncodingMajMin(uint8_t maj, uint8_t min);
+# define VER_FROM_ENC(enc) psVerFromEncoding(enc))
+
+/*
+ Note: the following conversion macros are typically called from only
+ one function in the code, so code duplication is not an issue.
+ We define the macros here, so that all version ID stuff is in the
+ same place. This makes e.g. adding new versions easier in the future.
+*/
+
+/* Get raw version identifier without attributes. */
+# define VER_GET_RAW(ver) \
+ ((ver) & 0x00ffffff)
+
+/* Is version a less (i.e. earlier) than version b? */
+# define VER_LT(a, b) ((VER_GET_RAW(a) < VER_GET_RAW(b)))
+
+/* Is version a greater (i.e. later) than version b? */
+# define VER_GT(a, b) ((VER_GET_RAW(a) > VER_GET_RAW(b)))
+
+/** Return the lowest version enabled in ver. */
+psProtocolVersion_t psVerGetLowest(psProtocolVersion_t ver, int allowDtls);
+psProtocolVersion_t psVerGetLowestTls(psProtocolVersion_t ver);
+
+/** Return the highest version enabled in ver. */
+psProtocolVersion_t psVerGetHighest(psProtocolVersion_t ver, int allowDtls);
+psProtocolVersion_t psVerGetHighestTls(psProtocolVersion_t ver);
+
+/** Convert from the example client/server command line version ID
+ to MatrixSSL internal ID. */
+# define DIGIT_TO_VER(ver) \
+ (ver == 1) ? v_tls_1_0 : \
+ (ver == 2) ? v_tls_1_1 : \
+ (ver == 3) ? v_tls_1_2 : \
+ (ver == 4) ? v_tls_1_3 : \
+ (ver == 22) ? v_tls_1_3_draft_22 : \
+ (ver == 23) ? v_tls_1_3_draft_23 : \
+ (ver == 24) ? v_tls_1_3_draft_24 : \
+ (ver == 26) ? v_tls_1_3_draft_26 : \
+ (ver == 28) ? v_tls_1_3_draft_28 : \
+ v_undefined
+
+/* Convert from MatrixSSL internal ID to string. */
+# define VER_TO_STR(ver) \
+ (ver == v_undefined) ? "undefined" : \
+ (ver == v_ssl_3_0) ? "SSL 3.0" : \
+ (ver == v_tls_1_0) ? "TLS 1.0" : \
+ (ver == v_tls_1_1) ? "TLS 1.1" : \
+ (ver == v_tls_1_2) ? "TLS 1.2" : \
+ (ver == v_tls_1_3) ? "TLS 1.3" : \
+ (ver == v_tls_1_3_draft_22) ? "TLS 1.3 draft 22" : \
+ (ver == v_tls_1_3_draft_23) ? "TLS 1.3 draft 23" : \
+ (ver == v_tls_1_3_draft_24) ? "TLS 1.3 draft 24" : \
+ (ver == v_tls_1_3_draft_26) ? "TLS 1.3 draft 26" : \
+ (ver == v_tls_1_3_draft_28) ? "TLS 1.3 draft 28" : \
+ (ver == v_dtls_1_0) ? "DTLS 1.0" : \
+ (ver == v_dtls_1_2) ? "DTLS 1.2" : \
+ "unknown/unsupported version identifier"
+
+/** Convert from official version ID to string. */
+# define ENCODED_VER_TO_STR(ver) \
+ (ver == v_undefined_enc) ? "undefined" : \
+ (ver == v_ssl_3_0_enc) ? "SSL 3.0" : \
+ (ver == v_tls_1_0_enc) ? "TLS 1.0" : \
+ (ver == v_tls_1_1_enc) ? "TLS 1.1" : \
+ (ver == v_tls_1_2_enc) ? "TLS 1.2" : \
+ (ver == v_tls_1_3_enc) ? "TLS 1.3" : \
+ (ver == v_tls_1_3_draft_22_enc) ? "TLS 1.3 draft 22" : \
+ (ver == v_tls_1_3_draft_23_enc) ? "TLS 1.3 draft 23" : \
+ (ver == v_tls_1_3_draft_24_enc) ? "TLS 1.3 draft 24" : \
+ (ver == v_tls_1_3_draft_26_enc) ? "TLS 1.3 draft 26" : \
+ (ver == v_tls_1_3_draft_28_enc) ? "TLS 1.3 draft 28" : \
+ (ver == v_dtls_1_0_enc) ? "DTLS 1.0" : \
+ (ver == v_dtls_1_2_enc) ? "DTLS 1.2" : \
+ "unknown/unsupported version encoding"
+
+/** Convert from MatrixSSL internal ID to (deprecated) version flag. */
+int32_t psVerToFlag(psProtocolVersion_t ver);
+# define VER_TO_FLAG(ver) \
+ (psVerToFlag(ver))
+
+/** Convert from (deprecated) version flag values to intenal ID. */
+psProtocolVersion_t psFlagToVer(int32_t flag);
+# define FLAG_TO_VER(flag) \
+ (psFlagToVer(flag))
+
+/** Is "ver" supported by the build-time configuration? */
+# define VER_SUPPORTED_BY_BUILD(ver) \
+ ((ver) & v_compiled_in)
+# define COMPILED_IN_VER(ver) \
+ VER_SUPPORTED_BY_BUILD(ver)
+
+/** Setters and getters. All access to variables of type psProtocolVersion_t
+ should be via these.
+
+ The ones that print out a message look like they could produce some
+ unnecessary code duplication. But psTrace* only produces code when
+ tracing is enabled, which is probably not the case in a footprint-critical
+ environment. */
+# define ADD_VER(var, ver) \
+ ((var) |= (ver))
+# define SET_ACTV_VER(ssl, ver) \
+ do \
+ { \
+ (ssl)->activeVersion = (ver); \
+ psTracePrintProtocolVersionNew(0, \
+ IS_SERVER(ssl) ? "Server activated" : "Client activated", \
+ (ssl)->activeVersion, \
+ PS_TRUE); \
+ } \
+ while (0)
+# define SET_NGTD_VER(ssl, ver) \
+ do \
+ { \
+ ((ssl)->activeVersion = ((ver) | v_tls_negotiated)); \
+ psTracePrintProtocolVersionNew(0, \
+ IS_SERVER(ssl) ? "Server negotiated" : "Client negotiated", \
+ (ssl)->activeVersion, \
+ PS_TRUE); \
+ } \
+ while (0)
+# define RESET_NGTD_VER(ssl) \
+ do \
+ { \
+ ((ssl)->activeVersion = ((ssl)->activeVersion & ~v_tls_negotiated)); \
+ psTracePrintProtocolVersionNew(0, \
+ IS_SERVER(ssl) ? "Server unnegotiated" : "Client unnegotiated", \
+ (ssl)->activeVersion, \
+ PS_TRUE); \
+ } \
+ while (0)
+# define RESET_ACTV_VER(ssl) \
+ do \
+ { \
+ psTracePrintProtocolVersionNew(0, \
+ IS_SERVER(ssl) ? "Server deactivated" : "Client deactivated", \
+ (ssl)->activeVersion, \
+ PS_TRUE); \
+ (ssl)->activeVersion = v_undefined; \
+ } \
+ while (0)
+
+# define SET_SUPP_VER(ssl, ver) \
+ ((ssl)->supportedVersions = (ver))
+# define ADD_SUPP_VER(ssl, ver) \
+ ADD_VER((ssl)->supportedVersions, ver)
+# define ADD_SUPP_VER_PRIORITY(ssl, ver) \
+ ((ssl)->supportedVersionsPriority[(ssl)->supportedVersionsPriorityLen++] = (ver))
+
+# define GET_NGTD_VER(ssl) \
+ ((ssl)->activeVersion)
+# define GET_ACTV_VER(ssl) \
+ ((ssl)->activeVersion)
+# define GET_SUPP_VER(ssl) \
+ ((ssl)->supportedVersions)
+
+# ifdef USE_TLS_1_3
+# define ADD_PEER_SUPP_VER(ssl, ver) \
+ ((ssl)->supportedVersionsPeer |= (ver))
+# define ADD_PEER_SUPP_VER_PRIORITY(ssl, ver) \
+ ((ssl)->peerSupportedVersionsPriority[(ssl)->peerSupportedVersionsPriorityLen++] = (ver))
+# define GET_PEER_SUPP_VER(ssl) \
+ ((ssl)->supportedVersionsPeer)
+# endif /* USE_TLS_1_3 */
+
+/* Is "ver" supported by us? */
+# define SUPP_VER(ssl, ver) ((ssl)->supportedVersions & (ver))
+
+# ifdef USE_TLS_1_3
+/* Is "ver" supported by the peer? */
+# define PEER_SUPP_VER(ssl, ver) ((ssl)->supportedVersionsPeer & (ver))
+# endif
+
+/* Is "ver" the active version (the spec we are complying with, but
+ which we may not have negotiated yet with the peer)? */
+# define ACTV_VER(ssl, ver) \
+ ((ssl)->activeVersion & (ver))
+
+/* Has version negotiation completed succesfully? */
+# define NGTD(ssl) \
+ ((ssl)->activeVersion & v_tls_negotiated)
+
+# define VersionNegotiationComplete(ssl) \
+ NGTD(ssl)
+
+/* Has "ver" been succesfully negotiated with the peer? */
+# define NGTD_VER(ssl, ver) \
+ (ACTV_VER(ssl,ver) && ((ssl)->activeVersion & v_tls_negotiated))
+
+# define USING_TLS_1_2(ssl) \
+ (ACTV_VER(ssl, v_tls_1_2)) ? PS_TRUE : PS_FALSE)
+# define USING_TLS_1_3(ssl) \
+ (ACTV_VER(ssl, v_tls_1_3_any) ? PS_TRUE : PS_FALSE)
+# define USING_ONLY_TLS_1_3(ssl) \
+ (GET_ACTV_VER(ssl) == v_tls_1_3)
+
+/*
+ Does the currently active TLS 1.3 version use AAD?
+
+ Note that we don't require the version to be negotiated yet.
+ This is because we may be trying to encrypt early data using
+ a PSK-derived key. The PSK may not necessarily have associated
+ version information and even if it did, we do not store the draft
+ version.
+*/
+# define USING_TLS_1_3_AAD(SSL) ((SSL)->activeVersion & v_tls_1_3_aad)
+
+/*
+ Convenience macros for min and max version from build-time config.
+ Note that these map to MatrixSSL's internal version identifiers,
+ i.e. to v_tls_*.
+*/
+# if defined(USE_TLS_1_3) && !defined(DISABLE_TLS_1_3)
+# define MAX_ENABLED_TLS_VER v_tls_1_3
+# define MIN_ENABLED_TLS_1_3_DRAFT_VERSION v_tls_1_3_draft_23
+# define MAX_ENABLED_TLS_1_3_DRAFT_VERSION v_tls_1_3_draft_28
+# elif defined(USE_TLS_1_2) && !defined(DISABLE_TLS_1_2)
+# define MAX_ENABLED_TLS_VER v_tls_1_2
+# elif defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1)
+# define MAX_ENABLED_TLS_VER v_tls_1_1
+# elif defined(USE_TLS) && !defined(DISABLE_TLS_1_0)
+# define MAX_ENABLED_TLS_VER v_tls_1_0
+# elif !defined(DISABLE_SSLV3)
+# define MAX_ENABLED_TLS_VER v_ssl_3_0
+# endif
+
+# if !defined(DISABLE_SSLV3)
+# define MIN_ENABLED_TLS_VER v_ssl_3_0
+# elif defined(USE_TLS) && !defined(DISABLE_TLS_1_0)
+# define MIN_ENABLED_TLS_VER v_tls_1_0
+# elif defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1)
+# define MIN_ENABLED_TLS_VER v_tls_1_1
+# elif defined(USE_TLS_1_2) && !defined(DISABLE_TLS_1_2)
+# define MIN_ENABLED_TLS_VER v_tls_1_2
+# elif defined(USE_TLS_1_3) && !defined(DISABLE_TLS_1_3)
+# define MIN_ENABLED_TLS_VER MIN_ENABLED_TLS_1_3_DRAFT_VERSION
+# endif
+
+/** Version flags can still be used to select the versions to support.
+ This is deprecated, but still allowed in order not to break
+ backwards compatibility. The version flags are translated to
+ MatrixSSL internal IDs during session configuration. */
+/** Any version flag. */
+# define ANY_VERSION_FLAG \
+ (SSL_FLAGS_TLS_1_0 \
+ | SSL_FLAGS_TLS_1_1 \
+ | SSL_FLAGS_TLS_1_2 \
+ | SSL_FLAGS_TLS_1_3 \
+ | SSL_FLAGS_TLS_1_3_DRAFT_22 \
+ | SSL_FLAGS_TLS_1_3_DRAFT_23 \
+ | SSL_FLAGS_TLS_1_3_DRAFT_24 \
+ | SSL_FLAGS_TLS_1_3_DRAFT_26 \
+ | SSL_FLAGS_TLS_1_3_DRAFT_28 \
+ | SSL_FLAGS_DTLS)
+
+#endif /* _h_MATRIXSSLLIB_VERSION */
diff --git a/matrixssl/sslDecode.c b/matrixssl/sslDecode.c
index 146d6bc..578a13f 100644
--- a/matrixssl/sslDecode.c
+++ b/matrixssl/sslDecode.c
@@ -59,6 +59,227 @@ static int32 addCompressCount(ssl_t *ssl, int32 padLen);
# define MATRIX_INFLATE_FINISHED_OH 128
#endif
+static inline
+psResSize_t parseSslv2RecordHdr(ssl_t *ssl,
+ unsigned char *c)
+{
+#if defined(USE_INTERCEPTOR) || defined(ALLOW_SSLV2_CLIENT_HELLO_PARSE)
+ ssl->rec.type = SSL_RECORD_TYPE_HANDSHAKE;
+ ssl->rec.majVer = 2;
+ ssl->rec.minVer = 0;
+ ssl->rec.len = (*c & 0x7f) << 8; c++;
+ ssl->rec.len += *c;
+ return PS_SUCCESS;
+#else
+ /* OpenSSL 0.9.8 will send a SSLv2 CLIENT_HELLO. Use the -no_ssl2
+ option when running a 0.9.8 client to prevent this */
+ ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
+ psTraceErrr("SSLv2 records not supported\n");
+ return MATRIXSSL_ERROR;
+#endif
+}
+
+static inline
+psRes_t validateRecordHdrType(ssl_t *ssl)
+{
+ switch (ssl->rec.type)
+ {
+ case SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC:
+ case SSL_RECORD_TYPE_ALERT:
+ case SSL_RECORD_TYPE_HANDSHAKE:
+ case SSL_RECORD_TYPE_APPLICATION_DATA:
+ break;
+ /* Any other case is unrecognized */
+ default:
+ ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE;
+ psTraceErrr("Invalid record header type\n");
+ psTraceIntInfo("Record header type not valid: %d\n", ssl->rec.type);
+ return MATRIXSSL_ERROR;
+ }
+
+ return MATRIXSSL_SUCCESS;
+}
+
+static inline
+psRes_t validateRecordHdrVersion(ssl_t *ssl)
+{
+ psProtocolVersion_t recordVer;
+ psBool_t ok = PS_TRUE;
+
+ recordVer = psVerFromEncodingMajMin(ssl->rec.majVer, ssl->rec.minVer);
+ if (recordVer == v_undefined)
+ {
+ psTraceErrr("Unrecognized record header version\n");
+ goto out_fail;
+ }
+
+ /* If we have negotiated a protocol version, check that the
+ record header version matches the version we have negotiated.
+ However, if we are using TLS 1.3, the record header version
+ number MUST be ignored. Also do not perform the check for
+ ClientHellos, as the these could be renegotation ClientHellos
+ or DTLS' 2nd ClientHellos, both of which require version
+ negotiation to be performed anew. */
+ if (ssl->hsState != SSL_HS_CLIENT_HELLO &&
+ VersionNegotiationComplete(ssl))
+ {
+ if (!NGTD_VER(ssl, v_tls_1_3_any) &&
+ !NGTD_VER(ssl, recordVer))
+ {
+ ok = PS_FALSE;
+ }
+ }
+# ifdef USE_DTLS
+ else
+ {
+ if (recordVer & v_dtls_any)
+ {
+ if (!SUPP_VER(ssl, v_dtls_any))
+ {
+ psTraceErrr("Received a DTLS record, but DTLS not enabled\n");
+ goto out_fail;
+ }
+ /* Set this as the active version now, so that we are able to
+ decode using the correct format. Support for this version
+ will be checked later. */
+ if (!ACTV_VER(ssl, v_dtls_any))
+ {
+ SET_ACTV_VER(ssl, recordVer);
+ }
+ }
+ }
+# endif
+
+ if (ok)
+ {
+ return MATRIXSSL_SUCCESS;
+ }
+ else
+ {
+#ifdef SSL_REHANDSHAKES_ENABLED
+ /*
+ If in DONE state and this version doesn't match the previously
+ negotiated one that can be OK because a CLIENT_HELLO for a
+ rehandshake might be acting like a first time send and using
+ a lower version to get to the parsing phase. Unsupported
+ versions will be weeded out at CLIENT_HELLO parse time.
+ */
+ if (ssl->hsState != SSL_HS_DONE ||
+ ssl->rec.type != SSL_RECORD_TYPE_HANDSHAKE)
+ {
+ goto out_fail_mismatch;
+ }
+#else
+ goto out_fail_mismatch;
+#endif
+ }
+
+out_fail_mismatch:
+ psTraceErrr("Record header version does not match negotiated\n");
+
+out_fail:
+ ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
+ psTracePrintProtocolVersionNew(INDENT_ERROR,
+ "Unexpected version",
+ recordVer,
+ PS_TRUE);
+ ssl->err = SSL_ALERT_PROTOCOL_VERSION;
+ return MATRIXSSL_ERROR;
+}
+
+static inline
+psRes_t validateRecordHdrLen(ssl_t *ssl)
+{
+ /*
+ Verify max and min record lengths
+ */
+ if (ssl->rec.len > SSL_MAX_RECORD_LEN || ssl->rec.len == 0)
+ {
+ ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
+ psTraceErrr("Invalid record header length\n");
+ psTraceIntInfo("Record header length not valid: %d\n", ssl->rec.len);
+ return MATRIXSSL_ERROR;
+ }
+
+ return MATRIXSSL_SUCCESS;
+}
+
+/** Parse and validate a record header.
+ Returns the number of bytes parsed or < 0 on error. */
+static inline
+psResSize_t handleRecordHdr(ssl_t *ssl,
+ unsigned char *c,
+ unsigned char *end,
+ uint32_t *requiredLen,
+ int32 *error)
+{
+ unsigned char *orig_c = c;
+ psRes_t res;
+
+ if ((*c & 0x80) && (GET_NGTD_VER(ssl) == v_undefined))
+ {
+ res = parseSslv2RecordHdr(ssl, c);
+ if (res < 0)
+ {
+ return res;
+ }
+ c += 2;
+ }
+
+ psAssert(ssl->recordHeadLen == SSL3_HEADER_LEN ||
+ ssl->recordHeadLen == DTLS_HEADER_LEN);
+
+ if (end - c < ssl->recordHeadLen)
+ {
+ *requiredLen = ssl->recordHeadLen;
+ return SSL_PARTIAL;
+ }
+
+ /*
+ Parse and validate the record header. The type must be valid,
+ the major and minor versions must match the negotiated versions
+ (if we're past ClientHello) and the length must be < 16K and > 0
+ */
+ ssl->rec.type = *c; c++;
+ res = validateRecordHdrType(ssl);
+ if (res != MATRIXSSL_SUCCESS)
+ {
+ return res;
+ }
+
+ ssl->rec.majVer = *c; c++;
+ ssl->rec.minVer = *c; c++;
+ res = validateRecordHdrVersion(ssl);
+ if (res != MATRIXSSL_SUCCESS)
+ {
+ return res;
+ }
+
+#ifdef USE_DTLS
+ if (ACTV_VER(ssl, v_dtls_any))
+ {
+ ssl->rec.epoch[0] = *c++;
+ ssl->rec.epoch[1] = *c++;
+ ssl->rec.rsn[0] = *c++;
+ ssl->rec.rsn[1] = *c++;
+ ssl->rec.rsn[2] = *c++;
+ ssl->rec.rsn[3] = *c++;
+ ssl->rec.rsn[4] = *c++;
+ ssl->rec.rsn[5] = *c++;
+ }
+#endif
+
+ ssl->rec.len = *c << 8; c++;
+ ssl->rec.len += *c++;
+ res = validateRecordHdrLen(ssl);
+ if (res != MATRIXSSL_SUCCESS)
+ {
+ return res;
+ }
+
+ return (c - orig_c);
+}
+
/******************************************************************************/
/*
Parse incoming data per http://wp.netscape.com/eng/ssl3
@@ -135,6 +356,7 @@ int32 matrixSslDecode(ssl_t *ssl, unsigned char **buf, uint32 *len,
#ifdef USE_TLS_1_3
psBool_t useOutbufForResponse = PS_FALSE;
#endif
+
/*
If we've had a protocol error, don't allow further use of the session
*/
@@ -179,8 +401,7 @@ int32 matrixSslDecode(ssl_t *ssl, unsigned char **buf, uint32 *len,
entire ServerHello. Without this check, we could fail for
an obscure reason, such as the ServerHello not containing
renegotiation_info extension if the client sent it.*/
- if (ssl->supportedVersionsLen > 0
- && !anyNonTls13VersionSupported(ssl))
+ if (!SUPP_VER(ssl, v_tls_legacy))
{
psTraceErrr("Server tried to downgrade to an earlier" \
" version, but we only support TLS 1.3\n");
@@ -191,12 +412,6 @@ int32 matrixSslDecode(ssl_t *ssl, unsigned char **buf, uint32 *len,
}
/*
Pre-TLS 1.3 version negotiated.*/
- ssl->flags &= ~(SSL_FLAGS_TLS_1_3 |
- SSL_FLAGS_TLS_1_3_DRAFT_22 |
- SSL_FLAGS_TLS_1_3_DRAFT_23 |
- SSL_FLAGS_TLS_1_3_DRAFT_24 |
- SSL_FLAGS_TLS_1_3_DRAFT_26 |
- SSL_FLAGS_TLS_1_3_DRAFT_28);
}
#endif /* USE_TLS_1_3 */
@@ -217,6 +432,7 @@ int32 matrixSslDecode(ssl_t *ssl, unsigned char **buf, uint32 *len,
goto encodeResponse;
}
#endif /* USE_EXT_CLIENT_CERT_KEY_LOADING */
+
# ifdef USE_EXT_CERTIFICATE_VERIFY_SIGNING
if (ssl->hwflags & SSL_HWFLAGS_PENDING_PKA_W ||
ssl->hwflags & SSL_HWFLAGS_PENDING_FLIGHT_W)
@@ -300,140 +516,18 @@ decodeMore:
}
#endif /* USE_CERT_CHAIN_PARSING */
- if (ssl->majVer != 0 || (*c & 0x80) == 0)
+ /* Parse and validate the record header. */
+ rc = handleRecordHdr(ssl, c, end, requiredLen, error);
+ if (rc < 0)
{
- if (end - c < ssl->recordHeadLen)
+ if (ssl->err != SSL_ALERT_NONE)
{
- *requiredLen = ssl->recordHeadLen;
- return SSL_PARTIAL;
- }
- ssl->rec.type = *c; c++;
- ssl->rec.majVer = *c; c++;
- ssl->rec.minVer = *c; c++;
-#ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
- {
- if (ssl->rec.majVer == DTLS_MAJ_VER &&
- ssl->rec.minVer >= DTLS_1_2_MIN_VER)
- {
- ssl->rec.epoch[0] = *c++;
- ssl->rec.epoch[1] = *c++;
- ssl->rec.rsn[0] = *c++;
- ssl->rec.rsn[1] = *c++;
- ssl->rec.rsn[2] = *c++;
- ssl->rec.rsn[3] = *c++;
- ssl->rec.rsn[4] = *c++;
- ssl->rec.rsn[5] = *c++;
- }
- else
- {
- psTraceIntDtls("Expecting DTLS record version. Got %d\n",
- ssl->rec.majVer);
- *error = PS_PROTOCOL_FAIL;
- return MATRIXSSL_ERROR;
- }
- }
- else /* Note: The else branch (not DTLS) is below,
- in code outside USE_DTLS */
-#endif /* USE_DTLS */
-#ifndef USE_SSL_PROTOCOL_VERSIONS_OTHER_THAN_3
- {
- /* RFC 5246 Suggests to accept all RSA minor versions,
- but only major version 0x03 (SSLv3, TLS 1.0,
- TLS 1.1, TLS 1.2, TLS 1.3 etc) */
- if (ssl->rec.majVer != 0x03)
- {
- /* Consider invalid major version protocol
- version error. */
- ssl->err = SSL_ALERT_PROTOCOL_VERSION;
- //*error = PS_PROTOCOL_FAIL;
- psTraceErrr(
- "Won't support client's SSL major version. (or maybe decode unexpected data)\n");
- *error = PS_PROTOCOL_FAIL;
- return MATRIXSSL_ERROR;
- }
- }
-#else
- { } /* No check for rec.MajVer. */
-#endif /* USE_SSL_PROTOCOL_VERSIONS_OTHER_THAN_3 */
-
- ssl->rec.len = *c << 8; c++;
- ssl->rec.len += *c; c++;
- }
- else
- {
-#if defined(USE_INTERCEPTOR) || defined(ALLOW_SSLV2_CLIENT_HELLO_PARSE)
- ssl->rec.type = SSL_RECORD_TYPE_HANDSHAKE;
- ssl->rec.majVer = 2;
- ssl->rec.minVer = 0;
- ssl->rec.len = (*c & 0x7f) << 8; c++;
- ssl->rec.len += *c; c++;
-#else
- /* OpenSSL 0.9.8 will send a SSLv2 CLIENT_HELLO. Use the -no_ssl2
- option when running a 0.9.8 client to prevent this */
- ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
- psTraceErrr("SSLv2 records not supported\n");
- goto encodeResponse;
-#endif
- }
-
-/*
- Validate the various record headers. The type must be valid,
- the major and minor versions must match the negotiated versions (if we're
- past ClientHello) and the length must be < 16K and > 0
- */
- switch (ssl->rec.type)
- {
- case SSL_RECORD_TYPE_CHANGE_CIPHER_SPEC:
- case SSL_RECORD_TYPE_ALERT:
- case SSL_RECORD_TYPE_HANDSHAKE:
- case SSL_RECORD_TYPE_APPLICATION_DATA:
- break;
- /* Any other case is unrecognized */
- default:
- ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE;
- psTraceIntInfo("Record header type not valid: %d\n", ssl->rec.type);
- goto encodeResponse;
- }
-
-/*
- Verify the record version numbers unless this is the first record we're
- reading.
- */
- if (ssl->hsState != SSL_HS_SERVER_HELLO &&
- ssl->hsState != SSL_HS_CLIENT_HELLO)
- {
- if (ssl->rec.majVer != ssl->majVer || ssl->rec.minVer != ssl->minVer)
- {
-#ifdef SSL_REHANDSHAKES_ENABLED
- /* If in DONE state and this version doesn't match the previously
- negotiated one that can be OK because a CLIENT_HELLO for a
- rehandshake might be acting like a first time send and using
- a lower version to get to the parsing phase. Unsupported
- versions will be weeded out at CLIENT_HELLO parse time */
- if (ssl->hsState != SSL_HS_DONE ||
- ssl->rec.type != SSL_RECORD_TYPE_HANDSHAKE)
- {
- ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
- psTraceErrr("Record header version not valid\n");
- goto encodeResponse;
- }
-#else
- ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
- psTraceErrr("Record header version not valid\n");
goto encodeResponse;
-#endif
}
+ return rc;
}
-/*
- Verify max and min record lengths
- */
- if (ssl->rec.len > SSL_MAX_RECORD_LEN || ssl->rec.len == 0)
- {
- ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
- psTraceIntInfo("Record header length not valid: %d\n", ssl->rec.len);
- goto encodeResponse;
- }
+ c += rc; /* handleRecordHdr returns number of bytes parsed. */
+
/*
This implementation requires the entire SSL record to be in the 'in' buffer
before we parse it. This is because we need to MAC the entire record before
@@ -570,7 +664,7 @@ SKIP_RECORD_PARSE:
if (end - c < ssl->rec.len)
{
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
psTraceErrr("DTLS error: Received PARTIAL record from peer.\n");
psTraceErrr("This indicates a PMTU mismatch\n");
@@ -585,7 +679,7 @@ SKIP_RECORD_PARSE:
#endif
#ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* Epoch and RSN validation. Silently ignore most mismatches (SUCCESS) */
@@ -753,7 +847,7 @@ ADVANCE_TO_APP_DATA:
!(ssl->flags & SSL_FLAGS_AEAD_R))
{
#ifdef USE_TLS_1_1
- if (ssl->flags & SSL_FLAGS_TLS_1_1)
+ if (ACTV_VER(ssl, v_tls_explicit_iv))
{
if (ssl->rec.len < (ssl->deMacSize + 1 + ssl->deBlockSize))
{
@@ -876,8 +970,7 @@ ADVANCE_TO_APP_DATA:
SSL3.0 requires the pad length to be less than blockSize
TLS can have a pad length up to 255 for obfuscating the data len
*/
- if (ssl->majVer == SSL3_MAJ_VER && ssl->minVer == SSL3_MIN_VER &&
- padLen >= ssl->deBlockSize)
+ if (ACTV_VER(ssl, v_ssl_3_0) && padLen >= ssl->deBlockSize)
{
macError = 1;
}
@@ -885,7 +978,7 @@ ADVANCE_TO_APP_DATA:
The minimum record length is the size of the mac, plus pad bytes
plus one length byte, plus explicit IV if TLS 1.1 or above
*/
- if (ssl->flags & SSL_FLAGS_TLS_1_1)
+ if (ACTV_VER(ssl, v_tls_explicit_iv))
{
if (ssl->rec.len < ssl->deMacSize + padLen + 1 + ssl->deBlockSize)
{
@@ -924,8 +1017,7 @@ ADVANCE_TO_APP_DATA:
(We're just overloading the 'mac' ptr here, this has nothing to
do with real MAC.)
*/
- if (!macError && ssl->majVer == TLS_MAJ_VER &&
- ssl->minVer >= TLS_MIN_VER)
+ if (!macError && !ACTV_VER(ssl, v_ssl_3_0))
{
for (mac = p - padLen - 1; mac < p; mac++)
{
@@ -994,7 +1086,7 @@ ADVANCE_TO_APP_DATA:
Clear the mac in the callers buffer if we're successful
*/
#ifdef USE_TLS_1_1
- if ((ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->deBlockSize > 1))
+ if (ACTV_VER(ssl, v_tls_explicit_iv) && (ssl->deBlockSize > 1))
{
decryptedStart += ssl->deBlockSize; /* skip explicit IV */
}
@@ -1277,7 +1369,7 @@ ADVANCE_TO_APP_DATA:
}
#ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (ssl->hsState != SSL_HS_FINISHED)
{
@@ -1918,7 +2010,7 @@ static int32 addCompressCount(ssl_t *ssl, int32 padLen)
len = ssl->rec.len;
# ifdef USE_TLS_1_1
- if (ssl->flags & SSL_FLAGS_TLS_1_1)
+ if (ACTV_VER(ssl, v_tls_explicit_iv))
{
len -= ssl->deBlockSize; /* skip explicit IV */
}
@@ -2017,7 +2109,7 @@ static int32 parseSSLHandshake(ssl_t *ssl, char *inbuf, uint32 len)
#ifdef USE_DTLS
msn = 0;
/* This is the non-DTLS fragmentation handler */
- if (!(ssl->flags & SSL_FLAGS_DTLS))
+ if (!(ACTV_VER(ssl, v_dtls_any)))
{
#endif
if (ssl->fragMessage != NULL)
@@ -2098,7 +2190,7 @@ parseHandshake:
are the ones that may bypass us to the wrong handshake type. Duplicates
are handled below.
*/
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (end - c < 5)
{
@@ -2183,7 +2275,7 @@ parseHandshake:
hsLen += *c << 8; c++;
hsLen += *c; c++;
#ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (end - c < 8)
{
@@ -2293,7 +2385,7 @@ parseHandshake:
/*
DTLS inserts an optional VERIFY_REQUEST back to clients
*/
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
# ifdef USE_CLIENT_SIDE_SSL
if ((hsType == SSL_HS_HELLO_VERIFY_REQUEST) &&
@@ -2407,7 +2499,7 @@ hsStateDetermined:
hsLen += *c << 8; c++;
hsLen += *c; c++;
#ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (end - c < 8)
{
@@ -2554,7 +2646,7 @@ hsStateDetermined:
}
}
#ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (ssl->fragTotal > 0)
{
@@ -3009,7 +3101,7 @@ SKIP_HSHEADER_PARSE:
}
#ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
ssl->lastMsn = msn; /* MSN of last message sucessfully parsed */
}
diff --git a/matrixssl/sslEncode.c b/matrixssl/sslEncode.c
index dd74559..2b63af5 100644
--- a/matrixssl/sslEncode.c
+++ b/matrixssl/sslEncode.c
@@ -276,7 +276,7 @@ int32 matrixSslGetEncodedSize(ssl_t *ssl, uint32 len)
that extra length here.
*/
if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) &&
- (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
+ ACTV_VER(ssl, v_tls_explicit_iv) && (ssl->enBlockSize > 1))
{
len += ssl->enBlockSize;
}
@@ -286,7 +286,7 @@ int32 matrixSslGetEncodedSize(ssl_t *ssl, uint32 len)
len += AEAD_TAG_LEN(ssl);
# ifdef USE_TLS_1_3
- if (USING_TLS_1_3(ssl))
+ if (ACTV_VER(ssl, v_tls_1_3_any))
{
/* TLS 1.3 does not send any part of the nonce over the
wire, but requires one additional byte and possibly
@@ -374,8 +374,12 @@ static int32 addCertFragOverhead(ssl_t *ssl, int32 totalCertLen)
be negative when creating the empty buffer spot where the signature
will be written. If this guess isn't correct, this function is called
to correct the buffer size */
-static int accountForEcdsaSizeChange(ssl_t *ssl, pkaAfter_t *pka, int real,
- unsigned char *sig, psBuf_t *out, int hsMsg)
+int accountForEcdsaSizeChange(ssl_t *ssl,
+ pkaAfter_t *pka,
+ int real,
+ unsigned char *sig,
+ psBuf_t *out,
+ int hsMsg)
{
flightEncode_t *flightMsg;
unsigned char *whereToMoveFrom, *whereToMoveTo, *msgLenLoc;
@@ -397,7 +401,7 @@ static int accountForEcdsaSizeChange(ssl_t *ssl, pkaAfter_t *pka, int real,
sigSizeChange = pka->user - real;
}
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* Needed somewhere to store the size change for DTLS retransmits */
ssl->ecdsaSizeChange = real - pka->user;
@@ -509,7 +513,7 @@ static int accountForEcdsaSizeChange(ssl_t *ssl, pkaAfter_t *pka, int real,
# ifdef USE_TLS_1_1
/* Account for explicit IV in TLS_1_1 and above. */
if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) &&
- (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
+ ACTV_VER(ssl, v_tls_explicit_iv) && (ssl->enBlockSize > 1))
{
msgLen -= ssl->enBlockSize;
msgLenLoc += ssl->enBlockSize;
@@ -517,7 +521,7 @@ static int accountForEcdsaSizeChange(ssl_t *ssl, pkaAfter_t *pka, int real,
# endif
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* Will also be a fragment length to update in handshake header.
Only supporting if there is no fragmentation here. The magic
@@ -536,7 +540,7 @@ static int accountForEcdsaSizeChange(ssl_t *ssl, pkaAfter_t *pka, int real,
msgLenLoc[2] = msgLen;
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* Update the fragLen as well. Sanity test was performed above */
msgLenLoc[8] = msgLen >> 16;
@@ -594,13 +598,8 @@ static int32 nowDoSkePka(ssl_t *ssl, psBuf_t *out)
# ifndef USE_ONLY_PSK_CIPHER_SUITE
pkaAfter_t *pka;
- sslIdentity_t *chosen = ssl->chosenIdentity;
-# if defined(USE_ECC_CIPHER_SUITE) || defined(USE_RSA_CIPHER_SUITE)
- psPool_t *pkiPool = NULL;
-# endif /* USE_ECC_CIPHER_SUITE || USE_RSA_CIPHER_SUITE */
-
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (ssl->retransmit)
{
@@ -614,171 +613,9 @@ static int32 nowDoSkePka(ssl_t *ssl, psBuf_t *out)
/* Always first one. clearPkaAfter will move 1 to 0 if needed */
pka = &ssl->pkaAfter[0];
+ rc = tlsMakeSkeSignature(ssl, pka, out);
+# endif /* USE_ONLY_PSK_CIPHER_SUITE */
-# ifdef USE_RSA_CIPHER_SUITE
- if (pka->type == PKA_AFTER_RSA_SIG_GEN_ELEMENT ||
- pka->type == PKA_AFTER_RSA_SIG_GEN)
- {
-
-# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
- {
- if ((rc = privRsaEncryptSignedElement(pkiPool,
- &chosen->privKey.key.rsa,
- pka->inbuf, pka->inlen, pka->outbuf,
- chosen->privKey.keysize, pka->data)) < 0)
- {
- if (rc != PS_PENDING)
- {
- psTraceIntInfo("Unable to sign SKE digital element %d\n",
- rc);
- return MATRIXSSL_ERROR;
- }
- /* If the result is going directly inline to the output
- buffer we unflag 'type' so this function isn't called
- again on the way back around. Also, we can safely
- free inbuf because it has been copied out */
- psFree(pka->inbuf, ssl->hsPool); pka->inbuf = NULL;
- pka->type = 0;
- return PS_PENDING;
- }
- }
- else
- {
- if ((rc = psRsaEncryptPriv(pkiPool, &chosen->privKey.key.rsa, pka->inbuf,
- pka->inlen, pka->outbuf, chosen->privKey.keysize,
- pka->data)) < 0)
- {
- if (rc != PS_PENDING)
- {
- psTraceInfo("Unable to sign SERVER_KEY_EXCHANGE message\n");
- return MATRIXSSL_ERROR;
- }
- /* If the result is going directly inline to the output
- buffer we unflag 'type' so this function isn't called
- again on the way back around. Also, we can safely free
- inbuf becuase it has been copied out */
- psFree(pka->inbuf, ssl->hsPool); pka->inbuf = NULL;
- pka->type = 0;
- return PS_PENDING;
- }
- }
-# else /* !USE_TLS_1_2 */
- if ((rc = psRsaEncryptPriv(pkiPool, &chosen->privKey.key.rsa, pka->inbuf,
- pka->inlen, pka->outbuf, chosen->privKey.keysize,
- pka->data)) < 0)
- {
- if (rc != PS_PENDING)
- {
- psTraceInfo("Unable to sign SERVER_KEY_EXCHANGE message\n");
- return MATRIXSSL_ERROR;
- }
- /* If the result is going directly inline to the output
- buffer we unflag 'type' so this function isn't called
- again on the way back around */
- psFree(pka->inbuf, ssl->hsPool); pka->inbuf = NULL;
- pka->type = 0;
- return PS_PENDING;
- }
-# endif /* USE_TLS_1_2 */
-
-
-# ifdef USE_DTLS
- if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 0))
- {
- /* Using existing ckeMsg and ckeSize that clients are using but
- this should be totally fine on the server side because it is
- freed at FINISHED parse */
- ssl->ckeSize = chosen->privKey.keysize;
- if ((ssl->ckeMsg = psMalloc(ssl->hsPool, ssl->ckeSize)) == NULL)
- {
- psTraceInfo("Memory allocation error ckeMsg\n");
- return PS_MEM_FAIL;
- }
- Memcpy(ssl->ckeMsg, pka->outbuf, ssl->ckeSize);
- }
-# endif /* USE_DTLS */
-
- clearPkaAfter(ssl); /* Blocking success case */
- }
-# endif /* USE_RSA_CIPHER_SUITE */
-
-# ifdef USE_ECC_CIPHER_SUITE
- if (pka->type == PKA_AFTER_ECDSA_SIG_GEN)
- {
-
- int32_t err;
- psSize_t len;
- /* New temp location for ECDSA sig which can be one len byte different
- than what we originally calculated (pka->user is holding) */
- unsigned char *tmpEcdsa;
-
- /* Only need to allocate 1 larger because 1 has already been added
- at creation */
- if ((tmpEcdsa = psMalloc(ssl->hsPool, pka->user + 1)) == NULL)
- {
- return PS_MEM_FAIL;
- }
-
- len = pka->user + 1;
-
-# ifdef USE_DTLS
- ssl->ecdsaSizeChange = 0;
-# endif
- if ((err = psEccDsaSign(pkiPool, &chosen->privKey.key.ecc,
- pka->inbuf, pka->inlen, tmpEcdsa, &len, 1, pka->data)) != 0)
- {
- /* DO NOT close pool (unless failed). It is kept around in
- pkaCmdInfo for result until finished and is closed there */
- if (err != PS_PENDING)
- {
- psFree(tmpEcdsa, ssl->hsPool);
- return MATRIXSSL_ERROR;
- }
-
- /* ASYNC: tmpEcdsa is not saved as output location so correct to
- free here */
- psFree(tmpEcdsa, ssl->hsPool);
- return PS_PENDING;
- }
- if (len != pka->user)
- {
- /* Confirmed ECDSA is not default size */
- if (accountForEcdsaSizeChange(ssl, pka, len, tmpEcdsa, out,
- SSL_HS_SERVER_KEY_EXCHANGE) < 0)
- {
- clearPkaAfter(ssl);
- psFree(tmpEcdsa, ssl->hsPool);
- return MATRIXSSL_ERROR;
- }
- }
- else
- {
- Memcpy(pka->outbuf, tmpEcdsa, pka->user);
- }
- psFree(tmpEcdsa, ssl->hsPool);
-
-# ifdef USE_DTLS
- if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 0))
- {
- /* ECC signatures have random bytes so need to save aside for
- retransmit cases. Using existing ckeMsg and ckeSize that
- clients are using but this should be totally fine on the
- server side because it is freed at FINISHED parse */
- ssl->ckeSize = len;
- if ((ssl->ckeMsg = psMalloc(ssl->hsPool, ssl->ckeSize)) == NULL)
- {
- psTraceInfo("Memory allocation error ckeMsg\n");
- return PS_MEM_FAIL;
- }
- Memcpy(ssl->ckeMsg, pka->outbuf, ssl->ckeSize);
- }
-# endif /* USE_DTLS */
-
- clearPkaAfter(ssl);
- }
-# endif /* USE_ECC_CIPHER_SUITE */
-# endif /* !USE_ONLY_PSK_CIPHER_SUITE */
return rc;
}
# endif /* USE_SERVER_SIDE_SSL */
@@ -792,7 +629,7 @@ psResSize_t calcCkeSize(ssl_t *ssl)
if ((ssl->flags & SSL_FLAGS_DHE_KEY_EXCH) != 0)
{
# ifdef USE_DTLS
- if ((ssl->flags & SSL_FLAGS_DTLS) && ssl->retransmit == 1)
+ if ((ACTV_VER(ssl, v_dtls_any)) && ssl->retransmit == 1)
{
return ssl->ckeSize; /* Keys have been freed - use cached. */
}
@@ -880,7 +717,7 @@ static int32 nowDoCkePka(ssl_t *ssl)
# endif
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (ssl->retransmit)
{
@@ -1080,7 +917,7 @@ static int32 nowDoCkePka(ssl_t *ssl)
# ifdef USE_DTLS
/* Save aside for retransmits */
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
ssl->ckeSize = pka->user + 1; /* The size is wrote first */
ssl->ckeMsg = psMalloc(ssl->hsPool, ssl->ckeSize);
@@ -1194,7 +1031,7 @@ if (g_reusePreLen == 0)
# ifdef USE_DTLS
/* This was first pass for DH ckex so set it aside */
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
ssl->ckeMsg = psMalloc(ssl->hsPool, pka->user);
@@ -1239,7 +1076,7 @@ if (g_reusePreLen == 0)
# ifdef USE_DTLS
/* Can't free cert in DTLS in case of retransmit */
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
return rc;
}
@@ -1360,7 +1197,7 @@ ok:
# endif
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* This function takes care of writing out entire flights so we know
to capture the current MSN and Epoch as the resends so that a
@@ -1425,7 +1262,7 @@ ok:
CAcert = ssl->keys->CAcerts;
certCount = certReqLen = CAcertLen = 0;
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
/* TLS 1.2 has a SigAndHashAlgorithm member in certRequest */
certReqLen += 2;
@@ -1463,7 +1300,7 @@ ok:
CAcert = CAcert->next;
}
# ifdef USE_DTLS
- /* if (ssl->flags & SSL_FLAGS_DTLS) { */
+ /* if (ACTV_VER(ssl, v_dtls_any)) { */
/* if (certReqLen + CAcertLen > ssl->pmtu) { */
/* / * Decrease the CA count or contact support if a */
/* needed requirement * / */
@@ -1591,7 +1428,7 @@ ok:
srvKeyExLen += 2;
}
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
srvKeyExLen += 2; /* hashSigAlg */
}
@@ -1616,7 +1453,7 @@ ok:
srvKeyExLen += (ssl->chosenIdentity->privKey.keysize + 2);
# endif
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
srvKeyExLen += 2; /* hashSigAlg */
}
@@ -1749,7 +1586,7 @@ ok:
messageSize += certReqLen + CAcertLen; /* certificate request */
messageSize += secureWriteAdditions(ssl, 1);
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* DTLS pmtu CERTIFICATE_REQUEST */
messageSize += (MAX_FRAGMENTS - 1) *
@@ -1768,7 +1605,7 @@ ok:
} /* not DHE key exchange */
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/*
If DTLS, make sure the max fragment overhead is accounted for on
@@ -2037,7 +1874,7 @@ ok:
/*
Account for the smaller finished message size for TLS.
*/
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (!NGTD_VER(ssl, v_ssl_3_0))
{
messageSize += TLS_HS_FINISHED_SIZE -
(MD5_HASH_SIZE + SHA1_HASH_SIZE);
@@ -2047,7 +1884,7 @@ ok:
/*
Adds explict IV overhead to the FINISHED message
*/
- if (ssl->flags & SSL_FLAGS_TLS_1_1)
+ if (NGTD_VER(ssl, v_tls_explicit_iv))
{
if (ssl->flags & SSL_FLAGS_AEAD_W)
{
@@ -2164,7 +2001,7 @@ ok:
Account for the smaller finished message size for TLS.
The MD5+SHA1 is SSLv3. TLS is 12 bytes.
*/
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (!NGTD_VER(ssl, v_ssl_3_0))
{
messageSize += TLS_HS_FINISHED_SIZE -
(MD5_HASH_SIZE + SHA1_HASH_SIZE);
@@ -2176,7 +2013,7 @@ ok:
Adds explict IV overhead to the FINISHED message.
Always added because FINISHED is never accounted for in
secureWriteAdditions */
- if (ssl->flags & SSL_FLAGS_TLS_1_1)
+ if (NGTD_VER(ssl, v_tls_explicit_iv))
{
if (ssl->cipher->flags &
(CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_CCM))
@@ -2293,7 +2130,7 @@ ok:
/*
SSLv3 sends a no_certificate warning alert for no match
*/
- if (ssl->majVer == SSL3_MAJ_VER && ssl->minVer == SSL3_MIN_VER)
+ if (NGTD_VER(ssl, v_ssl_3_0))
{
messageSize += 2 + ssl->recordHeadLen;
}
@@ -2328,7 +2165,7 @@ ok:
message. Also, at this time we can account for the smaller
finished message size for TLS. The MD5+SHA1 is SSLv3. TLS is
12 bytes. */
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (!NGTD_VER(ssl, v_ssl_3_0))
{
messageSize += 2 - MD5_HASH_SIZE - SHA1_HASH_SIZE +
TLS_HS_FINISHED_SIZE;
@@ -2346,7 +2183,7 @@ ok:
if (ssl->sec.certMatch > 0)
{
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
messageSize += 2; /* hashSigAlg in CertificateVerify */
}
@@ -2364,7 +2201,7 @@ ok:
}
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/*
If DTLS, make sure the max fragment overhead is accounted
@@ -2385,7 +2222,7 @@ ok:
Adds explict IV overhead to the FINISHED message. Always added
because FINISHED is never accounted for in secureWriteAdditions
*/
- if (ssl->flags & SSL_FLAGS_TLS_1_1)
+ if (NGTD_VER(ssl, v_tls_explicit_iv))
{
if (ssl->cipher->flags &
(CRYPTO_FLAGS_GCM | CRYPTO_FLAGS_CCM))
@@ -2428,8 +2265,7 @@ ok:
message be sent if there is no certificate match. SSLv3
tends to lean toward a NO_CERTIFIATE warning alert message
*/
- if (ssl->sec.certMatch == 0 &&
- ssl->majVer == SSL3_MAJ_VER && ssl->minVer == SSL3_MIN_VER)
+ if (ssl->sec.certMatch == 0 && NGTD_VER(ssl, v_ssl_3_0))
{
rc = writeAlert(ssl, SSL_ALERT_LEVEL_WARNING,
SSL_ALERT_NO_CERTIFICATE, out, requiredLen);
@@ -2514,20 +2350,8 @@ flightEncode:
}
else
{
-# ifdef USE_TLS_1_3
- if (USING_TLS_1_3(ssl))
- {
- /* TLS 1.3 code path may want to send specific protocol alerts
- here. */
- if (ssl->err == SSL_ALERT_NONE)
- {
- ssl->err = SSL_ALERT_INTERNAL_ERROR;
- }
- }
-# else
- ssl->err = SSL_ALERT_INTERNAL_ERROR;
-# endif
-
+ /* let tls13 set errors, others use internal error here. */
+ ssl->err = (USING_TLS_1_3(ssl) && ssl->err != SSL_ALERT_NONE) ? ssl->err : SSL_ALERT_INTERNAL_ERROR;
}
out->end = out->start;
alertReqLen = out->size;
@@ -2624,7 +2448,7 @@ int32_t processFinished(ssl_t *ssl, flightEncode_t *msg)
int32_t rc;
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (msg->hsMsg == SSL_HS_FINISHED)
{
@@ -2672,7 +2496,8 @@ int32_t processFinished(ssl_t *ssl, flightEncode_t *msg)
ssl->flags & SSL_FLAGS_SERVER);
if (rc <= 0)
{
- psTraceIntInfo("Error snapshotting HS hash flight %d\n", rc);
+ psTraceErrr("Error snapshotting HS hash flight\n");
+ psTraceIntInfo("sslSnapshotHSHash%d\n", rc);
clearFlightList(ssl);
return rc;
}
@@ -2680,7 +2505,7 @@ int32_t processFinished(ssl_t *ssl, flightEncode_t *msg)
# ifdef ENABLE_SECURE_REHANDSHAKES
/* The rehandshake verify data is the previous handshake msg hash */
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (ssl->myVerifyDataLen > 0)
{
@@ -2752,7 +2577,7 @@ static int32 encryptFlight(ssl_t *ssl, unsigned char **end)
out.start = out.buf = out.end = msg->start - ssl->recordHeadLen -
TLS_EXPLICIT_NONCE_LEN;
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* nonce */
*msg->seqDelay = ssl->epoch[0]; msg->seqDelay++;
@@ -2834,7 +2659,7 @@ static int32 encryptFlight(ssl_t *ssl, unsigned char **end)
# endif /* !PSK_ONLY */
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS && msg->fragCount > 0)
+ if (ACTV_VER(ssl, v_dtls_any) && msg->fragCount > 0)
{
# ifndef USE_ONLY_PSK_CIPHER_SUITE
# if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH)
@@ -2994,7 +2819,7 @@ static int32 secureWriteAdditions(ssl_t *ssl, int32 numRecs)
/*
Checks here for TLS1.1 with block cipher for explict IV additions.
*/
- if ((ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
+ if (NGTD_VER(ssl, v_tls_explicit_iv) && (ssl->enBlockSize > 1))
{
add += (numRecs * ssl->enBlockSize); /* explicitIV */
}
@@ -3067,7 +2892,7 @@ int32_t writeRecordHeader(ssl_t *ssl, uint8_t type, uint8_t hsType,
of an explicit IV. This is an extra random block of data
prepended to the plaintext before encryption. Account for
that extra length here. */
- if (hsType == SSL_HS_FINISHED && (ssl->flags & SSL_FLAGS_TLS_1_1))
+ if (hsType == SSL_HS_FINISHED && ACTV_VER(ssl, v_tls_explicit_iv))
{
if (ssl->cipher->blockSize > 1)
{
@@ -3075,7 +2900,8 @@ int32_t writeRecordHeader(ssl_t *ssl, uint8_t type, uint8_t hsType,
}
}
else if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) &&
- (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
+ ACTV_VER(ssl, v_tls_explicit_iv) &&
+ (ssl->enBlockSize > 1))
{
*messageSize += ssl->enBlockSize;
}
@@ -3100,7 +2926,7 @@ int32_t writeRecordHeader(ssl_t *ssl, uint8_t type, uint8_t hsType,
/* In TLS 1.2, part of the nonce is explicit and must be
sent over-the-wire. In TLS 1.3, it is fully implicit. */
- if (!(USING_TLS_1_3(ssl)))
+ if (ACTV_VER(ssl, v_tls_explicit_iv))
{
*messageSize += AEAD_NONCE_LEN(ssl);
}
@@ -3152,7 +2978,7 @@ int32_t writeRecordHeader(ssl_t *ssl, uint8_t type, uint8_t hsType,
This routine does not deal with DTLS fragmented messages, but it was
necessary to call for all the length computations to happen in here.
*/
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (*messageSize > ssl->pmtu)
{
@@ -3194,7 +3020,7 @@ int32_t writeRecordHeader(ssl_t *ssl, uint8_t type, uint8_t hsType,
if (hsType == SSL_HS_FINISHED)
{
- if ((ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->cipher->blockSize > 1))
+ if (ACTV_VER(ssl, v_tls_explicit_iv) && (ssl->cipher->blockSize > 1))
{
if (psGetPrngLocked(*c, ssl->cipher->blockSize,
ssl->userPtr) < 0)
@@ -3205,7 +3031,7 @@ int32_t writeRecordHeader(ssl_t *ssl, uint8_t type, uint8_t hsType,
}
}
else if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) &&
- (ssl->flags & SSL_FLAGS_TLS_1_1) &&
+ ACTV_VER(ssl, v_tls_explicit_iv) &&
(ssl->enBlockSize > 1))
{
if (psGetPrngLocked(*c, ssl->enBlockSize, ssl->userPtr) < 0)
@@ -3222,7 +3048,7 @@ int32_t writeRecordHeader(ssl_t *ssl, uint8_t type, uint8_t hsType,
if (type == SSL_RECORD_TYPE_HANDSHAKE)
{
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/*
A message sequence number is unique for each handshake message. It
@@ -3263,7 +3089,7 @@ static int32 encryptCompressedRecord(ssl_t *ssl, int32 type, int32 messageSize,
ptLen = *c - encryptStart;
# ifdef USE_TLS_1_1
- if ((ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
+ if (ACTV_VER(ssl, v_tls_explicit_iv) && (ssl->enBlockSize > 1))
{
/* Do not compress IV */
if (type == SSL_RECORD_TYPE_APPLICATION_DATA)
@@ -3357,7 +3183,7 @@ static int32 encryptCompressedRecord(ssl_t *ssl, int32 type, int32 messageSize,
ztmp = dataToMacAndEncryptLen + ssl->recordHeadLen + ssl->enMacSize + padLen;
# ifdef USE_TLS_1_1
- if ((ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
+ if (ACTV_VER(ssl, v_tls_explicit_iv) && (ssl->enBlockSize > 1))
{
ztmp += ssl->enBlockSize;
}
@@ -3458,7 +3284,7 @@ static int32 encryptCompressedRecord(ssl_t *ssl, int32 type, int32 messageSize,
Waited to increment record sequence number until completely finished
with the encoding because the HMAC in DTLS uses the rsn of current record
*/
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
dtlsIncrRsn(ssl);
}
@@ -3631,7 +3457,7 @@ int32 encryptRecord(ssl_t *ssl, int32 type, int32 hsMsgType,
# ifdef USE_TLS
# ifdef USE_TLS_1_1
if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) &&
- (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
+ ACTV_VER(ssl, v_tls_explicit_iv) && (ssl->enBlockSize > 1))
{
/*
Don't add the random bytes into the hash of the message. Makes
@@ -3731,9 +3557,11 @@ int32 encryptRecord(ssl_t *ssl, int32 type, int32 hsMsgType,
if (pt == encryptStart)
{
/* In-situ encode */
- if ((rc = ssl->encrypt(ssl, pt, encryptStart,
- (uint32) (*c - encryptStart))) < 0 ||
- *c - out->end != messageSize)
+ rc = ssl->encrypt(ssl,
+ pt,
+ encryptStart,
+ (uint32) (*c - encryptStart));
+ if (rc < 0 || *c - out->end != messageSize)
{
psTraceIntInfo("Error encrypting 1: %d\n", rc);
psTraceIntInfo("messageSize is %d\n", messageSize);
@@ -3800,7 +3628,7 @@ int32 encryptRecord(ssl_t *ssl, int32 type, int32 hsMsgType,
Waited to increment record sequence number until completely finished
with the encoding because the HMAC in DTLS uses the rsn of current record
*/
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
dtlsIncrRsn(ssl);
}
@@ -3854,19 +3682,18 @@ int32 psGenerateServerRandom(ssl_t *ssl)
The goal is to prevent active adversaries from downgrading the
connection.
*/
- if (tlsVersionSupported(ssl, TLS_1_3_MIN_VER)) /* RFC, not draft. */
+ if (SUPP_VER(ssl, v_tls_1_3)) /* RFC, not draft. */
{
- if (!NEGOTIATED_TLS_1_3(ssl))
+ if (!NGTD_VER(ssl, v_tls_1_3_any))
{
const char *suffix;
- if (ssl->minVer == TLS_1_2_MIN_VER)
+ if (NGTD_VER(ssl, v_tls_1_2 | v_dtls_1_2))
{
suffix = TLS13_DOWNGRADE_PROT_TLS12;
}
else
{
- psAssert(ssl->minVer <= TLS_1_1_MIN_VER);
suffix = TLS13_DOWNGRADE_PROT_TLS11_OR_BELOW;
}
Memcpy(ssl->sec.serverRandom + 24, suffix, 8);
@@ -3911,7 +3738,7 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out)
If peerVerifyData isn't available and we're doing a retransmit we know
this is the problematic case so forget we have a myVerifyData
*/
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if ((ssl->secureRenegotiationFlag == PS_TRUE) && (ssl->retransmit == 1)
&& (ssl->myVerifyDataLen > 0) && (ssl->peerVerifyDataLen == 0))
@@ -4025,7 +3852,7 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out)
messageSize += extLen;
t = 1;
# ifdef USE_DTLS
- if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1))
+ if ((ACTV_VER(ssl, v_dtls_any)) && (ssl->retransmit == 1))
{
/*
All retransmits must generate identical handshake messages as the
@@ -4067,8 +3894,8 @@ static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out)
First two fields in the ServerHello message are the major and minor
SSL protocol versions we agree to talk with
*/
- *c = ssl->majVer; c++;
- *c = ssl->minVer; c++;
+ *c = psEncodeVersionMaj(GET_ACTV_VER(ssl)); c++;
+ *c = psEncodeVersionMin(GET_ACTV_VER(ssl)); c++;
psTracePrintProtocolVersion(INDENT_HS_MSG,
"server_version",
@@ -4461,17 +4288,14 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen,
int32_t rc;
# ifndef USE_ONLY_PSK_CIPHER_SUITE
- psSize_t hashSize;
- unsigned char *hsMsgHash, *sigStart;
- psDigestContext_t digestCtx;
- pkaAfter_t *pkaAfter;
- void *pkiData = ssl->userPtr;
+ unsigned char *tbsStart;
sslIdentity_t *chosen = ssl->chosenIdentity;
+ int32_t skeSigAlg;
# endif
# if defined(USE_PSK_CIPHER_SUITE) && defined(USE_ANON_DH_CIPHER_SUITE)
- unsigned char *hint;
- uint8_t hintLen;
+ unsigned char *hint = NULL;
+ uint8_t hintLen = 0;
# endif /* USE_PSK_CIPHER_SUITE && USE_ANON_DH_CIPHER_SUITE */
# ifdef USE_ECC_CIPHER_SUITE
psSize_t eccPubKeyLen = 0;
@@ -4491,7 +4315,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen,
messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen +
6 + pLen + gLen + ssl->sec.dhKeyPriv->size;
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
messageSize -= 2; /* hashSigAlg not going to be needed */
}
@@ -4504,18 +4328,18 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen,
{
return MATRIXSSL_ERROR;
}
-/*
- * RFC4279: In the absence of an application profile specification
- * specifying otherwise, servers SHOULD NOT provide an identity hint
- * and clients MUST ignore the identity hint field. Applications that
- * do use this field MUST specify its contents, how the value is
- * chosen by the TLS server, and what the TLS client is expected to do
- * with the value.
- * @note Unlike pure PSK cipher which will omit the ServerKeyExchange
- * message if the hint is NULL, the DHE_PSK exchange simply puts
- * two zero bytes in this case, since the message must still be sent
- * to exchange the DHE public key.
- */
+ /*
+ RFC4279: In the absence of an application profile specification
+ specifying otherwise, servers SHOULD NOT provide an identity hint
+ and clients MUST ignore the identity hint field. Applications that
+ do use this field MUST specify its contents, how the value is
+ chosen by the TLS server, and what the TLS client is expected to do
+ with the value.
+ @note Unlike pure PSK cipher which will omit the ServerKeyExchange
+ message if the hint is NULL, the DHE_PSK exchange simply puts
+ two zero bytes in this case, since the message must still be sent
+ to exchange the DHE public key.
+ */
messageSize += 2; /* length of hint (even if zero) */
if (hintLen != 0 && hint != NULL)
{
@@ -4569,7 +4393,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen,
messageSize++; /* Extra byte for 'long' asn.1 encode */
}
# ifdef USE_DTLS
- if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1))
+ if ((ACTV_VER(ssl, v_dtls_any)) && (ssl->retransmit == 1))
{
/* We already know if this signature got resized */
messageSize += ssl->ecdsaSizeChange;
@@ -4602,7 +4426,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen,
return MATRIXSSL_ERROR;
}
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
messageSize += 2; /* hashSigAlg */
}
@@ -4614,7 +4438,7 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen,
return rc;
}
# ifndef USE_ONLY_PSK_CIPHER_SUITE
- sigStart = c;
+ tbsStart = c;
# endif
# if defined(USE_PSK_CIPHER_SUITE) && defined(USE_ANON_DH_CIPHER_SUITE)
@@ -4684,340 +4508,44 @@ static int32 writeServerKeyExchange(ssl_t *ssl, sslBuf_t *out, uint32 pLen,
}
# endif /* USE_ECC_CIPHER_SUITE */
- /* RFC 5246 - 7.4.3. Server Key Exchange Message
- In addition, the hash and signature algorithms MUST be compatible
- with the key in the server's end-entity certificate. RSA keys MAY be
- used with any permitted hash algorithm, subject to restrictions in
- the certificate, if any. */
-
-# ifdef USE_RSA_CIPHER_SUITE
-/*
- RSA authentication requires an additional signature portion to the message
- */
- if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA)
+# ifndef USE_ONLY_PSK_CIPHERSUITE
+ if (ssl->flags & (SSL_FLAGS_DHE_WITH_RSA | SSL_FLAGS_DHE_WITH_DSA))
{
- int32 skeSigAlg = 0; /* If this stays 0, we will use MD5-SHA-1. */
+ /* Message length been pre-computed, and we have written the public
+ value and/or the PSK hint. Next we shall choose the signature
+ algorithm, write the signature algorithm identifier (if (D)TLS 1.2)
+ and setup pkaAfter for later signature generation. */
-# ifdef USE_SSL_INFORMATIONAL_TRACE_VERBOSE
- psTracePrintSigAlgs(ssl->hashSigAlg, "Peer ClientHello");
-# endif
-# ifndef USE_ONLY_PSK_CIPHER_SUITE
- /* Saved aside for pkaAfter_t */
- if ((hsMsgHash = psMalloc(ssl->hsPool, SHA512_HASH_SIZE)) == NULL)
+ /* 1. Determine hash and signature algorithm to use. */
+ skeSigAlg = chooseSkeSigAlg(ssl, ssl->chosenIdentity);
+ if (skeSigAlg < 0)
{
- return PS_MEM_FAIL;
- }
-# endif
-# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
- {
- skeSigAlg = chooseSigAlg(chosen->cert, &chosen->privKey, ssl->hashSigAlg);
- if (skeSigAlg == PS_UNSUPPORTED_FAIL)
- {
- psTraceInfo("Unavailable sigAlgorithm for SKE write\n");
- psFree(hsMsgHash, ssl->hsPool);
- return PS_UNSUPPORTED_FAIL;
- }
- }
-# endif /* USE_TLS_1_2 */
-
- switch(skeSigAlg)
- {
-# ifdef USE_MD5SHA1
- case 0:
- hashSize = MD5SHA1_HASHLEN;
- 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);
- break;
-# endif /* USE_MD5SHA1 */
-# ifdef USE_SHA1
- case OID_SHA1_RSA_SIG:
- 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) (c - sigStart));
- psSha1Final(&digestCtx.sha1, hsMsgHash);
- *c++ = 0x2;
- *c++ = 0x1;
- break;
-# endif /* USE_SHA1 */
-# ifdef USE_SHA256
- case OID_SHA256_RSA_SIG:
- 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) (c - sigStart));
- psSha256Final(&digestCtx.sha256, hsMsgHash);
- *c++ = 0x4;
- *c++ = 0x1;
- break;
-# endif /* USE_SHA256 */
-# ifdef USE_SHA384
- case OID_SHA384_RSA_SIG:
- 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) (c - sigStart));
- psSha384Final(&digestCtx.sha384, hsMsgHash);
- *c++ = 0x5;
- *c++ = 0x1;
- break;
-# endif /* USE_SHA384 */
-# ifdef USE_SHA512
- case OID_SHA512_RSA_SIG:
- 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) (c - sigStart));
- psSha512Final(&digestCtx.sha512, hsMsgHash);
- *c++ = 0x6;
- *c++ = 0x1;
- break;
-# endif /* USE_SHA512 */
- default:
- psTraceIntInfo("Unavailable sigAlgorithm for SKE write: %d\n",
- skeSigAlg);
- psFree(hsMsgHash, ssl->hsPool);
- return PS_UNSUPPORTED_FAIL;
+ return skeSigAlg;
}
- *c = (chosen->privKey.keysize & 0xFF00) >> 8; c++;
- *c = chosen->privKey.keysize & 0xFF; c++;
-
-# ifdef USE_DTLS
- if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1))
+ /* 2. Compute the hash. */
+ /* 3. Setup pkaAfter_t for delayed signing op. */
+ rc = tlsPrepareSkeSignature(ssl,
+ skeSigAlg,
+ tbsStart,
+ c);
+ if (rc < 0)
{
- /* It is not optimal to have run through the above digest updates
- again on a retransmit just to free the hash here but the
- saved message is ONLY the signature portion done in nowDoSke
- so the few hashSigAlg bytes and keysize done above during the
- hash are important to rewrite */
- psFree(hsMsgHash, ssl->hsPool);
- Memcpy(c, ssl->ckeMsg, ssl->ckeSize);
- c += ssl->ckeSize;
+ return rc;
}
- else /* closed below */
- {
-# endif /* USE_DTLS */
- pkaAfter = getPkaAfter(ssl);
-# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
- {
- pkaAfter->type = PKA_AFTER_RSA_SIG_GEN_ELEMENT;
- }
- else
- {
- pkaAfter->type = PKA_AFTER_RSA_SIG_GEN;
- }
-# else /* !USE_TLS_1_2 */
- pkaAfter->type = PKA_AFTER_RSA_SIG_GEN;
-# endif /* USE_TLS_1_2 */
-
- pkaAfter->inbuf = hsMsgHash;
- pkaAfter->outbuf = c;
- pkaAfter->data = pkiData;
- pkaAfter->inlen = hashSize;
- c += chosen->privKey.keysize;
-# ifdef USE_DTLS
- }
-# endif /* USE_DTLS */
- }
-# endif /* USE_RSA_CIPHER_SUITE */
-
-# ifdef USE_ECC_CIPHER_SUITE
- if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA)
- {
- int32 skeSigAlg = OID_SHA1_ECDSA_SIG;
-# ifndef USE_ONLY_PSK_CIPHER_SUITE
- /* Saved aside for pkaAfter_t */
- if ((hsMsgHash = psMalloc(ssl->hsPool, SHA512_HASH_SIZE)) == NULL)
- {
- return PS_MEM_FAIL;
- }
-# endif
-# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
- {
- skeSigAlg = chooseSigAlg(chosen->cert, &chosen->privKey, ssl->hashSigAlg);
- if (skeSigAlg == PS_UNSUPPORTED_FAIL)
- {
- psTraceInfo("Unavailable sigAlgorithm for SKE write\n");
- psFree(hsMsgHash, ssl->hsPool);
- return PS_UNSUPPORTED_FAIL;
- }
- }
- else
- {
- skeSigAlg = OID_SHA1_ECDSA_SIG;
- }
- if (skeSigAlg == OID_SHA256_ECDSA_SIG)
- {
- 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) (c - sigStart));
- psSha256Final(&digestCtx.sha256, hsMsgHash);
- *c++ = 0x4; /* SHA256 */
- *c++ = 0x3; /* ECDSA */
-# ifdef USE_SHA384
- }
- else if ((ssl->flags & SSL_FLAGS_TLS_1_2) &&
- (skeSigAlg == OID_SHA384_ECDSA_SIG))
- {
- 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) (c - sigStart));
- psSha384Final(&digestCtx.sha384, hsMsgHash);
- *c++ = 0x5; /* SHA384 */
- *c++ = 0x3; /* ECDSA */
-# endif
-# ifdef USE_SHA512
- }
- else if ((ssl->flags & SSL_FLAGS_TLS_1_2) &&
- (skeSigAlg == OID_SHA512_ECDSA_SIG))
- {
- 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, (int32) (c - sigStart));
- psSha512Final(&digestCtx.sha512, hsMsgHash);
- *c++ = 0x6; /* SHA512 */
- *c++ = 0x3; /* ECDSA */
-# endif
-# ifdef USE_SHA1
- }
- else if (ssl->minVer < TLS_1_2_MIN_VER ||
-# ifdef USE_DTLS
- /* DTLS 1.0 is same at TLS 1.1 */
- ssl->minVer == DTLS_MIN_VER ||
-# endif
- ((ssl->flags & SSL_FLAGS_TLS_1_2) &&
- (skeSigAlg == OID_SHA1_ECDSA_SIG)))
- {
- 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) (c - sigStart));
- psSha1Final(&digestCtx.sha1, hsMsgHash);
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
- {
- *c++ = 0x2; /* SHA1 */
- *c++ = 0x3; /* ECDSA */
- }
-# endif
- }
- else
- {
- psFree(hsMsgHash, ssl->hsPool);
- return PS_UNSUPPORTED_FAIL;
- }
-# else
- 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) (c - sigStart));
- psSha1Final(&digestCtx.sha1, hsMsgHash);
-# endif
-
-# ifdef USE_DTLS
- if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1))
- {
- /* It is not optimal to have run through the above digest updates
- again on a retransmit just to free the hash here but the
- saved message is ONLY the signature portion done in nowDoSke
- so the few hashSigAlg bytes and keysize done above during the
- hash are important to rewrite */
- psFree(hsMsgHash, ssl->hsPool);
- Memcpy(c, ssl->ckeMsg, ssl->ckeSize);
- c += ssl->ckeSize;
- }
- else /* closed below */
- {
-# endif /* USE_DTLS */
-
- if ((pkaAfter = getPkaAfter(ssl)) == NULL)
- {
- psTraceInfo("getPkaAfter error\n");
- return PS_PLATFORM_FAIL;
- }
- pkaAfter->inbuf = hsMsgHash;
- pkaAfter->outbuf = c;
- pkaAfter->data = pkiData;
- pkaAfter->inlen = hashSize;
- pkaAfter->type = PKA_AFTER_ECDSA_SIG_GEN;
- rc = chosen->privKey.keysize + 8;
- /* NEGATIVE ECDSA - Adding spot for ONE 0x0 byte in ECDSA so we'll
- be right 50% of the time... 521 curve doesn't need */
- if (chosen->privKey.keysize != 132)
- {
- rc += 1;
- }
- /* Above we added in the 8 bytes of overhead (2 sigLen, 1 SEQ,
- 1 len (possibly 2!), 1 INT, 1 rLen, 1 INT, 1 sLen) and now
- subtract the first 3 bytes to see if the 1 len needs to be 2 */
- if (rc - 3 >= 128)
- {
- rc++;
- }
- pkaAfter->user = rc; /* outlen for later */
c += rc;
-# ifdef USE_DTLS
}
-# endif /* USE_DTLS */
- }
-# endif /* USE_ECC_CIPHER_SUITE */
+# endif /* USE_ONLY_PSK_CIPHERSUITE */
- if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE,
- SSL_HS_SERVER_KEY_EXCHANGE, messageSize, padLen, encryptStart, out,
- &c)) < 0)
+ rc = postponeEncryptRecord(ssl,
+ SSL_RECORD_TYPE_HANDSHAKE,
+ SSL_HS_SERVER_KEY_EXCHANGE,
+ messageSize,
+ padLen,
+ encryptStart,
+ out,
+ &c);
+ if (rc < 0)
{
return rc;
}
@@ -5498,7 +5026,7 @@ static int32 writeCertificate(ssl_t *ssl, sslBuf_t *out, int32 notEmpty)
end, &c)) < 0)
{
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/*
Is this the fragment case?
@@ -5603,7 +5131,7 @@ static int32 postponeSnapshotHSHash(ssl_t *ssl, unsigned char *c, int32 sender)
{
ssl->delayHsHash = c;
# ifdef USE_TLS
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (!ACTV_VER(ssl, v_ssl_3_0))
{
return TLS_HS_FINISHED_SIZE;
}
@@ -5637,15 +5165,22 @@ static int32 writeFinished(ssl_t *ssl, sslBuf_t *out)
verifyLen = MD5_HASH_SIZE + SHA1_HASH_SIZE;
# ifdef USE_TLS
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (!ACTV_VER(ssl, v_ssl_3_0))
{
verifyLen = TLS_HS_FINISHED_SIZE;
}
# endif /* USE_TLS */
messageSize = ssl->recordHeadLen + ssl->hshakeHeadLen + verifyLen;
- if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE, SSL_HS_FINISHED,
- &messageSize, &padLen, &encryptStart, end, &c)) < 0)
+ rc = writeRecordHeader(ssl,
+ SSL_RECORD_TYPE_HANDSHAKE,
+ SSL_HS_FINISHED,
+ &messageSize,
+ &padLen,
+ &encryptStart,
+ end,
+ &c);
+ if (rc < 0)
{
return rc;
}
@@ -5654,8 +5189,15 @@ static int32 writeFinished(ssl_t *ssl, sslBuf_t *out)
*/
c += postponeSnapshotHSHash(ssl, c, ssl->flags & SSL_FLAGS_SERVER);
- if ((rc = postponeEncryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE,
- SSL_HS_FINISHED, messageSize, padLen, encryptStart, out, &c)) < 0)
+ rc = postponeEncryptRecord(ssl,
+ SSL_RECORD_TYPE_HANDSHAKE,
+ SSL_HS_FINISHED,
+ messageSize,
+ padLen,
+ encryptStart,
+ out,
+ &c);
+ if (rc < 0)
{
return rc;
}
@@ -5663,7 +5205,7 @@ static int32 writeFinished(ssl_t *ssl, sslBuf_t *out)
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/*
Can't free the sec.cert buffer or close the handshake pool if
@@ -5874,7 +5416,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
cookieLen = 0;
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* TODO DTLS make sure a block cipher suite is being used */
if (ssl->haveCookie)
@@ -5883,7 +5425,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
}
else
{
- cookieLen = 1; /* Always send the length (0) even if no cookie */
+ cookieLen = 1; /* Always send the length (0) even if no cookie */
}
/* save for next time called for VERIFY_REQUEST response */
ssl->cipherSpecLen = min(8, cipherSpecLen); /* 8 is arbitrary limit */
@@ -5919,8 +5461,10 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
cipherDetails = sslGetCipherSpec(ssl, cipherSpecs[i]);
if (cipherDetails == NULL)
{
- psTraceIntInfo("Cipher suite not supported: %d\n",
- cipherSpecs[i]);
+ psTracePrintCiphersuiteName(0,
+ "Ciphersuite not supported",
+ cipherSpecs[i],
+ PS_TRUE);
return PS_UNSUPPORTED_FAIL;
}
cipherLen += 2;
@@ -5938,7 +5482,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
# endif
if (options->fallbackScsv)
{
- if (ssl->minVer == TLS_HIGHEST_MINOR)
+ if (ACTV_VER(ssl, psVerGetHighestTls(v_compiled_in)))
{
/** If a client sets ClientHello.client_version to its highest
supported protocol version, it MUST NOT include TLS_FALLBACK_SCSV.
@@ -5970,7 +5514,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
version but the server did not support it. In that case, the fallbackScsv
option should have been specified to mitigate version rollback attacks.
*/
- if (ssl->minVer < TLS_HIGHEST_MINOR)
+ if (!ACTV_VER(ssl, psVerGetHighestTls(v_compiled_in)))
{
psTraceInfo("Warning, if this is a fallback connection, set fallbackScsv?\n");
}
@@ -5989,7 +5533,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
/* Max Fragment extension request */
ssl->maxPtFrag = SSL_MAX_PLAINTEXT_LEN;
- if (ssl->minVer > 0 && (options->maxFragLen > 0) &&
+ if (!ACTV_VER(ssl, v_ssl_3_0) && (options->maxFragLen > 0) &&
(options->maxFragLen < SSL_MAX_PLAINTEXT_LEN))
{
if (options->maxFragLen == 0x200 ||
@@ -6055,11 +5599,20 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
curveListLen = 0;
if (eccSuitesSupported(ssl, cipherSpecs, cipherSpecLen))
{
- /* Getting the curve list from crypto directly */
+ uint32_t ecFlags = options->ecFlags;
+
+ /* Getting the curve list from crypto directly */
curveListLen = sizeof(eccCurveList);
- if (options->ecFlags)
+# ifdef USE_SEC_CONFIG
+ /* Allow security profile to override the ECC curve list. */
+ if (ssl->ecFlagsOverride != 0)
{
- userSuppliedEccList(eccCurveList, &curveListLen, options->ecFlags);
+ ecFlags = ssl->ecFlagsOverride;
+ }
+# endif
+ if (ecFlags)
+ {
+ userSuppliedEccList(eccCurveList, &curveListLen, ecFlags);
}
else
{
@@ -6177,7 +5730,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
}
# ifdef USE_DTLS
- if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->helloExtLen > 0))
+ if ((ACTV_VER(ssl, v_dtls_any)) && (ssl->helloExtLen > 0))
{
/* Override all the extension calculations and just grab what was
sent the first time. Can't rebuild because there is no good line
@@ -6191,9 +5744,15 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
c = out->end;
end = out->buf + out->size;
- if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE,
- SSL_HS_CLIENT_HELLO, &messageSize, &padLen, &encryptStart,
- end, &c)) < 0)
+ rc = writeRecordHeader(ssl,
+ SSL_RECORD_TYPE_HANDSHAKE,
+ SSL_HS_CLIENT_HELLO,
+ &messageSize,
+ &padLen,
+ &encryptStart,
+ end,
+ &c);
+ if (rc < 0)
{
*requiredLen = messageSize;
return rc;
@@ -6216,12 +5775,12 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
CompressionMethod compression_methods<1..2^8-1>;
} ClientHello;
*/
- if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->haveCookie))
+ if ((ACTV_VER(ssl, v_dtls_any)) && (ssl->haveCookie))
{
t = 0;
}
/* Also test for retransmit */
- if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1))
+ if ((ACTV_VER(ssl, v_dtls_any)) && (ssl->retransmit == 1))
{
t = 0;
}
@@ -6259,12 +5818,16 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
First two fields in the ClientHello message are the maximum major
and minor SSL protocol versions we support.
*/
- *c = ssl->majVer; c++;
- *c = ssl->minVer; c++;
-
- psTracePrintProtocolVersion(INDENT_HS_MSG,
+ *c = psEncodeVersionMaj(GET_ACTV_VER(ssl)); c++;
+ *c = psEncodeVersionMin(GET_ACTV_VER(ssl)); c++;
+ psTracePrintProtocolVersionNew(INDENT_HS_MSG,
"client_version",
- ssl->majVer, ssl->minVer, 1);
+ GET_ACTV_VER(ssl),
+ PS_TRUE);
+ /* Active version may get overridden by the result of the version
+ negotiation, so save it. ClientHello.client_version is needed
+ for RSA premaster calculation in TLS 1.2 and below. */
+ ssl->ourHelloVersion = GET_ACTV_VER(ssl);
/*
The next 32 bytes are the server's random value, to be combined with
@@ -6300,7 +5863,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
PS_TRUE);
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (ssl->haveCookie)
{
@@ -6389,7 +5952,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
# endif
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* Need to save aside (or recall) extensions because the resend
path doesn't go back to the user to rebuild them. */
@@ -6621,7 +6184,7 @@ int32_t matrixSslEncodeClientHello(ssl_t *ssl, sslBuf_t *out,
}
# ifdef USE_DTLS
- if ((ssl->flags & SSL_FLAGS_DTLS) && (extLen > 0) && extStart)
+ if ((ACTV_VER(ssl, v_dtls_any)) && (extLen > 0) && extStart)
{
if (ssl->helloExtLen == 0)
{
@@ -6723,7 +6286,7 @@ static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out)
}
# ifdef USE_DTLS
/* Need to save for retransmit? */
- if (!(ssl->flags & SSL_FLAGS_DTLS))
+ if (!(ACTV_VER(ssl, v_dtls_any)))
{
psFree(ssl->sec.hint, ssl->hsPool); ssl->sec.hint = NULL;
}
@@ -6741,7 +6304,7 @@ static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out)
if (ssl->flags & SSL_FLAGS_DHE_KEY_EXCH)
{
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit == 1)
+ if (ACTV_VER(ssl, v_dtls_any) && ssl->retransmit == 1)
{
keyLen = ssl->ckeSize;
}
@@ -6817,7 +6380,7 @@ static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out)
explicitLen = 0;
# ifdef USE_TLS
/* Must always add the key size length to the message */
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (!NGTD_VER(ssl, v_ssl_3_0))
{
messageSize += 2;
explicitLen = 1;
@@ -6899,7 +6462,7 @@ static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out)
}
# ifdef USE_DTLS
- if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1))
+ if ((ACTV_VER(ssl, v_dtls_any)) && (ssl->retransmit == 1))
{
/*
Retransmit case. Must use the cached encrypted msg from
@@ -6931,7 +6494,7 @@ static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out)
}
psAssert(keyLen == (uint32) * (c - 1));
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* Set aside retransmit for this case here since there is
nothing happening in nowDoCke related to the handshake
@@ -6978,7 +6541,7 @@ static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out)
psAssert(dhLen == keyLen);
}
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/* Set aside retransmit for this case here since there is
nothing happening in nowDoCke related to the handshake
@@ -7123,8 +6686,10 @@ static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out)
return SSL_MEM_ERROR;
}
- ssl->sec.premaster[0] = ssl->reqMajVer;
- ssl->sec.premaster[1] = ssl->reqMinVer;
+ /* The version MUST be the same as the one we encoded in
+ ClientHello.client_version. */
+ ssl->sec.premaster[0] = psEncodeVersionMaj(ssl->ourHelloVersion);
+ ssl->sec.premaster[1] = psEncodeVersionMin(ssl->ourHelloVersion);
if (psGetPrngLocked(ssl->sec.premaster + 2,
SSL_HS_RSA_PREMASTER_SIZE - 2, ssl->userPtr) < 0)
{
@@ -7167,6 +6732,11 @@ static int32 writeClientKeyExchange(ssl_t *ssl, sslBuf_t *out)
}
out->end = c;
+# ifdef DEBUG_TLS_PREMASTER
+ psTraceBytes("client premaster_secret",
+ ssl->sec.premaster,
+ SSL_HS_RSA_PREMASTER_SIZE);
+# endif
return MATRIXSSL_SUCCESS;
}
@@ -7205,7 +6775,8 @@ static int32_t handleAsyncCvSigOp(ssl_t *ssl, pkaAfter_t *pka, unsigned char *ha
ssl->extCvSigAlg = PS_ECC;
}
- if (ssl->flags & SSL_FLAGS_TLS_1_2 || ssl->extCvSigAlg == PS_RSA)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithmts)
+ || ssl->extCvSigAlg == PS_RSA)
{
hash_tbs = hash;
hash_tbs_len = pka->inlen;
@@ -7286,7 +6857,7 @@ static int32 getSnapshotHSHash(ssl_t *ssl,
}
# ifdef USE_TLS_1_2
/* Tweak if needed */
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
switch (pka->inlen)
{
@@ -7365,7 +6936,7 @@ static int nowDoCvPkaInnerECDSA(ssl_t *ssl, pkaAfter_t *pka,
}
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
/*
TLS 1.2 defined and used.
@@ -7473,7 +7044,7 @@ static int nowDoCvPkaInnerECDSA(ssl_t *ssl, pkaAfter_t *pka,
} /* endif (len == pka->user) */
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
int32_t saveSize;
@@ -7546,28 +7117,28 @@ static int nowDoCvPkaInnerRSA(ssl_t *ssl, pkaAfter_t *pka,
# endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
- {
- /* RFC: "The hash and signature algorithms used in the
- signature MUST be one of those present in the
- supported_signature_algorithms field of the
- CertificateRequest message. In addition, the hash and
- signature algorithms MUST be compatible with the key in the
- client's end-entity certificate.
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
+ {
+ /* RFC: "The hash and signature algorithms used in the
+ signature MUST be one of those present in the
+ supported_signature_algorithms field of the
+ CertificateRequest message. In addition, the hash and
+ signature algorithms MUST be compatible with the key in the
+ client's end-entity certificate.
- We've done the above tests in the parse of the
- CertificateRequest message and wouldn't be here if our
- certs didn't match the sigAlgs. However, we do have
- to test for both sig algorithm types here to find the
- hash strength because the sig alg might not match the
- pubkey alg. This was also already confirmed in
- CertRequest parse so wouldn't be here if not allowed */
- using_tls_1_2 = 1; /* TLS 1.2 defined and used. */
- }
- else
- {
- using_tls_1_2 = 0; /* TLS 1.2 defined but not used. */
- }
+ We've done the above tests in the parse of the
+ CertificateRequest message and wouldn't be here if our
+ certs didn't match the sigAlgs. However, we do have
+ to test for both sig algorithm types here to find the
+ hash strength because the sig alg might not match the
+ pubkey alg. This was also already confirmed in
+ CertRequest parse so wouldn't be here if not allowed */
+ using_tls_1_2 = 1; /* TLS 1.2 defined and used. */
+ }
+ else
+ {
+ using_tls_1_2 = 0; /* TLS 1.2 defined but not used. */
+ }
# else /* ! USE_TLS_1_2 */
using_tls_1_2 = 0; /* TLS 1.2 not defined and thus not used. */
# endif /* USE_TLS_1_2 */
@@ -7606,7 +7177,7 @@ static int nowDoCvPkaInnerRSA(ssl_t *ssl, pkaAfter_t *pka,
# endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
int32_t saveSize;
@@ -7644,7 +7215,7 @@ static int32 nowDoCvPka(ssl_t *ssl, psBuf_t *out)
pka = &ssl->pkaAfter[0];
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (ssl->retransmit)
{
@@ -7713,7 +7284,7 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out)
int32_t rc;
pkaAfter_t *pkaAfter;
void *pkiData = ssl->userPtr;
- int32_t sigAlg;
+ int32_t sigAlg = 0;
sslIdentity_t *chosen = ssl->chosenIdentity;
if (chosen == NULL)
@@ -7763,7 +7334,7 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out)
messageSize++; /* Extra byte for 'long' asn.1 encode */
}
# ifdef USE_DTLS
- if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 1))
+ if ((ACTV_VER(ssl, v_dtls_any)) && (ssl->retransmit == 1))
{
/* We already know if this signature got resized */
messageSize += ssl->ecdsaSizeChange;
@@ -7787,7 +7358,7 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out)
running total. Not a huge deal for the updating but
the current snapshot framework didn't support this so there
are one-off algorithm specific snapshots where needed. */
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
messageSize += 2; /* hashSigAlg */
}
@@ -7804,7 +7375,7 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out)
one associated with the private key.
*/
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
/*
Pick the hash algorithm to use with the public key.
@@ -7832,7 +7403,7 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out)
if (chosen->cert->pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
{
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
unsigned char b1, b2;
@@ -7848,7 +7419,7 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out)
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit)
+ if (ACTV_VER(ssl, v_dtls_any) && ssl->retransmit)
{
Memcpy(c, ssl->certVerifyMsg, ssl->certVerifyMsgLen);
c += ssl->certVerifyMsgLen;
@@ -7887,7 +7458,7 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out)
# ifdef USE_RSA
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
unsigned char b1, b2;
@@ -7960,7 +7531,7 @@ static int32 writeCertificateVerify(ssl_t *ssl, sslBuf_t *out)
*c = (chosen->privKey.keysize & 0xFF); c++;
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit)
+ if (ACTV_VER(ssl, v_dtls_any) && ssl->retransmit)
{
pkaAfter->type = 0; /* reset so AFTER logic doesn't trigger */
Memcpy(c, ssl->certVerifyMsg, ssl->certVerifyMsgLen);
@@ -8042,7 +7613,7 @@ static int32 writeCertificateRequest(ssl_t *ssl, sslBuf_t *out, int32 certLen,
# endif /* USE_ECC */
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
/* TLS 1.2 has a SignatureAndHashAlgorithm type after CertType */
sigHashLen = 2;
@@ -8075,7 +7646,7 @@ static int32 writeCertificateRequest(ssl_t *ssl, sslBuf_t *out, int32 certLen,
&encryptStart, end, &c)) < 0)
{
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/*
Is this the fragment case?
@@ -8107,7 +7678,7 @@ static int32 writeCertificateRequest(ssl_t *ssl, sslBuf_t *out, int32 certLen,
# endif
*c++ = RSA_SIGN;
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
/* RFC: "The interaction of the certificate_types and
supported_signature_algorithms fields is somewhat complicated.
@@ -8244,7 +7815,7 @@ static int32 writeMultiRecordCertRequest(ssl_t *ssl, sslBuf_t *out,
*c++ = RSA_SIGN;
countDown--;
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
{
*c++ = 0x0;
*c++ = sigHashLen - 2;
@@ -8499,11 +8070,16 @@ static int32 writeHelloVerifyRequest(ssl_t *ssl, sslBuf_t *out)
return rc;
}
-/*
- Message content is version, cookie length, and cookie itself
- */
- *c++ = ssl->rec.majVer;
- *c++ = ssl->rec.minVer;
+ /*
+ Message content is version, cookie length, and cookie itself.
+
+ RFC 6347, section 4.2.1 is contradictory regarding which version
+ we should encode as server_version in HelloRetryRequest (see errata
+ 4103). We could either use DTLS 1.0 here or the negotiated version.
+ We choose the former.
+ */
+ *c++ = DTLS_MAJ_VER;
+ *c++ = DTLS_1_0_MIN_VER;
*c++ = DTLS_COOKIE_SIZE;
Memcpy(c, ssl->srvCookie, DTLS_COOKIE_SIZE);
c += DTLS_COOKIE_SIZE;
@@ -8540,10 +8116,10 @@ int32 psWriteRecordInfo(ssl_t *ssl, unsigned char type, int32 len,
type = SSL_RECORD_TYPE_HANDSHAKE;
}
*c = type; c++;
- *c = ssl->majVer; c++;
- *c = ssl->minVer; c++;
+ *c = psEncodeVersionMaj(GET_ACTV_VER(ssl)); c++;
+ *c = psEncodeVersionMin(GET_ACTV_VER(ssl)); c++;
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
ssl->seqDelay = c;
*c = ssl->epoch[0]; c++;
@@ -8573,7 +8149,7 @@ int32 psWriteRecordInfo(ssl_t *ssl, unsigned char type, int32 len,
if (explicitNonce)
{
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
c++;
*c = ssl->epoch[0]; c++;
@@ -8623,7 +8199,7 @@ int32 psWriteHandshakeHeader(ssl_t *ssl, unsigned char type, int32 len,
*c = (unsigned char) ((len & 0xFF0000) >> 16); c++;
*c = (len & 0xFF00) >> 8; c++;
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
*c = (len & 0xFF); c++;
*c = (seq & 0xFF00) >> 8; c++;
diff --git a/matrixssl/test/sslTest.c b/matrixssl/test/sslTest.c
index a9214ff..19cdef7 100644
--- a/matrixssl/test/sslTest.c
+++ b/matrixssl/test/sslTest.c
@@ -670,6 +670,10 @@ const static __THREAD testCipherSpec_t ciphers[] = {
CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256),
# endif
+# ifdef USE_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ CS(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384),
+# endif
+
# ifdef USE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
CS(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA),
# endif
@@ -849,7 +853,7 @@ void *sslTestPt(void *mustBeNull)
int main(int argc, char **argv)
{
- int rc, num_threads;
+ int rc, num_threads = 0;
# ifdef USE_MULTITHREADING
int i;
pthread_t thread[FLPS_SSL_TEST_MAX_THREADS];
@@ -1445,7 +1449,7 @@ L_NEXT_DH:
# if defined(SSL_REHANDSHAKES_ENABLED) && !defined(USE_ZLIB_COMPRESSION)
# ifdef DISABLE_DTLS_CLIENT_CHANGE_CIPHER_FROM_GCM_TO_GCM
- if (clnConn->ssl->flags & SSL_FLAGS_DTLS &&
+ if (NGTD_VER(clnConn->ssl, v_dtls_any) &&
clnConn->ssl->cipher->flags & CRYPTO_FLAGS_GCM &&
spec->flags & CRYPTO_FLAGS_GCM)
{
@@ -1573,7 +1577,7 @@ skip_client_initiated_rehandshake:
*/
testTrace(" Resumed Re-handshake test (client initiated)\n");
# ifdef DISABLE_DTLS_CLIENT_CHANGE_CIPHER_FROM_GCM_TO_GCM
- if (clnConn->ssl->flags & SSL_FLAGS_DTLS &&
+ if (NGTD_VER(clnConn->ssl, v_dtls_any) &&
clnConn->ssl->cipher->flags & CRYPTO_FLAGS_GCM &&
spec->flags & CRYPTO_FLAGS_GCM)
{
@@ -1667,7 +1671,7 @@ skip_client_initiated_resumed_rehandshake:
/* Re-handshaking with "upgraded" parameters */
testTrace(" Change cert callback Re-handshake test\n");
# ifdef DISABLE_DTLS_CLIENT_CHANGE_CIPHER_FROM_GCM_TO_GCM
- if (clnConn->ssl->flags & SSL_FLAGS_DTLS &&
+ if (NGTD_VER(clnConn->ssl, v_dtls_any) &&
clnConn->ssl->cipher->flags & CRYPTO_FLAGS_GCM &&
spec->flags & CRYPTO_FLAGS_GCM)
{
@@ -1740,7 +1744,7 @@ skip_client_upgrade_parameters_rehandshake:
{
testTrace(" Change cipher suite Re-handshake test\n");
# ifdef DISABLE_DTLS_CLIENT_CHANGE_CIPHER_FROM_GCM_TO_GCM
- if (clnConn->ssl->flags & SSL_FLAGS_DTLS &&
+ if (NGTD_VER(clnConn->ssl, v_dtls_any) &&
clnConn->ssl->cipher->flags & CRYPTO_FLAGS_GCM &&
spec->flags & CRYPTO_FLAGS_GCM)
{
@@ -2096,7 +2100,7 @@ static int32 initializeResumedHandshake(sslConn_t *clnConn, sslConn_t *svrConn,
{
sslSessionId_t *sessionId;
sslSessOpts_t options;
-
+ int32_t rc;
# ifdef ENABLE_PERF_TIMING
psTime_t start, end;
# endif /* ENABLE_PERF_TIMING */
@@ -2105,6 +2109,7 @@ static int32 initializeResumedHandshake(sslConn_t *clnConn, sslConn_t *svrConn,
Memset(&options, 0x0, sizeof(sslSessOpts_t));
options.versionFlag = g_versionFlag;
+
# ifdef USE_ECC_CIPHER_SUITE
options.ecFlags = clnConn->ssl->ecInfo.ecFlags;
# endif
@@ -2121,10 +2126,17 @@ static int32 initializeResumedHandshake(sslConn_t *clnConn, sslConn_t *svrConn,
# ifdef USE_EXT_CERTIFICATE_VERIFY_SIGNING
options.useExtCvSigOp = 1;
# endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */
- if (matrixSslNewClientSession(&clnConn->ssl, clnConn->keys, sessionId,
- &cipherSuite, 1, clnCertChecker, "localhost", NULL, NULL,
- &options)
- < 0)
+ rc = matrixSslNewClientSession(&clnConn->ssl,
+ clnConn->keys,
+ sessionId,
+ &cipherSuite,
+ 1,
+ clnCertChecker,
+ "localhost",
+ NULL,
+ NULL,
+ &options);
+ if (rc < 0)
{
return PS_FAILURE;
}
@@ -2140,8 +2152,11 @@ static int32 initializeResumedHandshake(sslConn_t *clnConn, sslConn_t *svrConn,
psGetTime(&start, NULL);
# endif /* ENABLE_PERF_TIMING */
# ifdef USE_SERVER_SIDE_SSL
- if (matrixSslNewServerSession(&svrConn->ssl, svrConn->keys, NULL,
- &options) < 0)
+ rc = matrixSslNewServerSession(&svrConn->ssl,
+ svrConn->keys,
+ NULL,
+ &options);
+ if (rc < 0)
{
return PS_FAILURE;
}
@@ -2276,7 +2291,7 @@ static int32 performHandshake(sslConn_t *sendingSide, sslConn_t *receivingSide)
psGetTime(&start, NULL);
# endif /* ENABLE_PERF_TIMING */
# ifdef USE_DTLS
- if (sendingSide->ssl->flags & SSL_FLAGS_DTLS)
+ if (NGTD_VER(sendingSide->ssl, v_dtls_any))
{
outbufLen = matrixDtlsGetOutdata(sendingSide->ssl, &outbuf);
}
@@ -2321,7 +2336,7 @@ static int32 performHandshake(sslConn_t *sendingSide, sslConn_t *receivingSide)
psGetTime(&start, NULL);
# endif /* ENABLE_PERF_TIMING */
# ifdef USE_DTLS
- if (sendingSide->ssl->flags & SSL_FLAGS_DTLS)
+ if (NGTD_VER(sendingSide->ssl, v_dtls_any))
{
matrixDtlsSentData(sendingSide->ssl, dataSent);
}
@@ -2502,7 +2517,7 @@ static int32_t throughputTest(sslConn_t *s, sslConn_t *r, uint16_t nrec, psSize_
# endif
# ifdef USE_DTLS
- if (s->ssl->flags & SSL_FLAGS_DTLS)
+ if (NGTD_VER(s->ssl, v_dtls_any))
{
return PS_SUCCESS;
}
@@ -2709,7 +2724,7 @@ static int32 exchangeAppData(sslConn_t *sendingSide,
SEND_MORE:
# ifdef USE_DTLS
- if (sendingSide->ssl->flags & SSL_FLAGS_DTLS)
+ if (NGTD_VER(sendingSide->ssl, v_dtls_any))
{
writeBufLen = matrixDtlsGetOutdata(sendingSide->ssl, &writeBuf);
}
@@ -2741,7 +2756,7 @@ SEND_MORE:
/* Now update the sending side that data has been "sent" */
# ifdef USE_DTLS
- if (sendingSide->ssl->flags & SSL_FLAGS_DTLS)
+ if (NGTD_VER(sendingSide->ssl, v_dtls_any))
{
sentRc = matrixDtlsSentData(sendingSide->ssl, dataSent);
}
diff --git a/matrixssl/tls.c b/matrixssl/tls.c
index c6de9b9..5d56e98 100644
--- a/matrixssl/tls.c
+++ b/matrixssl/tls.c
@@ -100,7 +100,7 @@ static int32_t genKeyBlock(ssl_t *ssl)
}
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_tls_1_2_prf))
{
if ((rc = prf2(ssl->sec.masterSecret, SSL_HS_MASTER_SIZE, msSeed,
(SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.keyBlock,
@@ -181,7 +181,7 @@ int32_t tlsDeriveKeys(ssl_t *ssl)
int32_t rc = PS_FAIL;
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit == 1)
+ if (ACTV_VER(ssl, v_dtls_any) && ssl->retransmit == 1)
{
/* The keyblock is still valid from the first pass */
return SSL_HS_MASTER_SIZE;
@@ -214,7 +214,7 @@ int32_t tlsDeriveKeys(ssl_t *ssl)
ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE);
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_tls_1_2_prf))
{
if ((rc = prf2(ssl->sec.premaster, ssl->sec.premasterSize, msSeed,
(SSL_HS_RANDOM_SIZE * 2) + LABEL_SIZE, ssl->sec.masterSecret,
@@ -244,7 +244,7 @@ int32_t tlsDeriveKeys(ssl_t *ssl)
# endif
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/*
May need premaster for retransmits. DTLS will free this when handshake
@@ -272,7 +272,7 @@ int32_t tlsExtendedDeriveKeys(ssl_t *ssl)
int32_t rc = PS_FAIL;
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS && ssl->retransmit == 1)
+ if (ACTV_VER(ssl, v_dtls_any) && ssl->retransmit == 1)
{
/* The keyblock is still valid from the first pass */
return SSL_HS_MASTER_SIZE;
@@ -306,7 +306,7 @@ int32_t tlsExtendedDeriveKeys(ssl_t *ssl)
Memcpy(msSeed + LABEL_EXT_SIZE, hash, outLen);
# ifdef USE_TLS_1_2
- if (ssl->flags & SSL_FLAGS_TLS_1_2)
+ if (NGTD_VER(ssl, v_tls_with_tls_1_2_prf))
{
if ((rc = prf2(ssl->sec.premaster, ssl->sec.premasterSize, msSeed,
outLen + LABEL_EXT_SIZE, ssl->sec.masterSecret,
@@ -336,7 +336,7 @@ int32_t tlsExtendedDeriveKeys(ssl_t *ssl)
# endif
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
/*
May need premaster for retransmits. DTLS will free this when handshake
@@ -434,8 +434,8 @@ int32_t tlsHMACSha1(ssl_t *ssl, int32 mode, unsigned char type,
uint32 alt_len;
# endif /* USE_HMAC_TLS */
- majVer = ssl->majVer;
- minVer = ssl->minVer;
+ majVer = psEncodeVersionMaj(GET_ACTV_VER(ssl));
+ minVer = psEncodeVersionMin(GET_ACTV_VER(ssl));
if (mode == HMAC_CREATE)
{
@@ -455,7 +455,7 @@ int32_t tlsHMACSha1(ssl_t *ssl, int32 mode, unsigned char type,
}
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (mode == HMAC_CREATE)
{
@@ -561,8 +561,8 @@ int32_t tlsHMACSha2(ssl_t *ssl, int32 mode, unsigned char type,
uint32 alt_len;
# endif /* USE_HMAC_TLS */
- majVer = ssl->majVer;
- minVer = ssl->minVer;
+ majVer = psEncodeVersionMaj(GET_ACTV_VER(ssl));
+ minVer = psEncodeVersionMin(GET_ACTV_VER(ssl));
if (mode == HMAC_CREATE)
{
@@ -581,7 +581,7 @@ int32_t tlsHMACSha2(ssl_t *ssl, int32 mode, unsigned char type,
}
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (mode == HMAC_CREATE)
{
@@ -667,8 +667,8 @@ int32_t tlsHMACMd5(ssl_t *ssl, int32 mode, unsigned char type,
unsigned char majVer, minVer, tmp[5];
int32 i;
- majVer = ssl->majVer;
- minVer = ssl->minVer;
+ majVer = psEncodeVersionMaj(GET_ACTV_VER(ssl));
+ minVer = psEncodeVersionMin(GET_ACTV_VER(ssl));
if (mode == HMAC_CREATE)
{
@@ -691,7 +691,7 @@ int32_t tlsHMACMd5(ssl_t *ssl, int32 mode, unsigned char type,
return PS_FAIL;
}
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (mode == HMAC_CREATE)
{
@@ -738,7 +738,7 @@ int32_t tlsHMACMd5(ssl_t *ssl, int32 mode, unsigned char type,
int32 sslCreateKeys(ssl_t *ssl)
{
# ifdef USE_TLS
- if (ssl->flags & SSL_FLAGS_TLS)
+ if (!NGTD_VER(ssl, v_ssl_3_0))
{
return tlsDeriveKeys(ssl);
}
@@ -838,7 +838,7 @@ int32 sslActivateReadCipher(ssl_t *ssl)
if (ssl->sec.rIVptr)
Memcpy(ssl->sec.readIV, ssl->sec.rIVptr, ssl->cipher->ivSize);
# ifdef DEBUG_TLS_MAC
- psTracePrintTlsKeys(ssl);
+ psTracePrintTlsKeys("read keys", ssl, PS_TRUE);
# endif /* DEBUG_TLS_MAC */
/*
@@ -861,7 +861,7 @@ int32 sslActivateReadCipher(ssl_t *ssl)
int32 sslActivateWriteCipher(ssl_t *ssl)
{
# ifdef USE_DTLS
- if (ssl->flags & SSL_FLAGS_DTLS)
+ if (ACTV_VER(ssl, v_dtls_any))
{
if (ssl->retransmit == 0)
{
@@ -941,7 +941,7 @@ int32 sslActivateWriteCipher(ssl_t *ssl)
Memcpy(ssl->sec.writeKey, ssl->sec.wKeyptr, ssl->cipher->keySize);
Memcpy(ssl->sec.writeIV, ssl->sec.wIVptr, ssl->cipher->ivSize);
# ifdef DEBUG_TLS_MAC
- psTracePrintTlsKeys(ssl);
+ psTracePrintTlsKeys("Write keys", ssl, PS_TRUE);
# endif /* DEBUG_TLS_MAC */
/*
@@ -1144,560 +1144,6 @@ int32 matrixSslLoadHelloExtension(tlsExtension_t *ext,
}
#endif /* USE_CLIENT_SIDE_SSL */
-#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH)
-#ifndef USE_ONLY_PSK_CIPHER_SUITE
-/**
- Return PS_TRUE if sigAlg is in peerSigAlgs, PS_FALSE otherwise.
-
- peerSigAlgs should be the a set of masks we created after
- parsing the peer's supported_signature_algorithms list
- in ClientHello or CertificateRequest.
-*/
-psBool_t peerSupportsSigAlg(int32_t sigAlg,
- uint16_t peerSigAlgs
- /* , psSize_t peerSigAlgsLen) */
- )
-{
- uint16_t yes;
-
- if (sigAlg == OID_MD5_RSA_SIG)
- {
- yes = ((peerSigAlgs & HASH_SIG_MD5_RSA_MASK) != 0);
- }
- else if (sigAlg == OID_SHA1_RSA_SIG)
- {
- yes = ((peerSigAlgs & HASH_SIG_SHA1_RSA_MASK) != 0);
- }
- else if (sigAlg == OID_SHA256_RSA_SIG)
- {
- yes = ((peerSigAlgs & HASH_SIG_SHA256_RSA_MASK) != 0);
- }
- else if (sigAlg == OID_SHA384_RSA_SIG)
- {
- yes = ((peerSigAlgs & HASH_SIG_SHA384_RSA_MASK) != 0);
- }
- else if (sigAlg == OID_SHA512_RSA_SIG)
- {
- yes = ((peerSigAlgs & HASH_SIG_SHA512_RSA_MASK) != 0);
- }
- else if (sigAlg == OID_SHA1_ECDSA_SIG)
- {
- yes = ((peerSigAlgs & HASH_SIG_SHA1_ECDSA_MASK) != 0);
- }
- else if (sigAlg == OID_SHA256_ECDSA_SIG)
- {
- yes = ((peerSigAlgs & HASH_SIG_SHA256_ECDSA_MASK) != 0);
- }
- else if (sigAlg == OID_SHA384_ECDSA_SIG)
- {
- yes = ((peerSigAlgs & HASH_SIG_SHA384_ECDSA_MASK) != 0);
- }
- else if (sigAlg == OID_SHA512_ECDSA_SIG)
- {
- yes = ((peerSigAlgs & HASH_SIG_SHA512_ECDSA_MASK) != 0);
- }
- else
- {
- return PS_FALSE; /* Unknown/unsupported sig alg. */
- }
-
- if (yes)
- {
- return PS_TRUE;
- }
- else
- {
- return PS_FALSE;
- }
-}
-
-/**
- Return PS_TRUE when we support sigAlg for signature generation,
- PS_FALSE otherwise.
-
- Compile-time switches as well as FIPS or non-FIPS mode is taken
- into account.
-
- @param[in] sigAlg The signature algorithm whose support is to
- be checked.
- @param[in] pubKeyAlgorithm The public key algorithm of our
- private/public key pair (OID_RSA_KEY_ALG or OID_ECDSA_KEY_ALG.)
-*/
-psBool_t weSupportSigAlg(int32_t sigAlg,
- int32_t pubKeyAlgorithm)
-{
- uint16_t we_support = 0;
- uint16_t is_non_fips = 0; /* 1 if not allowed in FIPS mode for
- signature generation. */
-
- PS_VARIABLE_SET_BUT_UNUSED(is_non_fips);
-
-#ifndef USE_RSA
- if (pubKeyAlgorithm == OID_RSA_KEY_ALG)
- {
- return PS_FALSE;
- }
-#endif
-#ifndef USE_ECC
- if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
- {
- return PS_FALSE;
- }
-#endif
-
- if (pubKeyAlgorithm == OID_RSA_KEY_ALG)
- {
- if (sigAlg == OID_MD2_RSA_SIG || sigAlg == OID_MD5_RSA_SIG)
- {
- /* No support for generating RSA-MD2 or RSA-MD5 signatures. */
- is_non_fips = 1;
- we_support = 0;
- }
- else if (sigAlg == OID_SHA1_RSA_SIG)
- {
- is_non_fips = 1;
-#ifdef USE_SHA1
- we_support = 1;
-#endif
- }
- else if (sigAlg == OID_SHA256_RSA_SIG)
- {
-#ifdef USE_SHA256
- we_support = 1;
-#endif
- }
- else if (sigAlg == OID_SHA384_RSA_SIG)
- {
-#ifdef USE_SHA384
- we_support = 1;
-#endif
- }
- else if (sigAlg == OID_SHA512_RSA_SIG)
- {
-#ifdef USE_SHA512
- we_support = 1;
-#endif
- }
- else
- {
- /* Our key does not support this algorithm. */
- return PS_FALSE;
- }
- }
- else if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
- {
- if (sigAlg == OID_SHA1_ECDSA_SIG)
- {
-#ifdef USE_SHA1
- we_support = 1;
-#endif
- }
- else if (sigAlg == OID_SHA256_ECDSA_SIG)
- {
-#ifdef USE_SHA256
- we_support = 1;
-#endif
- }
- else if (sigAlg == OID_SHA384_ECDSA_SIG)
- {
-#ifdef USE_SHA384
- we_support = 1;
-#endif
- }
- else if (sigAlg == OID_SHA512_ECDSA_SIG)
- {
-#ifdef USE_SHA512
- we_support = 1;
-#endif
- }
- else
- {
- /* Our key does not support this algorithm. */
- return PS_FALSE;
- }
- }
- else
- {
- return PS_FALSE; /* Unsupported public key alg, e.g. DSA. */
- }
-
- /* The basic capability is there. Now do some further checks
- if needed. */
-
- if (we_support)
- {
- return PS_TRUE;
- }
- else
- {
- return PS_FALSE;
- }
-}
-
-/** Return PS_TRUE when:
- - We support sigAlg for signature generation.
- - sigAlg is in peerSigAlgs.
-
- @param[in] sigAlg The signature algorithm whose support to check.
- @param[in] pubKeyAlgorithm The public key algorithm of our key.
- @param[in] peerSigAlgs The masks of the sigAlgs supported by the
- peer. This should be the one parsed from the peer's
- supported_signature_algorithms list in CertificateVerify or
- CertificateRequest. In this case, sigAlg \in peerSigAlgs
- means that the peer supports sigAlg for signature verification.
-*/
-psBool_t canUseSigAlg(int32_t sigAlg,
- int32_t pubKeyAlgorithm,
- uint16_t peerSigAlgs)
-{
- return (weSupportSigAlg(sigAlg, pubKeyAlgorithm) &&
- peerSupportsSigAlg(sigAlg, peerSigAlgs));
-}
-
-/**
- Upgrade to a more secure signature algorithm. If the algorithm
- is already the strongest possible for the key type (i.e.
- RSA-SHA-512 or ECDSA-SHA-512) change to the most popular
- one (i.e. RSA-SHA-256 or ECDSA-SHA-256).
-*/
-int32_t upgradeSigAlg(int32_t sigAlg, int32_t pubKeyAlgorithm)
-{
- /*
- RSA:
- MD2 -> SHA256
- MD5 -> SHA256
- SHA1 -> SHA256
- SHA256 -> SHA384
- SHA384 -> SHA512
- SHA512 -> SHA256
- */
- if (pubKeyAlgorithm == OID_RSA_KEY_ALG)
- {
- if (sigAlg == OID_MD2_RSA_SIG ||
- sigAlg == OID_MD5_RSA_SIG ||
- sigAlg == OID_SHA1_RSA_SIG)
- {
- return OID_SHA256_RSA_SIG;
- }
- else if (sigAlg == OID_SHA256_RSA_SIG)
- {
- return OID_SHA384_RSA_SIG;
- }
- else if (sigAlg == OID_SHA384_RSA_SIG)
- {
- return OID_SHA512_RSA_SIG;
- }
- else if (sigAlg == OID_SHA512_RSA_SIG)
- {
- return OID_SHA256_RSA_SIG;
- }
- else
- {
- return PS_UNSUPPORTED_FAIL;
- }
- }
- /*
- ECDSA:
- SHA1 -> SHA256
- SHA256 -> SHA384
- SHA384 -> SHA512
- SHA512 -> SHA256
- */
- else if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
- {
- if (sigAlg == OID_SHA1_ECDSA_SIG)
- {
- return OID_SHA256_ECDSA_SIG;
- }
- else if (sigAlg == OID_SHA256_ECDSA_SIG)
- {
- return OID_SHA384_ECDSA_SIG;
- }
- else if (sigAlg == OID_SHA384_ECDSA_SIG)
- {
- return OID_SHA512_ECDSA_SIG;
- }
- else if (sigAlg == OID_SHA512_ECDSA_SIG)
- {
- return OID_SHA256_ECDSA_SIG;
- }
- else
- {
- return PS_UNSUPPORTED_FAIL;
- }
- }
- else
- {
- return PS_UNSUPPORTED_FAIL;
- }
-}
-
-static
-int32_t sigAlgRsaToEcdsa(int32_t sigAlg)
-{
- if (sigAlg == OID_SHA1_RSA_SIG)
- {
- return OID_SHA1_ECDSA_SIG;
- }
- if (sigAlg == OID_SHA256_RSA_SIG)
- {
- return OID_SHA256_ECDSA_SIG;
- }
- if (sigAlg == OID_SHA384_RSA_SIG)
- {
- return OID_SHA384_ECDSA_SIG;
- }
- if (sigAlg == OID_SHA512_RSA_SIG)
- {
- return OID_SHA512_ECDSA_SIG;
- }
- else
- {
- return OID_SHA256_ECDSA_SIG;
- }
-}
-
-static
-int32_t ecdsaToRsa(int32_t sigAlg)
-{
- if (sigAlg == OID_SHA1_ECDSA_SIG)
- {
- return OID_SHA1_RSA_SIG;
- }
- if (sigAlg == OID_SHA256_ECDSA_SIG)
- {
- return OID_SHA256_RSA_SIG;
- }
- if (sigAlg == OID_SHA384_ECDSA_SIG)
- {
- return OID_SHA384_RSA_SIG;
- }
- if (sigAlg == OID_SHA512_ECDSA_SIG)
- {
- return OID_SHA512_RSA_SIG;
- }
- else
- {
- return OID_SHA256_RSA_SIG;
- }
-}
-
-/**
- Determine signature algorithm to use in the CertificateVerify or
- ServerKeyExchange handshake messages in TLS 1.2.
-
- TODO: add support for RSASSA-PSS.
-
- This function should only be called when using TLS 1.2.
-
- @param[in] certSigAlg The signature algorithm with which our
- certificate was signed.
- @param[in] keySize The size of our private key in bytes. For RSA,
- this is modulus; for ECDSA, this is the curve size.
- @param[in] pubKeyAlgorithm The public key algorithm to use for
- authentication. This should the same algorithm our public/private key
- pair is meant for. Must be either OID_RSA_KEY_ALG or
- OID_ECDSA_KEY_ALG.
- @param[in] peerSigAlg The list of signature algorithm masks
- the peer supports (e.g. HASH_SIG_SHA*_RSA_MASK). This should
- be the list created during parsing of the ClientHello or
- CertificateRequest message.
- @return The signature algorithm to use.
-*/
-int32_t chooseSigAlgInt(int32_t certSigAlg,
- psSize_t keySize,
- int32_t keyAlgorithm,
- uint16_t peerSigAlgs)
-{
- int32 a = certSigAlg;
- psResSize_t hashLen;
-
-#ifndef USE_RSA
- if (keyAlgorithm == OID_RSA_KEY_ALG)
- {
- return PS_UNSUPPORTED_FAIL;
- }
-#endif
-#ifndef USE_ECC
- if (keyAlgorithm == OID_ECDSA_KEY_ALG)
- {
- return PS_UNSUPPORTED_FAIL;
- }
-#endif
-
- /*
- We are going to use certSigAlg as the basis of our choice.
- This is because the SSL layer must ensure anyway that the peer
- supports this algorithm.
- */
- if (keyAlgorithm == OID_RSA_KEY_ALG)
- {
- if (certSigAlg == OID_SHA1_ECDSA_SIG ||
- certSigAlg == OID_SHA256_ECDSA_SIG ||
- certSigAlg == OID_SHA384_ECDSA_SIG ||
- certSigAlg == OID_SHA512_ECDSA_SIG)
- {
- /* Pubkey is RSA, but cert is signed with ECDSA.
- Convert certSigAlg to corresponding RSA alg. */
- a = ecdsaToRsa(certSigAlg);
- }
- }
- else if (keyAlgorithm == OID_ECDSA_KEY_ALG)
- {
- if (certSigAlg != OID_SHA1_ECDSA_SIG &&
- certSigAlg != OID_SHA256_ECDSA_SIG &&
- certSigAlg != OID_SHA384_ECDSA_SIG &&
- certSigAlg != OID_SHA512_ECDSA_SIG)
- {
- /* Pubkey is ECDSA, but cert is signed with RSA.
- Convert to corresponding ECDSA alg. */
- a = sigAlgRsaToEcdsa(certSigAlg);
- }
- }
-
- hashLen = psSigAlgToHashLen(a);
- if (hashLen < 0)
- { /* unknown sigAlg; error on hashLen */
- return hashLen;
- }
-
- /*
- For RSA signatures, RFC 5746 allows to pick any hash algorithm,
- as long as it is supported by the peer, i.e. included in the
- peer's signature_algorithms list.
-
- We use this opportunity to switch from the insecure MD5 and
- SHA-1 to SHA-256, if possible. We don't want to contribute
- to the longevity of obsolete hash algorithms.
- */
- if (psIsInsecureSigAlg(a, keyAlgorithm, keySize, hashLen)
- || !canUseSigAlg(a, keyAlgorithm, peerSigAlgs))
- {
- /* Try to upgrade: This won't select inscure ones. */
- a = upgradeSigAlg(a, keyAlgorithm);
- if (!canUseSigAlg(a, keyAlgorithm, peerSigAlgs))
- {
- /* Stil not supported. Try the next alternative. */
- a = upgradeSigAlg(a, keyAlgorithm);
- if (!canUseSigAlg(a, keyAlgorithm, peerSigAlgs))
- {
- /* Unable to upgrade insecure alg. Have to use the
- server cert sig alg. */
- a = certSigAlg;
- psTraceIntInfo("Fallback to certificate sigAlg: %d\n", a);
- }
- }
- }
- psTraceIntInfo("Chose sigAlg %d\n", a);
- return a;
-}
-
-int32_t chooseSigAlg(psX509Cert_t *cert,
- psPubKey_t *privKey,
- uint16_t peerSigAlgs)
-{
- int32 pubKeyAlg;
-
-# ifdef USE_CERT_PARSE
- pubKeyAlg = cert->pubKeyAlgorithm;
-# else
- if (privKey->type == PS_RSA)
- {
- pubKeyAlg = OID_RSA_KEY_ALG;
- }
- else if (privKey->type == PS_ECC)
- {
- pubKeyAlg = OID_ECDSA_KEY_ALG;
- }
- else
- {
- return PS_UNSUPPORTED_FAIL;
- }
-# endif /* USE_CERT_PARSE */
-
- return chooseSigAlgInt(cert->sigAlgorithm,
- privKey->keysize,
- pubKeyAlg,
- peerSigAlgs);
-}
-
-
-/* Return the TLS 1.2 SignatureAndHashAlgorithm encoding for the
- given algorithm OID. */
-int32_t getSignatureAndHashAlgorithmEncoding(uint16_t sigAlgOid,
- unsigned char *octet1,
- unsigned char *octet2,
- uint16_t *hashSize)
-{
- unsigned char b1, b2;
- uint16_t hLen = 0;
-
- switch (sigAlgOid)
- {
-#ifdef USE_SHA1
- case OID_SHA1_ECDSA_SIG:
- b1 = 0x2; /* SHA-1 */
- b2 = 0x3; /* ECDSA */
- hLen = SHA1_HASH_SIZE;
- break;
- case OID_SHA1_RSA_SIG:
- b1 = 0x2; /* SHA-1 */
- b2 = 0x1; /* RSA */
- hLen = SHA1_HASH_SIZE;
- break;
-#endif
-#ifdef USE_SHA256
- case OID_SHA256_ECDSA_SIG:
- b1 = 0x4; /* SHA-256 */
- b2 = 0x3; /* ECDSA */
- hLen = SHA256_HASH_SIZE;
- break;
- case OID_SHA256_RSA_SIG:
- b1 = 0x4; /* SHA-256 */
- b2 = 0x1; /* RSA */
- hLen = SHA256_HASH_SIZE;
- break;
-#endif
-#ifdef USE_SHA384
- case OID_SHA384_ECDSA_SIG:
- b1 = 0x5; /* SHA-384 */
- b2 = 0x3; /* ECDSA */
- hLen = SHA384_HASH_SIZE;
- break;
- case OID_SHA384_RSA_SIG:
- b1 = 0x5; /* SHA-384 */
- b2 = 0x1; /* RSA */
- hLen = SHA384_HASH_SIZE;
- break;
-#endif
-#ifdef USE_SHA512
- case OID_SHA512_ECDSA_SIG:
- b1 = 0x6; /* SHA-512 */
- b2 = 0x3; /* ECDSA */
- hLen = SHA512_HASH_SIZE;
- break;
- case OID_SHA512_RSA_SIG:
- b1 = 0x6; /* SHA-512 */
- b2 = 0x1; /* RSA */
- hLen = SHA512_HASH_SIZE;
- break;
-#endif
- default:
- return PS_UNSUPPORTED_FAIL; /* algorithm not supported */
- }
-
- if (octet1 && octet2 && hashSize)
- {
- *octet1 = b1;
- *octet2 = b2;
- *hashSize = hLen;
- return PS_SUCCESS;
- }
- return PS_ARG_FAIL;
-}
-#endif /* ! USE_ONLY_PSK_CIPHER_SUITE */
-#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */
-
/* Helper function that searches for an uint16 item in an array */
int32_t findFromUint16Array(const uint16_t *a,
psSize_t aLen,
@@ -1714,67 +1160,21 @@ int32_t findFromUint16Array(const uint16_t *a,
return PS_FAILURE;
}
-/* Helper function that determines whether TLS minor version is supported */
-psBool_t tlsVersionSupported(ssl_t *ssl, const uint8_t minVersion)
-{
- psSize_t i;
- for (i = 0; i < ssl->supportedVersionsLen; i++)
- {
- if ((ssl->supportedVersions[i] & 0xff) == minVersion)
- {
- return PS_TRUE;
- }
- }
- return PS_FALSE;
-}
-
psBool_t anyTls13VersionSupported(ssl_t *ssl)
{
- return tlsVersionSupported(ssl, tls_v_1_3) ||
- tlsVersionSupported(ssl, tls_v_1_3_draft_22) ||
- tlsVersionSupported(ssl, tls_v_1_3_draft_23) ||
- tlsVersionSupported(ssl, tls_v_1_3_draft_24) ||
- tlsVersionSupported(ssl, tls_v_1_3_draft_26) ||
- tlsVersionSupported(ssl, tls_v_1_3_draft_28);
+ return SUPP_VER(ssl, v_tls_1_3_any);
}
psBool_t anyNonTls13VersionSupported(ssl_t *ssl)
{
- return tlsVersionSupported(ssl, tls_v_1_2) ||
- tlsVersionSupported(ssl, tls_v_1_1) ||
- tlsVersionSupported(ssl, tls_v_1_0);
+ return SUPP_VER(ssl, v_tls_legacy);
}
# ifdef USE_TLS_1_3
-psBool_t tlsVersionSupportedByPeer(ssl_t *ssl, const uint8_t minVersion)
-{
- psSize_t i;
- for (i = 0; i < ssl->tls13PeerSupportedVersionsLen; i++)
- {
- if ((ssl->tls13PeerSupportedVersions[i] & 0xff) == minVersion)
- {
- return PS_TRUE;
- }
- }
- return PS_FALSE;
-}
-
-psBool_t anyTls13VersionSupportedByPeer(ssl_t *ssl)
-{
- return tlsVersionSupportedByPeer(ssl, tls_v_1_3) ||
- tlsVersionSupportedByPeer(ssl, tls_v_1_3_draft_22) ||
- tlsVersionSupportedByPeer(ssl, tls_v_1_3_draft_23) ||
- tlsVersionSupportedByPeer(ssl, tls_v_1_3_draft_24) ||
- tlsVersionSupportedByPeer(ssl, tls_v_1_3_draft_26) ||
- tlsVersionSupportedByPeer(ssl, tls_v_1_3_draft_28);
-}
-
psBool_t peerOnlySupportsTls13(ssl_t *ssl)
{
- if (anyTls13VersionSupportedByPeer(ssl)
- && !tlsVersionSupportedByPeer(ssl, TLS_1_0_MIN_VER)
- && !tlsVersionSupportedByPeer(ssl, TLS_1_1_MIN_VER)
- && !tlsVersionSupportedByPeer(ssl, TLS_1_2_MIN_VER))
+ if (PEER_SUPP_VER(ssl, v_tls_1_3_any)
+ && !PEER_SUPP_VER(ssl, v_tls_legacy))
{
return PS_TRUE;
}
@@ -1783,10 +1183,10 @@ psBool_t peerOnlySupportsTls13(ssl_t *ssl)
psBool_t weOnlySupportTls13(ssl_t *ssl)
{
- if (anyTls13VersionSupported(ssl)
- && !tlsVersionSupported(ssl, TLS_1_0_MIN_VER)
- && !tlsVersionSupported(ssl, TLS_1_1_MIN_VER)
- && !tlsVersionSupported(ssl, TLS_1_2_MIN_VER))
+ if (SUPP_VER(ssl, v_tls_1_3_any)
+ && !SUPP_VER(ssl, v_tls_1_0)
+ && !SUPP_VER(ssl, v_tls_1_1)
+ && !SUPP_VER(ssl, v_tls_1_2))
{
return PS_TRUE;
}
diff --git a/matrixssl/tls13Authenticate.c b/matrixssl/tls13Authenticate.c
index e4c4476..37d454c 100644
--- a/matrixssl/tls13Authenticate.c
+++ b/matrixssl/tls13Authenticate.c
@@ -38,6 +38,7 @@
# endif
# ifdef USE_TLS_1_3
+# ifdef USE_CERT_VALIDATE
static int32_t matrixSslValidatePeerCerts(ssl_t *ssl,
void *pkiData);
@@ -279,4 +280,5 @@ void psCheckSetPathLenFailure(ssl_t *ssl,
cert = cert->next;
}
}
+# endif /* USE_CERT_VALIDATE */
# endif /* USE_TLS_1_3 */
diff --git a/matrixssl/tls13CipherSuite.c b/matrixssl/tls13CipherSuite.c
index ea6d2e6..7cd3310 100644
--- a/matrixssl/tls13CipherSuite.c
+++ b/matrixssl/tls13CipherSuite.c
@@ -78,8 +78,8 @@ static inline
void tls13MakeEncryptAad(ssl_t *ssl, unsigned char aadOut[5])
{
aadOut[0] = SSL_RECORD_TYPE_APPLICATION_DATA;
- aadOut[1] = ssl->majVer;
- aadOut[2] = ssl->minVer;
+ aadOut[1] = 0x03;
+ aadOut[2] = 0x03;
aadOut[3] = (ssl->outRecLen & 0xff00) >> 8;
aadOut[4] = (ssl->outRecLen & 0xff);
}
@@ -88,8 +88,8 @@ static inline
void tls13MakeDecryptAad(ssl_t *ssl, unsigned char aadOut[5])
{
aadOut[0] = SSL_RECORD_TYPE_APPLICATION_DATA;
- aadOut[1] = ssl->majVer;
- aadOut[2] = ssl->minVer;
+ aadOut[1] = 0x03;
+ aadOut[2] = 0x03;
aadOut[3] = (ssl->rec.len & 0xff00) >> 8;
aadOut[4] = (ssl->rec.len & 0xff);
}
@@ -221,7 +221,7 @@ int32 csAesGcmDecryptTls13(void *ssl, unsigned char *ct,
return bytes;
}
-#ifdef USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE
+#if defined(USE_CHACHA20_POLY1305_IETF_CIPHER_SUITE) || defined(USE_CHACHA20_POLY1305_IETF)
int32 csChacha20Poly1305IetfEncryptTls13(void *ssl, unsigned char *pt,
unsigned char *ct, uint32 len)
{
diff --git a/matrixssl/tls13Decode.c b/matrixssl/tls13Decode.c
index 701eeb6..6a92549 100644
--- a/matrixssl/tls13Decode.c
+++ b/matrixssl/tls13Decode.c
@@ -139,12 +139,19 @@ static int32_t tls13ParseNewSessionTicket(ssl_t *ssl,
psParseBuf_t *pb);
static int32_t tls13ParseServerHello(ssl_t *ssl,
psParseBuf_t *pb);
+#ifdef USE_IDENTITY_CERTIFICATES
+# ifdef USE_CLIENT_SIDE_SSL
static int32_t tls13ParseCertificateRequest(ssl_t *ssl,
psParseBuf_t *pb);
+# endif
static int32_t tls13ParseCertificate(ssl_t *ssl,
psParseBuf_t *pb);
+# ifdef USE_CERT_VALIDATE
static int32_t tls13ParseCertificateVerify(ssl_t *ssl,
psParseBuf_t *pb);
+# endif
+#endif
+
static int32_t tls13HandleAlert(ssl_t *ssl,
unsigned char level,
unsigned char type,
@@ -661,9 +668,10 @@ static int32_t tls13CheckHsState(ssl_t *ssl,
}
else
{
- psTraceErrr("Received unexpected message.\n Got: ");
+ psTraceErrr("Received unexpected handshake message.\n");
+ psTraceInfo(" Got ");
psTracePrintHsMsgType(msg, PS_FALSE);
- psTraceErrr(" in state: ");
+ psTraceInfo(" in state ");
psTracePrintHsState(ssl->hsState, PS_TRUE);
ssl->err = SSL_ALERT_UNEXPECTED_MESSAGE;
return MATRIXSSL_ERROR;
@@ -918,6 +926,8 @@ static int32_t tls13ParseHandshakeMessage(ssl_t *ssl,
ssl->hsState = SSL_HS_TLS_1_3_WAIT_CERT_CR;
}
break;
+# ifdef USE_IDENTITY_CERTIFICATES
+# ifdef USE_CLIENT_SIDE_SSL
case SSL_HS_CERTIFICATE_REQUEST:
rc = tls13ParseCertificateRequest(ssl, &pb);
if (rc < 0)
@@ -927,6 +937,10 @@ static int32_t tls13ParseHandshakeMessage(ssl_t *ssl,
tls13TranscriptHashUpdate(ssl, msgStart, msgEnd-msgStart);
ssl->hsState = SSL_HS_TLS_1_3_WAIT_CERT;
break;
+# endif
+# endif
+
+# ifdef USE_CERT_VALIDATE
case SSL_HS_CERTIFICATE:
rc = tls13ParseCertificate(ssl, &pb);
if (rc < 0)
@@ -948,6 +962,7 @@ static int32_t tls13ParseHandshakeMessage(ssl_t *ssl,
tls13TranscriptHashUpdate(ssl, msgStart, msgEnd-msgStart);
ssl->hsState = SSL_HS_TLS_1_3_WAIT_FINISHED;
break;
+# endif /* USE_CERT_VALIDATE */
case SSL_HS_EOED:
psTracePrintHsMessageParse(ssl, SSL_HS_EOED);
rc = tls13ActivateHsReadKeys(ssl);
@@ -1045,6 +1060,7 @@ static int32_t tls13ParseServerHello(ssl_t *ssl,
uint32_t cipher;
unsigned char compressionMethod;
uint16_t tmp_u16;
+ uint16_t legacy_version;
psTracePrintHsMessageParse(ssl, SSL_HS_SERVER_HELLO);
@@ -1060,14 +1076,16 @@ static int32_t tls13ParseServerHello(ssl_t *ssl,
*/
/* ProtocolVersion legacy_version = 0x0303; */
- if (!psParseOctet(pb, &ssl->reqMajVer)
- || !psParseOctet(pb, &ssl->reqMinVer))
+ rc = psParseBufTryParseBigEndianUint16(pb, &legacy_version);
+ if (rc != 2)
{
return PS_PARSE_FAIL;
}
- psTracePrintProtocolVersion(INDENT_HS_MSG,
+ ssl->peerHelloVersion = psVerFromEncoding(legacy_version);
+ psTracePrintProtocolVersionNew(INDENT_HS_MSG,
"legacy_version",
- ssl->reqMajVer, ssl->reqMinVer, 1);
+ ssl->peerHelloVersion,
+ PS_TRUE);
/* Ignore legacy_version. */
/*
@@ -1228,7 +1246,8 @@ exit:
return rc;
}
-
+#ifdef USE_IDENTITY_CERTIFICATES
+# ifdef USE_CLIENT_SIDE_SSL
static psRes_t tls13ParseCertificateRequest(ssl_t *ssl,
psParseBuf_t *pb)
{
@@ -1251,11 +1270,11 @@ static psRes_t tls13ParseCertificateRequest(ssl_t *ssl,
ssl->err = SSL_ALERT_HANDSHAKE_FAILURE;
return PS_PARSE_FAIL;
}
-#ifdef DEBUG_TLS_1_3_DECODE_DUMP
+# ifdef DEBUG_TLS_1_3_DECODE_DUMP
psTraceBytes("Parsed CertificateRequest.certRequestContext",
pb->buf.start,
certificateRequestContextLen);
-# endif
+# endif
if (certificateRequestContextLen > 0)
{
/* Store the value from server */
@@ -1371,7 +1390,10 @@ static psRes_t tls13ParseCertificateRequest(ssl_t *ssl,
return MATRIXSSL_SUCCESS;
}
+# endif /* USE_CLIENT_SIDE_SSL */
+# endif /* USE_IDENTITY_CERTIFICATES */
+# ifdef USE_CERT_VALIDATE
static int32_t tls13ParseCertificate(ssl_t *ssl,
psParseBuf_t *pb)
{
@@ -1647,6 +1669,7 @@ static int32_t tls13ParseCertificateVerify(ssl_t *ssl,
return MATRIXSSL_SUCCESS;
}
+# endif /* USE_CERT_VALIDATE */
static int32_t tls13ParseFinished(ssl_t *ssl, psParseBuf_t *pb)
{
@@ -1941,8 +1964,8 @@ static int32_t tls13ParseNewSessionTicket(ssl_t *ssl, psParseBuf_t *pb)
}
params.alpn = NULL;
params.alpnLen = 0;
- params.majVer = TLS_MAJ_VER;
- params.minVer = ssl->tls13NegotiatedMinorVer;
+ params.majVer = psEncodeVersionMaj(ssl->activeVersion);
+ params.minVer = psEncodeVersionMin(ssl->activeVersion);
params.cipherId = ssl->cipher->ident;
params.ticketLifetime = ticketLifetime;
params.ticketAgeAdd = ticketAgeAdd;
@@ -1981,10 +2004,12 @@ static int32_t tls13ParseNewSessionTicket(ssl_t *ssl, psParseBuf_t *pb)
multiple tickets in a single handshake, but we only support
storing the last one. TODO: add support for storing multiple
tickets. */
+# ifdef USE_STATELESS_SESSION_TICKETS
if (ssl->sid->sessionTicket)
{
psFree(ssl->sid->sessionTicket, ssl->sid->pool);
}
+# endif
if (ssl->sid->psk)
{
tls13FreePsk(ssl->sid->psk, ssl->sid->pool);
@@ -2000,7 +2025,7 @@ static int32_t tls13ParseNewSessionTicket(ssl_t *ssl, psParseBuf_t *pb)
Memset(ssl->sid, 0, sizeof(sslSessionId_t));
ssl->sid->pool = ssl->hsPool;
}
-
+# ifdef USE_STATELESS_SESSION_TICKETS
ssl->sid->sessionTicket = psMalloc(ssl->sid->pool, ticketLen);
if (ssl->sid->sessionTicket == NULL)
{
@@ -2008,6 +2033,7 @@ static int32_t tls13ParseNewSessionTicket(ssl_t *ssl, psParseBuf_t *pb)
}
Memcpy(ssl->sid->sessionTicket, ticket, ticketLen);
ssl->sid->sessionTicketLen = ticketLen;
+# endif
ssl->sid->cipherId = psk->params->cipherId;
ssl->sid->psk = tls13NewPsk(psk->pskKey,
diff --git a/matrixssl/tls13DecodeExt.c b/matrixssl/tls13DecodeExt.c
index c6c7c96..b129f2f 100644
--- a/matrixssl/tls13DecodeExt.c
+++ b/matrixssl/tls13DecodeExt.c
@@ -145,6 +145,7 @@ psBool_t tls13ExtensionAllowedInMessage(ssl_t *ssl,
return PS_TRUE;
}
+# if defined(USE_IDENTITY_CERTIFICATES) && defined(USE_OCSP_RESPONSE)
int32_t tls13ParseStatusRequest(ssl_t *ssl,
psParseBuf_t *extBuf)
{
@@ -200,7 +201,10 @@ int32_t tls13ParseStatusRequest(ssl_t *ssl,
cert = cert->next;
}
- psParseOctet(extBuf, &type);
+ if (!psParseOctet(extBuf, &type))
+ {
+ goto out_decode_error;
+ }
if (type != 0x01)
{
psTraceErrr("Invalid status_type in status_request\n");
@@ -255,6 +259,7 @@ out_bad_certificate_status_response:
ssl->err = SSL_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE;
return MATRIXSSL_ERROR;
}
+# endif /* USE_IDENTITY_CERTIFICATES && USE_OCSP_RESPONSE */
/*
Parses a single extension:
@@ -322,6 +327,7 @@ int32_t tls13ParseSingleExtension(ssl_t *ssl,
return rc;
}
break;
+# if defined(USE_IDENTITY_CERTIFICATES) && defined(USE_OCSP_RESPONSE)
case EXT_STATUS_REQUEST:
rc = tls13ParseStatusRequest(ssl, &extDataBuf);
if (rc < 0)
@@ -329,6 +335,7 @@ int32_t tls13ParseSingleExtension(ssl_t *ssl,
return rc;
}
break;
+# endif
default:
psTraceIntInfo("Ignoring unknown extension: %hu\n", extType);
}
@@ -401,6 +408,7 @@ psSize_t tls13ParseSupportedVersions(ssl_t *ssl,
psSize_t dataLen;
int32 i = 0;
unsigned char majVer, minVer;
+ psProtocolVersion_t ver;
const unsigned char *p = *c;
psSize_t parsedLen;
@@ -431,17 +439,17 @@ psSize_t tls13ParseSupportedVersions(ssl_t *ssl,
psTraceErrr("Malformed supported_versions extension\n");
goto out_decode_error;
}
-
ssl->extFlags.got_supported_versions = 1;
- ssl->tls13PeerSupportedVersionsLen = 0;
+ ssl->peerSupportedVersionsPriorityLen = 0;
while(len > 0)
{
majVer = *p; p++;
minVer = *p; p++;
len -= 2;
+ ver = psVerFromEncodingMajMin(majVer, minVer);
- ssl->tls13PeerSupportedVersions[i] = (majVer << 8) | minVer;
- ssl->tls13PeerSupportedVersionsLen++;
+ ADD_PEER_SUPP_VER(ssl, ver);
+ ADD_PEER_SUPP_VER_PRIORITY(ssl, ver);
i++;
if (i >= TLS_MAX_SUPPORTED_VERSIONS)
@@ -469,7 +477,7 @@ int32_t tls13ParseServerSupportedVersions(ssl_t *ssl,
psParseBuf_t *pb)
{
unsigned char maj, min;
- psBool_t negotiatedTls13 = PS_FALSE;
+ psProtocolVersion_t ver;
psTracePrintExtensionParse(ssl, EXT_SUPPORTED_VERSIONS);
@@ -477,29 +485,23 @@ int32_t tls13ParseServerSupportedVersions(ssl_t *ssl,
{
return PS_PARSE_FAIL;
}
+ ver = psVerFromEncodingMajMin(maj, min);
psTracePrintProtocolVersion(INDENT_EXTENSION,
"selected_version",
maj, min, 1);
- if (!tlsVersionSupported(ssl, min))
+ if (!SUPP_VER(ssl, ver))
{
ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
psTraceIntInfo("Unsupported server version: %u", min);
return MATRIXSSL_ERROR;
}
- if ((maj == TLS_MAJ_VER && min == TLS_1_3_MIN_VER) ||
- (maj == TLS_1_3_DRAFT_MAJ_VER &&
- min >= MIN_ENABLED_TLS_1_3_DRAFT_VERSION))
- {
- negotiatedTls13 = PS_TRUE;
- }
+ SET_NGTD_VER(ssl, ver);
- if (negotiatedTls13)
+ if (ver & v_tls_1_3_any)
{
- ssl->flags |= SSL_FLAGS_TLS_1_3_NEGOTIATED;
- ssl->tls13NegotiatedMinorVer = min;
return PS_SUCCESS;
}
else
@@ -509,6 +511,7 @@ int32_t tls13ParseServerSupportedVersions(ssl_t *ssl,
}
}
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
static
int32_t tls13ParseServerKeyShare(ssl_t *ssl,
psParseBuf_t *pb)
@@ -607,6 +610,7 @@ out_illegal_parameter:
ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
return MATRIXSSL_ERROR;
}
+# endif /* USE_ONLY_PSK_CIPHER_SUITE */
static
int32_t tls13VerifyBinder(ssl_t *ssl,
@@ -757,6 +761,11 @@ psBool_t tls13ServerFoundSupportedPsk(ssl_t *ssl,
psTls13Psk_t *psk,
uint16_t indexInClientPreSharedKey)
{
+ psProtocolVersion_t pskVer;
+ uint8_t majVer, minVer;
+
+ (void)pskVer;
+
psTraceInfo("Server recognized a PSK in pre_shared_key\n");
if (psk->isResumptionPsk)
{
@@ -768,9 +777,14 @@ psBool_t tls13ServerFoundSupportedPsk(ssl_t *ssl,
ssl->sec.tls13SelectedIdentityIndex = indexInClientPreSharedKey;
if (psk->params != NULL)
{
- ssl->majVer = psk->params->majVer;
- ssl->minVer = TLS_1_2_MIN_VER; /* legacy_version. */
- ssl->flags |= tlsMinVerToVersionFlag(psk->params->minVer);
+ majVer = psk->params->majVer;
+ minVer = psk->params->minVer;
+ if (minVer == 0)
+ {
+ minVer = TLS_1_2_MIN_VER;
+ }
+ pskVer = psVerFromEncodingMajMin(majVer, minVer);
+
ssl->cipher = sslGetCipherSpec(ssl, psk->params->cipherId);
if (ssl->cipher == NULL)
{
@@ -778,14 +792,10 @@ psBool_t tls13ServerFoundSupportedPsk(ssl_t *ssl,
"ciphersuite\n");
return PS_FALSE;
}
- if (psk->params->minVer != 0)
- {
- psTracePrintProtocolVersion(INDENT_EXTENSION,
- "PSK is associated with protocol version",
- ssl->majVer,
- psk->params->minVer,
- PS_TRUE);
- }
+ psTracePrintProtocolVersionNew(INDENT_EXTENSION,
+ "PSK is associated with protocol version",
+ pskVer,
+ PS_TRUE);
psTracePrintCiphersuiteName(INDENT_EXTENSION,
"PSK is associated with ciphersuite",
ssl->cipher->ident,
@@ -1209,7 +1219,7 @@ int32_t tls13ParseServerName(ssl_t *ssl,
*/
psAssert(!IS_SERVER(ssl));
psTracePrintExtensionParse(ssl, EXT_SERVER_NAME);
-
+# ifdef USE_CLIENT_SIDE_SSL
/* Solicited or not? */
if (ssl->extFlags.req_sni == 0)
{
@@ -1226,7 +1236,9 @@ int32_t tls13ParseServerName(ssl_t *ssl,
}
psTraceInfo("Received empty server_name in EncryptedExtensions\n");
-
+# else
+ return MATRIXSSL_ERROR;
+# endif
return PS_SUCCESS;
}
@@ -1279,6 +1291,7 @@ int32_t tls13ParseSignatureAlgorithms(ssl_t *ssl,
psTracePrintExtensionParse(ssl, EXT_SIGNATURE_ALGORITHMS);
}
+
(void)psParseBufFromStaticData(&pb, *c, len);
/* Move the supplied pointer forwards to the end
of this extension */
@@ -1293,7 +1306,9 @@ int32_t tls13ParseSignatureAlgorithms(ssl_t *ssl,
if (isCert)
{
+# ifdef USE_IDENTITY_CERTIFICATES
ssl->sec.keySelect.peerCertSigAlgsLen = 0;
+# endif
}
else
{
@@ -1318,6 +1333,7 @@ int32_t tls13ParseSignatureAlgorithms(ssl_t *ssl,
/* Save the algoritm based on which extension this is */
if (isCert)
{
+# ifdef USE_IDENTITY_CERTIFICATES
/* Make sure this sig_alg_cert is in our supported list */
if (findFromUint16Array(
ssl->tls13SupportedSigAlgsCert,
@@ -1331,6 +1347,7 @@ int32_t tls13ParseSignatureAlgorithms(ssl_t *ssl,
ssl->sec.keySelect.peerCertSigAlgMask |= mask;
i++;
}
+# endif
}
else
{
@@ -1352,12 +1369,14 @@ int32_t tls13ParseSignatureAlgorithms(ssl_t *ssl,
if (isCert)
{
+# ifdef USE_IDENTITY_CERTIFICATES
/* signature_algorithms_cert only defined in TLS 1.3. */
psTracePrintTls13SigAlgList(INDENT_EXTENSION,
"Parsed signature_algorithms_cert",
ssl->sec.keySelect.peerCertSigAlgs,
ssl->sec.keySelect.peerCertSigAlgsLen,
PS_TRUE);
+# endif
}
else
{
@@ -1370,7 +1389,7 @@ int32_t tls13ParseSignatureAlgorithms(ssl_t *ssl,
return MATRIXSSL_SUCCESS;
}
-
+# ifdef USE_IDENTITY_CERTIFICATES
psRes_t tls13ParseCertificateAuthorities(ssl_t *ssl,
const unsigned char **start, psSizeL_t len)
{
@@ -1446,6 +1465,7 @@ psRes_t tls13ParseCertificateAuthorities(ssl_t *ssl,
psTraceIntInfo(" got %d CA names\n", keySelect->nCas);
return PS_SUCCESS;
}
+# endif
int32_t tls13ParseEncryptedExtensions(ssl_t *ssl,
psParseBuf_t *pb)
@@ -1642,6 +1662,7 @@ int32_t tls13ParseServerHelloExtensions(ssl_t *ssl,
switch (extensionType)
{
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
case EXT_KEY_SHARE_PRE_DRAFT_23:
case EXT_KEY_SHARE:
rc = tls13ParseServerKeyShare(ssl, &extDataBuf);
@@ -1650,6 +1671,7 @@ int32_t tls13ParseServerHelloExtensions(ssl_t *ssl,
return rc;
}
break;
+# endif
case EXT_PRE_SHARED_KEY:
rc = tls13ParsePreSharedKey(ssl, &extDataBuf);
if (rc < 0)
@@ -1687,7 +1709,7 @@ int32_t tls13ParseServerHelloExtensions(ssl_t *ssl,
}
/* We should have negotiated 1.3 if we get here. */
- psAssert(NEGOTIATED_TLS_1_3(ssl));
+ psAssert(NGTD_VER(ssl, v_tls_1_3_any));
if (gotForbiddenExtension)
{
diff --git a/matrixssl/tls13Encode.c b/matrixssl/tls13Encode.c
index db037d4..186f5a0 100644
--- a/matrixssl/tls13Encode.c
+++ b/matrixssl/tls13Encode.c
@@ -215,6 +215,10 @@ int32_t tls13WriteRecordHeader(ssl_t *ssl,
if (bodyLen + 1 > TLS_1_3_MAX_INNER_PLAINTEXT_LEN)
{
psTraceErrr("Error: tried to encode oversized TLSInnerPlaintext.\n");
+ if (mustFreeBody)
+ {
+ psFree(body, pool);
+ }
return PS_ARG_FAIL;
}
psDynBufInit(pool, &TLSInnerPlaintext, bodyLen + 1 + *padLen);
@@ -614,6 +618,8 @@ static int32_t makeHsRecord(ssl_t *ssl,
return PS_SUCCESS;
}
+#ifdef USE_SERVER_SIDE_SSL
+
static int32 tls13WriteServerHello(ssl_t *ssl, sslBuf_t *out,
psBool_t isHelloRetryRequest)
{
@@ -877,6 +883,7 @@ static int32 tls13WriteCertificateRequest(ssl_t *ssl, sslBuf_t *out)
return rc;
}
+# ifdef USE_IDENTITY_CERTIFICATES
rc = tls13WriteCertificateAuthorities(ssl,
&extBuf);
if (rc < 0)
@@ -885,7 +892,7 @@ static int32 tls13WriteCertificateRequest(ssl_t *ssl, sslBuf_t *out)
psDynBufUninit(&extBuf);
return rc;
}
-
+# endif
ext = psDynBufDetachPsSize(&extBuf, &extLen);
if (ext == NULL)
{
@@ -926,6 +933,9 @@ out_internal_error:
return MATRIXSSL_ERROR;
}
+# endif /* USE_SERVER_SIDE_SSL */
+
+# ifdef USE_IDENTITY_CERTIFICATES
static int32 tls13WriteCertificate(ssl_t *ssl, sslBuf_t *out)
{
int32 rc;
@@ -983,6 +993,7 @@ static int32 tls13WriteCertificate(ssl_t *ssl, sslBuf_t *out)
{
for (i = 0; i < ssl->sec.keySelect.peerCertSigAlgsLen; i++)
{
+# ifdef USE_RSA
if (c->sigAlgorithm == OID_SHA256_RSA_SIG ||
c->sigAlgorithm == OID_SHA384_RSA_SIG ||
c->sigAlgorithm == OID_SHA512_RSA_SIG)
@@ -992,15 +1003,18 @@ static int32 tls13WriteCertificate(ssl_t *ssl, sslBuf_t *out)
break;
}
}
- else if (c->sigAlgorithm == OID_SHA256_ECDSA_SIG ||
- c->sigAlgorithm == OID_SHA384_ECDSA_SIG ||
- c->sigAlgorithm == OID_SHA512_ECDSA_SIG)
+# endif
+# ifdef USE_ECC
+ if (c->sigAlgorithm == OID_SHA256_ECDSA_SIG ||
+ c->sigAlgorithm == OID_SHA384_ECDSA_SIG ||
+ c->sigAlgorithm == OID_SHA512_ECDSA_SIG)
{
if (tls13IsEcdsaSigAlg(ssl->sec.keySelect.peerCertSigAlgs[i]))
{
break;
}
}
+# endif
}
}
if (c == NULL || i == ssl->sec.keySelect.peerCertSigAlgsLen)
@@ -1027,6 +1041,7 @@ static int32 tls13WriteCertificate(ssl_t *ssl, sslBuf_t *out)
extData = NULL;
extDataLen = 0;
+# ifdef USE_OCSP_RESPONSE
/* Add the OCSP status request extension, if requested.
Only support adding the extension for our own (server) cert. */
if (ssl->extFlags.status_request == 1 && c == ssl->chosenIdentity->cert)
@@ -1042,9 +1057,11 @@ static int32 tls13WriteCertificate(ssl_t *ssl, sslBuf_t *out)
extData = psDynBufDetach(&extBuf, &extDataLen);
if (extData == NULL)
{
- goto out_internal_error;
+ ssl->err = SSL_ALERT_INTERNAL_ERROR;
+ return MATRIXSSL_ERROR;
}
}
+# endif
/* Extension extensions<0..2^16-1>; */
psDynBufAppendTlsVector(&certListBuf,
@@ -1062,6 +1079,7 @@ static int32 tls13WriteCertificate(ssl_t *ssl, sslBuf_t *out)
certList = psDynBufDetachPsSize(&certListBuf, &certListLen);
if (certList == NULL)
{
+ ssl->err = SSL_ALERT_INTERNAL_ERROR;
return PS_MEM_FAIL;
}
@@ -1075,6 +1093,7 @@ static int32 tls13WriteCertificate(ssl_t *ssl, sslBuf_t *out)
certData = psDynBufDetachPsSize(&certBuf, &certDataLen);
if (certData == NULL)
{
+ ssl->err = SSL_ALERT_INTERNAL_ERROR;
return PS_MEM_FAIL;
}
@@ -1087,15 +1106,7 @@ static int32 tls13WriteCertificate(ssl_t *ssl, sslBuf_t *out)
PS_TRUE,
out);
psFree(certData, ssl->hsPool);
- if (rc < 0)
- {
- return rc;
- }
- return MATRIXSSL_SUCCESS;
-
-out_internal_error:
- ssl->err = SSL_ALERT_INTERNAL_ERROR;
- return MATRIXSSL_ERROR;
+ return rc;
}
/* Should be good for both client and server? */
@@ -1129,6 +1140,7 @@ static int32 tls13WriteCertificateVerify(ssl_t *ssl, sslBuf_t *out)
ssl->sec.keySelect.peerSigAlgsLen);
if (chosenSigAlg == 0 || hmacLen < 0)
{
+ psTraceErrr("Failed to negotiate CertificateVerify sig alg\n");
ssl->err = SSL_ALERT_HANDSHAKE_FAILURE;
return SSL_SEND_RESPONSE;
}
@@ -1184,6 +1196,7 @@ static int32 tls13WriteCertificateVerify(ssl_t *ssl, sslBuf_t *out)
#ifdef TLS_1_3_VERIFY_OWN_SIG
verifyOwnSig = PS_TRUE;
#else
+# ifdef USE_RSA
if (tls13IsRsaSigAlg(chosenSigAlg))
{
/*
@@ -1194,14 +1207,16 @@ static int32 tls13WriteCertificateVerify(ssl_t *ssl, sslBuf_t *out)
When using crypto-cl, the self-verification has already
been done within CL/SL (CL_HashSafeSign).
*/
-# ifndef USE_CL_RSA
+# ifndef USE_CL_RSA
verifyOwnSig = PS_TRUE;
-# endif
+# endif
}
+# endif
#endif
if (verifyOwnSig)
{
+# ifdef USE_CERT_PARSE
/* Verify the signature we just generated. */
rc = tls13Verify(ssl->hsPool,
&ssl->chosenIdentity->cert->publicKey,
@@ -1218,6 +1233,7 @@ static int32 tls13WriteCertificateVerify(ssl_t *ssl, sslBuf_t *out)
psTraceErrr("Could not verify own sig!!\n");
return rc;
}
+# endif
}
ssl->sec.tls13KsState.generateCvSigDone = 1;
@@ -1250,6 +1266,9 @@ static int32 tls13WriteCertificateVerify(ssl_t *ssl, sslBuf_t *out)
return MATRIXSSL_SUCCESS;
}
+# endif /* USE_IDENTITY_CERTIFICATES */
+
+# ifdef USE_CLIENT_SIDE_SSL
static int32 tls13WriteEndOfEarlyData(ssl_t *ssl, sslBuf_t *out)
{
int32 rc;
@@ -1271,6 +1290,7 @@ static int32 tls13WriteEndOfEarlyData(ssl_t *ssl, sslBuf_t *out)
}
return PS_SUCCESS;
}
+# endif
static int32 tls13WriteFinished(ssl_t *ssl, sslBuf_t *out)
{
@@ -1360,6 +1380,7 @@ static int32 tls13WriteFinished(ssl_t *ssl, sslBuf_t *out)
return PS_SUCCESS;
}
+# ifdef USE_SERVER_SIDE_SSL
static
int32_t tls13WriteNewSessionTicket(ssl_t *ssl, sslBuf_t *out)
{
@@ -1467,6 +1488,7 @@ out_internal_error:
ssl->err = SSL_ALERT_INTERNAL_ERROR;
return MATRIXSSL_ERROR;
}
+# endif /* USE_SERVER_SIDE_SSL */
/* Estimate buffer size needed for the next flight we are going
to send. */
@@ -1512,15 +1534,15 @@ void tls13ClearHsTemporaryState(ssl_t *ssl)
static inline
psBool_t clientKeyShareOk(ssl_t *ssl)
{
- if (ssl->sec.eccKeyPub != NULL ||
-# ifdef USE_DH
- ssl->sec.dhKeyPub != NULL ||
+# ifdef USE_ECC
+ if (ssl->sec.eccKeyPub != NULL) return PS_TRUE;
+# endif
+# ifdef USE_DH
+ if (ssl->sec.dhKeyPub != NULL) return PS_TRUE;
+# endif
+# ifdef USE_X25519
+ if (ssl->sec.x25519KeyPub != NULL) return PS_TRUE;
# endif
- ssl->sec.x25519KeyPub != NULL)
- {
- return PS_TRUE;
- }
-
return PS_FALSE;
}
@@ -1742,6 +1764,7 @@ int32_t tls13EncodeResponseServer(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen)
"Servers which are authenticating with a PSK MUST NOT send
the CertificateRequest in the main handshake."
*/
+# ifdef USE_SERVER_SIDE_SSL
if (ssl->flags & SSL_FLAGS_CLIENT_AUTH)
{
rc = tls13WriteCertificateRequest(ssl, out);
@@ -1750,6 +1773,8 @@ int32_t tls13EncodeResponseServer(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen)
return rc;
}
}
+# endif
+# ifdef USE_IDENTITY_CERTIFICATES
rc = tls13WriteCertificate(ssl, out);
if (rc < 0)
{
@@ -1760,6 +1785,7 @@ int32_t tls13EncodeResponseServer(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen)
{
return rc;
}
+# endif
}
rc = tls13WriteFinished(ssl, out);
if (rc < 0)
@@ -1853,6 +1879,7 @@ int32 tls13EncodeResponseClient(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen)
return rc;
}
}
+# ifdef USE_IDENTITY_CERTIFICATES
/* In the client side the only way we know about peer signature
algorithms is that we have received CertificateRequest. Respond
to that here */
@@ -1872,6 +1899,7 @@ int32 tls13EncodeResponseClient(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen)
}
}
}
+# endif
rc = tls13WriteFinished(ssl, out);
if (rc < 0)
{
@@ -1917,24 +1945,19 @@ int32 tls13EncodeResponse(ssl_t *ssl, psBuf_t *out, uint32 *requiredLen)
void tls13ResetState(ssl_t *ssl)
{
- Memset(ssl->tls13PeerSupportedVersions,
- 0, sizeof(ssl->tls13PeerSupportedVersions));
- ssl->tls13PeerSupportedVersionsLen = 0;
- ssl->tls13NegotiatedMinorVer = 0;
+ Memset(ssl->peerSupportedVersionsPriority,
+ 0, sizeof(ssl->peerSupportedVersionsPriority));
+ ssl->peerSupportedVersionsPriorityLen = 0;
ssl->tls13ServerEarlyDataEnabled = PS_FALSE;
+# ifdef USE_IDENTITY_CERTIFICATES
Memset(ssl->sec.keySelect.peerSigAlgs,
0, sizeof(ssl->sec.keySelect.peerSigAlgs));
ssl->sec.keySelect.peerSigAlgsLen = 0;
Memset(ssl->sec.keySelect.peerCertSigAlgs,
0, sizeof(ssl->sec.keySelect.peerCertSigAlgs));
ssl->sec.keySelect.peerCertSigAlgsLen = 0;
- ssl->flags &= ~(SSL_FLAGS_TLS_1_3 |
- SSL_FLAGS_TLS_1_3_DRAFT_22 |
- SSL_FLAGS_TLS_1_3_DRAFT_23 |
- SSL_FLAGS_TLS_1_3_DRAFT_24 |
- SSL_FLAGS_TLS_1_3_DRAFT_26 |
- SSL_FLAGS_TLS_1_3_DRAFT_28);
- ssl->flags &= ~SSL_FLAGS_TLS_1_3_NEGOTIATED;
+# endif
+ RESET_ACTV_VER(ssl);
Memset(ssl->sec.seq, 0, sizeof(ssl->sec.seq));
Memset(ssl->sec.remSeq, 0, sizeof(ssl->sec.remSeq));
}
@@ -2018,7 +2041,10 @@ int32_t tls13EncryptMessage(ssl_t *ssl,
/* This was actually a HelloRetryRequest.
Now we need to start over and negotiate TLS 1.3 anew. */
tls13ResetState(ssl);
- /* Return to the <1.3 code path. */
+ /* Return to the <1.3 code path. We must do this because:
+ 1) we wish to start version negotiation from scratch
+ 2) we have no TLS 1.3-specific ClientHello parsing function.
+ */
ssl->hsState = SSL_HS_CLIENT_HELLO;
}
else
@@ -2265,6 +2291,7 @@ int32_t tls13EncodeAlert(ssl_t *ssl,
return MATRIXSSL_SUCCESS;
}
+# ifdef USE_CLIENT_SIDE_SSL
static int32_t tls13SetUpClientEarlyData(ssl_t *ssl)
{
int32_t rc;
@@ -2356,6 +2383,7 @@ int32 tls13WriteClientHello(ssl_t *ssl, sslBuf_t *out,
/* ProtocolVersion legacy_version == 0x0303 */
psDynBufAppendByte(&chBuf, TLS_MAJ_VER);
psDynBufAppendByte(&chBuf, TLS_1_2_MIN_VER);
+ ssl->ourHelloVersion = v_tls_1_2;
if (ssl->sec.tls13KsState.generateRandomDone == 0)
{
@@ -2508,4 +2536,6 @@ out_internal_error:
ssl->err = SSL_ALERT_INTERNAL_ERROR;
return MATRIXSSL_ERROR;
}
+
+# endif /* USE_CLIENT_SIDE_SSL */
#endif /* USE_TLS_1_3 */
diff --git a/matrixssl/tls13EncodeExt.c b/matrixssl/tls13EncodeExt.c
index c91c3c0..f0e2f5a 100644
--- a/matrixssl/tls13EncodeExt.c
+++ b/matrixssl/tls13EncodeExt.c
@@ -44,6 +44,7 @@
# warning "DEBUG_TLS_1_3_ENCODE_EXTENSIONS will leak secrets into logs!"
# endif
+# ifdef USE_CLIENT_SIDE_SSL
static int32_t tls13WriteClientSupportedVersions(ssl_t *ssl,
psDynBuf_t *extBuf)
{
@@ -60,10 +61,10 @@ static int32_t tls13WriteClientSupportedVersions(ssl_t *ssl,
psDynBufInit(ssl->hsPool, &workBuf,
TLS_MAX_SUPPORTED_VERSIONS * 2);
- for (i = 0; i < ssl->supportedVersionsLen; i++)
+ for (i = 0; i < ssl->supportedVersionsPriorityLen; i++)
{
- maj = ssl->supportedVersions[i] >> 8;
- min = ssl->supportedVersions[i] & 0xff;
+ maj = psEncodeVersionMaj(ssl->supportedVersionsPriority[i]);
+ min = psEncodeVersionMin(ssl->supportedVersionsPriority[i]);
psDynBufAppendByte(&workBuf, maj);
psDynBufAppendByte(&workBuf, min);
@@ -71,8 +72,8 @@ static int32_t tls13WriteClientSupportedVersions(ssl_t *ssl,
psTracePrintVersionsList(INDENT_HS_MSG,
"supported_versions",
- ssl->supportedVersions,
- ssl->supportedVersionsLen,
+ ssl->supportedVersionsPriority,
+ ssl->supportedVersionsPriorityLen,
PS_FALSE);
extensionData = psDynBufDetach(&workBuf, &extensionDataLen);
@@ -105,6 +106,7 @@ static int32_t tls13WriteClientSupportedVersions(ssl_t *ssl,
return PS_SUCCESS;
}
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
static
int32_t tls13WriteKeyShareEntry(ssl_t *ssl,
psDynBuf_t *sharesBuf,
@@ -199,12 +201,14 @@ int32_t tls13WriteClientKeyShare(ssl_t *ssl, psDynBuf_t *extBuf)
psDynBufAppendOctets(extBuf, extensionType, 2);
+#ifndef USE_ONLY_PSK_CIPHER_SUITE
/* Generate keys. */
rc = tls13GenerateEphemeralKeys(ssl);
if (rc < 0)
{
return rc;
}
+
/* KeyShareEntry client_shares<0..2^16-1>; */
psDynBufInit(ssl->hsPool, &workBuf, 256);
@@ -246,6 +250,7 @@ int32_t tls13WriteClientKeyShare(ssl_t *ssl, psDynBuf_t *extBuf)
extensionData,
extensionDataLen);
psFree(extensionData, ssl->hsPool);
+# endif
return PS_SUCCESS;
}
@@ -272,7 +277,7 @@ static int32_t tls13WriteClientSupportedGroups(ssl_t *ssl, psDynBuf_t *extBuf)
}
extensionData = psDynBufDetach(&workBuf,
- &extensionDataLen);
+ &extensionDataLen);
if (extensionData == NULL)
{
return PS_MEM_FAIL;
@@ -297,6 +302,8 @@ static int32_t tls13WriteClientSupportedGroups(ssl_t *ssl, psDynBuf_t *extBuf)
psFree(extensionData, ssl->hsPool);
return PS_SUCCESS;
}
+# endif /* USE_ONLY_PSK_CIPHER_SUITE */
+# endif /* USE_CLIENT_SIDE_SSL */
int32_t tls13WriteSigAlgs(ssl_t *ssl,
psDynBuf_t *extBuf,
@@ -368,6 +375,7 @@ out_internal_error:
return MATRIXSSL_ERROR;
}
+# ifdef USE_IDENTITY_CERTIFICATES
int32_t tls13WriteCertificateAuthorities(ssl_t *ssl,
psDynBuf_t *extBuf)
{
@@ -387,21 +395,22 @@ int32_t tls13WriteCertificateAuthorities(ssl_t *ssl,
cert = ssl->keys->CAcerts;
if (cert == NULL)
{
-#ifdef SERVER_CAN_SEND_EMPTY_CERT_REQUEST
+# ifdef SERVER_CAN_SEND_EMPTY_CERT_REQUEST
/* Return success even in the case of no CAs in which
case the extension is omitted. This might not be an error
situation in case the cert verification is done by the
application using the callback */
return MATRIXSSL_SUCCESS;
-#else
+# else
psTraceInfo("Failed writing certificate_authorities because no " \
"CA certificates configured. Configure CA certificates or "\
"define SERVER_CAN_SEND_EMPTY_CERT_REQUEST.\n");
return PS_ARG_FAIL;
-#endif
+# endif
}
psDynBufAppendOctets(extBuf, extensionType, 2);
psDynBufInit(ssl->hsPool, &dnBuf, 1024);
+# ifdef USE_CERT_PARSE
while (cert)
{
if (cert->parseStatus == PS_X509_PARSE_SUCCESS)
@@ -413,6 +422,7 @@ int32_t tls13WriteCertificateAuthorities(ssl_t *ssl,
}
cert = cert->next;
}
+# endif
extensionData = psDynBufDetach(&dnBuf, &extensionDataLen);
if (extensionData == NULL)
{
@@ -439,7 +449,7 @@ int32_t tls13WriteCertificateAuthorities(ssl_t *ssl,
psFree(extensionData, ssl->hsPool);
return PS_SUCCESS;
}
-
+# endif /* USE_IDENTITY_CERTIFICATES */
int32_t tls13WriteEarlyData(ssl_t *ssl,
psDynBuf_t *extBuf,
@@ -467,27 +477,26 @@ int32_t tls13WriteEarlyData(ssl_t *ssl,
return PS_SUCCESS;
}
+# ifdef USE_SERVER_SIDE_SSL
static int32_t tls13WriteServerSupportedVersions(ssl_t *ssl,
psDynBuf_t *extBuf)
{
psDynBuf_t verBuf;
unsigned char extensionType[2] = {0x00, EXT_SUPPORTED_VERSIONS};
unsigned char *extensionData;
- unsigned char maj = TLS_MAJ_VER;
+ unsigned char maj, min;
size_t extensionDataLen;
psTracePrintExtensionCreate(ssl, EXT_SUPPORTED_VERSIONS);
psDynBufAppendOctets(extBuf, extensionType, 2);
- /* ProtocolVersion selected_version; */
+ /* ProtocolVersion selected_version; */
psDynBufInit(ssl->hsPool, &verBuf, 2);
- if (ssl->tls13NegotiatedMinorVer > TLS_1_3_MIN_VER)
- {
- maj = TLS_1_3_DRAFT_MAJ_VER;
- }
+ maj = psEncodeVersionMaj(GET_ACTV_VER(ssl));
+ min = psEncodeVersionMin(GET_ACTV_VER(ssl));
psDynBufAppendOctets(&verBuf, &maj, 1);
- psDynBufAppendOctets(&verBuf, &ssl->tls13NegotiatedMinorVer, 1);
+ psDynBufAppendOctets(&verBuf, &min, 1);
/* opaque extensionData<0..2^16-1>; */
extensionData = psDynBufDetach(&verBuf, &extensionDataLen);
@@ -503,6 +512,9 @@ static int32_t tls13WriteServerSupportedVersions(ssl_t *ssl,
return PS_SUCCESS;
}
+# endif /* USE_SERVER_SIDE_SSL */
+
+# ifdef USE_CLIENT_SIDE_SSL
static int32_t tls13WriteExtendedMasterSecret(ssl_t *ssl,
psDynBuf_t *extBuf,
sslSessOpts_t *options)
@@ -550,7 +562,7 @@ static int32_t tls13WriteExtendedMasterSecret(ssl_t *ssl,
return PS_SUCCESS;
}
-# ifdef ENABLE_SECURE_REHANDSHAKES
+# ifdef ENABLE_SECURE_REHANDSHAKES
static int32_t tls13WriteRenegotiationInfo(ssl_t *ssl,
psDynBuf_t *extBuf)
{
@@ -567,8 +579,11 @@ static int32_t tls13WriteRenegotiationInfo(ssl_t *ssl,
return PS_SUCCESS;
}
-# endif /* ENABLE_SECURE_REHANDSHAKES */
+# endif /* ENABLE_SECURE_REHANDSHAKES */
+# endif /* USE_CLIENT_SIDE_SSL */
+# ifdef USE_SERVER_SIDE_SSL
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
static int32_t tls13WriteServerKeyShare(ssl_t *ssl,
psDynBuf_t *extBuf,
psBool_t isHelloRetryRequest)
@@ -584,8 +599,7 @@ static int32_t tls13WriteServerKeyShare(ssl_t *ssl,
int32_t rc;
extensionType[0] = 0x00;
- if (ssl->tls13NegotiatedMinorVer == TLS_1_3_MIN_VER ||
- ssl->tls13NegotiatedMinorVer >= TLS_1_3_DRAFT_23_MIN_VER)
+ if (NGTD_VER(ssl, v_tls_1_3_key_share_51))
{
extensionType[1] = EXT_KEY_SHARE;
}
@@ -637,7 +651,6 @@ static int32_t tls13WriteServerKeyShare(ssl_t *ssl,
if (!isHelloRetryRequest)
{
/* Standard ServerHello --> KeyShareServerHello. */
-
rc = tls13GenerateEphemeralKeys(ssl);
if (rc < 0)
{
@@ -684,6 +697,8 @@ static int32_t tls13WriteServerKeyShare(ssl_t *ssl,
return PS_SUCCESS;
}
+# endif /* USE_ONLY_PSK_CIPHER_SUITE */
+# endif /* USE_SERVER_SIDE_SSL */
static
int32_t tls13WritePskIdentity(ssl_t *ssl,
@@ -959,71 +974,6 @@ out_internal_failure:
return MATRIXSSL_ERROR;
}
-static
-int32_t tls13WritePskKeyExchangeModes(ssl_t *ssl,
- psDynBuf_t *extBuf)
-{
- psDynBuf_t buf, modesBuf;
- unsigned char extensionType[2] = { 0x00, EXT_PSK_KEY_EXCHANGE_MODES };
- unsigned char *modes, *extensionData;
- psSize_t modesLen, extensionDataLen;
- unsigned char psk_ke = 0;
- unsigned char psk_dhe_ke = 1;
-
- psTracePrintExtensionCreate(ssl, EXT_PSK_KEY_EXCHANGE_MODES);
-
- /*
- enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;
-
- struct {
- PskKeyExchangeMode ke_modes<1..255>;
- } PskKeyExchangeModes;
- */
-
- psDynBufAppendOctets(extBuf, extensionType, 2);
-
- psDynBufInit(ssl->hsPool, &buf, 6);
- psDynBufInit(ssl->hsPool, &modesBuf, 4);
-
- /* Always support both psk_dhe_ke and psk_ke. We can always support
- psk_dhe_ke, because we always encode a key_share currently. Caller
- has already ensured that we have a PSK for psk_ke. */
- psDynBufAppendOctets(&modesBuf, &psk_dhe_ke, 1);
- psDynBufAppendOctets(&modesBuf, &psk_ke, 1);
-
- modes = psDynBufDetachPsSize(&modesBuf, &modesLen);
- if (modes == NULL)
- {
- goto out_internal_failure;
- }
- psDynBufUninit(&modesBuf);
-
- /* PskKeyExchangeMode ke_modes<1..255>; */
- psDynBufAppendTlsVector(&buf,
- 1, 255,
- modes,
- modesLen);
- psFree(modes, ssl->hsPool);
-
- /* opaque extensionData<0..2^16-1>; */
- extensionData = psDynBufDetachPsSize(&buf, &extensionDataLen);
- if (extensionData == NULL)
- {
- goto out_internal_failure;
- }
- psDynBufAppendTlsVector(extBuf,
- 0, (1 << 16) - 1,
- extensionData,
- extensionDataLen);
-
- psFree(extensionData, ssl->hsPool);
- psDynBufUninit(&buf);
- return PS_SUCCESS;
-
-out_internal_failure:
- ssl->err = SSL_ALERT_INTERNAL_ERROR;
- return MATRIXSSL_ERROR;
-}
static
int32_t tls13WriteCookie(ssl_t *ssl,
@@ -1106,6 +1056,7 @@ int32_t tls13WriteCookie(ssl_t *ssl,
return PS_SUCCESS;
}
+# ifdef USE_SERVER_SIDE_SSL
/*
Add mandatory extensions to TLS 1.3 ServerHello:
supported_versions, key_share
@@ -1128,13 +1079,13 @@ int32 tls13WriteServerHelloExtensions(ssl_t *ssl,
{
return rc;
}
-
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
rc = tls13WriteServerKeyShare(ssl, extBuf, isHelloRetryRequest);
if (rc < 0)
{
return rc;
}
-
+# endif
if (ssl->sec.tls13UsingPsk)
{
rc = tls13WritePreSharedKey(ssl, extBuf, isHelloRetryRequest);
@@ -1155,6 +1106,74 @@ int32 tls13WriteServerHelloExtensions(ssl_t *ssl,
return PS_SUCCESS;
}
+# endif /* USE_SERVER_SIDE_SSL */
+
+# ifdef USE_CLIENT_SIDE_SSL
+static
+int32_t tls13WritePskKeyExchangeModes(ssl_t *ssl,
+ psDynBuf_t *extBuf)
+{
+ psDynBuf_t buf, modesBuf;
+ unsigned char extensionType[2] = { 0x00, EXT_PSK_KEY_EXCHANGE_MODES };
+ unsigned char *modes, *extensionData;
+ psSize_t modesLen, extensionDataLen;
+ unsigned char psk_ke = 0;
+ unsigned char psk_dhe_ke = 1;
+
+ psTracePrintExtensionCreate(ssl, EXT_PSK_KEY_EXCHANGE_MODES);
+
+ /*
+ enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;
+
+ struct {
+ PskKeyExchangeMode ke_modes<1..255>;
+ } PskKeyExchangeModes;
+ */
+
+ psDynBufAppendOctets(extBuf, extensionType, 2);
+
+ psDynBufInit(ssl->hsPool, &buf, 6);
+ psDynBufInit(ssl->hsPool, &modesBuf, 4);
+
+ /* Always support both psk_dhe_ke and psk_ke. We can always support
+ psk_dhe_ke, because we always encode a key_share currently. Caller
+ has already ensured that we have a PSK for psk_ke. */
+ psDynBufAppendOctets(&modesBuf, &psk_dhe_ke, 1);
+ psDynBufAppendOctets(&modesBuf, &psk_ke, 1);
+
+ modes = psDynBufDetachPsSize(&modesBuf, &modesLen);
+ if (modes == NULL)
+ {
+ goto out_internal_failure;
+ }
+ psDynBufUninit(&modesBuf);
+
+ /* PskKeyExchangeMode ke_modes<1..255>; */
+ psDynBufAppendTlsVector(&buf,
+ 1, 255,
+ modes,
+ modesLen);
+ psFree(modes, ssl->hsPool);
+
+ /* opaque extensionData<0..2^16-1>; */
+ extensionData = psDynBufDetachPsSize(&buf, &extensionDataLen);
+ if (extensionData == NULL)
+ {
+ goto out_internal_failure;
+ }
+ psDynBufAppendTlsVector(extBuf,
+ 0, (1 << 16) - 1,
+ extensionData,
+ extensionDataLen);
+
+ psFree(extensionData, ssl->hsPool);
+ psDynBufUninit(&buf);
+ return PS_SUCCESS;
+
+out_internal_failure:
+ ssl->err = SSL_ALERT_INTERNAL_ERROR;
+ return MATRIXSSL_ERROR;
+}
int32_t tls13WriteUserExtensions(ssl_t *ssl,
psDynBuf_t *extBuf,
@@ -1194,6 +1213,9 @@ int32_t tls13WriteUserExtensions(ssl_t *ssl,
return MATRIXSSL_SUCCESS;
}
+# endif /* USE_CLIENT_SIDE_SSL */
+
+# ifdef USE_OCSP_RESPONSE
int32_t tls13WriteOCSPStatusRequest(ssl_t *ssl,
psDynBuf_t *extBuf)
{
@@ -1244,6 +1266,7 @@ int32_t tls13WriteOCSPStatusRequest(ssl_t *ssl,
if (IS_SERVER(ssl))
{
+# ifdef USE_SERVER_SIDE_SSL
/* Server sends the stored OCSPResponse. */
psAssert(ssl->keys->OCSPResponseBuf
&& ssl->keys->OCSPResponseBufLen > 0);
@@ -1258,6 +1281,7 @@ int32_t tls13WriteOCSPStatusRequest(ssl_t *ssl,
1, (1 << 24) - 1,
ssl->keys->OCSPResponseBuf,
ssl->keys->OCSPResponseBufLen);
+# endif /* ifdef USE_SERVER_SIDE_SSL */
}
else
{
@@ -1286,7 +1310,9 @@ out_internal_error:
ssl->err = SSL_ALERT_INTERNAL_ERROR;
return MATRIXSSL_ERROR;
}
+# endif /* USE_OCSP_RESPONSE */
+# ifdef USE_CLIENT_SIDE_SSL
int32_t tls13WriteClientHelloExtensions(ssl_t *ssl,
psDynBuf_t *extBuf,
tlsExtension_t *userExt,
@@ -1325,7 +1351,7 @@ int32_t tls13WriteClientHelloExtensions(ssl_t *ssl,
{
return rc;
}
-
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
rc = tls13WriteClientSupportedGroups(ssl, extBuf);
if (rc < 0)
{
@@ -1337,7 +1363,7 @@ int32_t tls13WriteClientHelloExtensions(ssl_t *ssl,
{
return rc;
}
-
+# endif /* USE_ONLY_PSK_CIPHER_SUITE */
if (ssl->tls13IncorrectDheKeyShare)
{
if (ssl->sec.tls13CookieFromServer
@@ -1351,6 +1377,7 @@ int32_t tls13WriteClientHelloExtensions(ssl_t *ssl,
}
}
+# if defined(USE_OCSP_RESPONSE) && defined(USE_SERVER_SIDE_SSL)
/*
Add OCSP status request if:
- it was requested in the session options
@@ -1368,7 +1395,7 @@ int32_t tls13WriteClientHelloExtensions(ssl_t *ssl,
}
ssl->extFlags.req_status_request = 1;
}
-
+# endif /* USE_OCSP_RESPONSE */
/* Add user-provided extensions, e.g. server_name (SNI). */
if (ssl->userExt)
{
@@ -1378,7 +1405,6 @@ int32_t tls13WriteClientHelloExtensions(ssl_t *ssl,
return rc;
}
}
-
/*
When offering TLS 1.0, 1.1 or 1.2, add some security-critical
TLS 1.2 extensions.
@@ -1386,9 +1412,7 @@ int32_t tls13WriteClientHelloExtensions(ssl_t *ssl,
Not that some old, incompliant TLS 1.0 implementations
may not be able to parse any extensions.
*/
- if (tlsVersionSupported(ssl, TLS_1_0_MIN_VER)
- || tlsVersionSupported(ssl, TLS_1_1_MIN_VER)
- || tlsVersionSupported(ssl, TLS_1_2_MIN_VER))
+ if (SUPP_VER(ssl, v_tls_legacy))
{
rc = tls13WriteExtendedMasterSecret(ssl, extBuf, options);
if (rc < 0)
@@ -1444,4 +1468,5 @@ int32_t tls13WriteClientHelloExtensions(ssl_t *ssl,
}
return PS_SUCCESS;
}
+# endif /* USE_CLIENT_SIDE_SSL */
#endif
diff --git a/matrixssl/tls13KeyAgree.c b/matrixssl/tls13KeyAgree.c
index 1db9728..197976a 100644
--- a/matrixssl/tls13KeyAgree.c
+++ b/matrixssl/tls13KeyAgree.c
@@ -90,19 +90,19 @@ int32_t tls13LoadDhParams(ssl_t *ssl,
}
# endif /* USE_DH */
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
int32_t tls13ImportPublicValue(ssl_t *ssl,
const unsigned char *keyExchangeData,
psSize_t keyExchangeDataLen,
uint16_t namedGroup)
{
int32_t rc;
- const psEccCurve_t *curve;
if (psIsEcdheGroup(namedGroup))
{
-# ifdef USE_X25519
if (namedGroup == namedgroup_x25519)
{
+# ifdef USE_X25519
if (keyExchangeDataLen != PS_DH_X25519_PUBLIC_KEY_BYTES)
{
ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
@@ -118,49 +118,58 @@ int32_t tls13ImportPublicValue(ssl_t *ssl,
keyExchangeData,
PS_DH_X25519_PUBLIC_KEY_BYTES);
return PS_SUCCESS;
- }
-# endif
-
- rc = getEccParamById(namedGroup, &curve);
- if (rc < 0)
- {
+# else
goto out_internal_error;
+# endif
}
-
- if (ssl->sec.eccKeyPub != NULL)
+ else
{
- psEccClearKey(ssl->sec.eccKeyPub);
- }
+# ifdef USE_ECC
+ const psEccCurve_t *curve;
+ rc = getEccParamById(namedGroup, &curve);
+ if (rc < 0)
+ {
+ goto out_internal_error;
+ }
- rc = psEccNewKey(ssl->hsPool, &ssl->sec.eccKeyPub,
- curve);
- if (rc < 0)
- {
- psTraceErrr("Unable to create new EC key\n");
+ if (ssl->sec.eccKeyPub != NULL)
+ {
+ psEccClearKey(ssl->sec.eccKeyPub);
+ }
+
+ rc = psEccNewKey(ssl->hsPool, &ssl->sec.eccKeyPub, curve);
+ if (rc < 0)
+ {
+ psTraceErrr("Unable to create new EC key\n");
+ goto out_internal_error;
+ }
+
+ rc = psEccX963ImportKey(
+ ssl->hsPool,
+ keyExchangeData,
+ keyExchangeDataLen,
+ ssl->sec.eccKeyPub,
+ curve);
+ if (rc < 0)
+ {
+ psTraceErrr("Could not import peer ECDHE public value\n");
+ goto out_handshake_failure;
+ }
+# ifdef DEBUG_TLS_1_3_KEY_AGREE
+ psTraceIntInfo("Imported ECDHE pub val of length %d\n",
+ keyExchangeDataLen);
+# endif
+# else
goto out_internal_error;
+# endif /* USE_ECC */
}
-
- rc = psEccX963ImportKey(ssl->hsPool,
- keyExchangeData,
- keyExchangeDataLen,
- ssl->sec.eccKeyPub,
- curve);
- if (rc < 0)
- {
- psTraceErrr("Could not import peer ECDHE public value\n");
- goto out_handshake_failure;
- }
-# ifdef DEBUG_TLS_1_3_KEY_AGREE
- psTraceIntInfo("Imported ECDHE pub val of length %d\n",
- keyExchangeDataLen);
-# endif
}
else
{
-# ifndef USE_DH
+# ifndef USE_DH
psTraceInfo("Need USE_DH to be able to import DHE public values\n");
goto out_internal_error;
-# else
+# else
ssl->sec.dhKeyPub = psMalloc(ssl->hsPool,
sizeof(psDhKey_t));
if (ssl->sec.dhKeyPub == NULL)
@@ -176,11 +185,11 @@ int32_t tls13ImportPublicValue(ssl_t *ssl,
psTraceErrr("Could not import peer DHE public value\n");
goto out_handshake_failure;
}
-# ifdef DEBUG_TLS_1_3_KEY_AGREE
+# ifdef DEBUG_TLS_1_3_KEY_AGREE
psTraceIntInfo("Imported DHE pub val of length %d\n",
keyExchangeDataLen);
-# endif
-# endif /* USE_DH */
+# endif
+# endif /* USE_DH */
}
return MATRIXSSL_SUCCESS;
@@ -207,7 +216,7 @@ int32_t tls13ExportPublicValue(ssl_t *ssl,
{
if (namedGroup == namedgroup_x25519)
{
-# ifdef USE_X25519
+# ifdef USE_X25519
pubVal = psMalloc(ssl->hsPool,
PS_DH_X25519_PUBLIC_KEY_BYTES);
if (pubVal == NULL)
@@ -218,12 +227,13 @@ int32_t tls13ExportPublicValue(ssl_t *ssl,
key->key.x25519.pub,
PS_DH_X25519_PUBLIC_KEY_BYTES);
pubValLen = PS_DH_X25519_PUBLIC_KEY_BYTES;
-# else
+# else
goto out_internal_error;
-# endif
+# endif /* USE_X25519 */
}
else
{
+# ifdef USE_ECC
pubValLen = key->key.ecc.curve->size*2 + 1;
pubVal = psMalloc(ssl->hsPool, pubValLen);
if (pubVal == NULL)
@@ -232,26 +242,29 @@ int32_t tls13ExportPublicValue(ssl_t *ssl,
}
rc = psEccX963ExportKey(ssl->hsPool,
- &key->key.ecc,
- pubVal,
- &pubValLen);
+ &key->key.ecc,
+ pubVal,
+ &pubValLen);
if (rc < 0)
{
psFree(pubVal, ssl->hsPool);
goto out_internal_error;
}
-# ifdef DEBUG_TLS_1_3_KEY_AGREE
+# ifdef DEBUG_TLS_1_3_KEY_AGREE
psTraceIntInfo("Exported ECDHE pub val of length %d\n",
pubValLen);
-# endif
+# endif
+# else
+ goto out_internal_error;
+# endif /* USE_ECC */
}
}
else
{
-# ifndef USE_DH
+# ifndef USE_DH
psTraceInfo("Need USE_DH to export DHE pub values\n");
goto out_internal_error;
-# else
+# else
pubValLen = key->key.dh.size;
pubVal = psMalloc(ssl->hsPool, pubValLen);
if (pubVal == NULL)
@@ -268,7 +281,7 @@ int32_t tls13ExportPublicValue(ssl_t *ssl,
psFree(pubVal, ssl->hsPool);
goto out_internal_error;
}
-# endif /* USE_DH */
+# endif /* USE_DH */
}
*out = pubVal;
*outLen = pubValLen;
@@ -280,6 +293,8 @@ out_internal_error:
return MATRIXSSL_ERROR;
}
+
+# ifdef USE_ECC
/** Generate an ECDHE private key given the curve NamedGroup id. */
int32_t tls13GenerateEcdheKey(ssl_t *ssl,
psEccKey_t *key,
@@ -305,7 +320,9 @@ int32_t tls13GenerateEcdheKey(ssl_t *ssl,
}
rc = matrixSslGenEphemeralEcKey(ssl->keys,
- key, curve, pkiData);
+ key,
+ curve,
+ pkiData);
if (rc < 0)
{
return rc;
@@ -316,12 +333,11 @@ int32_t tls13GenerateEcdheKey(ssl_t *ssl,
return PS_SUCCESS;
}
+# endif /* USE_ECC */
static
int32_t tls13GenerateKeyForGroup(ssl_t *ssl, uint16_t namedGroup)
{
- psPubKey_t *key;
- uint8_t keyType;
psSize_t i;
int32_t rc;
@@ -330,7 +346,8 @@ int32_t tls13GenerateKeyForGroup(ssl_t *ssl, uint16_t namedGroup)
# ifdef DEBUG_TLS_1_3_KEY_AGREE
psTracePrintTls13NamedGroup(0,
"Generating key for group",
- namedGroup, PS_TRUE);
+ namedGroup,
+ PS_TRUE);
# endif
/* Find the correct spot. */
@@ -361,6 +378,10 @@ int32_t tls13GenerateKeyForGroup(ssl_t *ssl, uint16_t namedGroup)
/* Generate the ephemeral key pair. */
if (psIsEcdheGroup(namedGroup))
{
+# if defined(USE_ECC) || defined(USE_X25519)
+ psPubKey_t *key;
+ uint8_t keyType;
+
if (namedGroup == namedgroup_x25519)
{
keyType = PS_X25519;
@@ -379,7 +400,7 @@ int32_t tls13GenerateKeyForGroup(ssl_t *ssl, uint16_t namedGroup)
}
key = ssl->sec.tls13KeyAgreeKeys[i];
-# ifdef USE_X25519
+# ifdef USE_X25519
if (namedGroup == namedgroup_x25519)
{
psRes_t res;
@@ -392,7 +413,7 @@ int32_t tls13GenerateKeyForGroup(ssl_t *ssl, uint16_t namedGroup)
}
return PS_SUCCESS;
}
-# endif /* USE_X25519 */
+# endif /* USE_X25519 */
rc = tls13GenerateEcdheKey(ssl,
&key->key.ecc,
@@ -401,6 +422,9 @@ int32_t tls13GenerateKeyForGroup(ssl_t *ssl, uint16_t namedGroup)
{
goto out_internal_error;
}
+# else
+ goto out_internal_error;
+# endif
}
else
{
@@ -447,6 +471,7 @@ out_internal_error:
ssl->err = SSL_ALERT_INTERNAL_ERROR;
return MATRIXSSL_ERROR;
}
+#endif /* USE_ONLY_PSK_CIPHER_SUITE */
/** Return the element with the lowest sum of indexes from the
intersection of two priority-ordered arrays a and b, such that
@@ -458,16 +483,16 @@ out_internal_error:
Precondition: The input arrays must be arranged in priority
order such that the highest-priority item is at index 0.
*/
-int32_t tls13IntersectionPrioritySelect(const uint16_t *a,
+int32_t tls13IntersectionPrioritySelect(const uint32_t *a,
psSize_t aLen,
- const uint16_t *b,
+ const uint32_t *b,
psSize_t bLen,
- const uint16_t *f,
+ const uint32_t *f,
psSize_t fLen,
- uint16_t *selectedElement)
+ uint32_t *selectedElement)
{
- uint16_t sum, minSum;
- uint16_t best;
+ psSize_t sum, minSum;
+ uint32_t best;
psSize_t i, k, l;
psBool_t foundCommon = PS_FALSE;
psBool_t forbidden;
@@ -478,6 +503,7 @@ int32_t tls13IntersectionPrioritySelect(const uint16_t *a,
return PS_ARG_FAIL;
}
+ best = a[0];
minSum = aLen + bLen - 2;
for (i = 0; i < aLen; i++)
@@ -527,6 +553,71 @@ int32_t tls13IntersectionPrioritySelect(const uint16_t *a,
}
}
+/* An uint16_t wrapper for tls13IntersectionPrioritySelect.*/
+int32_t tls13IntersectionPrioritySelectU16(const uint16_t *a,
+ psSize_t aLen,
+ const uint16_t *b,
+ psSize_t bLen,
+ const uint16_t *f,
+ psSize_t fLen,
+ uint16_t *selectedElement)
+{
+ uint32_t selectedElement32 = *selectedElement;
+ uint32_t *a32 = NULL;
+ uint32_t *b32 = NULL;
+ uint32_t *f32 = NULL;
+ int32_t rc = PS_ARG_FAIL;
+ psSize_t i;
+
+ a32 = psMalloc(ssl->hsPool, aLen * sizeof(uint32_t));
+ if (a32 == NULL)
+ {
+ psTraceInfo("Out of mem in tls13NegotiateGroup\n");
+ goto out;
+ }
+ b32 = psMalloc(ssl->hsPool, bLen * sizeof(uint32_t));
+ if (b32 == NULL)
+ {
+ psTraceInfo("Out of mem in tls13NegotiateGroup\n");
+ goto out;
+ }
+ f32 = psMalloc(ssl->hsPool, bLen * sizeof(uint32_t));
+ if (f32 == NULL)
+ {
+ psTraceInfo("Out of mem in tls13NegotiateGroup\n");
+ goto out;
+ }
+ for (i = 0; i < aLen; i++)
+ {
+ a32[i] = a[i];
+ }
+ for (i = 0; i < bLen; i++)
+ {
+ b32[i] = b[i];
+ }
+ for (i = 0; i < fLen; i++)
+ {
+ f32[i] = f[i];
+ }
+
+ rc = tls13IntersectionPrioritySelect(a32,
+ aLen,
+ b32,
+ bLen,
+ f32,
+ fLen,
+ &selectedElement32);
+
+ *selectedElement = selectedElement32;
+
+out:
+ psFree(a32, ssl->hsPool);
+ psFree(b32, ssl->hsPool);
+ psFree(f32, ssl->hsPool);
+
+ return rc;
+}
+
/** Given our and the peer's list of supported groups, negotiate
the group to use, taking into account our and the peer's
priorities. */
@@ -539,7 +630,10 @@ uint16_t tls13NegotiateGroup(ssl_t *ssl,
psAssert(ssl->tls13SupportedGroups[0] != 0);
- rc = tls13IntersectionPrioritySelect(ssl->tls13SupportedGroups,
+ /* Default. If anything goes wrong, use this. */
+ negotiatedGroup = ssl->tls13SupportedGroups[0];
+
+ rc = tls13IntersectionPrioritySelectU16(ssl->tls13SupportedGroups,
ssl->tls13SupportedGroupsLen,
peerList,
peerListLen,
@@ -548,7 +642,7 @@ uint16_t tls13NegotiateGroup(ssl_t *ssl,
&negotiatedGroup);
if (rc == PS_ARG_FAIL)
{
- return ssl->tls13SupportedGroups[0];
+ psTraceInfo("tls13IntersectionPrioritySelect failed\n");
}
return negotiatedGroup;
@@ -583,6 +677,7 @@ int32_t tls13ServerChooseHelloRetryRequestGroup(ssl_t *ssl,
return PS_SUCCESS;
}
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
int32_t tls13GenerateEphemeralKeys(ssl_t *ssl)
{
psSize_t i;
@@ -634,8 +729,10 @@ int32_t tls13GenerateEphemeralKeys(ssl_t *ssl)
return PS_SUCCESS;
}
+# endif
+# ifdef USE_ECC
static inline
int32_t tls13GenSharedSecretNist(ssl_t *ssl,
psPubKey_t *privKey,
@@ -689,6 +786,7 @@ out_internal_error:
return MATRIXSSL_ERROR;
}
+# endif /* USE_ECC */
# ifdef USE_X25519
static inline
int32_t tls13GenSharedSecretX25519(ssl_t *ssl,
@@ -844,43 +942,36 @@ int32_t tls13GenSharedSecret(ssl_t *ssl,
switch (privKey->type)
{
+# ifdef USE_ECC
case PS_ECC:
rc = tls13GenSharedSecretNist(ssl, privKey, &secret, &secretLen);
- if (rc < 0)
- {
- return rc;
- }
break;
- case PS_X25519:
+#endif
# ifdef USE_X25519
+ case PS_X25519:
rc = tls13GenSharedSecretX25519(ssl, privKey, &secret, &secretLen);
- if (rc < 0)
- {
- return rc;
- }
break;
# endif
# ifdef USE_DH
case PS_DH:
rc = tls13GenSharedSecretDh(ssl, privKey, &secret, &secretLen);
- if (rc < 0)
- {
- return rc;
- }
break;
# endif
default:
- return PS_UNSUPPORTED_FAIL;
+ rc = PS_UNSUPPORTED_FAIL;
+ break;
}
+ if (rc == PS_SUCCESS)
+ {
# ifdef DEBUG_TLS_1_3_KEY_AGREE
- psTraceBytes("(EC)DHE shared secret", secret, secretLen);
+ psTraceBytes("(EC)DHE shared secret", secret, secretLen);
# endif
- *out = secret;
- *outLen = secretLen;
-
- return PS_SUCCESS;
+ *out = secret;
+ *outLen = secretLen;
+ }
+ return rc;
}
/** Return the key corresponding to a NamedGroup.
diff --git a/matrixssl/tls13KeySchedule.c b/matrixssl/tls13KeySchedule.c
index fa6ce78..439a650 100644
--- a/matrixssl/tls13KeySchedule.c
+++ b/matrixssl/tls13KeySchedule.c
@@ -389,20 +389,21 @@ int32_t tls13DeriveAppTrafficSecrets(ssl_t *ssl)
unsigned char derivedSecret[MAX_TLS_1_3_HASH_SIZE];
unsigned char zeroKey[MAX_TLS_1_3_HASH_SIZE] = {0};
int32_t hmacAlg = tls13GetCipherHmacAlg(ssl);
- psSize_t secretLen = psGetOutputBlockLength(hmacAlg);
+ psSize_t secretLen;
psSize_t hsSecretLen;
unsigned char zeroByte = 0;
- int32_t rc;
+ int32_t rc = psGetOutputBlockLength(hmacAlg);
if (ssl->sec.tls13KsState.deriveAppTrafficSecretsDone)
{
return PS_SUCCESS;
}
- if (secretLen < 0)
+ if (rc < 0)
{ /* this is an error code */
- return secretLen;
+ return rc;
}
+ secretLen = rc;
/* Derive-Secret(Handshake Secret, "derived", "") */
rc = tls13DeriveSecret(ssl,
@@ -499,13 +500,14 @@ int32_t tls13DeriveAppTrafficSecrets(ssl_t *ssl)
int32_t tls13DeriveResumptionMasterSecret(ssl_t *ssl)
{
int32_t hmacAlg = tls13GetCipherHmacAlg(ssl);
- psSize_t secretLen = psGetOutputBlockLength(hmacAlg);
- int32_t rc;
+ psSize_t secretLen;
+ int32_t rc = psGetOutputBlockLength(hmacAlg);
- if (secretLen < 0)
+ if (rc < 0)
{ /* this is an error code */
- return secretLen;
+ return rc;
}
+ secretLen = rc;
/* Derive-Secret(Master Secret, "res master",
Transcript-Hash(ClientHello...client Finished) ) */
@@ -528,9 +530,9 @@ int32_t tls13DeriveResumptionMasterSecret(ssl_t *ssl)
int32_t tls13DeriveHandshakeKeys(ssl_t *ssl)
{
- int32_t rc;
int32_t hmacAlg = tls13GetCipherHmacAlg(ssl);
- psSize_t secretLen = psGetOutputBlockLength(hmacAlg);
+ int32_t rc = psGetOutputBlockLength(hmacAlg);
+ psSize_t secretLen;
psBool_t isServer = (ssl->flags & SSL_FLAGS_SERVER) ? PS_TRUE : PS_FALSE;
unsigned char *inputSecretRead, *inputSecretWrite;
@@ -539,10 +541,11 @@ int32_t tls13DeriveHandshakeKeys(ssl_t *ssl)
return PS_SUCCESS;
}
- if (secretLen < 0)
+ if (rc < 0)
{ /* this is an error code */
- return secretLen;
+ return rc;
}
+ secretLen = rc;
if (isServer)
{
@@ -761,9 +764,9 @@ int32_t tls13DeriveEarlyDataKeys(ssl_t *ssl)
int32_t tls13DeriveAppKeys(ssl_t *ssl)
{
- int32_t rc;
int32_t hmacAlg = tls13GetCipherHmacAlg(ssl);
- psSize_t secretLen = psGetOutputBlockLength(hmacAlg);
+ int32_t rc = psGetOutputBlockLength(hmacAlg);
+ psSize_t secretLen;
psBool_t isServer = (ssl->flags & SSL_FLAGS_SERVER) ? PS_TRUE : PS_FALSE;
unsigned char *inputSecretRead, *inputSecretWrite;
@@ -772,10 +775,11 @@ int32_t tls13DeriveAppKeys(ssl_t *ssl)
return PS_SUCCESS;
}
- if (secretLen < 0)
+ if (rc < 0)
{ /* this is an error code */
- return secretLen;
+ return rc;
}
+ secretLen = rc;
if (isServer)
{
@@ -883,15 +887,17 @@ int32_t tls13DeriveBinderKey(ssl_t *ssl,
psSize_t *binderKeyOutLen)
{
int32 rc;
- psSize_t secretLen = psGetOutputBlockLength(hmacAlg);
+ psSize_t secretLen;
unsigned char *base_key;
base_key = binderSecret;
- if (secretLen < 0)
+ rc = psGetOutputBlockLength(hmacAlg);
+ if (rc < 0)
{ /* this is an error code */
- return secretLen;
+ return rc;
}
+ secretLen = rc;
/*
finished_key =
@@ -925,9 +931,9 @@ int32_t tls13DeriveBinderKey(ssl_t *ssl,
int32_t tls13DeriveFinishedKey(ssl_t *ssl, psBool_t wantServerKey)
{
- int32 rc;
int32_t hmacAlg = tls13GetCipherHmacAlg(ssl);
- psSize_t secretLen = psGetOutputBlockLength(hmacAlg);
+ int32 rc = psGetOutputBlockLength(hmacAlg);
+ psSize_t secretLen;
unsigned char *base_key;
if (wantServerKey)
@@ -947,10 +953,11 @@ int32_t tls13DeriveFinishedKey(ssl_t *ssl, psBool_t wantServerKey)
base_key = ssl->sec.tls13HsTrafficSecretClient;
}
- if (secretLen < 0)
+ if (rc < 0)
{ /* this is an error code */
- return secretLen;
+ return rc;
}
+ secretLen = rc;
/*
finished_key =
diff --git a/matrixssl/tls13Negotiate.c b/matrixssl/tls13Negotiate.c
index 11877a7..ed81e84 100644
--- a/matrixssl/tls13Negotiate.c
+++ b/matrixssl/tls13Negotiate.c
@@ -35,7 +35,7 @@
#include "matrixsslImpl.h"
#ifdef USE_TLS_1_3
-
+# ifdef USE_IDENTITY_CERTIFICATES
/** This function is called to validate our private key and cert chain
against against the peer's signature_algorithms,
signature_algorithms_cert and supported_groups extensions. */
@@ -66,24 +66,30 @@ int32_t tls13TryNegotiateParams(ssl_t *ssl,
{
continue;
}
+# ifdef USE_RSA
if (givenKey->privKey.type == PS_RSA &&
tls13IsRsaSigAlg(ssl->sec.keySelect.peerSigAlgs[i]))
{
peerCanVerifyCvSig = PS_TRUE;
break;
}
+# endif
+# ifdef USE_ECC
if (givenKey->privKey.type == PS_ECC &&
tls13IsEcdsaSigAlg(ssl->sec.keySelect.peerSigAlgs[i]))
{
peerCanVerifyCvSig = PS_TRUE;
break;
}
+# endif
+# ifdef USE_ED25519
if (givenKey->privKey.type == PS_ED25519 &&
ssl->sec.keySelect.peerSigAlgs[i] == sigalg_ed25519)
{
peerCanVerifyCvSig = PS_TRUE;
break;
}
+# endif
}
if (!peerCanVerifyCvSig)
@@ -103,6 +109,7 @@ int32_t tls13TryNegotiateParams(ssl_t *ssl,
for (i = 0; i < ssl->sec.keySelect.peerSigAlgsLen; i++)
{
+# ifdef USE_CERT_PARSE
if (!Memcmp(cert->subject.hash,
cert->issuer.hash,
SHA1_HASH_SIZE))
@@ -110,14 +117,23 @@ int32_t tls13TryNegotiateParams(ssl_t *ssl,
/* Root cert. Peer doesn't need to verify. */
peerCanVerifyCert = PS_TRUE;
}
+# else
+ if (0)
+ {
+ }
+# endif
+# ifdef USE_RSA
else if (cert->sigAlgorithm == OID_SHA256_RSA_SIG ||
cert->sigAlgorithm == OID_SHA384_RSA_SIG)
{
if (tls13IsRsaSigAlg(ssl->sec.keySelect.peerSigAlgs[i]))
{
peerCanVerifyCert = PS_TRUE;
+
}
}
+# endif
+# ifdef USE_ECC
else if (cert->sigAlgorithm == OID_SHA256_ECDSA_SIG ||
cert->sigAlgorithm == OID_SHA384_ECDSA_SIG)
{
@@ -126,11 +142,14 @@ int32_t tls13TryNegotiateParams(ssl_t *ssl,
peerCanVerifyCert = PS_TRUE;
}
}
+# endif
+# ifdef USE_ED25519
else if (cert->sigAlgorithm == OID_ED25519_KEY_ALG &&
ssl->sec.keySelect.peerSigAlgs[i] == sigalg_ed25519)
{
peerCanVerifyCert = PS_TRUE;
}
+# endif
else
{
if (cert->sigAlgorithm == OID_ED25519_KEY_ALG)
@@ -161,5 +180,5 @@ int32_t tls13TryNegotiateParams(ssl_t *ssl,
return PS_UNSUPPORTED_FAIL;
}
}
-
+# endif
#endif /* USE_TLS_1_3 */
diff --git a/matrixssl/tls13Psk.c b/matrixssl/tls13Psk.c
index f6937f5..77840c6 100644
--- a/matrixssl/tls13Psk.c
+++ b/matrixssl/tls13Psk.c
@@ -246,7 +246,6 @@ int32_t tls13FindSessionPsk(ssl_t *ssl,
psTls13Psk_t **pskOut)
{
psTls13Psk_t *psk;
- psSessionTicketKeys_t *key;
if (idLen <= 0)
{
@@ -266,6 +265,9 @@ int32_t tls13FindSessionPsk(ssl_t *ssl,
*/
if (IS_SERVER(ssl))
{
+# ifdef USE_SERVER_SIDE_SSL
+ psSessionTicketKeys_t *key;
+
if (idLen >= 16 + 12 + 16)
{
key = ssl->keys->sessTickets;
@@ -278,6 +280,7 @@ int32_t tls13FindSessionPsk(ssl_t *ssl,
key = key->next;
}
}
+# endif
}
psk = ssl->sec.tls13SessionPskList;
diff --git a/matrixssl/tls13Resume.c b/matrixssl/tls13Resume.c
index f199915..26e4d97 100644
--- a/matrixssl/tls13Resume.c
+++ b/matrixssl/tls13Resume.c
@@ -47,13 +47,14 @@ int32_t tls13DeriveResumptionPsk(ssl_t *ssl,
unsigned char *pskOut,
psSize_t pskOutLen)
{
- psSize_t secretLen = psGetOutputBlockLength(hmacAlg);
- int32_t rc;
+ psSize_t secretLen;
+ int32_t rc = psGetOutputBlockLength(hmacAlg);
- if (secretLen < 0)
+ if (rc < 0)
{ /* this is an error code */
- return secretLen;
+ return rc;
}
+ secretLen = rc;
if (pskOutLen < secretLen)
{
@@ -90,8 +91,8 @@ void tls13GetCurrSessParams(ssl_t *ssl,
params->sniLen = 0;
params->alpn = NULL;
params->alpnLen = 0;
- params->majVer = TLS_1_3_DRAFT_MAJ_VER;
- params->minVer = ssl->tls13NegotiatedMinorVer;
+ params->majVer = psEncodeVersionMaj(GET_ACTV_VER(ssl));
+ params->minVer = psEncodeVersionMin(GET_ACTV_VER(ssl));
params->cipherId = ssl->cipher->ident;
psGetTime(¶ms->timestamp, ssl->userPtr);
params->maxEarlyData = ssl->tls13SessionMaxEarlyData;
@@ -476,8 +477,10 @@ int32_t tls13ExportState(ssl_t *ssl,
0, (1 << 16) - 1,
psk->params->alpn,
psk->params->alpnLen);
- psDynBufAppendByte(¶msBuf, TLS_1_3_DRAFT_MAJ_VER);
- psDynBufAppendByte(¶msBuf, ssl->tls13NegotiatedMinorVer);
+ psDynBufAppendByte(¶msBuf,
+ psEncodeVersionMaj(ssl->activeVersion));
+ psDynBufAppendByte(¶msBuf,
+ psEncodeVersionMin(ssl->activeVersion));
psDynBufAppendAsBigEndianUint16(¶msBuf, psk->params->cipherId);
psDynBufAppendAsBigEndianUint32(¶msBuf, psk->params->ticketLifetime);
@@ -643,20 +646,20 @@ int32_t tls13ParseMatrixSessionParams(ssl_t *ssl,
int32_t tls13ValidateSessionParams(ssl_t *ssl,
psTls13SessionParams_t *params)
{
- if (params->majVer != TLS_1_3_DRAFT_MAJ_VER)
- {
- psTraceErrr("Decrypted session: major version mismatch\n");
- psTraceIntInfo("Got %u ", params->majVer);
- psTraceIntInfo("Expected: %u\n", TLS_1_3_DRAFT_MAJ_VER);
- goto out_handshake_failure;
- }
+ psProtocolVersion_t ver;
- if (params->minVer != ssl->tls13NegotiatedMinorVer)
+ ver = psVerFromEncodingMajMin(params->majVer, params->minVer);
+ if (ver != VER_GET_RAW(ssl->activeVersion))
{
- psTraceErrr("Decrypted session: major version mismatch\n");
- psTraceIntInfo("Got %u ", params->minVer);
- psTraceIntInfo("Expected: %u\n",
- ssl->tls13NegotiatedMinorVer);
+ psTraceErrr("Decrypted session: version mismatch\n");
+ psTracePrintProtocolVersionNew(INDENT_ERROR,
+ "Got",
+ ver,
+ PS_TRUE);
+ psTracePrintProtocolVersionNew(INDENT_ERROR,
+ "Expected",
+ ssl->activeVersion,
+ PS_TRUE);
goto out_handshake_failure;
}
diff --git a/matrixssl/tls13SigVer.c b/matrixssl/tls13SigVer.c
index 28414b9..622267b 100644
--- a/matrixssl/tls13SigVer.c
+++ b/matrixssl/tls13SigVer.c
@@ -49,6 +49,7 @@
priority.
@param peerSigAlgsLen Number of entries in peerSigAlgs.
*/
+# ifdef USE_IDENTITY_CERTIFICATES
uint16_t tls13ChooseSigAlg(ssl_t *ssl,
const uint16_t *peerSigAlgs,
psSize_t peerSigAlgsLen)
@@ -57,14 +58,15 @@ uint16_t tls13ChooseSigAlg(ssl_t *ssl,
psBool_t foundMatch = PS_FALSE;
uint16_t ourSigAlgs[8] = {0};
psSize_t ourSigAlgsLen;
- uint16_t chosenSigAlg;
+ uint16_t chosenSigAlg = 0;
sslIdentity_t *p;
/* Should only be generating signatures when NOT using a PSK. */
psAssert(ssl->sec.tls13UsingPsk == PS_FALSE);
/* Consider all the configured/present keys. */
- for (p = ssl->keys->identity; p; p = p->next)
+ for (p = ssl->keys->identity; p && !foundMatch; p = p->next)
{
+# ifdef USE_CERT_PARSE
pubKeyAlg = p->cert->pubKeyAlgorithm;
if (pubKeyAlg != OID_ECDSA_KEY_ALG &&
pubKeyAlg != OID_RSA_KEY_ALG &&
@@ -75,6 +77,11 @@ uint16_t tls13ChooseSigAlg(ssl_t *ssl,
pubKeyAlg);
return PS_UNSUPPORTED_FAIL;
}
+# else
+ /* If not having USE_CERT_PARSE, we'll need to have just one
+ IdKey, and that's what we're going to use. */
+ foundMatch = PS_TRUE;
+# endif
/*
MatrixSSL only allows the server to load a single cert chain.
This means that the public key in our cert fully determines:
@@ -89,6 +96,7 @@ uint16_t tls13ChooseSigAlg(ssl_t *ssl,
*/
/* Build our list. */
+# ifdef USE_ECC
if (p->privKey.type == PS_ECC)
{
if (p->privKey.key.ecc.curve->curveId == IANA_SECP256R1)
@@ -112,12 +120,15 @@ uint16_t tls13ChooseSigAlg(ssl_t *ssl,
continue;
}
}
+# endif
+# ifdef USE_RSA
else if (p->privKey.type == PS_RSA)
{
/* The OID restrictions are from section 4.2.3 of the TLS 1.3 draft.
The restrictions apply when the public key is carried in a
certificate. We would not be here unless we are using
a certificate to authenticate ourselves. */
+# ifdef USE_CERT_PARSE
if (p->cert->pubKeyAlgorithm == OID_RSASSA_PSS)
{
/*
@@ -144,19 +155,30 @@ uint16_t tls13ChooseSigAlg(ssl_t *ssl,
"the type of public key in cert\n");
return PS_UNSUPPORTED_FAIL;
}
+# else
+ /* We can do PSS with RSAE, but not the otherway around, so
+ default to PSS when we don't know. */
+ ourSigAlgs[0] = sigalg_rsa_pss_pss_sha256;
+ ourSigAlgs[1] = sigalg_rsa_pss_pss_sha384;
+ ourSigAlgs[2] = sigalg_rsa_pss_pss_sha512;
+ ourSigAlgsLen = 3;
+# endif
}
+# endif
+# ifdef USE_ED25519
else if (p->privKey.type == PS_ED25519)
{
ourSigAlgs[0] = sigalg_ed25519;
ourSigAlgsLen = 1;
}
+# endif
else
{
psTraceInfo("Key type not supported in TLS 1.3\n");
continue;
}
- rc = tls13IntersectionPrioritySelect(ourSigAlgs,
+ rc = tls13IntersectionPrioritySelectU16(ourSigAlgs,
ourSigAlgsLen,
peerSigAlgs,
peerSigAlgsLen,
@@ -241,7 +263,7 @@ int32_t tls13Sign(psPool_t *pool,
psSize_t hashTbsLen = sizeof(hashTbs);
int32_t rc;
int32_t hashSigAlg, sigAlgOid;
- psSignOpts_t opts;
+ psSignOpts_t opts = {0};
psBool_t needPreHash = PS_FALSE;
rc = tls13MakeTbs(pool,
@@ -267,6 +289,7 @@ int32_t tls13Sign(psPool_t *pool,
switch (sigAlg)
{
+# ifdef USE_ECC
case sigalg_ecdsa_secp256r1_sha256:
hashSigAlg = OID_SHA256_ECDSA_SIG;
sigAlgOid = hashSigAlg;
@@ -279,10 +302,14 @@ int32_t tls13Sign(psPool_t *pool,
hashSigAlg = OID_SHA512_ECDSA_SIG;
sigAlgOid = hashSigAlg;
break;
+# endif
+# ifdef USE_ED25519
case sigalg_ed25519:
/* No pre-hashing used with Ed25519. */
sigAlgOid = OID_ED25519_KEY_ALG;
break;
+# endif
+# ifdef USE_RSA
case sigalg_rsa_pss_pss_sha256:
case sigalg_rsa_pss_rsae_sha256:
hashSigAlg = OID_SHA256_RSA_SIG;
@@ -307,6 +334,7 @@ int32_t tls13Sign(psPool_t *pool,
opts.rsaPssSalt = NULL; /* Random salt. */
opts.rsaPssSaltLen = SHA512_HASH_SIZE;
break;
+# endif /* USE_RSA */
default:
psTraceErrr("Unsupported sig alg\n");
rc = PS_UNSUPPORTED_FAIL;
@@ -354,7 +382,6 @@ out_fail:
}
return rc;
}
-
/**
@return PS_SUCCESS when signature was successfully verified;
@@ -399,6 +426,7 @@ int32_t tls13Verify(psPool_t *pool,
/* Translate TLS 1.3 signature algorithm encoding to what
our crypto layer uses. */
+# ifdef USE_ECC
if (sigAlg == sigalg_ecdsa_secp256r1_sha256)
{
cryptoLayerSigAlg = OID_SHA256_ECDSA_SIG;
@@ -414,6 +442,8 @@ int32_t tls13Verify(psPool_t *pool,
cryptoLayerSigAlg = OID_SHA512_ECDSA_SIG;
psAssert(pubKey->key.ecc.curve->curveId == IANA_SECP521R1);
}
+# endif
+# ifdef USE_RSA
else if (sigAlg == sigalg_rsa_pss_pss_sha256 ||
sigAlg == sigalg_rsa_pss_rsae_sha256)
{
@@ -438,11 +468,14 @@ int32_t tls13Verify(psPool_t *pool,
opts.rsaPssSaltLen = SHA512_HASH_SIZE;
opts.useRsaPss = PS_TRUE;
}
+# endif
+#ifdef USE_ED25519
else if (sigAlg == sigalg_ed25519)
{
cryptoLayerSigAlg = OID_ED25519_KEY_ALG;
psAssert(pubKey->type == PS_ED25519);
}
+#endif
else
{
psTraceIntInfo("Unsupported sig alg in tls13Verify: %u\n",
@@ -462,6 +495,7 @@ int32_t tls13Verify(psPool_t *pool,
&opts);
if (rc < 0)
{
+ psFree(tbs, pool);
return rc;
}
psFree(tbs, pool);
@@ -476,6 +510,9 @@ int32_t tls13Verify(psPool_t *pool,
}
}
+# endif /* USE_IDENTITY_CERTIFICATES */
+
+# ifdef USE_RSA
psBool_t tls13IsRsaPssSigAlg(uint16_t alg)
{
switch (alg)
@@ -505,7 +542,7 @@ psBool_t tls13IsRsaSigAlg(uint16_t alg)
return tls13IsRsaPssSigAlg(alg);
}
-
+# endif
psBool_t tls13IsEcdsaSigAlg(uint16_t alg)
{
switch (alg)
@@ -539,16 +576,19 @@ psBool_t tls13RequiresPreHash(uint16_t alg)
{
return PS_FALSE;
}
+
+# ifdef USE_RSA
else if (tls13IsRsaPssSigAlg(alg))
{
-# ifdef USE_CL_RSA
+# ifdef USE_CL_RSA
/* Crypto-cl cannot sign pre-hashed data with PSS.
So we shall sign the original message instead. */
return PS_FALSE;
-# else
+# else
return PS_TRUE;
-# endif /* USE_CL_RSA */
+# endif /* USE_CL_RSA */
}
+# endif /* USE_RSA */
else
{
return PS_TRUE;
diff --git a/matrixssl/tls13TrHash.c b/matrixssl/tls13TrHash.c
index 051d05f..3671bf5 100644
--- a/matrixssl/tls13TrHash.c
+++ b/matrixssl/tls13TrHash.c
@@ -62,7 +62,7 @@ int32_t tls13TranscriptHashInit(ssl_t *ssl)
{
int32_t alg;
- if (ssl->cipher->ident == SSL_NULL_WITH_NULL_NULL)
+ if (ssl->cipher == NULL || ssl->cipher->ident == SSL_NULL_WITH_NULL_NULL)
{
/* When parsing ClientHello, the ciphersuite has not been negotiated
yet, which means that do not know which hash we will end up using.
@@ -174,12 +174,12 @@ int32_t tls13TranscriptHashUpdate(ssl_t *ssl,
In case of server we originally parse ClientHello in the 1.2 side
and later move to 1.3. That's why the hash functions call each other
both ways */
- if (!NEGOTIATED_TLS_1_3(ssl) && !(ssl->flags & SSL_FLAGS_SERVER))
+ if (!NGTD_VER(ssl, v_tls_1_3_any) && !IS_SERVER(ssl))
{
sslUpdateHSHash(ssl, in, len);
}
- if (ssl->cipher->ident == SSL_NULL_WITH_NULL_NULL)
+ if (ssl->cipher == NULL || ssl->cipher->ident == SSL_NULL_WITH_NULL_NULL)
{
/* When parsing ClientHello, the ciphersuite has not been negotiated
yet, which means that do not know which hash we will end up using.
diff --git a/matrixssl/tlsDefaults.c b/matrixssl/tlsDefaults.c
index 869e1aa..2fdb969 100644
--- a/matrixssl/tlsDefaults.c
+++ b/matrixssl/tlsDefaults.c
@@ -120,19 +120,15 @@ static const uint16_t allSigAlgs[] = {
int32 getDefaultSigAlgs(ssl_t *ssl)
{
psSize_t i = 0, j = 0;
- psBool_t tls12Enabled = tlsVersionSupported(ssl, tls_v_1_2);
- psBool_t tls13Enabled = anyTls13VersionSupported(ssl);
-# ifdef USE_DTLS
+ psBool_t tls12Enabled = PS_FALSE;
+ psBool_t tls13Enabled = PS_FALSE;
- /* DTLS 1.2 should use the TLS 1.2 list. */
- if (ssl->flags & SSL_FLAGS_DTLS)
+ /* Note that DTLS 1.2 should use the TLS 1.2 list. */
+ if (SUPP_VER(ssl, v_tls_1_2) || SUPP_VER(ssl, v_dtls_1_2))
{
- if (ssl->minVer == DTLS_1_2_MIN_VER)
- {
- tls12Enabled = PS_TRUE;
- }
+ tls12Enabled = PS_TRUE;
}
-# endif /* USE_DTLS */
+ tls13Enabled = anyTls13VersionSupported(ssl);
if (tls12Enabled && !tls13Enabled)
{
@@ -280,119 +276,25 @@ int32 getDefaultCipherSuites(ssl_t *ssl, psPool_t *pool,
return PS_SUCCESS;
}
-int32 getClientDefaultVersions(ssl_t *ssl)
+extern void addVersion(ssl_t *ssl, psProtocolVersion_t ver);
+
+int32 getDefaultVersions(ssl_t *ssl)
{
-#ifdef USE_TLS_1_3
- uint32_t j;
-#endif
+ uint32_t k;
+ psProtocolVersion_t mask;
-#ifdef USE_TLS
-# ifndef DISABLE_TLS_1_0
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_MIN_VER;
-# endif
-# if defined(USE_TLS_1_1) && !defined(DISABLE_TLS_1_1)
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_1_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_1;
-# endif /* USE_TLS_1_1 */
-# ifdef USE_TLS_1_2
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_2_MIN_VER;
- ssl->flags |= SSL_FLAGS_TLS_1_2 | SSL_FLAGS_TLS_1_1;
-# endif
-# ifdef USE_TLS_1_3
- /* Set TLS1.3 as the highest priority but allow all others
- * as well. For now, add both the RFC and draft 28. */
- ssl->majVer = TLS_MAJ_VER;
- ssl->minVer = TLS_1_2_MIN_VER;
-
- j = 0;
- ssl->supportedVersionsLen = 0;
-
-#define ADD_SUPPORTED_VER(ssl, maj, min) \
- do \
- { \
- ssl->flags |= tlsMinVerToVersionFlag(min); \
- ssl->supportedVersions[j++] = (maj << 8) | min; \
- ssl->supportedVersionsLen++; \
- } while(0)
-
- ADD_SUPPORTED_VER(ssl, TLS_MAJ_VER, TLS_1_3_MIN_VER);
- ADD_SUPPORTED_VER(ssl, TLS_1_3_DRAFT_MAJ_VER, TLS_1_3_DRAFT_28_MIN_VER);
- ADD_SUPPORTED_VER(ssl, TLS_MAJ_VER, TLS_1_2_MIN_VER);
-# if !defined(DISABLE_TLS_1_1)
- ADD_SUPPORTED_VER(ssl, TLS_MAJ_VER, TLS_1_1_MIN_VER);
-# endif
-# if !defined(DISABLE_TLS_1_0)
- ADD_SUPPORTED_VER(ssl, TLS_MAJ_VER, TLS_MIN_VER);
-# endif
-# endif /* USE_TLS_1_3 */
-
- if (ssl->majVer == 0)
+ /* Loop over versions from latest to earliest (priority order). */
+ mask = (1 << 23);
+ for (k = 23; k >= 1; k--)
{
- /* USE_TLS enabled but all DISABLE_TLS versions are enabled so
- use SSLv3. Compile time tests would catch if no versions
- are enabled at all */
- ssl->majVer = SSL3_MAJ_VER;
- ssl->minVer = SSL3_MIN_VER;
- }
- else
- {
- ssl->flags |= SSL_FLAGS_TLS;
+ /* Supported by the build-time config? */
+ if (mask & v_compiled_in)
+ {
+ /* Add it. */
+ addVersion(ssl, mask);
+ }
+ mask >>= 1;
}
-# ifdef USE_DTLS
- /* ssl->flags will have already been set above. Just set version */
- if (ssl->flags & SSL_FLAGS_DTLS)
- {
- ssl->minVer = DTLS_MIN_VER;
- ssl->majVer = DTLS_MAJ_VER;
-# ifdef USE_TLS_1_2
- ssl->minVer = DTLS_1_2_MIN_VER;
-# endif
- }
-# endif /* USE_DTLS */
-
-#else /* USE_TLS */
- ssl->majVer = SSL3_MAJ_VER;
- ssl->minVer = SSL3_MIN_VER;
-#endif /* USE_TLS */
- return MATRIXSSL_SUCCESS;
-}
-
-int32 getServerDefaultVersions(ssl_t *ssl)
-{
- uint32_t j;
- j = 0;
- ssl->supportedVersionsLen = 0;
-#ifdef USE_TLS_1_3
- /* For now, add both the RFC and draft 28.*/
- ssl->supportedVersions[j] = (TLS_MAJ_VER << 8) | TLS_1_3_MIN_VER;
- ssl->supportedVersionsLen++;
- j++;
- ssl->supportedVersions[j] = (TLS_1_3_DRAFT_MAJ_VER << 8) |
- TLS_1_3_DRAFT_28_MIN_VER;
- ssl->supportedVersionsLen++;
- j++;
-#endif
-#ifndef DISABLE_TLS_1_2
- ssl->supportedVersions[j] = (TLS_MAJ_VER << 8) |
- TLS_1_2_MIN_VER;
- ssl->supportedVersionsLen++;
- j++;
-#endif
-#ifndef DISABLE_TLS_1_1
- ssl->supportedVersions[j] = (TLS_MAJ_VER << 8) |
- TLS_1_1_MIN_VER;
- ssl->supportedVersionsLen++;
- j++;
-#endif
-#ifndef DISABLE_TLS_1_0
- ssl->supportedVersions[j] = (TLS_MAJ_VER << 8) |
- TLS_MIN_VER;
- ssl->supportedVersionsLen++;
- j++;
-#endif
return MATRIXSSL_SUCCESS;
}
diff --git a/matrixssl/tlsSigVer.c b/matrixssl/tlsSigVer.c
new file mode 100644
index 0000000..501d428
--- /dev/null
+++ b/matrixssl/tlsSigVer.c
@@ -0,0 +1,1341 @@
+/**
+ * @file tlsSigVer.c
+ * @version $Format:%h%d$
+ *
+ * Functions for signature generation and verification for TLS 1.2
+ * and below.
+ */
+/*
+ * Copyright (c) 2013-2018 INSIDE Secure Corporation
+ * Copyright (c) PeerSec Networks, 2002-2011
+ * All Rights Reserved
+ *
+ * The latest version of this code is available at http://www.matrixssl.org
+ *
+ * This software is open source; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This General Public License does NOT permit incorporating this software
+ * into proprietary programs. If you are unable to comply with the GPL, a
+ * commercial license for this software may be purchased from INSIDE at
+ * http://www.insidesecure.com/
+ *
+ * This program is distributed in WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+/******************************************************************************/
+
+#include "matrixsslImpl.h"
+
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
+
+uint32_t getDefaultSkeHashSize(ssl_t *ssl)
+{
+ uint32_t hashSize;
+
+ hashSize = MD5SHA1_HASH_SIZE; /* Default for (D)TLS <1.2. */
+# ifdef USE_ECC_CIPHER_SUITE
+ if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA)
+ {
+ /* RFC 4492: SHA-1 is the default. */
+ hashSize = SHA1_HASH_SIZE;
+ }
+# endif /* USE_ECC_CIPHER_SUITE */
+
+ return hashSize;
+}
+
+int32_t computeSkeHash(ssl_t *ssl,
+ psDigestContext_t *digestCtx,
+ uint32_t hashSize,
+ const unsigned char *tbsStart, /* Start of ServerParams. */
+ const unsigned char *tbsStop,
+ unsigned char *hsMsgHash)
+{
+ /*
+ In both TLS 1.2 and below, the SKE signature is computed
+ over the hash of:
+ ClientHello.random || ServerHello.random || ServerParams
+
+ Unfortunately, we cannot use psComputeHashForSig, since
+ it only supports single part operation - we would have to
+ concatenate the above data into a single buffer, something
+ which we are not willing to do here.
+ */
+ switch (hashSize)
+ {
+# ifdef USE_MD5SHA1
+ case MD5SHA1_HASH_SIZE:
+ 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, tbsStart,
+ (uint32) (tbsStop - tbsStart));
+ psMd5Sha1Final(&digestCtx->md5sha1, hsMsgHash);
+ break;
+# endif /* USE_MD5SHA1 */
+# ifdef USE_SHA1
+ case 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, tbsStart,
+ (uint32) (tbsStop - tbsStart));
+ psSha1Final(&digestCtx->sha1, hsMsgHash);
+ break;
+# endif /* USE_SHA1 */
+# ifdef USE_TLS_1_2
+ case 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, tbsStart,
+ (uint32) (tbsStop - tbsStart));
+ psSha256Final(&digestCtx->sha256, hsMsgHash);
+ break;
+# ifdef USE_SHA384
+ case 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, tbsStart,
+ (uint32) (tbsStop - tbsStart));
+ psSha384Final(&digestCtx->sha384, hsMsgHash);
+ break;
+# endif /* USE_SHA384 */
+# ifdef USE_SHA512
+ case 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, tbsStart,
+ (uint32) (tbsStop - tbsStart));
+ psSha512Final(&digestCtx->sha512, hsMsgHash);
+ break;
+# endif /* USE_SHA512 */
+# endif /* USE_TLS_1_2 */
+ default:
+ psTraceErrr("Unsupported hash algorithm in SKE\n");
+ psTraceIntInfo("Unsupported hash size: %u\n", hashSize);
+ return PS_UNSUPPORTED_FAIL;
+ }
+
+ return PS_SUCCESS;
+}
+
+static inline
+int32_t chooseSkeSigAlgTls12(ssl_t *ssl, sslIdentity_t *id)
+{
+ int32_t sigAlg;
+
+ sigAlg = chooseSigAlg(id->cert, &id->privKey, ssl->hashSigAlg);
+ if (sigAlg == PS_UNSUPPORTED_FAIL)
+ {
+ psTraceInfo("Unavailable sigAlgorithm for SKE write\n");
+ return PS_UNSUPPORTED_FAIL;
+ }
+ return sigAlg;
+}
+
+static inline
+int32_t chooseSkeSigAlgTls11(ssl_t *ssl, sslIdentity_t *id)
+{
+ if (id->privKey.type == PS_RSA)
+ {
+ return 0; /* MD5SHA1-RSA does not have an OID, so use 0. */
+ }
+ else
+ {
+ /* ECDSA uses SHA-1 by default. */
+ return OID_SHA1_ECDSA_SIG;
+ }
+}
+
+int32_t chooseSkeSigAlg(ssl_t *ssl, sslIdentity_t *id)
+{
+# ifdef USE_TLS_1_2
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
+ {
+ return chooseSkeSigAlgTls12(ssl, id);
+ }
+# endif
+
+ return chooseSkeSigAlgTls11(ssl, id);
+}
+
+/** Prepare for a postponed SKE signing operation.
+
+ @precond The function is only called when the SKE message needs
+ a signature, i.e. only when using non-PSK (EC)DHE ciphersuites.
+*/
+psRes_t tlsPrepareSkeSignature(ssl_t *ssl,
+ int32_t skeSigAlg,
+ unsigned char *tbsStart,
+ unsigned char *c)
+{
+ sslIdentity_t *chosen = ssl->chosenIdentity;
+ unsigned char *orig = c;
+ psDigestContext_t digestCtx;
+ unsigned char *hsMsgHash, *tbsStop;
+ int32_t rc;
+ void *pkiData = ssl->userPtr;
+ pkaAfter_t *pkaAfter;
+ psSize_t hashSize;
+ unsigned char sigAlgId[2];
+ uint16_t pkaType = 0;
+
+ /*
+ ServerDHParams params;
+ digitally-signed struct {
+ opaque client_random[32];
+ opaque server_random[32];
+ ServerDHParams params;
+ } signed_params;
+
+ How we shall encode the signature (a digitally-signed struct):
+ TLS 1.2 and below:
+ struct {
+ SignatureAndHashAlgorithm algorithm;
+ opaque signature<0..2^16-1>;
+ } DigitallySigned;
+ TLS 1.1 and below:
+ opaque vector <0..2^16-1>
+ */
+
+ /* [tbsStart, tbsStop] == signed_params. */
+ tbsStop = c;
+
+ /* Reserve space for the hash of signed_params. */
+ hsMsgHash = psMalloc(ssl->hsPool, SHA512_HASH_SIZE);
+ if (hsMsgHash == NULL)
+ {
+ return PS_MEM_FAIL;
+ }
+
+ hashSize = getDefaultSkeHashSize(ssl);
+
+# ifdef USE_TLS_1_2
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
+ {
+ rc = getSignatureAndHashAlgorithmEncoding(skeSigAlg,
+ &sigAlgId[0],
+ &sigAlgId[1],
+ &hashSize);
+ if (rc < 0)
+ {
+ psFree(hsMsgHash, ssl->hsPool);
+ return rc;
+ }
+ *c++ = sigAlgId[0];
+ *c++ = sigAlgId[1];
+ }
+# endif
+
+ /* Compute the hash. */
+ rc = computeSkeHash(ssl,
+ &digestCtx,
+ hashSize,
+ tbsStart,
+ tbsStop,
+ hsMsgHash);
+ if (rc < 0)
+ {
+ psFree(hsMsgHash, ssl->hsPool);
+ return rc;
+ }
+
+ /* Compute the signature lengths and write the signature length
+ octets. */
+
+#ifdef USE_RSA_CIPHER_SUITE
+ if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA)
+ {
+ /* Signature size == RSA private key modulus size. */
+ *c = (chosen->privKey.keysize & 0xFF00) >> 8; c++;
+ *c = chosen->privKey.keysize & 0xFF; c++;
+
+ pkaType = PKA_AFTER_RSA_SIG_GEN;
+# ifdef USE_TLS_1_2
+ if (NGTD_VER(ssl, v_tls_with_pkcs15_auth))
+ {
+ /* The protocol uses PKCS #1.5 signatures. */
+ pkaType = PKA_AFTER_RSA_SIG_GEN_ELEMENT;
+ }
+# endif /* USE_TLS_1_2 */
+ }
+#endif /* USE_RSA_CIPHER_SUITE */
+
+# ifdef USE_ECC_CIPHER_SUITE
+ if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA)
+ {
+ /*
+ For ECDSA, the signature length octets are written later by
+ psEccDsaSign in nowDoSkePka. Not being consistent is bad. But,
+ because of the "negative ECDSA" case, we do not completely
+ know the signature length in advance.
+ */
+ pkaType = PKA_AFTER_ECDSA_SIG_GEN;
+ }
+# endif /* USE_ECC_CIPHER_SUITE */
+
+# ifdef USE_DTLS
+ if (ACTV_VER(ssl, v_dtls_any) && (ssl->retransmit == 1))
+ {
+ /* It is not optimal to have run through the above digest updates
+ again on a retransmit just to free the hash here but the
+ saved message is ONLY the signature portion done in nowDoSke
+ so the few hashSigAlg bytes and keysize done above during the
+ hash are important to rewrite */
+ psFree(hsMsgHash, ssl->hsPool);
+ Memcpy(c, ssl->ckeMsg, ssl->ckeSize);
+ c += ssl->ckeSize;
+ return (c - orig);
+ }
+# endif /* USE_DTLS */
+
+ pkaAfter = getPkaAfter(ssl);
+ if (pkaAfter == NULL)
+ {
+ psTraceInfo("getPkaAfter error\n");
+ psFree(hsMsgHash, ssl->hsPool);
+ return PS_PLATFORM_FAIL;
+ }
+ pkaAfter->inbuf = hsMsgHash;
+ pkaAfter->outbuf = c;
+ pkaAfter->data = pkiData;
+ pkaAfter->inlen = hashSize;
+ pkaAfter->type = pkaType;
+
+ /* Advance write pointer by the predicted size of the signature. */
+
+# ifdef USE_RSA_CIPHER_SUITE
+ if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA)
+ {
+ c += chosen->privKey.keysize;
+ }
+# endif
+
+# ifdef USE_ECC_CIPHER_SUITE
+ if (ssl->flags & SSL_FLAGS_DHE_WITH_DSA)
+ {
+ rc = chosen->privKey.keysize + 8;
+ /* NEGATIVE ECDSA - Adding spot for ONE 0x0 byte in ECDSA so we'll
+ be right 50% of the time... 521 curve doesn't need */
+ if (chosen->privKey.keysize != 132)
+ {
+ rc += 1;
+ }
+ /* Above we added in the 8 bytes of overhead (2 sigLen, 1 SEQ,
+ 1 len (possibly 2!), 1 INT, 1 rLen, 1 INT, 1 sLen) and now
+ subtract the first 3 bytes to see if the 1 len needs to be 2 */
+ if (rc - 3 >= 128)
+ {
+ rc++;
+ }
+ pkaAfter->user = rc; /* outlen for later */
+ c += rc;
+ }
+# endif
+
+ /* Return the predicted size of the digitally-signed struct. */
+ return (c - orig);
+}
+
+static
+psPool_t *getTmpPkiPool(ssl_t *ssl, pkaAfter_t *pka)
+{
+ return NULL;
+}
+
+psRes_t tlsMakeSkeSignature(ssl_t *ssl,
+ pkaAfter_t *pka,
+ psBuf_t *out)
+{
+ int32_t rc;
+ psPool_t *pkiPool = getTmpPkiPool(ssl, pka);
+ int32_t sigAlg = OID_RSA_TLS_SIG_ALG;
+ sslIdentity_t *chosen = ssl->chosenIdentity;
+ psPubKey_t *privKey = &chosen->privKey;
+ unsigned char *sigBuf = pka->outbuf;
+ psSize_t sigLen;
+ psSignOpts_t opts = {0};
+ /* New temp location for ECDSA sig which can be one len byte different
+ than what we originally calculated (pka->user is holding) */
+ unsigned char *tmpEcdsa = NULL;
+
+ /* Prepare for the call to psSign. */
+ switch (pka->type)
+ {
+# ifdef USE_RSA_CIPHER_SUITE
+ case PKA_AFTER_RSA_SIG_GEN_ELEMENT:
+ sigAlg = OID_RSA_PKCS15_SIG_ALG;
+ sigLen = privKey->keysize;
+ break;
+
+ case PKA_AFTER_RSA_SIG_GEN:
+ sigAlg = OID_RSA_TLS_SIG_ALG;
+ sigLen = privKey->keysize;
+ break;
+# endif /* USE_RSA_CIPHER_SUITE */
+
+# ifdef USE_ECC_CIPHER_SUITE
+ case PKA_AFTER_ECDSA_SIG_GEN:
+ sigAlg = OID_ECDSA_TLS_SIG_ALG;
+ /* pka->user is the predicted ECDSA signature size. We predicted
+ that one of the INTEGERs has a leading 0x00 octet, but there
+ may actually be 0 to 2 extra octets. So allocate 1 larger
+ than predicted. */
+ tmpEcdsa = psMalloc(ssl->hsPool, pka->user + 1);
+ if (tmpEcdsa == NULL)
+ {
+ return PS_MEM_FAIL;
+ }
+# ifdef USE_DTLS
+ ssl->ecdsaSizeChange = 0;
+# endif
+ sigBuf = tmpEcdsa;
+ /* We did not write the signature vector length octets earlier,
+ because we cannot completely predict the signature legnth.
+ Let psSign do this. */
+ opts.flags |= PS_SIGN_OPTS_ECDSA_INCLUDE_SIZE;
+ break;
+# endif /* USE_ECC_CIPHER_SUITE */
+
+ default:
+ psTraceErrr("Unsupported type of PKA operation\n");
+ return PS_UNSUPPORTED_FAIL;
+ }
+ opts.userData = pka->data;
+ opts.flags |= PS_SIGN_OPTS_USE_PREALLOCATED_OUTBUF;
+
+ /* Compute the signature. */
+ rc = psSignHash(pkiPool,
+ privKey,
+ sigAlg,
+ pka->inbuf,
+ pka->inlen,
+ &sigBuf,
+ &sigLen,
+ &opts);
+ if (rc == PS_PENDING)
+ {
+ /* Async operation launched, but not complete. */
+ /* If the result is going directly inline to the output
+ buffer we unflag 'type' so this function isn't called
+ again on the way back around. Also, we can safely
+ free inbuf because it has been copied out */
+ psFree(pka->inbuf, ssl->hsPool); pka->inbuf = NULL;
+ pka->type = 0;
+ psFree(tmpEcdsa, ssl->hsPool);
+ return rc;
+ }
+ else if (rc < 0)
+ {
+ psFree(tmpEcdsa, ssl->hsPool);
+ psTraceErrr("SKE signature generation failed\n");
+ psTraceIntInfo("Signature return code: %d\n", rc);
+ return MATRIXSSL_ERROR;
+ }
+
+ /* Signature is ready, either in tmpEcdsa or in pka->outbuf. */
+
+ /* If the signature size is different than predicted, we need to
+ tweak the previously encoded flight to account for this.
+ This is a huge mess, but cannot be avoided with the current
+ approach, where the entire flight is encoded before public
+ key operations are used to fill the signature spots. */
+# ifdef USE_ECC_CIPHER_SUITE
+ if (pka->type == PKA_AFTER_ECDSA_SIG_GEN)
+ {
+ if (sigLen != pka->user)
+ {
+ /* Confirmed ECDSA is not default size */
+ psTraceInfo("Need accountForEcdsaSizeChange\n");
+ rc = accountForEcdsaSizeChange(ssl,
+ pka,
+ sigLen,
+ tmpEcdsa,
+ out,
+ SSL_HS_SERVER_KEY_EXCHANGE);
+ if (rc < 0)
+ {
+ clearPkaAfter(ssl);
+ psFree(tmpEcdsa, ssl->hsPool);
+ return MATRIXSSL_ERROR;
+ }
+ }
+ else
+ {
+ Memcpy(pka->outbuf, tmpEcdsa, pka->user);
+ }
+ psFree(tmpEcdsa, ssl->hsPool);
+ }
+# endif /* USE_ECC_CIPHER_SUITE */
+
+ /* Store the signature in case of a message retransmit in DTLS. */
+# ifdef USE_DTLS
+ if ((ssl->flags & SSL_FLAGS_DTLS) && (ssl->retransmit == 0))
+ {
+ /* Using existing ckeMsg and ckeSize that clients are using but
+ this should be totally fine on the server side because it is
+ freed at FINISHED parse */
+ ssl->ckeSize = sigLen;
+ ssl->ckeMsg = psMalloc(ssl->hsPool, ssl->ckeSize);
+ if (ssl->ckeMsg == NULL)
+ {
+ psTraceInfo("Memory allocation error ckeMsg\n");
+ return PS_MEM_FAIL;
+ }
+ Memcpy(ssl->ckeMsg, pka->outbuf, ssl->ckeSize);
+ }
+# endif /* USE_DTLS */
+
+ clearPkaAfter(ssl);
+
+ return rc;
+}
+
+psBool_t tlsIsSupportedRsaSigAlg(int32_t alg)
+{
+ switch (alg)
+ {
+ case OID_RSA_TLS_SIG_ALG:
+ case sigalg_rsa_pkcs1_sha1:
+ case sigalg_rsa_pkcs1_sha256:
+ case sigalg_rsa_pkcs1_sha384:
+ case sigalg_rsa_pkcs1_sha512:
+ return PS_TRUE;
+ default:
+ return PS_FALSE;
+ }
+
+ return PS_FALSE;
+}
+
+psBool_t tlsIsSupportedEcdsaSigAlg(int32_t alg)
+{
+ switch (alg)
+ {
+ case OID_ECDSA_TLS_SIG_ALG:
+ case sigalg_ecdsa_sha1:
+ case sigalg_ecdsa_secp256r1_sha256:
+ case sigalg_ecdsa_secp384r1_sha384:
+ case sigalg_ecdsa_secp521r1_sha512:
+ return PS_TRUE;
+ default:
+ return PS_FALSE;
+ }
+}
+
+psSize_t tlsSigAlgToHashLen(uint16_t alg)
+{
+ /* Note: We are in TLS 1.2 context here. The sigalg_* names below
+ are from TLS 1.3, but they are compatible with the TLS 1.2
+ ones. Only difference is that the TLS 1.2 ECDSA sig algs
+ do not specify the curve. So sigalg_ecdsa_secp256r1_sha256
+ just means ECDSA-SHA256 here, for example. */
+ switch (alg)
+ {
+ case sigalg_rsa_pkcs1_sha1:
+ case sigalg_ecdsa_sha1:
+ return SHA1_HASH_SIZE;
+ case sigalg_rsa_pkcs1_sha256:
+ case sigalg_ecdsa_secp256r1_sha256:
+ return SHA256_HASH_SIZE;
+ case sigalg_rsa_pkcs1_sha384:
+ case sigalg_ecdsa_secp384r1_sha384:
+ return SHA384_HASH_SIZE;
+ case sigalg_rsa_pkcs1_sha512:
+ case sigalg_ecdsa_secp521r1_sha512:
+ return SHA512_HASH_SIZE;
+ default:
+ return PS_UNSUPPORTED_FAIL;
+ }
+}
+
+int32_t tlsSigAlgToMatrix(uint16_t alg)
+{
+ switch (alg)
+ {
+ case sigalg_rsa_pkcs1_sha1:
+ return OID_SHA1_RSA_SIG;
+ case sigalg_rsa_pkcs1_sha256:
+ return OID_SHA256_RSA_SIG;
+ case sigalg_rsa_pkcs1_sha384:
+ return OID_SHA384_RSA_SIG;
+ case sigalg_rsa_pkcs1_sha512:
+ return OID_SHA512_RSA_SIG;
+ case sigalg_ecdsa_sha1:
+ return OID_SHA1_ECDSA_SIG;
+ case sigalg_ecdsa_secp256r1_sha256:
+ return OID_SHA256_ECDSA_SIG;
+ case sigalg_ecdsa_secp384r1_sha384:
+ return OID_SHA384_ECDSA_SIG;
+ case sigalg_ecdsa_secp521r1_sha512:
+ return OID_SHA512_ECDSA_SIG;
+ default:
+ return PS_UNSUPPORTED_FAIL;
+ }
+}
+
+int32_t tlsVerify(ssl_t *ssl,
+ const unsigned char *tbs,
+ psSizeL_t tbsLen,
+ const unsigned char *c,
+ const unsigned char *end,
+ psPubKey_t *pubKey,
+ psVerifyOptions_t *opts)
+{
+ int32_t rc;
+ uint16_t sigAlgTls = 0;
+ int32_t matrixSigAlg;
+ psSize_t sigLen;
+ psDigestContext_t digestCtx;
+ psResSize_t hashLen = 0;
+ unsigned char hashBuf[SHA512_HASH_SIZE];
+ psVerifyOptions_t defaultOpts = {0};
+ psBool_t verifyResult;
+ const unsigned char *orig_c = c;
+ psBool_t useRsa = PS_FALSE;;
+
+ if (opts == NULL)
+ {
+ opts = &defaultOpts;
+ }
+ if (ssl->flags & SSL_FLAGS_DHE_WITH_RSA)
+ {
+ useRsa = PS_TRUE; /* Default for TLS 1.1 and below. */
+ }
+
+ /*
+ (D)TLS 1.2:
+ struct {
+ SignatureAndHashAlgorithm algorithm;
+ opaque signature<0..2^16-1>;
+ } DigitallySigned;
+
+ TLS 1.1 and below:
+ opaque vector <0..2^16-1>
+ */
+
+# ifdef USE_TLS_1_2
+ if (NGTD_VER(ssl, v_tls_with_signature_algorithms))
+ {
+ if (end - c < 2)
+ {
+ goto out_decode_error;
+ }
+ sigAlgTls = *c << 8; c++;
+ sigAlgTls += *c; c++;
+ if (tlsIsSupportedRsaSigAlg(sigAlgTls))
+ {
+ useRsa = PS_TRUE;
+ }
+ /* Note: this a TLS sig alg ID. */
+ hashLen = tlsSigAlgToHashLen(sigAlgTls);
+ if (hashLen <= 0)
+ {
+ goto out_decode_error;
+ }
+ }
+# endif /* USE_TLS_1_2 */
+
+ /* Sig alg must match the ciphersuite auth alg. */
+ if (!useRsa && (ssl->flags & SSL_FLAGS_DHE_WITH_RSA))
+ {
+ psTraceErrr("Peer used RSA signature for non-RSA suite\n");
+ goto out_decode_error;
+ }
+ if (useRsa && (ssl->flags & SSL_FLAGS_DHE_WITH_DSA))
+ {
+ psTraceErrr("Peer used ECDSA signature for non-ECDSA suite\n");
+ goto out_decode_error;
+ }
+
+
+# ifdef USE_SEC_CONFIG
+ /* Ask the security callback whether the verify operation
+ with this sig alg and key is allowed. */
+ {
+ psSecOperation_t secOp;
+ psSizeL_t secOpBits;
+
+ if (useRsa)
+ {
+ secOp = secop_rsa_verify;
+ secOpBits = pubKey->keysize * 8;
+ }
+ else
+ {
+ secOp = secop_ecdsa_verify;
+ secOpBits = pubKey->key.ecc.curve->size * 8;
+ }
+
+ rc = matrixSslCallSecurityCallback(ssl, secOp, secOpBits, NULL);
+ if (rc < 0)
+ {
+ psTraceErrr("Operation forbidden by security callback\n");
+ ssl->err = SSL_ALERT_INSUFFICIENT_SECURITY;
+ return rc;
+ }
+ }
+# endif /* USE_SEC_CONFIG */
+
+ /* Parse signature vector length. */
+ if (end - c < 2)
+ {
+ psTraceErrr("Could not decode TLS signature\n");
+ goto out_decode_error;
+ }
+ sigLen = *c << 8; c++;
+ sigLen |= *c; c++;
+
+ /* Sanity check. */
+ if (sigLen > (end - c))
+ {
+ psTraceErrr("Sig len sanity check failed\n");
+ goto out_decode_error;
+ }
+
+ /* Now compute the reference hash. */
+
+ if (hashLen == 0)
+ {
+ hashLen = getDefaultSkeHashSize(ssl);
+ }
+ rc = computeSkeHash(ssl,
+ &digestCtx,
+ hashLen,
+ tbs,
+ tbs + tbsLen,
+ hashBuf);
+ if (rc < 0)
+ {
+ goto out_illegal_parameter;
+ }
+
+ /* Now verify the signature. */
+
+ if (NGTD_VER(ssl, v_tls_with_pkcs15_auth))
+ {
+ opts->msgIsDigestInfo = PS_TRUE;
+ }
+ if (sigAlgTls == 0)
+ {
+ matrixSigAlg = useRsa ? OID_RSA_TLS_SIG_ALG : OID_SHA1_ECDSA_SIG;
+ }
+ else
+ {
+ matrixSigAlg = tlsSigAlgToMatrix(sigAlgTls);
+ }
+
+ rc = psVerifySig(ssl->hsPool,
+ hashBuf,
+ hashLen,
+ c,
+ sigLen,
+ pubKey,
+ matrixSigAlg,
+ &verifyResult,
+ opts);
+ if (rc < 0 || verifyResult != PS_TRUE)
+ {
+ psTraceErrr("Can't verify serverKeyExchange sig\n");
+ goto out_decrypt_error;
+ }
+
+ c += sigLen;
+
+ psAssert(c > orig_c);
+ psAssert(c <= end);
+
+ return (c - orig_c);
+
+out_illegal_parameter:
+ ssl->err = SSL_ALERT_ILLEGAL_PARAMETER;
+ return MATRIXSSL_ERROR;
+out_decode_error:
+ ssl->err = SSL_ALERT_DECODE_ERROR;
+ return MATRIXSSL_ERROR;
+out_decrypt_error:
+ ssl->err = SSL_ALERT_DECRYPT_ERROR;
+ return MATRIXSSL_ERROR;
+}
+
+#if defined(USE_SERVER_SIDE_SSL) || defined(USE_CLIENT_AUTH)
+
+/**
+ Return PS_TRUE if sigAlg is in peerSigAlgs, PS_FALSE otherwise.
+
+ peerSigAlgs should be the a set of masks we created after
+ parsing the peer's supported_signature_algorithms list
+ in ClientHello or CertificateRequest.
+*/
+psBool_t peerSupportsSigAlg(int32_t sigAlg,
+ uint16_t peerSigAlgs
+ /* , psSize_t peerSigAlgsLen) */
+ )
+{
+ uint16_t yes;
+
+ if (sigAlg == OID_MD5_RSA_SIG)
+ {
+ yes = ((peerSigAlgs & HASH_SIG_MD5_RSA_MASK) != 0);
+ }
+ else if (sigAlg == OID_SHA1_RSA_SIG)
+ {
+ yes = ((peerSigAlgs & HASH_SIG_SHA1_RSA_MASK) != 0);
+ }
+ else if (sigAlg == OID_SHA256_RSA_SIG)
+ {
+ yes = ((peerSigAlgs & HASH_SIG_SHA256_RSA_MASK) != 0);
+ }
+ else if (sigAlg == OID_SHA384_RSA_SIG)
+ {
+ yes = ((peerSigAlgs & HASH_SIG_SHA384_RSA_MASK) != 0);
+ }
+ else if (sigAlg == OID_SHA512_RSA_SIG)
+ {
+ yes = ((peerSigAlgs & HASH_SIG_SHA512_RSA_MASK) != 0);
+ }
+ else if (sigAlg == OID_SHA1_ECDSA_SIG)
+ {
+ yes = ((peerSigAlgs & HASH_SIG_SHA1_ECDSA_MASK) != 0);
+ }
+ else if (sigAlg == OID_SHA256_ECDSA_SIG)
+ {
+ yes = ((peerSigAlgs & HASH_SIG_SHA256_ECDSA_MASK) != 0);
+ }
+ else if (sigAlg == OID_SHA384_ECDSA_SIG)
+ {
+ yes = ((peerSigAlgs & HASH_SIG_SHA384_ECDSA_MASK) != 0);
+ }
+ else if (sigAlg == OID_SHA512_ECDSA_SIG)
+ {
+ yes = ((peerSigAlgs & HASH_SIG_SHA512_ECDSA_MASK) != 0);
+ }
+ else
+ {
+ return PS_FALSE; /* Unknown/unsupported sig alg. */
+ }
+
+ if (yes)
+ {
+ return PS_TRUE;
+ }
+ else
+ {
+ return PS_FALSE;
+ }
+}
+
+/**
+ Return PS_TRUE when we support sigAlg for signature generation,
+ PS_FALSE otherwise.
+
+ Compile-time switches as well as FIPS or non-FIPS mode is taken
+ into account.
+
+ @param[in] sigAlg The signature algorithm whose support is to
+ be checked.
+ @param[in] pubKeyAlgorithm The public key algorithm of our
+ private/public key pair (OID_RSA_KEY_ALG or OID_ECDSA_KEY_ALG.)
+*/
+psBool_t weSupportSigAlg(int32_t sigAlg,
+ int32_t pubKeyAlgorithm)
+{
+ uint16_t we_support = 0;
+ uint16_t is_non_fips = 0; /* 1 if not allowed in FIPS mode for
+ signature generation. */
+
+ PS_VARIABLE_SET_BUT_UNUSED(is_non_fips);
+
+#ifndef USE_RSA
+ if (pubKeyAlgorithm == OID_RSA_KEY_ALG)
+ {
+ return PS_FALSE;
+ }
+#endif
+#ifndef USE_ECC
+ if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
+ {
+ return PS_FALSE;
+ }
+#endif
+
+ if (pubKeyAlgorithm == OID_RSA_KEY_ALG)
+ {
+ if (sigAlg == OID_MD2_RSA_SIG || sigAlg == OID_MD5_RSA_SIG)
+ {
+ /* No support for generating RSA-MD2 or RSA-MD5 signatures. */
+ is_non_fips = 1;
+ we_support = 0;
+ }
+ else if (sigAlg == OID_SHA1_RSA_SIG)
+ {
+ is_non_fips = 1;
+#ifdef USE_SHA1
+ we_support = 1;
+#endif
+ }
+ else if (sigAlg == OID_SHA256_RSA_SIG)
+ {
+#ifdef USE_SHA256
+ we_support = 1;
+#endif
+ }
+ else if (sigAlg == OID_SHA384_RSA_SIG)
+ {
+#ifdef USE_SHA384
+ we_support = 1;
+#endif
+ }
+ else if (sigAlg == OID_SHA512_RSA_SIG)
+ {
+#ifdef USE_SHA512
+ we_support = 1;
+#endif
+ }
+ else
+ {
+ /* Our key does not support this algorithm. */
+ return PS_FALSE;
+ }
+ }
+ else if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
+ {
+ if (sigAlg == OID_SHA1_ECDSA_SIG)
+ {
+#ifdef USE_SHA1
+ we_support = 1;
+#endif
+ }
+ else if (sigAlg == OID_SHA256_ECDSA_SIG)
+ {
+#ifdef USE_SHA256
+ we_support = 1;
+#endif
+ }
+ else if (sigAlg == OID_SHA384_ECDSA_SIG)
+ {
+#ifdef USE_SHA384
+ we_support = 1;
+#endif
+ }
+ else if (sigAlg == OID_SHA512_ECDSA_SIG)
+ {
+#ifdef USE_SHA512
+ we_support = 1;
+#endif
+ }
+ else
+ {
+ /* Our key does not support this algorithm. */
+ return PS_FALSE;
+ }
+ }
+ else
+ {
+ return PS_FALSE; /* Unsupported public key alg, e.g. DSA. */
+ }
+
+ /* The basic capability is there. Now do some further checks
+ if needed. */
+
+ if (we_support)
+ {
+ return PS_TRUE;
+ }
+ else
+ {
+ return PS_FALSE;
+ }
+}
+
+/** Return PS_TRUE when:
+ - We support sigAlg for signature generation.
+ - sigAlg is in peerSigAlgs.
+
+ @param[in] sigAlg The signature algorithm whose support to check.
+ @param[in] pubKeyAlgorithm The public key algorithm of our key.
+ @param[in] peerSigAlgs The masks of the sigAlgs supported by the
+ peer. This should be the one parsed from the peer's
+ supported_signature_algorithms list in CertificateVerify or
+ CertificateRequest. In this case, sigAlg \in peerSigAlgs
+ means that the peer supports sigAlg for signature verification.
+*/
+psBool_t canUseSigAlg(int32_t sigAlg,
+ int32_t pubKeyAlgorithm,
+ uint16_t peerSigAlgs)
+{
+ return (weSupportSigAlg(sigAlg, pubKeyAlgorithm) &&
+ peerSupportsSigAlg(sigAlg, peerSigAlgs));
+}
+
+/**
+ Upgrade to a more secure signature algorithm. If the algorithm
+ is already the strongest possible for the key type (i.e.
+ RSA-SHA-512 or ECDSA-SHA-512) change to the most popular
+ one (i.e. RSA-SHA-256 or ECDSA-SHA-256).
+*/
+int32_t upgradeSigAlg(int32_t sigAlg, int32_t pubKeyAlgorithm)
+{
+ /*
+ RSA:
+ MD2 -> SHA256
+ MD5 -> SHA256
+ SHA1 -> SHA256
+ SHA256 -> SHA384
+ SHA384 -> SHA512
+ SHA512 -> SHA256
+ */
+ if (pubKeyAlgorithm == OID_RSA_KEY_ALG)
+ {
+ if (sigAlg == OID_MD2_RSA_SIG ||
+ sigAlg == OID_MD5_RSA_SIG ||
+ sigAlg == OID_SHA1_RSA_SIG)
+ {
+ return OID_SHA256_RSA_SIG;
+ }
+ else if (sigAlg == OID_SHA256_RSA_SIG)
+ {
+ return OID_SHA384_RSA_SIG;
+ }
+ else if (sigAlg == OID_SHA384_RSA_SIG)
+ {
+ return OID_SHA512_RSA_SIG;
+ }
+ else if (sigAlg == OID_SHA512_RSA_SIG)
+ {
+ return OID_SHA256_RSA_SIG;
+ }
+ else
+ {
+ return PS_UNSUPPORTED_FAIL;
+ }
+ }
+ /*
+ ECDSA:
+ SHA1 -> SHA256
+ SHA256 -> SHA384
+ SHA384 -> SHA512
+ SHA512 -> SHA256
+ */
+ else if (pubKeyAlgorithm == OID_ECDSA_KEY_ALG)
+ {
+ if (sigAlg == OID_SHA1_ECDSA_SIG)
+ {
+ return OID_SHA256_ECDSA_SIG;
+ }
+ else if (sigAlg == OID_SHA256_ECDSA_SIG)
+ {
+ return OID_SHA384_ECDSA_SIG;
+ }
+ else if (sigAlg == OID_SHA384_ECDSA_SIG)
+ {
+ return OID_SHA512_ECDSA_SIG;
+ }
+ else if (sigAlg == OID_SHA512_ECDSA_SIG)
+ {
+ return OID_SHA256_ECDSA_SIG;
+ }
+ else
+ {
+ return PS_UNSUPPORTED_FAIL;
+ }
+ }
+ else
+ {
+ return PS_UNSUPPORTED_FAIL;
+ }
+}
+
+static
+int32_t sigAlgRsaToEcdsa(int32_t sigAlg)
+{
+ if (sigAlg == OID_SHA1_RSA_SIG)
+ {
+ return OID_SHA1_ECDSA_SIG;
+ }
+ if (sigAlg == OID_SHA256_RSA_SIG)
+ {
+ return OID_SHA256_ECDSA_SIG;
+ }
+ if (sigAlg == OID_SHA384_RSA_SIG)
+ {
+ return OID_SHA384_ECDSA_SIG;
+ }
+ if (sigAlg == OID_SHA512_RSA_SIG)
+ {
+ return OID_SHA512_ECDSA_SIG;
+ }
+ else
+ {
+ return OID_SHA256_ECDSA_SIG;
+ }
+}
+
+static
+int32_t ecdsaToRsa(int32_t sigAlg)
+{
+ if (sigAlg == OID_SHA1_ECDSA_SIG)
+ {
+ return OID_SHA1_RSA_SIG;
+ }
+ if (sigAlg == OID_SHA256_ECDSA_SIG)
+ {
+ return OID_SHA256_RSA_SIG;
+ }
+ if (sigAlg == OID_SHA384_ECDSA_SIG)
+ {
+ return OID_SHA384_RSA_SIG;
+ }
+ if (sigAlg == OID_SHA512_ECDSA_SIG)
+ {
+ return OID_SHA512_RSA_SIG;
+ }
+ else
+ {
+ return OID_SHA256_RSA_SIG;
+ }
+}
+
+/**
+ Determine signature algorithm to use in the CertificateVerify or
+ ServerKeyExchange handshake messages in TLS 1.2.
+
+ TODO: add support for RSASSA-PSS.
+
+ This function should only be called when using TLS 1.2.
+
+ @param[in] certSigAlg The signature algorithm with which our
+ certificate was signed.
+ @param[in] keySize The size of our private key in bytes. For RSA,
+ this is modulus; for ECDSA, this is the curve size.
+ @param[in] pubKeyAlgorithm The public key algorithm to use for
+ authentication. This should the same algorithm our public/private key
+ pair is meant for. Must be either OID_RSA_KEY_ALG or
+ OID_ECDSA_KEY_ALG.
+ @param[in] peerSigAlg The list of signature algorithm masks
+ the peer supports (e.g. HASH_SIG_SHA*_RSA_MASK). This should
+ be the list created during parsing of the ClientHello or
+ CertificateRequest message.
+ @return The signature algorithm to use.
+*/
+int32_t chooseSigAlgInt(int32_t certSigAlg,
+ psSize_t keySize,
+ int32_t keyAlgorithm,
+ uint16_t peerSigAlgs)
+{
+ int32 a = certSigAlg;
+ psResSize_t hashLen;
+
+#ifndef USE_RSA
+ if (keyAlgorithm == OID_RSA_KEY_ALG)
+ {
+ return PS_UNSUPPORTED_FAIL;
+ }
+#endif
+#ifndef USE_ECC
+ if (keyAlgorithm == OID_ECDSA_KEY_ALG)
+ {
+ return PS_UNSUPPORTED_FAIL;
+ }
+#endif
+
+ /*
+ We are going to use certSigAlg as the basis of our choice.
+ This is because the SSL layer must ensure anyway that the peer
+ supports this algorithm.
+ */
+ if (keyAlgorithm == OID_RSA_KEY_ALG)
+ {
+ if (certSigAlg == OID_SHA1_ECDSA_SIG ||
+ certSigAlg == OID_SHA256_ECDSA_SIG ||
+ certSigAlg == OID_SHA384_ECDSA_SIG ||
+ certSigAlg == OID_SHA512_ECDSA_SIG)
+ {
+ /* Pubkey is RSA, but cert is signed with ECDSA.
+ Convert certSigAlg to corresponding RSA alg. */
+ a = ecdsaToRsa(certSigAlg);
+ }
+ }
+ else if (keyAlgorithm == OID_ECDSA_KEY_ALG)
+ {
+ if (certSigAlg != OID_SHA1_ECDSA_SIG &&
+ certSigAlg != OID_SHA256_ECDSA_SIG &&
+ certSigAlg != OID_SHA384_ECDSA_SIG &&
+ certSigAlg != OID_SHA512_ECDSA_SIG)
+ {
+ /* Pubkey is ECDSA, but cert is signed with RSA.
+ Convert to corresponding ECDSA alg. */
+ a = sigAlgRsaToEcdsa(certSigAlg);
+ }
+ }
+
+ hashLen = psSigAlgToHashLen(a);
+ if (hashLen < 0)
+ { /* unknown sigAlg; error on hashLen */
+ return hashLen;
+ }
+
+ /*
+ For RSA signatures, RFC 5746 allows to pick any hash algorithm,
+ as long as it is supported by the peer, i.e. included in the
+ peer's signature_algorithms list.
+
+ We use this opportunity to switch from the insecure MD5 and
+ SHA-1 to SHA-256, if possible. We don't want to contribute
+ to the longevity of obsolete hash algorithms.
+ */
+ if (psIsInsecureSigAlg(a, keyAlgorithm, keySize, hashLen)
+ || !canUseSigAlg(a, keyAlgorithm, peerSigAlgs))
+ {
+ /* Try to upgrade: This won't select inscure ones. */
+ a = upgradeSigAlg(a, keyAlgorithm);
+ if (!canUseSigAlg(a, keyAlgorithm, peerSigAlgs))
+ {
+ /* Stil not supported. Try the next alternative. */
+ a = upgradeSigAlg(a, keyAlgorithm);
+ if (!canUseSigAlg(a, keyAlgorithm, peerSigAlgs))
+ {
+ /* Unable to upgrade insecure alg. Have to use the
+ server cert sig alg. */
+ a = certSigAlg;
+ psTraceIntInfo("Fallback to certificate sigAlg: %d\n", a);
+ }
+ }
+ }
+ psTraceIntInfo("Chose sigAlg %d\n", a);
+ return a;
+}
+
+int32_t chooseSigAlg(psX509Cert_t *cert,
+ psPubKey_t *privKey,
+ uint16_t peerSigAlgs)
+{
+ int32 pubKeyAlg;
+
+# ifdef USE_CERT_PARSE
+ pubKeyAlg = cert->pubKeyAlgorithm;
+# else
+ if (privKey->type == PS_RSA)
+ {
+ pubKeyAlg = OID_RSA_KEY_ALG;
+ }
+ else if (privKey->type == PS_ECC)
+ {
+ pubKeyAlg = OID_ECDSA_KEY_ALG;
+ }
+ else
+ {
+ return PS_UNSUPPORTED_FAIL;
+ }
+# endif /* USE_CERT_PARSE */
+
+ return chooseSigAlgInt(cert->sigAlgorithm,
+ privKey->keysize,
+ pubKeyAlg,
+ peerSigAlgs);
+}
+
+
+/* Return the TLS 1.2 SignatureAndHashAlgorithm encoding for the
+ given algorithm OID. */
+int32_t getSignatureAndHashAlgorithmEncoding(uint16_t sigAlgOid,
+ unsigned char *octet1,
+ unsigned char *octet2,
+ uint16_t *hashSize)
+{
+ unsigned char b1, b2;
+ uint16_t hLen = 0;
+
+ switch (sigAlgOid)
+ {
+#ifdef USE_SHA1
+ case OID_SHA1_ECDSA_SIG:
+ b1 = 0x2; /* SHA-1 */
+ b2 = 0x3; /* ECDSA */
+ hLen = SHA1_HASH_SIZE;
+ break;
+ case OID_SHA1_RSA_SIG:
+ b1 = 0x2; /* SHA-1 */
+ b2 = 0x1; /* RSA */
+ hLen = SHA1_HASH_SIZE;
+ break;
+#endif
+#ifdef USE_SHA256
+ case OID_SHA256_ECDSA_SIG:
+ b1 = 0x4; /* SHA-256 */
+ b2 = 0x3; /* ECDSA */
+ hLen = SHA256_HASH_SIZE;
+ break;
+ case OID_SHA256_RSA_SIG:
+ b1 = 0x4; /* SHA-256 */
+ b2 = 0x1; /* RSA */
+ hLen = SHA256_HASH_SIZE;
+ break;
+#endif
+#ifdef USE_SHA384
+ case OID_SHA384_ECDSA_SIG:
+ b1 = 0x5; /* SHA-384 */
+ b2 = 0x3; /* ECDSA */
+ hLen = SHA384_HASH_SIZE;
+ break;
+ case OID_SHA384_RSA_SIG:
+ b1 = 0x5; /* SHA-384 */
+ b2 = 0x1; /* RSA */
+ hLen = SHA384_HASH_SIZE;
+ break;
+#endif
+#ifdef USE_SHA512
+ case OID_SHA512_ECDSA_SIG:
+ b1 = 0x6; /* SHA-512 */
+ b2 = 0x3; /* ECDSA */
+ hLen = SHA512_HASH_SIZE;
+ break;
+ case OID_SHA512_RSA_SIG:
+ b1 = 0x6; /* SHA-512 */
+ b2 = 0x1; /* RSA */
+ hLen = SHA512_HASH_SIZE;
+ break;
+#endif
+ default:
+ return PS_UNSUPPORTED_FAIL; /* algorithm not supported */
+ }
+
+ if (octet1 && octet2 && hashSize)
+ {
+ *octet1 = b1;
+ *octet2 = b2;
+ *hashSize = hLen;
+ return PS_SUCCESS;
+ }
+ return PS_ARG_FAIL;
+}
+
+#endif /* ! USE_ONLY_PSK_CIPHER_SUITE */
+#endif /* USE_SERVER_SIDE_SSL || USE_CLIENT_AUTH */
diff --git a/matrixssl/tlsTrace.c b/matrixssl/tlsTrace.c
index 6e843d9..9e72ed1 100644
--- a/matrixssl/tlsTrace.c
+++ b/matrixssl/tlsTrace.c
@@ -139,10 +139,12 @@ void tlsTraceErrorIndent(psSize_t indentLevel,
/* srcFile:srcLine as a suffix (if errorMsg does not contain newline)
or on a separate line (otherwise) has the benefit that then the actual
errorMsg lines up nicely with previous messages that have the same
- indentLevel. */
+ indentLevel.
+ Add 1 space before and after parenthesis to allow file:line to be
+ easily copied from terminal window. */
tlsTraceIndent(indentLevel, errorMsg);
- tlsTraceStr(" (%s:", srcFile);
- tlsTraceInt("%d)\n", srcLine);
+ tlsTraceStr(" ( %s:", srcFile);
+ tlsTraceInt("%d )\n", srcLine);
# else
tlsTraceIndent(indentLevel, srcFile);
tlsTraceInt(":%d ", srcLine);
@@ -355,7 +357,7 @@ void psPrintHsMessageCreate(ssl_t *ssl, unsigned char hsMsgType)
{
tlsTrace("<<< Client creating ");
}
- if (NEGOTIATED_TLS_1_3(ssl))
+ if (NGTD_VER(ssl, v_tls_1_3_any))
{
tlsTrace("TLS 1.3 ");
}
@@ -370,7 +372,7 @@ psBool_t isTls13ClientHello(ssl_t *ssl, unsigned char hsMsgType)
{
return PS_FALSE;
}
- if (NEGOTIATED_TLS_1_3(ssl))
+ if (NGTD_VER(ssl, v_tls_1_3_any))
{
return PS_TRUE;
}
@@ -395,7 +397,7 @@ void psPrintHsMessageParse(ssl_t *ssl, unsigned char hsMsgType)
{
tlsTrace(">>> Client parsing ");
}
- if (NEGOTIATED_TLS_1_3(ssl) ||
+ if (NGTD_VER(ssl, v_tls_1_3_any) ||
isTls13ClientHello(ssl, hsMsgType))
{
tlsTrace("TLS 1.3 ");
@@ -449,7 +451,7 @@ void psPrintExtensionParse(ssl_t *ssl, uint16_t extType)
{
tlsTrace(">>> Client parsing ");
}
- if (NEGOTIATED_TLS_1_3(ssl))
+ if (NGTD_VER(ssl, v_tls_1_3_any))
{
tlsTrace("TLS 1.3 ");
}
@@ -662,10 +664,14 @@ void psPrintTls13SigAlgList(psSize_t indentLevel,
tlsTrace("\n");
}
-void psPrintProtocolVersion(psSize_t indentLevel,
+void psPrintVer(psProtocolVersion_t ver)
+{
+ tlsTrace(VER_TO_STR(VER_GET_RAW(ver)));
+}
+
+void psPrintProtocolVersionNew(psSize_t indentLevel,
const char *where,
- unsigned char majVer,
- unsigned char minVer,
+ psProtocolVersion_t ver,
psBool_t addNewline)
{
tlsTraceIndent(indentLevel, NULL);
@@ -675,58 +681,60 @@ void psPrintProtocolVersion(psSize_t indentLevel,
tlsTraceStr("%s: ", where);
}
- if (majVer == TLS_MAJ_VER)
+ psPrintVer(ver);
+
+ if (addNewline)
{
- if (minVer == TLS_1_3_MIN_VER)
- {
- tlsTrace("TLS 1.3");
- }
- else if (minVer == TLS_1_2_MIN_VER)
- {
- tlsTrace("TLS 1.2");
- }
- else if (minVer == TLS_1_1_MIN_VER)
- {
- tlsTrace("TLS 1.1");
- }
- else if (minVer == TLS_1_0_MIN_VER)
- {
- tlsTrace("TLS 1.0");
- }
- else if (minVer == SSL3_MIN_VER)
- {
- tlsTrace("SSL 3.0");
- }
- else
- {
- tlsTraceInt("Unsupported TLS minor version: %d", minVer);
- }
+ tlsTrace("\n");
}
- else if (majVer == TLS_1_3_DRAFT_MAJ_VER)
+}
+
+void psPrintProtocolVersionNewWithAttribs(psSize_t indentLevel,
+ const char *where,
+ psProtocolVersion_t ver,
+ psBool_t addNewline)
+{
+ const char *str;
+
+ tlsTraceIndent(indentLevel, NULL);
+
+ if (where)
{
- tlsTraceInt("TLS 1.3 draft %d", minVer);
+ tlsTraceStr("%s: ", where);
}
-# ifdef USE_DTLS
- else if (majVer == DTLS_MAJ_VER)
+
+ str = VER_TO_STR(VER_GET_RAW(ver));
+ tlsTrace(str);
+
+ if (ver & v_tls_negotiated)
{
- if (minVer == DTLS_1_2_MIN_VER)
- {
- tlsTrace("DTLS 1.2");
- }
- else if (minVer == DTLS_MIN_VER)
- {
- tlsTrace("DTLS 1.0");
- }
- else
- {
- tlsTraceInt("Unsupported DTLS minor version: %d", minVer);
- }
+ tlsTrace(" (negotiated)");
}
-# endif /* USE_DTLS */
- else
+ if (addNewline)
{
- tlsTraceInt("Unsupported major version: %d", majVer);
+ tlsTrace("\n");
}
+}
+
+void psPrintProtocolVersion(psSize_t indentLevel,
+ const char *where,
+ unsigned char majVer,
+ unsigned char minVer,
+ psBool_t addNewline)
+{
+ uint32_t ver;
+ const char *str;
+
+ tlsTraceIndent(indentLevel, NULL);
+
+ if (where)
+ {
+ tlsTraceStr("%s: ", where);
+ }
+
+ ver = (majVer << 8) | minVer;
+ str = ENCODED_VER_TO_STR(ver);
+ tlsTrace(str);
if (addNewline)
{
@@ -741,38 +749,27 @@ void psPrintNegotiatedProtocolVersion(psSize_t indentLevel,
ssl_t *ssl,
psBool_t addNewline)
{
- uint8_t selectedMajVer, selectedMinVer;
+ psProtocolVersion_t ver;
- selectedMajVer = ssl->majVer;
- selectedMinVer = ssl->minVer;
-
-# ifdef USE_TLS_1_3
- if (USING_TLS_1_3(ssl))
+ ver = GET_ACTV_VER(ssl);
+ if (!NGTD(ssl))
{
- selectedMajVer = TLS_MAJ_VER;
- if (ssl->tls13NegotiatedMinorVer > TLS_1_3_MIN_VER)
- {
- selectedMajVer = TLS_1_3_DRAFT_MAJ_VER;
- }
- selectedMinVer = ssl->tls13NegotiatedMinorVer;
+ ver = v_undefined;
}
-# endif
- psTracePrintProtocolVersion(indentLevel,
+ psTracePrintProtocolVersionNew(indentLevel,
where,
- selectedMajVer,
- selectedMinVer,
+ ver,
PS_TRUE);
}
void psPrintVersionsList(psSize_t indentLevel,
const char *where,
- uint16_t *list,
+ psProtocolVersion_t *list,
psSize_t listLen,
psBool_t addNewline)
{
psSize_t i;
- unsigned char min, maj;
tlsTraceIndent(indentLevel, NULL);
@@ -784,18 +781,17 @@ void psPrintVersionsList(psSize_t indentLevel,
for (i = 0; i < listLen; i++)
{
- maj = list[i] >> 8;
- min = list[i] & 0xff;
-
- if (maj == 0 && min == 0)
+ if (list[i] == 0)
{
/* Array is 0-terminated. */
break;
}
else
{
- psPrintProtocolVersion(indentLevel,
- NULL, maj, min, PS_TRUE);
+ psPrintProtocolVersionNew(indentLevel,
+ NULL,
+ list[i],
+ PS_TRUE);
}
}
@@ -814,10 +810,10 @@ void psPrintSupportedVersionsList(psSize_t indentLevel,
if (peer)
{
# ifdef USE_TLS_1_3
- return psPrintVersionsList(indentLevel,
+ psPrintVersionsList(indentLevel,
where,
- ssl->tls13PeerSupportedVersions,
- ssl->tls13PeerSupportedVersionsLen,
+ ssl->peerSupportedVersionsPriority,
+ ssl->peerSupportedVersionsPriorityLen,
addNewline);
# else
tlsTrace("psPrintSupportedVersionsList error: " \
@@ -827,47 +823,14 @@ void psPrintSupportedVersionsList(psSize_t indentLevel,
}
else
{
- return psPrintVersionsList(indentLevel,
+ psPrintVersionsList(indentLevel,
where,
- ssl->supportedVersions,
- ssl->supportedVersionsLen,
+ ssl->supportedVersionsPriority,
+ ssl->supportedVersionsPriorityLen,
addNewline);
}
}
-void psPrintVersionsList32(psSize_t indentLevel,
- const char *where,
- int32_t *list,
- psSize_t listLen,
- psBool_t addNewline)
-{
- psSize_t i;
- uint16_t ver;
-
- tlsTraceIndent(indentLevel, NULL);
-
- if (where)
- {
- tlsTraceStr("%s :\n", where);
- indentLevel++;
- }
-
- for (i = 0; i < listLen; i++)
- {
- ver = tlsMinVerToOfficialVer(list[i]);
- psPrintProtocolVersion(indentLevel,
- NULL,
- (ver >> 8) & 0xff,
- ver & 0xff,
- PS_TRUE);
- }
-
- if (addNewline)
- {
- tlsTrace("\n");
- }
-}
-
void psPrintTls13NamedGroup(psSize_t indentLevel,
const char *where,
uint16_t namedGroup,
@@ -1584,6 +1547,9 @@ void psPrintCiphersuiteName(psSize_t indentLevel,
case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
tlsTrace("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384");
break;
+ case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+ tlsTrace("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384");
+ break;
case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
tlsTrace("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA");
break;
@@ -1767,34 +1733,62 @@ void psPrintPubKeyTypeAndSize(ssl_t *ssl,
tlsTrace("Ed25519\n");
break;
default:
- tlsTrace("Unknown/unsupported key type\n");
+ tlsTraceInt("Unknown/unsupported key type: %hhu\n", authKey->type);
}
}
+static
+void psPrintPubKeyTypeAndSizeRaw(ssl_t *ssl,
+ uint8_t keyType,
+ psSize_t keyNBits,
+ psBool_t eccIsEcdh)
+{
+ switch(keyType)
+ {
+ case PS_RSA:
+ tlsTrace("RSA");
+ break;
+ case PS_ECC:
+ if (eccIsEcdh)
+ {
+ tlsTrace("ECDHE");
+ }
+ else
+ {
+ tlsTrace("ECDSA");
+ }
+ if (keyNBits == 528)
+ {
+ keyNBits = 521; /* Kludge. */
+ }
+ break;
+ case PS_DH:
+ tlsTrace("DHE");
+ break;
+ case PS_DSA:
+ tlsTrace("DSA\n");
+ break;
+ case PS_X25519:
+ tlsTrace("X25519\n");
+ break;
+ case PS_ED25519:
+ tlsTrace("Ed25519\n");
+ break;
+ default:
+ tlsTraceInt("Unknown/unsupported key type: %hhu", keyType);
+ }
+
+ tlsTraceInt(" (%hu-bit)\n", keyNBits);
+}
+
/* Print out information about a completed handshake. */
void matrixSslPrintHSDetails(ssl_t *ssl)
{
- uint16_t majVer, minVer;
-
if (ssl->hsState == SSL_HS_DONE)
{
- majVer = ssl->majVer;
- minVer = ssl->minVer;
-
tlsTrace("\n");
-# ifdef USE_TLS_1_3
- if (ssl->flags & SSL_FLAGS_TLS_1_3_NEGOTIATED)
- {
- majVer = TLS_MAJ_VER;
- minVer = ssl->tls13NegotiatedMinorVer;
- if (minVer > TLS_1_3_MIN_VER)
- {
- majVer = TLS_1_3_DRAFT_MAJ_VER;
- }
- }
-# endif /* USE_TLS_1_3 */
- psTracePrintProtocolVersion(INDENT_CONN_ESTABLISHED,
- NULL, majVer, minVer, 0);
+ psTracePrintProtocolVersionNew(INDENT_CONN_ESTABLISHED,
+ NULL, GET_ACTV_VER(ssl), PS_FALSE);
tlsTrace(" connection established: ");
psTracePrintCiphersuiteName(INDENT_CONN_ESTABLISHED,
NULL, ssl->cipher->ident, PS_TRUE);
@@ -1815,9 +1809,8 @@ void matrixSslPrintHSDetails(ssl_t *ssl)
{
tlsTrace(" New session\n");
}
-
# ifdef USE_TLS_1_3
- if (ssl->flags & SSL_FLAGS_TLS_1_3_NEGOTIATED)
+ if (NGTD_VER(ssl, v_tls_1_3_any))
{
if (ssl->sec.tls13UsingPsk)
@@ -1847,6 +1840,7 @@ void matrixSslPrintHSDetails(ssl_t *ssl)
}
if (!ssl->sec.tls13UsingPsk)
{
+# ifndef USE_ONLY_PSK_CIPHER_SUITE
if (ssl->sec.tls13CvSigAlg != 0)
{
if (IS_SERVER(ssl))
@@ -1886,6 +1880,7 @@ void matrixSslPrintHSDetails(ssl_t *ssl)
NULL,
ssl->sec.tls13PeerCvSigAlg,
PS_TRUE);
+# ifdef USE_CERT_PARSE
if (IS_SERVER(ssl))
{
tlsTrace(" Client key: ");
@@ -1896,6 +1891,7 @@ void matrixSslPrintHSDetails(ssl_t *ssl)
}
psTracePrintPubKeyTypeAndSize(ssl,
&ssl->sec.cert->publicKey);
+# endif /* USE_CERT_PARSE */
}
else
{
@@ -1904,6 +1900,72 @@ void matrixSslPrintHSDetails(ssl_t *ssl)
tlsTrace(" No client authentication\n");
}
}
+# endif /* USE_ONLY_PSK_CIPHER_SUITE */
+ }
+ } /* endif(TLS 1.3) */
+# endif
+# ifndef USE_ONLY_PSK_CIPHERSUITE
+ if (!NGTD_VER(ssl, v_tls_1_3_any))
+ {
+ if (ssl->flags & SSL_FLAGS_CLIENT_AUTH)
+ {
+ tlsTrace(" Client authenticated\n");
+ }
+ else
+ {
+ tlsTrace(" No client authentication\n");
+ }
+ if (IS_SERVER(ssl))
+ {
+ if (ssl->keys && ssl->chosenIdentity)
+ {
+ tlsTrace(" Server key: ");
+ psTracePrintPubKeyTypeAndSize(ssl,
+ &ssl->chosenIdentity->privKey);
+ }
+ if (ssl->flags & SSL_FLAGS_CLIENT_AUTH)
+ {
+ tlsTrace(" Client key: ");
+ psPrintPubKeyTypeAndSizeRaw(ssl,
+ ssl->peerAuthKeyType,
+ ssl->peerAuthKeyNBits,
+ PS_FALSE);
+ }
+ }
+ else /* We are client. */
+ {
+ if ((ssl->flags & SSL_FLAGS_CLIENT_AUTH) && ssl->chosenIdentity)
+ {
+ tlsTrace(" Client key: ");
+ psTracePrintPubKeyTypeAndSize(ssl,
+ &ssl->chosenIdentity->privKey);
+ }
+ tlsTrace(" Server key: ");
+ psPrintPubKeyTypeAndSizeRaw(ssl,
+ ssl->peerAuthKeyType,
+ ssl->peerAuthKeyNBits,
+ PS_FALSE);
+ }
+ tlsTrace(" Key exchange: ");
+ if (ssl->flags & SSL_FLAGS_PSK_CIPHER)
+ {
+ tlsTrace("PSK\n");
+ }
+ else
+ {
+ /* We are not using PSK and we only filled
+ ssl->peerKeyExKeyType if we used (EC)DH. */
+ if (ssl->peerKeyExKeyType == 0)
+ {
+ tlsTrace("RSA key transport\n");
+ }
+ else
+ {
+ psPrintPubKeyTypeAndSizeRaw(ssl,
+ ssl->peerKeyExKeyType,
+ ssl->peerKeyExKeyNBits,
+ PS_TRUE);
+ }
}
}
# endif
diff --git a/matrixssl/version.h b/matrixssl/version.h
index 0b34ecc..ec6c52b 100644
--- a/matrixssl/version.h
+++ b/matrixssl/version.h
@@ -8,10 +8,10 @@
extern "C" {
#endif
-#define MATRIXSSL_VERSION "4.0.0-OPEN"
+#define MATRIXSSL_VERSION "4.0.1-OPEN"
#define MATRIXSSL_VERSION_MAJOR 4
#define MATRIXSSL_VERSION_MINOR 0
-#define MATRIXSSL_VERSION_PATCH 0
+#define MATRIXSSL_VERSION_PATCH 1
#define MATRIXSSL_VERSION_CODE "OPEN"
#ifdef __cplusplus
diff --git a/release_notes-4-0-0-open.html b/release_notes-4-0-1-open.html
similarity index 76%
rename from release_notes-4-0-0-open.html
rename to release_notes-4-0-1-open.html
index 1e8ad36..08ce9e3 100644
--- a/release_notes-4-0-0-open.html
+++ b/release_notes-4-0-1-open.html
@@ -8,7 +8,25 @@
-MatrixSSL 4.0 changelog
+MatrixSSL 4.x changelog
+Changes between 4.0.0 and 4.0.1 [November 2018]
+This version improves the security of RSA PKCS #1.5 signature verification and adds better support for run-time security configuration.
+
+TLS:
+
+Added a run-time security callback feature (matrixSslRegisterSecurityCallback). The security callback can allow or deny a cryptographic operation based on the operation type and the key size. Currently only authentication and key exchange operations are supported. The default security callback supports pre-defined security profiles (matrixSslSetSecurityProfile).
+Added an example security profile: WPA3 1.0 Enterprise 192-bit mode restrictions for EAP-TLS.
+Added support for the TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ciphersuite.
+Changed the way how protocol version IDs are stored internally and rewrote most of the version negotiation code. This is almost entirely an internal code refactoring. To the API user, the only visible change is that version selection APIs now take in an argument of type psProtocolVersion_t instead of int32_t. See the API reference guide for details.
+Refactored ServerKeyExchange signature generation and verification code.
+
+Crypto:
+
+Changed from a parsing-based to a comparison-based approach in DigestInfo validation when verifying RSA PKCS #1.5 signatures. There are no known practical attacks against the old code, but the comparison-based approach is theoretically more sound. Thanks to Sze Yiu Chau from Purdue University for pointing this out.
+(MatrixSSL FIPS Edition only:) Fix DH key exchange when using DH parameter files containing optional privateValueLength argument.
+psX509AuthenticateCert now uses the common psVerifySig API for signature verification. Previously, CRLs and certificates used different code paths for signature verification.
+
+
Changes between 3.9.5 and 4.0.0 [August 2018]
This version adds support for RFC 8446 (TLS 1.3), new APIs for configuring session options as well as fixes to security vulnerabilities.
diff --git a/testkeys/EC/256_EC_KEY.noparam.nopub.pem b/testkeys/EC/256_EC_KEY.noparam.nopub.pem
new file mode 100644
index 0000000..38ebe9c
--- /dev/null
+++ b/testkeys/EC/256_EC_KEY.noparam.nopub.pem
@@ -0,0 +1,3 @@
+-----BEGIN EC PRIVATE KEY-----
+MDECAQEEIFzpicWxU6ACPJC+OipzsggWw+281dZnJhBO7HkoD7/LoAoGCCqGSM49AwEH
+-----END EC PRIVATE KEY-----