mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
Includes: A light weight CBOR generator This patch adds a header only CBOR generator and unit tests. It allows expressing CBOR datastructures in C++ for subsequent serialization. The implementation performs no memory allocation and only depends on stdint.h (for (u)intx_t) and stddefs.h (for size_t). It is tailored for use in constrained environments such as TEEs. Convenience method for generating a SHA256 HMAC Bug: 63928580 Test: android.hardware.confirmationui@support-lib-tests Change-Id: I1d93a85503f861281e71e09b1ede5cbb74219694
198 lines
8.5 KiB
C++
198 lines
8.5 KiB
C++
/*
|
|
**
|
|
** Copyright 2017, The Android Open Source Project
|
|
**
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
** you may not use this file except in compliance with the License.
|
|
** You may obtain a copy of the License at
|
|
**
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
**
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
** See the License for the specific language governing permissions and
|
|
** limitations under the License.
|
|
*/
|
|
|
|
#include <android/hardware/confirmationui/support/cbor.h>
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
using namespace android::hardware::confirmationui::support;
|
|
|
|
uint8_t testVector[] = {
|
|
0xA4, 0x63, 0x6B, 0x65, 0x79, 0x65, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x63, 0x6B, 0x65, 0x79, 0x4D,
|
|
0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x31, 0x30, 0x00, 0x04, 0x07, 0x1B,
|
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x07, 0x1A, 0xFD, 0x49, 0x8C, 0xFF,
|
|
0xFF, 0x82, 0x69, 0xE2, 0x99, 0xA8, 0xE2, 0x9A, 0x96, 0xE2, 0xB6, 0x96, 0x59, 0x01, 0x91, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
|
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x00,
|
|
};
|
|
|
|
// 400 'a's and a '\0'
|
|
constexpr char fourHundredAs[] =
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
"aaaaaaaaaaaaaaaaaaaaaaaa";
|
|
|
|
WriteState writeTest(WriteState state) {
|
|
return write(state, //
|
|
map( //
|
|
pair(text("key"), text("value")), //
|
|
pair(text("key"), bytes("100101010010")), //
|
|
pair(4, 7), //
|
|
pair((UINT64_C(1) << 62), INT64_C(-2000000000000000)) //
|
|
), //
|
|
arr(text("♨⚖ⶖ"), bytes(fourHundredAs)));
|
|
}
|
|
|
|
TEST(Cbor, FeatureTest) {
|
|
uint8_t buffer[0x1000];
|
|
WriteState state(buffer);
|
|
state = writeTest(state);
|
|
ASSERT_EQ(sizeof(testVector), size_t(state.data_ - buffer));
|
|
ASSERT_EQ(Error::OK, state.error_);
|
|
ASSERT_EQ(0, memcmp(buffer, testVector, sizeof(testVector)));
|
|
}
|
|
|
|
// Test if in all write cases an out of data error is correctly propagated and we don't
|
|
// write beyond the end of the buffer.
|
|
TEST(Cbor, BufferTooShort) {
|
|
uint8_t buffer[0x1000];
|
|
for (size_t s = 1; s < sizeof(testVector); ++s) {
|
|
memset(buffer, 0x22, 0x1000); // 0x22 is not in the testVector
|
|
WriteState state(buffer, s);
|
|
state = writeTest(state);
|
|
for (size_t t = s; t < 0x1000; ++t) {
|
|
ASSERT_EQ(0x22, buffer[t]); // check if a canary has been killed
|
|
}
|
|
ASSERT_EQ(Error::OUT_OF_DATA, state.error_);
|
|
}
|
|
}
|
|
|
|
TEST(Cbor, MalformedUTF8Test_Stray) {
|
|
uint8_t buffer[20];
|
|
WriteState state(buffer);
|
|
char malformed[] = {char(0x80), 0};
|
|
state = write(state, text(malformed));
|
|
ASSERT_EQ(Error::MALFORMED_UTF8, state.error_);
|
|
}
|
|
|
|
TEST(Cbor, MalformendUTF8Test_StringEndsMidMultiByte) {
|
|
uint8_t buffer[20];
|
|
WriteState state(buffer);
|
|
char malformed[] = {char(0xc0), 0};
|
|
state = write(state, text(malformed));
|
|
ASSERT_EQ(Error::MALFORMED_UTF8, state.error_);
|
|
}
|
|
|
|
TEST(Cbor, UTF8Test_TwoBytes) {
|
|
uint8_t buffer[20];
|
|
WriteState state(buffer);
|
|
char neat[] = {char(0xc3), char(0x82), 0};
|
|
state = write(state, text(neat));
|
|
ASSERT_EQ(Error::OK, state.error_);
|
|
}
|
|
|
|
TEST(Cbor, UTF8Test_ThreeBytes) {
|
|
uint8_t buffer[20];
|
|
WriteState state(buffer);
|
|
char neat[] = {char(0xe3), char(0x82), char(0x82), 0};
|
|
state = write(state, text(neat));
|
|
ASSERT_EQ(Error::OK, state.error_);
|
|
}
|
|
|
|
TEST(Cbor, UTF8Test_FourBytes) {
|
|
uint8_t buffer[20];
|
|
WriteState state(buffer);
|
|
char neat[] = {char(0xf3), char(0x82), char(0x82), char(0x82), 0};
|
|
state = write(state, text(neat));
|
|
ASSERT_EQ(Error::OK, state.error_);
|
|
}
|
|
|
|
TEST(Cbor, MalformendUTF8Test_CharacterTooLong) {
|
|
uint8_t buffer[20];
|
|
WriteState state(buffer);
|
|
char malformed[] = {char(0xf8), char(0x82), char(0x82), char(0x82), char(0x82), 0};
|
|
state = write(state, text(malformed));
|
|
ASSERT_EQ(Error::MALFORMED_UTF8, state.error_);
|
|
}
|
|
|
|
TEST(Cbor, MalformendUTF8Test_StringEndsMidMultiByte2) {
|
|
uint8_t buffer[20];
|
|
WriteState state(buffer);
|
|
char malformed[] = {char(0xc0), char(0x82), char(0x83), 0};
|
|
state = write(state, text(malformed));
|
|
ASSERT_EQ(Error::MALFORMED_UTF8, state.error_);
|
|
}
|
|
|
|
TEST(Cbor, MinimalViableHeaderSizeTest) {
|
|
uint8_t buffer[20];
|
|
WriteState state(buffer);
|
|
state = writeHeader(state, Type::NUMBER, 23);
|
|
ASSERT_EQ(state.data_ - buffer, 1);
|
|
|
|
state = WriteState(buffer);
|
|
state = writeHeader(state, Type::NUMBER, 24);
|
|
ASSERT_EQ(state.data_ - buffer, 2);
|
|
|
|
state = WriteState(buffer);
|
|
state = writeHeader(state, Type::NUMBER, 0xff);
|
|
ASSERT_EQ(state.data_ - buffer, 2);
|
|
|
|
state = WriteState(buffer);
|
|
state = writeHeader(state, Type::NUMBER, 0x100);
|
|
ASSERT_EQ(state.data_ - buffer, 3);
|
|
|
|
state = WriteState(buffer);
|
|
state = writeHeader(state, Type::NUMBER, 0xffff);
|
|
ASSERT_EQ(state.data_ - buffer, 3);
|
|
|
|
state = WriteState(buffer);
|
|
state = writeHeader(state, Type::NUMBER, 0x10000);
|
|
ASSERT_EQ(state.data_ - buffer, 5);
|
|
|
|
state = WriteState(buffer);
|
|
state = writeHeader(state, Type::NUMBER, 0xffffffff);
|
|
ASSERT_EQ(state.data_ - buffer, 5);
|
|
|
|
state = WriteState(buffer);
|
|
state = writeHeader(state, Type::NUMBER, 0x100000000);
|
|
ASSERT_EQ(state.data_ - buffer, 9);
|
|
|
|
state = WriteState(buffer);
|
|
state = writeHeader(state, Type::NUMBER, 0xffffffffffffffff);
|
|
ASSERT_EQ(state.data_ - buffer, 9);
|
|
}
|