X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=6ae2c4d0f0a13ed91ef55b38986e7700273c6ab0;hp=a23d36f02df0af98cdb2fdb6a5f3db0f8cf6d713;hb=0f229cce65c1e7a04ed114c04327d75169b6dac3;hpb=8e1dc4d7ca9278fdfe68b81467b588dfdd7f8f1b diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index a23d36f02d..6ae2c4d0f0 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -152,7 +152,6 @@ #define NETSCAPE_HANG_BUG #include -#include #include "ssl_locl.h" #include "kssl_lcl.h" #include @@ -181,7 +180,7 @@ static const SSL_METHOD *ssl3_get_server_method(int ver) } #ifndef OPENSSL_NO_SRP -static int ssl_check_srp_ext_ClientHello(SSL *s,int *al) +static int ssl_check_srp_ext_ClientHello(SSL *s, int *al) { int ret = SSL_ERROR_NONE; @@ -298,6 +297,7 @@ int ssl3_accept(SSL *s) s->init_num=0; s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE; + s->s3->flags &= ~TLS1_FLAGS_SKIP_CERT_VERIFY; if (s->state != SSL_ST_RENEGOTIATE) { @@ -402,9 +402,30 @@ int ssl3_accept(SSL *s) s->state=SSL3_ST_SW_CHANGE_A; #endif else - s->state=SSL3_ST_SW_CERT_A; - s->init_num=0; +#ifndef OPENSSL_NO_TLSEXT + s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_A; +#else + s->state = SSL3_ST_SW_CERT_A; +#endif + s->init_num = 0; + break; + +#ifndef OPENSSL_NO_TLSEXT + case SSL3_ST_SW_SUPPLEMENTAL_DATA_A: + case SSL3_ST_SW_SUPPLEMENTAL_DATA_B: + /* We promised to send an audit proof in the hello. */ + if (s->s3->tlsext_authz_promised_to_client) + { + ret = tls1_send_server_supplemental_data(s); + if (ret <= 0) goto end; + } + else + skip = 1; + + s->state = SSL3_ST_SW_CERT_A; + s->init_num = 0; break; +#endif case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: @@ -872,14 +893,6 @@ int ssl3_check_client_hello(SSL *s) int ok; long n; - /* We only allow the client to restart the handshake once per - * negotiation. */ - if (s->s3->flags & SSL3_FLAGS_SGC_RESTART_DONE) - { - SSLerr(SSL_F_SSL3_CHECK_CLIENT_HELLO, SSL_R_MULTIPLE_SGC_RESTARTS); - return -1; - } - /* this function is called when we really expect a Certificate message, * so permit appropriate message length */ n=s->method->ssl_get_message(s, @@ -892,6 +905,13 @@ int ssl3_check_client_hello(SSL *s) s->s3->tmp.reuse_message = 1; if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO) { + /* We only allow the client to restart the handshake once per + * negotiation. */ + if (s->s3->flags & SSL3_FLAGS_SGC_RESTART_DONE) + { + SSLerr(SSL_F_SSL3_CHECK_CLIENT_HELLO, SSL_R_MULTIPLE_SGC_RESTARTS); + return -1; + } /* Throw away what we have done so far in the current handshake, * which will now be aborted. (A full SSL_clear would be too much.) */ #ifndef OPENSSL_NO_DH @@ -916,7 +936,7 @@ int ssl3_check_client_hello(SSL *s) int ssl3_get_client_hello(SSL *s) { - int i,j,ok,al,ret= -1; + int i,j,ok,al=SSL_AD_INTERNAL_ERROR,ret= -1; unsigned int cookie_len; long n; unsigned long id; @@ -1177,16 +1197,11 @@ int ssl3_get_client_hello(SSL *s) /* TLS extensions*/ if (s->version >= SSL3_VERSION) { - if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al)) + if (!ssl_parse_clienthello_tlsext(s,&p,d,n)) { - /* 'al' set by ssl_parse_clienthello_tlsext */ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLSEXT); - goto f_err; - } - } - if (ssl_check_clienthello_tlsext(s) <= 0) { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); goto err; + } } /* Check if we want to use external pre-shared secret for this @@ -1201,7 +1216,6 @@ int ssl3_get_client_hello(SSL *s) l2n(Time,pos); if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) { - al=SSL_AD_INTERNAL_ERROR; goto f_err; } } @@ -1256,7 +1270,6 @@ int ssl3_get_client_hello(SSL *s) /* Can't disable compression */ if (s->options & SSL_OP_NO_COMPRESSION) { - al=SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION); goto f_err; } @@ -1272,7 +1285,6 @@ int ssl3_get_client_hello(SSL *s) } if (s->s3->tmp.new_compression == NULL) { - al=SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INVALID_COMPRESSION_ALGORITHM); goto f_err; } @@ -1321,7 +1333,6 @@ int ssl3_get_client_hello(SSL *s) */ if (s->session->compress_meth != 0) { - al=SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION); goto f_err; } @@ -1683,7 +1694,14 @@ int ssl3_send_server_key_exchange(SSL *s) const EC_GROUP *group; ecdhp=cert->ecdh_tmp; - if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL)) + if (s->cert->ecdh_tmp_auto) + { + /* Get NID of first shared curve */ + int nid = tls1_shared_curve(s, 0); + if (nid != NID_undef) + ecdhp = EC_KEY_new_by_curve_name(nid); + } + else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb) { ecdhp=s->cert->ecdh_tmp_cb(s, SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), @@ -1708,7 +1726,9 @@ int ssl3_send_server_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; } - if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) + if (s->cert->ecdh_tmp_auto) + ecdh = ecdhp; + else if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); goto err; @@ -2046,7 +2066,7 @@ int ssl3_send_certificate_request(SSL *s) if (TLS1_get_version(s) >= TLS1_2_VERSION) { - nl = tls12_get_req_sig_algs(s, p + 2); + nl = tls12_get_sig_algs(s, p + 2); s2n(nl, p); p += nl + 2; n += nl + 2; @@ -2132,7 +2152,7 @@ int ssl3_get_client_key_exchange(SSL *s) #endif #ifndef OPENSSL_NO_DH BIGNUM *pub=NULL; - DH *dh_srvr; + DH *dh_srvr, *dh_clnt = NULL; #endif #ifndef OPENSSL_NO_KRB5 KSSL_ERR kssl_err; @@ -2266,8 +2286,13 @@ int ssl3_get_client_key_exchange(SSL *s) #ifndef OPENSSL_NO_DH if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) { - n2s(p,i); - if (n != i+2) + int idx = -1; + EVP_PKEY *skey = NULL; + if (n) + n2s(p,i); + else + i = 0; + if (n && n != i+2) { if (!(s->options & SSL_OP_SSLEAY_080_CLIENT_DH_BUG)) { @@ -2280,44 +2305,52 @@ int ssl3_get_client_key_exchange(SSL *s) i=(int)n; } } - - if (n == 0L) /* the parameters are in the cert */ + if (alg_k & SSL_kDHr) + idx = SSL_PKEY_DH_RSA; + else if (alg_k & SSL_kDHd) + idx = SSL_PKEY_DH_DSA; + if (idx >= 0) + { + skey = s->cert->pkeys[idx].privatekey; + if ((skey == NULL) || + (skey->type != EVP_PKEY_DH) || + (skey->pkey.dh == NULL)) + { + al=SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE); + goto f_err; + } + dh_srvr = skey->pkey.dh; + } + else if (s->s3->tmp.dh == NULL) { al=SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_DECODE_DH_CERTS); + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY); goto f_err; } else + dh_srvr=s->s3->tmp.dh; + + if (n == 0L) { - int idx = -1; - if (alg_k & SSL_kDHr) - idx = SSL_PKEY_DH_RSA; - else if (alg_k & SSL_kDHd) - idx = SSL_PKEY_DH_DSA; - if (idx >= 0) - { - EVP_PKEY *skey = s->cert->pkeys[idx].privatekey; - if ((skey == NULL) || - (skey->type != EVP_PKEY_DH) || - (skey->pkey.dh == NULL)) - { - al=SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_RSA_CERTIFICATE); - goto f_err; - } - dh_srvr = skey->pkey.dh; + /* Get pubkey from cert */ + EVP_PKEY *clkey=X509_get_pubkey(s->session->peer); + if (clkey) + { + if (EVP_PKEY_cmp_parameters(clkey, skey) == 1) + dh_clnt = EVP_PKEY_get1_DH(clkey); } - else if (s->s3->tmp.dh == NULL) + if (dh_clnt == NULL) { al=SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY); goto f_err; } - else - dh_srvr=s->s3->tmp.dh; + EVP_PKEY_free(clkey); + pub = dh_clnt->pub_key; } - - pub=BN_bin2bn(p,i,NULL); + else + pub=BN_bin2bn(p,i,NULL); if (pub == NULL) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BN_LIB); @@ -2335,13 +2368,17 @@ int ssl3_get_client_key_exchange(SSL *s) DH_free(s->s3->tmp.dh); s->s3->tmp.dh=NULL; - - BN_clear_free(pub); + if (dh_clnt) + DH_free(dh_clnt); + else + BN_clear_free(pub); pub=NULL; s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, s->session->master_key,p,i); OPENSSL_cleanse(p,i); + if (dh_clnt) + return 2; } else #endif @@ -2959,7 +2996,7 @@ int ssl3_get_cert_verify(SSL *s) if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_VERIFY) { s->s3->tmp.reuse_message=1; - if ((peer != NULL) && (type | EVP_PKT_SIGN)) + if ((peer != NULL) && (type & EVP_PKT_SIGN)) { al=SSL_AD_UNEXPECTED_MESSAGE; SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_MISSING_VERIFY_MESSAGE); @@ -3346,12 +3383,12 @@ err: int ssl3_send_server_certificate(SSL *s) { unsigned long l; - X509 *x; + CERT_PKEY *cpk; if (s->state == SSL3_ST_SW_CERT_A) { - x=ssl_get_server_send_cert(s); - if (x == NULL) + cpk=ssl_get_server_send_pkey(s); + if (cpk == NULL) { /* VRS: allow null cert if auth == KRB5 */ if ((s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5) || @@ -3362,7 +3399,7 @@ int ssl3_send_server_certificate(SSL *s) } } - l=ssl3_output_cert_chain(s,x); + l=ssl3_output_cert_chain(s,cpk); s->state=SSL3_ST_SW_CERT_B; s->init_num=(int)l; s->init_off=0; @@ -3545,7 +3582,7 @@ int ssl3_send_cert_status(SSL *s) return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -# ifndef OPENSSL_NO_NPN +# ifndef OPENSSL_NO_NEXTPROTONEG /* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It * sets the next_proto member in s if found */ int ssl3_get_next_proto(SSL *s) @@ -3612,4 +3649,99 @@ int ssl3_get_next_proto(SSL *s) return 1; } # endif + +int tls1_send_server_supplemental_data(SSL *s) + { + size_t length = 0; + const unsigned char *authz, *orig_authz; + unsigned char *p; + size_t authz_length, i; + + if (s->state != SSL3_ST_SW_SUPPLEMENTAL_DATA_A) + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); + + orig_authz = authz = ssl_get_authz_data(s, &authz_length); + if (authz == NULL) + { + /* This should never occur. */ + return 0; + } + + /* First we walk over the authz data to see how long the handshake + * message will be. */ + for (i = 0; i < authz_length; i++) + { + unsigned short len; + unsigned char type; + + type = *(authz++); + n2s(authz, len); + /* n2s increments authz by 2*/ + i += 2; + + if (memchr(s->s3->tlsext_authz_client_types, + type, + s->s3->tlsext_authz_client_types_len) != NULL) + length += 1 /* authz type */ + 2 /* length */ + len; + + authz += len; + i += len; + } + + length += 1 /* handshake type */ + + 3 /* handshake length */ + + 3 /* supplemental data length */ + + 2 /* supplemental entry type */ + + 2 /* supplemental entry length */; + + if (!BUF_MEM_grow_clean(s->init_buf, length)) + { + SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB); + return 0; + } + + p = (unsigned char *)s->init_buf->data; + *(p++) = SSL3_MT_SUPPLEMENTAL_DATA; + /* Handshake length */ + l2n3(length - 4, p); + /* Length of supplemental data */ + l2n3(length - 7, p); + /* Supplemental data type */ + s2n(TLSEXT_SUPPLEMENTALDATATYPE_authz_data, p); + /* Its length */ + s2n(length - 11, p); + + authz = orig_authz; + + /* Walk over the authz again and append the selected elements. */ + for (i = 0; i < authz_length; i++) + { + unsigned short len; + unsigned char type; + + type = *(authz++); + n2s(authz, len); + /* n2s increments authz by 2 */ + i += 2; + + if (memchr(s->s3->tlsext_authz_client_types, + type, + s->s3->tlsext_authz_client_types_len) != NULL) + { + *(p++) = type; + s2n(len, p); + memcpy(p, authz, len); + p += len; + } + + authz += len; + i += len; + } + + s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_B; + s->init_num = length; + s->init_off = 0; + + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); + } #endif