xref: /rk3399_ARM-atf/drivers/auth/mbedtls/mbedtls_psa_crypto.c (revision 4eaaaa19299040cfee0585d7daa744dee716d398)
1 /*
2  * Copyright (c) 2023, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <stddef.h>
9 #include <string.h>
10 
11 /* mbed TLS headers */
12 #include <mbedtls/gcm.h>
13 #include <mbedtls/md.h>
14 #include <mbedtls/memory_buffer_alloc.h>
15 #include <mbedtls/oid.h>
16 #include <mbedtls/platform.h>
17 #include <mbedtls/version.h>
18 #include <mbedtls/x509.h>
19 #include <psa/crypto.h>
20 #include <psa/crypto_platform.h>
21 #include <psa/crypto_types.h>
22 #include <psa/crypto_values.h>
23 
24 #include <common/debug.h>
25 #include <drivers/auth/crypto_mod.h>
26 #include <drivers/auth/mbedtls/mbedtls_common.h>
27 #include <plat/common/platform.h>
28 
29 #define LIB_NAME		"mbed TLS PSA"
30 
31 #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
32 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
33 /*
34  * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available
35  * so make sure that mbed TLS MD maximum size must be lesser than this.
36  */
37 CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE,
38 	assert_mbedtls_md_size_overflow);
39 
40 #endif /*
41 	* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
42 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
43 	*/
44 
45 /*
46  * AlgorithmIdentifier  ::=  SEQUENCE  {
47  *     algorithm               OBJECT IDENTIFIER,
48  *     parameters              ANY DEFINED BY algorithm OPTIONAL
49  * }
50  *
51  * SubjectPublicKeyInfo  ::=  SEQUENCE  {
52  *     algorithm            AlgorithmIdentifier,
53  *     subjectPublicKey     BIT STRING
54  * }
55  *
56  * DigestInfo ::= SEQUENCE {
57  *     digestAlgorithm AlgorithmIdentifier,
58  *     digest OCTET STRING
59  * }
60  */
61 
62 /*
63  * We pretend using an external RNG (through MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
64  * mbedTLS config option) so we need to provide an implementation of
65  * mbedtls_psa_external_get_random(). Provide a fake one, since we do not
66  * actually have any external RNG and TF-A itself doesn't engage in
67  * cryptographic operations that demands randomness.
68  */
69 psa_status_t mbedtls_psa_external_get_random(
70 			mbedtls_psa_external_random_context_t *context,
71 			uint8_t *output, size_t output_size,
72 			size_t *output_length)
73 {
74 	return PSA_ERROR_INSUFFICIENT_ENTROPY;
75 }
76 
77 /*
78  * Initialize the library and export the descriptor
79  */
80 static void init(void)
81 {
82 	/* Initialize mbed TLS */
83 	mbedtls_init();
84 
85 	/* Initialise PSA mbedTLS */
86 	psa_status_t status = psa_crypto_init();
87 
88 	if (status != PSA_SUCCESS) {
89 		ERROR("Failed to initialize %s crypto (%d).\n", LIB_NAME, status);
90 		panic();
91 	}
92 
93 	INFO("PSA crypto initialized successfully!\n");
94 }
95 
96 #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
97 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
98 /*
99  * Verify a signature.
100  *
101  * Parameters are passed using the DER encoding format following the ASN.1
102  * structures detailed above.
103  */
104 static int verify_signature(void *data_ptr, unsigned int data_len,
105 			    void *sig_ptr, unsigned int sig_len,
106 			    void *sig_alg, unsigned int sig_alg_len,
107 			    void *pk_ptr, unsigned int pk_len)
108 {
109 	mbedtls_asn1_buf sig_oid, sig_params;
110 	mbedtls_asn1_buf signature;
111 	mbedtls_md_type_t md_alg;
112 	mbedtls_pk_type_t pk_alg;
113 	mbedtls_pk_context pk = {0};
114 	int rc;
115 	void *sig_opts = NULL;
116 	const mbedtls_md_info_t *md_info;
117 	unsigned char *p, *end;
118 	unsigned char hash[MBEDTLS_MD_MAX_SIZE];
119 
120 	/* Get pointers to signature OID and parameters */
121 	p = (unsigned char *)sig_alg;
122 	end = (unsigned char *)(p + sig_alg_len);
123 	rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
124 	if (rc != 0) {
125 		return CRYPTO_ERR_SIGNATURE;
126 	}
127 
128 	/* Get the actual signature algorithm (MD + PK) */
129 	rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts);
130 	if (rc != 0) {
131 		return CRYPTO_ERR_SIGNATURE;
132 	}
133 
134 	/* Parse the public key */
135 	mbedtls_pk_init(&pk);
136 	p = (unsigned char *)pk_ptr;
137 	end = (unsigned char *)(p + pk_len);
138 	rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
139 	if (rc != 0) {
140 		rc = CRYPTO_ERR_SIGNATURE;
141 		goto end2;
142 	}
143 
144 	/* Get the signature (bitstring) */
145 	p = (unsigned char *)sig_ptr;
146 	end = (unsigned char *)(p + sig_len);
147 	signature.tag = *p;
148 	rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
149 	if ((rc != 0) || ((size_t)(end - p) != signature.len)) {
150 		rc = CRYPTO_ERR_SIGNATURE;
151 		goto end1;
152 	}
153 	signature.p = p;
154 
155 	/* Calculate the hash of the data */
156 	md_info = mbedtls_md_info_from_type(md_alg);
157 	if (md_info == NULL) {
158 		rc = CRYPTO_ERR_SIGNATURE;
159 		goto end1;
160 	}
161 	p = (unsigned char *)data_ptr;
162 	rc = mbedtls_md(md_info, p, data_len, hash);
163 	if (rc != 0) {
164 		rc = CRYPTO_ERR_SIGNATURE;
165 		goto end1;
166 	}
167 
168 	/* Verify the signature */
169 	rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
170 			mbedtls_md_get_size(md_info),
171 			signature.p, signature.len);
172 	if (rc != 0) {
173 		rc = CRYPTO_ERR_SIGNATURE;
174 		goto end1;
175 	}
176 
177 	/* Signature verification success */
178 	rc = CRYPTO_SUCCESS;
179 
180 end1:
181 	mbedtls_pk_free(&pk);
182 end2:
183 	mbedtls_free(sig_opts);
184 	return rc;
185 }
186 
187 /*
188  * Match a hash
189  *
190  * Digest info is passed in DER format following the ASN.1 structure detailed
191  * above.
192  */
193 static int verify_hash(void *data_ptr, unsigned int data_len,
194 		       void *digest_info_ptr, unsigned int digest_info_len)
195 {
196 	mbedtls_asn1_buf hash_oid, params;
197 	mbedtls_md_type_t md_alg;
198 	const mbedtls_md_info_t *md_info;
199 	unsigned char *p, *end, *hash;
200 	unsigned char data_hash[MBEDTLS_MD_MAX_SIZE];
201 	size_t len;
202 	int rc;
203 
204 	/*
205 	 * Digest info should be an MBEDTLS_ASN1_SEQUENCE, but padding after
206 	 * it is allowed.  This is necessary to support multiple hash
207 	 * algorithms.
208 	 */
209 	p = (unsigned char *)digest_info_ptr;
210 	end = p + digest_info_len;
211 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
212 				  MBEDTLS_ASN1_SEQUENCE);
213 	if (rc != 0) {
214 		return CRYPTO_ERR_HASH;
215 	}
216 
217 	end = p + len;
218 
219 	/* Get the hash algorithm */
220 	rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
221 	if (rc != 0) {
222 		return CRYPTO_ERR_HASH;
223 	}
224 
225 	rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
226 	if (rc != 0) {
227 		return CRYPTO_ERR_HASH;
228 	}
229 
230 	md_info = mbedtls_md_info_from_type(md_alg);
231 	if (md_info == NULL) {
232 		return CRYPTO_ERR_HASH;
233 	}
234 
235 	/* Hash should be octet string type and consume all bytes */
236 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
237 	if ((rc != 0) || ((size_t)(end - p) != len)) {
238 		return CRYPTO_ERR_HASH;
239 	}
240 
241 	/* Length of hash must match the algorithm's size */
242 	if (len != mbedtls_md_get_size(md_info)) {
243 		return CRYPTO_ERR_HASH;
244 	}
245 	hash = p;
246 
247 	/* Calculate the hash of the data */
248 	p = (unsigned char *)data_ptr;
249 	rc = mbedtls_md(md_info, p, data_len, data_hash);
250 	if (rc != 0) {
251 		return CRYPTO_ERR_HASH;
252 	}
253 
254 	/* Compare values */
255 	rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info));
256 	if (rc != 0) {
257 		return CRYPTO_ERR_HASH;
258 	}
259 
260 	return CRYPTO_SUCCESS;
261 }
262 #endif /*
263 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
264 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
265 	*/
266 
267 #if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
268 CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
269 /*
270  * Map a generic crypto message digest algorithm to the corresponding macro used
271  * by Mbed TLS.
272  */
273 static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo)
274 {
275 	switch (algo) {
276 	case CRYPTO_MD_SHA512:
277 		return MBEDTLS_MD_SHA512;
278 	case CRYPTO_MD_SHA384:
279 		return MBEDTLS_MD_SHA384;
280 	case CRYPTO_MD_SHA256:
281 		return MBEDTLS_MD_SHA256;
282 	default:
283 		/* Invalid hash algorithm. */
284 		return MBEDTLS_MD_NONE;
285 	}
286 }
287 
288 /*
289  * Calculate a hash
290  *
291  * output points to the computed hash
292  */
293 static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr,
294 		     unsigned int data_len,
295 		     unsigned char output[CRYPTO_MD_MAX_SIZE])
296 {
297 	const mbedtls_md_info_t *md_info;
298 
299 	md_info = mbedtls_md_info_from_type(md_type(md_algo));
300 	if (md_info == NULL) {
301 		return CRYPTO_ERR_HASH;
302 	}
303 
304 	/*
305 	 * Calculate the hash of the data, it is safe to pass the
306 	 * 'output' hash buffer pointer considering its size is always
307 	 * bigger than or equal to MBEDTLS_MD_MAX_SIZE.
308 	 */
309 	return mbedtls_md(md_info, data_ptr, data_len, output);
310 }
311 #endif /*
312 	* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
313 	* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
314 	*/
315 
316 #if TF_MBEDTLS_USE_AES_GCM
317 /*
318  * Stack based buffer allocation for decryption operation. It could
319  * be configured to balance stack usage vs execution speed.
320  */
321 #define DEC_OP_BUF_SIZE		128
322 
323 static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key,
324 			   unsigned int key_len, const void *iv,
325 			   unsigned int iv_len, const void *tag,
326 			   unsigned int tag_len)
327 {
328 	mbedtls_gcm_context ctx;
329 	mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
330 	unsigned char buf[DEC_OP_BUF_SIZE];
331 	unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
332 	unsigned char *pt = data_ptr;
333 	size_t dec_len;
334 	int diff, i, rc;
335 	size_t output_length __unused;
336 
337 	mbedtls_gcm_init(&ctx);
338 
339 	rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8);
340 	if (rc != 0) {
341 		rc = CRYPTO_ERR_DECRYPTION;
342 		goto exit_gcm;
343 	}
344 
345 #if (MBEDTLS_VERSION_MAJOR < 3)
346 	rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0);
347 #else
348 	rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len);
349 #endif
350 	if (rc != 0) {
351 		rc = CRYPTO_ERR_DECRYPTION;
352 		goto exit_gcm;
353 	}
354 
355 	while (len > 0) {
356 		dec_len = MIN(sizeof(buf), len);
357 
358 #if (MBEDTLS_VERSION_MAJOR < 3)
359 		rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf);
360 #else
361 		rc = mbedtls_gcm_update(&ctx, pt, dec_len, buf, sizeof(buf), &output_length);
362 #endif
363 
364 		if (rc != 0) {
365 			rc = CRYPTO_ERR_DECRYPTION;
366 			goto exit_gcm;
367 		}
368 
369 		memcpy(pt, buf, dec_len);
370 		pt += dec_len;
371 		len -= dec_len;
372 	}
373 
374 #if (MBEDTLS_VERSION_MAJOR < 3)
375 	rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf));
376 #else
377 	rc = mbedtls_gcm_finish(&ctx, NULL, 0, &output_length, tag_buf, sizeof(tag_buf));
378 #endif
379 
380 	if (rc != 0) {
381 		rc = CRYPTO_ERR_DECRYPTION;
382 		goto exit_gcm;
383 	}
384 
385 	/* Check tag in "constant-time" */
386 	for (diff = 0, i = 0; i < tag_len; i++)
387 		diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
388 
389 	if (diff != 0) {
390 		rc = CRYPTO_ERR_DECRYPTION;
391 		goto exit_gcm;
392 	}
393 
394 	/* GCM decryption success */
395 	rc = CRYPTO_SUCCESS;
396 
397 exit_gcm:
398 	mbedtls_gcm_free(&ctx);
399 	return rc;
400 }
401 
402 /*
403  * Authenticated decryption of an image
404  */
405 static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
406 			size_t len, const void *key, unsigned int key_len,
407 			unsigned int key_flags, const void *iv,
408 			unsigned int iv_len, const void *tag,
409 			unsigned int tag_len)
410 {
411 	int rc;
412 
413 	assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0);
414 
415 	switch (dec_algo) {
416 	case CRYPTO_GCM_DECRYPT:
417 		rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len,
418 				     tag, tag_len);
419 		if (rc != 0)
420 			return rc;
421 		break;
422 	default:
423 		return CRYPTO_ERR_DECRYPTION;
424 	}
425 
426 	return CRYPTO_SUCCESS;
427 }
428 #endif /* TF_MBEDTLS_USE_AES_GCM */
429 
430 /*
431  * Register crypto library descriptor
432  */
433 #if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
434 #if TF_MBEDTLS_USE_AES_GCM
435 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
436 		    auth_decrypt, NULL);
437 #else
438 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
439 		    NULL, NULL);
440 #endif
441 #elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY
442 #if TF_MBEDTLS_USE_AES_GCM
443 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
444 		    auth_decrypt, NULL);
445 #else
446 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL,
447 		    NULL, NULL);
448 #endif
449 #elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY
450 REGISTER_CRYPTO_LIB(LIB_NAME, init, NULL, NULL, calc_hash, NULL, NULL);
451 #endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
452