xref: /optee_os/core/pta/imx/dek_blob.c (revision 3afba469a98b7bea135aa7b3c300d98c11d17ac4)
144ce4e40SClement Faure // SPDX-License-Identifier: BSD-2-Clause
244ce4e40SClement Faure /*
344ce4e40SClement Faure  * Copyright 2019, 2023 NXP
444ce4e40SClement Faure  */
544ce4e40SClement Faure 
644ce4e40SClement Faure #include <assert.h>
744ce4e40SClement Faure #include <drivers/caam_extension.h>
844ce4e40SClement Faure #include <initcall.h>
944ce4e40SClement Faure #include <kernel/pseudo_ta.h>
1044ce4e40SClement Faure #include <pta_imx_dek_blob.h>
1144ce4e40SClement Faure #include <string.h>
1244ce4e40SClement Faure #include <tee_api_defines.h>
1344ce4e40SClement Faure #include <tee_api_types.h>
1444ce4e40SClement Faure #include <trace.h>
1544ce4e40SClement Faure 
1644ce4e40SClement Faure #define PTA_NAME "dek_blob.pta"
1744ce4e40SClement Faure 
1844ce4e40SClement Faure /* Blob size padding in bytes */
1944ce4e40SClement Faure #define BLOB_PAD_SIZE 48
2044ce4e40SClement Faure 
2144ce4e40SClement Faure /* HAB Blob header values */
2244ce4e40SClement Faure #define HAB_HDR_TAG	 0x81
2344ce4e40SClement Faure #define HAB_HDR_V4	 0x43
2444ce4e40SClement Faure #define HAB_HDR_MODE_CCM 0x66
2544ce4e40SClement Faure #define HAB_HDR_ALG_AES	 0x55
2644ce4e40SClement Faure 
2744ce4e40SClement Faure /*
2844ce4e40SClement Faure  * DEK blobs are stored by the HAB in a secret key blob data structure. Notice
2944ce4e40SClement Faure  * that the HAB supports a set of encryption algorithms, but the encrypted boot
3044ce4e40SClement Faure  * protocol expects AES. The key length is a variable; it can be 128-bit,
3144ce4e40SClement Faure  * 192-bit, or 256-bit.
3244ce4e40SClement Faure  * For more info, see NXP application note AN12056
3344ce4e40SClement Faure  */
3444ce4e40SClement Faure struct dek_blob_header {
3544ce4e40SClement Faure 	uint8_t tag;	 /* Constant identifying HAB struct: 0x81 */
3644ce4e40SClement Faure 	uint8_t len_msb; /* Struct length in 8-bit msb */
3744ce4e40SClement Faure 	uint8_t len_lsb; /* Struct length in 8-bit lsb */
3844ce4e40SClement Faure 	uint8_t par;	 /* Constant value, HAB version: 0x43 */
3944ce4e40SClement Faure 	uint8_t mode;	 /* AES encryption CCM mode: 0x66 */
4044ce4e40SClement Faure 	uint8_t alg;	 /* AES encryption alg: 0x55 */
4144ce4e40SClement Faure 	uint8_t size;	 /* Unwrapped key value size in bytes */
4244ce4e40SClement Faure 	uint8_t flg;	 /* Key flags */
4344ce4e40SClement Faure };
4444ce4e40SClement Faure 
4544ce4e40SClement Faure /*
4644ce4e40SClement Faure  * Generate HAB DEK blob for encrypted boot
4744ce4e40SClement Faure  *
4844ce4e40SClement Faure  * payload	[in] Plain text key to encapsulate.
4944ce4e40SClement Faure  * payload_size [in] Plain text key size. Must be 128, 192 or 256 bits.
5044ce4e40SClement Faure  * blob		[out] DEK blob.
5144ce4e40SClement Faure  * blob_size	[in/out] DEK blob size.
5244ce4e40SClement Faure  */
do_generate(const uint8_t * payload,size_t payload_size,uint8_t * blob,size_t * blob_size)5344ce4e40SClement Faure static TEE_Result do_generate(const uint8_t *payload, size_t payload_size,
5444ce4e40SClement Faure 			      uint8_t *blob, size_t *blob_size)
5544ce4e40SClement Faure {
5644ce4e40SClement Faure 	struct dek_blob_header *header = NULL;
5744ce4e40SClement Faure 	size_t expected_blob_size = 0;
5844ce4e40SClement Faure 	size_t dek_size = 0;
5944ce4e40SClement Faure 
6044ce4e40SClement Faure 	/*
6144ce4e40SClement Faure 	 * Prevent against an unexpected padding of dek_blob_header structure
6244ce4e40SClement Faure 	 * that must remain packed. This structure will be seriailized to a
6344ce4e40SClement Faure 	 * buffer along the DEK blob.
6444ce4e40SClement Faure 	 */
6544ce4e40SClement Faure 	static_assert(sizeof(struct dek_blob_header) == 8 * sizeof(uint8_t));
6644ce4e40SClement Faure 
6744ce4e40SClement Faure 	assert(payload && blob && payload_size && blob_size);
6844ce4e40SClement Faure 	assert(payload_size == (128 / 8) || payload_size == (192 / 8) ||
6944ce4e40SClement Faure 	       payload_size == (256 / 8));
7044ce4e40SClement Faure 
7144ce4e40SClement Faure 	/*
7244ce4e40SClement Faure 	 * The DEK size is equals to input key size plus the required blob
7344ce4e40SClement Faure 	 * padding. The total output size is the DEK size plus its header
7444ce4e40SClement Faure 	 */
7544ce4e40SClement Faure 	dek_size = payload_size + BLOB_PAD_SIZE;
7644ce4e40SClement Faure 	expected_blob_size = sizeof(*header) + dek_size;
7744ce4e40SClement Faure 
7844ce4e40SClement Faure 	/* Check that the output buffer has the required size */
7944ce4e40SClement Faure 	if (*blob_size < expected_blob_size) {
8044ce4e40SClement Faure 		*blob_size = expected_blob_size;
8144ce4e40SClement Faure 		return TEE_ERROR_SHORT_BUFFER;
8244ce4e40SClement Faure 	}
8344ce4e40SClement Faure 	*blob_size = expected_blob_size;
8444ce4e40SClement Faure 
8544ce4e40SClement Faure 	/* Defined header */
8644ce4e40SClement Faure 	header = (struct dek_blob_header *)blob;
8744ce4e40SClement Faure 	header->tag = HAB_HDR_TAG;
8844ce4e40SClement Faure 	header->len_msb = 0;
8944ce4e40SClement Faure 	header->len_lsb = expected_blob_size;
9044ce4e40SClement Faure 	header->par = HAB_HDR_V4;
9144ce4e40SClement Faure 	header->mode = HAB_HDR_MODE_CCM;
9244ce4e40SClement Faure 	header->alg = HAB_HDR_ALG_AES;
9344ce4e40SClement Faure 	header->size = payload_size;
9444ce4e40SClement Faure 	header->flg = 0;
9544ce4e40SClement Faure 
9644ce4e40SClement Faure 	/* Generate DEK */
9744ce4e40SClement Faure 	return caam_dek_generate(payload, payload_size, blob + sizeof(*header),
9844ce4e40SClement Faure 				 dek_size);
9944ce4e40SClement Faure }
10044ce4e40SClement Faure 
cmd_dek_generate(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])10144ce4e40SClement Faure static TEE_Result cmd_dek_generate(uint32_t param_types,
10244ce4e40SClement Faure 				   TEE_Param params[TEE_NUM_PARAMS])
10344ce4e40SClement Faure {
10444ce4e40SClement Faure 	uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
10544ce4e40SClement Faure 						   TEE_PARAM_TYPE_MEMREF_OUTPUT,
10644ce4e40SClement Faure 						   TEE_PARAM_TYPE_NONE,
10744ce4e40SClement Faure 						   TEE_PARAM_TYPE_NONE);
10844ce4e40SClement Faure 
10944ce4e40SClement Faure 	if (param_types != exp_param_types)
11044ce4e40SClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
11144ce4e40SClement Faure 
11244ce4e40SClement Faure 	if (params[0].memref.size != (128 / 8) &&
11344ce4e40SClement Faure 	    params[0].memref.size != (192 / 8) &&
11444ce4e40SClement Faure 	    params[0].memref.size != (256 / 8))
11544ce4e40SClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
11644ce4e40SClement Faure 
11744ce4e40SClement Faure 	memset(params[1].memref.buffer, 0, params[1].memref.size);
11844ce4e40SClement Faure 
11944ce4e40SClement Faure 	return do_generate(params[0].memref.buffer, params[0].memref.size,
12044ce4e40SClement Faure 			   params[1].memref.buffer, &params[1].memref.size);
12144ce4e40SClement Faure }
12244ce4e40SClement Faure 
invoke_command(void * sess_ctx __unused,uint32_t cmd_id,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])12344ce4e40SClement Faure static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id,
12444ce4e40SClement Faure 				 uint32_t param_types,
12544ce4e40SClement Faure 				 TEE_Param params[TEE_NUM_PARAMS])
12644ce4e40SClement Faure {
12744ce4e40SClement Faure 	switch (cmd_id) {
128*3afba469SClement Faure 	case PTA_IMX_DEK_BLOB_CMD_GENERATE:
12944ce4e40SClement Faure 		return cmd_dek_generate(param_types, params);
13044ce4e40SClement Faure 	default:
13144ce4e40SClement Faure 		return TEE_ERROR_BAD_PARAMETERS;
13244ce4e40SClement Faure 	}
13344ce4e40SClement Faure }
13444ce4e40SClement Faure 
13544ce4e40SClement Faure pseudo_ta_register(.uuid = PTA_DEK_BLOB_UUID, .name = PTA_NAME,
13644ce4e40SClement Faure 		   .flags = PTA_DEFAULT_FLAGS,
13744ce4e40SClement Faure 		   .invoke_command_entry_point = invoke_command);
138