* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
*/
/* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/md5.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
-static SSL_METHOD *dtls1_get_client_method(int ver);
+static const SSL_METHOD *dtls1_get_client_method(int ver);
static int dtls1_get_hello_verify(SSL *s);
-static SSL_METHOD *dtls1_get_client_method(int ver)
+static const SSL_METHOD *dtls1_get_client_method(int ver)
{
if (ver == DTLS1_VERSION)
return(DTLSv1_client_method());
return(NULL);
}
-SSL_METHOD *DTLSv1_client_method(void)
- {
- static int init=1;
- static SSL_METHOD DTLSv1_client_data;
-
- if (init)
- {
- CRYPTO_w_lock(CRYPTO_LOCK_SSL_METHOD);
-
- if (init)
- {
- memcpy((char *)&DTLSv1_client_data,(char *)dtlsv1_base_method(),
- sizeof(SSL_METHOD));
- DTLSv1_client_data.ssl_connect=dtls1_connect;
- DTLSv1_client_data.get_ssl_method=dtls1_get_client_method;
- init=0;
- }
-
- CRYPTO_w_unlock(CRYPTO_LOCK_SSL_METHOD);
- }
- return(&DTLSv1_client_data);
- }
+IMPLEMENT_dtls1_meth_func(DTLSv1_client_method,
+ ssl_undefined_function,
+ dtls1_connect,
+ dtls1_get_client_method)
int dtls1_connect(SSL *s)
{
BUF_MEM *buf=NULL;
- unsigned long Time=time(NULL),l;
+ unsigned long Time=(unsigned long)time(NULL);
long num1;
void (*cb)(const SSL *ssl,int type,int val)=NULL;
int ret= -1;
if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00))
{
- SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR);
ret = -1;
goto end;
}
/* don't push the buffering BIO quite yet */
- ssl3_init_finished_mac(s);
-
s->state=SSL3_ST_CW_CLNT_HELLO_A;
s->ctx->stats.sess_connect++;
s->init_num=0;
+ /* mark client_random uninitialized */
+ memset(s->s3->client_random,0,sizeof(s->s3->client_random));
break;
case SSL3_ST_CW_CLNT_HELLO_A:
case SSL3_ST_CW_CLNT_HELLO_B:
s->shutdown=0;
+
+ /* every DTLS ClientHello resets Finished MAC */
+ ssl3_init_finished_mac(s);
+
ret=dtls1_client_hello(s);
if (ret <= 0) goto end;
case SSL3_ST_CR_CERT_A:
case SSL3_ST_CR_CERT_B:
/* Check if it is anon DH */
- if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
+ if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
{
ret=ssl3_get_server_certificate(s);
if (ret <= 0) goto end;
case SSL3_ST_CW_KEY_EXCH_B:
ret=dtls1_send_client_key_exchange(s);
if (ret <= 0) goto end;
- l=s->s3->tmp.new_cipher->algorithms;
/* EAY EAY EAY need to check for DH fix cert
* sent back */
/* For TLS, cert_req is set to 2, so a cert chain
s->init_num=0;
s->session->cipher=s->s3->tmp.new_cipher;
+#ifdef OPENSSL_NO_COMP
+ s->session->compress_meth=0;
+#else
if (s->s3->tmp.new_compression == NULL)
s->session->compress_meth=0;
else
s->session->compress_meth=
s->s3->tmp.new_compression->id;
+#endif
if (!s->method->ssl3_enc->setup_key_block(s))
{
ret= -1;
s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
}
s->init_num=0;
+ /* mark client_random uninitialized */
+ memset (s->s3->client_random,0,sizeof(s->s3->client_random));
break;
case SSL3_ST_CR_FINISHED_A:
/* break; */
default:
- SSLerr(SSL_F_SSL3_CONNECT,SSL_R_UNKNOWN_STATE);
+ SSLerr(SSL_F_DTLS1_CONNECT,SSL_R_UNKNOWN_STATE);
ret= -1;
goto end;
/* break; */
{
unsigned char *buf;
unsigned char *p,*d;
- int i,j;
+ unsigned int i,j;
unsigned long Time,l;
SSL_COMP *comp;
/* else use the pre-loaded session */
p=s->s3->client_random;
- Time=time(NULL); /* Time */
- l2n(Time,p);
- RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
+
+ /* 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]);
{
if (i > sizeof s->session->session_id)
{
- SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
goto err;
}
memcpy(p,s->session->session_id,i);
/* cookie stuff */
if ( s->d1->cookie_len > sizeof(s->d1->cookie))
{
- SSLerr(SSL_F_SSL3_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_DTLS1_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
goto err;
}
*(p++) = s->d1->cookie_len;
p += s->d1->cookie_len;
/* Ciphers supported */
- i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]));
+ i=ssl_cipher_list_to_bytes(s,SSL_get_ciphers(s),&(p[2]),0);
if (i == 0)
{
- SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
+ SSLerr(SSL_F_DTLS1_CLIENT_HELLO,SSL_R_NO_CIPHERS_AVAILABLE);
goto err;
}
s2n(i,p);
if ((data[0] != (s->version>>8)) || (data[1] != (s->version&0xff)))
{
- SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_SSL_VERSION);
+ SSLerr(SSL_F_DTLS1_GET_HELLO_VERIFY,SSL_R_WRONG_SSL_VERSION);
s->version=(s->version&0xff00)|data[1];
al = SSL_AD_PROTOCOL_VERSION;
goto f_err;
{
unsigned char *p,*d;
int n;
- unsigned long l;
+ unsigned long alg_k;
#ifndef OPENSSL_NO_RSA
unsigned char *q;
EVP_PKEY *pkey=NULL;
{
d=(unsigned char *)s->init_buf->data;
p= &(d[DTLS1_HM_HEADER_LENGTH]);
-
- l=s->s3->tmp.new_cipher->algorithms;
+
+ alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
/* Fool emacs indentation */
if (0) {}
#ifndef OPENSSL_NO_RSA
- else if (l & SSL_kRSA)
+ else if (alg_k & SSL_kRSA)
{
RSA *rsa;
unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
(pkey->type != EVP_PKEY_RSA) ||
(pkey->pkey.rsa == NULL))
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
goto err;
}
rsa=pkey->pkey.rsa;
s->session->master_key_length=sizeof tmp_buf;
q=p;
- /* Fix buf for TLS and beyond */
+ /* Fix buf for TLS and [incidentally] DTLS */
if (s->version > SSL3_VERSION)
p+=2;
n=RSA_public_encrypt(sizeof tmp_buf,
#endif
if (n <= 0)
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_ENCRYPT);
goto err;
}
- /* Fix buf for TLS and beyond */
+ /* Fix buf for TLS and [incidentally] DTLS */
if (s->version > SSL3_VERSION)
{
s2n(n,q);
}
#endif
#ifndef OPENSSL_NO_KRB5
- else if (l & SSL_kKRB5)
+ else if (alg_k & SSL_kKRB5)
{
krb5_error_code krb5rc;
KSSL_CTX *kssl_ctx = s->kssl_ctx;
#ifdef KSSL_DEBUG
printf("ssl3_send_client_key_exchange(%lx & %lx)\n",
- l, SSL_kKRB5);
+ alg_k, SSL_kKRB5);
#endif /* KSSL_DEBUG */
authp = NULL;
{
ssl3_send_alert(s,SSL3_AL_FATAL,
SSL_AD_HANDSHAKE_FAILURE);
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,
kssl_err.reason);
goto err;
}
outl += padl;
if (outl > sizeof epms)
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_CIPHER_CTX_cleanup(&ciph_ctx);
}
#endif
#ifndef OPENSSL_NO_DH
- else if (l & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+ else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
{
DH *dh_srvr,*dh_clnt;
{
/* we get them from the cert */
ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_DH_PARAMETERS);
+ 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_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
goto err;
}
if (!DH_generate_key(dh_clnt))
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
goto err;
}
if (n <= 0)
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_DH_LIB);
goto err;
}
else
{
ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
- SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
goto err;
}
p= &(d[DTLS1_HM_HEADER_LENGTH]);
pkey=s->cert->key->privatekey;
- s->method->ssl3_enc->cert_verify_mac(s,&(s->s3->finish_dgst2),
+ 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,
- &(s->s3->finish_dgst1),&(data[0]));
+ 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_SSL3_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,ERR_R_RSA_LIB);
goto err;
}
s2n(u,p);
SHA_DIGEST_LENGTH,&(p[2]),
(unsigned int *)&j,pkey->pkey.dsa))
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,ERR_R_DSA_LIB);
goto err;
}
s2n(j,p);
else
#endif
{
- SSLerr(SSL_F_SSL3_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_VERIFY,ERR_R_INTERNAL_ERROR);
goto err;
}
else if (i == 1)
{
i=0;
- SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
+ SSLerr(SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
}
if (x509 != NULL) X509_free(x509);