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 */
do_generate(const uint8_t * payload,size_t payload_size,uint8_t * blob,size_t * blob_size)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
cmd_dek_generate(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])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
invoke_command(void * sess_ctx __unused,uint32_t cmd_id,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])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