Skip to content

Commit e7490d0

Browse files
metsmamrts
authored andcommitted
Return PIN locked info
WE2-1114 Signed-off-by: Raul Metsma <[email protected]>
1 parent dfb29b8 commit e7490d0

File tree

16 files changed

+106
-94
lines changed

16 files changed

+106
-94
lines changed

.github/vcpkg.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "web-eid-app",
3+
"dependencies": ["openssl", "gtest"],
4+
"builtin-baseline": "bc38a15b0bee8bc48a49ea267cc32fbb49aedfc4"
5+
}

.github/workflows/cmake-windows.yml

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ on: [push, pull_request]
55
env:
66
BUILD_TYPE: RelWithDebInfo
77
CMAKE_BUILD_PARALLEL_LEVEL: 3
8+
VCPKG_MANIFEST_DIR: .github
9+
VCPKG_INSTALLED_DIR: ${{ github.workspace }}/build/vcpkg_installed
810

911
jobs:
1012
build:
@@ -14,15 +16,25 @@ jobs:
1416
- name: Checkout code
1517
uses: actions/checkout@v4
1618

19+
- name: Cache vcpkg
20+
uses: actions/cache@v4
21+
with:
22+
path: ${{ github.workspace }}/vcpkg_cache
23+
key: vcpkg-${{ hashFiles(format('{0}/vcpkg.json', env.VCPKG_MANIFEST_DIR)) }}
24+
1725
- name: Prepare vcpkg and libraries
18-
uses: lukka/run-vcpkg@v7
26+
uses: lukka/run-vcpkg@v11
1927
with:
20-
vcpkgArguments: gtest:x64-windows openssl:x64-windows
21-
vcpkgTriplet: x64-windows
22-
vcpkgGitCommitId: 031ad89ce6c575df35a8e58707ad2c898446c63e
28+
vcpkgJsonGlob: ${{ env.VCPKG_MANIFEST_DIR }}/vcpkg.json
29+
runVcpkgInstall: true
30+
env:
31+
VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/vcpkg_cache,readwrite
2332

2433
- name: Configure CMake
25-
run: cmake -A x64 "-DCMAKE_TOOLCHAIN_FILE=${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" "-DCMAKE_BUILD_TYPE=${env:BUILD_TYPE}" -S . -B build
34+
run: |
35+
cmake -A x64 -S . -B build "-DCMAKE_BUILD_TYPE=${env:BUILD_TYPE}" `
36+
"-DCMAKE_TOOLCHAIN_FILE=${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" `
37+
"-DVCPKG_MANIFEST_DIR=${{ env.VCPKG_MANIFEST_DIR }}"
2638
2739
- name: Build
2840
run: cmake --build build --config ${env:BUILD_TYPE}

include/electronic-id/electronic-id.hpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424

2525
#include "enums.hpp"
2626

27-
#include <optional>
2827
#include <functional>
28+
#include <optional>
2929

3030
namespace electronic_id
3131
{
@@ -37,11 +37,17 @@ class ElectronicID
3737
public:
3838
using ptr = std::shared_ptr<ElectronicID>;
3939
using PinMinMaxLength = std::pair<uint8_t, uint8_t>;
40-
using PinRetriesRemainingAndMax = std::pair<uint8_t, int8_t>;
4140
using byte_vector = pcsc_cpp::byte_vector;
4241
using byte_type = pcsc_cpp::byte_type;
4342
using Signature = std::pair<byte_vector, SignatureAlgorithm>;
4443

44+
struct PinInfo
45+
{
46+
uint8_t retryCount;
47+
int8_t maxRetry;
48+
bool pinActive;
49+
};
50+
4551
enum Type : uint8_t {
4652
EstEID,
4753
FinEID,
@@ -68,7 +74,7 @@ class ElectronicID
6874

6975
virtual PinMinMaxLength authPinMinMaxLength() const = 0;
7076

71-
virtual PinRetriesRemainingAndMax authPinRetriesLeft() const = 0;
77+
virtual PinInfo authPinInfo() const = 0;
7278

7379
virtual pcsc_cpp::byte_vector signWithAuthKey(byte_vector&& pin,
7480
const byte_vector& hash) const = 0;
@@ -80,7 +86,7 @@ class ElectronicID
8086

8187
virtual PinMinMaxLength signingPinMinMaxLength() const = 0;
8288

83-
virtual PinRetriesRemainingAndMax signingPinRetriesLeft() const = 0;
89+
virtual PinInfo signingPinInfo() const = 0;
8490

8591
virtual Signature signWithSigningKey(byte_vector&& pin, const byte_vector& hash,
8692
const HashAlgorithm hashAlgo) const = 0;

src/electronic-ids/ms-cryptoapi/MsCryptoApiElectronicID.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ class MsCryptoApiElectronicID : public ElectronicID
7878
return {PIN_LENGTH_PLACEHOLDER, PIN_LENGTH_PLACEHOLDER};
7979
}
8080

81-
PinRetriesRemainingAndMax authPinRetriesLeft() const override
81+
PinInfo authPinInfo() const override
8282
{
83-
return {uint8_t(PIN_RETRY_COUNT_PLACEHOLDER), PIN_RETRY_COUNT_PLACEHOLDER};
83+
return {uint8_t(PIN_RETRY_COUNT_PLACEHOLDER), PIN_RETRY_COUNT_PLACEHOLDER, true};
8484
}
8585

8686
byte_vector signWithAuthKey(byte_vector&& pin, const byte_vector& hash) const override;
@@ -92,9 +92,9 @@ class MsCryptoApiElectronicID : public ElectronicID
9292
return {PIN_LENGTH_PLACEHOLDER, PIN_LENGTH_PLACEHOLDER};
9393
}
9494

