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
read_from_buffer(const uint8_t ** buffer,const uint8_t * end,SizedBuffer * target)53 static inline gatekeeper_error_t read_from_buffer(const uint8_t **buffer, const uint8_t *end,
54 SizedBuffer *target) {
55 if (target == nullptr) return ERROR_INVALID;
56 if (!fitsBuffer(*buffer, end, sizeof(uint32_t))) return ERROR_INVALID;
57
58 // read length from incomming buffer
59 uint32_t length;
60 memcpy(&length, *buffer, sizeof(length));
61 // advance out buffer
62 *buffer += sizeof(length);
63
64 if (length == 0) {
65 *target = {};
66 } else {
67 // sanitize incoming buffer size
68 if (!fitsBuffer(*buffer, end, length)) return ERROR_INVALID;
69
70 uint8_t *target_buffer = new(std::nothrow) uint8_t[length];
71 if (target_buffer == nullptr) return ERROR_MEMORY_ALLOCATION_FAILED;
72
73 memcpy(target_buffer, *buffer, length);
74 *buffer += length;
75 *target = { target_buffer, length };
76 }
77 return ERROR_NONE;
78 }
79
80
GetSerializedSize() const81 uint32_t GateKeeperMessage::GetSerializedSize() const {
82 if (error == ERROR_NONE) {
83 uint32_t size = sizeof(serial_header_t) + nonErrorSerializedSize();
84 return size;
85 } else {
86 uint32_t size = sizeof(serial_header_t);
87 if (error == ERROR_RETRY) {
88 size += sizeof(retry_timeout);
89 }
90 return size;
91 }
92 }
93
Serialize(uint8_t * buffer,const uint8_t * end) const94 uint32_t GateKeeperMessage::Serialize(uint8_t *buffer, const uint8_t *end) const {
95 uint32_t bytes_written = 0;
96 if (!fitsBuffer(buffer, end, GetSerializedSize())) {
97 return 0;
98 }
99
100 serial_header_t *header = reinterpret_cast<serial_header_t *>(buffer);
101 if (!fitsBuffer(buffer, end, sizeof(serial_header_t))) return 0;
102 header->error = error;
103 header->user_id = user_id;
104 bytes_written += sizeof(*header);
105 buffer += sizeof(*header);
106 if (error == ERROR_RETRY) {
107 if (!fitsBuffer(buffer, end, sizeof(retry_timeout))) return 0;
108 memcpy(buffer, &retry_timeout, sizeof(retry_timeout));
109 bytes_written += sizeof(retry_timeout);
110 } else if (error == ERROR_NONE) {
111 uint32_t serialized_size = nonErrorSerializedSize();
112 if (!fitsBuffer(buffer, end, serialized_size)) return 0;
113 nonErrorSerialize(buffer);
114 bytes_written += serialized_size;
115 }
116 return bytes_written;
117 }
118
Deserialize(const uint8_t * payload,const uint8_t * end)119 gatekeeper_error_t GateKeeperMessage::Deserialize(const uint8_t *payload, const uint8_t *end) {
120 if (!fitsBuffer(payload, end, sizeof(serial_header_t))) return ERROR_INVALID;
121 const serial_header_t *header = reinterpret_cast<const serial_header_t *>(payload);
122 error = static_cast<gatekeeper_error_t>(header->error);
123 user_id = header->user_id;
124 payload += sizeof(*header);
125 if (error == ERROR_NONE) {
126 return nonErrorDeserialize(payload, end);
127 } else {
128 retry_timeout = 0;
129 if (error == ERROR_RETRY) {
130 if (!fitsBuffer(payload, end, sizeof(retry_timeout))) {
131 return ERROR_INVALID;
132 }
133 memcpy(&retry_timeout, payload, sizeof(retry_timeout));
134 }
135 }
136
137 return ERROR_NONE;
138 }
139
SetRetryTimeout(uint32_t retry_timeout)140 void GateKeeperMessage::SetRetryTimeout(uint32_t retry_timeout) {
141 this->retry_timeout = retry_timeout;
142 this->error = ERROR_RETRY;
143 }
144
VerifyRequest(uint32_t user_id,uint64_t challenge,SizedBuffer enrolled_password_handle,SizedBuffer provided_password_payload)145 VerifyRequest::VerifyRequest(uint32_t user_id, uint64_t challenge,
146 SizedBuffer enrolled_password_handle, SizedBuffer provided_password_payload) {
147 this->user_id = user_id;
148 this->challenge = challenge;
149 this->password_handle = move(enrolled_password_handle);
150 this->provided_password = move(provided_password_payload);
151 }
152
nonErrorSerializedSize() const153 uint32_t VerifyRequest::nonErrorSerializedSize() const {
154 return sizeof(challenge) + serialized_buffer_size(password_handle)
155 + serialized_buffer_size(provided_password);
156 }
157
nonErrorSerialize(uint8_t * buffer) const158 void VerifyRequest::nonErrorSerialize(uint8_t *buffer) const {
159 memcpy(buffer, &challenge, sizeof(challenge));
160 buffer += sizeof(challenge);
161 append_to_buffer(&buffer, password_handle);
162 append_to_buffer(&buffer, provided_password);
163 }
164
nonErrorDeserialize(const uint8_t * payload,const uint8_t * end)165 gatekeeper_error_t VerifyRequest::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
166 gatekeeper_error_t error = ERROR_NONE;
167
168 password_handle = {};
169 provided_password = {};
170
171 if (!fitsBuffer(payload, end, sizeof(challenge))) return ERROR_INVALID;
172
173 memcpy(&challenge, payload, sizeof(challenge));
174 payload += sizeof(challenge);
175
176 error = read_from_buffer(&payload, end, &password_handle);
177 if (error != ERROR_NONE) return error;
178
179 return read_from_buffer(&payload, end, &provided_password);
180
181 }
182
VerifyResponse(uint32_t user_id,SizedBuffer auth_token)183 VerifyResponse::VerifyResponse(uint32_t user_id, SizedBuffer auth_token) {
184 this->user_id = user_id;
185 this->auth_token = move(auth_token);
186 this->request_reenroll = false;
187 }
188
VerifyResponse()189 VerifyResponse::VerifyResponse() {
190 request_reenroll = false;
191 };
192
SetVerificationToken(SizedBuffer auth_token)193 void VerifyResponse::SetVerificationToken(SizedBuffer auth_token) {
194 this->auth_token = move(auth_token);
195 }
196
nonErrorSerializedSize() const197 uint32_t VerifyResponse::nonErrorSerializedSize() const {
198 return serialized_buffer_size(auth_token) + sizeof(request_reenroll);
199 }
200
nonErrorSerialize(uint8_t * buffer) const201 void VerifyResponse::nonErrorSerialize(uint8_t *buffer) const {
202 append_to_buffer(&buffer, auth_token);
203 memcpy(buffer, &request_reenroll, sizeof(request_reenroll));
204 }
205
nonErrorDeserialize(const uint8_t * payload,const uint8_t * end)206 gatekeeper_error_t VerifyResponse::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
207
208 auth_token = {};
209
210 gatekeeper_error_t err = read_from_buffer(&payload, end, &auth_token);
211 if (err != ERROR_NONE) {
212 return err;
213 }
214
215 if (!fitsBuffer(payload, end, sizeof(request_reenroll))) return ERROR_INVALID;
216 memcpy(&request_reenroll, payload, sizeof(request_reenroll));
217 return ERROR_NONE;
218 }
219
EnrollRequest(uint32_t user_id,SizedBuffer password_handle,SizedBuffer provided_password,SizedBuffer enrolled_password)220 EnrollRequest::EnrollRequest(uint32_t user_id, SizedBuffer password_handle,
221 SizedBuffer provided_password, SizedBuffer enrolled_password) {
222 this->user_id = user_id;
223
224 this->provided_password = move(provided_password);
225 this->enrolled_password = move(enrolled_password);
226 this->password_handle = move(password_handle);
227 }
228
nonErrorSerializedSize() const229 uint32_t EnrollRequest::nonErrorSerializedSize() const {
230 return serialized_buffer_size(provided_password) + serialized_buffer_size(enrolled_password)
231 + serialized_buffer_size(password_handle);
232 }
233
nonErrorSerialize(uint8_t * buffer) const234 void EnrollRequest::nonErrorSerialize(uint8_t *buffer) const {
235 append_to_buffer(&buffer, provided_password);
236 append_to_buffer(&buffer, enrolled_password);
237 append_to_buffer(&buffer, password_handle);
238 }
239
nonErrorDeserialize(const uint8_t * payload,const uint8_t * end)240 gatekeeper_error_t EnrollRequest::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
241 gatekeeper_error_t ret;
242
243 provided_password = {};
244 enrolled_password = {};
245 password_handle = {};
246
247 ret = read_from_buffer(&payload, end, &provided_password);
248 if (ret != ERROR_NONE) {
249 return ret;
250 }
251
252 ret = read_from_buffer(&payload, end, &enrolled_password);
253 if (ret != ERROR_NONE) {
254 return ret;
255 }
256
257 return read_from_buffer(&payload, end, &password_handle);
258 }
259
EnrollResponse(uint32_t user_id,SizedBuffer enrolled_password_handle)260 EnrollResponse::EnrollResponse(uint32_t user_id, SizedBuffer enrolled_password_handle) {
261 this->user_id = user_id;
262 this->enrolled_password_handle = move(enrolled_password_handle);
263 }
264
SetEnrolledPasswordHandle(SizedBuffer enrolled_password_handle)265 void EnrollResponse::SetEnrolledPasswordHandle(SizedBuffer enrolled_password_handle) {
266 this->enrolled_password_handle = move(enrolled_password_handle);
267 }
268
nonErrorSerializedSize() const269 uint32_t EnrollResponse::nonErrorSerializedSize() const {
270 return serialized_buffer_size(enrolled_password_handle);
271 }
272
nonErrorSerialize(uint8_t * buffer) const273 void EnrollResponse::nonErrorSerialize(uint8_t *buffer) const {
274 append_to_buffer(&buffer, enrolled_password_handle);
275 }
276
nonErrorDeserialize(const uint8_t * payload,const uint8_t * end)277 gatekeeper_error_t EnrollResponse::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
278 enrolled_password_handle = {};
279
280 return read_from_buffer(&payload, end, &enrolled_password_handle);
281 }
282
283 };
284
285