// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. // // Reference implementation utilities of OEMCrypto APIs // #include "cbor_validator.h" #include #include #include #include #include #include namespace wvoec { namespace util { std::string CppborMajorTypeToString(cppbor::MajorType type) { switch (type) { case cppbor::UINT: return "UINT"; case cppbor::NINT: return "NINT"; case cppbor::BSTR: return "BSTR"; case cppbor::TSTR: return "TSTR"; case cppbor::ARRAY: return "ARRAY"; case cppbor::MAP: return "MAP"; case cppbor::SEMANTIC: return "SEMANTIC"; case cppbor::SIMPLE: return "SIMPLE"; } return "undefined type"; } std::string CborMessageStatusToString(CborMessageStatus status) { switch (status) { case kCborUninitialized: return "Uninitialized"; case kCborParseOk: return "ParseOk"; case kCborParseError: return "ParseError"; case kCborValidateOk: return "ValidateOk"; case kCborValidateWarning: return "ValidateWarning"; case kCborValidateError: return "ValidateError"; case kCborValidateFatal: return "ValidateFatal"; } return "undefined status"; } void CborValidator::Reset() { message_status_ = kCborUninitialized; parse_result_ = {nullptr, nullptr, ""}; validate_messages_.clear(); } CborMessageStatus CborValidator::Parse(const std::vector& cbor) { Reset(); parse_result_ = cppbor::parse(cbor); message_status_ = (std::get<0>(parse_result_) && std::get<2>(parse_result_).empty()) ? kCborParseOk : kCborParseError; return message_status_; } const cppbor::ParseResult* CborValidator::GetParseResult() const { if (message_status_ == kCborUninitialized) { return nullptr; } return &parse_result_; } std::string CborValidator::GetRawMessage() const { if (message_status_ == kCborUninitialized || message_status_ == kCborParseError) { return std::string(); } const cppbor::Item* parsed_item = std::get<0>(parse_result_).get(); if (parsed_item == nullptr) { return ""; } return cppbor::prettyPrint(parsed_item); } CborMessageStatus CborValidator::Validate() { if (message_status_ != kCborParseOk) return message_status_; // No other validations to be done than Parse() being successful. AddValidationMessage(kCborValidateOk, "No validations are done."); return message_status_; } std::string CborValidator::GetFormattedMessage() const { return GetRawMessage(); } void CborValidator::AddValidationMessage(CborMessageStatus status, const std::string& msg) { validate_messages_.push_back({status, msg}); if (status > message_status_) message_status_ = status; } // TODO(b/314141962): Replace this with the map lookup function in cppbor // library const cppbor::Item* CborValidator::GetMapEntry(const cppbor::Map& map, const std::string& entry_name) { for (auto const& entry : map) { if (!entry.first->asTstr()) continue; const std::string& name = entry.first->asTstr()->value(); if (name == entry_name) return entry.second.get(); } return nullptr; } std::string CborValidator::CheckMapEntry(const cppbor::Map& map, cppbor::MajorType major_type, const std::string& entry_name) { const cppbor::Item* value = GetMapEntry(map, entry_name); if (!value) { return entry_name + " is missing."; } if (value->type() != major_type) { return entry_name + " has the wrong type. Expect: " + CppborMajorTypeToString(major_type) + ", actual: " + CppborMajorTypeToString(value->type()); } return ""; } } // namespace util } // namespace wvoec