1 #include "logging/logging.h"
2 #include "uptane/exceptions.h"
3 #include "uptane/tuf.h"
7 MetaWithKeys::MetaWithKeys(
const Json::Value &json) :
BaseMeta(json) {}
9 const std::shared_ptr<MetaWithKeys> &signer)
10 :
BaseMeta(repo, role, json, signer) {}
12 void Uptane::MetaWithKeys::ParseKeys(
const RepositoryType repo,
const Json::Value &keys) {
13 for (
auto it = keys.begin(); it != keys.end(); ++it) {
14 const std::string key_type = boost::algorithm::to_lower_copy((*it)[
"keytype"].asString());
15 if (key_type !=
"rsa" && key_type !=
"ed25519") {
16 throw SecurityException(repo,
"Unsupported key type: " + (*it)[
"keytype"].asString());
18 const KeyId keyid = it.key().asString();
24 void Uptane::MetaWithKeys::ParseRole(
const RepositoryType repo,
const Json::ValueConstIterator &it,
const Role &role,
25 const std::string &meta_role) {
26 if (role == Role::InvalidRole()) {
27 LOG_WARNING <<
"Invalid role in " << meta_role <<
".json";
28 LOG_TRACE <<
"Role name:" << role.ToString();
32 const int64_t requiredThreshold = (*it)[
"threshold"].asInt64();
33 if (requiredThreshold < kMinSignatures) {
37 LOG_DEBUG <<
"Failing with threshold for role " << role <<
" too small: " << requiredThreshold <<
" < "
38 <<
static_cast<int64_t
>(kMinSignatures);
39 throw IllegalThreshold(repo,
"The role " + role.ToString() +
" had an illegal signature threshold.");
41 if (kMaxSignatures < requiredThreshold) {
45 LOG_DEBUG <<
"Failing with threshold for role " << role <<
" too large: " <<
static_cast<int>(kMaxSignatures)
46 <<
" < " << requiredThreshold;
47 throw IllegalThreshold(repo, meta_role +
".json contains a role that requires too many signatures");
49 thresholds_for_role_[role] = requiredThreshold;
52 const Json::Value keyids = (*it)[
"keyids"];
53 for (
auto itk = keyids.begin(); itk != keyids.end(); ++itk) {
54 keys_for_role_.insert(std::make_pair(role, (*itk).asString()));
59 const Json::Value &signed_object) {
60 const std::string repository = repo;
62 const Uptane::Role type(signed_object[
"signed"][
"_type"].asString());
63 if (role.IsDelegation()) {
64 if (type != Uptane::Role::Targets()) {
65 LOG_ERROR <<
"Delegated role " << role <<
" has an invalid type: " << type;
66 throw SecurityException(repo,
"Delegated role " + role.ToString() +
" has invalid type " + type.ToString());
68 }
else if (role != type) {
69 LOG_ERROR <<
"Metadata type " << type <<
" does not match expected role: " << role;
71 "Metadata type " + type.ToString() +
" does not match expected role " + role.ToString());
74 const std::string canonical = Utils::jsonToCanonicalStr(signed_object[
"signed"]);
75 const Json::Value signatures = signed_object[
"signatures"];
76 int valid_signatures = 0;
78 std::set<std::string> used_keyids;
79 for (
auto sig = signatures.begin(); sig != signatures.end(); ++sig) {
80 const std::string keyid = (*sig)[
"keyid"].asString();
81 if (used_keyids.count(keyid) != 0) {
84 used_keyids.insert(keyid);
86 std::string method((*sig)[
"method"].asString());
87 std::transform(method.begin(), method.end(), method.begin(), ::tolower);
89 if (method !=
"rsassa-pss" && method !=
"rsassa-pss-sha256" && method !=
"ed25519") {
90 throw SecurityException(repository, std::string(
"Unsupported sign method: ") + (*sig)[
"method"].asString());
93 if (keys_.count(keyid) == 0U) {
94 LOG_DEBUG <<
"Signed by unknown KeyId: " << keyid <<
". Skipping.";
98 if (keys_for_role_.count(std::make_pair(role, keyid)) == 0U) {
99 LOG_WARNING <<
"KeyId " << keyid <<
" is not valid to sign for this role (" << role.ToString() <<
").";
102 const std::string signature = (*sig)[
"sig"].asString();
103 if (keys_[keyid].VerifySignature(signature, canonical)) {
106 LOG_WARNING <<
"Signature was present but invalid: " << signature <<
" with KeyId: " << keyid;
109 const int64_t threshold = thresholds_for_role_[role];
110 if (threshold < kMinSignatures || kMaxSignatures < threshold) {
115 if (signatures.size() == 1 && valid_signatures == 0) {
118 if (valid_signatures < threshold) {