// Copyright (c) 2012 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 <vector>

#include <gtest/gtest.h>

#include "base/logging.h"
#include "permission_broker/deny_unsafe_hidraw_device_rule.h"

#define MAKE_DESCRIPTOR(array) GenerateReportDescriptor(array, sizeof(array))

namespace permission_broker {

namespace {

// Some invalid descriptors.
const uint8_t kInvalidDescriptor0[] = { 0x1 };
const uint8_t kInvalidDescriptor1[] = { 0x6 };
const uint8_t kInvalidDescriptor2[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

// Interface descriptor contents from a LUFA TinyHID firmware.
const uint8_t kLUFATestFirmwareDescriptor[] = {
  0x6, 0x0, 0xff, 0x9, 0x1, 0xa1, 0x1, 0x9, 0x2, 0x15, 0x0, 0x25, 0xff, 0x75,
  0x8, 0x95, 0x8, 0x81, 0x2, 0x9, 0x3, 0x15, 0x0, 0x25, 0xff, 0x75, 0x8, 0x95,
  0x8, 0x91, 0x2, 0xc0
};

// Interface descriptor contents from a Logitech G13 controller.
const uint8_t kLogitechG13Descriptor[] = {
  0x6, 0x0, 0xff, 0x9, 0x0, 0xa1, 0x1, 0x15, 0x0, 0x26, 0xff, 0x0, 0x9, 0x1,
  0x85, 0x1, 0x95, 0x7, 0x75, 0x8, 0x81, 0x2, 0x85, 0x3, 0x9, 0x2, 0x96, 0xdf,
  0x3, 0x91, 0x2, 0x85, 0x7, 0x9, 0x3, 0x95, 0x4, 0xb1, 0x2, 0x85, 0x4, 0x9,
  0x4, 0xb1, 0x2, 0x85, 0x5, 0x9, 0x5, 0xb1, 0x2, 0x85, 0x6, 0x9, 0x6, 0x96,
  0x1, 0x1, 0xb1, 0x2, 0xc0
};

// Interface descriptor contents from the keyboard interface of GCS1784
// KVM Switch.
const uint8_t kSampleKeyboardDescriptor[] = {
  0x5, 0x1, 0x9, 0x6, 0xa1, 0x1, 0x5, 0x7, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x0,
  0x25, 0x1, 0x75, 0x1, 0x95, 0x8, 0x81, 0x2, 0x95, 0x1, 0x75, 0x8, 0x81, 0x1,
  0x95, 0x5, 0x75, 0x1, 0x5, 0x8, 0x19, 0x1, 0x29, 0x5, 0x91, 0x2, 0x95, 0x1,
  0x75, 0x3, 0x91, 0x1, 0x5, 0x7, 0x95, 0x6, 0x75, 0x8, 0x15, 0x0, 0x26, 0xff,
  0x0, 0x19, 0x0, 0x2a, 0xff, 0x0, 0x81, 0x0, 0xc0
};

// Interface descriptor contents from the mouse interface of an GCS1784
// KVM Switch.
const uint8_t kSampleMouseDescriptor[] = {
  0x5, 0x1, 0x9, 0x2, 0xa1, 0x1, 0x9, 0x1, 0xa1, 0x0, 0x5, 0x9, 0x19, 0x1, 0x29,
  0x5, 0x15, 0x0, 0x25, 0x1, 0x95, 0x5, 0x75, 0x1, 0x81, 0x2, 0x95, 0x1, 0x75,
  0x3, 0x81, 0x1, 0x5, 0x1, 0x9, 0x30, 0x9, 0x31, 0x9, 0x38, 0x15, 0x81, 0x25,
  0x7f, 0x75, 0x8, 0x95, 0x3, 0x81, 0x6, 0xc0, 0xc0
};

HidReportDescriptor GenerateReportDescriptor(const uint8_t raw_data[],
                                             size_t size) {
  HidReportDescriptor descriptor;
  descriptor.size = size;
  memcpy(&descriptor.data[0], &raw_data[0], size);
  return descriptor;
}

bool IsDeviceSafe(const std::vector<HidUsage>& usages) {
  for (std::vector<HidUsage>::const_iterator iter = usages.begin();
       iter != usages.end(); ++iter) {
    if (DenyUnsafeHidrawDeviceRule::IsUnsafeUsage(*iter))
      return false;
  }
  return true;
}

}  // namespace

class DenyUnsafeHidrawDeviceRuleTest : public testing::Test {
 public:
  DenyUnsafeHidrawDeviceRuleTest() = default;
  ~DenyUnsafeHidrawDeviceRuleTest() override = default;

 private:
  DISALLOW_COPY_AND_ASSIGN(DenyUnsafeHidrawDeviceRuleTest);
};

TEST_F(DenyUnsafeHidrawDeviceRuleTest, IgnoreInvalidDescriptors) {
  std::vector<HidUsage> usages;
  ASSERT_FALSE(
      HidrawSubsystemUdevRule::ParseToplevelCollectionUsages(
          MAKE_DESCRIPTOR(kInvalidDescriptor0), &usages));
  ASSERT_FALSE(
      HidrawSubsystemUdevRule::ParseToplevelCollectionUsages(
          MAKE_DESCRIPTOR(kInvalidDescriptor1), &usages));
  ASSERT_FALSE(
      HidrawSubsystemUdevRule::ParseToplevelCollectionUsages(
          MAKE_DESCRIPTOR(kInvalidDescriptor2), &usages));
}

TEST_F(DenyUnsafeHidrawDeviceRuleTest, IgnoreSafeDevices) {
  std::vector<HidUsage> usages;
  ASSERT_TRUE(
      HidrawSubsystemUdevRule::ParseToplevelCollectionUsages(
          MAKE_DESCRIPTOR(kLUFATestFirmwareDescriptor), &usages));
  ASSERT_EQ(1u, usages.size());
  ASSERT_TRUE(IsDeviceSafe(usages));

  usages.clear();
  ASSERT_TRUE(
      HidrawSubsystemUdevRule::ParseToplevelCollectionUsages(
          MAKE_DESCRIPTOR(kLogitechG13Descriptor), &usages));
  ASSERT_EQ(1u, usages.size());
  ASSERT_TRUE(IsDeviceSafe(usages));
}

TEST_F(DenyUnsafeHidrawDeviceRuleTest, DenyKeyboardAccess) {
  std::vector<HidUsage> usages;
  ASSERT_TRUE(
      HidrawSubsystemUdevRule::ParseToplevelCollectionUsages(
          MAKE_DESCRIPTOR(kSampleKeyboardDescriptor), &usages));
  ASSERT_EQ(1u, usages.size());
  ASSERT_FALSE(IsDeviceSafe(usages));
}

TEST_F(DenyUnsafeHidrawDeviceRuleTest, DenyMouseAccess) {
  std::vector<HidUsage> usages;
  ASSERT_TRUE(
      HidrawSubsystemUdevRule::ParseToplevelCollectionUsages(
          MAKE_DESCRIPTOR(kSampleMouseDescriptor), &usages));
  ASSERT_EQ(1u, usages.size());
  ASSERT_FALSE(IsDeviceSafe(usages));
}

}  // namespace permission_broker
