xref: /aosp_15_r20/external/tink/cc/prf/aes_cmac_prf_key_manager.h (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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