blob: 5c7039f0a0083193d5a242abe393ad9ef186e691 [file] [log] [blame]
// 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 <gmock/gmock.h>
#include <gtest/gtest.h>
#include "attestation/common/attestation_interface.h"
#include "attestation/server/attestation_flow.h"
namespace attestation {
namespace {
using ::testing::ElementsAreArray;
constexpr size_t kAliasLimit = 10;
constexpr char kUsername1[] = "user1";
constexpr char kUsername2[] = "user2";
constexpr char kKeyLabel1[] = "label1";
constexpr char kKeyLabel2[] = "label2";
// Makes an |AttestationFlowData| with |request| and a dummy callback.
std::shared_ptr<AttestationFlowData> MakeAttestationFlowData(
const GetCertificateRequest& request) {
AttestationInterface::GetCertificateCallback callback;
return std::make_shared<AttestationFlowData>(request, callback);
}
// Makes a |GetCertificateRequest| with |username| and |key_label|, and makes an
// |AttestationFlowData| with it and a dummy callback.
std::shared_ptr<AttestationFlowData> MakeAttestationFlowData(
ACAType aca_type,
const std::string& username,
const std::string& key_label) {
GetCertificateRequest request;
request.set_aca_type(aca_type);
request.set_username(username);
request.set_key_label(key_label);
AttestationInterface::GetCertificateCallback callback;
return std::make_shared<AttestationFlowData>(request, callback);
}
std::shared_ptr<AttestationFlowData> MakeDummyAttestationFlowData() {
return MakeAttestationFlowData(DEFAULT_ACA, "", "");
}
} // namespace
TEST(CertificateQueueTest, PushSuccessUntilLimitPerAlias) {
CertificateQueue certificate_queue(kAliasLimit);
std::vector<std::shared_ptr<AttestationFlowData>> entries;
// For each combination of aca type, username, and key_label, the size of the
// queue should be independently up to |kAliasLimit|.
for (ACAType aca_type : {DEFAULT_ACA, TEST_ACA}) {
for (const char* username : {kUsername1, kUsername2}) {
for (const char* key_label : {kKeyLabel1, kKeyLabel2}) {
std::vector<std::shared_ptr<AttestationFlowData>> entries;
for (int i = 0; i < kAliasLimit; ++i) {
EXPECT_EQ(certificate_queue.Push(
MakeAttestationFlowData(aca_type, username, key_label)),
CertificateQueue::PushResult::kSuccess);
}
// Up to the limit, the push operation should fail.
EXPECT_EQ(certificate_queue.Push(
MakeAttestationFlowData(aca_type, username, key_label)),
CertificateQueue::PushResult::kAliasLimit);
}
}
}
}
TEST(CertificateQueueTest, ConsistentInputOutput) {
CertificateQueue certificate_queue(kAliasLimit);
std::vector<std::shared_ptr<AttestationFlowData>> entries;
for (int i = 0; i < kAliasLimit; ++i) {
entries.push_back(MakeDummyAttestationFlowData());
EXPECT_EQ(certificate_queue.Push(entries.back()),
CertificateQueue::PushResult::kSuccess);
}
// This should be |true| if the queue is not empty.
EXPECT_TRUE(certificate_queue.HasAnyAlias(MakeDummyAttestationFlowData()));
// Popped items should match the entries we push into the queue.
EXPECT_THAT(certificate_queue.PopAllAliases(MakeDummyAttestationFlowData()),
ElementsAreArray(entries));
// Makes sure after popping the entries, the queue is empty.
EXPECT_TRUE(
certificate_queue.PopAllAliases(MakeDummyAttestationFlowData()).empty());
// And this should be |false| if the queue is empty.
EXPECT_FALSE(certificate_queue.HasAnyAlias(MakeDummyAttestationFlowData()));
}
TEST(CertificateQueueTest, InconsistentConfig) {
CertificateQueue certificate_queue(kAliasLimit);
auto first_entry = MakeDummyAttestationFlowData();
EXPECT_EQ(certificate_queue.Push(first_entry),
CertificateQueue::PushResult::kSuccess);
GetCertificateRequest inconsistent_request;
inconsistent_request = first_entry->get_certificate_request();
inconsistent_request.set_certificate_profile(XTS_CERTIFICATE);
EXPECT_EQ(
certificate_queue.Push(MakeAttestationFlowData(inconsistent_request)),
CertificateQueue::PushResult::kInconsistentConfig);
inconsistent_request = first_entry->get_certificate_request();
inconsistent_request.set_request_origin("inconsistent origin");
EXPECT_EQ(
certificate_queue.Push(MakeAttestationFlowData(inconsistent_request)),
CertificateQueue::PushResult::kInconsistentConfig);
inconsistent_request = first_entry->get_certificate_request();
inconsistent_request.set_key_type(KEY_TYPE_ECC);
ASSERT_NE(first_entry->get_certificate_request().key_type(),
inconsistent_request.key_type());
EXPECT_EQ(
certificate_queue.Push(MakeAttestationFlowData(inconsistent_request)),
CertificateQueue::PushResult::kInconsistentConfig);
}
} // namespace attestation