-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathcst_signer.h
More file actions
296 lines (257 loc) · 11.2 KB
/
Copy pathcst_signer.h
File metadata and controls
296 lines (257 loc) · 11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/*
* Copyright 2022-2024 NXP
* SPDX-License-Identifier: GPL-2.0-only
*/
#ifndef CST_SIGNER_H
#define CST_SIGNER_H
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <libgen.h>
#include <stdbool.h>
#include <unistd.h>
/************************
Command line arguments
************************/
/* Valid short command line option letters. */
const char* const short_opt = "hfdi:o:c:p:";
/* Valid long command line options. */
const struct option long_opt[] =
{
{"image", required_argument, 0, 'i'},
{"cfg-file", required_argument, 0, 'c'},
{"offset", required_argument, 0, 'o'},
{"debug", no_argument, 0, 'd'},
{"fdt-debug", no_argument, 0, 'f'},
{"pkcs11", no_argument, 0, 'p'},
{"help", no_argument, 0, 'h'},
{NULL, 0, NULL, 0}
};
/* Option descriptions */
const char* desc_opt[] =
{
"Input image to be signed",
"Input config file to prepare CSF (See csf_ahab.cfg.sample/csf_hab.cfg.sample for details)",
"(Optional) Offset to the start of image",
"(Optional) Enable debug information",
"(Optional) FDT debug information",
"(Optional) Enable pkcs#11 signing. Currently only Linux support, and for cst-3.4.1 you must compile the source",
"This text",
NULL
};
#define FREE(x) do { \
if(NULL != x) { \
free(x); \
x = NULL; \
} \
} while(0)
#define FCLOSE(x) do { \
if(NULL != x) { \
fclose(x); \
x = NULL; \
} \
} while(0)
#define DEBUG(fmt, ...) do { \
if (1 == g_debug) { \
printf("%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__); \
} \
} while(0)
#define ASSERT(x, y) do { \
if (NULL == x) { \
fprintf(stderr, "ERROR: ASSERT failed at %s:%d\n", __FUNCTION__, __LINE__); \
return y; \
} \
} while(0)
#define BASE_HEX 16UL
#define FILENAME_MAX_LEN 100UL
#define SYS_CMD_LEN 400UL
#define IV_MAX_LEN 32
#define HASH_MAX_LEN 64
#define MAX_NUM_IMGS 8
#define MAX_NUM_OF_CONTAINER 4
#define IVT_HEADER_TAG 0xD1
#define IVT_HEADER_TAG_B0 0x87
#define IVT_HEADER_TAG_MSG 0x89
#define IMAGE_TYPE_MASK 0xF
#define CONTAINER_ALIGNMENT 0x400
#define ALIGN(x,a) __ALIGN_MASK((x),(__typeof__(x))(a)-1)
#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
typedef enum SOC_TYPE {
NONE = 0,
QX,
QM,
DXL,
ULP,
} soc_type_t;
#define E_OK 0
#define E_FAILURE 1
#define ASCENDING 0
#define DESCENDING 1
/* offset of the FIT images relative to IVT offset */
#define FIT_IMAGES_OFFSET 0x2000
typedef struct {
uint8_t tag;
uint16_t length;
uint8_t version;
} __attribute__((packed)) ivt_header_t;
typedef struct {
ivt_header_t ivt_hdr;
uint32_t entry;
uint32_t reserved1;
uint32_t dcd;
uint32_t boot_data;
uint32_t self_addr;
uint32_t csf_addr;
uint32_t reserved2;
} __attribute__((packed)) ivt_t;
typedef struct {
uint32_t start;
uint32_t length;
uint32_t plugin_flag;
} __attribute__((packed)) boot_data_t;
typedef struct {
uint8_t version;
uint16_t length;
uint8_t tag;
uint16_t srk_table_offset;
uint16_t cert_offset;
uint16_t blob_offset;
uint16_t signature_offset;
uint32_t reserved;
} __attribute__((packed)) sig_blk_hdr_t;
typedef struct {
char type;
char core_id;
char hash_type;
bool encrypted;
uint16_t boot_flags;
} img_flags_t;
typedef struct {
uint32_t offset;
uint32_t size;
uint64_t dst;
uint64_t entry;
uint32_t hab_flags;
uint32_t meta;
uint8_t hash[HASH_MAX_LEN];
uint8_t iv[IV_MAX_LEN];
} __attribute__((packed)) boot_img_t;
typedef struct {
uint8_t version;
uint16_t length;
uint8_t tag;
uint32_t flags;
uint16_t sw_version;
uint8_t fuse_version;
uint8_t num_images;
uint16_t sig_blk_offset;
uint16_t reserved;
boot_img_t img[MAX_NUM_IMGS];
sig_blk_hdr_t sig_blk_hdr;
uint32_t sigblk_size;
uint32_t padding;
} __attribute__((packed)) flash_header_v3_t;
/* Global Variables */
static bool g_debug = 0;
static char *g_csf_cfgfilename = NULL;
extern uint32_t g_image_offset;
static char *g_cst_path = NULL;
static bool g_pkcs11 = 0; // static to enable pkcs#11 signing
unsigned char g_ivt_v1_mask[] = {0xFF,0xFF,0xFF,0xF0};
unsigned char g_ivt_v1[] = {0xD1,0x00,0x20,0x41};
unsigned char g_ivt_v3_mask[] = {0xff, 0x00, 0x00, 0xff};
/* array contains tag_b0, tag_msg*/
unsigned char g_ivt_v3_ahab_array[2][4] = {{0x00 ,0x00, 0x00, 0x87},/*tag_b0*/
{0x00 ,0x00, 0x00, 0x89}};/*tag_msg*/
#define TAG_B0 0x87
#define TAG_MSG 0x89
#define TAG_SIG_BLK 0x90
#define AHAB_1K_ALIGN 0x400
/*
* header tag check happens at every 0x400 offset inside the image as per NXP
* BSP boot image architecture
*/
#define HAB_IVT_SEARCH_STEP 0x400
#define AHAB_IVT_SEARCH_STEP 0x400
/*
* Length is the size of the container header, up through, and
* including the signature block. A valid image must have the length at least this
* value
*/
#define AHAB_CONTAINER_MIN_LENGTH (sizeof(((flash_header_v3_t *)(0))->version) + \
sizeof(((flash_header_v3_t *)(0))->length) + \
sizeof(((flash_header_v3_t *)(0))->tag) + \
sizeof(((flash_header_v3_t *)(0))->flags) + \
sizeof(((flash_header_v3_t *)(0))->sw_version) + \
sizeof(((flash_header_v3_t *)(0))->fuse_version) + \
sizeof(((flash_header_v3_t *)(0))->num_images) + \
sizeof(((flash_header_v3_t *)(0))->sig_blk_offset) + \
sizeof(((flash_header_v3_t *)(0))->reserved) + \
sizeof(boot_img_t))
/* Message Container length should be exactly 0x48 */
#define AHAB_MSG_CONTAINER_LENGTH 0x48
#define HDMI_IMAGE_FLAG_MASK (0x0002) /* bit 1 is HDMI image indicator */
#define IS_AHAB_IMAGE(buf, size, ahab_array, ivt_v3_mask, off) \
({ \
int num_cntr_tags = sizeof(ahab_array)/sizeof(ahab_array[0]); \
unsigned char (*p)[sizeof(ahab_array[0])] = ahab_array; \
bool is_valid = false; \
\
do { \
off = search_pattern(buf, *p++, size, sizeof(ahab_array[0]), \
ASCENDING, g_image_offset, ivt_v3_mask, \
AHAB_IVT_SEARCH_STEP); \
if (off < size) { \
flash_header_v3_t *hdr_v3 = (flash_header_v3_t *)(buf + off); \
sig_blk_hdr_t *sig_blk_hdr = \
(sig_blk_hdr_t *)(buf + off + hdr_v3->sig_blk_offset); \
if (hdr_v3->tag == TAG_B0) { \
/* Strengthen AHAB header search with following: \
* - Minimum length of container \
* - Reserved fields \
* - Signature block header tag and version \
* - Version \
*/ \
if (hdr_v3->length >= AHAB_CONTAINER_MIN_LENGTH \
&& (!hdr_v3->reserved) \
&& sig_blk_hdr->tag == TAG_SIG_BLK \
&& (!sig_blk_hdr->version) \
&& (!sig_blk_hdr->reserved)) \
is_valid = true; \
} else if (hdr_v3->tag == TAG_MSG) { \
if (hdr_v3->length == AHAB_MSG_CONTAINER_LENGTH) \
is_valid = true; \
} \
\
break; \
} \
} while(--num_cntr_tags); \
(size > off && is_valid); \
}) \
#define IS_HAB_IMAGE(buf, size, ivt_v1, ivt_v1_mask, off) \
({ \
off = search_pattern(buf, ivt_v1, size, sizeof(ivt_v1) / sizeof(ivt_v1[0]), \
ASCENDING, g_image_offset, ivt_v1_mask, \
HAB_IVT_SEARCH_STEP); \
bool is_valid = false; \
ivt_t *ivt = (ivt_t *)(buf + off); \
\
if (off < size) { \
/* Strengthen HAB header search with following: \
* - CSF address is always greater than ENTRY and SELF address \
* - Reserved fields \
*/ \
if ((ivt->csf_addr > ivt->entry) && (ivt->csf_addr > ivt->self_addr) && \
(!ivt->reserved1) && (!ivt->reserved2)) \
is_valid = true; \
} \
(size > off && is_valid); \
}) \
/* Function prototypes */
int copy_files(char *ifname, char *ofname);
long int get_file_size(FILE *fp, char *input_file);
unsigned char *alloc_buffer(FILE *fp, char *input_file);
#endif /* CST_SIGNER_H */