X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=44b9c9cdac35d70c84c7f64367db37b0e385fa5b;hp=b1fff12191f6279586be5cdf762d0012fe2a9af0;hb=c7474d077bbb502d0e774d000b74a82121f5e7cf;hpb=00a357ab203b4153eee970ffb33f0f22ef59f734 diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index b1fff12191..44b9c9cdac 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ /* ==================================================================== - * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -117,19 +117,6 @@ * The Contribution is licensed pursuant to the OpenSSL open source * license provided above. * - * In addition, Sun covenants to all licensees who provide a reciprocal - * covenant with respect to their own patents if any, not to sue under - * current and future patent claims necessarily infringed by the making, - * using, practicing, selling, offering for sale and/or otherwise - * disposing of the Contribution as delivered hereunder - * (or portions thereof), provided that such covenant shall not apply: - * 1) for code that a licensee deletes from the Contribution; - * 2) separates from the Contribution; or - * 3) for infringements caused by: - * i) the modification of the Contribution or - * ii) the combination of the Contribution with other software or - * devices where such combination causes the infringement. - * * ECC cipher suite support in OpenSSL originally written by * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. * @@ -146,27 +133,22 @@ #include #include #include +#ifndef OPENSSL_NO_DH +#include +#endif +#include +#ifndef OPENSSL_NO_KRB5 #include +#endif #include -#include "cryptlib.h" - -static SSL_METHOD *ssl3_get_server_method(int ver); -static int ssl3_get_client_hello(SSL *s); -static int ssl3_check_client_hello(SSL *s); -static int ssl3_send_server_hello(SSL *s); -static int ssl3_send_server_key_exchange(SSL *s); -static int ssl3_send_certificate_request(SSL *s); -static int ssl3_send_server_done(SSL *s); -static int ssl3_get_client_key_exchange(SSL *s); -static int ssl3_get_client_certificate(SSL *s); -static int ssl3_get_cert_verify(SSL *s); -static int ssl3_send_hello_request(SSL *s); + +static const SSL_METHOD *ssl3_get_server_method(int ver); #ifndef OPENSSL_NO_ECDH static int nid2curve_id(int nid); #endif -static SSL_METHOD *ssl3_get_server_method(int ver) +static const SSL_METHOD *ssl3_get_server_method(int ver) { if (ver == SSL3_VERSION) return(SSLv3_server_method()); @@ -174,33 +156,15 @@ static SSL_METHOD *ssl3_get_server_method(int ver) return(NULL); } -SSL_METHOD *SSLv3_server_method(void) - { - static int init=1; - static SSL_METHOD SSLv3_server_data; - - if (init) - { - CRYPTO_w_lock(CRYPTO_LOCK_SSL_METHOD); - - if (init) - { - memcpy((char *)&SSLv3_server_data,(char *)sslv3_base_method(), - sizeof(SSL_METHOD)); - SSLv3_server_data.ssl_accept=ssl3_accept; - SSLv3_server_data.get_ssl_method=ssl3_get_server_method; - init=0; - } - - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_METHOD); - } - return(&SSLv3_server_data); - } +IMPLEMENT_ssl3_meth_func(SSLv3_server_method, + ssl3_accept, + ssl_undefined_function, + ssl3_get_server_method) int ssl3_accept(SSL *s) { BUF_MEM *buf; - unsigned long l,Time=time(NULL); + unsigned long l,Time=(unsigned long)time(NULL); void (*cb)(const SSL *ssl,int type,int val)=NULL; long num1; int ret= -1; @@ -317,6 +281,7 @@ int ssl3_accept(SSL *s) s->shutdown=0; ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; + s->new_session = 2; s->state=SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; @@ -469,10 +434,11 @@ int ssl3_accept(SSL *s) if (ret == 2) s->state = SSL3_ST_SR_CLNT_HELLO_C; else { - /* could be sent for a DH cert, even if we - * have not asked for it :-) */ - ret=ssl3_get_client_certificate(s); - if (ret <= 0) goto end; + if (s->s3->tmp.cert_request) + { + ret=ssl3_get_client_certificate(s); + if (ret <= 0) goto end; + } s->init_num=0; s->state=SSL3_ST_SR_KEY_EXCH_A; } @@ -638,7 +604,7 @@ end: return(ret); } -static int ssl3_send_hello_request(SSL *s) +int ssl3_send_hello_request(SSL *s) { unsigned char *p; @@ -660,14 +626,14 @@ static int ssl3_send_hello_request(SSL *s) return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -static int ssl3_check_client_hello(SSL *s) +int ssl3_check_client_hello(SSL *s) { int ok; long n; /* this function is called when we really expect a Certificate message, * so permit appropriate message length */ - n=ssl3_get_message(s, + n=s->method->ssl_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, -1, @@ -693,14 +659,17 @@ static int ssl3_check_client_hello(SSL *s) return 1; } -static int ssl3_get_client_hello(SSL *s) +int ssl3_get_client_hello(SSL *s) { int i,j,ok,al,ret= -1; + unsigned int cookie_len; long n; unsigned long id; unsigned char *p,*d,*q; SSL_CIPHER *c; +#ifndef OPENSSL_NO_COMP SSL_COMP *comp=NULL; +#endif STACK_OF(SSL_CIPHER) *ciphers=NULL; /* We do this so that we will respond with our native type. @@ -714,7 +683,7 @@ static int ssl3_get_client_hello(SSL *s) s->first_packet=1; s->state=SSL3_ST_SR_CLNT_HELLO_B; } - n=ssl3_get_message(s, + n=s->method->ssl_get_message(s, SSL3_ST_SR_CLNT_HELLO_B, SSL3_ST_SR_CLNT_HELLO_C, SSL3_MT_CLIENT_HELLO, @@ -779,6 +748,68 @@ static int ssl3_get_client_hello(SSL *s) } p+=j; + + if (SSL_version(s) == DTLS1_VERSION) + { + /* cookie stuff */ + cookie_len = *(p++); + + if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && + s->d1->send_cookie == 0) + { + /* HelloVerifyMessage has already been sent */ + if ( cookie_len != s->d1->cookie_len) + { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); + goto f_err; + } + } + + /* + * The ClientHello may contain a cookie even if the + * HelloVerify message has not been sent--make sure that it + * does not cause an overflow. + */ + if ( cookie_len > sizeof(s->d1->rcvd_cookie)) + { + /* too much data */ + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); + goto f_err; + } + + /* verify the cookie if appropriate option is set. */ + if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && + cookie_len > 0) + { + memcpy(s->d1->rcvd_cookie, p, cookie_len); + + if ( s->ctx->app_verify_cookie_cb != NULL) + { + if ( s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie, + cookie_len) == 0) + { + al=SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_COOKIE_MISMATCH); + goto f_err; + } + /* else cookie verification succeeded */ + } + else if ( memcmp(s->d1->rcvd_cookie, s->d1->cookie, + s->d1->cookie_len) != 0) /* default verification */ + { + al=SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_COOKIE_MISMATCH); + goto f_err; + } + } + + p += cookie_len; + } + n2s(p,i); if ((i == 0) && (j != 0)) { @@ -828,8 +859,7 @@ static int ssl3_get_client_hello(SSL *s) if ((s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) && (sk_SSL_CIPHER_num(ciphers) == 1)) { /* Very bad for multi-threading.... */ - s->session->cipher=sk_SSL_CIPHER_value(ciphers, - 0); + s->session->cipher=sk_SSL_CIPHER_value(ciphers, 0); } else { @@ -866,11 +896,29 @@ static int ssl3_get_client_hello(SSL *s) goto f_err; } +#ifndef OPENSSL_NO_TLSEXT + /* TLS extensions*/ + if (s->version > SSL3_VERSION) + { + if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al)) + { + /* 'al' set by ssl_parse_clienthello_tlsext */ + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLS_EXT); + goto f_err; + } + } + if (ssl_check_tlsext(s,1) <= 0) { + SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_CLIENTHELLO_TLS_EXT); + goto err; + } +#endif + /* Worst case, we will use the NULL compression, but if we have other * options, we will now look for them. We have i-1 compression * algorithms from the client, starting at q. */ s->s3->tmp.new_compression=NULL; - if (s->ctx->comp_methods != NULL) +#ifndef OPENSSL_NO_COMP + if (!(s->options & SSL_OP_NO_COMPRESSION) && s->ctx->comp_methods) { /* See if we have a match */ int m,nn,o,v,done=0; @@ -894,26 +942,18 @@ static int ssl3_get_client_hello(SSL *s) else comp=NULL; } - - /* TLS does not mind if there is extra stuff */ - if (s->version == SSL3_VERSION) - { - if (p < (d+n)) - { - /* wrong number of bytes, - * there could be more to follow */ - al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH); - goto f_err; - } - } +#endif /* Given s->session->ciphers and SSL_get_ciphers, we must * pick a cipher */ if (!s->hit) { +#ifdef OPENSSL_NO_COMP + s->session->compress_meth=0; +#else s->session->compress_meth=(comp == NULL)?0:comp->id; +#endif if (s->session->ciphers != NULL) sk_SSL_CIPHER_free(s->session->ciphers); s->session->ciphers=ciphers; @@ -988,7 +1028,7 @@ err: return(ret); } -static int ssl3_send_server_hello(SSL *s) +int ssl3_send_server_hello(SSL *s) { unsigned char *buf; unsigned char *p,*d; @@ -999,9 +1039,10 @@ static int ssl3_send_server_hello(SSL *s) { buf=(unsigned char *)s->init_buf->data; p=s->s3->server_random; - Time=time(NULL); /* Time */ + Time=(unsigned long)time(NULL); /* Time */ l2n(Time,p); - RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time)); + if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) + return -1; /* Do the message type and length last */ d=p= &(buf[4]); @@ -1024,7 +1065,7 @@ static int ssl3_send_server_hello(SSL *s) s->session->session_id_length=0; sl=s->session->session_id_length; - if (sl > sizeof s->session->session_id) + if (sl > (int)sizeof(s->session->session_id)) { SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR); return -1; @@ -1038,10 +1079,21 @@ static int ssl3_send_server_hello(SSL *s) p+=i; /* put the compression method */ +#ifdef OPENSSL_NO_COMP + *(p++)=0; +#else if (s->s3->tmp.new_compression == NULL) *(p++)=0; else *(p++)=s->s3->tmp.new_compression->id; +#endif +#ifndef OPENSSL_NO_TLSEXT + if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) + { + SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR); + return -1; + } +#endif /* do the header */ l=(p-d); @@ -1059,7 +1111,7 @@ static int ssl3_send_server_hello(SSL *s) return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -static int ssl3_send_server_done(SSL *s) +int ssl3_send_server_done(SSL *s) { unsigned char *p; @@ -1083,7 +1135,7 @@ static int ssl3_send_server_done(SSL *s) return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -static int ssl3_send_server_key_exchange(SSL *s) +int ssl3_send_server_key_exchange(SSL *s) { #ifndef OPENSSL_NO_RSA unsigned char *q; @@ -1213,6 +1265,8 @@ static int ssl3_send_server_key_exchange(SSL *s) #ifndef OPENSSL_NO_ECDH if (type & SSL_kECDHE) { + const EC_GROUP *group; + ecdhp=cert->ecdh_tmp; if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL)) { @@ -1242,14 +1296,14 @@ static int ssl3_send_server_key_exchange(SSL *s) } if (!EC_KEY_up_ref(ecdhp)) { - SSLerr(SSL_F_SSL3_CTRL,ERR_R_ECDH_LIB); + SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } ecdh = ecdhp; s->s3->tmp.ecdh=ecdh; - if ((ecdh->pub_key == NULL) || - (ecdh->priv_key == NULL) || + if ((EC_KEY_get0_public_key(ecdh) == NULL) || + (EC_KEY_get0_private_key(ecdh) == NULL) || (s->options & SSL_OP_SINGLE_ECDH_USE)) { if(!EC_KEY_generate_key(ecdh)) @@ -1259,16 +1313,16 @@ static int ssl3_send_server_key_exchange(SSL *s) } } - if ((ecdh->group == NULL) || - (ecdh->pub_key == NULL) || - (ecdh->priv_key == NULL)) + if (((group = EC_KEY_get0_group(ecdh)) == NULL) || + (EC_KEY_get0_public_key(ecdh) == NULL) || + (EC_KEY_get0_private_key(ecdh) == NULL)) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && - (EC_GROUP_get_degree(ecdh->group) > 163)) + (EC_GROUP_get_degree(group) > 163)) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER); goto err; @@ -1279,7 +1333,7 @@ static int ssl3_send_server_key_exchange(SSL *s) * supported named curves, curve_id is non-zero. */ if ((curve_id = - nid2curve_id(EC_GROUP_get_nid(ecdh->group))) + nid2curve_id(EC_GROUP_get_curve_name(group))) == 0) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); @@ -1290,8 +1344,8 @@ static int ssl3_send_server_key_exchange(SSL *s) * First check the size of encoding and * allocate memory accordingly. */ - encodedlen = EC_POINT_point2oct(ecdh->group, - ecdh->pub_key, + encodedlen = EC_POINT_point2oct(group, + EC_KEY_get0_public_key(ecdh), POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); @@ -1305,8 +1359,8 @@ static int ssl3_send_server_key_exchange(SSL *s) } - encodedlen = EC_POINT_point2oct(ecdh->group, - ecdh->pub_key, + encodedlen = EC_POINT_point2oct(group, + EC_KEY_get0_public_key(ecdh), POINT_CONVERSION_UNCOMPRESSED, encodedPoint, encodedlen, bn_ctx); @@ -1320,11 +1374,11 @@ static int ssl3_send_server_key_exchange(SSL *s) /* XXX: For now, we only support named (not * generic) curves in ECDH ephemeral key exchanges. - * In this situation, we need three additional bytes + * In this situation, we need four additional bytes * to encode the entire ServerECDHParams * structure. */ - n = 3 + encodedlen; + n = 4 + encodedlen; /* We'll generate the serverKeyExchange message * explicitly so we can set these to NULLs @@ -1332,6 +1386,7 @@ static int ssl3_send_server_key_exchange(SSL *s) r[0]=NULL; r[1]=NULL; r[2]=NULL; + r[3]=NULL; } else #endif /* !OPENSSL_NO_ECDH */ @@ -1362,7 +1417,7 @@ static int ssl3_send_server_key_exchange(SSL *s) kn=0; } - if (!BUF_MEM_grow(buf,n+4+kn)) + if (!BUF_MEM_grow_clean(buf,n+4+kn)) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF); goto err; @@ -1382,12 +1437,14 @@ static int ssl3_send_server_key_exchange(SSL *s) { /* XXX: For now, we only support named (not generic) curves. * In this situation, the serverKeyExchange message has: - * [1 byte CurveType], [1 byte CurveName] + * [1 byte CurveType], [2 byte CurveName] * [1 byte length of encoded point], followed by * the actual encoded point itself */ *p = NAMED_CURVE_TYPE; p += 1; + *p = 0; + p += 1; *p = curve_id; p += 1; *p = encodedlen; @@ -1502,7 +1559,7 @@ err: return(-1); } -static int ssl3_send_certificate_request(SSL *s) +int ssl3_send_certificate_request(SSL *s) { unsigned char *p,*d; int i,j,nl,off,n; @@ -1535,7 +1592,7 @@ static int ssl3_send_certificate_request(SSL *s) { name=sk_X509_NAME_value(sk,i); j=i2d_X509_NAME(name,NULL); - if (!BUF_MEM_grow(buf,4+n+j+2)) + if (!BUF_MEM_grow_clean(buf,4+n+j+2)) { SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB); goto err; @@ -1582,6 +1639,7 @@ static int ssl3_send_certificate_request(SSL *s) s->init_num += 4; #endif + s->state = SSL3_ST_SW_CERT_REQ_B; } /* SSL3_ST_SW_CERT_REQ_B */ @@ -1590,7 +1648,7 @@ err: return(-1); } -static int ssl3_get_client_key_exchange(SSL *s) +int ssl3_get_client_key_exchange(SSL *s) { int i,al,ok; long n; @@ -1615,7 +1673,7 @@ static int ssl3_get_client_key_exchange(SSL *s) BN_CTX *bn_ctx = NULL; #endif - n=ssl3_get_message(s, + n=s->method->ssl_get_message(s, SSL3_ST_SR_KEY_EXCH_A, SSL3_ST_SR_KEY_EXCH_B, SSL3_MT_CLIENT_KEY_EXCHANGE, @@ -1684,7 +1742,7 @@ static int ssl3_get_client_key_exchange(SSL *s) if (i != SSL_MAX_MASTER_KEY_LENGTH) { al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); + /* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT); */ } if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff)))) @@ -1700,37 +1758,36 @@ static int ssl3_get_client_key_exchange(SSL *s) (p[0] == (s->version>>8)) && (p[1] == (s->version & 0xff)))) { al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); - goto f_err; + /* SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_PROTOCOL_VERSION_NUMBER); */ + + /* The Klima-Pokorny-Rosa extension of Bleichenbacher's attack + * (http://eprint.iacr.org/2003/052/) exploits the version + * number check as a "bad version oracle" -- an alert would + * reveal that the plaintext corresponding to some ciphertext + * made up by the adversary is properly formatted except + * that the version number is wrong. To avoid such attacks, + * we should treat this just like any other decryption error. */ } } if (al != -1) { -#if 0 - goto f_err; -#else /* Some decryption failure -- use random value instead as countermeasure * against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding - * (see RFC 2246, section 7.4.7.1). - * But note that due to length and protocol version checking, the - * attack is impractical anyway (see section 5 in D. Bleichenbacher: - * "Chosen Ciphertext Attacks Against Protocols Based on the RSA - * Encryption Standard PKCS #1", CRYPTO '98, LNCS 1462, pp. 1-12). - */ + * (see RFC 2246, section 7.4.7.1). */ ERR_clear_error(); i = SSL_MAX_MASTER_KEY_LENGTH; p[0] = s->client_version >> 8; p[1] = s->client_version & 0xff; - RAND_pseudo_bytes(p+2, i-2); /* should be RAND_bytes, but we cannot work around a failure */ -#endif + if (RAND_pseudo_bytes(p+2, i-2) <= 0) /* should be RAND_bytes, but we cannot work around a failure */ + goto err; } s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key, p,i); - memset(p,0,i); + OPENSSL_cleanse(p,i); } else #endif @@ -1793,7 +1850,7 @@ static int ssl3_get_client_key_exchange(SSL *s) s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key,p,i); - memset(p,0,i); + OPENSSL_cleanse(p,i); } else #endif @@ -1820,11 +1877,27 @@ static int ssl3_get_client_key_exchange(SSL *s) n2s(p,i); enc_ticket.length = i; + + if (n < enc_ticket.length + 6) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + enc_ticket.data = (char *)p; p+=enc_ticket.length; n2s(p,i); authenticator.length = i; + + if (n < enc_ticket.length + authenticator.length + 6) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + authenticator.data = (char *)p; p+=authenticator.length; @@ -1843,8 +1916,8 @@ static int ssl3_get_client_key_exchange(SSL *s) goto err; } - if (n != enc_ticket.length + authenticator.length + - enc_pms.length + 6) + if (n != (long)(enc_ticket.length + authenticator.length + + enc_pms.length + 6)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); @@ -1860,7 +1933,7 @@ static int ssl3_get_client_key_exchange(SSL *s) if (kssl_err.text) printf("kssl_err text= %s\n", kssl_err.text); #endif /* KSSL_DEBUG */ - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, kssl_err.reason); goto err; } @@ -1877,14 +1950,14 @@ static int ssl3_get_client_key_exchange(SSL *s) if (kssl_err.text) printf("kssl_err text= %s\n", kssl_err.text); #endif /* KSSL_DEBUG */ - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, kssl_err.reason); goto err; } if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0) { - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, krb5rc); + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, krb5rc); goto err; } @@ -1896,7 +1969,7 @@ static int ssl3_get_client_key_exchange(SSL *s) if (enc == NULL) goto err; - memset(iv, 0, EVP_MAX_IV_LENGTH); /* per RFC 1510 */ + memset(iv, 0, sizeof iv); /* per RFC 1510 */ if (!EVP_DecryptInit_ex(&ciph_ctx,enc,NULL,kssl_ctx->key,iv)) { @@ -1960,6 +2033,10 @@ static int ssl3_get_client_key_exchange(SSL *s) if ((l & SSL_kECDH) || (l & SSL_kECDHE)) { int ret = 1; + int field_size = 0; + const EC_KEY *tkey; + const EC_GROUP *group; + const BIGNUM *priv_key; /* initialize structures for server's ECDH key pair */ if ((srvr_ecdh = EC_KEY_new()) == NULL) @@ -1973,23 +2050,29 @@ static int ssl3_get_client_key_exchange(SSL *s) if (l & SSL_kECDH) { /* use the certificate */ - srvr_ecdh->group = s->cert->key->privatekey-> \ - pkey.eckey->group; - srvr_ecdh->priv_key = s->cert->key->privatekey-> \ - pkey.eckey->priv_key; + tkey = s->cert->key->privatekey->pkey.ec; } else { /* use the ephermeral values we saved when * generating the ServerKeyExchange msg. */ - srvr_ecdh->group = s->s3->tmp.ecdh->group; - srvr_ecdh->priv_key = s->s3->tmp.ecdh->priv_key; + tkey = s->s3->tmp.ecdh; + } + + group = EC_KEY_get0_group(tkey); + priv_key = EC_KEY_get0_private_key(tkey); + + if (!EC_KEY_set_group(srvr_ecdh, group) || + !EC_KEY_set_private_key(srvr_ecdh, priv_key)) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_EC_LIB); + goto err; } /* Let's get client's public key */ - if ((clnt_ecpoint = EC_POINT_new(srvr_ecdh->group)) - == NULL) + if ((clnt_ecpoint = EC_POINT_new(group)) == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE); @@ -2027,8 +2110,13 @@ static int ssl3_get_client_key_exchange(SSL *s) goto f_err; } - EC_POINT_copy(clnt_ecpoint, - clnt_pub_pkey->pkey.eckey->pub_key); + if (EC_POINT_copy(clnt_ecpoint, + EC_KEY_get0_public_key(clnt_pub_pkey->pkey.ec)) == 0) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_EC_LIB); + goto err; + } ret = 2; /* Skip certificate verify processing */ } else @@ -2046,7 +2134,7 @@ static int ssl3_get_client_key_exchange(SSL *s) /* Get encoded point length */ i = *p; p += 1; - if (EC_POINT_oct2point(srvr_ecdh->group, + if (EC_POINT_oct2point(group, clnt_ecpoint, p, i, bn_ctx) == 0) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, @@ -2060,7 +2148,14 @@ static int ssl3_get_client_key_exchange(SSL *s) } /* Compute the shared pre-master secret */ - i = ECDH_compute_key(p, clnt_ecpoint, srvr_ecdh); + field_size = EC_GROUP_get_degree(group); + if (field_size <= 0) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + ERR_R_ECDH_LIB); + goto err; + } + i = ECDH_compute_key(p, (field_size+7)/8, clnt_ecpoint, srvr_ecdh, NULL); if (i <= 0) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, @@ -2071,18 +2166,14 @@ static int ssl3_get_client_key_exchange(SSL *s) EVP_PKEY_free(clnt_pub_pkey); EC_POINT_free(clnt_ecpoint); if (srvr_ecdh != NULL) - { - srvr_ecdh->priv_key = NULL; - srvr_ecdh->group = NULL; EC_KEY_free(srvr_ecdh); - } BN_CTX_free(bn_ctx); /* Compute the master secret */ s->session->master_key_length = s->method->ssl3_enc-> \ generate_master_secret(s, s->session->master_key, p, i); - memset(p, 0, i); + OPENSSL_cleanse(p, i); return (ret); } else @@ -2100,21 +2191,17 @@ f_err: #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_ECDH) err: #endif -#ifndef NO_OPENSSL_ECDH +#ifndef OPENSSL_NO_ECDH EVP_PKEY_free(clnt_pub_pkey); EC_POINT_free(clnt_ecpoint); if (srvr_ecdh != NULL) - { - srvr_ecdh->priv_key = NULL; - srvr_ecdh->group = NULL; EC_KEY_free(srvr_ecdh); - } BN_CTX_free(bn_ctx); #endif return(-1); } -static int ssl3_get_cert_verify(SSL *s) +int ssl3_get_cert_verify(SSL *s) { EVP_PKEY *pkey=NULL; unsigned char *p; @@ -2123,7 +2210,7 @@ static int ssl3_get_cert_verify(SSL *s) int type=0,i,j; X509 *peer; - n=ssl3_get_message(s, + n=s->method->ssl_get_message(s, SSL3_ST_SR_CERT_VRFY_A, SSL3_ST_SR_CERT_VRFY_B, -1, @@ -2239,7 +2326,7 @@ static int ssl3_get_cert_verify(SSL *s) { j=ECDSA_verify(pkey->save_type, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]), - SHA_DIGEST_LENGTH,p,i,pkey->pkey.eckey); + SHA_DIGEST_LENGTH,p,i,pkey->pkey.ec); if (j <= 0) { /* bad signature */ @@ -2269,15 +2356,16 @@ end: return(ret); } -static int ssl3_get_client_certificate(SSL *s) +int ssl3_get_client_certificate(SSL *s) { int i,ok,al,ret= -1; X509 *x=NULL; unsigned long l,nc,llen,n; - unsigned char *p,*d,*q; + const unsigned char *p,*q; + unsigned char *d; STACK_OF(X509) *sk=NULL; - n=ssl3_get_message(s, + n=s->method->ssl_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, -1, @@ -2312,7 +2400,7 @@ static int ssl3_get_client_certificate(SSL *s) SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE); goto f_err; } - d=p=(unsigned char *)s->init_msg; + p=d=(unsigned char *)s->init_msg; if ((sk=sk_X509_new_null()) == NULL) { @@ -2457,7 +2545,8 @@ int ssl3_send_server_certificate(SSL *s) /* This is the complement of curve_id2nid in s3_clnt.c. */ static int nid2curve_id(int nid) { - /* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) */ + /* ECC curves from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) + * (no changes in draft-ietf-tls-ecc-03.txt [June 2003]) */ switch (nid) { case NID_sect163k1: /* sect163k1 (1) */ return 1;