aboutsummaryrefslogtreecommitdiff
path: root/drivers/nxp/crypto/caam/src/auth/rsa.c
blob: 0c4446238dcba133d40e8a4edc9043688e93e870 (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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
 * Copyright 2021 NXP
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <arch_helpers.h>
#include "caam.h"
#include <common/debug.h>
#include <drivers/auth/crypto_mod.h>

#include "jobdesc.h"
#include "rsa.h"
#include "sec_hw_specific.h"

/* This array contains DER value for SHA-256 */
static const uint8_t hash_identifier[] = {
	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
	0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
	0x04, 0x20
};

static void rsa_done(uint32_t *desc, uint32_t status, void *arg,
		     void *job_ring)
{
	INFO("RSA Desc SUCCESS with status %x\n", status);
}

static int rsa_public_verif_sec(uint8_t *sign, uint8_t *to,
				uint8_t *rsa_pub_key, uint32_t klen)
{
	int ret = 0;
	struct rsa_context ctx __aligned(CACHE_WRITEBACK_GRANULE);
	struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE);

	jobdesc.arg = NULL;
	jobdesc.callback = rsa_done;

	memset(&ctx, 0, sizeof(struct rsa_context));

	ctx.pkin.a = sign;
	ctx.pkin.a_siz = klen;
	ctx.pkin.n = rsa_pub_key;
	ctx.pkin.n_siz = klen;
	ctx.pkin.e = rsa_pub_key + klen;
	ctx.pkin.e_siz = klen;

	cnstr_jobdesc_pkha_rsaexp(jobdesc.desc, &ctx.pkin, to, klen);

#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
	flush_dcache_range((uintptr_t)sign, klen);
	flush_dcache_range((uintptr_t)rsa_pub_key, 2 * klen);
	flush_dcache_range((uintptr_t)&ctx.pkin, sizeof(ctx.pkin));
	inv_dcache_range((uintptr_t)to, klen);

	dmbsy();
	dsbsy();
	isb();
#endif

	/* Finally, generate the requested random data bytes */
	ret = run_descriptor_jr(&jobdesc);
	if (ret != 0) {
		ERROR("Error in running descriptor\n");
		ret = -1;
	}
#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
	inv_dcache_range((uintptr_t)to, klen);
	dmbsy();
	dsbsy();
	isb();
#endif
	return ret;
}

/*
 * Construct encoded hash EM' wrt PKCSv1.5. This function calculates the
 * pointers for padding, DER value and hash. And finally, constructs EM'
 * which includes hash of complete CSF header and ESBC image. If SG flag
 * is on, hash of SG table and entries is also included.
 */
static int construct_img_encoded_hash_second(uint8_t *hash, uint8_t hash_len,
					     uint8_t *encoded_hash_second,
					     unsigned int key_len)
{
	/*
	 * RSA PKCSv1.5 encoding format for encoded message is below
	 * EM = 0x0 || 0x1 || PS || 0x0 || DER || Hash
	 * PS is Padding String
	 * DER is DER value for SHA-256
	 * Hash is SHA-256 hash
	 * *********************************************************
	 * representative points to first byte of EM initially and is
	 * filled with 0x0
	 * representative is incremented by 1 and second byte is filled
	 * with 0x1
	 * padding points to third byte of EM
	 * digest points to full length of EM - 32 bytes
	 * hash_id (DER value) points to 19 bytes before pDigest
	 * separator is one byte which separates padding and DER
	 */

	unsigned int len;
	uint8_t *representative;
	uint8_t *padding, *digest;
	uint8_t *hash_id, *separator;
	int i;
	int ret = 0;

	if (hash_len != SHA256_BYTES) {
		return -1;
	}

	/* Key length = Modulus length */
	len = (key_len / 2U) - 1U;
	representative = encoded_hash_second;
	representative[0] = 0U;
	representative[1] = 1U;	/* block type 1 */

	padding = &representative[2];
	digest = &representative[1] + len - 32;
	hash_id = digest - sizeof(hash_identifier);
	separator = hash_id - 1;

	/* fill padding area pointed by padding with 0xff */
	memset(padding, 0xff, separator - padding);

	/* fill byte pointed by separator */
	*separator = 0U;

	/* fill SHA-256 DER value  pointed by HashId */
	memcpy(hash_id, hash_identifier, sizeof(hash_identifier));

	/* fill hash pointed by Digest */
	for (i = 0; i < SHA256_BYTES; i++) {
		digest[i] = hash[i];
	}

	return ret;
}

int rsa_verify_signature(void *hash_ptr, unsigned int hash_len,
			 void *sig_ptr, unsigned int sig_len,
			 void *pk_ptr, unsigned int pk_len)
{
	uint8_t img_encoded_hash_second[RSA_4K_KEY_SZ_BYTES];
	uint8_t encoded_hash[RSA_4K_KEY_SZ_BYTES] __aligned(CACHE_WRITEBACK_GRANULE);
	int ret = 0;

	ret = construct_img_encoded_hash_second(hash_ptr, hash_len,
						img_encoded_hash_second,
						pk_len);
	if (ret != 0) {
		ERROR("Encoded Hash Failure\n");
		return CRYPTO_ERR_SIGNATURE;
	}

	ret = rsa_public_verif_sec(sig_ptr, encoded_hash, pk_ptr, pk_len / 2);
	if (ret != 0) {
		ERROR("RSA signature Failure\n");
		return CRYPTO_ERR_SIGNATURE;
	}

	ret = memcmp(img_encoded_hash_second, encoded_hash, sig_len);
	if (ret != 0) {
		ERROR("Comparison Failure\n");
		return CRYPTO_ERR_SIGNATURE;
	}

	return CRYPTO_SUCCESS;
}