普通文本  |  383行  |  14.84 KB

//
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include <string>

#include <brillo/bind_lambda.h>
#include <brillo/dbus/dbus_object_test_helpers.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_exported_object.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "attestation/common/dbus_interface.h"
#include "attestation/common/mock_attestation_interface.h"
#include "attestation/server/dbus_service.h"

using testing::_;
using testing::Invoke;
using testing::NiceMock;
using testing::Return;
using testing::StrictMock;
using testing::WithArgs;

namespace attestation {

class DBusServiceTest : public testing::Test {
 public:
  ~DBusServiceTest() override = default;
  void SetUp() override {
    dbus::Bus::Options options;
    mock_bus_ = new NiceMock<dbus::MockBus>(options);
    dbus::ObjectPath path(kAttestationServicePath);
    mock_exported_object_ = new NiceMock<dbus::MockExportedObject>(
        mock_bus_.get(), path);
    ON_CALL(*mock_bus_, GetExportedObject(path))
        .WillByDefault(Return(mock_exported_object_.get()));
    dbus_service_.reset(new DBusService(mock_bus_, &mock_service_));
    dbus_service_->Register(brillo::dbus_utils::AsyncEventSequencer::
                                GetDefaultCompletionAction());
  }

  std::unique_ptr<dbus::Response> CallMethod(dbus::MethodCall* method_call) {
    return brillo::dbus_utils::testing::CallMethod(
        dbus_service_->dbus_object_, method_call);
  }

  std::unique_ptr<dbus::MethodCall> CreateMethodCall(
      const std::string& method_name) {
    std::unique_ptr<dbus::MethodCall> call(new dbus::MethodCall(
        kAttestationInterface, method_name));
    call->SetSerial(1);
    return call;
  }

 protected:
  scoped_refptr<dbus::MockBus> mock_bus_;
  scoped_refptr<dbus::MockExportedObject> mock_exported_object_;
  StrictMock<MockAttestationInterface> mock_service_;
  std::unique_ptr<DBusService> dbus_service_;
};

TEST_F(DBusServiceTest, CreateGoogleAttestedKey) {
  CreateGoogleAttestedKeyRequest request;
  request.set_key_label("label");
  request.set_key_type(KEY_TYPE_ECC);
  request.set_key_usage(KEY_USAGE_SIGN);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("username");
  request.set_origin("origin");
  EXPECT_CALL(mock_service_, CreateGoogleAttestedKey(_, _))
      .WillOnce(Invoke([](
          const CreateGoogleAttestedKeyRequest& request,
          const AttestationInterface::
              CreateGoogleAttestedKeyCallback& callback) {
        EXPECT_EQ("label", request.key_label());
        EXPECT_EQ(KEY_TYPE_ECC, request.key_type());
        EXPECT_EQ(KEY_USAGE_SIGN, request.key_usage());
        EXPECT_EQ(ENTERPRISE_MACHINE_CERTIFICATE,
                  request.certificate_profile());
        EXPECT_EQ("username", request.username());
        EXPECT_EQ("origin", request.origin());
        CreateGoogleAttestedKeyReply reply;
        reply.set_status(STATUS_SUCCESS);
        reply.set_certificate_chain("certificate");
        reply.set_server_error("server_error");
        callback.Run(reply);
      }));
  std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(
      kCreateGoogleAttestedKey);
  dbus::MessageWriter writer(call.get());
  writer.AppendProtoAsArrayOfBytes(request);
  auto response = CallMethod(call.get());
  dbus::MessageReader reader(response.get());
  CreateGoogleAttestedKeyReply reply;
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply));
  EXPECT_EQ(STATUS_SUCCESS, reply.status());
  EXPECT_EQ("certificate", reply.certificate_chain());
  EXPECT_EQ("server_error", reply.server_error());
}

