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 * Helper function to validate that the buffer base and length are 60 * within range. 61 */ 62 static int validate_buffer_params(uint64_t buf_pa, uint64_t buf_len) 63 { 64 unsigned long shared_buf_page; 65 uintptr_t shared_buf_base; 66 67 (void)plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base); 68 69 shared_buf_page = shared_buf_base & ~PAGE_SIZE_MASK; 70 71 /* Validate the buffer pointer */ 72 if ((buf_pa & ~PAGE_SIZE_MASK) != shared_buf_page) { 73 ERROR("Buffer PA out of range\n"); 74 return E_RMM_BAD_ADDR; 75 } 76 77 /* Validate the size of the shared area */ 78 if (((buf_pa + buf_len - 1UL) & ~PAGE_SIZE_MASK) != shared_buf_page) { 79 ERROR("Invalid buffer length\n"); 80 return E_RMM_INVAL; 81 } 82 83 return 0; /* No error */ 84 } 85 86 int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_size, 87 uint64_t c_size) 88 { 89 int err; 90 uint8_t temp_buf[SHA512_DIGEST_SIZE]; 91 92 err = validate_buffer_params(buf_pa, *buf_size); 93 if (err != 0) { 94 return err; 95 } 96 97 if ((c_size != SHA256_DIGEST_SIZE) && 98 (c_size != SHA384_DIGEST_SIZE) && 99 (c_size != SHA512_DIGEST_SIZE)) { 100 ERROR("Invalid hash size: %lu\n", c_size); 101 return E_RMM_INVAL; 102 } 103 104 spin_lock(&lock); 105 106 (void)memcpy(temp_buf, (void *)buf_pa, c_size); 107 108 print_challenge((uint8_t *)temp_buf, c_size); 109 110 /* Get the platform token. */ 111 err = plat_rmmd_get_cca_attest_token((uintptr_t)buf_pa, 112 buf_size, (uintptr_t)temp_buf, c_size); 113 114 if (err != 0) { 115 ERROR("Failed to get platform token: %d.\n", err); 116 err = E_RMM_UNK; 117 } 118 119 spin_unlock(&lock); 120 121 return err; 122 } 123 124 int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_size, 125 uint64_t ecc_curve) 126 { 127 int err; 128 129 err = validate_buffer_params(buf_pa, *buf_size); 130 if (err != 0) { 131 return err; 132 } 133 134 if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) { 135 ERROR("Invalid ECC curve specified\n"); 136 return E_RMM_INVAL; 137 } 138 139 spin_lock(&lock); 140 141 /* Get the Realm attestation key. */ 142 err = plat_rmmd_get_cca_realm_attest_key((uintptr_t)buf_pa, buf_size, 143 (unsigned int)ecc_curve); 144 if (err != 0) { 145 ERROR("Failed to get attestation key: %d.\n", err); 146 err = E_RMM_UNK; 147 } 148 149 spin_unlock(&lock); 150 151 return err; 152 } 153