Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 82 additions & 16 deletions src/electronic-id.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,52 @@

#include <map>
#include <numeric>
#include <sstream>

using namespace pcsc_cpp;
using namespace electronic_id;
using namespace std::string_literals;

namespace
{
// Add a structure for ElectronicID Type because, in Belgium, there's a token to identify the EId Card
// but this token has a mask that must be applied during comparison.
struct ElectronicIDType
{
const byte_vector token;
const byte_vector mask;

friend bool operator<(const ElectronicIDType& lhs, const ElectronicIDType& rhs)
{
if (lhs.token.size() != rhs.token.size())
return lhs.token < rhs.token;

byte_vector lToken;
if (rhs.mask.size() != 0) {
for (size_t i = 0; i < lhs.token.size(); ++i)
if (i < rhs.mask.size())
lToken.push_back(lhs.token.at(i) & rhs.mask.at(i));
else
lToken.push_back(lhs.token.at(i));
}
else {
lToken = lhs.token;
}
byte_vector rToken;
if (lhs.mask.size() != 0) {
for (size_t i = 0; i < rhs.token.size(); ++i)
if (i < lhs.mask.size())
rToken.push_back(rhs.token.at(i) & lhs.mask.at(i));
else
rToken.push_back(rhs.token.at(i));
}
else {
rToken = rhs.token;
}

return lToken < rToken;
}
};

using ElectronicIDConstructor = std::function<ElectronicID::ptr(const Reader&)>;

Expand All @@ -57,57 +96,82 @@ constexpr auto constructor(const Reader&)
}

