• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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/streamingaead/aes_gcm_hkdf_streaming_key_manager.h"
18 
19 #include <string>
20 
21 #include "absl/status/status.h"
22 #include "tink/subtle/aes_gcm_hkdf_stream_segment_encrypter.h"
23 #include "tink/subtle/random.h"
24 #include "tink/util/input_stream_util.h"
25 #include "tink/util/validation.h"
26 
27 namespace crypto {
28 namespace tink {
29 
30 using ::crypto::tink::subtle::AesGcmHkdfStreamSegmentEncrypter;
31 using ::crypto::tink::util::Status;
32 using ::crypto::tink::util::StatusOr;
33 using ::google::crypto::tink::AesGcmHkdfStreamingKey;
34 using ::google::crypto::tink::AesGcmHkdfStreamingKeyFormat;
35 using ::google::crypto::tink::AesGcmHkdfStreamingParams;
36 using ::google::crypto::tink::HashType;
37 
38 namespace {
39 
ValidateParams(const AesGcmHkdfStreamingParams & params)40 Status ValidateParams(const AesGcmHkdfStreamingParams& params) {
41   if (!(params.hkdf_hash_type() == HashType::SHA1 ||
42         params.hkdf_hash_type() == HashType::SHA256 ||
43         params.hkdf_hash_type() == HashType::SHA512)) {
44     return Status(absl::StatusCode::kInvalidArgument,
45                   "unsupported hkdf_hash_type");
46   }
47   int header_size = 1 + params.derived_key_size() +
48       AesGcmHkdfStreamSegmentEncrypter::kNoncePrefixSizeInBytes;
49   if (params.ciphertext_segment_size() <=
50       header_size + AesGcmHkdfStreamSegmentEncrypter::kTagSizeInBytes) {
51     return Status(absl::StatusCode::kInvalidArgument,
52                   "ciphertext_segment_size too small");
53   }
54   return ValidateAesKeySize(params.derived_key_size());
55 }
56 
57 }  // namespace
58 
59 crypto::tink::util::StatusOr<google::crypto::tink::AesGcmHkdfStreamingKey>
CreateKey(const google::crypto::tink::AesGcmHkdfStreamingKeyFormat & key_format) const60 AesGcmHkdfStreamingKeyManager::CreateKey(
61     const google::crypto::tink::AesGcmHkdfStreamingKeyFormat& key_format)
62     const {
63   AesGcmHkdfStreamingKey key;
64   key.set_version(get_version());
65   key.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size()));
66   *key.mutable_params() = key_format.params();
67   return key;
68 };
69 
70 crypto::tink::util::StatusOr<google::crypto::tink::AesGcmHkdfStreamingKey>
DeriveKey(const google::crypto::tink::AesGcmHkdfStreamingKeyFormat & key_format,InputStream * input_stream) const71 AesGcmHkdfStreamingKeyManager::DeriveKey(
72     const google::crypto::tink::AesGcmHkdfStreamingKeyFormat& key_format,
73     InputStream* input_stream) const {
74   crypto::tink::util::Status status =
75       ValidateVersion(key_format.version(), get_version());
76   if (!status.ok()) return status;
77 
78   crypto::tink::util::StatusOr<std::string> randomness_or =
79       ReadBytesFromStream(key_format.key_size(), input_stream);
80   if (!randomness_or.ok()) {
81     return randomness_or.status();
82   }
83   AesGcmHkdfStreamingKey key;
84   key.set_version(get_version());
85   key.set_key_value(randomness_or.value());
86   *key.mutable_params() = key_format.params();
87   return key;
88 }
89 
ValidateKey(const AesGcmHkdfStreamingKey & key) const90 Status AesGcmHkdfStreamingKeyManager::ValidateKey(
91     const AesGcmHkdfStreamingKey& key) const {
92   Status status = ValidateVersion(key.version(), get_version());
93   if (!status.ok()) return status;
94   if (key.key_value().size() < key.params().derived_key_size()) {
95     return Status(absl::StatusCode::kInvalidArgument,
96                   "key_value (i.e. ikm) too short");
97   }
98   return ValidateParams(key.params());
99 }
100 
ValidateKeyFormat(const AesGcmHkdfStreamingKeyFormat & key_format) const101 Status AesGcmHkdfStreamingKeyManager::ValidateKeyFormat(
102     const AesGcmHkdfStreamingKeyFormat& key_format) const {
103   if (key_format.key_size() < key_format.params().derived_key_size()) {
104     return Status(absl::StatusCode::kInvalidArgument,
105                   "key_size must not be smaller than derived_key_size");
106   }
107   return ValidateParams(key_format.params());
108 }
109 
110 }  // namespace tink
111 }  // namespace crypto
112