1 /*
2  * Copyright (C) 2022 The Android Open Source Project
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  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <apploader/cbor.h>
18 #include <cstdint>
19 #include <limits>
20 #include <optional>
21 #include <span>
22 #include <vector>
23 
24 #include "dice/cbor_reader.h"
25 #include "dice/cbor_writer.h"
26 #include "gmock/gmock.h"
27 #include "gtest/gtest.h"
28 
29 #include "cppbor.h"
30 #include "cppbor_parse.h"
31 
TEST(CborTest,ReadCborBoolean)32 TEST(CborTest, ReadCborBoolean) {
33     uint8_t buffer[8];
34     struct CborOut out;
35     CborOutInit(buffer, sizeof(buffer), &out);
36     CborWriteTrue(&out);
37     CborWriteFalse(&out);
38     CborWriteNull(&out);
39     ASSERT_FALSE(CborOutOverflowed(&out));
40 
41     struct CborIn in;
42     CborInInit(buffer, CborOutSize(&out), &in);
43     std::optional<bool> res;
44 
45     res = cbor::readCborBoolean(in);
46     ASSERT_TRUE(res.has_value());
47     EXPECT_TRUE(res.value());
48 
49     res = cbor::readCborBoolean(in);
50     ASSERT_TRUE(res.has_value());
51     EXPECT_FALSE(res.value());
52 
53     res = cbor::readCborBoolean(in);
54     EXPECT_FALSE(res.has_value());
55 }
56 
TEST(CborTest,EncodedSizeOf)57 TEST(CborTest, EncodedSizeOf) {
58     std::vector<uint64_t> cases = {0,
59                                    1,
60                                    23,
61                                    24,
62                                    255,
63                                    256,
64                                    65535,
65                                    65536,
66                                    4294967295,
67                                    4294967296,
68                                    std::numeric_limits<uint64_t>::max()};
69 
70     for (uint64_t val : cases) {
71         EXPECT_EQ(cppbor::headerSize(val), cbor::encodedSizeOf(val));
72     }
73 }
74 
75 static std::vector<int64_t> int64_cases = {std::numeric_limits<int64_t>::min(),
76                                            -4294967297,
77                                            -4294967296,
78                                            -65537,
79                                            -65536,
80                                            -257,
81                                            -256,
82                                            -25,
83                                            -24,
84                                            -1,
85                                            0,
86                                            1,
87                                            23,
88                                            24,
89                                            255,
90                                            256,
91                                            65535,
92                                            65536,
93                                            4294967295,
94                                            4294967296,
95                                            std::numeric_limits<int64_t>::max()};
96 
TEST(CborTest,EncodedSizeOfInt)97 TEST(CborTest, EncodedSizeOfInt) {
98     for (int64_t val : int64_cases) {
99         size_t expected = val < 0 ? cppbor::headerSize(-1ll - val)
100                                   : cppbor::headerSize(val);
101         EXPECT_EQ(expected, cbor::encodedSizeOfInt(val));
102     }
103 }
104 
TEST(CborTest,EncodeBstrHeader)105 TEST(CborTest, EncodeBstrHeader) {
106     uint8_t cborBuf[16], cppborBuf[16];
107     std::vector<uint64_t> cases = {
108             0, 1, 23, 24, 255, 256, 65535, 65536, 4294967295, 4294967296,
109     };
110     for (uint64_t payloadSize : cases) {
111         uint8_t* cborHeaderEnd =
112                 cbor::encodeBstrHeader(payloadSize, sizeof(cborBuf), cborBuf);
113         uint8_t* cppborHeaderEnd =
114                 cppbor::encodeHeader(cppbor::BSTR, payloadSize, cppborBuf,
115                                      cppborBuf + sizeof(cppborBuf));
116 
117         ASSERT_NE(cborHeaderEnd, nullptr);
118         const ptrdiff_t cborOutputLen = cborHeaderEnd - cborBuf;
119         ASSERT_LT(cborOutputLen, (ptrdiff_t)sizeof(cborBuf));
120 
121         ASSERT_NE(cppborHeaderEnd, (uint8_t*)NULL);
122         const ptrdiff_t cppborOutputLen = cppborHeaderEnd - cppborBuf;
123         ASSERT_LT(cppborOutputLen, (ptrdiff_t)sizeof(cppborBuf));
124 
125         std::span<const uint8_t> cborOutput(cborBuf, cborOutputLen);
126         std::span<const uint8_t> cppborOutput(cppborBuf, cppborOutputLen);
127         ASSERT_THAT(cborOutput, testing::ElementsAreArray(cppborOutput));
128     }
129 
130     // Pass in a string that's longer than we could possibly handle
131     auto res = cbor::encodeBstrHeader(std::numeric_limits<uint64_t>::max(),
132                                       sizeof(cborBuf), cborBuf);
133     EXPECT_EQ(res, nullptr);
134 }
135 
TEST(CborTest,MergeMapsEmpty)136 TEST(CborTest, MergeMapsEmpty) {
137     cppbor::Map empty;
138     std::vector<uint8_t> emptyEncoded = empty.encode();
139     auto res = cbor::mergeMaps(emptyEncoded, emptyEncoded);
140     ASSERT_TRUE(res.has_value());
141 
142     // parse the bytes we got to ensure it is an empty map
143     auto [item, _, err] = cppbor::parse(res.value());
144     ASSERT_NE(item, nullptr);
145     auto resMap = item->asMap();
146     ASSERT_NE(resMap, nullptr);
147     EXPECT_EQ(resMap->size(), 0lu);
148 }
149 
TEST(CborTest,MergeMapsCanonical)150 TEST(CborTest, MergeMapsCanonical) {
151     cppbor::Map first, second, expected;
152 
153     for (auto k = int64_cases.rbegin(); k != int64_cases.rend(); k++) {
154         int64_t key = *k;
155         if (key & 1) {
156             first.add(key, key);
157         } else {
158             second.add(key, key);
159         }
160         expected.add(key, key);
161     }
162 
163     expected.canonicalize();
164 
165     auto firstEncoded = first.encode();
166     auto secondEncoded = second.encode();
167     auto merged = cbor::mergeMaps(firstEncoded, secondEncoded);
168     ASSERT_TRUE(merged.has_value());
169 
170     EXPECT_TRUE(expected.isCanonical());
171     auto expectedEncoded = expected.encode();
172     ASSERT_TRUE(merged.value() == expectedEncoded);
173 }
174 
TEST(CborTest,MergeMapsCanonicalNoncanonicalInput)175 TEST(CborTest, MergeMapsCanonicalNoncanonicalInput) {
176     cppbor::Map first, second, expected;
177     /*
178      * -1 comes before 1000 in CBOR order so this map will be non-canonical
179      * because cppbor stores map items in the order they were added and we do
180      * not make it canonical before encoding.
181      */
182     first.add(1000, 1000);
183     first.add(-1, -1);
184     /* check that cppbor::Map preserves insertion order */
185     ASSERT_EQ(first[0].first->asInt()->value(), 1000);
186     ASSERT_EQ(first[1].first->asInt()->value(), -1);
187 
188     const std::vector<uint8_t> firstEncoded = first.encode();
189 
190     second.add(1, 1);
191     second.add(42, 42);
192     const std::vector<uint8_t> secondEncoded = second.encode();
193     auto merged = cbor::mergeMaps(firstEncoded, secondEncoded);
194     ASSERT_TRUE(merged.has_value());
195 
196     for (int64_t key : {-1, 1, 42, 1000}) {
197         expected.add(key, key);
198     }
199     expected.canonicalize();
200 
201     EXPECT_TRUE(expected.isCanonical());
202     auto expectedEncoded = expected.encode();
203     ASSERT_TRUE(merged.value() == expectedEncoded);
204 }
205 
TEST(CborTest,MapEncodingIsCanonical)206 TEST(CborTest, MapEncodingIsCanonical) {
207     cbor::VectorCborEncoder canonical;
208     canonical.encodeMap([&](auto& enc) {
209         for (int64_t key : {-1, 1000}) {
210             enc.encodeKeyValue(key, key);
211         }
212     });
213     EXPECT_EQ(canonical.state(), cbor::VectorCborEncoder::State::kEncoding);
214 
215     cbor::VectorCborEncoder innerCanonical;
216     innerCanonical.encodeMap([&](auto& enc) {
217         for (int64_t key : {-1, 42}) {
218             enc.encodeKeyValue(key, [&](auto& kvenc) {
219                 kvenc.encodeMap([&](auto& innerenc) {
220                     for (int64_t key : {1, 1000}) {
221                         innerenc.encodeKeyValue(key, key);
222                     }
223                 });
224             });
225         }
226     });
227     EXPECT_EQ(innerCanonical.state(),
228               cbor::VectorCborEncoder::State::kEncoding);
229 
230     cbor::VectorCborEncoder nonCanonical;
231     nonCanonical.encodeMap([&](auto& enc) {
232         /* -1 comes before 1000 in CBOR order so map will be non-canonical */
233         for (int64_t key : {1000, -1}) {
234             enc.encodeKeyValue(key, key);
235         }
236     });
237 
238     EXPECT_EQ(nonCanonical.state(), cbor::VectorCborEncoder::State::kInvalid);
239 
240     cbor::VectorCborEncoder innerNonCanonical;
241     innerNonCanonical.encodeMap([&](auto& enc) {
242         for (int64_t key : {-1, 1000}) {
243             enc.encodeKeyValue(key, [&](auto& kvenc) {
244                 kvenc.encodeMap([&](auto& innerenc) {
245                     /* write inner map keys in non-canonical order */
246                     for (int64_t key : {1000, -1}) {
247                         innerenc.encodeKeyValue(key, key);
248                     }
249                 });
250             });
251         }
252     });
253 
254     EXPECT_EQ(innerNonCanonical.state(),
255               cbor::VectorCborEncoder::State::kInvalid);
256 }
257 
TEST(CborTest,EncodeKeyValue)258 TEST(CborTest, EncodeKeyValue) {
259     cbor::VectorCborEncoder enc;
260     enc.encodeArray([&](auto& enc) {
261         /*
262          * calling encodeKeyValue outside of an encodeMap operation is an error
263          */
264         enc.encodeKeyValue(1, 1);
265     });
266     EXPECT_EQ(enc.state(), cbor::VectorCborEncoder::State::kInvalid);
267 }
268 
TEST(CborTest,MustCallEncodeArrayTagOrMap)269 TEST(CborTest, MustCallEncodeArrayTagOrMap) {
270     const char* err =
271             "Call encodeArray, encodeTag, or encodeMap before this method";
272 
273     EXPECT_DEBUG_DEATH(
274             {
275                 cbor::VectorCborEncoder bstrEnc;
276                 const std::span<const uint8_t> empty;
277                 bstrEnc.encodeBstr(empty);
278             },
279             err);
280 
281     EXPECT_DEBUG_DEATH(
282             {
283                 cbor::VectorCborEncoder emptyBstrEnc;
284                 emptyBstrEnc.encodeEmptyBstr();
285             },
286             err);
287 
288     EXPECT_DEBUG_DEATH(
289             {
290                 const char* testStr = "Carsten Bormann";
291                 cbor::VectorCborEncoder tstrEnc;
292                 tstrEnc.encodeBstr(testStr);
293             },
294             err);
295 
296     EXPECT_DEBUG_DEATH(
297             {
298                 cbor::VectorCborEncoder intEnc;
299                 intEnc.encodeInt(42);
300             },
301             err);
302 
303     EXPECT_DEBUG_DEATH(
304             {
305                 cbor::VectorCborEncoder uintEnc;
306                 uintEnc.encodeUint(42u);
307             },
308             err);
309 }
310 
TEST(CborTest,EncodeArrayOfTstr)311 TEST(CborTest, EncodeArrayOfTstr) {
312     const char* testStr = "Carsten Bormann";
313     const size_t testStrlen = strlen(testStr);
314 
315     cbor::VectorCborEncoder enc;
316     enc.encodeArray([&](auto& enc) { enc.encodeTstr(testStr); });
317 
318     auto res = enc.view();
319     const char* decodedStr;
320     size_t arrLen, decodedStrLen;
321     struct CborIn in;
322     enum CborReadResult rr;
323     CborInInit(res.data(), res.size(), &in);
324 
325     rr = CborReadArray(&in, &arrLen);
326     ASSERT_EQ(rr, CBOR_READ_RESULT_OK);
327     ASSERT_EQ(arrLen, 1u);
328 
329     CborReadTstr(&in, &decodedStrLen, &decodedStr);
330     ASSERT_EQ(rr, CBOR_READ_RESULT_OK);
331     ASSERT_EQ(CborInAtEnd(&in), true);
332 
333     ASSERT_EQ(testStrlen, decodedStrLen);
334     /* Use memcmp instead of strcmp since decodedStr isn't null terminated */
335     ASSERT_EQ(0, memcmp(testStr, decodedStr, decodedStrLen));
336 }
337 
TEST(CborTest,ViewsAndVectors)338 TEST(CborTest, ViewsAndVectors) {
339     cbor::VectorCborEncoder initialEnc;
340     auto initialView = initialEnc.view();
341     EXPECT_EQ(initialView.size(), 0u);
342     auto initialVec = initialEnc.intoVec();
343     EXPECT_EQ(initialVec.size(), 0u);
344     EXPECT_DEATH({ initialEnc.intoVec(); }, "buffer was moved out of encoder");
345     EXPECT_DEATH({ initialEnc.view(); },
346                  "requested view of buffer from encoder in invalid state");
347 
348     cbor::VectorCborEncoder enc;
349     enc.encodeArray([&](auto& enc) { enc.encodeEmptyBstr(); });
350     auto view = enc.view();
351     EXPECT_EQ(view.size(), 2u);
352     auto vec = enc.intoVec();
353     EXPECT_EQ(vec.size(), 2u);
354     EXPECT_DEATH({ enc.intoVec(); }, "buffer was moved out of encoder");
355     EXPECT_DEATH({ enc.view(); },
356                  "requested view of buffer from encoder in invalid state");
357 }
358 
359 #if __clang_major__ < 15
TEST(CborTest,EncodeArrayOfFakeBstrOverflows)360 TEST(CborTest, EncodeArrayOfFakeBstrOverflows) {
361 #else
362 // Newer clang compilers, e.g. clang-r458507 15.0.1, have ASAN that
363 // can detect stack overview in enc.encodeBstr(fake).
364 // So this test will fail at that point with newer compilers.
365 TEST(CborTest, EncodeArrayOfFakeBstrOverflows) __attribute__((no_sanitize("address"))) {
366 #endif
367     cbor::VectorCborEncoder enc;
368     const std::span<const uint8_t> fake(static_cast<const uint8_t*>(nullptr),
369                                         std::numeric_limits<size_t>::max());
370     enc.encodeArray([&](auto& enc) { enc.encodeBstr(fake); });
371     EXPECT_EQ(enc.state(), cbor::VectorCborEncoder::State::kOverflowed);
372     EXPECT_DEATH({ enc.size(); }, "requested encoding size after overflow");
373     EXPECT_DEATH({ enc.intoVec(); },
374                  "buffer was too small to hold cbor encoded content");
375     EXPECT_DEATH({ enc.view(); },
376                  "requested view of buffer from encoder in invalid state");
377 }
378 
379 TEST(CborTest, CopyBytes) {
380     const uint64_t ans = 42;
381     cbor::VectorCborEncoder innerEncoder, outerEncoder;
382     innerEncoder.encodeArray([&](auto& enc) { enc.encodeUint(ans); });
383     const auto view = innerEncoder.view();
384 
385     outerEncoder.encodeArray([&](auto& enc) { enc.copyBytes(view); });
386 
387     const auto vec = outerEncoder.intoVec();
388     auto [item, _, err] = cppbor::parse(vec);
389     ASSERT_NE(item, nullptr);
390     const auto outerArray = item->asArray();
391     ASSERT_NE(outerArray, nullptr);
392     ASSERT_EQ(outerArray->size(), 1u);
393     const auto innerArray = outerArray->get(0)->asArray();
394     ASSERT_NE(innerArray, nullptr);
395     ASSERT_EQ(innerArray->size(), 1u);
396     const auto innerInt = innerArray->get(0)->asUint();
397     ASSERT_NE(innerInt, nullptr);
398     ASSERT_EQ(innerInt->unsignedValue(), ans);
399 }
400