| /* |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef SYSTEM_KEYMASTER_ANDROID_KEYMASTER_MESSAGES_H_ |
| #define SYSTEM_KEYMASTER_ANDROID_KEYMASTER_MESSAGES_H_ |
| |
| #include <assert.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include <keymaster/authorization_set.h> |
| #include <keymaster/android_keymaster_utils.h> |
| |
| namespace keymaster { |
| |
| // Commands |
| const uint32_t GENERATE_KEY = 0; |
| const uint32_t BEGIN_OPERATION = 1; |
| const uint32_t UPDATE_OPERATION = 2; |
| const uint32_t FINISH_OPERATION = 3; |
| const uint32_t ABORT_OPERATION = 4; |
| const uint32_t IMPORT_KEY = 5; |
| const uint32_t EXPORT_KEY = 6; |
| const uint32_t GET_VERSION = 7; |
| const uint32_t ADD_RNG_ENTROPY = 8; |
| |
| /** |
| * Keymaster message versions are tied to keymaster versions. We map the keymaster |
| * major.minor.subminor version to a sequential "message version". |
| * |
| * Rather than encoding a version number into each message we rely on the client -- who initiates |
| * all requests -- to check the version of the keymaster implementation with the GET_VERSION command |
| * and to send only requests that the implementation can understand. This means that only the |
| * client side needs to manage version compatibility; the implementation can always expect/produce |
| * messages of its format. |
| * |
| * Because message version selection is purely a client-side issue, all messages default to using |
| * the latest version (MAX_MESSAGE_VERSION). Client code must take care to check versions and pass |
| * correct version values to message constructors. The AndroidKeymaster implementation always uses |
| * the default, latest. |
| * |
| * Note that this approach implies that GetVersionRequest and GetVersionResponse cannot be |
| * versioned. |
| */ |
| const int32_t MAX_MESSAGE_VERSION = 1; |
| inline int32_t MessageVersion(uint8_t major_ver, uint8_t /* minor_ver */, |
| uint8_t /* subminor_ver */) { |
| int32_t message_version = -1; |
| switch (major_ver) { |
| case 0: |
| // For the moment we still support version 0, though in general the plan is not to support |
| // non-matching major versions. |
| message_version = 0; |
| break; |
| case 1: |
| // Currently all 1.X.X versions are interoperable and all use message version 1. In the |
| // future minor numbers may indicate incompatibility. Subminor version should never matter |
| // for compatibility. |
| message_version = 1; |
| break; |
| }; |
| return message_version; |
| } |
| |
| struct KeymasterMessage : public Serializable { |
| KeymasterMessage(int32_t ver) : message_version(ver) { assert(ver >= 0); } |
| uint32_t message_version; |
| }; |
| |
| /** |
| * All responses include an error value, and if the error is not KM_ERROR_OK, return no additional |
| * data. This abstract class factors out the common serialization functionality for all of the |
| * responses, so we only have to implement it once. Inheritance for reuse is generally not a great |
| * structure, but in this case it's the cleanest option. |
| */ |
| struct KeymasterResponse : public KeymasterMessage { |
| KeymasterResponse(int32_t ver) : KeymasterMessage(ver), error(KM_ERROR_UNKNOWN_ERROR) {} |
| |
| size_t SerializedSize() const; |
| uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const; |
| bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| virtual size_t NonErrorSerializedSize() const = 0; |
| virtual uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const = 0; |
| virtual bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) = 0; |
| |
| keymaster_error_t error; |
| }; |
| |
| struct SupportedAlgorithmsResponse : public KeymasterResponse { |
| SupportedAlgorithmsResponse(int32_t ver = MAX_MESSAGE_VERSION) |
| : KeymasterResponse(ver), algorithms(NULL), algorithms_length(0) {} |
| ~SupportedAlgorithmsResponse() { delete[] algorithms; } |
| |
| size_t NonErrorSerializedSize() const; |
| uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const; |
| bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| keymaster_algorithm_t* algorithms; |
| size_t algorithms_length; |
| }; |
| |
| template <typename T> struct SupportedResponse : public KeymasterResponse { |
| SupportedResponse(int32_t ver = MAX_MESSAGE_VERSION) |
| : KeymasterResponse(ver), results(NULL), results_length(0) {} |
| ~SupportedResponse() { delete[] results; } |
| |
| template <size_t N> void SetResults(const T(&arr)[N]) { SetResults(arr, N); } |
| |
| void SetResults(const T* arr, size_t n) { |
| delete[] results; |
| results_length = 0; |
| results = dup_array(arr, n); |
| if (results == NULL) { |
| error = KM_ERROR_MEMORY_ALLOCATION_FAILED; |
| } else { |
| results_length = n; |
| error = KM_ERROR_OK; |
| } |
| } |
| |
| size_t NonErrorSerializedSize() const { |
| return sizeof(uint32_t) + results_length * sizeof(uint32_t); |
| } |
| uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const { |
| return append_uint32_array_to_buf(buf, end, results, results_length); |
| } |
| bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) { |
| delete[] results; |
| results = NULL; |
| UniquePtr<T[]> tmp; |
| if (!copy_uint32_array_from_buf(buf_ptr, end, &tmp, &results_length)) |
| return false; |
| results = tmp.release(); |
| return true; |
| } |
| |
| T* results; |
| size_t results_length; |
| }; |
| |
| struct GenerateKeyRequest : public KeymasterMessage { |
| GenerateKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} |
| |
| size_t SerializedSize() const { return key_description.SerializedSize(); } |
| uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const { |
| return key_description.Serialize(buf, end); |
| } |
| bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) { |
| return key_description.Deserialize(buf_ptr, end); |
| } |
| |
| AuthorizationSet key_description; |
| }; |
| |
| struct GenerateKeyResponse : public KeymasterResponse { |
| GenerateKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) { |
| key_blob.key_material = NULL; |
| key_blob.key_material_size = 0; |
| } |
| ~GenerateKeyResponse(); |
| |
| size_t NonErrorSerializedSize() const; |
| uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const; |
| bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| keymaster_key_blob_t key_blob; |
| AuthorizationSet enforced; |
| AuthorizationSet unenforced; |
| }; |
| |
| struct GetKeyCharacteristicsRequest : public KeymasterMessage { |
| GetKeyCharacteristicsRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) { |
| key_blob.key_material = NULL; |
| key_blob.key_material_size = 0; |
| } |
| ~GetKeyCharacteristicsRequest(); |
| |
| void SetKeyMaterial(const void* key_material, size_t length); |
| void SetKeyMaterial(const keymaster_key_blob_t& blob) { |
| SetKeyMaterial(blob.key_material, blob.key_material_size); |
| } |
| |
| size_t SerializedSize() const; |
| uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const; |
| bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| keymaster_key_blob_t key_blob; |
| AuthorizationSet additional_params; |
| }; |
| |
| struct GetKeyCharacteristicsResponse : public KeymasterResponse { |
| GetKeyCharacteristicsResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {} |
| size_t NonErrorSerializedSize() const; |
| uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const; |
| bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| AuthorizationSet enforced; |
| AuthorizationSet unenforced; |
| }; |
| |
| struct BeginOperationRequest : public KeymasterMessage { |
| BeginOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) { |
| key_blob.key_material = NULL; |
| key_blob.key_material_size = 0; |
| } |
| ~BeginOperationRequest() { delete[] key_blob.key_material; } |
| |
| void SetKeyMaterial(const void* key_material, size_t length); |
| void SetKeyMaterial(const keymaster_key_blob_t& blob) { |
| SetKeyMaterial(blob.key_material, blob.key_material_size); |
| } |
| |
| size_t SerializedSize() const; |
| uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const; |
| bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| keymaster_purpose_t purpose; |
| keymaster_key_blob_t key_blob; |
| AuthorizationSet additional_params; |
| }; |
| |
| struct BeginOperationResponse : public KeymasterResponse { |
| BeginOperationResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {} |
| |
| size_t NonErrorSerializedSize() const; |
| uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const; |
| bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| keymaster_operation_handle_t op_handle; |
| AuthorizationSet output_params; |
| }; |
| |
| struct UpdateOperationRequest : public KeymasterMessage { |
| UpdateOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} |
| |
| size_t SerializedSize() const; |
| uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const; |
| bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| keymaster_operation_handle_t op_handle; |
| Buffer input; |
| AuthorizationSet additional_params; |
| }; |
| |
| struct UpdateOperationResponse : public KeymasterResponse { |
| UpdateOperationResponse(int32_t ver = MAX_MESSAGE_VERSION) |
| : KeymasterResponse(ver), input_consumed(0) {} |
| |
| size_t NonErrorSerializedSize() const; |
| uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const; |
| bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| Buffer output; |
| size_t input_consumed; |
| }; |
| |
| struct FinishOperationRequest : public KeymasterMessage { |
| FinishOperationRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} |
| |
| size_t SerializedSize() const; |
| uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const; |
| bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| keymaster_operation_handle_t op_handle; |
| Buffer signature; |
| AuthorizationSet additional_params; |
| }; |
| |
| struct FinishOperationResponse : public KeymasterResponse { |
| FinishOperationResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) {} |
| |
| size_t NonErrorSerializedSize() const; |
| uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const; |
| bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| Buffer output; |
| }; |
| |
| struct AddEntropyRequest : public KeymasterMessage { |
| AddEntropyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) {} |
| |
| size_t SerializedSize() const; |
| uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const; |
| bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| Buffer random_data; |
| }; |
| |
| struct ImportKeyRequest : public KeymasterMessage { |
| ImportKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver), key_data(NULL) {} |
| ~ImportKeyRequest() { delete[] key_data; } |
| |
| void SetKeyMaterial(const void* key_material, size_t length); |
| void SetKeyMaterial(const keymaster_key_blob_t& blob) { |
| SetKeyMaterial(blob.key_material, blob.key_material_size); |
| } |
| |
| size_t SerializedSize() const; |
| uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const; |
| bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| AuthorizationSet key_description; |
| keymaster_key_format_t key_format; |
| uint8_t* key_data; |
| size_t key_data_length; |
| }; |
| |
| struct ImportKeyResponse : public KeymasterResponse { |
| ImportKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver) { |
| key_blob.key_material = NULL; |
| key_blob.key_material_size = 0; |
| } |
| ~ImportKeyResponse() { delete[] key_blob.key_material; } |
| |
| void SetKeyMaterial(const void* key_material, size_t length); |
| void SetKeyMaterial(const keymaster_key_blob_t& blob) { |
| SetKeyMaterial(blob.key_material, blob.key_material_size); |
| } |
| |
| size_t NonErrorSerializedSize() const; |
| uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const; |
| bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| keymaster_key_blob_t key_blob; |
| AuthorizationSet enforced; |
| AuthorizationSet unenforced; |
| }; |
| |
| struct ExportKeyRequest : public KeymasterMessage { |
| ExportKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) { |
| key_blob.key_material = NULL; |
| key_blob.key_material_size = 0; |
| } |
| ~ExportKeyRequest() { delete[] key_blob.key_material; } |
| |
| void SetKeyMaterial(const void* key_material, size_t length); |
| void SetKeyMaterial(const keymaster_key_blob_t& blob) { |
| SetKeyMaterial(blob.key_material, blob.key_material_size); |
| } |
| |
| size_t SerializedSize() const; |
| uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const; |
| bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| AuthorizationSet additional_params; |
| keymaster_key_format_t key_format; |
| keymaster_key_blob_t key_blob; |
| }; |
| |
| struct ExportKeyResponse : public KeymasterResponse { |
| ExportKeyResponse(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterResponse(ver), key_data(NULL) {} |
| ~ExportKeyResponse() { delete[] key_data; } |
| |
| void SetKeyMaterial(const void* key_material, size_t length); |
| void SetKeyMaterial(const keymaster_key_blob_t& blob) { |
| SetKeyMaterial(blob.key_material, blob.key_material_size); |
| } |
| |
| size_t NonErrorSerializedSize() const; |
| uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const; |
| bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| uint8_t* key_data; |
| size_t key_data_length; |
| }; |
| |
| struct DeleteKeyRequest : public KeymasterMessage { |
| DeleteKeyRequest(int32_t ver = MAX_MESSAGE_VERSION) : KeymasterMessage(ver) { |
| key_blob.key_material = nullptr; |
| key_blob.key_material_size = 0; |
| } |
| ~DeleteKeyRequest() { delete[] key_blob.key_material; } |
| |
| void SetKeyMaterial(const void* key_material, size_t length); |
| void SetKeyMaterial(const keymaster_key_blob_t& blob) { |
| SetKeyMaterial(blob.key_material, blob.key_material_size); |
| } |
| |
| size_t SerializedSize() const; |
| uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const; |
| bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| keymaster_key_blob_t key_blob; |
| }; |
| |
| struct GetVersionRequest : public KeymasterMessage { |
| GetVersionRequest() : KeymasterMessage(0 /* not versionable */) {} |
| |
| size_t SerializedSize() const { return 0; } |
| uint8_t* Serialize(uint8_t* buf, const uint8_t*) const { return buf; } |
| bool Deserialize(const uint8_t**, const uint8_t*) { return true; }; |
| }; |
| |
| struct GetVersionResponse : public KeymasterResponse { |
| GetVersionResponse() |
| : KeymasterResponse(0 /* not versionable */), major_ver(0), minor_ver(0), subminor_ver(0) {} |
| |
| size_t NonErrorSerializedSize() const; |
| uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const; |
| bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end); |
| |
| uint8_t major_ver; |
| uint8_t minor_ver; |
| uint8_t subminor_ver; |
| }; |
| |
| } // namespace keymaster |
| |
| #endif // SYSTEM_KEYMASTER_ANDROID_KEYMASTER_MESSAGES_H_ |