• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16 
17 #include "tink/hybrid/ecies_aead_hkdf_hybrid_encrypt.h"
18 
19 #include <memory>
20 #include <string>
21 #include <utility>
22 
23 #include "gtest/gtest.h"
24 #include "absl/memory/memory.h"
25 #include "tink/aead/aes_gcm_key_manager.h"
26 #include "tink/hybrid_encrypt.h"
27 #include "tink/internal/ec_util.h"
28 #include "tink/util/enums.h"
29 #include "tink/util/statusor.h"
30 #include "tink/util/test_util.h"
31 #include "proto/common.pb.h"
32 #include "proto/ecies_aead_hkdf.pb.h"
33 
34 using google::crypto::tink::EciesAeadHkdfPublicKey;
35 using google::crypto::tink::EcPointFormat;
36 using google::crypto::tink::EllipticCurveType;
37 using google::crypto::tink::HashType;
38 
39 
40 namespace crypto {
41 namespace tink {
42 namespace {
43 
44 class EciesAeadHkdfHybridEncryptTest : public ::testing::Test {
45  protected:
SetUp()46   void SetUp() override {
47   }
TearDown()48   void TearDown() override {
49   }
50 };
51 
TEST_F(EciesAeadHkdfHybridEncryptTest,testInvalidKeys)52 TEST_F(EciesAeadHkdfHybridEncryptTest, testInvalidKeys) {
53   {  // No fields set.
54     EciesAeadHkdfPublicKey recipient_key;
55     auto result = EciesAeadHkdfHybridEncrypt::New(recipient_key);
56     EXPECT_FALSE(result.ok());
57     EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code());
58     EXPECT_PRED_FORMAT2(testing::IsSubstring, "missing required fields",
59                         std::string(result.status().message()));
60   }
61 
62   {  // Only some fields set.
63     EciesAeadHkdfPublicKey recipient_key;
64     recipient_key.set_version(0);
65     recipient_key.set_x("some x bytes");
66     recipient_key.set_y("some y bytes");
67     auto result(EciesAeadHkdfHybridEncrypt::New(recipient_key));
68     EXPECT_FALSE(result.ok());
69     EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code());
70     EXPECT_PRED_FORMAT2(testing::IsSubstring, "missing required fields",
71                         std::string(result.status().message()));
72   }
73 
74   {  // Wrong EC type.
75     EciesAeadHkdfPublicKey recipient_key;
76     recipient_key.set_version(0);
77     recipient_key.set_x("some x bytes");
78     recipient_key.set_y("some y bytes");
79     recipient_key.mutable_params();
80     auto result(EciesAeadHkdfHybridEncrypt::New(recipient_key));
81     EXPECT_FALSE(result.ok());
82     EXPECT_EQ(absl::StatusCode::kUnimplemented, result.status().code());
83     EXPECT_PRED_FORMAT2(testing::IsSubstring, "Unsupported elliptic curve",
84                         std::string(result.status().message()));
85   }
86 
87   {  // Unsupported DEM key type.
88     EllipticCurveType curve = EllipticCurveType::NIST_P256;
89     auto test_key =
90         internal::NewEcKey(util::Enums::ProtoToSubtle(curve)).value();
91     EciesAeadHkdfPublicKey recipient_key;
92     recipient_key.set_version(0);
93     recipient_key.set_x(test_key.pub_x);
94     recipient_key.set_y(test_key.pub_y);
95     auto params = recipient_key.mutable_params();
96     params->mutable_kem_params()->set_curve_type(curve);
97     params->mutable_kem_params()->set_hkdf_hash_type(HashType::SHA256);
98     auto aead_dem = params->mutable_dem_params()->mutable_aead_dem();
99     aead_dem->set_type_url("some.type.url/that.is.not.supported");
100     auto result(EciesAeadHkdfHybridEncrypt::New(recipient_key));
101     EXPECT_FALSE(result.ok());
102     EXPECT_EQ(absl::StatusCode::kInvalidArgument, result.status().code());
103     EXPECT_PRED_FORMAT2(testing::IsSubstring, "Unsupported DEM",
104                         std::string(result.status().message()));
105   }
106 }
107 
TEST_F(EciesAeadHkdfHybridEncryptTest,testBasic)108 TEST_F(EciesAeadHkdfHybridEncryptTest, testBasic) {
109   // Prepare an ECIES key.
110   auto ecies_key = test::GetEciesAesGcmHkdfTestKey(
111       EllipticCurveType::NIST_P256,
112       EcPointFormat::UNCOMPRESSED,
113       HashType::SHA256,
114       32);
115 
116   // Generate and test many keys with various parameters.
117   std::string plaintext = "some plaintext";
118   std::string context_info = "some context info";
119   for (auto curve : {EllipticCurveType::NIST_P256, EllipticCurveType::NIST_P384,
120                      EllipticCurveType::NIST_P521}) {
121     for (auto ec_point_format :
122         {EcPointFormat::UNCOMPRESSED, EcPointFormat::COMPRESSED}) {
123       for (auto hash_type : {HashType::SHA256, HashType::SHA512}) {
124         for (uint32_t aes_gcm_key_size : {16, 32}) {
125           ecies_key = test::GetEciesAesGcmHkdfTestKey(
126               curve, ec_point_format, hash_type, aes_gcm_key_size);
127           auto result(EciesAeadHkdfHybridEncrypt::New(ecies_key.public_key()));
128           ASSERT_TRUE(result.ok()) << result.status()
129                                    << ecies_key.SerializeAsString();
130           std::unique_ptr<HybridEncrypt> hybrid_encrypt(
131               std::move(result.value()));
132 
133           // Use the primitive.
134           auto encrypt_result =
135               hybrid_encrypt->Encrypt(plaintext, context_info);
136           EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status();
137         }
138       }
139     }
140   }
141 }
142 
143 }  // namespace
144 }  // namespace tink
145 }  // namespace crypto
146