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 
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 
39 static inline uint32_t serialized_buffer_size(const SizedBuffer &buf) {
40     return sizeof(decltype(buf.size())) + buf.size();
41 }
42 
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 
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 
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 
97 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 
110 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 
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 
156 void GateKeeperMessage::SetRetryTimeout(uint32_t retry_timeout) {
157     this->retry_timeout = retry_timeout;
158     this->error = ERROR_RETRY;
159 }
160 
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 
169 uint32_t VerifyRequest::nonErrorSerializedSize() const {
170     return sizeof(challenge) + serialized_buffer_size(password_handle)
171             + serialized_buffer_size(provided_password);
172 }
173 
174 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 
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 
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 
205 VerifyResponse::VerifyResponse() {
206     request_reenroll = false;
207 };
208 
209 void VerifyResponse::SetVerificationToken(SizedBuffer auth_token) {
210     this->auth_token = move(auth_token);
211 }
212 
213 uint32_t VerifyResponse::nonErrorSerializedSize() const {
214     return serialized_buffer_size(auth_token) + sizeof(request_reenroll);
215 }
216 
217 void VerifyResponse::nonErrorSerialize(uint8_t *buffer) const {
218     append_to_buffer(&buffer, auth_token);
219     memcpy(buffer, &request_reenroll, sizeof(request_reenroll));
220 }
221 
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 
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 
245 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 
250 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 
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 
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 
281 void EnrollResponse::SetEnrolledPasswordHandle(SizedBuffer enrolled_password_handle) {
282     this->enrolled_password_handle = move(enrolled_password_handle);
283 }
284 
285 uint32_t EnrollResponse::nonErrorSerializedSize() const {
286     return serialized_buffer_size(enrolled_password_handle);
287 }
288 
289 void EnrollResponse::nonErrorSerialize(uint8_t *buffer) const {
290     append_to_buffer(&buffer, enrolled_password_handle);
291 }
292 
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 
299 DeleteUserRequest::DeleteUserRequest(uint32_t user_id) {
300     this->user_id = user_id;
301 }
302 };
303 
304