mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-11-13 20:25:53 +08:00
[fix] distinguish trusted device authentication failures
This commit is contained in:
1 parent
9d61aacffe
commit
7d8daa27eb
4 files changed
+67
-18
No files matched your search
@@ -202,12 +202,18 @@ std::string TrustedDevices::Sign(std::string_view text) const {
|
||||
}
|
||||
|
||||
std::optional<TrustedDevices::Device> TrustedDevices::Verify(
|
||||
const nlohmann::json& proof, const std::string& nonce) {
|
||||
const nlohmann::json& proof, const std::string& nonce, ProofFailure* failure) {
|
||||
if (failure) *failure = ProofFailure::None;
|
||||
const auto reject = [failure](ProofFailure reason) -> std::optional<Device> {
|
||||
if (failure) *failure = reason;
|
||||
return std::nullopt;
|
||||
};
|
||||
try {
|
||||
if (proof.at("version") != 1 || proof.at("nonce") != nonce || !IsHex(nonce, 32))
|
||||
return std::nullopt;
|
||||
if (proof.at("version") != 1) return reject(ProofFailure::UnsupportedVersion);
|
||||
if (!IsHex(nonce, 32)) return reject(ProofFailure::Malformed);
|
||||
if (proof.at("nonce") != nonce) return reject(ProofFailure::NonceMismatch);
|
||||
Device device{proof.at("public_key"), proof.at("name"), proof.at("device_id")};
|
||||
if (!Label(device.name) || !Label(device.device_id)) return std::nullopt;
|
||||
if (!Label(device.name) || !Label(device.device_id)) return reject(ProofFailure::Malformed);
|
||||
const auto public_key = Unhex(device.public_key, 32);
|
||||
const auto signature = Unhex(proof.at("signature"), 64);
|
||||
std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> key(
|
||||
@@ -215,12 +221,28 @@ std::optional<TrustedDevices::Device> TrustedDevices::Verify(
|
||||
EVP_PKEY_free);
|
||||
Context context(EVP_MD_CTX_new(), EVP_MD_CTX_free);
|
||||
const auto text = Transcript(nonce, device);
|
||||
if (key && context && EVP_DigestVerifyInit(context.get(), nullptr, nullptr, nullptr, key.get()) == 1 &&
|
||||
EVP_DigestVerify(context.get(), signature.data(), signature.size(),
|
||||
reinterpret_cast<const uint8_t*>(text.data()), text.size()) == 1)
|
||||
return device;
|
||||
} catch (const std::exception&) {}
|
||||
return std::nullopt;
|
||||
if (!key || !context ||
|
||||
EVP_DigestVerifyInit(context.get(), nullptr, nullptr, nullptr, key.get()) != 1)
|
||||
return reject(ProofFailure::CryptoUnavailable);
|
||||
const int verified = EVP_DigestVerify(context.get(), signature.data(), signature.size(),
|
||||
reinterpret_cast<const uint8_t*>(text.data()), text.size());
|
||||
if (verified == 1) return device;
|
||||
return reject(verified == 0 ? ProofFailure::InvalidSignature : ProofFailure::CryptoUnavailable);
|
||||
} catch (const std::exception&) {
|
||||
return reject(ProofFailure::Malformed);
|
||||
}
|
||||
}
|
||||
|
||||
const char* TrustedDevices::ProofFailureReason(ProofFailure failure) {
|
||||
switch (failure) {
|
||||
case ProofFailure::None: return "none";
|
||||
case ProofFailure::Malformed: return "malformed_proof";
|
||||
case ProofFailure::UnsupportedVersion: return "unsupported_proof_version";
|
||||
case ProofFailure::NonceMismatch: return "nonce_mismatch";
|
||||
case ProofFailure::InvalidSignature: return "invalid_signature";
|
||||
case ProofFailure::CryptoUnavailable: return "crypto_unavailable";
|
||||
}
|
||||
return "invalid_proof";
|
||||
}
|
||||
|
||||
bool TrustedDevices::Contains(const std::string& public_key) const {
|
||||
|
||||
Reference in new issue
Block a user