1 /*
2 * Copyright 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #include <gatekeeper/gatekeeper_messages.h>
19
20 #include <string.h>
21
22 namespace gatekeeper {
23
24 /**
25 * Methods for serializing/deserializing SizedBuffers
26 */
27
28 struct __attribute__((__packed__)) serial_header_t {
29 uint32_t error;
30 uint32_t user_id;
31 };
32
fitsBuffer(const uint8_t * begin,const uint8_t * end,uint32_t field_size)33 static inline bool fitsBuffer(const uint8_t* begin, const uint8_t* end, uint32_t field_size) {
34 uintptr_t dummy;
35 return !__builtin_add_overflow(reinterpret_cast<uintptr_t>(begin), field_size, &dummy)
36 && dummy <= reinterpret_cast<uintptr_t>(end);
37 }
38
serialized_buffer_size(const SizedBuffer & buf)39 static inline uint32_t serialized_buffer_size(const SizedBuffer &buf) {
40 return sizeof(decltype(buf.size())) + buf.size();
41 }
42
append_to_buffer(uint8_t ** buffer,const SizedBuffer & to_append)43 static inline void append_to_buffer(uint8_t **buffer, const SizedBuffer &to_append) {
44 uint32_t length = to_append.size();
45 memcpy(*buffer, &length, sizeof(length));
46 *buffer += sizeof(length);
47 if (length != 0 && to_append.Data<uint8_t>() != nullptr) {
48 memcpy(*buffer, to_append.Data<uint8_t>(), length);
49 *buffer += length;
50 }
51 }
52
readError(uint32_t code)53 static inline gatekeeper_error_t readError(uint32_t code) {
54 switch (code) {
55 case ERROR_NONE:
56 return ERROR_NONE;
57 case ERROR_INVALID:
58 return ERROR_INVALID;
59 case ERROR_RETRY:
60 return ERROR_RETRY;
61 case ERROR_MEMORY_ALLOCATION_FAILED:
62 return ERROR_MEMORY_ALLOCATION_FAILED;
63 case ERROR_UNKNOWN:
64 default:
65 return ERROR_UNKNOWN;
66 }
67 }
68
read_from_buffer(const uint8_t ** buffer,const uint8_t * end,SizedBuffer * target)69 static inline gatekeeper_error_t read_from_buffer(const uint8_t **buffer, const uint8_t *end,
70 SizedBuffer *target) {
71 if (target == nullptr) return ERROR_INVALID;
72 if (!fitsBuffer(*buffer, end, sizeof(uint32_t))) return ERROR_INVALID;
73
74 // read length from incomming buffer
75 uint32_t length;
76 memcpy(&length, *buffer, sizeof(length));
77 // advance out buffer
78 *buffer += sizeof(length);
79
80 if (length == 0) {
81 *target = {};
82 } else {
83 // sanitize incoming buffer size
84 if (!fitsBuffer(*buffer, end, length)) return ERROR_INVALID;
85
86 uint8_t *target_buffer = new(std::nothrow) uint8_t[length];
87 if (target_buffer == nullptr) return ERROR_MEMORY_ALLOCATION_FAILED;
88
89 memcpy(target_buffer, *buffer, length);
90 *buffer += length;
91 *target = { target_buffer, length };
92 }
93 return ERROR_NONE;
94 }
95
96
GetSerializedSize() const97 uint32_t GateKeeperMessage::GetSerializedSize() const {
98 if (error == ERROR_NONE) {
99 uint32_t size = sizeof(serial_header_t) + nonErrorSerializedSize();
100 return size;
101 } else {
102 uint32_t size = sizeof(serial_header_t);
103 if (error == ERROR_RETRY) {
104 size += sizeof(retry_timeout);
105 }
106 return size;
107 }
108 }
109
Serialize(uint8_t * buffer,const uint8_t * end) const110 uint32_t GateKeeperMessage::Serialize(uint8_t *buffer, const uint8_t *end) const {
111 uint32_t bytes_written = 0;
112 if (!fitsBuffer(buffer, end, GetSerializedSize())) {
113 return 0;
114 }
115
116 serial_header_t *header = reinterpret_cast<serial_header_t *>(buffer);
117 if (!fitsBuffer(buffer, end, sizeof(serial_header_t))) return 0;
118 header->error = error;
119 header->user_id = user_id;
120 bytes_written += sizeof(*header);
121 buffer += sizeof(*header);
122 if (error == ERROR_RETRY) {
123 if (!fitsBuffer(buffer, end, sizeof(retry_timeout))) return 0;
124 memcpy(buffer, &retry_timeout, sizeof(retry_timeout));
125 bytes_written += sizeof(retry_timeout);
126 } else if (error == ERROR_NONE) {
127 uint32_t serialized_size = nonErrorSerializedSize();
128 if (!fitsBuffer(buffer, end, serialized_size)) return 0;
129 nonErrorSerialize(buffer);
130 bytes_written += serialized_size;
131 }
132 return bytes_written;
133 }
134
Deserialize(const uint8_t * payload,const uint8_t * end)135 gatekeeper_error_t GateKeeperMessage::Deserialize(const uint8_t *payload, const uint8_t *end) {
136 if (!fitsBuffer(payload, end, sizeof(serial_header_t))) return ERROR_INVALID;
137 const serial_header_t *header = reinterpret_cast<const serial_header_t *>(payload);
138 error = readError(header->error);
139 user_id = header->user_id;
140 payload += sizeof(*header);
141 if (error == ERROR_NONE) {
142 return nonErrorDeserialize(payload, end);
143 } else {
144 retry_timeout = 0;
145 if (error == ERROR_RETRY) {
146 if (!fitsBuffer(payload, end, sizeof(retry_timeout))) {
147 return ERROR_INVALID;
148 }
149 memcpy(&retry_timeout, payload, sizeof(retry_timeout));
150 }
151 }
152
153 return ERROR_NONE;
154 }
155
SetRetryTimeout(uint32_t retry_timeout)156 void GateKeeperMessage::SetRetryTimeout(uint32_t retry_timeout) {
157 this->retry_timeout = retry_timeout;
158 this->error = ERROR_RETRY;
159 }
160
VerifyRequest(uint32_t user_id,uint64_t challenge,SizedBuffer enrolled_password_handle,SizedBuffer provided_password_payload)161 VerifyRequest::VerifyRequest(uint32_t user_id, uint64_t challenge,
162 SizedBuffer enrolled_password_handle, SizedBuffer provided_password_payload) {
163 this->user_id = user_id;
164 this->challenge = challenge;
165 this->password_handle = move(enrolled_password_handle);
166 this->provided_password = move(provided_password_payload);
167 }
168
nonErrorSerializedSize() const169 uint32_t VerifyRequest::nonErrorSerializedSize() const {
170 return sizeof(challenge) + serialized_buffer_size(password_handle)
171 + serialized_buffer_size(provided_password);
172 }
173
nonErrorSerialize(uint8_t * buffer) const174 void VerifyRequest::nonErrorSerialize(uint8_t *buffer) const {
175 memcpy(buffer, &challenge, sizeof(challenge));
176 buffer += sizeof(challenge);
177 append_to_buffer(&buffer, password_handle);
178 append_to_buffer(&buffer, provided_password);
179 }
180
nonErrorDeserialize(const uint8_t * payload,const uint8_t * end)181 gatekeeper_error_t VerifyRequest::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
182 gatekeeper_error_t error = ERROR_NONE;
183
184 password_handle = {};
185 provided_password = {};
186
187 if (!fitsBuffer(payload, end, sizeof(challenge))) return ERROR_INVALID;
188
189 memcpy(&challenge, payload, sizeof(challenge));
190 payload += sizeof(challenge);
191
192 error = read_from_buffer(&payload, end, &password_handle);
193 if (error != ERROR_NONE) return error;
194
195 return read_from_buffer(&payload, end, &provided_password);
196
197 }
198
VerifyResponse(uint32_t user_id,SizedBuffer auth_token)199 VerifyResponse::VerifyResponse(uint32_t user_id, SizedBuffer auth_token) {
200 this->user_id = user_id;
201 this->auth_token = move(auth_token);
202 this->request_reenroll = false;
203 }
204
VerifyResponse()205 VerifyResponse::VerifyResponse() {
206 request_reenroll = false;
207 };
208
SetVerificationToken(SizedBuffer auth_token)209 void VerifyResponse::SetVerificationToken(SizedBuffer auth_token) {
210 this->auth_token = move(auth_token);
211 }
212
nonErrorSerializedSize() const213 uint32_t VerifyResponse::nonErrorSerializedSize() const {
214 return serialized_buffer_size(auth_token) + sizeof(request_reenroll);
215 }
216
nonErrorSerialize(uint8_t * buffer) const217 void VerifyResponse::nonErrorSerialize(uint8_t *buffer) const {
218 append_to_buffer(&buffer, auth_token);
219 memcpy(buffer, &request_reenroll, sizeof(request_reenroll));
220 }
221
nonErrorDeserialize(const uint8_t * payload,const uint8_t * end)222 gatekeeper_error_t VerifyResponse::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
223
224 auth_token = {};
225
226 gatekeeper_error_t err = read_from_buffer(&payload, end, &auth_token);
227 if (err != ERROR_NONE) {
228 return err;
229 }
230
231 if (!fitsBuffer(payload, end, sizeof(request_reenroll))) return ERROR_INVALID;
232 memcpy(&request_reenroll, payload, sizeof(request_reenroll));
233 return ERROR_NONE;
234 }
235
EnrollRequest(uint32_t user_id,SizedBuffer password_handle,SizedBuffer provided_password,SizedBuffer enrolled_password)236 EnrollRequest::EnrollRequest(uint32_t user_id, SizedBuffer password_handle,
237 SizedBuffer provided_password, SizedBuffer enrolled_password) {
238 this->user_id = user_id;
239
240 this->provided_password = move(provided_password);
241 this->enrolled_password = move(enrolled_password);
242 this->password_handle = move(password_handle);
243 }
244
nonErrorSerializedSize() const245 uint32_t EnrollRequest::nonErrorSerializedSize() const {
246 return serialized_buffer_size(provided_password) + serialized_buffer_size(enrolled_password)
247 + serialized_buffer_size(password_handle);
248 }
249
nonErrorSerialize(uint8_t * buffer) const250 void EnrollRequest::nonErrorSerialize(uint8_t *buffer) const {
251 append_to_buffer(&buffer, provided_password);
252 append_to_buffer(&buffer, enrolled_password);
253 append_to_buffer(&buffer, password_handle);
254 }
255
nonErrorDeserialize(const uint8_t * payload,const uint8_t * end)256 gatekeeper_error_t EnrollRequest::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
257 gatekeeper_error_t ret;
258
259 provided_password = {};
260 enrolled_password = {};
261 password_handle = {};
262
263 ret = read_from_buffer(&payload, end, &provided_password);
264 if (ret != ERROR_NONE) {
265 return ret;
266 }
267
268 ret = read_from_buffer(&payload, end, &enrolled_password);
269 if (ret != ERROR_NONE) {
270 return ret;
271 }
272
273 return read_from_buffer(&payload, end, &password_handle);
274 }
275
EnrollResponse(uint32_t user_id,SizedBuffer enrolled_password_handle)276 EnrollResponse::EnrollResponse(uint32_t user_id, SizedBuffer enrolled_password_handle) {
277 this->user_id = user_id;
278 this->enrolled_password_handle = move(enrolled_password_handle);
279 }
280
SetEnrolledPasswordHandle(SizedBuffer enrolled_password_handle)281 void EnrollResponse::SetEnrolledPasswordHandle(SizedBuffer enrolled_password_handle) {
282 this->enrolled_password_handle = move(enrolled_password_handle);
283 }
284
nonErrorSerializedSize() const285 uint32_t EnrollResponse::nonErrorSerializedSize() const {
286 return serialized_buffer_size(enrolled_password_handle);
287 }
288
nonErrorSerialize(uint8_t * buffer) const289 void EnrollResponse::nonErrorSerialize(uint8_t *buffer) const {
290 append_to_buffer(&buffer, enrolled_password_handle);
291 }
292
nonErrorDeserialize(const uint8_t * payload,const uint8_t * end)293 gatekeeper_error_t EnrollResponse::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
294 enrolled_password_handle = {};
295
296 return read_from_buffer(&payload, end, &enrolled_password_handle);
297 }
298
DeleteUserRequest(uint32_t user_id)299 DeleteUserRequest::DeleteUserRequest(uint32_t user_id) {
300 this->user_id = user_id;
301 }
302 };
303
304