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_annotations.h"
19 : : #include "utils/s2n_safety.h"
20 : :
21 : : /* Writes length bytes of input to stuffer, in network order, starting from the smallest byte of input. */
22 : : int s2n_stuffer_write_network_order(struct s2n_stuffer *stuffer, const uint64_t input, const uint8_t length)
23 : 8724861 : {
24 [ + + ]: 8724861 : if (length == 0) {
25 : 1 : return S2N_SUCCESS;
26 : 1 : }
27 [ + + ][ + - ]: 8724860 : POSIX_ENSURE_REF(stuffer);
28 [ - + ][ # # ]: 8724855 : POSIX_ENSURE(length <= sizeof(input), S2N_ERR_SAFETY);
29 [ + + ]: 8724855 : POSIX_GUARD(s2n_stuffer_skip_write(stuffer, length));
30 [ # # ][ - + ]: 8724851 : POSIX_ENSURE_REF(stuffer->blob.data);
31 : 8724851 : uint8_t *data = stuffer->blob.data + stuffer->write_cursor - length;
32 [ + + ]: 26506598 : for (int i = 0; i < length; i++) {
33 : 17781747 : S2N_INVARIANT(i <= length);
34 : 17781747 : uint8_t shift = (length - i - 1) * CHAR_BIT;
35 : 17781747 : data[i] = (input >> (shift)) & UINT8_MAX;
36 : 17781747 : }
37 [ - + ][ + - ]: 8724851 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
38 : 8724851 : return S2N_SUCCESS;
39 : 8724851 : }
40 : :
41 : : int s2n_stuffer_reserve(struct s2n_stuffer *stuffer, struct s2n_stuffer_reservation *reservation, const uint8_t length)
42 : 129777 : {
43 [ + + ][ + + ]: 129777 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
44 [ + + ][ + - ]: 129774 : POSIX_ENSURE_REF(reservation);
45 : :
46 : 129772 : *reservation = (struct s2n_stuffer_reservation){ .stuffer = stuffer,
47 : 129772 : .write_cursor = stuffer->write_cursor,
48 : 129772 : .length = length };
49 : :
50 [ + + ]: 129772 : POSIX_GUARD(s2n_stuffer_skip_write(stuffer, reservation->length));
51 [ # # ][ - + ]: 129771 : POSIX_CHECKED_MEMSET(stuffer->blob.data + reservation->write_cursor, S2N_WIPE_PATTERN, reservation->length);
[ + - ]
52 [ - + ][ + - ]: 129771 : POSIX_POSTCONDITION(s2n_stuffer_reservation_validate(reservation));
53 : 129771 : return S2N_SUCCESS;
54 : 129771 : }
55 : :
56 : : int s2n_stuffer_read_uint8(struct s2n_stuffer *stuffer, uint8_t *u)
57 : 7646129 : {
58 [ + + ]: 7646129 : POSIX_GUARD(s2n_stuffer_read_bytes(stuffer, u, sizeof(uint8_t)));
59 : :
60 : 7629619 : return S2N_SUCCESS;
61 : 7646129 : }
62 : :
63 : : int s2n_stuffer_write_uint8(struct s2n_stuffer *stuffer, const uint8_t u)
64 : 5045325 : {
65 [ + + ]: 5045325 : POSIX_GUARD(s2n_stuffer_write_bytes(stuffer, &u, sizeof(u)));
66 : :
67 : 5045323 : return S2N_SUCCESS;
68 : 5045325 : }
69 : :
70 : : int s2n_stuffer_reserve_uint8(struct s2n_stuffer *stuffer, struct s2n_stuffer_reservation *reservation)
71 : 8 : {
72 : 8 : return s2n_stuffer_reserve(stuffer, reservation, sizeof(uint8_t));
73 : 8 : }
74 : :
75 : : int s2n_stuffer_read_uint16(struct s2n_stuffer *stuffer, uint16_t *u)
76 : 15131837 : {
77 [ # # ][ - + ]: 15131837 : POSIX_ENSURE_REF(u);
78 : 15131837 : uint8_t data[sizeof(uint16_t)] = { 0 };
79 : :
80 [ + + ]: 15131837 : POSIX_GUARD(s2n_stuffer_read_bytes(stuffer, data, sizeof(data)));
81 : :
82 : 15131735 : *u = data[0] << 8;
83 : 15131735 : *u |= data[1];
84 : :
85 : 15131735 : return S2N_SUCCESS;
86 : 15131837 : }
87 : :
88 : : int s2n_stuffer_write_uint16(struct s2n_stuffer *stuffer, const uint16_t u)
89 : 8280176 : {
90 : 8280176 : return s2n_stuffer_write_network_order(stuffer, u, sizeof(u));
91 : 8280176 : }
92 : :
93 : : int s2n_stuffer_reserve_uint16(struct s2n_stuffer *stuffer, struct s2n_stuffer_reservation *reservation)
94 : 123392 : {
95 : 123392 : return s2n_stuffer_reserve(stuffer, reservation, sizeof(uint16_t));
96 : 123392 : }
97 : :
98 : : int s2n_stuffer_read_uint24(struct s2n_stuffer *stuffer, uint32_t *u)
99 : 164222 : {
100 [ - + ][ # # ]: 164222 : POSIX_ENSURE_REF(u);
101 : 164222 : uint8_t data[SIZEOF_UINT24] = { 0 };
102 : :
103 [ - + ]: 164222 : POSIX_GUARD(s2n_stuffer_read_bytes(stuffer, data, sizeof(data)));
104 : :
105 : 164222 : *u = data[0] << 16;
106 : 164222 : *u |= data[1] << 8;
107 : 164222 : *u |= data[2];
108 : :
109 : 164222 : return S2N_SUCCESS;
110 : 164222 : }
111 : :
112 : : int s2n_stuffer_write_uint24(struct s2n_stuffer *stuffer, const uint32_t u)
113 : 112882 : {
114 [ + + ][ + - ]: 112882 : POSIX_ENSURE(u < (1 << 24), S2N_ERR_INTEGER_OVERFLOW);
115 : 112881 : return s2n_stuffer_write_network_order(stuffer, u, SIZEOF_UINT24);
116 : 112882 : }
117 : :
118 : : int s2n_stuffer_reserve_uint24(struct s2n_stuffer *stuffer, struct s2n_stuffer_reservation *reservation)
119 : 6377 : {
120 : 6377 : return s2n_stuffer_reserve(stuffer, reservation, SIZEOF_UINT24);
121 : 6377 : }
122 : :
123 : : int s2n_stuffer_read_uint32(struct s2n_stuffer *stuffer, uint32_t *u)
124 : 67755 : {
125 [ - + ][ # # ]: 67755 : POSIX_ENSURE_REF(u);
126 : 67755 : uint8_t data[sizeof(uint32_t)] = { 0 };
127 : :
128 [ + + ]: 67755 : POSIX_GUARD(s2n_stuffer_read_bytes(stuffer, data, sizeof(data)));
129 : :
130 : 67752 : *u = ((uint32_t) data[0]) << 24;
131 : 67752 : *u |= data[1] << 16;
132 : 67752 : *u |= data[2] << 8;
133 : 67752 : *u |= data[3];
134 : :
135 : 67752 : return S2N_SUCCESS;
136 : 67755 : }
137 : :
138 : : int s2n_stuffer_write_uint32(struct s2n_stuffer *stuffer, const uint32_t u)
139 : 3975 : {
140 : 3975 : return s2n_stuffer_write_network_order(stuffer, u, sizeof(u));
141 : 3975 : }
142 : :
143 : : int s2n_stuffer_read_uint64(struct s2n_stuffer *stuffer, uint64_t *u)
144 : 534 : {
145 [ # # ][ - + ]: 534 : POSIX_ENSURE_REF(u);
146 : 534 : uint8_t data[sizeof(uint64_t)] = { 0 };
147 : :
148 [ + + ]: 534 : POSIX_GUARD(s2n_stuffer_read_bytes(stuffer, data, sizeof(data)));
149 : :
150 : 533 : *u = ((uint64_t) data[0]) << 56;
151 : 533 : *u |= ((uint64_t) data[1]) << 48;
152 : 533 : *u |= ((uint64_t) data[2]) << 40;
153 : 533 : *u |= ((uint64_t) data[3]) << 32;
154 : 533 : *u |= ((uint64_t) data[4]) << 24;
155 : 533 : *u |= ((uint64_t) data[5]) << 16;
156 : 533 : *u |= ((uint64_t) data[6]) << 8;
157 : 533 : *u |= data[7];
158 : :
159 : 533 : return S2N_SUCCESS;
160 : 534 : }
161 : :
162 : : int s2n_stuffer_write_uint64(struct s2n_stuffer *stuffer, const uint64_t u)
163 : 1460 : {
164 : 1460 : return s2n_stuffer_write_network_order(stuffer, u, sizeof(u));
165 : 1460 : }
166 : :
167 : : static int length_matches_value_check(uint32_t value, uint8_t length)
168 : 129756 : {
169 : : /* Value is represented as a uint32_t, so shouldn't be assumed larger */
170 [ - + ][ # # ]: 129756 : POSIX_ENSURE(length <= sizeof(uint32_t), S2N_ERR_SIZE_MISMATCH);
171 : :
172 [ + - ]: 129756 : if (length < sizeof(uint32_t)) {
173 : : /* Value should be less than the maximum for its length */
174 : 129756 : const uint32_t size_max = 1 << (length * 8);
175 [ + + ][ + - ]: 129756 : POSIX_ENSURE(value < size_max, S2N_ERR_SIZE_MISMATCH);
176 : 129756 : }
177 : :
178 : 129754 : return S2N_SUCCESS;
179 : 129756 : }
180 : :
181 : : static int s2n_stuffer_write_reservation_impl(struct s2n_stuffer_reservation *reservation, const uint32_t u)
182 : 129756 : {
183 : 129756 : reservation->stuffer->write_cursor = reservation->write_cursor;
184 [ - + ][ + - ]: 129756 : POSIX_PRECONDITION(s2n_stuffer_validate(reservation->stuffer));
185 : :
186 [ + + ]: 129756 : POSIX_GUARD(length_matches_value_check(u, reservation->length));
187 [ - + ]: 129754 : POSIX_GUARD(s2n_stuffer_write_network_order(reservation->stuffer, u, reservation->length));
188 [ - + ][ + - ]: 129754 : POSIX_POSTCONDITION(s2n_stuffer_validate(reservation->stuffer));
189 : 129754 : return S2N_SUCCESS;
190 : 129754 : }
191 : :
192 : : int s2n_stuffer_write_reservation(struct s2n_stuffer_reservation *reservation, const uint32_t u)
193 : 129760 : {
194 [ + + ][ + + ]: 129760 : POSIX_PRECONDITION(s2n_stuffer_reservation_validate(reservation));
195 : 129756 : uint32_t old_write_cursor = reservation->stuffer->write_cursor;
196 : 129756 : int result = s2n_stuffer_write_reservation_impl(reservation, u);
197 : 129756 : reservation->stuffer->write_cursor = old_write_cursor;
198 : 129756 : return result;
199 : 129760 : }
200 : :
201 : : int s2n_stuffer_get_vector_size(const struct s2n_stuffer_reservation *reservation, uint32_t *size)
202 : 129755 : {
203 [ - + ][ + - ]: 129755 : POSIX_PRECONDITION(s2n_stuffer_reservation_validate(reservation));
204 [ - + ][ # # ]: 129755 : POSIX_ENSURE_REF(size);
205 : 129755 : *size = reservation->stuffer->write_cursor - (reservation->write_cursor + reservation->length);
206 : 129755 : return S2N_SUCCESS;
207 : 129755 : }
208 : :
209 : : int s2n_stuffer_write_vector_size(struct s2n_stuffer_reservation *reservation)
210 : 121882 : {
211 : 121882 : uint32_t size = 0;
212 [ - + ]: 121882 : POSIX_GUARD(s2n_stuffer_get_vector_size(reservation, &size));
213 [ + + ]: 121882 : POSIX_GUARD(s2n_stuffer_write_reservation(reservation, size));
214 : 121880 : return S2N_SUCCESS;
215 : 121882 : }
|