Skip to content
Merged
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
3 changes: 2 additions & 1 deletion lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ struct CommandApdu
byte_vector data, byte_type le) :
CommandApdu {cls, ins, p1, p2, std::move(data)}
{
#if defined(__GNUC__) && __GNUC__ == 15 // Apply workaround for GCC 15
// https://gcc.gnu.org/pipermail/gcc-patches/2025-February/676226.html
#if defined(__GNUC__) && (__GNUC__ == 15 || __GNUC__ == 16) // Apply workaround for GCC 15, 16
d.reserve(d.size() + 1);
#endif
d.push_back(le);
Expand Down
68 changes: 43 additions & 25 deletions src/electronic-ids/pkcs11/Pkcs11ElectronicID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
*/

#include "Pkcs11ElectronicID.hpp"
#include "../scope.hpp"

#include <algorithm>
#include <map>

#ifdef _WIN32
Expand Down Expand Up @@ -211,7 +213,7 @@ const Pkcs11ElectronicIDModule& getModule(ElectronicID::Type eidType)
return SUPPORTED_PKCS11_MODULES.at(eidType);
} catch (const std::out_of_range&) {
THROW(ProgrammingError,
"Unknown Pkcs11ElectronicIDType enum value '" + std::to_string(int(eidType)) + "'");
"Unknown Pkcs11ElectronicIDType enum value '" + std::to_string(int(eidType)) + '\'');
}
}

Expand All @@ -222,57 +224,54 @@ Pkcs11ElectronicID::Pkcs11ElectronicID(ElectronicID::Type type) :
{
REQUIRE_NON_NULL(manager)

bool seenAuthToken = false;
bool seenSigningToken = false;

for (const auto& token : manager->tokens()) {
const auto certType = certificateType(token.cert);
if (certType.isAuthentication()) {
authToken = token;
seenAuthToken = true;
} else if (certType.isSigning()) {
signingToken = token;
seenSigningToken = true;
}
}
if (!(seenAuthToken && seenSigningToken)) {
THROW(SmartCardChangeRequiredError, "Either authentication or signing token is missing");
}
}

pcsc_cpp::byte_vector Pkcs11ElectronicID::getCertificate(const CertificateType type) const
{
return type.isAuthentication() ? authToken.cert : signingToken.cert;
return token(type).cert;
}

JsonWebSignatureAlgorithm Pkcs11ElectronicID::authSignatureAlgorithm() const
{
return getAuthAlgorithmFromCert(authToken.cert);
return getAuthAlgorithmFromCert(token(CertificateType::AUTHENTICATION).cert);
}

ElectronicID::PinMinMaxLength Pkcs11ElectronicID::authPinMinMaxLength() const
{
return {authToken.minPinLen, authToken.maxPinLen};
const auto& t = token(CertificateType::AUTHENTICATION);
return {t.minPinLen, t.maxPinLen};
}

ElectronicID::PinInfo Pkcs11ElectronicID::authPinInfo() const
{
return {authToken.retry, module.retryMax, true};
return {token(CertificateType::AUTHENTICATION).retry, module.retryMax, true};
}

pcsc_cpp::byte_vector Pkcs11ElectronicID::signWithAuthKey(byte_vector&& pin,
const byte_vector& hash) const
{
auto clearPin = stdext::make_scope_exit([&pin] {
std::fill(pin.begin(), pin.end(), byte_type(0));
pin.clear();
});
REQUIRE_NON_NULL(manager)

try {
validateAuthHashLength(authSignatureAlgorithm(), name(), hash);

const auto signature =
manager->sign(authToken, hash, authSignatureAlgorithm().hashAlgorithm(),
module.providesExternalPinDialog,
reinterpret_cast<const char*>(pin.data()), pin.size());
return signature.first;
auto signature = manager->sign(token(CertificateType::AUTHENTICATION), hash,
authSignatureAlgorithm().hashAlgorithm(),
module.providesExternalPinDialog,
reinterpret_cast<const char*>(pin.data()), pin.size());
return std::move(signature.first);
} catch (const VerifyPinFailed& e) {
// Catch and rethrow the VerifyPinFailed error with -1 to inform the caller of the special
// case where the card does not return the remaining retry count. This is arguably a
Expand All @@ -287,34 +286,39 @@ pcsc_cpp::byte_vector Pkcs11ElectronicID::signWithAuthKey(byte_vector&& pin,

const std::set<SignatureAlgorithm>& Pkcs11ElectronicID::supportedSigningAlgorithms() const
{
return getSignAlgorithmFromCert(signingToken.cert);
return getSignAlgorithmFromCert(token(CertificateType::SIGNING).cert);
}

ElectronicID::PinMinMaxLength Pkcs11ElectronicID::signingPinMinMaxLength() const
{
return {signingToken.minPinLen, signingToken.maxPinLen};
const auto& t = token(CertificateType::SIGNING);
return {t.minPinLen, t.maxPinLen};
}

ElectronicID::PinInfo Pkcs11ElectronicID::signingPinInfo() const
{
return {signingToken.retry, module.retryMax, true};
return {token(CertificateType::SIGNING).retry, module.retryMax, true};
}

ElectronicID::Signature Pkcs11ElectronicID::signWithSigningKey(byte_vector&& pin,
const byte_vector& hash,
const HashAlgorithm hashAlgo) const
{
auto clearPin = stdext::make_scope_exit([&pin] {
std::fill(pin.begin(), pin.end(), byte_type(0));
pin.clear();
});
REQUIRE_NON_NULL(manager)

try {
validateSigningHash(*this, hashAlgo, hash);

// TODO: add step for supported algo detection before sign(), see if () below.
auto signature =
manager->sign(signingToken, hash, hashAlgo, module.providesExternalPinDialog,
reinterpret_cast<const char*>(pin.data()), pin.size());
auto signature = manager->sign(token(CertificateType::SIGNING), hash, hashAlgo,
module.providesExternalPinDialog,
reinterpret_cast<const char*>(pin.data()), pin.size());

if (!supportedSigningAlgorithms().count(signature.second)) {
if (!supportedSigningAlgorithms().contains(signature.second)) {
THROW(SmartCardChangeRequiredError,
"Signature algorithm " + std::string(signature.second) + " is not supported by "
+ name());
Expand All @@ -330,6 +334,20 @@ ElectronicID::Signature Pkcs11ElectronicID::signWithSigningKey(byte_vector&& pin
}
}

const PKCS11CardManager::Token& Pkcs11ElectronicID::token(CertificateType type) const
{
if (type.isAuthentication()) {
if (authToken.cert.empty()) {
THROW(SmartCardChangeRequiredError, "Authentication token is missing");
}
return authToken;
}
if (signingToken.cert.empty()) {
THROW(SmartCardChangeRequiredError, "Signing token is missing");
}
return signingToken;
}

void Pkcs11ElectronicID::release() const
{
manager.reset();
Expand Down
2 changes: 2 additions & 0 deletions src/electronic-ids/pkcs11/Pkcs11ElectronicID.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class Pkcs11ElectronicID : public ElectronicID
std::string name() const override { return module.name; }
Type type() const override { return module.type; }

const PKCS11CardManager::Token& token(CertificateType type) const;

const Pkcs11ElectronicIDModule& module;
mutable std::shared_ptr<PKCS11CardManager> manager;
PKCS11CardManager::Token authToken;
Expand Down
Loading