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
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)
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)
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;
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
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)))
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);
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' && i<sizeof(s->s3->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; i<j; i++)
- {
- comp=sk_SSL_COMP_value(s->ctx->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;
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 <sxw@sxw.org.uk>)
- ** 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));
- }
-
-
#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);
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)
(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);
+ }
+
+
s->shutdown=0;
dtls1_clear_record_buffer(s);
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_SR_CLNT_HELLO_A;
s->state=SSL3_ST_SW_FLUSH;
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)
&& !(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)
)
{
dtls1_start_timer(s);
- ret=dtls1_send_server_key_exchange(s);
+ ret=ssl3_send_server_key_exchange(s);
if (ret <= 0) goto end;
}
else
{
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;
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;
#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;
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);
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;
/* 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; i<sk_X509_NAME_num(sk); i++)
- {
- name=sk_X509_NAME_value(sk,i);
- j=i2d_X509_NAME(name,NULL);
- if (!BUF_MEM_grow_clean(buf,DTLS1_HM_HEADER_LENGTH+n+j+2))
- {
- SSLerr(SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB);
- goto err;
- }
- p=(unsigned char *)&(buf->data[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
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
*/
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
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),
/* 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
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)
}
#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);
}
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
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;
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);
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;
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);
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);
X509 *x509=NULL;
EVP_PKEY *pkey=NULL;
int i;
- unsigned long l;
if (s->state == SSL3_ST_CW_CERT_A)
{
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))
(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)
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;
return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
return alg2;
}
-
+
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)
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;
#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)
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++)
{
?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;
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))
{
}
}
- *(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:
{
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++;
}
}
/* 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);
}
int ssl3_send_server_certificate(SSL *s)
{
- unsigned long l;
CERT_PKEY *cpk;
if (s->state == SSL3_ST_SW_CERT_A)
}
}
- 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
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
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)
#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
(c)->algo_strength)
#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->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)
/* Mostly for SSLv3 */
#define SSL_PKEY_RSA_ENC 0
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
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;
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);
#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);
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);
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)