#include <stdio.h>
#include "ssl_locl.h"
#include "kssl_lcl.h"
+#include "../crypto/constant_time_locl.h"
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include <openssl/objects.h>
#endif
#include <openssl/md5.h>
+#ifndef OPENSSL_NO_SSL3_METHOD
static const SSL_METHOD *ssl3_get_server_method(int ver);
static const SSL_METHOD *ssl3_get_server_method(int ver)
return(NULL);
}
+IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
+ ssl3_accept,
+ ssl_undefined_function,
+ ssl3_get_server_method)
+#endif
+
#ifndef OPENSSL_NO_SRP
static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
{
}
#endif
-IMPLEMENT_ssl3_meth_func(SSLv3_server_method,
- ssl3_accept,
- ssl_undefined_function,
- ssl3_get_server_method)
-
int ssl3_accept(SSL *s)
{
BUF_MEM *buf;
SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR);
return -1;
}
+
+ if (!ssl_security(s, SSL_SECOP_VERSION, 0,
+ s->version, NULL))
+ {
+ SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_VERSION_TOO_LOW);
+ return -1;
+ }
+
s->type=SSL_ST_ACCEPT;
if (s->init_buf == NULL)
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)
s->state=SSL3_ST_SW_CHANGE_A;
#endif
else
-#ifndef OPENSSL_NO_TLSEXT
- s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_A;
-#else
- s->state = SSL3_ST_SW_CERT_A;
-#endif
- s->init_num = 0;
- break;
-
-#ifndef OPENSSL_NO_TLSEXT
- case SSL3_ST_SW_SUPPLEMENTAL_DATA_A:
- case SSL3_ST_SW_SUPPLEMENTAL_DATA_B:
- ret = tls1_send_server_supplemental_data(s, &skip);
- if (ret <= 0) goto end;
-
- s->state = SSL3_ST_SW_CERT_A;
+ s->state = SSL3_ST_SW_CERT_A;
s->init_num = 0;
break;
-#endif
case SSL3_ST_SW_CERT_A:
case SSL3_ST_SW_CERT_B:
/* Check if it is anon DH or anon ECDH, */
/* normal PSK or KRB5 or SRP */
- if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
- && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)
- && !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5))
+ if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL|SSL_aKRB5|SSL_aSRP))
+ && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
{
ret=ssl3_send_server_certificate(s);
if (ret <= 0) goto end;
/* 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)
* (against the specs, but s3_clnt.c accepts this for SSL 3) */
!(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
/* never request cert in Kerberos ciphersuites */
- (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)
+ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5) ||
+ /* don't request certificate for SRP auth */
+ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP)
/* With normal PSK Certificates and
* Certificate Requests are omitted */
|| (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
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)
{
case SSL3_ST_SR_CERT_VRFY_A:
case SSL3_ST_SR_CERT_VRFY_B:
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
/* we should decide if we expected this one */
ret=ssl3_get_cert_verify(s);
if (ret <= 0) goto end;
case SSL3_ST_SR_FINISHED_A:
case SSL3_ST_SR_FINISHED_B:
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
SSL3_ST_SR_FINISHED_B);
if (ret <= 0) goto end;
s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
#else
if (s->s3->next_proto_neg_seen)
+ {
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PROTO_A;
+ }
else
s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
#endif
&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 && !s->first_packet)
+ 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.
int m, comp_id = s->session->compress_meth;
/* Perform sanity checks on resumed compression algorithm */
/* Can't disable compression */
- if (s->options & SSL_OP_NO_COMPRESSION)
+ if (!ssl_allow_compression(s))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION);
goto f_err;
}
else if (s->hit)
comp = NULL;
- else if (!(s->options & SSL_OP_NO_COMPRESSION) && s->ctx->comp_methods)
+ else if (ssl_allow_compression(s) && s->ctx->comp_methods)
{ /* See if we have a match */
int m,nn,o,v,done=0;
goto f_err;
}
ciphers=NULL;
+ if (!tls1_set_server_sigalgs(s))
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
+ goto err;
+ }
/* 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;
* ssl version is set - sslv3
* s->session - The ssl session has been setup.
* s->hit - session reuse flag
- * s->tmp.new_cipher - the new cipher to use.
+ * s->s3->tmp.new_cipher- the new cipher to use.
*/
/* Handles TLS extensions that we couldn't check earlier */
unsigned char *buf;
unsigned char *p,*d;
int i,sl;
+ int al = 0;
unsigned long l;
if (s->state == SSL3_ST_SW_SRVR_HELLO_A)
SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT);
return -1;
}
- if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+ if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH, &al)) == NULL)
{
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
return -1;
}
else
#endif
#ifndef OPENSSL_NO_DH
- if (type & SSL_kEDH)
+ if (type & SSL_kDHE)
{
- dhp=cert->dh_tmp;
+ if (s->cert->dh_tmp_auto)
+ {
+ dhp = ssl_get_auto_dh(s);
+ if (dhp == NULL)
+ {
+ al=SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ goto f_err;
+ }
+ }
+ else
+ 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),
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_MISSING_TMP_DH_KEY);
goto f_err;
}
-
+ if (!ssl_security(s, SSL_SECOP_TMP_DH,
+ DH_security_bits(dhp), 0, dhp))
+ {
+ al=SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_DH_KEY_TOO_SMALL);
+ goto f_err;
+ }
if (s->s3->tmp.dh != NULL)
{
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
- if ((dh=DHparams_dup(dhp)) == NULL)
+ if (s->cert->dh_tmp_auto)
+ dh = dhp;
+ else if ((dh=DHparams_dup(dhp)) == NULL)
{
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_R_DH_LIB);
goto err;
else
#endif
#ifndef OPENSSL_NO_ECDH
- if (type & SSL_kEECDH)
+ if (type & SSL_kECDHE)
{
const EC_GROUP *group;
SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
goto f_err;
}
- for (i=0; r[i] != NULL && i<4; i++)
+ for (i=0; i < 4 && r[i] != NULL; i++)
{
nr[i]=BN_num_bytes(r[i]);
#ifndef OPENSSL_NO_SRP
n+=2+nr[i];
}
- 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))
{
if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher,&md))
}
d = p = ssl_handshake_start(s);
- for (i=0; r[i] != NULL && i<4; i++)
+ for (i=0; i < 4 && r[i] != NULL; i++)
{
#ifndef OPENSSL_NO_SRP
if ((i == 2) && (type & SSL_kSRP))
}
#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:
if (SSL_USE_SIGALGS(s))
{
const unsigned char *psigs;
+ unsigned char *etmp = p;
nl = tls12_get_psigalgs(s, &psigs);
- s2n(nl, p);
- memcpy(p, psigs, nl);
+ /* Skip over length for now */
+ p += 2;
+ nl = tls12_copy_sigalgs(s, p, psigs, nl);
+ /* Now fill in length */
+ s2n(nl, etmp);
p += nl;
n += nl + 2;
}
#ifdef NETSCAPE_HANG_BUG
if (!SSL_IS_DTLS(s))
{
+ if (!BUF_MEM_grow_clean(buf, s->init_num + 4))
+ {
+ SSLerr(SSL_F_SSL3_SEND_CERTIFICATE_REQUEST,ERR_R_BUF_LIB);
+ goto err;
+ }
p=(unsigned char *)s->init_buf->data + s->init_num;
/* do the header */
*(p++)=SSL3_MT_SERVER_DONE;
if (alg_k & SSL_kRSA)
{
unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
- int decrypt_len, decrypt_good_mask;
- unsigned char version_good;
+ int decrypt_len;
+ unsigned char decrypt_good, version_good;
/* FIX THIS UP EAY EAY EAY EAY */
if (s->s3->tmp.use_rsa_tmp)
ERR_clear_error();
/* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH.
- * decrypt_good_mask will be zero if so and non-zero otherwise. */
- decrypt_good_mask = decrypt_len ^ SSL_MAX_MASTER_KEY_LENGTH;
+ * decrypt_good will be 0xff if so and zero otherwise. */
+ decrypt_good = constant_time_eq_int_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH);
/* If the version in the decrypted pre-master secret is correct
- * then version_good will be zero. The Klima-Pokorny-Rosa
- * extension of Bleichenbacher's attack
+ * then version_good will be 0xff, otherwise it'll be zero.
+ * The Klima-Pokorny-Rosa extension of Bleichenbacher's attack
* (http://eprint.iacr.org/2003/052/) exploits the version
* number check as a "bad version oracle". Thus version checks
* are done in constant time and are treated like any other
* decryption error. */
- version_good = p[0] ^ (s->client_version>>8);
- version_good |= p[1] ^ (s->client_version&0xff);
+ version_good = constant_time_eq_8(p[0], (unsigned)(s->client_version>>8));
+ version_good &= constant_time_eq_8(p[1], (unsigned)(s->client_version&0xff));
/* The premaster secret must contain the same version number as
* the ClientHello to detect version rollback attacks
* SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such clients. */
if (s->options & SSL_OP_TLS_ROLLBACK_BUG)
{
- unsigned char workaround_mask = version_good;
- unsigned char workaround;
-
- /* workaround_mask will be 0xff if version_good is
- * non-zero (i.e. the version match failed). Otherwise
- * it'll be 0x00. */
- workaround_mask |= workaround_mask >> 4;
- workaround_mask |= workaround_mask >> 2;
- workaround_mask |= workaround_mask >> 1;
- workaround_mask = ~((workaround_mask & 1) - 1);
-
- workaround = p[0] ^ (s->version>>8);
- workaround |= p[1] ^ (s->version&0xff);
-
- /* If workaround_mask is 0xff (i.e. there was a version
- * mismatch) then we copy the value of workaround over
- * version_good. */
- version_good = (workaround & workaround_mask) |
- (version_good & ~workaround_mask);
- }
-
- /* If any bits in version_good are set then they'll poision
- * decrypt_good_mask and cause rand_premaster_secret to be
- * used. */
- decrypt_good_mask |= version_good;
-
- /* decrypt_good_mask will be zero iff decrypt_len ==
- * SSL_MAX_MASTER_KEY_LENGTH and the version check passed. We
- * fold the bottom 32 bits of it with an OR so that the LSB
- * will be zero iff everything is good. This assumes that we'll
- * never decrypt a value > 2**31 bytes, which seems safe. */
- decrypt_good_mask |= decrypt_good_mask >> 16;
- decrypt_good_mask |= decrypt_good_mask >> 8;
- decrypt_good_mask |= decrypt_good_mask >> 4;
- decrypt_good_mask |= decrypt_good_mask >> 2;
- decrypt_good_mask |= decrypt_good_mask >> 1;
- /* Now select only the LSB and subtract one. If decrypt_len ==
- * SSL_MAX_MASTER_KEY_LENGTH and the version check passed then
- * decrypt_good_mask will be all ones. Otherwise it'll be all
- * zeros. */
- decrypt_good_mask &= 1;
- decrypt_good_mask--;
+ unsigned char workaround_good;
+ workaround_good = constant_time_eq_8(p[0], (unsigned)(s->version>>8));
+ workaround_good &= constant_time_eq_8(p[1], (unsigned)(s->version&0xff));
+ version_good |= workaround_good;
+ }
+
+ /* Both decryption and version must be good for decrypt_good
+ * to remain non-zero (0xff). */
+ decrypt_good &= version_good;
/* Now copy rand_premaster_secret over p using
* decrypt_good_mask. */
for (i = 0; i < (int) sizeof(rand_premaster_secret); i++)
{
- p[i] = (p[i] & decrypt_good_mask) |
- (rand_premaster_secret[i] & ~decrypt_good_mask);
+ p[i] = constant_time_select_8(decrypt_good, p[i],
+ rand_premaster_secret[i]);
}
s->session->master_key_length=
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);
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,ERR_R_BN_LIB);
goto err;
}
+ if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0
+ || BN_is_zero(s->srp_ctx.A))
+ {
+ al=SSL_AD_ILLEGAL_PARAMETER;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_SRP_PARAMETERS);
+ goto f_err;
+ }
if (s->session->srp_username != NULL)
OPENSSL_free(s->session->srp_username);
s->session->srp_username = BUF_strdup(s->srp_ctx.login);
unsigned char premaster_secret[32], *start;
size_t outlen=32, inlen;
unsigned long alg_a;
+ int Ttag, Tclass;
+ long Tlen;
/* Get our certificate private key*/
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
ERR_clear_error();
}
/* Decrypt session key */
- if ((*p!=( V_ASN1_SEQUENCE| V_ASN1_CONSTRUCTED)))
- {
- SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
- goto gerr;
- }
- if (p[1] == 0x81)
- {
- start = p+3;
- inlen = p[2];
- }
- else if (p[1] < 0x80)
- {
- start = p+2;
- inlen = p[1];
- }
- else
+ if (ASN1_get_object((const unsigned char **)&p, &Tlen, &Ttag, &Tclass, n) != V_ASN1_CONSTRUCTED ||
+ Ttag != V_ASN1_SEQUENCE ||
+ Tclass != V_ASN1_UNIVERSAL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_DECRYPTION_FAILED);
goto gerr;
}
+ start = p;
+ inlen = Tlen;
if (EVP_PKEY_decrypt(pkey_ctx,premaster_secret,&outlen,start,inlen) <=0)
{
SSL3_ST_SR_CERT_VRFY_A,
SSL3_ST_SR_CERT_VRFY_B,
-1,
- 516, /* Enough for 4096 bit RSA key with TLS v1.2 */
+ SSL3_RT_MAX_PLAIN_LENGTH,
&ok);
if (!ok) return((int)n);
}
else
{
+ EVP_PKEY *pkey;
i=ssl_verify_cert_chain(s,sk);
if (i <= 0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
goto f_err;
}
+ if (i > 1)
+ {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, i);
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ goto f_err;
+ }
+ pkey = X509_get_pubkey(sk_X509_value(sk, 0));
+ if (pkey == NULL)
+ {
+ al=SSL3_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,
+ SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ goto f_err;
+ }
+ EVP_PKEY_free(pkey);
}
if (s->session->peer != NULL) /* This should not be needed */
}
}
- ssl3_output_cert_chain(s,cpk);
+ if (!ssl3_output_cert_chain(s,cpk))
+ {
+ SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR);
+ return(0);
+ }
s->state=SSL3_ST_SW_CERT_B;
}
}
# endif
-int tls1_send_server_supplemental_data(SSL *s, int *skip)
- {
- 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;
- }
-
-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;
-
- 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);
-
- 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_CLIENT_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->srv_supp_data_records_count; i++)
- {
- 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;
- }
- }
- }
- p+=supp_data_entry_len;
- }
- return 1;
-f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
- return -1;
- }
#endif