ec_params.len = 2; ec_params.data = (unsigned char*)PORT_Alloc(ec_params.len); rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length); if (rv != SECSuccess) { goto loser;		 }   if ((ec_params.data[0] != ec_type_named) || !supportedCurve(ec_params.data[1])) { errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE; desc = handshake_failure; goto alert_loser; }  rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length); if (rv != SECSuccess) { goto loser;		 }  if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) { errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM; desc = handshake_failure; goto alert_loser; }  rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length); if (rv != SECSuccess) { goto loser;		 }  if (length != 0) { if (isTLS) desc = decode_error; goto alert_loser;		 }  PRINT_BUF(60, (NULL, "Server EC params", ec_params.data, ec_params.len)); PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));    desc = isTLS ? decrypt_error : handshake_failure;   rv = ssl3_ComputeECDHKeyHash(ec_params, ec_point, &ss->ssl3->hs.client_random, &ss->ssl3->hs.server_random, &hashes);  if (rv != SECSuccess) { errCode = ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); goto alert_loser; } rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature, isTLS, ss->pkcs11PinArg); if (rv != SECSuccess)  { errCode = ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); goto alert_loser; }  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { goto no_memory; }  ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey); if (peerKey == NULL) { goto no_memory; }  peerKey->arena                 = arena; peerKey->keyType               = ecKey;   if (ecName2params(arena, ec_params.data[1], &peerKey->u.ec.DEREncodedParams) != SECSuccess) {  errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE; goto alert_loser; }   if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue,  &ec_point)) { PORT_FreeArena(arena, PR_FALSE); goto no_memory; } peerKey->pkcs11Slot         = NULL; peerKey->pkcs11ID           = CK_INVALID_HANDLE;  ss->sec.peerKey = peerKey; SECITEM_FreeItem(&ec_params, PR_FALSE); SECITEM_FreeItem(&ec_point, PR_FALSE); ss->ssl3->hs.ws = wait_cert_request;  return SECSuccess;
rv = ssl3_HandleECDHServerKeyExchange(ss, b, length); return rv;
ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length){    PRArenaPool *    arena     = NULL;    SECKEYPublicKey *peerKey   = NULL;    PRBool           isTLS;    SECStatus        rv;    int              errCode   = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;    SSL3AlertDescription desc  = illegal_parameter;    SECItem          modulus   = {siBuffer, NULL, 0};    SECItem          exponent  = {siBuffer, NULL, 0};    SECItem          signature = {siBuffer, NULL, 0};    SECItem          dh_p      = {siBuffer, NULL, 0};    SECItem          dh_g      = {siBuffer, NULL, 0};    SECItem          dh_Ys     = {siBuffer, NULL, 0};    SSL3Hashes       hashes;#ifdef NSS_ENABLE_ECC    SECItem          ec_params = {siBuffer, NULL, 0};    SECItem          ec_point  = {siBuffer, NULL, 0};#endif /* NSS_ENABLE_ECC */    SSL_TRC(3, ("%d: SSL3[%d]: handle server_key_exchange handshake",		SSL_GETPID(), ss->fd));    PORT_Assert( ssl_HaveRecvBufLock(ss) );    PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) );    if (ss->ssl3->hs.ws != wait_server_key &&	ss->ssl3->hs.ws != wait_server_cert) {	errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH;	desc    = unexpected_message;	goto alert_loser;    }    if (ss->sec.peerCert == NULL) {	errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH;	desc    = unexpected_message;	goto alert_loser;    }    isTLS = (PRBool)(ss->ssl3->prSpec->version > SSL_LIBRARY_VERSION_3_0);    switch (ss->ssl3->hs.kea_def->exchKeyType) {    case kt_rsa:    	rv = ssl3_ConsumeHandshakeVariable(ss, &modulus, 2, &b, &length);    	if (rv != SECSuccess) {	    goto loser;		/* malformed. */	}    	rv = ssl3_ConsumeHandshakeVariable(ss, &exponent, 2, &b, &length);    	if (rv != SECSuccess) {	    goto loser;		/* malformed. */	}    	rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);    	if (rv != SECSuccess) {	    goto loser;		/* malformed. */	}    	if (length != 0) {	    if (isTLS)		desc = decode_error;	    goto alert_loser;		/* malformed. */	}	/* failures after this point are not malformed handshakes. */	/* TLS: send decrypt_error if signature failed. */    	desc = isTLS ? decrypt_error : handshake_failure;    	/*     	 *  check to make sure the hash is signed by right guy     	 */    	rv = ssl3_ComputeExportRSAKeyHash(modulus, exponent,					  &ss->ssl3->hs.client_random,					  &ss->ssl3->hs.server_random, &hashes);        if (rv != SECSuccess) {	    errCode =	    	ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);	    goto alert_loser;	}        rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,				    isTLS, ss->pkcs11PinArg);	if (rv != SECSuccess)  {	    errCode =	    	ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);	    goto alert_loser;	}	/*	 * we really need to build a new key here because we can no longer	 * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate	 * pkcs11 slots and ID's.	 */    	arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);	if (arena == NULL) {	    goto no_memory;	}    	peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);    	if (peerKey == NULL) {            PORT_FreeArena(arena, PR_FALSE);	    goto no_memory;	}	peerKey->arena              = arena;	peerKey->keyType            = rsaKey;	peerKey->pkcs11Slot         = NULL;	peerKey->pkcs11ID           = CK_INVALID_HANDLE;	if (SECITEM_CopyItem(arena, &peerKey->u.rsa.modulus,        &modulus) ||	    SECITEM_CopyItem(arena, &peerKey->u.rsa.publicExponent, &exponent))	{            PORT_FreeArena(arena, PR_FALSE);	    goto no_memory;        }    	ss->sec.peerKey = peerKey;	SECITEM_FreeItem(&modulus,   PR_FALSE);	SECITEM_FreeItem(&exponent,  PR_FALSE);	SECITEM_FreeItem(&signature, PR_FALSE);    	ss->ssl3->hs.ws = wait_cert_request;    	return SECSuccess;    case kt_dh:    	rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length);    	if (rv != SECSuccess) {	    goto loser;		/* malformed. */	}    	rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length);    	if (rv != SECSuccess) {	    goto loser;		/* malformed. */	}    	rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length);    	if (rv != SECSuccess) {	    goto loser;		/* malformed. */	}    	rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);    	if (rv != SECSuccess) {	    goto loser;		/* malformed. */	}    	if (length != 0) {	    if (isTLS)		desc = decode_error;	    goto alert_loser;		/* malformed. */	}	PRINT_BUF(60, (NULL, "Server DH p", dh_p.data, dh_p.len));	PRINT_BUF(60, (NULL, "Server DH g", dh_g.data, dh_g.len));	PRINT_BUF(60, (NULL, "Server DH Ys", dh_Ys.data, dh_Ys.len));	/* failures after this point are not malformed handshakes. */	/* TLS: send decrypt_error if signature failed. */    	desc = isTLS ? decrypt_error : handshake_failure;    	/*     	 *  check to make sure the hash is signed by right guy     	 */    	rv = ssl3_ComputeDHKeyHash(dh_p, dh_g, dh_Ys,					  &ss->ssl3->hs.client_random,					  &ss->ssl3->hs.server_random, &hashes);        if (rv != SECSuccess) {	    errCode =	    	ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);	    goto alert_loser;	}        rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,				    isTLS, ss->pkcs11PinArg);	if (rv != SECSuccess)  {	    errCode =	    	ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);	    goto alert_loser;	}	/*	 * we really need to build a new key here because we can no longer	 * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate	 * pkcs11 slots and ID's.	 */    	arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);	if (arena == NULL) {	    goto no_memory;	}    	ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);    	if (peerKey == NULL) {	    goto no_memory;	}	peerKey->arena              = arena;	peerKey->keyType            = dhKey;	peerKey->pkcs11Slot         = NULL;	peerKey->pkcs11ID           = CK_INVALID_HANDLE;	if (SECITEM_CopyItem(arena, &peerKey->u.dh.prime,        &dh_p) ||	    SECITEM_CopyItem(arena, &peerKey->u.dh.base,         &dh_g) ||	    SECITEM_CopyItem(arena, &peerKey->u.dh.publicValue,  &dh_Ys))	{            PORT_FreeArena(arena, PR_FALSE);	    goto no_memory;        }    	ss->sec.peerKey = peerKey;	SECITEM_FreeItem(&dh_p,   PR_FALSE);	SECITEM_FreeItem(&dh_g,  PR_FALSE);	SECITEM_FreeItem(&dh_Ys, PR_FALSE);    	ss->ssl3->hs.ws = wait_cert_request;    	return SECSuccess;#ifdef NSS_ENABLE_ECC    case kt_ecdh:	/* XXX This works only for named curves, revisit this when	 * we support generic curves.	 */	ec_params.len = 2;	ec_params.data = (unsigned char*)PORT_Alloc(ec_params.len);    	rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length);    	if (rv != SECSuccess) {	    goto loser;		/* malformed. */	}	/* Fail if the curve is not a named curve */	if ((ec_params.data[0] != ec_type_named) || 	    !supportedCurve(ec_params.data[1])) {		errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;		desc = handshake_failure;		goto alert_loser;	}    	rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length);    	if (rv != SECSuccess) {	    goto loser;		/* malformed. */	}	/* Fail if the ec point uses compressed representation */	if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {		errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;		desc = handshake_failure;		goto alert_loser;	}    	rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);    	if (rv != SECSuccess) {	    goto loser;		/* malformed. */	}    	if (length != 0) {	    if (isTLS)		desc = decode_error;	    goto alert_loser;		/* malformed. */	}	PRINT_BUF(60, (NULL, "Server EC params", ec_params.data, 	    ec_params.len));	PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));	/* failures after this point are not malformed handshakes. */	/* TLS: send decrypt_error if signature failed. */    	desc = isTLS ? decrypt_error : handshake_failure;    	/*     	 *  check to make sure the hash is signed by right guy     	 */    	rv = ssl3_ComputeECDHKeyHash(ec_params, ec_point,					  &ss->ssl3->hs.client_random,					  &ss->ssl3->hs.server_random, &hashes);        if (rv != SECSuccess) {	    errCode =	    	ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);	    goto alert_loser;	}        rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,				    isTLS, ss->pkcs11PinArg);	if (rv != SECSuccess)  {	    errCode =	    	ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);	    goto alert_loser;	}    	arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);	if (arena == NULL) {	    goto no_memory;	}    	ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);    	if (peerKey == NULL) {	    goto no_memory;	}	peerKey->arena                 = arena;	peerKey->keyType               = ecKey;	/* set up EC parameters in peerKey */	if (ecName2params(arena, ec_params.data[1], 	        &peerKey->u.ec.DEREncodedParams) != SECSuccess) {	    /* we should never get here since we already 	     * checked that we are dealing with a supported curve	     */	    errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;	    goto alert_loser;	}	/* copy publicValue in peerKey */	if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue,  &ec_point))	{            PORT_FreeArena(arena, PR_FALSE);	    goto no_memory;        }	peerKey->pkcs11Slot         = NULL;	peerKey->pkcs11ID           = CK_INVALID_HANDLE;    	ss->sec.peerKey = peerKey;	SECITEM_FreeItem(&ec_params, PR_FALSE);	SECITEM_FreeItem(&ec_point, PR_FALSE);    	ss->ssl3->hs.ws = wait_cert_request;	return SECSuccess;#endif /* NSS_ENABLE_ECC */    default:    	desc    = handshake_failure;	errCode = SEC_ERROR_UNSUPPORTED_KEYALG;	break;		/* goto alert_loser; */    }alert_loser:    (void)SSL3_SendAlert(ss, alert_fatal, desc);loser:    if (modulus.data   != NULL) SECITEM_FreeItem(&modulus,   PR_FALSE);    if (exponent.data  != NULL) SECITEM_FreeItem(&exponent,  PR_FALSE);    if (signature.data != NULL) SECITEM_FreeItem(&signature, PR_FALSE);    if (dh_p.data != NULL) SECITEM_FreeItem(&dh_p, PR_FALSE);    if (dh_g.data != NULL) SECITEM_FreeItem(&dh_g, PR_FALSE);    if (dh_Ys.data != NULL) SECITEM_FreeItem(&dh_Ys, PR_FALSE);#ifdef NSS_ENABLE_ECC    if (ec_params.data != NULL) SECITEM_FreeItem(&ec_params, PR_FALSE);    if (ec_point.data != NULL) SECITEM_FreeItem(&ec_point, PR_FALSE);#endif /* NSS_ENABLE_ECC */    PORT_SetError( errCode );    return SECFailure;no_memory:	/* no-memory error has already been set. */    if (modulus.data   != NULL) SECITEM_FreeItem(&modulus,   PR_FALSE);    if (exponent.data  != NULL) SECITEM_FreeItem(&exponent,  PR_FALSE);    if (signature.data != NULL) SECITEM_FreeItem(&signature, PR_FALSE);    if (dh_p.data != NULL) SECITEM_FreeItem(&dh_p, PR_FALSE);    if (dh_g.data != NULL) SECITEM_FreeItem(&dh_g, PR_FALSE);    if (dh_Ys.data != NULL) SECITEM_FreeItem(&dh_Ys, PR_FALSE);#ifdef NSS_ENABLE_ECC    if (ec_params.data != NULL) SECITEM_FreeItem(&ec_params, PR_FALSE);    if (ec_point.data != NULL) SECITEM_FreeItem(&ec_point, PR_FALSE);#endif /* NSS_ENABLE_ECC */    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);    return SECFailure;}