Fixed mishandling of tree structure in the cache for session parameters.
[BearSSL] / src / ssl / ssl_hs_common.t0
index da6fc8a..05b1797 100644 (file)
@@ -157,6 +157,8 @@ addr-eng: pad
 addr-eng: action
 addr-eng: alert
 addr-eng: close_received
+addr-eng: protocol_names_num
+addr-eng: selected_protocol
 
 \ Similar to 'addr-eng:', for fields in the 'session' substructure.
 : addr-session-field:
@@ -273,7 +275,9 @@ cc: flush-record ( -- ) {
        addr-action get8 dup if
                case
                        1 of 0 do-close endof
-                       2 of addr-application_data get8 if 0x10 or then endof
+                       2 of addr-application_data get8 1 = if
+                               0x10 or
+                       then endof
                endcase
        else
                drop
@@ -328,13 +332,18 @@ cc: flush-record ( -- ) {
 \ -- If 'cnr' is zero, then incoming data is discarded until a close_notify
 \    is received.
 \ -- At the end, the context is terminated.
+\
+\ cnr shall be either 0 or -1.
 : do-close ( cnr -- ! )
        \ 'cnr' is set to non-zero when a close_notify is received from
        \ the peer.
        { cnr }
 
-       \ Get out of application data state.
-       0 addr-application_data set8
+       \ Get out of application data state. If we were accepting
+       \ application data (flag is 1), and we still expect a close_notify
+       \ from the peer (cnr is 0), then we should set the flag to 2.
+       \ In all other cases, flag should be set to 0.
+       addr-application_data get8 cnr not and 1 << addr-application_data set8
 
        \ Flush existing payload if any.
        flush-record
@@ -367,6 +376,10 @@ cc: flush-record ( -- ) {
                has-input? if
                        addr-record_type_in get8 21 = if
                                drop process-alerts
+                               \ If we received a close_notify then we
+                               \ no longer accept incoming application
+                               \ data records.
+                               0 addr-application_data set8
                        else
                                discard-input
                        then
@@ -467,7 +480,7 @@ cc: read-chunk-native ( addr len -- addr len ) {
                        \ no_renegotiation has value 100, and we treat it
                        \ as a fatal alert.
                        dup 100 = if 256 + fail then
-                       0= ret
+                       0=
                endof
                \ Fatal alert implies context termination.
                drop 256 + fail
@@ -903,8 +916,14 @@ hexb| 0000 | \ List terminator.
                        then
                endof
 
-               \ ChaCha20/Poly1305
-               \ 5 of endof
+               \ ChaCha20+Poly1305
+               5 of drop
+                       for-input if
+                               switch-chapol-in
+                       else
+                               switch-chapol-out
+                       then
+               endof
 
                ERR_BAD_PARAM fail
        endcase
@@ -958,6 +977,22 @@ cc: switch-aesgcm-in ( is_client prf_id cipher_key_len -- ) {
                ENG->iaes_ctr, cipher_key_len);
 }
 
+cc: switch-chapol-out ( is_client prf_id -- ) {
+       int is_client, prf_id;
+
+       prf_id = T0_POP();
+       is_client = T0_POP();
+       br_ssl_engine_switch_chapol_out(ENG, is_client, prf_id);
+}
+
+cc: switch-chapol-in ( is_client prf_id -- ) {
+       int is_client, prf_id;
+
+       prf_id = T0_POP();
+       is_client = T0_POP();
+       br_ssl_engine_switch_chapol_in(ENG, is_client, prf_id);
+}
+
 \ Write Finished message.
 : write-Finished ( from_client -- )
        compute-Finished
@@ -1038,13 +1073,22 @@ cc: compute-Finished-inner ( from_client prf_id -- ) {
        read16 open-elt
        begin dup while
                read8 { hash } read8 { sign }
-               \ We keep the value if the signature is either 1 (RSA)
-               \ or 3 (ECDSA), and the hash is one of the SHA-* functions
-               \ (2 to 6, from SHA-1 to SHA-512); we reject MD5.
-               hash 2 >= hash 6 <= and
-               sign 1 = sign 3 = or
-               and if
-                       hashes 1 sign 1- 2 << hash + << or >hashes
+
+               \ If hash is 0x08 then this is a "new algorithm" identifier,
+               \ and we set the corresponding bit if it is in the 0..15
+               \ range. Otherwise, we keep the value only if the signature
+               \ is either 1 (RSA) or 3 (ECDSA), and the hash is one of the
+               \ SHA-* functions (2 to 6). Note that we reject MD5.
+               hash 8 = if
+                       sign 15 <= if
+                               1 sign 16 + << hashes or >hashes
+                       then
+               else
+                       hash 2 >= hash 6 <= and
+                       sign 1 = sign 3 = or
+                       and if
+                               hashes 1 sign 1- 2 << hash + << or >hashes
+                       then
                then
        repeat
        close-elt
@@ -1213,3 +1257,33 @@ cc: get-key-type-usages ( -- key-type-usages ) {
 
        \ Return key type and usages.
        get-key-type-usages ;
+
+\ =======================================================================
+
+\ Copy a specific protocol name from the list to the pad. The byte
+\ length is returned.
+cc: copy-protocol-name ( idx -- len ) {
+       size_t idx = T0_POP();
+       size_t len = strlen(ENG->protocol_names[idx]);
+       memcpy(ENG->pad, ENG->protocol_names[idx], len);
+       T0_PUSH(len);
+}
+
+\ Compare name in pad with the configured list of protocol names.
+\ If a match is found, then the index is returned; otherwise, -1
+\ is returned.
+cc: test-protocol-name ( len -- n ) {
+       size_t len = T0_POP();
+       size_t u;
+
+       for (u = 0; u < ENG->protocol_names_num; u ++) {
+               const char *name;
+
+               name = ENG->protocol_names[u];
+               if (len == strlen(name) && memcmp(ENG->pad, name, len) == 0) {
+                       T0_PUSH(u);
+                       T0_RET();
+               }
+       }
+       T0_PUSHi(-1);
+}