提交 173e72e6 编写于 作者: D Dr. Stephen Henson

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.
上级 80ccc66d
......@@ -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)
......
......@@ -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));
}
......@@ -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);
}
......@@ -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
......@@ -150,20 +150,18 @@ int ssl3_do_write(SSL *s, int type)
int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
{
unsigned char *p,*d;
unsigned char *p;
int i;
unsigned long l;
if (s->state == a)
{
d=(unsigned char *)s->init_buf->data;
p= &(d[4]);
p = ssl_handshake_start(s);
i=s->method->ssl3_enc->final_finish_mac(s,
sender,slen,s->s3->tmp.finish_md);
s->s3->tmp.finish_md_len = i;
memcpy(p, s->s3->tmp.finish_md, i);
p+=i;
l=i;
/* Copy the finished so we can use it for
......@@ -189,17 +187,12 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
*/
l&=0xffff;
#endif
*(d++)=SSL3_MT_FINISHED;
l2n3(l,d);
s->init_num=(int)l+4;
s->init_off=0;
ssl_set_handshake_header(s, SSL3_MT_FINISHED, l);
s->state=b;
}
/* SSL3_ST_SEND_xxxxxx_HELLO_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
return ssl_do_write(s);
}
#ifndef OPENSSL_NO_NEXTPROTONEG
......@@ -324,21 +317,17 @@ int ssl3_send_change_cipher_spec(SSL *s, int a, int b)
unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk)
{
unsigned char *p;
unsigned long l=7;
BUF_MEM *buf = s->init_buf;
unsigned long l = 3 + SSL_HM_HEADER_LENGTH(s);
if (!ssl_add_cert_chain(s, cpk, &l))
return 0;
l-=7;
p=(unsigned char *)&(buf->data[4]);
l2n3(l,p);
l+=3;
p=(unsigned char *)&(buf->data[0]);
*(p++)=SSL3_MT_CERTIFICATE;
l -= 3 + SSL_HM_HEADER_LENGTH(s);
p = ssl_handshake_start(s);
l2n3(l,p);
l+=4;
return(l);
l += 3;
ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l);
return l + SSL_HM_HEADER_LENGTH(s);
}
/* Obtain handshake message of message type 'mt' (any if mt == -1),
......
......@@ -697,13 +697,34 @@ int ssl3_client_hello(SSL *s)
/* else use the pre-loaded session */
p=s->s3->client_random;
/* 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);
if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
goto err;
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;
......@@ -2985,17 +3012,12 @@ int ssl3_send_client_key_exchange(SSL *s)
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))
......
......@@ -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;
......
......@@ -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
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)
......
......@@ -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
......
......@@ -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);
......
......@@ -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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册