blob: 0432ec3a9816f1e0f4fbb53efe7feb82687c9420 [file] [log] [blame]
Soby Mathew294e1cf2022-03-22 16:19:39 +00001/*
2 * Copyright (c) 2022, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <stdint.h>
7#include <string.h>
8#include <common/debug.h>
9#include <lib/spinlock.h>
10#include <lib/xlat_tables/xlat_tables_v2.h>
11#include <plat/common/platform.h>
12#include "rmmd_private.h"
13#include <services/rmmd_svc.h>
14
15static spinlock_t lock;
16
17/* For printing Realm attestation token hash */
18#define DIGITS_PER_BYTE 2UL
19#define LENGTH_OF_TERMINATING_ZERO_IN_BYTES 1UL
20#define BYTES_PER_LINE_BASE 4UL
21
22static void print_challenge(uint8_t *hash, size_t hash_size)
23{
24 size_t leftover;
25 /*
26 * bytes_per_line is always a power of two, so it can be used to
27 * construct mask with it when it is necessary to count remainder.
28 *
29 */
30 const size_t bytes_per_line = 1 << BYTES_PER_LINE_BASE;
31 char hash_text[(1 << BYTES_PER_LINE_BASE) * DIGITS_PER_BYTE +
32 LENGTH_OF_TERMINATING_ZERO_IN_BYTES];
33 const char hex_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7',
34 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
35 unsigned int i;
36
37 for (i = 0U; i < hash_size; ++i) {
38 hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE] =
39 hex_chars[hash[i] >> 4];
40 hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE + 1] =
41 hex_chars[hash[i] & 0x0f];
42 if (((i + 1) & (bytes_per_line - 1)) == 0U) {
43 hash_text[bytes_per_line * DIGITS_PER_BYTE] = '\0';
44 VERBOSE("hash part %u = %s\n",
45 (i >> BYTES_PER_LINE_BASE) + 1, hash_text);
46 }
47 }
48
49 leftover = (size_t)i & (bytes_per_line - 1);
50
51 if (leftover != 0UL) {
52 hash_text[leftover * DIGITS_PER_BYTE] = '\0';
53 VERBOSE("hash part %u = %s\n", (i >> BYTES_PER_LINE_BASE) + 1,
54 hash_text);
55 }
56}
57
58/*
59 * TODO: Have different error codes for different errors so that the caller can
60 * differentiate various error cases.
61 */
62int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_len, uint64_t challenge_hash_len)
63{
64 int err;
65 uintptr_t va;
66 uint8_t temp_buf[SHA512_DIGEST_SIZE];
67
68 /*
69 * TODO: Currently we don't validate incoming buf_pa. This is a
70 * prototype and we will need to allocate static buffer for EL3-RMM
71 * communication.
72 */
73
74 /* We need a page of buffer to pass data */
75 if (*buf_len != PAGE_SIZE) {
76 ERROR("Invalid buffer length\n");
77 return RMMD_ERR_INVAL;
78 }
79
80 if ((challenge_hash_len != SHA256_DIGEST_SIZE) &&
81 (challenge_hash_len != SHA384_DIGEST_SIZE) &&
82 (challenge_hash_len != SHA512_DIGEST_SIZE)) {
83 ERROR("Invalid hash size: %lu\n", challenge_hash_len);
84 return RMMD_ERR_INVAL;
85 }
86
87 spin_lock(&lock);
88
89 /* Map the buffer that was provided by the RMM. */
90 err = mmap_add_dynamic_region_alloc_va(buf_pa, &va, PAGE_SIZE,
91 MT_RW_DATA | MT_REALM);
92 if (err != 0) {
93 ERROR("mmap_add_dynamic_region_alloc_va failed: %d (%p).\n"
94 , err, (void *)buf_pa);
95 spin_unlock(&lock);
96 return RMMD_ERR_NOMEM;
97 }
98
99 (void)memcpy(temp_buf, (void *)va, challenge_hash_len);
100
101 print_challenge((uint8_t *)temp_buf, challenge_hash_len);
102
103 /* Get the platform token. */
104 err = plat_get_cca_attest_token(va,
105 buf_len, (uintptr_t)temp_buf, challenge_hash_len);
106
107 if (err != 0) {
108 ERROR("Failed to get platform token: %d.\n", err);
109 err = RMMD_ERR_UNK;
110 }
111
112 /* Unmap RMM memory. */
113 (void)mmap_remove_dynamic_region(va, PAGE_SIZE);
114 spin_unlock(&lock);
115
116 return err;
117}
118
Soby Mathewf05d93a2022-03-22 16:21:19 +0000119int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_len,
120 uint64_t ecc_curve)
121{
122 int err;
123 uintptr_t va;
124
125 /*
126 * TODO: Currently we don't validate incoming buf_pa. This is a
127 * prototype and we will need to allocate static buffer for EL3-RMM
128 * communication.
129 */
130
131 /* We need a page of buffer to pass data */
132 if (*buf_len != PAGE_SIZE) {
133 ERROR("Invalid buffer length\n");
134 return RMMD_ERR_INVAL;
135 }
136
137 if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) {
138 ERROR("Invalid ECC curve specified\n");
139 return RMMD_ERR_INVAL;
140 }
141
142 spin_lock(&lock);
143
144 /* Map the buffer that was provided by the RMM. */
145 err = mmap_add_dynamic_region_alloc_va(buf_pa, &va, PAGE_SIZE,
146 MT_RW_DATA | MT_REALM);
147 if (err != 0) {
148 ERROR("mmap_add_dynamic_region_alloc_va failed: %d (%p).\n"
149 , err, (void *)buf_pa);
150 spin_unlock(&lock);
151 return RMMD_ERR_NOMEM;
152 }
153
154 /* Get the Realm attestation key. */
155 err = plat_get_cca_realm_attest_key(va, buf_len, (unsigned int)ecc_curve);
156 if (err != 0) {
157 ERROR("Failed to get attestation key: %d.\n", err);
158 err = RMMD_ERR_UNK;
159 }
160
161 /* Unmap RMM memory. */
162 (void)mmap_remove_dynamic_region(va, PAGE_SIZE);
163 spin_unlock(&lock);
164
165 return err;
166}