TLS 1.3 client hello issue

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

TLS 1.3 client hello issue

Mahesh Bhoothapuri

Hi,

I am sending a Tls 1.3 client hello, and am seeing an issue with

ossl_statem_client_write_transition in statem_clnt.c.


    /*
     * Note that immediately before/after a ClientHello we don't know what
     * version we are going to negotiate yet, so we don't take this branch until
     * later
     */

/*
 * ossl_statem_client_write_transition() works out what handshake state to
 * move to next when the client is writing messages to be sent to the server.
 */
WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
{

    if (SSL_IS_TLS13(s))
        return ossl_statem_client13_write_transition(s);
}

And in:


/*
 * ossl_statem_client_write_transition() works out what handshake state to
 * move to next when the client is writing messages to be sent to the server.
 */
WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
{

   /*
     * Note: There are no cases for TLS_ST_BEFORE because we haven't negotiated
     * TLSv1.3 yet at that point. They are handled by
     * ossl_statem_client_write_transition().
     */

    switch (st->hand_state) {
    default:
        /* Shouldn't happen */
        return WRITE_TRAN_ERROR;

}

With a TLS 1.3 client hello, using tls 1.3 version, the st->hand_state is TLS_ST_BEFORE and so, the default error is returned.

When I added :

    case TLS_ST_BEFORE:
        st->hand_state = TLS_ST_CW_CLNT_HELLO;
        return WRITE_TRAN_CONTINUE;

The client hello gets sent out, but I only saw a TLS 1.2 version being sent.
Is this a bug?

Thanks,
Mahesh

--
openssl-dev mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Reply | Threaded
Open this post in threaded view
|

Re: TLS 1.3 client hello issue

OpenSSL - Dev mailing list
On 09/18/2017 01:07 AM, Mahesh Bhoothapuri wrote:

Hi,

I am sending a Tls 1.3 client hello, and am seeing an issue with

ossl_statem_client_write_transition in statem_clnt.c.


    /*
     * Note that immediately before/after a ClientHello we don't know what
     * version we are going to negotiate yet, so we don't take this branch until
     * later
     */

/*
 * ossl_statem_client_write_transition() works out what handshake state to
 * move to next when the client is writing messages to be sent to the server.
 */
WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
{

    if (SSL_IS_TLS13(s))
        return ossl_statem_client13_write_transition(s);
}

And in:


/*
 * ossl_statem_client_write_transition() works out what handshake state to
 * move to next when the client is writing messages to be sent to the server.
 */
WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
{

   /*
     * Note: There are no cases for TLS_ST_BEFORE because we haven't negotiated
     * TLSv1.3 yet at that point. They are handled by
     * ossl_statem_client_write_transition().
     */

    switch (st->hand_state) {
    default:
        /* Shouldn't happen */
        return WRITE_TRAN_ERROR;

}

With a TLS 1.3 client hello, using tls 1.3 version, the st->hand_state is

Sorry, I just want to clarify what you are doing -- are you taking SSL_CTX_new(TLS_method()) and then calling SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION) and SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)?

I note that there is no version-specific TLSv1_3_method() available, and in any case, it's of questionable wisdom to attempt to force TLS 1.3 only while the specification is still in draft status -- in any case where the client and server implementations are not tightly controlled, negotiation failures seem quite likely.

TLS_ST_BEFORE and so, the default error is returned.

When I added :

    case TLS_ST_BEFORE:
        st->hand_state = TLS_ST_CW_CLNT_HELLO;
        return WRITE_TRAN_CONTINUE;


The reason there is not currently a case for TLS_ST_BEFORE is that whether or not we're going to be using TLS 1.3 is supposed to be determined on the server as part of version negotiation, so when we're sending a ClientHello, our version is in an indeterminate status -- the general-purpose TLS method must be used at that part of the handshake.

The client hello gets sent out, but I only saw a TLS 1.2 version being sent.
Is this a bug?