TEST_F(DBusServiceTest, CopyableCallback) {
  EXPECT_CALL(mock_service_, CreateGoogleAttestedKey(_, _))
      .WillOnce(WithArgs<1>(Invoke([](const AttestationInterface::
          CreateGoogleAttestedKeyCallback& callback) {
        // Copy the callback, then call the original.
        CreateGoogleAttestedKeyReply reply;
        base::Closure copy = base::Bind(callback, reply);
        callback.Run(reply);
      })));
  std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(
      kCreateGoogleAttestedKey);
  CreateGoogleAttestedKeyRequest request;
  dbus::MessageWriter writer(call.get());
  writer.AppendProtoAsArrayOfBytes(request);
  auto response = CallMethod(call.get());
  dbus::MessageReader reader(response.get());
  CreateGoogleAttestedKeyReply reply;
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply));
}

TEST_F(DBusServiceTest, GetKeyInfo) {
  GetKeyInfoRequest request;
  request.set_key_label("label");
  request.set_username("username");
  EXPECT_CALL(mock_service_, GetKeyInfo(_, _))
      .WillOnce(Invoke([](
          const GetKeyInfoRequest& request,
          const AttestationInterface::GetKeyInfoCallback& callback) {
        EXPECT_EQ("label", request.key_label());
        EXPECT_EQ("username", request.username());
        GetKeyInfoReply reply;
        reply.set_status(STATUS_SUCCESS);
        reply.set_key_type(KEY_TYPE_ECC);
        reply.set_key_usage(KEY_USAGE_SIGN);
        reply.set_public_key("public_key");
        reply.set_certify_info("certify");
        reply.set_certify_info_signature("signature");
        reply.set_certificate("certificate");
        callback.Run(reply);
      }));
  std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(kGetKeyInfo);
  dbus::MessageWriter writer(call.get());
  writer.AppendProtoAsArrayOfBytes(request);
  auto response = CallMethod(call.get());
  dbus::MessageReader reader(response.get());
  GetKeyInfoReply reply;
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply));
  EXPECT_EQ(STATUS_SUCCESS, reply.status());
  EXPECT_EQ(KEY_TYPE_ECC, reply.key_type());
  EXPECT_EQ(KEY_USAGE_SIGN, reply.key_usage());
  EXPECT_EQ("public_key", reply.public_key());
  EXPECT_EQ("certify", reply.certify_info());
  EXPECT_EQ("signature", reply.certify_info_signature());
  EXPECT_EQ("certificate", reply.certificate());
}

TEST_F(DBusServiceTest, GetEndorsementInfo) {
  GetEndorsementInfoRequest request;
  request.set_key_type(KEY_TYPE_ECC);
  EXPECT_CALL(mock_service_, GetEndorsementInfo(_, _))
      .WillOnce(Invoke([](
          const GetEndorsementInfoRequest& request,
          const AttestationInterface::GetEndorsementInfoCallback& callback) {
        EXPECT_EQ(KEY_TYPE_ECC, request.key_type());
        GetEndorsementInfoReply reply;
        reply.set_status(STATUS_SUCCESS);
        reply.set_ek_public_key("public_key");
        reply.set_ek_certificate("certificate");
        callback.Run(reply);
      }));
  std::unique_ptr<dbus::MethodCall> call =
      CreateMethodCall(kGetEndorsementInfo);
  dbus::MessageWriter writer(call.get());
  writer.AppendProtoAsArrayOfBytes(request);
  auto response = CallMethod(call.get());
  dbus::MessageReader reader(response.get());
  GetEndorsementInfoReply reply;
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply));
  EXPECT_EQ(STATUS_SUCCESS, reply.status());
  EXPECT_EQ("public_key", reply.ek_public_key());
  EXPECT_EQ("certificate", reply.ek_certificate());
}

