xref: /rk3399_ARM-atf/services/std_svc/rmmd/rmmd_attest.c (revision 1d0ca40e9084903d21e570bb312646626aaf574b)
10f9159b7SSoby Mathew /*
20f9159b7SSoby Mathew  * Copyright (c) 2022, Arm Limited. All rights reserved.
30f9159b7SSoby Mathew  *
40f9159b7SSoby Mathew  * SPDX-License-Identifier: BSD-3-Clause
50f9159b7SSoby Mathew  */
60f9159b7SSoby Mathew #include <stdint.h>
70f9159b7SSoby Mathew #include <string.h>
8*1d0ca40eSJavier Almansa Sobrino 
90f9159b7SSoby Mathew #include <common/debug.h>
100f9159b7SSoby Mathew #include <lib/spinlock.h>
110f9159b7SSoby Mathew #include <lib/xlat_tables/xlat_tables_v2.h>
120f9159b7SSoby Mathew #include <plat/common/platform.h>
130f9159b7SSoby Mathew #include "rmmd_private.h"
140f9159b7SSoby Mathew #include <services/rmmd_svc.h>
150f9159b7SSoby Mathew 
160f9159b7SSoby Mathew static spinlock_t lock;
170f9159b7SSoby Mathew 
180f9159b7SSoby Mathew /* For printing Realm attestation token hash */
190f9159b7SSoby Mathew #define DIGITS_PER_BYTE				2UL
200f9159b7SSoby Mathew #define LENGTH_OF_TERMINATING_ZERO_IN_BYTES	1UL
210f9159b7SSoby Mathew #define BYTES_PER_LINE_BASE			4UL
220f9159b7SSoby Mathew 
230f9159b7SSoby Mathew static void print_challenge(uint8_t *hash, size_t hash_size)
240f9159b7SSoby Mathew {
250f9159b7SSoby Mathew 	size_t leftover;
260f9159b7SSoby Mathew 	/*
270f9159b7SSoby Mathew 	 * bytes_per_line is always a power of two, so it can be used to
280f9159b7SSoby Mathew 	 * construct mask with it when it is necessary to count remainder.
290f9159b7SSoby Mathew 	 *
300f9159b7SSoby Mathew 	 */
310f9159b7SSoby Mathew 	const size_t bytes_per_line = 1 << BYTES_PER_LINE_BASE;
320f9159b7SSoby Mathew 	char hash_text[(1 << BYTES_PER_LINE_BASE) * DIGITS_PER_BYTE +
330f9159b7SSoby Mathew 		LENGTH_OF_TERMINATING_ZERO_IN_BYTES];
340f9159b7SSoby Mathew 	const char hex_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7',
350f9159b7SSoby Mathew 				  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
360f9159b7SSoby Mathew 	unsigned int i;
370f9159b7SSoby Mathew 
380f9159b7SSoby Mathew 	for (i = 0U; i < hash_size; ++i) {
390f9159b7SSoby Mathew 		hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE] =
400f9159b7SSoby Mathew 			hex_chars[hash[i] >> 4];
410f9159b7SSoby Mathew 		hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE + 1] =
420f9159b7SSoby Mathew 			hex_chars[hash[i] & 0x0f];
430f9159b7SSoby Mathew 		if (((i + 1) & (bytes_per_line - 1)) == 0U) {
440f9159b7SSoby Mathew 			hash_text[bytes_per_line * DIGITS_PER_BYTE] = '\0';
450f9159b7SSoby Mathew 			VERBOSE("hash part %u = %s\n",
460f9159b7SSoby Mathew 				(i >> BYTES_PER_LINE_BASE) + 1, hash_text);
470f9159b7SSoby Mathew 		}
480f9159b7SSoby Mathew 	}
490f9159b7SSoby Mathew 
500f9159b7SSoby Mathew 	leftover = (size_t)i & (bytes_per_line - 1);
510f9159b7SSoby Mathew 
520f9159b7SSoby Mathew 	if (leftover != 0UL) {
530f9159b7SSoby Mathew 		hash_text[leftover * DIGITS_PER_BYTE] = '\0';
540f9159b7SSoby Mathew 		VERBOSE("hash part %u = %s\n", (i >> BYTES_PER_LINE_BASE) + 1,
550f9159b7SSoby Mathew 			hash_text);
560f9159b7SSoby Mathew 	}
570f9159b7SSoby Mathew }
580f9159b7SSoby Mathew 
590f9159b7SSoby Mathew /*
60dc65ae46SJavier Almansa Sobrino  * Helper function to validate that the buffer base and length are
61dc65ae46SJavier Almansa Sobrino  * within range.
620f9159b7SSoby Mathew  */
63dc65ae46SJavier Almansa Sobrino static int validate_buffer_params(uint64_t buf_pa, uint64_t buf_len)
640f9159b7SSoby Mathew {
65dc65ae46SJavier Almansa Sobrino 	unsigned long shared_buf_page;
66dc65ae46SJavier Almansa Sobrino 	uintptr_t shared_buf_base;
670f9159b7SSoby Mathew 
68dc65ae46SJavier Almansa Sobrino 	(void)plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base);
690f9159b7SSoby Mathew 
70dc65ae46SJavier Almansa Sobrino 	shared_buf_page = shared_buf_base & ~PAGE_SIZE_MASK;
71dc65ae46SJavier Almansa Sobrino 
72dc65ae46SJavier Almansa Sobrino 	/* Validate the buffer pointer */
73dc65ae46SJavier Almansa Sobrino 	if ((buf_pa & ~PAGE_SIZE_MASK) != shared_buf_page) {
74dc65ae46SJavier Almansa Sobrino 		ERROR("Buffer PA out of range\n");
75dc65ae46SJavier Almansa Sobrino 		return E_RMM_BAD_ADDR;
760f9159b7SSoby Mathew 	}
770f9159b7SSoby Mathew 
78dc65ae46SJavier Almansa Sobrino 	/* Validate the size of the shared area */
79dc65ae46SJavier Almansa Sobrino 	if (((buf_pa + buf_len - 1UL) & ~PAGE_SIZE_MASK) != shared_buf_page) {
80dc65ae46SJavier Almansa Sobrino 		ERROR("Invalid buffer length\n");
81dc65ae46SJavier Almansa Sobrino 		return E_RMM_INVAL;
82dc65ae46SJavier Almansa Sobrino 	}
83dc65ae46SJavier Almansa Sobrino 
84dc65ae46SJavier Almansa Sobrino 	return 0; /* No error */
85dc65ae46SJavier Almansa Sobrino }
86dc65ae46SJavier Almansa Sobrino 
87dc65ae46SJavier Almansa Sobrino int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_size,
88dc65ae46SJavier Almansa Sobrino 				   uint64_t c_size)
89dc65ae46SJavier Almansa Sobrino {
90dc65ae46SJavier Almansa Sobrino 	int err;
91dc65ae46SJavier Almansa Sobrino 	uint8_t temp_buf[SHA512_DIGEST_SIZE];
92dc65ae46SJavier Almansa Sobrino 
93dc65ae46SJavier Almansa Sobrino 	err = validate_buffer_params(buf_pa, *buf_size);
94dc65ae46SJavier Almansa Sobrino 	if (err != 0) {
95dc65ae46SJavier Almansa Sobrino 		return err;
96dc65ae46SJavier Almansa Sobrino 	}
97dc65ae46SJavier Almansa Sobrino 
98dc65ae46SJavier Almansa Sobrino 	if ((c_size != SHA256_DIGEST_SIZE) &&
99dc65ae46SJavier Almansa Sobrino 	    (c_size != SHA384_DIGEST_SIZE) &&
100dc65ae46SJavier Almansa Sobrino 	    (c_size != SHA512_DIGEST_SIZE)) {
101dc65ae46SJavier Almansa Sobrino 		ERROR("Invalid hash size: %lu\n", c_size);
102dc65ae46SJavier Almansa Sobrino 		return E_RMM_INVAL;
1030f9159b7SSoby Mathew 	}
1040f9159b7SSoby Mathew 
1050f9159b7SSoby Mathew 	spin_lock(&lock);
1060f9159b7SSoby Mathew 
107dc65ae46SJavier Almansa Sobrino 	(void)memcpy(temp_buf, (void *)buf_pa, c_size);
1080f9159b7SSoby Mathew 
109dc65ae46SJavier Almansa Sobrino 	print_challenge((uint8_t *)temp_buf, c_size);
1100f9159b7SSoby Mathew 
1110f9159b7SSoby Mathew 	/* Get the platform token. */
112dc65ae46SJavier Almansa Sobrino 	err = plat_rmmd_get_cca_attest_token((uintptr_t)buf_pa,
113dc65ae46SJavier Almansa Sobrino 		buf_size, (uintptr_t)temp_buf, c_size);
1140f9159b7SSoby Mathew 
1150f9159b7SSoby Mathew 	if (err != 0) {
1160f9159b7SSoby Mathew 		ERROR("Failed to get platform token: %d.\n", err);
117dc65ae46SJavier Almansa Sobrino 		err = E_RMM_UNK;
1180f9159b7SSoby Mathew 	}
1190f9159b7SSoby Mathew 
1200f9159b7SSoby Mathew 	spin_unlock(&lock);
1210f9159b7SSoby Mathew 
1220f9159b7SSoby Mathew 	return err;
1230f9159b7SSoby Mathew }
1240f9159b7SSoby Mathew 
125dc65ae46SJavier Almansa Sobrino int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_size,
126a0435105SSoby Mathew 				uint64_t ecc_curve)
127a0435105SSoby Mathew {
128a0435105SSoby Mathew 	int err;
129a0435105SSoby Mathew 
130dc65ae46SJavier Almansa Sobrino 	err = validate_buffer_params(buf_pa, *buf_size);
131dc65ae46SJavier Almansa Sobrino 	if (err != 0) {
132dc65ae46SJavier Almansa Sobrino 		return err;
133a0435105SSoby Mathew 	}
134a0435105SSoby Mathew 
135a0435105SSoby Mathew 	if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) {
136a0435105SSoby Mathew 		ERROR("Invalid ECC curve specified\n");
137dc65ae46SJavier Almansa Sobrino 		return E_RMM_INVAL;
138a0435105SSoby Mathew 	}
139a0435105SSoby Mathew 
140a0435105SSoby Mathew 	spin_lock(&lock);
141a0435105SSoby Mathew 
142a0435105SSoby Mathew 	/* Get the Realm attestation key. */
143dc65ae46SJavier Almansa Sobrino 	err = plat_rmmd_get_cca_realm_attest_key((uintptr_t)buf_pa, buf_size,
144dc65ae46SJavier Almansa Sobrino 						 (unsigned int)ecc_curve);
145a0435105SSoby Mathew 	if (err != 0) {
146a0435105SSoby Mathew 		ERROR("Failed to get attestation key: %d.\n", err);
147dc65ae46SJavier Almansa Sobrino 		err =  E_RMM_UNK;
148a0435105SSoby Mathew 	}
149a0435105SSoby Mathew 
150a0435105SSoby Mathew 	spin_unlock(&lock);
151a0435105SSoby Mathew 
152a0435105SSoby Mathew 	return err;
153a0435105SSoby Mathew }
154