| // Copyright 2020 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "attestation/server/certificate_queue.h" |
| |
| #include <string> |
| #include <utility> |
| |
| namespace attestation { |
| |
| namespace { |
| |
| // The URL query style separator used to concat username and the key label. |
| constexpr char kNameLabelSeparator[] = "?key_label="; |
| |
| // Compares all the field other than |aca_type|, |username|, and |key_label| of |
| // |request1| and |request2|; returns |false| if any mismatch. |
| bool HaveConsistentConfigs(const GetCertificateRequest& request1, |
| const GetCertificateRequest& request2) { |
| DCHECK_EQ(request1.username(), request2.username()); |
| DCHECK_EQ(request1.aca_type(), request2.aca_type()); |
| DCHECK_EQ(request1.key_label(), request2.key_label()); |
| return request1.certificate_profile() == request2.certificate_profile() && |
| request1.request_origin() == request2.request_origin() && |
| request1.key_type() == request2.key_type(); |
| } |
| |
| } // namespace |
| |
| CertificateQueue::CertificateQueue(size_t alias_limit) |
| : alias_limit_(alias_limit) {} |
| |
| CertificateQueue::PushResult CertificateQueue::Push( |
| const std::shared_ptr<AttestationFlowData>& data) { |
| DCHECK(data->shall_get_certificate()); |
| auto& aliases = table_[data]; |
| if (aliases.size() == alias_limit_) { |
| return PushResult::kAliasLimit; |
| } |
| // Checks the consistency of the cert requests. |
| if (!aliases.empty() && |
| !HaveConsistentConfigs(aliases[0]->get_certificate_request(), |
| data->get_certificate_request())) { |
| return PushResult::kInconsistentConfig; |
| } |
| aliases.push_back(data); |
| return PushResult::kSuccess; |
| } |
| |
| bool CertificateQueue::HasAnyAlias( |
| const std::shared_ptr<AttestationFlowData>& data) const { |
| auto iter = table_.find(data); |
| return iter != table_.end(); |
| } |
| |
| std::vector<std::shared_ptr<AttestationFlowData>> |
| CertificateQueue::PopAllAliases( |
| const std::shared_ptr<AttestationFlowData>& data) { |
| auto iter = table_.find(data); |
| if (iter == table_.end()) { |
| return {}; |
| } |
| // Swaps out the aliases and erases the entry. |
| auto aliases = std::move(iter->second); |
| table_.erase(iter); |
| return aliases; |
| } |
| |
| size_t CertificateQueue::DataHash::operator()( |
| const std::shared_ptr<AttestationFlowData>& data) const { |
| // By design, we don't hash |aca_type|. |
| return std::hash<std::string>()(data->username() + kNameLabelSeparator + |
| data->key_label()); |
| } |
| |
| bool CertificateQueue::DataEqual::operator()( |
| const std::shared_ptr<AttestationFlowData>& data1, |
| const std::shared_ptr<AttestationFlowData>& data2) const { |
| return data1->aca_type() == data2->aca_type() && |
| data1->username() == data2->username() && |
| data1->key_label() == data2->key_label(); |
| } |
| |
| } // namespace attestation |