• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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 //    https://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 #include "anonymous_tokens/cpp/client/anonymous_tokens_public_key_client.h"
16 
17 #include <memory>
18 #include <string>
19 #include <tuple>
20 #include <utility>
21 #include <vector>
22 
23 #include "absl/container/flat_hash_set.h"
24 #include "absl/strings/string_view.h"
25 #include "absl/types/optional.h"
26 #include "anonymous_tokens/cpp/shared/proto_utils.h"
27 #include "anonymous_tokens/cpp/shared/status_utils.h"
28 #include "anonymous_tokens/proto/anonymous_tokens.pb.h"
29 
30 
31 namespace anonymous_tokens {
32 
33 namespace {
34 
ValidityChecksForRequestCreation(const AnonymousTokensPublicKeysGetRequest & public_key_request,AnonymousTokensUseCase use_case,int64_t key_version,absl::Time key_validity_start_time,absl::optional<absl::Time> key_validity_end_time)35 absl::Status ValidityChecksForRequestCreation(
36     const AnonymousTokensPublicKeysGetRequest& public_key_request,
37     AnonymousTokensUseCase use_case, int64_t key_version,
38     absl::Time key_validity_start_time,
39     absl::optional<absl::Time> key_validity_end_time) {
40   // Basic validity checks.
41   if (!public_key_request.use_case().empty()) {
42     // Cannot create a public key request more than once using the same client.
43     return absl::FailedPreconditionError(
44         "Public Key request is already created.");
45   } else if (use_case == ANONYMOUS_TOKENS_USE_CASE_UNDEFINED) {
46     // Use case must be valid.
47     return absl::InvalidArgumentError("Use case must be defined.");
48   } else if (key_version < 0) {
49     // Key version cannot be negative.
50     return absl::InvalidArgumentError(
51         "Key Version in an AnonymousTokensPublicKeysGetRequest "
52         "must be 0 or greater than 0.");
53   } else if (key_validity_end_time.has_value() &&
54              key_validity_end_time.value() <= key_validity_start_time) {
55     // Key cannot expire before or at its validity start time.
56     return absl::InvalidArgumentError(
57         "Key validity start time can not be the same or after key validity "
58         "end time (if set).");
59   } else if (key_validity_end_time.has_value() &&
60              key_validity_end_time.value() < absl::Now()) {
61     // Key's expiry time cannot be in the past.
62     return absl::InvalidArgumentError(
63         "Requested Key expiry time (if set) must not be in the past.");
64   }
65   return absl::OkStatus();
66 }
67 
ValidityChecksForResponseProcessing(const RSABlindSignaturePublicKey & public_key,const AnonymousTokensPublicKeysGetRequest & public_key_request)68 absl::Status ValidityChecksForResponseProcessing(
69     const RSABlindSignaturePublicKey& public_key,
70     const AnonymousTokensPublicKeysGetRequest& public_key_request) {
71   // Basic validity checks.
72   ANON_TOKENS_RETURN_IF_ERROR(ParseUseCase(public_key.use_case()).status());
73   if (public_key_request.use_case() != public_key.use_case()) {
74     // Use case must be the same as the requested use case.
75     return absl::InvalidArgumentError(
76         "Public key is not for the Use Case requested.");
77   } else if (public_key.key_version() <= 0) {
78     // Key version must be greater than zero.
79     return absl::InvalidArgumentError(
80         "Key_version cannot be zero or negative.");
81   } else if (public_key_request.key_version() > 0 &&
82              public_key_request.key_version() != public_key.key_version()) {
83     // Key version must be the same as the requested key version if the
84     // latter was greater than zero (explicit).
85     return absl::InvalidArgumentError(
86         "Public key is not for the Key Version requested.");
87   } else if (public_key.salt_length() <= 0) {
88     // We do not want deterministic signatures and negative lengths are
89     // invalid.
90     return absl::InvalidArgumentError(
91         "Salt length must not be zero or negative.");
92   } else if (public_key.key_size() < 256) {
93     // Key size must be a valid value.
94     return absl::InvalidArgumentError(
95         "Key_size cannot be less than 256 bytes.");
96   } else if (public_key.message_mask_type() == AT_MESSAGE_MASK_TYPE_UNDEFINED ||
97              public_key.message_mask_type() == AT_MESSAGE_MASK_XOR) {
98     return absl::InvalidArgumentError(
99         "Message mask type must be defined and supported.");
100   } else if (public_key.message_mask_type() == AT_MESSAGE_MASK_CONCAT &&
101              public_key.message_mask_size() < 32) {
102     return absl::InvalidArgumentError(
103         "Message mask concat type must have a size of at least 32 bytes.");
104   } else if (public_key.message_mask_type() == AT_MESSAGE_MASK_NO_MASK &&
105              public_key.message_mask_size() != 0) {
106     return absl::InvalidArgumentError(
107         "Message mask no mask type must be set to size 0 bytes.");
108   } else if (public_key.serialized_public_key().empty()) {
109     // Public key should not be empty.
110     return absl::InvalidArgumentError(
111         "Public Key not set for a particular use case and key version.");
112   } else if (!public_key.has_key_validity_start_time()) {
113     // Public key must have a key validity start time.
114     return absl::InvalidArgumentError(
115         "Public Key has no set validity start time.");
116   }
117   ANON_TOKENS_ASSIGN_OR_RETURN(
118       absl::Time requested_key_validity_start_time,
119       TimeFromProto(public_key_request.key_validity_start_time()));
120   ANON_TOKENS_ASSIGN_OR_RETURN(
121       absl::Time public_key_validity_start_time,
122       TimeFromProto(public_key.key_validity_start_time()));
123   if (requested_key_validity_start_time < public_key_validity_start_time) {
124     // Public key start time must be at or before the requested validity
125     // start time.
126     return absl::InvalidArgumentError(
127         "Public Key is not valid at the requested validity start time.");
128   } else if (public_key_request.has_key_validity_end_time() &&
129              !public_key.has_expiration_time()) {
130     // If a public key with explicit expiration was requested, indefinitely
131     // valid public key should not be returned.
132     return absl::InvalidArgumentError("Public Key does not expire.");
133   } else if (!public_key_request.has_key_validity_end_time() &&
134              public_key.has_expiration_time()) {
135     // If an indefinitely valid public key was requested, a public key with
136     // an expiry time should not be returned.
137     return absl::InvalidArgumentError("Public Key is not indefinitely valid");
138   }
139   absl::optional<absl::Time> public_key_expiry_time = absl::nullopt;
140   if (public_key_request.has_key_validity_end_time() &&
141       public_key.has_expiration_time()) {
142     ANON_TOKENS_ASSIGN_OR_RETURN(
143         absl::Time requested_key_expiry_time,
144         TimeFromProto(public_key_request.key_validity_end_time()));
145     ANON_TOKENS_ASSIGN_OR_RETURN(public_key_expiry_time,
146                                  TimeFromProto(public_key.expiration_time()));
147     if (requested_key_expiry_time < public_key_expiry_time) {
148       // Public key expiry time must be at or before the requested expiry
149       // time.
150       return absl::InvalidArgumentError(
151           "Public Key expires after the requested expiry time.");
152     } else if (public_key_expiry_time <= public_key_validity_start_time) {
153       // Key cannot expire before its validity period has even started.
154       return absl::InvalidArgumentError(
155           "Public Key cannot be expired at or before its validity start "
156           "time.");
157     } else if (public_key_expiry_time <= absl::Now()) {
158       // Key cannot be already expired.
159       return absl::InvalidArgumentError("Expired Public Key was returned");
160     }
161   }
162   RSAPublicKey rsa_public_key_pb;
163   if (!rsa_public_key_pb.ParseFromString(public_key.serialized_public_key())) {
164     return absl::InvalidArgumentError("Public key is malformed.");
165   }
166   if (rsa_public_key_pb.n().size() !=
167       static_cast<size_t>(public_key.key_size())) {
168     return absl::InvalidArgumentError(
169         "Actual and given Public Key sizes are different.");
170   }
171   return absl::OkStatus();
172 }
173 
174 }  // namespace
175 
176 absl::StatusOr<std::unique_ptr<AnonymousTokensPublicKeysGetClient>>
Create()177 AnonymousTokensPublicKeysGetClient::Create() {
178   return absl::WrapUnique(new AnonymousTokensPublicKeysGetClient());
179 }
180 
181 absl::StatusOr<AnonymousTokensPublicKeysGetRequest>
CreateAnonymousTokensPublicKeysGetRequest(AnonymousTokensUseCase use_case,int64_t key_version,absl::Time key_validity_start_time,absl::optional<absl::Time> key_validity_end_time)182 AnonymousTokensPublicKeysGetClient::CreateAnonymousTokensPublicKeysGetRequest(
183     AnonymousTokensUseCase use_case, int64_t key_version,
184     absl::Time key_validity_start_time,
185     absl::optional<absl::Time> key_validity_end_time) {
186   ANON_TOKENS_RETURN_IF_ERROR(ValidityChecksForRequestCreation(
187       public_key_request_, use_case, key_version, key_validity_start_time,
188       key_validity_end_time));
189   AnonymousTokensPublicKeysGetRequest request;
190   request.set_use_case(AnonymousTokensUseCase_Name(use_case));
191   request.set_key_version(key_version);
192   ANON_TOKENS_ASSIGN_OR_RETURN(*(request.mutable_key_validity_start_time()),
193                                TimeToProto(key_validity_start_time));
194   if (key_validity_end_time.has_value()) {
195     ANON_TOKENS_ASSIGN_OR_RETURN(*(request.mutable_key_validity_end_time()),
196                                  TimeToProto(*key_validity_end_time));
197   }
198   // Record the request.
199   public_key_request_ = request;
200   return request;
201 }
202 
203 absl::StatusOr<std::vector<RSABlindSignaturePublicKey>>
204 AnonymousTokensPublicKeysGetClient::
ProcessAnonymousTokensRSAPublicKeysGetResponse(const AnonymousTokensPublicKeysGetResponse & rsa_public_key_get_response)205     ProcessAnonymousTokensRSAPublicKeysGetResponse(
206         const AnonymousTokensPublicKeysGetResponse&
207             rsa_public_key_get_response) {
208   if (public_key_request_.use_case().empty()) {
209     // Create request method must be called before processing the response.
210     return absl::FailedPreconditionError(
211         "CreateAnonymousTokensPublicKeysGetRequest has not been called yet.");
212   }
213   std::vector<RSABlindSignaturePublicKey> rsa_public_keys;
214   // Temporary set structure to identify duplicate responses.
215   absl::flat_hash_set<std::tuple<std::string, int>> use_case_and_key_version;
216   for (const auto& resp_public_key :
217        rsa_public_key_get_response.rsa_public_keys()) {
218     ANON_TOKENS_RETURN_IF_ERROR(ValidityChecksForResponseProcessing(
219         resp_public_key, public_key_request_));
220 
221     // Extract use case and key version.
222     ANON_TOKENS_ASSIGN_OR_RETURN(AnonymousTokensUseCase use_case,
223                                  ParseUseCase(resp_public_key.use_case()));
224     int key_version = resp_public_key.key_version();
225 
226     // Check for duplicate responses.
227     std::tuple<std::string, int> use_case_key_version_tuple =
228         std::make_pair(AnonymousTokensUseCase_Name(use_case), key_version);
229     if (use_case_and_key_version.contains(use_case_key_version_tuple)) {
230       return absl::InvalidArgumentError(
231           "Use Case and Key Version combination must not be repeated in the "
232           "response.");
233     } else {
234       use_case_and_key_version.insert(use_case_key_version_tuple);
235     }
236 
237     rsa_public_keys.push_back(resp_public_key);
238   }
239 
240   return rsa_public_keys;
241 }
242 
243 }  // namespace anonymous_tokens
244 
245