xref: /aosp_15_r20/external/tink/cc/subtle/aes_gcm_hkdf_streaming.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2019 Google Inc.
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/subtle/aes_gcm_hkdf_streaming.h"
18 
19 #include <memory>
20 #include <string>
21 #include <utility>
22 
23 #include "absl/memory/memory.h"
24 #include "absl/status/status.h"
25 #include "tink/subtle/aes_gcm_hkdf_stream_segment_decrypter.h"
26 #include "tink/subtle/aes_gcm_hkdf_stream_segment_encrypter.h"
27 #include "tink/subtle/common_enums.h"
28 #include "tink/subtle/hkdf.h"
29 #include "tink/subtle/random.h"
30 #include "tink/util/status.h"
31 
32 namespace crypto {
33 namespace tink {
34 namespace subtle {
35 
36 namespace {
Validate(const AesGcmHkdfStreaming::Params & params)37 util::Status Validate(const AesGcmHkdfStreaming::Params& params) {
38   if (!(params.hkdf_hash == SHA1 || params.hkdf_hash == SHA256 ||
39         params.hkdf_hash == SHA512)) {
40     return util::Status(absl::StatusCode::kInvalidArgument,
41                         "unsupported hkdf_hash");
42   }
43   if (params.ikm.size() < 16 || params.ikm.size() < params.derived_key_size) {
44     return util::Status(absl::StatusCode::kInvalidArgument, "ikm too small");
45   }
46   if (params.derived_key_size != 16 && params.derived_key_size != 32) {
47     return util::Status(absl::StatusCode::kInvalidArgument,
48                         "derived_key_size must be 16 or 32");
49   }
50   if (params.ciphertext_offset < 0) {
51     return util::Status(absl::StatusCode::kInvalidArgument,
52                         "ciphertext_offset must be non-negative");
53   }
54   if (params.ciphertext_segment_size <=
55       params.ciphertext_offset + params.derived_key_size +
56           AesGcmHkdfStreamSegmentEncrypter::kTagSizeInBytes) {
57     return util::Status(absl::StatusCode::kInvalidArgument,
58                         "ciphertext_segment_size too small");
59   }
60   return util::OkStatus();
61 }
62 }  // namespace
63 
New(Params params)64 util::StatusOr<std::unique_ptr<AesGcmHkdfStreaming>> AesGcmHkdfStreaming::New(
65     Params params) {
66   auto status = internal::CheckFipsCompatibility<AesGcmHkdfStreaming>();
67   if (!status.ok()) return status;
68 
69   status = Validate(params);
70   if (!status.ok()) return status;
71   return {absl::WrapUnique(new AesGcmHkdfStreaming(std::move(params)))};
72 }
73 
74 util::StatusOr<std::unique_ptr<StreamSegmentEncrypter>>
NewSegmentEncrypter(absl::string_view associated_data) const75 AesGcmHkdfStreaming::NewSegmentEncrypter(
76     absl::string_view associated_data) const {
77   AesGcmHkdfStreamSegmentEncrypter::Params params;
78   params.salt = Random::GetRandomBytes(derived_key_size_);
79   auto hkdf_result = Hkdf::ComputeHkdf(hkdf_hash_, ikm_, params.salt,
80                                        associated_data, derived_key_size_);
81   if (!hkdf_result.ok()) return hkdf_result.status();
82   params.key = std::move(hkdf_result).value();
83   params.ciphertext_offset = ciphertext_offset_;
84   params.ciphertext_segment_size = ciphertext_segment_size_;
85   return AesGcmHkdfStreamSegmentEncrypter::New(std::move(params));
86 }
87 
88 util::StatusOr<std::unique_ptr<StreamSegmentDecrypter>>
NewSegmentDecrypter(absl::string_view associated_data) const89 AesGcmHkdfStreaming::NewSegmentDecrypter(
90     absl::string_view associated_data) const {
91   AesGcmHkdfStreamSegmentDecrypter::Params params;
92   params.ikm = ikm_;
93   params.hkdf_hash = hkdf_hash_;
94   params.derived_key_size = derived_key_size_;
95   params.ciphertext_offset = ciphertext_offset_;
96   params.ciphertext_segment_size = ciphertext_segment_size_;
97   params.associated_data = std::string(associated_data);
98   return AesGcmHkdfStreamSegmentDecrypter::New(std::move(params));
99 }
100 
101 }  // namespace subtle
102 }  // namespace tink
103 }  // namespace crypto
104