1 /* 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 15 static 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 22 static 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 */ 62 int 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 119 int 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 } 167