The legacy_version field in a TLS 1.3 ClientHello will be 0x0303, matching the historical value for TLS 1.2.  The actual list of versions are conveyed in a "supported_versions" extension, which is what you need to be looking at.

-Ben

--
openssl-dev mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Reply | Threaded
Open this post in threaded view
|

Re: TLS 1.3 client hello issue

Mahesh Bhoothapuri
Thanks for responding.  Yes,  I have done the steps mentioned above.   Here are my settings:

    int min_version = TLS1_3_VERSION, max_version = TLS1_3_VERSION;

    meth = isClient ? tlsv1_3_client_method() : tlsv1_3_server_method();
    //meth = isClient ? TLS_client_method() : TLS_server_method();

    ///////////////////////////////////////////////////////////
    // Create new SSL context using the chosen SSL_METHOD
    ctx = SSL_CTX_new(meth);
    if (ctx == NULL)
    {
        // throw error
    }

    if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
    {
        //  throw error
    }

    if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
    {
        // throw error
    }

    // Configure SSL to use the cipher suite specified
    // TLS1_3_TXT_AES_128_GCM_SHA256
    // ./include/openssl/tls1.h:# define TLS1_3_TXT_AES_128_GCM_SHA256                     "TLS13-AES-128-GCM-SHA256"
    int set_cipher;
    if (! (set_cipher = SSL_CTX_set_cipher_list(ctx, cipherSuite.c_str())) )
    {
        throw (InvalidTestConfiguration("OpenSslApi::OpenSslInitContext",
                    "Failed to set ciphers"));
    }

The set_min_proto/set_max_proto calls succeed.

If I want to get the AES_128_GCM_SHA256 Cipher for TLS 1.3 to be used, are these the steps to be used?

Should I instead, select also, AES128-GCM-SHA256 a TLS 1.2 cipher in the list, and set the min_proto to TLS 1.2, and max_proto to 1.3 ?  I need to avoid hitting the default case below:


