cc->hlen_out = hlen_out;
cc->action = action;
cc->hsrun(&cc->cpu);
+ if (br_ssl_engine_closed(cc)) {
+ return;
+ }
if (cc->hbuf_out != cc->saved_hbuf_out) {
sendpld_ack(cc, cc->hbuf_out - cc->saved_hbuf_out);
}
unsigned char *
br_ssl_engine_sendapp_buf(const br_ssl_engine_context *cc, size_t *len)
{
- if (!cc->application_data) {
+ if (!(cc->application_data & 1)) {
*len = 0;
return NULL;
}
unsigned char *
br_ssl_engine_recvapp_buf(const br_ssl_engine_context *cc, size_t *len)
{
- if (!cc->application_data
+ if (!(cc->application_data & 1)
|| cc->record_type_in != BR_SSL_APPLICATION_DATA)
{
*len = 0;
sendrec_ack(cc, len);
if (len != 0 && !has_rec_tosend(cc)
&& (cc->record_type_out != BR_SSL_APPLICATION_DATA
- || cc->application_data == 0))
+ || (cc->application_data & 1) == 0))
{
jump_handshake(cc, 0);
}
jump_handshake(cc, 0);
break;
case BR_SSL_APPLICATION_DATA:
- if (cc->application_data) {
+ if (cc->application_data == 1) {
+ break;
+ }
+
+ /*
+ * If we are currently closing, and waiting for
+ * a close_notify from the peer, then incoming
+ * application data should be discarded.
+ */
+ if (cc->application_data == 2) {
+ recvpld_ack(cc, len);
break;
}
+
/* Fall through */
default:
br_ssl_engine_fail(cc, BR_ERR_UNEXPECTED);
int
br_ssl_engine_renegotiate(br_ssl_engine_context *cc)
{
+ size_t len;
+
if (br_ssl_engine_closed(cc) || cc->reneg == 1
- || (cc->flags & BR_OPT_NO_RENEGOTIATION) != 0)
+ || (cc->flags & BR_OPT_NO_RENEGOTIATION) != 0
+ || br_ssl_engine_recvapp_buf(cc, &len) != NULL)
{
return 0;
}
void
br_ssl_engine_flush(br_ssl_engine_context *cc, int force)
{
- if (!br_ssl_engine_closed(cc) && cc->application_data) {
+ if (!br_ssl_engine_closed(cc) && (cc->application_data & 1) != 0) {
sendpld_flush(cc, force);
}
}
cc->hsrun = hsrun;
cc->shutdown_recv = 0;
cc->application_data = 0;
+ cc->alert = 0;
jump_handshake(cc, 0);
}
int prf_id, const void *pms, size_t pms_len)
{
br_tls_prf_impl iprf;
- unsigned char seed[64];
+ br_tls_prf_seed_chunk seed[2] = {
+ { cc->client_random, sizeof cc->client_random },
+ { cc->server_random, sizeof cc->server_random }
+ };
iprf = br_ssl_engine_get_PRF(cc, prf_id);
- memcpy(seed, cc->client_random, 32);
- memcpy(seed + 32, cc->server_random, 32);
iprf(cc->session.master_secret, sizeof cc->session.master_secret,
- pms, pms_len, "master secret", seed, sizeof seed);
+ pms, pms_len, "master secret", 2, seed);
}
/*
size_t half_len, unsigned char *kb)
{
br_tls_prf_impl iprf;
- unsigned char seed[64];
+ br_tls_prf_seed_chunk seed[2] = {
+ { cc->server_random, sizeof cc->server_random },
+ { cc->client_random, sizeof cc->client_random }
+ };
iprf = br_ssl_engine_get_PRF(cc, prf_id);
- memcpy(seed, cc->server_random, 32);
- memcpy(seed + 32, cc->client_random, 32);
iprf(kb, half_len << 1,
cc->session.master_secret, sizeof cc->session.master_secret,
- "key expansion", seed, sizeof seed);
+ "key expansion", 2, seed);
}
/* see inner.h */
cc->igcm_out->init(&cc->out.gcm.vtable.out,
bc_impl, cipher_key, cipher_key_len, cc->ighash, iv);
}
+
+/* see inner.h */
+void
+br_ssl_engine_switch_chapol_in(br_ssl_engine_context *cc,
+ int is_client, int prf_id)
+{
+ unsigned char kb[88];
+ unsigned char *cipher_key, *iv;
+
+ compute_key_block(cc, prf_id, 44, kb);
+ if (is_client) {
+ cipher_key = &kb[32];
+ iv = &kb[76];
+ } else {
+ cipher_key = &kb[0];
+ iv = &kb[64];
+ }
+ cc->ichapol_in->init(&cc->in.chapol.vtable.in,
+ cc->ichacha, cc->ipoly, cipher_key, iv);
+ cc->incrypt = 1;
+}
+
+/* see inner.h */
+void
+br_ssl_engine_switch_chapol_out(br_ssl_engine_context *cc,
+ int is_client, int prf_id)
+{
+ unsigned char kb[88];
+ unsigned char *cipher_key, *iv;
+
+ compute_key_block(cc, prf_id, 44, kb);
+ if (is_client) {
+ cipher_key = &kb[0];
+ iv = &kb[64];
+ } else {
+ cipher_key = &kb[32];
+ iv = &kb[76];
+ }
+ cc->ichapol_out->init(&cc->out.chapol.vtable.out,
+ cc->ichacha, cc->ipoly, cipher_key, iv);
+}