Skip to content

Commit 22bc69f

Browse files
alexandre-rcdevsmrts
authored andcommitted
Add lux cards support
fix syntax fix atr not exist in scope Add masked cards map Format code enhance support mask
1 parent 7991e0e commit 22bc69f

File tree

4 files changed

+189
-9
lines changed

4 files changed

+189
-9
lines changed

include/electronic-id/electronic-id.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class ElectronicID
4747
HrvEID,
4848
BelEID,
4949
CzeEID,
50+
LuxtrustV2,
51+
LuxEID,
5052
#ifdef _WIN32
5153
MsCryptoApiEID,
5254
#endif

src/electronic-id.cpp

Lines changed: 143 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,118 @@ const std::map<byte_vector, ElectronicIDConstructor> SUPPORTED_ATRS {
110110
{{0x3b, 0x7e, 0x94, 0x00, 0x00, 0x80, 0x25, 0xd2, 0x03, 0x10, 0x01, 0x00, 0x56, 0x00, 0x00,
111111
0x00, 0x02, 0x02, 0x00},
112112
constructor<ElectronicID::Type::CzeEID>},
113+
// LuxtrustV2
114+
{{0x3B, 0x7D, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x83,
115+
0x00, 0x90, 0x00},
116+
constructor<ElectronicID::Type::LuxtrustV2>},
117+
// LuxEID
118+
{{0x3B, 0x7F, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xB0,
119+
0x00, 0x03, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00},
120+
constructor<ElectronicID::Type::LuxEID>},
121+
// LuxEID
122+
{{0x3B, 0xFF, 0x00, 0x00, 0x00, 0x81, 0x31, 0x00, 0x43, 0x80, 0x31, 0x80, 0x65,
123+
0xB0, 0x00, 0x03, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00},
124+
constructor<ElectronicID::Type::LuxEID>},
125+
// LuxEID
126+
{{0x3B, 0x8F, 0x00, 0x01, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00,
127+
0x03, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00},
128+
constructor<ElectronicID::Type::LuxEID>},
129+
// LuxEID
130+
{{0x3B, 0x88, 0x00, 0x01, 0xE1, 0xF3, 0x5E, 0x11, 0x00, 0x87, 0x95, 0x00, 0x00},
131+
constructor<ElectronicID::Type::LuxEID>},
132+
// LuxEID
133+
{{0x3b, 0x7f, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xb0,
134+
0x00, 0x04, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00},
135+
constructor<ElectronicID::Type::LuxEID>},
136+
// LuxEID
137+
{{0x3b, 0xff, 0x00, 0x00, 0x00, 0x81, 0x31, 0x00, 0x43, 0x80, 0x31, 0x80, 0x65,
138+
0xb0, 0x00, 0x04, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00, 0x00},
139+
constructor<ElectronicID::Type::LuxEID>},
140+
// LuxEID
141+
{{0x3B, 0x8F, 0x80, 0x01, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00,
142+
0x04, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00},
143+
constructor<ElectronicID::Type::LuxEID>},
144+
// LuxEID
145+
{{0x3b, 0x88, 0x80, 0x01, 0x00, 0x88, 0x3c, 0x1f, 0x77, 0x81, 0x95, 0x00, 0xc1},
146+
constructor<ElectronicID::Type::LuxEID>},
147+
// LuxEID
148+
{{0x3b, 0x7f, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xb0,
149+
0x00, 0x05, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00},
150+
constructor<ElectronicID::Type::LuxEID>},
151+
// LuxEID
152+
{{0x3b, 0xff, 0x00, 0x00, 0x00, 0x81, 0x31, 0x00, 0x43, 0x80, 0x31, 0x80, 0x65,
153+
0xb0, 0x00, 0x05, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00, 0x00},
154+
constructor<ElectronicID::Type::LuxEID>},
155+
// LuxEID
156+
{{0x3B, 0x8F, 0x80, 0x01, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00,
157+
0x05, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00},
158+
constructor<ElectronicID::Type::LuxEID>},
159+
// LuxEID
160+
{{0x3b, 0x88, 0x80, 0x01, 0xe1, 0xf3, 0x5e, 0x11, 0x77, 0xa1, 0x97, 0x00, 0x15},
161+
constructor<ElectronicID::Type::LuxEID>},
162+
};
163+
164+
// Masked cards.
165+
const std::map<byte_vector, byte_vector> MASKED_ATRS {
166+
// LuxtrustV2
167+
{{0x3B, 0x7D, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x83,
168+
0x00, 0x90, 0x00},
169+
{0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF,
170+
0x00, 0xFF, 0xFF}},
171+
// LuxEID
172+
{{0x3B, 0x7F, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xB0,
173+
0x00, 0x03, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00},
174+
{0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
175+
0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
176+
// LuxEID
177+
{{0x3B, 0xFF, 0x00, 0x00, 0x00, 0x81, 0x31, 0x00, 0x43, 0x80, 0x31, 0x80, 0x65,
178+
0xB0, 0x00, 0x03, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00},
179+
{0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
180+
0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
181+
// LuxEID
182+
{{0x3B, 0x8F, 0x00, 0x01, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00,
183+
0x03, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00},
184+
{0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
185+
0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
186+
// LuxEID
187+
{{0x3B, 0x88, 0x00, 0x01, 0xE1, 0xF3, 0x5E, 0x11, 0x00, 0x87, 0x95, 0x00, 0x00},
188+
{0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00}},
189+
// LuxEID
190+
{{0x3b, 0x7f, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xb0,
191+
0x00, 0x04, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00},
192+
{0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
193+
0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
194+
// LuxEID
195+
{{0x3b, 0xff, 0x00, 0x00, 0x00, 0x81, 0x31, 0x00, 0x43, 0x80, 0x31, 0x80, 0x65,
196+
0xb0, 0x00, 0x04, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00, 0x00},
197+
{0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
198+
0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
199+
// LuxEID
200+
{{0x3B, 0x8F, 0x80, 0x01, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00,
201+
0x04, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00},
202+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
203+
0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
204+
// LuxEID
205+
{{0x3b, 0x88, 0x80, 0x01, 0x00, 0x88, 0x3c, 0x1f, 0x77, 0x81, 0x95, 0x00, 0xc1},
206+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
207+
// LuxEID
208+
{{0x3b, 0x7f, 0x00, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65, 0xb0,
209+
0x00, 0x05, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00},
210+
{0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
211+
0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
212+
// LuxEID
213+
{{0x3b, 0xff, 0x00, 0x00, 0x00, 0x81, 0x31, 0x00, 0x43, 0x80, 0x31, 0x80, 0x65,
214+
0xb0, 0x00, 0x05, 0x00, 0x00, 0x12, 0x0f, 0xff, 0x82, 0x90, 0x00, 0x00},
215+
{0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
216+
0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
217+
// LuxEID
218+
{{0x3B, 0x8F, 0x80, 0x01, 0x80, 0x31, 0x80, 0x65, 0xB0, 0x00,
219+
0x05, 0x00, 0x00, 0x12, 0x0F, 0xFF, 0x82, 0x90, 0x00, 0x00},
220+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
221+
0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}},
222+
// LuxEID
223+
{{0x3b, 0x88, 0x80, 0x01, 0xe1, 0xf3, 0x5e, 0x11, 0x77, 0xa1, 0x97, 0x00, 0x15},
224+
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}},
113225
};
114226

115227
inline std::string byteVectorToHexString(const byte_vector& bytes)
@@ -137,22 +249,46 @@ const auto SUPPORTED_ALGORITHMS = std::map<std::string, HashAlgorithm> {
137249
namespace electronic_id
138250
{
139251

252+
pcsc_cpp::byte_vector applyMask(const pcsc_cpp::byte_vector& atr, const pcsc_cpp::byte_vector& mask)
253+
{
254+
pcsc_cpp::byte_vector result(atr.size());
255+
for (size_t i = 0; i < atr.size(); ++i) {
256+
result[i] = atr[i] & mask[i];
257+
}
258+
return result;
259+
}
260+
140261
bool isCardSupported(const pcsc_cpp::byte_vector& atr)
141262
{
142-
return SUPPORTED_ATRS.count(atr);
263+
if (SUPPORTED_ATRS.count(atr)) {
264+
return true;
265+
}
266+
for (const auto& [maskedAtr, mask] : MASKED_ATRS) {
267+
if (applyMask(atr, mask) == maskedAtr) {
268+
return SUPPORTED_ATRS.count(maskedAtr);
269+
}
270+
}
271+
return false;
143272
}
144273

145274
ElectronicID::ptr getElectronicID(const pcsc_cpp::Reader& reader)
146275
{
147-
try {
276+
if (SUPPORTED_ATRS.count(reader.cardAtr)) {
148277
const auto& eidConstructor = SUPPORTED_ATRS.at(reader.cardAtr);
149278
return eidConstructor(reader);
150-
} catch (const std::out_of_range&) {
151-
// It should be verified that the card is supported with isCardSupported() before
152-
// calling getElectronicID(), so it is a programming error if out_of_range occurs here.
153-
THROW(ProgrammingError,
154-
"Card with ATR '" + byteVectorToHexString(reader.cardAtr) + "' is not supported");
155279
}
280+
281+
for (const auto& [maskedAtr, mask] : MASKED_ATRS) {
282+
if (applyMask(reader.cardAtr, mask) == maskedAtr && SUPPORTED_ATRS.count(maskedAtr)) {
283+
const auto& eidConstructor = SUPPORTED_ATRS.at(maskedAtr);
284+
return eidConstructor(reader);
285+
}
286+
}
287+
288+
// It should be verified that the card is supported with isCardSupported() before
289+
// calling getElectronicID(), so it is a programming error if out_of_range occurs here.
290+
THROW(ProgrammingError,
291+
"Card with ATR '" + byteVectorToHexString(reader.cardAtr) + "' is not supported");
156292
}
157293

158294
bool ElectronicID::isSupportedSigningHashAlgorithm(const HashAlgorithm hashAlgo) const

src/electronic-ids/pkcs11/Pkcs11ElectronicID.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,18 @@ inline fs::path czechPkcs11ModulePath()
103103
#endif
104104
}
105105

106+
inline fs::path luxembourgPkcs11ModulePath()
107+
{
108+
#ifdef _WIN32
109+
return programFilesPath() / L"Gemalto/Classic Client/BIN/gclib.dll";
110+
#elif defined __APPLE__
111+
return "/Library/Frameworks/Pkcs11ClassicClient.framework/Versions/A/Pkcs11ClassicClient/"
112+
"libgclib.dylib";
113+
#else // Linux
114+
return "/usr/lib/pkcs11/libgclib.so";
115+
#endif
116+
}
117+
106118
const std::map<ElectronicID::Type, Pkcs11ElectronicIDModule> SUPPORTED_PKCS11_MODULES {
107119
// EstEID configuration is here only for testing,
108120
// it is not enabled in getElectronicID().
@@ -156,6 +168,26 @@ const std::map<ElectronicID::Type, Pkcs11ElectronicIDModule> SUPPORTED_PKCS11_MO
156168
true,
157169
false,
158170
}},
171+
{ElectronicID::Type::LuxtrustV2,
172+
{
173+
"LuxtrustV2 eID (PKCS#11)"s, // name
174+
ElectronicID::Type::LuxtrustV2, // type
175+
luxembourgPkcs11ModulePath().make_preferred(), // path
176+
177+
3,
178+
true,
179+
false,
180+
}},
181+
{ElectronicID::Type::LuxEID,
182+
{
183+
"Luxembourg eID (PKCS#11)"s, // name
184+
ElectronicID::Type::LuxEID, // type
185+
luxembourgPkcs11ModulePath().make_preferred(), // path
186+
187+
3,
188+
true,
189+
true,
190+
}},
159191
};
160192

161193
const Pkcs11ElectronicIDModule& getModule(ElectronicID::Type eidType)
@@ -176,11 +208,14 @@ Pkcs11ElectronicID::Pkcs11ElectronicID(ElectronicID::Type type) :
176208
{
177209
REQUIRE_NON_NULL(manager)
178210

211+
const bool checkExtKeyUsage =
212+
(type != ElectronicID::Type::LuxtrustV2 && type != ElectronicID::Type::LuxEID);
213+
179214
bool seenAuthToken = false;
180215
bool seenSigningToken = false;
181216

182217
for (const auto& token : manager->tokens()) {
183-
const auto certType = certificateType(token.cert);
218+
const auto certType = certificateType(token.cert, checkExtKeyUsage);
184219
if (certType.isAuthentication()) {
185220
authToken = token;
186221
seenAuthToken = true;

src/electronic-ids/x509.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <openssl/x509v3.h>
99
#include <openssl/err.h>
1010

11+
#include <optional>
12+
1113
namespace electronic_id
1214
{
1315

@@ -37,7 +39,8 @@ inline bool hasClientAuthExtendedKeyUsage(EXTENDED_KEY_USAGE* usage) noexcept
3739
return false;
3840
}
3941

40-
inline CertificateType certificateType(const pcsc_cpp::byte_vector& cert)
42+
inline CertificateType certificateType(const pcsc_cpp::byte_vector& cert,
43+
const bool checkExtKeyUsage = true)
4144
{
4245
auto x509 = make_x509(cert);
4346
auto keyUsage = extension(x509.get(), NID_key_usage, ASN1_BIT_STRING_free);
@@ -52,6 +55,10 @@ inline CertificateType certificateType(const pcsc_cpp::byte_vector& cert)
5255

5356
static const int KEY_USAGE_DIGITAL_SIGNATURE = 0;
5457
if (ASN1_BIT_STRING_get_bit(keyUsage.get(), KEY_USAGE_DIGITAL_SIGNATURE)) {
58+
if (!checkExtKeyUsage) {
59+
return CertificateType::AUTHENTICATION;
60+
}
61+
5562
if (auto extKeyUsage = extension(x509.get(), NID_ext_key_usage, EXTENDED_KEY_USAGE_free);
5663
extKeyUsage && hasClientAuthExtendedKeyUsage(extKeyUsage.get())) {
5764
return CertificateType::AUTHENTICATION;

0 commit comments

Comments
 (0)