}
s->init_num=0;
break;
-#ifndef OPENSSL_NO_TLSEXT
- case SSL3_ST_CR_SUPPLEMENTAL_DATA_A:
- case SSL3_ST_CR_SUPPLEMENTAL_DATA_B:
- ret = tls1_get_server_supplemental_data(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CR_CERT_A;
- s->init_num = 0;
- break;
-#endif
case SSL3_ST_CR_CERT_A:
case SSL3_ST_CR_CERT_B:
#ifndef OPENSSL_NO_TLSEXT
ret=ssl3_check_finished(s);
if (ret <= 0) goto end;
- if (ret == 3)
- {
- s->state=SSL3_ST_CR_SUPPLEMENTAL_DATA_A;
- s->init_num=0;
- break;
- }
if (ret == 2)
{
s->hit = 1;
break;
}
#endif
- /* Check if it is anon DH/ECDH */
+ /* Check if it is anon DH/ECDH, SRP auth */
/* or PSK */
- if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
+ if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aSRP)) &&
!(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
{
ret=ssl3_get_server_certificate(s);
}
}
#endif
-#ifndef OPENSSL_NO_TLSEXT
- s->state=SSL3_ST_CW_SUPPLEMENTAL_DATA_A;
-#else
if (s->s3->tmp.cert_req)
s->state=SSL3_ST_CW_CERT_A;
else
s->state=SSL3_ST_CW_KEY_EXCH_A;
-#endif
s->init_num=0;
break;
break;
#endif
-#ifndef OPENSSL_NO_TLSEXT
- case SSL3_ST_CW_SUPPLEMENTAL_DATA_A:
- case SSL3_ST_CW_SUPPLEMENTAL_DATA_B:
- ret = tls1_send_client_supplemental_data(s, &skip);
- if (ret <= 0) goto end;
- if (s->s3->tmp.cert_req)
- s->state=SSL3_ST_CW_CERT_A;
- else
- s->state=SSL3_ST_CW_KEY_EXCH_A;
- s->init_num=0;
- break;
-#endif
-
case SSL3_ST_CW_FINISHED_A:
case SSL3_ST_CW_FINISHED_B:
ret=ssl3_send_finished(s,
s->method->ssl3_enc->client_finished_label,
s->method->ssl3_enc->client_finished_label_len);
if (ret <= 0) goto end;
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
s->state=SSL3_ST_CW_FLUSH;
/* clear flags */
case SSL3_ST_CR_FINISHED_A:
case SSL3_ST_CR_FINISHED_B:
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
SSL3_ST_CR_FINISHED_B);
if (ret <= 0) goto end;
{
s->session->cipher = pref_cipher ?
pref_cipher : ssl_get_cipher_by_char(s, p+j);
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
}
}
#endif /* OPENSSL_NO_TLSEXT */
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
goto f_err;
}
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
s->hit=1;
}
else /* a miss or crap from the other end */
#endif
EVP_MD_CTX md_ctx;
unsigned char *param,*p;
- int al,i,j,param_len,ok;
- long n,alg_k,alg_a;
+ int al,j,ok;
+ long i,param_len,n,alg_k,alg_a;
EVP_PKEY *pkey=NULL;
const EVP_MD *md = NULL;
#ifndef OPENSSL_NO_RSA
s->session->sess_cert=ssl_sess_cert_new();
}
+ /* Total length of the parameters including the length prefix */
param_len=0;
+
alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
alg_a=s->s3->tmp.new_cipher->algorithm_auth;
EVP_MD_CTX_init(&md_ctx);
+ al=SSL_AD_DECODE_ERROR;
+
#ifndef OPENSSL_NO_PSK
if (alg_k & SSL_kPSK)
{
char tmp_id_hint[PSK_MAX_IDENTITY_LEN+1];
- al=SSL_AD_HANDSHAKE_FAILURE;
+ param_len = 2;
+ if (param_len > n)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
n2s(p,i);
- param_len=i+2;
+
/* Store PSK identity hint for later use, hint is used
* in ssl3_send_client_key_exchange. Assume that the
* maximum length of a PSK identity hint can be as
* long as the maximum length of a PSK identity. */
if (i > PSK_MAX_IDENTITY_LEN)
{
+ al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
SSL_R_DATA_LENGTH_TOO_LONG);
goto f_err;
}
- if (param_len > n)
+ if (i > n - param_len)
{
- al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH);
goto f_err;
}
+ param_len += i;
+
/* If received PSK identity hint contains NULL
* characters, the hint is truncated from the first
* NULL. p may not be ending with NULL, so create a
s->ctx->psk_identity_hint = BUF_strdup(tmp_id_hint);
if (s->ctx->psk_identity_hint == NULL)
{
+ al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
goto f_err;
}
#ifndef OPENSSL_NO_SRP
if (alg_k & SSL_kSRP)
{
- n2s(p,i);
- param_len=i+2;
+ param_len = 2;
if (param_len > n)
{
- al=SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ n2s(p,i);
+
+ if (i > n - param_len)
+ {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_N_LENGTH);
goto f_err;
}
+ param_len += i;
+
if (!(s->srp_ctx.N=BN_bin2bn(p,i,NULL)))
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
}
p+=i;
+
+ if (2 > n - param_len)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ param_len += 2;
+
n2s(p,i);
- param_len+=i+2;
- if (param_len > n)
+
+ if (i > n - param_len)
{
- al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_G_LENGTH);
goto f_err;
}
+ param_len += i;
+
if (!(s->srp_ctx.g=BN_bin2bn(p,i,NULL)))
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
}
p+=i;
+
+ if (1 > n - param_len)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ param_len += 1;
+
i = (unsigned int)(p[0]);
p++;
- param_len+=i+1;
- if (param_len > n)
+
+ if (i > n - param_len)
{
- al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_S_LENGTH);
goto f_err;
}
+ param_len += i;
+
if (!(s->srp_ctx.s=BN_bin2bn(p,i,NULL)))
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
}
p+=i;
+ if (2 > n - param_len)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ param_len += 2;
+
n2s(p,i);
- param_len+=i+2;
- if (param_len > n)
+
+ if (i > n - param_len)
{
- al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_B_LENGTH);
goto f_err;
}
+ param_len += i;
+
if (!(s->srp_ctx.B=BN_bin2bn(p,i,NULL)))
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
p+=i;
n-=param_len;
+ if (!srp_verify_server_param(s, &al))
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_SRP_PARAMETERS);
+ goto f_err;
+ }
+
/* We must check if there is a certificate */
#ifndef OPENSSL_NO_RSA
if (alg_a & SSL_aRSA)
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_MALLOC_FAILURE);
goto err;
}
- n2s(p,i);
- param_len=i+2;
+
+ param_len = 2;
if (param_len > n)
{
- al=SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ n2s(p,i);
+
+ if (i > n - param_len)
+ {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_MODULUS_LENGTH);
goto f_err;
}
+ param_len += i;
+
if (!(rsa->n=BN_bin2bn(p,i,rsa->n)))
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
}
p+=i;
+ if (2 > n - param_len)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ param_len += 2;
+
n2s(p,i);
- param_len+=i+2;
- if (param_len > n)
+
+ if (i > n - param_len)
{
- al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_RSA_E_LENGTH);
goto f_err;
}
+ param_len += i;
+
if (!(rsa->e=BN_bin2bn(p,i,rsa->e)))
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_DH_LIB);
goto err;
}
- n2s(p,i);
- param_len=i+2;
+
+ param_len = 2;
if (param_len > n)
{
- al=SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ n2s(p,i);
+
+ if (i > n - param_len)
+ {
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_P_LENGTH);
goto f_err;
}
+ param_len += i;
+
if (!(dh->p=BN_bin2bn(p,i,NULL)))
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
}
p+=i;
+ if (2 > n - param_len)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ param_len += 2;
+
n2s(p,i);
- param_len+=i+2;
- if (param_len > n)
+
+ if (i > n - param_len)
{
- al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_G_LENGTH);
goto f_err;
}
+ param_len += i;
+
if (!(dh->g=BN_bin2bn(p,i,NULL)))
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
}
p+=i;
+ if (2 > n - param_len)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ param_len += 2;
+
n2s(p,i);
- param_len+=i+2;
- if (param_len > n)
+
+ if (i > n - param_len)
{
- al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_DH_PUB_KEY_LENGTH);
goto f_err;
}
+ param_len += i;
+
if (!(dh->pub_key=BN_bin2bn(p,i,NULL)))
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_BN_LIB);
*/
/* XXX: For now we only support named (not generic) curves
- * and the ECParameters in this case is just three bytes.
+ * and the ECParameters in this case is just three bytes. We
+ * also need one byte for the length of the encoded point
*/
- param_len=3;
- /* Check curve is one of our prefrences, if not server has
- * sent an invalid curve.
+ param_len=4;
+ if (param_len > n)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ /* Check curve is one of our preferences, if not server has
+ * sent an invalid curve. ECParameters is 3 bytes.
*/
- if (!tls1_check_curve(s, p, param_len))
+ if (!tls1_check_curve(s, p, 3))
{
- al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_CURVE);
goto f_err;
}
encoded_pt_len = *p; /* length of encoded point */
p+=1;
- param_len += (1 + encoded_pt_len);
- if ((param_len > n) ||
+
+ if ((encoded_pt_len > n - param_len) ||
(EC_POINT_oct2point(group, srvr_ecpoint,
p, encoded_pt_len, bn_ctx) == 0))
{
- al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_BAD_ECPOINT);
goto f_err;
}
+ param_len += encoded_pt_len;
n-=param_len;
p+=encoded_pt_len;
{
if (SSL_USE_SIGALGS(s))
{
- int rv = tls12_check_peer_sigalg(&md, s, p, pkey);
+ int rv;
+ if (2 > n)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+ rv = tls12_check_peer_sigalg(&md, s, p, pkey);
if (rv == -1)
goto err;
else if (rv == 0)
{
- al = SSL_AD_DECODE_ERROR;
goto f_err;
}
#ifdef SSL_DEBUG
}
else
md = EVP_sha1();
-
+
+ if (2 > n)
+ {
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,
+ SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
n2s(p,i);
n-=2;
j=EVP_PKEY_size(pkey);
+ /* Check signature length. If n is 0 then signature is empty */
if ((i != n) || (n > j) || (n <= 0))
{
/* wrong packet length */
- al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_LENGTH);
goto f_err;
}
if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s))
{
int num;
+ unsigned int size;
j=0;
q=md_buf;
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,param,param_len);
- EVP_DigestFinal_ex(&md_ctx,q,(unsigned int *)&i);
- q+=i;
- j+=i;
+ EVP_DigestFinal_ex(&md_ctx,q,&size);
+ q+=size;
+ j+=size;
}
i=RSA_verify(NID_md5_sha1, md_buf, j, p, n,
pkey->pkey.rsa);
}
else
{
- /* aNULL or kPSK do not need public keys */
- if (!(alg_a & SSL_aNULL) && !(alg_k & SSL_kPSK))
+ /* aNULL, aSRP or kPSK do not need public keys */
+ if (!(alg_a & (SSL_aNULL|SSL_aSRP)) && !(alg_k & SSL_kPSK))
{
/* Might be wrong key type, check it */
if (ssl3_check_cert_and_algorithm(s))
/* still data left over */
if (n != 0)
{
- al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_EXTRA_DATA_IN_MESSAGE);
goto f_err;
}
s->cert->pkeys[i].digest = NULL;
s->cert->pkeys[i].valid_flags = 0;
}
- if ((llen & 1) || !tls1_process_sigalgs(s, p, llen))
+ if ((llen & 1) || !tls1_save_sigalgs(s, p, llen))
{
ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_SIGNATURE_ALGORITHMS_ERROR);
goto err;
}
+ if (!tls1_process_sigalgs(s))
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
p += llen;
}
RSA *rsa;
unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+ if (s->session->sess_cert == NULL)
+ {
+ /* We should always have a server certificate with SSL_kRSA. */
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
if (s->session->sess_cert->peer_rsa_tmp != NULL)
rsa=s->session->sess_cert->peer_rsa_tmp;
else
int ecdh_clnt_cert = 0;
int field_size = 0;
+ if (s->session->sess_cert == NULL)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
/* Did we send out the client's
* ECDH share for use in premaster
* computation as part of client certificate?
#ifndef OPENSSL_NO_PSK
else if (alg_k & SSL_kPSK)
{
- char identity[PSK_MAX_IDENTITY_LEN];
+ /* The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes
+ * to return a \0-terminated identity. The last byte
+ * is for us for simulating strnlen. */
+ char identity[PSK_MAX_IDENTITY_LEN + 2];
+ size_t 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;
goto err;
}
+ memset(identity, 0, sizeof(identity));
psk_len = s->psk_client_callback(s, s->ctx->psk_identity_hint,
- identity, PSK_MAX_IDENTITY_LEN,
+ identity, sizeof(identity) - 1,
psk_or_pre_ms, sizeof(psk_or_pre_ms));
if (psk_len > PSK_MAX_PSK_LEN)
{
SSL_R_PSK_IDENTITY_NOT_FOUND);
goto psk_err;
}
-
+ identity[PSK_MAX_IDENTITY_LEN + 1] = '\0';
+ identity_len = strlen(identity);
+ if (identity_len > PSK_MAX_IDENTITY_LEN)
+ {
+ SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+ ERR_R_INTERNAL_ERROR);
+ goto psk_err;
+ }
/* create PSK pre_master_secret */
pre_ms_len = 2+psk_len+2+psk_len;
t = psk_or_pre_ms;
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_or_pre_ms, pre_ms_len);
+ s2n(identity_len, p);
+ memcpy(p, identity, identity_len);
+ n = 2 + identity_len;
psk_err = 0;
psk_err:
- OPENSSL_cleanse(identity, PSK_MAX_IDENTITY_LEN);
+ OPENSSL_cleanse(identity, sizeof(identity));
OPENSSL_cleanse(psk_or_pre_ms, sizeof(psk_or_pre_ms));
if (psk_err != 0)
{
int ok;
long n;
- /* Read the message to see if it is supplemental data,
- * regardless if there is a session ticket this function is
- * called when we really expect a Certificate message, so
- * permit appropriate message length */
+ /* If we have no ticket it cannot be a resumed session. */
+ if (!s->session->tlsext_tick)
+ return 1;
+ /* this function is called when we really expect a Certificate
+ * message, so permit appropriate message length */
n=s->method->ssl_get_message(s,
SSL3_ST_CR_CERT_A,
SSL3_ST_CR_CERT_B,
if (!ok) return((int)n);
s->s3->tmp.reuse_message = 1;
- if (s->s3->tmp.message_type == SSL3_MT_SUPPLEMENTAL_DATA)
- return 3;
- /* If we have no ticket it cannot be a resumed session. */
- if (!s->session->tlsext_tick)
- return 1;
if ((s->s3->tmp.message_type == SSL3_MT_FINISHED)
|| (s->s3->tmp.message_type == SSL3_MT_NEWSESSION_TICKET))
return 2;
return i;
}
-#ifndef OPENSSL_NO_TLSEXT
-int tls1_send_client_supplemental_data(SSL *s, int *skip)
- {
- int al = 0;
- if (s->ctx->cli_supp_data_records_count)
- {
- unsigned char *p = NULL;
- unsigned char *size_loc = NULL;
- cli_supp_data_record *record = NULL;
- size_t length = 0;
- size_t i = 0;
-
- for (i = 0; i < s->ctx->cli_supp_data_records_count; i++)
- {
- const unsigned char *out = NULL;
- unsigned short outlen = 0;
- int cb_retval = 0;
- record = &s->ctx->cli_supp_data_records[i];
-
- /* NULL callback or -1 omits supp data entry*/
- if (!record->fn2)
- continue;
- cb_retval = record->fn2(s, record->supp_data_type,
- &out, &outlen, &al,
- record->arg);
- if (cb_retval == -1)
- continue; /* skip this supp data entry */
- if (cb_retval == 0)
- {
- SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
- goto f_err;
- }
- if (outlen == 0 || TLSEXT_MAXLEN_supplemental_data < outlen + 4 + length)
- {
- SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
- return 0;
- }
- /* if first entry, write handshake message type */
- if (length == 0)
- {
- if (!BUF_MEM_grow_clean(s->init_buf, 4))
- {
- SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
- return 0;
- }
- p = (unsigned char *)s->init_buf->data;
- *(p++) = SSL3_MT_SUPPLEMENTAL_DATA;
- /* update message length when all
- * callbacks complete */
- size_loc = p;
- /* skip over handshake length field (3
- * bytes) and supp_data length field
- * (3 bytes) */
- p += 3 + 3;
- length += 1 +3 +3;
- }
- if (!BUF_MEM_grow(s->init_buf, outlen + 4))
- {
- SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB);
- return 0;
- }
- s2n(record->supp_data_type, p);
- s2n(outlen, p);
- memcpy(p, out, outlen);
- 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_CW_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;
-
- f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
- return 0;
- }
-
-int tls1_get_server_supplemental_data(SSL *s)
- {
- int al = 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;
- int cb_retval = 0;
-
- n=s->method->ssl_get_message(s,
- SSL3_ST_CR_SUPPLEMENTAL_DATA_A,
- SSL3_ST_CR_SUPPLEMENTAL_DATA_B,
- SSL3_MT_SUPPLEMENTAL_DATA,
- /* use default limit */
- TLSEXT_MAXLEN_supplemental_data,
- &ok);
-
- if (!ok) return((int)n);
-
- p = (unsigned char *)s->init_msg;
- d = p;
- /* The message cannot be empty */
- if (n < 3)
- {
- al = SSL_AD_DECODE_ERROR;
- SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA,SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
- n2l3(p, supp_data_len);
- while (p < d+supp_data_len)
- {
- 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->cli_supp_data_records_count; i++)
- {
- if (s->ctx->cli_supp_data_records[i].supp_data_type == supp_data_entry_type &&
- s->ctx->cli_supp_data_records[i].fn1)
- {
- cb_retval = s->ctx->cli_supp_data_records[i].fn1(s, supp_data_entry_type, p,
- supp_data_entry_len, &al,
- s->ctx->cli_supp_data_records[i].arg);
- if (cb_retval == 0)
- {
- SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA, ERR_R_SSL_LIB);
- goto f_err;
- }
- }
- }
- p += supp_data_entry_len;
- }
- return 1;
-f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
- return -1;
- }
-#endif