95-
PinRetriesRemainingAndMax signingPinRetriesLeft() const override
95+
PinInfo signingPinInfo() const override
9696
{
97-
return {uint8_t(PIN_RETRY_COUNT_PLACEHOLDER), PIN_RETRY_COUNT_PLACEHOLDER};
97+
return {uint8_t(PIN_RETRY_COUNT_PLACEHOLDER), PIN_RETRY_COUNT_PLACEHOLDER, true};
9898
}
9999

100100
Signature signWithSigningKey(byte_vector&& pin, const byte_vector& hash,

src/electronic-ids/pcsc/EIDIDEMIA.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ byte_vector EIDIDEMIA::signWithAuthKeyImpl(const SmartCard::Session& session, by
107107
return std::move(response.data);
108108
}
109109

110-
ElectronicID::PinRetriesRemainingAndMax
111-
EIDIDEMIA::authPinRetriesLeftImpl(const SmartCard::Session& session) const
110+
ElectronicID::PinInfo EIDIDEMIA::authPinInfoImpl(const SmartCard::Session& session) const
112111
{
113112
selectMain(session);
114113
return pinRetriesLeft(session, AUTH_PIN_REFERENCE);
@@ -154,15 +153,14 @@ ElectronicID::Signature EIDIDEMIA::signWithSigningKeyImpl(const SmartCard::Sessi
154153
{isECC ? SignatureAlgorithm::ES : SignatureAlgorithm::RS, hashAlgo}};
155154
}
156155

157-
ElectronicID::PinRetriesRemainingAndMax
158-
EIDIDEMIA::signingPinRetriesLeftImpl(const SmartCard::Session& session) const
156+
ElectronicID::PinInfo EIDIDEMIA::signingPinInfoImpl(const SmartCard::Session& session) const
159157
{
160158
selectADF2(session);
161159
return pinRetriesLeft(session, SIGN_PIN_REFERENCE);
162160
}
163161

164-
ElectronicID::PinRetriesRemainingAndMax EIDIDEMIA::pinRetriesLeft(const SmartCard::Session& session,
165-
byte_type pinReference)
162+
ElectronicID::PinInfo EIDIDEMIA::pinRetriesLeft(const SmartCard::Session& session,
163+
byte_type pinReference)
166164
{
167165
auto ref = byte_type(pinReference & 0x0F);
168166
const CommandApdu GET_DATA_ODD {
@@ -175,7 +173,7 @@ ElectronicID::PinRetriesRemainingAndMax EIDIDEMIA::pinRetriesLeft(const SmartCar
175173
TLV max = info[0x9A];
176174
TLV tries = info[0x9B];
177175
if (max && tries) {
178-
return {*tries.begin, *max.begin};
176+
return {*tries.begin, int8_t(*max.begin), true};
179177
}
180178
THROW(SmartCardError, "Command GET DATA ODD failed: missing expected info");
181179
}

src/electronic-ids/pcsc/EIDIDEMIA.hpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,18 @@ class EIDIDEMIA : public PcscElectronicID
4242
byte_vector getCertificateImpl(const SmartCard::Session& session,
4343
const CertificateType type) const override;
4444

45-
PinRetriesRemainingAndMax
46-
authPinRetriesLeftImpl(const SmartCard::Session& session) const override;
45+
PinInfo authPinInfoImpl(const SmartCard::Session& session) const override;
4746
virtual KeyInfo authKeyRef(const SmartCard::Session& session) const;
4847
byte_vector signWithAuthKeyImpl(const SmartCard::Session& session, byte_vector&& pin,
4948
const byte_vector& hash) const override;
5049

51-
PinRetriesRemainingAndMax
52-
signingPinRetriesLeftImpl(const SmartCard::Session& session) const override;
50+
PinInfo signingPinInfoImpl(const SmartCard::Session& session) const override;
5351
virtual KeyInfo signKeyRef(const SmartCard::Session& session) const;
5452
Signature signWithSigningKeyImpl(const SmartCard::Session& session, byte_vector&& pin,
5553
const byte_vector& hash,
5654
const HashAlgorithm hashAlgo) const override;
5755

58-
static PinRetriesRemainingAndMax pinRetriesLeft(const SmartCard::Session& session,
59-
byte_type pinReference);
56+
static PinInfo pinRetriesLeft(const SmartCard::Session& session, byte_type pinReference);
6057

6158
static void selectMain(const SmartCard::Session& session);
6259
static void selectADF1(const SmartCard::Session& session);

src/electronic-ids/pcsc/EIDThales.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,15 @@ namespace
4848

4949
constexpr byte_type PIN_PADDING_CHAR = 0x00;
5050
constexpr byte_type ECDSA_ALGO = 0x04;
51-
constexpr byte_type SIGNING_PIN_REFERENCE = 0x82;
5251

5352
const auto SELECT_MAIN_AID = CommandApdu::select(
5453
0x04, {0xa0, 0x00, 0x00, 0x00, 0x63, 0x50, 0x4b, 0x43, 0x53, 0x2d, 0x31, 0x35});
5554

5655
} // namespace
5756

58-
ElectronicID::PinRetriesRemainingAndMax
59-
EIDThales::authPinRetriesLeftImpl(const SmartCard::Session& session) const
57+
ElectronicID::PinInfo EIDThales::authPinInfoImpl(const SmartCard::Session& session) const
6058
{
61-
return pinRetriesLeft(session, authPinReference());
59+
return pinRetriesLeft(session, authPinReference(), true);
6260
}
6361

6462
byte_vector EIDThales::getCertificateImpl(const SmartCard::Session& session,
@@ -68,8 +66,8 @@ byte_vector EIDThales::getCertificateImpl(const SmartCard::Session& session,
6866
return readFile(session, type.isAuthentication() ? authCertFile() : signCertFile());
6967
}
7068

71-
ElectronicID::PinRetriesRemainingAndMax EIDThales::pinRetriesLeft(const SmartCard::Session& session,
72-
byte_type pinReference) const
69+
ElectronicID::PinInfo EIDThales::pinRetriesLeft(const SmartCard::Session& session,
70+
byte_type pinReference, bool pinActive) const
7371
{
7472
const auto GET_DATA = smartcard().protocol() == SmartCard::Protocol::T1
7573
? CommandApdu {0x00, 0xCB, 0x00, 0xFF, {0xA0, 0x03, 0x83, 0x01, pinReference}, 0x00}
@@ -78,8 +76,9 @@ ElectronicID::PinRetriesRemainingAndMax EIDThales::pinRetriesLeft(const SmartCar
7876
if (!response.isOK()) {
7977
THROW(SmartCardError, "Command GET DATA failed with error " + response);
8078
}
81-
if (TLV info = TLV(response.data).find(0xA0)[0xdf21]) {
82-
return {*info.begin, maximumPinRetries()};
79+
if (TLV info = TLV(response.data).find(0xA0); TLV count = info[0xdf21]) {
80+
TLV pinChanged = info[0xdf2f];
81+
return {*count.begin, maximumPinRetries(), pinActive || !pinChanged || *pinChanged.begin};
8382
}
8483
THROW(SmartCardError,
8584
"Command GET DATA failed: received data does not contain the PIN remaining retries info");
@@ -147,10 +146,9 @@ byte_vector EIDThales::sign(const SmartCard::Session& session, const HashAlgorit
147146
return std::move(signature.data);
148147
}
149148

150-
ElectronicID::PinRetriesRemainingAndMax
151-
EIDThales::signingPinRetriesLeftImpl(const SmartCard::Session& session) const
149+
ElectronicID::PinInfo EIDThales::signingPinInfoImpl(const SmartCard::Session& session) const
152150
{
153-
return pinRetriesLeft(session, SIGNING_PIN_REFERENCE);
151+
return pinRetriesLeft(session, SIGNING_PIN_REFERENCE, true);
154152
}
155153

156154
byte_vector EIDThales::signWithAuthKeyImpl(const SmartCard::Session& session, byte_vector&& pin,

src/electronic-ids/pcsc/EIDThales.hpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,24 @@ class EIDThales : public PcscElectronicID
4242
virtual constexpr byte_type signingKeyReference() const = 0;
4343

4444
byte_vector getCertificateImpl(const SmartCard::Session& session,
45-
const CertificateType type) const override;
46-
PinRetriesRemainingAndMax
47-
authPinRetriesLeftImpl(const SmartCard::Session& session) const override;
48-
PinRetriesRemainingAndMax
49-
signingPinRetriesLeftImpl(const SmartCard::Session& session) const override;
45+
CertificateType type) const override;
46+
PinInfo authPinInfoImpl(const SmartCard::Session& session) const override;
47+
PinInfo signingPinInfoImpl(const SmartCard::Session& session) const override;
5048
byte_vector signWithAuthKeyImpl(const SmartCard::Session& session, byte_vector&& pin,
5149
const byte_vector& hash) const override;
5250
Signature signWithSigningKeyImpl(const SmartCard::Session& session, byte_vector&& pin,
5351
const byte_vector& hash,
54-
const HashAlgorithm hashAlgo) const override;
52+
HashAlgorithm hashAlgo) const override;
5553

56-
PinRetriesRemainingAndMax pinRetriesLeft(const SmartCard::Session& session,
57-
byte_type pinReference) const;
58-
byte_vector sign(const SmartCard::Session& session, const HashAlgorithm hashAlgo,
54+
PinInfo pinRetriesLeft(const SmartCard::Session& session, byte_type pinReference,
55+
bool pinActive) const;
56+
byte_vector sign(const SmartCard::Session& session, HashAlgorithm hashAlgo,
5957
const byte_vector& hash, byte_vector&& pin, byte_type pinReference,
6058
PinMinMaxLength pinMinMaxLength, byte_type keyReference,
6159
byte_type signatureAlgo) const;
6260

6361
static constexpr byte_type AUTH_KEY_REFERENCE = 0x01;
62+
static constexpr byte_type SIGNING_PIN_REFERENCE = 0x82;
6463
};
6564

66-
} // namespace electronic_id
65+
} // namespace electronic_id

src/electronic-ids/pcsc/EstEIDThales.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ class EstEIDThales : public EIDThales
4747
}
4848
constexpr byte_type signingKeyReference() const override { return 0x05; }
4949
constexpr PinMinMaxLength signingPinMinMaxLength() const override { return {5, 12}; }
50+
PinInfo signingPinInfoImpl(const SmartCard::Session& session) const override
51+
{
52+
// EstEID cards must change PIN2 first to use signing key
53+
return pinRetriesLeft(session, SIGNING_PIN_REFERENCE, false);
54+
}
5055
};
5156

52-
} // namespace electronic_id
57+
} // namespace electronic_id

