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