1 // Copyright 2022 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/mac/internal/chunked_mac_impl.h"
18
19 #include <memory>
20 #include <string>
21 #include <utility>
22
23 #include "absl/strings/string_view.h"
24 #include "openssl/crypto.h"
25 #include "tink/chunked_mac.h"
26 #include "tink/subtle/mac/stateful_mac.h"
27 #include "tink/subtle/stateful_cmac_boringssl.h"
28 #include "tink/subtle/stateful_hmac_boringssl.h"
29 #include "tink/util/enums.h"
30 #include "tink/util/secret_data.h"
31 #include "tink/util/status.h"
32 #include "tink/util/statusor.h"
33 #include "proto/aes_cmac.pb.h"
34 #include "proto/hmac.pb.h"
35
36 namespace crypto {
37 namespace tink {
38 namespace internal {
39
40 using ::google::crypto::tink::AesCmacKey;
41 using ::google::crypto::tink::HmacKey;
42
Update(absl::string_view data)43 util::Status ChunkedMacComputationImpl::Update(absl::string_view data) {
44 if (!status_.ok()) return status_;
45 return stateful_mac_->Update(data);
46 }
47
ComputeMac()48 util::StatusOr<std::string> ChunkedMacComputationImpl::ComputeMac() {
49 if (!status_.ok()) return status_;
50 status_ = util::Status(absl::StatusCode::kFailedPrecondition,
51 "MAC computation already finalized.");
52 return stateful_mac_->Finalize();
53 }
54
Update(absl::string_view data)55 util::Status ChunkedMacVerificationImpl::Update(absl::string_view data) {
56 if (!status_.ok()) return status_;
57 return stateful_mac_->Update(data);
58 }
59
VerifyMac()60 util::Status ChunkedMacVerificationImpl::VerifyMac() {
61 if (!status_.ok()) return status_;
62 status_ = util::Status(absl::StatusCode::kFailedPrecondition,
63 "MAC verification already finalized.");
64 util::StatusOr<std::string> computed_mac = stateful_mac_->Finalize();
65 if (!computed_mac.ok()) {
66 return computed_mac.status();
67 }
68 if (computed_mac->size() != tag_.size()) {
69 return util::Status(absl::StatusCode::kInvalidArgument,
70 "Verification failed.");
71 }
72 if (CRYPTO_memcmp(computed_mac->data(), tag_.data(), computed_mac->size())) {
73 return util::Status(absl::StatusCode::kInvalidArgument,
74 "Verification failed.");
75 }
76 return util::OkStatus();
77 }
78
79 util::StatusOr<std::unique_ptr<ChunkedMacComputation>>
CreateComputation() const80 ChunkedMacImpl::CreateComputation() const {
81 util::StatusOr<std::unique_ptr<subtle::StatefulMac>> stateful_mac =
82 stateful_mac_factory_->Create();
83 if (!stateful_mac.ok()) return stateful_mac.status();
84
85 return std::unique_ptr<ChunkedMacComputation>(
86 new ChunkedMacComputationImpl(*std::move(stateful_mac)));
87 }
88
89 util::StatusOr<std::unique_ptr<ChunkedMacVerification>>
CreateVerification(absl::string_view tag) const90 ChunkedMacImpl::CreateVerification(absl::string_view tag) const {
91 util::StatusOr<std::unique_ptr<subtle::StatefulMac>> stateful_mac =
92 stateful_mac_factory_->Create();
93 if (!stateful_mac.ok()) return stateful_mac.status();
94
95 return std::unique_ptr<ChunkedMacVerification>(
96 new ChunkedMacVerificationImpl(*std::move(stateful_mac), tag));
97 }
98
NewChunkedCmac(const AesCmacKey & key)99 util::StatusOr<std::unique_ptr<ChunkedMac>> NewChunkedCmac(
100 const AesCmacKey& key) {
101 if (!key.has_params()) {
102 return util::Status(absl::StatusCode::kInvalidArgument,
103 "Invalid key: missing parameters.");
104 }
105 util::SecretData secret_key_data =
106 util::SecretDataFromStringView(key.key_value());
107 auto stateful_mac_factory =
108 absl::make_unique<subtle::StatefulCmacBoringSslFactory>(
109 key.params().tag_size(), secret_key_data);
110 return std::unique_ptr<ChunkedMac>(
111 new ChunkedMacImpl(std::move(stateful_mac_factory)));
112 }
113
NewChunkedHmac(const HmacKey & key)114 util::StatusOr<std::unique_ptr<ChunkedMac>> NewChunkedHmac(const HmacKey& key) {
115 if (!key.has_params()) {
116 return util::Status(absl::StatusCode::kInvalidArgument,
117 "Invalid key: missing paramaters.");
118 }
119 subtle::HashType hash_type = util::Enums::ProtoToSubtle(key.params().hash());
120 util::SecretData secret_key_data =
121 util::SecretDataFromStringView(key.key_value());
122 auto stateful_mac_factory =
123 absl::make_unique<subtle::StatefulHmacBoringSslFactory>(
124 hash_type, key.params().tag_size(), secret_key_data);
125 return std::unique_ptr<ChunkedMac>(
126 new ChunkedMacImpl(std::move(stateful_mac_factory)));
127 }
128
129 } // namespace internal
130 } // namespace tink
131 } // namespace crypto
132