src/electronic-ids/pcsc/PcscElectronicID.hpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,9 @@ class PcscElectronicID : public ElectronicID
6565
return signWithSigningKeyImpl(card.beginSession(), std::move(pin), hash, hashAlgo);
6666
}
6767

68-
PinRetriesRemainingAndMax signingPinRetriesLeft() const override
69-
{
70-
return signingPinRetriesLeftImpl(card.beginSession());
71-
}
68+
PinInfo signingPinInfo() const override { return signingPinInfoImpl(card.beginSession()); }
7269

73-
ElectronicID::PinRetriesRemainingAndMax authPinRetriesLeft() const override
74-
{
75-
return authPinRetriesLeftImpl(card.beginSession());
76-
}
70+
PinInfo authPinInfo() const override { return authPinInfoImpl(card.beginSession()); }
7771

7872
// The following pure virtual *Impl functions are the interface of all
7973
// PC/SC electronic ID implementations,
@@ -86,15 +80,13 @@ class PcscElectronicID : public ElectronicID
8680
virtual byte_vector signWithAuthKeyImpl(const SmartCard::Session& session, byte_vector&& pin,
8781
const byte_vector& hash) const = 0;
8882

89-
virtual PinRetriesRemainingAndMax
90-
authPinRetriesLeftImpl(const SmartCard::Session& session) const = 0;
83+
virtual PinInfo authPinInfoImpl(const SmartCard::Session& session) const = 0;
9184

9285
virtual Signature signWithSigningKeyImpl(const SmartCard::Session& session, byte_vector&& pin,
9386
const byte_vector& hash,
9487
const HashAlgorithm hashAlgo) const = 0;
9588

96-
virtual PinRetriesRemainingAndMax
97-
signingPinRetriesLeftImpl(const SmartCard::Session& session) const = 0;
89+
virtual PinInfo signingPinInfoImpl(const SmartCard::Session& session) const = 0;
9890
};
9991

10092
} // namespace electronic_id

0 commit comments

Comments
 (0)