summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ssl/ssl3ecc.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/ssl3ecc.c')
-rw-r--r--security/nss/lib/ssl/ssl3ecc.c160
1 files changed, 98 insertions, 62 deletions
diff --git a/security/nss/lib/ssl/ssl3ecc.c b/security/nss/lib/ssl/ssl3ecc.c
index 913a14f63..b440b4b02 100644
--- a/security/nss/lib/ssl/ssl3ecc.c
+++ b/security/nss/lib/ssl/ssl3ecc.c
@@ -111,7 +111,7 @@ ssl_ECPubKey2NamedGroup(const SECKEYPublicKey *pubKey)
static SECStatus
ssl3_ComputeECDHKeyHash(SSLHashType hashAlg,
SECItem ec_params, SECItem server_ecpoint,
- PRUint8 *client_rand, PRUint8 *server_rand,
+ SSL3Random *client_rand, SSL3Random *server_rand,
SSL3Hashes *hashes)
{
PRUint8 *hashBuf;
@@ -175,8 +175,8 @@ ssl3_SendECDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
- isTLS12 = (PRBool)(ss->version >= SSL_LIBRARY_VERSION_TLS_1_2);
+ isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
+ isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
/* Generate ephemeral EC keypair */
if (svrPubKey->keyType != ecKey) {
@@ -219,7 +219,7 @@ ssl3_SendECDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
goto loser;
}
- rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_client_key_exchange,
+ rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
pubKey->u.ec.publicValue.len + 1);
if (rv != SECSuccess) {
goto loser; /* err set by ssl3_AppendHandshake* */
@@ -232,7 +232,7 @@ ssl3_SendECDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
goto loser; /* err set by ssl3_AppendHandshake* */
}
- rv = ssl3_InitPendingCipherSpecs(ss, pms, PR_TRUE);
+ rv = ssl3_InitPendingCipherSpec(ss, pms);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
goto loser;
@@ -250,6 +250,19 @@ loser:
return SECFailure;
}
+/* This function encodes the key_exchange field in
+ * the KeyShareEntry structure. */
+SECStatus
+tls13_EncodeECDHEKeyShareKEX(const sslSocket *ss, const SECKEYPublicKey *pubKey)
+{
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
+ PORT_Assert(pubKey->keyType == ecKey);
+
+ return ssl3_ExtAppendHandshake(ss, pubKey->u.ec.publicValue.data,
+ pubKey->u.ec.publicValue.len);
+}
+
/*
** Called from ssl3_HandleClientKeyExchange()
*/
@@ -313,7 +326,7 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, PRUint8 *b,
return SECFailure;
}
- rv = ssl3_InitPendingCipherSpecs(ss, pms, PR_TRUE);
+ rv = ssl3_InitPendingCipherSpec(ss, pms);
PK11_FreeSymKey(pms);
if (rv != SECSuccess) {
/* error code set by ssl3_InitPendingCipherSpec */
@@ -584,8 +597,8 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, PRUint8 *b, PRUint32 length)
* check to make sure the hash is signed by right guy
*/
rv = ssl3_ComputeECDHKeyHash(hashAlg, ec_params, ec_point,
- ss->ssl3.hs.client_random,
- ss->ssl3.hs.server_random,
+ &ss->ssl3.hs.client_random,
+ &ss->ssl3.hs.server_random,
&hashes);
if (rv != SECSuccess) {
@@ -690,7 +703,7 @@ ssl3_SendECDHServerKeyExchange(sslSocket *ss)
ec_params.data[2] = keyPair->group->name & 0xff;
pubKey = keyPair->keys->pubKey;
- if (ss->version == SSL_LIBRARY_VERSION_TLS_1_2) {
+ if (ss->ssl3.pwSpec->version == SSL_LIBRARY_VERSION_TLS_1_2) {
hashAlg = ssl_SignatureSchemeToHashType(ss->ssl3.hs.signatureScheme);
} else {
/* Use ssl_hash_none to represent the MD5+SHA1 combo. */
@@ -698,15 +711,15 @@ ssl3_SendECDHServerKeyExchange(sslSocket *ss)
}
rv = ssl3_ComputeECDHKeyHash(hashAlg, ec_params,
pubKey->u.ec.publicValue,
- ss->ssl3.hs.client_random,
- ss->ssl3.hs.server_random,
+ &ss->ssl3.hs.client_random,
+ &ss->ssl3.hs.server_random,
&hashes);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
goto loser;
}
- isTLS12 = (PRBool)(ss->version >= SSL_LIBRARY_VERSION_TLS_1_2);
+ isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
rv = ssl3_SignHashes(ss, &hashes,
ss->sec.serverCert->serverKeyPair->privKey, &signed_hash);
@@ -718,7 +731,7 @@ ssl3_SendECDHServerKeyExchange(sslSocket *ss)
1 + pubKey->u.ec.publicValue.len +
(isTLS12 ? 2 : 0) + 2 + signed_hash.len;
- rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_server_key_exchange, length);
+ rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
if (rv != SECSuccess) {
goto loser; /* err set by AppendHandshake. */
}
@@ -857,16 +870,20 @@ ssl_IsDHEEnabled(const sslSocket *ss)
}
/* Send our Supported Groups extension. */
-SECStatus
-ssl_SendSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+PRInt32
+ssl_SendSupportedGroupsXtn(const sslSocket *ss,
+ TLSExtensionData *xtnData,
+ PRBool append, PRUint32 maxBytes)
{
+ PRInt32 extension_length;
+ unsigned char enabledGroups[64];
+ unsigned int enabledGroupsLen = 0;
unsigned int i;
PRBool ec;
PRBool ff = PR_FALSE;
- PRBool found = PR_FALSE;
- SECStatus rv;
- unsigned int lengthOffset;
+
+ if (!ss)
+ return 0;
/* We only send FF supported groups if we require DH named groups
* or if TLS 1.3 is a possibility. */
@@ -875,19 +892,13 @@ ssl_SendSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData,
if (ss->opt.requireDHENamedGroups) {
ff = ssl_IsDHEEnabled(ss);
}
- if (!ec && !ff) {
- return SECSuccess;
- }
+ if (!ec && !ff)
+ return 0;
} else {
ec = ff = PR_TRUE;
}
- /* Mark the location of the length. */
- rv = sslBuffer_Skip(buf, 2, &lengthOffset);
- if (rv != SECSuccess) {
- return SECFailure;
- }
-
+ PORT_Assert(sizeof(enabledGroups) > SSL_NAMED_GROUP_COUNT * 2);
for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
const sslNamedGroupDef *group = ss->namedGroupPreferences[i];
if (!group) {
@@ -900,53 +911,78 @@ ssl_SendSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData,
continue;
}
- found = PR_TRUE;
- rv = sslBuffer_AppendNumber(buf, group->name, 2);
- if (rv != SECSuccess) {
- return SECFailure;
+ if (append) {
+ (void)ssl_EncodeUintX(group->name, 2, &enabledGroups[enabledGroupsLen]);
+ }
+ enabledGroupsLen += 2;
+ }
+
+ if (enabledGroupsLen == 0) {
+ return 0;
+ }
+
+ extension_length =
+ 2 /* extension type */ +
+ 2 /* extension length */ +
+ 2 /* enabled groups length */ +
+ enabledGroupsLen;
+
+ if (maxBytes < (PRUint32)extension_length) {
+ return 0;
+ }
+
+ if (append) {
+ SECStatus rv;
+ rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_supported_groups_xtn, 2);
+ if (rv != SECSuccess)
+ return -1;
+ rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2);
+ if (rv != SECSuccess)
+ return -1;
+ rv = ssl3_ExtAppendHandshakeVariable(ss, enabledGroups,
+ enabledGroupsLen, 2);
+ if (rv != SECSuccess)
+ return -1;
+ if (!ss->sec.isServer) {
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_supported_groups_xtn;
}
}
-
- if (!found) {
- /* We added nothing, don't send the extension. */
- return SECSuccess;
- }
-
- rv = sslBuffer_InsertLength(buf, lengthOffset, 2);
- if (rv != SECSuccess) {
- return SECFailure;
- }
-
- *added = PR_TRUE;
- return SECSuccess;
+ return extension_length;
}
/* Send our "canned" (precompiled) Supported Point Formats extension,
* which says that we only support uncompressed points.
*/
-SECStatus
-ssl3_SendSupportedPointFormatsXtn(const sslSocket *ss, TLSExtensionData *xtnData,
- sslBuffer *buf, PRBool *added)
+PRInt32
+ssl3_SendSupportedPointFormatsXtn(
+ const sslSocket *ss,
+ TLSExtensionData *xtnData,
+ PRBool append,
+ PRUint32 maxBytes)
{
- SECStatus rv;
+ static const PRUint8 ecPtFmt[6] = {
+ 0, 11, /* Extension type */
+ 0, 2, /* octets that follow */
+ 1, /* octets that follow */
+ 0 /* uncompressed type only */
+ };
/* No point in doing this unless we have a socket that supports ECC.
* Similarly, no point if we are going to do TLS 1.3 only or we have already
* picked TLS 1.3 (server) given that it doesn't use point formats. */
if (!ss || !ssl_IsECCEnabled(ss) ||
ss->vrange.min >= SSL_LIBRARY_VERSION_TLS_1_3 ||
- (ss->sec.isServer && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3)) {
- return SECSuccess;
- }
- rv = sslBuffer_AppendNumber(buf, 1, 1); /* length */
- if (rv != SECSuccess) {
- return SECFailure;
- }
- rv = sslBuffer_AppendNumber(buf, 0, 1); /* uncompressed type only */
- if (rv != SECSuccess) {
- return SECFailure;
+ (ss->sec.isServer && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3))
+ return 0;
+ if (append && maxBytes >= (sizeof ecPtFmt)) {
+ SECStatus rv = ssl3_ExtAppendHandshake(ss, ecPtFmt, (sizeof ecPtFmt));
+ if (rv != SECSuccess)
+ return -1;
+ if (!ss->sec.isServer) {
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_ec_point_formats_xtn;
+ }
}
-
- *added = PR_TRUE;
- return SECSuccess;
+ return sizeof(ecPtFmt);
}