case SSL3_ST_SR_CLNT_HELLO_B:
case SSL3_ST_SR_CLNT_HELLO_C:
- if (s->rwstate != SSL_X509_LOOKUP)
- {
- ret=ssl3_get_client_hello(s);
- if (ret <= 0) goto end;
- }
+ ret=ssl3_get_client_hello(s);
+ if (ret <= 0) goto end;
#ifndef OPENSSL_NO_SRP
+ s->state = SSL3_ST_SR_CLNT_HELLO_D;
+ case SSL3_ST_SR_CLNT_HELLO_D:
{
int al;
if ((ret = ssl_check_srp_ext_ClientHello(s,&al)) < 0)
#ifndef OPENSSL_NO_TLSEXT
case SSL3_ST_SW_SUPPLEMENTAL_DATA_A:
case SSL3_ST_SW_SUPPLEMENTAL_DATA_B:
- /* We promised to send an audit proof in the hello. */
- if (s->s3->tlsext_authz_promised_to_client)
- {
- ret = tls1_send_server_supplemental_data(s);
- if (ret <= 0) goto end;
- }
- else
- skip = 1;
+ ret = tls1_send_server_supplemental_data(s, &skip);
+ if (ret <= 0) goto end;
s->state = SSL3_ST_SW_CERT_A;
s->init_num = 0;
/* SRP: send ServerKeyExchange */
|| (alg_k & SSL_kSRP)
#endif
- || (alg_k & SSL_kEDH)
- || (alg_k & SSL_kEECDH)
+ || (alg_k & SSL_kDHE)
+ || (alg_k & SSL_kECDHE)
|| ((alg_k & SSL_kRSA)
&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
|| (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
s->state=s->s3->tmp.next_state;
break;
-
+#ifndef OPENSSL_NO_TLSEXT
+ case SSL3_ST_SR_SUPPLEMENTAL_DATA_A:
+ case SSL3_ST_SR_SUPPLEMENTAL_DATA_B:
+ ret=tls1_get_client_supplemental_data(s);
+ if (ret <= 0) goto end;
+ s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
+ s->state=SSL3_ST_SW_FLUSH;
+ s->init_num=0;
+ break;
+#endif
case SSL3_ST_SR_CERT_A:
case SSL3_ST_SR_CERT_B:
/* Check for second client hello (MS SGC) */
goto end;
if (ret == 2)
s->state = SSL3_ST_SR_CLNT_HELLO_C;
+#ifndef OPENSSL_NO_TLSEXT
+ else if (ret == 3)
+ s->state = SSL3_ST_SR_SUPPLEMENTAL_DATA_A;
+#endif
else {
if (s->s3->tmp.cert_request)
{
&ok);
if (!ok) return((int)n);
s->s3->tmp.reuse_message = 1;
+#ifndef OPENSSL_NO_TLSEXT
+ if (s->s3->tmp.message_type == SSL3_MT_SUPPLEMENTAL_DATA)
+ return 3;
+#endif
if (s->s3->tmp.message_type == SSL3_MT_CLIENT_HELLO)
{
/* We only allow the client to restart the handshake once per
#endif
STACK_OF(SSL_CIPHER) *ciphers=NULL;
+ if (s->state == SSL3_ST_SR_CLNT_HELLO_C)
+ goto retry_cert;
+
/* We do this so that we will respond with our native type.
* If we are TLSv1 and we get SSLv3, we will respond with TLSv1,
* This down switching should be handled by a different method.
s->client_version=(((int)p[0])<<8)|(int)p[1];
p+=2;
- if ((SSL_IS_DTLS(s) && s->client_version > s->version
- && s->method->version != DTLS_ANY_VERSION) ||
- (!SSL_IS_DTLS(s) && s->client_version < s->version))
+ if (SSL_IS_DTLS(s) ? (s->client_version > s->version &&
+ s->method->version != DTLS_ANY_VERSION)
+ : (s->client_version < s->version))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
- if ((s->client_version>>8) == SSL3_VERSION_MAJOR)
+ if ((s->client_version>>8) == SSL3_VERSION_MAJOR &&
+ !s->enc_write_ctx && !s->write_hash)
{
/* similar to ssl3_get_record, send alert using remote version number */
s->version = s->client_version;
* server_random before calling tls_session_secret_cb in order to allow
* SessionTicket processing to use it in key derivation. */
{
- unsigned long Time;
unsigned char *pos;
- Time=(unsigned long)time(NULL); /* Time */
pos=s->s3->server_random;
- l2n(Time,pos);
- if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
+ if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE) <= 0)
{
goto f_err;
}
}
ciphers=NULL;
/* Let cert callback update server certificates if required */
- if (s->cert->cert_cb
- && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0)
+ retry_cert:
+ if (s->cert->cert_cb)
{
- al=SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CERT_CB_ERROR);
- goto f_err;
+ int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);
+ if (rv == 0)
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CERT_CB_ERROR);
+ goto f_err;
+ }
+ if (rv < 0)
+ {
+ s->rwstate=SSL_X509_LOOKUP;
+ return -1;
+ }
+ s->rwstate = SSL_NOTHING;
}
c=ssl3_choose_cipher(s,s->session->ciphers,
SSL_get_ciphers(s));
/* check whether we should disable session resumption */
if (s->not_resumable_session_cb != NULL)
s->session->not_resumable=s->not_resumable_session_cb(s,
- ((c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH)) != 0));
+ ((c->algorithm_mkey & (SSL_kDHE | SSL_kECDHE)) != 0));
if (s->session->not_resumable)
/* do not send a session ticket */
s->tlsext_ticket_expected = 0;
unsigned char *p,*d;
int i,sl;
unsigned long l;
-#ifdef OPENSSL_NO_TLSEXT
- unsigned long Time;
-#endif
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
{
buf=(unsigned char *)s->init_buf->data;
#ifdef OPENSSL_NO_TLSEXT
p=s->s3->server_random;
- /* Generate server_random if it was not needed previously */
- Time=(unsigned long)time(NULL); /* Time */
- l2n(Time,p);
- if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
+ if (ssl_fill_hello_random(s, 1, p, SSL3_RANDOM_SIZE) <= 0)
return -1;
#endif
/* Do the message type and length last */
else
#endif
#ifndef OPENSSL_NO_DH
- if (type & SSL_kEDH)
+ if (type & SSL_kDHE)
{
dhp=cert->dh_tmp;
if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL))
else
#endif
#ifndef OPENSSL_NO_ECDH
- if (type & SSL_kEECDH)
+ if (type & SSL_kECDHE)
{
const EC_GROUP *group;
}
#ifndef OPENSSL_NO_ECDH
- if (type & SSL_kEECDH)
+ if (type & SSL_kECDHE)
{
/* XXX: For now, we only support named (not generic) curves.
* In this situation, the serverKeyExchange message has:
{
name=sk_X509_NAME_value(sk,i);
j=i2d_X509_NAME(name,NULL);
- if (!BUF_MEM_grow_clean(buf,4+n+j+2))
+ if (!BUF_MEM_grow_clean(buf,SSL_HM_HEADER_LENGTH(s)+n+j+2))
{
SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB);
goto err;
}
- p=(unsigned char *)&(buf->data[4+n]);
+ p = ssl_handshake_start(s) + n;
if (!(s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
{
s2n(j,p);
else
#endif
#ifndef OPENSSL_NO_DH
- if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
+ if (alg_k & (SSL_kDHE|SSL_kDHr|SSL_kDHd))
{
int idx = -1;
EVP_PKEY *skey = NULL;
#endif /* OPENSSL_NO_KRB5 */
#ifndef OPENSSL_NO_ECDH
- if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe))
+ if (alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe))
{
int ret = 1;
int field_size = 0;
{
/* Client Publickey was in Client Certificate */
- if (alg_k & SSL_kEECDH)
+ if (alg_k & SSL_kECDHE)
{
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_MISSING_TMP_ECDH_KEY);
}
# endif
-int tls1_send_server_supplemental_data(SSL *s)
+int tls1_send_server_supplemental_data(SSL *s, int *skip)
{
- size_t length = 0;
- const unsigned char *authz, *orig_authz;
- unsigned char *p;
- size_t authz_length, i;
-
- if (s->state != SSL3_ST_SW_SUPPLEMENTAL_DATA_A)
- return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
-
- orig_authz = authz = ssl_get_authz_data(s, &authz_length);
- if (authz == NULL)
- {
- /* This should never occur. */
- return 0;
- }
-
- /* First we walk over the authz data to see how long the handshake
- * message will be. */
- for (i = 0; i < authz_length; i++)
- {
- unsigned short len;
- unsigned char type;
+ if (s->ctx->srv_supp_data_records_count)
+ {
+ unsigned char *p = NULL;
+ unsigned char *size_loc = NULL;
+ srv_supp_data_record *record = NULL;
+ size_t length = 0;
+ size_t i = 0;
+
+ for (i = 0; i < s->ctx->srv_supp_data_records_count; i++)
+ {
+ const unsigned char *out = NULL;
+ unsigned short outlen = 0;
+ int cb_retval = 0;
+ record = &s->ctx->srv_supp_data_records[i];
+
+ /* NULL callback or -1 omits supp data entry */
+ if (!record->fn1)
+ continue;
+ cb_retval = record->fn1(s, record->supp_data_type,
+ &out, &outlen,
+ record->arg);
+ if (cb_retval == -1)
+ continue; /* skip this supp data entry */
+ if (cb_retval == 0)
+ {
+ SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ if (outlen == 0 || TLSEXT_MAXLEN_supplemental_data < outlen + 4 + length)
+ {
+ SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ /* write supp data entry...
+ * if first entry, write handshake message type
+ * jump back to write length at end */
+ if (length == 0)
+ {
+ /* 1 byte message type + 3 bytes for
+ * message length */
+ if (!BUF_MEM_grow_clean(s->init_buf, 4))
+ {
+ SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ p = (unsigned char *)s->init_buf->data;
+ *(p++) = SSL3_MT_SUPPLEMENTAL_DATA;
+ /* hold on to length field to update later */
+ size_loc = p;
+ /* skip over handshake length field (3
+ * bytes) and supp_data length field
+ * (3 bytes) */
+ p += 3 + 3;
+ length += 1 +3 +3;
+ }
+ /* 2 byte supp data type + 2 byte length + outlen */
+ if (!BUF_MEM_grow(s->init_buf, outlen + 4))
+ {
+ SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
+ return 0;
+ }
+ s2n(record->supp_data_type, p);
+ s2n(outlen, p);
+ memcpy(p, out, outlen);
+ /* update length to supp data type (2 bytes) +
+ * supp data length (2 bytes) + supp data */
+ length += (outlen + 4);
+ p += outlen;
+ }
+ if (length > 0)
+ {
+ /* write handshake length */
+ l2n3(length - 4, size_loc);
+ /* supp_data length */
+ l2n3(length - 7, size_loc);
+ s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_B;
+ s->init_num = length;
+ s->init_off = 0;
+
+ return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+ }
+ }
+
+ /* no supp data message sent */
+ *skip = 1;
+ s->init_num = 0;
+ s->init_off = 0;
+ return 1;
+ }
- type = *(authz++);
- n2s(authz, len);
- /* n2s increments authz by 2*/
- i += 2;
+int tls1_get_client_supplemental_data(SSL *s)
+ {
+ int al = 0;
+ int cb_retval = 0;
+ int ok;
+ long n;
+ const unsigned char *p, *d;
+ unsigned short supp_data_entry_type = 0;
+ unsigned long supp_data_entry_len = 0;
+ unsigned long supp_data_len = 0;
+ size_t i = 0;
- if (memchr(s->s3->tlsext_authz_client_types,
- type,
- s->s3->tlsext_authz_client_types_len) != NULL)
- length += 1 /* authz type */ + 2 /* length */ + len;
+ n=s->method->ssl_get_message(s,
+ SSL3_ST_SR_SUPPLEMENTAL_DATA_A,
+ SSL3_ST_SR_SUPPLEMENTAL_DATA_B,
+ SSL3_MT_SUPPLEMENTAL_DATA,
+ /* use default limit */
+ TLSEXT_MAXLEN_supplemental_data,
+ &ok);
- authz += len;
- i += len;
- }
+ if (!ok) return((int)n);
- length += 1 /* handshake type */ +
- 3 /* handshake length */ +
- 3 /* supplemental data length */ +
- 2 /* supplemental entry type */ +
- 2 /* supplemental entry length */;
+ p = (unsigned char *)s->init_msg;
+ d = p;
- if (!BUF_MEM_grow_clean(s->init_buf, length))
+ /* The message cannot be empty */
+ if (n < 3)
{
- SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
- return 0;
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS1_GET_CLIENT_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
+ goto f_err;
}
-
- p = (unsigned char *)s->init_buf->data;
- *(p++) = SSL3_MT_SUPPLEMENTAL_DATA;
- /* Handshake length */
- l2n3(length - 4, p);
- /* Length of supplemental data */
- l2n3(length - 7, p);
- /* Supplemental data type */
- s2n(TLSEXT_SUPPLEMENTALDATATYPE_authz_data, p);
- /* Its length */
- s2n(length - 11, p);
-
- authz = orig_authz;
-
- /* Walk over the authz again and append the selected elements. */
- for (i = 0; i < authz_length; i++)
+ n2l3(p, supp_data_len);
+ while (p<d+supp_data_len)
{
- unsigned short len;
- unsigned char type;
-
- type = *(authz++);
- n2s(authz, len);
- /* n2s increments authz by 2 */
- i += 2;
-
- if (memchr(s->s3->tlsext_authz_client_types,
- type,
- s->s3->tlsext_authz_client_types_len) != NULL)
+ n2s(p, supp_data_entry_type);
+ n2s(p, supp_data_entry_len);
+ /* if there is a callback for this supp data type, send it */
+ for (i=0; i < s->ctx->srv_supp_data_records_count; i++)
{
- *(p++) = type;
- s2n(len, p);
- memcpy(p, authz, len);
- p += len;
+ if (s->ctx->srv_supp_data_records[i].supp_data_type == supp_data_entry_type && s->ctx->srv_supp_data_records[i].fn2)
+ {
+ cb_retval = s->ctx->srv_supp_data_records[i].fn2(s, supp_data_entry_type, p, supp_data_entry_len, &al, s->ctx->srv_supp_data_records[i].arg);
+ if (cb_retval == 0)
+ {
+ SSLerr(SSL_F_TLS1_GET_CLIENT_SUPPLEMENTAL_DATA, ERR_R_SSL_LIB);
+ goto f_err;
+ }
+ }
}
-
- authz += len;
- i += len;
+ p+=supp_data_entry_len;
}
-
- s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_B;
- s->init_num = length;
- s->init_off = 0;
-
- return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+ return 1;
+f_err:
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
+ return -1;
}
#endif