static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
{
    OSSL_STATEM *st = &s->statem;
   
    /*
     * Note: There are no cases for TLS_ST_BEFORE because we haven't negotiated
     * TLSv1.3 yet at that point. They are handled by
     * ossl_statem_client_write_transition().
     */
    switch (st->hand_state) {
    default:



"




On Mon, Sep 18, 2017 at 5:40 AM, Benjamin Kaduk <[hidden email]> wrote:
On 09/18/2017 01:07 AM, Mahesh Bhoothapuri wrote:

Hi,

I am sending a Tls 1.3 client hello, and am seeing an issue with

ossl_statem_client_write_transition in statem_clnt.c.


    /*
     * Note that immediately before/after a ClientHello we don't know what
     * version we are going to negotiate yet, so we don't take this branch until
     * later
     */

/*
 * ossl_statem_client_write_transition() works out what handshake state to
 * move to next when the client is writing messages to be sent to the server.
 */
WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
{

    if (SSL_IS_TLS13(s))
        return ossl_statem_client13_write_transition(s);
}

And in:


/*
 * ossl_statem_client_write_transition() works out what handshake state to
 * move to next when the client is writing messages to be sent to the server.
 */
WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
{

   /*
     * Note: There are no cases for TLS_ST_BEFORE because we haven't negotiated
     * TLSv1.3 yet at that point. They are handled by
     * ossl_statem_client_write_transition().
     */

    switch (st->hand_state) {
    default:
        /* Shouldn't happen */
        return WRITE_TRAN_ERROR;

}

With a TLS 1.3 client hello, using tls 1.3 version, the st->hand_state is

Sorry, I just want to clarify what you are doing -- are you taking SSL_CTX_new(TLS_method()) and then calling SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION) and SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)?

I note that there is no version-specific TLSv1_3_method() available, and in any case, it's of questionable wisdom to attempt to force TLS 1.3 only while the specification is still in draft status -- in any case where the client and server implementations are not tightly controlled, negotiation failures seem quite likely.

TLS_ST_BEFORE and so, the default error is returned.

When I added :

    case TLS_ST_BEFORE:
        st->hand_state = TLS_ST_CW_CLNT_HELLO;
        return WRITE_TRAN_CONTINUE;


The reason there is not currently a case for TLS_ST_BEFORE is that whether or not we're going to be using TLS 1.3 is supposed to be determined on the server as part of version negotiation, so when we're sending a ClientHello, our version is in an indeterminate status -- the general-purpose TLS method must be used at that part of the handshake.

The client hello gets sent out, but I only saw a TLS 1.2 version being sent.
Is this a bug?

The legacy_version field in a TLS 1.3 ClientHello will be 0x0303, matching the historical value for TLS 1.2.  The actual list of versions are conveyed in a "supported_versions" extension, which is what you need to be looking at.

-Ben


--
openssl-dev mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Reply | Threaded
Open this post in threaded view
|

Re: TLS 1.3 client hello issue

Matt Caswell-2
Sorry for the slightly slow response on this. I am away this week travelling (https://www.openssl.org/blog/blog/2017/08/28/china/).

Some comments inserted below.

On Mon, 18 Sep 2017 07:25:18 -0700
Mahesh Bhoothapuri <[hidden email]> wrote:

> Thanks for responding.  Yes,  I have done the steps mentioned above.   Here
> are my settings:
>
>     int min_version = TLS1_3_VERSION, max_version = TLS1_3_VERSION;
>
>     meth = isClient ? tlsv1_3_client_method() : tlsv1_3_server_method();

This is *not* correct. These are internal functions that are not exposed via the public header files or exported by the library. You should not be using them at all.

>     //meth = isClient ? TLS_client_method() : TLS_server_method();

This commented out line is corret.

In a private email to me you stated that you are not using enable-tls1_3. You absolutely *must* use that to get TLSv1.3 working.

>
>     ///////////////////////////////////////////////////////////
>     // Create new SSL context using the chosen SSL_METHOD
>     ctx = SSL_CTX_new(meth);
>     if (ctx == NULL)
>     {
>         // throw error
>     }
>
>     if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
>     {
>         //  throw error
>     }
>
>     if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
>     {
>         // throw error
>     }
>
>     // Configure SSL to use the cipher suite specified
>     // TLS1_3_TXT_AES_128_GCM_SHA256
>     // ./include/openssl/tls1.h:# define
> TLS1_3_TXT_AES_128_GCM_SHA256                     "TLS13-AES-128-GCM-SHA256"
>     int set_cipher;
>     if (! (set_cipher = SSL_CTX_set_cipher_list(ctx, cipherSuite.c_str())) )
>     {
>         throw (InvalidTestConfiguration("OpenSslApi::OpenSslInitContext",
>                     "Failed to set ciphers"));
>     }
>
> The set_min_proto/set_max_proto calls succeed.
>
> If I want to get the AES_128_GCM_SHA256 Cipher for TLS 1.3 to be used, are
> these the steps to be used?

Well I can't see what cipherSuite.c_str() does, but it looks ok.

>
> Should I instead, select also, AES128-GCM-SHA256 a TLS 1.2 cipher in the
> list, and set the min_proto to TLS 1.2, and max_proto to 1.3 ?

It depends. If both client and server are guaranteed to support TLSv1.3 then you don't need to support TLSv1.2 ciphersuites as well and you can set min and max to 1.3. If however you want to be able to fallback to TLSv1.2 (or below) then you should set min appropriately (to something less than 1.3).

>  I need to
> avoid hitting the default case below:

You are hitting this default case because you are not doing it right. You must not call the internal functions above. Build with enable-tls1_3 and TLS_client_method() and TLS_server_method() will start trying to negotiate TLSv1.3

I believe you would benefit from reading this blog post:

https://www.openssl.org/blog/blog/2017/05/04/tlsv1.3/

Matt



>
>
> static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
> {
>     OSSL_STATEM *st = &s->statem;
>
>     /*
>      * Note: There are no cases for TLS_ST_BEFORE because we haven't
> negotiated
>      * TLSv1.3 yet at that point. They are handled by
>      * ossl_statem_client_write_transition().
>      */
>     switch (st->hand_state) {
>     default:
>
>
>
> "
>
>
>
>
> On Mon, Sep 18, 2017 at 5:40 AM, Benjamin Kaduk <[hidden email]> wrote:
>
> > On 09/18/2017 01:07 AM, Mahesh Bhoothapuri wrote:
> >
> > Hi,
> >
> > I am sending a Tls 1.3 client hello, and am seeing an issue with
> >
> > ossl_statem_client_write_transition in statem_clnt.c.
> >
> >
> >     /*
> >      * Note that immediately before/after a ClientHello we don't know what
> >      * version we are going to negotiate yet, so we don't take this branch
> > until
> >      * later
> >      */
> >
> > /*
> >  * ossl_statem_client_write_transition() works out what handshake state to
> >  * move to next when the client is writing messages to be sent to the
> > server.
> >  */
> > WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
> > {
> >
> >     if (SSL_IS_TLS13(s))
> >         return ossl_statem_client13_write_transition(s);
> > }
> >
> > And in:
> >
> >
> > /*
> >  * ossl_statem_client_write_transition() works out what handshake state to
> >  * move to next when the client is writing messages to be sent to the
> > server.
> >  */
> > WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
> > {
> >
> >    /*
> >      * Note: There are no cases for TLS_ST_BEFORE because we haven't
> > negotiated
> >      * TLSv1.3 yet at that point. They are handled by
> >      * ossl_statem_client_write_transition().
> >      */
> >
> >     switch (st->hand_state) {
> >     default:
> >         /* Shouldn't happen */
> >         return WRITE_TRAN_ERROR;
> >
> > }
> >
> > With a TLS 1.3 client hello, using tls 1.3 version, the st->hand_state is
> >
> >
> > Sorry, I just want to clarify what you are doing -- are you taking
> > SSL_CTX_new(TLS_method()) and then calling SSL_CTX_set_min_proto_version(ctx,
> > TLS1_3_VERSION) and SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)?
> >
> > I note that there is no version-specific TLSv1_3_method() available, and
> > in any case, it's of questionable wisdom to attempt to force TLS 1.3 only
> > while the specification is still in draft status -- in any case where the
> > client and server implementations are not tightly controlled, negotiation
> > failures seem quite likely.
> >
> > TLS_ST_BEFORE and so, the default error is returned.
> >
> > When I added :
> >
> >     case TLS_ST_BEFORE:
> >         st->hand_state = TLS_ST_CW_CLNT_HELLO;
> >         return WRITE_TRAN_CONTINUE;
> >
> >
> > The reason there is not currently a case for TLS_ST_BEFORE is that whether
> > or not we're going to be using TLS 1.3 is supposed to be determined on the
> > server as part of version negotiation, so when we're sending a ClientHello,
> > our version is in an indeterminate status -- the general-purpose TLS method
> > must be used at that part of the handshake.
> >
> > The client hello gets sent out, but I only saw a TLS 1.2 version being
> > sent.
> > Is this a bug?
> >
> >
> > The legacy_version field in a TLS 1.3 ClientHello will be 0x0303, matching
> > the historical value for TLS 1.2.  The actual list of versions are conveyed
> > in a "supported_versions" extension, which is what you need to be looking
> > at.
> >
> > -Ben
> >


--
Matt Caswell <[hidden email]>
--
openssl-dev mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Reply | Threaded
Open this post in threaded view
|

Re: TLS 1.3 client hello issue

Mahesh Bhoothapuri
After enabling tls1.3,  and uncommenting
 //meth = isClient ? TLS_client_method() : TLS_server_method();

the handshake does succeed.  

The client version is still TLS 1.2, but it does contain the cipher suite configured.
Confirmed this using the TLS 1.3 version of wireshark.
The Server is responding with a Hello Retry request with TLS 1.3.   The RFC says that this is caused by a mismatched configuration.
The client hello contains the Key Share Extension - with group x22519.

Looking into how to configure the groups so that the Server does not need to send a Hello Retry request.

Thanks,
Mahesh


On Mon, Sep 18, 2017 at 7:56 AM, Matt Caswell <[hidden email]> wrote:
Sorry for the slightly slow response on this. I am away this week travelling (https://www.openssl.org/blog/blog/2017/08/28/china/).

Some comments inserted below.

On Mon, 18 Sep 2017 07:25:18 -0700
Mahesh Bhoothapuri <[hidden email]> wrote:

> Thanks for responding.  Yes,  I have done the steps mentioned above.   Here
> are my settings:
>
>     int min_version = TLS1_3_VERSION, max_version = TLS1_3_VERSION;
>
>     meth = isClient ? tlsv1_3_client_method() : tlsv1_3_server_method();

This is *not* correct. These are internal functions that are not exposed via the public header files or exported by the library. You should not be using them at all.

>     //meth = isClient ? TLS_client_method() : TLS_server_method();

This commented out line is corret.

In a private email to me you stated that you are not using enable-tls1_3. You absolutely *must* use that to get TLSv1.3 working.

>
>     ///////////////////////////////////////////////////////////
>     // Create new SSL context using the chosen SSL_METHOD
>     ctx = SSL_CTX_new(meth);
>     if (ctx == NULL)
>     {
>         // throw error
>     }
>
>     if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
>     {
>         //  throw error
>     }
>
>     if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
>     {
>         // throw error
>     }
>
>     // Configure SSL to use the cipher suite specified
>     // TLS1_3_TXT_AES_128_GCM_SHA256
>     // ./include/openssl/tls1.h:# define
> TLS1_3_TXT_AES_128_GCM_SHA256                     "TLS13-AES-128-GCM-SHA256"
>     int set_cipher;
>     if (! (set_cipher = SSL_CTX_set_cipher_list(ctx, cipherSuite.c_str())) )
>     {
>         throw (InvalidTestConfiguration("OpenSslApi::OpenSslInitContext",
>                     "Failed to set ciphers"));
>     }
>
> The set_min_proto/set_max_proto calls succeed.
>
> If I want to get the AES_128_GCM_SHA256 Cipher for TLS 1.3 to be used, are
> these the steps to be used?

Well I can't see what cipherSuite.c_str() does, but it looks ok.

>
> Should I instead, select also, AES128-GCM-SHA256 a TLS 1.2 cipher in the
> list, and set the min_proto to TLS 1.2, and max_proto to 1.3 ?

It depends. If both client and server are guaranteed to support TLSv1.3 then you don't need to support TLSv1.2 ciphersuites as well and you can set min and max to 1.3. If however you want to be able to fallback to TLSv1.2 (or below) then you should set min appropriately (to something less than 1.3).

>  I need to
> avoid hitting the default case below:

You are hitting this default case because you are not doing it right. You must not call the internal functions above. Build with enable-tls1_3 and TLS_client_method() and TLS_server_method() will start trying to negotiate TLSv1.3

I believe you would benefit from reading this blog post:

https://www.openssl.org/blog/blog/2017/05/04/tlsv1.3/

Matt



>
>
> static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
> {
>     OSSL_STATEM *st = &s->statem;
>
>     /*
>      * Note: There are no cases for TLS_ST_BEFORE because we haven't
> negotiated
>      * TLSv1.3 yet at that point. They are handled by
>      * ossl_statem_client_write_transition().
>      */
>     switch (st->hand_state) {
>     default:
>
>
>
> "
>
>
>
>
> On Mon, Sep 18, 2017 at 5:40 AM, Benjamin Kaduk <[hidden email]> wrote:
>
> > On 09/18/2017 01:07 AM, Mahesh Bhoothapuri wrote:
> >
> > Hi,
> >
> > I am sending a Tls 1.3 client hello, and am seeing an issue with
> >
> > ossl_statem_client_write_transition in statem_clnt.c.
> >
> >
> >     /*
> >      * Note that immediately before/after a ClientHello we don't know what
> >      * version we are going to negotiate yet, so we don't take this branch
> > until
> >      * later
> >      */
> >
> > /*
> >  * ossl_statem_client_write_transition() works out what handshake state to
> >  * move to next when the client is writing messages to be sent to the
> > server.
> >  */
> > WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
> > {
> >
> >     if (SSL_IS_TLS13(s))
> >         return ossl_statem_client13_write_transition(s);
> > }
> >
> > And in:
> >
> >
> > /*
> >  * ossl_statem_client_write_transition() works out what handshake state to
> >  * move to next when the client is writing messages to be sent to the
> > server.
> >  */
> > WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
> > {
> >
> >    /*
> >      * Note: There are no cases for TLS_ST_BEFORE because we haven't
> > negotiated
> >      * TLSv1.3 yet at that point. They are handled by
> >      * ossl_statem_client_write_transition().
> >      */
> >
> >     switch (st->hand_state) {
> >     default:
> >         /* Shouldn't happen */
> >         return WRITE_TRAN_ERROR;
> >
> > }
> >
> > With a TLS 1.3 client hello, using tls 1.3 version, the st->hand_state is
> >
> >
> > Sorry, I just want to clarify what you are doing -- are you taking
> > SSL_CTX_new(TLS_method()) and then calling SSL_CTX_set_min_proto_version(ctx,
> > TLS1_3_VERSION) and SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)?
> >
> > I note that there is no version-specific TLSv1_3_method() available, and
> > in any case, it's of questionable wisdom to attempt to force TLS 1.3 only
> > while the specification is still in draft status -- in any case where the
> > client and server implementations are not tightly controlled, negotiation
> > failures seem quite likely.
> >
> > TLS_ST_BEFORE and so, the default error is returned.
> >
> > When I added :
> >
> >     case TLS_ST_BEFORE:
> >         st->hand_state = TLS_ST_CW_CLNT_HELLO;
> >         return WRITE_TRAN_CONTINUE;
> >
> >
> > The reason there is not currently a case for TLS_ST_BEFORE is that whether
> > or not we're going to be using TLS 1.3 is supposed to be determined on the
> > server as part of version negotiation, so when we're sending a ClientHello,
> > our version is in an indeterminate status -- the general-purpose TLS method
> > must be used at that part of the handshake.
> >
> > The client hello gets sent out, but I only saw a TLS 1.2 version being
> > sent.
> > Is this a bug?
> >
> >
> > The legacy_version field in a TLS 1.3 ClientHello will be 0x0303, matching
> > the historical value for TLS 1.2.  The actual list of versions are conveyed
> > in a "supported_versions" extension, which is what you need to be looking
> > at.
> >
> > -Ben
> >


--
Matt Caswell <[hidden email]>


--
openssl-dev mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Reply | Threaded
Open this post in threaded view
|

Re: TLS 1.3 client hello issue

Matt Caswell-2
On Tue, 19 Sep 2017 06:05:21 -0700
Mahesh Bhoothapuri <[hidden email]> wrote:

> The client version is still TLS 1.2, but it does contain the cipher suite
> configured.

This is correct behaviour for a TLS1.3 ClientHello. The client_version field is
considered "legacy" and is unused in TLSv1.3 version negotiation and is always set to TLSv1.2.

Matt

--
Matt Caswell <[hidden email]>
--
openssl-dev mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev