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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ add_library(${PROJECT_NAME}
src/electronic-ids/ms-cryptoapi/MsCryptoApiElectronicID.cpp
src/electronic-ids/ms-cryptoapi/MsCryptoApiElectronicID.hpp
>
src/magic_enum/magic_enum.hpp
)

target_include_directories(${PROJECT_NAME}
Expand Down
1 change: 1 addition & 0 deletions include/electronic-id/electronic-id.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <functional>
#include <optional>
#include <set>

namespace electronic_id
{
Expand Down
82 changes: 49 additions & 33 deletions include/electronic-id/enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@

#include "pcsc-cpp/pcsc-cpp.hpp"

#include <set>
#include <string>
Comment thread
metsma marked this conversation as resolved.
#include <string_view>

namespace electronic_id
{
Expand All @@ -35,15 +35,17 @@ class CertificateType
public:
enum CertificateTypeEnum : int8_t { AUTHENTICATION, SIGNING, NONE = -1 };

CertificateType() = default;
constexpr CertificateType(const CertificateTypeEnum _value) : value(_value) {}
constexpr CertificateType() noexcept = default;
constexpr CertificateType(const CertificateTypeEnum _value) noexcept : value(_value) {}

bool isAuthentication() const { return value == AUTHENTICATION; }
constexpr bool isAuthentication() const noexcept { return value == AUTHENTICATION; }
constexpr bool isSigning() const noexcept { return value == SIGNING; }

bool isSigning() const { return value == SIGNING; }

constexpr bool operator==(const CertificateType other) const { return value == other.value; }
operator std::string() const;
constexpr bool operator==(const CertificateType other) const noexcept
{
return value == other.value;
}
operator std::string_view() const noexcept;

private:
CertificateTypeEnum value = NONE;
Expand All @@ -66,27 +68,27 @@ class HashAlgorithm
NONE = -1
};

HashAlgorithm() = default;
constexpr HashAlgorithm(const HashAlgorithmEnum _value) : value(_value) {}
constexpr HashAlgorithm() = default;
constexpr HashAlgorithm(const HashAlgorithmEnum _value) noexcept : value(_value) {}
// String conversion constructor.
HashAlgorithm(const std::string&);
explicit HashAlgorithm(const std::string&);

constexpr bool operator==(HashAlgorithmEnum other) const { return value == other; }
constexpr operator HashAlgorithmEnum() const { return value; }
constexpr bool operator==(HashAlgorithmEnum other) const noexcept { return value == other; }
constexpr operator HashAlgorithmEnum() const noexcept { return value; }

operator std::string() const;
operator std::string_view() const noexcept;

constexpr size_t hashByteLength() const
constexpr size_t hashByteLength() const noexcept
{
return size_t(value <= SHA512 ? value / 8 : (value / 10) / 8);
return size_t((value <= SHA512 ? value : (value / 10)) / 8);
}

constexpr bool isSHA2() const
constexpr bool isSHA2() const noexcept
{
return value >= HashAlgorithm::SHA224 && value <= HashAlgorithm::SHA512;
}

constexpr bool isSHA3() const
constexpr bool isSHA3() const noexcept
{
return value >= HashAlgorithm::SHA3_224 && value <= HashAlgorithm::SHA3_512;
}
Expand Down Expand Up @@ -136,26 +138,25 @@ class SignatureAlgorithm
NONE = -1
};

constexpr SignatureAlgorithm(const SignatureAlgorithmEnum _value) : value(_value) {}
constexpr SignatureAlgorithm(const SignatureAlgorithmEnum key, const HashAlgorithm hash) :
constexpr SignatureAlgorithm(const SignatureAlgorithmEnum _value) noexcept : value(_value) {}
constexpr SignatureAlgorithm(const SignatureAlgorithmEnum key,
const HashAlgorithm hash) noexcept :
value(SignatureAlgorithmEnum(key | int16_t(hash)))
{
}

constexpr bool operator==(HashAlgorithm other) const
constexpr bool operator==(HashAlgorithm other) const noexcept
{
return other.operator==(operator HashAlgorithm());
}
constexpr bool operator==(SignatureAlgorithmEnum other) const { return value == other; }

constexpr operator HashAlgorithm() const
constexpr operator HashAlgorithm() const noexcept
{
return HashAlgorithm::HashAlgorithmEnum(value & ~(ES | PS | RS));
}

constexpr operator SignatureAlgorithmEnum() const { return value; }
constexpr operator SignatureAlgorithmEnum() const noexcept { return value; }

operator std::string() const;
operator std::string_view() const noexcept;

private:
SignatureAlgorithmEnum value = NONE;
Expand All @@ -175,17 +176,16 @@ class JsonWebSignatureAlgorithm
RS256, // RSASSA-PKCS1-v1_5
RS384,
RS512,
NONE = -1
};

constexpr JsonWebSignatureAlgorithm(const JsonWebSignatureAlgorithmEnum _value) : value(_value)
constexpr JsonWebSignatureAlgorithm(const JsonWebSignatureAlgorithmEnum _value) :
value(validate(_value))
{
}

constexpr bool operator==(JsonWebSignatureAlgorithmEnum other) const { return value == other; }
constexpr operator JsonWebSignatureAlgorithmEnum() const { return value; }
constexpr operator JsonWebSignatureAlgorithmEnum() const noexcept { return value; }

operator std::string() const;
operator std::string_view() const noexcept;

constexpr HashAlgorithm hashAlgorithm() const
{
Expand All @@ -208,15 +208,31 @@ class JsonWebSignatureAlgorithm
}
}

constexpr bool isRSAWithPKCS1Padding()
constexpr bool isRSAWithPKCS1Padding() const noexcept
{
return value == RS256 || value == RS384 || value == RS512;
}

constexpr size_t hashByteLength() const { return hashAlgorithm().hashByteLength(); }

private:
JsonWebSignatureAlgorithmEnum value = NONE;
static constexpr JsonWebSignatureAlgorithmEnum validate(JsonWebSignatureAlgorithmEnum v)
{
switch (v) {
case ES256:
case ES384:
case ES512:
case PS256:
case PS384:
case PS512:
case RS256:
case RS384:
case RS512:
return v;
}
throw std::logic_error("Invalid JsonWebSignatureAlgorithm value");
}
JsonWebSignatureAlgorithmEnum value;
};

} // namespace electronic_id
1 change: 0 additions & 1 deletion lib/libpcsc-cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ add_library(${PROJECT_NAME}
include/${PROJECT_NAME}/${PROJECT_NAME}.hpp
include/${PROJECT_NAME}/${PROJECT_NAME}-utils.hpp
include/${PROJECT_NAME}/comp_winscard.hpp
include/magic_enum/magic_enum.hpp
src/Context.hpp
src/SCardCall.hpp
src/SmartCard.cpp
Expand Down
4 changes: 1 addition & 3 deletions lib/libpcsc-cpp/include/pcsc-cpp/pcsc-cpp-utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,5 @@ constexpr const char* removeAbsolutePathPrefix(std::string_view filePath)

#define REQUIRE_NON_NULL(val) \
if (!(val)) { \
throw std::logic_error("Null " + std::string(#val) + " in " \
+ pcsc_cpp::removeAbsolutePathPrefix(__FILE__) + ':' \
+ std::to_string(__LINE__) + ':' + __func__); \
THROW(std::logic_error, "Null " #val); \
Comment thread
metsma marked this conversation as resolved.
}
51 changes: 27 additions & 24 deletions src/electronic-id.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,11 @@ const std::vector<MaskedATREntry> MASKED_ATRS = {
constructor<ElectronicID::Type::LuxEID>},
};

const auto SUPPORTED_ALGORITHMS = std::map<std::string, HashAlgorithm> {
{"SHA-224"s, HashAlgorithm::SHA224}, {"SHA-256"s, HashAlgorithm::SHA256},
{"SHA-384"s, HashAlgorithm::SHA384}, {"SHA-512"s, HashAlgorithm::SHA512},
{"SHA3-224"s, HashAlgorithm::SHA3_224}, {"SHA3-256"s, HashAlgorithm::SHA3_256},
{"SHA3-384"s, HashAlgorithm::SHA3_384}, {"SHA3-512"s, HashAlgorithm::SHA3_512},
const auto SUPPORTED_ALGORITHMS = std::map<std::string_view, HashAlgorithm> {
{"SHA-224", HashAlgorithm::SHA224}, {"SHA-256", HashAlgorithm::SHA256},
{"SHA-384", HashAlgorithm::SHA384}, {"SHA-512", HashAlgorithm::SHA512},
{"SHA3-224", HashAlgorithm::SHA3_224}, {"SHA3-256", HashAlgorithm::SHA3_256},
{"SHA3-384", HashAlgorithm::SHA3_384}, {"SHA3-512", HashAlgorithm::SHA3_512},
};

} // namespace
Expand Down Expand Up @@ -263,14 +263,14 @@ bool ElectronicID::isSupportedSigningHashAlgorithm(const HashAlgorithm hashAlgo)
}

AutoSelectFailed::AutoSelectFailed(Reason r) :
Error(std::string("Auto-select card failed, reason: ") + std::string(magic_enum::enum_name(r))),
Error(std::string("Auto-select card failed, reason: ").append(magic_enum::enum_name(r))),
_reason(r)
{
}

VerifyPinFailed::VerifyPinFailed(const Status s, const observer_ptr<pcsc_cpp::ResponseApdu> ra,
const int8_t r) :
Error(std::string("Verify PIN failed, status: ") + std::string(magic_enum::enum_name(s))
Error(std::string("Verify PIN failed, status: ").append(magic_enum::enum_name(s))
+ (ra ? ", response: " + *ra : "")),
_status(s), _retries(r)
{
Expand All @@ -286,68 +286,71 @@ HashAlgorithm::HashAlgorithm(const std::string& algoName)
value = SUPPORTED_ALGORITHMS.at(algoName);
}

HashAlgorithm::operator std::string() const
HashAlgorithm::operator std::string_view() const noexcept
{
const auto algoNameValuePair =
std::find_if(SUPPORTED_ALGORITHMS.cbegin(), SUPPORTED_ALGORITHMS.cend(),
[this](const auto& pair) { return pair.second == value; });
return algoNameValuePair != SUPPORTED_ALGORITHMS.cend() ? algoNameValuePair->first : "UNKNOWN";
if (algoNameValuePair != SUPPORTED_ALGORITHMS.cend())
return algoNameValuePair->first;
return "UNKNOWN";
}

std::string HashAlgorithm::allSupportedAlgorithmNames()
{
static const auto SUPPORTED_ALGORITHM_NAMES = std::accumulate(
std::next(SUPPORTED_ALGORITHMS.begin()), SUPPORTED_ALGORITHMS.end(),
std::string(SUPPORTED_ALGORITHMS.begin()->first),
[](auto result, const auto& value) { return result + ", "s + std::string(value.first); });
[](auto result, const auto& value) { return (result + ", ").append(value.first); });
return SUPPORTED_ALGORITHM_NAMES;
}

pcsc_cpp::byte_vector HashAlgorithm::rsaOID(const HashAlgorithmEnum hash)
{
switch (hash) {
case HashAlgorithm::SHA224:
using enum HashAlgorithm::HashAlgorithmEnum;
case SHA224:
return {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c};
case HashAlgorithm::SHA256:
case SHA256:
return {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
case HashAlgorithm::SHA384:
case SHA384:
return {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
case HashAlgorithm::SHA512:
case SHA512:
return {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
case HashAlgorithm::SHA3_224:
case SHA3_224:
return {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x07, 0x05, 0x00, 0x04, 0x1c};
case HashAlgorithm::SHA3_256:
case SHA3_256:
return {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20};
case HashAlgorithm::SHA3_384:
case SHA3_384:
return {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x09, 0x05, 0x00, 0x04, 0x30};
case HashAlgorithm::SHA3_512:
case SHA3_512:
return {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
0x65, 0x03, 0x04, 0x02, 0x0A, 0x05, 0x00, 0x04, 0x40};
default:
THROW(ArgumentFatalError, "No OID for algorithm " + std::string(HashAlgorithm(hash)));
}
}

CertificateType::operator std::string() const
CertificateType::operator std::string_view() const noexcept
{
return std::string(magic_enum::enum_name(value));
return magic_enum::enum_name(value);
}

JsonWebSignatureAlgorithm::operator std::string() const
JsonWebSignatureAlgorithm::operator std::string_view() const noexcept
{
return std::string(magic_enum::enum_name(value));
return magic_enum::enum_name(value);
}

SignatureAlgorithm::operator std::string() const
SignatureAlgorithm::operator std::string_view() const noexcept
{
return std::string(magic_enum::enum_name(value));
return magic_enum::enum_name(value);
}

} // namespace electronic_id
4 changes: 2 additions & 2 deletions src/electronic-ids/ms-cryptoapi/MsCryptoApiElectronicID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ JsonWebSignatureAlgorithm MsCryptoApiElectronicID::authSignatureAlgorithm() cons
byte_vector MsCryptoApiElectronicID::signWithAuthKey(byte_vector&& /* pin */,
const byte_vector& hash) const
{
if (certType != CertificateType::AUTHENTICATION) {
if (!certType.isAuthentication()) {
THROW(WrongCertificateTypeError,
"This electronic ID does not support signing with the authentication key. "
"It contains a "
Expand All @@ -59,7 +59,7 @@ ElectronicID::Signature
MsCryptoApiElectronicID::signWithSigningKey(byte_vector&& /* pin */, const byte_vector& hash,
const HashAlgorithm hashAlgo) const
{
if (certType != CertificateType::SIGNING) {
if (!certType.isSigning()) {
THROW(WrongCertificateTypeError,
"This electronic ID does not support signing with the digital signature key. "
"It contains a "
Expand Down
Loading
Loading