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 #ifndef TINK_PRF_AES_CMAC_PRF_KEY_MANAGER_H_ 17 #define TINK_PRF_AES_CMAC_PRF_KEY_MANAGER_H_ 18 19 #include <algorithm> 20 #include <memory> 21 #include <string> 22 #include <vector> 23 24 #include "absl/memory/memory.h" 25 #include "absl/status/status.h" 26 #include "absl/strings/string_view.h" 27 #include "tink/core/key_type_manager.h" 28 #include "tink/key_manager.h" 29 #include "tink/subtle/prf/prf_set_util.h" 30 #include "tink/subtle/random.h" 31 #include "tink/subtle/stateful_cmac_boringssl.h" 32 #include "tink/util/constants.h" 33 #include "tink/util/errors.h" 34 #include "tink/util/input_stream_util.h" 35 #include "tink/util/protobuf_helper.h" 36 #include "tink/util/secret_data.h" 37 #include "tink/util/status.h" 38 #include "tink/util/statusor.h" 39 #include "tink/util/validation.h" 40 #include "proto/aes_cmac_prf.pb.h" 41 #include "proto/tink.pb.h" 42 43 namespace crypto { 44 namespace tink { 45 46 class AesCmacPrfKeyManager 47 : public KeyTypeManager<google::crypto::tink::AesCmacPrfKey, 48 google::crypto::tink::AesCmacPrfKeyFormat, 49 List<Prf>> { 50 public: 51 class PrfSetFactory : public PrimitiveFactory<Prf> { Create(const google::crypto::tink::AesCmacPrfKey & key)52 crypto::tink::util::StatusOr<std::unique_ptr<Prf>> Create( 53 const google::crypto::tink::AesCmacPrfKey& key) const override { 54 return subtle::CreatePrfFromStatefulMacFactory( 55 absl::make_unique<subtle::StatefulCmacBoringSslFactory>( 56 AesCmacPrfKeyManager::MaxOutputLength(), 57 util::SecretDataFromStringView(key.key_value()))); 58 } 59 }; 60 AesCmacPrfKeyManager()61 AesCmacPrfKeyManager() 62 : KeyTypeManager( 63 absl::make_unique<AesCmacPrfKeyManager::PrfSetFactory>()) {} 64 get_version()65 uint32_t get_version() const override { return 0; } 66 key_material_type()67 google::crypto::tink::KeyData::KeyMaterialType key_material_type() 68 const override { 69 return google::crypto::tink::KeyData::SYMMETRIC; 70 } 71 MaxOutputLength()72 static uint64_t MaxOutputLength() { return 16; } get_key_type()73 const std::string& get_key_type() const override { return key_type_; } 74 ValidateKey(const google::crypto::tink::AesCmacPrfKey & key)75 crypto::tink::util::Status ValidateKey( 76 const google::crypto::tink::AesCmacPrfKey& key) const override { 77 crypto::tink::util::Status status = 78 ValidateVersion(key.version(), get_version()); 79 if (!status.ok()) return status; 80 if (key.key_value().size() != kKeySizeInBytes) { 81 return crypto::tink::util::Status( 82 absl::StatusCode::kInvalidArgument, 83 "Invalid AesCmacPrfKey: key_value wrong length."); 84 } 85 return util::OkStatus(); 86 } 87 ValidateKeyFormat(const google::crypto::tink::AesCmacPrfKeyFormat & key_format)88 crypto::tink::util::Status ValidateKeyFormat( 89 const google::crypto::tink::AesCmacPrfKeyFormat& key_format) 90 const override { 91 crypto::tink::util::Status status = 92 ValidateVersion(key_format.version(), get_version()); 93 if (!status.ok()) return status; 94 if (key_format.key_size() != kKeySizeInBytes) { 95 return crypto::tink::util::Status( 96 absl::StatusCode::kInvalidArgument, 97 "Invalid AesCmacPrfKeyFormat: invalid key_size."); 98 } 99 return util::OkStatus(); 100 } 101 CreateKey(const google::crypto::tink::AesCmacPrfKeyFormat & key_format)102 crypto::tink::util::StatusOr<google::crypto::tink::AesCmacPrfKey> CreateKey( 103 const google::crypto::tink::AesCmacPrfKeyFormat& key_format) 104 const override { 105 google::crypto::tink::AesCmacPrfKey key; 106 key.set_version(get_version()); 107 key.set_key_value(subtle::Random::GetRandomBytes(key_format.key_size())); 108 return key; 109 } 110 DeriveKey(const google::crypto::tink::AesCmacPrfKeyFormat & key_format,InputStream * input_stream)111 crypto::tink::util::StatusOr<google::crypto::tink::AesCmacPrfKey> DeriveKey( 112 const google::crypto::tink::AesCmacPrfKeyFormat& key_format, 113 InputStream* input_stream) const override { 114 auto status = ValidateKeyFormat(key_format); 115 if (!status.ok()) { 116 return status; 117 } 118 crypto::tink::util::StatusOr<std::string> randomness = 119 ReadBytesFromStream(key_format.key_size(), input_stream); 120 if (!randomness.status().ok()) { 121 return randomness.status(); 122 } 123 google::crypto::tink::AesCmacPrfKey key; 124 key.set_version(get_version()); 125 key.set_key_value(randomness.value()); 126 return key; 127 } 128 129 private: 130 // Due to https://www.math.uwaterloo.ca/~ajmeneze/publications/tightness.pdf, 131 // we only allow key sizes of 256 bit. 132 const int kKeySizeInBytes = 32; 133 134 const std::string key_type_ = absl::StrCat( 135 kTypeGoogleapisCom, google::crypto::tink::AesCmacPrfKey().GetTypeName()); 136 }; 137 138 } // namespace tink 139 } // namespace crypto 140 141 #endif // TINK_PRF_AES_CMAC_PRF_KEY_MANAGER_H_ 142