diff --git a/cc/BUILD.bazel b/cc/BUILD.bazel index a133466250df57e46a89e948820db3af849ae2e5..0e93059fcefa7612bce19d26a864337f0154d3a4 100644 --- a/cc/BUILD.bazel +++ b/cc/BUILD.bazel @@ -39,6 +39,7 @@ PUBLIC_APIS = [ "mac_config.h", "mac_factory.h", "mac_key_templates.h", + "output_stream_with_result.h", "output_stream.h", "public_key_sign.h", "public_key_sign_factory.h", @@ -51,6 +52,7 @@ PUBLIC_APIS = [ "streaming_aead.h", "streaming_aead_config.h", "streaming_aead_key_templates.h", + "streaming_mac.h", "tink_config.h", "version.h", ] @@ -72,11 +74,13 @@ PUBLIC_API_DEPS = [ ":keyset_writer", ":kms_client", ":mac", + ":output_stream_with_result", ":output_stream", ":primitive_set", ":public_key_sign", ":public_key_verify", ":streaming_aead", + ":streaming_mac", ":random_access_stream", ":registry", ":registry_impl", @@ -159,6 +163,19 @@ cc_library( ], ) +cc_library( + name = "output_stream_with_result", + hdrs = ["output_stream_with_result.h"], + include_prefix = "tink", + strip_include_prefix = "/cc", + visibility = ["//visibility:public"], + deps = [ + ":output_stream", + "//cc/util:status", + "//cc/util:statusor", + ], +) + cc_library( name = "aead", hdrs = ["aead.h"], @@ -198,6 +215,20 @@ cc_library( ], ) +cc_library( + name = "streaming_mac", + hdrs = ["streaming_mac.h"], + include_prefix = "tink", + strip_include_prefix = "/cc", + visibility = ["//visibility:public"], + deps = [ + ":output_stream_with_result", + "//cc/util:status", + "//cc/util:statusor", + "@com_google_absl//absl/strings", + ], +) + cc_library( name = "hybrid_decrypt", hdrs = ["hybrid_decrypt.h"], diff --git a/cc/CMakeLists.txt b/cc/CMakeLists.txt index 35d36ec134b423f0abbc3526fbb2bd324a4900c9..0f4ffe336e84d3d64f9ed7ba4560976398f03a57 100644 --- a/cc/CMakeLists.txt +++ b/cc/CMakeLists.txt @@ -46,6 +46,7 @@ set(TINK_PUBLIC_APIS mac_config.h mac_factory.h mac_key_templates.h + output_stream_with_result.h output_stream.h public_key_sign.h public_key_sign_factory.h @@ -58,6 +59,7 @@ set(TINK_PUBLIC_APIS streaming_aead.h streaming_aead_config.h streaming_aead_key_templates.h + streaming_mac.h tink_config.h "${TINK_VERSION_H}" ) @@ -79,6 +81,7 @@ set(TINK_PUBLIC_API_DEPS tink::core::keyset_reader tink::core::keyset_writer tink::core::kms_client + tink::core::output_stream_with_result tink::core::output_stream tink::core::public_key_sign tink::core::public_key_verify @@ -88,6 +91,7 @@ set(TINK_PUBLIC_API_DEPS tink::core::registry tink::core::registry_impl tink::core::streaming_aead + tink::core::streaming_mac tink::core::version tink::aead::aead_config tink::aead::aead_factory @@ -155,6 +159,15 @@ tink_cc_library( tink::util::statusor ) +tink_cc_library( + NAME output_stream_with_result + SRCS output_stream_with_result.h + DEPS + tink::core::output_stream_with_result + tink::util::status + tink::util::statusor +) + tink_cc_library( NAME aead SRCS aead.h @@ -182,6 +195,16 @@ tink_cc_library( absl::strings ) +tink_cc_library( + NAME streaming_mac + SRCS streaming_mac.h + DEPS + tink::core::output_stream_with_result + tink::util::status + tink::util::statusor + absl::strings +) + tink_cc_library( NAME hybrid_decrypt SRCS hybrid_decrypt.h diff --git a/cc/output_stream_with_result.h b/cc/output_stream_with_result.h new file mode 100644 index 0000000000000000000000000000000000000000..01f330da018bb3210bac3e986b84d7b2e4482fc7 --- /dev/null +++ b/cc/output_stream_with_result.h @@ -0,0 +1,110 @@ +// Copyright 2018 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TINK_OUTPUT_STREAM_WITH_RESULT_H_ +#define TINK_OUTPUT_STREAM_WITH_RESULT_H_ + +#include <type_traits> + +#include "tink/output_stream.h" +#include "tink/util/status.h" +#include "tink/util/statusor.h" + +namespace crypto { +namespace tink { + +// An abstract OutputStream subclass that acts as a sink for data and returns a +// result after the stream has been closed. +// The result is only available if the stream was able to close with an ok +// status. Otherwise, the status of the GetResult call will be the same status +// as the Close call had. If Close is successful, GetResult is guaranteed to +// return a valid result. +// The return type of GetResult will be StatusOr<T>, except for T == Status, in +// which case the return type is Status. +template <class T> +class OutputStreamWithResult : public OutputStream { + public: + OutputStreamWithResult() : closed_(false) {} + ~OutputStreamWithResult() override {} + + // The return type is StatusOr<T> if T != Status, and Status otherwise. + using ResultType = + typename std::conditional<std::is_same<T, util::Status>::value, + util::Status, util::StatusOr<T>>::type; + + // Get the result associated with this OutputStream. Can only be called on + // closed streams, and will otherwise fail with FAILED_PRECONDITION as error + // code. + // If Close() returned an ok status, this method is guaranteed to contain a + // valid result. + // The return type is StatusOr<T> if T != Status, and Status otherwise. + ResultType GetResult() { + if (!closed_) { + return util::Status(util::error::FAILED_PRECONDITION, + "Stream is not closed"); + } + return result_; + } + + // Close the stream and return the computed result. Equivalent to calling + // Close() and GetResult() if Close() returned an OK status. + // The return type is StatusOr<T> if T != Status, and Status otherwise. + ResultType CloseAndGetResult() { + util::Status closing_status = Close(); + if (!closing_status.ok()) { + return closing_status; + } + return GetResult(); + } + + // Closes the OutputStream. + util::Status Close() final { + if (closed_) { + return util::Status(util::error::FAILED_PRECONDITION, "Stream closed"); + } + result_ = CloseStreamAndComputeResult(); + closed_ = true; + return result_.status(); + } + + // Getting the next OutputStream buffer. See OutputStream for detailed + // description. + crypto::tink::util::StatusOr<int> Next(void** data) final { + if (closed_) { + return util::Status(util::error::FAILED_PRECONDITION, + "Write on closed Stream"); + } + return NextBuffer(data); + } + + protected: + // Compute the result for this OutputStream. Safe for thread safety problems, + // this method will only be called once. + // The return type is StatusOr<T> if T != Status, and Status otherwise. + virtual ResultType CloseStreamAndComputeResult() = 0; + // Getting the next OutputStream buffer. See OutputStream for detailed + // description. + virtual util::StatusOr<int> NextBuffer(void** data) = 0; + + private: + bool closed_; + ResultType result_; +}; + +} // namespace tink +} // namespace crypto + +#endif // TINK_OUTPUT_STREAM_WITH_RESULT_H_ diff --git a/cc/streaming_mac.h b/cc/streaming_mac.h new file mode 100644 index 0000000000000000000000000000000000000000..037b14895963527fa3ee09e5378781405bbe5841 --- /dev/null +++ b/cc/streaming_mac.h @@ -0,0 +1,53 @@ +// Copyright 2017 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef TINK_STREAMING_MAC_H_ +#define TINK_STREAMING_MAC_H_ + +#include <memory> +#include <string> + +#include "absl/strings/string_view.h" +#include "tink/output_stream_with_result.h" +#include "tink/util/status.h" +#include "tink/util/statusor.h" + +namespace crypto { +namespace tink { + +/////////////////////////////////////////////////////////////////////////////// +// Interface for Streaming MACs (Message Authentication Codes). +// This interface should be used for authentication only, and not for other +// purposes (e.g., it should not be used to generate pseudorandom bytes). +class StreamingMac { + public: + // Returns an ComputeMacOutputStream, which when closed will return the + // message authentication code (MAC) of the data put into the stream. + virtual util::StatusOr<std::unique_ptr<OutputStreamWithResult<std::string>>> + NewComputeMacOutputStream() const = 0; + + // Returns an VerifyMacOutputStream which verifies if 'mac' is a correct + // message authentication code (MAC) for the data written to it. + virtual util::StatusOr<std::unique_ptr<OutputStreamWithResult<util::Status>>> + NewVerifyMacOutputStream(const std::string& mac_value) const = 0; + + virtual ~StreamingMac() {} +}; + +} // namespace tink +} // namespace crypto + +#endif // TINK_STREAMING_MAC_H_