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