xref: /aosp_15_r20/external/tink/cc/mac/internal/chunked_mac_impl.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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