Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Select supported cards based on AID #39

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "lib/libpcsc-cpp"]
path = lib/libpcsc-cpp
url = ../libpcsc-cpp
url = https://github.com/web-eid/libpcsc-cpp
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be reverted to the original relative path.

6 changes: 4 additions & 2 deletions include/electronic-id/electronic-id.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,11 @@ class ElectronicID
ElectronicID& operator=(ElectronicID&&) = delete;
};

bool isCardSupported(const pcsc_cpp::byte_vector& atr);
bool isCardATRSupported(const pcsc_cpp::byte_vector& atr);
bool isCardAIDSupported(const pcsc_cpp::SmartCard& card);

ElectronicID::ptr getElectronicID(const pcsc_cpp::Reader& reader);
ElectronicID::ptr getElectronicIDbyATR(const pcsc_cpp::Reader& reader);
ElectronicID::ptr getElectronicIDbyAID(const pcsc_cpp::byte_vector& aid, pcsc_cpp::SmartCard::ptr card);

/** Aggregates reader and electronic ID objects for communicating with and inspecting the eID card.
*/
Expand Down
21 changes: 17 additions & 4 deletions src/availableSupportedCards.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,16 @@ namespace

using namespace electronic_id;

inline CardInfo::ptr connectToCard(const pcsc_cpp::Reader& reader)
inline CardInfo::ptr connectToEIDByATR(const pcsc_cpp::Reader& reader)
{
auto eid = getElectronicID(reader);
auto eid = getElectronicIDbyATR(reader);
return std::make_shared<CardInfo>(reader, eid);
}

inline CardInfo::ptr connectToEIDByAID(const pcsc_cpp::Reader& reader,
pcsc_cpp::SmartCard::ptr card)
{
auto eid = getElectronicIDbyAID(reader.cardAtr, std::move(card));
return std::make_shared<CardInfo>(reader, eid);
}

Expand All @@ -57,8 +64,14 @@ std::vector<CardInfo::ptr> availableSupportedCards()
continue;
}
seenCard = true;
if (isCardSupported(reader.cardAtr)) {
cards.push_back(connectToCard(reader));
if (isCardATRSupported(reader.cardAtr)) {
cards.push_back(connectToEIDByATR(reader));
} else {
pcsc_cpp::SmartCard::ptr card_ptr = reader.connectToCard();

if (isCardAIDSupported(*card_ptr)) {
cards.push_back(connectToEIDByAID(reader, std::move(card_ptr)));
}
}
}

Expand Down
45 changes: 41 additions & 4 deletions src/electronic-id.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ const std::map<byte_vector, ElectronicIDConstructor> SUPPORTED_ATRS = {
}},
};

const std::map<byte_vector, ElectronicIDConstructor> SUPPORTED_AIDS = {
// EXAMPLE:
// PIV FIPS 201-3
// {{0xa0, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00},
// [](SmartCard::ptr&& card) { return std::make_unique<PIV>(std::move(card)); }},
};

inline std::string byteVectorToHexString(const byte_vector& bytes)
{
std::ostringstream hexStringBuilder;
Expand All @@ -143,24 +150,54 @@ const auto SUPPORTED_ALGORITHMS = std::map<std::string, HashAlgorithm> {
namespace electronic_id
{

bool isCardSupported(const pcsc_cpp::byte_vector& atr)
bool isCardATRSupported(const pcsc_cpp::byte_vector& atr)
{
return SUPPORTED_ATRS.count(atr);
}

ElectronicID::ptr getElectronicID(const pcsc_cpp::Reader& reader)
bool isCardAIDSupported(const pcsc_cpp::SmartCard& card)
{
for (const auto& aid_eid_pair : SUPPORTED_AIDS) {
const pcsc_cpp::CommandApdu SELECT_AID_HEADER {0x00, 0xA4, 0x04, 0x00};
const auto select_aid = pcsc_cpp::CommandApdu {SELECT_AID_HEADER, aid_eid_pair.first};

pcsc_cpp::ResponseApdu response;
response = card.transmit(select_aid);

if (response.isOK()) {
return true;
}
}

return false;
}

ElectronicID::ptr getElectronicIDbyATR(const pcsc_cpp::Reader& reader)
{
try {
const auto& eidConstructor = SUPPORTED_ATRS.at(reader.cardAtr);
return eidConstructor(reader.connectToCard());
} catch (const std::out_of_range&) {
// It should be verified that the card is supported with isCardSupported() before
// calling getElectronicID(), so it is a programming error if out_of_range occurs here.
// It should be verified that the card is supported with isCardATRSupported() before
// calling getElectronicIDbyATR(), so it is a programming error if out_of_range occurs here.
THROW(ProgrammingError,
"Card with ATR '" + byteVectorToHexString(reader.cardAtr) + "' is not supported");
}
}

ElectronicID::ptr getElectronicIDbyAID(const byte_vector& aid, pcsc_cpp::SmartCard::ptr card)
{
try {
const auto& eidConstructor = SUPPORTED_AIDS.at(aid);
return eidConstructor(std::move(card));
} catch (const std::out_of_range&) {
// It should be verified that the card is supported with isCardAIDSupported() before
// calling getElectronicIDbyAID(), so it is a programming error if out_of_range occurs here.
THROW(ProgrammingError,
"Card with AID '" + byteVectorToHexString(aid) + "' is not supported");
}
}

bool ElectronicID::isSupportedSigningHashAlgorithm(const HashAlgorithm hashAlgo) const
{
auto supported = supportedSigningAlgorithms();
Expand Down
2 changes: 1 addition & 1 deletion src/electronic-ids/pkcs11/Pkcs11ElectronicID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ std::string belgianPkcs11ModulePath()
const std::map<electronic_id::Pkcs11ElectronicIDType, electronic_id::Pkcs11ElectronicIDModule>
SUPPORTED_PKCS11_MODULES = {
// EstEIDIDEMIAV1 configuration is here only for testing,
// it is not enabled in getElectronicID().
// it is not enabled in getElectronicIDbyATR().
{electronic_id::Pkcs11ElectronicIDType::EstEIDIDEMIAV1,
{
"EstEID IDEMIA v1 (PKCS#11)"s, // name
Expand Down