@@ -502,6 +502,8 @@ dtls_set_record_header(uint8 type, dtls_security_parameters_t *security,
502502 return buf + sizeof (uint16 );
503503}
504504
505+ enum seq_inc_t { DTLS_SEQ_NR_DONT_INCREASE , DTLS_SEQ_NR_INCREASE };
506+
505507/**
506508 * Initializes \p buf as handshake header. The caller must ensure that \p
507509 * buf is capable of holding at least \c sizeof(dtls_handshake_header_t)
@@ -512,7 +514,7 @@ static inline uint8 *
512514dtls_set_handshake_header (uint8 type , dtls_peer_t * peer ,
513515 int length , int frag_offset ,
514516 int frag_length , uint8 * buf ,
515- int seq_nr_inc ) {
517+ enum seq_inc_t seq_nr_inc ) {
516518
517519 dtls_int_to_uint8 (buf , type );
518520 buf += sizeof (uint8 );
@@ -525,7 +527,7 @@ dtls_set_handshake_header(uint8 type, dtls_peer_t *peer,
525527 dtls_int_to_uint16 (buf , peer -> handshake_params -> hs_state .mseq_s );
526528
527529 /* increment handshake message sequence counter by 1 */
528- if (seq_nr_inc ) {
530+ if (seq_nr_inc == DTLS_SEQ_NR_INCREASE ) {
529531 peer -> handshake_params -> hs_state .mseq_s ++ ;
530532 }
531533 } else {
@@ -1481,66 +1483,90 @@ dtls_send_handshake_msg_hash(dtls_context_t *ctx,
14811483 uint8 * data , size_t data_length ,
14821484 int add_hash )
14831485{
1484- int ret = 0 ;
1486+ int ret = 0 , result ;
14851487 int last_fragment = 0 ; /* indicates if the fragment being processed is the last one */
14861488 size_t remaining_data_length = data_length ;
14871489
14881490 uint8 buf [DTLS_HS_LENGTH ];
1489- uint8 * end ; /* a pointer used to calculate the amount of data written into buf */
1491+ uint8 * end = NULL ; /* a pointer used to calculate the amount of data written into buf */
14901492 uint8 * data_array [2 ];
14911493 size_t data_len_array [2 ];
14921494 dtls_security_parameters_t * security = peer ? dtls_security_params (peer ) : NULL ;
14931495 const size_t fragment_size = DTLS_MAXIMUM_HANDSHAKE_FRAGMENT_SIZE ;
14941496
1495- do {
1496- size_t i = 0 ;
1497+ last_fragment = (data_length <= fragment_size );
1498+
1499+ if (add_hash ) {
1500+ /* Update hash values for Finished MAC. The hash value is
1501+ * calculated as if the data has been sent in a single
1502+ * fragment. Setting the end pointer != NULL indicates that buf
1503+ * already contains a handshake header for a single fragment. If
1504+ * there is only one fragment so send, the sequence number will be
1505+ * increased as indicated by inc. */
1506+ enum seq_inc_t inc = last_fragment ? DTLS_SEQ_NR_INCREASE : DTLS_SEQ_NR_DONT_INCREASE ;
1507+ end = dtls_set_handshake_header (header_type , peer , data_length ,
1508+ 0 , data_length , /* fragment offset and length */
1509+ buf , inc );
1510+ update_hs_hash (peer , buf , end - buf );
1511+ if (data )
1512+ update_hs_hash (peer , data , data_length );
14971513
1498- last_fragment = (remaining_data_length <= fragment_size );
1514+ /* clear end pointer if message is fragmented. */
1515+ if (!last_fragment )
1516+ end = NULL ;
1517+ }
1518+
1519+ do {
1520+ size_t data_array_len = 1 ;
1521+ size_t len = remaining_data_length ; /* data length of current fragment */
14991522
15001523 dtls_debug ("sending (fragmented) handshake, %zu bytes remaining\n" , remaining_data_length );
15011524
1502- // Create single fragment header for full data and hash it, see RFC6347 Section 4.2.6
1503- // TODO: Do not create same header twice for non-fragmented packets
1504- if (add_hash && remaining_data_length == data_length ) {
1525+ /* Create fragment header, see RFC6347 Section 4.2.6. If end is
1526+ * set, the message is not fragmented and buf already contains the
1527+ * handshake header. */
1528+ if (!end ) {
1529+ enum seq_inc_t inc ;
1530+
1531+ if (last_fragment ) {
1532+ inc = DTLS_SEQ_NR_INCREASE ;
1533+ } else {
1534+ len = fragment_size ;
1535+ inc = DTLS_SEQ_NR_DONT_INCREASE ;
1536+ }
15051537 end = dtls_set_handshake_header (header_type , peer , data_length , data_length - remaining_data_length ,
1506- min (remaining_data_length , fragment_size ),
1507- buf , 0 );
1508- update_hs_hash (peer , buf , end - buf );
1538+ len , buf , inc );
15091539 }
1540+ data_array [0 ] = buf ;
1541+ data_len_array [0 ] = end - buf ;
15101542
1511- end = dtls_set_handshake_header (header_type , peer , data_length , data_length - remaining_data_length ,
1512- min (remaining_data_length , fragment_size ), buf , last_fragment );
1513-
1514- data_array [i ] = buf ;
1515- data_len_array [i ] = end - buf ;
1516- i ++ ;
1543+ end = NULL ;
15171544
1545+ /* set data to send in this fragment */
15181546 if (data != NULL ) {
1519- // Hash full data while sending first fragment, see RFC6347 Section 4.2.6
1520- if (add_hash && remaining_data_length == data_length ) {
1521- update_hs_hash (peer , data , data_length );
1522- }
1523- data_array [i ] = data ;
1524- data_len_array [i ] = (last_fragment ? remaining_data_length : fragment_size );
1525- i ++ ;
1547+ data_array [1 ] = data ;
1548+ data_len_array [1 ] = len ;
1549+ data_array_len = 2 ;
15261550 }
15271551 dtls_debug ("send handshake packet of type: %s (%i)\n" ,
15281552 dtls_handshake_type_to_name (header_type ), header_type );
15291553
15301554 dtls_debug ("sending fragment: offset: %zu, length: %zu \n" ,
15311555 data_length - remaining_data_length , (last_fragment ? remaining_data_length : fragment_size ));
15321556
1533- // TODO: Treat send errors here
1534- ret += dtls_send_multi (ctx , peer , security , session , DTLS_CT_HANDSHAKE ,
1535- data_array , data_len_array , i );
1536-
1537- // If not in last fragment
1538- if (last_fragment ){
1539- remaining_data_length = 0 ;
1540- } else {
1541- remaining_data_length -= fragment_size ;
1542- data += fragment_size ;
1557+ result = dtls_send_multi (ctx , peer , security , session , DTLS_CT_HANDSHAKE ,
1558+ data_array , data_len_array , data_array_len );
1559+ if (result < 0 ) {
1560+ dtls_debug ("error %d from dtls_send_multi()\n" , result );
1561+ return result ;
15431562 }
1563+ ret += result ;
1564+
1565+ /* update data pointer and length */
1566+ remaining_data_length -= len ;
1567+ data += len ;
1568+
1569+ last_fragment = (remaining_data_length <= fragment_size );
15441570 } while (remaining_data_length > 0 );
15451571
15461572 return ret ;
0 commit comments