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.
This commit is contained in:
Dr. Stephen Henson 2013-03-11 15:34:28 +00:00
parent 80ccc66d7e
commit 173e72e64c
11 changed files with 232 additions and 1970 deletions

View file

@ -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)

View file

@ -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' && 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;
@ -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 <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));
}

View file

@ -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);
}

View file

@ -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; 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

View file

@ -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]);
l -= 3 + SSL_HM_HEADER_LENGTH(s);
p = ssl_handshake_start(s);
l2n3(l,p);
l+=3;
p=(unsigned char *)&(buf->data[0]);
*(p++)=SSL3_MT_CERTIFICATE;
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),

View file

@ -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))

View file

@ -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;
}

View file

@ -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)

View file

@ -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

View file

@ -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);

View file

@ -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)