From: Dr. Stephen Henson Date: Mon, 11 Mar 2013 15:34:28 +0000 (+0000) Subject: DTLS revision. X-Git-Tag: master-post-reformat~1384 X-Git-Url: https://git.openssl.org/?p=openssl.git;a=commitdiff_plain;h=173e72e64c6a07ae97660c322396b66215009f33 DTLS revision. Revise DTLS code. There was a *lot* of code duplication in the DTLS code that generates records. This makes it harder to maintain and sometimes a TLS update is omitted by accident from the DTLS code. Specifically almost all of the record generation functions have code like this: some_pointer = buffer + HANDSHAKE_HEADER_LENGTH; ... Record creation stuff ... set_handshake_header(ssl, SSL_MT_SOMETHING, message_len); ... write_handshake_message(ssl); Where the "Record creation stuff" is identical between SSL/TLS and DTLS or in some cases has very minor differences. By adding a few fields to SSL3_ENC to include the header length, some flags and function pointers for handshake header setting and handshake writing the code can cope with both cases. Note: although this passes "make test" and some simple DTLS tests there may be some minor differences in the DTLS code that have to be accounted for. --- diff --git a/ssl/d1_both.c b/ssl/d1_both.c index bb9be8ad65..ee945cbd3a 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -896,63 +896,6 @@ f_err: return(-1); } -int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen) - { - unsigned char *p,*d; - int i; - unsigned long l; - - if (s->state == a) - { - d=(unsigned char *)s->init_buf->data; - p= &(d[DTLS1_HM_HEADER_LENGTH]); - - i=s->method->ssl3_enc->final_finish_mac(s, - sender,slen,s->s3->tmp.finish_md); - s->s3->tmp.finish_md_len = i; - memcpy(p, s->s3->tmp.finish_md, i); - p+=i; - l=i; - - /* Copy the finished so we can use it for - * renegotiation checks - */ - if(s->type == SSL_ST_CONNECT) - { - OPENSSL_assert(i <= EVP_MAX_MD_SIZE); - memcpy(s->s3->previous_client_finished, - s->s3->tmp.finish_md, i); - s->s3->previous_client_finished_len=i; - } - else - { - OPENSSL_assert(i <= EVP_MAX_MD_SIZE); - memcpy(s->s3->previous_server_finished, - s->s3->tmp.finish_md, i); - s->s3->previous_server_finished_len=i; - } - -#ifdef OPENSSL_SYS_WIN16 - /* MSVC 1.5 does not clear the top bytes of the word unless - * I do this. - */ - l&=0xffff; -#endif - - d = dtls1_set_message_header(s, d, SSL3_MT_FINISHED, l, 0, l); - s->init_num=(int)l+DTLS1_HM_HEADER_LENGTH; - s->init_off=0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - - s->state=b; - } - - /* SSL3_ST_SEND_xxxxxx_HELLO_B */ - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); - } - /* for these 2 messages, we need to * ssl->enc_read_ctx re-init * ssl->s3->read_sequence zero @@ -993,27 +936,6 @@ int dtls1_send_change_cipher_spec(SSL *s, int a, int b) return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC)); } -unsigned long dtls1_output_cert_chain(SSL *s, CERT_PKEY *cpk) - { - unsigned char *p; - unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH; - BUF_MEM *buf=s->init_buf; - - if (!ssl_add_cert_chain(s, cpk, &l)) - return 0; - - l-= (3 + DTLS1_HM_HEADER_LENGTH); - - p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]); - l2n3(l,p); - l+=3; - p=(unsigned char *)&(buf->data[0]); - p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l); - - l+=DTLS1_HM_HEADER_LENGTH; - return(l); - } - int dtls1_read_failed(SSL *s, int code) { if ( code > 0) diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c index 4af8ffda4d..f2f991e6f7 100644 --- a/ssl/d1_clnt.c +++ b/ssl/d1_clnt.c @@ -296,7 +296,7 @@ int dtls1_connect(SSL *s) ssl3_init_finished_mac(s); dtls1_start_timer(s); - ret=dtls1_client_hello(s); + ret=ssl3_client_hello(s); if (ret <= 0) goto end; if ( s->d1->send_cookie) @@ -460,7 +460,7 @@ int dtls1_connect(SSL *s) case SSL3_ST_CW_CERT_C: case SSL3_ST_CW_CERT_D: dtls1_start_timer(s); - ret=dtls1_send_client_certificate(s); + ret=ssl3_send_client_certificate(s); if (ret <= 0) goto end; s->state=SSL3_ST_CW_KEY_EXCH_A; s->init_num=0; @@ -469,7 +469,7 @@ int dtls1_connect(SSL *s) case SSL3_ST_CW_KEY_EXCH_A: case SSL3_ST_CW_KEY_EXCH_B: dtls1_start_timer(s); - ret=dtls1_send_client_key_exchange(s); + ret=ssl3_send_client_key_exchange(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP @@ -515,7 +515,7 @@ int dtls1_connect(SSL *s) case SSL3_ST_CW_CERT_VRFY_A: case SSL3_ST_CW_CERT_VRFY_B: dtls1_start_timer(s); - ret=dtls1_send_client_verify(s); + ret=ssl3_send_client_verify(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SCTP if (BIO_dgram_is_sctp(SSL_get_wbio(s))) @@ -578,7 +578,7 @@ int dtls1_connect(SSL *s) case SSL3_ST_CW_FINISHED_B: if (!s->hit) dtls1_start_timer(s); - ret=dtls1_send_finished(s, + ret=ssl3_send_finished(s, SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B, s->method->ssl3_enc->client_finished_label, s->method->ssl3_enc->client_finished_label_len); @@ -768,133 +768,6 @@ end: return(ret); } -int dtls1_client_hello(SSL *s) - { - unsigned char *buf; - unsigned char *p,*d; - unsigned int i,j; - unsigned long Time,l; - SSL_COMP *comp; - - buf=(unsigned char *)s->init_buf->data; - if (s->state == SSL3_ST_CW_CLNT_HELLO_A) - { - SSL_SESSION *sess = s->session; - if ((s->session == NULL) || - (s->session->ssl_version != s->version) || -#ifdef OPENSSL_NO_TLSEXT - !sess->session_id_length || -#else - (!sess->session_id_length && !sess->tlsext_tick) || -#endif - (s->session->not_resumable)) - { - if (!ssl_get_new_session(s,0)) - goto err; - } - /* else use the pre-loaded session */ - - p=s->s3->client_random; - - /* if client_random is initialized, reuse it, we are - * required to use same upon reply to HelloVerify */ - for (i=0;p[i]=='\0' && is3->client_random);i++) ; - if (i==sizeof(s->s3->client_random)) - { - Time=(unsigned long)time(NULL); /* Time */ - l2n(Time,p); - RAND_pseudo_bytes(p,sizeof(s->s3->client_random)-4); - } - - /* Do the message type and length last */ - d=p= &(buf[DTLS1_HM_HEADER_LENGTH]); - - *(p++)=s->version>>8; - *(p++)=s->version&0xff; - s->client_version=s->version; - - /* Random stuff */ - memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE); - p+=SSL3_RANDOM_SIZE; - - /* Session ID */ - if (s->new_session) - i=0; - else - i=s->session->session_id_length; - *(p++)=i; - if (i != 0) - { - if (i > sizeof s->session->session_id) - { - SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); - goto err; - } - memcpy(p,s->session->session_id,i); - p+=i; - } - - /* cookie stuff */ - if ( s->d1->cookie_len > sizeof(s->d1->cookie)) - { - SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); - goto err; - } - *(p++) = s->d1->cookie_len; - memcpy(p, s->d1->cookie, s->d1->cookie_len); - p += s->d1->cookie_len; - - /* Ciphers supported */ - i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0); - if (i == 0) - { - SSLerr(SSL_F_DTLS1_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE); - goto err; - } - s2n(i,p); - p+=i; - - /* COMPRESSION */ - if (s->ctx->comp_methods == NULL) - j=0; - else - j=sk_SSL_COMP_num(s->ctx->comp_methods); - *(p++)=1+j; - for (i=0; ictx->comp_methods,i); - *(p++)=comp->id; - } - *(p++)=0; /* Add the NULL method */ - -#ifndef OPENSSL_NO_TLSEXT - if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) - { - SSLerr(SSL_F_DTLS1_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); - goto err; - } -#endif - - l=(p-d); - d=buf; - - d = dtls1_set_message_header(s, d, SSL3_MT_CLIENT_HELLO, l, 0, l); - - s->state=SSL3_ST_CW_CLNT_HELLO_B; - /* number of bytes to write */ - s->init_num=p-buf; - s->init_off=0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_CW_CLNT_HELLO_B */ - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); -err: - return(-1); - } - static int dtls1_get_hello_verify(SSL *s) { int n, al, ok = 0; @@ -946,765 +819,3 @@ f_err: return -1; } -int dtls1_send_client_key_exchange(SSL *s) - { - unsigned char *p,*d; - int n; - unsigned long alg_k; -#ifndef OPENSSL_NO_RSA - unsigned char *q; - EVP_PKEY *pkey=NULL; -#endif -#ifndef OPENSSL_NO_KRB5 - KSSL_ERR kssl_err; -#endif /* OPENSSL_NO_KRB5 */ -#ifndef OPENSSL_NO_ECDH - EC_KEY *clnt_ecdh = NULL; - const EC_POINT *srvr_ecpoint = NULL; - EVP_PKEY *srvr_pub_pkey = NULL; - unsigned char *encodedPoint = NULL; - int encoded_pt_len = 0; - BN_CTX * bn_ctx = NULL; -#endif - - if (s->state == SSL3_ST_CW_KEY_EXCH_A) - { - d=(unsigned char *)s->init_buf->data; - p= &(d[DTLS1_HM_HEADER_LENGTH]); - - alg_k=s->s3->tmp.new_cipher->algorithm_mkey; - - /* Fool emacs indentation */ - if (0) {} -#ifndef OPENSSL_NO_RSA - else if (alg_k & SSL_kRSA) - { - RSA *rsa; - unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; - - if (s->session->sess_cert->peer_rsa_tmp != NULL) - rsa=s->session->sess_cert->peer_rsa_tmp; - else - { - pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); - if ((pkey == NULL) || - (pkey->type != EVP_PKEY_RSA) || - (pkey->pkey.rsa == NULL)) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); - goto err; - } - rsa=pkey->pkey.rsa; - EVP_PKEY_free(pkey); - } - - tmp_buf[0]=s->client_version>>8; - tmp_buf[1]=s->client_version&0xff; - if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0) - goto err; - - s->session->master_key_length=sizeof tmp_buf; - - q=p; - /* Fix buf for TLS and [incidentally] DTLS */ - if (s->version > SSL3_VERSION) - p+=2; - n=RSA_public_encrypt(sizeof tmp_buf, - tmp_buf,p,rsa,RSA_PKCS1_PADDING); -#ifdef PKCS1_CHECK - if (s->options & SSL_OP_PKCS1_CHECK_1) p[1]++; - if (s->options & SSL_OP_PKCS1_CHECK_2) tmp_buf[0]=0x70; -#endif - if (n <= 0) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT); - goto err; - } - - /* Fix buf for TLS and [incidentally] DTLS */ - if (s->version > SSL3_VERSION) - { - s2n(n,q); - n+=2; - } - - s->session->master_key_length= - s->method->ssl3_enc->generate_master_secret(s, - s->session->master_key, - tmp_buf,sizeof tmp_buf); - OPENSSL_cleanse(tmp_buf,sizeof tmp_buf); - } -#endif -#ifndef OPENSSL_NO_KRB5 - else if (alg_k & SSL_kKRB5) - { - krb5_error_code krb5rc; - KSSL_CTX *kssl_ctx = s->kssl_ctx; - /* krb5_data krb5_ap_req; */ - krb5_data *enc_ticket; - krb5_data authenticator, *authp = NULL; - EVP_CIPHER_CTX ciph_ctx; - const EVP_CIPHER *enc = NULL; - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; - unsigned char epms[SSL_MAX_MASTER_KEY_LENGTH - + EVP_MAX_IV_LENGTH]; - int padl, outl = sizeof(epms); - - EVP_CIPHER_CTX_init(&ciph_ctx); - -#ifdef KSSL_DEBUG - printf("ssl3_send_client_key_exchange(%lx & %lx)\n", - alg_k, SSL_kKRB5); -#endif /* KSSL_DEBUG */ - - authp = NULL; -#ifdef KRB5SENDAUTH - if (KRB5SENDAUTH) authp = &authenticator; -#endif /* KRB5SENDAUTH */ - - krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp, - &kssl_err); - enc = kssl_map_enc(kssl_ctx->enctype); - if (enc == NULL) - goto err; -#ifdef KSSL_DEBUG - { - printf("kssl_cget_tkt rtn %d\n", krb5rc); - if (krb5rc && kssl_err.text) - printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text); - } -#endif /* KSSL_DEBUG */ - - if (krb5rc) - { - ssl3_send_alert(s,SSL3_AL_FATAL, - SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - kssl_err.reason); - goto err; - } - - /* 20010406 VRS - Earlier versions used KRB5 AP_REQ - ** in place of RFC 2712 KerberosWrapper, as in: - ** - ** Send ticket (copy to *p, set n = length) - ** n = krb5_ap_req.length; - ** memcpy(p, krb5_ap_req.data, krb5_ap_req.length); - ** if (krb5_ap_req.data) - ** kssl_krb5_free_data_contents(NULL,&krb5_ap_req); - ** - ** Now using real RFC 2712 KerberosWrapper - ** (Thanks to Simon Wilkinson ) - ** Note: 2712 "opaque" types are here replaced - ** with a 2-byte length followed by the value. - ** Example: - ** KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms - ** Where "xx xx" = length bytes. Shown here with - ** optional authenticator omitted. - */ - - /* KerberosWrapper.Ticket */ - s2n(enc_ticket->length,p); - memcpy(p, enc_ticket->data, enc_ticket->length); - p+= enc_ticket->length; - n = enc_ticket->length + 2; - - /* KerberosWrapper.Authenticator */ - if (authp && authp->length) - { - s2n(authp->length,p); - memcpy(p, authp->data, authp->length); - p+= authp->length; - n+= authp->length + 2; - - free(authp->data); - authp->data = NULL; - authp->length = 0; - } - else - { - s2n(0,p);/* null authenticator length */ - n+=2; - } - - if (RAND_bytes(tmp_buf,sizeof tmp_buf) <= 0) - goto err; - - /* 20010420 VRS. Tried it this way; failed. - ** EVP_EncryptInit_ex(&ciph_ctx,enc, NULL,NULL); - ** EVP_CIPHER_CTX_set_key_length(&ciph_ctx, - ** kssl_ctx->length); - ** EVP_EncryptInit_ex(&ciph_ctx,NULL, key,iv); - */ - - memset(iv, 0, sizeof iv); /* per RFC 1510 */ - EVP_EncryptInit_ex(&ciph_ctx,enc, NULL, - kssl_ctx->key,iv); - EVP_EncryptUpdate(&ciph_ctx,epms,&outl,tmp_buf, - sizeof tmp_buf); - EVP_EncryptFinal_ex(&ciph_ctx,&(epms[outl]),&padl); - outl += padl; - if (outl > (int)sizeof epms) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); - goto err; - } - EVP_CIPHER_CTX_cleanup(&ciph_ctx); - - /* KerberosWrapper.EncryptedPreMasterSecret */ - s2n(outl,p); - memcpy(p, epms, outl); - p+=outl; - n+=outl + 2; - - s->session->master_key_length= - s->method->ssl3_enc->generate_master_secret(s, - s->session->master_key, - tmp_buf, sizeof tmp_buf); - - OPENSSL_cleanse(tmp_buf, sizeof tmp_buf); - OPENSSL_cleanse(epms, outl); - } -#endif -#ifndef OPENSSL_NO_DH - else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) - { - DH *dh_srvr,*dh_clnt; - - if (s->session->sess_cert->peer_dh_tmp != NULL) - dh_srvr=s->session->sess_cert->peer_dh_tmp; - else - { - /* we get them from the cert */ - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); - goto err; - } - - /* generate a new random key */ - if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); - goto err; - } - if (!DH_generate_key(dh_clnt)) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); - goto err; - } - - /* use the 'p' output buffer for the DH key, but - * make sure to clear it out afterwards */ - - n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt); - - if (n <= 0) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB); - goto err; - } - - /* generate master key from the result */ - s->session->master_key_length= - s->method->ssl3_enc->generate_master_secret(s, - s->session->master_key,p,n); - /* clean up */ - memset(p,0,n); - - /* send off the data */ - n=BN_num_bytes(dh_clnt->pub_key); - s2n(n,p); - BN_bn2bin(dh_clnt->pub_key,p); - n+=2; - - DH_free(dh_clnt); - - /* perhaps clean things up a bit EAY EAY EAY EAY*/ - } -#endif -#ifndef OPENSSL_NO_ECDH - else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) - { - const EC_GROUP *srvr_group = NULL; - EC_KEY *tkey; - int ecdh_clnt_cert = 0; - int field_size = 0; - - /* Did we send out the client's - * ECDH share for use in premaster - * computation as part of client certificate? - * If so, set ecdh_clnt_cert to 1. - */ - if ((alg_k & (SSL_kECDHr|SSL_kECDHe)) && (s->cert != NULL)) - { - /* XXX: For now, we do not support client - * authentication using ECDH certificates. - * To add such support, one needs to add - * code that checks for appropriate - * conditions and sets ecdh_clnt_cert to 1. - * For example, the cert have an ECC - * key on the same curve as the server's - * and the key should be authorized for - * key agreement. - * - * One also needs to add code in ssl3_connect - * to skip sending the certificate verify - * message. - * - * if ((s->cert->key->privatekey != NULL) && - * (s->cert->key->privatekey->type == - * EVP_PKEY_EC) && ...) - * ecdh_clnt_cert = 1; - */ - } - - if (s->session->sess_cert->peer_ecdh_tmp != NULL) - { - tkey = s->session->sess_cert->peer_ecdh_tmp; - } - else - { - /* Get the Server Public Key from Cert */ - srvr_pub_pkey = X509_get_pubkey(s->session-> \ - sess_cert->peer_pkeys[SSL_PKEY_ECC].x509); - if ((srvr_pub_pkey == NULL) || - (srvr_pub_pkey->type != EVP_PKEY_EC) || - (srvr_pub_pkey->pkey.ec == NULL)) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - - tkey = srvr_pub_pkey->pkey.ec; - } - - srvr_group = EC_KEY_get0_group(tkey); - srvr_ecpoint = EC_KEY_get0_public_key(tkey); - - if ((srvr_group == NULL) || (srvr_ecpoint == NULL)) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto err; - } - - if ((clnt_ecdh=EC_KEY_new()) == NULL) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB); - goto err; - } - if (ecdh_clnt_cert) - { - /* Reuse key info from our certificate - * We only need our private key to perform - * the ECDH computation. - */ - const BIGNUM *priv_key; - tkey = s->cert->key->privatekey->pkey.ec; - priv_key = EC_KEY_get0_private_key(tkey); - if (priv_key == NULL) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); - goto err; - } - if (!EC_KEY_set_private_key(clnt_ecdh, priv_key)) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_EC_LIB); - goto err; - } - } - else - { - /* Generate a new ECDH key pair */ - if (!(EC_KEY_generate_key(clnt_ecdh))) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_ECDH_LIB); - goto err; - } - } - - /* use the 'p' output buffer for the ECDH key, but - * make sure to clear it out afterwards - */ - - field_size = EC_GROUP_get_degree(srvr_group); - if (field_size <= 0) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_ECDH_LIB); - goto err; - } - n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL); - if (n <= 0) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_ECDH_LIB); - goto err; - } - - /* generate master key from the result */ - s->session->master_key_length = s->method->ssl3_enc \ - -> generate_master_secret(s, - s->session->master_key, - p, n); - - memset(p, 0, n); /* clean up */ - - if (ecdh_clnt_cert) - { - /* Send empty client key exch message */ - n = 0; - } - else - { - /* First check the size of encoding and - * allocate memory accordingly. - */ - encoded_pt_len = - EC_POINT_point2oct(srvr_group, - EC_KEY_get0_public_key(clnt_ecdh), - POINT_CONVERSION_UNCOMPRESSED, - NULL, 0, NULL); - - encodedPoint = (unsigned char *) - OPENSSL_malloc(encoded_pt_len * - sizeof(unsigned char)); - bn_ctx = BN_CTX_new(); - if ((encodedPoint == NULL) || - (bn_ctx == NULL)) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); - goto err; - } - - /* Encode the public key */ - n = EC_POINT_point2oct(srvr_group, - EC_KEY_get0_public_key(clnt_ecdh), - POINT_CONVERSION_UNCOMPRESSED, - encodedPoint, encoded_pt_len, bn_ctx); - - *p = n; /* length of encoded point */ - /* Encoded point will be copied here */ - p += 1; - /* copy the point */ - memcpy((unsigned char *)p, encodedPoint, n); - /* increment n to account for length field */ - n += 1; - } - - /* Free allocated memory */ - BN_CTX_free(bn_ctx); - if (encodedPoint != NULL) OPENSSL_free(encodedPoint); - if (clnt_ecdh != NULL) - EC_KEY_free(clnt_ecdh); - EVP_PKEY_free(srvr_pub_pkey); - } -#endif /* !OPENSSL_NO_ECDH */ - -#ifndef OPENSSL_NO_PSK - else if (alg_k & SSL_kPSK) - { - char identity[PSK_MAX_IDENTITY_LEN]; - unsigned char *t = NULL; - unsigned char psk_or_pre_ms[PSK_MAX_PSK_LEN*2+4]; - unsigned int pre_ms_len = 0, psk_len = 0; - int psk_err = 1; - - n = 0; - if (s->psk_client_callback == NULL) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_PSK_NO_CLIENT_CB); - goto err; - } - - psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint, - identity, PSK_MAX_IDENTITY_LEN, - psk_or_pre_ms, sizeof(psk_or_pre_ms)); - if (psk_len > PSK_MAX_PSK_LEN) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_INTERNAL_ERROR); - goto psk_err; - } - else if (psk_len == 0) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - SSL_R_PSK_IDENTITY_NOT_FOUND); - goto psk_err; - } - - /* create PSK pre_master_secret */ - pre_ms_len = 2+psk_len+2+psk_len; - t = psk_or_pre_ms; - memmove(psk_or_pre_ms+psk_len+4, psk_or_pre_ms, psk_len); - s2n(psk_len, t); - memset(t, 0, psk_len); - t+=psk_len; - s2n(psk_len, t); - - if (s->session->psk_identity_hint != NULL) - OPENSSL_free(s->session->psk_identity_hint); - s->session->psk_identity_hint = BUF_strdup(s->ctx->psk_identity_hint); - if (s->ctx->psk_identity_hint != NULL && - s->session->psk_identity_hint == NULL) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto psk_err; - } - - if (s->session->psk_identity != NULL) - OPENSSL_free(s->session->psk_identity); - s->session->psk_identity = BUF_strdup(identity); - if (s->session->psk_identity == NULL) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, - ERR_R_MALLOC_FAILURE); - goto psk_err; - } - - s->session->master_key_length = - s->method->ssl3_enc->generate_master_secret(s, - s->session->master_key, - psk_or_pre_ms, pre_ms_len); - n = strlen(identity); - s2n(n, p); - memcpy(p, identity, n); - n+=2; - psk_err = 0; - psk_err: - OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN); - OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms)); - if (psk_err != 0) - { - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); - goto err; - } - } -#endif - else - { - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); - goto err; - } - - d = dtls1_set_message_header(s, d, - SSL3_MT_CLIENT_KEY_EXCHANGE, n, 0, n); - /* - *(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE; - l2n3(n,d); - l2n(s->d1->handshake_write_seq,d); - s->d1->handshake_write_seq++; - */ - - s->state=SSL3_ST_CW_KEY_EXCH_B; - /* number of bytes to write */ - s->init_num=n+DTLS1_HM_HEADER_LENGTH; - s->init_off=0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_CW_KEY_EXCH_B */ - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); -err: -#ifndef OPENSSL_NO_ECDH - BN_CTX_free(bn_ctx); - if (encodedPoint != NULL) OPENSSL_free(encodedPoint); - if (clnt_ecdh != NULL) - EC_KEY_free(clnt_ecdh); - EVP_PKEY_free(srvr_pub_pkey); -#endif - return(-1); - } - -int dtls1_send_client_verify(SSL *s) - { - unsigned char *p,*d; - unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; - EVP_PKEY *pkey; -#ifndef OPENSSL_NO_RSA - unsigned u=0; -#endif - unsigned long n; -#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA) - int j; -#endif - - if (s->state == SSL3_ST_CW_CERT_VRFY_A) - { - d=(unsigned char *)s->init_buf->data; - p= &(d[DTLS1_HM_HEADER_LENGTH]); - pkey=s->cert->key->privatekey; - - s->method->ssl3_enc->cert_verify_mac(s, - NID_sha1, - &(data[MD5_DIGEST_LENGTH])); - -#ifndef OPENSSL_NO_RSA - if (pkey->type == EVP_PKEY_RSA) - { - s->method->ssl3_enc->cert_verify_mac(s, - NID_md5, - &(data[0])); - if (RSA_sign(NID_md5_sha1, data, - MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, - &(p[2]), &u, pkey->pkey.rsa) <= 0 ) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB); - goto err; - } - s2n(u,p); - n=u+2; - } - else -#endif -#ifndef OPENSSL_NO_DSA - if (pkey->type == EVP_PKEY_DSA) - { - if (!DSA_sign(pkey->save_type, - &(data[MD5_DIGEST_LENGTH]), - SHA_DIGEST_LENGTH,&(p[2]), - (unsigned int *)&j,pkey->pkey.dsa)) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB); - goto err; - } - s2n(j,p); - n=j+2; - } - else -#endif -#ifndef OPENSSL_NO_ECDSA - if (pkey->type == EVP_PKEY_EC) - { - if (!ECDSA_sign(pkey->save_type, - &(data[MD5_DIGEST_LENGTH]), - SHA_DIGEST_LENGTH,&(p[2]), - (unsigned int *)&j,pkey->pkey.ec)) - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY, - ERR_R_ECDSA_LIB); - goto err; - } - s2n(j,p); - n=j+2; - } - else -#endif - { - SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR); - goto err; - } - - d = dtls1_set_message_header(s, d, - SSL3_MT_CERTIFICATE_VERIFY, n, 0, n) ; - - s->init_num=(int)n+DTLS1_HM_HEADER_LENGTH; - s->init_off=0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - - s->state = SSL3_ST_CW_CERT_VRFY_B; - } - - /* s->state = SSL3_ST_CW_CERT_VRFY_B */ - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); -err: - return(-1); - } - -int dtls1_send_client_certificate(SSL *s) - { - X509 *x509=NULL; - EVP_PKEY *pkey=NULL; - int i; - unsigned long l; - - if (s->state == SSL3_ST_CW_CERT_A) - { - if ((s->cert == NULL) || - (s->cert->key->x509 == NULL) || - (s->cert->key->privatekey == NULL)) - s->state=SSL3_ST_CW_CERT_B; - else - s->state=SSL3_ST_CW_CERT_C; - } - - /* We need to get a client cert */ - if (s->state == SSL3_ST_CW_CERT_B) - { - /* If we get an error, we need to - * ssl->rwstate=SSL_X509_LOOKUP; return(-1); - * We then get retied later */ - i=0; - i = ssl_do_client_cert_cb(s, &x509, &pkey); - if (i < 0) - { - s->rwstate=SSL_X509_LOOKUP; - return(-1); - } - s->rwstate=SSL_NOTHING; - if ((i == 1) && (pkey != NULL) && (x509 != NULL)) - { - s->state=SSL3_ST_CW_CERT_B; - if ( !SSL_use_certificate(s,x509) || - !SSL_use_PrivateKey(s,pkey)) - i=0; - } - else if (i == 1) - { - i=0; - SSLerr(SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); - } - - if (x509 != NULL) X509_free(x509); - if (pkey != NULL) EVP_PKEY_free(pkey); - if (i == 0) - { - if (s->version == SSL3_VERSION) - { - s->s3->tmp.cert_req=0; - ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE); - return(1); - } - else - { - s->s3->tmp.cert_req=2; - } - } - - /* Ok, we have a cert */ - s->state=SSL3_ST_CW_CERT_C; - } - - if (s->state == SSL3_ST_CW_CERT_C) - { - s->state=SSL3_ST_CW_CERT_D; - l=dtls1_output_cert_chain(s, - (s->s3->tmp.cert_req == 2)?NULL:s->cert->key); - s->init_num=(int)l; - s->init_off=0; - - /* set header called by dtls1_output_cert_chain() */ - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - /* SSL3_ST_CW_CERT_D */ - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); - } - - diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index db180f2ce2..b739153309 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c @@ -67,6 +67,8 @@ #endif static void get_current_time(struct timeval *t); +static void dtls1_set_handshake_header(SSL *s, int type, unsigned long len); +static int dtls1_handshake_write(SSL *s); const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT; int dtls1_listen(SSL *s, struct sockaddr *client); @@ -83,6 +85,10 @@ SSL3_ENC_METHOD DTLSv1_enc_data={ TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, tls1_alert_code, tls1_export_keying_material, + SSL_ENC_FLAG_DTLS|SSL_ENC_FLAG_EXPLICIT_IV, + DTLS1_HM_HEADER_LENGTH, + dtls1_set_handshake_header, + dtls1_handshake_write }; long dtls1_default_timeout(void) @@ -484,3 +490,20 @@ int dtls1_listen(SSL *s, struct sockaddr *client) (void) BIO_dgram_get_peer(SSL_get_rbio(s), client); return 1; } + +static void dtls1_set_handshake_header(SSL *s, int htype, unsigned long len) + { + unsigned char *p = (unsigned char *)s->init_buf->data; + dtls1_set_message_header(s, p, htype, len, 0, len); + s->init_num = (int)len + DTLS1_HM_HEADER_LENGTH; + s->init_off = 0; + /* Buffer the message to handle re-xmits */ + dtls1_buffer_message(s, 0); + } + +static int dtls1_handshake_write(SSL *s) + { + return dtls1_do_write(s, SSL3_RT_HANDSHAKE); + } + + diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c index 7ab9091836..7934ad535d 100644 --- a/ssl/d1_srvr.c +++ b/ssl/d1_srvr.c @@ -277,7 +277,7 @@ int dtls1_accept(SSL *s) s->shutdown=0; dtls1_start_timer(s); - ret=dtls1_send_hello_request(s); + ret=ssl3_send_hello_request(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C; s->state=SSL3_ST_SW_FLUSH; @@ -382,7 +382,7 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_SRVR_HELLO_B: s->renegotiate = 2; dtls1_start_timer(s); - ret=dtls1_send_server_hello(s); + ret=ssl3_send_server_hello(s); if (ret <= 0) goto end; if (s->hit) @@ -422,7 +422,7 @@ int dtls1_accept(SSL *s) && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { dtls1_start_timer(s); - ret=dtls1_send_server_certificate(s); + ret=ssl3_send_server_certificate(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_TLSEXT if (s->tlsext_status_expected) @@ -484,7 +484,7 @@ int dtls1_accept(SSL *s) ) { dtls1_start_timer(s); - ret=dtls1_send_server_key_exchange(s); + ret=ssl3_send_server_key_exchange(s); if (ret <= 0) goto end; } else @@ -531,7 +531,7 @@ int dtls1_accept(SSL *s) { s->s3->tmp.cert_request=1; dtls1_start_timer(s); - ret=dtls1_send_certificate_request(s); + ret=ssl3_send_certificate_request(s); if (ret <= 0) goto end; #ifndef NETSCAPE_HANG_BUG s->state=SSL3_ST_SW_SRVR_DONE_A; @@ -560,7 +560,7 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_SRVR_DONE_A: case SSL3_ST_SW_SRVR_DONE_B: dtls1_start_timer(s); - ret=dtls1_send_server_done(s); + ret=ssl3_send_server_done(s); if (ret <= 0) goto end; s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; s->state=SSL3_ST_SW_FLUSH; @@ -692,7 +692,7 @@ int dtls1_accept(SSL *s) #ifndef OPENSSL_NO_TLSEXT case SSL3_ST_SW_SESSION_TICKET_A: case SSL3_ST_SW_SESSION_TICKET_B: - ret=dtls1_send_newsession_ticket(s); + ret=ssl3_send_newsession_ticket(s); if (ret <= 0) goto end; s->state=SSL3_ST_SW_CHANGE_A; s->init_num=0; @@ -742,7 +742,7 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_FINISHED_A: case SSL3_ST_SW_FINISHED_B: - ret=dtls1_send_finished(s, + ret=ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, s->method->ssl3_enc->server_finished_label, s->method->ssl3_enc->server_finished_label_len); @@ -845,28 +845,6 @@ end: return(ret); } -int dtls1_send_hello_request(SSL *s) - { - unsigned char *p; - - if (s->state == SSL3_ST_SW_HELLO_REQ_A) - { - p=(unsigned char *)s->init_buf->data; - p = dtls1_set_message_header(s, p, SSL3_MT_HELLO_REQUEST, 0, 0, 0); - - s->state=SSL3_ST_SW_HELLO_REQ_B; - /* number of bytes to write */ - s->init_num=DTLS1_HM_HEADER_LENGTH; - s->init_off=0; - - /* no need to buffer this message, since there are no retransmit - * requests for it */ - } - - /* SSL3_ST_SW_HELLO_REQ_B */ - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); - } - int dtls1_send_hello_verify_request(SSL *s) { unsigned int msg_len; @@ -905,807 +883,3 @@ int dtls1_send_hello_verify_request(SSL *s) /* s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */ return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); } - -int dtls1_send_server_hello(SSL *s) - { - unsigned char *buf; - unsigned char *p,*d; - int i; - unsigned int sl; - unsigned long l,Time; - - if (s->state == SSL3_ST_SW_SRVR_HELLO_A) - { - buf=(unsigned char *)s->init_buf->data; - p=s->s3->server_random; - Time=(unsigned long)time(NULL); /* Time */ - l2n(Time,p); - RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4); - /* Do the message type and length last */ - d=p= &(buf[DTLS1_HM_HEADER_LENGTH]); - - *(p++)=s->version>>8; - *(p++)=s->version&0xff; - - /* Random stuff */ - memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE); - p+=SSL3_RANDOM_SIZE; - - /* now in theory we have 3 options to sending back the - * session id. If it is a re-use, we send back the - * old session-id, if it is a new session, we send - * back the new session-id or we send back a 0 length - * session-id if we want it to be single use. - * Currently I will not implement the '0' length session-id - * 12-Jan-98 - I'll now support the '0' length stuff. - */ - if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)) - s->session->session_id_length=0; - - sl=s->session->session_id_length; - if (sl > sizeof s->session->session_id) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR); - return -1; - } - *(p++)=sl; - memcpy(p,s->session->session_id,sl); - p+=sl; - - /* put the cipher */ - if (s->s3->tmp.new_cipher == NULL) - return -1; - i=ssl3_put_cipher_by_char(s->s3->tmp.new_cipher,p); - 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_DTLS1_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR); - return -1; - } -#endif - - /* do the header */ - l=(p-d); - d=buf; - - d = dtls1_set_message_header(s, d, SSL3_MT_SERVER_HELLO, l, 0, l); - - s->state=SSL3_ST_SW_SRVR_HELLO_B; - /* number of bytes to write */ - s->init_num=p-buf; - s->init_off=0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_SW_SRVR_HELLO_B */ - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); - } - -int dtls1_send_server_done(SSL *s) - { - unsigned char *p; - - if (s->state == SSL3_ST_SW_SRVR_DONE_A) - { - p=(unsigned char *)s->init_buf->data; - - /* do the header */ - p = dtls1_set_message_header(s, p, SSL3_MT_SERVER_DONE, 0, 0, 0); - - s->state=SSL3_ST_SW_SRVR_DONE_B; - /* number of bytes to write */ - s->init_num=DTLS1_HM_HEADER_LENGTH; - s->init_off=0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_SW_SRVR_DONE_B */ - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); - } - -int dtls1_send_server_key_exchange(SSL *s) - { -#ifndef OPENSSL_NO_RSA - unsigned char *q; - int j,num; - RSA *rsa; - unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; - unsigned int u; -#endif -#ifndef OPENSSL_NO_DH - DH *dh=NULL,*dhp; -#endif -#ifndef OPENSSL_NO_ECDH - EC_KEY *ecdh=NULL, *ecdhp; - unsigned char *encodedPoint = NULL; - int encodedlen = 0; - int curve_id = 0; - BN_CTX *bn_ctx = NULL; -#endif - EVP_PKEY *pkey; - unsigned char *p,*d; - int al,i; - unsigned long type; - int n; - CERT *cert; - BIGNUM *r[4]; - int nr[4],kn; - BUF_MEM *buf; - EVP_MD_CTX md_ctx; - - EVP_MD_CTX_init(&md_ctx); - if (s->state == SSL3_ST_SW_KEY_EXCH_A) - { - type=s->s3->tmp.new_cipher->algorithm_mkey; - cert=s->cert; - - buf=s->init_buf; - - r[0]=r[1]=r[2]=r[3]=NULL; - n=0; -#ifndef OPENSSL_NO_RSA - if (type & SSL_kRSA) - { - rsa=cert->rsa_tmp; - if ((rsa == NULL) && (s->cert->rsa_tmp_cb != NULL)) - { - rsa=s->cert->rsa_tmp_cb(s, - SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), - SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); - if(rsa == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY); - goto f_err; - } - RSA_up_ref(rsa); - cert->rsa_tmp=rsa; - } - if (rsa == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_RSA_KEY); - goto f_err; - } - r[0]=rsa->n; - r[1]=rsa->e; - s->s3->tmp.use_rsa_tmp=1; - } - else -#endif -#ifndef OPENSSL_NO_DH - if (type & SSL_kEDH) - { - dhp=cert->dh_tmp; - if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) - dhp=s->cert->dh_tmp_cb(s, - SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), - SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); - if (dhp == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY); - goto f_err; - } - - if (s->s3->tmp.dh != NULL) - { - DH_free(dh); - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); - goto err; - } - - if ((dh=DHparams_dup(dhp)) == NULL) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); - goto err; - } - - s->s3->tmp.dh=dh; - if ((dhp->pub_key == NULL || - dhp->priv_key == NULL || - (s->options & SSL_OP_SINGLE_DH_USE))) - { - if(!DH_generate_key(dh)) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, - ERR_R_DH_LIB); - goto err; - } - } - else - { - dh->pub_key=BN_dup(dhp->pub_key); - dh->priv_key=BN_dup(dhp->priv_key); - if ((dh->pub_key == NULL) || - (dh->priv_key == NULL)) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB); - goto err; - } - } - r[0]=dh->p; - r[1]=dh->g; - r[2]=dh->pub_key; - } - else -#endif -#ifndef OPENSSL_NO_ECDH - if (type & SSL_kEECDH) - { - const EC_GROUP *group; - - ecdhp=cert->ecdh_tmp; - if ((ecdhp == NULL) && (s->cert->ecdh_tmp_cb != NULL)) - { - ecdhp=s->cert->ecdh_tmp_cb(s, - SSL_C_IS_EXPORT(s->s3->tmp.new_cipher), - SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)); - } - if (ecdhp == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY); - goto f_err; - } - - if (s->s3->tmp.ecdh != NULL) - { - EC_KEY_free(s->s3->tmp.ecdh); - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR); - goto err; - } - - /* Duplicate the ECDH structure. */ - if (ecdhp == NULL) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); - goto err; - } - if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); - goto err; - } - - s->s3->tmp.ecdh=ecdh; - 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)) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); - goto err; - } - } - - 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_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); - goto err; - } - - if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && - (EC_GROUP_get_degree(group) > 163)) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER); - goto err; - } - - /* XXX: For now, we only support ephemeral ECDH - * keys over named (not generic) curves. For - * supported named curves, curve_id is non-zero. - */ - if ((curve_id = - tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group))) - == 0) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); - goto err; - } - - /* Encode the public key. - * First check the size of encoding and - * allocate memory accordingly. - */ - encodedlen = EC_POINT_point2oct(group, - EC_KEY_get0_public_key(ecdh), - POINT_CONVERSION_UNCOMPRESSED, - NULL, 0, NULL); - - encodedPoint = (unsigned char *) - OPENSSL_malloc(encodedlen*sizeof(unsigned char)); - bn_ctx = BN_CTX_new(); - if ((encodedPoint == NULL) || (bn_ctx == NULL)) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE); - goto err; - } - - - encodedlen = EC_POINT_point2oct(group, - EC_KEY_get0_public_key(ecdh), - POINT_CONVERSION_UNCOMPRESSED, - encodedPoint, encodedlen, bn_ctx); - - if (encodedlen == 0) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_R_ECDH_LIB); - goto err; - } - - BN_CTX_free(bn_ctx); bn_ctx=NULL; - - /* XXX: For now, we only support named (not - * generic) curves in ECDH ephemeral key exchanges. - * In this situation, we need four additional bytes - * to encode the entire ServerECDHParams - * structure. - */ - n = 4 + encodedlen; - - /* We'll generate the serverKeyExchange message - * explicitly so we can set these to NULLs - */ - r[0]=NULL; - r[1]=NULL; - r[2]=NULL; - r[3]=NULL; - } - else -#endif /* !OPENSSL_NO_ECDH */ -#ifndef OPENSSL_NO_PSK - if (type & SSL_kPSK) - { - /* reserve size for record length and PSK identity hint*/ - n+=2+strlen(s->ctx->psk_identity_hint); - } - else -#endif /* !OPENSSL_NO_PSK */ - { - al=SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); - goto f_err; - } - for (i=0; r[i] != NULL; i++) - { - nr[i]=BN_num_bytes(r[i]); - n+=2+nr[i]; - } - - if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) - && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) - { - if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher, NULL)) - == NULL) - { - al=SSL_AD_DECODE_ERROR; - goto f_err; - } - kn=EVP_PKEY_size(pkey); - } - else - { - pkey=NULL; - kn=0; - } - - if (!BUF_MEM_grow_clean(buf,n+DTLS1_HM_HEADER_LENGTH+kn)) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF); - goto err; - } - d=(unsigned char *)s->init_buf->data; - p= &(d[DTLS1_HM_HEADER_LENGTH]); - - for (i=0; r[i] != NULL; i++) - { - s2n(nr[i],p); - BN_bn2bin(r[i],p); - p+=nr[i]; - } - -#ifndef OPENSSL_NO_ECDH - if (type & SSL_kEECDH) - { - /* XXX: For now, we only support named (not generic) curves. - * In this situation, the serverKeyExchange message has: - * [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; - p += 1; - memcpy((unsigned char*)p, - (unsigned char *)encodedPoint, - encodedlen); - OPENSSL_free(encodedPoint); - p += encodedlen; - } -#endif - -#ifndef OPENSSL_NO_PSK - if (type & SSL_kPSK) - { - /* copy PSK identity hint */ - s2n(strlen(s->ctx->psk_identity_hint), p); - strncpy((char *)p, s->ctx->psk_identity_hint, strlen(s->ctx->psk_identity_hint)); - p+=strlen(s->ctx->psk_identity_hint); - } -#endif - - /* not anonymous */ - if (pkey != NULL) - { - /* n is the length of the params, they start at - * &(d[DTLS1_HM_HEADER_LENGTH]) and p points to the space - * at the end. */ -#ifndef OPENSSL_NO_RSA - if (pkey->type == EVP_PKEY_RSA) - { - q=md_buf; - j=0; - for (num=2; num > 0; num--) - { - EVP_DigestInit_ex(&md_ctx,(num == 2) - ?s->ctx->md5:s->ctx->sha1, NULL); - EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); - EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); - EVP_DigestUpdate(&md_ctx,&(d[DTLS1_HM_HEADER_LENGTH]),n); - EVP_DigestFinal_ex(&md_ctx,q, - (unsigned int *)&i); - q+=i; - j+=i; - } - if (RSA_sign(NID_md5_sha1, md_buf, j, - &(p[2]), &u, pkey->pkey.rsa) <= 0) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_RSA); - goto err; - } - s2n(u,p); - n+=u+2; - } - else -#endif -#if !defined(OPENSSL_NO_DSA) - if (pkey->type == EVP_PKEY_DSA) - { - /* lets do DSS */ - EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL); - EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx,&(d[DTLS1_HM_HEADER_LENGTH]),n); - if (!EVP_SignFinal(&md_ctx,&(p[2]), - (unsigned int *)&i,pkey)) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_DSA); - goto err; - } - s2n(i,p); - n+=i+2; - } - else -#endif -#if !defined(OPENSSL_NO_ECDSA) - if (pkey->type == EVP_PKEY_EC) - { - /* let's do ECDSA */ - EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL); - EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx,&(d[DTLS1_HM_HEADER_LENGTH]),n); - if (!EVP_SignFinal(&md_ctx,&(p[2]), - (unsigned int *)&i,pkey)) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_ECDSA); - goto err; - } - s2n(i,p); - n+=i+2; - } - else -#endif - { - /* Is this error check actually needed? */ - al=SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_PKEY_TYPE); - goto f_err; - } - } - - d = dtls1_set_message_header(s, d, - SSL3_MT_SERVER_KEY_EXCHANGE, n, 0, n); - - /* we should now have things packed up, so lets send - * it off */ - s->init_num=n+DTLS1_HM_HEADER_LENGTH; - s->init_off=0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - s->state = SSL3_ST_SW_KEY_EXCH_B; - EVP_MD_CTX_cleanup(&md_ctx); - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); -err: -#ifndef OPENSSL_NO_ECDH - if (encodedPoint != NULL) OPENSSL_free(encodedPoint); - BN_CTX_free(bn_ctx); -#endif - EVP_MD_CTX_cleanup(&md_ctx); - return(-1); - } - -int dtls1_send_certificate_request(SSL *s) - { - unsigned char *p,*d; - int i,j,nl,off,n; - STACK_OF(X509_NAME) *sk=NULL; - X509_NAME *name; - BUF_MEM *buf; - unsigned int msg_len; - - if (s->state == SSL3_ST_SW_CERT_REQ_A) - { - buf=s->init_buf; - - d=p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]); - - /* get the list of acceptable cert types */ - p++; - n=ssl3_get_req_cert_type(s,p); - d[0]=n; - p+=n; - n++; - - off=n; - p+=2; - n+=2; - - sk=SSL_get_client_CA_list(s); - nl=0; - if (sk != NULL) - { - for (i=0; idata[DTLS1_HM_HEADER_LENGTH+n]); - if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG)) - { - s2n(j,p); - i2d_X509_NAME(name,&p); - n+=2+j; - nl+=2+j; - } - else - { - d=p; - i2d_X509_NAME(name,&p); - j-=2; s2n(j,d); j+=2; - n+=j; - nl+=j; - } - } - } - /* else no CA names */ - p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH+off]); - s2n(nl,p); - - d=(unsigned char *)buf->data; - *(d++)=SSL3_MT_CERTIFICATE_REQUEST; - l2n3(n,d); - s2n(s->d1->handshake_write_seq,d); - s->d1->handshake_write_seq++; - - /* we should now have things packed up, so lets send - * it off */ - - s->init_num=n+DTLS1_HM_HEADER_LENGTH; - s->init_off=0; -#ifdef NETSCAPE_HANG_BUG -/* XXX: what to do about this? */ - p=(unsigned char *)s->init_buf->data + s->init_num; - - /* do the header */ - *(p++)=SSL3_MT_SERVER_DONE; - *(p++)=0; - *(p++)=0; - *(p++)=0; - s->init_num += 4; -#endif - - /* XDTLS: set message header ? */ - msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH; - dtls1_set_message_header(s, (void *)s->init_buf->data, - SSL3_MT_CERTIFICATE_REQUEST, msg_len, 0, msg_len); - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - - s->state = SSL3_ST_SW_CERT_REQ_B; - } - - /* SSL3_ST_SW_CERT_REQ_B */ - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); -err: - return(-1); - } - -int dtls1_send_server_certificate(SSL *s) - { - unsigned long l; - CERT_PKEY *cpk; - - if (s->state == SSL3_ST_SW_CERT_A) - { - cpk=ssl_get_server_send_pkey(s); - if (cpk == NULL) - { - /* VRS: allow null cert if auth == KRB5 */ - if ((s->s3->tmp.new_cipher->algorithm_mkey != SSL_kKRB5) || - (s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5)) - { - SSLerr(SSL_F_DTLS1_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR); - return(0); - } - } - - l=dtls1_output_cert_chain(s,cpk); - s->state=SSL3_ST_SW_CERT_B; - s->init_num=(int)l; - s->init_off=0; - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_SW_CERT_B */ - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); - } - -#ifndef OPENSSL_NO_TLSEXT -int dtls1_send_newsession_ticket(SSL *s) - { - if (s->state == SSL3_ST_SW_SESSION_TICKET_A) - { - unsigned char *p, *senc, *macstart; - int len, slen; - unsigned int hlen, msg_len; - EVP_CIPHER_CTX ctx; - HMAC_CTX hctx; - SSL_CTX *tctx = s->initial_ctx; - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char key_name[16]; - - /* get session encoding length */ - slen = i2d_SSL_SESSION(s->session, NULL); - /* Some length values are 16 bits, so forget it if session is - * too long - */ - if (slen > 0xFF00) - return -1; - /* Grow buffer if need be: the length calculation is as - * follows 12 (DTLS handshake message header) + - * 4 (ticket lifetime hint) + 2 (ticket length) + - * 16 (key name) + max_iv_len (iv length) + - * session_length + max_enc_block_size (max encrypted session - * length) + max_md_size (HMAC). - */ - if (!BUF_MEM_grow(s->init_buf, - DTLS1_HM_HEADER_LENGTH + 22 + EVP_MAX_IV_LENGTH + - EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen)) - return -1; - senc = OPENSSL_malloc(slen); - if (!senc) - return -1; - p = senc; - i2d_SSL_SESSION(s->session, &p); - - p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]); - EVP_CIPHER_CTX_init(&ctx); - HMAC_CTX_init(&hctx); - /* Initialize HMAC and cipher contexts. If callback present - * it does all the work otherwise use generated values - * from parent ctx. - */ - if (tctx->tlsext_ticket_key_cb) - { - if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, - &hctx, 1) < 0) - { - OPENSSL_free(senc); - return -1; - } - } - else - { - RAND_pseudo_bytes(iv, 16); - EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, - tctx->tlsext_tick_aes_key, iv); - HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, - tlsext_tick_md(), NULL); - memcpy(key_name, tctx->tlsext_tick_key_name, 16); - } - l2n(s->session->tlsext_tick_lifetime_hint, p); - /* Skip ticket length for now */ - p += 2; - /* Output key name */ - macstart = p; - memcpy(p, key_name, 16); - p += 16; - /* output IV */ - memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx)); - p += EVP_CIPHER_CTX_iv_length(&ctx); - /* Encrypt session data */ - EVP_EncryptUpdate(&ctx, p, &len, senc, slen); - p += len; - EVP_EncryptFinal(&ctx, p, &len); - p += len; - EVP_CIPHER_CTX_cleanup(&ctx); - - HMAC_Update(&hctx, macstart, p - macstart); - HMAC_Final(&hctx, p, &hlen); - HMAC_CTX_cleanup(&hctx); - - p += hlen; - /* Now write out lengths: p points to end of data written */ - /* Total length */ - len = p - (unsigned char *)(s->init_buf->data); - /* Ticket length */ - p=(unsigned char *)&(s->init_buf->data[DTLS1_HM_HEADER_LENGTH]) + 4; - s2n(len - DTLS1_HM_HEADER_LENGTH - 6, p); - - /* number of bytes to write */ - s->init_num= len; - s->state=SSL3_ST_SW_SESSION_TICKET_B; - s->init_off=0; - OPENSSL_free(senc); - - /* XDTLS: set message header ? */ - msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH; - dtls1_set_message_header(s, (void *)s->init_buf->data, - SSL3_MT_NEWSESSION_TICKET, msg_len, 0, msg_len); - - /* buffer the message to handle re-xmits */ - dtls1_buffer_message(s, 0); - } - - /* SSL3_ST_SW_SESSION_TICKET_B */ - return(dtls1_do_write(s,SSL3_RT_HANDSHAKE)); - } -#endif diff --git a/ssl/s3_both.c b/ssl/s3_both.c index a537738f42..76258b3c5c 100644 --- a/ssl/s3_both.c +++ b/ssl/s3_both.c @@ -150,20 +150,18 @@ int ssl3_do_write(SSL *s, int type) int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) { - unsigned char *p,*d; + unsigned char *p; int i; unsigned long l; if (s->state == a) { - d=(unsigned char *)s->init_buf->data; - p= &(d[4]); + p = ssl_handshake_start(s); i=s->method->ssl3_enc->final_finish_mac(s, sender,slen,s->s3->tmp.finish_md); s->s3->tmp.finish_md_len = i; memcpy(p, s->s3->tmp.finish_md, i); - p+=i; l=i; /* Copy the finished so we can use it for @@ -189,17 +187,12 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) */ l&=0xffff; #endif - - *(d++)=SSL3_MT_FINISHED; - l2n3(l,d); - s->init_num=(int)l+4; - s->init_off=0; - + ssl_set_handshake_header(s, SSL3_MT_FINISHED, l); s->state=b; } /* SSL3_ST_SEND_xxxxxx_HELLO_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } #ifndef OPENSSL_NO_NEXTPROTONEG @@ -324,21 +317,17 @@ int ssl3_send_change_cipher_spec(SSL *s, int a, int b) unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk) { unsigned char *p; - unsigned long l=7; - BUF_MEM *buf = s->init_buf; + unsigned long l = 3 + SSL_HM_HEADER_LENGTH(s); if (!ssl_add_cert_chain(s, cpk, &l)) return 0; - l-=7; - p=(unsigned char *)&(buf->data[4]); - l2n3(l,p); - l+=3; - p=(unsigned char *)&(buf->data[0]); - *(p++)=SSL3_MT_CERTIFICATE; + l -= 3 + SSL_HM_HEADER_LENGTH(s); + p = ssl_handshake_start(s); l2n3(l,p); - l+=4; - return(l); + l += 3; + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l); + return l + SSL_HM_HEADER_LENGTH(s); } /* Obtain handshake message of message type 'mt' (any if mt == -1), diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index b5c939f9a1..1bbe99401f 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -697,13 +697,34 @@ int ssl3_client_hello(SSL *s) /* else use the pre-loaded session */ p=s->s3->client_random; - Time=(unsigned long)time(NULL); /* Time */ - l2n(Time,p); - if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) - goto err; + + /* for DTLS if client_random is initialized, reuse it, we are + * required to use same upon reply to HelloVerify */ + if (SSL_IS_DTLS(s)) + { + size_t idx; + i = 1; + for (idx=0; idx < sizeof(s->s3->client_random); idx++) + { + if (p[idx]) + { + i = 0; + break; + } + } + } + else + i = 1; + + if (i) + { + Time=(unsigned long)time(NULL); /* Time */ + l2n(Time,p); + RAND_pseudo_bytes(p,sizeof(s->s3->client_random)-4); + } /* Do the message type and length last */ - d=p= &(buf[4]); + d=p= ssl_handshake_start(s); /* version indicates the negotiated version: for example from * an SSLv2/v3 compatible client hello). The client_version @@ -764,6 +785,19 @@ int ssl3_client_hello(SSL *s) p+=i; } + /* cookie stuff for DTLS */ + if (SSL_IS_DTLS(s)) + { + if ( s->d1->cookie_len > sizeof(s->d1->cookie)) + { + SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + goto err; + } + *(p++) = s->d1->cookie_len; + memcpy(p, s->d1->cookie, s->d1->cookie_len); + p += s->d1->cookie_len; + } + /* Ciphers supported */ i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0); if (i == 0) @@ -816,19 +850,13 @@ int ssl3_client_hello(SSL *s) } #endif - l=(p-d); - d=buf; - *(d++)=SSL3_MT_CLIENT_HELLO; - l2n3(l,d); - + l= p-d; + ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l); s->state=SSL3_ST_CW_CLNT_HELLO_B; - /* number of bytes to write */ - s->init_num=p-buf; - s->init_off=0; } /* SSL3_ST_CW_CLNT_HELLO_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: return(-1); } @@ -2261,7 +2289,7 @@ int ssl3_get_server_done(SSL *s) int ssl3_send_client_key_exchange(SSL *s) { - unsigned char *p,*d; + unsigned char *p; int n; unsigned long alg_k; #ifndef OPENSSL_NO_RSA @@ -2282,8 +2310,7 @@ int ssl3_send_client_key_exchange(SSL *s) if (s->state == SSL3_ST_CW_KEY_EXCH_A) { - d=(unsigned char *)s->init_buf->data; - p= &(d[4]); + p = ssl_handshake_start(s); alg_k=s->s3->tmp.new_cipher->algorithm_mkey; @@ -2984,18 +3011,13 @@ int ssl3_send_client_key_exchange(SSL *s) ERR_R_INTERNAL_ERROR); goto err; } - - *(d++)=SSL3_MT_CLIENT_KEY_EXCHANGE; - l2n3(n,d); + ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n); s->state=SSL3_ST_CW_KEY_EXCH_B; - /* number of bytes to write */ - s->init_num=n+4; - s->init_off=0; } /* SSL3_ST_CW_KEY_EXCH_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: #ifndef OPENSSL_NO_ECDH BN_CTX_free(bn_ctx); @@ -3009,7 +3031,7 @@ err: int ssl3_send_client_verify(SSL *s) { - unsigned char *p,*d; + unsigned char *p; unsigned char data[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH]; EVP_PKEY *pkey; EVP_PKEY_CTX *pctx=NULL; @@ -3022,8 +3044,7 @@ int ssl3_send_client_verify(SSL *s) if (s->state == SSL3_ST_CW_CERT_VRFY_A) { - d=(unsigned char *)s->init_buf->data; - p= &(d[4]); + p= ssl_handshake_start(s); pkey=s->cert->key->privatekey; /* Create context from key and test if sha1 is allowed as digest */ pctx = EVP_PKEY_CTX_new(pkey,NULL); @@ -3149,16 +3170,12 @@ int ssl3_send_client_verify(SSL *s) SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR); goto err; } - *(d++)=SSL3_MT_CERTIFICATE_VERIFY; - l2n3(n,d); - + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n); s->state=SSL3_ST_CW_CERT_VRFY_B; - s->init_num=(int)n+4; - s->init_off=0; } EVP_MD_CTX_cleanup(&mctx); EVP_PKEY_CTX_free(pctx); - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: EVP_MD_CTX_cleanup(&mctx); EVP_PKEY_CTX_free(pctx); @@ -3215,7 +3232,6 @@ int ssl3_send_client_certificate(SSL *s) X509 *x509=NULL; EVP_PKEY *pkey=NULL; int i; - unsigned long l; if (s->state == SSL3_ST_CW_CERT_A) { @@ -3284,13 +3300,11 @@ int ssl3_send_client_certificate(SSL *s) if (s->state == SSL3_ST_CW_CERT_C) { s->state=SSL3_ST_CW_CERT_D; - l=ssl3_output_cert_chain(s, + ssl3_output_cert_chain(s, (s->s3->tmp.cert_req == 2)?NULL:s->cert->key); - s->init_num=(int)l; - s->init_off=0; } /* SSL3_ST_CW_CERT_D */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } #define has_bits(i,m) (((i)&(m)) == (m)) diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 6c09e43463..2fe30d77a6 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -2918,6 +2918,10 @@ SSL3_ENC_METHOD SSLv3_enc_data={ (int (*)(SSL *, unsigned char *, size_t, const char *, size_t, const unsigned char *, size_t, int use_context))ssl_undefined_function, + 0, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write }; long ssl3_default_timeout(void) @@ -2948,6 +2952,20 @@ int ssl3_pending(const SSL *s) return (s->s3->rrec.type == SSL3_RT_APPLICATION_DATA) ? s->s3->rrec.length : 0; } +void ssl3_set_handshake_header(SSL *s, int htype, unsigned long len) + { + unsigned char *p = (unsigned char *)s->init_buf->data; + *(p++) = htype; + l2n3(len, p); + s->init_num = (int)len + SSL3_HM_HEADER_LENGTH; + s->init_off = 0; + } + +int ssl3_handshake_write(SSL *s) + { + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); + } + int ssl3_new(SSL *s) { SSL3_STATE *s3; @@ -4451,4 +4469,4 @@ long ssl_get_algorithm2(SSL *s) return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256; return alg2; } - + diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 389f708b3e..5d7ab1325e 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -868,24 +868,15 @@ end: int ssl3_send_hello_request(SSL *s) { - unsigned char *p; if (s->state == SSL3_ST_SW_HELLO_REQ_A) { - p=(unsigned char *)s->init_buf->data; - *(p++)=SSL3_MT_HELLO_REQUEST; - *(p++)=0; - *(p++)=0; - *(p++)=0; - + ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0); s->state=SSL3_ST_SW_HELLO_REQ_B; - /* number of bytes to write */ - s->init_num=4; - s->init_off=0; } /* SSL3_ST_SW_HELLO_REQ_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } int ssl3_check_client_hello(SSL *s) @@ -1478,7 +1469,7 @@ int ssl3_send_server_hello(SSL *s) return -1; #endif /* Do the message type and length last */ - d=p= &(buf[4]); + d=p= ssl_handshake_start(s); *(p++)=s->version>>8; *(p++)=s->version&0xff; @@ -1544,42 +1535,25 @@ int ssl3_send_server_hello(SSL *s) #endif /* do the header */ l=(p-d); - d=buf; - *(d++)=SSL3_MT_SERVER_HELLO; - l2n3(l,d); - + ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l); s->state=SSL3_ST_SW_SRVR_HELLO_B; - /* number of bytes to write */ - s->init_num=p-buf; - s->init_off=0; } /* SSL3_ST_SW_SRVR_HELLO_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } int ssl3_send_server_done(SSL *s) { - unsigned char *p; if (s->state == SSL3_ST_SW_SRVR_DONE_A) { - p=(unsigned char *)s->init_buf->data; - - /* do the header */ - *(p++)=SSL3_MT_SERVER_DONE; - *(p++)=0; - *(p++)=0; - *(p++)=0; - - s->state=SSL3_ST_SW_SRVR_DONE_B; - /* number of bytes to write */ - s->init_num=4; - s->init_off=0; + ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0); + s->state = SSL3_ST_SW_SRVR_DONE_B; } /* SSL3_ST_SW_SRVR_DONE_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } int ssl3_send_server_key_exchange(SSL *s) @@ -1903,13 +1877,12 @@ int ssl3_send_server_key_exchange(SSL *s) kn=0; } - if (!BUF_MEM_grow_clean(buf,n+4+kn)) + if (!BUF_MEM_grow_clean(buf,n+SSL_HM_HEADER_LENGTH(s)+kn)) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF); goto err; } - d=(unsigned char *)s->init_buf->data; - p= &(d[4]); + d = p = ssl_handshake_start(s); for (i=0; r[i] != NULL && i<4; i++) { @@ -1981,7 +1954,7 @@ int ssl3_send_server_key_exchange(SSL *s) ?s->ctx->md5:s->ctx->sha1, NULL); EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); - EVP_DigestUpdate(&md_ctx,&(d[4]),n); + EVP_DigestUpdate(&md_ctx,d,n); EVP_DigestFinal_ex(&md_ctx,q, (unsigned int *)&i); q+=i; @@ -2020,7 +1993,7 @@ int ssl3_send_server_key_exchange(SSL *s) EVP_SignInit_ex(&md_ctx, md, NULL); EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx,&(d[4]),n); + EVP_SignUpdate(&md_ctx,d,n); if (!EVP_SignFinal(&md_ctx,&(p[2]), (unsigned int *)&i,pkey)) { @@ -2041,18 +2014,12 @@ int ssl3_send_server_key_exchange(SSL *s) } } - *(d++)=SSL3_MT_SERVER_KEY_EXCHANGE; - l2n3(n,d); - - /* we should now have things packed up, so lets send - * it off */ - s->init_num=n+4; - s->init_off=0; + ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n); } s->state = SSL3_ST_SW_KEY_EXCH_B; EVP_MD_CTX_cleanup(&md_ctx); - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: @@ -2076,7 +2043,7 @@ int ssl3_send_certificate_request(SSL *s) { buf=s->init_buf; - d=p=(unsigned char *)&(buf->data[4]); + d=p=ssl_handshake_start(s); /* get the list of acceptable cert types */ p++; @@ -2131,34 +2098,29 @@ int ssl3_send_certificate_request(SSL *s) } } /* else no CA names */ - p=(unsigned char *)&(buf->data[4+off]); + p = ssl_handshake_start(s) + off; s2n(nl,p); - d=(unsigned char *)buf->data; - *(d++)=SSL3_MT_CERTIFICATE_REQUEST; - l2n3(n,d); + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n); - /* we should now have things packed up, so lets send - * it off */ - - s->init_num=n+4; - s->init_off=0; #ifdef NETSCAPE_HANG_BUG - p=(unsigned char *)s->init_buf->data + s->init_num; - - /* do the header */ - *(p++)=SSL3_MT_SERVER_DONE; - *(p++)=0; - *(p++)=0; - *(p++)=0; - s->init_num += 4; + if (!SSL_IS_DTLS(s)) + { + p=(unsigned char *)s->init_buf->data + s->init_num; + /* do the header */ + *(p++)=SSL3_MT_SERVER_DONE; + *(p++)=0; + *(p++)=0; + *(p++)=0; + s->init_num += 4; + } #endif s->state = SSL3_ST_SW_CERT_REQ_B; } /* SSL3_ST_SW_CERT_REQ_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: return(-1); } @@ -3394,7 +3356,6 @@ err: int ssl3_send_server_certificate(SSL *s) { - unsigned long l; CERT_PKEY *cpk; if (s->state == SSL3_ST_SW_CERT_A) @@ -3411,14 +3372,12 @@ int ssl3_send_server_certificate(SSL *s) } } - l=ssl3_output_cert_chain(s,cpk); + ssl3_output_cert_chain(s,cpk); s->state=SSL3_ST_SW_CERT_B; - s->init_num=(int)l; - s->init_off=0; } /* SSL3_ST_SW_CERT_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } #ifndef OPENSSL_NO_TLSEXT @@ -3472,22 +3431,17 @@ int ssl3_send_newsession_ticket(SSL *s) SSL_SESSION_free(sess); /* Grow buffer if need be: the length calculation is as - * follows 1 (size of message name) + 3 (message length - * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) + + * follows handshake_header_length + + * 4 (ticket lifetime hint) + 2 (ticket length) + * 16 (key name) + max_iv_len (iv length) + * session_length + max_enc_block_size (max encrypted session * length) + max_md_size (HMAC). */ if (!BUF_MEM_grow(s->init_buf, - 26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + - EVP_MAX_MD_SIZE + slen)) + SSL_HM_HEADER_LENGTH(s) + 22 + EVP_MAX_IV_LENGTH + + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen)) return -1; - - p=(unsigned char *)s->init_buf->data; - /* do the header */ - *(p++)=SSL3_MT_NEWSESSION_TICKET; - /* Skip message length for now */ - p += 3; + p = ssl_handshake_start(s); EVP_CIPHER_CTX_init(&ctx); HMAC_CTX_init(&hctx); /* Initialize HMAC and cipher contexts. If callback present @@ -3542,21 +3496,17 @@ int ssl3_send_newsession_ticket(SSL *s) p += hlen; /* Now write out lengths: p points to end of data written */ /* Total length */ - len = p - (unsigned char *)s->init_buf->data; - p=(unsigned char *)s->init_buf->data + 1; - l2n3(len - 4, p); /* Message length */ - p += 4; - s2n(len - 10, p); /* Ticket length */ - - /* number of bytes to write */ - s->init_num= len; + len = p - ssl_handshake_start(s); + ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len); + /* Skip ticket lifetime hint */ + p = ssl_handshake_start(s) + 4; + s2n(len - 6, p); s->state=SSL3_ST_SW_SESSION_TICKET_B; - s->init_off=0; OPENSSL_free(senc); } /* SSL3_ST_SW_SESSION_TICKET_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } int ssl3_send_cert_status(SSL *s) diff --git a/ssl/ssl3.h b/ssl/ssl3.h index 2486011bb5..d8ed725d2d 100644 --- a/ssl/ssl3.h +++ b/ssl/ssl3.h @@ -251,6 +251,8 @@ extern "C" { #define SSL3_SESSION_ID_SIZE 32 #define SSL3_RT_HEADER_LENGTH 5 +#define SSL3_HM_HEADER_LENGTH 4 + #ifndef SSL3_ALIGN_PAYLOAD /* Some will argue that this increases memory footprint, but it's * not actually true. Point is that malloc has to return at least diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index 67239755e0..9f3a5c9f7b 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -439,7 +439,7 @@ #define SSL_C_EXPORT_PKEYLENGTH(c) SSL_EXPORT_PKEYLENGTH((c)->algo_strength) /* Check if an SSL structure is using DTLS */ -#define SSL_IS_DTLS(s) ((s->method->version >> 8) == 0xfe) +#define SSL_IS_DTLS(s) (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS) /* Mostly for SSLv3 */ @@ -679,8 +679,32 @@ typedef struct ssl3_enc_method const char *, size_t, const unsigned char *, size_t, int use_context); + /* Various flags indicating protocol version requirements */ + unsigned int enc_flags; + /* Handshake header length */ + unsigned int hhlen; + /* Set the handshake header */ + void (*set_handshake_header)(SSL *s, int type, unsigned long len); + /* Write out handshake message */ + int (*do_write)(SSL *s); } SSL3_ENC_METHOD; +#define SSL_HM_HEADER_LENGTH(s) s->method->ssl3_enc->hhlen +#define ssl_handshake_start(s) \ + (((unsigned char *)s->init_buf->data) + s->method->ssl3_enc->hhlen) +#define ssl_set_handshake_header(s, htype, len) \ + s->method->ssl3_enc->set_handshake_header(s, htype, len) +#define ssl_do_write(s) s->method->ssl3_enc->do_write(s) + +/* Values for enc_flags */ + +/* Uses explicit IV for CBC mode */ +#define SSL_ENC_FLAG_EXPLICIT_IV 0x1 +/* Uses signature algorithms extension */ +#define SSL_ENC_FLAG_SIGALGS 0x2 +/* Is DTLS */ +#define SSL_ENC_FLAG_DTLS 0x4 + #ifndef OPENSSL_NO_COMP /* Used for holding the relevant compression methods loaded into SSL_CTX */ typedef struct ssl3_comp_st @@ -713,6 +737,8 @@ OPENSSL_EXTERN SSL_CIPHER ssl3_ciphers[]; SSL_METHOD *ssl_bad_method(int ver); extern SSL3_ENC_METHOD TLSv1_enc_data; +extern SSL3_ENC_METHOD TLSv1_1_enc_data; +extern SSL3_ENC_METHOD TLSv1_2_enc_data; extern SSL3_ENC_METHOD SSLv3_enc_data; extern SSL3_ENC_METHOD DTLSv1_enc_data; @@ -1044,6 +1070,9 @@ void ssl3_record_sequence_update(unsigned char *seq); int ssl3_do_change_cipher_spec(SSL *ssl); long ssl3_default_timeout(void ); +void ssl3_set_handshake_header(SSL *s, int htype, unsigned long len); +int ssl3_handshake_write(SSL *s); + int ssl23_num_ciphers(void ); const SSL_CIPHER *ssl23_get_cipher(unsigned int u); int ssl23_read(SSL *s, void *buf, int len); @@ -1115,9 +1144,6 @@ int ssl3_send_next_proto(SSL *s); #endif int dtls1_client_hello(SSL *s); -int dtls1_send_client_certificate(SSL *s); -int dtls1_send_client_key_exchange(SSL *s); -int dtls1_send_client_verify(SSL *s); /* some server-only functions */ int ssl3_get_client_hello(SSL *s); @@ -1134,15 +1160,6 @@ int ssl3_get_cert_verify(SSL *s); int ssl3_get_next_proto(SSL *s); #endif -int dtls1_send_hello_request(SSL *s); -int dtls1_send_server_hello(SSL *s); -int dtls1_send_server_certificate(SSL *s); -int dtls1_send_server_key_exchange(SSL *s); -int dtls1_send_certificate_request(SSL *s); -int dtls1_send_server_done(SSL *s); - - - int ssl23_accept(SSL *s); int ssl23_connect(SSL *s); int ssl23_read_bytes(SSL *s, int n); diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 92e8f88c53..359edbc298 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -140,6 +140,48 @@ SSL3_ENC_METHOD TLSv1_enc_data={ TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, tls1_alert_code, tls1_export_keying_material, + 0, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write + }; + +SSL3_ENC_METHOD TLSv1_1_enc_data={ + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS1_FINISH_MAC_LENGTH, + tls1_cert_verify_mac, + TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + SSL_ENC_FLAG_EXPLICIT_IV, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write + }; + +SSL3_ENC_METHOD TLSv1_2_enc_data={ + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS1_FINISH_MAC_LENGTH, + tls1_cert_verify_mac, + TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + SSL_ENC_FLAG_EXPLICIT_IV|SSL_ENC_FLAG_SIGALGS, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write }; long tls1_default_timeout(void)