xref: /rk3399_ARM-atf/drivers/auth/mbedtls/mbedtls_crypto.c (revision 6dc5979a6cb2121e4c16e7bd62e24030e0f42755)
1 /*
2  * Copyright (c) 2015-2022, Arm Limited and Contributors. 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/x509.h>
18 
19 #include <common/debug.h>
20 #include <drivers/auth/crypto_mod.h>
21 #include <drivers/auth/mbedtls/mbedtls_common.h>
22 #include <drivers/auth/mbedtls/mbedtls_config.h>
23 #include <plat/common/platform.h>
24 
25 #define LIB_NAME		"mbed TLS"
26 
27 #if MEASURED_BOOT
28 /*
29  * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available
30  * so make sure that mbed TLS MD maximum size must be lesser than this.
31  */
32 CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE,
33 	assert_mbedtls_md_size_overflow);
34 
35 #endif /* MEASURED_BOOT */
36 
37 /*
38  * AlgorithmIdentifier  ::=  SEQUENCE  {
39  *     algorithm               OBJECT IDENTIFIER,
40  *     parameters              ANY DEFINED BY algorithm OPTIONAL
41  * }
42  *
43  * SubjectPublicKeyInfo  ::=  SEQUENCE  {
44  *     algorithm            AlgorithmIdentifier,
45  *     subjectPublicKey     BIT STRING
46  * }
47  *
48  * DigestInfo ::= SEQUENCE {
49  *     digestAlgorithm AlgorithmIdentifier,
50  *     digest OCTET STRING
51  * }
52  */
53 
54 /*
55  * Initialize the library and export the descriptor
56  */
57 static void init(void)
58 {
59 	/* Initialize mbed TLS */
60 	mbedtls_init();
61 }
62 
63 #if TRUSTED_BOARD_BOOT
64 /*
65  * Verify a signature.
66  *
67  * Parameters are passed using the DER encoding format following the ASN.1
68  * structures detailed above.
69  */
70 static int verify_signature(void *data_ptr, unsigned int data_len,
71 			    void *sig_ptr, unsigned int sig_len,
72 			    void *sig_alg, unsigned int sig_alg_len,
73 			    void *pk_ptr, unsigned int pk_len)
74 {
75 	mbedtls_asn1_buf sig_oid, sig_params;
76 	mbedtls_asn1_buf signature;
77 	mbedtls_md_type_t md_alg;
78 	mbedtls_pk_type_t pk_alg;
79 	mbedtls_pk_context pk = {0};
80 	int rc;
81 	void *sig_opts = NULL;
82 	const mbedtls_md_info_t *md_info;
83 	unsigned char *p, *end;
84 	unsigned char hash[MBEDTLS_MD_MAX_SIZE];
85 
86 	/* Get pointers to signature OID and parameters */
87 	p = (unsigned char *)sig_alg;
88 	end = (unsigned char *)(p + sig_alg_len);
89 	rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
90 	if (rc != 0) {
91 		return CRYPTO_ERR_SIGNATURE;
92 	}
93 
94 	/* Get the actual signature algorithm (MD + PK) */
95 	rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts);
96 	if (rc != 0) {
97 		return CRYPTO_ERR_SIGNATURE;
98 	}
99 
100 	/* Parse the public key */
101 	mbedtls_pk_init(&pk);
102 	p = (unsigned char *)pk_ptr;
103 	end = (unsigned char *)(p + pk_len);
104 	rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
105 	if (rc != 0) {
106 		rc = CRYPTO_ERR_SIGNATURE;
107 		goto end2;
108 	}
109 
110 	/* Get the signature (bitstring) */
111 	p = (unsigned char *)sig_ptr;
112 	end = (unsigned char *)(p + sig_len);
113 	signature.tag = *p;
114 	rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
115 	if (rc != 0) {
116 		rc = CRYPTO_ERR_SIGNATURE;
117 		goto end1;
118 	}
119 	signature.p = p;
120 
121 	/* Calculate the hash of the data */
122 	md_info = mbedtls_md_info_from_type(md_alg);
123 	if (md_info == NULL) {
124 		rc = CRYPTO_ERR_SIGNATURE;
125 		goto end1;
126 	}
127 	p = (unsigned char *)data_ptr;
128 	rc = mbedtls_md(md_info, p, data_len, hash);
129 	if (rc != 0) {
130 		rc = CRYPTO_ERR_SIGNATURE;
131 		goto end1;
132 	}
133 
134 	/* Verify the signature */
135 	rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
136 			mbedtls_md_get_size(md_info),
137 			signature.p, signature.len);
138 	if (rc != 0) {
139 		rc = CRYPTO_ERR_SIGNATURE;
140 		goto end1;
141 	}
142 
143 	/* Signature verification success */
144 	rc = CRYPTO_SUCCESS;
145 
146 end1:
147 	mbedtls_pk_free(&pk);
148 end2:
149 	mbedtls_free(sig_opts);
150 	return rc;
151 }
152 
153 /*
154  * Match a hash
155  *
156  * Digest info is passed in DER format following the ASN.1 structure detailed
157  * above.
158  */
159 static int verify_hash(void *data_ptr, unsigned int data_len,
160 		       void *digest_info_ptr, unsigned int digest_info_len)
161 {
162 	mbedtls_asn1_buf hash_oid, params;
163 	mbedtls_md_type_t md_alg;
164 	const mbedtls_md_info_t *md_info;
165 	unsigned char *p, *end, *hash;
166 	unsigned char data_hash[MBEDTLS_MD_MAX_SIZE];
167 	size_t len;
168 	int rc;
169 
170 	/* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
171 	p = (unsigned char *)digest_info_ptr;
172 	end = p + digest_info_len;
173 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
174 				  MBEDTLS_ASN1_SEQUENCE);
175 	if (rc != 0) {
176 		return CRYPTO_ERR_HASH;
177 	}
178 
179 	/* Get the hash algorithm */
180 	rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
181 	if (rc != 0) {
182 		return CRYPTO_ERR_HASH;
183 	}
184 
185 	rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
186 	if (rc != 0) {
187 		return CRYPTO_ERR_HASH;
188 	}
189 
190 	md_info = mbedtls_md_info_from_type(md_alg);
191 	if (md_info == NULL) {
192 		return CRYPTO_ERR_HASH;
193 	}
194 
195 	/* Hash should be octet string type */
196 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
197 	if (rc != 0) {
198 		return CRYPTO_ERR_HASH;
199 	}
200 
201 	/* Length of hash must match the algorithm's size */
202 	if (len != mbedtls_md_get_size(md_info)) {
203 		return CRYPTO_ERR_HASH;
204 	}
205 	hash = p;
206 
207 	/* Calculate the hash of the data */
208 	p = (unsigned char *)data_ptr;
209 	rc = mbedtls_md(md_info, p, data_len, data_hash);
210 	if (rc != 0) {
211 		return CRYPTO_ERR_HASH;
212 	}
213 
214 	/* Compare values */
215 	rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info));
216 	if (rc != 0) {
217 		return CRYPTO_ERR_HASH;
218 	}
219 
220 	return CRYPTO_SUCCESS;
221 }
222 #endif /* TRUSTED_BOARD_BOOT */
223 
224 #if MEASURED_BOOT
225 /*
226  * Map a generic crypto message digest algorithm to the corresponding macro used
227  * by Mbed TLS.
228  */
229 static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo)
230 {
231 	switch (algo) {
232 	case CRYPTO_MD_SHA512:
233 		return MBEDTLS_MD_SHA512;
234 	case CRYPTO_MD_SHA384:
235 		return MBEDTLS_MD_SHA384;
236 	case CRYPTO_MD_SHA256:
237 		return MBEDTLS_MD_SHA256;
238 	default:
239 		/* Invalid hash algorithm. */
240 		return MBEDTLS_MD_NONE;
241 	}
242 }
243 
244 /*
245  * Calculate a hash
246  *
247  * output points to the computed hash
248  */
249 static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr,
250 		     unsigned int data_len,
251 		     unsigned char output[CRYPTO_MD_MAX_SIZE])
252 {
253 	const mbedtls_md_info_t *md_info;
254 
255 	md_info = mbedtls_md_info_from_type(md_type(md_algo));
256 	if (md_info == NULL) {
257 		return CRYPTO_ERR_HASH;
258 	}
259 
260 	/*
261 	 * Calculate the hash of the data, it is safe to pass the
262 	 * 'output' hash buffer pointer considering its size is always
263 	 * bigger than or equal to MBEDTLS_MD_MAX_SIZE.
264 	 */
265 	return mbedtls_md(md_info, data_ptr, data_len, output);
266 }
267 #endif /* MEASURED_BOOT */
268 
269 #if TF_MBEDTLS_USE_AES_GCM
270 /*
271  * Stack based buffer allocation for decryption operation. It could
272  * be configured to balance stack usage vs execution speed.
273  */
274 #define DEC_OP_BUF_SIZE		128
275 
276 static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key,
277 			   unsigned int key_len, const void *iv,
278 			   unsigned int iv_len, const void *tag,
279 			   unsigned int tag_len)
280 {
281 	mbedtls_gcm_context ctx;
282 	mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
283 	unsigned char buf[DEC_OP_BUF_SIZE];
284 	unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
285 	unsigned char *pt = data_ptr;
286 	size_t dec_len;
287 	int diff, i, rc;
288 
289 	mbedtls_gcm_init(&ctx);
290 
291 	rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8);
292 	if (rc != 0) {
293 		rc = CRYPTO_ERR_DECRYPTION;
294 		goto exit_gcm;
295 	}
296 
297 	rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0);
298 	if (rc != 0) {
299 		rc = CRYPTO_ERR_DECRYPTION;
300 		goto exit_gcm;
301 	}
302 
303 	while (len > 0) {
304 		dec_len = MIN(sizeof(buf), len);
305 
306 		rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf);
307 		if (rc != 0) {
308 			rc = CRYPTO_ERR_DECRYPTION;
309 			goto exit_gcm;
310 		}
311 
312 		memcpy(pt, buf, dec_len);
313 		pt += dec_len;
314 		len -= dec_len;
315 	}
316 
317 	rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf));
318 	if (rc != 0) {
319 		rc = CRYPTO_ERR_DECRYPTION;
320 		goto exit_gcm;
321 	}
322 
323 	/* Check tag in "constant-time" */
324 	for (diff = 0, i = 0; i < tag_len; i++)
325 		diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
326 
327 	if (diff != 0) {
328 		rc = CRYPTO_ERR_DECRYPTION;
329 		goto exit_gcm;
330 	}
331 
332 	/* GCM decryption success */
333 	rc = CRYPTO_SUCCESS;
334 
335 exit_gcm:
336 	mbedtls_gcm_free(&ctx);
337 	return rc;
338 }
339 
340 /*
341  * Authenticated decryption of an image
342  */
343 static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
344 			size_t len, const void *key, unsigned int key_len,
345 			unsigned int key_flags, const void *iv,
346 			unsigned int iv_len, const void *tag,
347 			unsigned int tag_len)
348 {
349 	int rc;
350 
351 	assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0);
352 
353 	switch (dec_algo) {
354 	case CRYPTO_GCM_DECRYPT:
355 		rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len,
356 				     tag, tag_len);
357 		if (rc != 0)
358 			return rc;
359 		break;
360 	default:
361 		return CRYPTO_ERR_DECRYPTION;
362 	}
363 
364 	return CRYPTO_SUCCESS;
365 }
366 #endif /* TF_MBEDTLS_USE_AES_GCM */
367 
368 /*
369  * Register crypto library descriptor
370  */
371 #if MEASURED_BOOT && TRUSTED_BOARD_BOOT
372 #if TF_MBEDTLS_USE_AES_GCM
373 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
374 		    auth_decrypt);
375 #else
376 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
377 		    NULL);
378 #endif
379 #elif TRUSTED_BOARD_BOOT
380 #if TF_MBEDTLS_USE_AES_GCM
381 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash,
382 		    auth_decrypt);
383 #else
384 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
385 #endif
386 #elif MEASURED_BOOT
387 REGISTER_CRYPTO_LIB(LIB_NAME, init, calc_hash);
388 #endif /* MEASURED_BOOT && TRUSTED_BOARD_BOOT */
389