mirror of
https://github.com/m5stack/M5Unit-NFC.git
synced 2026-05-20 11:48:34 -07:00
Add test,refactoring,fixes bug
This commit is contained in:
+174
-114
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
|
||||
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
#include <gtest/gtest.h>
|
||||
#include <M5Unified.h>
|
||||
#include <M5Utility.hpp>
|
||||
#include "nfc/f/nfcf.hpp"
|
||||
#include <cstring>
|
||||
|
||||
@@ -17,120 +16,181 @@ using namespace m5::nfc::f;
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr Type type_table[] = {
|
||||
Type::Unknown, Type::FeliCaStandard, Type::FeliCaLite, Type::FeliCaLiteS, Type::FeliCaPlug,
|
||||
// FeliCaLink,
|
||||
};
|
||||
constexpr TimeSlot time_slot_table[] = {
|
||||
TimeSlot::Slot1, TimeSlot::Slot2, TimeSlot::Slot4, TimeSlot::Slot8, TimeSlot::Slot16,
|
||||
};
|
||||
constexpr block_t block_table[] = {0x00, 0xFF, 0x100, 0xFFFF};
|
||||
constexpr uint32_t block_number_table[] = {0x00, 0xFF, 0x100, 0xFFFF};
|
||||
constexpr uint8_t kIdm[FELICA_ID_LENGTH] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
|
||||
constexpr uint8_t kPmm[FELICA_ID_LENGTH] = {0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(NFC_F, Basic)
|
||||
TEST(NFC_F, TimeSlot)
|
||||
{
|
||||
//
|
||||
{
|
||||
for (auto&& t : type_table) {
|
||||
auto ftag = get_nfc_forum_tag_type(t);
|
||||
if (t == Type::Unknown) {
|
||||
EXPECT_EQ(ftag, NFCForumTag::None);
|
||||
} else {
|
||||
EXPECT_EQ(ftag, NFCForumTag::Type3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
{
|
||||
uint16_t idx{};
|
||||
for (auto&& ts : time_slot_table) {
|
||||
auto slots = timeslot_to_slot(ts);
|
||||
EXPECT_EQ(slots, 1U << idx);
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
{
|
||||
uint32_t idx{};
|
||||
for (auto&& b : block_table) {
|
||||
auto bnum = b.block();
|
||||
auto num = block_number_table[idx];
|
||||
EXPECT_EQ(bnum, num);
|
||||
if (num < 0x100) {
|
||||
EXPECT_TRUE(b.is_2byte());
|
||||
EXPECT_FALSE(b.is_3byte());
|
||||
} else {
|
||||
EXPECT_FALSE(b.is_2byte());
|
||||
EXPECT_TRUE(b.is_3byte());
|
||||
}
|
||||
EXPECT_EQ(b.access_mode(), 0u);
|
||||
EXPECT_EQ(b.order(), 0u);
|
||||
|
||||
uint8_t buf[3]{};
|
||||
auto len = b.store(buf);
|
||||
EXPECT_EQ(len, b.is_2byte() ? 2 : 3);
|
||||
EXPECT_EQ(buf[0], b.is_2byte() ? 0x80 : 0x00);
|
||||
EXPECT_EQ(buf[1], bnum & 0xFF);
|
||||
EXPECT_EQ(buf[2], bnum >> 8);
|
||||
|
||||
++idx;
|
||||
}
|
||||
|
||||
block_t b{0x12, 0x07, 0x0C};
|
||||
EXPECT_EQ(b.block(), 0x12);
|
||||
EXPECT_EQ(b.access_mode(), 0x07);
|
||||
EXPECT_EQ(b.order(), 0x0C);
|
||||
|
||||
b.access_mode(0);
|
||||
EXPECT_EQ(b.block(), 0x12);
|
||||
EXPECT_EQ(b.access_mode(), 0);
|
||||
EXPECT_EQ(b.order(), 0x0C);
|
||||
|
||||
b.access_mode(0xFF);
|
||||
EXPECT_EQ(b.block(), 0x12);
|
||||
EXPECT_EQ(b.access_mode(), 0x07);
|
||||
EXPECT_EQ(b.order(), 0x0C);
|
||||
|
||||
b.order(0);
|
||||
EXPECT_EQ(b.block(), 0x12);
|
||||
EXPECT_EQ(b.access_mode(), 0x07);
|
||||
EXPECT_EQ(b.order(), 0);
|
||||
|
||||
b.order(0xFF);
|
||||
EXPECT_EQ(b.block(), 0x12);
|
||||
EXPECT_EQ(b.access_mode(), 0x07);
|
||||
EXPECT_EQ(b.order(), 0x0F);
|
||||
|
||||
b.block(0);
|
||||
EXPECT_TRUE(b.is_2byte());
|
||||
EXPECT_FALSE(b.is_3byte());
|
||||
EXPECT_EQ(b.block(), 0);
|
||||
EXPECT_EQ(b.access_mode(), 0x07);
|
||||
EXPECT_EQ(b.order(), 0x0F);
|
||||
|
||||
b.block(0XFFFF);
|
||||
EXPECT_FALSE(b.is_2byte());
|
||||
EXPECT_TRUE(b.is_3byte());
|
||||
EXPECT_EQ(b.block(), 0XFFFF);
|
||||
EXPECT_EQ(b.access_mode(), 0x07);
|
||||
EXPECT_EQ(b.order(), 0x0F);
|
||||
|
||||
b.block(0XFF);
|
||||
EXPECT_TRUE(b.is_2byte());
|
||||
EXPECT_FALSE(b.is_3byte());
|
||||
EXPECT_EQ(b.block(), 0XFF);
|
||||
EXPECT_EQ(b.access_mode(), 0x07);
|
||||
EXPECT_EQ(b.order(), 0x0F);
|
||||
|
||||
b.block(0X100);
|
||||
EXPECT_FALSE(b.is_2byte());
|
||||
EXPECT_TRUE(b.is_3byte());
|
||||
EXPECT_EQ(b.block(), 0X100);
|
||||
EXPECT_EQ(b.access_mode(), 0x07);
|
||||
EXPECT_EQ(b.order(), 0x0F);
|
||||
}
|
||||
EXPECT_EQ(timeslot_to_slot(TimeSlot::Slot1), 1);
|
||||
EXPECT_EQ(timeslot_to_slot(TimeSlot::Slot2), 2);
|
||||
EXPECT_EQ(timeslot_to_slot(TimeSlot::Slot4), 4);
|
||||
EXPECT_EQ(timeslot_to_slot(TimeSlot::Slot8), 8);
|
||||
EXPECT_EQ(timeslot_to_slot(TimeSlot::Slot16), 16);
|
||||
EXPECT_EQ(timeslot_to_slot(static_cast<TimeSlot>(0xFF)), 0);
|
||||
}
|
||||
|
||||
TEST(NFC_F, Block)
|
||||
{
|
||||
block_t b{0x0102, 0x03, 0x04};
|
||||
EXPECT_TRUE(b.is_3byte());
|
||||
EXPECT_FALSE(b.is_2byte());
|
||||
EXPECT_EQ(b.access_mode(), 0x03);
|
||||
EXPECT_EQ(b.order(), 0x04);
|
||||
EXPECT_EQ(b.block(), 0x0102);
|
||||
|
||||
uint8_t buf[3] = {0};
|
||||
auto len = b.store(buf);
|
||||
EXPECT_EQ(len, 3u);
|
||||
EXPECT_EQ(buf[0], b.header);
|
||||
EXPECT_EQ(buf[1], 0x02);
|
||||
EXPECT_EQ(buf[2], 0x01);
|
||||
|
||||
auto b2 = block_t::from(buf);
|
||||
EXPECT_TRUE(b2.is_3byte());
|
||||
EXPECT_EQ(b2.block(), 0x0102);
|
||||
EXPECT_EQ(b2.access_mode(), 0x03);
|
||||
EXPECT_EQ(b2.order(), 0x04);
|
||||
|
||||
b2.block(0x00FE);
|
||||
EXPECT_TRUE(b2.is_2byte());
|
||||
EXPECT_EQ(b2.block(), 0x00FE);
|
||||
|
||||
b2.access_mode(0x07);
|
||||
b2.order(0x0F);
|
||||
EXPECT_EQ(b2.access_mode(), 0x07);
|
||||
EXPECT_EQ(b2.order(), 0x0F);
|
||||
}
|
||||
|
||||
TEST(NFC_F, UserArea)
|
||||
{
|
||||
EXPECT_EQ(get_nfc_forum_tag_type(Type::Unknown), NFCForumTag::None);
|
||||
EXPECT_EQ(get_nfc_forum_tag_type(Type::FeliCaLiteS), NFCForumTag::Type3);
|
||||
|
||||
EXPECT_EQ(get_number_of_user_blocks(Type::Unknown), 0);
|
||||
EXPECT_EQ(get_number_of_user_blocks(Type::FeliCaLite), 14);
|
||||
EXPECT_EQ(get_number_of_user_blocks(Type::FeliCaLiteS), 14);
|
||||
|
||||
EXPECT_EQ(get_first_user_block(Type::FeliCaLite), 0);
|
||||
EXPECT_EQ(get_last_user_block(Type::FeliCaLite), 0x0D);
|
||||
|
||||
EXPECT_TRUE(is_user_block(Type::FeliCaLite, 0));
|
||||
EXPECT_TRUE(is_user_block(Type::FeliCaLite, 0x0D));
|
||||
EXPECT_FALSE(is_user_block(Type::FeliCaLite, 0x0E));
|
||||
|
||||
EXPECT_EQ(get_maxumum_read_blocks(Type::FeliCaStandard), 8u);
|
||||
EXPECT_EQ(get_maxumum_read_blocks(Type::FeliCaLite), 4u);
|
||||
EXPECT_EQ(get_maxumum_write_blocks(Type::FeliCaLiteS), 1u);
|
||||
}
|
||||
|
||||
TEST(NFC_F, PICC)
|
||||
{
|
||||
PICC picc{};
|
||||
EXPECT_FALSE(picc.valid());
|
||||
EXPECT_FALSE(picc.validEmulation());
|
||||
EXPECT_EQ(picc.firstUserBlock(), 0xFFFF);
|
||||
EXPECT_EQ(picc.lastUserBlock(), 0xFFFF);
|
||||
EXPECT_EQ(picc.userAreaSize(), 0u);
|
||||
EXPECT_EQ(picc.nfcForumTagType(), NFCForumTag::None);
|
||||
|
||||
std::memcpy(picc.idm, kIdm, sizeof(kIdm));
|
||||
std::memcpy(picc.pmm, kPmm, sizeof(kPmm));
|
||||
picc.type = Type::FeliCaLiteS;
|
||||
picc.format = format_lite;
|
||||
picc.emulation_sc = system_code_lite;
|
||||
|
||||
EXPECT_TRUE(picc.valid());
|
||||
EXPECT_TRUE(picc.validEmulation());
|
||||
EXPECT_EQ(picc.userAreaSize(), 16u * 14u);
|
||||
EXPECT_EQ(picc.firstUserBlock(), 0u);
|
||||
EXPECT_EQ(picc.lastUserBlock(), 0x0Du);
|
||||
EXPECT_TRUE(picc.isUserBlock(block_t{0x0D}));
|
||||
EXPECT_FALSE(picc.isUserBlock(block_t{0x0E}));
|
||||
|
||||
EXPECT_EQ(picc.idmAsString(), std::string("0123456789ABCDEF"));
|
||||
EXPECT_EQ(picc.pmmAsString(), std::string("1032547698BADCFE"));
|
||||
EXPECT_EQ(picc.typeAsString(), std::string("FeliCa Lite-S"));
|
||||
|
||||
PICC picc2 = picc;
|
||||
EXPECT_TRUE(picc == picc2);
|
||||
picc2.pmm[0] ^= 0x01;
|
||||
EXPECT_TRUE(picc != picc2);
|
||||
|
||||
// emulation
|
||||
PICC picc3{};
|
||||
EXPECT_TRUE(picc3.emulate(Type::FeliCaLiteS, kIdm, kPmm));
|
||||
EXPECT_TRUE(picc3.validEmulation());
|
||||
EXPECT_FALSE(picc3.emulate(Type::FeliCaLite, kIdm, kPmm));
|
||||
}
|
||||
|
||||
TEST(NFC_F, Reg)
|
||||
{
|
||||
REG r{};
|
||||
r.regA(0x11223344);
|
||||
r.regB(0xA1A2A3A4);
|
||||
r.regC(0x0102030405060708ULL);
|
||||
|
||||
EXPECT_EQ(r.regA(), 0x11223344u);
|
||||
EXPECT_EQ(r.regB(), 0xA1A2A3A4u);
|
||||
EXPECT_EQ(r.regC(), 0x0102030405060708ULL);
|
||||
|
||||
REG o = r;
|
||||
REG n = r;
|
||||
n.regA(0x00112233);
|
||||
n.regB(0x01020304);
|
||||
EXPECT_TRUE(can_write_reg(o, n));
|
||||
|
||||
n.regA(0xFFFFFFFF);
|
||||
EXPECT_FALSE(can_write_reg(o, n));
|
||||
}
|
||||
|
||||
TEST(NFC_F, BlockPermission)
|
||||
{
|
||||
EXPECT_TRUE(is_read_only_lite(lite::MAC));
|
||||
EXPECT_TRUE(is_read_only_lite(lite::SYS_C));
|
||||
EXPECT_FALSE(is_read_only_lite(lite::S_PAD1));
|
||||
|
||||
EXPECT_TRUE(is_read_only_lite_s(lite_s::MAC));
|
||||
EXPECT_TRUE(is_read_only_lite_s(lite_s::D_ID));
|
||||
EXPECT_TRUE(is_read_only_lite_s(lite_s::SYS_C));
|
||||
EXPECT_TRUE(is_read_only_lite_s(lite_s::WCNT));
|
||||
EXPECT_TRUE(is_read_only_lite_s(lite_s::CRC_CHECK));
|
||||
|
||||
EXPECT_FALSE(can_read_lite(lite_s::RC));
|
||||
EXPECT_FALSE(can_read_lite(lite_s::CK));
|
||||
EXPECT_TRUE(can_read_lite(lite::S_PAD0));
|
||||
|
||||
EXPECT_FALSE(can_read_lite_s(lite_s::RC));
|
||||
EXPECT_FALSE(can_read_lite_s(lite_s::CK));
|
||||
EXPECT_TRUE(can_read_lite_s(lite_s::S_PAD0));
|
||||
}
|
||||
|
||||
TEST(NFC_F, CryptoInvalid)
|
||||
{
|
||||
uint8_t out[16]{};
|
||||
uint8_t key16[16]{};
|
||||
uint8_t key24[24]{};
|
||||
uint8_t rc[16]{};
|
||||
uint8_t plain[16]{};
|
||||
uint8_t block[16]{};
|
||||
uint8_t sk1[8]{};
|
||||
uint8_t sk2[8]{};
|
||||
|
||||
EXPECT_FALSE(make_session_key(nullptr, key16, rc));
|
||||
EXPECT_FALSE(make_session_key(out, nullptr, rc));
|
||||
EXPECT_FALSE(make_session_key(out, key16, nullptr));
|
||||
|
||||
EXPECT_FALSE(generate_mac(nullptr, plain, sizeof(plain), block, sizeof(block), sk1, sk2, rc));
|
||||
EXPECT_FALSE(generate_mac(out, nullptr, sizeof(plain), block, sizeof(block), sk1, sk2, rc));
|
||||
EXPECT_TRUE(generate_mac(out, plain, 0, block, sizeof(block), sk1, sk2, rc));
|
||||
EXPECT_FALSE(generate_mac(out, plain, sizeof(plain), nullptr, sizeof(block), sk1, sk2, rc));
|
||||
EXPECT_FALSE(generate_mac(out, plain, sizeof(plain), block, 0, sk1, sk2, rc));
|
||||
EXPECT_FALSE(generate_mac(out, plain, sizeof(plain), block, sizeof(block), nullptr, sk2, rc));
|
||||
EXPECT_FALSE(generate_mac(out, plain, sizeof(plain), block, sizeof(block), sk1, nullptr, rc));
|
||||
EXPECT_FALSE(generate_mac(out, plain, sizeof(plain), block, sizeof(block), sk1, sk2, nullptr));
|
||||
|
||||
EXPECT_FALSE(make_personalized_card_key_lite_s(nullptr, key24, block));
|
||||
EXPECT_FALSE(make_personalized_card_key_lite_s(out, nullptr, block));
|
||||
EXPECT_FALSE(make_personalized_card_key_lite_s(out, key24, nullptr));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user