// 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 "tink/mac/aes_cmac_key_manager.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"
#include "tink/util/test_matchers.h"
#include "proto/aes_cmac.pb.h"

namespace crypto {
namespace tink {

namespace {

using ::crypto::tink::test::IsOk;
using ::google::crypto::tink::AesCmacKey;
using ::google::crypto::tink::AesCmacKeyFormat;
using ::google::crypto::tink::AesCmacParams;
using ::testing::Eq;
using ::testing::Not;
using ::testing::SizeIs;

TEST(AesCmacKeyManagerTest, Basics) {
  EXPECT_THAT(AesCmacKeyManager().get_version(), Eq(0));
  EXPECT_THAT(AesCmacKeyManager().get_key_type(),
              Eq("type.googleapis.com/google.crypto.tink.AesCmacKey"));
  EXPECT_THAT(AesCmacKeyManager().key_material_type(),
              Eq(google::crypto::tink::KeyData::SYMMETRIC));
}

TEST(AesCmacKeyManagerTest, ValidateEmptyKey) {
  EXPECT_THAT(AesCmacKeyManager().ValidateKey(AesCmacKey()), Not(IsOk()));
}

AesCmacParams ValidParams() {
  AesCmacParams params;
  params.set_tag_size(16);
  return params;
}

AesCmacKeyFormat ValidKeyFormat() {
  AesCmacKeyFormat format;
  *format.mutable_params() = ValidParams();
  format.set_key_size(32);
  return format;
}

TEST(AesCmacKeyManagerTest, ValidateEmptyKeyFormat) {
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(AesCmacKeyFormat()),
              Not(IsOk()));
}

TEST(AesCmacKeyManagerTest, ValidateSimpleKeyFormat) {
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(ValidKeyFormat()), IsOk());
}

TEST(AesCmacKeyManagerTest, ValidateKeyFormatKeySizes) {
  AesCmacKeyFormat format = ValidKeyFormat();

  format.set_key_size(0);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk()));

  format.set_key_size(1);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk()));

  format.set_key_size(15);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk()));

  format.set_key_size(16);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk()));

  format.set_key_size(17);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk()));

  format.set_key_size(31);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk()));

  format.set_key_size(32);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk());

  format.set_key_size(33);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk()));
}

TEST(AesCmacKeyManagerTest, ValidateKeyFormatTagSizes) {
  AesCmacKeyFormat format = ValidKeyFormat();

  format.mutable_params()->set_tag_size(0);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk()));

  format.mutable_params()->set_tag_size(9);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk()));

  format.mutable_params()->set_tag_size(10);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk());

  format.mutable_params()->set_tag_size(11);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk());

  format.mutable_params()->set_tag_size(12);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk());

  format.mutable_params()->set_tag_size(15);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk());

  format.mutable_params()->set_tag_size(16);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), IsOk());

  format.mutable_params()->set_tag_size(17);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk()));

  format.mutable_params()->set_tag_size(32);
  EXPECT_THAT(AesCmacKeyManager().ValidateKeyFormat(format), Not(IsOk()));
}

TEST(AesCmacKeyManagerTest, CreateKey) {
  AesCmacKeyFormat format = ValidKeyFormat();
  ASSERT_THAT(AesCmacKeyManager().CreateKey(format).status(), IsOk());
  AesCmacKey key = AesCmacKeyManager().CreateKey(format).ValueOrDie();
  EXPECT_THAT(key.version(), Eq(0));
  EXPECT_THAT(key.key_value(), SizeIs(format.key_size()));
  EXPECT_THAT(key.params().tag_size(), Eq(format.params().tag_size()));
}

TEST(AesCmacKeyManagerTest, ValidateKey) {
  AesCmacKeyFormat format = ValidKeyFormat();
  AesCmacKey key = AesCmacKeyManager().CreateKey(format).ValueOrDie();
  EXPECT_THAT(AesCmacKeyManager().ValidateKey(key), IsOk());
}

TEST(AesCmacKeyManagerTest, ValidateKeyInvalidVersion) {
  AesCmacKeyFormat format = ValidKeyFormat();
  AesCmacKey key = AesCmacKeyManager().CreateKey(format).ValueOrDie();
  key.set_version(1);
  EXPECT_THAT(AesCmacKeyManager().ValidateKey(key), Not(IsOk()));
}

TEST(AesCmacKeyManagerTest, ValidateKeyShortKey) {
  AesCmacKeyFormat format = ValidKeyFormat();
  AesCmacKey key = AesCmacKeyManager().CreateKey(format).ValueOrDie();
  key.set_key_value("0123456789abcdef");
  EXPECT_THAT(AesCmacKeyManager().ValidateKey(key), Not(IsOk()));
}

TEST(AesCmacKeyManagerTest, ValidateKeyLongTagSize) {
  AesCmacKeyFormat format = ValidKeyFormat();
  AesCmacKey key = AesCmacKeyManager().CreateKey(format).ValueOrDie();
  key.mutable_params()->set_tag_size(17);
  EXPECT_THAT(AesCmacKeyManager().ValidateKey(key), Not(IsOk()));
}


TEST(AesCmacKeyManagerTest, ValidateKeyTooShortTagSize) {
  AesCmacKeyFormat format = ValidKeyFormat();
  AesCmacKey key = AesCmacKeyManager().CreateKey(format).ValueOrDie();
  key.mutable_params()->set_tag_size(9);
  EXPECT_THAT(AesCmacKeyManager().ValidateKey(key), Not(IsOk()));
}

TEST(AesCmacKeyManagerTest, GetPrimitive) {
  AesCmacKeyFormat format = ValidKeyFormat();
  AesCmacKey key = AesCmacKeyManager().CreateKey(format).ValueOrDie();
  auto manager_mac_or = AesCmacKeyManager().GetPrimitive<Mac>(key);
  ASSERT_THAT(manager_mac_or.status(), IsOk());
  auto mac_value_or = manager_mac_or.ValueOrDie()->ComputeMac("some plaintext");
  ASSERT_THAT(mac_value_or.status(), IsOk());

  auto direct_mac_or =
      subtle::AesCmacBoringSsl::New(key.key_value(), key.params().tag_size());
  ASSERT_THAT(direct_mac_or.status(), IsOk());
  EXPECT_THAT(direct_mac_or.ValueOrDie()->VerifyMac(mac_value_or.ValueOrDie(),
                                                    "some plaintext"), IsOk());
}

}  // namespace
}  // namespace tink
}  // namespace crypto
