LCOV - code coverage report
Current view: top level - src/oscore - option.c (source / functions) Coverage Total Hit
Test: lcov.info Lines: 96.2 % 78 75
Test Date: 2026-03-12 12:01:18 Functions: 100.0 % 8 8
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 76.6 % 64 49

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :    Copyright (c) 2021 Fraunhofer AISEC. See the COPYRIGHT
       3                 :             :    file at the top-level directory of this distribution.
       4                 :             : 
       5                 :             :    Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
       6                 :             :    http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
       7                 :             :    <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
       8                 :             :    option. This file may not be copied, modified, or distributed
       9                 :             :    except according to those terms.
      10                 :             : */
      11                 :             : 
      12                 :             : #include <string.h>
      13                 :             : 
      14                 :             : #include "oscore/option.h"
      15                 :             : #include "oscore/oscore_coap.h"
      16                 :             : 
      17                 :             : #include "common/memcpy_s.h"
      18                 :             : 
      19                 :             : /**
      20                 :             :  * @brief Securely append a substring to given buffer.
      21                 :             :  * 
      22                 :             :  * @param buffer Buffer to have the substring appended.
      23                 :             :  * @param current_size Current size of the buffer content. Updated after successfull append.
      24                 :             :  * @param max_size Memory size allocated for the buffer.
      25                 :             :  * @param substring Substring buffer to be appended.
      26                 :             :  * @param substring_size Substring size.
      27                 :             :  * @return ok or error
      28                 :             :  */
      29                 :          28 : static enum err buffer_append(uint8_t *buffer, uint32_t *current_size,
      30                 :             :                               uint32_t max_size, const uint8_t *substring,
      31                 :             :                               uint32_t substring_size)
      32                 :             : {
      33                 :          28 :         uint8_t *destination =
      34                 :          28 :                 &buffer[*current_size]; //pointer to current end of the content
      35                 :          28 :         uint32_t remaining_size =
      36                 :             :                 max_size -
      37                 :          28 :                 (*current_size); //how many bytes in the buffer are still available
      38         [ -  + ]:          28 :         TRY(_memcpy_s(destination, remaining_size, substring, substring_size));
      39                 :          28 :         *current_size += substring_size;
      40                 :          28 :         return ok;
      41                 :             : }
      42                 :             : 
      43                 :          37 : bool is_class_e(uint16_t code)
      44                 :             : {
      45                 :             :         // blacklist, because OSCORE dictates that unknown options SHALL be processed as class E
      46                 :             :         // RFC 9668 Section 3.1: EDHOC option (21) is Class U for OSCORE
      47   [ +  +  +  +  :          33 :         return code != URI_HOST && code != URI_PORT && code != OSCORE &&
                   +  + ]
      48   [ +  +  +  +  :          70 :                code != PROXY_URI && code != PROXY_SCHEME && code != EDHOC;
                   +  - ]
      49                 :             : }
      50                 :             : 
      51                 :          24 : bool is_observe(struct o_coap_option *options, uint8_t options_cnt)
      52                 :             : {
      53         [ +  + ]:          32 :         for (uint8_t i = 0; i < options_cnt; i++) {
      54         [ +  + ]:          14 :                 if (options[i].option_number == OBSERVE) {
      55                 :           6 :                         return true;
      56                 :             :                 }
      57                 :             :         }
      58                 :          18 :         return false;
      59                 :             : }
      60                 :             : 
      61                 :          41 : bool get_observe_value(struct o_coap_option *options, uint8_t options_cnt,
      62                 :             :                        struct byte_array *output)
      63                 :             : {
      64   [ +  -  -  + ]:          41 :         if ((NULL == options) || (NULL == output)) {
      65                 :           0 :                 return false;
      66                 :             :         }
      67                 :             : 
      68         [ +  + ]:          79 :         for (uint8_t i = 0; i < options_cnt; i++) {
      69         [ +  + ]:          44 :                 if (OBSERVE != options[i].option_number) {
      70                 :          38 :                         continue;
      71                 :             :                 }
      72                 :             : 
      73                 :           6 :                 output->ptr = options[i].value;
      74                 :           6 :                 output->len = options[i].len;
      75                 :           6 :                 return true;
      76                 :             :         }
      77                 :          35 :         output = NULL;
      78                 :          35 :         return false;
      79                 :             : }
      80                 :             : 
      81                 :           6 : enum err cache_echo_val(struct byte_array *dest, struct o_coap_option *options,
      82                 :             :                         uint8_t options_cnt)
      83                 :             : {
      84         [ +  + ]:          12 :         for (uint8_t i = 0; i < options_cnt; i++) {
      85         [ +  + ]:          10 :                 if (options[i].option_number == ECHO) {
      86                 :           4 :                         PRINT_MSG("Caching the ECHO value!\n");
      87         [ -  + ]:           4 :                         TRY(_memcpy_s(dest->ptr, dest->len, options[i].value,
      88                 :             :                                       options[i].len));
      89                 :           4 :                         dest->len = options[i].len;
      90                 :           4 :                         return ok;
      91                 :             :                 }
      92                 :             :         }
      93                 :           2 :         return no_echo_option;
      94                 :             : }
      95                 :             : 
      96                 :          18 : enum err oscore_decrypted_payload_parser(struct byte_array *in_payload,
      97                 :             :                                          uint8_t *out_code,
      98                 :             :                                          struct o_coap_option *out_E_options,
      99                 :             :                                          uint8_t *E_options_cnt,
     100                 :             :                                          struct byte_array *out_o_coap_payload)
     101                 :             : {
     102                 :          18 :         uint8_t *temp_payload_ptr = in_payload->ptr;
     103                 :          18 :         uint32_t temp_payload_len = in_payload->len;
     104                 :             : 
     105                 :             :         /* Code */
     106                 :          18 :         *out_code = *(temp_payload_ptr++);
     107                 :          18 :         temp_payload_len--;
     108                 :             : 
     109                 :          18 :         struct byte_array remaining_bytes =
     110                 :             :                 BYTE_ARRAY_INIT(temp_payload_ptr, temp_payload_len);
     111         [ -  + ]:          18 :         TRY(options_deserialize(&remaining_bytes, out_E_options, E_options_cnt,
     112                 :             :                                 out_o_coap_payload));
     113                 :             : 
     114                 :          18 :         return ok;
     115                 :             : }
     116                 :             : 
     117                 :           5 : enum err echo_val_is_fresh(struct byte_array *cache_val,
     118                 :             :                            struct byte_array *decrypted_payload)
     119                 :             : {
     120                 :           5 :         uint8_t code = 0;
     121                 :             :         struct byte_array unprotected_o_coap_payload;
     122                 :             : 
     123                 :             :         struct o_coap_option E_options[10];
     124                 :           5 :         uint8_t E_options_cnt = 0;
     125                 :             : 
     126                 :             :         /* Parse decrypted payload: code + options + unprotected CoAP payload*/
     127         [ -  + ]:           5 :         TRY(oscore_decrypted_payload_parser(decrypted_payload, &code, E_options,
     128                 :             :                                             &E_options_cnt,
     129                 :             :                                             &unprotected_o_coap_payload));
     130                 :             : 
     131         [ +  + ]:           7 :         for (uint8_t i = 0; i < E_options_cnt; i++) {
     132         [ +  + ]:           5 :                 if (E_options[i].option_number == ECHO) {
     133         [ +  - ]:           3 :                         if (cache_val->len == E_options[i].len &&
     134         [ +  + ]:           3 :                             0 == memcmp(E_options[i].value, cache_val->ptr, cache_val->len) ) {
     135                 :           1 :                                 PRINT_MSG("ECHO option check -- OK\n");
     136                 :           1 :                                 return ok;
     137                 :             :                         } else {
     138                 :           2 :                                 return echo_val_mismatch;
     139                 :             :                         }
     140                 :             :                 }
     141                 :             :         }
     142                 :             : 
     143                 :           2 :         return no_echo_option;
     144                 :             : }
     145                 :             : 
     146                 :             : 
     147                 :          28 : enum err uri_path_create(struct o_coap_option *options, uint32_t options_size,
     148                 :             :                          uint8_t *uri_path, uint32_t *uri_path_size)
     149                 :             : {
     150   [ +  -  +  -  :          28 :         if ((NULL == options) || (NULL == uri_path) ||
                   -  + ]
     151                 :             :             (NULL == uri_path_size)) {
     152                 :           0 :                 return wrong_parameter;
     153                 :             :         }
     154                 :             : 
     155                 :          28 :         uint32_t current_size = 0;
     156                 :          28 :         uint32_t max_size = *uri_path_size;
     157                 :          28 :         memset(uri_path, 0, max_size);
     158                 :             : 
     159                 :          28 :         const uint8_t delimiter = '/';
     160                 :          28 :         const uint32_t delimiter_size = 1;
     161                 :             : 
     162         [ +  + ]:          60 :         for (uint32_t index = 0; index < options_size; index++) {
     163                 :          32 :                 struct o_coap_option *option = &options[index];
     164         [ +  + ]:          32 :                 if (URI_PATH != option->option_number) {
     165                 :          18 :                         continue;
     166                 :             :                 }
     167   [ +  -  -  + ]:          14 :                 if ((0 != option->len) && (NULL == option->value)) {
     168                 :           0 :                         return oscore_wrong_uri_path;
     169                 :             :                 }
     170                 :             : 
     171         [ -  + ]:          14 :                 TRY(buffer_append(uri_path, &current_size, max_size,
     172                 :             :                                   option->value, option->len));
     173         [ -  + ]:          14 :                 TRY(buffer_append(uri_path, &current_size, max_size, &delimiter,
     174                 :             :                                   delimiter_size));
     175                 :             :         }
     176                 :             : 
     177                 :             :         /* Remove last '/' character, or add a single one if the path is empty */
     178         [ +  + ]:          28 :         if (current_size > 0) {
     179                 :          14 :                 uri_path[current_size] = 0;
     180                 :          14 :                 current_size--;
     181                 :             :         } else {
     182                 :          14 :                 uri_path[0] = delimiter;
     183                 :          14 :                 current_size = delimiter_size;
     184                 :             :         }
     185                 :             : 
     186                 :          28 :         *uri_path_size = current_size;
     187                 :          28 :         return ok;
     188                 :             : }
        

Generated by: LCOV version 2.0-1