• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 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 
17 #ifndef TINK_PYTHON_TINK_CC_CC_KEY_MANAGER_H_
18 #define TINK_PYTHON_TINK_CC_CC_KEY_MANAGER_H_
19 
20 #include <string>
21 #include <utility>
22 
23 #include "absl/memory/memory.h"
24 #include "absl/status/status.h"
25 #include "absl/strings/str_cat.h"
26 #include "pybind11/pybind11.h"
27 #include "tink/key_manager.h"
28 #include "tink/registry.h"
29 #include "tink/util/status.h"
30 #include "tink/util/statusor.h"
31 #include "tink/cc/pybind/tink_exception.h"
32 
33 namespace crypto {
34 namespace tink {
35 
36 using pybind11::google_tink::TinkException;
37 
38 /**
39  * CcKeyManager is a thin wrapper of KeyManager in
40  * third_party/tink/cc/key_manager.h
41  * It only implements the methods currently needed in Python, and slightly
42  * changes the interface to ease usage of pybind.
43  */
44 template<class P>
45 class CcKeyManager {
46  public:
47   // Returns a key manager from the registry.
GetFromCcRegistry(const std::string & type_url)48   static std::unique_ptr<CcKeyManager<P>> GetFromCcRegistry(
49       const std::string& type_url) {
50     auto key_manager_result = Registry::get_key_manager<P>(type_url);
51     if (!key_manager_result.ok()) {
52       throw TinkException(
53           util::Status(absl::StatusCode::kFailedPrecondition,
54                        absl::StrCat("No manager for key type '", type_url,
55                                     "' found in the registry.")));
56     }
57     return absl::make_unique<CcKeyManager<P>>(key_manager_result.value());
58   }
59 
CcKeyManager(const KeyManager<P> * key_manager)60   explicit CcKeyManager(const KeyManager<P>* key_manager)
61       : key_manager_(key_manager) {}
62 
63   // Constructs an instance of P for the given 'key_data'.
GetPrimitive(const std::string & serialized_key_data)64   std::unique_ptr<P> GetPrimitive(
65       const std::string& serialized_key_data) const {
66     google::crypto::tink::KeyData key_data;
67     key_data.ParseFromString(serialized_key_data);
68     util::StatusOr<std::unique_ptr<P>> result =
69         key_manager_->GetPrimitive(key_data);
70     if (!result.ok()) {
71       throw TinkException(result.status());
72     }
73     return *std::move(result);
74   }
75 
76   // Creates a new random key, based on the specified 'key_format'.
NewKeyData(const std::string & serialized_key_template)77   pybind11::bytes NewKeyData(const std::string& serialized_key_template) const {
78     google::crypto::tink::KeyTemplate key_template;
79     key_template.ParseFromString(serialized_key_template);
80     if (key_manager_->get_key_type() != key_template.type_url()) {
81       throw TinkException(
82           util::Status(absl::StatusCode::kInvalidArgument,
83                        absl::StrCat("Key type '", key_template.type_url(),
84                                     "' is not supported by this manager.")));
85     }
86 
87     auto key_data =
88         key_manager_->get_key_factory().NewKeyData(key_template.value());
89     if (!key_data.ok()) {
90       throw TinkException(key_data.status());
91     }
92     return pybind11::bytes(key_data.value()->SerializeAsString());
93   }
94 
95   // Returns public key data extracted from the given private_key_data.
GetPublicKeyData(const std::string & serialized_private_key_data)96   pybind11::bytes GetPublicKeyData(
97       const std::string& serialized_private_key_data) const {
98     const PrivateKeyFactory* factory = dynamic_cast<const PrivateKeyFactory*>(
99         &key_manager_->get_key_factory());
100     if (factory == nullptr) {
101       throw TinkException(util::Status(
102           absl::StatusCode::kInvalidArgument,
103           absl::StrCat("KeyManager for type '", key_manager_->get_key_type(),
104                        "' does not have "
105                        "a PrivateKeyFactory.")));
106     }
107 
108     google::crypto::tink::KeyData private_key_data;
109     private_key_data.ParseFromString(serialized_private_key_data);
110     auto result = factory->GetPublicKeyData(private_key_data.value());
111     if (!result.ok()) {
112       throw TinkException(result.status());
113     }
114     return pybind11::bytes(result.value()->SerializeAsString());
115   }
116 
117   // Returns the type_url identifying the key type handled by this manager.
KeyType()118   std::string KeyType() const { return key_manager_->get_key_type(); }
119 
120  private:
121   const KeyManager<P>* key_manager_;
122 };
123 
124 }  // namespace tink
125 }  // namespace crypto
126 #endif  // TINK_PYTHON_TINK_CC_CC_KEY_MANAGER_H_
127