From 58a51517a7b74b696788f798614817dda97b7c0c Mon Sep 17 00:00:00 2001 From: Evgeny P <34085769+evgenyp67@users.noreply.github.com> Date: Sat, 2 Dec 2023 19:49:21 -0800 Subject: [PATCH 1/2] In-enclave ELF loading (#326) Changes are in SDK, driver, SM, and runtime. Loader is added to runtime. A contributor-private branch based on this fully passes `tests` on CVA6. ### Changes & Rationale Previously, the host SDK was required to produce the same mapping as the developer SDK. This complicates measurement, keeping SDK versions in sync, alternate loading features a developer may want, and the Keystone code in general. - Enclaves now need "trusted loader" that loads the runtime and enclave app binaries - ELF parsing/loading was removed from SDK and added to `runtime/loader` and `runtime/loader-binary` - Enclave measurement is now just the measurement of the binaries concatenated The new design creates a much simpler code design where the host simply passes the required elf files to the enclave memory and those files are measured. The loading code lives in the enclave that makes it simpler and more standard. Trust assumptions are unchanged because the developer needs to have correct loading code either way. The developer can now also have completely custom loading logic that is independent from what the host supports. ### Outstanding issues 1. Improving enclave measurement: untrusted and free memory are not measured in, so host can deny resources with measurement not reflecting that. 2. Minor memory leak: when elf file pages are not guaranteed to be non-colliding, a new page is allocated instead of that page being used to one of the colliding program headers. 3. (Unrelated) Buildroot system bug: `fw_bin` is not properly set in the examples build, added temporary fix. ### Refactor needs 1. `linux-driver` structures 2. No longer needed in SDK: simulated, Memory 3. Make structures consistent across: `sm - open_sbi - driver - ioctl - host` --------- Signed-off-by: Jarkko Sakkinen Co-authored-by: Jarkko Sakkinen --- examples/attestation/CMakeLists.txt | 10 +- examples/attestation/host/attestor-runner.cpp | 16 +- examples/attestation/host/host.cpp | 2 +- examples/attestation/host/host.h | 6 +- examples/attestation/host/verifier.cpp | 10 +- examples/attestation/host/verifier.h | 4 +- examples/hello-native/CMakeLists.txt | 4 +- examples/hello-native/host/host_native.cpp | 2 +- examples/hello/CMakeLists.txt | 4 +- examples/hello/host/host.cpp | 6 +- examples/tests/CMakeLists.txt | 6 +- examples/tests/test-runner.cpp | 7 +- fast-setup.sh | 10 + linux-keystone-driver/keystone-enclave.c | 19 - linux-keystone-driver/keystone-ioctl.c | 3 +- linux-keystone-driver/keystone.h | 7 - runtime/CMakeLists.txt | 8 +- runtime/call/syscall.c | 4 +- runtime/include/loader/elf.h | 464 +++++++++++++++++ runtime/include/loader/elf32.h | 153 ++++++ runtime/include/loader/elf64.h | 152 ++++++ runtime/include/loader/loader.h | 3 + runtime/include/mm/freemem.h | 3 + runtime/include/mm/mm.h | 1 + runtime/include/mm/vm.h | 64 +-- runtime/include/mm/vm_defs.h | 2 + runtime/include/sys/auxvec.h | 55 ++ runtime/loader-binary/CMakeLists.txt | 13 + runtime/loader-binary/loader-binary.c | 91 ++++ runtime/loader-binary/loader.S | 69 +++ runtime/loader-binary/loader.lds | 29 ++ runtime/loader/CMakeLists.txt | 8 + runtime/loader/elf.c | 470 ++++++++++++++++++ runtime/loader/elf32.c | 64 +++ runtime/loader/elf64.c | 68 +++ runtime/loader/loader.c | 94 ++++ runtime/mm/CMakeLists.txt | 6 +- runtime/mm/freemem_ld.c | 43 ++ runtime/mm/mm.c | 30 +- runtime/mm/vm.c | 56 ++- runtime/sys/CMakeLists.txt | 2 +- runtime/sys/boot.c | 91 ++-- runtime/sys/entry.S | 8 + runtime/sys/env.c | 1 + sdk/include/host/ElfFile.hpp | 2 + sdk/include/host/Elfloader.hpp | 3 + sdk/include/host/Enclave.hpp | 31 +- sdk/include/host/Memory.hpp | 24 +- sdk/macros.cmake | 3 +- sdk/src/host/ElfFile.cpp | 63 +-- sdk/src/host/Enclave.cpp | 365 ++++---------- sdk/src/host/KeystoneDevice.cpp | 2 +- sdk/src/host/Memory.cpp | 260 +--------- sdk/src/host/PhysicalEnclaveMemory.cpp | 17 +- sdk/src/host/SimulatedEnclaveMemory.cpp | 7 +- sdk/tests/CMakeLists.txt | 12 +- sdk/tests/dl_tests.cpp | 73 +++ sm/src/attest.c | 196 +------- sm/src/enclave.c | 11 +- sm/src/sm.h | 2 +- 60 files changed, 2261 insertions(+), 978 deletions(-) create mode 100755 fast-setup.sh create mode 100644 runtime/include/loader/elf.h create mode 100644 runtime/include/loader/elf32.h create mode 100644 runtime/include/loader/elf64.h create mode 100644 runtime/include/loader/loader.h create mode 100644 runtime/include/sys/auxvec.h create mode 100644 runtime/loader-binary/CMakeLists.txt create mode 100644 runtime/loader-binary/loader-binary.c create mode 100644 runtime/loader-binary/loader.S create mode 100644 runtime/loader-binary/loader.lds create mode 100644 runtime/loader/CMakeLists.txt create mode 100644 runtime/loader/elf.c create mode 100644 runtime/loader/elf32.c create mode 100644 runtime/loader/elf64.c create mode 100644 runtime/loader/loader.c create mode 100644 runtime/mm/freemem_ld.c create mode 100644 sdk/include/host/Elfloader.hpp create mode 100644 sdk/tests/dl_tests.cpp diff --git a/examples/attestation/CMakeLists.txt b/examples/attestation/CMakeLists.txt index 21354e535..7da2c9f03 100644 --- a/examples/attestation/CMakeLists.txt +++ b/examples/attestation/CMakeLists.txt @@ -3,7 +3,7 @@ set(eapp_src eapp/attestor.c) set(host_bin attestor-runner) set(host_src host/attestor-runner.cpp host/host.cpp host/verifier.cpp) set(package_name "attestor.ke") -set(package_script "./attestor-runner attestor eyrie-rt --sm-bin fw_jump.bin") +set(package_script "./attestor-runner attestor eyrie-rt loader.bin --sm-bin fw_jump.bin") if(RISCV32) set(eyrie_plugins "freemem rv32") @@ -35,11 +35,17 @@ target_include_directories(${host_bin} # add target for Eyrie runtime (see keystone.cmake) -set(eyrie_files_to_copy .options_log eyrie-rt) +set(eyrie_files_to_copy .options_log eyrie-rt loader.bin) add_eyrie_runtime(${eapp_bin}-eyrie ${eyrie_plugins} ${eyrie_files_to_copy}) +# add sm binary -- TODO: fix, should come from upper levels +if(NOT DEFINED fw_bin) + message(AUTHOR_WARNING "fw_bin should be defined by upper CMake files/ build system. Setting to default") + set(fw_bin ../../../images/fw_jump.bin) +endif() + # add target for packaging (see keystone.cmake) add_keystone_package(${eapp_bin}-package diff --git a/examples/attestation/host/attestor-runner.cpp b/examples/attestation/host/attestor-runner.cpp index 067c3c160..4da367e5e 100644 --- a/examples/attestation/host/attestor-runner.cpp +++ b/examples/attestation/host/attestor-runner.cpp @@ -19,10 +19,10 @@ int main(int argc, char** argv) { - if (argc < 3 || argc > 8) { + if (argc < 4 || argc > 9) { printf( - "Usage: %s [--utm-size SIZE(K)] [--freemem-size " - "SIZE(K)] [--utm-ptr 0xPTR] [--sm-bin SM_BIN_PATH]\n", + "Usage: %s [--utm-size SIZE(K)] " + "[--freemem-size SIZE(K)] [--utm-ptr 0xPTR] [--sm-bin SM_BIN_PATH]\n", argv[0]); return 0; } @@ -45,10 +45,11 @@ main(int argc, char** argv) { char* eapp_file = argv[1]; char* rt_file = argv[2]; + char* ld_file = argv[3]; char* sm_bin_file = NULL; int c; - int opt_index = 3; + int opt_index = 4; while (1) { c = getopt_long(argc, argv, "u:p:f:s:", long_options, &opt_index); @@ -72,12 +73,17 @@ main(int argc, char** argv) { } } + if (sm_bin_file == NULL) { + printf("--sm-bin is missing.\n"); + return 0; + } + Keystone::Params params; params.setFreeMemSize(freemem_size); params.setUntrustedMem(utm_ptr, untrusted_size); - Verifier verifier{params, eapp_file, rt_file, sm_bin_file}; + Verifier verifier{params, eapp_file, rt_file, ld_file, sm_bin_file}; verifier.run(); return 0; diff --git a/examples/attestation/host/host.cpp b/examples/attestation/host/host.cpp index 31122b7a3..b121ac59a 100644 --- a/examples/attestation/host/host.cpp +++ b/examples/attestation/host/host.cpp @@ -235,7 +235,7 @@ Host::dispatch_ocall(RunData& run_data) { Report Host::run(const std::string& nonce) { Keystone::Enclave enclave; - enclave.init(eapp_file_.c_str(), rt_file_.c_str(), params_); + enclave.init(eapp_file_.c_str(), rt_file_.c_str(), ld_file_.c_str(), params_); RunData run_data{ SharedBuffer{enclave.getSharedBuffer(), enclave.getSharedBufferSize()}, diff --git a/examples/attestation/host/host.h b/examples/attestation/host/host.h index 0ee19a94b..470eb8929 100644 --- a/examples/attestation/host/host.h +++ b/examples/attestation/host/host.h @@ -58,8 +58,9 @@ class Host { public: Host( const Keystone::Params& params, const std::string& eapp_file, - const std::string& rt_file) - : params_(params), eapp_file_(eapp_file), rt_file_(rt_file) {} + const std::string& rt_file, const std::string& ld_file) + : params_(params), eapp_file_(eapp_file), rt_file_(rt_file), + ld_file_(ld_file) {} // Given a random nonce from the remote verifier, this method leaves // it for the enclave to fetch, and returns the attestation report // from the enclave to the verifier. @@ -79,6 +80,7 @@ Host( const Keystone::Params params_; const std::string eapp_file_; const std::string rt_file_; + const std::string ld_file_; }; #endif /* _ATTESTATION_HOST_H_ */ diff --git a/examples/attestation/host/verifier.cpp b/examples/attestation/host/verifier.cpp index 206f0eaf3..b90fe7168 100644 --- a/examples/attestation/host/verifier.cpp +++ b/examples/attestation/host/verifier.cpp @@ -23,7 +23,7 @@ void Verifier::run() { const std::string nonce = std::to_string(random() % 0x100000000); - Host host(params_, eapp_file_, rt_file_); + Host host(params_, eapp_file_, rt_file_, ld_file_); Report report = host.run(nonce); verify_report(report, nonce); } @@ -78,13 +78,7 @@ Verifier::verify_data(Report& report, const std::string& nonce) { void Verifier::compute_expected_enclave_hash(byte* expected_enclave_hash) { - Keystone::Enclave enclave; - Keystone::Params simulated_params = params_; - simulated_params.setSimulated(true); - // This will cause validate_and_hash_enclave to be called when - // isSimulated() == true. - enclave.init(eapp_file_.c_str(), rt_file_.c_str(), simulated_params); - memcpy(expected_enclave_hash, enclave.getHash(), MDSIZE); + Keystone::Enclave::measure((char*) expected_enclave_hash, eapp_file_.c_str(), rt_file_.c_str(), ld_file_.c_str()); } void diff --git a/examples/attestation/host/verifier.h b/examples/attestation/host/verifier.h index f921553d9..b85ba0fad 100644 --- a/examples/attestation/host/verifier.h +++ b/examples/attestation/host/verifier.h @@ -22,10 +22,11 @@ class Verifier { public: Verifier( const Keystone::Params& params, const std::string& eapp_file, - const std::string& rt_file, const std::string& sm_bin_file) + const std::string& rt_file, const std::string& ld_file, const std::string& sm_bin_file) : params_(params), eapp_file_(eapp_file), rt_file_(rt_file), + ld_file_(ld_file), sm_bin_file_(sm_bin_file) {} // This method generates a random nonce, invokes the run() method // of the Host, and verifies that the returned attestation report @@ -59,5 +60,6 @@ class Verifier { const Keystone::Params params_; const std::string eapp_file_; const std::string rt_file_; + const std::string ld_file_; const std::string sm_bin_file_; }; diff --git a/examples/hello-native/CMakeLists.txt b/examples/hello-native/CMakeLists.txt index 20b0beff6..5c88a9709 100644 --- a/examples/hello-native/CMakeLists.txt +++ b/examples/hello-native/CMakeLists.txt @@ -3,7 +3,7 @@ set(eapp_src eapp/eapp_native.c) set(host_bin hello-native-runner) set(host_src host/host_native.cpp) set(package_name "hello-native.ke") -set(package_script "./hello-native-runner hello-native eyrie-rt") +set(package_script "./hello-native-runner hello-native eyrie-rt loader.bin") if(RISCV32) set(eyrie_plugins "rv32 freemem") @@ -34,7 +34,7 @@ target_include_directories(${host_bin} # add target for Eyrie runtime (see keystone.cmake) -set(eyrie_files_to_copy .options_log eyrie-rt) +set(eyrie_files_to_copy .options_log eyrie-rt loader.bin) add_eyrie_runtime(${eapp_bin}-eyrie ${eyrie_plugins} ${eyrie_files_to_copy}) diff --git a/examples/hello-native/host/host_native.cpp b/examples/hello-native/host/host_native.cpp index 5f492f1f2..6398d7bbc 100644 --- a/examples/hello-native/host/host_native.cpp +++ b/examples/hello-native/host/host_native.cpp @@ -30,7 +30,7 @@ main(int argc, char** argv) { params.setFreeMemSize(1024 * 1024); params.setUntrustedMem(DEFAULT_UNTRUSTED_PTR, 1024 * 1024); - enclave.init(argv[1], argv[2], params); + enclave.init(argv[1], argv[2], argv[3], params); enclave.registerOcallDispatch(incoming_call_dispatch); diff --git a/examples/hello/CMakeLists.txt b/examples/hello/CMakeLists.txt index a169eaf6a..ff45519c0 100644 --- a/examples/hello/CMakeLists.txt +++ b/examples/hello/CMakeLists.txt @@ -3,7 +3,7 @@ set(eapp_src eapp/hello.c) set(host_bin hello-runner) set(host_src host/host.cpp) set(package_name "hello.ke") -set(package_script "./hello-runner hello eyrie-rt") +set(package_script "./hello-runner hello eyrie-rt loader.bin") if(RISCV32) set(eyrie_plugins "freemem io_syscall linux_syscall env_setup rv32") @@ -23,7 +23,7 @@ target_link_libraries(${host_bin} ${KEYSTONE_LIB_HOST} ${KEYSTONE_LIB_EDGE}) # add target for Eyrie runtime (see keystone.cmake) -set(eyrie_files_to_copy .options_log eyrie-rt) +set(eyrie_files_to_copy .options_log eyrie-rt loader.bin) add_eyrie_runtime(${eapp_bin}-eyrie ${eyrie_plugins} ${eyrie_files_to_copy}) diff --git a/examples/hello/host/host.cpp b/examples/hello/host/host.cpp index f17d645f9..d5ba3b55a 100644 --- a/examples/hello/host/host.cpp +++ b/examples/hello/host/host.cpp @@ -12,10 +12,10 @@ main(int argc, char** argv) { Enclave enclave; Params params; - params.setFreeMemSize(1024 * 1024); - params.setUntrustedMem(DEFAULT_UNTRUSTED_PTR, 1024 * 1024); + params.setFreeMemSize(256 * 1024); + params.setUntrustedMem(DEFAULT_UNTRUSTED_PTR, 256 * 1024); - enclave.init(argv[1], argv[2], params); + enclave.init(argv[1], argv[2], argv[3], params); enclave.registerOcallDispatch(incoming_call_dispatch); edge_call_init_internals( diff --git a/examples/tests/CMakeLists.txt b/examples/tests/CMakeLists.txt index 7c72e31c8..4117ffa8e 100644 --- a/examples/tests/CMakeLists.txt +++ b/examples/tests/CMakeLists.txt @@ -80,9 +80,9 @@ foreach (test IN ITEMS ${all_test_bins}) file(APPEND ${test_script_tmp} "echo 'testing ${test}'\n") if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${test}/retval) execute_process(COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/${test}/retval OUTPUT_VARIABLE retval) - file(APPEND ${test_script_tmp} "./${host_bin} ${test} eyrie-rt --retval ${retval}") + file(APPEND ${test_script_tmp} "./${host_bin} ${test} eyrie-rt loader.bin --retval ${retval}") else() - file(APPEND ${test_script_tmp} "./${host_bin} ${test} eyrie-rt\n") + file(APPEND ${test_script_tmp} "./${host_bin} ${test} eyrie-rt loader.bin\n") endif() endforeach(test) @@ -102,7 +102,7 @@ target_link_libraries(${host_bin} ${KEYSTONE_LIB_HOST} ${KEYSTONE_LIB_EDGE} ${KE # add target for Eyrie runtime (see keystone.cmake) -set(eyrie_files_to_copy .options_log eyrie-rt) +set(eyrie_files_to_copy .options_log eyrie-rt loader.bin) add_eyrie_runtime(test-eyrie ${eyrie_plugins} ${eyrie_files_to_copy}) diff --git a/examples/tests/test-runner.cpp b/examples/tests/test-runner.cpp index 02fb60c22..a98385d70 100644 --- a/examples/tests/test-runner.cpp +++ b/examples/tests/test-runner.cpp @@ -55,7 +55,7 @@ copy_report(void* buffer) { int main(int argc, char** argv) { - if (argc < 3 || argc > 8) { + if (argc < 4 || argc > 9) { printf( "Usage: %s [--utm-size SIZE(K)] [--freemem-size " "SIZE(K)] [--time] [--load-only] [--utm-ptr 0xPTR] [--retval EXPECTED]\n", @@ -83,6 +83,7 @@ main(int argc, char** argv) { char* eapp_file = argv[1]; char* rt_file = argv[2]; + char* ld_file = argv[3]; int c; int opt_index = 3; @@ -121,7 +122,7 @@ main(int argc, char** argv) { asm volatile("rdcycle %0" : "=r"(cycles1)); } - enclave.init(eapp_file, rt_file, params); + enclave.init(eapp_file, rt_file, ld_file, params); if (self_timing) { asm volatile("rdcycle %0" : "=r"(cycles2)); @@ -133,7 +134,7 @@ main(int argc, char** argv) { asm volatile("rdcycle %0" : "=r"(cycles3)); } - uintptr_t encl_ret; + unsigned long encl_ret; if (!load_only) enclave.run(&encl_ret); if (retval_exist && encl_ret != retval) { diff --git a/fast-setup.sh b/fast-setup.sh new file mode 100755 index 000000000..f010839b3 --- /dev/null +++ b/fast-setup.sh @@ -0,0 +1,10 @@ +git submodule update --init --recursive --depth 1 +echo "please read this file for further instructions" + +### INSTRUCTIONS +# make -j 12 # change 12 to desired parallelism +### find port in command from make, 9821 at the time of writing +# make run +### switch terminals +# scp -i build-generic64/overlay/root/.ssh/id-rsa -P build-generic64/buildroot.build/build/keystone-*/*.ko root@localhost:. +# scp -i build-generic64/overlay/root/.ssh/id-rsa -P build-generic64/buildroot.build/build/keystone-examples-*/*/*.ke root@localhost:. diff --git a/linux-keystone-driver/keystone-enclave.c b/linux-keystone-driver/keystone-enclave.c index 564356660..ee3f7d78c 100644 --- a/linux-keystone-driver/keystone-enclave.c +++ b/linux-keystone-driver/keystone-enclave.c @@ -11,25 +11,6 @@ DEFINE_MUTEX(idr_enclave_lock); #define ENCLAVE_IDR_MIN 0x1000 #define ENCLAVE_IDR_MAX 0xffff -unsigned long calculate_required_pages( - unsigned long eapp_sz, - unsigned long eapp_stack_sz, - unsigned long rt_sz, - unsigned long rt_stack_sz) -{ - unsigned long req_pages = 0; - - req_pages += PAGE_UP(eapp_sz)/PAGE_SIZE; - req_pages += PAGE_UP(eapp_stack_sz)/PAGE_SIZE; - req_pages += PAGE_UP(rt_sz)/PAGE_SIZE; - req_pages += PAGE_UP(rt_stack_sz)/PAGE_SIZE; - - // FIXME: calculate the required number of pages for the page table. - // For now, we must allocate at least 1 (top) + 2 (enclave) + 2 (runtime) pages for pg tables - req_pages += 15; - return req_pages; -} - /* Smart destroy, handles partial initialization of epm and utm etc */ int destroy_enclave(struct enclave* enclave) { diff --git a/linux-keystone-driver/keystone-ioctl.c b/linux-keystone-driver/keystone-ioctl.c index 2d4489390..d743076e8 100644 --- a/linux-keystone-driver/keystone-ioctl.c +++ b/linux-keystone-driver/keystone-ioctl.c @@ -7,6 +7,7 @@ #include "keystone_user.h" #include #include +#include int __keystone_destroy_enclave(unsigned int ueid); @@ -76,7 +77,7 @@ int keystone_finalize_enclave(unsigned long arg) ret = sbi_sm_create_enclave(&create_args); if (ret.error) { - keystone_err("keystone_create_enclave: SBI call failed with error codd %ld\n", ret.error); + keystone_err("keystone_create_enclave: SBI call failed with error code %ld\n", ret.error); goto error_destroy_enclave; } diff --git a/linux-keystone-driver/keystone.h b/linux-keystone-driver/keystone.h index cb54491ae..95deeebe5 100644 --- a/linux-keystone-driver/keystone.h +++ b/linux-keystone-driver/keystone.h @@ -90,13 +90,6 @@ int utm_destroy(struct utm* utm); int utm_init(struct utm* utm, size_t untrusted_size); paddr_t epm_va_to_pa(struct epm* epm, vaddr_t addr); - -unsigned long calculate_required_pages( - unsigned long eapp_sz, - unsigned long eapp_stack_sz, - unsigned long rt_sz, - unsigned long rt_stack_sz); - #define keystone_info(fmt, ...) \ pr_info("keystone_enclave: " fmt, ##__VA_ARGS__) #define keystone_err(fmt, ...) \ diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 58e175401..f8816d257 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -54,11 +54,14 @@ include_directories(include) ## Build recipes ## ################### -add_compile_options(-Wall -Werror -fPIC -fno-builtin -std=c11 -g) +# medany creates PIC w/o a GOT. loader-binary (and thus libs) inherently needs PIC +# because it's in physical addressing; currently doesn't work with Global Offset Table +add_compile_options(-Wall -Werror -fno-builtin -static -mcmodel=medany -std=c11 -g) # Generate all the library targets add_subdirectory(call) add_subdirectory(crypto) +add_subdirectory(loader) add_subdirectory(mm) add_subdirectory(tmplib) add_subdirectory(util) @@ -72,5 +75,6 @@ set_target_properties(rt_linkscript PROPERTIES PREFIX "") set_target_properties(rt_linkscript PROPERTIES OUTPUT_NAME runtime.ld) set_target_properties(rt_linkscript PROPERTIES SUFFIX "") -# Generate final executable +# Generate final executables add_subdirectory(sys) +add_subdirectory(loader-binary) diff --git a/runtime/call/syscall.c b/runtime/call/syscall.c index c181c0392..eed63fb2b 100644 --- a/runtime/call/syscall.c +++ b/runtime/call/syscall.c @@ -185,10 +185,10 @@ void handle_syscall(struct encl_ctx* ctx) break; case(RUNTIME_SYSCALL_GET_SEALING_KEY):; /* Stores the key receive structure */ - uintptr_t buffer_1_pa = kernel_va_to_pa(rt_copy_buffer_1); + uintptr_t buffer_1_pa = translate((uintptr_t) rt_copy_buffer_1); /* Stores the key identifier */ - uintptr_t buffer_2_pa = kernel_va_to_pa(rt_copy_buffer_2); + uintptr_t buffer_2_pa = translate((uintptr_t) rt_copy_buffer_2); if (arg1 > sizeof(rt_copy_buffer_1) || arg3 > sizeof(rt_copy_buffer_2)) { diff --git a/runtime/include/loader/elf.h b/runtime/include/loader/elf.h new file mode 100644 index 000000000..61110709b --- /dev/null +++ b/runtime/include/loader/elf.h @@ -0,0 +1,464 @@ +/* + * Copyright (c) 1999-2004 University of New South Wales + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#pragma once + +#include +#include +#include +#include + +struct elf { + void* elfFile; + size_t elfSize; + unsigned char elfClass; /* 32-bit or 64-bit */ +}; +typedef struct elf elf_t; + +enum elf_addr_type { VIRTUAL, PHYSICAL }; +typedef enum elf_addr_type elf_addr_type_t; + +/* ELF header functions */ +/** + * Initialises an elf_t structure and checks that the ELF file is valid. + * This function must be called to validate the ELF before any other function. + * Otherwise, attempting to call other functions with an invalid ELF file may + * result in undefined behaviour. + * + * @param file ELF file to use + * @param size Size of the ELF file + * @param res elf_t to initialise + * + * \return 0 on success, otherwise < 0 + */ +int +elf_newFile(void* file, size_t size, elf_t* res); + +/** + * Initialises and elf_t structure and checks that the ELF file is valid. + * The validity of a potential ELF file can be determined by the arguments + * check_pht and check_st. + * If both check_pht and check_st are true, this function is equivalent to + * elf_newFile. + * Calling other functions with an invalid ELF file may result in undefined + * behaviour. + * + * @param file ELF file to use + * @param size Size of the ELF file + * @param check_pht Whether to check the ELF program header table is valid + * @param check_st Whether to check the ELF section table is valid + * @param res elf_t to initialise + * + * \return 0 on success, otherwise < 0 + */ +int +elf_newFile_maybe_unsafe( + void* file, size_t size, bool check_pht, bool check_st, elf_t* res); + +/** + * Checks that file starts with the ELF magic number. + * File must be at least 4 bytes (SELFMAG). + * + * @param file to check + * + * \return 0 on success, otherwise < 0 + */ +int +elf_check_magic(char* file); + +/** + * Checks that elfFile points to an ELF file with a valid ELF header. + * + * @param elfFile Potential ELF file to check + * + * \return 0 on success, otherwise < 0 + */ +int +elf_checkFile(elf_t* elfFile); + +/** + * Checks that elfFile points to an ELF file with a valid program header table. + * + * @param elfFile Potential ELF file to check + * + * \return 0 on success, otherwise < 0 + */ +int +elf_checkProgramHeaderTable(elf_t* elfFile); + +/** + * Checks that elfFile points to an ELF file with a valid section table. + * + * @param elfFile Potential ELF file to check + * + * \return 0 on success, otherwise < 0 + */ +int +elf_checkSectionTable(elf_t* elfFile); + +/** + * Find the entry point of an ELF file. + * + * @param elfFile Pointer to a valid ELF structure + * + * \return The entry point address. + */ +uintptr_t +elf_getEntryPoint(elf_t* elfFile); + +/** + * Determine number of program headers in an ELF file. + * + * @param elfFile Pointer to a valid ELF structure. + * + * \return Number of program headers in the ELF file. + */ +size_t +elf_getNumProgramHeaders(elf_t* elfFile); + +/** + * Determine number of sections in an ELF file. + * + * @param elfFile Pointer to a valid ELF structure. + * + * \return Number of sections in the ELF file. + */ +size_t +elf_getNumSections(elf_t* elfFile); + +/** + * Get the index of the section header string table of an ELF file. + * + * @param elf Pointer to a valid ELF structure. + * + * \return The index of the section header string table. + */ +size_t +elf_getSectionStringTableIndex(elf_t* elf); + +/** + * Get a string table section of an ELF file. + * + * @param elfFile Pointer to a valid ELF structure. + * @param string_section The section number of the string table. + * + * \return The string table, or NULL if the section is not a string table. + */ +const char* +elf_getStringTable(elf_t* elfFile, size_t string_segment); + +/** + * Get the string table for section header names. + * + * @param elfFile Pointer to a valid ELF structure. + * + * \return The string table, or NULL if there is no table. + */ +const char* +elf_getSectionStringTable(elf_t* elfFile); + +/* Section header functions */ +/** + * Get a section of an ELF file. + * + * @param elfFile Pointer to a valid ELF structure + * @param i The section number + * + * \return The section, or NULL if there is no section. + */ +void* +elf_getSection(elf_t* elfFile, size_t i); + +/** + * Get the section of an ELF file with a given name. + * + * @param elfFile Pointer to a valid ELF structure + * @param str Name of the section + * @param i Pointer to store the section number + * + * \return The section, or NULL if there is no section. + */ +void* +elf_getSectionNamed(elf_t* elfFile, const char* str, size_t* i); + +/** + * Return the name of a given section. + * + * @param elfFile Pointer to a valid ELF structure + * @param i Index of the section + * + * \return The name of a given section. + */ +const char* +elf_getSectionName(elf_t* elfFile, size_t i); + +/** + * Return the offset to the name of a given section in the section header + * string table. + * + * @param elfFile Pointer to a valid ELF structure + * @param i Index of the section + * + * \return The offset to the name of a given section in the section header + * string table. + */ +size_t +elf_getSectionNameOffset(elf_t* elfFile, size_t i); + +/** + * Return the type of a given section + * + * @param elfFile Pointer to a valid ELF structure + * @param i Index of the section + * + * \return The type of a given section. + */ +uint32_t +elf_getSectionType(elf_t* elfFile, size_t i); + +/** + * Return the flags of a given section + * + * @param elfFile Pointer to a valid ELF structure + * @param i Index of the section + * + * \return The flags of a given section. + */ +size_t +elf_getSectionFlags(elf_t* elfFile, size_t i); + +/** + * Return the address of a given section + * + * @param elfFile Pointer to a valid ELF structure + * @param i Index of the section + * + * \return The address of a given section. + */ +uintptr_t +elf_getSectionAddr(elf_t* elfFile, size_t i); + +/** + * Return the offset of a given section + * + * @param elfFile Pointer to a valid ELF structure + * @param i Index of the section + * + * \return The offset of a given section. + */ +size_t +elf_getSectionOffset(elf_t* elfFile, size_t i); + +/** + * Return the size of a given section + * + * @param elfFile Pointer to a valid ELF structure + * @param i Index of the section + * + * \return The size of a given section. + */ +size_t +elf_getSectionSize(elf_t* elfFile, size_t i); + +/** + * Return the related section index of a given section + * + * @param elfFile Pointer to a valid ELF structure + * @param i Index of the section + * + * \return The related section index of a given section. + */ +uint32_t +elf_getSectionLink(elf_t* elfFile, size_t i); + +/** + * Return extra information of a given section + * + * @param elfFile Pointer to a valid ELF structure + * @param i Index of the section + * + * \return Extra information of a given section. + */ +uint32_t +elf_getSectionInfo(elf_t* elfFile, size_t i); + +/** + * Return the alignment of a given section + * + * @param elfFile Pointer to a valid ELF structure + * @param i Index of the section + * + * \return The alignment of a given section. + */ +size_t +elf_getSectionAddrAlign(elf_t* elfFile, size_t i); + +/** + * Return the entry size of a given section + * + * @param elfFile Pointer to a valid ELF structure + * @param i Index of the section + * + * \return The entry size of a given section. + */ +size_t +elf_getSectionEntrySize(elf_t* elfFile, size_t i); + +/* Program header functions */ + +/** + * Return the segment data for a given program header. + * + * @param elf Pointer to a valid ELF structure + * @param ph Index of the program header + * + * \return Pointer to the segment data + */ +void* +elf_getProgramSegment(elf_t* elf, size_t ph); + +/** + * Return the type for a given program header. + * + * @param elfFile Pointer to a valid ELF structure + * @param ph Index of the program header + * + * \return The type of a given program header. + */ +uint32_t +elf_getProgramHeaderType(elf_t* elfFile, size_t ph); + +/** + * Return the segment offset for a given program header. + * + * @param elfFile Pointer to a valid ELF structure + * @param ph Index of the program header + * + * \return The offset of this program header from the start of the file. + */ +size_t +elf_getProgramHeaderOffset(elf_t* elfFile, size_t ph); + +/** + * Return the base virtual address of given program header. + * + * @param elfFile Pointer to a valid ELF structure + * @param ph Index of the program header + * + * \return The memory size of the specified program header. + */ +uintptr_t +elf_getProgramHeaderVaddr(elf_t* elfFile, size_t ph); + +/** + * Return the base physical address of given program header. + * + * @param elfFile Pointer to a valid ELF structure + * @param ph Index of the program header + * + * \return The memory size of the specified program header. + */ +uintptr_t +elf_getProgramHeaderPaddr(elf_t* elfFile, size_t ph); + +/** + * Return the file size of a given program header. + * + * @param elfFile Pointer to a valid ELF structure + * @param ph Index of the program header + * + * \return The file size of the specified program header. + */ +size_t +elf_getProgramHeaderFileSize(elf_t* elfFile, size_t ph); + +/** + * Return the memory size of a given program header. + * + * @param elfFile Pointer to a valid ELF structure + * @param ph Index of the program header + * + * \return The memory size of the specified program header. + */ +size_t +elf_getProgramHeaderMemorySize(elf_t* elfFile, size_t ph); + +/** + * Return the flags for a given program header. + * + * @param elfFile Pointer to a valid ELF structure + * @param ph Index of the program header + * + * \return The flags of a given program header. + */ +uint32_t +elf_getProgramHeaderFlags(elf_t* elfFile, size_t ph); + +/** + * Return the alignment for a given program header. + * + * @param elfFile Pointer to a valid ELF structure + * @param ph Index of the program header + * + * \return The alignment of the given program header. + */ +size_t +elf_getProgramHeaderAlign(elf_t* elfFile, size_t ph); + +/* Utility functions */ + +/** + * Determine the memory bounds of an ELF file + * + * @param elfFile Pointer to a valid ELF structure + * @param addr_type If PHYSICAL return bounds of physical memory, otherwise + * return bounds of virtual memory + * @param min Pointer to return value of the minimum + * @param max Pointer to return value of the maximum + * + * \return true on success. false on failure, if for example, it is an invalid + * ELF file + */ +int +elf_getMemoryBounds( + elf_t* elfFile, elf_addr_type_t addr_type, uintptr_t* min, uintptr_t* max); + +/** + * + * \return true if the address in in this program header + */ +int +elf_vaddrInProgramHeader(elf_t* elfFile, size_t ph, uintptr_t vaddr); + +/** + * Return the physical translation of a physical address, with respect + * to a given program header + * + */ +uintptr_t +elf_vtopProgramHeader(elf_t* elfFile, size_t ph, uintptr_t vaddr); + +/** + * Load an ELF file into memory + * + * @param elfFile Pointer to a valid ELF file + * @param addr_type If PHYSICAL load using the physical address, otherwise using + * the + * virtual addresses + * + * \return true on success, false on failure. + * + * The function assumes that the ELF file is loaded in memory at some + * address different to the target address at which it will be loaded. + * It also assumes direct access to the source and destination address, i.e: + * Memory must be able to be loaded with a simple memcpy. + * + * Obviously this also means that if we are loading a 64bit ELF on a 32bit + * platform, we assume that any memory addresses are within the first 4GB. + * + */ +int +elf_loadFile(elf_t* elfFile, elf_addr_type_t addr_type); diff --git a/runtime/include/loader/elf32.h b/runtime/include/loader/elf32.h new file mode 100644 index 000000000..b061fa3a2 --- /dev/null +++ b/runtime/include/loader/elf32.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1999-2004 University of New South Wales + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#pragma once + +#include "loader/elf.h" +#include "string.h" +#include + +/* ELF header functions */ +int +elf32_checkFile(elf_t* elf); + +int +elf32_checkProgramHeaderTable(elf_t* elf); + +int +elf32_checkSectionTable(elf_t* elf); + +static inline bool +elf_isElf32(elf_t* elf) { + return elf->elfClass == ELFCLASS32; +} + +static inline Elf32_Ehdr +elf32_getHeader(elf_t* elf) { + return *(Elf32_Ehdr*)elf->elfFile; +} + +static inline uintptr_t +elf32_getEntryPoint(elf_t* elf) { + return elf32_getHeader(elf).e_entry; +} + +static inline Elf32_Phdr* +elf32_getProgramHeaderTable(elf_t* file) { + return (Elf32_Phdr*)((uint8_t*)file->elfFile + elf32_getHeader(file).e_phoff); +} + +static inline Elf32_Shdr* +elf32_getSectionTable(elf_t* elf) { + return (Elf32_Shdr*)((uint8_t*)elf->elfFile + elf32_getHeader(elf).e_shoff); +} + +static inline size_t +elf32_getNumProgramHeaders(elf_t* elf) { + return elf32_getHeader(elf).e_phnum; +} + +static inline size_t +elf32_getNumSections(elf_t* elf) { + return elf32_getHeader(elf).e_shnum; +} + +static inline size_t +elf32_getSectionStringTableIndex(elf_t* elf) { + return elf32_getHeader(elf).e_shstrndx; +} + +/* Section header functions */ +static inline size_t +elf32_getSectionNameOffset(elf_t* elf, size_t s) { + return elf32_getSectionTable(elf)[s].sh_name; +} + +static inline uint32_t +elf32_getSectionType(elf_t* elf, size_t i) { + return elf32_getSectionTable(elf)[i].sh_type; +} + +static inline size_t +elf32_getSectionFlags(elf_t* elf, size_t i) { + return elf32_getSectionTable(elf)[i].sh_flags; +} + +static inline uintptr_t +elf32_getSectionAddr(elf_t* elf, size_t i) { + return elf32_getSectionTable(elf)[i].sh_addr; +} + +static inline size_t +elf32_getSectionOffset(elf_t* elf, size_t i) { + return elf32_getSectionTable(elf)[i].sh_offset; +} + +static inline size_t +elf32_getSectionSize(elf_t* elf, size_t i) { + return elf32_getSectionTable(elf)[i].sh_size; +} + +static inline uint32_t +elf32_getSectionLink(elf_t* elf, size_t i) { + return elf32_getSectionTable(elf)[i].sh_link; +} + +static inline uint32_t +elf32_getSectionInfo(elf_t* elf, size_t i) { + return elf32_getSectionTable(elf)[i].sh_info; +} + +static inline size_t +elf32_getSectionAddrAlign(elf_t* elf, size_t i) { + return elf32_getSectionTable(elf)[i].sh_addralign; +} + +static inline size_t +elf32_getSectionEntrySize(elf_t* elf, size_t i) { + return elf32_getSectionTable(elf)[i].sh_entsize; +} + +/* Program header functions */ +static inline uint32_t +elf32_getProgramHeaderType(elf_t* file, size_t ph) { + return elf32_getProgramHeaderTable(file)[ph].p_type; +} + +static inline size_t +elf32_getProgramHeaderOffset(elf_t* file, size_t ph) { + return elf32_getProgramHeaderTable(file)[ph].p_offset; +} + +static inline uintptr_t +elf32_getProgramHeaderVaddr(elf_t* file, size_t ph) { + return elf32_getProgramHeaderTable(file)[ph].p_vaddr; +} + +static inline uintptr_t +elf32_getProgramHeaderPaddr(elf_t* file, size_t ph) { + return elf32_getProgramHeaderTable(file)[ph].p_paddr; +} + +static inline size_t +elf32_getProgramHeaderFileSize(elf_t* file, size_t ph) { + return elf32_getProgramHeaderTable(file)[ph].p_filesz; +} + +static inline size_t +elf32_getProgramHeaderMemorySize(elf_t* file, size_t ph) { + return elf32_getProgramHeaderTable(file)[ph].p_memsz; +} + +static inline uint32_t +elf32_getProgramHeaderFlags(elf_t* file, size_t ph) { + return elf32_getProgramHeaderTable(file)[ph].p_flags; +} + +static inline size_t +elf32_getProgramHeaderAlign(elf_t* file, size_t ph) { + return elf32_getProgramHeaderTable(file)[ph].p_align; +} diff --git a/runtime/include/loader/elf64.h b/runtime/include/loader/elf64.h new file mode 100644 index 000000000..98b78e12b --- /dev/null +++ b/runtime/include/loader/elf64.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1999-2004 University of New South Wales + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#pragma once + +#include "loader/elf.h" +#include + +/* ELF header functions */ +int +elf64_checkFile(elf_t* elf); + +int +elf64_checkProgramHeaderTable(elf_t* elf); + +int +elf64_checkSectionTable(elf_t* elf); + +static inline bool +elf_isElf64(elf_t* elf) { + return elf->elfClass == ELFCLASS64; +} + +static inline Elf64_Ehdr +elf64_getHeader(elf_t* elf) { + return *(Elf64_Ehdr*)elf->elfFile; +} + +static inline uintptr_t +elf64_getEntryPoint(elf_t* file) { + return elf64_getHeader(file).e_entry; +} + +static inline Elf64_Phdr* +elf64_getProgramHeaderTable(elf_t* file) { + return (Elf64_Phdr*)((uint8_t*)file->elfFile + elf64_getHeader(file).e_phoff); +} + +static inline Elf64_Shdr* +elf64_getSectionTable(elf_t* file) { + return (Elf64_Shdr*)((uint8_t*)file->elfFile + elf64_getHeader(file).e_shoff); +} + +static inline size_t +elf64_getNumProgramHeaders(elf_t* file) { + return elf64_getHeader(file).e_phnum; +} + +static inline size_t +elf64_getNumSections(elf_t* elf) { + return elf64_getHeader(elf).e_shnum; +} + +static inline size_t +elf64_getSectionStringTableIndex(elf_t* elf) { + return elf64_getHeader(elf).e_shstrndx; +} + +/* Section header functions */ +static inline size_t +elf64_getSectionNameOffset(elf_t* elf, size_t s) { + return elf64_getSectionTable(elf)[s].sh_name; +} + +static inline uint32_t +elf64_getSectionType(elf_t* file, size_t s) { + return elf64_getSectionTable(file)[s].sh_type; +} + +static inline size_t +elf64_getSectionFlags(elf_t* file, size_t s) { + return elf64_getSectionTable(file)[s].sh_flags; +} + +static inline uintptr_t +elf64_getSectionAddr(elf_t* elf, size_t i) { + return elf64_getSectionTable(elf)[i].sh_addr; +} + +static inline size_t +elf64_getSectionOffset(elf_t* elf, size_t i) { + return elf64_getSectionTable(elf)[i].sh_offset; +} + +static inline size_t +elf64_getSectionSize(elf_t* elf, size_t i) { + return elf64_getSectionTable(elf)[i].sh_size; +} + +static inline uint32_t +elf64_getSectionLink(elf_t* elf, size_t i) { + return elf64_getSectionTable(elf)[i].sh_link; +} + +static inline uint32_t +elf64_getSectionInfo(elf_t* elf, size_t i) { + return elf64_getSectionTable(elf)[i].sh_info; +} + +static inline size_t +elf64_getSectionAddrAlign(elf_t* elf, size_t i) { + return elf64_getSectionTable(elf)[i].sh_addralign; +} + +static inline size_t +elf64_getSectionEntrySize(elf_t* elf, size_t i) { + return elf64_getSectionTable(elf)[i].sh_entsize; +} + +/* Program header functions */ +static inline uint32_t +elf64_getProgramHeaderType(elf_t* file, size_t ph) { + return elf64_getProgramHeaderTable(file)[ph].p_type; +} + +static inline size_t +elf64_getProgramHeaderOffset(elf_t* file, size_t ph) { + return elf64_getProgramHeaderTable(file)[ph].p_offset; +} + +static inline uintptr_t +elf64_getProgramHeaderVaddr(elf_t* file, size_t ph) { + return elf64_getProgramHeaderTable(file)[ph].p_vaddr; +} + +static inline uintptr_t +elf64_getProgramHeaderPaddr(elf_t* file, size_t ph) { + return elf64_getProgramHeaderTable(file)[ph].p_paddr; +} + +static inline size_t +elf64_getProgramHeaderFileSize(elf_t* file, size_t ph) { + return elf64_getProgramHeaderTable(file)[ph].p_filesz; +} + +static inline size_t +elf64_getProgramHeaderMemorySize(elf_t* file, size_t ph) { + return elf64_getProgramHeaderTable(file)[ph].p_memsz; +} + +static inline uint32_t +elf64_getProgramHeaderFlags(elf_t* file, size_t ph) { + return elf64_getProgramHeaderTable(file)[ph].p_flags; +} + +static inline size_t +elf64_getProgramHeaderAlign(elf_t* file, size_t ph) { + return elf64_getProgramHeaderTable(file)[ph].p_align; +} diff --git a/runtime/include/loader/loader.h b/runtime/include/loader/loader.h new file mode 100644 index 000000000..2d3d19d0b --- /dev/null +++ b/runtime/include/loader/loader.h @@ -0,0 +1,3 @@ +#include "loader/elf.h" + +int loadElf(elf_t* elf, bool user); diff --git a/runtime/include/mm/freemem.h b/runtime/include/mm/freemem.h index 9c88afaad..deb205e42 100644 --- a/runtime/include/mm/freemem.h +++ b/runtime/include/mm/freemem.h @@ -3,6 +3,9 @@ #ifndef __FREEMEM_H__ #define __FREEMEM_H__ +#include +#include + #define NEXT_PAGE(page) *((uintptr_t*)page) #define LIST_EMPTY(list) ((list).count == 0 || (list).head == 0) #define LIST_INIT(list) { (list).count = 0; (list).head = 0; (list).tail = 0; } diff --git a/runtime/include/mm/mm.h b/runtime/include/mm/mm.h index 5ae6b960c..ac2b5c42a 100644 --- a/runtime/include/mm/mm.h +++ b/runtime/include/mm/mm.h @@ -8,6 +8,7 @@ uintptr_t translate(uintptr_t va); pte* pte_of_va(uintptr_t va); #ifdef USE_FREEMEM +uintptr_t map_page(uintptr_t vpn, uintptr_t ppn, int flags); uintptr_t alloc_page(uintptr_t vpn, int flags); uintptr_t realloc_page(uintptr_t vpn, int flags); void free_page(uintptr_t vpn); diff --git a/runtime/include/mm/vm.h b/runtime/include/mm/vm.h index 684b96e6a..a42f31c66 100644 --- a/runtime/include/mm/vm.h +++ b/runtime/include/mm/vm.h @@ -1,38 +1,37 @@ #ifndef __VM_H__ #define __VM_H__ -#include - #include "mm/common.h" #include "util/printf.h" #include "mm/vm_defs.h" -extern void* rt_base; - extern uintptr_t runtime_va_start; -extern uintptr_t kernel_offset; + +/* root page table */ +extern pte* root_page_table; + +uintptr_t kernel_va_to_pa(void* ptr); +uintptr_t __va(uintptr_t pa); +uintptr_t __pa(uintptr_t va); + +#ifndef LOADER_BIN + +extern void* rt_base; +extern uintptr_t kernel_offset; // TODO: is this needed? extern uintptr_t load_pa_start; -/* Eyrie is for Sv39 */ -static inline uintptr_t satp_new(uintptr_t pa) -{ - return (SATP_MODE | (pa >> RISCV_PAGE_BITS)); -} +/* Program break */ +extern uintptr_t program_break; -static inline uintptr_t kernel_va_to_pa(void* ptr) -{ - return (uintptr_t) ptr - kernel_offset; -} +/* freemem */ +extern uintptr_t freemem_va_start; +extern size_t freemem_size; -static inline uintptr_t __va(uintptr_t pa) -{ - return (pa - load_pa_start) + EYRIE_LOAD_START; -} +/* shared buffer */ +extern uintptr_t shared_buffer; +extern uintptr_t shared_buffer_size; -static inline uintptr_t __pa(uintptr_t va) -{ - return (va - EYRIE_LOAD_START) + load_pa_start; -} +#endif static inline pte pte_create(uintptr_t ppn, int type) { @@ -65,25 +64,4 @@ static inline uintptr_t pte_ppn(pte pte) return pte >> PTE_PPN_SHIFT; } -/* root page table */ -extern pte root_page_table[]; -/* page tables for kernel remap */ -extern pte kernel_l2_page_table[]; -extern pte kernel_l3_page_table[]; -/* page tables for loading physical memory */ -extern pte load_l2_page_table[]; -extern pte load_l3_page_table[]; - -/* Program break */ -extern uintptr_t program_break; - -/* freemem */ -extern uintptr_t freemem_va_start; -extern size_t freemem_size; - -/* shared buffer */ -extern uintptr_t shared_buffer; -extern uintptr_t shared_buffer_size; - - #endif diff --git a/runtime/include/mm/vm_defs.h b/runtime/include/mm/vm_defs.h index 1e6710f6e..7bb18bbe8 100644 --- a/runtime/include/mm/vm_defs.h +++ b/runtime/include/mm/vm_defs.h @@ -33,6 +33,7 @@ /* Starting address of the enclave memory */ #if __riscv_xlen == 64 +#define RUNTIME_VA_START 0xffffffffc0000000 #define EYRIE_LOAD_START 0xffffffff00000000 #define EYRIE_PAGING_START 0xffffffff40000000 #define EYRIE_UNTRUSTED_START 0xffffffff80000000 @@ -40,6 +41,7 @@ #define EYRIE_ANON_REGION_START \ 0x0000002000000000 // Arbitrary VA to start looking for large mappings #elif __riscv_xlen == 32 +#define RUNTIME_VA_START 0xc0000000 #define EYRIE_LOAD_START 0xf0000000 #define EYRIE_PAGING_START 0x40000000 #define EYRIE_UNTRUSTED_START 0x80000000 diff --git a/runtime/include/sys/auxvec.h b/runtime/include/sys/auxvec.h new file mode 100644 index 000000000..ed9a1fe9b --- /dev/null +++ b/runtime/include/sys/auxvec.h @@ -0,0 +1,55 @@ +//PARTIAL elf.h from musl-libc +#ifndef _ELF_H_ +#define _ELF_H_ + +#define AT_NULL 0 +#define AT_IGNORE 1 +#define AT_EXECFD 2 +#define AT_PHDR 3 +#define AT_PHENT 4 +#define AT_PHNUM 5 +#define AT_PAGESZ 6 +#define AT_BASE 7 +#define AT_FLAGS 8 +#define AT_ENTRY 9 +#define AT_NOTELF 10 +#define AT_UID 11 +#define AT_EUID 12 +#define AT_GID 13 +#define AT_EGID 14 +#define AT_CLKTCK 17 + + +#define AT_PLATFORM 15 +#define AT_HWCAP 16 + + + + +#define AT_FPUCW 18 + + +#define AT_DCACHEBSIZE 19 +#define AT_ICACHEBSIZE 20 +#define AT_UCACHEBSIZE 21 + + + +#define AT_IGNOREPPC 22 + +#define AT_SECURE 23 + +#define AT_BASE_PLATFORM 24 + +#define AT_RANDOM 25 + +#define AT_HWCAP2 26 + +#define AT_EXECFN 31 + + + +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 + +#endif /* _ELF_H_ */ diff --git a/runtime/loader-binary/CMakeLists.txt b/runtime/loader-binary/CMakeLists.txt new file mode 100644 index 000000000..2e6ff8971 --- /dev/null +++ b/runtime/loader-binary/CMakeLists.txt @@ -0,0 +1,13 @@ + +set(LOADER_SOURCES loader.S loader-binary.c) +set(LOADER_LINK_SCRIPT loader.lds) + +add_executable(loader ${LOADER_SOURCES}) +target_link_libraries(loader rt_call ld_mm rt_util rt_loader) +target_link_options(loader PRIVATE -static -nostdlib -T ${LOADER_LINK_SCRIPT}) + +add_custom_target(loader.bin ALL + DEPENDS loader + COMMAND ${CMAKE_OBJCOPY} -O binary --only-section .text + ${CMAKE_CURRENT_BINARY_DIR}/loader + ${CMAKE_SOURCE_DIR}/loader.bin) diff --git a/runtime/loader-binary/loader-binary.c b/runtime/loader-binary/loader-binary.c new file mode 100644 index 000000000..0c0bd56b2 --- /dev/null +++ b/runtime/loader-binary/loader-binary.c @@ -0,0 +1,91 @@ +#include "loader/loader.h" +#include "mm/vm.h" +#include "mm/mm.h" +#include "mm/common.h" +#include "mm/freemem.h" +#include "util/printf.h" +#include + +/* root page table */ +pte root_page_table_storage[BIT(RISCV_PT_INDEX_BITS)] __attribute__((aligned(RISCV_PAGE_SIZE))); +/* page tables for loading physical memory */ +pte load_l2_page_table_storage[BIT(RISCV_PT_INDEX_BITS)] __attribute__((aligned(RISCV_PAGE_SIZE))); +pte load_l3_page_table_storage[BIT(RISCV_PT_INDEX_BITS)] __attribute__((aligned(RISCV_PAGE_SIZE))); + +uintptr_t free_base_final = 0; + +uintptr_t satp_new(uintptr_t pa) +{ + return (SATP_MODE | (pa >> RISCV_PAGE_BITS)); +} + +void map_physical_memory(uintptr_t dram_base, uintptr_t dram_size) { + uintptr_t ptr = EYRIE_LOAD_START; + /* load address should not override kernel address */ + assert(RISCV_GET_PT_INDEX(ptr, 1) != RISCV_GET_PT_INDEX(RUNTIME_VA_START, 1)); + map_with_reserved_page_table(dram_base, dram_size, + ptr, load_l2_page_table_storage, load_l3_page_table_storage); +} + +int map_untrusted_memory(uintptr_t untrusted_ptr, uintptr_t untrusted_size) { + uintptr_t va = EYRIE_UNTRUSTED_START; + while (va < EYRIE_UNTRUSTED_START + untrusted_size) { + if (!map_page(vpn(va), ppn(untrusted_ptr), PTE_W | PTE_R | PTE_D)) { + return -1; + } + va += RISCV_PAGE_SIZE; + untrusted_ptr += RISCV_PAGE_SIZE; + } + return 0; +} + +int load_runtime(uintptr_t dummy, + uintptr_t dram_base, uintptr_t dram_size, + uintptr_t runtime_base, uintptr_t user_base, + uintptr_t free_base, uintptr_t untrusted_ptr, + uintptr_t untrusted_size) { + int ret = 0; + + root_page_table = root_page_table_storage; + + // initialize freemem + spa_init(free_base, dram_base + dram_size - free_base); + + // validate runtime elf + size_t runtime_size = user_base - runtime_base; + if (((void*) runtime_base == NULL) || (runtime_size <= 0)) { + return -1; + } + + // create runtime elf struct + elf_t runtime_elf; + ret = elf_newFile((void*) runtime_base, runtime_size, &runtime_elf); + if (ret != 0) { + return ret; + } + + // map runtime memory + ret = loadElf(&runtime_elf, 0); + if (ret != 0) { + return ret; + } + + // map enclave physical memory, so that runtime will be able to access all memory + map_physical_memory(dram_base, dram_size); + + // map untrusted memory + ret = map_untrusted_memory(untrusted_ptr, untrusted_size); + if (ret != 0) { + return ret; + } + + free_base_final = dram_base + dram_size - spa_available() * RISCV_PAGE_SIZE; + + return ret; +} + +void error_and_exit() { + printf("[loader] FATAL: failed to load.\n"); + sbi_exit_enclave(-1); +} + diff --git a/runtime/loader-binary/loader.S b/runtime/loader-binary/loader.S new file mode 100644 index 000000000..5908ffa73 --- /dev/null +++ b/runtime/loader-binary/loader.S @@ -0,0 +1,69 @@ +#define __PREPROCESSING__ +#include "mm/vm_defs.h" +#include +#include "util/asm_helpers.h" + +.section .text +_start: + // a1: dram_base + // a2: dram_size + // a3: runtime_base + // a4: user_base + // a5: free_base + // a6: untrusted_ptr + // a7: untrusted_size + + // use designated stack + la sp, _estack + + // save all args to stack + addi sp, sp, -(REGBYTES*7) + STORE a1, 0(sp) + STORE a2, 1*REGBYTES(sp) + STORE a3, 2*REGBYTES(sp) + STORE a4, 3*REGBYTES(sp) + STORE a5, 4*REGBYTES(sp) + STORE a6, 5*REGBYTES(sp) + STORE a7, 6*REGBYTES(sp) + + // call load_runtime + call load_runtime + + // exit if errors + bne a0, zero, exit + + // switch to va and jump to runtime code + li t0, RUNTIME_VA_START + csrw stvec, t0 // store runtime start addresss in stvec + + // construct new satp + // below assembly and fences work on CVA6, for satp specifically. + // FIXME: declutter if possible according to more testing + la a0, root_page_table_storage + li a1, RISCV_PAGE_BITS + li a2, SATP_MODE + srl a0, a0, a1 + or a0, a0, a2 + + // flush TLB's just in case + fence.i + sfence.vma + + // set arguments for eyrie_boot + LOAD a1, 0(sp) + LOAD a2, 1*REGBYTES(sp) + LOAD a3, 2*REGBYTES(sp) + LOAD a4, 3*REGBYTES(sp) + LOAD a5, free_base_final + LOAD a6, 5*REGBYTES(sp) + LOAD a7, 6*REGBYTES(sp) + + // flush TLB's just in case + fence.i + sfence.vma + + csrw satp, a0 // switch to virtual addresssing + sfence.vma + +exit: + call error_and_exit diff --git a/runtime/loader-binary/loader.lds b/runtime/loader-binary/loader.lds new file mode 100644 index 000000000..622d1692b --- /dev/null +++ b/runtime/loader-binary/loader.lds @@ -0,0 +1,29 @@ +OUTPUT_ARCH("riscv") + +ENTRY( _start ) + +PAGE_SIZE = 0x1000; /* TODO: figure out the page size to use here */ +STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0100; + +SECTIONS +{ + .text : + { + PROVIDE( _start = . ); + *(._start); + *(*); + + /* + * Only text section is copied into final loader binary + * Stack is added to text section as temporary stack space for loader + */ + . = ALIGN(8); + PROVIDE ( _sstack = . ); + *(._sstack); + . = . + STACK_SIZE; + . = ALIGN(8); + PROVIDE ( _estack = . ); + *(._estack); + } + +} diff --git a/runtime/loader/CMakeLists.txt b/runtime/loader/CMakeLists.txt new file mode 100644 index 000000000..59e2c388f --- /dev/null +++ b/runtime/loader/CMakeLists.txt @@ -0,0 +1,8 @@ + +set(LOADER_SOURCES elf.c elf32.c elf64.c) + +if(FREEMEM) + list(APPEND LOADER_SOURCES loader.c) +endif() + +add_library(rt_loader ${LOADER_SOURCES}) diff --git a/runtime/loader/elf.c b/runtime/loader/elf.c new file mode 100644 index 000000000..2952247f5 --- /dev/null +++ b/runtime/loader/elf.c @@ -0,0 +1,470 @@ +/* + * Copyright (c) 1999-2004 University of New South Wales + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "loader/elf.h" +#include "loader/elf32.h" +#include "loader/elf64.h" +#include "string.h" +#include "mm/common.h" + +/* ELF header functions */ +int +elf_newFile(void* file, size_t size, elf_t* res) { + debug("Creating new elf file struct\n"); + + return elf_newFile_maybe_unsafe(file, size, true, true, res); +} + +int +elf_newFile_maybe_unsafe( + void* file, size_t size, bool check_pht, bool check_st, elf_t* res) { + elf_t new_file = {.elfFile = file, .elfSize = size}; + + debug("Check elf file\n"); + int status = elf_checkFile(&new_file); + if (status < 0) { + return status; + } + + debug("Check program header\n"); + if (check_pht) { + status = elf_checkProgramHeaderTable(&new_file); + if (status < 0) { + return status; + } + } + + debug("Check section table\n"); + if (check_st) { + status = elf_checkSectionTable(&new_file); + if (status < 0) { + return status; + } + } + + debug("Finished validating elf\n"); + if (res) { + *res = new_file; + } + + return status; +} + +int +elf_check_magic(char* file) { + if (memcmp(file, ELFMAG, SELFMAG) != 0) { + return -1; + } + + return 0; +} + +/* + * Checks that elfFile points to a valid elf file. Returns 0 if the elf + * file is valid, < 0 if invalid. + */ +int +elf_checkFile(elf_t* elfFile) { + int res = elf32_checkFile(elfFile); + if (res == 0) { + return 0; + } + debug("Check elf file 32\n"); + + res = elf64_checkFile(elfFile); + if (res == 0) { + return 0; + } + debug("Check elf file 64\n"); + + return -1; +} + +int +elf_checkProgramHeaderTable(elf_t* elfFile) { + if (elf_isElf32(elfFile)) { + return elf32_checkProgramHeaderTable(elfFile); + } else { + return elf64_checkProgramHeaderTable(elfFile); + } +} + +int +elf_checkSectionTable(elf_t* elfFile) { + if (elf_isElf32(elfFile)) { + return elf32_checkSectionTable(elfFile); + } else { + return elf64_checkSectionTable(elfFile); + } +} + +uintptr_t +elf_getEntryPoint(elf_t* elfFile) { + if (elf_isElf32(elfFile)) { + return elf32_getEntryPoint(elfFile); + } else { + return elf64_getEntryPoint(elfFile); + } +} + +size_t +elf_getNumProgramHeaders(elf_t* elfFile) { + if (elf_isElf32(elfFile)) { + return elf32_getNumProgramHeaders(elfFile); + } else { + return elf64_getNumProgramHeaders(elfFile); + } +} + +size_t +elf_getNumSections(elf_t* elfFile) { + if (elf_isElf32(elfFile)) { + return elf32_getNumSections(elfFile); + } else { + return elf64_getNumSections(elfFile); + } +} + +size_t +elf_getSectionStringTableIndex(elf_t* elf) { + if (elf_isElf32(elf)) { + return elf32_getSectionStringTableIndex(elf); + } else { + return elf64_getSectionStringTableIndex(elf); + } +} + +const char* +elf_getStringTable(elf_t* elf, size_t string_segment) { + const char* string_table = (const char*)elf_getSection(elf, string_segment); + if (string_table == NULL) { + return NULL; /* no such section */ + } + + if (elf_getSectionType(elf, string_segment) != SHT_STRTAB) { + return NULL; /* not a string table */ + } + + size_t size = elf_getSectionSize(elf, string_segment); + if (string_table[size - 1] != 0) { + return NULL; /* string table is not null-terminated */ + } + + return string_table; +} + +const char* +elf_getSectionStringTable(elf_t* elf) { + size_t index = elf_getSectionStringTableIndex(elf); + return elf_getStringTable(elf, index); +} + +/* Section header functions */ +void* +elf_getSection(elf_t* elf, size_t i) { + if (i == 0 || i >= elf_getNumSections(elf)) { + return NULL; /* no such section */ + } + + size_t section_offset = elf_getSectionOffset(elf, i); + size_t section_size = elf_getSectionSize(elf, i); + if (section_size == 0) { + return NULL; /* section is empty */ + } + + size_t section_end = section_offset + section_size; + /* possible wraparound - check that section end is not before section start */ + if (section_end > elf->elfSize || section_end < section_offset) { + return NULL; + } + + return (uint8_t*)elf->elfFile + section_offset; +} + +void* +elf_getSectionNamed(elf_t* elfFile, const char* str, size_t* id) { + size_t numSections = elf_getNumSections(elfFile); + for (size_t i = 0; i < numSections; i++) { + if (strcmp(str, elf_getSectionName(elfFile, i)) == 0) { + if (id != NULL) { + *id = i; + } + return elf_getSection(elfFile, i); + } + } + return NULL; +} + +const char* +elf_getSectionName(elf_t* elf, size_t i) { + size_t str_table_idx = elf_getSectionStringTableIndex(elf); + const char* str_table = elf_getStringTable(elf, str_table_idx); + size_t offset = elf_getSectionNameOffset(elf, i); + size_t size = elf_getSectionSize(elf, str_table_idx); + + if (str_table == NULL || offset > size) { + return ""; + } + + return str_table + offset; +} + +size_t +elf_getSectionNameOffset(elf_t* elfFile, size_t i) { + if (elf_isElf32(elfFile)) { + return elf32_getSectionNameOffset(elfFile, i); + } else { + return elf64_getSectionNameOffset(elfFile, i); + } +} + +uint32_t +elf_getSectionType(elf_t* elfFile, size_t i) { + if (elf_isElf32(elfFile)) { + return elf32_getSectionType(elfFile, i); + } else { + return elf64_getSectionType(elfFile, i); + } +} + +size_t +elf_getSectionFlags(elf_t* elfFile, size_t i) { + if (elf_isElf32(elfFile)) { + return elf32_getSectionFlags(elfFile, i); + } else { + return elf64_getSectionFlags(elfFile, i); + } +} + +uintptr_t +elf_getSectionAddr(elf_t* elfFile, size_t i) { + if (elf_isElf32(elfFile)) { + return elf32_getSectionAddr(elfFile, i); + } else { + return elf64_getSectionAddr(elfFile, i); + } +} + +size_t +elf_getSectionOffset(elf_t* elfFile, size_t i) { + if (elf_isElf32(elfFile)) { + return elf32_getSectionOffset(elfFile, i); + } else { + return elf64_getSectionOffset(elfFile, i); + } +} + +size_t +elf_getSectionSize(elf_t* elfFile, size_t i) { + if (elf_isElf32(elfFile)) { + return elf32_getSectionSize(elfFile, i); + } else { + return elf64_getSectionSize(elfFile, i); + } +} + +uint32_t +elf_getSectionLink(elf_t* elfFile, size_t i) { + if (elf_isElf32(elfFile)) { + return elf32_getSectionLink(elfFile, i); + } else { + return elf64_getSectionLink(elfFile, i); + } +} + +uint32_t +elf_getSectionInfo(elf_t* elfFile, size_t i) { + if (elf_isElf32(elfFile)) { + return elf32_getSectionInfo(elfFile, i); + } else { + return elf64_getSectionInfo(elfFile, i); + } +} + +size_t +elf_getSectionAddrAlign(elf_t* elfFile, size_t i) { + if (elf_isElf32(elfFile)) { + return elf32_getSectionAddrAlign(elfFile, i); + } else { + return elf64_getSectionAddrAlign(elfFile, i); + } +} + +size_t +elf_getSectionEntrySize(elf_t* elfFile, size_t i) { + if (elf_isElf32(elfFile)) { + return elf32_getSectionEntrySize(elfFile, i); + } else { + return elf64_getSectionEntrySize(elfFile, i); + } +} + +/* Program headers function */ +void* +elf_getProgramSegment(elf_t* elf, size_t ph) { + size_t offset = elf_getProgramHeaderOffset(elf, ph); + size_t file_size = elf_getProgramHeaderFileSize(elf, ph); + size_t segment_end = offset + file_size; + /* possible wraparound - check that segment end is not before segment start */ + if (elf->elfSize < segment_end || segment_end < offset) { + return NULL; + } + + return (uint8_t*)elf->elfFile + offset; +} + +uint32_t +elf_getProgramHeaderType(elf_t* elfFile, size_t ph) { + if (elf_isElf32(elfFile)) { + return elf32_getProgramHeaderType(elfFile, ph); + } else { + return elf64_getProgramHeaderType(elfFile, ph); + } +} + +size_t +elf_getProgramHeaderOffset(elf_t* elfFile, size_t ph) { + if (elf_isElf32(elfFile)) { + return elf32_getProgramHeaderOffset(elfFile, ph); + } else { + return elf64_getProgramHeaderOffset(elfFile, ph); + } +} + +uintptr_t +elf_getProgramHeaderVaddr(elf_t* elfFile, size_t ph) { + if (elf_isElf32(elfFile)) { + return elf32_getProgramHeaderVaddr(elfFile, ph); + } else { + return elf64_getProgramHeaderVaddr(elfFile, ph); + } +} + +uintptr_t +elf_getProgramHeaderPaddr(elf_t* elfFile, size_t ph) { + if (elf_isElf32(elfFile)) { + return elf32_getProgramHeaderPaddr(elfFile, ph); + } else { + return elf64_getProgramHeaderPaddr(elfFile, ph); + } +} + +size_t +elf_getProgramHeaderFileSize(elf_t* elfFile, size_t ph) { + if (elf_isElf32(elfFile)) { + return elf32_getProgramHeaderFileSize(elfFile, ph); + } else { + return elf64_getProgramHeaderFileSize(elfFile, ph); + } +} + +size_t +elf_getProgramHeaderMemorySize(elf_t* elfFile, size_t ph) { + if (elf_isElf32(elfFile)) { + return elf32_getProgramHeaderMemorySize(elfFile, ph); + } else { + return elf64_getProgramHeaderMemorySize(elfFile, ph); + } +} + +uint32_t +elf_getProgramHeaderFlags(elf_t* elfFile, size_t ph) { + if (elf_isElf32(elfFile)) { + return elf32_getProgramHeaderFlags(elfFile, ph); + } else { + return elf64_getProgramHeaderFlags(elfFile, ph); + } +} + +size_t +elf_getProgramHeaderAlign(elf_t* elfFile, size_t ph) { + if (elf_isElf32(elfFile)) { + return elf32_getProgramHeaderAlign(elfFile, ph); + } else { + return elf64_getProgramHeaderAlign(elfFile, ph); + } +} + +/* Utility functions */ +int +elf_getMemoryBounds( + elf_t* elfFile, elf_addr_type_t addr_type, uintptr_t* min, uintptr_t* max) { + uintptr_t mem_min = UINTPTR_MAX; + uintptr_t mem_max = 0; + size_t i; + + for (i = 0; i < elf_getNumProgramHeaders(elfFile); i++) { + uintptr_t sect_min, sect_max; + + if (elf_getProgramHeaderMemorySize(elfFile, i) == 0) { + continue; + } + + if (addr_type == PHYSICAL) { + sect_min = elf_getProgramHeaderPaddr(elfFile, i); + } else { + sect_min = elf_getProgramHeaderVaddr(elfFile, i); + } + + sect_max = sect_min + elf_getProgramHeaderMemorySize(elfFile, i); + + if (sect_max > mem_max) { + mem_max = sect_max; + } + if (sect_min < mem_min) { + mem_min = sect_min; + } + } + *min = mem_min; + *max = mem_max; + + return 1; +} + +int +elf_vaddrInProgramHeader(elf_t* elfFile, size_t ph, uintptr_t vaddr) { + uintptr_t min = elf_getProgramHeaderVaddr(elfFile, ph); + uintptr_t max = min + elf_getProgramHeaderMemorySize(elfFile, ph); + if (vaddr >= min && vaddr < max) { + return 1; + } else { + return 0; + } +} + +uintptr_t +elf_vtopProgramHeader(elf_t* elfFile, size_t ph, uintptr_t vaddr) { + uintptr_t ph_phys = elf_getProgramHeaderPaddr(elfFile, ph); + uintptr_t ph_virt = elf_getProgramHeaderVaddr(elfFile, ph); + uintptr_t paddr; + + paddr = vaddr - ph_virt + ph_phys; + + return paddr; +} + +int +elf_loadFile(elf_t* elf, elf_addr_type_t addr_type) { + size_t i; + + for (i = 0; i < elf_getNumProgramHeaders(elf); i++) { + /* Load that section */ + uintptr_t dest, src; + size_t len; + if (addr_type == PHYSICAL) { + dest = elf_getProgramHeaderPaddr(elf, i); + } else { + dest = elf_getProgramHeaderVaddr(elf, i); + } + len = elf_getProgramHeaderFileSize(elf, i); + src = (uintptr_t)elf->elfFile + elf_getProgramHeaderOffset(elf, i); + memcpy((void*)dest, (void*)src, len); + dest += len; + memset((void*)dest, 0, elf_getProgramHeaderMemorySize(elf, i) - len); + } + + return 1; +} diff --git a/runtime/loader/elf32.c b/runtime/loader/elf32.c new file mode 100644 index 000000000..5353a7b10 --- /dev/null +++ b/runtime/loader/elf32.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1999-2004 University of New South Wales + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "loader/elf.h" +#include "loader/elf32.h" +#include +#include "string.h" + +/* ELF header functions */ +int +elf32_checkFile(elf_t* elf) { + if (elf->elfSize < sizeof(Elf32_Ehdr)) { + return -1; /* file smaller than ELF header */ + } + + if (elf_check_magic((char*)elf->elfFile) < 0) { + return -1; /* not an ELF file */ + } + + Elf32_Ehdr* header = (Elf32_Ehdr*)elf->elfFile; + if (header->e_ident[EI_CLASS] != ELFCLASS32) { + return -1; /* not a 32-bit ELF */ + } + + if (header->e_phentsize != sizeof(Elf32_Phdr)) { + return -1; /* unexpected program header size */ + } + + if (header->e_shentsize != sizeof(Elf32_Shdr)) { + return -1; /* unexpected section header size */ + } + + if (header->e_shstrndx >= header->e_shnum) { + return -1; /* invalid section header string table section */ + } + + elf->elfClass = header->e_ident[EI_CLASS]; + return 0; /* elf header looks OK */ +} + +int +elf32_checkProgramHeaderTable(elf_t* elf) { + Elf32_Ehdr* header = (Elf32_Ehdr*)elf->elfFile; + size_t ph_end = header->e_phoff + header->e_phentsize * header->e_phnum; + if (elf->elfSize < ph_end || ph_end < header->e_phoff) { + return -1; /* invalid program header table */ + } + + return 0; +} + +int +elf32_checkSectionTable(elf_t* elf) { + Elf32_Ehdr* header = (Elf32_Ehdr*)elf->elfFile; + size_t sh_end = header->e_shoff + header->e_shentsize * header->e_shnum; + if (elf->elfSize < sh_end || sh_end < header->e_shoff) { + return -1; /* invalid section header table */ + } + + return 0; +} diff --git a/runtime/loader/elf64.c b/runtime/loader/elf64.c new file mode 100644 index 000000000..2382430ef --- /dev/null +++ b/runtime/loader/elf64.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1999-2004 University of New South Wales + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "loader/elf.h" +#include "loader/elf64.h" +#include "string.h" +#include + +/* ELF header functions */ +int +elf64_checkFile(elf_t* elf) { + if (sizeof(uintptr_t) != sizeof(uint64_t)) { + return -1; /* not supported on 32-bit architecture */ + } + + if (elf->elfSize < sizeof(Elf64_Ehdr)) { + return -1; /* file smaller than ELF header */ + } + + if (elf_check_magic((char*)elf->elfFile) < 0) { + return -1; /* not an ELF file */ + } + + Elf64_Ehdr* header = (Elf64_Ehdr*)elf->elfFile; + if (header->e_ident[EI_CLASS] != ELFCLASS64) { + return -1; /* not a 64-bit ELF */ + } + + if (header->e_phentsize != sizeof(Elf64_Phdr)) { + return -1; /* unexpected program header size */ + } + + if (header->e_shentsize != sizeof(Elf64_Shdr)) { + return -1; /* unexpected section header size */ + } + + if (header->e_shstrndx >= header->e_shnum) { + return -1; /* invalid section header string table section */ + } + + elf->elfClass = header->e_ident[EI_CLASS]; + return 0; /* elf header looks OK */ +} + +int +elf64_checkProgramHeaderTable(elf_t* elf) { + Elf64_Ehdr* header = (Elf64_Ehdr*)elf->elfFile; + size_t ph_end = header->e_phoff + header->e_phentsize * header->e_phnum; + if (elf->elfSize < ph_end || ph_end < header->e_phoff) { + return -1; /* invalid program header table */ + } + + return 0; +} + +int +elf64_checkSectionTable(elf_t* elf) { + Elf64_Ehdr* header = (Elf64_Ehdr*)elf->elfFile; + size_t sh_end = header->e_shoff + header->e_shentsize * header->e_shnum; + if (elf->elfSize < sh_end || sh_end < header->e_shoff) { + return -1; /* invalid section header table */ + } + + return 0; +} diff --git a/runtime/loader/loader.c b/runtime/loader/loader.c new file mode 100644 index 000000000..f65a3aee0 --- /dev/null +++ b/runtime/loader/loader.c @@ -0,0 +1,94 @@ +#include "loader/loader.h" +#include "loader/elf.h" +#include "string.h" +#include "mm/mm.h" +#include "mm/common.h" +#include "mm/vm_defs.h" +#include "mm/vm.h" + +static inline int pt_mode_from_elf(int elf_pt_mode) { + return + (((elf_pt_mode & PF_X) > 0) * PTE_X) | + (((elf_pt_mode & PF_W) > 0) * (PTE_W | PTE_R | PTE_D)) | + (((elf_pt_mode & PF_R) > 0) * PTE_R) + ; +} + +int loadElf(elf_t* elf, bool user) { + for (unsigned int i = 0; i < elf_getNumProgramHeaders(elf); i++) { + if (elf_getProgramHeaderType(elf, i) != PT_LOAD) { + continue; + } + + uintptr_t start = elf_getProgramHeaderVaddr(elf, i); + uintptr_t file_end = start + elf_getProgramHeaderFileSize(elf, i); + uintptr_t memory_end = start + elf_getProgramHeaderMemorySize(elf, i); + char* src = (char*)(elf_getProgramSegment(elf, i)); + uintptr_t va = start; + int pt_mode = pt_mode_from_elf(elf_getProgramHeaderFlags(elf, i)); + pt_mode |= (user > 0) * PTE_U; + + /* va is not page-aligned, so it doesn't own some of the page. Page may already be mapped. */ + if (RISCV_PAGE_OFFSET(va)) { + if (RISCV_PAGE_OFFSET(va) != RISCV_PAGE_OFFSET((uintptr_t) src)) { + printf("loadElf: va and src are misaligned"); + return -1; + } + uintptr_t new_page = alloc_page(vpn(va), pt_mode); + if (!new_page) + return -1; + memcpy((void *) (new_page + RISCV_PAGE_OFFSET(va)), src, RISCV_PAGE_SIZE - RISCV_PAGE_OFFSET(va)); + va = PAGE_DOWN(va) + RISCV_PAGE_SIZE; + src = (char *) (PAGE_DOWN((uintptr_t) src) + RISCV_PAGE_SIZE); + } + + /* first load all pages that do not include .bss segment */ + while (va + RISCV_PAGE_SIZE <= file_end) { + uintptr_t src_pa = __pa((uintptr_t) src); + if (!map_page(vpn(va), ppn(src_pa), pt_mode)) + return -1; + src += RISCV_PAGE_SIZE; + va += RISCV_PAGE_SIZE; + } + + /* load the .bss segments */ + while (va < memory_end) { + uintptr_t new_page = alloc_page(vpn(va), pt_mode); + if (!new_page) + return -1; + /* copy over non .bss part of the page if it's a part of the page */ + if (va < file_end) { + memcpy((void*) new_page, src, file_end - va); + } + va += RISCV_PAGE_SIZE; + } + } + + return 0; +} + +// assumes beginning and next file are page-aligned +static inline void freeUnusedElf(elf_t* elf) { + assert(false); // TODO: needs free to be implemented properly + for (unsigned int i = 0; i < elf_getNumProgramHeaders(elf); i++) { + uintptr_t start = elf_getProgramHeaderVaddr(elf, i); + uintptr_t file_end = start + elf_getProgramHeaderFileSize(elf, i); + uintptr_t src = (uintptr_t) elf_getProgramSegment(elf, i); + + if (elf_getProgramHeaderType(elf, i) != PT_LOAD) { + uintptr_t src_end = file_end - start + src; + for (; src < src_end; src += RISCV_PAGE_SIZE) { + // free_page(vpn(src)); + } + continue; + } + + if (RISCV_PAGE_OFFSET(start)) { + // free_page(vpn(start)); + } + + if (RISCV_PAGE_OFFSET(file_end)) { + // free_page(vpn(file_end)); + } + } +} diff --git a/runtime/mm/CMakeLists.txt b/runtime/mm/CMakeLists.txt index 5ba56cf76..3f9550e7a 100644 --- a/runtime/mm/CMakeLists.txt +++ b/runtime/mm/CMakeLists.txt @@ -9,4 +9,8 @@ if(PAGING) list(APPEND MM_SOURCES paging.c) endif() -add_library(rt_mm ${MM_SOURCES}) \ No newline at end of file +add_library(rt_mm ${MM_SOURCES}) + +set(LD_MM_SOURCES vm.c freemem_ld.c mm.c) +add_library(ld_mm ${LD_MM_SOURCES}) +target_compile_options(ld_mm PUBLIC -DLOADER_BIN -DUSE_FREEMEM) diff --git a/runtime/mm/freemem_ld.c b/runtime/mm/freemem_ld.c new file mode 100644 index 000000000..5cf98a809 --- /dev/null +++ b/runtime/mm/freemem_ld.c @@ -0,0 +1,43 @@ +#ifdef USE_FREEMEM +#include "mm/freemem.h" +#include "mm/common.h" +#include "mm/vm_defs.h" +#include "util/string.h" + +static uintptr_t freeBase; +static uintptr_t freeEnd; + +void spa_init(uintptr_t base, size_t size) +{ + freeBase = base; + freeEnd = freeBase + size; +} + +uintptr_t spa_get() +{ + return spa_get_zero(); // not allowed, so change to safe +} + +uintptr_t spa_get_zero() +{ + if (freeBase >= freeEnd) { + return 0; + } + uintptr_t new_page = freeBase; + memset((void *) new_page, 0, RISCV_PAGE_SIZE); + + freeBase += RISCV_PAGE_SIZE; + return new_page; +} + +void spa_put(uintptr_t page) +{ + assert(false); // not implemented +} + +unsigned int spa_available() +{ + return (freeEnd - freeBase) / RISCV_PAGE_SIZE; +} + +#endif diff --git a/runtime/mm/mm.c b/runtime/mm/mm.c index 85052d809..cefe1bef3 100644 --- a/runtime/mm/mm.c +++ b/runtime/mm/mm.c @@ -1,7 +1,6 @@ -#include "util/rt_util.h" #include "mm/common.h" -#include "call/syscall.h" #include "mm/mm.h" +#include "mm/vm.h" #include "mm/freemem.h" #include "mm/paging.h" @@ -14,11 +13,13 @@ __walk_create(pte* root, uintptr_t addr); /* Hacky storage of current u-mode break */ static uintptr_t current_program_break; -uintptr_t get_program_break(){ +uintptr_t get_program_break() +{ return current_program_break; } -void set_program_break(uintptr_t new_break){ +void set_program_break(uintptr_t new_break) +{ current_program_break = new_break; } @@ -67,6 +68,20 @@ __walk_create(pte* root, uintptr_t addr) return __walk_internal(root, addr, 1); } +/* Create a virtual memory mapping between a physical and virtual page */ +uintptr_t +map_page(uintptr_t vpn, uintptr_t ppn, int flags) +{ + pte* pte = __walk_create(root_page_table, vpn << RISCV_PAGE_BITS); + + // TODO: what is supposed to happen if page is already allocated? + if (*pte & PTE_V) { + return -1; + } + + *pte = pte_create(ppn, PTE_D | PTE_A | PTE_V | flags); + return 1; +} /* allocate a new page to a given vpn * returns VA of the page, (returns 0 if fails) */ @@ -76,8 +91,6 @@ alloc_page(uintptr_t vpn, int flags) uintptr_t page; pte* pte = __walk_create(root_page_table, vpn << RISCV_PAGE_BITS); - assert(flags & PTE_U); - if (!pte) return 0; @@ -90,7 +103,7 @@ alloc_page(uintptr_t vpn, int flags) page = spa_get_zero(); assert(page); - *pte = pte_create(ppn(__pa(page)), flags | PTE_V); + *pte = pte_create(ppn(__pa(page)), PTE_D | PTE_A | PTE_V | flags); #ifdef USE_PAGING paging_inc_user_page(); #endif @@ -116,7 +129,8 @@ realloc_page(uintptr_t vpn, int flags) } void -free_page(uintptr_t vpn){ +free_page(uintptr_t vpn) +{ pte* pte = __walk(root_page_table, vpn << RISCV_PAGE_BITS); diff --git a/runtime/mm/vm.c b/runtime/mm/vm.c index 2da8b1d57..589565163 100644 --- a/runtime/mm/vm.c +++ b/runtime/mm/vm.c @@ -1,18 +1,49 @@ +#include +#include #include "mm/vm.h" uintptr_t runtime_va_start; -uintptr_t kernel_offset; -uintptr_t load_pa_start; -#ifdef USE_FREEMEM /* root page table */ -pte root_page_table[BIT(RISCV_PT_INDEX_BITS)] __attribute__((aligned(RISCV_PAGE_SIZE))); -/* page tables for kernel remap */ -pte kernel_l2_page_table[BIT(RISCV_PT_INDEX_BITS)] __attribute__((aligned(RISCV_PAGE_SIZE))); -pte kernel_l3_page_table[BIT(RISCV_PT_INDEX_BITS)] __attribute__((aligned(RISCV_PAGE_SIZE))); -/* page tables for loading physical memory */ -pte load_l2_page_table[BIT(RISCV_PT_INDEX_BITS)] __attribute__((aligned(RISCV_PAGE_SIZE))); -pte load_l3_page_table[BIT(RISCV_PT_INDEX_BITS)] __attribute__((aligned(RISCV_PAGE_SIZE))); +pte* root_page_table; + +#ifdef LOADER_BIN + +/* no-ops */ + +uintptr_t kernel_va_to_pa(void* ptr) +{ + return (uintptr_t) ptr; +} + +uintptr_t __va(uintptr_t pa) +{ + return pa; +} + +uintptr_t __pa(uintptr_t va) +{ + return va; +} + +#else // !LOADER_BIN + +uintptr_t kernel_va_to_pa(void* ptr) +{ + return (uintptr_t) ptr - kernel_offset; +} + +uintptr_t __va(uintptr_t pa) +{ + return (pa - load_pa_start) + EYRIE_LOAD_START; +} + +uintptr_t __pa(uintptr_t va) +{ + return (va - EYRIE_LOAD_START) + load_pa_start; +} + +#ifdef USE_FREEMEM /* Program break */ uintptr_t program_break; @@ -26,4 +57,9 @@ size_t freemem_size; uintptr_t shared_buffer; uintptr_t shared_buffer_size; +uintptr_t kernel_offset; +uintptr_t load_pa_start; + +#endif // LOADER_BIN + diff --git a/runtime/sys/CMakeLists.txt b/runtime/sys/CMakeLists.txt index 12615ec78..54d445d83 100644 --- a/runtime/sys/CMakeLists.txt +++ b/runtime/sys/CMakeLists.txt @@ -6,7 +6,7 @@ add_executable(eyrie-build EXCLUDE_FROM_ALL ${SYS_SOURCES}) # required by one library are defined by the time that it is added to this list target_link_libraries(eyrie-build - rt_call rt_mm rt_crypto rt_tmplib rt_util + rt_call rt_mm rt_crypto rt_tmplib rt_util rt_loader gcc ${KEYSTONE_SDK_DIR}/lib/libkeystone-edge.a) target_link_options(eyrie-build PRIVATE -static -nostdlib -T $) add_dependencies(eyrie-build rt_linkscript) diff --git a/runtime/sys/boot.c b/runtime/sys/boot.c index 6f6932dd0..20b4020d3 100644 --- a/runtime/sys/boot.c +++ b/runtime/sys/boot.c @@ -10,6 +10,8 @@ #include "mm/mm.h" #include "sys/env.h" #include "mm/paging.h" +#include "loader/elf.h" +#include "loader/loader.h" /* defined in vm.h */ extern uintptr_t shared_buffer; @@ -24,51 +26,28 @@ extern void* encl_trap_handler; #ifdef USE_FREEMEM +int verify_and_load_elf_file(uintptr_t ptr, size_t file_size, bool is_eapp) { + int ret = 0; + // validate elf + if (((void*) ptr == NULL) || (file_size <= 0)) { + return -1; + } + + // create elf struct + elf_t elf_file; + ret = elf_newFile((void*) ptr, file_size, &elf_file); + if (ret < 0) { + return ret; + } -/* map entire enclave physical memory so that - * we can access the old page table and free memory */ -/* remap runtime kernel to a new root page table */ -void -map_physical_memory(uintptr_t dram_base, - uintptr_t dram_size) -{ - uintptr_t ptr = EYRIE_LOAD_START; - /* load address should not override kernel address */ - assert(RISCV_GET_PT_INDEX(ptr, 1) != RISCV_GET_PT_INDEX(runtime_va_start, 1)); - map_with_reserved_page_table(dram_base, dram_size, - ptr, load_l2_page_table, load_l3_page_table); -} - -void -remap_kernel_space(uintptr_t runtime_base, - uintptr_t runtime_size) -{ - /* eyrie runtime is supposed to be smaller than a megapage */ - - #if __riscv_xlen == 64 - assert(runtime_size <= RISCV_GET_LVL_PGSIZE(2)); - #elif __riscv_xlen == 32 - assert(runtime_size <= RISCV_GET_LVL_PGSIZE(1)); - #endif - - map_with_reserved_page_table(runtime_base, runtime_size, - runtime_va_start, kernel_l2_page_table, kernel_l3_page_table); -} + // parse and load elf file + ret = loadElf(&elf_file, 1); -void -copy_root_page_table() -{ - /* the old table lives in the first page */ - pte* old_root_page_table = (pte*) EYRIE_LOAD_START; - int i; - - /* copy all valid entries of the old root page table */ - for (i = 0; i < BIT(RISCV_PT_INDEX_BITS); i++) { - if (old_root_page_table[i] & PTE_V && - !(root_page_table[i] & PTE_V)) { - root_page_table[i] = old_root_page_table[i]; - } + if (is_eapp) { // setup entry point + uintptr_t entry = elf_getEntryPoint(&elf_file); + csr_write(sepc, entry); } + return ret; } /* initialize free memory with a simple page allocator*/ @@ -119,32 +98,35 @@ eyrie_boot(uintptr_t dummy, // $a0 contains the return value from the SBI { /* set initial values */ load_pa_start = dram_base; - shared_buffer = utm_vaddr; + root_page_table = (pte*) __va(csr_read(satp) << RISCV_PAGE_BITS); + shared_buffer = EYRIE_UNTRUSTED_START; shared_buffer_size = utm_size; runtime_va_start = (uintptr_t) &rt_base; kernel_offset = runtime_va_start - runtime_paddr; + debug("ROOT PAGE TABLE: 0x%lx", root_page_table); debug("UTM : 0x%lx-0x%lx (%u KB)", utm_vaddr, utm_vaddr+utm_size, utm_size/1024); debug("DRAM: 0x%lx-0x%lx (%u KB)", dram_base, dram_base + dram_size, dram_size/1024); + debug("USER: 0x%lx-0x%lx (%u KB)", user_paddr, free_paddr, (free_paddr-user_paddr)/1024); + + /* set trap vector */ + csr_write(stvec, &encl_trap_handler); #ifdef USE_FREEMEM freemem_va_start = __va(free_paddr); freemem_size = dram_base + dram_size - free_paddr; debug("FREE: 0x%lx-0x%lx (%u KB), va 0x%lx", free_paddr, dram_base + dram_size, freemem_size/1024, freemem_va_start); - /* remap kernel VA */ - remap_kernel_space(runtime_paddr, user_paddr - runtime_paddr); - map_physical_memory(dram_base, dram_size); - - /* switch to the new page table */ - csr_write(satp, satp_new(kernel_va_to_pa(root_page_table))); - - /* copy valid entries from the old page table */ - copy_root_page_table(); - /* initialize free memory */ init_freemem(); + /* load eapp elf */ + assert(!verify_and_load_elf_file(__va(user_paddr), free_paddr-user_paddr, true)); + + /* free leaking memory */ + // TODO: clean up after loader -- entire file no longer needed + // TODO: load elf file doesn't map some pages; those can be re-used. runtime and eapp. + //TODO: This should be set by walking the userspace vm and finding //highest used addr. Instead we start partway through the anon space set_program_break(EYRIE_ANON_REGION_START + (1024 * 1024 * 1024)); @@ -157,9 +139,6 @@ eyrie_boot(uintptr_t dummy, // $a0 contains the return value from the SBI /* initialize user stack */ init_user_stack_and_env((ELF(Ehdr) *) __va(user_paddr)); - /* set trap vector */ - csr_write(stvec, &encl_trap_handler); - /* prepare edge & system calls */ init_edge_internals(); diff --git a/runtime/sys/entry.S b/runtime/sys/entry.S index 337fa8583..a21e1a676 100644 --- a/runtime/sys/entry.S +++ b/runtime/sys/entry.S @@ -108,16 +108,24 @@ .endm _start: + /* set up runtime stack */ la sp, kernel_stack_end /* set sscratch zero so that the trap handler can * notice that the trap is from S-mode */ csrw sscratch, x0 + sfence.vma jal eyrie_boot + sfence.vma + + /* set spp to user */ + li t0, 0x100 + csrrc x0, sstatus, t0 /* start running enclave */ csrrw sp, sscratch, sp + li a0, 0 // passed as rtld_fini to entry point/ __libc_start_main sret .align 6 diff --git a/runtime/sys/env.c b/runtime/sys/env.c index a39669707..7bc939892 100644 --- a/runtime/sys/env.c +++ b/runtime/sys/env.c @@ -1,4 +1,5 @@ #include "sys/env.h" +#include "sys/auxvec.h" #include "uaccess.h" #include "util/rt_util.h" #include "util/string.h" diff --git a/sdk/include/host/ElfFile.hpp b/sdk/include/host/ElfFile.hpp index 4f0cb19c2..3a3200030 100644 --- a/sdk/include/host/ElfFile.hpp +++ b/sdk/include/host/ElfFile.hpp @@ -23,10 +23,12 @@ class ElfFile { ~ElfFile(); size_t getFileSize() { return fileSize; } bool isValid(); + void* getPtr() { return ptr; } uintptr_t getMinVaddr() { return minVaddr; } size_t getTotalMemorySize() { return maxVaddr - minVaddr; } bool initialize(bool isRuntime); + bool parseElf(bool isRuntime); unsigned int getPageMode() { return (isRuntime ? RT_FULL : USER_FULL); } diff --git a/sdk/include/host/Elfloader.hpp b/sdk/include/host/Elfloader.hpp new file mode 100644 index 000000000..439ae4db5 --- /dev/null +++ b/sdk/include/host/Elfloader.hpp @@ -0,0 +1,3 @@ +#include "ElfFile.hpp" + +int parseElf(char* fileName); diff --git a/sdk/include/host/Enclave.hpp b/sdk/include/host/Enclave.hpp index 88125e05c..76048622d 100644 --- a/sdk/include/host/Enclave.hpp +++ b/sdk/include/host/Enclave.hpp @@ -33,47 +33,42 @@ typedef std::function OcallFunc; class Enclave { private: Params params; - ElfFile* runtimeFile; - ElfFile* enclaveFile; + uintptr_t runtimeElfAddr; + uintptr_t enclaveElfAddr; Memory* pMemory; KeystoneDevice* pDevice; - char hash[MDSIZE]; - hash_ctx_t hash_ctx; - uintptr_t runtime_stk_sz; void* shared_buffer; size_t shared_buffer_size; OcallFunc oFuncDispatch; bool mapUntrusted(size_t size); - bool allocPage(uintptr_t va, uintptr_t src, unsigned int mode); - bool initStack(uintptr_t start, size_t size, bool is_rt); - Error loadUntrusted(); - bool mapElf(ElfFile* file); - Error loadElf(ElfFile* file); - Error validate_and_hash_enclave(struct runtime_params_t args); + uintptr_t copyFile(uintptr_t filePtr, size_t fileSize); + void allocUninitialized(ElfFile* elfFile); + void loadElf(ElfFile* elfFile); bool initFiles(const char*, const char*); bool initDevice(); - bool prepareEnclave(uintptr_t alternatePhysAddr); + bool prepareEnclaveMemory(size_t requiredPages, uintptr_t alternatePhysAddr); bool initMemory(); public: Enclave(); ~Enclave(); - const char* getHash(); + static Error measure(char* hash, const char* eapppath, const char* runtimepath, const char* loaderpath); void* getSharedBuffer(); size_t getSharedBufferSize(); + Memory* getMemory(); + uintptr_t getRuntimeElfAddr() { return runtimeElfAddr; } + uintptr_t getEnclaveElfAddr() { return enclaveElfAddr; } Error registerOcallDispatch(OcallFunc func); - Error init(const char* filepath, const char* runtime, Params parameters); + Error init(const char* filepath, const char* runtime, const char* loaderpath, Params parameters); Error init( - const char* eapppath, const char* runtimepath, Params _params, + const char* eapppath, const char* runtimepath, const char* loaderpath, Params _params, uintptr_t alternatePhysAddr); Error destroy(); Error run(uintptr_t* ret = nullptr); }; uint64_t -calculate_required_pages( - uint64_t eapp_sz, uint64_t eapp_stack_sz, uint64_t rt_sz, - uint64_t rt_stack_sz); +calculate_required_pages(ElfFile** elfFiles, size_t numElfFiles); } // namespace Keystone diff --git a/sdk/include/host/Memory.hpp b/sdk/include/host/Memory.hpp index a1bb937f9..31c1af2a4 100644 --- a/sdk/include/host/Memory.hpp +++ b/sdk/include/host/Memory.hpp @@ -77,13 +77,14 @@ class Memory { virtual void writeMem(uintptr_t src, uintptr_t dst, size_t size) = 0; virtual uintptr_t allocMem(size_t size) = 0; virtual uintptr_t allocUtm(size_t size) = 0; - bool allocPage(uintptr_t eva, uintptr_t src, unsigned int mode); size_t epmAllocVspace(uintptr_t addr, size_t num_pages); + uintptr_t allocPages(size_t size); + // getters to be deprecated uintptr_t getStartAddr() { return startAddr; } - uintptr_t getCurrentEPMAddress() { return epmFreeList; } - uintptr_t getRootPageTable() { return rootPageTable; } + uintptr_t getCurrentOffset() { return epmFreeList; } + uintptr_t getCurrentEPMAddress() { return epmFreeList + startAddr; } int validateAndHashEpm( hash_ctx_t* hash_ctx, int level, pte* tb, uintptr_t vaddr, int contiguous, @@ -93,22 +94,16 @@ class Memory { void startEappMem(); void startFreeMem(); + void incrementEPMFreeList(); + uintptr_t getRuntimePhysAddr() { return runtimePhysAddr; } uintptr_t getEappPhysAddr() { return eappPhysAddr; } uintptr_t getFreePhysAddr() { return freePhysAddr; } - protected: - pte* __ept_walk_create(uintptr_t addr); - pte* __ept_continue_walk_create(uintptr_t addr, pte* pte); - pte* __ept_walk_internal(uintptr_t addr, int create); - pte* __ept_walk(uintptr_t addr); - uintptr_t epm_va_to_pa(uintptr_t addr); - KeystoneDevice* pDevice; size_t epmSize; uintptr_t epmFreeList; uintptr_t utmFreeList; - uintptr_t rootPageTable; uintptr_t startAddr; // for hash calculation @@ -118,13 +113,6 @@ class Memory { uintptr_t utmPhysAddr; uintptr_t untrustedPtr; uintptr_t untrustedSize; - - private: - pte pte_create(uintptr_t, int); - pte ptd_create(uintptr_t); - uintptr_t pte_ppn(pte); - uintptr_t ppn(uintptr_t); - size_t pt_idx(uintptr_t, int); }; class PhysicalEnclaveMemory : public Memory { diff --git a/sdk/macros.cmake b/sdk/macros.cmake index 3fc7956eb..1c7f92ed4 100644 --- a/sdk/macros.cmake +++ b/sdk/macros.cmake @@ -120,7 +120,7 @@ macro(add_eyrie_runtime target_name plugins) # the files are passed via ${ARGN} DOWNLOAD_COMMAND rm -rf ${eyrie_src} && cp -ar ${KEYSTONE_EYRIE_RUNTIME} ${eyrie_src} CMAKE_ARGS "${PLUGIN_FLAGS}" -DEYRIE_SRCDIR=${KEYSTONE_EYRIE_RUNTIME} -DKEYSTONE_SDK_DIR=${KEYSTONE_SDK_DIR} BUILD_IN_SOURCE TRUE - BUILD_BYPRODUCTS ${eyrie_src}/eyrie-rt ${eyrie_src}/.options_log + BUILD_BYPRODUCTS ${eyrie_src}/eyrie-rt ${eyrie_src}/.options_log ${eyrie_src}/loader.bin INSTALL_COMMAND "") add_custom_target(${target_name} DEPENDS ${ARGN}) @@ -132,6 +132,7 @@ macro(add_eyrie_runtime target_name plugins) # the files are passed via ${ARGN} endmacro(add_eyrie_runtime) +# CMake macro for Keystone Package macro(add_keystone_package target_name package_name package_script) # files are passed via ${ARGN} set(pkg_dir ${CMAKE_CURRENT_BINARY_DIR}/pkg) add_custom_command(OUTPUT ${pkg_dir} COMMAND mkdir ${pkg_dir}) diff --git a/sdk/src/host/ElfFile.cpp b/sdk/src/host/ElfFile.cpp index 2a44c5e2f..b8c83c009 100644 --- a/sdk/src/host/ElfFile.cpp +++ b/sdk/src/host/ElfFile.cpp @@ -5,7 +5,6 @@ #include "ElfFile.hpp" #include #include -#include namespace Keystone { @@ -37,74 +36,24 @@ ElfFile::ElfFile(std::string filename) { if (!ptr) { ERROR("mmap failed for %s", filename.c_str()); } -} - -ElfFile::~ElfFile() { - close(filep); - munmap(ptr, fileSize); -} - -bool -ElfFile::isValid() { - return (filep > 0 && fileSize > 0 && ptr != NULL); -} - -bool -ElfFile::initialize(bool _isRuntime) { - if (!isValid()) return false; - - /* preparation for libelf */ + /* preparation for libelf */ if (elf_newFile(ptr, fileSize, &elf)) { - return false; + return; } /* get bound vaddrs */ elf_getMemoryBounds(&elf, VIRTUAL, &minVaddr, &maxVaddr); if (!IS_ALIGNED(minVaddr, PAGE_SIZE)) { - return false; + return; } maxVaddr = ROUND_UP(maxVaddr, PAGE_BITS); - - isRuntime = _isRuntime; - - return true; } -/* Functions below are wrappers for libelf */ -size_t -ElfFile::getNumProgramHeaders(void) { - return elf_getNumProgramHeaders(&elf); -} - -size_t -ElfFile::getProgramHeaderType(size_t ph) { - return elf_getProgramHeaderType(&elf, ph); -} - -size_t -ElfFile::getProgramHeaderFileSize(size_t ph) { - return elf_getProgramHeaderFileSize(&elf, ph); -} - -size_t -ElfFile::getProgramHeaderMemorySize(size_t ph) { - return elf_getProgramHeaderMemorySize(&elf, ph); -} - -uintptr_t -ElfFile::getProgramHeaderVaddr(size_t ph) { - return elf_getProgramHeaderVaddr(&elf, ph); -} - -uintptr_t -ElfFile::getEntryPoint() { - return elf_getEntryPoint(&elf); +ElfFile::~ElfFile() { + close(filep); + munmap(ptr, fileSize); } -void* -ElfFile::getProgramSegment(size_t ph) { - return elf_getProgramSegment(&elf, ph); -} } // namespace Keystone diff --git a/sdk/src/host/Enclave.cpp b/sdk/src/host/Enclave.cpp index 7f1d1fa42..b21d3cf23 100644 --- a/sdk/src/host/Enclave.cpp +++ b/sdk/src/host/Enclave.cpp @@ -16,23 +16,20 @@ extern "C" { namespace Keystone { Enclave::Enclave() { - runtimeFile = NULL; - enclaveFile = NULL; } Enclave::~Enclave() { - if (runtimeFile) delete runtimeFile; - if (enclaveFile) delete enclaveFile; destroy(); } uint64_t -calculate_required_pages(uint64_t eapp_sz, uint64_t rt_sz) { +calculate_required_pages(ElfFile** elfFiles, size_t numElfFiles) { uint64_t req_pages = 0; - req_pages += ceil(eapp_sz / PAGE_SIZE); - req_pages += ceil(rt_sz / PAGE_SIZE); - + for (int i = 0; i < numElfFiles; i++) { + ElfFile* elfFile = elfFiles[i]; + req_pages += ceil(elfFile->getFileSize() / PAGE_SIZE); + } /* FIXME: calculate the required number of pages for the page table. * We actually don't know how many page tables the enclave might need, * because the SDK never knows how its memory will be aligned. @@ -41,293 +38,150 @@ calculate_required_pages(uint64_t eapp_sz, uint64_t rt_sz) { * away from this problem. * 15 pages will be more than sufficient to cover several hundreds of * megabytes of enclave/runtime. */ - req_pages += 15; + /* FIXME Part 2: now that loader does loading, .bss sections also eat up + * space. Eapp dev must make FREEMEM big enough to fit this!! + * Possible fix -- re-add exact .bss calculations? + */ + + /* Add one page each for bss segments of runtime and eapp */ + // TODO: add space for stack? + req_pages += 16; return req_pages; } -Error -Enclave::loadUntrusted() { - uintptr_t va_start = ROUND_DOWN(params.getUntrustedMem(), PAGE_BITS); - uintptr_t va_end = ROUND_UP(params.getUntrustedEnd(), PAGE_BITS); +bool +Enclave::prepareEnclaveMemory(size_t requiredPages, uintptr_t alternatePhysAddr) { + // FIXME: this will be deprecated with complete freemem support. + // We just add freemem size for now. + uint64_t minPages; + minPages = ROUND_UP(params.getFreeMemSize(), PAGE_BITS) / PAGE_SIZE; + minPages += requiredPages; - while (va_start < va_end) { - if (!pMemory->allocPage(va_start, 0, UTM_FULL)) { - return Error::PageAllocationFailure; - } - va_start += PAGE_SIZE; + if (params.isSimulated()) { + pMemory->init(0, 0, minPages); + return true; } - return Error::Success; -} -/* This function will be deprecated when we implement freemem */ -bool -Enclave::initStack(uintptr_t start, size_t size, bool is_rt) { - static char nullpage[PAGE_SIZE] = { - 0, - }; - uintptr_t high_addr = ROUND_UP(start, PAGE_BITS); - uintptr_t va_start_stk = ROUND_DOWN((high_addr - size), PAGE_BITS); - int stk_pages = (high_addr - va_start_stk) / PAGE_SIZE; - - for (int i = 0; i < stk_pages; i++) { - if (!pMemory->allocPage( - va_start_stk, (uintptr_t)nullpage, - (is_rt ? RT_NOEXEC : USER_NOEXEC))) - return false; - - va_start_stk += PAGE_SIZE; + /* Call Enclave Driver */ + if (pDevice->create(minPages) != Error::Success) { + return false; } - return true; -} - -bool -Enclave::mapElf(ElfFile* elf) { - uintptr_t va; - - assert(elf); - - size_t num_pages = - ROUND_DOWN(elf->getTotalMemorySize(), PAGE_BITS) / PAGE_SIZE; - va = elf->getMinVaddr(); - - if (pMemory->epmAllocVspace(va, num_pages) != num_pages) { - ERROR("failed to allocate vspace\n"); - return false; + /* We switch out the phys addr as needed */ + uintptr_t physAddr; + if (alternatePhysAddr) { + physAddr = alternatePhysAddr; + } else { + physAddr = pDevice->getPhysAddr(); } + pMemory->init(pDevice, physAddr, minPages); return true; } -Error -Enclave::loadElf(ElfFile* elf) { - static char nullpage[PAGE_SIZE] = { - 0, - }; - - unsigned int mode = elf->getPageMode(); - for (unsigned int i = 0; i < elf->getNumProgramHeaders(); i++) { - if (elf->getProgramHeaderType(i) != PT_LOAD) { - continue; - } +uintptr_t +Enclave::copyFile(uintptr_t filePtr, size_t fileSize) { + uintptr_t startOffset = pMemory->getCurrentOffset(); + size_t bytesRemaining = fileSize; + + uintptr_t currOffset; + while (bytesRemaining > 0) { + currOffset = pMemory->getCurrentOffset(); + pMemory->incrementEPMFreeList(); - uintptr_t start = elf->getProgramHeaderVaddr(i); - uintptr_t file_end = start + elf->getProgramHeaderFileSize(i); - uintptr_t memory_end = start + elf->getProgramHeaderMemorySize(i); - char* src = reinterpret_cast(elf->getProgramSegment(i)); - uintptr_t va = start; - - /* FIXME: This is a temporary fix for loading iozone binary - * which has a page-misaligned program header. */ - if (!IS_ALIGNED(va, PAGE_SIZE)) { - size_t offset = va - PAGE_DOWN(va); - size_t length = PAGE_UP(va) - va; + size_t bytesToWrite = (bytesRemaining > PAGE_SIZE) ? PAGE_SIZE : bytesRemaining; + size_t bytesWritten = fileSize - bytesRemaining; + + if (bytesToWrite < PAGE_SIZE) { char page[PAGE_SIZE]; memset(page, 0, PAGE_SIZE); - memcpy(page + offset, (const void*)src, length); - if (!pMemory->allocPage(PAGE_DOWN(va), (uintptr_t)page, mode)) - return Error::PageAllocationFailure; - va += length; - src += length; + memcpy(page, (const void*) (filePtr + bytesWritten), (size_t)(bytesToWrite)); + pMemory->writeMem((uintptr_t) page, currOffset, PAGE_SIZE); + } else { + pMemory->writeMem(filePtr + bytesWritten, currOffset, bytesToWrite); } + bytesRemaining -= bytesToWrite; + } + return startOffset; +} - /* first load all pages that do not include .bss segment */ - while (va + PAGE_SIZE <= file_end) { - if (!pMemory->allocPage(va, (uintptr_t)src, mode)) - return Error::PageAllocationFailure; +static void measureElfFile(hash_ctx_t* hash_ctx, ElfFile* file) { + uintptr_t fptr = (uintptr_t) file->getPtr(); + uintptr_t fend = fptr + (uintptr_t) file->getFileSize(); - src += PAGE_SIZE; - va += PAGE_SIZE; - } - - /* next, load the page that has both initialized and uninitialized segments - */ - if (va < file_end) { + for (; fptr < fend; fptr += PAGE_SIZE) { + if (fend - fptr < PAGE_SIZE) { char page[PAGE_SIZE]; memset(page, 0, PAGE_SIZE); - memcpy(page, (const void*)src, static_cast(file_end - va)); - if (!pMemory->allocPage(va, (uintptr_t)page, mode)) - return Error::PageAllocationFailure; - va += PAGE_SIZE; - } - - /* finally, load the remaining .bss segments */ - while (va < memory_end) { - if (!pMemory->allocPage(va, (uintptr_t)nullpage, mode)) - return Error::PageAllocationFailure; - va += PAGE_SIZE; + memcpy(page, (const void*) fptr, (size_t)(fend-fptr)); + hash_extend_page(hash_ctx, (void*) page); + } else { + hash_extend_page(hash_ctx, (void*) fptr); } } - - return Error::Success; } Error -Enclave::validate_and_hash_enclave(struct runtime_params_t args) { +Enclave::measure(char* hash, const char* eapppath, const char* runtimepath, const char* loaderpath) { hash_ctx_t hash_ctx; - int ptlevel = RISCV_PGLEVEL_TOP; - hash_init(&hash_ctx); - // hash the runtime parameters - hash_extend(&hash_ctx, &args, sizeof(struct runtime_params_t)); + ElfFile* loader = new ElfFile(loaderpath); + ElfFile* runtime = new ElfFile(runtimepath); + ElfFile* eapp = new ElfFile(eapppath); - uintptr_t runtime_max_seen = 0; - uintptr_t user_max_seen = 0; + uintptr_t sizes[3] = { PAGE_UP(loader->getFileSize()), PAGE_UP(runtime->getFileSize()), + PAGE_UP(eapp->getFileSize()) }; + hash_extend(&hash_ctx, (void*) sizes, sizeof(sizes)); - // hash the epm contents including the virtual addresses - int valid = pMemory->validateAndHashEpm( - &hash_ctx, ptlevel, reinterpret_cast(pMemory->getRootPageTable()), - 0, 0, &runtime_max_seen, &user_max_seen); - - if (valid == -1) { - return Error::InvalidEnclave; - } + measureElfFile(&hash_ctx, loader); + delete loader; + measureElfFile(&hash_ctx, runtime); + delete runtime; + measureElfFile(&hash_ctx, eapp); + delete eapp; hash_finalize(hash, &hash_ctx); return Error::Success; } -bool -Enclave::initFiles(const char* eapppath, const char* runtimepath) { - if (runtimeFile || enclaveFile) { - ERROR("ELF files already initialized"); - return false; - } - - runtimeFile = new ElfFile(runtimepath); - enclaveFile = new ElfFile(eapppath); - - if (!runtimeFile->initialize(true)) { - ERROR("Invalid runtime ELF\n"); - destroy(); - return false; - } - - if (!enclaveFile->initialize(false)) { - ERROR("Invalid enclave ELF\n"); - destroy(); - return false; - } - - if (!runtimeFile->isValid()) { - ERROR("runtime file is not valid"); - destroy(); - return false; - } - if (!enclaveFile->isValid()) { - ERROR("enclave file is not valid"); - destroy(); - return false; - } - - return true; -} - -bool -Enclave::prepareEnclave(uintptr_t alternatePhysAddr) { - // FIXME: this will be deprecated with complete freemem support. - // We just add freemem size for now. - uint64_t minPages; - minPages = ROUND_UP(params.getFreeMemSize(), PAGE_BITS) / PAGE_SIZE; - minPages += calculate_required_pages( - enclaveFile->getTotalMemorySize(), runtimeFile->getTotalMemorySize()); - - if (params.isSimulated()) { - pMemory->init(0, 0, minPages); - return true; - } - - /* Call Enclave Driver */ - if (pDevice->create(minPages) != Error::Success) { - return false; - } - - /* We switch out the phys addr as needed */ - uintptr_t physAddr; - if (alternatePhysAddr) { - physAddr = alternatePhysAddr; - } else { - physAddr = pDevice->getPhysAddr(); - } - - pMemory->init(pDevice, physAddr, minPages); - return true; -} - Error -Enclave::init(const char* eapppath, const char* runtimepath, Params _params) { - return this->init(eapppath, runtimepath, _params, (uintptr_t)0); -} - -const char* -Enclave::getHash() { - return this->hash; +Enclave::init(const char* eapppath, const char* runtimepath, const char* loaderpath, Params _params) { + return this->init(eapppath, runtimepath, loaderpath, _params, (uintptr_t)0); } Error Enclave::init( - const char* eapppath, const char* runtimepath, Params _params, + const char* eapppath, const char* runtimepath, const char* loaderpath, Params _params, uintptr_t alternatePhysAddr) { params = _params; if (params.isSimulated()) { pMemory = new SimulatedEnclaveMemory(); pDevice = new MockKeystoneDevice(); + return Error::DeviceInitFailure; } else { pMemory = new PhysicalEnclaveMemory(); pDevice = new KeystoneDevice(); } - if (!initFiles(eapppath, runtimepath)) { - return Error::FileInitFailure; - } + ElfFile* enclaveFile = new ElfFile(eapppath); + ElfFile* runtimeFile = new ElfFile(runtimepath); + ElfFile* loaderFile = new ElfFile(loaderpath); if (!pDevice->initDevice(params)) { destroy(); return Error::DeviceInitFailure; } - if (!prepareEnclave(alternatePhysAddr)) { - destroy(); - return Error::DeviceError; - } - - if (!mapElf(runtimeFile)) { - destroy(); - return Error::VSpaceAllocationFailure; - } - - pMemory->startRuntimeMem(); + ElfFile* elfFiles[3] = {enclaveFile, runtimeFile, loaderFile}; + size_t requiredPages = calculate_required_pages(elfFiles, 3); - if (loadElf(runtimeFile) != Error::Success) { - ERROR("failed to load runtime ELF"); + if (!prepareEnclaveMemory(requiredPages, alternatePhysAddr)) { destroy(); - return Error::ELFLoadFailure; - } - - if (!mapElf(enclaveFile)) { - destroy(); - return Error::VSpaceAllocationFailure; - } - - pMemory->startEappMem(); - - if (loadElf(enclaveFile) != Error::Success) { - ERROR("failed to load enclave ELF"); - destroy(); - return Error::ELFLoadFailure; - } - -/* initialize stack. If not using freemem */ -#ifndef USE_FREEMEM - if (!initStack(DEFAULT_STACK_START, DEFAULT_STACK_SIZE, 0)) { - ERROR("failed to init static stack"); - destroy(); - return Error::PageAllocationFailure; + return Error::DeviceError; } -#endif /* USE_FREEMEM */ uintptr_t utm_free; utm_free = pMemory->allocUtm(params.getUntrustedSize()); @@ -337,28 +191,24 @@ Enclave::init( destroy(); return Error::DeviceError; } + + /* Copy loader into beginning of enclave memory */ + copyFile((uintptr_t) loaderFile->getPtr(), loaderFile->getFileSize()); - if (loadUntrusted() != Error::Success) { - ERROR("failed to load untrusted"); - } + pMemory->startRuntimeMem(); + runtimeElfAddr = copyFile((uintptr_t) runtimeFile->getPtr(), runtimeFile->getFileSize()); // TODO: figure out if we need runtimeELFAddr + + pMemory->startEappMem(); + enclaveElfAddr = copyFile((uintptr_t) enclaveFile->getPtr(), enclaveFile->getFileSize()); // TODO: figure out if we need enclaveElfAddr + + pMemory->startFreeMem(); struct runtime_params_t runtimeParams; - runtimeParams.runtime_entry = - reinterpret_cast(runtimeFile->getEntryPoint()); - runtimeParams.user_entry = - reinterpret_cast(enclaveFile->getEntryPoint()); runtimeParams.untrusted_ptr = - reinterpret_cast(params.getUntrustedMem()); + reinterpret_cast(utm_free); runtimeParams.untrusted_size = reinterpret_cast(params.getUntrustedSize()); - pMemory->startFreeMem(); - - /* TODO: This should be invoked with some other function e.g., measure() */ - if (params.isSimulated()) { - validate_and_hash_enclave(runtimeParams); - } - if (pDevice->finalize( pMemory->getRuntimePhysAddr(), pMemory->getEappPhysAddr(), pMemory->getFreePhysAddr(), runtimeParams) != Error::Success) { @@ -372,13 +222,11 @@ Enclave::init( destroy(); return Error::DeviceMemoryMapError; } - //} /* ELF files are no longer needed */ delete enclaveFile; delete runtimeFile; - enclaveFile = NULL; - runtimeFile = NULL; + delete loaderFile; return Error::Success; } @@ -401,16 +249,6 @@ Enclave::mapUntrusted(size_t size) { Error Enclave::destroy() { - if (enclaveFile) { - delete enclaveFile; - enclaveFile = NULL; - } - - if (runtimeFile) { - delete runtimeFile; - runtimeFile = NULL; - } - return pDevice->destroy(); } @@ -448,6 +286,11 @@ Enclave::getSharedBufferSize() { return shared_buffer_size; } +Memory* +Enclave::getMemory() { + return pMemory; +} + Error Enclave::registerOcallDispatch(OcallFunc func) { oFuncDispatch = func; diff --git a/sdk/src/host/KeystoneDevice.cpp b/sdk/src/host/KeystoneDevice.cpp index 90597e8ce..916ce5522 100644 --- a/sdk/src/host/KeystoneDevice.cpp +++ b/sdk/src/host/KeystoneDevice.cpp @@ -132,7 +132,7 @@ KeystoneDevice::map(uintptr_t addr, size_t size) { } bool -KeystoneDevice::initDevice(Params params) { +KeystoneDevice::initDevice(Params params) { // TODO: why does this need params /* open device driver */ fd = open(KEYSTONE_DEV_PATH, O_RDWR); if (fd < 0) { diff --git a/sdk/src/host/Memory.cpp b/sdk/src/host/Memory.cpp index dd4e7fb89..acda34898 100644 --- a/sdk/src/host/Memory.cpp +++ b/sdk/src/host/Memory.cpp @@ -11,7 +11,6 @@ namespace Keystone { Memory::Memory() { epmFreeList = 0; utmFreeList = 0; - rootPageTable = 0; startAddr = 0; } @@ -30,142 +29,22 @@ Memory::startFreeMem() { freePhysAddr = getCurrentEPMAddress(); } -inline pte -Memory::pte_create(uintptr_t ppn, int type) { - return __pte((ppn << PTE_PPN_SHIFT) | PTE_V | type); -} - -inline pte -Memory::ptd_create(uintptr_t ppn) { - return pte_create(ppn, PTE_V); -} - -uintptr_t -Memory::pte_ppn(pte pte) { - return pte_val(pte) >> PTE_PPN_SHIFT; +void +Memory::incrementEPMFreeList() { + epmFreeList += PAGE_SIZE; } uintptr_t -Memory::ppn(uintptr_t addr) { - return __pa(addr) >> RISCV_PGSHIFT; -} - -size_t -Memory::pt_idx(uintptr_t addr, int level) { - size_t idx = addr >> (RISCV_PGLEVEL_BITS * level + RISCV_PGSHIFT); - return idx & ((1 << RISCV_PGLEVEL_BITS) - 1); -} - -bool -Memory::allocPage(uintptr_t va, uintptr_t src, unsigned int mode) { - uintptr_t page_addr; - uintptr_t* pFreeList = (mode == UTM_FULL ? &utmFreeList : &epmFreeList); - - pte* pte = __ept_walk_create(va); - - /* if the page has been already allocated, return the page */ - if (pte_val(*pte) & PTE_V) { - return true; - } - - /* otherwise, allocate one from EPM freelist */ - page_addr = *pFreeList >> PAGE_BITS; - *pFreeList += PAGE_SIZE; - - switch (mode) { - case USER_NOEXEC: { - *pte = - pte_create(page_addr, PTE_D | PTE_A | PTE_R | PTE_W | PTE_U | PTE_V); - break; - } - case RT_NOEXEC: { - *pte = pte_create(page_addr, PTE_D | PTE_A | PTE_R | PTE_W | PTE_V); - break; - } - case RT_FULL: { - *pte = - pte_create(page_addr, PTE_D | PTE_A | PTE_R | PTE_W | PTE_X | PTE_V); - writeMem(src, (uintptr_t)page_addr << PAGE_BITS, PAGE_SIZE); - break; - } - case USER_FULL: { - *pte = pte_create( - page_addr, PTE_D | PTE_A | PTE_R | PTE_W | PTE_X | PTE_U | PTE_V); - writeMem(src, (uintptr_t)page_addr << PAGE_BITS, PAGE_SIZE); - break; - } - case UTM_FULL: { - assert(!src); - *pte = pte_create(page_addr, PTE_D | PTE_A | PTE_R | PTE_W | PTE_V); - break; - } - default: { - PERROR("failed to add page - mode is invalid"); - return false; - } - } - - return true; -} - -pte* -Memory::__ept_continue_walk_create(uintptr_t addr, pte* pte) { - uint64_t free_ppn = ppn(epmFreeList); - *pte = ptd_create(free_ppn); - epmFreeList += PAGE_SIZE; - return __ept_walk_create(addr); -} - -pte* -Memory::__ept_walk_internal(uintptr_t addr, int create) { - pte* t = reinterpret_cast(rootPageTable); - - int i; - for (i = (VA_BITS - RISCV_PGSHIFT) / RISCV_PGLEVEL_BITS - 1; i > 0; i--) { - size_t idx = pt_idx(addr, i); - if (!(pte_val(t[idx]) & PTE_V)) { - return create ? __ept_continue_walk_create(addr, &t[idx]) : 0; - } - - t = reinterpret_cast(readMem( - reinterpret_cast(pte_ppn(t[idx]) << RISCV_PGSHIFT), - PAGE_SIZE)); +Memory::allocPages(size_t size) { + uintptr_t addr = epmFreeList; + if (size % PAGE_SIZE > 0) { + epmFreeList += (size / PAGE_SIZE + 1) * PAGE_SIZE; + } else { + epmFreeList += (size / PAGE_SIZE) * PAGE_SIZE; } - return &t[pt_idx(addr, 0)]; + return addr; } -pte* -Memory::__ept_walk_create(uintptr_t addr) { - return __ept_walk_internal(addr, 1); -} - -pte* -Memory::__ept_walk(uintptr_t addr) { - return __ept_walk_internal(addr, 0); -} - -uintptr_t -Memory::epm_va_to_pa(uintptr_t addr) { - pte* pte = __ept_walk(addr); - if (pte) - return pte_ppn(*pte) << RISCV_PGSHIFT; - else - return 0; -} - -/* This function pre-allocates the required page tables so that - * the virtual addresses are linearly mapped to the physical memory */ -size_t -Memory::epmAllocVspace(uintptr_t addr, size_t num_pages) { - size_t count; - - for (count = 0; count < num_pages; count++, addr += PAGE_SIZE) { - pte* pte = __ept_walk_create(addr); - if (!pte) break; - } - - return count; -} /* This will walk the entire vaddr space in the enclave, validating linear at-most-once paddr mappings, and then hashing valid pages */ @@ -173,124 +52,7 @@ int Memory::validateAndHashEpm( hash_ctx_t* hash_ctx, int level, pte* tb, uintptr_t vaddr, int contiguous, uintptr_t* runtime_max_seen, uintptr_t* user_max_seen) { - pte* walk; - int i; - - /* iterate over PTEs */ - for (walk = tb, i = 0; walk < tb + (RISCV_PGSIZE / sizeof(pte)); - walk += 1, i++) { - if (pte_val(*walk) == 0) { - contiguous = 0; - continue; - } - uintptr_t vpn; - uintptr_t phys_addr = (pte_val(*walk) >> PTE_PPN_SHIFT) << RISCV_PGSHIFT; - /* Check for blatently invalid mappings */ - int map_in_epm = - (phys_addr >= startAddr && phys_addr < startAddr + epmSize); - int map_in_utm = - (phys_addr >= utmPhysAddr && phys_addr < utmPhysAddr + untrustedSize); - - /* EPM may map anything, UTM may not map pgtables */ - if (!map_in_epm && (!map_in_utm || level != 1)) { - printf("1\n"); - goto fatal_bail; - } - - /* propagate the highest bit of the VA */ - if (level == RISCV_PGLEVEL_TOP && i & RISCV_PGTABLE_HIGHEST_BIT) - vpn = ((-1UL << RISCV_PGLEVEL_BITS) | (i & RISCV_PGLEVEL_MASK)); - else - vpn = ((vaddr << RISCV_PGLEVEL_BITS) | (i & RISCV_PGLEVEL_MASK)); - - uintptr_t va_start = vpn << RISCV_PGSHIFT; - - /* include the first virtual address of a contiguous range */ - if (level == 1 && !contiguous) { - hash_extend(hash_ctx, &va_start, sizeof(uintptr_t)); - // printf("user VA hashed: 0x%lx\n", va_start); - contiguous = 1; - } - - if (level == 1) { - /* - * This is where we enforce the at-most-one-mapping property. - * To make our lives easier, we also require a 'linear' mapping - * (for each of the user and runtime spaces independently). - * - * That is: Given V1->P1 and V2->P2: - * - * V1 < V2 ==> P1 < P2 (Only for within a given space) - * - * V1 != V2 ==> P1 != P2 - * - * We also validate that all utm vaddrs -> utm paddrs - */ - int in_runtime = - ((phys_addr >= runtimePhysAddr) && (phys_addr < eappPhysAddr)); - int in_user = ((phys_addr >= eappPhysAddr) && (phys_addr < freePhysAddr)); - - /* Validate U bit */ - if (in_user && !(pte_val(*walk) & PTE_U)) { - goto fatal_bail; - } - - /* If the vaddr is in UTM, the paddr must be in UTM */ - if (va_start >= utmPhysAddr && va_start < (utmPhysAddr + untrustedSize) && - !map_in_utm) { - goto fatal_bail; - } - - /* Do linear mapping validation */ - if (in_runtime) { - if (phys_addr <= *runtime_max_seen) { - goto fatal_bail; - } else { - *runtime_max_seen = phys_addr; - } - } else if (in_user) { - if (phys_addr <= *user_max_seen) { - goto fatal_bail; - } else { - *user_max_seen = phys_addr; - } - } else if (map_in_utm) { - // we checked this above, its OK - } else { - // printf("BAD GENERIC MAP %x %x %x\n", in_runtime, in_user, - // map_in_utm); - goto fatal_bail; - } - - /* Page is valid, add it to the hash */ - - /* if PTE is leaf, extend hash for the page */ - hash_extend_page(hash_ctx, reinterpret_cast(phys_addr)); - // printf("user PAGE hashed: 0x%lx (pa: 0x%lx)\n", vpn << - // RISCV_PGSHIFT, phys_addr); - } else { - /* otherwise, recurse on a lower level */ - contiguous = validateAndHashEpm( - hash_ctx, level - 1, reinterpret_cast(phys_addr), vpn, - contiguous, runtime_max_seen, user_max_seen); - if (contiguous == -1) { - printf( - "BAD MAP: %p->%p epm %u %p uer %u %p\n", - reinterpret_cast(va_start), - reinterpret_cast(phys_addr), - // in_runtime, - 0, reinterpret_cast(runtimePhysAddr), - // in_user, - 0, reinterpret_cast(eappPhysAddr)); - goto fatal_bail; - } - } - } - - return contiguous; - -fatal_bail: - return -1; + return 0; } } // namespace Keystone diff --git a/sdk/src/host/PhysicalEnclaveMemory.cpp b/sdk/src/host/PhysicalEnclaveMemory.cpp index 01d9ba8df..b0f3455d6 100644 --- a/sdk/src/host/PhysicalEnclaveMemory.cpp +++ b/sdk/src/host/PhysicalEnclaveMemory.cpp @@ -12,9 +12,8 @@ PhysicalEnclaveMemory::init( pDevice = dev; // TODO(dayeol): need to set actual EPM size epmSize = PAGE_SIZE * min_pages; - rootPageTable = allocMem(PAGE_SIZE); - epmFreeList = phys_addr + PAGE_SIZE; - startAddr = phys_addr; + epmFreeList = 0; + startAddr = phys_addr; } uintptr_t @@ -26,30 +25,34 @@ PhysicalEnclaveMemory::allocUtm(size_t size) { return ret; } +// TODO: delete this +/* Only used to allocate memory for root page table */ uintptr_t PhysicalEnclaveMemory::allocMem(size_t size) { uintptr_t ret; assert(pDevice); - ret = reinterpret_cast(pDevice->map(0, PAGE_SIZE)); + ret = reinterpret_cast(pDevice->map(0, size)); return ret; } +// unused uintptr_t PhysicalEnclaveMemory::readMem(uintptr_t src, size_t size) { uintptr_t ret; assert(pDevice); - ret = reinterpret_cast(pDevice->map(src - startAddr, size)); + ret = reinterpret_cast(pDevice->map(src, size)); return ret; } +/* src: virtual address */ void -PhysicalEnclaveMemory::writeMem(uintptr_t src, uintptr_t dst, size_t size) { +PhysicalEnclaveMemory::writeMem(uintptr_t src, uintptr_t offset, size_t size) { assert(pDevice); - void* va_dst = pDevice->map(dst - startAddr, size); + void* va_dst = pDevice->map(offset, size); memcpy(va_dst, reinterpret_cast(src), size); } diff --git a/sdk/src/host/SimulatedEnclaveMemory.cpp b/sdk/src/host/SimulatedEnclaveMemory.cpp index 3c726cde8..72357ae52 100644 --- a/sdk/src/host/SimulatedEnclaveMemory.cpp +++ b/sdk/src/host/SimulatedEnclaveMemory.cpp @@ -11,9 +11,8 @@ SimulatedEnclaveMemory::init( KeystoneDevice* dev, uintptr_t phys_addr, size_t min_pages) { pDevice = dev; epmSize = PAGE_SIZE * min_pages; - rootPageTable = allocMem(PAGE_SIZE * min_pages); - startAddr = rootPageTable; - epmFreeList = startAddr + PAGE_SIZE; + epmFreeList = 0; // offset + startAddr = 0; } void* @@ -23,6 +22,7 @@ SimulatedEnclaveMemory::allocateAligned(size_t size, size_t alignment) { return reinterpret_cast((mem + mask) & ~mask); } +// unused uintptr_t SimulatedEnclaveMemory::allocMem(size_t size) { uintptr_t ret; @@ -43,6 +43,7 @@ SimulatedEnclaveMemory::readMem(uintptr_t src, size_t size) { return src; } +// TODO: change write Mem to use addresses relative to start of section rather than absolute addresses void SimulatedEnclaveMemory::writeMem(uintptr_t src, uintptr_t dst, size_t size) { memcpy(reinterpret_cast(dst), reinterpret_cast(src), size); diff --git a/sdk/tests/CMakeLists.txt b/sdk/tests/CMakeLists.txt index 52c19aaf1..868d80dcd 100644 --- a/sdk/tests/CMakeLists.txt +++ b/sdk/tests/CMakeLists.txt @@ -6,6 +6,8 @@ project(keystone-sdk-test C CXX) set(SOURCES keystone_test.cpp) +set(DL_SOURCES + dl_tests.cpp) SET(CTEST_OUTPUT_ON_FAILURE ON) @@ -33,17 +35,23 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include ${HOST_LIB_INCLUDE} $ add_executable(TestKeystone ${SOURCES} ${HOST_LIB_SOURCES} ${COMMON_SOURCES}) +add_executable(TestDL + ${DL_SOURCES} + ${HOST_LIB_SOURCES} ${COMMON_SOURCES}) message(STATUS ${GTEST_FOUND}) -target_link_libraries(TestKeystone ${GTEST_LIBRARIES} pthread) +target_link_libraries(TestKeystone ${GTEST_LIBRARIES}) +target_link_libraries(TestDL ${GTEST_LIBRARIES}) add_test(NAME TestKeystone COMMAND ./TestKeystone) +add_test(NAME TestDL + COMMAND ./TestDL) add_custom_target(check DEPENDS binaries COMMAND env CTEST_OUTPUT_ON_FAILURE=1 GTEST_COLOR=1 ${CMAKE_CTEST_COMMAND} - DEPENDS TestKeystone) + DEPENDS TestKeystone TestDL) enable_testing() diff --git a/sdk/tests/dl_tests.cpp b/sdk/tests/dl_tests.cpp new file mode 100644 index 000000000..ce6f36f64 --- /dev/null +++ b/sdk/tests/dl_tests.cpp @@ -0,0 +1,73 @@ +//****************************************************************************** +// Copyright (c) 2020, The Regents of the University of California (Regents). +// All Rights Reserved. See LICENSE for license details. +//------------------------------------------------------------------------------ +#include +#include +#include +#include +#include "gtest/gtest.h" + +#define EYRIE_RT "eyrie-rt" +#define TEST_EAPP "stack.eapp_riscv" +#define FAKE_EAPP "fake_file.riscv" +#define FAKE_RT "fake-rt" +#define MD_SIZE 64 + +const uint8_t ref_hash[MD_SIZE] = { + 0xfd, 0xd8, 0x49, 0xe1, 0x89, 0xf8, 0x38, 0x45, 0xa6, 0x22, 0x33, + 0x78, 0x02, 0x22, 0xb9, 0xdf, 0x31, 0x32, 0xb7, 0xc1, 0xaa, 0x10, + 0xce, 0xb2, 0xec, 0x55, 0x6e, 0x78, 0xb4, 0x4f, 0x6e, 0xf6, 0x11, + 0x95, 0x12, 0xb5, 0x54, 0xc7, 0x6b, 0xc8, 0x5a, 0xe9, 0x36, 0xef, + 0x5c, 0x14, 0x7f, 0x37, 0x86, 0x4c, 0x36, 0x7c, 0x8f, 0xff, 0xa2, + 0x0c, 0x67, 0x0f, 0x17, 0xd5, 0xe6, 0x1e, 0x7e, 0xe1}; + +size_t untrusted_size = 2 * 1024 * 1024; +size_t freemem_size = 48 * 1024 * 1024; +uintptr_t utm_ptr = (uintptr_t)DEFAULT_UNTRUSTED_PTR; + +using Keystone::Enclave; +using Keystone::Params; +using Keystone::Error; +using Keystone::ElfFile; +using Keystone::Memory; + +TEST(Copy_Elf, Valid) { + Enclave enclave; + Params params; + + params.setFreeMemSize(untrusted_size); + params.setUntrustedMem(utm_ptr, untrusted_size); + params.setSimulated(true); + + enclave.init(TEST_EAPP, EYRIE_RT, params); + + ElfFile runtimeElf = ElfFile(EYRIE_RT); + size_t rtFileSize = runtimeElf.getFileSize(); + char* rtElfPtr = (char *) runtimeElf.getPtr(); + + ElfFile enclaveElf = ElfFile(TEST_EAPP); + size_t eappFileSize = enclaveElf.getFileSize(); + char* eappElfPtr = (char *) enclaveElf.getPtr(); + + Memory* pMemory = enclave.getMemory(); + uintptr_t runtimeElfAddr = enclave.getRuntimeElfAddr(); + char rtCopiedElf[rtFileSize]; + char* copiedRtPtr = (char *) pMemory->readMem(runtimeElfAddr, rtFileSize); + memcpy((void*) rtCopiedElf, copiedRtPtr, rtFileSize); + + uintptr_t enclaveElfAddr = enclave.getEnclaveElfAddr(); + char eappCopiedElf[eappFileSize]; + char* copiedEappPtr = (char *) pMemory->readMem(enclaveElfAddr, eappFileSize); + memcpy((void*) eappCopiedElf, copiedEappPtr, eappFileSize); + + ASSERT_STREQ(rtElfPtr, rtCopiedElf); + ASSERT_STREQ(eappElfPtr, eappCopiedElf); +} + + +int +main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/sm/src/attest.c b/sm/src/attest.c index 7fbca114d..6317b3a0a 100644 --- a/sm/src/attest.c +++ b/sm/src/attest.c @@ -7,186 +7,40 @@ #include "page.h" #include -typedef uintptr_t pte_t; -/* This will walk the entire vaddr space in the enclave, validating - linear at-most-once paddr mappings, and then hashing valid pages */ -int validate_and_hash_epm(hash_ctx* hash_ctx, int level, - pte_t* tb, uintptr_t vaddr, int contiguous, - struct enclave* encl, - uintptr_t* runtime_max_seen, - uintptr_t* user_max_seen) +/* This will hash the loader and the runtime + eapp elf files. */ +int validate_and_hash_epm(hash_ctx* hash_ctx, struct enclave* encl) { - pte_t* walk; - int i; - - //TODO check for failures - uintptr_t epm_start, epm_size; - uintptr_t utm_start, utm_size; - int idx = get_enclave_region_index(encl->eid, REGION_EPM); - epm_start = pmp_region_get_addr(encl->regions[idx].pmp_rid); - epm_size = pmp_region_get_size(encl->regions[idx].pmp_rid); - idx = get_enclave_region_index(encl->eid, REGION_UTM); - utm_start = pmp_region_get_addr(encl->regions[idx].pmp_rid); - utm_size = pmp_region_get_size(encl->regions[idx].pmp_rid); - - - - /* iterate over PTEs */ - for (walk=tb, i=0; walk < tb + (RISCV_PGSIZE/sizeof(pte_t)); walk += 1,i++) - { - if (*walk == 0) { - contiguous = 0; - continue; - } - uintptr_t vpn; - uintptr_t phys_addr = (*walk >> PTE_PPN_SHIFT) << RISCV_PGSHIFT; - - /* Check for blatently invalid mappings */ - int map_in_epm = (phys_addr >= epm_start && - phys_addr < epm_start + epm_size); - int map_in_utm = (phys_addr >= utm_start && - phys_addr < utm_start + utm_size); - - /* EPM may map anything, UTM may not map pgtables */ - if(!map_in_epm && (!map_in_utm || level != 1)){ - goto fatal_bail; - } - - - /* propagate the highest bit of the VA */ - if ( level == RISCV_PGLEVEL_TOP && i & RISCV_PGTABLE_HIGHEST_BIT ) - vpn = ((-1UL << RISCV_PGLEVEL_BITS) | (i & RISCV_PGLEVEL_MASK)); - else - vpn = ((vaddr << RISCV_PGLEVEL_BITS) | (i & RISCV_PGLEVEL_MASK)); - - uintptr_t va_start = vpn << RISCV_PGSHIFT; - - /* include the first virtual address of a contiguous range */ - if (level == 1 && !contiguous) - { - - hash_extend(hash_ctx, &va_start, sizeof(uintptr_t)); - //printm("VA hashed: 0x%lx\n", va_start); - contiguous = 1; - } - - if (level == 1) - { - - /* - * This is where we enforce the at-most-one-mapping property. - * To make our lives easier, we also require a 'linear' mapping - * (for each of the user and runtime spaces independently). - * - * That is: Given V1->P1 and V2->P2: - * - * V1 < V2 ==> P1 < P2 (Only for within a given space) - * - * V1 != V2 ==> P1 != P2 - * - * We also validate that all utm vaddrs -> utm paddrs - */ - int in_runtime = ((phys_addr >= encl->pa_params.runtime_base) && - (phys_addr < encl->pa_params.user_base)); - int in_user = ((phys_addr >= encl->pa_params.user_base) && - (phys_addr < encl->pa_params.free_base)); - - /* Validate U bit */ - if(in_user && !(*walk & PTE_U)){ - goto fatal_bail; - } - - /* If the vaddr is in UTM, the paddr must be in UTM */ - if(va_start >= encl->params.untrusted_ptr && - va_start < (encl->params.untrusted_ptr + encl->params.untrusted_size) && - !map_in_utm){ - goto fatal_bail; - } - - /* Do linear mapping validation */ - if(in_runtime){ - if(phys_addr <= *runtime_max_seen){ - goto fatal_bail; - } - else{ - *runtime_max_seen = phys_addr; - } - } - else if(in_user){ - if(phys_addr <= *user_max_seen){ - goto fatal_bail; - } - else{ - *user_max_seen = phys_addr; - } - } - else if(map_in_utm){ - // we checked this above, its OK - } - else{ - //printm("BAD GENERIC MAP %x %x %x\n", in_runtime, in_user, map_in_utm); - goto fatal_bail; - } - - /* Page is valid, add it to the hash */ - - /* if PTE is leaf, extend hash for the page */ - hash_extend_page(hash_ctx, (void*)phys_addr); - - - - //printm("PAGE hashed: 0x%lx (pa: 0x%lx)\n", vpn << RISCV_PGSHIFT, phys_addr); - } - else - { - /* otherwise, recurse on a lower level */ - contiguous = validate_and_hash_epm(hash_ctx, - level - 1, - (pte_t*) phys_addr, - vpn, - contiguous, - encl, - runtime_max_seen, - user_max_seen); - if(contiguous == -1){ - sbi_printf("BAD MAP: %lx->%lx epm %x %lx uer %x %lx\n", - va_start,phys_addr, - //in_runtime, - 0, - encl->pa_params.runtime_base, - 0, - //in_user, - encl->pa_params.user_base); - goto fatal_bail; - } - } + uintptr_t loader = encl->pa_params.dram_base; // also base + uintptr_t runtime = encl->pa_params.runtime_base; + uintptr_t eapp = encl->pa_params.user_base; + uintptr_t free = encl->pa_params.free_base; + + // ensure pointers don't point to middle of correct files + uintptr_t sizes[3] = {runtime - loader, eapp - runtime, free - eapp}; + hash_extend(hash_ctx, (void*) sizes, sizeof(sizes)); + + // using pointers to ensure that they themselves are correct + // TODO(Evgeny): can extend by entire file instead of page at a time? + for (uintptr_t page = loader; page < runtime; page += RISCV_PGSIZE) { + hash_extend_page(hash_ctx, (void*) page); } - - return contiguous; - - fatal_bail: - return -1; + for (uintptr_t page = runtime; page < eapp; page += RISCV_PGSIZE) { + hash_extend_page(hash_ctx, (void*) page); + } + for (uintptr_t page = eapp; page < free; page += RISCV_PGSIZE) { + hash_extend_page(hash_ctx, (void*) page); + } + return 0; } unsigned long validate_and_hash_enclave(struct enclave* enclave){ - hash_ctx hash_ctx; - int ptlevel = RISCV_PGLEVEL_TOP; - hash_init(&hash_ctx); - // hash the runtime parameters - hash_extend(&hash_ctx, &enclave->params, sizeof(struct runtime_va_params_t)); - - - uintptr_t runtime_max_seen=0; - uintptr_t user_max_seen=0;; + // TODO: ensure untrusted and free sizes - // hash the epm contents including the virtual addresses - int valid = validate_and_hash_epm(&hash_ctx, - ptlevel, - (pte_t*) (enclave->encl_satp << RISCV_PGSHIFT), - 0, 0, enclave, &runtime_max_seen, &user_max_seen); + // hash the epm contents + int valid = validate_and_hash_epm(&hash_ctx, enclave); if(valid == -1){ return SBI_ERR_SM_ENCLAVE_ILLEGAL_PTE; diff --git a/sm/src/enclave.c b/sm/src/enclave.c index 3ec9c5d73..dba749dcd 100644 --- a/sm/src/enclave.c +++ b/sm/src/enclave.c @@ -51,8 +51,7 @@ static inline void context_switch_to_enclave(struct sbi_trap_regs* regs, if(load_parameters) { // passing parameters for a first run - csr_write(sepc, (uintptr_t) enclaves[eid].params.user_entry); - regs->mepc = (uintptr_t) enclaves[eid].params.runtime_entry - 4; // regs->mepc will be +4 before sbi_ecall_handler return + regs->mepc = (uintptr_t) enclaves[eid].pa_params.dram_base - 4; // regs->mepc will be +4 before sbi_ecall_handler return regs->mstatus = (1 << MSTATUS_MPP_SHIFT); // $a1: (PA) DRAM base, regs->a1 = (uintptr_t) enclaves[eid].pa_params.dram_base; @@ -64,13 +63,13 @@ static inline void context_switch_to_enclave(struct sbi_trap_regs* regs, regs->a4 = (uintptr_t) enclaves[eid].pa_params.user_base; // $a5: (PA) freemem location, regs->a5 = (uintptr_t) enclaves[eid].pa_params.free_base; - // $a6: (VA) utm base, + // $a6: (PA) utm base, regs->a6 = (uintptr_t) enclaves[eid].params.untrusted_ptr; // $a7: (size_t) utm size regs->a7 = (uintptr_t) enclaves[eid].params.untrusted_size; - // switch to the initial enclave page table - csr_write(satp, enclaves[eid].encl_satp); + // enclave will only have physical addresses in the first run + csr_write(satp, 0); } switch_vector_enclave(); @@ -410,6 +409,7 @@ unsigned long create_enclave(unsigned long *eidptr, struct keystone_sbi_create c /* Validate memory, prepare hash and signature for attestation */ spin_lock(&encl_lock); // FIXME This should error for second enter. + ret = validate_and_hash_enclave(&enclaves[eid]); /* The enclave is fresh if it has been validated and hashed but not run yet. */ if (ret) @@ -504,7 +504,6 @@ unsigned long destroy_enclave(enclave_id eid) return SBI_ERR_SM_ENCLAVE_SUCCESS; } - unsigned long run_enclave(struct sbi_trap_regs *regs, enclave_id eid) { int runable; diff --git a/sm/src/sm.h b/sm/src/sm.h index 8a40feb0e..9330e47cf 100644 --- a/sm/src/sm.h +++ b/sm/src/sm.h @@ -107,7 +107,7 @@ struct keystone_sbi_create uintptr_t free_paddr; struct runtime_va_params_t params; - unsigned int* eid_pptr; + unsigned int* eid_pptr; // TODO: remove? }; int osm_pmp_set(uint8_t perm); From a06b05485ed59489ba0a8158a7de8c85988a1009 Mon Sep 17 00:00:00 2001 From: Akihiro Saiki Date: Thu, 14 Dec 2023 07:28:54 +0900 Subject: [PATCH 2/2] Support for HiFive Unmatched (#386) This PR adds board support for HiFive Unmatched. (#384) You can generate SD card image for unmatched using buildroot by single `make` command. It will not be available for production, but it will allow for easy testing. I checked that almost all example runs correctly, but only `attestor.ke` throw runtime error bacause the package does not include firmware image (`fw_jump.elf`) correctly. Same thing is happening with qemu target. ## New items/Changes - Add buildroot config for unmatched in `overlays/keystone/configs` - Add board specific configs/patches in `overlays/keystone/board` - Some patches in `freedom-u-sdk` & `meta-sifive` (2023.08) are included - Implement secureboot same as bootrom in u-boot. This is applied via a patch. - Unmatched's platform overrides in upstream OpenSBI is added to `sm/plat` - Add make target to flush SD card image - Other minor modifications ## Known issue Porting issue mentioned [here](https://groups.google.com/g/keystone-enclave-forum/c/6vnr6pWPZjw/m/HBeq4a5OBAAJ) is still remaining. With default `SMM_SIZE` (`0x200000`), machine hangs when switching to S-Mode entering u-boot proper (when function `sbi_hart_switch_mode` is called). In this PR, change `SMM_SIZE` to `0x80000` same as sbi domain region by passing compile flag for unmatched target. This is temporary fix. ## Remarks FU740 has waymasks same as FU540. Waymasking implemented for FU540 can be ported to FU740, I think. --- .gitignore | 2 +- Makefile | 3 + mkutils/plat/unmatched/run.mk | 25 + .../sifive/hifive-unmatched/extlinux.conf | 5 + .../hifive-unmatched/genimage_sdcard.cfg | 23 + .../linux-sifive-unmatched-defconfig | 590 +++++++ ...cpumap-Make-counter-as-unsigned-ints.patch | 69 + ...40-cpu-1-2-3-4-set-compatible-to-sif.patch | 56 + ...scv-sifive-unmatched-define-PWM-LEDs.patch | 67 + ...-sifive-unmatched-Link-the-tmp451-wi.patch | 29 + ...-Initialized-the-PWM-setting-in-the-.patch | 107 ++ ...-LED-s-color-to-purple-in-the-U-boot.patch | 71 + ...-LED-s-color-to-blue-before-jumping-.patch | 37 + ...-Set-remote-thermal-of-TMP451-to-85-.patch | 112 ++ .../0005-riscv-dts-Add-few-PMU-events.patch | 42 + .../0006-implement-keystone-secure-boot.patch | 89 + ...ystone-prefer-mmc-boot-for-unmatched.patch | 28 + .../sifive/hifive-unmatched/post-build.sh | 14 + .../hifive-unmatched/src/uboot/keystone.h | 5 + .../src/uboot/keystone/Makefile | 3 + .../src/uboot/keystone/ed25519/LICENSE | 17 + .../src/uboot/keystone/ed25519/Makefile | 1 + .../src/uboot/keystone/ed25519/ed25519.h | 39 + .../src/uboot/keystone/ed25519/fe.c | 1491 +++++++++++++++++ .../src/uboot/keystone/ed25519/fe.h | 41 + .../src/uboot/keystone/ed25519/fixedint.h | 73 + .../src/uboot/keystone/ed25519/ge.c | 467 ++++++ .../src/uboot/keystone/ed25519/ge.h | 74 + .../src/uboot/keystone/ed25519/keypair.c | 16 + .../src/uboot/keystone/ed25519/precomp_data.h | 1391 +++++++++++++++ .../src/uboot/keystone/ed25519/sc.c | 809 +++++++++ .../src/uboot/keystone/ed25519/sc.h | 12 + .../src/uboot/keystone/ed25519/sign.c | 31 + .../src/uboot/keystone/ed25519/verify.c | 77 + .../src/uboot/keystone/keystone.c | 80 + .../uboot/keystone/keystone_test_dev_key.h | 22 + .../uboot/keystone/keystone_use_test_keys.h | 3 + .../src/uboot/keystone/sha3/Makefile | 1 + .../src/uboot/keystone/sha3/sha3.c | 165 ++ .../src/uboot/keystone/sha3/sha3.h | 40 + .../src/uboot/u-boot-spl-sanctum.lds | 92 + .../uboot_sifive_unmatched_keystone_defconfig | 69 + .../keystone/boot/keystone-sm/keystone-sm.mk | 3 + .../riscv64_hifive_unmatched_defconfig | 60 + overlays/keystone/external.mk | 13 + .../opensbi-firmware-secure-boot.patch | 2 +- sm/plat/generic/objects.mk | 2 +- sm/plat/generic/sifive/fu740.c | 260 +++ sm/plat/generic/sifive/objects.mk | 6 + sm/src/objects.mk | 2 +- sm/src/platform/unmatched/platform.c | 44 + sm/src/platform/unmatched/platform.h | 5 + 52 files changed, 6781 insertions(+), 4 deletions(-) create mode 100644 mkutils/plat/unmatched/run.mk create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/extlinux.conf create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/genimage_sdcard.cfg create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/linux-sifive-unmatched-defconfig create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0001-perf-cpumap-Make-counter-as-unsigned-ints.patch create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0001-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0002-riscv-sifive-unmatched-define-PWM-LEDs.patch create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0003-Revert-riscv-dts-sifive-unmatched-Link-the-tmp451-wi.patch create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0001-board-sifive-spl-Initialized-the-PWM-setting-in-the-.patch create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0002-board-sifive-Set-LED-s-color-to-purple-in-the-U-boot.patch create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0003-board-sifive-Set-LED-s-color-to-blue-before-jumping-.patch create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0004-board-sifive-spl-Set-remote-thermal-of-TMP451-to-85-.patch create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0005-riscv-dts-Add-few-PMU-events.patch create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0006-implement-keystone-secure-boot.patch create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0007-keystone-prefer-mmc-boot-for-unmatched.patch create mode 100755 overlays/keystone/board/sifive/hifive-unmatched/post-build.sh create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone.h create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/Makefile create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/LICENSE create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/Makefile create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ed25519.h create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fe.c create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fe.h create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fixedint.h create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ge.c create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ge.h create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/keypair.c create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/precomp_data.h create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sc.c create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sc.h create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sign.c create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/verify.c create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone.c create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone_test_dev_key.h create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone_use_test_keys.h create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/Makefile create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/sha3.c create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/sha3.h create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/src/uboot/u-boot-spl-sanctum.lds create mode 100644 overlays/keystone/board/sifive/hifive-unmatched/uboot_sifive_unmatched_keystone_defconfig create mode 100644 overlays/keystone/configs/riscv64_hifive_unmatched_defconfig create mode 100644 sm/plat/generic/sifive/fu740.c create mode 100644 sm/plat/generic/sifive/objects.mk create mode 100644 sm/src/platform/unmatched/platform.c create mode 100644 sm/src/platform/unmatched/platform.h diff --git a/.gitignore b/.gitignore index 0641574f7..ada2d0639 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ *~ *.swp .venv/ -build/ +build*/ riscv/ riscv64/ riscv32/ diff --git a/Makefile b/Makefile index 63550fe08..71a8df1aa 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,8 @@ include mkutils/log.mk BUILDROOT_CONFIGFILE ?= qemu_riscv$(KEYSTONE_BITS)_virt_defconfig ifeq ($(KEYSTONE_PLATFORM),mpfs) EXTERNALS += microchip +else ifeq ($(KEYSTONE_PLATFORM),unmatched) + BUILDROOT_CONFIGFILE = riscv64_hifive_unmatched_defconfig endif # Highest priority external @@ -114,3 +116,4 @@ linux-configure: $(BUILDROOT_BUILDDIR)/.config ################# -include mkutils/plat/$(KEYSTONE_PLATFORM)/run.mk + diff --git a/mkutils/plat/unmatched/run.mk b/mkutils/plat/unmatched/run.mk new file mode 100644 index 000000000..cd0a40653 --- /dev/null +++ b/mkutils/plat/unmatched/run.mk @@ -0,0 +1,25 @@ +######################### +## Flush SD card image ## +######################### + +DEVICE ?= +EXTEND ?= 0 +FLUSH_IMAGE ?= $(BUILDROOT_BUILDDIR)/images/sdcard.img + +flush: +ifeq ($(DEVICE),) + $(call log,error,Set target device to env DEVICE) +else + $(call log,info,Flushing SD image) + sudo dd if=$(FLUSH_IMAGE) of=$(DEVICE) bs=64k iflag=fullblock oflag=direct conv=fsync status=progress + +ifeq ($(EXTEND),1) + $(call log,info,Extending rootfs end of the block device) + echo "w" | sudo fdisk $(DEVICE) + echo "- +" | sudo sfdisk -N 3 $(DEVICE) + sudo e2fsck -f $(DEVICE)3 + sudo resize2fs $(DEVICE)3 +endif + +endif + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/extlinux.conf b/overlays/keystone/board/sifive/hifive-unmatched/extlinux.conf new file mode 100644 index 000000000..33e7e6e2d --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/extlinux.conf @@ -0,0 +1,5 @@ +default buildroot +label buildroot + kernel /boot/Image.gz + fdt /boot/hifive-unmatched-a00.dtb + append root=/dev/mmcblk0p3 rootfstype=ext4 rootwait console=ttySIF0,115200 earlycon diff --git a/overlays/keystone/board/sifive/hifive-unmatched/genimage_sdcard.cfg b/overlays/keystone/board/sifive/hifive-unmatched/genimage_sdcard.cfg new file mode 100644 index 000000000..079ac5ed2 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/genimage_sdcard.cfg @@ -0,0 +1,23 @@ +image sdcard.img { + hdimage { + partition-table-type = "gpt" + } + + partition u-boot-spl { + image = "u-boot-spl.bin" + offset = 17K + partition-type-uuid = 5b193300-fc78-40cd-8002-e86c45580b47 + } + + partition u-boot { + image = "u-boot.itb" + offset = 1041K + partition-type-uuid = 2e54b353-1271-4842-806f-e436d6af6985 + } + + partition rootfs { + image = "rootfs.ext4" + partition-type-uuid = 0fc63daf-8483-4772-8e79-3d69d8477de4 + bootable = true + } +} diff --git a/overlays/keystone/board/sifive/hifive-unmatched/linux-sifive-unmatched-defconfig b/overlays/keystone/board/sifive/hifive-unmatched/linux-sifive-unmatched-defconfig new file mode 100644 index 000000000..811decc38 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/linux-sifive-unmatched-defconfig @@ -0,0 +1,590 @@ +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BPF_SYSCALL=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_BPF=y +CONFIG_NAMESPACES=y +CONFIG_USER_NS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EXPERT=y +# CONFIG_SYSFS_SYSCALL is not set +CONFIG_KALLSYMS_ALL=y +CONFIG_PROFILING=y +CONFIG_SOC_SIFIVE=y +CONFIG_SOC_VIRT=y +CONFIG_SMP=y +CONFIG_HOTPLUG_CPU=y +CONFIG_RISCV_SBI_V01=y +CONFIG_CPU_IDLE=y +CONFIG_KPROBES=y +CONFIG_JUMP_LABEL=y +# CONFIG_STACKPROTECTOR_STRONG is not set +# CONFIG_GCC_PLUGINS is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_BLK_DEV_ZONED=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_CMA=y +CONFIG_USERFAULTFD=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NETLINK_DIAG=y +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_HS=y +CONFIG_BT_LEDS=y +CONFIG_BT_MSFTEXT=y +# CONFIG_BT_DEBUGFS is not set +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_AUTOSUSPEND=y +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_INTEL=y +CONFIG_BT_HCIUART_AG6XX=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_BT_MTKSDIO=m +CONFIG_CFG80211=m +CONFIG_MAC80211=m +CONFIG_MAC80211_DEBUGFS=y +CONFIG_RFKILL=y +CONFIG_NET_9P=y +CONFIG_NET_9P_VIRTIO=y +CONFIG_PCI=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=y +CONFIG_PCIEAER=y +CONFIG_PCIEAER_INJECT=m +CONFIG_PCIE_ECRC=y +CONFIG_PCIE_DPC=y +CONFIG_PCIE_PTM=y +CONFIG_PCI_STUB=y +CONFIG_PCI_PF_STUB=m +CONFIG_PCI_IOV=y +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_SHPC=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PCIE_XILINX=y +CONFIG_PCIE_FU740=y +CONFIG_PCI_SW_SWITCHTEC=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_SPI_NOR=y +CONFIG_OF_OVERLAY=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_NBD=y +CONFIG_ATA_OVER_ETH=m +CONFIG_VIRTIO_BLK=y +CONFIG_BLK_DEV_NVME=y +CONFIG_NVME_MULTIPATH=y +CONFIG_NVME_HWMON=y +CONFIG_NVME_FC=y +CONFIG_NVME_TARGET=y +CONFIG_NVME_TARGET_LOOP=y +CONFIG_NVME_TARGET_FC=y +CONFIG_NVME_TARGET_FCLOOP=y +CONFIG_NVME_TARGET_TCP=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=y +CONFIG_SCSI_VIRTIO=y +CONFIG_ATA=y +CONFIG_SATA_AHCI=y +CONFIG_SATA_MOBILE_LPM_POLICY=3 +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_SATA_INIC162X=m +CONFIG_SATA_ACARD_AHCI=m +CONFIG_SATA_SIL24=m +CONFIG_SATA_QSTOR=m +CONFIG_SATA_SX4=m +CONFIG_ATA_PIIX=y +CONFIG_SATA_MV=y +CONFIG_SATA_NV=m +CONFIG_SATA_PROMISE=m +CONFIG_SATA_SIL=y +CONFIG_SATA_SIS=m +CONFIG_SATA_SVW=m +CONFIG_SATA_ULI=m +CONFIG_SATA_VIA=m +CONFIG_SATA_VITESSE=m +CONFIG_ATA_GENERIC=m +CONFIG_TARGET_CORE=y +CONFIG_TCM_IBLOCK=y +CONFIG_TCM_FILEIO=y +CONFIG_ISCSI_TARGET=y +CONFIG_NETDEVICES=y +CONFIG_VIRTIO_NET=y +CONFIG_MACB=y +CONFIG_E1000E=y +CONFIG_R8169=y +CONFIG_MICROSEMI_PHY=y +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +CONFIG_IWL4965=m +CONFIG_IWL3945=m +CONFIG_IWLEGACY_DEBUG=y +CONFIG_IWLEGACY_DEBUGFS=y +CONFIG_IWLWIFI=m +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m +CONFIG_IWLWIFI_DEBUG=y +CONFIG_IWLWIFI_DEBUGFS=y +# CONFIG_IWLWIFI_DEVICE_TRACING is not set +CONFIG_RTL8180=m +CONFIG_RTL8187=m +CONFIG_RTL8192CE=m +CONFIG_RTL8192SE=m +CONFIG_RTL8192DE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8188EE=m +CONFIG_RTL8192EE=m +CONFIG_RTL8821AE=m +CONFIG_RTL8192CU=m +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTW88=m +CONFIG_RTW88_8822BE=m +CONFIG_RTW88_8822CE=m +CONFIG_RTW88_8723DE=m +CONFIG_MAC80211_HWSIM=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_VIRT_WIFI=m +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_MOUSE_PS2 is not set +CONFIG_INPUT_TABLET=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_USB_COMPOSITE=y +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_VIRTIO_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_VIRTIO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y +CONFIG_I2C_OCORES=y +CONFIG_SPI=y +CONFIG_SPI_SIFIVE=y +CONFIG_SPI_SPIDEV=y +# CONFIG_PTP_1588_CLOCK is not set +CONFIG_GPIOLIB=y +CONFIG_GPIO_SIFIVE=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +CONFIG_POWER_RESET_RESTART=y +CONFIG_SENSORS_LM90=y +CONFIG_THERMAL=y +CONFIG_DRM=y +CONFIG_DRM_RADEON=m +CONFIG_DRM_RADEON_USERPTR=y +CONFIG_DRM_AMDGPU=m +CONFIG_DRM_AMDGPU_SI=y +CONFIG_DRM_AMDGPU_CIK=y +CONFIG_DRM_AMDGPU_USERPTR=y +CONFIG_DRM_AMD_ACP=y +CONFIG_DRM_NOUVEAU=m +CONFIG_DRM_VIRTIO_GPU=y +CONFIG_FB=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_DEBUG=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=y +CONFIG_SND_HRTIMER=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_SEQUENCER_OSS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m +CONFIG_SND_AC97_POWER_SAVE=y +CONFIG_SND_AD1889=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_BT87X=m +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_OXYGEN=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CTXFI=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_INDIGOIOX=m +CONFIG_SND_INDIGODJX=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_FM801=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1724=m +CONFIG_SND_KORG1212=m +CONFIG_SND_LOLA=m +CONFIG_SND_LX6464ES=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_VIRTUOSO=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDA_HWDEP=y +CONFIG_SND_HDA_INPUT_BEEP=y +CONFIG_SND_HDA_INPUT_BEEP_MODE=0 +CONFIG_SND_HDA_PATCH_LOADER=y +CONFIG_SND_HDA_CODEC_REALTEK=m +CONFIG_SND_HDA_CODEC_ANALOG=m +CONFIG_SND_HDA_CODEC_SIGMATEL=m +CONFIG_SND_HDA_CODEC_VIA=m +CONFIG_SND_HDA_CODEC_HDMI=m +CONFIG_SND_HDA_CODEC_CIRRUS=m +CONFIG_SND_HDA_CODEC_CONEXANT=m +CONFIG_SND_HDA_CODEC_CA0110=m +CONFIG_SND_HDA_CODEC_CA0132=m +CONFIG_SND_HDA_CODEC_CMEDIA=m +CONFIG_SND_HDA_CODEC_SI3054=m +CONFIG_SND_HDA_PREALLOC_SIZE=4096 +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_6FIRE=m +CONFIG_SND_USB_HIFACE=m +CONFIG_SND_BCD2000=m +CONFIG_SND_USB_POD=m +CONFIG_SND_USB_PODHD=m +CONFIG_SND_USB_TONEPORT=m +CONFIG_SND_USB_VARIAX=m +CONFIG_SND_SOC=m +CONFIG_SND_SOC_AMD_ACP=m +CONFIG_SND_SOC_AMD_CZ_RT5645_MACH=m +CONFIG_SND_DESIGNWARE_I2S=m +CONFIG_SND_DESIGNWARE_PCM=y +CONFIG_SND_SOC_ADAU1761_I2C=m +CONFIG_SND_SOC_ADAU7002=m +CONFIG_SND_SOC_AK5558=m +CONFIG_SND_SOC_BD28623=m +CONFIG_SND_SOC_CS35L34=m +CONFIG_SND_SOC_CS35L35=m +CONFIG_SND_SOC_CS35L36=m +CONFIG_SND_SOC_CS42L42=m +CONFIG_SND_SOC_CS43130=m +CONFIG_SND_SOC_DMIC=m +CONFIG_SND_SOC_ES7134=m +CONFIG_SND_SOC_MAX98088=m +CONFIG_SND_SOC_MAX98357A=m +CONFIG_SND_SOC_MAX9867=m +CONFIG_SND_SOC_MAX98927=m +CONFIG_SND_SOC_PCM1789_I2C=m +CONFIG_SND_SOC_PCM186X_I2C=m +CONFIG_SND_SOC_PCM3060_I2C=m +CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m +CONFIG_SND_SOC_SPDIF=m +CONFIG_SND_SOC_TAS6424=m +CONFIG_SND_SOC_TDA7419=m +CONFIG_SND_SOC_TLV320AIC32X4_I2C=m +CONFIG_SND_SOC_TSCS42XX=m +CONFIG_SND_SOC_WM8524=m +CONFIG_SND_SOC_MAX9759=m +CONFIG_SND_SOC_NAU8824=m +CONFIG_SND_SIMPLE_CARD=m +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_LED_TRIG=y +CONFIG_USB_ULPI_BUS=m +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_LEDS_TRIGGER_USBPORT=m +CONFIG_USB_MON=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DBGCAP=y +CONFIG_USB_XHCI_PCI_RENESAS=y +CONFIG_USB_XHCI_PLATFORM=m +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_HCD_ISO=y +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=m +CONFIG_USB_TMC=m +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_ENE_UB6250=m +CONFIG_USB_UAS=m +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USBIP_CORE=m +CONFIG_USBIP_VHCI_HCD=m +CONFIG_USBIP_HOST=m +CONFIG_USB_SERIAL=y +CONFIG_USB_SERIAL_CONSOLE=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F8153X=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_UPD78F0730=m +CONFIG_USB_SERIAL_DEBUG=m +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_APPLE_MFI_FASTCHARGE=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_YUREX=m +CONFIG_USB_HUB_USB251XB=m +CONFIG_USB_HSIC_USB3503=m +CONFIG_USB_HSIC_USB4604=m +CONFIG_USB_CHAOSKEY=m +CONFIG_NOP_USB_XCEIV=m +CONFIG_TYPEC=m +CONFIG_TYPEC_TCPM=m +CONFIG_TYPEC_TCPCI=m +CONFIG_TYPEC_TCPCI_MAXIM=m +CONFIG_TYPEC_FUSB302=m +CONFIG_TYPEC_UCSI=m +CONFIG_UCSI_CCG=m +CONFIG_TYPEC_TPS6598X=m +CONFIG_TYPEC_HD3SS3220=m +CONFIG_TYPEC_STUSB160X=m +CONFIG_TYPEC_MUX_PI3USB30532=m +CONFIG_TYPEC_DP_ALTMODE=m +CONFIG_TYPEC_NVIDIA_ALTMODE=m +CONFIG_MMC=y +CONFIG_MMC_SPI=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_CLASS_MULTICOLOR=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_PWM_MULTICOLOR=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LEDS_TRIGGER_MTD=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_ACTIVITY=y +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_TRANSIENT=y +CONFIG_LEDS_TRIGGER_CAMERA=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=y +CONFIG_LEDS_TRIGGER_PATTERN=y +CONFIG_LEDS_TRIGGER_AUDIO=y +CONFIG_EDAC=y +CONFIG_RTC_CLASS=y +CONFIG_DMADEVICES=y +CONFIG_SF_PDMA=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_INPUT=y +CONFIG_VIRTIO_MMIO=y +CONFIG_COMMON_CLK_PWM=y +CONFIG_RPMSG_VIRTIO=y +CONFIG_PWM=y +CONFIG_PWM_SIFIVE=y +CONFIG_USB4=m +CONFIG_EXT3_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_XFS_FS=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_ONLINE_SCRUB=y +CONFIG_BTRFS_FS=y +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_F2FS_FS=y +CONFIG_F2FS_FS_SECURITY=y +CONFIG_FANOTIFY=y +CONFIG_QUOTA=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=m +CONFIG_VIRTIO_FS=m +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_NFS_FS=y +# CONFIG_NFS_V2 is not set +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_SWAP=y +CONFIG_NFS_V4_1=y +CONFIG_NFS_V4_2=y +CONFIG_ROOT_NFS=y +# CONFIG_NFS_DISABLE_UDP_SUPPORT is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_BLOCKLAYOUT=y +CONFIG_NFSD_SCSILAYOUT=y +CONFIG_NFSD_FLEXFILELAYOUT=y +CONFIG_NFSD_V4_2_INTER_SSC=y +CONFIG_9P_FS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_8=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_ISO8859_3=y +CONFIG_NLS_ISO8859_4=y +CONFIG_NLS_ISO8859_5=y +CONFIG_NLS_ISO8859_6=y +CONFIG_NLS_ISO8859_7=y +CONFIG_NLS_ISO8859_9=y +CONFIG_NLS_ISO8859_13=y +CONFIG_NLS_ISO8859_14=y +CONFIG_NLS_ISO8859_15=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_DEV_VIRTIO=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=1024 +CONFIG_CMA_ALIGNMENT=9 +CONFIG_PRINTK_TIME=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_WX=y +# CONFIG_RCU_TRACE is not set +CONFIG_STACK_TRACER=y +CONFIG_SCHED_TRACER=y +CONFIG_HWLAT_TRACER=y +CONFIG_FTRACE_SYSCALLS=y +CONFIG_STRICT_DEVMEM=y +CONFIG_IO_STRICT_DEVMEM=y diff --git a/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0001-perf-cpumap-Make-counter-as-unsigned-ints.patch b/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0001-perf-cpumap-Make-counter-as-unsigned-ints.patch new file mode 100644 index 000000000..2bfc40fe0 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0001-perf-cpumap-Make-counter-as-unsigned-ints.patch @@ -0,0 +1,69 @@ +From d14450f9e0f05ea7177c5404a7a9289352caab77 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Mon, 23 Jan 2023 13:04:10 -0800 +Subject: [PATCH] perf cpumap: Make counter as unsigned ints + +These are loop counters which is inherently unsigned. Therefore make +them unsigned. Moreover it also fixes alloc-size-larger-than +error with gcc-13, where malloc can be called with (-1) due to tmp_len +being an int type. + +Fixes +| cpumap.c:366:20: error: argument 1 range [18446744065119617024, 18446744073709551612] exceeds maximum object size 9223372036854775807 [-Werror=alloc-size-larger-than=] +| 366 | tmp_cpus = malloc(tmp_len * sizeof(struct perf_cpu)); +| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Khem Raj +Cc: Peter Zijlstra +Cc: Ingo Molnar +Cc: Arnaldo Carvalho de Melo +Cc: Mark Rutland +Cc: Alexander Shishkin +Cc: Jiri Olsa +Cc: Namhyung Kim + +Upstream-Status: Submitted [https://lore.kernel.org/linux-perf-users/20230123211310.127532-1-raj.khem@gmail.com/T/#u] +--- + tools/lib/perf/cpumap.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/tools/lib/perf/cpumap.c b/tools/lib/perf/cpumap.c +index 6cd0be7c1bb4..d960880dd903 100644 +--- a/tools/lib/perf/cpumap.c ++++ b/tools/lib/perf/cpumap.c +@@ -351,8 +351,8 @@ struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig, + struct perf_cpu_map *other) + { + struct perf_cpu *tmp_cpus; +- int tmp_len; +- int i, j, k; ++ unsigned int tmp_len; ++ unsigned int i, j, k; + struct perf_cpu_map *merged; + + if (perf_cpu_map__is_subset(orig, other)) +@@ -369,7 +369,7 @@ struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig, + + /* Standard merge algorithm from wikipedia */ + i = j = k = 0; +- while (i < orig->nr && j < other->nr) { ++ while (i < (unsigned int)orig->nr && j < (unsigned int)other->nr) { + if (orig->map[i].cpu <= other->map[j].cpu) { + if (orig->map[i].cpu == other->map[j].cpu) + j++; +@@ -378,10 +378,10 @@ struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig, + tmp_cpus[k++] = other->map[j++]; + } + +- while (i < orig->nr) ++ while (i < (unsigned int)orig->nr) + tmp_cpus[k++] = orig->map[i++]; + +- while (j < other->nr) ++ while (j < (unsigned int)other->nr) + tmp_cpus[k++] = other->map[j++]; + assert(k <= tmp_len); + +-- +2.39.1 + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0001-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch b/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0001-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch new file mode 100644 index 000000000..5b0b2015e --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0001-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch @@ -0,0 +1,56 @@ +From 77f06f908c4e03bf1e2f7d34ccd2f5c72ce22ad4 Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +Date: Wed, 17 Feb 2021 06:06:14 -0800 +Subject: [PATCH 1/3] riscv: sifive: fu740: cpu{1,2,3,4} set compatible to + sifive,u74-mc + +Upstream-Status: Pending +Signed-off-by: David Abdurachmanov +Signed-off-by: Thomas Perrot +--- + arch/riscv/boot/dts/sifive/fu740-c000.dtsi | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi +index 5235fd1c9cb6..b1c403ac563d 100644 +--- a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi ++++ b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi +@@ -39,7 +39,7 @@ cpu0_intc: interrupt-controller { + }; + }; + cpu1: cpu@1 { +- compatible = "sifive,bullet0", "riscv"; ++ compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; +@@ -63,7 +63,7 @@ cpu1_intc: interrupt-controller { + }; + }; + cpu2: cpu@2 { +- compatible = "sifive,bullet0", "riscv"; ++ compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; +@@ -87,7 +87,7 @@ cpu2_intc: interrupt-controller { + }; + }; + cpu3: cpu@3 { +- compatible = "sifive,bullet0", "riscv"; ++ compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; +@@ -111,7 +111,7 @@ cpu3_intc: interrupt-controller { + }; + }; + cpu4: cpu@4 { +- compatible = "sifive,bullet0", "riscv"; ++ compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; +-- +2.39.1 + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0002-riscv-sifive-unmatched-define-PWM-LEDs.patch b/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0002-riscv-sifive-unmatched-define-PWM-LEDs.patch new file mode 100644 index 000000000..2dcdc68f2 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0002-riscv-sifive-unmatched-define-PWM-LEDs.patch @@ -0,0 +1,67 @@ +From 4b38d485f38e51106f8f16a10dd5d84d221ef276 Mon Sep 17 00:00:00 2001 +From: Ruinland Tsai +Date: Mon, 11 Apr 2022 16:16:10 +0800 +Subject: [PATCH 2/3] riscv: sifive: unmatched: define PWM LEDs + +Add D2 (RGB) and D12 (green) LEDs for SiFive Unmatched board. + +Upstream-Status: Pending +Signed-off-by: Ruinland Tsai +Signed-off-by: Thomas Perrot +--- + .../boot/dts/sifive/hifive-unmatched-a00.dts | 39 +++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts +index 07387f9c135c..e4ad9c40abd3 100644 +--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts ++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts +@@ -28,6 +28,45 @@ memory@80000000 { + reg = <0x0 0x80000000 0x4 0x00000000>; + }; + ++ pwmleds { ++ compatible = "pwm-leds"; ++ green-d12 { ++ label = "green:d12"; ++ color = ; ++ pwms = <&pwm0 0 7812500 PWM_POLARITY_INVERTED>; ++ active-low = <1>; ++ max-brightness = <255>; ++ linux,default-trigger = "none"; ++ }; ++ ++ green-d2 { ++ label = "green:d2"; ++ color = ; ++ pwms = <&pwm0 1 7812500 PWM_POLARITY_INVERTED>; ++ active-low = <1>; ++ max-brightness = <255>; ++ linux,default-trigger = "none"; ++ }; ++ ++ red-d2 { ++ label = "red:d2"; ++ color = ; ++ pwms = <&pwm0 2 7812500 PWM_POLARITY_INVERTED>; ++ active-low = <1>; ++ max-brightness = <255>; ++ linux,default-trigger = "none"; ++ }; ++ ++ blue-d2 { ++ label = "blue:d2"; ++ color = ; ++ pwms = <&pwm0 3 7812500 PWM_POLARITY_INVERTED>; ++ active-low = <1>; ++ max-brightness = <255>; ++ linux,default-trigger = "none"; ++ }; ++ }; ++ + hfclk: hfclk { + #clock-cells = <0>; + compatible = "fixed-clock"; +-- +2.39.1 + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0003-Revert-riscv-dts-sifive-unmatched-Link-the-tmp451-wi.patch b/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0003-Revert-riscv-dts-sifive-unmatched-Link-the-tmp451-wi.patch new file mode 100644 index 000000000..8dce74075 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/patches/linux/0003-Revert-riscv-dts-sifive-unmatched-Link-the-tmp451-wi.patch @@ -0,0 +1,29 @@ +From 95f7b206d1ba7b52eb44139e74ade5440b6711c2 Mon Sep 17 00:00:00 2001 +From: Ruinland Tsai +Date: Wed, 13 Apr 2022 17:47:41 +0800 +Subject: [PATCH 3/3] Revert "riscv: dts: sifive unmatched: Link the tmp451 + with its power supply" + +This reverts commit f6f7fbb89bf8dc9132fde55cfe67483138eea880. + +Upstream-Status: Pending +Signed-off-by: Thomas Perrot +--- + arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts +index e4ad9c40abd3..eafede7e1edd 100644 +--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts ++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts +@@ -141,7 +141,6 @@ &i2c0 { + temperature-sensor@4c { + compatible = "ti,tmp451"; + reg = <0x4c>; +- vcc-supply = <&vdd_bpro>; + interrupt-parent = <&gpio>; + interrupts = <6 IRQ_TYPE_LEVEL_LOW>; + }; +-- +2.39.1 + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0001-board-sifive-spl-Initialized-the-PWM-setting-in-the-.patch b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0001-board-sifive-spl-Initialized-the-PWM-setting-in-the-.patch new file mode 100644 index 000000000..9496a8969 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0001-board-sifive-spl-Initialized-the-PWM-setting-in-the-.patch @@ -0,0 +1,107 @@ +From 271e1ea3c38ef49cc0a296a68e5a4e6ea9bd8d35 Mon Sep 17 00:00:00 2001 +From: Vincent Chen +Date: Mon, 15 Nov 2021 03:31:04 -0800 +Subject: [PATCH 1/7] board: sifive: spl: Initialized the PWM setting in the + SPL stage + +LEDs and multiple fans can be controlled by SPL. This patch ensures +that all fans have been enabled in the SPL stage. In addition, the +LED's color will be set to yellow. + +Upstream-Status: Pending +Signed-off-by: Vincent Chen +--- + board/sifive/unmatched/Makefile | 1 + + board/sifive/unmatched/pwm.c | 57 +++++++++++++++++++++++++++++++++ + board/sifive/unmatched/spl.c | 2 ++ + 3 files changed, 60 insertions(+) + create mode 100644 board/sifive/unmatched/pwm.c + +diff --git a/board/sifive/unmatched/Makefile b/board/sifive/unmatched/Makefile +index 1345330089..5df01982e9 100644 +--- a/board/sifive/unmatched/Makefile ++++ b/board/sifive/unmatched/Makefile +@@ -9,3 +9,4 @@ obj-y += spl.o + else + obj-y += unmatched.o + endif ++obj-y += pwm.o +diff --git a/board/sifive/unmatched/pwm.c b/board/sifive/unmatched/pwm.c +new file mode 100644 +index 0000000000..e1cc02310a +--- /dev/null ++++ b/board/sifive/unmatched/pwm.c +@@ -0,0 +1,57 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright (c) 2021, SiFive Inc ++ * ++ * Authors: ++ * Vincent Chen ++ * David Abdurachmanov ++ */ ++ ++#include ++#include ++ ++struct pwm_sifive_regs { ++ unsigned int cfg; /* PWM configuration register */ ++ unsigned int pad0; /* Reserved */ ++ unsigned int cnt; /* PWM count register */ ++ unsigned int pad1; /* Reserved */ ++ unsigned int pwms; /* Scaled PWM count register */ ++ unsigned int pad2; /* Reserved */ ++ unsigned int pad3; /* Reserved */ ++ unsigned int pad4; /* Reserved */ ++ unsigned int cmp0; /* PWM 0 compare register */ ++ unsigned int cmp1; /* PWM 1 compare register */ ++ unsigned int cmp2; /* PWM 2 compare register */ ++ unsigned int cmp3; /* PWM 3 compare register */ ++}; ++ ++#define PWM0_BASE 0x10020000 ++#define PWM1_BASE 0x10021000 ++#define PWM_CFG_INIT 0x1000 ++#define PWM_CMP_ENABLE_VAL 0x0 ++#define PWM_CMP_DISABLE_VAL 0xffff ++ ++void pwm_device_init(void) ++{ ++ struct pwm_sifive_regs *pwm0, *pwm1; ++ pwm0 = (struct pwm_sifive_regs *)PWM0_BASE; ++ pwm1 = (struct pwm_sifive_regs *)PWM1_BASE; ++ writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp0); ++ /* Set the 3-color PWM LEDs to yellow in SPL */ ++ writel(PWM_CMP_ENABLE_VAL, (void *)&pwm0->cmp1); ++ writel(PWM_CMP_ENABLE_VAL, (void *)&pwm0->cmp2); ++ writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp3); ++ writel(PWM_CFG_INIT, (void *)&pwm0->cfg); ++ ++ writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp3); ++ /* Turn on all the fans, (J21), (J23) and (J24), on the unmatched board */ ++ /* The SoC fan(J21) on the rev3 board cannot be controled by PWM_COMP0, ++ so here sets the initial value of PWM_COMP0 as DISABLE */ ++ if (get_pcb_revision_from_eeprom() == PCB_REVISION_REV3) ++ writel(PWM_CMP_DISABLE_VAL, (void *)&pwm1->cmp1); ++ else ++ writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp1); ++ writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp2); ++ writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp3); ++ writel(PWM_CFG_INIT, (void *)&pwm1->cfg); ++} +diff --git a/board/sifive/unmatched/spl.c b/board/sifive/unmatched/spl.c +index 7c0beedc08..f3a661a81e 100644 +--- a/board/sifive/unmatched/spl.c ++++ b/board/sifive/unmatched/spl.c +@@ -90,6 +90,8 @@ int spl_board_init_f(void) + goto end; + } + ++ pwm_device_init(); ++ + ret = spl_gemgxl_init(); + if (ret) { + debug("Gigabit ethernet PHY (VSC8541) init failed: %d\n", ret); +-- +2.34.1 + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0002-board-sifive-Set-LED-s-color-to-purple-in-the-U-boot.patch b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0002-board-sifive-Set-LED-s-color-to-purple-in-the-U-boot.patch new file mode 100644 index 000000000..aa7648219 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0002-board-sifive-Set-LED-s-color-to-purple-in-the-U-boot.patch @@ -0,0 +1,71 @@ +From 9e276ec1e5467942798d007884bae0258d31a004 Mon Sep 17 00:00:00 2001 +From: Vincent Chen +Date: Mon, 24 Jan 2022 02:42:02 -0800 +Subject: [PATCH 2/7] board: sifive: Set LED's color to purple in the U-boot + stage + +Set LED's color to purple in the U-boot stage. Because there are still +some functions to be executed before board_early_init_f(), it means +the LED's is not changed to purple instantly when entering the U-boot +stage. + +Upstream-Status: Pending +Signed-off-by: Vincent Chen +--- + board/sifive/unmatched/pwm.c | 7 +++++++ + board/sifive/unmatched/unmatched.c | 6 ++++++ + configs/sifive_unmatched_defconfig | 1 + + 3 files changed, 14 insertions(+) + +diff --git a/board/sifive/unmatched/pwm.c b/board/sifive/unmatched/pwm.c +index e1cc02310a..bd67672c22 100644 +--- a/board/sifive/unmatched/pwm.c ++++ b/board/sifive/unmatched/pwm.c +@@ -36,6 +36,7 @@ void pwm_device_init(void) + struct pwm_sifive_regs *pwm0, *pwm1; + pwm0 = (struct pwm_sifive_regs *)PWM0_BASE; + pwm1 = (struct pwm_sifive_regs *)PWM1_BASE; ++#ifdef CONFIG_SPL_BUILD + writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp0); + /* Set the 3-color PWM LEDs to yellow in SPL */ + writel(PWM_CMP_ENABLE_VAL, (void *)&pwm0->cmp1); +@@ -54,4 +55,10 @@ void pwm_device_init(void) + writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp2); + writel(PWM_CMP_ENABLE_VAL, (void *)&pwm1->cmp3); + writel(PWM_CFG_INIT, (void *)&pwm1->cfg); ++#else ++ /* Set the 3-color PWM LEDs to purple in U-boot */ ++ writel(PWM_CMP_DISABLE_VAL, (void *)&pwm0->cmp1); ++ writel(PWM_CMP_ENABLE_VAL, (void *)&pwm0->cmp2); ++ writel(PWM_CMP_ENABLE_VAL, (void *)&pwm0->cmp3); ++#endif + } +diff --git a/board/sifive/unmatched/unmatched.c b/board/sifive/unmatched/unmatched.c +index 6295deeae2..30c082d001 100644 +--- a/board/sifive/unmatched/unmatched.c ++++ b/board/sifive/unmatched/unmatched.c +@@ -22,6 +22,12 @@ void *board_fdt_blob_setup(int *err) + return (ulong *)&_end; + } + ++int board_early_init_f(void) ++{ ++ pwm_device_init(); ++ return 0; ++} ++ + int board_init(void) + { + /* enable all cache ways */ +diff --git a/configs/sifive_unmatched_defconfig b/configs/sifive_unmatched_defconfig +index ffae8655c9..a34c8837d4 100644 +--- a/configs/sifive_unmatched_defconfig ++++ b/configs/sifive_unmatched_defconfig +@@ -62,3 +62,4 @@ CONFIG_DM_SCSI=y + CONFIG_USB=y + CONFIG_USB_XHCI_HCD=y + CONFIG_USB_XHCI_PCI=y ++CONFIG_BOARD_EARLY_INIT_F=y +-- +2.34.1 + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0003-board-sifive-Set-LED-s-color-to-blue-before-jumping-.patch b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0003-board-sifive-Set-LED-s-color-to-blue-before-jumping-.patch new file mode 100644 index 000000000..b1f2b2938 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0003-board-sifive-Set-LED-s-color-to-blue-before-jumping-.patch @@ -0,0 +1,37 @@ +From 0ac451c97241ef859bc95d1d83088387fe569f98 Mon Sep 17 00:00:00 2001 +From: Vincent Chen +Date: Mon, 15 Nov 2021 03:39:07 -0800 +Subject: [PATCH 3/7] board: sifive: Set LED's color to blue before jumping to + Linux + +The LED's color wil be changed from purple to blue before executing +the sysboot command. Because the sysboot command includes the image loading +from the boot partition, It means the LED's color is blue when executing +"Retrieving file: /Image.gz". + +Upstream-Status: Pending +Signed-off-by: Vincent Chen +--- + include/configs/sifive-unmatched.h | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/include/configs/sifive-unmatched.h b/include/configs/sifive-unmatched.h +index 74150b7d4b..78d83a098c 100644 +--- a/include/configs/sifive-unmatched.h ++++ b/include/configs/sifive-unmatched.h +@@ -48,6 +48,11 @@ + "type_guid_gpt_system=" TYPE_GUID_SYSTEM "\0" \ + "partitions=" PARTS_DEFAULT "\0" \ + "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \ +- BOOTENV ++ "setled_blue=mw.l 0x10020024 0x0000ffff; mw.l 0x10020028 0x0000ffff; mw.l 0x1002002c 0x0\0" \ ++ BOOTENV \ ++ "boot_extlinux=" \ ++ "run setled_blue; " \ ++ "sysboot ${devtype} ${devnum}:${distro_bootpart} any " \ ++ "${scriptaddr} ${prefix}${boot_syslinux_conf};\0" + + #endif /* __SIFIVE_UNMATCHED_H */ +-- +2.34.1 + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0004-board-sifive-spl-Set-remote-thermal-of-TMP451-to-85-.patch b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0004-board-sifive-spl-Set-remote-thermal-of-TMP451-to-85-.patch new file mode 100644 index 000000000..05ba54f35 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0004-board-sifive-spl-Set-remote-thermal-of-TMP451-to-85-.patch @@ -0,0 +1,112 @@ +From b148ef5fdb182fdccee7e10d7abd8ebffd43a79f Mon Sep 17 00:00:00 2001 +From: Vincent Chen +Date: Mon, 24 Jan 2022 02:57:40 -0800 +Subject: [PATCH 4/7] board: sifive: spl: Set remote thermal of TMP451 to 85 + deg C for the unmatched board + +For TMP451 on the unmatched board, the default value of the remote +thermal threshold is 108 deg C. This commit initilizes it to 85 deg C at SPL. + +Upstream-Status: Pending +Signed-off-by: Vincent Chen +--- + board/sifive/unmatched/spl.c | 29 +++++++++++++++++++++++++++++ + drivers/misc/Kconfig | 10 ++++++++++ + include/configs/sifive-unmatched.h | 4 ++++ + 3 files changed, 43 insertions(+) + +diff --git a/board/sifive/unmatched/spl.c b/board/sifive/unmatched/spl.c +index f3a661a81e..05ba59160a 100644 +--- a/board/sifive/unmatched/spl.c ++++ b/board/sifive/unmatched/spl.c +@@ -10,6 +10,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -26,6 +28,27 @@ + #define MODE_SELECT_SD 0xb + #define MODE_SELECT_MASK GENMASK(3, 0) + ++#define TMP451_REMOTE_THERM_LIMIT_REG_OFFSET 0x19 ++#define TMP451_REMOTE_THERM_LIMIT_INIT_VALUE 0x55 ++ ++static inline int init_tmp451_remote_therm_limit(void) ++{ ++ struct udevice *dev; ++ unsigned char r_therm_limit = TMP451_REMOTE_THERM_LIMIT_INIT_VALUE; ++ int ret; ++ ++ ret = i2c_get_chip_for_busnum(CONFIG_SYS_TMP451_BUS_NUM, ++ CONFIG_SYS_I2C_TMP451_ADDR, ++ CONFIG_SYS_I2C_TMP451_ADDR_LEN, ++ &dev); ++ ++ if (!ret) ++ ret = dm_i2c_write(dev, TMP451_REMOTE_THERM_LIMIT_REG_OFFSET, ++ &r_therm_limit, ++ sizeof(unsigned char)); ++ return ret; ++} ++ + static inline int spl_reset_device_by_gpio(const char *label, int pin, int low_width) + { + int ret; +@@ -92,6 +115,12 @@ int spl_board_init_f(void) + + pwm_device_init(); + ++ ret = init_tmp451_remote_therm_limit(); ++ if (ret) { ++ debug("TMP451 remote THERM limit init failed: %d\n", ret); ++ goto end; ++ } ++ + ret = spl_gemgxl_init(); + if (ret) { + debug("Gigabit ethernet PHY (VSC8541) init failed: %d\n", ret); +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 04460f1acb..77d36ed0c5 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -557,8 +557,18 @@ config SYS_I2C_EEPROM_ADDR + depends on ID_EEPROM || I2C_EEPROM || SPL_I2C_EEPROM || CMD_EEPROM || ENV_IS_IN_EEPROM + default 0 + ++config SYS_I2C_TMP451_ADDR ++ hex "Chip address of the TMP451 device" ++ default 0 ++ + if I2C_EEPROM + ++config SYS_I2C_TMP451_ADDR_LEN ++ int "Length in bytes of the TMP451 memory array address" ++ default 1 ++ help ++ Note: This is NOT the chip address length! ++ + config SYS_I2C_EEPROM_ADDR_OVERFLOW + hex "EEPROM Address Overflow" + default 0x0 +diff --git a/include/configs/sifive-unmatched.h b/include/configs/sifive-unmatched.h +index 78d83a098c..5e8fab031a 100644 +--- a/include/configs/sifive-unmatched.h ++++ b/include/configs/sifive-unmatched.h +@@ -13,6 +13,10 @@ + + #define CFG_SYS_SDRAM_BASE 0x80000000 + ++#define CONFIG_SYS_TMP451_BUS_NUM 0 ++#define CONFIG_SYS_I2C_TMP451_ADDR 0x4c ++#define CONFIG_SYS_I2C_TMP451_ADDR_LEN 0x1 ++ + /* Environment options */ + + #define BOOT_TARGET_DEVICES(func) \ +-- +2.34.1 + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0005-riscv-dts-Add-few-PMU-events.patch b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0005-riscv-dts-Add-few-PMU-events.patch new file mode 100644 index 000000000..780d20f75 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0005-riscv-dts-Add-few-PMU-events.patch @@ -0,0 +1,42 @@ +From 2aa15bc3e739943d1607ff5b4e6ce7529bed2ef6 Mon Sep 17 00:00:00 2001 +From: Atish Patra +Date: Mon, 25 Oct 2021 11:35:41 -0700 +Subject: [PATCH 5/7] riscv: dts: Add few PMU events + +fu740 has 2 HPM counters and many HPM events defined in the fu740 manual[1]. +This patch adds some of these events and their mapping as per the +OpenSBI PMU DT binding for now. + +[1]https://sifive.cdn.prismic.io/sifive/de1491e5-077c-461d-9605-e8a0ce57337d_fu740-c000-manual-v1p3.pdf + +Upstream-Status: Pending +Signed-off-by: Atish Patra +--- + arch/riscv/dts/fu740-c000.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/arch/riscv/dts/fu740-c000.dtsi b/arch/riscv/dts/fu740-c000.dtsi +index 7b77c13496..ea634a3b4c 100644 +--- a/arch/riscv/dts/fu740-c000.dtsi ++++ b/arch/riscv/dts/fu740-c000.dtsi +@@ -140,6 +140,17 @@ + #size-cells = <2>; + compatible = "simple-bus"; + ranges; ++ pmu { ++ compatible = "riscv,pmu"; ++ riscv,raw-event-to-mhpmcounters = <0x00000000 0x200 0x18 ++ 0x00000000 0x400 0x18 ++ 0x00000000 0x800 0x18>; ++ riscv,event-to-mhpmcounters = <0x05 0x06 0x18 ++ 0x10009 0x10009 0x18>; ++ riscv,event-to-mhpmevent = <0x05 0x00000000 0x4000 ++ 0x06 0x00000000 0x4001 ++ 0x10008 0x00000000 0x102>; ++ }; + plic0: interrupt-controller@c000000 { + #interrupt-cells = <1>; + #address-cells = <0>; +-- +2.34.1 + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0006-implement-keystone-secure-boot.patch b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0006-implement-keystone-secure-boot.patch new file mode 100644 index 000000000..ea1a8f325 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0006-implement-keystone-secure-boot.patch @@ -0,0 +1,89 @@ +From 7fb062c8ab1bacbcfcc64cfb9ad6a84d4ae91854 Mon Sep 17 00:00:00 2001 +From: Akihiro Saiki +Date: Thu, 16 Nov 2023 00:30:28 +0900 +Subject: [PATCH 6/7] implement keystone secure boot + +--- + arch/riscv/Kconfig | 24 ++++++++++++++++++++++++ + arch/riscv/lib/Makefile | 6 ++++++ + common/spl/spl_opensbi.c | 10 ++++++++++ + 3 files changed, 40 insertions(+) + +diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig +index f6ed05906a..c99d74a7ab 100644 +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -405,4 +405,28 @@ config TPL_USE_ARCH_MEMSET + + endmenu + ++config SPL_KEYSTONE_SECUREBOOT ++ bool "Secureboot for keystone enclave" ++ default n ++ depends on SPL && SPL_OPENSBI ++ help ++ Enable secureboot feature for keystone enclave. ++ This measure the SM binary and create keypair. ++ ++config SPL_KEYSTONE_USE_TEST_KEYS ++ bool "Use test keys in keystone secureboot" ++ default y ++ depends on SPL_KEYSTONE_SECUREBOOT ++ help ++ Use embedded test keys for keystone secureboot feature. ++ On the practical environment, the platform needs to provide ++ secure keystore. TEST USE ONLY. ++ ++config SPL_KEYSTONE_USE_RNG ++ bool "Use hardware rng to generate random number" ++ default n ++ depends on SPL_KEYSTONE_SECUREBOOT && DM_RNG ++ help ++ Use hardware rng device to generate random for keypair creation ++ + endmenu +diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile +index e5a81ba722..3ae18c7e16 100644 +--- a/arch/riscv/lib/Makefile ++++ b/arch/riscv/lib/Makefile +@@ -44,3 +44,9 @@ obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMMOVE) += memmove.o + obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMCPY) += memcpy.o + + obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o ++ ++# For Keystone Enclave ++ifdef CONFIG_SPL_BUILD ++obj-$(CONFIG_SPL_KEYSTONE_SECUREBOOT) += keystone/ ++endif ++ +diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c +index b0f40076c3..5d328c0789 100644 +--- a/common/spl/spl_opensbi.c ++++ b/common/spl/spl_opensbi.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + DECLARE_GLOBAL_DATA_PTR; + +@@ -66,6 +67,15 @@ void spl_invoke_opensbi(struct spl_image_info *spl_image) + if (ret) + ret = fit_image_get_load(spl_image->fdt_addr, uboot_node, &uboot_entry); + ++ /* Prepare for Keystone SM */ ++#if CONFIG_IS_ENABLED(KEYSTONE_SECUREBOOT) ++ ret = keystone_init(); ++ if (ret < 0) { ++ pr_err("Failed to prepare keystone sm\n"); ++ hang(); ++ } ++#endif ++ + /* Prepare opensbi_info object */ + opensbi_info.magic = FW_DYNAMIC_INFO_MAGIC_VALUE; + opensbi_info.version = FW_DYNAMIC_INFO_VERSION; +-- +2.34.1 + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0007-keystone-prefer-mmc-boot-for-unmatched.patch b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0007-keystone-prefer-mmc-boot-for-unmatched.patch new file mode 100644 index 000000000..3d09f718b --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/patches/uboot/0007-keystone-prefer-mmc-boot-for-unmatched.patch @@ -0,0 +1,28 @@ +From 5ab2e687c5ba9ff45af57f29e4973da40e4914cf Mon Sep 17 00:00:00 2001 +From: Akihiro Saiki +Date: Thu, 16 Nov 2023 00:31:32 +0900 +Subject: [PATCH 7/7] keystone: prefer mmc boot for unmatched + +--- + include/configs/sifive-unmatched.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/configs/sifive-unmatched.h b/include/configs/sifive-unmatched.h +index 5e8fab031a..f73d1a231e 100644 +--- a/include/configs/sifive-unmatched.h ++++ b/include/configs/sifive-unmatched.h +@@ -20,10 +20,10 @@ + /* Environment options */ + + #define BOOT_TARGET_DEVICES(func) \ ++ func(MMC, mmc, 0) \ + func(NVME, nvme, 0) \ + func(NVME, nvme, 1) \ + func(USB, usb, 0) \ +- func(MMC, mmc, 0) \ + func(SCSI, scsi, 0) \ + func(PXE, pxe, na) \ + func(DHCP, dhcp, na) +-- +2.34.1 + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/post-build.sh b/overlays/keystone/board/sifive/hifive-unmatched/post-build.sh new file mode 100755 index 000000000..c8f4a1f1b --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/post-build.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +FUSDK_VER="2023.08.00" + +# Copy extlinux config +mkdir -p $TARGET_DIR/boot/extlinux +cp $BR2_EXTERNAL_KEYSTONE_PATH/board/sifive/hifive-unmatched/extlinux.conf $TARGET_DIR/boot/extlinux/extlinux.conf + +# Install udev rules & systemd units +mkdir -p $TARGET_DIR/usr/lib/systemd/system +mkdir -p $TARGET_DIR/etc/udev/rules.d +wget -P "${TARGET_DIR}/etc/udev/rules.d" "https://raw.githubusercontent.com/sifive/freedom-u-sdk/${FUSDK_VER}/recipes-sifive/unmatched-udev-rules/files/unmatched/99-pwm-leds.rules" +wget -P "${TARGET_DIR}/usr/lib/systemd/system" "https://raw.githubusercontent.com/sifive/freedom-u-sdk/${FUSDK_VER}/recipes-sifive/unmatched-systemd-units/files/led-bootstate-green.service" +wget -P "${TARGET_DIR}/usr/lib/systemd/system" "https://raw.githubusercontent.com/sifive/freedom-u-sdk/${FUSDK_VER}/recipes-sifive/unmatched-systemd-units/files/led-bootstate-green.timer" diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone.h b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone.h new file mode 100644 index 000000000..addddeaf3 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone.h @@ -0,0 +1,5 @@ +/* + * keystone.h + */ + +int keystone_init(void); \ No newline at end of file diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/Makefile b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/Makefile new file mode 100644 index 000000000..024a60b80 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/Makefile @@ -0,0 +1,3 @@ +# Keystone Secure Boot +obj-y += keystone.o sha3/ ed25519/ + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/LICENSE b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/LICENSE new file mode 100644 index 000000000..8a573d83a --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/LICENSE @@ -0,0 +1,17 @@ +Copyright (c) 2015 Orson Peters , altered by Ilia Lebedev + +This software is provided 'as-is', without any express or implied warranty. In no event will the +authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial +applications, and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the + original software. If you use this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as + being the original software. + +3. This notice may not be removed or altered from any source distribution. + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/Makefile b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/Makefile new file mode 100644 index 000000000..6e8ae2fac --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/Makefile @@ -0,0 +1 @@ +obj-y += fe.o ge.o keypair.o sc.o sign.o verify.o \ No newline at end of file diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ed25519.h b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ed25519.h new file mode 100644 index 000000000..b5b1560dc --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ed25519.h @@ -0,0 +1,39 @@ +#ifndef ED25519_H +#define ED25519_H + +#include + +#if defined(_WIN32) + #if defined(ED25519_BUILD_DLL) + #define ED25519_DECLSPEC __declspec(dllexport) + #elif defined(ED25519_DLL) + #define ED25519_DECLSPEC __declspec(dllimport) + #else + #define ED25519_DECLSPEC + #endif +#else + #define ED25519_DECLSPEC +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ED25519_NO_SEED +int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed); +#endif + +void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed); +void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key); +int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key); + +//void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); +//void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fe.c b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fe.c new file mode 100644 index 000000000..2105eb7b2 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fe.c @@ -0,0 +1,1491 @@ +#include "fixedint.h" +#include "fe.h" + + +/* + helper functions +*/ +static uint64_t load_3(const unsigned char *in) { + uint64_t result; + + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + + return result; +} + +static uint64_t load_4(const unsigned char *in) { + uint64_t result; + + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + result |= ((uint64_t) in[3]) << 24; + + return result; +} + + + +/* + h = 0 +*/ + +void fe_0(fe h) { + h[0] = 0; + h[1] = 0; + h[2] = 0; + h[3] = 0; + h[4] = 0; + h[5] = 0; + h[6] = 0; + h[7] = 0; + h[8] = 0; + h[9] = 0; +} + + + +/* + h = 1 +*/ + +void fe_1(fe h) { + h[0] = 1; + h[1] = 0; + h[2] = 0; + h[3] = 0; + h[4] = 0; + h[5] = 0; + h[6] = 0; + h[7] = 0; + h[8] = 0; + h[9] = 0; +} + + + +/* + h = f + g + Can overlap h with f or g. + + Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + + Postconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +void fe_add(fe h, const fe f, const fe g) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t h0 = f0 + g0; + int32_t h1 = f1 + g1; + int32_t h2 = f2 + g2; + int32_t h3 = f3 + g3; + int32_t h4 = f4 + g4; + int32_t h5 = f5 + g5; + int32_t h6 = f6 + g6; + int32_t h7 = f7 + g7; + int32_t h8 = f8 + g8; + int32_t h9 = f9 + g9; + + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + + + +/* + Replace (f,g) with (g,g) if b == 1; + replace (f,g) with (f,g) if b == 0. + + Preconditions: b in {0,1}. +*/ + +void fe_cmov(fe f, const fe g, unsigned int b) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t x0 = f0 ^ g0; + int32_t x1 = f1 ^ g1; + int32_t x2 = f2 ^ g2; + int32_t x3 = f3 ^ g3; + int32_t x4 = f4 ^ g4; + int32_t x5 = f5 ^ g5; + int32_t x6 = f6 ^ g6; + int32_t x7 = f7 ^ g7; + int32_t x8 = f8 ^ g8; + int32_t x9 = f9 ^ g9; + + b = (unsigned int) (- (int) b); /* silence warning */ + x0 &= b; + x1 &= b; + x2 &= b; + x3 &= b; + x4 &= b; + x5 &= b; + x6 &= b; + x7 &= b; + x8 &= b; + x9 &= b; + + f[0] = f0 ^ x0; + f[1] = f1 ^ x1; + f[2] = f2 ^ x2; + f[3] = f3 ^ x3; + f[4] = f4 ^ x4; + f[5] = f5 ^ x5; + f[6] = f6 ^ x6; + f[7] = f7 ^ x7; + f[8] = f8 ^ x8; + f[9] = f9 ^ x9; +} + +/* + Replace (f,g) with (g,f) if b == 1; + replace (f,g) with (f,g) if b == 0. + + Preconditions: b in {0,1}. +*/ + +void fe_cswap(fe f,fe g,unsigned int b) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t x0 = f0 ^ g0; + int32_t x1 = f1 ^ g1; + int32_t x2 = f2 ^ g2; + int32_t x3 = f3 ^ g3; + int32_t x4 = f4 ^ g4; + int32_t x5 = f5 ^ g5; + int32_t x6 = f6 ^ g6; + int32_t x7 = f7 ^ g7; + int32_t x8 = f8 ^ g8; + int32_t x9 = f9 ^ g9; + b = (unsigned int) (- (int) b); /* silence warning */ + x0 &= b; + x1 &= b; + x2 &= b; + x3 &= b; + x4 &= b; + x5 &= b; + x6 &= b; + x7 &= b; + x8 &= b; + x9 &= b; + f[0] = f0 ^ x0; + f[1] = f1 ^ x1; + f[2] = f2 ^ x2; + f[3] = f3 ^ x3; + f[4] = f4 ^ x4; + f[5] = f5 ^ x5; + f[6] = f6 ^ x6; + f[7] = f7 ^ x7; + f[8] = f8 ^ x8; + f[9] = f9 ^ x9; + g[0] = g0 ^ x0; + g[1] = g1 ^ x1; + g[2] = g2 ^ x2; + g[3] = g3 ^ x3; + g[4] = g4 ^ x4; + g[5] = g5 ^ x5; + g[6] = g6 ^ x6; + g[7] = g7 ^ x7; + g[8] = g8 ^ x8; + g[9] = g9 ^ x9; +} + + + +/* + h = f +*/ + +void fe_copy(fe h, const fe f) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + + h[0] = f0; + h[1] = f1; + h[2] = f2; + h[3] = f3; + h[4] = f4; + h[5] = f5; + h[6] = f6; + h[7] = f7; + h[8] = f8; + h[9] = f9; +} + + + +/* + Ignores top bit of h. +*/ + +void fe_frombytes(fe h, const unsigned char *s) { + int64_t h0 = load_4(s); + int64_t h1 = load_3(s + 4) << 6; + int64_t h2 = load_3(s + 7) << 5; + int64_t h3 = load_3(s + 10) << 3; + int64_t h4 = load_3(s + 13) << 2; + int64_t h5 = load_4(s + 16); + int64_t h6 = load_3(s + 20) << 7; + int64_t h7 = load_3(s + 23) << 5; + int64_t h8 = load_3(s + 26) << 4; + int64_t h9 = (load_3(s + 29) & 8388607) << 2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry9 = (h9 + (int64_t) (1 << 24)) >> 25; + h0 += carry9 * 19; + h9 -= carry9 << 25; + carry1 = (h1 + (int64_t) (1 << 24)) >> 25; + h2 += carry1; + h1 -= carry1 << 25; + carry3 = (h3 + (int64_t) (1 << 24)) >> 25; + h4 += carry3; + h3 -= carry3 << 25; + carry5 = (h5 + (int64_t) (1 << 24)) >> 25; + h6 += carry5; + h5 -= carry5 << 25; + carry7 = (h7 + (int64_t) (1 << 24)) >> 25; + h8 += carry7; + h7 -= carry7 << 25; + carry0 = (h0 + (int64_t) (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + carry2 = (h2 + (int64_t) (1 << 25)) >> 26; + h3 += carry2; + h2 -= carry2 << 26; + carry4 = (h4 + (int64_t) (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + carry6 = (h6 + (int64_t) (1 << 25)) >> 26; + h7 += carry6; + h6 -= carry6 << 26; + carry8 = (h8 + (int64_t) (1 << 25)) >> 26; + h9 += carry8; + h8 -= carry8 << 26; + + h[0] = (int32_t) h0; + h[1] = (int32_t) h1; + h[2] = (int32_t) h2; + h[3] = (int32_t) h3; + h[4] = (int32_t) h4; + h[5] = (int32_t) h5; + h[6] = (int32_t) h6; + h[7] = (int32_t) h7; + h[8] = (int32_t) h8; + h[9] = (int32_t) h9; +} + + + +void fe_invert(fe out, const fe z) { + fe t0; + fe t1; + fe t2; + fe t3; + int i; + + fe_sq(t0, z); + + for (i = 1; i < 1; ++i) { + fe_sq(t0, t0); + } + + fe_sq(t1, t0); + + for (i = 1; i < 2; ++i) { + fe_sq(t1, t1); + } + + fe_mul(t1, z, t1); + fe_mul(t0, t0, t1); + fe_sq(t2, t0); + + for (i = 1; i < 1; ++i) { + fe_sq(t2, t2); + } + + fe_mul(t1, t1, t2); + fe_sq(t2, t1); + + for (i = 1; i < 5; ++i) { + fe_sq(t2, t2); + } + + fe_mul(t1, t2, t1); + fe_sq(t2, t1); + + for (i = 1; i < 10; ++i) { + fe_sq(t2, t2); + } + + fe_mul(t2, t2, t1); + fe_sq(t3, t2); + + for (i = 1; i < 20; ++i) { + fe_sq(t3, t3); + } + + fe_mul(t2, t3, t2); + fe_sq(t2, t2); + + for (i = 1; i < 10; ++i) { + fe_sq(t2, t2); + } + + fe_mul(t1, t2, t1); + fe_sq(t2, t1); + + for (i = 1; i < 50; ++i) { + fe_sq(t2, t2); + } + + fe_mul(t2, t2, t1); + fe_sq(t3, t2); + + for (i = 1; i < 100; ++i) { + fe_sq(t3, t3); + } + + fe_mul(t2, t3, t2); + fe_sq(t2, t2); + + for (i = 1; i < 50; ++i) { + fe_sq(t2, t2); + } + + fe_mul(t1, t2, t1); + fe_sq(t1, t1); + + for (i = 1; i < 5; ++i) { + fe_sq(t1, t1); + } + + fe_mul(out, t1, t0); +} + + + +/* + return 1 if f is in {1,3,5,...,q-2} + return 0 if f is in {0,2,4,...,q-1} + + Preconditions: + |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +int fe_isnegative(const fe f) { + unsigned char s[32]; + + fe_tobytes(s, f); + + return s[0] & 1; +} + + + +/* + return 1 if f == 0 + return 0 if f != 0 + + Preconditions: + |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +int fe_isnonzero(const fe f) { + unsigned char s[32]; + unsigned char r; + + fe_tobytes(s, f); + + r = s[0]; + #define F(i) r |= s[i] + F(1); + F(2); + F(3); + F(4); + F(5); + F(6); + F(7); + F(8); + F(9); + F(10); + F(11); + F(12); + F(13); + F(14); + F(15); + F(16); + F(17); + F(18); + F(19); + F(20); + F(21); + F(22); + F(23); + F(24); + F(25); + F(26); + F(27); + F(28); + F(29); + F(30); + F(31); + #undef F + + return r != 0; +} + + + +/* + h = f * g + Can overlap h with f or g. + + Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + + Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. + */ + + /* + Notes on implementation strategy: + + Using schoolbook multiplication. + Karatsuba would save a little in some cost models. + + Most multiplications by 2 and 19 are 32-bit precomputations; + cheaper than 64-bit postcomputations. + + There is one remaining multiplication by 19 in the carry chain; + one *19 precomputation can be merged into this, + but the resulting data flow is considerably less clean. + + There are 12 carries below. + 10 of them are 2-way parallelizable and vectorizable. + Can get away with 11 carries, but then data flow is much deeper. + + With tighter constraints on inputs can squeeze carries into int32. +*/ + +void fe_mul(fe h, const fe f, const fe g) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */ + int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ + int32_t g3_19 = 19 * g3; + int32_t g4_19 = 19 * g4; + int32_t g5_19 = 19 * g5; + int32_t g6_19 = 19 * g6; + int32_t g7_19 = 19 * g7; + int32_t g8_19 = 19 * g8; + int32_t g9_19 = 19 * g9; + int32_t f1_2 = 2 * f1; + int32_t f3_2 = 2 * f3; + int32_t f5_2 = 2 * f5; + int32_t f7_2 = 2 * f7; + int32_t f9_2 = 2 * f9; + int64_t f0g0 = f0 * (int64_t) g0; + int64_t f0g1 = f0 * (int64_t) g1; + int64_t f0g2 = f0 * (int64_t) g2; + int64_t f0g3 = f0 * (int64_t) g3; + int64_t f0g4 = f0 * (int64_t) g4; + int64_t f0g5 = f0 * (int64_t) g5; + int64_t f0g6 = f0 * (int64_t) g6; + int64_t f0g7 = f0 * (int64_t) g7; + int64_t f0g8 = f0 * (int64_t) g8; + int64_t f0g9 = f0 * (int64_t) g9; + int64_t f1g0 = f1 * (int64_t) g0; + int64_t f1g1_2 = f1_2 * (int64_t) g1; + int64_t f1g2 = f1 * (int64_t) g2; + int64_t f1g3_2 = f1_2 * (int64_t) g3; + int64_t f1g4 = f1 * (int64_t) g4; + int64_t f1g5_2 = f1_2 * (int64_t) g5; + int64_t f1g6 = f1 * (int64_t) g6; + int64_t f1g7_2 = f1_2 * (int64_t) g7; + int64_t f1g8 = f1 * (int64_t) g8; + int64_t f1g9_38 = f1_2 * (int64_t) g9_19; + int64_t f2g0 = f2 * (int64_t) g0; + int64_t f2g1 = f2 * (int64_t) g1; + int64_t f2g2 = f2 * (int64_t) g2; + int64_t f2g3 = f2 * (int64_t) g3; + int64_t f2g4 = f2 * (int64_t) g4; + int64_t f2g5 = f2 * (int64_t) g5; + int64_t f2g6 = f2 * (int64_t) g6; + int64_t f2g7 = f2 * (int64_t) g7; + int64_t f2g8_19 = f2 * (int64_t) g8_19; + int64_t f2g9_19 = f2 * (int64_t) g9_19; + int64_t f3g0 = f3 * (int64_t) g0; + int64_t f3g1_2 = f3_2 * (int64_t) g1; + int64_t f3g2 = f3 * (int64_t) g2; + int64_t f3g3_2 = f3_2 * (int64_t) g3; + int64_t f3g4 = f3 * (int64_t) g4; + int64_t f3g5_2 = f3_2 * (int64_t) g5; + int64_t f3g6 = f3 * (int64_t) g6; + int64_t f3g7_38 = f3_2 * (int64_t) g7_19; + int64_t f3g8_19 = f3 * (int64_t) g8_19; + int64_t f3g9_38 = f3_2 * (int64_t) g9_19; + int64_t f4g0 = f4 * (int64_t) g0; + int64_t f4g1 = f4 * (int64_t) g1; + int64_t f4g2 = f4 * (int64_t) g2; + int64_t f4g3 = f4 * (int64_t) g3; + int64_t f4g4 = f4 * (int64_t) g4; + int64_t f4g5 = f4 * (int64_t) g5; + int64_t f4g6_19 = f4 * (int64_t) g6_19; + int64_t f4g7_19 = f4 * (int64_t) g7_19; + int64_t f4g8_19 = f4 * (int64_t) g8_19; + int64_t f4g9_19 = f4 * (int64_t) g9_19; + int64_t f5g0 = f5 * (int64_t) g0; + int64_t f5g1_2 = f5_2 * (int64_t) g1; + int64_t f5g2 = f5 * (int64_t) g2; + int64_t f5g3_2 = f5_2 * (int64_t) g3; + int64_t f5g4 = f5 * (int64_t) g4; + int64_t f5g5_38 = f5_2 * (int64_t) g5_19; + int64_t f5g6_19 = f5 * (int64_t) g6_19; + int64_t f5g7_38 = f5_2 * (int64_t) g7_19; + int64_t f5g8_19 = f5 * (int64_t) g8_19; + int64_t f5g9_38 = f5_2 * (int64_t) g9_19; + int64_t f6g0 = f6 * (int64_t) g0; + int64_t f6g1 = f6 * (int64_t) g1; + int64_t f6g2 = f6 * (int64_t) g2; + int64_t f6g3 = f6 * (int64_t) g3; + int64_t f6g4_19 = f6 * (int64_t) g4_19; + int64_t f6g5_19 = f6 * (int64_t) g5_19; + int64_t f6g6_19 = f6 * (int64_t) g6_19; + int64_t f6g7_19 = f6 * (int64_t) g7_19; + int64_t f6g8_19 = f6 * (int64_t) g8_19; + int64_t f6g9_19 = f6 * (int64_t) g9_19; + int64_t f7g0 = f7 * (int64_t) g0; + int64_t f7g1_2 = f7_2 * (int64_t) g1; + int64_t f7g2 = f7 * (int64_t) g2; + int64_t f7g3_38 = f7_2 * (int64_t) g3_19; + int64_t f7g4_19 = f7 * (int64_t) g4_19; + int64_t f7g5_38 = f7_2 * (int64_t) g5_19; + int64_t f7g6_19 = f7 * (int64_t) g6_19; + int64_t f7g7_38 = f7_2 * (int64_t) g7_19; + int64_t f7g8_19 = f7 * (int64_t) g8_19; + int64_t f7g9_38 = f7_2 * (int64_t) g9_19; + int64_t f8g0 = f8 * (int64_t) g0; + int64_t f8g1 = f8 * (int64_t) g1; + int64_t f8g2_19 = f8 * (int64_t) g2_19; + int64_t f8g3_19 = f8 * (int64_t) g3_19; + int64_t f8g4_19 = f8 * (int64_t) g4_19; + int64_t f8g5_19 = f8 * (int64_t) g5_19; + int64_t f8g6_19 = f8 * (int64_t) g6_19; + int64_t f8g7_19 = f8 * (int64_t) g7_19; + int64_t f8g8_19 = f8 * (int64_t) g8_19; + int64_t f8g9_19 = f8 * (int64_t) g9_19; + int64_t f9g0 = f9 * (int64_t) g0; + int64_t f9g1_38 = f9_2 * (int64_t) g1_19; + int64_t f9g2_19 = f9 * (int64_t) g2_19; + int64_t f9g3_38 = f9_2 * (int64_t) g3_19; + int64_t f9g4_19 = f9 * (int64_t) g4_19; + int64_t f9g5_38 = f9_2 * (int64_t) g5_19; + int64_t f9g6_19 = f9 * (int64_t) g6_19; + int64_t f9g7_38 = f9_2 * (int64_t) g7_19; + int64_t f9g8_19 = f9 * (int64_t) g8_19; + int64_t f9g9_38 = f9_2 * (int64_t) g9_19; + int64_t h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38; + int64_t h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19; + int64_t h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38; + int64_t h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19; + int64_t h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38; + int64_t h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19; + int64_t h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38; + int64_t h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19; + int64_t h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38; + int64_t h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 ; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry0 = (h0 + (int64_t) (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + + carry1 = (h1 + (int64_t) (1 << 24)) >> 25; + h2 += carry1; + h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1 << 24)) >> 25; + h6 += carry5; + h5 -= carry5 << 25; + + carry2 = (h2 + (int64_t) (1 << 25)) >> 26; + h3 += carry2; + h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1 << 25)) >> 26; + h7 += carry6; + h6 -= carry6 << 26; + + carry3 = (h3 + (int64_t) (1 << 24)) >> 25; + h4 += carry3; + h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1 << 24)) >> 25; + h8 += carry7; + h7 -= carry7 << 25; + + carry4 = (h4 + (int64_t) (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1 << 25)) >> 26; + h9 += carry8; + h8 -= carry8 << 26; + + carry9 = (h9 + (int64_t) (1 << 24)) >> 25; + h0 += carry9 * 19; + h9 -= carry9 << 25; + + carry0 = (h0 + (int64_t) (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + + h[0] = (int32_t) h0; + h[1] = (int32_t) h1; + h[2] = (int32_t) h2; + h[3] = (int32_t) h3; + h[4] = (int32_t) h4; + h[5] = (int32_t) h5; + h[6] = (int32_t) h6; + h[7] = (int32_t) h7; + h[8] = (int32_t) h8; + h[9] = (int32_t) h9; +} + + +/* +h = f * 121666 +Can overlap h with f. + +Preconditions: + |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + +Postconditions: + |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +*/ + +void fe_mul121666(fe h, fe f) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int64_t h0 = f0 * (int64_t) 121666; + int64_t h1 = f1 * (int64_t) 121666; + int64_t h2 = f2 * (int64_t) 121666; + int64_t h3 = f3 * (int64_t) 121666; + int64_t h4 = f4 * (int64_t) 121666; + int64_t h5 = f5 * (int64_t) 121666; + int64_t h6 = f6 * (int64_t) 121666; + int64_t h7 = f7 * (int64_t) 121666; + int64_t h8 = f8 * (int64_t) 121666; + int64_t h9 = f9 * (int64_t) 121666; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + + h[0] = (int32_t) h0; + h[1] = (int32_t) h1; + h[2] = (int32_t) h2; + h[3] = (int32_t) h3; + h[4] = (int32_t) h4; + h[5] = (int32_t) h5; + h[6] = (int32_t) h6; + h[7] = (int32_t) h7; + h[8] = (int32_t) h8; + h[9] = (int32_t) h9; +} + + +/* +h = -f + +Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + +Postconditions: + |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +*/ + +void fe_neg(fe h, const fe f) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t h0 = -f0; + int32_t h1 = -f1; + int32_t h2 = -f2; + int32_t h3 = -f3; + int32_t h4 = -f4; + int32_t h5 = -f5; + int32_t h6 = -f6; + int32_t h7 = -f7; + int32_t h8 = -f8; + int32_t h9 = -f9; + + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + + +void fe_pow22523(fe out, const fe z) { + fe t0; + fe t1; + fe t2; + int i; + fe_sq(t0, z); + + for (i = 1; i < 1; ++i) { + fe_sq(t0, t0); + } + + fe_sq(t1, t0); + + for (i = 1; i < 2; ++i) { + fe_sq(t1, t1); + } + + fe_mul(t1, z, t1); + fe_mul(t0, t0, t1); + fe_sq(t0, t0); + + for (i = 1; i < 1; ++i) { + fe_sq(t0, t0); + } + + fe_mul(t0, t1, t0); + fe_sq(t1, t0); + + for (i = 1; i < 5; ++i) { + fe_sq(t1, t1); + } + + fe_mul(t0, t1, t0); + fe_sq(t1, t0); + + for (i = 1; i < 10; ++i) { + fe_sq(t1, t1); + } + + fe_mul(t1, t1, t0); + fe_sq(t2, t1); + + for (i = 1; i < 20; ++i) { + fe_sq(t2, t2); + } + + fe_mul(t1, t2, t1); + fe_sq(t1, t1); + + for (i = 1; i < 10; ++i) { + fe_sq(t1, t1); + } + + fe_mul(t0, t1, t0); + fe_sq(t1, t0); + + for (i = 1; i < 50; ++i) { + fe_sq(t1, t1); + } + + fe_mul(t1, t1, t0); + fe_sq(t2, t1); + + for (i = 1; i < 100; ++i) { + fe_sq(t2, t2); + } + + fe_mul(t1, t2, t1); + fe_sq(t1, t1); + + for (i = 1; i < 50; ++i) { + fe_sq(t1, t1); + } + + fe_mul(t0, t1, t0); + fe_sq(t0, t0); + + for (i = 1; i < 2; ++i) { + fe_sq(t0, t0); + } + + fe_mul(out, t0, z); + return; +} + + +/* +h = f * f +Can overlap h with f. + +Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + +Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +*/ + +/* +See fe_mul.c for discussion of implementation strategy. +*/ + +void fe_sq(fe h, const fe f) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t f0_2 = 2 * f0; + int32_t f1_2 = 2 * f1; + int32_t f2_2 = 2 * f2; + int32_t f3_2 = 2 * f3; + int32_t f4_2 = 2 * f4; + int32_t f5_2 = 2 * f5; + int32_t f6_2 = 2 * f6; + int32_t f7_2 = 2 * f7; + int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ + int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ + int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ + int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ + int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ + int64_t f0f0 = f0 * (int64_t) f0; + int64_t f0f1_2 = f0_2 * (int64_t) f1; + int64_t f0f2_2 = f0_2 * (int64_t) f2; + int64_t f0f3_2 = f0_2 * (int64_t) f3; + int64_t f0f4_2 = f0_2 * (int64_t) f4; + int64_t f0f5_2 = f0_2 * (int64_t) f5; + int64_t f0f6_2 = f0_2 * (int64_t) f6; + int64_t f0f7_2 = f0_2 * (int64_t) f7; + int64_t f0f8_2 = f0_2 * (int64_t) f8; + int64_t f0f9_2 = f0_2 * (int64_t) f9; + int64_t f1f1_2 = f1_2 * (int64_t) f1; + int64_t f1f2_2 = f1_2 * (int64_t) f2; + int64_t f1f3_4 = f1_2 * (int64_t) f3_2; + int64_t f1f4_2 = f1_2 * (int64_t) f4; + int64_t f1f5_4 = f1_2 * (int64_t) f5_2; + int64_t f1f6_2 = f1_2 * (int64_t) f6; + int64_t f1f7_4 = f1_2 * (int64_t) f7_2; + int64_t f1f8_2 = f1_2 * (int64_t) f8; + int64_t f1f9_76 = f1_2 * (int64_t) f9_38; + int64_t f2f2 = f2 * (int64_t) f2; + int64_t f2f3_2 = f2_2 * (int64_t) f3; + int64_t f2f4_2 = f2_2 * (int64_t) f4; + int64_t f2f5_2 = f2_2 * (int64_t) f5; + int64_t f2f6_2 = f2_2 * (int64_t) f6; + int64_t f2f7_2 = f2_2 * (int64_t) f7; + int64_t f2f8_38 = f2_2 * (int64_t) f8_19; + int64_t f2f9_38 = f2 * (int64_t) f9_38; + int64_t f3f3_2 = f3_2 * (int64_t) f3; + int64_t f3f4_2 = f3_2 * (int64_t) f4; + int64_t f3f5_4 = f3_2 * (int64_t) f5_2; + int64_t f3f6_2 = f3_2 * (int64_t) f6; + int64_t f3f7_76 = f3_2 * (int64_t) f7_38; + int64_t f3f8_38 = f3_2 * (int64_t) f8_19; + int64_t f3f9_76 = f3_2 * (int64_t) f9_38; + int64_t f4f4 = f4 * (int64_t) f4; + int64_t f4f5_2 = f4_2 * (int64_t) f5; + int64_t f4f6_38 = f4_2 * (int64_t) f6_19; + int64_t f4f7_38 = f4 * (int64_t) f7_38; + int64_t f4f8_38 = f4_2 * (int64_t) f8_19; + int64_t f4f9_38 = f4 * (int64_t) f9_38; + int64_t f5f5_38 = f5 * (int64_t) f5_38; + int64_t f5f6_38 = f5_2 * (int64_t) f6_19; + int64_t f5f7_76 = f5_2 * (int64_t) f7_38; + int64_t f5f8_38 = f5_2 * (int64_t) f8_19; + int64_t f5f9_76 = f5_2 * (int64_t) f9_38; + int64_t f6f6_19 = f6 * (int64_t) f6_19; + int64_t f6f7_38 = f6 * (int64_t) f7_38; + int64_t f6f8_38 = f6_2 * (int64_t) f8_19; + int64_t f6f9_38 = f6 * (int64_t) f9_38; + int64_t f7f7_38 = f7 * (int64_t) f7_38; + int64_t f7f8_38 = f7_2 * (int64_t) f8_19; + int64_t f7f9_76 = f7_2 * (int64_t) f9_38; + int64_t f8f8_19 = f8 * (int64_t) f8_19; + int64_t f8f9_38 = f8 * (int64_t) f9_38; + int64_t f9f9_38 = f9 * (int64_t) f9_38; + int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; + int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; + int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; + int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38; + int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38; + int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38; + int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19; + int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38; + int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38; + int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + carry0 = (h0 + (int64_t) (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + carry1 = (h1 + (int64_t) (1 << 24)) >> 25; + h2 += carry1; + h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1 << 24)) >> 25; + h6 += carry5; + h5 -= carry5 << 25; + carry2 = (h2 + (int64_t) (1 << 25)) >> 26; + h3 += carry2; + h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1 << 25)) >> 26; + h7 += carry6; + h6 -= carry6 << 26; + carry3 = (h3 + (int64_t) (1 << 24)) >> 25; + h4 += carry3; + h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1 << 24)) >> 25; + h8 += carry7; + h7 -= carry7 << 25; + carry4 = (h4 + (int64_t) (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1 << 25)) >> 26; + h9 += carry8; + h8 -= carry8 << 26; + carry9 = (h9 + (int64_t) (1 << 24)) >> 25; + h0 += carry9 * 19; + h9 -= carry9 << 25; + carry0 = (h0 + (int64_t) (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + h[0] = (int32_t) h0; + h[1] = (int32_t) h1; + h[2] = (int32_t) h2; + h[3] = (int32_t) h3; + h[4] = (int32_t) h4; + h[5] = (int32_t) h5; + h[6] = (int32_t) h6; + h[7] = (int32_t) h7; + h[8] = (int32_t) h8; + h[9] = (int32_t) h9; +} + + +/* +h = 2 * f * f +Can overlap h with f. + +Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + +Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +*/ + +/* +See fe_mul.c for discussion of implementation strategy. +*/ + +void fe_sq2(fe h, const fe f) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t f0_2 = 2 * f0; + int32_t f1_2 = 2 * f1; + int32_t f2_2 = 2 * f2; + int32_t f3_2 = 2 * f3; + int32_t f4_2 = 2 * f4; + int32_t f5_2 = 2 * f5; + int32_t f6_2 = 2 * f6; + int32_t f7_2 = 2 * f7; + int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ + int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ + int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ + int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ + int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ + int64_t f0f0 = f0 * (int64_t) f0; + int64_t f0f1_2 = f0_2 * (int64_t) f1; + int64_t f0f2_2 = f0_2 * (int64_t) f2; + int64_t f0f3_2 = f0_2 * (int64_t) f3; + int64_t f0f4_2 = f0_2 * (int64_t) f4; + int64_t f0f5_2 = f0_2 * (int64_t) f5; + int64_t f0f6_2 = f0_2 * (int64_t) f6; + int64_t f0f7_2 = f0_2 * (int64_t) f7; + int64_t f0f8_2 = f0_2 * (int64_t) f8; + int64_t f0f9_2 = f0_2 * (int64_t) f9; + int64_t f1f1_2 = f1_2 * (int64_t) f1; + int64_t f1f2_2 = f1_2 * (int64_t) f2; + int64_t f1f3_4 = f1_2 * (int64_t) f3_2; + int64_t f1f4_2 = f1_2 * (int64_t) f4; + int64_t f1f5_4 = f1_2 * (int64_t) f5_2; + int64_t f1f6_2 = f1_2 * (int64_t) f6; + int64_t f1f7_4 = f1_2 * (int64_t) f7_2; + int64_t f1f8_2 = f1_2 * (int64_t) f8; + int64_t f1f9_76 = f1_2 * (int64_t) f9_38; + int64_t f2f2 = f2 * (int64_t) f2; + int64_t f2f3_2 = f2_2 * (int64_t) f3; + int64_t f2f4_2 = f2_2 * (int64_t) f4; + int64_t f2f5_2 = f2_2 * (int64_t) f5; + int64_t f2f6_2 = f2_2 * (int64_t) f6; + int64_t f2f7_2 = f2_2 * (int64_t) f7; + int64_t f2f8_38 = f2_2 * (int64_t) f8_19; + int64_t f2f9_38 = f2 * (int64_t) f9_38; + int64_t f3f3_2 = f3_2 * (int64_t) f3; + int64_t f3f4_2 = f3_2 * (int64_t) f4; + int64_t f3f5_4 = f3_2 * (int64_t) f5_2; + int64_t f3f6_2 = f3_2 * (int64_t) f6; + int64_t f3f7_76 = f3_2 * (int64_t) f7_38; + int64_t f3f8_38 = f3_2 * (int64_t) f8_19; + int64_t f3f9_76 = f3_2 * (int64_t) f9_38; + int64_t f4f4 = f4 * (int64_t) f4; + int64_t f4f5_2 = f4_2 * (int64_t) f5; + int64_t f4f6_38 = f4_2 * (int64_t) f6_19; + int64_t f4f7_38 = f4 * (int64_t) f7_38; + int64_t f4f8_38 = f4_2 * (int64_t) f8_19; + int64_t f4f9_38 = f4 * (int64_t) f9_38; + int64_t f5f5_38 = f5 * (int64_t) f5_38; + int64_t f5f6_38 = f5_2 * (int64_t) f6_19; + int64_t f5f7_76 = f5_2 * (int64_t) f7_38; + int64_t f5f8_38 = f5_2 * (int64_t) f8_19; + int64_t f5f9_76 = f5_2 * (int64_t) f9_38; + int64_t f6f6_19 = f6 * (int64_t) f6_19; + int64_t f6f7_38 = f6 * (int64_t) f7_38; + int64_t f6f8_38 = f6_2 * (int64_t) f8_19; + int64_t f6f9_38 = f6 * (int64_t) f9_38; + int64_t f7f7_38 = f7 * (int64_t) f7_38; + int64_t f7f8_38 = f7_2 * (int64_t) f8_19; + int64_t f7f9_76 = f7_2 * (int64_t) f9_38; + int64_t f8f8_19 = f8 * (int64_t) f8_19; + int64_t f8f9_38 = f8 * (int64_t) f9_38; + int64_t f9f9_38 = f9 * (int64_t) f9_38; + int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38; + int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38; + int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19; + int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38; + int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38; + int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38; + int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19; + int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38; + int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38; + int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + h0 += h0; + h1 += h1; + h2 += h2; + h3 += h3; + h4 += h4; + h5 += h5; + h6 += h6; + h7 += h7; + h8 += h8; + h9 += h9; + carry0 = (h0 + (int64_t) (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + carry1 = (h1 + (int64_t) (1 << 24)) >> 25; + h2 += carry1; + h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1 << 24)) >> 25; + h6 += carry5; + h5 -= carry5 << 25; + carry2 = (h2 + (int64_t) (1 << 25)) >> 26; + h3 += carry2; + h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1 << 25)) >> 26; + h7 += carry6; + h6 -= carry6 << 26; + carry3 = (h3 + (int64_t) (1 << 24)) >> 25; + h4 += carry3; + h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1 << 24)) >> 25; + h8 += carry7; + h7 -= carry7 << 25; + carry4 = (h4 + (int64_t) (1 << 25)) >> 26; + h5 += carry4; + h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1 << 25)) >> 26; + h9 += carry8; + h8 -= carry8 << 26; + carry9 = (h9 + (int64_t) (1 << 24)) >> 25; + h0 += carry9 * 19; + h9 -= carry9 << 25; + carry0 = (h0 + (int64_t) (1 << 25)) >> 26; + h1 += carry0; + h0 -= carry0 << 26; + h[0] = (int32_t) h0; + h[1] = (int32_t) h1; + h[2] = (int32_t) h2; + h[3] = (int32_t) h3; + h[4] = (int32_t) h4; + h[5] = (int32_t) h5; + h[6] = (int32_t) h6; + h[7] = (int32_t) h7; + h[8] = (int32_t) h8; + h[9] = (int32_t) h9; +} + + +/* +h = f - g +Can overlap h with f or g. + +Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + +Postconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +void fe_sub(fe h, const fe f, const fe g) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t h0 = f0 - g0; + int32_t h1 = f1 - g1; + int32_t h2 = f2 - g2; + int32_t h3 = f3 - g3; + int32_t h4 = f4 - g4; + int32_t h5 = f5 - g5; + int32_t h6 = f6 - g6; + int32_t h7 = f7 - g7; + int32_t h8 = f8 - g8; + int32_t h9 = f9 - g9; + + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + + + +/* +Preconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + +Write p=2^255-19; q=floor(h/p). +Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). + +Proof: + Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. + Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. + + Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). + Then 0> 25; + q = (h0 + q) >> 26; + q = (h1 + q) >> 25; + q = (h2 + q) >> 26; + q = (h3 + q) >> 25; + q = (h4 + q) >> 26; + q = (h5 + q) >> 25; + q = (h6 + q) >> 26; + q = (h7 + q) >> 25; + q = (h8 + q) >> 26; + q = (h9 + q) >> 25; + /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ + h0 += 19 * q; + /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ + carry0 = h0 >> 26; + h1 += carry0; + h0 -= carry0 << 26; + carry1 = h1 >> 25; + h2 += carry1; + h1 -= carry1 << 25; + carry2 = h2 >> 26; + h3 += carry2; + h2 -= carry2 << 26; + carry3 = h3 >> 25; + h4 += carry3; + h3 -= carry3 << 25; + carry4 = h4 >> 26; + h5 += carry4; + h4 -= carry4 << 26; + carry5 = h5 >> 25; + h6 += carry5; + h5 -= carry5 << 25; + carry6 = h6 >> 26; + h7 += carry6; + h6 -= carry6 << 26; + carry7 = h7 >> 25; + h8 += carry7; + h7 -= carry7 << 25; + carry8 = h8 >> 26; + h9 += carry8; + h8 -= carry8 << 26; + carry9 = h9 >> 25; + h9 -= carry9 << 25; + + /* h10 = carry9 */ + /* + Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. + Have h0+...+2^230 h9 between 0 and 2^255-1; + evidently 2^255 h10-2^255 q = 0. + Goal: Output h0+...+2^230 h9. + */ + s[0] = (unsigned char) (h0 >> 0); + s[1] = (unsigned char) (h0 >> 8); + s[2] = (unsigned char) (h0 >> 16); + s[3] = (unsigned char) ((h0 >> 24) | (h1 << 2)); + s[4] = (unsigned char) (h1 >> 6); + s[5] = (unsigned char) (h1 >> 14); + s[6] = (unsigned char) ((h1 >> 22) | (h2 << 3)); + s[7] = (unsigned char) (h2 >> 5); + s[8] = (unsigned char) (h2 >> 13); + s[9] = (unsigned char) ((h2 >> 21) | (h3 << 5)); + s[10] = (unsigned char) (h3 >> 3); + s[11] = (unsigned char) (h3 >> 11); + s[12] = (unsigned char) ((h3 >> 19) | (h4 << 6)); + s[13] = (unsigned char) (h4 >> 2); + s[14] = (unsigned char) (h4 >> 10); + s[15] = (unsigned char) (h4 >> 18); + s[16] = (unsigned char) (h5 >> 0); + s[17] = (unsigned char) (h5 >> 8); + s[18] = (unsigned char) (h5 >> 16); + s[19] = (unsigned char) ((h5 >> 24) | (h6 << 1)); + s[20] = (unsigned char) (h6 >> 7); + s[21] = (unsigned char) (h6 >> 15); + s[22] = (unsigned char) ((h6 >> 23) | (h7 << 3)); + s[23] = (unsigned char) (h7 >> 5); + s[24] = (unsigned char) (h7 >> 13); + s[25] = (unsigned char) ((h7 >> 21) | (h8 << 4)); + s[26] = (unsigned char) (h8 >> 4); + s[27] = (unsigned char) (h8 >> 12); + s[28] = (unsigned char) ((h8 >> 20) | (h9 << 6)); + s[29] = (unsigned char) (h9 >> 2); + s[30] = (unsigned char) (h9 >> 10); + s[31] = (unsigned char) (h9 >> 18); +} diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fe.h b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fe.h new file mode 100644 index 000000000..b4b62d282 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fe.h @@ -0,0 +1,41 @@ +#ifndef FE_H +#define FE_H + +#include "fixedint.h" + + +/* + fe means field element. + Here the field is \Z/(2^255-19). + An element t, entries t[0]...t[9], represents the integer + t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. + Bounds on each t[i] vary depending on context. +*/ + + +typedef int32_t fe[10]; + + +void fe_0(fe h); +void fe_1(fe h); + +void fe_frombytes(fe h, const unsigned char *s); +void fe_tobytes(unsigned char *s, const fe h); + +void fe_copy(fe h, const fe f); +int fe_isnegative(const fe f); +int fe_isnonzero(const fe f); +void fe_cmov(fe f, const fe g, unsigned int b); +void fe_cswap(fe f, fe g, unsigned int b); + +void fe_neg(fe h, const fe f); +void fe_add(fe h, const fe f, const fe g); +void fe_invert(fe out, const fe z); +void fe_sq(fe h, const fe f); +void fe_sq2(fe h, const fe f); +void fe_mul(fe h, const fe f, const fe g); +void fe_mul121666(fe h, fe f); +void fe_pow22523(fe out, const fe z); +void fe_sub(fe h, const fe f, const fe g); + +#endif diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fixedint.h b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fixedint.h new file mode 100644 index 000000000..9edbe0d87 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/fixedint.h @@ -0,0 +1,73 @@ +/* + Portable header to provide the 32 and 64 bits type. + + Not a compatible replacement for , do not blindly use it as such. +*/ + +#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)) )) && !defined(FIXEDINT_H_INCLUDED) + //#include + #include + #define FIXEDINT_H_INCLUDED + + #if defined(__WATCOMC__) && __WATCOMC__ >= 1250 && !defined(UINT64_C) + #include + #define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) + #endif +#endif + + +#ifndef FIXEDINT_H_INCLUDED + #define FIXEDINT_H_INCLUDED + + #include + + /* (u)int32_t */ + #ifndef uint32_t + #if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long uint32_t; + #elif (UINT_MAX == 0xffffffffUL) + typedef unsigned int uint32_t; + #elif (USHRT_MAX == 0xffffffffUL) + typedef unsigned short uint32_t; + #endif + #endif + + + #ifndef int32_t + #if (LONG_MAX == 0x7fffffffL) + typedef signed long int32_t; + #elif (INT_MAX == 0x7fffffffL) + typedef signed int int32_t; + #elif (SHRT_MAX == 0x7fffffffL) + typedef signed short int32_t; + #endif + #endif + + + /* (u)int64_t */ + #if (defined(__STDC__) && defined(__STDC_VERSION__) && __STDC__ && __STDC_VERSION__ >= 199901L) + typedef long long int64_t; + typedef unsigned long long uint64_t; + + #define UINT64_C(v) v ##ULL + #define INT64_C(v) v ##LL + #elif defined(__GNUC__) + __extension__ typedef long long int64_t; + __extension__ typedef unsigned long long uint64_t; + + #define UINT64_C(v) v ##ULL + #define INT64_C(v) v ##LL + #elif defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__APPLE_CC__) || defined(_LONG_LONG) || defined(_CRAYC) + typedef long long int64_t; + typedef unsigned long long uint64_t; + + #define UINT64_C(v) v ##ULL + #define INT64_C(v) v ##LL + #elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || defined(__alpha) || defined(__DECC) + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + + #define UINT64_C(v) v ##UI64 + #define INT64_C(v) v ##I64 + #endif +#endif diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ge.c b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ge.c new file mode 100644 index 000000000..87c691bff --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ge.c @@ -0,0 +1,467 @@ +#include "ge.h" +#include "precomp_data.h" + + +/* +r = p + q +*/ + +void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { + fe t0; + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->YplusX); + fe_mul(r->Y, r->Y, q->YminusX); + fe_mul(r->T, q->T2d, p->T); + fe_mul(r->X, p->Z, q->Z); + fe_add(t0, r->X, r->X); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_add(r->Z, t0, r->T); + fe_sub(r->T, t0, r->T); +} + + +static void slide(signed char *r, const unsigned char *a) { + int i; + int b; + int k; + + for (i = 0; i < 256; ++i) { + r[i] = 1 & (a[i >> 3] >> (i & 7)); + } + + for (i = 0; i < 256; ++i) + if (r[i]) { + for (b = 1; b <= 6 && i + b < 256; ++b) { + if (r[i + b]) { + if (r[i] + (r[i + b] << b) <= 15) { + r[i] += r[i + b] << b; + r[i + b] = 0; + } else if (r[i] - (r[i + b] << b) >= -15) { + r[i] -= r[i + b] << b; + + for (k = i + b; k < 256; ++k) { + if (!r[k]) { + r[k] = 1; + break; + } + + r[k] = 0; + } + } else { + break; + } + } + } + } +} + +/* +r = a * A + b * B +where a = a[0]+256*a[1]+...+256^31 a[31]. +and b = b[0]+256*b[1]+...+256^31 b[31]. +B is the Ed25519 base point (x,4/5) with x positive. +*/ + +void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) { + signed char aslide[256]; + signed char bslide[256]; + ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ + ge_p1p1 t; + ge_p3 u; + ge_p3 A2; + int i; + slide(aslide, a); + slide(bslide, b); + ge_p3_to_cached(&Ai[0], A); + ge_p3_dbl(&t, A); + ge_p1p1_to_p3(&A2, &t); + ge_add(&t, &A2, &Ai[0]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[1], &u); + ge_add(&t, &A2, &Ai[1]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[2], &u); + ge_add(&t, &A2, &Ai[2]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[3], &u); + ge_add(&t, &A2, &Ai[3]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[4], &u); + ge_add(&t, &A2, &Ai[4]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[5], &u); + ge_add(&t, &A2, &Ai[5]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[6], &u); + ge_add(&t, &A2, &Ai[6]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[7], &u); + ge_p2_0(r); + + for (i = 255; i >= 0; --i) { + if (aslide[i] || bslide[i]) { + break; + } + } + + for (; i >= 0; --i) { + ge_p2_dbl(&t, r); + + if (aslide[i] > 0) { + ge_p1p1_to_p3(&u, &t); + ge_add(&t, &u, &Ai[aslide[i] / 2]); + } else if (aslide[i] < 0) { + ge_p1p1_to_p3(&u, &t); + ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); + } + + if (bslide[i] > 0) { + ge_p1p1_to_p3(&u, &t); + ge_madd(&t, &u, &Bi[bslide[i] / 2]); + } else if (bslide[i] < 0) { + ge_p1p1_to_p3(&u, &t); + ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]); + } + + ge_p1p1_to_p2(r, &t); + } +} + + +static const fe d = { + -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116 +}; + +static const fe sqrtm1 = { + -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482 +}; + +int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s) { + fe u; + fe v; + fe v3; + fe vxx; + fe check; + fe_frombytes(h->Y, s); + fe_1(h->Z); + fe_sq(u, h->Y); + fe_mul(v, u, d); + fe_sub(u, u, h->Z); /* u = y^2-1 */ + fe_add(v, v, h->Z); /* v = dy^2+1 */ + fe_sq(v3, v); + fe_mul(v3, v3, v); /* v3 = v^3 */ + fe_sq(h->X, v3); + fe_mul(h->X, h->X, v); + fe_mul(h->X, h->X, u); /* x = uv^7 */ + fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */ + fe_mul(h->X, h->X, v3); + fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */ + fe_sq(vxx, h->X); + fe_mul(vxx, vxx, v); + fe_sub(check, vxx, u); /* vx^2-u */ + + if (fe_isnonzero(check)) { + fe_add(check, vxx, u); /* vx^2+u */ + + if (fe_isnonzero(check)) { + return -1; + } + + fe_mul(h->X, h->X, sqrtm1); + } + + if (fe_isnegative(h->X) == (s[31] >> 7)) { + fe_neg(h->X, h->X); + } + + fe_mul(h->T, h->X, h->Y); + return 0; +} + + +/* +r = p + q +*/ + +void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { + fe t0; + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->yplusx); + fe_mul(r->Y, r->Y, q->yminusx); + fe_mul(r->T, q->xy2d, p->T); + fe_add(t0, p->Z, p->Z); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_add(r->Z, t0, r->T); + fe_sub(r->T, t0, r->T); +} + + +/* +r = p - q +*/ + +void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { + fe t0; + + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->yminusx); + fe_mul(r->Y, r->Y, q->yplusx); + fe_mul(r->T, q->xy2d, p->T); + fe_add(t0, p->Z, p->Z); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_sub(r->Z, t0, r->T); + fe_add(r->T, t0, r->T); +} + + +/* +r = p +*/ + +void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) { + fe_mul(r->X, p->X, p->T); + fe_mul(r->Y, p->Y, p->Z); + fe_mul(r->Z, p->Z, p->T); +} + + + +/* +r = p +*/ + +void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) { + fe_mul(r->X, p->X, p->T); + fe_mul(r->Y, p->Y, p->Z); + fe_mul(r->Z, p->Z, p->T); + fe_mul(r->T, p->X, p->Y); +} + + +void ge_p2_0(ge_p2 *h) { + fe_0(h->X); + fe_1(h->Y); + fe_1(h->Z); +} + + + +/* +r = 2 * p +*/ + +void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) { + fe t0; + + fe_sq(r->X, p->X); + fe_sq(r->Z, p->Y); + fe_sq2(r->T, p->Z); + fe_add(r->Y, p->X, p->Y); + fe_sq(t0, r->Y); + fe_add(r->Y, r->Z, r->X); + fe_sub(r->Z, r->Z, r->X); + fe_sub(r->X, t0, r->Y); + fe_sub(r->T, r->T, r->Z); +} + + +void ge_p3_0(ge_p3 *h) { + fe_0(h->X); + fe_1(h->Y); + fe_1(h->Z); + fe_0(h->T); +} + + +/* +r = 2 * p +*/ + +void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) { + ge_p2 q; + ge_p3_to_p2(&q, p); + ge_p2_dbl(r, &q); +} + + + +/* +r = p +*/ + +static const fe d2 = { + -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 +}; + +void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) { + fe_add(r->YplusX, p->Y, p->X); + fe_sub(r->YminusX, p->Y, p->X); + fe_copy(r->Z, p->Z); + fe_mul(r->T2d, p->T, d2); +} + + +/* +r = p +*/ + +void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) { + fe_copy(r->X, p->X); + fe_copy(r->Y, p->Y); + fe_copy(r->Z, p->Z); +} + + +void ge_p3_tobytes(unsigned char *s, const ge_p3 *h) { + fe recip; + fe x; + fe y; + fe_invert(recip, h->Z); + fe_mul(x, h->X, recip); + fe_mul(y, h->Y, recip); + fe_tobytes(s, y); + s[31] ^= fe_isnegative(x) << 7; +} + + +static unsigned char equal(signed char b, signed char c) { + unsigned char ub = b; + unsigned char uc = c; + unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ + uint64_t y = x; /* 0: yes; 1..255: no */ + y -= 1; /* large: yes; 0..254: no */ + y >>= 63; /* 1: yes; 0: no */ + return (unsigned char) y; +} + +static unsigned char negative(signed char b) { + uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ + x >>= 63; /* 1: yes; 0: no */ + return (unsigned char) x; +} + +static void cmov(ge_precomp *t, const ge_precomp *u, unsigned char b) { + fe_cmov(t->yplusx, u->yplusx, b); + fe_cmov(t->yminusx, u->yminusx, b); + fe_cmov(t->xy2d, u->xy2d, b); +} + + +static void select(ge_precomp *t, int pos, signed char b) { + ge_precomp minust; + unsigned char bnegative = negative(b); + unsigned char babs = b - (((-bnegative) & b) << 1); + fe_1(t->yplusx); + fe_1(t->yminusx); + fe_0(t->xy2d); + cmov(t, &base[pos][0], equal(babs, 1)); + cmov(t, &base[pos][1], equal(babs, 2)); + cmov(t, &base[pos][2], equal(babs, 3)); + cmov(t, &base[pos][3], equal(babs, 4)); + cmov(t, &base[pos][4], equal(babs, 5)); + cmov(t, &base[pos][5], equal(babs, 6)); + cmov(t, &base[pos][6], equal(babs, 7)); + cmov(t, &base[pos][7], equal(babs, 8)); + fe_copy(minust.yplusx, t->yminusx); + fe_copy(minust.yminusx, t->yplusx); + fe_neg(minust.xy2d, t->xy2d); + cmov(t, &minust, bnegative); +} + +/* +h = a * B +where a = a[0]+256*a[1]+...+256^31 a[31] +B is the Ed25519 base point (x,4/5) with x positive. + +Preconditions: + a[31] <= 127 +*/ + +void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) { + signed char e[64]; + signed char carry; + ge_p1p1 r; + ge_p2 s; + ge_precomp t; + int i; + + for (i = 0; i < 32; ++i) { + e[2 * i + 0] = (a[i] >> 0) & 15; + e[2 * i + 1] = (a[i] >> 4) & 15; + } + + /* each e[i] is between 0 and 15 */ + /* e[63] is between 0 and 7 */ + carry = 0; + + for (i = 0; i < 63; ++i) { + e[i] += carry; + carry = e[i] + 8; + carry >>= 4; + e[i] -= carry << 4; + } + + e[63] += carry; + /* each e[i] is between -8 and 8 */ + ge_p3_0(h); + + for (i = 1; i < 64; i += 2) { + select(&t, i / 2, e[i]); + ge_madd(&r, h, &t); + ge_p1p1_to_p3(h, &r); + } + + ge_p3_dbl(&r, h); + ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); + ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); + ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); + ge_p1p1_to_p3(h, &r); + + for (i = 0; i < 64; i += 2) { + select(&t, i / 2, e[i]); + ge_madd(&r, h, &t); + ge_p1p1_to_p3(h, &r); + } +} + + +/* +r = p - q +*/ + +void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { + fe t0; + + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->YminusX); + fe_mul(r->Y, r->Y, q->YplusX); + fe_mul(r->T, q->T2d, p->T); + fe_mul(r->X, p->Z, q->Z); + fe_add(t0, r->X, r->X); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_sub(r->Z, t0, r->T); + fe_add(r->T, t0, r->T); +} + + +void ge_tobytes(unsigned char *s, const ge_p2 *h) { + fe recip; + fe x; + fe y; + fe_invert(recip, h->Z); + fe_mul(x, h->X, recip); + fe_mul(y, h->Y, recip); + fe_tobytes(s, y); + s[31] ^= fe_isnegative(x) << 7; +} diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ge.h b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ge.h new file mode 100644 index 000000000..17fde2df1 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/ge.h @@ -0,0 +1,74 @@ +#ifndef GE_H +#define GE_H + +#include "fe.h" + + +/* +ge means group element. + +Here the group is the set of pairs (x,y) of field elements (see fe.h) +satisfying -x^2 + y^2 = 1 + d x^2y^2 +where d = -121665/121666. + +Representations: + ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z + ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT + ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T + ge_precomp (Duif): (y+x,y-x,2dxy) +*/ + +typedef struct { + fe X; + fe Y; + fe Z; +} ge_p2; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p3; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p1p1; + +typedef struct { + fe yplusx; + fe yminusx; + fe xy2d; +} ge_precomp; + +typedef struct { + fe YplusX; + fe YminusX; + fe Z; + fe T2d; +} ge_cached; + +void ge_p3_tobytes(unsigned char *s, const ge_p3 *h); +void ge_tobytes(unsigned char *s, const ge_p2 *h); +int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s); + +void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); +void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); +void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b); +void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); +void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); +void ge_scalarmult_base(ge_p3 *h, const unsigned char *a); + +void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p); +void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p); +void ge_p2_0(ge_p2 *h); +void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p); +void ge_p3_0(ge_p3 *h); +void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p); +void ge_p3_to_cached(ge_cached *r, const ge_p3 *p); +void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p); + +#endif diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/keypair.c b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/keypair.c new file mode 100644 index 000000000..9f5cde631 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/keypair.c @@ -0,0 +1,16 @@ +#include "ed25519.h" +#include "../sha3/sha3.h" +#include "ge.h" + + +void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) { + ge_p3 A; + + sha3(seed, 32, private_key, 64); + private_key[0] &= 248; + private_key[31] &= 63; + private_key[31] |= 64; + + ge_scalarmult_base(&A, private_key); + ge_p3_tobytes(public_key, &A); +} diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/precomp_data.h b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/precomp_data.h new file mode 100644 index 000000000..ff23986c3 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/precomp_data.h @@ -0,0 +1,1391 @@ +static const ge_precomp Bi[8] = { + { + { 25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605 }, + { -12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378 }, + { -8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546 }, + }, + { + { 15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024 }, + { 16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574 }, + { 30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357 }, + }, + { + { 10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380 }, + { 4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306 }, + { 19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942 }, + }, + { + { 5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766 }, + { -30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701 }, + { 28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300 }, + }, + { + { -22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877 }, + { -6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951 }, + { 4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784 }, + }, + { + { -25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436 }, + { 25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918 }, + { 23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877 }, + }, + { + { -33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800 }, + { -25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305 }, + { -13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300 }, + }, + { + { -3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876 }, + { -24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619 }, + { -3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683 }, + }, +}; + + +/* base[i][j] = (j+1)*256^i*B */ +static const ge_precomp base[32][8] = { + { + { + { 25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605 }, + { -12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378 }, + { -8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546 }, + }, + { + { -12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303 }, + { -21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081 }, + { 26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697 }, + }, + { + { 15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024 }, + { 16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574 }, + { 30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357 }, + }, + { + { -17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540 }, + { 23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397 }, + { 7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325 }, + }, + { + { 10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380 }, + { 4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306 }, + { 19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942 }, + }, + { + { -15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777 }, + { -8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737 }, + { -18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652 }, + }, + { + { 5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766 }, + { -30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701 }, + { 28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300 }, + }, + { + { 14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726 }, + { -7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955 }, + { 27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425 }, + }, + }, + { + { + { -13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171 }, + { 27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510 }, + { 17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660 }, + }, + { + { -10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639 }, + { 29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963 }, + { 5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950 }, + }, + { + { -27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568 }, + { 12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335 }, + { 25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628 }, + }, + { + { -26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007 }, + { -2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772 }, + { -22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653 }, + }, + { + { 2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567 }, + { 13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686 }, + { 21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372 }, + }, + { + { -13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887 }, + { -23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954 }, + { -29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953 }, + }, + { + { 24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833 }, + { -16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532 }, + { -22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876 }, + }, + { + { 2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268 }, + { 33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214 }, + { 1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038 }, + }, + }, + { + { + { 6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800 }, + { 4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645 }, + { -4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664 }, + }, + { + { 1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933 }, + { -25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182 }, + { -17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222 }, + }, + { + { -18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991 }, + { 20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880 }, + { 9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092 }, + }, + { + { -16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295 }, + { 19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788 }, + { 8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553 }, + }, + { + { -15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026 }, + { 11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347 }, + { -18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033 }, + }, + { + { -23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395 }, + { -27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278 }, + { 1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890 }, + }, + { + { 32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995 }, + { -30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596 }, + { -11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891 }, + }, + { + { 31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060 }, + { 11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608 }, + { -20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606 }, + }, + }, + { + { + { 7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389 }, + { -19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016 }, + { -11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341 }, + }, + { + { -22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505 }, + { 14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553 }, + { -28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655 }, + }, + { + { 15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220 }, + { 12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631 }, + { -4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099 }, + }, + { + { 26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556 }, + { 14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749 }, + { 236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930 }, + }, + { + { 1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391 }, + { 5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253 }, + { 20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066 }, + }, + { + { 24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958 }, + { -11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082 }, + { -28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383 }, + }, + { + { -30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521 }, + { -11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807 }, + { 23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948 }, + }, + { + { 9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134 }, + { -32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455 }, + { 27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629 }, + }, + }, + { + { + { -8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069 }, + { -32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746 }, + { 24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919 }, + }, + { + { 11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837 }, + { 8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906 }, + { -28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771 }, + }, + { + { -25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817 }, + { 10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098 }, + { 10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409 }, + }, + { + { -12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504 }, + { -26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727 }, + { 28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420 }, + }, + { + { -32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003 }, + { -1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605 }, + { -30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384 }, + }, + { + { -26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701 }, + { -23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683 }, + { 29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708 }, + }, + { + { -3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563 }, + { -19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260 }, + { -5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387 }, + }, + { + { -19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672 }, + { 23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686 }, + { -24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665 }, + }, + }, + { + { + { 11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182 }, + { -31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277 }, + { 14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628 }, + }, + { + { -4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474 }, + { -26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539 }, + { -25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822 }, + }, + { + { -10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970 }, + { 19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756 }, + { -24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508 }, + }, + { + { -26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683 }, + { -10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655 }, + { -20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158 }, + }, + { + { -4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125 }, + { -15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839 }, + { -20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664 }, + }, + { + { 27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294 }, + { -18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899 }, + { -11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070 }, + }, + { + { 3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294 }, + { -15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949 }, + { -21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083 }, + }, + { + { 31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420 }, + { -5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940 }, + { 29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396 }, + }, + }, + { + { + { -12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567 }, + { 20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127 }, + { -16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294 }, + }, + { + { -12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887 }, + { 22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964 }, + { 16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195 }, + }, + { + { 9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244 }, + { 24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999 }, + { -1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762 }, + }, + { + { -18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274 }, + { -33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236 }, + { -16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605 }, + }, + { + { -13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761 }, + { -22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884 }, + { -6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482 }, + }, + { + { -24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638 }, + { -11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490 }, + { -32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170 }, + }, + { + { 5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736 }, + { 10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124 }, + { -17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392 }, + }, + { + { 8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029 }, + { 6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048 }, + { 28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958 }, + }, + }, + { + { + { 24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593 }, + { 26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071 }, + { -11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692 }, + }, + { + { 11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687 }, + { -160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441 }, + { -20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001 }, + }, + { + { -938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460 }, + { -19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007 }, + { -21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762 }, + }, + { + { 15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005 }, + { -9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674 }, + { 4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035 }, + }, + { + { 7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590 }, + { -2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957 }, + { -30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812 }, + }, + { + { 33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740 }, + { -18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122 }, + { -27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158 }, + }, + { + { 8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885 }, + { 26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140 }, + { 19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857 }, + }, + { + { 801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155 }, + { 19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260 }, + { 19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483 }, + }, + }, + { + { + { -3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677 }, + { 32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815 }, + { 22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751 }, + }, + { + { -16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203 }, + { -11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208 }, + { 1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230 }, + }, + { + { 16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850 }, + { -21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389 }, + { -9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968 }, + }, + { + { -11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689 }, + { 14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880 }, + { 5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304 }, + }, + { + { 30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632 }, + { -3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412 }, + { 20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566 }, + }, + { + { -20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038 }, + { -26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232 }, + { -1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943 }, + }, + { + { 17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856 }, + { 23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738 }, + { 15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971 }, + }, + { + { -27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718 }, + { -13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697 }, + { -11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883 }, + }, + }, + { + { + { 5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912 }, + { -26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358 }, + { 3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849 }, + }, + { + { 29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307 }, + { -14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977 }, + { -6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335 }, + }, + { + { -29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644 }, + { -22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616 }, + { -27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735 }, + }, + { + { -21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099 }, + { 29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341 }, + { -936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336 }, + }, + { + { -23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646 }, + { 31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425 }, + { -17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388 }, + }, + { + { -31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743 }, + { -16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822 }, + { -8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462 }, + }, + { + { 18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985 }, + { 9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702 }, + { -22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797 }, + }, + { + { 21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293 }, + { 27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100 }, + { 19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688 }, + }, + }, + { + { + { 12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186 }, + { 2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610 }, + { -2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707 }, + }, + { + { 7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220 }, + { 915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025 }, + { 32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044 }, + }, + { + { 32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992 }, + { -4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027 }, + { 21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197 }, + }, + { + { 8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901 }, + { 31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952 }, + { 19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878 }, + }, + { + { -28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390 }, + { 32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730 }, + { 2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730 }, + }, + { + { -19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180 }, + { -30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272 }, + { -15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715 }, + }, + { + { -22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970 }, + { -31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772 }, + { -17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865 }, + }, + { + { 15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750 }, + { 20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373 }, + { 32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348 }, + }, + }, + { + { + { 9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144 }, + { -22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195 }, + { 5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086 }, + }, + { + { -13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684 }, + { -8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518 }, + { -2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233 }, + }, + { + { -5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793 }, + { -2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794 }, + { 580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435 }, + }, + { + { 23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921 }, + { 13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518 }, + { 2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563 }, + }, + { + { 14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278 }, + { -27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024 }, + { 4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030 }, + }, + { + { 10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783 }, + { 27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717 }, + { 6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844 }, + }, + { + { 14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333 }, + { 16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048 }, + { 22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760 }, + }, + { + { -4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760 }, + { -15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757 }, + { -2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112 }, + }, + }, + { + { + { -19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468 }, + { 3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184 }, + { 10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289 }, + }, + { + { 15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066 }, + { 24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882 }, + { 13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226 }, + }, + { + { 16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101 }, + { 29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279 }, + { -6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811 }, + }, + { + { 27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709 }, + { 20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714 }, + { -2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121 }, + }, + { + { 9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464 }, + { 12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847 }, + { 13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400 }, + }, + { + { 4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414 }, + { -15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158 }, + { 17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045 }, + }, + { + { -461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415 }, + { -5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459 }, + { -31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079 }, + }, + { + { 21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412 }, + { -20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743 }, + { -14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836 }, + }, + }, + { + { + { 12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022 }, + { 18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429 }, + { -6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065 }, + }, + { + { 30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861 }, + { 10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000 }, + { -33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101 }, + }, + { + { 32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815 }, + { 29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642 }, + { 10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966 }, + }, + { + { 25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574 }, + { -21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742 }, + { -18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689 }, + }, + { + { 12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020 }, + { -10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772 }, + { 3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982 }, + }, + { + { -14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953 }, + { -16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218 }, + { -17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265 }, + }, + { + { 29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073 }, + { -3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325 }, + { -11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798 }, + }, + { + { -4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870 }, + { -7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863 }, + { -13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927 }, + }, + }, + { + { + { -2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267 }, + { -9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663 }, + { 22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862 }, + }, + { + { -25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673 }, + { 15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943 }, + { 15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020 }, + }, + { + { -4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238 }, + { 11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064 }, + { 14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795 }, + }, + { + { 15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052 }, + { -10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904 }, + { 29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531 }, + }, + { + { -13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979 }, + { -5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841 }, + { 10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431 }, + }, + { + { 10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324 }, + { -31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940 }, + { 10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320 }, + }, + { + { -15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184 }, + { 14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114 }, + { 30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878 }, + }, + { + { 12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784 }, + { -2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091 }, + { -16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585 }, + }, + }, + { + { + { -8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208 }, + { 10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864 }, + { 17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661 }, + }, + { + { 7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233 }, + { 26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212 }, + { -12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525 }, + }, + { + { -24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068 }, + { 9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397 }, + { -8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988 }, + }, + { + { 5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889 }, + { 32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038 }, + { 14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697 }, + }, + { + { 20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875 }, + { -25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905 }, + { -25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656 }, + }, + { + { 11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818 }, + { 27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714 }, + { 10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203 }, + }, + { + { 20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931 }, + { -30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024 }, + { -23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084 }, + }, + { + { -1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204 }, + { 20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817 }, + { 27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667 }, + }, + }, + { + { + { 11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504 }, + { -12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768 }, + { -19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255 }, + }, + { + { 6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790 }, + { 1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438 }, + { -22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333 }, + }, + { + { 17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971 }, + { 31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905 }, + { 29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409 }, + }, + { + { 12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409 }, + { 6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499 }, + { -8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363 }, + }, + { + { 28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664 }, + { -11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324 }, + { -21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940 }, + }, + { + { 13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990 }, + { -17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914 }, + { -25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290 }, + }, + { + { 24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257 }, + { -6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433 }, + { -16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236 }, + }, + { + { -12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045 }, + { 11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093 }, + { -1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347 }, + }, + }, + { + { + { -28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191 }, + { -15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507 }, + { -12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906 }, + }, + { + { 3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018 }, + { -16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109 }, + { -23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926 }, + }, + { + { -24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528 }, + { 8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625 }, + { -32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286 }, + }, + { + { 2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033 }, + { 27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866 }, + { 21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896 }, + }, + { + { 30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075 }, + { 26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347 }, + { -22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437 }, + }, + { + { -5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165 }, + { -18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588 }, + { -32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193 }, + }, + { + { -19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017 }, + { -28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883 }, + { 21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961 }, + }, + { + { 8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043 }, + { 29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663 }, + { -20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362 }, + }, + }, + { + { + { -33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860 }, + { 2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466 }, + { -24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063 }, + }, + { + { -26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997 }, + { -1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295 }, + { -13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369 }, + }, + { + { 9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385 }, + { 18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109 }, + { 2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906 }, + }, + { + { 4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424 }, + { -19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185 }, + { 7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962 }, + }, + { + { -7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325 }, + { 10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593 }, + { 696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404 }, + }, + { + { -11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644 }, + { 17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801 }, + { 26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804 }, + }, + { + { -31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884 }, + { -586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577 }, + { -9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849 }, + }, + { + { 32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473 }, + { -8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644 }, + { -2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319 }, + }, + }, + { + { + { -11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599 }, + { -9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768 }, + { -27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084 }, + }, + { + { -27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328 }, + { -15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369 }, + { 20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920 }, + }, + { + { 12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815 }, + { -32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025 }, + { -21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397 }, + }, + { + { -20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448 }, + { 6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981 }, + { 30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165 }, + }, + { + { 32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501 }, + { 17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073 }, + { -1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861 }, + }, + { + { 14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845 }, + { -1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211 }, + { 18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870 }, + }, + { + { 10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096 }, + { 33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803 }, + { -32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168 }, + }, + { + { 30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965 }, + { -14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505 }, + { 18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598 }, + }, + }, + { + { + { 5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782 }, + { 5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900 }, + { -31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479 }, + }, + { + { -12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208 }, + { 8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232 }, + { 17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719 }, + }, + { + { 16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271 }, + { -4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326 }, + { -8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132 }, + }, + { + { 14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300 }, + { 8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570 }, + { 15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670 }, + }, + { + { -2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994 }, + { -12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913 }, + { 31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317 }, + }, + { + { -25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730 }, + { 842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096 }, + { -4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078 }, + }, + { + { -15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411 }, + { -19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905 }, + { -9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654 }, + }, + { + { -28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870 }, + { -23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498 }, + { 12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579 }, + }, + }, + { + { + { 14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677 }, + { 10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647 }, + { -2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743 }, + }, + { + { -25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468 }, + { 21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375 }, + { -25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155 }, + }, + { + { 6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725 }, + { -12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612 }, + { -10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943 }, + }, + { + { -30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944 }, + { 30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928 }, + { 9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406 }, + }, + { + { 22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139 }, + { -8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963 }, + { -31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693 }, + }, + { + { 1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734 }, + { -448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680 }, + { -24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410 }, + }, + { + { -9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931 }, + { -16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654 }, + { 22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710 }, + }, + { + { 29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180 }, + { -26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684 }, + { -10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895 }, + }, + }, + { + { + { 22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501 }, + { -11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413 }, + { 6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880 }, + }, + { + { -8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874 }, + { 22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962 }, + { -7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899 }, + }, + { + { 21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152 }, + { 9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063 }, + { 7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080 }, + }, + { + { -9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146 }, + { -17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183 }, + { -19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133 }, + }, + { + { -32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421 }, + { -3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622 }, + { -4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197 }, + }, + { + { 2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663 }, + { 31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753 }, + { 4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755 }, + }, + { + { -9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862 }, + { -26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118 }, + { 26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171 }, + }, + { + { 15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380 }, + { 16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824 }, + { 28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270 }, + }, + }, + { + { + { -817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438 }, + { -31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584 }, + { -594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562 }, + }, + { + { 30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471 }, + { 18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610 }, + { 19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269 }, + }, + { + { -30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650 }, + { 14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369 }, + { 19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461 }, + }, + { + { 30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462 }, + { -5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793 }, + { -2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218 }, + }, + { + { -24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226 }, + { 18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019 }, + { -15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037 }, + }, + { + { 31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171 }, + { -17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132 }, + { -28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841 }, + }, + { + { 21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181 }, + { -33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210 }, + { -1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040 }, + }, + { + { 3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935 }, + { 24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105 }, + { -28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814 }, + }, + }, + { + { + { 793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852 }, + { 5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581 }, + { -4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646 }, + }, + { + { 10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844 }, + { 10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025 }, + { 27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453 }, + }, + { + { -23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068 }, + { 4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192 }, + { -17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921 }, + }, + { + { -9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259 }, + { -12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426 }, + { -5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072 }, + }, + { + { -17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305 }, + { 13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832 }, + { 28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943 }, + }, + { + { -16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011 }, + { 24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447 }, + { 17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494 }, + }, + { + { -28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245 }, + { -20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859 }, + { 28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915 }, + }, + { + { 16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707 }, + { 10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848 }, + { -11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224 }, + }, + }, + { + { + { -25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391 }, + { 15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215 }, + { -23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101 }, + }, + { + { 23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713 }, + { 21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849 }, + { -7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930 }, + }, + { + { -29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940 }, + { -21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031 }, + { -17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404 }, + }, + { + { -25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243 }, + { -23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116 }, + { -24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525 }, + }, + { + { -23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509 }, + { -10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883 }, + { 15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865 }, + }, + { + { -3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660 }, + { 4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273 }, + { -28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138 }, + }, + { + { -25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560 }, + { -10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135 }, + { 2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941 }, + }, + { + { -4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739 }, + { 18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756 }, + { -30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819 }, + }, + }, + { + { + { -6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347 }, + { -27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028 }, + { 21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075 }, + }, + { + { 16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799 }, + { -2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609 }, + { -25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817 }, + }, + { + { -23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989 }, + { -30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523 }, + { 4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278 }, + }, + { + { 31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045 }, + { 19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377 }, + { 24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480 }, + }, + { + { 17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016 }, + { 510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426 }, + { 18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525 }, + }, + { + { 13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396 }, + { 9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080 }, + { 12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892 }, + }, + { + { 15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275 }, + { 11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074 }, + { 20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140 }, + }, + { + { -16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717 }, + { -1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101 }, + { 24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127 }, + }, + }, + { + { + { -12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632 }, + { -26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415 }, + { -31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160 }, + }, + { + { 31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876 }, + { 22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625 }, + { -15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478 }, + }, + { + { 27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164 }, + { 26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595 }, + { -7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248 }, + }, + { + { -16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858 }, + { 15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193 }, + { 8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184 }, + }, + { + { -18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942 }, + { -1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635 }, + { 21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948 }, + }, + { + { 11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935 }, + { -25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415 }, + { -15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416 }, + }, + { + { -7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018 }, + { 4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778 }, + { 366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659 }, + }, + { + { -24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385 }, + { 18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503 }, + { 476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329 }, + }, + }, + { + { + { 20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056 }, + { -13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838 }, + { 24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948 }, + }, + { + { -3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691 }, + { -15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118 }, + { -23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517 }, + }, + { + { -20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269 }, + { -6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904 }, + { -23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589 }, + }, + { + { -28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193 }, + { -7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910 }, + { -30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930 }, + }, + { + { -7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667 }, + { 25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481 }, + { -9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876 }, + }, + { + { 22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640 }, + { -8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278 }, + { -21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112 }, + }, + { + { 26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272 }, + { 17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012 }, + { -10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221 }, + }, + { + { 30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046 }, + { 13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345 }, + { -19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310 }, + }, + }, + { + { + { 19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937 }, + { 31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636 }, + { -9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008 }, + }, + { + { -2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429 }, + { -15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576 }, + { 31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066 }, + }, + { + { -9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490 }, + { -12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104 }, + { 33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053 }, + }, + { + { 31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275 }, + { -20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511 }, + { 22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095 }, + }, + { + { -28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439 }, + { 23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939 }, + { -23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424 }, + }, + { + { 2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310 }, + { 3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608 }, + { -32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079 }, + }, + { + { -23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101 }, + { 21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418 }, + { 18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576 }, + }, + { + { 30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356 }, + { 9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996 }, + { -26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099 }, + }, + }, + { + { + { -26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728 }, + { -13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658 }, + { -10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242 }, + }, + { + { -21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001 }, + { -4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766 }, + { 18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373 }, + }, + { + { 26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458 }, + { -17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628 }, + { -13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657 }, + }, + { + { -23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062 }, + { 25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616 }, + { 31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014 }, + }, + { + { 24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383 }, + { -25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814 }, + { -20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718 }, + }, + { + { 30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417 }, + { 2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222 }, + { 33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444 }, + }, + { + { -20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597 }, + { 23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970 }, + { 1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799 }, + }, + { + { -5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647 }, + { 13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511 }, + { -29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032 }, + }, + }, + { + { + { 9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834 }, + { -23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461 }, + { 29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062 }, + }, + { + { -25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516 }, + { -20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547 }, + { -24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240 }, + }, + { + { -17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038 }, + { -33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741 }, + { 16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103 }, + }, + { + { -19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747 }, + { -1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323 }, + { 31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016 }, + }, + { + { -14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373 }, + { 15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228 }, + { -2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141 }, + }, + { + { 16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399 }, + { 11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831 }, + { -185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376 }, + }, + { + { -32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313 }, + { -18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958 }, + { -6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577 }, + }, + { + { -22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743 }, + { 29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684 }, + { -20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476 }, + }, + }, +}; diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sc.c b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sc.c new file mode 100644 index 000000000..ca5bad2ca --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sc.c @@ -0,0 +1,809 @@ +#include "fixedint.h" +#include "sc.h" + +static uint64_t load_3(const unsigned char *in) { + uint64_t result; + + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + + return result; +} + +static uint64_t load_4(const unsigned char *in) { + uint64_t result; + + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + result |= ((uint64_t) in[3]) << 24; + + return result; +} + +/* +Input: + s[0]+256*s[1]+...+256^63*s[63] = s + +Output: + s[0]+256*s[1]+...+256^31*s[31] = s mod l + where l = 2^252 + 27742317777372353535851937790883648493. + Overwrites s in place. +*/ + +void sc_reduce(unsigned char *s) { + int64_t s0 = 2097151 & load_3(s); + int64_t s1 = 2097151 & (load_4(s + 2) >> 5); + int64_t s2 = 2097151 & (load_3(s + 5) >> 2); + int64_t s3 = 2097151 & (load_4(s + 7) >> 7); + int64_t s4 = 2097151 & (load_4(s + 10) >> 4); + int64_t s5 = 2097151 & (load_3(s + 13) >> 1); + int64_t s6 = 2097151 & (load_4(s + 15) >> 6); + int64_t s7 = 2097151 & (load_3(s + 18) >> 3); + int64_t s8 = 2097151 & load_3(s + 21); + int64_t s9 = 2097151 & (load_4(s + 23) >> 5); + int64_t s10 = 2097151 & (load_3(s + 26) >> 2); + int64_t s11 = 2097151 & (load_4(s + 28) >> 7); + int64_t s12 = 2097151 & (load_4(s + 31) >> 4); + int64_t s13 = 2097151 & (load_3(s + 34) >> 1); + int64_t s14 = 2097151 & (load_4(s + 36) >> 6); + int64_t s15 = 2097151 & (load_3(s + 39) >> 3); + int64_t s16 = 2097151 & load_3(s + 42); + int64_t s17 = 2097151 & (load_4(s + 44) >> 5); + int64_t s18 = 2097151 & (load_3(s + 47) >> 2); + int64_t s19 = 2097151 & (load_4(s + 49) >> 7); + int64_t s20 = 2097151 & (load_4(s + 52) >> 4); + int64_t s21 = 2097151 & (load_3(s + 55) >> 1); + int64_t s22 = 2097151 & (load_4(s + 57) >> 6); + int64_t s23 = (load_4(s + 60) >> 3); + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + int64_t carry12; + int64_t carry13; + int64_t carry14; + int64_t carry15; + int64_t carry16; + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + s23 = 0; + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + s22 = 0; + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + s21 = 0; + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + s20 = 0; + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + s19 = 0; + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + s18 = 0; + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry12 = (s12 + (1 << 20)) >> 21; + s13 += carry12; + s12 -= carry12 << 21; + carry14 = (s14 + (1 << 20)) >> 21; + s15 += carry14; + s14 -= carry14 << 21; + carry16 = (s16 + (1 << 20)) >> 21; + s17 += carry16; + s16 -= carry16 << 21; + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 << 21; + carry13 = (s13 + (1 << 20)) >> 21; + s14 += carry13; + s13 -= carry13 << 21; + carry15 = (s15 + (1 << 20)) >> 21; + s16 += carry15; + s15 -= carry15 << 21; + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + s17 = 0; + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + s16 = 0; + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + s15 = 0; + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + s14 = 0; + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + s13 = 0; + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + carry0 = (s0 + (1 << 20)) >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry2 = (s2 + (1 << 20)) >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry4 = (s4 + (1 << 20)) >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry1 = (s1 + (1 << 20)) >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry3 = (s3 + (1 << 20)) >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry5 = (s5 + (1 << 20)) >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 << 21; + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry11 = s11 >> 21; + s12 += carry11; + s11 -= carry11 << 21; + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 << 21; + + s[0] = (unsigned char) (s0 >> 0); + s[1] = (unsigned char) (s0 >> 8); + s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5)); + s[3] = (unsigned char) (s1 >> 3); + s[4] = (unsigned char) (s1 >> 11); + s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2)); + s[6] = (unsigned char) (s2 >> 6); + s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7)); + s[8] = (unsigned char) (s3 >> 1); + s[9] = (unsigned char) (s3 >> 9); + s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4)); + s[11] = (unsigned char) (s4 >> 4); + s[12] = (unsigned char) (s4 >> 12); + s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1)); + s[14] = (unsigned char) (s5 >> 7); + s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6)); + s[16] = (unsigned char) (s6 >> 2); + s[17] = (unsigned char) (s6 >> 10); + s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3)); + s[19] = (unsigned char) (s7 >> 5); + s[20] = (unsigned char) (s7 >> 13); + s[21] = (unsigned char) (s8 >> 0); + s[22] = (unsigned char) (s8 >> 8); + s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5)); + s[24] = (unsigned char) (s9 >> 3); + s[25] = (unsigned char) (s9 >> 11); + s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2)); + s[27] = (unsigned char) (s10 >> 6); + s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7)); + s[29] = (unsigned char) (s11 >> 1); + s[30] = (unsigned char) (s11 >> 9); + s[31] = (unsigned char) (s11 >> 17); +} + + + +/* +Input: + a[0]+256*a[1]+...+256^31*a[31] = a + b[0]+256*b[1]+...+256^31*b[31] = b + c[0]+256*c[1]+...+256^31*c[31] = c + +Output: + s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l + where l = 2^252 + 27742317777372353535851937790883648493. +*/ + +void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) { + int64_t a0 = 2097151 & load_3(a); + int64_t a1 = 2097151 & (load_4(a + 2) >> 5); + int64_t a2 = 2097151 & (load_3(a + 5) >> 2); + int64_t a3 = 2097151 & (load_4(a + 7) >> 7); + int64_t a4 = 2097151 & (load_4(a + 10) >> 4); + int64_t a5 = 2097151 & (load_3(a + 13) >> 1); + int64_t a6 = 2097151 & (load_4(a + 15) >> 6); + int64_t a7 = 2097151 & (load_3(a + 18) >> 3); + int64_t a8 = 2097151 & load_3(a + 21); + int64_t a9 = 2097151 & (load_4(a + 23) >> 5); + int64_t a10 = 2097151 & (load_3(a + 26) >> 2); + int64_t a11 = (load_4(a + 28) >> 7); + int64_t b0 = 2097151 & load_3(b); + int64_t b1 = 2097151 & (load_4(b + 2) >> 5); + int64_t b2 = 2097151 & (load_3(b + 5) >> 2); + int64_t b3 = 2097151 & (load_4(b + 7) >> 7); + int64_t b4 = 2097151 & (load_4(b + 10) >> 4); + int64_t b5 = 2097151 & (load_3(b + 13) >> 1); + int64_t b6 = 2097151 & (load_4(b + 15) >> 6); + int64_t b7 = 2097151 & (load_3(b + 18) >> 3); + int64_t b8 = 2097151 & load_3(b + 21); + int64_t b9 = 2097151 & (load_4(b + 23) >> 5); + int64_t b10 = 2097151 & (load_3(b + 26) >> 2); + int64_t b11 = (load_4(b + 28) >> 7); + int64_t c0 = 2097151 & load_3(c); + int64_t c1 = 2097151 & (load_4(c + 2) >> 5); + int64_t c2 = 2097151 & (load_3(c + 5) >> 2); + int64_t c3 = 2097151 & (load_4(c + 7) >> 7); + int64_t c4 = 2097151 & (load_4(c + 10) >> 4); + int64_t c5 = 2097151 & (load_3(c + 13) >> 1); + int64_t c6 = 2097151 & (load_4(c + 15) >> 6); + int64_t c7 = 2097151 & (load_3(c + 18) >> 3); + int64_t c8 = 2097151 & load_3(c + 21); + int64_t c9 = 2097151 & (load_4(c + 23) >> 5); + int64_t c10 = 2097151 & (load_3(c + 26) >> 2); + int64_t c11 = (load_4(c + 28) >> 7); + int64_t s0; + int64_t s1; + int64_t s2; + int64_t s3; + int64_t s4; + int64_t s5; + int64_t s6; + int64_t s7; + int64_t s8; + int64_t s9; + int64_t s10; + int64_t s11; + int64_t s12; + int64_t s13; + int64_t s14; + int64_t s15; + int64_t s16; + int64_t s17; + int64_t s18; + int64_t s19; + int64_t s20; + int64_t s21; + int64_t s22; + int64_t s23; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + int64_t carry12; + int64_t carry13; + int64_t carry14; + int64_t carry15; + int64_t carry16; + int64_t carry17; + int64_t carry18; + int64_t carry19; + int64_t carry20; + int64_t carry21; + int64_t carry22; + + s0 = c0 + a0 * b0; + s1 = c1 + a0 * b1 + a1 * b0; + s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0; + s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; + s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; + s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; + s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; + s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0; + s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 + a8 * b0; + s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; + s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; + s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; + s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; + s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; + s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3; + s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4; + s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; + s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; + s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; + s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; + s20 = a9 * b11 + a10 * b10 + a11 * b9; + s21 = a10 * b11 + a11 * b10; + s22 = a11 * b11; + s23 = 0; + carry0 = (s0 + (1 << 20)) >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry2 = (s2 + (1 << 20)) >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry4 = (s4 + (1 << 20)) >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry12 = (s12 + (1 << 20)) >> 21; + s13 += carry12; + s12 -= carry12 << 21; + carry14 = (s14 + (1 << 20)) >> 21; + s15 += carry14; + s14 -= carry14 << 21; + carry16 = (s16 + (1 << 20)) >> 21; + s17 += carry16; + s16 -= carry16 << 21; + carry18 = (s18 + (1 << 20)) >> 21; + s19 += carry18; + s18 -= carry18 << 21; + carry20 = (s20 + (1 << 20)) >> 21; + s21 += carry20; + s20 -= carry20 << 21; + carry22 = (s22 + (1 << 20)) >> 21; + s23 += carry22; + s22 -= carry22 << 21; + carry1 = (s1 + (1 << 20)) >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry3 = (s3 + (1 << 20)) >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry5 = (s5 + (1 << 20)) >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 << 21; + carry13 = (s13 + (1 << 20)) >> 21; + s14 += carry13; + s13 -= carry13 << 21; + carry15 = (s15 + (1 << 20)) >> 21; + s16 += carry15; + s15 -= carry15 << 21; + carry17 = (s17 + (1 << 20)) >> 21; + s18 += carry17; + s17 -= carry17 << 21; + carry19 = (s19 + (1 << 20)) >> 21; + s20 += carry19; + s19 -= carry19 << 21; + carry21 = (s21 + (1 << 20)) >> 21; + s22 += carry21; + s21 -= carry21 << 21; + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + s23 = 0; + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + s22 = 0; + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + s21 = 0; + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + s20 = 0; + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + s19 = 0; + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + s18 = 0; + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry12 = (s12 + (1 << 20)) >> 21; + s13 += carry12; + s12 -= carry12 << 21; + carry14 = (s14 + (1 << 20)) >> 21; + s15 += carry14; + s14 -= carry14 << 21; + carry16 = (s16 + (1 << 20)) >> 21; + s17 += carry16; + s16 -= carry16 << 21; + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 << 21; + carry13 = (s13 + (1 << 20)) >> 21; + s14 += carry13; + s13 -= carry13 << 21; + carry15 = (s15 + (1 << 20)) >> 21; + s16 += carry15; + s15 -= carry15 << 21; + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + s17 = 0; + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + s16 = 0; + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + s15 = 0; + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + s14 = 0; + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + s13 = 0; + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + carry0 = (s0 + (1 << 20)) >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry2 = (s2 + (1 << 20)) >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry4 = (s4 + (1 << 20)) >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry1 = (s1 + (1 << 20)) >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry3 = (s3 + (1 << 20)) >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry5 = (s5 + (1 << 20)) >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= carry11 << 21; + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 << 21; + carry11 = s11 >> 21; + s12 += carry11; + s11 -= carry11 << 21; + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 << 21; + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 << 21; + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 << 21; + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 << 21; + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 << 21; + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 << 21; + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 << 21; + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 << 21; + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 << 21; + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 << 21; + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 << 21; + + s[0] = (unsigned char) (s0 >> 0); + s[1] = (unsigned char) (s0 >> 8); + s[2] = (unsigned char) ((s0 >> 16) | (s1 << 5)); + s[3] = (unsigned char) (s1 >> 3); + s[4] = (unsigned char) (s1 >> 11); + s[5] = (unsigned char) ((s1 >> 19) | (s2 << 2)); + s[6] = (unsigned char) (s2 >> 6); + s[7] = (unsigned char) ((s2 >> 14) | (s3 << 7)); + s[8] = (unsigned char) (s3 >> 1); + s[9] = (unsigned char) (s3 >> 9); + s[10] = (unsigned char) ((s3 >> 17) | (s4 << 4)); + s[11] = (unsigned char) (s4 >> 4); + s[12] = (unsigned char) (s4 >> 12); + s[13] = (unsigned char) ((s4 >> 20) | (s5 << 1)); + s[14] = (unsigned char) (s5 >> 7); + s[15] = (unsigned char) ((s5 >> 15) | (s6 << 6)); + s[16] = (unsigned char) (s6 >> 2); + s[17] = (unsigned char) (s6 >> 10); + s[18] = (unsigned char) ((s6 >> 18) | (s7 << 3)); + s[19] = (unsigned char) (s7 >> 5); + s[20] = (unsigned char) (s7 >> 13); + s[21] = (unsigned char) (s8 >> 0); + s[22] = (unsigned char) (s8 >> 8); + s[23] = (unsigned char) ((s8 >> 16) | (s9 << 5)); + s[24] = (unsigned char) (s9 >> 3); + s[25] = (unsigned char) (s9 >> 11); + s[26] = (unsigned char) ((s9 >> 19) | (s10 << 2)); + s[27] = (unsigned char) (s10 >> 6); + s[28] = (unsigned char) ((s10 >> 14) | (s11 << 7)); + s[29] = (unsigned char) (s11 >> 1); + s[30] = (unsigned char) (s11 >> 9); + s[31] = (unsigned char) (s11 >> 17); +} diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sc.h b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sc.h new file mode 100644 index 000000000..e29e7fa5a --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sc.h @@ -0,0 +1,12 @@ +#ifndef SC_H +#define SC_H + +/* +The set of scalars is \Z/l +where l = 2^252 + 27742317777372353535851937790883648493. +*/ + +void sc_reduce(unsigned char *s); +void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c); + +#endif diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sign.c b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sign.c new file mode 100644 index 000000000..c7e6e90a5 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/sign.c @@ -0,0 +1,31 @@ +#include "ed25519.h" +#include "../sha3/sha3.h" +#include "ge.h" +#include "sc.h" + + +void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) { + sha3_ctx_t hash; + unsigned char hram[64]; + unsigned char r[64]; + ge_p3 R; + + + sha3_init(&hash, 64); + sha3_update(&hash, private_key + 32, 32); + sha3_update(&hash, message, message_len); + sha3_final(r, &hash); + + sc_reduce(r); + ge_scalarmult_base(&R, r); + ge_p3_tobytes(signature, &R); + + sha3_init(&hash, 64); + sha3_update(&hash, signature, 32); + sha3_update(&hash, public_key, 32); + sha3_update(&hash, message, message_len); + sha3_final(hram, &hash); + + sc_reduce(hram); + sc_muladd(signature + 32, hram, private_key, r); +} diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/verify.c b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/verify.c new file mode 100644 index 000000000..bc1ef3050 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/ed25519/verify.c @@ -0,0 +1,77 @@ +#include "ed25519.h" +#include "../sha3/sha3.h" +#include "ge.h" +#include "sc.h" + +static int consttime_equal(const unsigned char *x, const unsigned char *y) { + unsigned char r = 0; + + r = x[0] ^ y[0]; + #define F(i) r |= x[i] ^ y[i] + F(1); + F(2); + F(3); + F(4); + F(5); + F(6); + F(7); + F(8); + F(9); + F(10); + F(11); + F(12); + F(13); + F(14); + F(15); + F(16); + F(17); + F(18); + F(19); + F(20); + F(21); + F(22); + F(23); + F(24); + F(25); + F(26); + F(27); + F(28); + F(29); + F(30); + F(31); + #undef F + + return !r; +} + +int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) { + unsigned char h[64]; + unsigned char checker[32]; + sha3_ctx_t hash; + ge_p3 A; + ge_p2 R; + + if (signature[63] & 224) { + return 0; + } + + if (ge_frombytes_negate_vartime(&A, public_key) != 0) { + return 0; + } + + sha3_init(&hash, 64); + sha3_update(&hash, signature, 32); + sha3_update(&hash, public_key, 32); + sha3_update(&hash, message, message_len); + sha3_final(h, &hash); + + sc_reduce(h); + ge_double_scalarmult_vartime(&R, h, &A, signature + 32); + ge_tobytes(checker, &R); + + if (!consttime_equal(checker, signature)) { + return 0; + } + + return 1; +} diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone.c b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone.c new file mode 100644 index 000000000..507c65100 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone.c @@ -0,0 +1,80 @@ +/* + * keystone.c + */ + +#include +#include +#include +#include + +#define ED25519_NO_SEED 1 +#include "sha3/sha3.h" +#include "ed25519/ed25519.h" + +typedef unsigned char byte; + +/* Sanctum fields */ +extern byte sanctum_dev_public_key[32]; +extern byte sanctum_dev_secret_key[64]; +unsigned int sanctum_sm_size = 0x1ff000; +extern byte sanctum_sm_hash[64]; +extern byte sanctum_sm_public_key[32]; +extern byte sanctum_sm_secret_key[64]; +extern byte sanctum_sm_signature[64]; + +#if CONFIG_IS_ENABLED(KEYSTONE_USE_RNG) + +#error Random function using hardware rng is unimplemented + +#else + +#warning Bootloader does not have entropy source, keys are for TESTING ONLY + +inline byte random_byte(unsigned int i) { + return 0xac + (0xdd ^ i); +} + +#endif + +int keystone_init(void) { + byte scratchpad[128]; + sha3_ctx_t hash_ctx; + + for (unsigned int i = 0; i < 32; i++) { + scratchpad[i] = random_byte(i); + } + +#if CONFIG_IS_ENABLED(KEYSTONE_USE_TEST_KEYS) + #include "keystone_use_test_keys.h" +#else + #error Secure keystore operation is unimplemented +#endif + + /* Measure SM */ + sha3_init(&hash_ctx, 64); + sha3_update(&hash_ctx, (void *)CONFIG_SPL_OPENSBI_LOAD_ADDR, sanctum_sm_size); + sha3_final(sanctum_sm_hash, &hash_ctx); + + /* Combine SK_D and H_SM via a hash + * sm_key_seed <-- H(SK_D, H_SM), truncate to 32B */ + sha3_init(&hash_ctx, 64); + sha3_update(&hash_ctx, sanctum_dev_secret_key, sizeof(*sanctum_dev_secret_key)); + sha3_update(&hash_ctx, sanctum_sm_hash, sizeof(*sanctum_sm_hash)); + sha3_final(scratchpad, &hash_ctx); + + /* Derive {SK_D, PK_D} (device keys) from the first 32 B of the hash (NIST endorses SHA512 truncation as safe) */ + ed25519_create_keypair(sanctum_sm_public_key, sanctum_sm_secret_key, scratchpad); + + /* Endorse the SM */ + memcpy(scratchpad, sanctum_sm_hash, 64); + memcpy(scratchpad + 64, sanctum_sm_public_key, 32); + /* Sign (H_SM, PK_SM) with SK_D */ + ed25519_sign(sanctum_sm_signature, scratchpad, 64 + 32, sanctum_dev_public_key, sanctum_dev_secret_key); + + /* Clean up + * Erase SK_D */ + memset((void *)sanctum_dev_secret_key, 0, sizeof(*sanctum_dev_secret_key)); + + /* caller will clean core state and memory (including the stack). */ + return 0; +} diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone_test_dev_key.h b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone_test_dev_key.h new file mode 100644 index 000000000..ebf9bd5c9 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone_test_dev_key.h @@ -0,0 +1,22 @@ +/* These are known device TESTING keys, use them for testing on platforms/qemu */ + +#warning Using TEST device root key. No integrity guarantee. + +static const unsigned char _sanctum_dev_secret_key[] = { + 0x40, 0xa0, 0x99, 0x47, 0x8c, 0xce, 0xfa, 0x3a, 0x06, 0x63, 0xab, 0xc9, + 0x5e, 0x7a, 0x1e, 0xc9, 0x54, 0xb4, 0xf5, 0xf6, 0x45, 0xba, 0xd8, 0x04, + 0xdb, 0x13, 0xe7, 0xd7, 0x82, 0x6c, 0x70, 0x73, 0x57, 0x6a, 0x9a, 0xb6, + 0x21, 0x60, 0xd9, 0xd1, 0xc6, 0xae, 0xdc, 0x29, 0x85, 0x2f, 0xb9, 0x60, + 0xee, 0x51, 0x32, 0x83, 0x5a, 0x16, 0x89, 0xec, 0x06, 0xa8, 0x72, 0x34, + 0x51, 0xaa, 0x0e, 0x4a +}; + +static const size_t _sanctum_dev_secret_key_len = 64; + +static const unsigned char _sanctum_dev_public_key[] = { + 0x0f, 0xaa, 0xd4, 0xff, 0x01, 0x17, 0x85, 0x83, 0xba, 0xa5, 0x88, 0x96, + 0x6f, 0x7c, 0x1f, 0xf3, 0x25, 0x64, 0xdd, 0x17, 0xd7, 0xdc, 0x2b, 0x46, + 0xcb, 0x50, 0xa8, 0x4a, 0x69, 0x27, 0x0b, 0x4c +}; + +static const size_t _sanctum_dev_public_key_len = 32; \ No newline at end of file diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone_use_test_keys.h b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone_use_test_keys.h new file mode 100644 index 000000000..2bc568a1c --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/keystone_use_test_keys.h @@ -0,0 +1,3 @@ +#include "keystone_test_dev_key.h" +memcpy(sanctum_dev_secret_key, _sanctum_dev_secret_key, _sanctum_dev_secret_key_len); +memcpy(sanctum_dev_public_key, _sanctum_dev_public_key, _sanctum_dev_public_key_len); \ No newline at end of file diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/Makefile b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/Makefile new file mode 100644 index 000000000..b61eba8e3 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/Makefile @@ -0,0 +1 @@ +obj-y += sha3.o \ No newline at end of file diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/sha3.c b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/sha3.c new file mode 100644 index 000000000..198a023bd --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/sha3.c @@ -0,0 +1,165 @@ +// sha3.c +// 19-Nov-11 Markku-Juhani O. Saarinen + +// Revised 07-Aug-15 to match with official release of FIPS PUB 202 "SHA3" +// Revised 03-Sep-15 for portability + OpenSSL - style API + +#include "sha3.h" + +// update the state with given number of rounds + +void sha3_keccakf(uint64_t st[25]) +{ + // constants + const uint64_t keccakf_rndc[24] = { + 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, + 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, + 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, + 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, + 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, + 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, + 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 + }; + const int keccakf_rotc[24] = { + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 + }; + const int keccakf_piln[24] = { + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 + }; + + // variables + int i, j, r; + uint64_t t, bc[5]; + +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ + uint8_t *v; + + // endianess conversion. this is redundant on little-endian targets + for (i = 0; i < 25; i++) { + v = (uint8_t *) &st[i]; + st[i] = ((uint64_t) v[0]) | (((uint64_t) v[1]) << 8) | + (((uint64_t) v[2]) << 16) | (((uint64_t) v[3]) << 24) | + (((uint64_t) v[4]) << 32) | (((uint64_t) v[5]) << 40) | + (((uint64_t) v[6]) << 48) | (((uint64_t) v[7]) << 56); + } +#endif + + // actual iteration + for (r = 0; r < KECCAKF_ROUNDS; r++) { + + // Theta + for (i = 0; i < 5; i++) + bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; + + for (i = 0; i < 5; i++) { + t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); + for (j = 0; j < 25; j += 5) + st[j + i] ^= t; + } + + // Rho Pi + t = st[1]; + for (i = 0; i < 24; i++) { + j = keccakf_piln[i]; + bc[0] = st[j]; + st[j] = ROTL64(t, keccakf_rotc[i]); + t = bc[0]; + } + + // Chi + for (j = 0; j < 25; j += 5) { + for (i = 0; i < 5; i++) + bc[i] = st[j + i]; + for (i = 0; i < 5; i++) + st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; + } + + // Iota + st[0] ^= keccakf_rndc[r]; + } + +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ + // endianess conversion. this is redundant on little-endian targets + for (i = 0; i < 25; i++) { + v = (uint8_t *) &st[i]; + t = st[i]; + v[0] = t & 0xFF; + v[1] = (t >> 8) & 0xFF; + v[2] = (t >> 16) & 0xFF; + v[3] = (t >> 24) & 0xFF; + v[4] = (t >> 32) & 0xFF; + v[5] = (t >> 40) & 0xFF; + v[6] = (t >> 48) & 0xFF; + v[7] = (t >> 56) & 0xFF; + } +#endif +} + +// Initialize the context for SHA3 + +int sha3_init(sha3_ctx_t *c, int mdlen) +{ + int i; + + for (i = 0; i < 25; i++) + c->st.q[i] = 0; + c->mdlen = mdlen; + c->rsiz = 200 - 2 * mdlen; + c->pt = 0; + + return 1; +} + +// update state with more data + +int sha3_update(sha3_ctx_t *c, const void *data, size_t len) +{ + size_t i; + int j; + + j = c->pt; + for (i = 0; i < len; i++) { + c->st.b[j++] ^= ((const uint8_t *) data)[i]; + if (j >= c->rsiz) { + sha3_keccakf(c->st.q); + j = 0; + } + } + c->pt = j; + + return 1; +} + +// finalize and output a hash + +int sha3_final(void *md, sha3_ctx_t *c) +{ + int i; + + c->st.b[c->pt] ^= 0x06; + c->st.b[c->rsiz - 1] ^= 0x80; + sha3_keccakf(c->st.q); + + for (i = 0; i < c->mdlen; i++) { + ((uint8_t *) md)[i] = c->st.b[i]; + } + + return 1; +} + +// compute a SHA-3 hash (md) of given byte length from "in" + +void *sha3(const void *in, size_t inlen, void *md, int mdlen) +{ + sha3_ctx_t sha3; + + sha3_init(&sha3, mdlen); + sha3_update(&sha3, in, inlen); + sha3_final(md, &sha3); + + return md; +} + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/sha3.h b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/sha3.h new file mode 100644 index 000000000..279f2bc7c --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone/sha3/sha3.h @@ -0,0 +1,40 @@ +// sha3.h +// 19-Nov-11 Markku-Juhani O. Saarinen + +#ifndef SHA3_H +#define SHA3_H + +#include +//#include +#include + +#ifndef KECCAKF_ROUNDS +#define KECCAKF_ROUNDS 24 +#endif + +#ifndef ROTL64 +#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) +#endif + +// state context +typedef struct { + union { // state: + uint8_t b[200]; // 8-bit bytes + uint64_t q[25]; // 64-bit words + } st; + int pt, rsiz, mdlen; // these don't overflow +} sha3_ctx_t; + +// Compression function. +void sha3_keccakf(uint64_t st[25]); + +// OpenSSL - like interfece +int sha3_init(sha3_ctx_t *c, int mdlen); // mdlen = hash output in bytes +int sha3_update(sha3_ctx_t *c, const void *data, size_t len); +int sha3_final(void *md, sha3_ctx_t *c); // digest goes to md + +// compute a sha3 hash (md) of given byte length from "in" +void *sha3(const void *in, size_t inlen, void *md, int mdlen); + +#endif + diff --git a/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/u-boot-spl-sanctum.lds b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/u-boot-spl-sanctum.lds new file mode 100644 index 000000000..d1017f9c6 --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/u-boot-spl-sanctum.lds @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Based on arch/riscv/cpu/u-boot.lds, which is + * Copyright (C) 2017 Andes Technology Corporation + * Rick Chen, Andes Technology Corporation + * + * and arch/mips/cpu/u-boot-spl.lds. + */ +MEMORY { .spl_mem : ORIGIN = IMAGE_TEXT_BASE, LENGTH = IMAGE_MAX_SIZE } +MEMORY { .bss_mem : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_ARCH("riscv") +ENTRY(_start) + +SECTIONS +{ + . = ALIGN(4); + .text : { + arch/riscv/cpu/start.o (.text) + *(.text*) + } > .spl_mem + + . = ALIGN(4); + .rodata : { + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } > .spl_mem + + . = ALIGN(4); + .data : { + *(.data*) + } > .spl_mem + . = ALIGN(4); + + __u_boot_list : { + KEEP(*(SORT(__u_boot_list*))); + } > .spl_mem + + . = ALIGN(4); + + .binman_sym_table : { + __binman_sym_start = .; + KEEP(*(SORT(.binman_sym*))); + __binman_sym_end = .; + } > .spl_mem + + . = ALIGN(8); + + _end = .; + _image_binary_end = .; + + .bss : { + __bss_start = .; + *(.bss*) + . = ALIGN(8); + __bss_end = .; + } > .bss_mem + + . = 0x801ff000; /* the last page before the payload */ + + /* ## manufacturer_keys : */ + + /* 32 Bytes : manufacturer public key */ + PROVIDE( sanctum_m_public_key = . ); + . += 0x20; + + /* 32 Bytes : device public key */ + PROVIDE( sanctum_dev_public_key = . ); + . += 0x20; + + /* 64 Bytes : device secret key */ + PROVIDE( sanctum_dev_secret_key = . ); + . += 0x40; + + /* ## security_monitor_keys : */ + + /* 64 Bytes : security monitor hash */ + PROVIDE( sanctum_sm_hash = . ); + . += 0x40; + + /* 32 Bytes : security monitor public key */ + PROVIDE( sanctum_sm_public_key = . ); + . += 0x20; + + /* 64 Bytes : security monitor secret key */ + PROVIDE( sanctum_sm_secret_key = . ); + . += 0x40; + + /* 64 Bytes : security monitor's signature by device */ + PROVIDE( sanctum_sm_signature = . ); + . += 0x40; +} diff --git a/overlays/keystone/board/sifive/hifive-unmatched/uboot_sifive_unmatched_keystone_defconfig b/overlays/keystone/board/sifive/hifive-unmatched/uboot_sifive_unmatched_keystone_defconfig new file mode 100644 index 000000000..37374496c --- /dev/null +++ b/overlays/keystone/board/sifive/hifive-unmatched/uboot_sifive_unmatched_keystone_defconfig @@ -0,0 +1,69 @@ +CONFIG_RISCV=y +# CONFIG_SPL_USE_ARCH_MEMMOVE is not set +CONFIG_SYS_MALLOC_LEN=0x800000 +CONFIG_SYS_MALLOC_F_LEN=0x3000 +CONFIG_SPL_GPIO=y +CONFIG_NR_DRAM_BANKS=1 +CONFIG_SPL_LDSCRIPT="arch/$(ARCH)/cpu/u-boot-spl-sanctum.lds" +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80210000 +CONFIG_SPL_DM_SPI=y +CONFIG_DEFAULT_DEVICE_TREE="hifive-unmatched-a00" +CONFIG_DM_RESET=y +CONFIG_SPL_MMC=y +CONFIG_SPL_STACK=0x81cfe60 +CONFIG_SPL=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI=y +CONFIG_TEXT_BASE=0x80210000 +CONFIG_SYS_LOAD_ADDR=0x80210000 +CONFIG_SYS_PCI_64BIT=y +CONFIG_PCI=y +CONFIG_AHCI=y +CONFIG_TARGET_SIFIVE_UNMATCHED=y +CONFIG_ARCH_RV64I=y +CONFIG_RISCV_SMODE=y +CONFIG_SPL_KEYSTONE_SECUREBOOT=y +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT_ADDRESS=0x84000000 +CONFIG_DISTRO_DEFAULTS=y +CONFIG_USE_PREBOOT=y +CONFIG_PREBOOT="setenv fdt_addr ${fdtcontroladdr};fdt addr ${fdtcontroladdr};" +CONFIG_DEFAULT_FDT_FILE="sifive/hifive-unmatched-a00.dtb" +CONFIG_DISPLAY_CPUINFO=y +CONFIG_DISPLAY_BOARDINFO=y +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_ID_EEPROM=y +CONFIG_SPL_MAX_SIZE=0x100000 +CONFIG_SPL_BSS_START_ADDR=0x85000000 +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SYS_SPL_MALLOC=y +CONFIG_SPL_DM_SPI_FLASH=y +CONFIG_SPL_DM_RESET=y +CONFIG_SPL_SPI_LOAD=y +CONFIG_SYS_CBSIZE=256 +CONFIG_SYS_PBSIZE=276 +CONFIG_SYS_BOOTM_LEN=0x4000000 +CONFIG_CMD_EEPROM=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_PWM=y +CONFIG_CMD_GPT_RENAME=y +CONFIG_CMD_PCI=y +CONFIG_CMD_USB=y +CONFIG_ENV_SPI_BUS=1 +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SCSI_AHCI=y +CONFIG_AHCI_PCI=y +CONFIG_SPL_CLK=y +CONFIG_SYS_I2C_EEPROM_ADDR=0x54 +CONFIG_SPI_FLASH_ISSI=y +CONFIG_E1000=y +CONFIG_NVME_PCI=y +CONFIG_PCIE_DW_SIFIVE=y +CONFIG_SCSI=y +CONFIG_DM_SCSI=y +CONFIG_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI=y +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS=0x2 diff --git a/overlays/keystone/boot/keystone-sm/keystone-sm.mk b/overlays/keystone/boot/keystone-sm/keystone-sm.mk index b43e16aa1..b26c94246 100644 --- a/overlays/keystone/boot/keystone-sm/keystone-sm.mk +++ b/overlays/keystone/boot/keystone-sm/keystone-sm.mk @@ -17,6 +17,9 @@ $(OPENSBI_TARGET_CONFIGURE): keystone-sm-install # Point OpenSBI at the correct location of the SM sources OPENSBI_MAKE_ENV += PLATFORM_DIR=$(KEYSTONE_SM_BUILDDIR)/plat/ +# For abi issue +OPENSBI_MAKE_ENV += PLATFORM_RISCV_TOOLCHAIN_DEFAULT=1 + # Make keystone-sm dircleans also trigger opensbi-dirclean keystone-sm-dirclean: opensbi-dirclean diff --git a/overlays/keystone/configs/riscv64_hifive_unmatched_defconfig b/overlays/keystone/configs/riscv64_hifive_unmatched_defconfig new file mode 100644 index 000000000..c03ecffa3 --- /dev/null +++ b/overlays/keystone/configs/riscv64_hifive_unmatched_defconfig @@ -0,0 +1,60 @@ +BR2_riscv=y +BR2_TOOLCHAIN_BUILDROOT_CXX=y +BR2_CCACHE=y +BR2_GLOBAL_PATCH_DIR="$(BR2_EXTERNAL_KEYSTONE_PATH)/patches $(BR2_EXTERNAL_KEYSTONE_PATH)/board/sifive/hifive-unmatched/patches" +BR2_PER_PACKAGE_DIRECTORIES=y +BR2_SSP_NONE=y +BR2_TARGET_GENERIC_HOSTNAME="keystone" +BR2_INIT_SYSTEMD=y +BR2_TARGET_GENERIC_ROOT_PASSWD="sifive" +BR2_SYSTEM_BIN_SH_BASH=y +BR2_TARGET_GENERIC_GETTY_PORT="ttySIF0" +BR2_SYSTEM_DHCP="end0" +BR2_SYSTEM_DEFAULT_PATH="/bin:/sbin:/usr/bin:/usr/sbin" +BR2_ROOTFS_POST_BUILD_SCRIPT="$(BR2_EXTERNAL_KEYSTONE_PATH)/board/sifive/hifive-unmatched/post-build.sh" +BR2_ROOTFS_POST_IMAGE_SCRIPT="support/scripts/genimage.sh" +BR2_ROOTFS_POST_SCRIPT_ARGS="-c $(BR2_EXTERNAL_KEYSTONE_PATH)/board/sifive/hifive-unmatched/genimage_sdcard.cfg" +BR2_LINUX_KERNEL=y +BR2_LINUX_KERNEL_CUSTOM_VERSION=y +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.43" +BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y +BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_KEYSTONE_PATH)/board/sifive/hifive-unmatched/linux-sifive-unmatched-defconfig" +BR2_LINUX_KERNEL_IMAGEGZ=y +BR2_LINUX_KERNEL_DTS_SUPPORT=y +BR2_LINUX_KERNEL_INTREE_DTS_NAME="sifive/hifive-unmatched-a00" +BR2_LINUX_KERNEL_INSTALL_TARGET=y +BR2_PACKAGE_LINUX_TOOLS_PERF=y +BR2_PACKAGE_LINUX_TOOLS_PERF_TUI=y +BR2_PACKAGE_STRACE=y +BR2_PACKAGE_LINUX_FIRMWARE=y +BR2_PACKAGE_LINUX_FIRMWARE_AMDGPU=y +BR2_PACKAGE_LINUX_FIRMWARE_RADEON=y +BR2_PACKAGE_DHCPCD=y +BR2_PACKAGE_DROPBEAR=y +BR2_TARGET_ROOTFS_CPIO=y +BR2_TARGET_ROOTFS_EXT2=y +BR2_TARGET_ROOTFS_EXT2_4=y +BR2_TARGET_ROOTFS_EXT2_SIZE="300M" +BR2_TARGET_OPENSBI_CUSTOM_VERSION=y +BR2_TARGET_OPENSBI_CUSTOM_VERSION_VALUE="1.1" +BR2_TARGET_OPENSBI_PLAT="generic" +BR2_TARGET_UBOOT=y +BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y +BR2_TARGET_UBOOT_CUSTOM_VERSION=y +BR2_TARGET_UBOOT_CUSTOM_VERSION_VALUE="2023.07" +BR2_TARGET_UBOOT_USE_CUSTOM_CONFIG=y +BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_KEYSTONE_PATH)/board/sifive/hifive-unmatched/uboot_sifive_unmatched_keystone_defconfig" +BR2_TARGET_UBOOT_NEEDS_DTC=y +BR2_TARGET_UBOOT_NEEDS_PYLIBFDT=y +BR2_TARGET_UBOOT_NEEDS_OPENSSL=y +BR2_TARGET_UBOOT_NEEDS_OPENSBI=y +BR2_TARGET_UBOOT_FORMAT_CUSTOM=y +BR2_TARGET_UBOOT_FORMAT_CUSTOM_NAME="u-boot.itb" +BR2_TARGET_UBOOT_SPL=y +BR2_PACKAGE_HOST_GENIMAGE=y +BR2_PACKAGE_HOST_UBOOT_TOOLS=y +BR2_TARGET_KEYSTONE_SM=y +BR2_PACKAGE_KEYSTONE_DRIVER=y +BR2_PACKAGE_HOST_KEYSTONE_SDK=y +BR2_PACKAGE_KEYSTONE_RUNTIME=y +BR2_PACKAGE_KEYSTONE_EXAMPLES=y diff --git a/overlays/keystone/external.mk b/overlays/keystone/external.mk index 218ad688f..22ed42ceb 100644 --- a/overlays/keystone/external.mk +++ b/overlays/keystone/external.mk @@ -8,3 +8,16 @@ include $(sort $(wildcard $(BR2_EXTERNAL_KEYSTONE_PATH)/boot/*/*.mk)) # Packages include $(sort $(wildcard $(BR2_EXTERNAL_KEYSTONE_PATH)/package/*/*.mk)) + +# U-Boot +ifeq ($(KEYSTONE_PLATFORM),unmatched) + +define UBOOT_COPY_HIFIVE_SOURCES + cp -ar $(KEYSTONE)/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone $(@D)/arch/riscv/lib + cp -ar $(KEYSTONE)/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/keystone.h $(@D)/arch/riscv/include/asm + cp -ar $(KEYSTONE)/overlays/keystone/board/sifive/hifive-unmatched/src/uboot/u-boot-spl-sanctum.lds $(@D)/arch/riscv/cpu +endef + +UBOOT_POST_EXTRACT_HOOKS += UBOOT_COPY_HIFIVE_SOURCES + +endif diff --git a/overlays/keystone/patches/opensbi/opensbi-firmware-secure-boot.patch b/overlays/keystone/patches/opensbi/opensbi-firmware-secure-boot.patch index 0eec42949..c744ba574 100644 --- a/overlays/keystone/patches/opensbi/opensbi-firmware-secure-boot.patch +++ b/overlays/keystone/patches/opensbi/opensbi-firmware-secure-boot.patch @@ -7,7 +7,7 @@ index 0ac75f2..9aa9c1a 100644 PROVIDE(_fw_end = .); + -+ * # Sanctum params */ ++ /* # Sanctum params */ + /* ================ */ + . = 0x801ff000; /* the last page before the payload */ + diff --git a/sm/plat/generic/objects.mk b/sm/plat/generic/objects.mk index 3ba2350b4..0ea631898 100644 --- a/sm/plat/generic/objects.mk +++ b/sm/plat/generic/objects.mk @@ -7,7 +7,7 @@ ifeq ($(PLATFORM),) $(error PLATFORM not defined for SM) endif -platform-genflags-y += "-DTARGET_PLATFORM_HEADER=\"platform/$(PLATFORM)/platform.h\"" +platform-genflags-y += "-DTARGET_PLATFORM_HEADER=\"platform/$(KEYSTONE_PLATFORM)/platform.h\"" include $(KEYSTONE_SM)/src/objects.mk platform-objs-y += $(addprefix ../../src/,$(subst .c,.o,$(keystone-sm-sources))) diff --git a/sm/plat/generic/sifive/fu740.c b/sm/plat/generic/sifive/fu740.c new file mode 100644 index 000000000..531356420 --- /dev/null +++ b/sm/plat/generic/sifive/fu740.c @@ -0,0 +1,260 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2021 SiFive + * Copyright (c) 2021 YADRO + * + * Authors: + * David Abdurachmanov + * Nikita Shubin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sm.h" + +#define DA9063_REG_PAGE_CON 0x00 +#define DA9063_REG_CONTROL_A 0x0e +#define DA9063_REG_CONTROL_D 0x11 +#define DA9063_REG_CONTROL_F 0x13 +#define DA9063_REG_DEVICE_ID 0x81 + +#define DA9063_CONTROL_A_M_POWER1_EN (1 << 6) +#define DA9063_CONTROL_A_M_POWER_EN (1 << 5) +#define DA9063_CONTROL_A_STANDBY (1 << 3) + +#define DA9063_CONTROL_D_TWDSCALE_MASK 0x07 + +#define DA9063_CONTROL_F_WAKEUP (1 << 2) +#define DA9063_CONTROL_F_SHUTDOWN (1 << 1) + +#define PMIC_CHIP_ID_DA9063 0x61 + +static struct { + struct i2c_adapter *adapter; + uint32_t reg; +} da9063; + +static int da9063_system_reset_check(u32 type, u32 reason) +{ + switch (type) { + case SBI_SRST_RESET_TYPE_SHUTDOWN: + return 1; + case SBI_SRST_RESET_TYPE_COLD_REBOOT: + case SBI_SRST_RESET_TYPE_WARM_REBOOT: + return 255; + } + + return 0; +} + +static inline int da9063_sanity_check(struct i2c_adapter *adap, uint32_t reg) +{ + uint8_t val; + int rc = i2c_adapter_reg_write(adap, reg, DA9063_REG_PAGE_CON, 0x02); + + if (rc) + return rc; + + /* check set page*/ + rc = i2c_adapter_reg_read(adap, reg, 0x0, &val); + if (rc) + return rc; + + if (val != 0x02) + return SBI_ENODEV; + + /* read and check device id */ + rc = i2c_adapter_reg_read(adap, reg, DA9063_REG_DEVICE_ID, &val); + if (rc) + return rc; + + if (val != PMIC_CHIP_ID_DA9063) + return SBI_ENODEV; + + return 0; +} + +static inline int da9063_stop_watchdog(struct i2c_adapter *adap, uint32_t reg) +{ + uint8_t val; + int rc = i2c_adapter_reg_write(adap, reg, + DA9063_REG_PAGE_CON, 0x00); + + if (rc) + return rc; + + rc = i2c_adapter_reg_read(adap, reg, DA9063_REG_CONTROL_D, &val); + if (rc) + return rc; + + if ((val & DA9063_CONTROL_D_TWDSCALE_MASK) == 0) + return 0; + + val &= ~DA9063_CONTROL_D_TWDSCALE_MASK; + + return i2c_adapter_reg_write(adap, reg, DA9063_REG_CONTROL_D, val); +} + +static inline int da9063_shutdown(struct i2c_adapter *adap, uint32_t reg) +{ + int rc = i2c_adapter_reg_write(adap, reg, + DA9063_REG_PAGE_CON, 0x00); + + if (rc) + return rc; + + return i2c_adapter_reg_write(adap, reg, + DA9063_REG_CONTROL_F, + DA9063_CONTROL_F_SHUTDOWN); +} + +static inline int da9063_reset(struct i2c_adapter *adap, uint32_t reg) +{ + int rc = i2c_adapter_reg_write(adap, reg, + DA9063_REG_PAGE_CON, 0x00); + + if (rc) + return rc; + + rc = i2c_adapter_reg_write(adap, reg, + DA9063_REG_CONTROL_F, + DA9063_CONTROL_F_WAKEUP); + if (rc) + return rc; + + return i2c_adapter_reg_write(adap, reg, + DA9063_REG_CONTROL_A, + DA9063_CONTROL_A_M_POWER1_EN | + DA9063_CONTROL_A_M_POWER_EN | + DA9063_CONTROL_A_STANDBY); +} + +static void da9063_system_reset(u32 type, u32 reason) +{ + struct i2c_adapter *adap = da9063.adapter; + uint32_t reg = da9063.reg; + int rc; + + if (adap) { + /* sanity check */ + rc = da9063_sanity_check(adap, reg); + if (rc) { + sbi_printf("%s: chip is not da9063 PMIC\n", __func__); + goto skip_reset; + } + + switch (type) { + case SBI_SRST_RESET_TYPE_SHUTDOWN: + da9063_shutdown(adap, reg); + break; + case SBI_SRST_RESET_TYPE_COLD_REBOOT: + case SBI_SRST_RESET_TYPE_WARM_REBOOT: + da9063_stop_watchdog(adap, reg); + da9063_reset(adap, reg); + break; + } + } + +skip_reset: + sbi_hart_hang(); +} + +static struct sbi_system_reset_device da9063_reset_i2c = { + .name = "da9063-reset", + .system_reset_check = da9063_system_reset_check, + .system_reset = da9063_system_reset +}; + +static int da9063_reset_init(void *fdt, int nodeoff, + const struct fdt_match *match) +{ + int rc, i2c_bus; + struct i2c_adapter *adapter; + uint64_t addr; + + /* we are dlg,da9063 node */ + rc = fdt_get_node_addr_size(fdt, nodeoff, 0, &addr, NULL); + if (rc) + return rc; + + da9063.reg = addr; + + /* find i2c bus parent node */ + i2c_bus = fdt_parent_offset(fdt, nodeoff); + if (i2c_bus < 0) + return i2c_bus; + + /* i2c adapter get */ + rc = fdt_i2c_adapter_get(fdt, i2c_bus, &adapter); + if (rc) + return rc; + + da9063.adapter = adapter; + + sbi_system_reset_add_device(&da9063_reset_i2c); + + return 0; +} + +static const struct fdt_match da9063_reset_match[] = { + { .compatible = "dlg,da9063", .data = (void *)TRUE }, + { }, +}; + +struct fdt_reset fdt_reset_da9063 = { + .match_table = da9063_reset_match, + .init = da9063_reset_init, +}; + +static u64 sifive_fu740_tlbr_flush_limit(const struct fdt_match *match) +{ + /* + * Needed to address CIP-1200 errata on SiFive FU740 + * Title: Instruction TLB can fail to respect a non-global SFENCE + * Workaround: Flush the TLB using SFENCE.VMA x0, x0 + * See Errata_FU740-C000_20210205 from + * https://www.sifive.com/boards/hifive-unmatched + */ + return 0; +} + +static int sifive_fu740_final_init(bool cold_boot, + const struct fdt_match *match) +{ + int rc; + void *fdt = fdt_get_address(); + + if (cold_boot) { + rc = fdt_reset_driver_init(fdt, &fdt_reset_da9063); + if (rc) + sbi_printf("%s: failed to find da9063 for reset\n", + __func__); + } + + sm_init(cold_boot); + + return 0; +} + +static const struct fdt_match sifive_fu740_match[] = { + { .compatible = "sifive,fu740" }, + { .compatible = "sifive,fu740-c000" }, + { .compatible = "sifive,hifive-unmatched-a00" }, + { }, +}; + +const struct platform_override sifive_fu740 = { + .match_table = sifive_fu740_match, + .tlbr_flush_limit = sifive_fu740_tlbr_flush_limit, + .final_init = sifive_fu740_final_init, +}; diff --git a/sm/plat/generic/sifive/objects.mk b/sm/plat/generic/sifive/objects.mk new file mode 100644 index 000000000..dc3ca7981 --- /dev/null +++ b/sm/plat/generic/sifive/objects.mk @@ -0,0 +1,6 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# + +carray-platform_override_modules-y += sifive_fu740 +platform-objs-y += sifive/fu740.o diff --git a/sm/src/objects.mk b/sm/src/objects.mk index 5e45dd4c3..37bc7c68a 100644 --- a/sm/src/objects.mk +++ b/sm/src/objects.mk @@ -36,7 +36,7 @@ keystone-sm-sources += crypto.c sha3/sha3.c ed25519/fe.c ed25519/ge.c ed25519/ke hmac_sha3/hmac_sha3.c # Platform -keystone-sm-sources += platform/$(PLATFORM)/platform.c +keystone-sm-sources += platform/$(KEYSTONE_PLATFORM)/platform.c # Plugin files keystone-sm-sources += plugins/multimem.c plugins/plugins.c diff --git a/sm/src/platform/unmatched/platform.c b/sm/src/platform/unmatched/platform.c new file mode 100644 index 000000000..16416fbe5 --- /dev/null +++ b/sm/src/platform/unmatched/platform.c @@ -0,0 +1,44 @@ +/* Default platform does nothing special here */ +#include "../../enclave.h" + +unsigned long platform_init_global_once(){ + return SBI_ERR_SM_ENCLAVE_SUCCESS; +} + +unsigned long platform_init_global(){ + return SBI_ERR_SM_ENCLAVE_SUCCESS; +} + +void platform_init_enclave(struct enclave* enclave){ + return; +} + +void platform_destroy_enclave(struct enclave* enclave){ + return; +} + +unsigned long platform_create_enclave(struct enclave* enclave){ + return SBI_ERR_SM_ENCLAVE_SUCCESS; +} + +void platform_switch_to_enclave(struct enclave* enclave){ + return; +} + +void platform_switch_from_enclave(struct enclave* enclave){ + return; +} + +uint64_t platform_random(){ +#pragma message("Platform has no entropy source, this is unsafe. TEST ONLY") + static uint64_t w = 0, s = 0xb5ad4eceda1ce2a9; + + unsigned long cycles; + asm volatile ("rdcycle %0" : "=r" (cycles)); + + // from Middle Square Weyl Sequence algorithm + uint64_t x = cycles; + x *= x; + x += (w += s); + return (x>>32) | (x<<32); +} diff --git a/sm/src/platform/unmatched/platform.h b/sm/src/platform/unmatched/platform.h new file mode 100644 index 000000000..f6eaab3bc --- /dev/null +++ b/sm/src/platform/unmatched/platform.h @@ -0,0 +1,5 @@ + +// No special data needed for default platform +struct platform_enclave_data{ + +};