LCOV - code coverage report
Current view: top level - stuffer - s2n_stuffer_hex.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 99 99 100.0 %
Date: 2025-08-15 07:28:39 Functions: 10 10 100.0 %
Branches: 73 106 68.9 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License").
       5                 :            :  * You may not use this file except in compliance with the License.
       6                 :            :  * A copy of the License is located at
       7                 :            :  *
       8                 :            :  *  http://aws.amazon.com/apache2.0
       9                 :            :  *
      10                 :            :  * or in the "license" file accompanying this file. This file is distributed
      11                 :            :  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
      12                 :            :  * express or implied. See the License for the specific language governing
      13                 :            :  * permissions and limitations under the License.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "error/s2n_errno.h"
      17                 :            : #include "stuffer/s2n_stuffer.h"
      18                 :            : #include "utils/s2n_safety.h"
      19                 :            : 
      20                 :            : static const uint8_t value_to_hex[16] = {
      21                 :            :     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
      22                 :            : };
      23                 :            : 
      24                 :            : static const uint8_t hex_to_value[] = {
      25                 :            :     /* clang-format off */
      26                 :            :     ['0'] = 0,  ['1'] = 1,  ['2'] = 2,  ['3'] = 3,  ['4'] = 4,
      27                 :            :     ['5'] = 5,  ['6'] = 6,  ['7'] = 7,  ['8'] = 8,  ['9'] = 9,
      28                 :            :     ['a'] = 10, ['b'] = 11, ['c'] = 12, ['d'] = 13, ['e'] = 14, ['f'] = 15,
      29                 :            :     ['A'] = 10, ['B'] = 11, ['C'] = 12, ['D'] = 13, ['E'] = 14, ['F'] = 15,
      30                 :            :     /* clang-format on */
      31                 :            : };
      32                 :            : 
      33                 :            : S2N_RESULT s2n_hex_digit(uint8_t half_byte, uint8_t *hex_digit)
      34                 :          8 : {
      35 [ -  + ][ #  # ]:          8 :     RESULT_ENSURE_REF(hex_digit);
      36 [ #  # ][ -  + ]:          8 :     RESULT_ENSURE(half_byte < s2n_array_len(value_to_hex), S2N_ERR_BAD_HEX);
      37                 :          8 :     *hex_digit = value_to_hex[half_byte];
      38                 :          8 :     return S2N_RESULT_OK;
      39                 :          8 : }
      40                 :            : 
      41                 :            : static S2N_RESULT s2n_stuffer_hex_digit_from_char(uint8_t c, uint8_t *i)
      42                 :     336154 : {
      43 [ +  - ][ +  + ]:     336154 :     RESULT_ENSURE(c < s2n_array_len(hex_to_value), S2N_ERR_BAD_HEX);
      44                 :            :     /* Invalid characters map to 0 in hex_to_value, but so does '0'. */
      45         [ +  + ]:     336134 :     if (hex_to_value[c] == 0) {
      46 [ +  - ][ +  + ]:      25183 :         RESULT_ENSURE(c == '0', S2N_ERR_BAD_HEX);
      47                 :      25183 :     }
      48                 :     336086 :     *i = hex_to_value[c];
      49                 :     336086 :     return S2N_RESULT_OK;
      50                 :     336134 : }
      51                 :            : 
      52                 :            : S2N_RESULT s2n_stuffer_read_hex(struct s2n_stuffer *hex_in, const struct s2n_blob *bytes_out)
      53                 :        424 : {
      54 [ +  + ][ +  + ]:        424 :     RESULT_PRECONDITION(s2n_stuffer_validate(hex_in));
      55 [ +  + ][ +  + ]:        423 :     RESULT_PRECONDITION(s2n_blob_validate(bytes_out));
      56         [ +  + ]:        422 :     if (bytes_out->size == 0) {
      57                 :          3 :         return S2N_RESULT_OK;
      58                 :          3 :     }
      59                 :            : 
      60                 :        419 :     size_t hex_size = bytes_out->size * 2;
      61 [ +  + ][ +  - ]:        419 :     RESULT_ENSURE(s2n_stuffer_data_available(hex_in) >= hex_size, S2N_ERR_BAD_HEX);
      62                 :            : 
      63                 :        409 :     uint8_t *out = bytes_out->data;
      64                 :        409 :     uint8_t *in = hex_in->blob.data + hex_in->read_cursor;
      65                 :            : 
      66         [ +  + ]:      36443 :     for (size_t i = 0; i < bytes_out->size; i++) {
      67                 :      36068 :         uint8_t hex_high = 0, hex_low = 0;
      68         [ +  + ]:      36068 :         RESULT_GUARD(s2n_stuffer_hex_digit_from_char(in[(i * 2)], &hex_high));
      69         [ +  + ]:      36051 :         RESULT_GUARD(s2n_stuffer_hex_digit_from_char(in[(i * 2) + 1], &hex_low));
      70                 :      36034 :         out[i] = (hex_high * 16) + hex_low;
      71                 :      36034 :     }
      72                 :            : 
      73         [ -  + ]:        375 :     RESULT_GUARD_POSIX(s2n_stuffer_skip_read(hex_in, hex_size));
      74                 :        375 :     return S2N_RESULT_OK;
      75                 :        375 : }
      76                 :            : 
      77                 :            : S2N_RESULT s2n_stuffer_write_hex(struct s2n_stuffer *hex_out, const struct s2n_blob *bytes_in)
      78                 :        186 : {
      79 [ +  + ][ +  + ]:        186 :     RESULT_PRECONDITION(s2n_stuffer_validate(hex_out));
      80 [ +  + ][ +  + ]:        185 :     RESULT_PRECONDITION(s2n_blob_validate(bytes_in));
      81                 :            : 
      82                 :        184 :     size_t bytes_size = bytes_in->size;
      83                 :        184 :     size_t hex_size = bytes_size * 2;
      84                 :            : 
      85         [ -  + ]:        184 :     RESULT_GUARD_POSIX(s2n_stuffer_reserve_space(hex_out, hex_size));
      86                 :        184 :     uint8_t *out = hex_out->blob.data + hex_out->write_cursor;
      87                 :        184 :     uint8_t *in = bytes_in->data;
      88                 :            : 
      89         [ +  + ]:       2347 :     for (size_t i = 0; i < bytes_size; i++) {
      90                 :       2163 :         out[(i * 2)] = value_to_hex[(in[i] >> 4)];
      91                 :       2163 :         out[(i * 2) + 1] = value_to_hex[(in[i] & 0x0f)];
      92                 :       2163 :     }
      93                 :            : 
      94         [ -  + ]:        184 :     RESULT_GUARD_POSIX(s2n_stuffer_skip_write(hex_out, hex_size));
      95                 :        184 :     return S2N_RESULT_OK;
      96                 :        184 : }
      97                 :            : 
      98                 :            : static S2N_RESULT s2n_stuffer_hex_read_n_bytes(struct s2n_stuffer *stuffer, uint8_t n, uint64_t *u)
      99                 :      66440 : {
     100 [ #  # ][ -  + ]:      66440 :     RESULT_ENSURE_LTE(n, sizeof(uint64_t));
     101 [ -  + ][ #  # ]:      66440 :     RESULT_ENSURE_REF(u);
     102                 :            : 
     103                 :      66440 :     uint8_t hex_data[16] = { 0 };
     104                 :      66440 :     struct s2n_blob b = { 0 };
     105         [ -  + ]:      66440 :     RESULT_GUARD_POSIX(s2n_blob_init(&b, hex_data, n * 2));
     106                 :            : 
     107 [ +  - ][ +  + ]:      66440 :     RESULT_ENSURE_REF(stuffer);
     108 [ +  + ][ +  - ]:      66438 :     RESULT_ENSURE(s2n_stuffer_read(stuffer, &b) == S2N_SUCCESS, S2N_ERR_BAD_HEX);
     109                 :            : 
     110                 :            :     /* Start with u = 0 */
     111                 :      66428 :     *u = 0;
     112         [ +  + ]:     330429 :     for (size_t i = 0; i < b.size; i++) {
     113                 :     264035 :         *u <<= 4;
     114                 :     264035 :         uint8_t hex = 0;
     115         [ +  + ]:     264035 :         RESULT_GUARD(s2n_stuffer_hex_digit_from_char(b.data[i], &hex));
     116                 :     264001 :         *u += hex;
     117                 :     264001 :     }
     118                 :            : 
     119                 :      66394 :     return S2N_RESULT_OK;
     120                 :      66428 : }
     121                 :            : 
     122                 :            : S2N_RESULT s2n_stuffer_read_uint16_hex(struct s2n_stuffer *stuffer, uint16_t *u)
     123                 :      65617 : {
     124 [ +  + ][ +  - ]:      65617 :     RESULT_ENSURE_REF(u);
     125                 :      65616 :     uint64_t u64 = 0;
     126         [ +  + ]:      65616 :     RESULT_GUARD(s2n_stuffer_hex_read_n_bytes(stuffer, sizeof(uint16_t), &u64));
     127 [ -  + ][ #  # ]:      65586 :     RESULT_ENSURE_LTE(u64, UINT16_MAX);
     128                 :      65586 :     *u = u64;
     129                 :      65586 :     return S2N_RESULT_OK;
     130                 :      65586 : }
     131                 :            : 
     132                 :            : S2N_RESULT s2n_stuffer_read_uint8_hex(struct s2n_stuffer *stuffer, uint8_t *u)
     133                 :        825 : {
     134 [ +  + ][ +  - ]:        825 :     RESULT_ENSURE_REF(u);
     135                 :        824 :     uint64_t u64 = 0;
     136         [ +  + ]:        824 :     RESULT_GUARD(s2n_stuffer_hex_read_n_bytes(stuffer, sizeof(uint8_t), &u64));
     137 [ #  # ][ -  + ]:        808 :     RESULT_ENSURE_LTE(u64, UINT8_MAX);
     138                 :        808 :     *u = u64;
     139                 :        808 :     return S2N_RESULT_OK;
     140                 :        808 : }
     141                 :            : 
     142                 :            : static S2N_RESULT s2n_stuffer_hex_write_n_bytes(struct s2n_stuffer *stuffer, uint8_t n, uint64_t u)
     143                 :      67882 : {
     144 [ #  # ][ -  + ]:      67882 :     RESULT_ENSURE_LTE(n, sizeof(uint64_t));
     145                 :            : 
     146                 :      67882 :     uint8_t hex_data[16] = { 0 };
     147                 :      67882 :     struct s2n_blob b = { 0 };
     148         [ -  + ]:      67882 :     RESULT_GUARD_POSIX(s2n_blob_init(&b, hex_data, n * 2));
     149                 :            : 
     150         [ +  + ]:     337398 :     for (size_t i = b.size; i > 0; i--) {
     151                 :     269516 :         b.data[i - 1] = value_to_hex[u & 0x0f];
     152                 :     269516 :         u >>= 4;
     153                 :     269516 :     }
     154                 :            : 
     155         [ +  + ]:      67882 :     RESULT_GUARD_POSIX(s2n_stuffer_write(stuffer, &b));
     156                 :      67880 :     return S2N_RESULT_OK;
     157                 :      67882 : }
     158                 :            : 
     159                 :            : S2N_RESULT s2n_stuffer_write_uint16_hex(struct s2n_stuffer *stuffer, uint16_t u)
     160                 :      66876 : {
     161                 :      66876 :     return s2n_stuffer_hex_write_n_bytes(stuffer, sizeof(uint16_t), u);
     162                 :      66876 : }
     163                 :            : 
     164                 :            : S2N_RESULT s2n_stuffer_write_uint8_hex(struct s2n_stuffer *stuffer, uint8_t u)
     165                 :       1006 : {
     166                 :       1006 :     return s2n_stuffer_hex_write_n_bytes(stuffer, sizeof(uint8_t), u);
     167                 :       1006 : }

Generated by: LCOV version 1.14