pin_unittest.cc 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "device/fido/pin.h"
  5. #include "components/cbor/reader.h"
  6. #include "device/fido/fido_test_data.h"
  7. #include "device/fido/pin_internal.h"
  8. #include "testing/gmock/include/gmock/gmock.h"
  9. #include "testing/gtest/include/gtest/gtest.h"
  10. #include "third_party/boringssl/src/include/openssl/aes.h"
  11. #include "third_party/boringssl/src/include/openssl/ec.h"
  12. #include "third_party/boringssl/src/include/openssl/ec_key.h"
  13. #include "third_party/boringssl/src/include/openssl/mem.h"
  14. #include "third_party/boringssl/src/include/openssl/nid.h"
  15. namespace device {
  16. namespace {
  17. using testing::ElementsAreArray;
  18. using testing::Not;
  19. class PINProtocolTest : public ::testing::TestWithParam<PINUVAuthProtocol> {
  20. protected:
  21. void SetUp() override {
  22. peer_key_.reset(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
  23. CHECK(EC_KEY_generate_key(peer_key_.get()));
  24. }
  25. const pin::Protocol& pin_protocol() {
  26. return pin::ProtocolVersion(GetParam());
  27. }
  28. pin::KeyAgreementResponse PeerKeyAgreement() {
  29. std::array<uint8_t, kP256X962Length> peer_x962;
  30. CHECK_EQ(EC_POINT_point2oct(EC_KEY_get0_group(peer_key_.get()),
  31. EC_KEY_get0_public_key(peer_key_.get()),
  32. POINT_CONVERSION_UNCOMPRESSED, peer_x962.data(),
  33. peer_x962.size(), nullptr /* BN_CTX */),
  34. peer_x962.size());
  35. const absl::optional<pin::KeyAgreementResponse> peer_response =
  36. pin::KeyAgreementResponse::ParseFromCOSE(
  37. pin::EncodeCOSEPublicKey(peer_x962));
  38. CHECK(peer_response);
  39. return *peer_response;
  40. }
  41. EC_KEY* peer_key() { return peer_key_.get(); }
  42. bssl::UniquePtr<EC_KEY> peer_key_;
  43. };
  44. TEST_P(PINProtocolTest, EncapsulateDecapsulate) {
  45. // Encapsulate() and CalculateSharedKey() should yield the same shared secret.
  46. std::vector<uint8_t> shared_key;
  47. const std::array<uint8_t, kP256X962Length> platform_x962 =
  48. pin_protocol().Encapsulate(PeerKeyAgreement(), &shared_key);
  49. const bssl::UniquePtr<EC_GROUP> p256(
  50. EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
  51. const bssl::UniquePtr<EC_POINT> platform_point(EC_POINT_new(p256.get()));
  52. ASSERT_TRUE(EC_POINT_oct2point(p256.get(), platform_point.get(),
  53. platform_x962.data(), platform_x962.size(),
  54. /*ctx=*/nullptr));
  55. EXPECT_EQ(shared_key.size(),
  56. GetParam() == PINUVAuthProtocol::kV1 ? 32u : 64u);
  57. EXPECT_THAT(
  58. pin_protocol().CalculateSharedKey(peer_key(), platform_point.get()),
  59. ElementsAreArray(shared_key));
  60. }
  61. TEST_P(PINProtocolTest, EncryptDecrypt) {
  62. constexpr char kTestPlaintext[] = "pinprotocoltestpinprotocoltest_";
  63. static_assert(sizeof(kTestPlaintext) % AES_BLOCK_SIZE == 0u, "");
  64. std::vector<uint8_t> shared_key;
  65. pin_protocol().Encapsulate(PeerKeyAgreement(), &shared_key);
  66. const std::vector<uint8_t> ciphertext = pin_protocol().Encrypt(
  67. shared_key, base::as_bytes(base::make_span(kTestPlaintext)));
  68. ASSERT_FALSE(ciphertext.empty());
  69. EXPECT_THAT(pin_protocol().Decrypt(shared_key, ciphertext),
  70. ElementsAreArray(base::make_span(kTestPlaintext)));
  71. }
  72. TEST_P(PINProtocolTest, AuthenticateVerify) {
  73. constexpr char kTestMessage[] = "pin protocol test";
  74. std::vector<uint8_t> shared_key;
  75. pin_protocol().Encapsulate(PeerKeyAgreement(), &shared_key);
  76. const std::vector<uint8_t> mac = pin_protocol().Authenticate(
  77. shared_key, base::as_bytes(base::make_span(kTestMessage)));
  78. ASSERT_FALSE(mac.empty());
  79. EXPECT_TRUE(pin_protocol().Verify(
  80. shared_key, base::as_bytes(base::make_span(kTestMessage)), mac));
  81. }
  82. INSTANTIATE_TEST_SUITE_P(All,
  83. PINProtocolTest,
  84. testing::Values(PINUVAuthProtocol::kV1,
  85. PINUVAuthProtocol::kV2));
  86. } // namespace
  87. } // namespace device