Added encoded OID for hash functions (for use with PKCS#1 v1.5 signatures) into the...
[BearSSL] / src / ssl / ssl_engine.c
index 32bc406..cdd9bcb 100644 (file)
@@ -1091,6 +1091,9 @@ jump_handshake(br_ssl_engine_context *cc, int action)
                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);
                }
@@ -1129,7 +1132,7 @@ br_ssl_engine_flush_record(br_ssl_engine_context *cc)
 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;
        }
@@ -1147,7 +1150,7 @@ br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len)
 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;
@@ -1177,7 +1180,7 @@ br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len)
        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);
        }
@@ -1215,9 +1218,20 @@ br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len)
                        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);
@@ -1279,7 +1293,7 @@ br_ssl_engine_current_state(const br_ssl_engine_context *cc)
 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);
        }
 }
@@ -1296,6 +1310,7 @@ br_ssl_engine_hs_reset(br_ssl_engine_context *cc,
        cc->hsrun = hsrun;
        cc->shutdown_recv = 0;
        cc->application_data = 0;
+       cc->alert = 0;
        jump_handshake(cc, 0);
 }
 
@@ -1474,3 +1489,44 @@ br_ssl_engine_switch_gcm_out(br_ssl_engine_context *cc,
        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);
+}