1 // Copyright 2019 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/integration/gcpkms/gcp_kms_aead.h"
18
19 #include <memory>
20 #include <string>
21
22 #include "google/cloud/kms/v1/service.grpc.pb.h"
23 #include "absl/memory/memory.h"
24 #include "absl/status/status.h"
25 #include "absl/strings/str_cat.h"
26 #include "absl/strings/string_view.h"
27 #include "tink/aead.h"
28 #include "tink/util/status.h"
29 #include "tink/util/statusor.h"
30
31 namespace crypto {
32 namespace tink {
33 namespace integration {
34 namespace gcpkms {
35
36 using ::google::cloud::kms::v1::DecryptRequest;
37 using ::google::cloud::kms::v1::DecryptResponse;
38 using ::google::cloud::kms::v1::EncryptRequest;
39 using ::google::cloud::kms::v1::EncryptResponse;
40 using ::google::cloud::kms::v1::KeyManagementService;
41
New(absl::string_view key_name,std::shared_ptr<KeyManagementService::Stub> kms_stub)42 util::StatusOr<std::unique_ptr<Aead>> GcpKmsAead::New(
43 absl::string_view key_name,
44 std::shared_ptr<KeyManagementService::Stub> kms_stub) {
45 if (key_name.empty()) {
46 return util::Status(absl::StatusCode::kInvalidArgument,
47 "Key URI cannot be empty.");
48 }
49 if (kms_stub == nullptr) {
50 return util::Status(absl::StatusCode::kInvalidArgument,
51 "KMS stub cannot be null.");
52 }
53 return absl::WrapUnique(new GcpKmsAead(key_name, kms_stub));
54 }
55
Encrypt(absl::string_view plaintext,absl::string_view associated_data) const56 util::StatusOr<std::string> GcpKmsAead::Encrypt(
57 absl::string_view plaintext, absl::string_view associated_data) const {
58 EncryptRequest req;
59 req.set_name(key_name_);
60 req.set_plaintext(std::string(plaintext));
61 req.set_additional_authenticated_data(std::string(associated_data));
62
63 EncryptResponse resp;
64 grpc::ClientContext context;
65 context.AddMetadata("x-goog-request-params",
66 absl::StrCat("name=", key_name_));
67
68 grpc::Status status = kms_stub_->Encrypt(&context, req, &resp);
69
70 if (!status.ok()) {
71 return util::Status(
72 absl::StatusCode::kInvalidArgument,
73 absl::StrCat("GCP KMS encryption failed: ", status.error_message()));
74 }
75 return resp.ciphertext();
76 }
77
Decrypt(absl::string_view ciphertext,absl::string_view associated_data) const78 util::StatusOr<std::string> GcpKmsAead::Decrypt(
79 absl::string_view ciphertext, absl::string_view associated_data) const {
80 DecryptRequest req;
81 req.set_name(key_name_);
82 req.set_ciphertext(std::string(ciphertext));
83 req.set_additional_authenticated_data(std::string(associated_data));
84
85 DecryptResponse resp;
86 grpc::ClientContext context;
87 context.AddMetadata("x-goog-request-params",
88 absl::StrCat("name=", key_name_));
89
90 grpc::Status status = kms_stub_->Decrypt(&context, req, &resp);
91
92 if (!status.ok()) {
93 return util::Status(
94 absl::StatusCode::kInvalidArgument,
95 absl::StrCat("GCP KMS encryption failed: ", status.error_message()));
96 }
97 return resp.plaintext();
98 }
99
100 } // namespace gcpkms
101 } // namespace integration
102 } // namespace tink
103 } // namespace crypto
104