xref: /arm-trusted-firmware/services/std_svc/rmmd/rmmd_attest.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2022, Arm Limited. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu #include <stdint.h>
7*91f16700Schasinglulu #include <string.h>
8*91f16700Schasinglulu 
9*91f16700Schasinglulu #include <common/debug.h>
10*91f16700Schasinglulu #include <lib/spinlock.h>
11*91f16700Schasinglulu #include <lib/xlat_tables/xlat_tables_v2.h>
12*91f16700Schasinglulu #include <plat/common/platform.h>
13*91f16700Schasinglulu #include "rmmd_private.h"
14*91f16700Schasinglulu #include <services/rmmd_svc.h>
15*91f16700Schasinglulu 
16*91f16700Schasinglulu static spinlock_t lock;
17*91f16700Schasinglulu 
18*91f16700Schasinglulu /* For printing Realm attestation token hash */
19*91f16700Schasinglulu #define DIGITS_PER_BYTE				2UL
20*91f16700Schasinglulu #define LENGTH_OF_TERMINATING_ZERO_IN_BYTES	1UL
21*91f16700Schasinglulu #define BYTES_PER_LINE_BASE			4UL
22*91f16700Schasinglulu 
23*91f16700Schasinglulu static void print_challenge(uint8_t *hash, size_t hash_size)
24*91f16700Schasinglulu {
25*91f16700Schasinglulu 	size_t leftover;
26*91f16700Schasinglulu 	/*
27*91f16700Schasinglulu 	 * bytes_per_line is always a power of two, so it can be used to
28*91f16700Schasinglulu 	 * construct mask with it when it is necessary to count remainder.
29*91f16700Schasinglulu 	 *
30*91f16700Schasinglulu 	 */
31*91f16700Schasinglulu 	const size_t bytes_per_line = 1 << BYTES_PER_LINE_BASE;
32*91f16700Schasinglulu 	char hash_text[(1 << BYTES_PER_LINE_BASE) * DIGITS_PER_BYTE +
33*91f16700Schasinglulu 		LENGTH_OF_TERMINATING_ZERO_IN_BYTES];
34*91f16700Schasinglulu 	const char hex_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7',
35*91f16700Schasinglulu 				  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
36*91f16700Schasinglulu 	unsigned int i;
37*91f16700Schasinglulu 
38*91f16700Schasinglulu 	for (i = 0U; i < hash_size; ++i) {
39*91f16700Schasinglulu 		hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE] =
40*91f16700Schasinglulu 			hex_chars[hash[i] >> 4];
41*91f16700Schasinglulu 		hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE + 1] =
42*91f16700Schasinglulu 			hex_chars[hash[i] & 0x0f];
43*91f16700Schasinglulu 		if (((i + 1) & (bytes_per_line - 1)) == 0U) {
44*91f16700Schasinglulu 			hash_text[bytes_per_line * DIGITS_PER_BYTE] = '\0';
45*91f16700Schasinglulu 			VERBOSE("hash part %u = %s\n",
46*91f16700Schasinglulu 				(i >> BYTES_PER_LINE_BASE) + 1, hash_text);
47*91f16700Schasinglulu 		}
48*91f16700Schasinglulu 	}
49*91f16700Schasinglulu 
50*91f16700Schasinglulu 	leftover = (size_t)i & (bytes_per_line - 1);
51*91f16700Schasinglulu 
52*91f16700Schasinglulu 	if (leftover != 0UL) {
53*91f16700Schasinglulu 		hash_text[leftover * DIGITS_PER_BYTE] = '\0';
54*91f16700Schasinglulu 		VERBOSE("hash part %u = %s\n", (i >> BYTES_PER_LINE_BASE) + 1,
55*91f16700Schasinglulu 			hash_text);
56*91f16700Schasinglulu 	}
57*91f16700Schasinglulu }
58*91f16700Schasinglulu 
59*91f16700Schasinglulu /*
60*91f16700Schasinglulu  * Helper function to validate that the buffer base and length are
61*91f16700Schasinglulu  * within range.
62*91f16700Schasinglulu  */
63*91f16700Schasinglulu static int validate_buffer_params(uint64_t buf_pa, uint64_t buf_len)
64*91f16700Schasinglulu {
65*91f16700Schasinglulu 	unsigned long shared_buf_page;
66*91f16700Schasinglulu 	uintptr_t shared_buf_base;
67*91f16700Schasinglulu 
68*91f16700Schasinglulu 	(void)plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base);
69*91f16700Schasinglulu 
70*91f16700Schasinglulu 	shared_buf_page = shared_buf_base & ~PAGE_SIZE_MASK;
71*91f16700Schasinglulu 
72*91f16700Schasinglulu 	/* Validate the buffer pointer */
73*91f16700Schasinglulu 	if ((buf_pa & ~PAGE_SIZE_MASK) != shared_buf_page) {
74*91f16700Schasinglulu 		ERROR("Buffer PA out of range\n");
75*91f16700Schasinglulu 		return E_RMM_BAD_ADDR;
76*91f16700Schasinglulu 	}
77*91f16700Schasinglulu 
78*91f16700Schasinglulu 	/* Validate the size of the shared area */
79*91f16700Schasinglulu 	if (((buf_pa + buf_len - 1UL) & ~PAGE_SIZE_MASK) != shared_buf_page) {
80*91f16700Schasinglulu 		ERROR("Invalid buffer length\n");
81*91f16700Schasinglulu 		return E_RMM_INVAL;
82*91f16700Schasinglulu 	}
83*91f16700Schasinglulu 
84*91f16700Schasinglulu 	return 0; /* No error */
85*91f16700Schasinglulu }
86*91f16700Schasinglulu 
87*91f16700Schasinglulu int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_size,
88*91f16700Schasinglulu 				   uint64_t c_size)
89*91f16700Schasinglulu {
90*91f16700Schasinglulu 	int err;
91*91f16700Schasinglulu 	uint8_t temp_buf[SHA512_DIGEST_SIZE];
92*91f16700Schasinglulu 
93*91f16700Schasinglulu 	err = validate_buffer_params(buf_pa, *buf_size);
94*91f16700Schasinglulu 	if (err != 0) {
95*91f16700Schasinglulu 		return err;
96*91f16700Schasinglulu 	}
97*91f16700Schasinglulu 
98*91f16700Schasinglulu 	if ((c_size != SHA256_DIGEST_SIZE) &&
99*91f16700Schasinglulu 	    (c_size != SHA384_DIGEST_SIZE) &&
100*91f16700Schasinglulu 	    (c_size != SHA512_DIGEST_SIZE)) {
101*91f16700Schasinglulu 		ERROR("Invalid hash size: %lu\n", c_size);
102*91f16700Schasinglulu 		return E_RMM_INVAL;
103*91f16700Schasinglulu 	}
104*91f16700Schasinglulu 
105*91f16700Schasinglulu 	spin_lock(&lock);
106*91f16700Schasinglulu 
107*91f16700Schasinglulu 	(void)memcpy(temp_buf, (void *)buf_pa, c_size);
108*91f16700Schasinglulu 
109*91f16700Schasinglulu 	print_challenge((uint8_t *)temp_buf, c_size);
110*91f16700Schasinglulu 
111*91f16700Schasinglulu 	/* Get the platform token. */
112*91f16700Schasinglulu 	err = plat_rmmd_get_cca_attest_token((uintptr_t)buf_pa,
113*91f16700Schasinglulu 		buf_size, (uintptr_t)temp_buf, c_size);
114*91f16700Schasinglulu 
115*91f16700Schasinglulu 	if (err != 0) {
116*91f16700Schasinglulu 		ERROR("Failed to get platform token: %d.\n", err);
117*91f16700Schasinglulu 		err = E_RMM_UNK;
118*91f16700Schasinglulu 	}
119*91f16700Schasinglulu 
120*91f16700Schasinglulu 	spin_unlock(&lock);
121*91f16700Schasinglulu 
122*91f16700Schasinglulu 	return err;
123*91f16700Schasinglulu }
124*91f16700Schasinglulu 
125*91f16700Schasinglulu int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_size,
126*91f16700Schasinglulu 				uint64_t ecc_curve)
127*91f16700Schasinglulu {
128*91f16700Schasinglulu 	int err;
129*91f16700Schasinglulu 
130*91f16700Schasinglulu 	err = validate_buffer_params(buf_pa, *buf_size);
131*91f16700Schasinglulu 	if (err != 0) {
132*91f16700Schasinglulu 		return err;
133*91f16700Schasinglulu 	}
134*91f16700Schasinglulu 
135*91f16700Schasinglulu 	if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) {
136*91f16700Schasinglulu 		ERROR("Invalid ECC curve specified\n");
137*91f16700Schasinglulu 		return E_RMM_INVAL;
138*91f16700Schasinglulu 	}
139*91f16700Schasinglulu 
140*91f16700Schasinglulu 	spin_lock(&lock);
141*91f16700Schasinglulu 
142*91f16700Schasinglulu 	/* Get the Realm attestation key. */
143*91f16700Schasinglulu 	err = plat_rmmd_get_cca_realm_attest_key((uintptr_t)buf_pa, buf_size,
144*91f16700Schasinglulu 						 (unsigned int)ecc_curve);
145*91f16700Schasinglulu 	if (err != 0) {
146*91f16700Schasinglulu 		ERROR("Failed to get attestation key: %d.\n", err);
147*91f16700Schasinglulu 		err =  E_RMM_UNK;
148*91f16700Schasinglulu 	}
149*91f16700Schasinglulu 
150*91f16700Schasinglulu 	spin_unlock(&lock);
151*91f16700Schasinglulu 
152*91f16700Schasinglulu 	return err;
153*91f16700Schasinglulu }
154