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 : }
|