TEST_F(DBusServiceTest, GetAttestationKeyInfo) {
  GetAttestationKeyInfoRequest request;
  request.set_key_type(KEY_TYPE_ECC);
  EXPECT_CALL(mock_service_, GetAttestationKeyInfo(_, _))
      .WillOnce(Invoke([](
          const GetAttestationKeyInfoRequest& request,
          const AttestationInterface::GetAttestationKeyInfoCallback& callback) {
        EXPECT_EQ(KEY_TYPE_ECC, request.key_type());
        GetAttestationKeyInfoReply reply;
        reply.set_status(STATUS_SUCCESS);
        reply.set_public_key("public_key");
        reply.set_public_key_tpm_format("public_key_tpm_format");
        reply.set_certificate("certificate");
        reply.mutable_pcr0_quote()->set_quote("pcr0");
        reply.mutable_pcr1_quote()->set_quote("pcr1");
        callback.Run(reply);
      }));
  std::unique_ptr<dbus::MethodCall> call =
      CreateMethodCall(kGetAttestationKeyInfo);
  dbus::MessageWriter writer(call.get());
  writer.AppendProtoAsArrayOfBytes(request);
  auto response = CallMethod(call.get());
  dbus::MessageReader reader(response.get());
  GetAttestationKeyInfoReply reply;
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply));
  EXPECT_EQ(STATUS_SUCCESS, reply.status());
  EXPECT_EQ("public_key", reply.public_key());
  EXPECT_EQ("public_key_tpm_format", reply.public_key_tpm_format());
  EXPECT_EQ("certificate", reply.certificate());
  EXPECT_EQ("pcr0", reply.pcr0_quote().quote());
  EXPECT_EQ("pcr1", reply.pcr1_quote().quote());
}

TEST_F(DBusServiceTest, ActivateAttestationKey) {
  ActivateAttestationKeyRequest request;
  request.set_key_type(KEY_TYPE_ECC);
  request.mutable_encrypted_certificate()->set_asym_ca_contents("encrypted1");
  request.mutable_encrypted_certificate()->set_sym_ca_attestation("encrypted2");
  request.set_save_certificate(true);
  EXPECT_CALL(mock_service_, ActivateAttestationKey(_, _))
      .WillOnce(Invoke([](
          const ActivateAttestationKeyRequest& request,
          const AttestationInterface::ActivateAttestationKeyCallback&
              callback) {
        EXPECT_EQ(KEY_TYPE_ECC, request.key_type());
        EXPECT_EQ("encrypted1",
                  request.encrypted_certificate().asym_ca_contents());
        EXPECT_EQ("encrypted2",
                  request.encrypted_certificate().sym_ca_attestation());
        EXPECT_TRUE(request.save_certificate());
        ActivateAttestationKeyReply reply;
        reply.set_status(STATUS_SUCCESS);
        reply.set_certificate("certificate");
        callback.Run(reply);
      }));
  std::unique_ptr<dbus::MethodCall> call =
      CreateMethodCall(kActivateAttestationKey);
  dbus::MessageWriter writer(call.get());
  writer.AppendProtoAsArrayOfBytes(request);
  auto response = CallMethod(call.get());
  dbus::MessageReader reader(response.get());
  ActivateAttestationKeyReply reply;
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply));
  EXPECT_EQ(STATUS_SUCCESS, reply.status());
  EXPECT_EQ("certificate", reply.certificate());
}

TEST_F(DBusServiceTest, CreateCertifiableKey) {
  CreateCertifiableKeyRequest request;
  request.set_key_label("label");
  request.set_key_type(KEY_TYPE_ECC);
  request.set_key_usage(KEY_USAGE_SIGN);
  request.set_username("user");
  EXPECT_CALL(mock_service_, CreateCertifiableKey(_, _))
      .WillOnce(Invoke([](
          const CreateCertifiableKeyRequest& request,
          const AttestationInterface::CreateCertifiableKeyCallback& callback) {
        EXPECT_EQ("label", request.key_label());
        EXPECT_EQ(KEY_TYPE_ECC, request.key_type());
        EXPECT_EQ(KEY_USAGE_SIGN, request.key_usage());
        EXPECT_EQ("user", request.username());
        CreateCertifiableKeyReply reply;
        reply.set_status(STATUS_SUCCESS);
        reply.set_public_key("public_key");
        reply.set_certify_info("certify_info");
        reply.set_certify_info_signature("signature");
        callback.Run(reply);
      }));
  std::unique_ptr<dbus::MethodCall> call =
      CreateMethodCall(kCreateCertifiableKey);
  dbus::MessageWriter writer(call.get());
  writer.AppendProtoAsArrayOfBytes(request);
  auto response = CallMethod(call.get());
  dbus::MessageReader reader(response.get());
  CreateCertifiableKeyReply reply;
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply));
  EXPECT_EQ(STATUS_SUCCESS, reply.status());
  EXPECT_EQ("public_key", reply.public_key());
  EXPECT_EQ("certify_info", reply.certify_info());
  EXPECT_EQ("signature", reply.certify_info_signature());
}

