diff --git a/CMakeLists.txt b/CMakeLists.txt index eb14cd3..98918a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,8 @@ add_executable(${MOCK_TEST_EXE} tests/mock/select-certificate-script-LAT-V1.hpp tests/mock/select-certificate-script-LAT-V2.hpp tests/mock/test-autoselect-card.cpp + tests/mock/test-find-masked-atr.cpp + tests/mock/test-is-card-supported.cpp tests/mock/test-get-certificate.cpp tests/mock/test-pkcs11-token.cpp ) diff --git a/include/electronic-id/electronic-id.hpp b/include/electronic-id/electronic-id.hpp index d0affd2..9a745cc 100644 --- a/include/electronic-id/electronic-id.hpp +++ b/include/electronic-id/electronic-id.hpp @@ -24,6 +24,9 @@ #include "enums.hpp" +#include +#include + namespace electronic_id { @@ -47,6 +50,8 @@ class ElectronicID HrvEID, BelEID, CzeEID, + LuxtrustV2, + LuxEID, #ifdef _WIN32 MsCryptoApiEID, #endif @@ -101,6 +106,10 @@ class ElectronicID pcsc_cpp::SmartCard::ptr card; }; +using ElectronicIDConstructor = std::function; + +std::optional findMaskedATR(const pcsc_cpp::byte_vector& atr); + bool isCardSupported(const pcsc_cpp::byte_vector& atr); ElectronicID::ptr getElectronicID(const pcsc_cpp::Reader& reader); @@ -178,6 +187,12 @@ class Pkcs11Error : public Error using Error::Error; }; +/** The PKCS#11 library and/or slot does not recognize the token in the slot. */ +class Pkcs11TokenNotRecognized : public Pkcs11Error +{ + using Pkcs11Error::Pkcs11Error; +}; + /** Smart card was not present in its slot at the time that a PKCS#11 function was invoked. */ class Pkcs11TokenNotPresent : public Error { diff --git a/src/electronic-id.cpp b/src/electronic-id.cpp index 90c2a9a..5bb65fb 100644 --- a/src/electronic-id.cpp +++ b/src/electronic-id.cpp @@ -41,8 +41,6 @@ using namespace std::string_literals; namespace { -using ElectronicIDConstructor = std::function; - template constexpr auto constructor(const Reader& reader) { @@ -94,9 +92,6 @@ const std::map SUPPORTED_ATRS { 0x04, 0x44, 0xec, 0xc1, 0x73, 0x94, 0x01, 0x80, 0x82, 0x90, 0x00, 0x12}, constructor}, // BelEID - {{0x3b, 0x98, 0x13, 0x40, 0x0a, 0xa5, 0x03, 0x01, 0x01, 0x01, 0xad, 0x13, 0x11}, - constructor}, - // BelEID {{0x3B, 0x98, 0x94, 0x40, 0x0A, 0xA5, 0x03, 0x01, 0x01, 0x01, 0xAD, 0x13, 0x10}, constructor}, // BelEID @@ -112,7 +107,113 @@ const std::map SUPPORTED_ATRS { constructor}, }; -inline std::string byteVectorToHexString(const byte_vector& bytes) +// Holds ATR pattern, mask, and constructor for variable ATR cards. +struct MaskedATREntry +{ + // Single template parameter enforces equal size pattern and mask arrays at compile time. + template + constexpr MaskedATREntry(const byte_type (&_pat)[N], const byte_type (&_mask)[N], + ElectronicIDConstructor&& _constructor) : + pattern(std::begin(_pat), std::end(_pat)), mask(std::begin(_mask), std::end(_mask)), + constructor(std::move(_constructor)) + { + } + + bool operator==(const byte_vector& atr) const + { + return std::equal(atr.cbegin(), atr.cend(), pattern.cbegin(), pattern.cend(), + [mask_ptr = mask.data()](byte_type a, byte_type p) mutable { + bool result = (a & *mask_ptr) == (p & *mask_ptr); + ++mask_ptr; + return result; + }); + } + + byte_vector pattern; + byte_vector mask; + ElectronicIDConstructor constructor; +}; + +const std::vector MASKED_ATRS = { + // BelEID v1.7 + {{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}, + // LuxtrustV2 + {{0x3B, 0x7D, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x83, + 0x00, 0x90, 0x00}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0xFF, 0xFF}, + constructor}, + // LuxEID + {{0x3B, 0x7F, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xB0, + 0x00, 0x03, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + constructor}, + // LuxEID + {{0x3B, 0xFF, 0x00, 0x00, 0x00, 0x81, 0x31, 0x00, 0x43, 0x80, 0x31, 0x80, 0x65, + 0xB0, 0x00, 0x03, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, + constructor}, + // LuxEID + {{0x3B, 0x8F, 0x00, 0x01, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00, + 0x03, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, + constructor}, + // LuxEID + {{0x3B, 0x88, 0x00, 0x01, 0xE1, 0xF3, 0x5E, 0x11, 0x00, 0x87, 0x95, 0x00, 0x00}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00}, + constructor}, + // LuxEID + {{0x3b, 0x7f, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xb0, + 0x00, 0x04, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + constructor}, + // LuxEID + {{0x3b, 0xff, 0x00, 0x00, 0x00, 0x81, 0x31, 0x00, 0x43, 0x80, 0x31, 0x80, 0x65, + 0xb0, 0x00, 0x04, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00, 0x00}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, + constructor}, + // LuxEID + {{0x3B, 0x8F, 0x80, 0x01, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00, + 0x04, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, + constructor}, + // LuxEID + {{0x3b, 0x88, 0x80, 0x01, 0x00, 0x88, 0x3c, 0x1f, 0x77, 0x81, 0x95, 0x00, 0xc1}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + constructor}, + // LuxEID + {{0x3b, 0x7f, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xb0, + 0x00, 0x05, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + constructor}, + // LuxEID + {{0x3b, 0xff, 0x00, 0x00, 0x00, 0x81, 0x31, 0x00, 0x43, 0x80, 0x31, 0x80, 0x65, + 0xb0, 0x00, 0x05, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00, 0x00}, + {0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, + constructor}, + // LuxEID + {{0x3B, 0x8F, 0x80, 0x01, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00, + 0x05, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, + constructor}, + // LuxEID + {{0x3b, 0x88, 0x80, 0x01, 0xe1, 0xf3, 0x5e, 0x11, 0x77, 0xa1, 0x97, 0x00, 0x15}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + constructor}, +}; + +std::string byteVectorToHexString(const byte_vector& bytes) { std::ostringstream hexStringBuilder; @@ -137,22 +238,40 @@ const auto SUPPORTED_ALGORITHMS = std::map { namespace electronic_id { +std::optional findMaskedATR(const byte_vector& atr) +{ + if (auto i = std::find(MASKED_ATRS.cbegin(), MASKED_ATRS.cend(), atr); + i != MASKED_ATRS.cend()) { + return i->constructor; + } + return std::nullopt; +} + bool isCardSupported(const pcsc_cpp::byte_vector& atr) { - return SUPPORTED_ATRS.contains(atr); + if (SUPPORTED_ATRS.contains(atr)) { + return true; + } + + // If exact ATR match is not found, fall back to masked ATR lookup. + return findMaskedATR(atr).has_value(); } ElectronicID::ptr getElectronicID(const pcsc_cpp::Reader& reader) { - try { - const auto& eidConstructor = SUPPORTED_ATRS.at(reader.cardAtr); - return eidConstructor(reader); - } 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. - THROW(ProgrammingError, - "Card with ATR '" + byteVectorToHexString(reader.cardAtr) + "' is not supported"); + if (auto it = SUPPORTED_ATRS.find(reader.cardAtr); it != SUPPORTED_ATRS.end()) { + return it->second(reader); } + + // If exact ATR match is not found, fall back to masked ATR lookup. + if (auto eIDConstructor = findMaskedATR(reader.cardAtr)) { + return (*eIDConstructor)(reader); + } + + // It should be verified that the card is supported with isCardSupported() before + // calling getElectronicID(), so it is a programming error to reach this point. + THROW(ProgrammingError, + "Card with ATR '" + byteVectorToHexString(reader.cardAtr) + "' is not supported"); } bool ElectronicID::isSupportedSigningHashAlgorithm(const HashAlgorithm hashAlgo) const diff --git a/src/electronic-ids/pkcs11/PKCS11CardManager.hpp b/src/electronic-ids/pkcs11/PKCS11CardManager.hpp index 3117b83..aadc60f 100644 --- a/src/electronic-ids/pkcs11/PKCS11CardManager.hpp +++ b/src/electronic-ids/pkcs11/PKCS11CardManager.hpp @@ -153,6 +153,7 @@ class PKCS11CardManager try { C(GetTokenInfo, slotID, &tokenInfo); } catch (const Pkcs11Error&) { + // TODO: log a warning with the exception message. continue; } CK_SESSION_HANDLE session = 0; @@ -301,7 +302,7 @@ class PKCS11CardManager case CKR_PIN_LOCKED: throw VerifyPinFailed(VerifyPinFailed::Status::PIN_BLOCKED); case CKR_TOKEN_NOT_RECOGNIZED: - THROW_WITH_CALLER_INFO(SmartCardChangeRequiredError, + THROW_WITH_CALLER_INFO(Pkcs11TokenNotRecognized, std::string(apiFunction) + ": token not recognized", file, line, function); case CKR_TOKEN_NOT_PRESENT: diff --git a/src/electronic-ids/pkcs11/Pkcs11ElectronicID.cpp b/src/electronic-ids/pkcs11/Pkcs11ElectronicID.cpp index 62874a2..a30d4d4 100644 --- a/src/electronic-ids/pkcs11/Pkcs11ElectronicID.cpp +++ b/src/electronic-ids/pkcs11/Pkcs11ElectronicID.cpp @@ -72,11 +72,26 @@ inline fs::path lithuanianPKCS11ModulePath() inline fs::path croatianPkcs11ModulePath() { #ifdef _WIN32 - return programFilesPath() / L"AKD/eID Middleware/pkcs11/AkdEidPkcs11_64.dll"; + fs::path certiliaPath = + programFilesPath() / L"AKD/Certilia Middleware/pkcs11/AkdEidPkcs11_64.dll"; + fs::path eidPath = programFilesPath() / L"AKD/eID Middleware/pkcs11/AkdEidPkcs11_64.dll"; + return fs::exists(certiliaPath) ? certiliaPath : eidPath; #elif defined __APPLE__ - return "/Library/AKD/eID Middleware/pkcs11/libEidPkcs11.so"; // NB! Not tested. + // The driver provider installs the library to /usr/local/lib/pkcs11, but + // sandboxed applications cannot access /usr/local/ due to macOS restrictions. + // To make the solution work, the library libEidPkcs11.dylib and License.bin must be + // copied to /Library/AKD/pkcs11, which is accessible in sandboxed environments: + // + // sudo mkdir -p /Library/AKD/pkcs11 + // sudo cp -a /usr/local/lib/pkcs11/{libEidPkcs11.dylib,License.bin} /Library/AKD/pkcs11/ + // + // This workaround is required until the driver provider addresses the issue. + // NB! This is not tested. + return "/Library/AKD/pkcs11/libEidPkcs11.dylib"; #else // Linux - return "/usr/lib/akd/eidmiddleware/pkcs11/libEidPkcs11.so"; + fs::path certiliaPath = "/usr/lib/akd/certiliamiddleware/pkcs11/libEidPkcs11.so"; + fs::path eidPath = "/usr/lib/akd/eidmiddleware/pkcs11/libEidPkcs11.so"; + return fs::exists(certiliaPath) ? certiliaPath : eidPath; #endif } @@ -103,6 +118,18 @@ inline fs::path czechPkcs11ModulePath() #endif } +inline fs::path luxembourgPkcs11ModulePath() +{ +#ifdef _WIN32 + return programFilesPath() / L"Gemalto/Classic Client/BIN/gclib.dll"; +#elif defined __APPLE__ + return "/Library/Frameworks/Pkcs11ClassicClient.framework/Versions/A/Pkcs11ClassicClient/" + "libgclib.dylib"; +#else // Linux + return "/usr/lib/pkcs11/libgclib.so"; +#endif +} + const std::map SUPPORTED_PKCS11_MODULES { // EstEID configuration is here only for testing, // it is not enabled in getElectronicID(). @@ -156,6 +183,26 @@ const std::map SUPPORTED_PKCS11_MO true, false, }}, + {ElectronicID::Type::LuxtrustV2, + { + "LuxtrustV2 eID (PKCS#11)"s, // name + ElectronicID::Type::LuxtrustV2, // type + luxembourgPkcs11ModulePath().make_preferred(), // path + + 3, + true, + false, + }}, + {ElectronicID::Type::LuxEID, + { + "Luxembourg eID (PKCS#11)"s, // name + ElectronicID::Type::LuxEID, // type + luxembourgPkcs11ModulePath().make_preferred(), // path + + 3, + true, + true, + }}, }; const Pkcs11ElectronicIDModule& getModule(ElectronicID::Type eidType) diff --git a/src/electronic-ids/x509.hpp b/src/electronic-ids/x509.hpp index 9d04b6d..79e8fd0 100644 --- a/src/electronic-ids/x509.hpp +++ b/src/electronic-ids/x509.hpp @@ -52,10 +52,14 @@ inline CertificateType certificateType(const pcsc_cpp::byte_vector& cert) static const int KEY_USAGE_DIGITAL_SIGNATURE = 0; if (ASN1_BIT_STRING_get_bit(keyUsage.get(), KEY_USAGE_DIGITAL_SIGNATURE)) { - if (auto extKeyUsage = extension(x509.get(), NID_ext_key_usage, EXTENDED_KEY_USAGE_free); - extKeyUsage && hasClientAuthExtendedKeyUsage(extKeyUsage.get())) { - return CertificateType::AUTHENTICATION; + if (auto extKeyUsage = extension(x509.get(), NID_ext_key_usage, EXTENDED_KEY_USAGE_free)) { + return hasClientAuthExtendedKeyUsage(extKeyUsage.get()) + ? CertificateType::AUTHENTICATION + : CertificateType::NONE; } + // Digital Signature extension present, but Extended Key Usage extension not present, + // assume it is an authentication certificate (e.g. Luxembourg eID). + return CertificateType::AUTHENTICATION; } return CertificateType::NONE; diff --git a/tests/mock/test-find-masked-atr.cpp b/tests/mock/test-find-masked-atr.cpp new file mode 100644 index 0000000..e949e5e --- /dev/null +++ b/tests/mock/test-find-masked-atr.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020-2024 Estonian Information System Authority + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "electronic-id/electronic-id.hpp" + +#include + +using namespace electronic_id; + +const pcsc_cpp::byte_vector BEL_EID_V1_7_ATR {0x3b, 0x98, 0x13, 0x40, 0x0a, 0xa5, 0x03, + 0x01, 0x01, 0x01, 0xad, 0x13, 0x11}; +const pcsc_cpp::byte_vector INVALID_ATR {0xaa, 0xbb, 0xcc, 0x40, 0x0a, 0xa5, 0x03, + 0x01, 0x01, 0x01, 0xad, 0x13, 0x11}; + +TEST(electronic_id_test, findMaskedATRSuccessWithSupportedMaskedATR) +{ + EXPECT_TRUE(findMaskedATR(BEL_EID_V1_7_ATR).has_value()); +} + +TEST(electronic_id_test, findMaskedATRFailureWithUnSupportedATR) +{ + EXPECT_FALSE(findMaskedATR(INVALID_ATR).has_value()); +} + +TEST(electronic_id_test, isCardSupportedSuccessWithSupportedMaskedATR) +{ + EXPECT_TRUE(isCardSupported(BEL_EID_V1_7_ATR)); +} diff --git a/tests/mock/test-is-card-supported.cpp b/tests/mock/test-is-card-supported.cpp new file mode 100644 index 0000000..b1da7b7 --- /dev/null +++ b/tests/mock/test-is-card-supported.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020-2024 Estonian Information System Authority + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "electronic-id/electronic-id.hpp" + +#include + +using namespace electronic_id; + +const pcsc_cpp::byte_vector EstEIDIDEMIAV1_ATR {0x3b, 0xdb, 0x96, 0x00, 0x80, 0xb1, 0xfe, 0x45, + 0x1f, 0x83, 0x00, 0x12, 0x23, 0x3f, 0x53, 0x65, + 0x49, 0x44, 0x0f, 0x90, 0x00, 0xf1}; +const pcsc_cpp::byte_vector INVALID_ATR {0xaa, 0xbb, 0xcc, 0x40, 0x0a, 0xa5, 0x03, + 0x01, 0x01, 0x01, 0xad, 0x13, 0x11}; + +TEST(electronic_id_test, isCardSupportedSuccessWithSupportedATR) +{ + EXPECT_TRUE(isCardSupported(EstEIDIDEMIAV1_ATR)); +} + +TEST(electronic_id_test, isCardSupportedFailureWithUnsupportedATR) +{ + EXPECT_FALSE(isCardSupported(INVALID_ATR)); +} diff --git a/tests/mock/test-pkcs11-token.cpp b/tests/mock/test-pkcs11-token.cpp index 503d154..bd012ed 100644 --- a/tests/mock/test-pkcs11-token.cpp +++ b/tests/mock/test-pkcs11-token.cpp @@ -88,6 +88,7 @@ TEST(electronic_id_test, pkcs11TokenHasAuthenticationCert) PKCS11CardManager::Token token; token.cert = base64Decode(AUTH_CERT); EXPECT_TRUE(certificateType(token.cert).isAuthentication()); + EXPECT_FALSE(certificateType(token.cert).isSigning()); } TEST(electronic_id_test, pkcs11TokenHasSigningCert) @@ -95,4 +96,5 @@ TEST(electronic_id_test, pkcs11TokenHasSigningCert) PKCS11CardManager::Token token; token.cert = base64Decode(SIGNING_CERT); EXPECT_FALSE(certificateType(token.cert).isAuthentication()); + EXPECT_TRUE(certificateType(token.cert).isSigning()); }