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