/* Send our "canned" (precompiled) Supported Point Formats extension, * which says that we only support uncompressed points. */ PRInt32 ssl3_SendSupportedPointFormatsXtn( sslSocket *ss, PRBool append, PRUint32 maxBytes) { 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 0; if (append && maxBytes >= (sizeof ecPtFmt)) { SECStatus rv = ssl3_AppendHandshake(ss, ecPtFmt, (sizeof ecPtFmt)); if (rv != SECSuccess) return -1; if (!ss->sec.isServer) { TLSExtensionData *xtnData = &ss->xtnData; xtnData->advertised[xtnData->numAdvertised++] = ssl_ec_point_formats_xtn; } } return sizeof(ecPtFmt); }
/* This function encodes the key_exchange field in * the KeyShareEntry structure. */ SECStatus tls13_EncodeECDHEKeyShareKEX(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_AppendHandshake(ss, pubKey->u.ec.publicValue.data, pubKey->u.ec.publicValue.len); }
SECStatus ssl3_SendECDHServerKeyExchange( sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash) { SECStatus rv = SECFailure; int length; PRBool isTLS, isTLS12; SECItem signed_hash = { siBuffer, NULL, 0 }; SSL3Hashes hashes; SECItem ec_params = { siBuffer, NULL, 0 }; unsigned char paramBuf[3]; const namedGroupDef *ecGroup; sslEphemeralKeyPair *keyPair; SECKEYPublicKey *pubKey; /* Generate ephemeral ECDH key pair and send the public key */ ecGroup = ssl_GetECGroupForServerSocket(ss); if (!ecGroup) { goto loser; } PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs)); if (ss->opt.reuseServerECDHEKey) { rv = ssl_CreateECDHEphemeralKeys(ss, ecGroup); if (rv != SECSuccess) { goto loser; } keyPair = (sslEphemeralKeyPair *)PR_NEXT_LINK(&ss->ephemeralKeyPairs); } else { rv = ssl_CreateECDHEphemeralKeyPair(ecGroup, &keyPair); if (rv != SECSuccess) { goto loser; } PR_APPEND_LINK(&keyPair->link, &ss->ephemeralKeyPairs); } PORT_Assert(keyPair); if (!keyPair) { PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); return SECFailure; } ec_params.len = sizeof(paramBuf); ec_params.data = paramBuf; PORT_Assert(keyPair->group); PORT_Assert(keyPair->group->type == group_type_ec); ec_params.data[0] = ec_type_named; ec_params.data[1] = keyPair->group->name >> 8; ec_params.data[2] = keyPair->group->name & 0xff; pubKey = keyPair->keys->pubKey; rv = ssl3_ComputeECDHKeyHash(sigAndHash->hashAlg, ec_params, pubKey->u.ec.publicValue, &ss->ssl3.hs.client_random, &ss->ssl3.hs.server_random, &hashes, ss->opt.bypassPKCS11); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); goto loser; } isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); rv = ssl3_SignHashes(&hashes, ss->sec.serverCert->serverKeyPair->privKey, &signed_hash, isTLS); if (rv != SECSuccess) { goto loser; /* ssl3_SignHashes has set err. */ } if (signed_hash.data == NULL) { /* how can this happen and rv == SECSuccess ?? */ PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); goto loser; } length = ec_params.len + 1 + pubKey->u.ec.publicValue.len + (isTLS12 ? 2 : 0) + 2 + signed_hash.len; rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } rv = ssl3_AppendHandshakeVariable(ss, pubKey->u.ec.publicValue.data, pubKey->u.ec.publicValue.len, 1); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } if (isTLS12) { rv = ssl3_AppendSignatureAndHashAlgorithm(ss, sigAndHash); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } } rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data, signed_hash.len, 2); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } PORT_Free(signed_hash.data); return SECSuccess; loser: if (signed_hash.data != NULL) PORT_Free(signed_hash.data); return SECFailure; }
/* Thunks to let extension handlers operate on const sslSocket* objects. */ SECStatus ssl3_ExtAppendHandshake(const sslSocket *ss, const void *void_src, PRInt32 bytes) { return ssl3_AppendHandshake((sslSocket *)ss, void_src, bytes); }