1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright 2019, 2023 NXP 4 */ 5 6 #include <assert.h> 7 #include <drivers/caam_extension.h> 8 #include <initcall.h> 9 #include <kernel/pseudo_ta.h> 10 #include <pta_imx_dek_blob.h> 11 #include <string.h> 12 #include <tee_api_defines.h> 13 #include <tee_api_types.h> 14 #include <trace.h> 15 16 #define PTA_NAME "dek_blob.pta" 17 18 /* Blob size padding in bytes */ 19 #define BLOB_PAD_SIZE 48 20 21 /* HAB Blob header values */ 22 #define HAB_HDR_TAG 0x81 23 #define HAB_HDR_V4 0x43 24 #define HAB_HDR_MODE_CCM 0x66 25 #define HAB_HDR_ALG_AES 0x55 26 27 /* 28 * DEK blobs are stored by the HAB in a secret key blob data structure. Notice 29 * that the HAB supports a set of encryption algorithms, but the encrypted boot 30 * protocol expects AES. The key length is a variable; it can be 128-bit, 31 * 192-bit, or 256-bit. 32 * For more info, see NXP application note AN12056 33 */ 34 struct dek_blob_header { 35 uint8_t tag; /* Constant identifying HAB struct: 0x81 */ 36 uint8_t len_msb; /* Struct length in 8-bit msb */ 37 uint8_t len_lsb; /* Struct length in 8-bit lsb */ 38 uint8_t par; /* Constant value, HAB version: 0x43 */ 39 uint8_t mode; /* AES encryption CCM mode: 0x66 */ 40 uint8_t alg; /* AES encryption alg: 0x55 */ 41 uint8_t size; /* Unwrapped key value size in bytes */ 42 uint8_t flg; /* Key flags */ 43 }; 44 45 /* 46 * Generate HAB DEK blob for encrypted boot 47 * 48 * payload [in] Plain text key to encapsulate. 49 * payload_size [in] Plain text key size. Must be 128, 192 or 256 bits. 50 * blob [out] DEK blob. 51 * blob_size [in/out] DEK blob size. 52 */ 53 static TEE_Result do_generate(const uint8_t *payload, size_t payload_size, 54 uint8_t *blob, size_t *blob_size) 55 { 56 struct dek_blob_header *header = NULL; 57 size_t expected_blob_size = 0; 58 size_t dek_size = 0; 59 60 /* 61 * Prevent against an unexpected padding of dek_blob_header structure 62 * that must remain packed. This structure will be seriailized to a 63 * buffer along the DEK blob. 64 */ 65 static_assert(sizeof(struct dek_blob_header) == 8 * sizeof(uint8_t)); 66 67 assert(payload && blob && payload_size && blob_size); 68 assert(payload_size == (128 / 8) || payload_size == (192 / 8) || 69 payload_size == (256 / 8)); 70 71 /* 72 * The DEK size is equals to input key size plus the required blob 73 * padding. The total output size is the DEK size plus its header 74 */ 75 dek_size = payload_size + BLOB_PAD_SIZE; 76 expected_blob_size = sizeof(*header) + dek_size; 77 78 /* Check that the output buffer has the required size */ 79 if (*blob_size < expected_blob_size) { 80 *blob_size = expected_blob_size; 81 return TEE_ERROR_SHORT_BUFFER; 82 } 83 *blob_size = expected_blob_size; 84 85 /* Defined header */ 86 header = (struct dek_blob_header *)blob; 87 header->tag = HAB_HDR_TAG; 88 header->len_msb = 0; 89 header->len_lsb = expected_blob_size; 90 header->par = HAB_HDR_V4; 91 header->mode = HAB_HDR_MODE_CCM; 92 header->alg = HAB_HDR_ALG_AES; 93 header->size = payload_size; 94 header->flg = 0; 95 96 /* Generate DEK */ 97 return caam_dek_generate(payload, payload_size, blob + sizeof(*header), 98 dek_size); 99 } 100 101 static TEE_Result cmd_dek_generate(uint32_t param_types, 102 TEE_Param params[TEE_NUM_PARAMS]) 103 { 104 uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 105 TEE_PARAM_TYPE_MEMREF_OUTPUT, 106 TEE_PARAM_TYPE_NONE, 107 TEE_PARAM_TYPE_NONE); 108 109 if (param_types != exp_param_types) 110 return TEE_ERROR_BAD_PARAMETERS; 111 112 if (params[0].memref.size != (128 / 8) && 113 params[0].memref.size != (192 / 8) && 114 params[0].memref.size != (256 / 8)) 115 return TEE_ERROR_BAD_PARAMETERS; 116 117 memset(params[1].memref.buffer, 0, params[1].memref.size); 118 119 return do_generate(params[0].memref.buffer, params[0].memref.size, 120 params[1].memref.buffer, ¶ms[1].memref.size); 121 } 122 123 static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, 124 uint32_t param_types, 125 TEE_Param params[TEE_NUM_PARAMS]) 126 { 127 switch (cmd_id) { 128 case PTA_IMX_DEK_BLOB_CMD_GENERATE: 129 return cmd_dek_generate(param_types, params); 130 default: 131 return TEE_ERROR_BAD_PARAMETERS; 132 } 133 } 134 135 pseudo_ta_register(.uuid = PTA_DEK_BLOB_UUID, .name = PTA_NAME, 136 .flags = PTA_DEFAULT_FLAGS, 137 .invoke_command_entry_point = invoke_command); 138