forked from tink-crypto/tink
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkeyset_handle.h
188 lines (163 loc) · 7.76 KB
/
keyset_handle.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef TINK_KEYSET_HANDLE_H_
#define TINK_KEYSET_HANDLE_H_
#include "tink/aead.h"
#include "tink/key_manager.h"
#include "tink/keyset_reader.h"
#include "tink/keyset_writer.h"
#include "tink/primitive_set.h"
#include "tink/registry.h"
#include "proto/tink.pb.h"
namespace crypto {
namespace tink {
// KeysetHandle provides abstracted access to Keysets, to limit
// the exposure of actual protocol buffers that hold sensitive
// key material.
class KeysetHandle {
public:
// Creates a KeysetHandle from an encrypted keyset obtained via |reader|
// using |master_key_aead| to decrypt the keyset.
static crypto::tink::util::StatusOr<std::unique_ptr<KeysetHandle>> Read(
std::unique_ptr<KeysetReader> reader, const Aead& master_key_aead);
// Creates a KeysetHandle from a keyset which contains no secret key material.
// This can be used to load public keysets or envelope encryption keysets.
static crypto::tink::util::StatusOr<std::unique_ptr<KeysetHandle>>
ReadNoSecret(const std::string& serialized_keyset);
// Returns a new KeysetHandle that contains a single fresh key generated
// according to |key_template|.
static crypto::tink::util::StatusOr<std::unique_ptr<KeysetHandle>>
GenerateNew(const google::crypto::tink::KeyTemplate& key_template);
// Encrypts the underlying keyset with the provided |master_key_aead|
// and writes the resulting EncryptedKeyset to the given |writer|,
// which must be non-null.
crypto::tink::util::Status Write(KeysetWriter* writer,
const Aead& master_key_aead);
// Returns KeysetInfo, a "safe" Keyset that doesn't contain any actual
// key material, thus can be used for logging or monitoring.
google::crypto::tink::KeysetInfo GetKeysetInfo() const;
// Writes the underlying keyset to |writer| only if the keyset does not
// contain any secret key material.
// This can be used to persist public keysets or envelope encryption keysets.
// Users that need to persist cleartext keysets can use
// |CleartextKeysetHandle|.
crypto::tink::util::Status WriteNoSecret(KeysetWriter* writer);
// Returns a new KeysetHandle that contains public keys corresponding
// to the private keys from this handle.
// Returns an error if this handle contains keys that are not private keys.
crypto::tink::util::StatusOr<std::unique_ptr<KeysetHandle>>
GetPublicKeysetHandle() const;
// Creates a wrapped primitive corresponding to this keyset or fails with
// a non-ok status. Uses the KeyManager and PrimitiveWrapper objects in the
// global registry to create the primitive. This function is the most common
// way of creating a primitive.
template <class P>
crypto::tink::util::StatusOr<std::unique_ptr<P>> GetPrimitive() const;
// Creates a wrapped primitive corresponding to this keyset. Uses the given
// KeyManager, as well as the KeyManager and PrimitiveWrapper objects in the
// global registry to create the primitive. The given KeyManager is used for
// keys supported by it. For those, the registry is ignored.
template <class P>
crypto::tink::util::StatusOr<std::unique_ptr<P>> GetPrimitive(
const KeyManager<P>* custom_manager) const;
private:
// The classes below need access to get_keyset();
friend class CleartextKeysetHandle;
friend class KeysetManager;
friend class RegistryImpl;
// TestKeysetHandle::GetKeyset() provides access to get_keyset().
friend class TestKeysetHandle;
// Creates a handle that contains the given keyset.
explicit KeysetHandle(google::crypto::tink::Keyset keyset);
// Creates a handle that contains the given keyset.
explicit KeysetHandle(std::unique_ptr<google::crypto::tink::Keyset> keyset);
// Helper function which generates a key from a template, then adds it
// to the keyset. TODO(tholenst): Change this to a proper member operating
// on the internal keyset.
static crypto::tink::util::StatusOr<uint32_t> AddToKeyset(
const google::crypto::tink::KeyTemplate& key_template, bool as_primary,
google::crypto::tink::Keyset* keyset);
// Returns keyset held by this handle.
const google::crypto::tink::Keyset& get_keyset() const;
// Creates a set of primitives corresponding to the keys with
// (status == ENABLED) in the keyset given in 'keyset_handle',
// assuming all the corresponding key managers are present (keys
// with (status != ENABLED) are skipped).
//
// The returned set is usually later "wrapped" into a class that
// implements the corresponding Primitive-interface.
template <class P>
crypto::tink::util::StatusOr<std::unique_ptr<PrimitiveSet<P>>> GetPrimitives(
const KeyManager<P>* custom_manager) const;
google::crypto::tink::Keyset keyset_;
};
///////////////////////////////////////////////////////////////////////////////
// Implementation details of templated methods.
template <class P>
crypto::tink::util::StatusOr<std::unique_ptr<PrimitiveSet<P>>>
KeysetHandle::GetPrimitives(const KeyManager<P>* custom_manager) const {
crypto::tink::util::Status status = ValidateKeyset(get_keyset());
if (!status.ok()) return status;
std::unique_ptr<PrimitiveSet<P>> primitives(new PrimitiveSet<P>());
for (const google::crypto::tink::Keyset::Key& key : get_keyset().key()) {
if (key.status() == google::crypto::tink::KeyStatusType::ENABLED) {
std::unique_ptr<P> primitive;
if (custom_manager != nullptr &&
custom_manager->DoesSupport(key.key_data().type_url())) {
auto primitive_result = custom_manager->GetPrimitive(key.key_data());
if (!primitive_result.ok()) return primitive_result.status();
primitive = std::move(primitive_result.ValueOrDie());
} else {
auto primitive_result = Registry::GetPrimitive<P>(key.key_data());
if (!primitive_result.ok()) return primitive_result.status();
primitive = std::move(primitive_result.ValueOrDie());
}
auto entry_result = primitives->AddPrimitive(std::move(primitive), key);
if (!entry_result.ok()) return entry_result.status();
if (key.key_id() == get_keyset().primary_key_id()) {
auto primary_result =
primitives->set_primary(entry_result.ValueOrDie());
if (!primary_result.ok()) return primary_result;
}
}
}
return std::move(primitives);
}
template <class P>
crypto::tink::util::StatusOr<std::unique_ptr<P>> KeysetHandle::GetPrimitive()
const {
auto primitives_result = this->GetPrimitives<P>(nullptr);
if (!primitives_result.ok()) {
return primitives_result.status();
}
return Registry::Wrap<P>(std::move(primitives_result.ValueOrDie()));
}
template <class P>
crypto::tink::util::StatusOr<std::unique_ptr<P>> KeysetHandle::GetPrimitive(
const KeyManager<P>* custom_manager) const {
if (custom_manager == nullptr) {
return crypto::tink::util::Status(util::error::INVALID_ARGUMENT,
"custom_manager must not be null");
}
auto primitives_result = this->GetPrimitives<P>(custom_manager);
if (!primitives_result.ok()) {
return primitives_result.status();
}
return Registry::Wrap<P>(std::move(primitives_result.ValueOrDie()));
}
} // namespace tink
} // namespace crypto
#endif // TINK_KEYSET_HANDLE_H_