summaryrefslogtreecommitdiff
path: root/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c
blob: f369094d7977392d34daa78c8a232472a666ec2e (plain)
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
/*
 * Copyright (c) 2014-2016, Freescale Semiconductor, Inc.
 * Copyright 2017-2020 NXP
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include <arch_helpers.h>
#include <common/debug.h>
#include <csf_hdr.h>
#include <drivers/auth/crypto_mod.h>
#include <drivers/auth/img_parser_mod.h>
#include <lib/utils.h>
#include <sfp.h>

/* Temporary variables to speed up the authentication parameters search. These
 * variables are assigned once during the integrity check and used any time an
 * authentication parameter is requested, so we do not have to parse the image
 * again.
 */

/* Hash of Image + CSF Header + SRK table */
uint8_t img_hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE);
uint32_t hash_len;

/* Key being used for authentication
 * Points to the key in CSF header copied in DDR
 * ESBC client key
 */
void *img_key;
uint32_t key_len;

/* ESBC client signature */
void *img_sign;
uint32_t sign_len;
enum sig_alg alg;

/* Maximum OID string length ("a.b.c.d.e.f ...") */
#define MAX_OID_STR_LEN			64

#define LIB_NAME	"NXP CSFv2"

/*
 * Clear all static temporary variables.
 */
static void clear_temp_vars(void)
{
#define ZERO_AND_CLEAN(x)					\
	do {							\
		zeromem(&x, sizeof(x));				\
		clean_dcache_range((uintptr_t)&x, sizeof(x));	\
	} while (0)

	ZERO_AND_CLEAN(img_key);
	ZERO_AND_CLEAN(img_sign);
	ZERO_AND_CLEAN(img_hash);
	ZERO_AND_CLEAN(key_len);
	ZERO_AND_CLEAN(hash_len);
	ZERO_AND_CLEAN(sign_len);

#undef ZERO_AND_CLEAN
}

/* Exported functions */

static void init(void)
{
	clear_temp_vars();
}

/*
 * This function would check the integrity of the CSF header
 */
static int check_integrity(void *img, unsigned int img_len)
{

	int ret = 0;
	/*
	 * Image is appended at an offset of 16K (IMG_OFFSET) to the header.
	 * So the size in header should be equal to img_len - IMG_OFFSET
	 */
	VERBOSE("Barker code is %x\n", *(unsigned int *)img);
	ret = validate_esbc_header(img, &img_key, &key_len, &img_sign,
				   &sign_len, &alg);
	if (ret  < 0) {
		ERROR("Header authentication failed\n");
		clear_temp_vars();
		return IMG_PARSER_ERR;
	}
	/* Calculate the hash of various components from the image */
	ret = calc_img_hash(img, (uint8_t *)img + CSF_HDR_SZ,
			    img_len - CSF_HDR_SZ, img_hash, &hash_len);
	if (ret) {
		ERROR("Issue in hash calculation %d\n", ret);
		clear_temp_vars();
		return IMG_PARSER_ERR;
	}

	return IMG_PARSER_OK;
}

/*
 * Extract an authentication parameter from CSF header
 *
 * CSF header has already been parsed and the required information like
 * hash of data, signature, length stored in global variables has been
 * extracted in chek_integrity function.  This data
 * is returned back to the caller.
 */
static int get_auth_param(const auth_param_type_desc_t *type_desc,
		void *img, unsigned int img_len,
		void **param, unsigned int *param_len)
{
	int rc = IMG_PARSER_OK;

	/* We do not use img because the check_integrity function has already
	 * extracted the relevant data ( pk, sig_alg, etc)
	 */

	switch (type_desc->type) {
	/* Hash will be returned for comparison with signature */
	case AUTH_PARAM_HASH:
		*param = (void *)img_hash;
		*param_len = (unsigned int)SHA256_BYTES;
		break;
	/* Return the public key used for signature extracted from the SRK table
	 * after checks with key revocation
	 */
	case AUTH_PARAM_PUB_KEY:
		/* Get the subject public key */
		/* For a 1K key - the length would be 2k/8 = 0x100 bytes
		 * 2K RSA key - 0x200 , 4K RSA - 0x400
		 */
		*param = img_key;
		*param_len = (unsigned int)key_len;
		break;
	/* Call a function to tell if signature is RSA or ECDSA. ECDSA to be
	 * supported in later platforms like LX2 etc
	 */
	case AUTH_PARAM_SIG_ALG:
		/* Algo will be signature - RSA or ECDSA  on hash */
		*param = (void *)&alg;
		*param_len = 4;
		break;
	/* Return the signature */
	case AUTH_PARAM_SIG:
		*param = img_sign;
		*param_len = (unsigned int)sign_len;
		break;
	case AUTH_PARAM_NV_CTR:
	default:
		rc = IMG_PARSER_ERR_NOT_FOUND;
		break;
	}
	return rc;
}

REGISTER_IMG_PARSER_LIB(IMG_PLAT, LIB_NAME, init,
			 check_integrity, get_auth_param);