diff options
Diffstat (limited to 'security/nss/lib/ssl/ssl3ecc.c')
-rw-r--r-- | security/nss/lib/ssl/ssl3ecc.c | 160 |
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); } |