1 /* 2 * Copyright 2014 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 #ifndef SYSTEM_KEYMASTER_ANDROID_KEYMASTER_MESSAGES_H_ 18 #define SYSTEM_KEYMASTER_ANDROID_KEYMASTER_MESSAGES_H_ 19 20 #include <assert.h> 21 #include <stdlib.h> 22 #include <string.h> 23 24 #include <keymaster/authorization_set.h> 25 #include <keymaster/android_keymaster_utils.h> 26 27 namespace keymaster { 28 29 // Commands 30 enum AndroidKeymasterCommand { 31 GENERATE_KEY = 0, 32 BEGIN_OPERATION = 1, 33 UPDATE_OPERATION = 2, 34 FINISH_OPERATION = 3, 35 ABORT_OPERATION = 4, 36 IMPORT_KEY = 5, 37 EXPORT_KEY = 6, 38 GET_VERSION = 7, 39 ADD_RNG_ENTROPY = 8, 40 GET_SUPPORTED_ALGORITHMS = 9, 41 GET_SUPPORTED_BLOCK_MODES = 10, 42 GET_SUPPORTED_PADDING_MODES = 11, 43 GET_SUPPORTED_DIGESTS = 12, 44 GET_SUPPORTED_IMPORT_FORMATS = 13, 45 GET_SUPPORTED_EXPORT_FORMATS = 14, 46 GET_KEY_CHARACTERISTICS = 15, 47 }; 48 49 /** 50 * Keymaster message versions are tied to keymaster versions. We map the keymaster 51 * major.minor.subminor version to a sequential "message version". 52 * 53 * Rather than encoding a version number into each message we rely on the client -- who initiates 54 * all requests -- to check the version of the keymaster implementation with the GET_VERSION command 55 * and to send only requests that the implementation can understand. This means that only the 56 * client side needs to manage version compatibility; the implementation can always expect/produce 57 * messages of its format. 58 * 59 * Because message version selection is purely a client-side issue, all messages default to using 60 * the latest version (MAX_MESSAGE_VERSION). Client code must take care to check versions and pass 61 * correct version values to message constructors. The AndroidKeymaster implementation always uses 62 * the default, latest. 63 * 64 * Note that this approach implies that GetVersionRequest and GetVersionResponse cannot be 65 * versioned. 66 */ 67 const int32_t MAX_MESSAGE_VERSION = 2; 68 inline int32_t MessageVersion(uint8_t major_ver, uint8_t minor_ver, uint8_t /* subminor_ver */) { 69 int32_t message_version = -1; 70 switch (major_ver) { 71 case 0: 72 // For the moment we still support version 0, though in general the plan is not to support 73 // non-matching major versions. 74 message_version = 0; 75 break; 76 case 1: 77 switch (minor_ver) { 78 case 0: 79 message_version = 1; 80 break; 81 case 1: 82 message_version = 2; 83 break; 84 } 85 }; 86 return message_version; 87 } 88 89 struct KeymasterMessage : public Serializable { 90 KeymasterMessage(int32_t ver) : message_version(ver) { assert(ver >= 0); } 91 uint32_t message_version; 92 }; 93 94 /** 95 * All responses include an error value, and if the error is not KM_ERROR_OK, return no additional 96 * data. This abstract class factors out the common serialization functionality for all of the 97 * responses, so we only have to implement it once. Inheritance for reuse is generally not a great 98 * structure, but in this case it's the cleanest option. 99 */ 100 struct KeymasterResponse : public KeymasterMessage { 101 explicit KeymasterResponse(int32_t ver) 102 : KeymasterMessage(ver), error(KM_ERROR_UNKNOWN_ERROR) {} 103 104 size_t SerializedSize() const override; 105 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; 106 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 107 108 virtual size_t NonErrorSerializedSize() const = 0; 109 virtual uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const = 0; 110 virtual bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) = 0; 111 112 keymaster_error_t error; 113 }; 114 115 struct SupportedAlgorithmsRequest : public KeymasterMessage { 116 explicit SupportedAlgorithmsRequest(int32_t ver = MAX_MESSAGE_VERSION) 117 : KeymasterMessage(ver) {} 118 119 size_t SerializedSize() const override { return 0; }; 120 uint8_t* Serialize(uint8_t* buf, const uint8_t* /* end */) const override { return buf; } 121 bool Deserialize(const uint8_t** /* buf_ptr */, const uint8_t* /* end */) override { 122 return true; 123 } 124 }; 125 126 struct SupportedByAlgorithmRequest : public KeymasterMessage { 127 explicit SupportedByAlgorithmRequest(int32_t ver = MAX_MESSAGE_VERSION) 128 : KeymasterMessage(ver) {} 129 130 size_t SerializedSize() const override { return sizeof(uint32_t); }; 131 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { 132 return append_uint32_to_buf(buf, end, algorithm); 133 } 134 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override { 135 return copy_uint32_from_buf(buf_ptr, end, &algorithm); 136 } 137 138 keymaster_algorithm_t algorithm; 139 }; 140 141 class SupportedImportFormatsRequest : public SupportedByAlgorithmRequest {}; 142 class SupportedExportFormatsRequest : public SupportedByAlgorithmRequest {}; 143 144 struct SupportedByAlgorithmAndPurposeRequest : public KeymasterMessage { 145 explicit SupportedByAlgorithmAndPurposeRequest(int32_t ver = MAX_MESSAGE_VERSION) 146 : KeymasterMessage(ver) {} 147 148 size_t SerializedSize() const override { return sizeof(uint32_t) * 2; }; 149 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { 150 buf = append_uint32_to_buf(buf, end, algorithm); 151 return append_uint32_to_buf(buf, end, purpose); 152 } 153 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override { 154 return copy_uint32_from_buf(buf_ptr, end, &algorithm) && 155 copy_uint32_from_buf(buf_ptr, end, &purpose); 156 } 157 158 keymaster_algorithm_t algorithm; 159 keymaster_purpose_t purpose; 160 }; 161 162 class SupportedBlockModesRequest : public SupportedByAlgorithmAndPurposeRequest {}; 163 class SupportedPaddingModesRequest : public SupportedByAlgorithmAndPurposeRequest {}; 164 class SupportedDigestsRequest : public SupportedByAlgorithmAndPurposeRequest {}; 165 166 template <typename T> struct SupportedResponse : public KeymasterResponse { 167 explicit SupportedResponse(int32_t ver = MAX_MESSAGE_VERSION) 168 : KeymasterResponse(ver), results(NULL), results_length(0) {} 169 ~SupportedResponse() { delete[] results; } 170 171 template <size_t N> void SetResults(const T(&arr)[N]) { SetResults(arr, N); } 172 173 void SetResults(const T* arr, size_t n) { 174 delete[] results; 175 results_length = 0; 176 results = dup_array(arr, n); 177 if (results == NULL) { 178 error = KM_ERROR_MEMORY_ALLOCATION_FAILED; 179 } else { 180 results_length = n; 181 error = KM_ERROR_OK; 182 } 183 } 184 185 size_t NonErrorSerializedSize() const override { 186 return sizeof(uint32_t) + results_length * sizeof(uint32_t); 187 } 188 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override { 189 return append_uint32_array_to_buf(buf, end, results, results_length); 190 } 191 bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override { 192 delete[] results; 193 results = NULL; 194 UniquePtr<T[]> tmp; 195 if (!copy_uint32_array_from_buf(buf_ptr, end, &tmp, &results_length)) 196 return false; 197 results = tmp.release(); 198 return true; 199 } 200 201 T* results; 202 size_t results_length; 203 }; 204 205 class SupportedAlgorithmsResponse : public SupportedResponse<keymaster_algorithm_t> {}; 206 class SupportedBlockModesResponse : public SupportedResponse<keymaster_block_mode_t> {}; 207 class SupportedPaddingModesResponse : public SupportedResponse<keymaster_padding_t> {}; 208 class SupportedDigestsResponse : public SupportedResponse<keymaster_digest_t> {}; 209 class SupportedImportFormatsResponse : public SupportedResponse<keymaster_key_format_t> {}; 210 class SupportedExportFormatsResponse : public SupportedResponse<keymaster_key_format_t> {}; 211 212 struct GenerateKeyRequest : public KeymasterMessage { 213 explicit GenerateKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} 214 215 size_t SerializedSize() const override { return key_description.SerializedSize(); } 216 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { 217 return key_description.Serialize(buf, end); 218 } 219 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override { 220 return key_description.Deserialize(buf_ptr, end); 221 } 222 223 AuthorizationSet key_description; 224 }; 225 226 struct GenerateKeyResponse : public KeymasterResponse { 227 explicit GenerateKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) { 228 key_blob.key_material = NULL; 229 key_blob.key_material_size = 0; 230 } 231 ~GenerateKeyResponse(); 232 233 size_t NonErrorSerializedSize() const override; 234 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override; 235 bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 236 237 keymaster_key_blob_t key_blob; 238 AuthorizationSet enforced; 239 AuthorizationSet unenforced; 240 }; 241 242 struct GetKeyCharacteristicsRequest : public KeymasterMessage { 243 explicit GetKeyCharacteristicsRequest(int32_t ver = MAX_MESSAGE_VERSION) 244 : KeymasterMessage(ver) { 245 key_blob.key_material = NULL; 246 key_blob.key_material_size = 0; 247 } 248 ~GetKeyCharacteristicsRequest(); 249 250 void SetKeyMaterial(const void* key_material, size_t length); 251 void SetKeyMaterial(const keymaster_key_blob_t& blob) { 252 SetKeyMaterial(blob.key_material, blob.key_material_size); 253 } 254 255 size_t SerializedSize() const override; 256 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; 257 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 258 259 keymaster_key_blob_t key_blob; 260 AuthorizationSet additional_params; 261 }; 262 263 struct GetKeyCharacteristicsResponse : public KeymasterResponse { 264 explicit GetKeyCharacteristicsResponse(int32_t ver = MAX_MESSAGE_VERSION) 265 : KeymasterResponse(ver) {} 266 size_t NonErrorSerializedSize() const override; 267 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override; 268 bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 269 270 AuthorizationSet enforced; 271 AuthorizationSet unenforced; 272 }; 273 274 struct BeginOperationRequest : public KeymasterMessage { 275 explicit BeginOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) { 276 key_blob.key_material = NULL; 277 key_blob.key_material_size = 0; 278 } 279 ~BeginOperationRequest() { delete[] key_blob.key_material; } 280 281 void SetKeyMaterial(const void* key_material, size_t length); 282 void SetKeyMaterial(const keymaster_key_blob_t& blob) { 283 SetKeyMaterial(blob.key_material, blob.key_material_size); 284 } 285 286 size_t SerializedSize() const; 287 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; 288 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 289 290 keymaster_purpose_t purpose; 291 keymaster_key_blob_t key_blob; 292 AuthorizationSet additional_params; 293 }; 294 295 struct BeginOperationResponse : public KeymasterResponse { 296 explicit BeginOperationResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {} 297 298 size_t NonErrorSerializedSize() const override; 299 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override; 300 bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 301 302 keymaster_operation_handle_t op_handle; 303 AuthorizationSet output_params; 304 }; 305 306 struct UpdateOperationRequest : public KeymasterMessage { 307 explicit UpdateOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} 308 309 size_t SerializedSize() const override; 310 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; 311 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 312 313 keymaster_operation_handle_t op_handle; 314 Buffer input; 315 AuthorizationSet additional_params; 316 }; 317 318 struct UpdateOperationResponse : public KeymasterResponse { 319 explicit UpdateOperationResponse(int32_t ver = MAX_MESSAGE_VERSION) 320 : KeymasterResponse(ver), input_consumed(0) {} 321 322 size_t NonErrorSerializedSize() const override; 323 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override; 324 bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 325 326 Buffer output; 327 size_t input_consumed; 328 AuthorizationSet output_params; 329 }; 330 331 struct FinishOperationRequest : public KeymasterMessage { 332 explicit FinishOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} 333 334 size_t SerializedSize() const override; 335 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; 336 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 337 338 keymaster_operation_handle_t op_handle; 339 Buffer signature; 340 AuthorizationSet additional_params; 341 }; 342 343 struct FinishOperationResponse : public KeymasterResponse { 344 explicit FinishOperationResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {} 345 346 size_t NonErrorSerializedSize() const override; 347 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override; 348 bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 349 350 Buffer output; 351 AuthorizationSet output_params; 352 }; 353 354 struct AbortOperationRequest : public KeymasterMessage { 355 explicit AbortOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} 356 357 size_t SerializedSize() const override { return sizeof(uint64_t); } 358 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { 359 return append_uint64_to_buf(buf, end, op_handle); 360 } 361 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override { 362 return copy_uint64_from_buf(buf_ptr, end, &op_handle); 363 } 364 365 keymaster_operation_handle_t op_handle; 366 }; 367 368 struct AbortOperationResponse : public KeymasterResponse { 369 explicit AbortOperationResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {} 370 371 size_t NonErrorSerializedSize() const override { return 0; } 372 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; } 373 bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; } 374 }; 375 376 struct AddEntropyRequest : public KeymasterMessage { 377 explicit AddEntropyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} 378 379 size_t SerializedSize() const override; 380 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; 381 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 382 383 Buffer random_data; 384 }; 385 386 struct AddEntropyResponse : public KeymasterResponse { 387 explicit AddEntropyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {} 388 389 size_t NonErrorSerializedSize() const override { return 0; } 390 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* /* end */) const override { 391 return buf; 392 } 393 bool NonErrorDeserialize(const uint8_t** /* buf_ptr */, const uint8_t* /* end */) override { 394 return true; 395 } 396 }; 397 398 struct ImportKeyRequest : public KeymasterMessage { 399 explicit ImportKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) 400 : KeymasterMessage(ver), key_data(NULL) {} 401 ~ImportKeyRequest() { delete[] key_data; } 402 403 void SetKeyMaterial(const void* key_material, size_t length); 404 void SetKeyMaterial(const keymaster_key_blob_t& blob) { 405 SetKeyMaterial(blob.key_material, blob.key_material_size); 406 } 407 408 size_t SerializedSize() const override; 409 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; 410 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 411 412 AuthorizationSet key_description; 413 keymaster_key_format_t key_format; 414 uint8_t* key_data; 415 size_t key_data_length; 416 }; 417 418 struct ImportKeyResponse : public KeymasterResponse { 419 explicit ImportKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) { 420 key_blob.key_material = NULL; 421 key_blob.key_material_size = 0; 422 } 423 ~ImportKeyResponse() { delete[] key_blob.key_material; } 424 425 void SetKeyMaterial(const void* key_material, size_t length); 426 void SetKeyMaterial(const keymaster_key_blob_t& blob) { 427 SetKeyMaterial(blob.key_material, blob.key_material_size); 428 } 429 430 size_t NonErrorSerializedSize() const override; 431 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override; 432 bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 433 434 keymaster_key_blob_t key_blob; 435 AuthorizationSet enforced; 436 AuthorizationSet unenforced; 437 }; 438 439 struct ExportKeyRequest : public KeymasterMessage { 440 explicit ExportKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) { 441 key_blob.key_material = NULL; 442 key_blob.key_material_size = 0; 443 } 444 ~ExportKeyRequest() { delete[] key_blob.key_material; } 445 446 void SetKeyMaterial(const void* key_material, size_t length); 447 void SetKeyMaterial(const keymaster_key_blob_t& blob) { 448 SetKeyMaterial(blob.key_material, blob.key_material_size); 449 } 450 451 size_t SerializedSize() const override; 452 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; 453 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 454 455 AuthorizationSet additional_params; 456 keymaster_key_format_t key_format; 457 keymaster_key_blob_t key_blob; 458 }; 459 460 struct ExportKeyResponse : public KeymasterResponse { 461 explicit ExportKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) 462 : KeymasterResponse(ver), key_data(NULL) {} 463 ~ExportKeyResponse() { delete[] key_data; } 464 465 void SetKeyMaterial(const void* key_material, size_t length); 466 void SetKeyMaterial(const keymaster_key_blob_t& blob) { 467 SetKeyMaterial(blob.key_material, blob.key_material_size); 468 } 469 470 size_t NonErrorSerializedSize() const override; 471 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override; 472 bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 473 474 uint8_t* key_data; 475 size_t key_data_length; 476 }; 477 478 struct DeleteKeyRequest : public KeymasterMessage { 479 explicit DeleteKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) { 480 key_blob.key_material = nullptr; 481 key_blob.key_material_size = 0; 482 } 483 ~DeleteKeyRequest() { delete[] key_blob.key_material; } 484 485 void SetKeyMaterial(const void* key_material, size_t length); 486 void SetKeyMaterial(const keymaster_key_blob_t& blob) { 487 SetKeyMaterial(blob.key_material, blob.key_material_size); 488 } 489 490 size_t SerializedSize() const override; 491 uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; 492 bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 493 494 keymaster_key_blob_t key_blob; 495 }; 496 497 struct DeleteKeyResponse : public KeymasterResponse { 498 explicit DeleteKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {} 499 500 size_t NonErrorSerializedSize() const override { return 0; } 501 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; } 502 bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; } 503 }; 504 505 struct DeleteAllKeysRequest : public KeymasterMessage { 506 explicit DeleteAllKeysRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} 507 508 size_t SerializedSize() const override { return 0; } 509 uint8_t* Serialize(uint8_t* buf, const uint8_t*) const override { return buf; } 510 bool Deserialize(const uint8_t**, const uint8_t*) override { return true; }; 511 }; 512 513 struct DeleteAllKeysResponse : public KeymasterResponse { 514 explicit DeleteAllKeysResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {} 515 516 size_t NonErrorSerializedSize() const override { return 0; } 517 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; } 518 bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; } 519 }; 520 521 struct GetVersionRequest : public KeymasterMessage { 522 explicit GetVersionRequest() : KeymasterMessage(0 /* not versionable */) {} 523 524 size_t SerializedSize() const override { return 0; } 525 uint8_t* Serialize(uint8_t* buf, const uint8_t*) const override { return buf; } 526 bool Deserialize(const uint8_t**, const uint8_t*) override { return true; }; 527 }; 528 529 struct GetVersionResponse : public KeymasterResponse { 530 explicit GetVersionResponse() 531 : KeymasterResponse(0 /* not versionable */), major_ver(0), minor_ver(0), subminor_ver(0) {} 532 533 size_t NonErrorSerializedSize() const override; 534 uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override; 535 bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override; 536 537 uint8_t major_ver; 538 uint8_t minor_ver; 539 uint8_t subminor_ver; 540 }; 541 542 } // namespace keymaster 543 544 #endif // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_MESSAGES_H_ 545