// Supported cards.
const std::map<byte_vector, ElectronicIDConstructor> SUPPORTED_ATRS {
const std::map<ElectronicIDType, ElectronicIDConstructor> SUPPORTED_ATRS {
// EstEID Gemalto v3.5.8 cold
{{0x3b, 0xfa, 0x18, 0x00, 0x00, 0x80, 0x31, 0xfe, 0x45, 0xfe,
{ElectronicIDType {{0x3b, 0xfa, 0x18, 0x00, 0x00, 0x80, 0x31, 0xfe, 0x45, 0xfe,
0x65, 0x49, 0x44, 0x20, 0x2f, 0x20, 0x50, 0x4b, 0x49, 0x03},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
constructor<EstEIDGemaltoV3_5_8>},
// EstEID Gemalto v3.5.8 warm
{{0x3b, 0xfe, 0x18, 0x00, 0x00, 0x80, 0x31, 0xfe, 0x45, 0x80, 0x31, 0x80,
{ElectronicIDType {{0x3b, 0xfe, 0x18, 0x00, 0x00, 0x80, 0x31, 0xfe, 0x45, 0x80, 0x31, 0x80,
0x66, 0x40, 0x90, 0xa4, 0x16, 0x2a, 0x00, 0x83, 0x0f, 0x90, 0x00, 0xef},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
constructor<EstEIDGemaltoV3_5_8>},
// EstEID Idemia v1.0
{{0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, 0x1f, 0x83, 0x00,
{ElectronicIDType {{0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, 0x1f, 0x83, 0x00,
0x12, 0x23, 0x3f, 0x53, 0x65, 0x49, 0x44, 0x0f, 0x90, 0x00, 0xf1},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
constructor<EstEIDIDEMIAV1>},
// FinEID v3.0
{{0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0xB8, 0x65, 0xB0,
{ElectronicIDType {{0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0xB8, 0x65, 0xB0,
0x85, 0x03, 0x00, 0xEF, 0x12, 0x00, 0xF6, 0x82, 0x90, 0x00},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
constructor<FinEIDv3>},
// FinEID v3.1
{{0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0xB8, 0x65, 0xB0,
{ElectronicIDType {{0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0xB8, 0x65, 0xB0,
0x85, 0x04, 0x02, 0x1B, 0x12, 0x00, 0xF6, 0x82, 0x90, 0x00},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
constructor<FinEIDv3>},
// FinEID v4.0
{{0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0xB8, 0x65, 0xB0,
{ElectronicIDType {{0x3B, 0x7F, 0x96, 0x00, 0x00, 0x80, 0x31, 0xB8, 0x65, 0xB0,
0x85, 0x05, 0x00, 0x11, 0x12, 0x24, 0x60, 0x82, 0x90, 0x00},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
constructor<FinEIDv4>},
// LatEID Idemia v1.0
{{0x3b, 0xdd, 0x18, 0x00, 0x81, 0x31, 0xfe, 0x45, 0x90, 0x4c, 0x41,
{ElectronicIDType {{0x3b, 0xdd, 0x18, 0x00, 0x81, 0x31, 0xfe, 0x45, 0x90, 0x4c, 0x41,
0x54, 0x56, 0x49, 0x41, 0x2d, 0x65, 0x49, 0x44, 0x90, 0x00, 0x8c},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
constructor<LatEIDIDEMIAV1>},
// LatEID Idemia v2.0
{{0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, 0x1f, 0x83, 0x00,
{ElectronicIDType {{0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, 0x1f, 0x83, 0x00,
0x12, 0x42, 0x8f, 0x53, 0x65, 0x49, 0x44, 0x0f, 0x90, 0x00, 0x20},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
constructor<LatEIDIDEMIAV2>},
// LitEID
{{0x3B, 0x9D, 0x18, 0x81, 0x31, 0xFC, 0x35, 0x80, 0x31, 0xC0, 0x69,
{ElectronicIDType {{0x3B, 0x9D, 0x18, 0x81, 0x31, 0xFC, 0x35, 0x80, 0x31, 0xC0, 0x69,
0x4D, 0x54, 0x43, 0x4F, 0x53, 0x73, 0x02, 0x05, 0x05, 0xD3},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff}},
constructor<Pkcs11ElectronicIDType::LitEIDv3>},
// HrvEID
{{0x3b, 0xff, 0x13, 0x00, 0x00, 0x81, 0x31, 0xfe, 0x45, 0x00, 0x31, 0xb9, 0x64,
{ElectronicIDType {{0x3b, 0xff, 0x13, 0x00, 0x00, 0x81, 0x31, 0xfe, 0x45, 0x00, 0x31, 0xb9, 0x64,
0x04, 0x44, 0xec, 0xc1, 0x73, 0x94, 0x01, 0x80, 0x82, 0x90, 0x00, 0x12},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
constructor<Pkcs11ElectronicIDType::HrvEID>},
// BelEIDV1_7
{{0x3b, 0x98, 0x13, 0x40, 0x0a, 0xa5, 0x03, 0x01, 0x01, 0x01, 0xad, 0x13, 0x11},
{ElectronicIDType {{0x3b, 0x98, 0x13, 0x40, 0x0a, 0xa5, 0x03, 0x01, 0x01, 0x01, 0xad, 0x13, 0x11},
{0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}},
constructor<Pkcs11ElectronicIDType::BelEIDV1_7>},
// BelEIDV1_8
{{0x3b, 0x7f, 0x96, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xb0,
{ElectronicIDType {{0x3b, 0x7f, 0x96, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xb0,
0x85, 0x04, 0x01, 0x20, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
constructor<Pkcs11ElectronicIDType::BelEIDV1_8>},
// CzeEID
{{0x3b, 0x7e, 0x94, 0x00, 0x00, 0x80, 0x25, 0xd2, 0x03, 0x10, 0x01, 0x00, 0x56, 0x00, 0x00,
{ElectronicIDType {{0x3b, 0x7e, 0x94, 0x00, 0x00, 0x80, 0x25, 0xd2, 0x03, 0x10, 0x01, 0x00, 0x56, 0x00, 0x00,
0x00, 0x02, 0x02, 0x00},
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff}},
constructor<Pkcs11ElectronicIDType::CzeEID>},
};

Expand Down Expand Up @@ -138,13 +202,15 @@ namespace electronic_id

bool isCardSupported(const pcsc_cpp::byte_vector& atr)
{
return SUPPORTED_ATRS.count(atr);
ElectronicIDType atrToken = {atr, {}};
return SUPPORTED_ATRS.count(atrToken);
}

ElectronicID::ptr getElectronicID(const pcsc_cpp::Reader& reader)
{
try {
const auto& eidConstructor = SUPPORTED_ATRS.at(reader.cardAtr);
ElectronicIDType atrToken = {reader.cardAtr, {}};
const auto& eidConstructor = SUPPORTED_ATRS.at(atrToken);
return eidConstructor(reader);
} catch (const std::out_of_range&) {
// It should be verified that the card is supported with isCardSupported() before
Expand Down