mirror of
https://github.com/openssl/openssl.git
synced 2025-01-30 14:01:55 +08:00
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.
(cherry picked from commit 173e72e64c
)
This commit is contained in:
parent
7c23127fde
commit
741c9959f6
@ -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)
|
||||
|
899
ssl/d1_clnt.c
899
ssl/d1_clnt.c
@ -296,7 +296,7 @@ int dtls1_connect(SSL *s)
|
||||
ssl3_init_finished_mac(s);
|
||||
|
||||
dtls1_start_timer(s);
|
||||
ret=dtls1_client_hello(s);
|
||||
ret=ssl3_client_hello(s);
|
||||
if (ret <= 0) goto end;
|
||||
|
||||
if ( s->d1->send_cookie)
|
||||
@ -460,7 +460,7 @@ int dtls1_connect(SSL *s)
|
||||
case SSL3_ST_CW_CERT_C:
|
||||
case SSL3_ST_CW_CERT_D:
|
||||
dtls1_start_timer(s);
|
||||
ret=dtls1_send_client_certificate(s);
|
||||
ret=ssl3_send_client_certificate(s);
|
||||
if (ret <= 0) goto end;
|
||||
s->state=SSL3_ST_CW_KEY_EXCH_A;
|
||||
s->init_num=0;
|
||||
@ -469,7 +469,7 @@ int dtls1_connect(SSL *s)
|
||||
case SSL3_ST_CW_KEY_EXCH_A:
|
||||
case SSL3_ST_CW_KEY_EXCH_B:
|
||||
dtls1_start_timer(s);
|
||||
ret=dtls1_send_client_key_exchange(s);
|
||||
ret=ssl3_send_client_key_exchange(s);
|
||||
if (ret <= 0) goto end;
|
||||
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
@ -515,7 +515,7 @@ int dtls1_connect(SSL *s)
|
||||
case SSL3_ST_CW_CERT_VRFY_A:
|
||||
case SSL3_ST_CW_CERT_VRFY_B:
|
||||
dtls1_start_timer(s);
|
||||
ret=dtls1_send_client_verify(s);
|
||||
ret=ssl3_send_client_verify(s);
|
||||
if (ret <= 0) goto end;
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
|
||||
@ -578,7 +578,7 @@ int dtls1_connect(SSL *s)
|
||||
case SSL3_ST_CW_FINISHED_B:
|
||||
if (!s->hit)
|
||||
dtls1_start_timer(s);
|
||||
ret=dtls1_send_finished(s,
|
||||
ret=ssl3_send_finished(s,
|
||||
SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
|
||||
s->method->ssl3_enc->client_finished_label,
|
||||
s->method->ssl3_enc->client_finished_label_len);
|
||||
@ -768,133 +768,6 @@ end:
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int dtls1_client_hello(SSL *s)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned char *p,*d;
|
||||
unsigned int i,j;
|
||||
unsigned long Time,l;
|
||||
SSL_COMP *comp;
|
||||
|
||||
buf=(unsigned char *)s->init_buf->data;
|
||||
if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
|
||||
{
|
||||
SSL_SESSION *sess = s->session;
|
||||
if ((s->session == NULL) ||
|
||||
(s->session->ssl_version != s->version) ||
|
||||
#ifdef OPENSSL_NO_TLSEXT
|
||||
!sess->session_id_length ||
|
||||
#else
|
||||
(!sess->session_id_length && !sess->tlsext_tick) ||
|
||||
#endif
|
||||
(s->session->not_resumable))
|
||||
{
|
||||
if (!ssl_get_new_session(s,0))
|
||||
goto err;
|
||||
}
|
||||
/* else use the pre-loaded session */
|
||||
|
||||
p=s->s3->client_random;
|
||||
|
||||
/* if client_random is initialized, reuse it, we are
|
||||
* required to use same upon reply to HelloVerify */
|
||||
for (i=0;p[i]=='\0' && 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));
|
||||
}
|
||||
|
||||
|
||||
|
23
ssl/d1_lib.c
23
ssl/d1_lib.c
@ -67,6 +67,8 @@
|
||||
#endif
|
||||
|
||||
static void get_current_time(struct timeval *t);
|
||||
static void dtls1_set_handshake_header(SSL *s, int type, unsigned long len);
|
||||
static int dtls1_handshake_write(SSL *s);
|
||||
const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT;
|
||||
int dtls1_listen(SSL *s, struct sockaddr *client);
|
||||
|
||||
@ -83,6 +85,10 @@ SSL3_ENC_METHOD DTLSv1_enc_data={
|
||||
TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
|
||||
tls1_alert_code,
|
||||
tls1_export_keying_material,
|
||||
SSL_ENC_FLAG_DTLS|SSL_ENC_FLAG_EXPLICIT_IV,
|
||||
DTLS1_HM_HEADER_LENGTH,
|
||||
dtls1_set_handshake_header,
|
||||
dtls1_handshake_write
|
||||
};
|
||||
|
||||
long dtls1_default_timeout(void)
|
||||
@ -481,3 +487,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);
|
||||
}
|
||||
|
||||
|
||||
|
842
ssl/d1_srvr.c
842
ssl/d1_srvr.c
@ -278,7 +278,7 @@ int dtls1_accept(SSL *s)
|
||||
s->shutdown=0;
|
||||
dtls1_clear_record_buffer(s);
|
||||
dtls1_start_timer(s);
|
||||
ret=dtls1_send_hello_request(s);
|
||||
ret=ssl3_send_hello_request(s);
|
||||
if (ret <= 0) goto end;
|
||||
s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
|
||||
s->state=SSL3_ST_SW_FLUSH;
|
||||
@ -383,7 +383,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)
|
||||
@ -423,7 +423,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)
|
||||
@ -485,7 +485,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
|
||||
@ -532,7 +532,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;
|
||||
@ -561,7 +561,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;
|
||||
@ -693,7 +693,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;
|
||||
@ -743,7 +743,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);
|
||||
@ -846,28 +846,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;
|
||||
@ -906,807 +884,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]);
|
||||
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),
|
||||
|
@ -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))
|
||||
|
20
ssl/s3_lib.c
20
ssl/s3_lib.c
@ -2918,6 +2918,10 @@ SSL3_ENC_METHOD SSLv3_enc_data={
|
||||
(int (*)(SSL *, unsigned char *, size_t, const char *,
|
||||
size_t, const unsigned char *, size_t,
|
||||
int use_context))ssl_undefined_function,
|
||||
0,
|
||||
SSL3_HM_HEADER_LENGTH,
|
||||
ssl3_set_handshake_header,
|
||||
ssl3_handshake_write
|
||||
};
|
||||
|
||||
long ssl3_default_timeout(void)
|
||||
@ -2948,6 +2952,20 @@ int ssl3_pending(const SSL *s)
|
||||
return (s->s3->rrec.type == SSL3_RT_APPLICATION_DATA) ? s->s3->rrec.length : 0;
|
||||
}
|
||||
|
||||
void ssl3_set_handshake_header(SSL *s, int htype, unsigned long len)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)s->init_buf->data;
|
||||
*(p++) = htype;
|
||||
l2n3(len, p);
|
||||
s->init_num = (int)len + SSL3_HM_HEADER_LENGTH;
|
||||
s->init_off = 0;
|
||||
}
|
||||
|
||||
int ssl3_handshake_write(SSL *s)
|
||||
{
|
||||
return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
|
||||
}
|
||||
|
||||
int ssl3_new(SSL *s)
|
||||
{
|
||||
SSL3_STATE *s3;
|
||||
@ -4467,4 +4485,4 @@ long ssl_get_algorithm2(SSL *s)
|
||||
return SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256;
|
||||
return alg2;
|
||||
}
|
||||
|
||||
|
||||
|
132
ssl/s3_srvr.c
132
ssl/s3_srvr.c
@ -869,24 +869,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)
|
||||
@ -1472,7 +1463,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;
|
||||
@ -1537,42 +1528,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)
|
||||
@ -1896,13 +1870,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++)
|
||||
{
|
||||
@ -1974,7 +1947,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;
|
||||
@ -2013,7 +1986,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))
|
||||
{
|
||||
@ -2034,18 +2007,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:
|
||||
@ -2069,7 +2036,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++;
|
||||
@ -2124,34 +2091,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);
|
||||
}
|
||||
@ -3387,7 +3349,6 @@ err:
|
||||
|
||||
int ssl3_send_server_certificate(SSL *s)
|
||||
{
|
||||
unsigned long l;
|
||||
CERT_PKEY *cpk;
|
||||
|
||||
if (s->state == SSL3_ST_SW_CERT_A)
|
||||
@ -3404,14 +3365,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
|
||||
@ -3465,22 +3424,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
|
||||
@ -3535,21 +3489,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
|
||||
|
@ -440,8 +440,8 @@
|
||||
(c)->algo_strength)
|
||||
#define SSL_C_EXPORT_PKEYLENGTH(c) SSL_EXPORT_PKEYLENGTH((c)->algo_strength)
|
||||
|
||||
|
||||
|
||||
/* Check if an SSL structure is using DTLS */
|
||||
#define SSL_IS_DTLS(s) (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)
|
||||
|
||||
/* Mostly for SSLv3 */
|
||||
#define SSL_PKEY_RSA_ENC 0
|
||||
@ -688,8 +688,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
|
||||
@ -722,6 +746,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;
|
||||
|
||||
@ -1057,6 +1083,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);
|
||||
@ -1128,9 +1157,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);
|
||||
@ -1147,15 +1173,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);
|
||||
|
42
ssl/t1_lib.c
42
ssl/t1_lib.c
@ -140,6 +140,48 @@ SSL3_ENC_METHOD TLSv1_enc_data={
|
||||
TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
|
||||
tls1_alert_code,
|
||||
tls1_export_keying_material,
|
||||
0,
|
||||
SSL3_HM_HEADER_LENGTH,
|
||||
ssl3_set_handshake_header,
|
||||
ssl3_handshake_write
|
||||
};
|
||||
|
||||
SSL3_ENC_METHOD TLSv1_1_enc_data={
|
||||
tls1_enc,
|
||||
tls1_mac,
|
||||
tls1_setup_key_block,
|
||||
tls1_generate_master_secret,
|
||||
tls1_change_cipher_state,
|
||||
tls1_final_finish_mac,
|
||||
TLS1_FINISH_MAC_LENGTH,
|
||||
tls1_cert_verify_mac,
|
||||
TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
|
||||
TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
|
||||
tls1_alert_code,
|
||||
tls1_export_keying_material,
|
||||
SSL_ENC_FLAG_EXPLICIT_IV,
|
||||
SSL3_HM_HEADER_LENGTH,
|
||||
ssl3_set_handshake_header,
|
||||
ssl3_handshake_write
|
||||
};
|
||||
|
||||
SSL3_ENC_METHOD TLSv1_2_enc_data={
|
||||
tls1_enc,
|
||||
tls1_mac,
|
||||
tls1_setup_key_block,
|
||||
tls1_generate_master_secret,
|
||||
tls1_change_cipher_state,
|
||||
tls1_final_finish_mac,
|
||||
TLS1_FINISH_MAC_LENGTH,
|
||||
tls1_cert_verify_mac,
|
||||
TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
|
||||
TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
|
||||
tls1_alert_code,
|
||||
tls1_export_keying_material,
|
||||
SSL_ENC_FLAG_EXPLICIT_IV|SSL_ENC_FLAG_SIGALGS,
|
||||
SSL3_HM_HEADER_LENGTH,
|
||||
ssl3_set_handshake_header,
|
||||
ssl3_handshake_write
|
||||
};
|
||||
|
||||
long tls1_default_timeout(void)
|
||||
|
Loading…
Reference in New Issue
Block a user