From bc40997bd09401c2d7b513e1707379042957fd54 Mon Sep 17 00:00:00 2001 From: openeuler-ci-bot Date: Thu, 18 Apr 2024 02:35:07 +0000 Subject: [PATCH 1/2] rim_ref commit --- attestation/rim_ref/CMakeList.txt | 26 + attestation/rim_ref/build.sh | 164 +++++ attestation/rim_ref/inc/gen_rim_ref.h | 171 ++++++ attestation/rim_ref/src/rim_ref/CMakeList.txt | 18 + attestation/rim_ref/src/rim_ref/gen_rim_ref.c | 578 ++++++++++++++++++ 5 files changed, 957 insertions(+) create mode 100644 attestation/rim_ref/CMakeList.txt create mode 100644 attestation/rim_ref/build.sh create mode 100644 attestation/rim_ref/inc/gen_rim_ref.h create mode 100644 attestation/rim_ref/src/rim_ref/CMakeList.txt create mode 100644 attestation/rim_ref/src/rim_ref/gen_rim_ref.c diff --git a/attestation/rim_ref/CMakeList.txt b/attestation/rim_ref/CMakeList.txt new file mode 100644 index 0000000..b8f841c --- /dev/null +++ b/attestation/rim_ref/CMakeList.txt @@ -0,0 +1,26 @@ +# CMake version +cmake_minimum_required(VERSION 3.5.1) + +# Project +project(tsi-interface) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Build mode +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE) +endif() +message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") + +# Build options +option(BUILD_RIM_GEN "Compile rim reference generator" ON) + + +# Set install path +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/output) +set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + + +if(BUILD_RIM_GEN) + message(STATUS "Build gen_rim_ref: on") + add_subdirectory(src/rim_ref) +endif() diff --git a/attestation/rim_ref/build.sh b/attestation/rim_ref/build.sh new file mode 100644 index 0000000..a6d8135 --- /dev/null +++ b/attestation/rim_ref/build.sh @@ -0,0 +1,164 @@ +#!/bin/bash +# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. +set -e + +export USR_COMPILER_CC="" +export DEBUG_OR_RELEASE="" +export CLEAN_ENABLED="" +export ARCH="arm64" +export CROSS_COMPILE + +print_help() { + echo -e "\nUsage:" + echo -e " build.sh [options]...\n" + echo -e "Options:" + echo -e " -v, --usrcompiler \033[4musrcompiler\033[0m" + echo -e " compiler for target usr. Default value is aarch64-linux-gnu-gcc, you can config gcc\n" + echo -e " -t, --compile target, you can config \"all\", \"rim\", \"plat\" or \"usr\"\n" + echo -e " -r, --release" + echo -e " Enable release building. Default build for debug\n" + echo -e " -c, --clean" + echo -e " Clean all the files built\n" + echo -e " -h, --help" + echo -e " Display this help and exit.\n" +} + +! getopt --test > /dev/null +if [[ ${PIPESTATUS[0]} -ne 4 ]]; then + echo 'getopt is not the enhanced version.' + exit 1 +fi + +OPTIONS=v:rhct: +LONGOPTS=usrcompiler:,release,help,clean,target: + +! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "build" -- "$@") +if [[ ${PIPESTATUS[0]} -ne 0 ]]; then + print_help + exit 2 +fi + +# reset parameters +eval set -- "$PARSED" + +while true; do + case "${1}" in + -h|--help) + print_help + exit 0 + ;; + -r|--release) + DEBUG_OR_RELEASE="Release" + shift + ;; + -v|--usrcompiler) + USR_COMPILER_CC="${2}" + shift 2 + ;; + -t|--target) + BUILD_TARGET="${2}" + shift 2 + ;; + -c|--clean) + CLEAN_ENABLED="ON" + shift + ;; + --) + shift + break + ;; + *) + echo "Programming error" + exit 3 + ;; + esac +done + +if [[ $# -ne 0 ]]; then + echo "build: wrong parameter: ${1}" + print_help + exit 4 +fi + +export CC +export CXX + +if [[ "${USR_COMPILER_CC}" == "" ]]; then + USR_COMPILER_CC=aarch64-linux-gnu-gcc +elif [[ "${USR_COMPILER_CC}" == "aarch64-linux-gnu-gcc" ]]; then + echo "INFO: USR_COMPILER_CC == ${USR_COMPILER_CC}" +elif [[ "${USR_COMPILER_CC}" != "gcc" ]]; then + echo "ERROR: your input compiler is not support: ${USR_COMPILER_CC}" + print_help + exit 1 +else + echo "INFO: USR_COMPILER_CC == ${USR_COMPILER_CC}" +fi + +if [[ "${BUILD_TARGET}" == "" ]]; then + BUILD_TARGET="all" +fi + +if [[ "${DEBUG_OR_RELEASE}" == "" ]]; then + DEBUG_OR_RELEASE="Debug" +fi + +if [[ "${CLEAN_ENABLED}" == "" ]]; then + CLEAN_ENABLED=OFF +fi + +echo -e "\ntsi-interface compiling info:" +echo -e "build target = ${BUILD_TARGET}" +echo -e "debug or release = ${DEBUG_OR_RELEASE}" +echo -e "clean enabled = ${CLEAN_ENABLED}" + +if [[ -z "${CC}" ]]; then + CC="${USR_COMPILER_CC}" +fi +echo -e "user c compiler = ${CC}" + +if [[ -z "${CXX}" ]]; then + CXX=$(which g++) +fi +echo -e "user c++ compiler = ${CXX}\n" + +if [[ "${BUILD_TARGET}" == "all" ]]; then + BUILD_FAKE_PLAT=ON + BUILD_RIM_GEN=ON + BUILD_INTERFACE=ON +elif [[ "${BUILD_TARGET}" == "rim" ]]; then + BUILD_FAKE_PLAT=OFF + BUILD_RIM_GEN=ON + BUILD_INTERFACE=OFF +elif [[ "${BUILD_TARGET}" == "plat" ]]; then + BUILD_FAKE_PLAT=ON + BUILD_RIM_GEN=OFF + BUILD_INTERFACE=OFF +elif [[ "${BUILD_TARGET}" == "usr" ]]; then + BUILD_FAKE_PLAT=OFF + BUILD_RIM_GEN=OFF + BUILD_INTERFACE=ON +else + echo "ERROR: please input correct target name: ${BUILD_TARGET}" + exit 4 +fi + +cmake -DBUILD_RIM_GEN=${BUILD_RIM_GEN} \ + -DCMAKE_BUILD_TYPE=${DEBUG_OR_RELEASE} \ + -B ./build + +pushd ./build + +if [[ "${CLEAN_ENABLED}" == "ON" ]]; then + make clean +fi + +if [[ "${BUILD_INTERFACE}" == "ON" && "${DEBUG_OR_RELEASE}" = "Debug" ]]; then + make +else + make +fi + +popd + +echo "INFO: building tsi interface target ${BUILD_TARGET} finished." \ No newline at end of file diff --git a/attestation/rim_ref/inc/gen_rim_ref.h b/attestation/rim_ref/inc/gen_rim_ref.h new file mode 100644 index 0000000..57fe190 --- /dev/null +++ b/attestation/rim_ref/inc/gen_rim_ref.h @@ -0,0 +1,171 @@ +#ifndef GEN_RIM_REF_H +#define GEN_RIM_REF_H + +#include +#include + +#define GRANULE_SIZE 4096 +#define TMI_HASH_ALGO_SHA256 (0U) +#define TMI_HASH_ALGO_SHA512 (1U) +#define MEASUREMENT_CVM_HEADER (1U) +#define MEASUREMENT_DATA_HEADER (2U) +#define MEASUREMENT_REC_HEADER (3U) +#define SHA256_SIZE (32U) +#define SHA512_SIZE (64U) +#define MAX_MEASUREMENT_SIZE SHA512_SIZE +#define TMI_NO_MEASURE_CONTENT (0U) +#define TMI_MEASURE_CONTENT (1U) +#define RPV_SIZE 64 +#define TEC_CREATE_NR_GPRS (8U) +#define MEASURE_DESC_TYPE_DATA 0x0 +#define MEASURE_DESC_TYPE_REC 0x1 +#define MEASURE_DESC_TYPE_RIPAS 0x2 +#define L2_GRANULE 0x200000 /* 2MB */ +#define L3_GRANULE 0x1000 /* 4KB */ +#define BOOTLOADER_LEN_UINT32 10 +#define GiB 0x40000000 +#define MB 0x100000 +#define KERNEL_LOAD_OFFSET 2*MB +#define BLOCK_SIZE L2_GRANULE + +enum hash_algo { + HASH_ALGO_SHA256 = TMI_HASH_ALGO_SHA256, + HASH_ALGO_SHA512 = TMI_HASH_ALGO_SHA512, +}; + +#define SET_MEMBER(member, start, end) \ + union { \ + member; \ + unsigned char reserved##end[end - start]; \ + } + +#define SET_BIT(number, n) \ + ((number) |= ((uint64_t)1 << (n))) + +#define CLEAR_BIT(number, n) \ + ((number) &= ~((uint64_t)1 << (n))) + + +#define __typeof__ typeof +#define __round_mask(x, y) ((__typeof__(x))((y)-1)) +#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) +#define round_down(x, y) ((x) & ~__round_mask(x, y)) + +typedef struct tmi_cvm_create_params { + uint64_t flags; + uint64_t s2sz; + uint64_t sve_vl; + uint64_t num_bps; + uint64_t num_wps; + uint64_t pmu_num_cnts; + uint64_t measurement_algo; +} tmi_cvm_create_params_t; + +typedef struct tmi_tec_crreate_params { + uint64_t gprs[TEC_CREATE_NR_GPRS]; + uint64_t pc; + uint64_t flags; +} tmi_tec_create_params_t; + +typedef struct tmi_data_crreate_params { + uint64_t *data; + uint64_t size; + uint64_t flags; + uint64_t ipa; +} tmi_data_create_params_t; + +/* TmmMeasurementDescriptorCVM type as per RMM spec */ +typedef struct tmi_measure_cvm { + /* Flags */ + SET_MEMBER(unsigned long flags, 0, 0x8); /* Offset 0 */ + /* Requested IPA width */ + SET_MEMBER(unsigned int s2sz, 0x8, 0x10); /* 0x8 */ + /* Requested SVE vector length */ + SET_MEMBER(unsigned int sve_vl, 0x10, 0x18); /* 0x10 */ + /* Requested number of breakpoints */ + SET_MEMBER(unsigned int num_bps, 0x18, 0x20); /* 0x18 */ + /* Requested number of watchpoints */ + SET_MEMBER(unsigned int num_wps, 0x20, 0x28); /* 0x20 */ + /* Requested number of PMU counters */ + SET_MEMBER(unsigned int pmu_num_cnts, 0x28, 0x30); /* 0x28 */ + /* Measurement algorithm */ + SET_MEMBER(unsigned char measurement_algo, 0x30, 0x400); /* 0x30 */ + /* Realm Personalization Value */ + unsigned char reserved0x800[0x800 - 0x400]; /* 0x400 */ + unsigned char reserved0x1000[0x1000 - 0x800]; /* 0x800 */ +} tmi_measure_cvm_t; + +typedef struct tmi_tec_params { + uint64_t gprs[TEC_CREATE_NR_GPRS]; + uint64_t pc; + uint64_t flags; + uint64_t reserved0; + uint64_t reserved1[16]; +} tmi_tec_params_t; + +/* TmmMeasurementDescriptorData type as per RMM spec */ +typedef struct tmi_measure_data { + /* Measurement descriptor type, value 0x0 */ + SET_MEMBER(unsigned char desc_type, 0x0, 0x8); + /* Length of this data structure in bytes */ + SET_MEMBER(unsigned long len, 0x8, 0x10); + /* Current RIM value */ + SET_MEMBER(unsigned char rim[MAX_MEASUREMENT_SIZE], 0x10, 0x50); + /* IPA at which the DATA Granule is mapped in the cvm */ + SET_MEMBER(unsigned long ipa, 0x50, 0x58); + /* Flags provided by Host */ + SET_MEMBER(unsigned long flags, 0x58, 0x60); + /* + * Hash of contents of DATA Granule, or zero if flags indicate DATA + * Granule contents are unmeasured + */ + SET_MEMBER(unsigned char content[MAX_MEASUREMENT_SIZE], 0x60, 0x100); +} tmi_measure_data_t; + +/* TmmMeasurementDescriptorRec type as per RMM spec */ +typedef struct tmi_measure_tec { + /* Measurement descriptor type, value 0x1 */ + SET_MEMBER(unsigned char desc_type, 0x0, 0x8); + /* Length of this data structure in bytes */ + SET_MEMBER(unsigned long len, 0x8, 0x10); + /* Current RIM value */ + SET_MEMBER(unsigned char rim[MAX_MEASUREMENT_SIZE], 0x10, 0x50); + /* Hash of 4KB page which contains REC parameters data structure */ + SET_MEMBER(unsigned char content[MAX_MEASUREMENT_SIZE], 0x50, 0x100); +} tmi_measure_tec_t; + +typedef struct cvm_init_measure { + enum hash_algo measurement_algo; + unsigned char rim[MAX_MEASUREMENT_SIZE]; +} cvm_init_measure_t; + +void measure_create_cvm(cvm_init_measure_t *meas, + bool lpa2_enable, + bool sve_enable, + bool pmu_enable, + uint64_t ipa_width, + uint64_t sve_vector_length, + uint64_t num_bps, + uint64_t num_wps, + uint64_t num_pmu, + uint64_t hash_algo); + +void measure_create_tecs(cvm_init_measure_t *meas, + uint64_t loader_start, + unsigned int tec_num); + +void measure_load_data(cvm_init_measure_t *meas, + uint64_t loader_start, + uint64_t ram_size, + uint64_t initrd_start, + const char *kernel_path, + const char *ramdisk_path, + const char *dtb_path); + +void generate_rim_reference(const char *kernel_path, const char *dtb_path, + const char *ramdisk_path); + +void print_hash(unsigned char *measurement, + const enum hash_algo algorithm); + +#endif /* GEN_RIM_REF_H */ \ No newline at end of file diff --git a/attestation/rim_ref/src/rim_ref/CMakeList.txt b/attestation/rim_ref/src/rim_ref/CMakeList.txt new file mode 100644 index 0000000..afcb456 --- /dev/null +++ b/attestation/rim_ref/src/rim_ref/CMakeList.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.12) +# Project name +project(gen_rim_ref) + +find_package(OpenSSL REQUIRED) + +# Set include directory +set(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../inc + ) +# Set source file +set(SOURCES gen_rim_ref.c + ) + +# Generate excutable +add_executable(${PROJECT_NAME} ${SOURCES}) +target_compile_definitions(${PROJECT_NAME} PRIVATE LOG_PRINT=0) +target_include_directories(${PROJECT_NAME} PRIVATE ${INCLUDE_DIRS}) +target_link_libraries(${PROJECT_NAME} OpenSSL::SSL OpenSSL::Crypto) \ No newline at end of file diff --git a/attestation/rim_ref/src/rim_ref/gen_rim_ref.c b/attestation/rim_ref/src/rim_ref/gen_rim_ref.c new file mode 100644 index 0000000..2a4cbf0 --- /dev/null +++ b/attestation/rim_ref/src/rim_ref/gen_rim_ref.c @@ -0,0 +1,578 @@ +#include "gen_rim_ref.h" +#include +#include +#include +#include +#include +#include +#include + +#if LOG_PRINT +int data_measure_cnt = 0; +int data_unknown_cnt = 0; +#endif + +static size_t get_file_size(const char *filename) +{ + FILE *file = fopen(filename, "rb"); + if (file == NULL) { + return -1; + } + + fseek(file, 0, SEEK_END); + size_t size = ftell(file); + fclose(file); + + return size; +} + +static inline size_t measurement_get_size( + const enum hash_algo algorithm) +{ + size_t ret = 0; + switch (algorithm) { + case HASH_ALGO_SHA256: + ret = (size_t)SHA256_SIZE; + break; + case HASH_ALGO_SHA512: + ret = (size_t)SHA512_SIZE; + break; + default: + assert(false); + } + return ret; +} + +static uint32_t get_bootloader_aarch64(uint64_t kernel_start, + uint64_t dtb_start, + uint32_t *code) +{ + uint32_t bootloader[BOOTLOADER_LEN_UINT32]; + bootloader[0] = 0x580000c0; /* 0x 58 00 00 c0 ; ldr x0, arg ; Load the lower 32-bits of DTB */ + bootloader[1] = 0xaa1f03e1; /* 0x aa 1f 03 e1 ; mov x1, xzr */ + bootloader[2] = 0xaa1f03e2; /* 0x aa 1f 03 e2 ; mov x2, xzr */ + bootloader[3] = 0xaa1f03e3; /* 0x aa 1f 03 e3 ; mov x3, xzr */ + bootloader[4] = 0x58000084; /* 0x 58 00 00 84 ; ldr x4, entry ; Load the lower 32-bits of kernel entry */ + bootloader[5] = 0xd61f0080; /* 0x d6 1f 00 80 ; br x4 ; Jump to the kernel entry point */ + /* FIXUP_ARGPTR_LO ; arg: .word @DTB Lower 32-bits */ + bootloader[6] = dtb_start; + /* FIXUP_ARGPTR_HI ; .word @DTB Higher 32-bits */ + bootloader[7] = dtb_start >> 32; + /* FIXUP_ENTRYPOINT_LO ; entry: .word @Kernel Entry Lower 32-bits */ + bootloader[8] = kernel_start; + /* FIXUP_ENTRYPOINT_HI ; .word @Kernel Entry Higher 32-bits */ + bootloader[9] = kernel_start >> 32; + memcpy(code, bootloader, BOOTLOADER_LEN_UINT32 * sizeof(uint32_t)); +} + +void print_hash(unsigned char *measurement, + const enum hash_algo algorithm) +{ + unsigned int size = 0U; + assert(measurement != NULL); + char hexDigits[] = "0123456789ABCDEF"; + int hexIndex = 0; + + char hash_str[130] = ""; + + switch (algorithm) { + case HASH_ALGO_SHA256: + size = SHA256_SIZE; + break; + case HASH_ALGO_SHA512: + size = SHA512_SIZE; + break; + default: + assert(0); + } + + for (unsigned int i = 0U; i < size; ++i) { + hash_str[hexIndex++] = hexDigits[*(measurement+i) >> 4 & 0x0F]; + hash_str[hexIndex++] = hexDigits[*(measurement+i) & 0x0F]; + } + + printf("HASH: %s\n", hash_str); +} + +static void print_data(unsigned char *data) +{ + char hexDigits[] = "0123456789ABCDEF"; + int hexIndex = 0; + + char output[130] = ""; + + for (unsigned int i = 0; i < 32; ++i) { + output[hexIndex++] = hexDigits[*(data+i) >> 4 & 0x0F]; + output[hexIndex++] = hexDigits[*(data+i) & 0x0F]; + } + + printf("DATA: %s\n", output); +} + +static int do_hash(enum hash_algo hash_algo, + void *data, + size_t size, + unsigned char *out) +{ + int result = 0; + EVP_MD_CTX *mdctx; + const EVP_MD *md; + unsigned int md_len; + + OpenSSL_add_all_digests(); + + switch (hash_algo) { + case HASH_ALGO_SHA256: + md = EVP_sha256(); + break; + case HASH_ALGO_SHA512: + md = EVP_sha512(); + break; + default: + printf("Unspported hash algorithnm\n"); + return 1; + } + + mdctx = EVP_MD_CTX_new(); + if (mdctx == NULL) { + printf("Failed to initialiaze digest contex\n"); + return 2; + } + + if (EVP_DigestInit_ex(mdctx, md, NULL) != 1) { + printf("Failed to initialize digest\n"); + result = 3; + } else if (EVP_DigestUpdate(mdctx, data, size) != 1) { + printf("Failed to update digest\n"); + result = 4; + } else if (EVP_DigestFinal_ex(mdctx, out, &md_len) != 1) { + printf("Failed to finalize digest\n"); + result = 5; + } + EVP_MD_CTX_free(mdctx); + + #if LOG_PRINT + print_hash(out, hash_algo); + #endif + + return result; +} + +void measure_tmi_cvm_create(cvm_init_measure_t *meas, tmi_cvm_create_params_t *params) +{ + /* Allocate a zero-filled tmi_measure_cvm_t data structure to hold + the measured cVM parameters. By specification cVM_params is 4KB. */ + unsigned char buffer[sizeof(tmi_measure_cvm_t)] = {0}; + tmi_measure_cvm_t *tmm_params_measured = (tmi_measure_cvm_t *)buffer; + + /* + * Copy flags, s2sz, sve_vl, num_bps, num_wps, pmu_num_cnts + * and hash_algo to the measured cVM parameters. + */ + tmm_params_measured->flags = params->flags; + tmm_params_measured->s2sz = params->s2sz; + tmm_params_measured->sve_vl = params->sve_vl; + tmm_params_measured->num_bps = params->num_bps; + tmm_params_measured->num_wps = params->num_wps; + tmm_params_measured->pmu_num_cnts = params->pmu_num_cnts; + tmm_params_measured->measurement_algo = params->measurement_algo; + + meas->measurement_algo = params->measurement_algo; + + #if LOG_PRINT + printf("Measuring tmi_cvm_create\n"); + printf("flags: 0x%016lx\n", params->flags); + printf("s2sz: 0x%016lx\n", params->s2sz); + printf("sve_vl: 0x%016lx\n", params->sve_vl); + printf("num_bps: 0x%016lx\n", params->num_bps); + printf("num_wps: 0x%016lx\n", params->num_wps); + printf("pmu_cnt: 0x%016lx\n", params->pmu_num_cnts); + printf("h-algo: 0x%016lx\n", params->measurement_algo); + #endif + + /* Compute the HASH on tmm_params_measured data structurem, set the RIM to + this value, zero filling the upper bytes if the HASH output is smaller + than the size of the RIM. */ + do_hash(meas->measurement_algo, buffer, sizeof(buffer), meas->rim); +} + +void measure_tmi_tec_create(cvm_init_measure_t *meas, tmi_tec_create_params_t *params) +{ + /* Allocate a zero_filled TmiTecParams data structure to hold the measured + TEC parametsrs. */ + unsigned char buffer[sizeof(tmi_tec_params_t)] = {0}; + tmi_tec_params_t *tec_params_measured = (tmi_tec_params_t *)buffer; + + /* Copy gprs, pc, flags into the measured TEC parameters data structure */ + tec_params_measured->pc = params->pc; + tec_params_measured->flags = params->flags; + memcpy(tec_params_measured->gprs, params->gprs, sizeof(params->gprs)); + + #if LOG_PRINT + printf("Measuring tmi_tec_create\n"); + printf("pc: 0x%016lx\n", tec_params_measured->pc); + printf("flags: 0x%016lx\n", tec_params_measured->flags); + printf("gprs[0]: 0x%016lx\n", tec_params_measured->gprs[0]); + printf("gprs[1]: 0x%016lx\n", tec_params_measured->gprs[1]); + printf("gprs[2]: 0x%016lx\n", tec_params_measured->gprs[2]); + printf("gprs[3]: 0x%016lx\n", tec_params_measured->gprs[3]); + printf("gprs[4]: 0x%016lx\n", tec_params_measured->gprs[4]); + printf("gprs[5]: 0x%016lx\n", tec_params_measured->gprs[5]); + printf("gprs[6]: 0x%016lx\n", tec_params_measured->gprs[6]); + printf("gprs[7]: 0x%016lx\n", tec_params_measured->gprs[7]); + #endif + + /* Initialize the measurement descriptor structure and populate the descriptor */ + tmi_measure_tec_t measure_desc = {0}; + /* Set the desc_type field to the descriptor type */ + measure_desc.desc_type = MEASURE_DESC_TYPE_REC; + /* Set the len field to the descriptor length */ + measure_desc.len = sizeof(tmi_measure_tec_t); + /* Set the rim field to the current RIM value of the target cVM */ + memcpy(measure_desc.rim, meas->rim, measurement_get_size(meas->measurement_algo)); + /* Set the content field to the hash of the measured REC parameters */ + do_hash(meas->measurement_algo, tec_params_measured, sizeof(*tec_params_measured), measure_desc.content); + + /* Hashing the measurement descriptor structure and get the new RIM */ + do_hash(meas->measurement_algo, &measure_desc, sizeof(measure_desc), meas->rim); +} + +void measure_tmi_data_create(cvm_init_measure_t *meas, tmi_data_create_params_t *params) +{ + + /* Allocate an TmiMeasurementDescriptorData data structure */ + tmi_measure_data_t measure_desc = {0}; + + /* Initialize the measurement descriptior structure */ + /* Set the desc_type field to the descriptor type */ + measure_desc.desc_type = MEASURE_DESC_TYPE_DATA; + /* Set the len field to the descriptor length */ + measure_desc.len = sizeof(tmi_measure_data_t); + /* Set the ipa field to the IPA at which the DATA Granule is mapped in the target cVM */ + measure_desc.ipa = params->ipa; + /* Set the flags field to the flags */ + measure_desc.flags = params->flags; + /* Set the rim field to the current RIM value of the target cVM */ + (void)memcpy(measure_desc.rim, meas->rim, measurement_get_size(meas->measurement_algo)); + + /* If flags.measure == TMI_MEASURE_CONTENT then set the content field to the hash of + * the contents of the DATA Granule. Otherwise, set the content field to zero. + */ + if (measure_desc.flags == TMI_MEASURE_CONTENT) { + /* + * Hashing the data granules and store the result in the + * measurement descriptor structure. + */ + #if LOG_PRINT + data_measure_cnt ++; + printf("Measuring tmi_data_create %d\n", data_measure_cnt); + print_data((unsigned char *)params->data); + #endif + + do_hash(meas->measurement_algo, params->data, (size_t)params->size, measure_desc.content); + } else { + #if LOG_PRINT + data_unknown_cnt ++; + printf("Measuring tmi_data_create_unknown %d\n", data_unknown_cnt); + #endif + } + + #if LOG_PRINT + printf("ipa: 0x%016lx\n", params->ipa); + printf("size: 0x%016lx\n", params->size); + printf("flags: 0x%016lx\n", params->flags); + #endif + + /* + * Hashing the measurement descriptor structure; the result is the + * updated RIM. + */ + do_hash(meas->measurement_algo, &measure_desc, sizeof(measure_desc), meas->rim); +} + +void measure_load_data(cvm_init_measure_t *meas, + uint64_t loader_start, + uint64_t ram_size, + uint64_t initrd_start, + const char *kernel_path, + const char *initramfs_path, + const char *dtb_path) +{ + FILE *file; + size_t kernel_size; + size_t initrd_size; + size_t dtb_size; + + if (initramfs_path == NULL) { + initrd_size = 0; + } else { + initrd_size = get_file_size(initramfs_path); + if (initrd_size < 0) { + perror("Cannot open initramfs file"); + return; + } + } + + size_t bytes_read; + size_t addr = round_down(loader_start, BLOCK_SIZE); + size_t addr_end = round_up(loader_start + ram_size, BLOCK_SIZE); + size_t kernel_start = loader_start + KERNEL_LOAD_OFFSET; + size_t dtb_start = round_up(initrd_start + initrd_size, BLOCK_SIZE); + tmi_data_create_params_t params; + + unsigned char *buffer; + + buffer = malloc(BLOCK_SIZE); + if (buffer == NULL) { + perror("Memory allocation error"); + return; + } + + /* Measure bootloader */ + uint32_t code[BOOTLOADER_LEN_UINT32]; + get_bootloader_aarch64(kernel_start, dtb_start, code); + memset(buffer, 0, sizeof(buffer)); + memcpy(buffer, code, sizeof(code)); + memset(¶ms, 0, sizeof(params)); + params.data = (uint64_t *)buffer; + params.size = L2_GRANULE; + SET_BIT(params.flags, 0); + params.ipa = addr; + measure_tmi_data_create(meas, ¶ms); + addr += L2_GRANULE; + + /* Measure kernel*/ + file = fopen(kernel_path, "rb"); + if (file == NULL) { + perror("Error opening initramfs file"); + return; + } + + while (!feof(file)) { + bytes_read = fread(buffer, 1, BLOCK_SIZE, file); + if (bytes_read < BLOCK_SIZE) { + if (ferror(file)) { + perror("Error reading initramfs file"); + break; + } + memset(buffer + bytes_read, 0, BLOCK_SIZE - bytes_read); + } + + memset(¶ms, 0, sizeof(params)); + params.data = (uint64_t *)buffer; + params.size = BLOCK_SIZE; + SET_BIT(params.flags, 0); + params.ipa = addr; + measure_tmi_data_create(meas, ¶ms); + addr += BLOCK_SIZE; + } + + /* Useless measurement */ + while (addr < initrd_start) { + memset(buffer, 0, BLOCK_SIZE); + memset(¶ms, 0, sizeof(params)); + params.data = (uint64_t *)buffer; + params.size = BLOCK_SIZE; + CLEAR_BIT(params.flags, 0); + params.ipa = addr; + measure_tmi_data_create(meas, ¶ms); + addr += BLOCK_SIZE; + } + + /* Measure initramfs*/ + if (initrd_size != 0) { + file = fopen(initramfs_path, "rb"); + if (file == NULL) { + perror("Error opening initramfs file"); + return; + } + + while (!feof(file)) { + bytes_read = fread(buffer, 1, BLOCK_SIZE, file); + if (bytes_read < BLOCK_SIZE) { + if (ferror(file)) { + perror("Error reading initramfs file"); + break; + } + memset(buffer + bytes_read, 0, BLOCK_SIZE - bytes_read); + } + + memset(¶ms, 0, sizeof(params)); + params.data = (uint64_t *)buffer; + params.size = BLOCK_SIZE; + SET_BIT(params.flags, 0); + params.ipa = addr; + measure_tmi_data_create(meas, ¶ms); + addr += BLOCK_SIZE; + } + } + + /* Measure dtb*/ + file = fopen(dtb_path, "rb"); + if (file == NULL) { + perror("Error opening dtb file"); + return; + } + + while (!feof(file)) { + bytes_read = fread(buffer, 1, BLOCK_SIZE, file); + if (bytes_read < BLOCK_SIZE) { + if (ferror(file)) { + perror("Error reading dtb file"); + break; + } + memset(buffer + bytes_read, 0, BLOCK_SIZE - bytes_read); + } + + memset(¶ms, 0, sizeof(params)); + params.data = (uint64_t *)buffer; + params.size = BLOCK_SIZE; + SET_BIT(params.flags, 0); + params.ipa = addr; + measure_tmi_data_create(meas, ¶ms); + addr += BLOCK_SIZE; + } + + /* Measure data_create_unknown */ + while (addr < addr_end) { + memset(buffer, 0, sizeof(buffer)); + memset(¶ms, 0, sizeof(params)); + params.data = (uint64_t *)buffer; + params.size = BLOCK_SIZE; + CLEAR_BIT(params.flags, 0); + params.ipa = addr; + measure_tmi_data_create(meas, ¶ms); + addr += BLOCK_SIZE; + } +} + +void measure_create_tecs(cvm_init_measure_t *meas, + uint64_t loader_start, + unsigned int tec_num) +{ + tmi_tec_create_params_t params; + + for (size_t i = 0; i < tec_num; i++) + { + memset(¶ms, 0, sizeof(params)); + if (i == 0) { /* The master tec */ + params.pc = loader_start; + SET_BIT(params.flags, 0); + } + measure_tmi_tec_create(meas, ¶ms); + } + +} + +void measure_create_cvm(cvm_init_measure_t *meas, + bool lpa2_enable, + bool sve_enable, + bool pmu_enable, + uint64_t ipa_width, + uint64_t sve_vector_length, + uint64_t num_bps, + uint64_t num_wps, + uint64_t num_pmu, + uint64_t hash_algo) +{ + tmi_cvm_create_params_t params = {0}; + if (lpa2_enable) { + SET_BIT(params.flags, 0); + } else { + CLEAR_BIT(params.flags, 0); + } + + if (sve_enable) { + SET_BIT(params.flags, 1); + } else { + CLEAR_BIT(params.flags, 1); + } + + if (pmu_enable) { + SET_BIT(params.flags, 2); + } else { + CLEAR_BIT(params.flags, 2); + } + + params.s2sz = ipa_width; + params.sve_vl = sve_vector_length; + params.num_bps = num_bps; + params.num_wps = num_wps; + params.pmu_num_cnts = num_pmu; + params.measurement_algo = hash_algo; + + measure_tmi_cvm_create(meas, ¶ms); +} + +void generate_rim_reference(const char *kernel_path, const char *dtb_path, + const char *initramfs_path) +{ + bool lpa2_enable = false; + bool sve_enable = false; + bool pmu_enable = true; + uint64_t ipa_width = 40; + uint64_t sve_vector_length = 0; + uint64_t num_bps = 0; + uint64_t num_wps = 0; + uint64_t num_pmu = 1; + uint64_t hash_algo = 0; + uint64_t tec_num = 2; + uint64_t loader_start = 1 * GiB; + uint64_t ram_size = 512 * MB; + uint64_t initrd_start = 128 * MB + loader_start; + + cvm_init_measure_t meas={0}; + measure_create_cvm(&meas, lpa2_enable, sve_enable, pmu_enable, + ipa_width, sve_vector_length, num_bps, num_wps, + num_pmu, hash_algo); + measure_create_tecs(&meas, loader_start, tec_num); + measure_load_data(&meas, loader_start, ram_size, initrd_start, + kernel_path, initramfs_path, dtb_path); + printf("RIM-"); + print_hash(meas.rim, meas.measurement_algo); +} + +void print_help() +{ + printf("Generate rim reference value:\n"); + printf(" [] \n"); + printf(" kernel_path: path to kernel image\n"); + printf(" dtb_path: path to device tree dtb file\n"); + printf(" initramfs_path: path to initramfs gzip file\n"); +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + + /* TODO: Parse parameters based on inputted ini config file */ + + if (argc < 2) { + errno = EINVAL; + perror("Please input kernel path and dtb path"); + print_help(); + return -1; + } + + if (argc < 3) { + errno = EINVAL; + perror("Please input dtb path"); + print_help(); + return -1; + } + + char kernel_path[1000]; + char dtb_path[1000]; + char initramfs_path[1000]; + strncpy(kernel_path, argv[1], sizeof(kernel_path)); + strncpy(dtb_path, argv[2], sizeof(dtb_path)); + if (argc < 4) { + generate_rim_reference(kernel_path, dtb_path, NULL); + } else { + strncpy(initramfs_path, argv[3], sizeof(initramfs_path)); + generate_rim_reference(kernel_path, dtb_path, initramfs_path); + } + + return ret; + +} \ No newline at end of file -- Gitee From e0f3a9c441b2b587ea24f092303854c5bf7fe085 Mon Sep 17 00:00:00 2001 From: unholyzero <576175933@qq.com> Date: Tue, 21 May 2024 17:19:12 +0800 Subject: [PATCH 2/2] rim_ref generate tool --- .../rim_ref/{CMakeList.txt => CMakeLists.txt} | 16 +- attestation/rim_ref/build.sh | 164 ------------------ attestation/rim_ref/inc/gen_rim_ref.h | 11 ++ .../rim_ref/src/{rim_ref => }/gen_rim_ref.c | 13 +- attestation/rim_ref/src/rim_ref/CMakeList.txt | 18 -- 5 files changed, 37 insertions(+), 185 deletions(-) rename attestation/rim_ref/{CMakeList.txt => CMakeLists.txt} (55%) delete mode 100644 attestation/rim_ref/build.sh rename attestation/rim_ref/src/{rim_ref => }/gen_rim_ref.c (93%) delete mode 100644 attestation/rim_ref/src/rim_ref/CMakeList.txt diff --git a/attestation/rim_ref/CMakeList.txt b/attestation/rim_ref/CMakeLists.txt similarity index 55% rename from attestation/rim_ref/CMakeList.txt rename to attestation/rim_ref/CMakeLists.txt index b8f841c..bab1508 100644 --- a/attestation/rim_ref/CMakeList.txt +++ b/attestation/rim_ref/CMakeLists.txt @@ -2,8 +2,9 @@ cmake_minimum_required(VERSION 3.5.1) # Project -project(tsi-interface) +project(gen_rim_ref) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +find_package(OpenSSL REQUIRED) # Build mode if(NOT CMAKE_BUILD_TYPE) @@ -19,8 +20,19 @@ option(BUILD_RIM_GEN "Compile rim reference generator" ON) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/output) set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) +# Set include directory +set(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/inc + ) +# Set source file +set(SOURCES src/gen_rim_ref.c + ) + +# Generate excutable +add_executable(${PROJECT_NAME} ${SOURCES}) +target_compile_definitions(${PROJECT_NAME} PRIVATE LOG_PRINT=0) +target_include_directories(${PROJECT_NAME} PRIVATE ${INCLUDE_DIRS}) +target_link_libraries(${PROJECT_NAME} OpenSSL::SSL OpenSSL::Crypto) if(BUILD_RIM_GEN) message(STATUS "Build gen_rim_ref: on") - add_subdirectory(src/rim_ref) endif() diff --git a/attestation/rim_ref/build.sh b/attestation/rim_ref/build.sh deleted file mode 100644 index a6d8135..0000000 --- a/attestation/rim_ref/build.sh +++ /dev/null @@ -1,164 +0,0 @@ -#!/bin/bash -# Copyright Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. -set -e - -export USR_COMPILER_CC="" -export DEBUG_OR_RELEASE="" -export CLEAN_ENABLED="" -export ARCH="arm64" -export CROSS_COMPILE - -print_help() { - echo -e "\nUsage:" - echo -e " build.sh [options]...\n" - echo -e "Options:" - echo -e " -v, --usrcompiler \033[4musrcompiler\033[0m" - echo -e " compiler for target usr. Default value is aarch64-linux-gnu-gcc, you can config gcc\n" - echo -e " -t, --compile target, you can config \"all\", \"rim\", \"plat\" or \"usr\"\n" - echo -e " -r, --release" - echo -e " Enable release building. Default build for debug\n" - echo -e " -c, --clean" - echo -e " Clean all the files built\n" - echo -e " -h, --help" - echo -e " Display this help and exit.\n" -} - -! getopt --test > /dev/null -if [[ ${PIPESTATUS[0]} -ne 4 ]]; then - echo 'getopt is not the enhanced version.' - exit 1 -fi - -OPTIONS=v:rhct: -LONGOPTS=usrcompiler:,release,help,clean,target: - -! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "build" -- "$@") -if [[ ${PIPESTATUS[0]} -ne 0 ]]; then - print_help - exit 2 -fi - -# reset parameters -eval set -- "$PARSED" - -while true; do - case "${1}" in - -h|--help) - print_help - exit 0 - ;; - -r|--release) - DEBUG_OR_RELEASE="Release" - shift - ;; - -v|--usrcompiler) - USR_COMPILER_CC="${2}" - shift 2 - ;; - -t|--target) - BUILD_TARGET="${2}" - shift 2 - ;; - -c|--clean) - CLEAN_ENABLED="ON" - shift - ;; - --) - shift - break - ;; - *) - echo "Programming error" - exit 3 - ;; - esac -done - -if [[ $# -ne 0 ]]; then - echo "build: wrong parameter: ${1}" - print_help - exit 4 -fi - -export CC -export CXX - -if [[ "${USR_COMPILER_CC}" == "" ]]; then - USR_COMPILER_CC=aarch64-linux-gnu-gcc -elif [[ "${USR_COMPILER_CC}" == "aarch64-linux-gnu-gcc" ]]; then - echo "INFO: USR_COMPILER_CC == ${USR_COMPILER_CC}" -elif [[ "${USR_COMPILER_CC}" != "gcc" ]]; then - echo "ERROR: your input compiler is not support: ${USR_COMPILER_CC}" - print_help - exit 1 -else - echo "INFO: USR_COMPILER_CC == ${USR_COMPILER_CC}" -fi - -if [[ "${BUILD_TARGET}" == "" ]]; then - BUILD_TARGET="all" -fi - -if [[ "${DEBUG_OR_RELEASE}" == "" ]]; then - DEBUG_OR_RELEASE="Debug" -fi - -if [[ "${CLEAN_ENABLED}" == "" ]]; then - CLEAN_ENABLED=OFF -fi - -echo -e "\ntsi-interface compiling info:" -echo -e "build target = ${BUILD_TARGET}" -echo -e "debug or release = ${DEBUG_OR_RELEASE}" -echo -e "clean enabled = ${CLEAN_ENABLED}" - -if [[ -z "${CC}" ]]; then - CC="${USR_COMPILER_CC}" -fi -echo -e "user c compiler = ${CC}" - -if [[ -z "${CXX}" ]]; then - CXX=$(which g++) -fi -echo -e "user c++ compiler = ${CXX}\n" - -if [[ "${BUILD_TARGET}" == "all" ]]; then - BUILD_FAKE_PLAT=ON - BUILD_RIM_GEN=ON - BUILD_INTERFACE=ON -elif [[ "${BUILD_TARGET}" == "rim" ]]; then - BUILD_FAKE_PLAT=OFF - BUILD_RIM_GEN=ON - BUILD_INTERFACE=OFF -elif [[ "${BUILD_TARGET}" == "plat" ]]; then - BUILD_FAKE_PLAT=ON - BUILD_RIM_GEN=OFF - BUILD_INTERFACE=OFF -elif [[ "${BUILD_TARGET}" == "usr" ]]; then - BUILD_FAKE_PLAT=OFF - BUILD_RIM_GEN=OFF - BUILD_INTERFACE=ON -else - echo "ERROR: please input correct target name: ${BUILD_TARGET}" - exit 4 -fi - -cmake -DBUILD_RIM_GEN=${BUILD_RIM_GEN} \ - -DCMAKE_BUILD_TYPE=${DEBUG_OR_RELEASE} \ - -B ./build - -pushd ./build - -if [[ "${CLEAN_ENABLED}" == "ON" ]]; then - make clean -fi - -if [[ "${BUILD_INTERFACE}" == "ON" && "${DEBUG_OR_RELEASE}" = "Debug" ]]; then - make -else - make -fi - -popd - -echo "INFO: building tsi interface target ${BUILD_TARGET} finished." \ No newline at end of file diff --git a/attestation/rim_ref/inc/gen_rim_ref.h b/attestation/rim_ref/inc/gen_rim_ref.h index 57fe190..d9c8059 100644 --- a/attestation/rim_ref/inc/gen_rim_ref.h +++ b/attestation/rim_ref/inc/gen_rim_ref.h @@ -1,3 +1,14 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * virtCCA_sdk is licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ #ifndef GEN_RIM_REF_H #define GEN_RIM_REF_H diff --git a/attestation/rim_ref/src/rim_ref/gen_rim_ref.c b/attestation/rim_ref/src/gen_rim_ref.c similarity index 93% rename from attestation/rim_ref/src/rim_ref/gen_rim_ref.c rename to attestation/rim_ref/src/gen_rim_ref.c index 2a4cbf0..47d10b7 100644 --- a/attestation/rim_ref/src/rim_ref/gen_rim_ref.c +++ b/attestation/rim_ref/src/gen_rim_ref.c @@ -1,3 +1,14 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * virtCCA_sdk is licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ #include "gen_rim_ref.h" #include #include @@ -545,7 +556,7 @@ int main(int argc, char *argv[]) { int ret = 0; - /* TODO: Parse parameters based on inputted ini config file */ + /* Parse parameters based on inputted ini config file */ if (argc < 2) { errno = EINVAL; diff --git a/attestation/rim_ref/src/rim_ref/CMakeList.txt b/attestation/rim_ref/src/rim_ref/CMakeList.txt deleted file mode 100644 index afcb456..0000000 --- a/attestation/rim_ref/src/rim_ref/CMakeList.txt +++ /dev/null @@ -1,18 +0,0 @@ -cmake_minimum_required(VERSION 3.12) -# Project name -project(gen_rim_ref) - -find_package(OpenSSL REQUIRED) - -# Set include directory -set(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../inc - ) -# Set source file -set(SOURCES gen_rim_ref.c - ) - -# Generate excutable -add_executable(${PROJECT_NAME} ${SOURCES}) -target_compile_definitions(${PROJECT_NAME} PRIVATE LOG_PRINT=0) -target_include_directories(${PROJECT_NAME} PRIVATE ${INCLUDE_DIRS}) -target_link_libraries(${PROJECT_NAME} OpenSSL::SSL OpenSSL::Crypto) \ No newline at end of file -- Gitee