TEST_F(DBusServiceTest, Decrypt) {
  DecryptRequest request;
  request.set_key_label("label");
  request.set_username("user");
  request.set_encrypted_data("data");
  EXPECT_CALL(mock_service_, Decrypt(_, _))
      .WillOnce(Invoke([](
          const DecryptRequest& request,
          const AttestationInterface::DecryptCallback& callback) {
        EXPECT_EQ("label", request.key_label());
        EXPECT_EQ("user", request.username());
        EXPECT_EQ("data", request.encrypted_data());
        DecryptReply reply;
        reply.set_status(STATUS_SUCCESS);
        reply.set_decrypted_data("data");
        callback.Run(reply);
      }));
  std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(kDecrypt);
  dbus::MessageWriter writer(call.get());
  writer.AppendProtoAsArrayOfBytes(request);
  auto response = CallMethod(call.get());
  dbus::MessageReader reader(response.get());
  DecryptReply reply;
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply));
  EXPECT_EQ(STATUS_SUCCESS, reply.status());
  EXPECT_EQ("data", reply.decrypted_data());
}

TEST_F(DBusServiceTest, Sign) {
  SignRequest request;
  request.set_key_label("label");
  request.set_username("user");
  request.set_data_to_sign("data");
  EXPECT_CALL(mock_service_, Sign(_, _))
      .WillOnce(Invoke([](
          const SignRequest& request,
          const AttestationInterface::SignCallback& callback) {
        EXPECT_EQ("label", request.key_label());
        EXPECT_EQ("user", request.username());
        EXPECT_EQ("data", request.data_to_sign());
        SignReply reply;
        reply.set_status(STATUS_SUCCESS);
        reply.set_signature("signature");
        callback.Run(reply);
      }));
  std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(kSign);
  dbus::MessageWriter writer(call.get());
  writer.AppendProtoAsArrayOfBytes(request);
  auto response = CallMethod(call.get());
  dbus::MessageReader reader(response.get());
  SignReply reply;
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply));
  EXPECT_EQ(STATUS_SUCCESS, reply.status());
  EXPECT_EQ("signature", reply.signature());
}

TEST_F(DBusServiceTest, RegisterKeyWithChapsToken) {
  RegisterKeyWithChapsTokenRequest request;
  request.set_key_label("label");
  request.set_username("user");
  EXPECT_CALL(mock_service_, RegisterKeyWithChapsToken(_, _))
      .WillOnce(Invoke([](
          const RegisterKeyWithChapsTokenRequest& request,
          const AttestationInterface::RegisterKeyWithChapsTokenCallback&
              callback) {
        EXPECT_EQ("label", request.key_label());
        EXPECT_EQ("user", request.username());
        RegisterKeyWithChapsTokenReply reply;
        reply.set_status(STATUS_SUCCESS);
        callback.Run(reply);
      }));
  std::unique_ptr<dbus::MethodCall> call =
      CreateMethodCall(kRegisterKeyWithChapsToken);
  dbus::MessageWriter writer(call.get());
  writer.AppendProtoAsArrayOfBytes(request);
  auto response = CallMethod(call.get());
  dbus::MessageReader reader(response.get());
  RegisterKeyWithChapsTokenReply reply;
  EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply));
  EXPECT_EQ(STATUS_SUCCESS, reply.status());
}


}  // namespace attestation