blob: f73236cb7942dae1f6276b31355254ff3f73c3cd [file] [log] [blame]
Soby Mathew294e1cf2022-03-22 16:19:39 +00001/*
Juan Pablo Conde9b94a422024-07-10 14:33:42 -05002 * Copyright (c) 2022-2024, Arm Limited. All rights reserved.
Soby Mathew294e1cf2022-03-22 16:19:39 +00003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
Juan Pablo Conde9b94a422024-07-10 14:33:42 -05006#include <errno.h>
Soby Mathew294e1cf2022-03-22 16:19:39 +00007#include <stdint.h>
8#include <string.h>
Javier Almansa Sobrino4165e842022-04-25 17:18:15 +01009
Soby Mathew294e1cf2022-03-22 16:19:39 +000010#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
17static 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
24static 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/*
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010061 * Helper function to validate that the buffer base and length are
62 * within range.
Soby Mathew294e1cf2022-03-22 16:19:39 +000063 */
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010064static int validate_buffer_params(uint64_t buf_pa, uint64_t buf_len)
Soby Mathew294e1cf2022-03-22 16:19:39 +000065{
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010066 unsigned long shared_buf_page;
67 uintptr_t shared_buf_base;
Soby Mathew294e1cf2022-03-22 16:19:39 +000068
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010069 (void)plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base);
Soby Mathew294e1cf2022-03-22 16:19:39 +000070
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010071 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;
Soby Mathew294e1cf2022-03-22 16:19:39 +000077 }
78
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010079 /* 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;
Soby Mathew294e1cf2022-03-22 16:19:39 +000083 }
84
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010085 return 0; /* No error */
86}
87
88int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_size,
Juan Pablo Conde9b94a422024-07-10 14:33:42 -050089 uint64_t c_size,
90 uint64_t *remaining_len)
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010091{
92 int err;
93 uint8_t temp_buf[SHA512_DIGEST_SIZE];
Soby Mathew294e1cf2022-03-22 16:19:39 +000094
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010095 err = validate_buffer_params(buf_pa, *buf_size);
Soby Mathew294e1cf2022-03-22 16:19:39 +000096 if (err != 0) {
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +010097 return err;
Soby Mathew294e1cf2022-03-22 16:19:39 +000098 }
99
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100100 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);
Soby Mathew294e1cf2022-03-22 16:19:39 +0000108
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100109 (void)memcpy(temp_buf, (void *)buf_pa, c_size);
110
111 print_challenge((uint8_t *)temp_buf, c_size);
Soby Mathew294e1cf2022-03-22 16:19:39 +0000112
113 /* Get the platform token. */
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100114 err = plat_rmmd_get_cca_attest_token((uintptr_t)buf_pa,
Juan Pablo Conde9b94a422024-07-10 14:33:42 -0500115 buf_size, (uintptr_t)temp_buf, c_size, remaining_len);
Soby Mathew294e1cf2022-03-22 16:19:39 +0000116
Juan Pablo Conde9b94a422024-07-10 14:33:42 -0500117 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:
Soby Mathew294e1cf2022-03-22 16:19:39 +0000128 ERROR("Failed to get platform token: %d.\n", err);
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100129 err = E_RMM_UNK;
Soby Mathew294e1cf2022-03-22 16:19:39 +0000130 }
131
Soby Mathew294e1cf2022-03-22 16:19:39 +0000132 spin_unlock(&lock);
133
134 return err;
135}
136
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100137int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_size,
Soby Mathewf05d93a2022-03-22 16:21:19 +0000138 uint64_t ecc_curve)
139{
140 int err;
Soby Mathewf05d93a2022-03-22 16:21:19 +0000141
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100142 err = validate_buffer_params(buf_pa, *buf_size);
143 if (err != 0) {
144 return err;
Soby Mathewf05d93a2022-03-22 16:21:19 +0000145 }
146
147 if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) {
148 ERROR("Invalid ECC curve specified\n");
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100149 return E_RMM_INVAL;
Soby Mathewf05d93a2022-03-22 16:21:19 +0000150 }
151
152 spin_lock(&lock);
153
Soby Mathewf05d93a2022-03-22 16:21:19 +0000154 /* Get the Realm attestation key. */
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100155 err = plat_rmmd_get_cca_realm_attest_key((uintptr_t)buf_pa, buf_size,
156 (unsigned int)ecc_curve);
Soby Mathewf05d93a2022-03-22 16:21:19 +0000157 if (err != 0) {
158 ERROR("Failed to get attestation key: %d.\n", err);
Javier Almansa Sobrinodea652e2022-04-13 17:57:35 +0100159 err = E_RMM_UNK;
Soby Mathewf05d93a2022-03-22 16:21:19 +0000160 }
161
Soby Mathewf05d93a2022-03-22 16:21:19 +0000162 spin_unlock(&lock);
163
164 return err;
165}