1 // Copyright 2020 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 #include "tink/subtle/prf/prf_set_util.h"
17
18 #include <memory>
19 #include <string>
20 #include <utility>
21
22 #include "absl/memory/memory.h"
23 #include "absl/status/status.h"
24 #include "absl/strings/str_cat.h"
25 #include "tink/subtle/mac/stateful_mac.h"
26 #include "tink/util/input_stream_util.h"
27 #include "tink/util/status.h"
28 #include "tink/util/statusor.h"
29
30 namespace crypto {
31 namespace tink {
32 namespace subtle {
33 namespace {
34
35 class PrfFromStreamingPrf : public Prf {
36 public:
PrfFromStreamingPrf(std::unique_ptr<StreamingPrf> streaming_prf)37 explicit PrfFromStreamingPrf(std::unique_ptr<StreamingPrf> streaming_prf)
38 : streaming_prf_(std::move(streaming_prf)) {}
Compute(absl::string_view input,size_t output_length) const39 util::StatusOr<std::string> Compute(absl::string_view input,
40 size_t output_length) const override {
41 auto inputstream = streaming_prf_->ComputePrf(input);
42 auto output_result = ReadBytesFromStream(output_length, inputstream.get());
43 if (!output_result.ok()) {
44 return output_result.status();
45 }
46 std::string output = output_result.value();
47 return output;
48 }
49
50 private:
51 std::unique_ptr<StreamingPrf> streaming_prf_;
52 };
53
54 class PrfFromStatefulMacFactory : public Prf {
55 public:
PrfFromStatefulMacFactory(std::unique_ptr<StatefulMacFactory> stateful_mac_factory)56 explicit PrfFromStatefulMacFactory(
57 std::unique_ptr<StatefulMacFactory> stateful_mac_factory)
58 : stateful_mac_factory_(std::move(stateful_mac_factory)) {}
Compute(absl::string_view input,size_t output_length) const59 util::StatusOr<std::string> Compute(absl::string_view input,
60 size_t output_length) const override {
61 auto stateful_mac_result = stateful_mac_factory_->Create();
62 if (!stateful_mac_result.ok()) {
63 return stateful_mac_result.status();
64 }
65 auto stateful_mac = std::move(stateful_mac_result.value());
66 auto status = stateful_mac->Update(input);
67 if (!status.ok()) {
68 return status;
69 }
70 auto output_result = stateful_mac->Finalize();
71 if (!output_result.ok()) {
72 return output_result.status();
73 }
74 std::string output = std::move(output_result.value());
75 if (output.size() < output_length) {
76 return util::Status(
77 absl::StatusCode::kInvalidArgument,
78 absl::StrCat("PRF only supports outputs up to ", output.size(),
79 " bytes, but ", output_length, " bytes were requested"));
80 }
81 return output.substr(0, output_length);
82 }
83
84 private:
85 std::unique_ptr<StatefulMacFactory> stateful_mac_factory_;
86 };
87
88 } // namespace
89
CreatePrfFromStreamingPrf(std::unique_ptr<StreamingPrf> streaming_prf)90 std::unique_ptr<Prf> CreatePrfFromStreamingPrf(
91 std::unique_ptr<StreamingPrf> streaming_prf) {
92 return absl::make_unique<PrfFromStreamingPrf>(std::move(streaming_prf));
93 }
94
CreatePrfFromStatefulMacFactory(std::unique_ptr<StatefulMacFactory> stateful_mac_factory)95 std::unique_ptr<Prf> CreatePrfFromStatefulMacFactory(
96 std::unique_ptr<StatefulMacFactory> stateful_mac_factory) {
97 return absl::make_unique<PrfFromStatefulMacFactory>(
98 std::move(stateful_mac_factory));
99 }
100
101 } // namespace subtle
102 } // namespace tink
103 } // namespace crypto
104