1 // Copyright 2018 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 #ifndef TINK_DAEAD_AES_SIV_KEY_MANAGER_H_ 17 #define TINK_DAEAD_AES_SIV_KEY_MANAGER_H_ 18 19 #include <memory> 20 #include <string> 21 22 #include "absl/memory/memory.h" 23 #include "absl/status/status.h" 24 #include "absl/strings/str_cat.h" 25 #include "tink/core/key_type_manager.h" 26 #include "tink/deterministic_aead.h" 27 #include "tink/subtle/aes_siv_boringssl.h" 28 #include "tink/subtle/random.h" 29 #include "tink/util/constants.h" 30 #include "tink/util/errors.h" 31 #include "tink/util/input_stream_util.h" 32 #include "tink/util/protobuf_helper.h" 33 #include "tink/util/secret_data.h" 34 #include "tink/util/status.h" 35 #include "tink/util/statusor.h" 36 #include "tink/util/validation.h" 37 #include "proto/aes_siv.pb.h" 38 39 namespace crypto { 40 namespace tink { 41 42 class AesSivKeyManager 43 : public KeyTypeManager<google::crypto::tink::AesSivKey, 44 google::crypto::tink::AesSivKeyFormat, 45 List<DeterministicAead>> { 46 public: 47 class DeterministicAeadFactory : public PrimitiveFactory<DeterministicAead> { Create(const google::crypto::tink::AesSivKey & key)48 crypto::tink::util::StatusOr<std::unique_ptr<DeterministicAead>> Create( 49 const google::crypto::tink::AesSivKey& key) const override { 50 return subtle::AesSivBoringSsl::New( 51 util::SecretDataFromStringView(key.key_value())); 52 } 53 }; 54 AesSivKeyManager()55 AesSivKeyManager() 56 : KeyTypeManager(absl::make_unique<DeterministicAeadFactory>()) {} 57 get_version()58 uint32_t get_version() const override { return 0; } 59 key_material_type()60 google::crypto::tink::KeyData::KeyMaterialType key_material_type() 61 const override { 62 return google::crypto::tink::KeyData::SYMMETRIC; 63 } 64 get_key_type()65 const std::string& get_key_type() const override { return key_type_; } 66 ValidateKey(const google::crypto::tink::AesSivKey & key)67 crypto::tink::util::Status ValidateKey( 68 const google::crypto::tink::AesSivKey& key) const override { 69 crypto::tink::util::Status status = 70 ValidateVersion(key.version(), get_version()); 71 if (!status.ok()) return status; 72 return ValidateKeySize(key.key_value().size()); 73 } 74 ValidateKeyFormat(const google::crypto::tink::AesSivKeyFormat & key_format)75 crypto::tink::util::Status ValidateKeyFormat( 76 const google::crypto::tink::AesSivKeyFormat& key_format) const override { 77 return ValidateKeySize(key_format.key_size()); 78 } 79 CreateKey(const google::crypto::tink::AesSivKeyFormat & key_format)80 crypto::tink::util::StatusOr<google::crypto::tink::AesSivKey> CreateKey( 81 const google::crypto::tink::AesSivKeyFormat& key_format) const override { 82 google::crypto::tink::AesSivKey key; 83 key.set_version(get_version()); 84 key.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size())); 85 return key; 86 } 87 DeriveKey(const google::crypto::tink::AesSivKeyFormat & key_format,InputStream * input_stream)88 crypto::tink::util::StatusOr<google::crypto::tink::AesSivKey> DeriveKey( 89 const google::crypto::tink::AesSivKeyFormat& key_format, 90 InputStream* input_stream) const override { 91 crypto::tink::util::Status status = 92 ValidateVersion(key_format.version(), get_version()); 93 if (!status.ok()) return status; 94 95 crypto::tink::util::StatusOr<std::string> randomness = 96 ReadBytesFromStream(key_format.key_size(), input_stream); 97 98 if (!randomness.ok()) { 99 if (randomness.status().code() == absl::StatusCode::kOutOfRange) { 100 return crypto::tink::util::Status( 101 absl::StatusCode::kInvalidArgument, 102 "Could not get enough pseudorandomness from input stream"); 103 } 104 return randomness.status(); 105 } 106 google::crypto::tink::AesSivKey key; 107 key.set_version(get_version()); 108 key.set_key_value(randomness.value()); 109 return key; 110 } 111 112 private: ValidateKeySize(uint32_t key_size)113 crypto::tink::util::Status ValidateKeySize(uint32_t key_size) const { 114 if (key_size != kKeySizeInBytes) { 115 return crypto::tink::util::Status( 116 absl::StatusCode::kInvalidArgument, 117 absl::StrCat("Invalid key size: key size is ", key_size, 118 " bytes; supported size: ", kKeySizeInBytes, " bytes.")); 119 } 120 return crypto::tink::util::OkStatus(); 121 } 122 123 const std::string key_type_ = absl::StrCat( 124 kTypeGoogleapisCom, google::crypto::tink::AesSivKey().GetTypeName()); 125 const int kKeySizeInBytes = 64; 126 }; 127 128 } // namespace tink 129 } // namespace crypto 130 131 #endif // TINK_DAEAD_AES_SIV_KEY_MANAGER_H_ 132