1 /*
2  * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <cstring>
8 #include <common/tlv/tlv.h>
9 #include <CppUTest/TestHarness.h>
10 
TEST_GROUP(TlvTests)11 TEST_GROUP(TlvTests)
12 {
13 
14 };
15 
TEST(TlvTests,decodeGoodRecords)16 TEST(TlvTests, decodeGoodRecords)
17 {
18     struct tlv_const_iterator iter;
19     struct tlv_record decoded_record;
20 
21     /* Case 1: Valid single zero length record */
22     const uint8_t case_1[] = {
23         0x77, 0x31, 0x00, 0x00
24     };
25 
26     tlv_const_iterator_begin(&iter, case_1, sizeof(case_1));
27     CHECK_TRUE(tlv_decode(&iter, &decoded_record));
28     UNSIGNED_LONGS_EQUAL(0x7731, decoded_record.tag);
29     UNSIGNED_LONGS_EQUAL(0, decoded_record.length);
30     CHECK_FALSE(tlv_decode(&iter, &decoded_record));
31 
32     /* Case 2: Two valid records */
33     const uint8_t case_2[] = {
34         0x01, 0x10, 0x00, 0x01, 0x50,
35         0x02, 0x11, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04
36     };
37 
38     tlv_const_iterator_begin(&iter, case_2, sizeof(case_2));
39     CHECK_TRUE(tlv_decode(&iter, &decoded_record));
40     UNSIGNED_LONGS_EQUAL(0x0110, decoded_record.tag);
41     UNSIGNED_LONGS_EQUAL(1, decoded_record.length);
42     UNSIGNED_LONGS_EQUAL(0x50, decoded_record.value[0]);
43     CHECK_TRUE(tlv_decode(&iter, &decoded_record));
44     UNSIGNED_LONGS_EQUAL(0x0211, decoded_record.tag);
45     UNSIGNED_LONGS_EQUAL(4, decoded_record.length);
46     UNSIGNED_LONGS_EQUAL(0x01, decoded_record.value[0]);
47     UNSIGNED_LONGS_EQUAL(0x02, decoded_record.value[1]);
48     UNSIGNED_LONGS_EQUAL(0x03, decoded_record.value[2]);
49     UNSIGNED_LONGS_EQUAL(0x04, decoded_record.value[3]);
50     CHECK_FALSE(tlv_decode(&iter, &decoded_record));
51 }
52 
TEST(TlvTests,findAndDecode)53 TEST(TlvTests, findAndDecode)
54 {
55     struct tlv_const_iterator iter;
56     struct tlv_record decoded_record;
57 
58     /*
59      * Checks use of the tlv_find_decode method to extract known records
60      * from a sequence of records, encoded in ascending tag order, that includes
61      * ones that the receiver isn't interested in.
62      */
63     const uint8_t encoded_records[] = {
64         0x00, 0x01, 0x00, 0x00,
65         0x00, 0x02, 0x00, 0x03, 0x88, 0x88, 0x88,
66         0x00, 0x07, 0x00, 0x02, 0x77, 0x77,
67         0x00, 0x09, 0x00, 0x01, 0x77
68     };
69 
70     tlv_const_iterator_begin(&iter, encoded_records, sizeof(encoded_records));
71     CHECK_TRUE(tlv_find_decode(&iter, 0x0001, &decoded_record));
72     UNSIGNED_LONGS_EQUAL(0, decoded_record.length);
73     CHECK_TRUE(tlv_find_decode(&iter, 0x0007, &decoded_record));
74     UNSIGNED_LONGS_EQUAL(2, decoded_record.length);
75     CHECK_TRUE(tlv_find_decode(&iter, 0x0009, &decoded_record));
76     UNSIGNED_LONGS_EQUAL(1, decoded_record.length);
77 }
78 
TEST(TlvTests,findAndDecodeMissingOptional)79 TEST(TlvTests, findAndDecodeMissingOptional)
80 {
81     struct tlv_const_iterator iter;
82     struct tlv_record decoded_record;
83 
84     /*
85      * Checks finding a missing record is correctly
86      * identified as not present but that the following
87      * record is found.
88      */
89     const uint8_t encoded_records[] = {
90         0x00, 0x07, 0x00, 0x02, 0x77, 0x77
91     };
92 
93     tlv_const_iterator_begin(&iter, encoded_records, sizeof(encoded_records));
94     CHECK(!tlv_find_decode(&iter, 0x0001, &decoded_record));
95     CHECK(tlv_find_decode(&iter, 0x0007, &decoded_record));
96     CHECK_EQUAL(2, decoded_record.length);
97 }
98 
TEST(TlvTests,decodeBadRecords)99 TEST(TlvTests, decodeBadRecords)
100 {
101     struct tlv_const_iterator iter;
102     struct tlv_record decoded_record;
103 
104     /* Case 1: Too short to accommodate a valid header */
105     const uint8_t case_1[] = {
106         0x77, 0x31, 0x00
107     };
108 
109     tlv_const_iterator_begin(&iter, case_1, sizeof(case_1));
110     CHECK_FALSE(tlv_decode(&iter, &decoded_record));
111 
112     /* Case 1: A complete record followed by a truncated one */
113     const uint8_t case_2[] = {
114         0x77, 0x31, 0x00, 0x00,
115         0x03, 0x21, 0x00, 0x03, 0xaa
116     };
117 
118     tlv_const_iterator_begin(&iter, case_2, sizeof(case_2));
119     CHECK_TRUE(tlv_decode(&iter, &decoded_record));
120     CHECK_FALSE(tlv_decode(&iter, &decoded_record));
121 }
122 
TEST(TlvTests,encodeRecords)123 TEST(TlvTests, encodeRecords)
124 {
125     struct tlv_iterator iter;
126     struct tlv_record record_to_encode;
127     size_t required_space;
128 
129     /* Case 1: Encode zero length record */
130     const uint8_t case_1_expected[] = {
131         0x66, 0x77, 0x00, 0x00
132     };
133     record_to_encode.tag = 0x6677;
134     record_to_encode.length = 0;
135     record_to_encode.value = NULL;
136     required_space = tlv_required_space(record_to_encode.length);
137     uint8_t case_1_actual[required_space];
138     tlv_iterator_begin(&iter, case_1_actual, required_space);
139     CHECK_TRUE(tlv_encode(&iter, &record_to_encode));
140     MEMCMP_EQUAL(case_1_expected, case_1_actual, required_space);
141 
142     /* Case 2: Encode two records */
143     const uint8_t case_2_expected[] = {
144         0xa8, 0xa9, 0x00, 0x01, 0x88,
145         0xa8, 0xaa, 0x00, 0x02, 0x01, 0x02
146     };
147 
148     required_space = tlv_required_space(1) + tlv_required_space(2);
149     uint8_t case_2_actual[required_space];
150     tlv_iterator_begin(&iter, case_2_actual, required_space);
151 
152     record_to_encode.tag = 0xa8a9;
153     record_to_encode.length = 1;
154     record_to_encode.value = &case_2_expected[4];
155     CHECK_TRUE(tlv_encode(&iter, &record_to_encode));
156 
157     record_to_encode.tag = 0xa8aa;
158     record_to_encode.length = 2;
159     record_to_encode.value = &case_2_expected[9];
160     CHECK_TRUE(tlv_encode(&iter, &record_to_encode));
161 
162     MEMCMP_EQUAL(case_2_expected, case_2_actual, required_space);
163 
164     /* Check that you can't encode beyond the limit of the buffer */
165     CHECK_FALSE(tlv_encode(&iter, &record_to_encode));
166 }
167 
TEST(TlvTests,encodeInsufficientSpace)168 TEST(TlvTests, encodeInsufficientSpace)
169 {
170     struct tlv_iterator iter;
171     struct tlv_record record_to_encode;
172     size_t required_space;
173 
174     /* Case 1: Encode record into buffer that isn't big enough */
175     const uint8_t case_1_expected[] = {
176         0x66, 0x77, 0x00, 0x03, 0x01, 0x02, 0x03
177     };
178     record_to_encode.tag = 0x6677;
179     record_to_encode.length = 3;
180     record_to_encode.value = &case_1_expected[4];
181     required_space = tlv_required_space(record_to_encode.length) - 1;
182     uint8_t case_1_actual[required_space];
183     tlv_iterator_begin(&iter, case_1_actual, required_space);
184     CHECK_FALSE(tlv_encode(&iter, &record_to_encode));
185 }
186 
TEST(TlvTests,encodeWrongOrder)187 TEST(TlvTests, encodeWrongOrder)
188 {
189     struct tlv_iterator iter;
190     struct tlv_record record_to_encode;
191     size_t required_space;
192 
193     /* Check defence against encoding successive records
194      * out of tag value order.  Encoding rules require
195      * records to be in ascending tag value order.
196      */
197     const uint8_t record_value[] = {
198         0x11, 0x22, 0x33, 0x44
199     };
200 
201     /* Attemps to encode 4 records, the first 3 obey order
202      * rule, the last one doesn't
203      */
204     required_space = tlv_required_space(sizeof(record_value)) * 4;
205     uint8_t encode_buffer[required_space];
206     tlv_iterator_begin(&iter, encode_buffer, required_space);
207 
208     record_to_encode.tag = 1;
209     record_to_encode.length = sizeof(record_value);
210     record_to_encode.value = record_value;
211     CHECK_TRUE(tlv_encode(&iter, &record_to_encode));
212 
213     record_to_encode.tag = 2;
214     record_to_encode.length = sizeof(record_value);
215     record_to_encode.value = record_value;
216     CHECK_TRUE(tlv_encode(&iter, &record_to_encode));
217 
218     record_to_encode.tag = 2;
219     record_to_encode.length = sizeof(record_value);
220     record_to_encode.value = record_value;
221     CHECK_TRUE(tlv_encode(&iter, &record_to_encode));
222 
223     record_to_encode.tag = 1;
224     record_to_encode.length = sizeof(record_value);
225     record_to_encode.value = record_value;
226     CHECK_FALSE(tlv_encode(&iter, &record_to_encode));
227 }
228