├── .clang-format ├── .devcontainer └── Dockerfile ├── .gitignore ├── .pre-commit-config.yaml ├── CHANGES.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUES.md ├── LICENSE ├── NOTICE ├── README.md ├── SECURITY.md ├── adapter ├── CMakeLists.txt ├── adapter.cpp ├── config.h.in ├── convert.cpp ├── convert.h ├── fileops.cpp ├── fileops.h ├── generate.cpp ├── generate.h ├── utils.cpp └── utils.h ├── device ├── CMakeLists.txt ├── CMakeSettings.json ├── app_manifest.json ├── bench │ ├── CMakeLists.txt │ ├── bench_asym.c │ ├── bench_common.h │ ├── bench_ifft.c │ ├── bench_index_map.c │ ├── bench_ntt.c │ ├── bench_sample.c │ ├── bench_sym.c │ └── main.c ├── lib │ ├── CMakeLists.txt │ ├── ckks_asym.c │ ├── ckks_asym.h │ ├── ckks_common.c │ ├── ckks_common.h │ ├── ckks_sym.c │ ├── ckks_sym.h │ ├── defines.h │ ├── fft.c │ ├── fft.h │ ├── fileops.c │ ├── fileops.h │ ├── intt.c │ ├── intt.h │ ├── modulo.h │ ├── modulus.c │ ├── modulus.h │ ├── network.c │ ├── network.h │ ├── ntt.c │ ├── ntt.h │ ├── parameters.c │ ├── parameters.h │ ├── polymodarith.h │ ├── polymodmult.c │ ├── polymodmult.h │ ├── rng.c │ ├── rng.h │ ├── sample.c │ ├── sample.h │ ├── sdk_config.h │ ├── seal_embedded.c │ ├── seal_embedded.h │ ├── shake256 │ │ ├── CMakeLists.txt │ │ ├── cgmanifest.json │ │ ├── fips202.c │ │ ├── fips202.h │ │ ├── keccakf1600.asm │ │ ├── keccakf1600.c │ │ └── keccakf1600.h │ ├── timer.c │ ├── timer.h │ ├── uint_arith.c │ ├── uint_arith.h │ ├── uintmodarith.h │ ├── uintops.h │ ├── user_defines.h │ └── util_print.h ├── linker.ld ├── scripts │ ├── app_manifest_sphere_a7.txt │ ├── app_manifest_sphere_m4.txt │ ├── change_defines.py │ ├── commands_sphere_a7.gdb │ ├── commands_sphere_m4.gdb │ ├── gdb_launch_sphere_a7.sh │ ├── gdb_launch_sphere_m4.sh │ ├── minirc_sphere_m4.dfl │ ├── ocd_launch_sphere_m4.sh │ ├── sphere_a7_launch_cl.sh │ ├── sphere_m4_launch_cl.sh │ └── test_all_configs.sh └── test │ ├── CMakeLists.txt │ ├── api_tests.c │ ├── applibs_versions.h │ ├── ckks_tests_asym.c │ ├── ckks_tests_common.c │ ├── ckks_tests_common.h │ ├── ckks_tests_encode.c │ ├── ckks_tests_sym.c │ ├── fft_tests.c │ ├── main.c │ ├── modulo_tests.c │ ├── network_tests.c │ ├── ntt_tests.c │ ├── sample_tests.c │ ├── test_common.h │ ├── uintmodarith_tests.c │ └── uintops_tests.c ├── pipelines ├── device_docker.yml └── device_local.yml └── tools └── scripts └── clang-format-all.sh /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: Google 4 | AllowShortLoopsOnASingleLine: true 5 | AllowShortCaseLabelsOnASingleLine: true 6 | AllowShortIfStatementsOnASingleLine: true 7 | AllowShortBlocksOnASingleLine: true 8 | AllowShortFunctionsOnASingleLine: false 9 | AlignConsecutiveAssignments: true 10 | BreakBeforeBraces: Custom 11 | BraceWrapping: 12 | AfterEnum: false 13 | AfterFunction: true 14 | AfterStruct: true 15 | AfterCaseLabel: false 16 | BeforeElse: true 17 | AfterControlStatement: true 18 | BinPackParameters: true 19 | ColumnLimit: 100 20 | DerivePointerAlignment: false 21 | IncludeBlocks: Regroup 22 | IndentPPDirectives: None 23 | IndentWidth: 4 24 | IndentGotoLabels: false 25 | PointerAlignment: Right 26 | TabWidth: 4 27 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/azurespheresdk:latest AS dev 2 | 3 | FROM dev AS build 4 | COPY ./device /src/ 5 | WORKDIR /out 6 | RUN cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="/opt/azurespheresdk/CMakeFiles/AzureSphereToolchain.cmake" \ 7 | -DAZURE_SPHERE_TARGET_API_SET="latest-lts" -DCMAKE_BUILD_TYPE="Release" -DSE_BUILD_LOCAL=OFF -DSE_BUILD_TYPE="Tests" -DSE_BUILD_M4=OFF "/src" 8 | ENTRYPOINT [ "ninja" ] 9 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v2.0.0 4 | hooks: 5 | - id: check-added-large-files 6 | - id: trailing-whitespace 7 | - id: end-of-file-fixer 8 | - repo: local 9 | hooks: 10 | - id: clang-format 11 | name: clang-format 12 | entry: clang-format 13 | language: system 14 | files: \.(c|cpp|h)$ 15 | args: ["-i"] 16 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | # List of Changes 2 | 3 | ## Version 1.1.0 4 | 5 | ### New Features 6 | 7 | - Added explicit support for other parameter sets (for degree = 1024, 2048, 8192, and 16384, as well as an alternate prime set for degree = 4096) 8 | - Adapter can now just be build once for any of the supported degrees, and degree can be specied as a command line argument 9 | - Added scripts to [`device/scripts`](device/scripts) to automatically test configurations of the library 10 | 11 | ### Bug Fixes 12 | 13 | - Added an extra index map setting to fix memory bug encountered in certain edge-case configurations of the library 14 | - Fixed error with generated header files for special primes > 30 bits 15 | - Fixed error with IFFT header file generation 16 | - Fixed error with NTT tests 17 | 18 | ### Minor API Changes 19 | 20 | - Scale is now automatically set for default parameters 21 | - `set_custom_parms_ckks` now includes a parameter to set the scale 22 | 23 | ### Other 24 | 25 | - Corrected minor typos in code comments 26 | - Added description comments for some functions 27 | - Added `const` and explicit type casting as good practice 28 | - Added `memset` after array creation instances for when `malloc` is not used 29 | - Removed support for degree < 1024, which was just for initial debugging 30 | - Fixed path issue when building for an Azure Sphere A7 target 31 | - Updated adapter [`CMakeLists.txt`](adapter/CMakeLists.txt) to use Microsoft SEAL 3.7.2 32 | - Other minor code changes 33 | 34 | ## Version 1.0.0 35 | 36 | - Initial commit 37 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This project welcomes contributions and suggestions. 4 | Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. 5 | 6 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). 7 | Simply follow the instructions provided by the bot. 8 | You will only need to do this once across all repos using our CLA. 9 | 10 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 11 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 12 | 13 | ### Pull Requests 14 | 15 | Submit pull requrests to **branch *contrib***. 16 | Pull requests to any other branch will not be accepted. 17 | 18 | When you submit a pull request, a CLA bot will automatically determine whether you need to **provide a CLA** and decorate the PR appropriately (e.g., status check, comment). 19 | Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. 20 | 21 | ### Formatting 22 | 23 | SEAL-Embedded uses a customized `.clang-format` configuration for C/C++ code styling. 24 | A script `tools/scripts/clang-format-all.sh` is provided to easily format all C/C++ sources and headers in the `adapter`, `device`, and `example` directories. 25 | To ensure the code is properly formatted before making a pull request, we highly recommend using [pre-commit](https://pre-commit.com/). 26 | Note that the repository includes a `.pre-commit-config.yaml` that describes the appropriate formatting checks. 27 | 28 | Documentation are mostly written in GitHub-flavored Markdown. 29 | A line break is required after each full sentence. 30 | -------------------------------------------------------------------------------- /ISSUES.md: -------------------------------------------------------------------------------- 1 | # Issues 2 | 3 | ## Technical questions 4 | 5 | The best way to get help with technical questions is on [StackOverflow](https://stackoverflow.com/questions/tagged/seal) using the `[seal]` tag. 6 | To contact the Microsoft SEAL team directly, please email [sealcrypto@microsoft.com](mailto:sealcrypto@microsoft.com). 7 | 8 | ## Bug reports 9 | 10 | We appreciate community efforts to find and fix bugs and issues in Microsoft SEAL. 11 | If you believe you have found a bug or want to report some other issue, please 12 | do so on [GitHub](https://github.com/Microsoft/SEAL-Embedded/issues). To help others 13 | determine what the problem may be, we provide a helpful script that collects 14 | relevant system information that you can submit with the bug report (see below). 15 | 16 | ### System information 17 | 18 | To collect system information for an improved bug report, please run 19 | ``` 20 | make -C tools system_info 21 | ``` 22 | This will result in a file `system_info.tar.gz` to be generated, which you can 23 | optionally attach with your bug report. 24 | 25 | ## Critical security issues 26 | 27 | For reporting critical security issues, see [SECURITY.md](SECURITY.md). 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | THIRD-PARTY SOFTWARE NOTICES AND INFORMATION 2 | 3 | This software incorporates components from the projects listed below. The original copyright notices 4 | and the licenses under which Microsoft received such components are set forth below and are provided for 5 | informational purposes only. Microsoft reserves all rights not expressly granted herein, whether by 6 | implication, estoppel or otherwise. 7 | 8 | This software includes parts of the pqm4 library (https://github.com/mupq/pqm4). 9 | The code from pqm4 library used in SEAL-Embedded is licensed under CC0 Universal, version 1.0. You can find a copy of this license at https://creativecommons.org/publicdomain/zero/1.0/legalcode 10 | 11 | This software includes parts of the Microsoft SEAL library (https://github.com/microsoft/SEAL). 12 | The Kyber library is licensed under the MIT license. You can find a copy of this license at https://github.com/microsoft/SEAL/blob/main/LICENSE. 13 | 14 | This software includes parts of the Nordic Semiconductor nRF5 SDK (https://www.nordicsemi.com/Products/Development-software/nRF5-SDK/Download). 15 | The nRF5 SDK is licensed under the nRF5 SDK license. You can find a copy of this license at https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v12.x.x/doc/12.3.0/nRF5_Nordic_license.txt. 16 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ## Correct Use of SEAL-Embedded 2 | 3 | SEAL-Embedded supports encryption with either a secret key (symmetric) or a public key (asymmetric). 4 | When symmetric encryption is used, the secret key must be stored in device memory and is thus vulnerable to attackers with access to the device. 5 | Once the secret key is leaked, all previous data encrypted with the secret key (or a public key associated with the secret key) is at risk. 6 | Therefore, deployments of SEAL-Embedded should avoid using symmetric encryption, unless the deployment has been reviewed by security and cryptography experts. 7 | 8 | ## Correct Use of Microsoft SEAL 9 | 10 | Please see the [SECURITY.md document for Microsoft SEAL](https://github.com/microsoft/SEAL/blob/main/SECURITY.md#correct-use-of-microsoft-seal). 11 | 12 | ## Security 13 | 14 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 15 | 16 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. 17 | 18 | ## Reporting Security Issues 19 | 20 | **Please do not report security vulnerabilities through public GitHub issues.** 21 | 22 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 23 | 24 | If you prefer to submit without logging in, send an email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 25 | 26 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 27 | 28 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 29 | 30 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 31 | * Full paths of source file(s) related to the manifestation of the issue 32 | * The location of the affected source code (tag/branch/commit or direct URL) 33 | * Any special configuration required to reproduce the issue 34 | * Step-by-step instructions to reproduce the issue 35 | * Proof-of-concept or exploit code (if possible) 36 | * Impact of the issue, including how an attacker might exploit the issue 37 | 38 | This information will help us triage your report more quickly. 39 | 40 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 41 | 42 | ## Preferred Languages 43 | 44 | We prefer all communications to be in English. 45 | 46 | ## Policy 47 | 48 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 49 | 50 | 51 | -------------------------------------------------------------------------------- /adapter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | # Licensed under the MIT license. 3 | 4 | cmake_minimum_required(VERSION 3.13) 5 | 6 | # [option] CMAKE_BUILD_TYPE (default: "Release") 7 | # Build in one of the following modes: Release, Debug, MiniSizeRel, or RelWithDebInfo. 8 | # Most generators recognize these and can set the compiler flags accordingly. We set 9 | # the build type here before creating the project to prevent the CMake generator from 10 | # overriding our default of "Release". 11 | if(NOT CMAKE_BUILD_TYPE) 12 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE) 13 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY 14 | STRINGS "Release" "Debug" "MinSizeRel" "RelWithDebInfo") 15 | endif() 16 | message(STATUS "Build type (CMAKE_BUILD_TYPE): ${CMAKE_BUILD_TYPE}") 17 | 18 | if(CMAKE_BUILD_TYPE STREQUAL "Debug") 19 | # In Debug mode, enable extra compiler flags. 20 | include(CheckCXXCompilerFlag) 21 | # For easier adding of CXX compiler flags 22 | function(se_enable_cxx_compiler_flag_if_supported flag) 23 | string(FIND "${CMAKE_CXX_FLAGS}" "${flag}" flag_already_set) 24 | if(flag_already_set EQUAL -1) 25 | message(STATUS "Adding CXX compiler flag: ${flag} ...") 26 | check_cxx_compiler_flag("${flag}" flag_supported) 27 | if(flag_supported) 28 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE) 29 | endif() 30 | unset(flag_supported CACHE) 31 | endif() 32 | endfunction() 33 | if(NOT MSVC AND SEAL_DEBUG) 34 | se_enable_cxx_compiler_flag_if_supported("-Wall") 35 | se_enable_cxx_compiler_flag_if_supported("-Wextra") 36 | se_enable_cxx_compiler_flag_if_supported("-Wconversion") 37 | se_enable_cxx_compiler_flag_if_supported("-Wshadow") 38 | se_enable_cxx_compiler_flag_if_supported("-pedantic") 39 | endif() 40 | endif() 41 | 42 | project(SEAL_Embedded_Adapter VERSION 1.1.0 LANGUAGES CXX) 43 | 44 | if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13) 45 | cmake_policy(SET CMP0077 NEW) 46 | endif() 47 | 48 | # [option] SE_ADAPTER_USE_CXX17_OPTION_STR (default: ON) 49 | # Use C++17, use C++14 otherwise. An error will be thrown if SEAL_USE_CXX17 is ON but SE_ADAPTER_USE_CXX17 is OFF. 50 | set(SE_ADAPTER_USE_CXX17_OPTION_STR "Use C++17") 51 | option(SE_ADAPTER_USE_CXX17 ${SE_ADAPTER_USE_CXX17_OPTION_STR} ON) 52 | message(STATUS "SE_ADAPTER_USE_CXX17: ${SE_ADAPTER_USE_CXX17}") 53 | 54 | # Enable security-related compile options (MSVC only) 55 | set(SE_ADAPTER_SECURE_COMPILE_OPTIONS_OPTION_STR "Enable Control Flow Guard and Spectre mitigations (MSVC only)") 56 | option(SE_ADAPTER_SECURE_COMPILE_OPTIONS ${SE_ADAPTER_SECURE_COMPILE_OPTIONS_OPTION_STR} OFF) 57 | mark_as_advanced(SE_ADAPTER_SECURE_COMPILE_OPTIONS) 58 | 59 | # Source tree 60 | set(SE_ADAPTER_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) 61 | set(SE_ADAPTER_CONFIG_IN_FILENAME ${CMAKE_CURRENT_LIST_DIR}/config.h.in) 62 | set(SE_ADAPTER_THIRDPARTY_DIR ${CMAKE_CURRENT_LIST_DIR}/thirdparty) 63 | 64 | # Build tree 65 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${OUTLIB_PATH}) 66 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${OUTLIB_PATH}) 67 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) 68 | set(SE_ADAPTER_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) 69 | set(SE_ADAPTER_CONFIG_H_FILENAME ${CMAKE_CURRENT_BINARY_DIR}/config.h) 70 | 71 | ######################### 72 | # External Dependencies # 73 | ######################### 74 | 75 | # [option] SE_ADAPTER_BUILD_DEPS (default: ON) 76 | # Download and build missing dependencies, throw error if disabled. 77 | set(SE_ADAPTER_BUILD_DEPS_OPTION_STR "Automatically download and build unmet dependencies") 78 | option(SE_ADAPTER_BUILD_DEPS ${SE_ADAPTER_BUILD_DEPS_OPTION_STR} ON) 79 | message(STATUS "SE_ADAPTER_BUILD_DEPS: ${SE_ADAPTER_BUILD_DEPS}") 80 | 81 | if(SE_ADAPTER_BUILD_DEPS) 82 | include(FetchContent) 83 | mark_as_advanced(FETCHCONTENT_BASE_DIR) 84 | mark_as_advanced(FETCHCONTENT_FULLY_DISCONNECTED) 85 | mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED) 86 | mark_as_advanced(FETCHCONTENT_QUIET) 87 | endif() 88 | 89 | # Microsoft SEAL 90 | if(SE_ADAPTER_BUILD_DEPS) 91 | message(STATUS "Microsoft SEAL: download ...") 92 | set(SE_ADAPTER_FETCHCONTENT_BASE_DIR_OLD ${FETCHCONTENT_BASE_DIR}) 93 | set(FETCHCONTENT_BASE_DIR ${SE_ADAPTER_THIRDPARTY_DIR} CACHE STRING "" FORCE) 94 | FetchContent_Declare( 95 | seal 96 | GIT_REPOSITORY https://github.com/microsoft/SEAL.git 97 | GIT_TAG 79234726053c45eede688400aa219fdec0810bd8 # 3.7.2 98 | ) 99 | FetchContent_GetProperties(seal) 100 | 101 | if(NOT seal_POPULATED) 102 | FetchContent_Populate(seal) 103 | set(SEAL_USE_CXX17 ON) 104 | set(SEAL_BUILD_DEPS ON) 105 | mark_as_advanced(FETCHCONTENT_SOURCE_DIR_SEAL) 106 | mark_as_advanced(FETCHCONTENT_UPDATES_DISCONNECTED_SEAL) 107 | message(STATUS ${seal_SOURCE_DIR}) 108 | add_subdirectory( 109 | ${seal_SOURCE_DIR} 110 | EXCLUDE_FROM_ALL) 111 | endif() 112 | set(FETCHCONTENT_BASE_DIR ${SE_ADAPTER_FETCHCONTENT_BASE_DIR_OLD} CACHE STRING "" FORCE) 113 | unset(SE_ADAPTER_FETCHCONTENT_BASE_DIR_OLD) 114 | else() 115 | find_package(SEAL 3.7 QUIET REQUIRED) 116 | if(NOT SEAL_FOUND) 117 | message(FATAL_ERROR "Microsoft SEAL: not found") 118 | else() 119 | message(STATUS "Microsoft SEAL: found") 120 | endif() 121 | endif() 122 | if(NOT SE_ADAPTER_USE_CXX17 AND SEAL_USE_CXX17) 123 | message(FATAL_ERROR "CXX standards mismatch: SE_ADAPTER_USE_CXX17 is OFF, SEAL_USE_CXX17 is ON") 124 | endif() 125 | 126 | ################# 127 | # Configuration # 128 | ################# 129 | 130 | # Set a directory to save output files generated by SEAL-Embedded Adapter 131 | set(SE_ADAPTER_FILE_OUTPUT_DIR ${CMAKE_CURRENT_LIST_DIR}/../device CACHE STRING "File output directory" FORCE) 132 | message(STATUS "File output directory: ${SE_ADAPTER_FILE_OUTPUT_DIR}") 133 | if(NOT EXISTS ${SE_ADAPTER_FILE_OUTPUT_DIR}/adapter_output_data) 134 | make_directory(${SE_ADAPTER_FILE_OUTPUT_DIR}/adapter_output_data) 135 | endif() 136 | 137 | # Create the config file 138 | configure_file(${SE_ADAPTER_CONFIG_IN_FILENAME} ${SE_ADAPTER_CONFIG_H_FILENAME}) 139 | 140 | ##################################### 141 | # SEAL-Embedded Adapter C++ library # 142 | ##################################### 143 | 144 | # TODO: factorize adapter and build a C++ library 145 | 146 | #################################### 147 | # SEAL-Embedded Adapter Executable # 148 | #################################### 149 | 150 | add_executable(se_adapter) 151 | target_sources(se_adapter 152 | PRIVATE 153 | adapter.cpp 154 | fileops.cpp 155 | generate.cpp 156 | convert.cpp 157 | utils.cpp 158 | ) 159 | target_include_directories(se_adapter PUBLIC $) 160 | if(TARGET SEAL::seal) 161 | target_link_libraries(se_adapter PRIVATE SEAL::seal) 162 | elseif(TARGET SEAL::seal_shared) 163 | target_link_libraries(se_adapter PRIVATE SEAL::seal_shared) 164 | else() 165 | message(FATAL_ERROR "Cannot find target SEAL::seal or SEAL::seal_shared") 166 | endif() 167 | -------------------------------------------------------------------------------- /adapter/config.h.in: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file config.h 6 | */ 7 | 8 | #pragma once 9 | 10 | #define SE_ADAPTER_FILE_OUTPUT_DIR "@SE_ADAPTER_FILE_OUTPUT_DIR@" 11 | -------------------------------------------------------------------------------- /adapter/convert.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file convert.h 6 | 7 | @brief Functions to convert secret keys, public keys, and ciphertexts to NTT or non-NTT form, and 8 | compare secret key and public key instances. 9 | */ 10 | 11 | #pragma once 12 | 13 | #include "generate.h" // PublicKeyWrapper 14 | #include "seal/seal.h" 15 | 16 | /** 17 | Converts a secret key to NTT form. 18 | 19 | @param[in] context SEAL context 20 | @param[in,out] sk Secret key to convert 21 | */ 22 | void sk_to_ntt_form(const seal::SEALContext &context, seal::SecretKey &sk); 23 | 24 | /** 25 | Converts a secret key to non-NTT form. 26 | 27 | @param[in] context SEAL context 28 | @param[in,out] sk Secret key to convert 29 | */ 30 | void sk_to_non_ntt_form(const seal::SEALContext &context, seal::SecretKey &sk); 31 | 32 | /** 33 | Converts a public key to NTT form. 34 | 35 | @param[in] context SEAL context 36 | @param[in,out] pk_wr Wrapper containing public key to convert 37 | */ 38 | void pk_to_ntt_form(const seal::SEALContext &context, PublicKeyWrapper &pk_wr); 39 | 40 | /** 41 | Converts a public key to non-NTT form. 42 | 43 | @param[in] context SEAL context 44 | @param[in,out] pk_wr Wrapper containing public key to convert 45 | */ 46 | void pk_to_non_ntt_form(const seal::SEALContext &context, PublicKeyWrapper &pk_wr); 47 | 48 | /** 49 | Converts a ciphertext to NTT form. 50 | 51 | @param[in] evaluator SEAL evaluator 52 | @param[in,out] c_in Ciphertext to convert 53 | */ 54 | void ct_to_ntt_form(seal::Evaluator &evaluator, seal::Ciphertext &c_in); 55 | 56 | /** 57 | Converts a ciphertext to non-NTT form. 58 | 59 | @param[in] evaluator SEAL evaluator 60 | @param[in,out] c_in Ciphertext to convert 61 | */ 62 | void ct_to_non_ntt_form(seal::Evaluator &evaluator, seal::Ciphertext &c_in); 63 | 64 | /** 65 | Converts a plaintext to NTT form. 66 | 67 | @param[in] context SEAL context 68 | @param[in,out] pt Plaintext to convert 69 | */ 70 | void pt_to_ntt_form(const seal::SEALContext &context, seal::Plaintext &pt); 71 | 72 | /** 73 | Converts a plaintext to non-NTT form. 74 | 75 | @param[in] context SEAL context 76 | @param[in,out] pt Plaintext to convert 77 | */ 78 | void pt_to_non_ntt_form(const seal::SEALContext &context, seal::Plaintext &pt); 79 | 80 | /** 81 | Compares two secret key instances to see if they match. 82 | 83 | Note: This function may modify SecretKey instances to compare NTT and non-NTT forms of the secret 84 | key, but should revert all changes before returning. 85 | 86 | @param[in] context SEAL context 87 | @param[in] sk1 Secret key 1 88 | @param[in] sk2 Secret key 2 89 | @param[in] incl_sp If true, compares "special prime" component of secret keys 90 | @param[in] should_match If true, throws an error if sk1 != sk2 (debugging only) 91 | */ 92 | void compare_sk(const seal::SEALContext &context, seal::SecretKey &sk1, seal::SecretKey &sk2, 93 | bool incl_sp, bool should_match); 94 | 95 | /** 96 | Compares two public key instances to see if they match. 97 | 98 | Note: This function may modify PublicKeyWrapper instances to compare NTT and non-NTT forms of the 99 | public key, but should revert all changes before returning. 100 | 101 | @param[in] context SEAL context 102 | @param[in] pk1_wr Public key 1 wrapper 103 | @param[in] pk2_wr Public key 2 wrapper 104 | @param[in] incl_sp If true, compares "special prime" component of public keys 105 | @param[in] should_match If true, throws an error if pk1 != pk2 (debugging only) 106 | */ 107 | void compare_pk(const seal::SEALContext &context, PublicKeyWrapper &pk1_wr, 108 | PublicKeyWrapper &pk2_wr, bool incl_sp, bool should_match); 109 | -------------------------------------------------------------------------------- /adapter/generate.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file generate.h 6 | 7 | @brief Functions to generate secret keys, public keys, ifft/ntt roots, and index map (i.e. 8 | pi-inverse) values. Useful for generating objects to load onto a SEAL-Embedded device. 9 | */ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | #include "seal/seal.h" 16 | 17 | /** 18 | Wrapper struct for Public key. Required to keep track of whether public key is in NTT form. 19 | 20 | @param pk Pointer to public key 21 | @param is_ntt If true, pk is in NTT form 22 | */ 23 | typedef struct PublicKeyWrapper 24 | { 25 | seal::PublicKey *pk; 26 | bool is_ntt; 27 | } PublicKeyWrapper; 28 | 29 | /** 30 | Returns the upper 32 bits of a 64-bit value 31 | */ 32 | static inline uint32_t upper32(uint64_t val) 33 | { 34 | return (val >> 32) & 0xFFFFFFFF; 35 | } 36 | 37 | /** 38 | Generates and saves a secret key to file. 39 | 40 | @param[in] sk_fpath Path to file to store the secret key in SEAL-Embedded form 41 | @param[in] str_sk_fpath Path to code file to hard-code the values of the secret key 42 | @param[in] seal_sk_fpath Path to file to store the secret key in SEAL form 43 | @param[in] context SEAL context 44 | */ 45 | void gen_save_secret_key(std::string sk_fpath, std::string str_sk_fpath, std::string seal_sk_fpath, 46 | const seal::SEALContext &context); 47 | 48 | /** 49 | Generates and saves a public key to file. 50 | 51 | In order to generate the public key, the key generator must read in the secret key from file. This 52 | file may either be: 1) the file created using SEAL-Embedded's adapter save functionality 53 | (SEAL-Embedded form). In this case, set use_seal_sk_fpath to 0 and set sk_fpath to the path to the 54 | secret key. 2) the file created using SEAL's stream save functionality (SEAL form). In this case, 55 | set use_seal_sk_fpath to 1 and set seal_sk_fpath to the path to the secret key. 56 | 57 | @param[in] dirpath Path to the directory to store file containing public key in 58 | SEAL-Embedded form 59 | @param[in] seal_pk_fpath Path to file to store public key 60 | @param[in] sk_fpath Path to file storing secret key in SEAL-Embedded form 61 | @param[in] seal_sk_fpath Path to file storing secret key in SEAL form 62 | @param[in] context SEAL context 63 | @param[in] use_seal_sk_fpath If true, use seal_sk_fpath to load secret key. Else, use sk_fpath 64 | */ 65 | void gen_save_public_key(std::string dirpath, std::string seal_pk_fpath, std::string sk_fpath, 66 | std::string seal_sk_fpath, const seal::SEALContext &context, 67 | bool use_seal_sk_fpath); 68 | 69 | /** 70 | Generates and saves the IFFT roots to file for use with SEAL-Embedded. 71 | 72 | @param[in] dirpath Path to the directory to store file containing ifft roots 73 | @param[in] context SEAL context 74 | @param[in] high_byte_first Toggle for endianness 75 | @param[in] string_roots If true, generate string header file too 76 | */ 77 | void gen_save_ifft_roots(std::string dirpath, const seal::SEALContext &context, 78 | bool high_byte_first, bool string_roots); 79 | 80 | /** 81 | Generates and saves the NTT roots to file for use with SEAL-Embedded. 82 | 83 | @param[in] dirpath Path to directory to store file containing NTT roots 84 | @param[in] context SEAL context 85 | @param[in] lazy If true, generates "fast" NTT roots (false = regular roots) 86 | @param[in] inverse If true, generates inverse NTT roots (false = forward roots) 87 | @param[in] high_byte_first Toggle for endianness 88 | @param[in] string_roots If true, generate string header file too 89 | */ 90 | void gen_save_ntt_roots(std::string dirpath, const seal::SEALContext &context, bool lazy, 91 | bool inverse, bool high_byte_first, bool string_roots); 92 | 93 | /** 94 | Generates and saves the index map (i.e. pi-inverse) to file for use with SEAL-Embedded. 95 | Also generates a code file with hard-coded index map values for use with SEAL-Embedded. 96 | 97 | @param[in] dirpath Path to directory to store file containing index map values 98 | @param[in] context SEAL context 99 | @param[in] high_byte_first Toggle for endianness 100 | */ 101 | void gen_save_index_map(std::string dirpath, const seal::SEALContext &context, 102 | bool high_byte_first); 103 | -------------------------------------------------------------------------------- /device/CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "environments": [ 3 | { 4 | "environment": "AzureSphere" 5 | } 6 | ], 7 | "configurations": [ 8 | { 9 | "name": "ARM-Debug-Sphere-A7", 10 | "generator": "Ninja", 11 | "configurationType": "Debug", 12 | "inheritEnvironments": [ 13 | "AzureSphere" 14 | ], 15 | "buildRoot": "${projectDir}\\out\\${name}", 16 | "installRoot": "${projectDir}\\install\\${name}", 17 | "cmakeToolchain": "${env.AzureSphereDefaultSDKDir}CMakeFiles\\AzureSphereToolchain.cmake", 18 | "buildCommandArgs": "-v", 19 | "ctestCommandArgs": "", 20 | "variables": [ 21 | { 22 | "name": "AZURE_SPHERE_TARGET_API_SET", 23 | "value": "latest-lts" 24 | } 25 | ] 26 | }, 27 | { 28 | "name": "ARM-Release-Sphere-A7", 29 | "generator": "Ninja", 30 | "configurationType": "Release", 31 | "inheritEnvironments": [ 32 | "AzureSphere" 33 | ], 34 | "buildRoot": "${projectDir}\\out\\${name}", 35 | "installRoot": "${projectDir}\\install\\${name}", 36 | "cmakeToolchain": "${env.AzureSphereDefaultSDKDir}CMakeFiles\\AzureSphereToolchain.cmake", 37 | "buildCommandArgs": "-v", 38 | "ctestCommandArgs": "", 39 | "variables": [ 40 | { 41 | "name": "AZURE_SPHERE_TARGET_API_SET", 42 | "value": "latest-lts" 43 | } 44 | ] 45 | }, 46 | { 47 | "name": "ARM-Debug-Sphere-M4", 48 | "generator": "Ninja", 49 | "configurationType": "Debug", 50 | "inheritEnvironments": [ 51 | "AzureSphere" 52 | ], 53 | "buildRoot": "${projectDir}\\out\\${name}", 54 | "installRoot": "${projectDir}\\install\\${name}", 55 | "cmakeToolchain": "${env.AzureSphereDefaultSDKDir}CMakeFiles\\AzureSphereRTCoreToolchain.cmake", 56 | "buildCommandArgs": "-v", 57 | "ctestCommandArgs": "", 58 | "variables": [ 59 | { 60 | "name": "ARM_GNU_PATH", 61 | "value": "${env.DefaultArmToolsetPath}" 62 | } 63 | ] 64 | }, 65 | { 66 | "name": "ARM-Release-Sphere-M4", 67 | "generator": "Ninja", 68 | "configurationType": "Release", 69 | "inheritEnvironments": [ 70 | "AzureSphere" 71 | ], 72 | "buildRoot": "${projectDir}\\out\\${name}", 73 | "installRoot": "${projectDir}\\install\\${name}", 74 | "cmakeToolchain": "${env.AzureSphereDefaultSDKDir}CMakeFiles\\AzureSphereRTCoreToolchain.cmake", 75 | "buildCommandArgs": "-v", 76 | "ctestCommandArgs": "", 77 | "variables": [ 78 | { 79 | "name": "ARM_GNU_PATH", 80 | "value": "${env.DefaultArmToolsetPath}" 81 | } 82 | ] 83 | } 84 | ] 85 | } 86 | -------------------------------------------------------------------------------- /device/app_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "SchemaVersion": 1, 3 | "Name": "SealEmbeddedApp", 4 | "ComponentId": "5a4b43d1-a3b0-4f9f-a9c9-30a4cc52a2f2", 5 | "EntryPoint": "/bin/app", 6 | "CmdArgs": [], 7 | "Capabilities": { 8 | "Gpio": [ 9 ], 9 | "AllowedApplicationConnections": [], 10 | "AllowedConnections": [ "www.neverssl.com", "neverssl.com", "httpstat.us"] 11 | }, 12 | "ApplicationType": "Default" 13 | } 14 | -------------------------------------------------------------------------------- /device/bench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | # Licensed under the MIT license. 3 | 4 | set(SE_BENCH_SOURCE_FILES ${SE_BENCH_SOURCE_FILES} 5 | ${CMAKE_CURRENT_LIST_DIR}/bench_sym.c 6 | ${CMAKE_CURRENT_LIST_DIR}/bench_asym.c 7 | ${CMAKE_CURRENT_LIST_DIR}/bench_ntt.c 8 | ${CMAKE_CURRENT_LIST_DIR}/bench_ifft.c 9 | ${CMAKE_CURRENT_LIST_DIR}/bench_sample.c 10 | ${CMAKE_CURRENT_LIST_DIR}/bench_index_map.c 11 | ${CMAKE_CURRENT_LIST_DIR}/main.c 12 | ) 13 | 14 | set(SE_BENCH_SOURCE_FILES ${SE_BENCH_SOURCE_FILES} PARENT_SCOPE) 15 | -------------------------------------------------------------------------------- /device/bench/bench_asym.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file bench_asym.c 6 | */ 7 | 8 | #include "defines.h" 9 | #ifdef SE_ENABLE_TIMERS 10 | 11 | #include 12 | 13 | #include "bench_common.h" 14 | #include "ckks_asym.h" 15 | #include "ckks_common.h" 16 | #include "ckks_sym.h" 17 | #include "parameters.h" 18 | #include "timer.h" 19 | 20 | // -- Configuration 21 | // #define SE_BENCH_ENCODE 22 | // #define SE_BENCH_SAMPLE 23 | // #define SE_BENCH_ENCRYPT 24 | #define SE_BENCH_FULL 25 | 26 | // -- Sanity check 27 | #if !defined(SE_BENCH_ENCODE) && !defined(SE_BENCH_SAMPLE) && !defined(SE_BENCH_ENCRYPT) && \ 28 | !defined(SE_BENCH_FULL) 29 | #define SE_BENCH_ENCODE 30 | #endif 31 | 32 | void bench_asym(void) 33 | { 34 | // -- Config -- 35 | #ifdef SE_USE_MALLOC 36 | const size_t n = 4096; 37 | const size_t nprimes = 3; 38 | #else 39 | const size_t n = SE_DEGREE_N; 40 | const size_t nprimes = SE_NPRIMES; 41 | #endif 42 | // ------------ 43 | 44 | Parms parms; 45 | parms.pk_from_file = true; 46 | parms.is_asymmetric = true; 47 | parms.sample_s = false; 48 | parms.small_u = true; // should be this 49 | 50 | #ifdef SE_USE_MALLOC 51 | print_ckks_mempool_size(n, 0); 52 | ZZ *mempool = ckks_mempool_setup_asym(n); 53 | #else 54 | print_ckks_mempool_size(); 55 | ZZ mempool_local[MEMPOOL_SIZE]; 56 | memset(*mempool_local, 0, MEMPOOL_SIZE * sizeof(ZZ)); 57 | ZZ *mempool = &(mempool_local[0]); 58 | #endif 59 | 60 | // -- Get pointers 61 | SE_PTRS se_ptrs_local; 62 | ckks_set_ptrs_asym(n, mempool, &se_ptrs_local); 63 | double complex *conj_vals = se_ptrs_local.conj_vals; 64 | int64_t *conj_vals_int = se_ptrs_local.conj_vals_int_ptr; 65 | double complex *ifft_roots = se_ptrs_local.ifft_roots; 66 | ZZ *pk_c0 = se_ptrs_local.c0_ptr; 67 | ZZ *pk_c1 = se_ptrs_local.c1_ptr; 68 | uint16_t *index_map = se_ptrs_local.index_map_ptr; 69 | ZZ *ntt_roots = se_ptrs_local.ntt_roots_ptr; 70 | ZZ *ntt_u_e1_pte = se_ptrs_local.ntt_pte_ptr; 71 | ZZ *u = se_ptrs_local.ternary; 72 | flpt *v = se_ptrs_local.values; 73 | int8_t *e1 = se_ptrs_local.e1_ptr; 74 | size_t vlen = n / 2; 75 | 76 | SE_PRNG prng; 77 | 78 | // -- Set up parameters and index_map if applicable 79 | ckks_setup(n, nprimes, index_map, &parms); 80 | 81 | const char *bench_name = "Asymmetric_Encryption"; 82 | print_bench_banner(bench_name, &parms); 83 | 84 | Timer timer; 85 | const size_t COUNT = 10; 86 | float t_total = 0, t_min = 0, t_max = 0, t_curr = 0; 87 | for (size_t b_itr = 0; b_itr < COUNT + 1; b_itr++) 88 | { 89 | t_curr = 0; 90 | se_assert(parms.nprimes >= 1); 91 | gen_flpt_quarter_poly(v, -10, vlen); 92 | 93 | // -- Begin encode-encrypt sequence 94 | #if defined(SE_BENCH_ENCODE) || defined(SE_BENCH_FULL) 95 | reset_start_timer(&timer); 96 | #endif 97 | // -- First, encode base 98 | ckks_encode_base(&parms, v, vlen, index_map, ifft_roots, conj_vals); 99 | 100 | #ifdef SE_BENCH_ENCODE 101 | stop_timer(&timer); 102 | t_curr += read_timer(timer, MICRO_SEC); 103 | #elif defined(SE_BENCH_SAMPLE) 104 | reset_start_timer(&timer); 105 | #endif 106 | // -- Sample u, e0, e1. Store e0 directly as part of conj_vals_int 107 | ckks_asym_init(&parms, NULL, &prng, conj_vals_int, u, e1); 108 | 109 | #if defined(SE_BENCH_SAMPLE) || defined(SE_BENCH_FULL) 110 | stop_timer(&timer); 111 | t_curr += read_timer(timer, MICRO_SEC); 112 | #endif 113 | 114 | for (size_t i = 0; i < parms.nprimes; i++) 115 | { 116 | #if defined(SE_BENCH_ENCRYPT) || defined(SE_BENCH_FULL) 117 | reset_start_timer(&timer); 118 | #endif 119 | ckks_encode_encrypt_asym(&parms, conj_vals_int, u, e1, ntt_roots, ntt_u_e1_pte, NULL, 120 | NULL, pk_c0, pk_c1); 121 | 122 | #if defined(SE_BENCH_ENCRYPT) || defined(SE_BENCH_FULL) 123 | stop_timer(&timer); 124 | t_curr += read_timer(timer, MICRO_SEC); 125 | #endif 126 | 127 | if (b_itr && (i + 1) == parms.nprimes) 128 | set_print_time_vals(bench_name, t_curr, b_itr, &t_total, &t_min, &t_max); 129 | 130 | // -- We need to execute these printf calls to ensure the compiler does not 131 | // optimize away generation of c0 and c1 polynomials. 132 | print_poly_full("c0 ", pk_c0, n); 133 | print_poly_full("c1 ", pk_c1, n); 134 | if ((i + 1) < parms.nprimes) ckks_next_prime_asym(&parms, u); 135 | } 136 | } 137 | 138 | print_time_vals(bench_name, t_curr, COUNT, &t_total, &t_min, &t_max); 139 | print_bench_banner(bench_name, &parms); 140 | 141 | #ifdef SE_USE_MALLOC 142 | if (mempool) 143 | { 144 | free(mempool); 145 | mempool = 0; 146 | } 147 | delete_parameters(&parms); 148 | #endif 149 | } 150 | #endif 151 | -------------------------------------------------------------------------------- /device/bench/bench_common.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file bench_common.h 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "defines.h" 11 | #include "modulo.h" // barrett_reduce 12 | #include "sample.h" // random_zz 13 | #include "util_print.h" // print functions, printf 14 | 15 | /* 16 | Generate "random" uint 17 | Note: random_zz is already defined in sample.h 18 | */ 19 | static inline ZZ random_zzq(Modulus *q) 20 | { 21 | return barrett_reduce(random_zz(), q); 22 | } 23 | 24 | static inline ZZ random_zz_half(void) 25 | { 26 | // -- Don't do this. It doesn't work. 27 | // ZZ result; 28 | // getrandom((void*)&result, sizeof(result)/2, 0); 29 | return random_zz() & 0xFFFF; 30 | } 31 | 32 | static inline ZZ random_zz_quarter(void) 33 | { 34 | return random_zz() & 0xFF; 35 | } 36 | 37 | // Generate "random" double 38 | static inline double gen_double_half(int64_t div) 39 | { 40 | return (double)random_zz_half() / (double)div; 41 | } 42 | 43 | // "Random" uint poly 44 | static inline void random_zz_poly(ZZ *poly, size_t n) 45 | { 46 | for (size_t i = 0; i < n; i++) { poly[i] = random_zz(); } 47 | } 48 | 49 | static inline void random_zzq_poly(ZZ *poly, size_t n, Modulus *q) 50 | { 51 | for (size_t i = 0; i < n; i++) { poly[i] = random_zzq(q); } 52 | } 53 | 54 | // "Random" double complex 55 | static inline void gen_double_complex_half_vec(double complex *vec, int64_t div, size_t n) 56 | { 57 | for (size_t i = 0; i < n; i++) 58 | { vec[i] = (double complex)_complex(gen_double_half(div), gen_double_half(div)); } 59 | } 60 | 61 | static inline double gen_double_quarter(int64_t div) 62 | { 63 | return (double)random_zz_quarter() / (double)div; 64 | } 65 | 66 | static inline flpt gen_flpt_quarter(int64_t div) 67 | { 68 | return (flpt)gen_double_quarter(div); 69 | } 70 | 71 | // "Random" flpt 72 | static inline void gen_flpt_quarter_poly(flpt *poly, int64_t div, size_t n) 73 | { 74 | for (size_t i = 0; i < n; i++) poly[i] = gen_flpt_quarter(div); 75 | } 76 | 77 | static inline void print_bench_banner(const char *benchmark_name, const Parms *parms) 78 | { 79 | #if defined(SE_ON_NRF5) && defined(SE_NRF5_UART_PRINTF_ENABLED) 80 | return; // Printing banner on the NRF5 via serial doesn't work well. Just don't do it. 81 | #endif 82 | printf("***************************************************\n"); 83 | printf("Running Benchmark: %s\n", benchmark_name); 84 | if (parms) 85 | { 86 | printf("n: %zu, nprimes: %zu, scale: %0.2f\n", parms->coeff_count, parms->nprimes, 87 | parms->scale); 88 | print_config(!parms->is_asymmetric); 89 | } 90 | printf("***************************************************\n"); 91 | } 92 | 93 | static inline void set_time_vals(float time_curr, float *time_total, float *time_min, 94 | float *time_max) 95 | { 96 | se_assert(time_total); 97 | time_total[0] += time_curr; 98 | if (time_min && ((time_curr < time_min[0]) || (time_min[0] == 0))) time_min[0] = time_curr; 99 | if (time_max && (time_curr > time_max[0])) time_max[0] = time_curr; 100 | } 101 | 102 | static inline void print_time_vals(const char *name, float time_curr, size_t num_runs, 103 | float *time_total, float *time_min, float *time_max) 104 | { 105 | printf("\n\n"); 106 | for (size_t k = 0; k < 3; k++) 107 | { 108 | printf("-- Runtimes out of %zu runs (%s) --\n", num_runs, name); 109 | printf("curr runtime (us) = %0.2f\n", time_curr); 110 | if (num_runs) printf("avg runtime (us) = %0.2f\n", time_total[0] / (float)num_runs); 111 | printf("max runtime (us) = %0.2f\n", time_max[0]); 112 | printf("min runtime (us) = %0.2f\n", time_min[0]); 113 | } 114 | } 115 | 116 | static inline void set_print_time_vals(const char *name, float time_curr, size_t num_runs, 117 | float *time_total, float *time_min, float *time_max) 118 | { 119 | set_time_vals(time_curr, time_total, time_min, time_max); 120 | print_time_vals(name, time_curr, num_runs, time_total, time_min, time_max); 121 | } 122 | -------------------------------------------------------------------------------- /device/bench/bench_ifft.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file bench_ifft.h 6 | */ 7 | 8 | #include "defines.h" 9 | 10 | #ifdef SE_ENABLE_TIMERS 11 | #include 12 | #include 13 | #include 14 | 15 | #include "bench_common.h" 16 | #include "ckks_common.h" 17 | #include "fft.h" 18 | #include "fileops.h" 19 | #include "parameters.h" 20 | #include "timer.h" 21 | #include "util_print.h" 22 | 23 | // -- Configuration 24 | // #define SE_BENCH_IFFT_ROOTS 25 | // #define SE_BENCH_IFFT_COMP 26 | #define SE_BENCH_IFFT_FULL 27 | 28 | // -- Sanity check 29 | #if !defined(SE_BENCH_IFFT_ROOTS) && !defined(SE_BENCH_IFFT_COMP) && !defined(SE_BENCH_IFFT_FULL) 30 | #define SE_BENCH_IFFT_ROOTS 31 | #endif 32 | 33 | #ifndef SE_USE_MALLOC 34 | #if defined(SE_IFFT_LOAD_FULL) || defined(SE_IFFT_ONE_SHOT) 35 | #define IFFT_TEST_ROOTS_MEM SE_DEGREE_N 36 | #else 37 | #define IFFT_TEST_ROOTS_MEM 0 38 | #endif 39 | #endif 40 | 41 | void bench_ifft(void) 42 | { 43 | #ifdef SE_USE_MALLOC 44 | const PolySizeType n = 4096; 45 | #else 46 | const PolySizeType n = SE_DEGREE_N; 47 | #endif 48 | size_t logn = get_log2(n); 49 | 50 | size_t size_mult = sizeof(double complex) / sizeof(ZZ); 51 | size_t vec_size = n * size_mult; 52 | #ifdef SE_IFFT_OTF 53 | size_t ifft_roots_size = 0; 54 | #else 55 | size_t ifft_roots_size = n * size_mult; 56 | #endif 57 | 58 | size_t mempool_size = vec_size + ifft_roots_size; 59 | #ifdef SE_USE_MALLOC 60 | ZZ *mempool = calloc(mempool_size, sizeof(ZZ)); 61 | #else 62 | ZZ mempool[SE_DEGREE_N + IFFT_TEST_ROOTS_MEM]; 63 | memset(&mempool, 0, (SE_DEGREE_N + IFFT_TEST_ROOTS_MEM) * sizeof(ZZ)); 64 | #endif 65 | 66 | double complex *vec = (double complex *)mempool; 67 | 68 | #ifdef SE_IFFT_OTF 69 | double complex *ifft_roots = 0; 70 | #else 71 | double complex *ifft_roots = (double complex *)&(mempool[vec_size]); 72 | #endif 73 | 74 | Parms parms; 75 | ckks_setup(n, 1, NULL, &parms); 76 | 77 | #ifdef SE_BENCH_IFFT_ROOTS 78 | const char *bench_name = "inverse fft (timing roots load/gen)"; 79 | #elif defined(SE_BENCH_IFFT_COMP) 80 | const char *bench_name = "inverse fft (timing computation)"; 81 | #else 82 | const char *bench_name = "inverse fft (timing roots + computation)"; 83 | #endif 84 | print_bench_banner(bench_name, &parms); 85 | 86 | Timer timer; 87 | const size_t COUNT = 10; 88 | float t_total = 0, t_min = 0, t_max = 0; 89 | volatile float t_curr = 0; 90 | for (size_t b_itr = 0; b_itr < COUNT + 1; b_itr++) 91 | { 92 | t_curr = 0; 93 | gen_double_complex_half_vec(vec, pow(10, 6), n); 94 | 95 | #if defined(SE_IFFT_LOAD_FULL) 96 | se_secure_zero_memset(ifft_roots, n * sizeof(double complex)); 97 | #endif 98 | 99 | #if defined(SE_BENCH_IFFT_ROOTS) || defined(SE_BENCH_IFFT_FULL) 100 | reset_start_timer(&timer); 101 | #endif 102 | // -- Load or generate the roots -- 103 | #ifdef SE_IFFT_LOAD_FULL 104 | se_assert(ifft_roots); 105 | load_ifft_roots(n, ifft_roots); 106 | #endif 107 | 108 | #ifdef SE_BENCH_IFFT_ROOTS 109 | stop_timer(&timer); 110 | t_curr += read_timer(timer, MICRO_SEC); 111 | #elif defined(SE_BENCH_IFFT_COMP) 112 | reset_start_timer(&timer); 113 | #endif 114 | 115 | // -- Ifft computation -- 116 | ifft_inpl(vec, n, logn, ifft_roots); 117 | 118 | #if defined(SE_BENCH_IFFT_COMP) || defined(SE_BENCH_IFFT_FULL) 119 | stop_timer(&timer); 120 | t_curr += read_timer(timer, MICRO_SEC); 121 | #endif 122 | 123 | if (b_itr) set_print_time_vals(bench_name, t_curr, b_itr, &t_total, &t_min, &t_max); 124 | print_poly_double_complex_full("ifft(vec)", vec, n); 125 | } 126 | 127 | print_time_vals(bench_name, t_curr, COUNT, &t_total, &t_min, &t_max); 128 | print_bench_banner(bench_name, &parms); 129 | 130 | #ifdef SE_USE_MALLOC 131 | if (mempool) 132 | { 133 | free(mempool); 134 | mempool = 0; 135 | } 136 | #endif 137 | 138 | delete_parameters(&parms); 139 | } 140 | #endif 141 | 142 | #ifndef SE_USE_MALLOC 143 | #ifdef IFFT_TEST_ROOTS_MEM 144 | #undef IFFT_TEST_ROOTS_MEM 145 | #endif 146 | #endif 147 | -------------------------------------------------------------------------------- /device/bench/bench_index_map.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file bench_index_map.c 6 | */ 7 | 8 | #include "defines.h" 9 | 10 | #if defined(SE_ENABLE_TIMERS) 11 | #include 12 | #include 13 | 14 | #include "bench_common.h" 15 | #include "ckks_common.h" 16 | #include "fileops.h" 17 | #include "parameters.h" 18 | #include "timer.h" 19 | #include "util_print.h" 20 | 21 | void bench_index_map(void) 22 | { 23 | #ifdef SE_USE_MALLOC 24 | const PolySizeType n = 4096; 25 | uint16_t *vec = calloc(n, sizeof(uint16_t)); 26 | #else 27 | const PolySizeType n = SE_DEGREE_N; 28 | uint16_t vec[SE_DEGREE_N]; 29 | memset(&vec, 0, SE_DEGREE_N * sizeof(uint16_t)); 30 | #endif 31 | uint16_t *index_map = &(vec[0]); 32 | 33 | Parms parms; 34 | ckks_setup(n, 1, NULL, &parms); 35 | 36 | const char *bench_name = "index map"; 37 | print_bench_banner(bench_name, &parms); 38 | 39 | Timer timer; 40 | const size_t COUNT = 10; 41 | float t_total = 0, t_min = 0, t_max = 0, t_curr = 0; 42 | for (size_t b_itr = 0; b_itr < COUNT + 1; b_itr++) 43 | { 44 | se_secure_zero_memset(index_map, n * sizeof(uint16_t)); 45 | reset_start_timer(&timer); 46 | 47 | #if defined(SE_INDEX_MAP_PERSIST) || defined(SE_INDEX_MAP_OTF) 48 | ckks_calc_index_map(&parms, index_map); 49 | #elif defined(SE_INDEX_MAP_LOAD) || defined(SE_INDEX_MAP_LOAD_PERSIST) || \ 50 | defined(SE_INDEX_MAP_LOAD_PERSIST_SYM_LOAD_ASYM) 51 | load_index_map(&parms, index_map); 52 | #endif 53 | 54 | stop_timer(&timer); 55 | t_curr = read_timer(timer, MICRO_SEC); 56 | fflush(stdout); 57 | 58 | if (b_itr) set_print_time_vals(bench_name, t_curr, b_itr, &t_total, &t_min, &t_max); 59 | 60 | fflush(stdout); 61 | print_poly_uint16_full("indices", index_map, n); 62 | fflush(stdout); 63 | } 64 | fflush(stdout); 65 | print_time_vals(bench_name, t_curr, COUNT, &t_total, &t_min, &t_max); 66 | 67 | fflush(stdout); 68 | print_bench_banner(bench_name, &parms); 69 | 70 | #ifdef SE_USE_MALLOC 71 | if (vec) 72 | { 73 | free(vec); 74 | vec = 0; 75 | } 76 | #endif 77 | 78 | delete_parameters(&parms); 79 | } 80 | #endif 81 | -------------------------------------------------------------------------------- /device/bench/bench_ntt.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file bench_ntt.c 6 | */ 7 | 8 | #include "defines.h" 9 | 10 | #if defined(SE_ENABLE_TIMERS) 11 | #include 12 | #include 13 | 14 | #include "bench_common.h" 15 | #include "ckks_common.h" 16 | #include "fileops.h" 17 | #include "ntt.h" 18 | #include "parameters.h" 19 | #include "timer.h" 20 | #include "util_print.h" 21 | 22 | // -- Configuration 23 | // #define SE_BENCH_NTT_ROOTS 24 | // #define SE_BENCH_NTT_COMP 25 | #define SE_BENCH_NTT_FULL 26 | 27 | // -- Sanity check 28 | #if !defined(SE_BENCH_NTT_ROOTS) && !defined(SE_BENCH_NTT_COMP) && !defined(SE_BENCH_NTT_FULL) 29 | #define SE_BENCH_NTT_ROOTS 30 | #endif 31 | 32 | #ifndef SE_USE_MALLOC 33 | #ifdef SE_NTT_FAST 34 | #define NTT_TESTS_ROOTS_MEM 2 * SE_DEGREE_N 35 | #elif defined(SE_NTT_REG) || defined(SE_NTT_ONE_SHOT) 36 | #define NTT_TESTS_ROOTS_MEM SE_DEGREE_N 37 | #else 38 | #define NTT_TESTS_ROOTS_MEM 0 39 | #endif 40 | #endif 41 | 42 | void bench_ntt(void) 43 | { 44 | #ifdef SE_USE_MALLOC 45 | const PolySizeType n = 4096; 46 | #else 47 | const PolySizeType n = SE_DEGREE_N; 48 | #endif 49 | 50 | const size_t vec_size = n; 51 | 52 | #ifdef SE_USE_MALLOC 53 | 54 | #ifdef SE_NTT_FAST 55 | size_t ntt_roots_size = 2 * n; 56 | #elif defined(SE_NTT_OTF) 57 | size_t ntt_roots_size = 0; 58 | #else 59 | size_t ntt_roots_size = n; 60 | #endif 61 | 62 | size_t mempool_size = vec_size + ntt_roots_size; 63 | ZZ *mempool = calloc(mempool_size, sizeof(ZZ)); 64 | #else 65 | ZZ mempool[SE_DEGREE_N + NTT_TESTS_ROOTS_MEM]; 66 | memset(&mempool, 0, (SE_DEGREE_N + NTT_TEST_ROOTS_MEM) * sizeof(ZZ)); 67 | #endif 68 | 69 | ZZ *vec = mempool; 70 | 71 | #ifdef SE_NTT_OTF 72 | ZZ *ntt_roots = 0; 73 | #else 74 | ZZ *ntt_roots = &(mempool[vec_size]); 75 | #endif 76 | 77 | Parms parms; 78 | parms.nprimes = 1; 79 | ckks_setup(n, 1, NULL, &parms); 80 | 81 | #ifdef SE_BENCH_NTT_ROOTS 82 | const char *bench_name = "ntt (timing roots load/gen)"; 83 | #elif defined(SE_BENCH_NTT_COMP) 84 | const char *bench_name = "ntt (timing computation)"; 85 | #else 86 | const char *bench_name = "ntt (timing roots + computation)"; 87 | #endif 88 | print_bench_banner(bench_name, &parms); 89 | 90 | Timer timer; 91 | const size_t COUNT = 10; 92 | float t_total = 0, t_min = 0, t_max = 0, t_curr = 0; 93 | for (size_t b_itr = 0; b_itr < COUNT + 1; b_itr++) 94 | { 95 | t_curr = 0; 96 | random_zzq_poly(vec, n, parms.curr_modulus); 97 | 98 | #ifdef SE_NTT_FAST 99 | se_secure_zero_memset(ntt_roots, n * sizeof(ZZ) * 2); 100 | #elif defined(SE_NTT_REG) || defined(SE_NTT_ONE_SHOT) 101 | se_secure_zero_memset(ntt_roots, n * sizeof(ZZ)); 102 | #endif 103 | 104 | #if defined(SE_BENCH_NTT_ROOTS) || defined(SE_BENCH_NTT_FULL) 105 | printf("curr runtime (us) = %0.2f\n", t_curr); 106 | reset_start_timer(&timer); 107 | #endif 108 | 109 | // -- Load or generate the roots 110 | ntt_roots_initialize(&parms, ntt_roots); 111 | 112 | #ifdef SE_BENCH_NTT_ROOTS 113 | stop_timer(&timer); 114 | t_curr += read_timer(timer, MICRO_SEC); 115 | #elif defined(SE_BENCH_NTT_COMP) 116 | reset_start_timer(&timer); 117 | #endif 118 | 119 | // -- Ntt computation 120 | ntt_inpl(&parms, ntt_roots, vec); 121 | 122 | #if defined(SE_BENCH_NTT_COMP) || defined(SE_BENCH_NTT_FULL) 123 | stop_timer(&timer); 124 | t_curr += read_timer(timer, MICRO_SEC); 125 | #endif 126 | if (b_itr) set_print_time_vals(bench_name, t_curr, b_itr, &t_total, &t_min, &t_max); 127 | print_poly_full("ntt(vec)", vec, n); 128 | } 129 | 130 | print_time_vals(bench_name, t_curr, COUNT, &t_total, &t_min, &t_max); 131 | print_bench_banner(bench_name, &parms); 132 | 133 | #ifdef SE_USE_MALLOC 134 | if (mempool) 135 | { 136 | free(mempool); 137 | mempool = 0; 138 | } 139 | #endif 140 | 141 | delete_parameters(&parms); 142 | } 143 | #endif 144 | 145 | #ifdef SE_USE_MALLOC 146 | #ifdef NTT_TESTS_ROOTS_MEM 147 | #undef NTT_TESTS_ROOTS_MEM 148 | #endif 149 | #endif 150 | -------------------------------------------------------------------------------- /device/bench/bench_sample.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file bench_sample.c 6 | */ 7 | 8 | #include "defines.h" 9 | #ifdef SE_ENABLE_TIMERS 10 | #include "bench_common.h" 11 | #include "sample.h" 12 | #include "timer.h" 13 | #include "util_print.h" 14 | 15 | void bench_sample_poly_cbd(void) 16 | { 17 | #ifdef SE_USE_MALLOC 18 | const size_t n = 4096; 19 | int8_t *vec = calloc(n, sizeof(int8_t)); 20 | #else 21 | const size_t n = SE_DEGREE_N; 22 | int8_t vec[SE_DEGREE_N]; 23 | #endif 24 | 25 | int8_t *poly = &(vec[0]); 26 | const char *bench_name = "sample poly cbd"; 27 | print_bench_banner(bench_name, 0); 28 | 29 | SE_PRNG prng; 30 | prng_randomize_reset(&prng, NULL); 31 | 32 | Timer timer; 33 | const size_t COUNT = 10; 34 | float t_total = 0, t_min = 0, t_max = 0, t_curr = 0; 35 | for (size_t b_itr = 0; b_itr < COUNT + 1; b_itr++) 36 | { 37 | reset_start_timer(&timer); 38 | 39 | sample_poly_cbd_generic_prng_16(n, &prng, poly); // now stores [e1] 40 | 41 | stop_timer(&timer); 42 | t_curr = read_timer(timer, MICRO_SEC); 43 | if (b_itr) set_print_time_vals(bench_name, t_curr, b_itr, &t_total, &t_min, &t_max); 44 | print_poly_int8_full("cbd poly", poly, n); 45 | } 46 | print_time_vals(bench_name, t_curr, COUNT, &t_total, &t_min, &t_max); 47 | #ifdef SE_USE_MALLOC 48 | if (vec) 49 | { 50 | free(vec); 51 | vec = 0; 52 | } 53 | #endif 54 | } 55 | 56 | void bench_sample_ternary_small(void) 57 | { 58 | #ifdef SE_USE_MALLOC 59 | const size_t n = 4096; 60 | ZZ *vec = malloc(n / 4); 61 | #else 62 | const size_t n = SE_DEGREE_N; 63 | ZZ vec[SE_DEGREE_N / 4]; 64 | #endif 65 | 66 | Parms parms; 67 | parms.small_u = 1; 68 | set_parms_ckks(n, 1, &parms); 69 | 70 | ZZ *poly = &(vec[0]); 71 | const char *bench_name = "sample poly ternary (small)"; 72 | print_bench_banner(bench_name, &parms); 73 | SE_PRNG prng; 74 | prng_randomize_reset(&prng, NULL); 75 | Timer timer; 76 | const size_t COUNT = 10; 77 | float t_total = 0, t_min = 0, t_max = 0, t_curr = 0; 78 | for (size_t b_itr = 0; b_itr < COUNT + 1; b_itr++) 79 | { 80 | reset_start_timer(&timer); 81 | 82 | sample_small_poly_ternary_prng_96(n, &prng, poly); 83 | 84 | stop_timer(&timer); 85 | t_curr = read_timer(timer, MICRO_SEC); 86 | if (b_itr) set_print_time_vals(bench_name, t_curr, b_itr, &t_total, &t_min, &t_max); 87 | print_poly_ternary_full("ternary (small) poly", poly, n, 1); 88 | } 89 | print_time_vals(bench_name, t_curr, COUNT, &t_total, &t_min, &t_max); 90 | #ifdef SE_USE_MALLOC 91 | if (vec) 92 | { 93 | free(vec); 94 | vec = 0; 95 | } 96 | delete_parameters(&parms); 97 | #endif 98 | } 99 | 100 | void bench_sample_uniform(void) 101 | { 102 | #ifdef SE_USE_MALLOC 103 | const size_t n = 4096; 104 | ZZ *vec = calloc(n, sizeof(ZZ)); 105 | #else 106 | const size_t n = SE_DEGREE_N; 107 | ZZ vec[SE_DEGREE_N]; 108 | #endif 109 | 110 | Parms parms; 111 | set_parms_ckks(n, 1, &parms); 112 | 113 | ZZ *poly = &(vec[0]); 114 | const char *bench_name = "sample poly uniform"; 115 | print_bench_banner(bench_name, &parms); 116 | 117 | SE_PRNG prng; 118 | prng_randomize_reset(&prng, NULL); 119 | 120 | Timer timer; 121 | const size_t COUNT = 10; 122 | float t_total = 0, t_min = 0, t_max = 0, t_curr = 0; 123 | for (size_t b_itr = 0; b_itr < COUNT + 1; b_itr++) 124 | { 125 | reset_start_timer(&timer); 126 | 127 | sample_poly_uniform(&parms, &prng, poly); 128 | 129 | stop_timer(&timer); 130 | t_curr = read_timer(timer, MICRO_SEC); 131 | if (b_itr) set_print_time_vals(bench_name, t_curr, b_itr, &t_total, &t_min, &t_max); 132 | print_poly_full("uniform poly", poly, n); 133 | } 134 | print_time_vals(bench_name, t_curr, COUNT, &t_total, &t_min, &t_max); 135 | #ifdef SE_USE_MALLOC 136 | if (vec) 137 | { 138 | free(vec); 139 | vec = 0; 140 | } 141 | delete_parameters(&parms); 142 | #endif 143 | } 144 | 145 | void bench_prng_randomize_seed(void) 146 | { 147 | const char *bench_name = "prng randomize seed"; 148 | print_bench_banner(bench_name, 0); 149 | 150 | SE_PRNG prng; 151 | Timer timer; 152 | 153 | const size_t COUNT = 10; 154 | float t_total = 0, t_min = 0, t_max = 0, t_curr = 0; 155 | for (size_t b_itr = 0; b_itr < COUNT + 1; b_itr++) 156 | { 157 | reset_start_timer(&timer); 158 | 159 | prng_randomize_reset(&prng, NULL); 160 | 161 | stop_timer(&timer); 162 | t_curr = read_timer(timer, MICRO_SEC); 163 | if (b_itr) set_print_time_vals(bench_name, t_curr, b_itr, &t_total, &t_min, &t_max); 164 | print_poly_uint8_full("random seed", prng.seed, SE_PRNG_SEED_BYTE_COUNT); 165 | } 166 | print_time_vals(bench_name, t_curr, COUNT, &t_total, &t_min, &t_max); 167 | } 168 | 169 | void bench_prng_fill_buffer(void) 170 | { 171 | const char *bench_name = "prng fill buffer"; 172 | print_bench_banner(bench_name, 0); 173 | 174 | #ifdef SE_USE_MALLOC 175 | const size_t n = 4096; 176 | ZZ *vec = calloc(n, sizeof(ZZ)); 177 | #else 178 | const size_t n = SE_DEGREE_N; 179 | ZZ vec[SE_DEGREE_N]; 180 | #endif 181 | ZZ *poly = &(vec[0]); 182 | 183 | SE_PRNG prng; 184 | 185 | Timer timer; 186 | const size_t COUNT = 10; 187 | float t_total = 0, t_min = 0, t_max = 0, t_curr = 0; 188 | for (size_t b_itr = 0; b_itr < COUNT + 1; b_itr++) 189 | { 190 | prng_randomize_reset(&prng, NULL); 191 | reset_start_timer(&timer); 192 | 193 | prng_fill_buffer(n * sizeof(ZZ), &prng, (void *)poly); 194 | 195 | stop_timer(&timer); 196 | t_curr = read_timer(timer, MICRO_SEC); 197 | if (b_itr) set_print_time_vals(bench_name, t_curr, b_itr, &t_total, &t_min, &t_max); 198 | print_poly_full("random buffer", vec, n); 199 | } 200 | print_time_vals(bench_name, t_curr, COUNT, &t_total, &t_min, &t_max); 201 | #ifdef SE_USE_MALLOC 202 | if (vec) 203 | { 204 | free(vec); 205 | vec = 0; 206 | } 207 | #endif 208 | } 209 | 210 | void bench_prng_randomize_seed_fill_buffer(void) 211 | { 212 | const char *bench_name = "prng randomize + fill buffer"; 213 | print_bench_banner(bench_name, 0); 214 | 215 | #ifdef SE_USE_MALLOC 216 | const size_t n = 4096; 217 | ZZ *vec = calloc(n, sizeof(ZZ)); 218 | #else 219 | const size_t n = SE_DEGREE_N; 220 | ZZ vec[SE_DEGREE_N]; 221 | #endif 222 | ZZ *poly = &(vec[0]); 223 | 224 | SE_PRNG prng; 225 | 226 | Timer timer; 227 | const size_t COUNT = 10; 228 | float t_total = 0, t_min = 0, t_max = 0, t_curr = 0; 229 | for (size_t b_itr = 0; b_itr < COUNT + 1; b_itr++) 230 | { 231 | reset_start_timer(&timer); 232 | 233 | prng_randomize_reset(&prng, NULL); 234 | prng_fill_buffer(n * sizeof(ZZ), &prng, (void *)poly); 235 | 236 | stop_timer(&timer); 237 | t_curr = read_timer(timer, MICRO_SEC); 238 | if (b_itr) set_print_time_vals(bench_name, t_curr, b_itr, &t_total, &t_min, &t_max); 239 | print_poly_full("random buffer", vec, n); 240 | } 241 | print_time_vals(bench_name, t_curr, COUNT, &t_total, &t_min, &t_max); 242 | #ifdef SE_USE_MALLOC 243 | if (vec) 244 | { 245 | free(vec); 246 | vec = 0; 247 | } 248 | #endif 249 | } 250 | #endif 251 | -------------------------------------------------------------------------------- /device/bench/bench_sym.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file bench_sym.c 6 | */ 7 | 8 | #include "defines.h" 9 | #ifdef SE_ENABLE_TIMERS 10 | #include 11 | 12 | #include "bench_common.h" 13 | #include "ckks_common.h" 14 | #include "ckks_sym.h" 15 | #include "parameters.h" 16 | #include "timer.h" 17 | 18 | // -- Configuration 19 | // #define SE_BENCH_ENCODE 20 | // #define SE_BENCH_SAMPLE 21 | // #define SE_BENCH_ENCRYPT 22 | #define SE_BENCH_FULL 23 | 24 | // -- Sanity check 25 | #if !defined(SE_BENCH_ENCODE) && !defined(SE_BENCH_SAMPLE) && !defined(SE_BENCH_ENCRYPT) && \ 26 | !defined(SE_BENCH_FULL) 27 | #define SE_BENCH_ENCODE 28 | #endif 29 | 30 | void bench_sym(void) 31 | { 32 | #ifdef SE_USE_MALLOC 33 | const size_t n = 4096; 34 | const size_t nprimes = 3; 35 | #else 36 | const size_t n = SE_DEGREE_N; 37 | const size_t nprimes = SE_NPRIMES; 38 | #endif 39 | Parms parms; 40 | parms.is_asymmetric = false; 41 | parms.small_s = true; 42 | parms.sample_s = false; 43 | 44 | // -- Make sure we didn't set this accidentally 45 | if (!parms.sample_s) se_assert(parms.small_s); 46 | 47 | #ifdef SE_USE_MALLOC 48 | print_ckks_mempool_size(n, 1); 49 | ZZ *mempool = ckks_mempool_setup_sym(n); 50 | #else 51 | print_ckks_mempool_size(); 52 | ZZ mempool_local[MEMPOOL_SIZE]; 53 | memset(&mempool_local, 0, MEMPOOL_SIZE * sizeof(ZZ)); 54 | ZZ *mempool = &(mempool_local[0]); 55 | #endif 56 | 57 | // -- Get pointers 58 | SE_PTRS se_ptrs_local; 59 | ckks_set_ptrs_sym(n, mempool, &se_ptrs_local); 60 | double complex *conj_vals = se_ptrs_local.conj_vals; 61 | int64_t *conj_vals_int = se_ptrs_local.conj_vals_int_ptr; 62 | double complex *ifft_roots = se_ptrs_local.ifft_roots; 63 | ZZ *c0 = se_ptrs_local.c0_ptr; 64 | ZZ *c1 = se_ptrs_local.c1_ptr; 65 | uint16_t *index_map = se_ptrs_local.index_map_ptr; 66 | ZZ *ntt_roots = se_ptrs_local.ntt_roots_ptr; 67 | ZZ *ntt_pte = se_ptrs_local.ntt_pte_ptr; 68 | ZZ *s = se_ptrs_local.ternary; 69 | flpt *v = se_ptrs_local.values; 70 | size_t vlen = n / 2; 71 | 72 | SE_PRNG prng; 73 | SE_PRNG shareable_prng; 74 | 75 | // -- Set up parameters and index_map if applicable 76 | ckks_setup(n, nprimes, index_map, &parms); 77 | 78 | // -- If s is allocated space ahead of time, can load ahead of time too 79 | // -- If we are testing and sample s is set, this will also sample s 80 | ckks_setup_s(&parms, NULL, &prng, s); 81 | 82 | const char *bench_name = "Symmetric_Encryption"; 83 | print_bench_banner(bench_name, &parms); 84 | 85 | Timer timer; 86 | const size_t COUNT = 10; 87 | float t_total = 0, t_min = 0, t_max = 0, t_curr = 0; 88 | for (size_t b_itr = 0; b_itr < COUNT + 1; b_itr++) 89 | { 90 | t_curr = 0; 91 | se_assert(parms.nprimes >= 1); 92 | gen_flpt_quarter_poly(v, -10, vlen); 93 | // print_poly_flpt("v ", v, vlen); 94 | 95 | // -- Begin encode-encrypt sequence 96 | #if defined(SE_BENCH_ENCODE) || defined(SE_BENCH_FULL) 97 | reset_start_timer(&timer); 98 | #endif 99 | // -- First, encode base 100 | ckks_encode_base(&parms, v, vlen, index_map, ifft_roots, conj_vals); 101 | // print_poly_int64_full("conj_vals_int ", conj_vals_int_ptr, n); 102 | 103 | #ifdef SE_BENCH_ENCODE 104 | stop_timer(&timer); 105 | t_curr += read_timer(timer, MICRO_SEC); 106 | #elif defined(SE_BENCH_SAMPLE) 107 | reset_start_timer(&timer); 108 | #endif 109 | // -- First prime, so need to sample error e 110 | // -- While sampling error e, add it in place to the base message 111 | ckks_sym_init(&parms, NULL, NULL, &shareable_prng, &prng, conj_vals_int); 112 | 113 | #if defined(SE_BENCH_SAMPLE) || defined(SE_BENCH_FULL) 114 | stop_timer(&timer); 115 | t_curr += read_timer(timer, MICRO_SEC); 116 | #endif 117 | 118 | for (size_t i = 0; i < parms.nprimes; i++) 119 | { 120 | #if defined(SE_BENCH_ENCRYPT) || defined(SE_BENCH_FULL) 121 | reset_start_timer(&timer); 122 | #endif 123 | // -- Per prime Encode + Encrypt 124 | ckks_encode_encrypt_sym(&parms, conj_vals_int, 0, &shareable_prng, s, ntt_pte, 125 | ntt_roots, c0, c1, 0, 0); 126 | 127 | #if defined(SE_BENCH_ENCRYPT) || defined(SE_BENCH_FULL) 128 | stop_timer(&timer); 129 | t_curr += read_timer(timer, MICRO_SEC); 130 | #endif 131 | 132 | if (b_itr && ((i + 1) == parms.nprimes)) 133 | set_print_time_vals(bench_name, t_curr, b_itr, &t_total, &t_min, &t_max); 134 | 135 | // -- We must execute these printf calls to ensure the compiler does not 136 | // optimize away generation of c0 and c1 polynomials. (Note that in the 137 | // ifft truly on-the-fly case, c1 is overwritten by c0 and their 138 | // outputs at this point will therefore be the same. We do not have to 139 | // be concerned about c1 not being evaluated in this case though since 140 | // c1 == a, which is necessary for the generation of c0.) 141 | print_poly_full("c0 ", c0, n); 142 | print_poly_full("c1 ", c1, n); 143 | if ((i + 1) < parms.nprimes) ckks_next_prime_sym(&parms, s); 144 | } 145 | } 146 | 147 | print_time_vals(bench_name, t_curr, COUNT, &t_total, &t_min, &t_max); 148 | print_bench_banner(bench_name, &parms); 149 | 150 | #ifdef SE_USE_MALLOC 151 | if (mempool) 152 | { 153 | free(mempool); 154 | mempool = 0; 155 | } 156 | delete_parameters(&parms); 157 | #endif 158 | } 159 | #endif 160 | -------------------------------------------------------------------------------- /device/bench/main.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file main.c 6 | 7 | Note: While the benchmarks can run back-to-back, on device it is best to run only one benchmark at a 8 | time (i.e., uncomment the benchmark you want to run and uncomment all others before compiling.) 9 | */ 10 | 11 | #include "defines.h" 12 | 13 | #ifdef SE_ENABLE_TIMERS 14 | #include "util_print.h" 15 | 16 | // -- Benchmarks 17 | extern void bench_index_map(void); 18 | extern void bench_ifft(void); 19 | extern void bench_ntt(void); 20 | extern void bench_prng_randomize_seed(void); 21 | extern void bench_prng_fill_buffer(void); 22 | extern void bench_prng_randomize_seed_fill_buffer(void); 23 | extern void bench_sample_uniform(void); 24 | extern void bench_sample_ternary_small(void); 25 | extern void bench_sample_poly_cbd(void); 26 | extern void bench_sym(void); 27 | extern void bench_asym(void); 28 | 29 | #ifdef SE_ON_SPHERE_M4 30 | #include "mt3620.h" 31 | #include "os_hal_gpt.h" 32 | #include "os_hal_uart.h" 33 | 34 | static const uint8_t uart_port_num = OS_HAL_UART_PORT0; 35 | // static const uint8_t uart_port_num = OS_HAL_UART_ISU0; 36 | 37 | /** 38 | Hook for "printf" 39 | @param[in] character Character to print 40 | */ 41 | // /* 42 | void _putchar(char character) 43 | { 44 | mtk_os_hal_uart_put_char(uart_port_num, character); 45 | if (character == '\n') mtk_os_hal_uart_put_char(uart_port_num, '\r'); 46 | } 47 | // */ 48 | 49 | void RTCoreMain(void) 50 | { 51 | // -- Init Vector Table -- 52 | NVIC_SetupVectorTable(); 53 | 54 | // -- Init UART -- 55 | mtk_os_hal_uart_ctlr_init(uart_port_num); 56 | printf("\nUART Inited (port_num=%d)\n", uart_port_num); 57 | 58 | // -- Init GPT -- 59 | // gpt0_int.gpt_cb_hdl = Gpt0Callback; 60 | // gpt0_int.gpt_cb_data = (void *)gpt_cb_data; 61 | mtk_os_hal_gpt_init(); 62 | #else 63 | 64 | int main(void) 65 | { 66 | #ifdef SE_NRF5_UART_PRINTF_ENABLED 67 | se_setup_uart(); 68 | #endif 69 | #endif 70 | 71 | printf("Beginning bench...\n"); 72 | #ifdef SE_RAND_NRF5 73 | se_randomness_init(); // required for nrf 74 | #endif 75 | 76 | // -- Uncomment benchmark to run 77 | // -- Note: All benchmarks use n = 4K, 3 primes if malloc is used, 78 | // SE_DEGREE_N and SE_NPRIMES otherwise 79 | // TODO: make benchmarks easily configurable for other degrees 80 | 81 | bench_index_map(); 82 | bench_ifft(); 83 | bench_ntt(); 84 | bench_prng_randomize_seed(); 85 | bench_prng_fill_buffer(); 86 | bench_prng_randomize_seed_fill_buffer(); 87 | bench_sample_uniform(); 88 | bench_sample_ternary_small(); 89 | bench_sample_poly_cbd(); 90 | bench_sym(); 91 | #if defined(SE_USE_MALLOC) || defined(SE_DEFINE_PK_DATA) 92 | bench_asym(); 93 | #endif 94 | printf("...done with all benchmarks!\n"); 95 | } 96 | #endif 97 | -------------------------------------------------------------------------------- /device/lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | # Licensed under the MIT license. 3 | 4 | set(SE_LIB_SOURCE_FILES ${SE_LIB_SOURCE_FILES} 5 | ${CMAKE_CURRENT_LIST_DIR}/ckks_common.c 6 | ${CMAKE_CURRENT_LIST_DIR}/ckks_sym.c 7 | ${CMAKE_CURRENT_LIST_DIR}/ckks_asym.c 8 | ${CMAKE_CURRENT_LIST_DIR}/fft.c 9 | ${CMAKE_CURRENT_LIST_DIR}/fileops.c 10 | ${CMAKE_CURRENT_LIST_DIR}/modulus.c 11 | ${CMAKE_CURRENT_LIST_DIR}/network.c 12 | ${CMAKE_CURRENT_LIST_DIR}/parameters.c 13 | ${CMAKE_CURRENT_LIST_DIR}/polymodmult.c 14 | ${CMAKE_CURRENT_LIST_DIR}/rng.c 15 | ${CMAKE_CURRENT_LIST_DIR}/sample.c 16 | ${CMAKE_CURRENT_LIST_DIR}/timer.c 17 | ${CMAKE_CURRENT_LIST_DIR}/uint_arith.c 18 | ${CMAKE_CURRENT_LIST_DIR}/ntt.c 19 | ${CMAKE_CURRENT_LIST_DIR}/intt.c 20 | ${CMAKE_CURRENT_LIST_DIR}/seal_embedded.c 21 | ) 22 | 23 | add_subdirectory(shake256) 24 | set(SE_LIB_SOURCE_FILES ${SE_LIB_SOURCE_FILES} PARENT_SCOPE) 25 | -------------------------------------------------------------------------------- /device/lib/ckks_asym.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file ckks_asym.h 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | #include "ckks_common.h" 14 | #include "defines.h" 15 | #include "modulo.h" 16 | #include "parameters.h" 17 | #include "rng.h" 18 | 19 | #ifdef SE_USE_MALLOC 20 | /** 21 | Returns the required size of the memory pool in units of sizeof(ZZ). 22 | 23 | @param[in] degree Desired polynomial ring degree 24 | @returns Required size of the memory pool units of sizeof(ZZ) 25 | */ 26 | size_t ckks_get_mempool_size_asym(size_t degree); 27 | 28 | /** 29 | Sets up the memory pool for CKKS asymmetric encryption. 30 | 31 | Note: This function calls calloc. 32 | 33 | @param[in] degree Desired polynomial ring degree 34 | @returns A handle to the memory pool 35 | */ 36 | ZZ *ckks_mempool_setup_asym(size_t degree); 37 | #endif 38 | 39 | /** 40 | Sets addresses of objects according to parameter settings for asymmetric CKKS encryption. 41 | Should only need to be called once during initial memory allocation. 42 | 43 | @param[in] degree Polynomial ring degree 44 | @param[in] mempool Handle to memory pool 45 | @param[out] se_ptrs Pointers object. Pointers will be updated to mempool locations 46 | */ 47 | void ckks_set_ptrs_asym(size_t degree, ZZ *mempool, SE_PTRS *se_ptrs); 48 | 49 | /** 50 | Generates a CKKS public key from a CKKS secret key. Mainly useful for testing. 51 | 52 | Size req: If SE_NTT_OTF is not defined, 'ntt_roots' must contain space for roots according to NTT 53 | type chosen. If seed != NULL, seed must be SE_PRNG_SEED_BYTE_COUNT long. 54 | 55 | @param[in] parms Parameters set by ckks_setup 56 | @param[in] s_small Secret key in small form 57 | @param ntt_roots [Optional]. Scratch for ntt roots. Ignored if SE_NTT_OTF is chosen. 58 | @param[in] seed [Optional]. Seed to seed 'prng' with. 59 | @param[in,out] shareable_prng A shareable prng instance. Will reset and update counter. 60 | @param[out] s_save Secret key mod current modulus (in ntt form) (for testing) 61 | @param[out] ep_small Secret key error polynomial ep in small form 62 | @param[out] ntt_ep Expanded ep modulus the current modulus (in ntt form) 63 | @param[out] pk_c0 First component of public key for current modulus 64 | @param[out] pk_c1 Second component of public key for current modulus 65 | */ 66 | void gen_pk(const Parms *parms, ZZ *s_small, ZZ *ntt_roots, uint8_t *seed, SE_PRNG *shareable_prng, 67 | ZZ *s_save, int8_t *ep_small, ZZ *ntt_ep, ZZ *pk_c0, ZZ *pk_c1); 68 | 69 | /** 70 | Initializes values for a single full asymmetric CKKS encryption. Samples the errors (w/o respect to 71 | any prime), as well as the ternary polynomial 'u'. Should be called once per encode-encrypt sequence 72 | (just after ckks_encode_base). 73 | 74 | Note: This function modifies (i.e. resets and re-randomizes) the prng instance. 75 | 76 | Size req: If seed != NULL, seed must be SE_PRNG_SEED_BYTE_COUNT long. 77 | 78 | @param[in] parms Parameters set by ckks_setup 79 | @param[in] seed [Optional]. Seed to seed 'prng' with. 80 | @param[in,out] prng PRNG instance needed to generate error and ternary polynomials. 81 | @param[in,out] conj_vals_int As pointed to by conj_vals_int_ptr (n int64 values). In: 82 | ckks plaintext; Out: plaintext + e0 (in non-reduced form) 83 | @param[out] u Ternary polynomial 84 | @param[out] e1 Error e1 (in non-reduced form) 85 | */ 86 | void ckks_asym_init(const Parms *parms, uint8_t *seed, SE_PRNG *prng, int64_t *conj_vals_int, ZZ *u, 87 | int8_t *e1); 88 | 89 | /** 90 | Encodes and asymmetrically encrypts a vector of values using CKKS, for the current modulus prime. 91 | Optionally returns some additional values useful for testing, if SE_DISABLE_TESTING_CAPABILITY is 92 | not defined. 93 | 94 | Size req: 'ntt_roots' should have space for NTT roots according to NTT option chosen. 95 | 'ntt_u_e1_pte', 'pk_c0', and 'pk_c1' should have space for n ZZ elements. If testing, 96 | 'ntt_u_save' and 'ntt_e1_save' should have space for n ZZ elements. 97 | 98 | @param[in] parms Parameters set by ckks_setup 99 | @param[in] conj_vals_int As set by ckks_asym_init 100 | @param[in] u As set by ckks_asym_init 101 | @param[in] e1 As set by ckks_asym_init 102 | @param ntt_roots [Optional]. Scratch space for ntt roots. Ignored if SE_NTT_OTF is chosen. 103 | @param[out] ntt_u_e1_pte Scratch space. Out: m + e0 in reduced and ntt form (useful for testing). 104 | @param[out] ntt_u_save [Optional, ignored if NULL]. Expanded and ntt form of u (for testing) 105 | @param[out] ntt_e1_save [Optional, ignored if NULL]. Reduced and ntt form of e1 (for testing) 106 | @param[out] pk_c0 First component of ciphertext 107 | @param[out] pk_c1 Second component of ciphertext 108 | */ 109 | void ckks_encode_encrypt_asym(const Parms *parms, const int64_t *conj_vals_int, const ZZ *u, 110 | const int8_t *e1, ZZ *ntt_roots, ZZ *ntt_u_e1_pte, ZZ *ntt_u_save, 111 | ZZ *ntt_e1_save, ZZ *pk_c0, ZZ *pk_c1); 112 | 113 | /** 114 | Updates parameters to next prime in modulus switching chain for asymmetric CKKS encryption. Also 115 | reduces ternary polynomial to next prime modulus if used in expanded form (compressed form u will be 116 | reduced later). 117 | 118 | @param[in,out] parms Parameters set by ckks_setup. curr_modulus_idx will be advanced by 1 119 | @param[in,out] u [Optional]. Ternary polynomial for asymmetric encryption. 120 | Can be null if 'u' is stored in compressed form. 121 | @returns 1 on success, 0 on failure (reached end of modulus chain) 122 | */ 123 | bool ckks_next_prime_asym(Parms *parms, ZZ *u); 124 | -------------------------------------------------------------------------------- /device/lib/ckks_sym.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file ckks_sym.h 6 | 7 | Symmetric CKKS encryption. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | 14 | #include "ckks_common.h" 15 | #include "defines.h" 16 | #include "parameters.h" 17 | #include "rng.h" 18 | 19 | #ifdef SE_USE_MALLOC 20 | /** 21 | Returns the required size of the memory pool in units of sizeof(ZZ). 22 | 23 | @param[in] degree Desired polynomial ring degree 24 | @returns Required size of the memory pool units of sizeof(ZZ) 25 | */ 26 | size_t ckks_get_mempool_size_sym(size_t degree); 27 | 28 | /** 29 | Sets up the memory pool for CKKS symmetric encryption. 30 | 31 | Note: This function calls calloc. 32 | 33 | @param[in] degree Desired polynomial ring degree 34 | @returns A handle to the memory pool 35 | */ 36 | ZZ *ckks_mempool_setup_sym(size_t degree); 37 | #endif 38 | 39 | /** 40 | Sets addresses of objects according to parameter settings for symmetric CKKS encryption. 41 | Should only need to be called once during initial memory allocation. 42 | 43 | @param[in] degree Polynomial ring degree 44 | @param[in] mempool Handle to memory pool 45 | @param[out] se_ptrs Pointers object. Pointers will be updated to mempool locations. 46 | */ 47 | void ckks_set_ptrs_sym(size_t degree, ZZ *mempool, SE_PTRS *se_ptrs); 48 | 49 | /** 50 | Sets up a CKKS secret key. For symmetric encryption, this should either be called once at the start 51 | during memory allocation (if storing s persistently in working memory) or once per encode-encrypt 52 | sequence (between base and remaining steps, if not storing s persistently in working memory). 53 | 54 | If parms.sample_s == 1, will internally generate the secret key (from the uniform ternary 55 | distribution). This is mainly useful for testing. If parms.sample_s == 0, will read in secret key 56 | from file. 57 | 58 | Size req: If seed is !NULL, seed must be SE_PRNG_SEED_BYTE_COUNT long. 59 | 60 | @param[in] parms Parameters set by ckks_setup 61 | @param[in] seed [Optional]. Seed to seed 'prng' with, if prng is used. 62 | @param[in,out] prng [Optional]. PRNG instance needed to generate randomness for secret key 63 | polynomial. Should not be shared. 64 | @param[out] s Secret key polynomial. Must have space for n coefficients. If 'small' s is 65 | used, this must be 2 bits per coefficient. Otherwise, this must be sizeof(ZZ) 66 | per coefficient. 67 | */ 68 | void ckks_setup_s(const Parms *parms, uint8_t *seed, SE_PRNG *prng, ZZ *s); 69 | 70 | /** 71 | Initializes values for a single full symmetric CKKS encryption. Samples the error (w/o respect to 72 | any prime). Should be called once per encode-encrypt sequence (just after ckks_encode_base). 73 | 74 | Note: This function modifies (i.e. resets and re-randomizes) the prng instance. 75 | 76 | Size req: If seeds are !NULL, seeds must be SE_PRNG_SEED_BYTE_COUNT long. 77 | 78 | @param[in] parms Parameters set by ckks_setup 79 | @param[in] share_seed_in [Optional]. Seed to seed 'shareable_prng' with. 80 | @param[in] seed_in [Optional]. Seed to seed 'prng' with. 81 | @param[in,out] shareable_prng PRNG instance needed to generate first component of ciphertexts. Is 82 | safe to share. 83 | @param[in,out] prng PRNG instance needed to generate error polynomial. Should not be 84 | shared. 85 | @param[in,out] conj_vals_int As pointed to by conj_vals_int_ptr (n int64 values). 86 | In: ckks pt; Out: pt + error (non-reduced) 87 | */ 88 | void ckks_sym_init(const Parms *parms, uint8_t *share_seed_in, uint8_t *seed_in, 89 | SE_PRNG *shareable_prng, SE_PRNG *prng, int64_t *conj_vals_int); 90 | 91 | /** 92 | Encodes and symmetrically encrypts a vector of values using CKKS for the current modulus prime. 93 | 94 | Internally converts various objects to NTT form. If debugging encryption-only (assuming a message of 95 | 0), or if calling to generate a public key, can set conj_vals_int to zero. In this case, must set 96 | ep_small to the compessed form of the error. 97 | 98 | @param[in] parms Parameters set by ckks_setup 99 | @param[in] conj_vals_int [Optional]. See description. 100 | @param[in] ep_small [Optional]. See description. For debugging only. 101 | @param[in,out] shareable_prng PRNG instance needed to generate first component of ciphertexts. Is 102 | safe to share. 103 | @param ntt_pte Scratch space. Will be used to store pt + e (in NTT form) 104 | @param ntt_roots Scratch space. May be used to load NTT roots. 105 | @param[out] c0_s 1st component of the ciphertext. Stores n coeffs of size ZZ. 106 | @param[out] c1 2nd component of the ciphertext. Stores n coeffs of size ZZ. 107 | @param[out] s_save [Optional]. Useful for testing. 108 | @param[out] c1_save [Optional]. Useful for testing. 109 | */ 110 | void ckks_encode_encrypt_sym(const Parms *parms, const int64_t *conj_vals_int, 111 | const int8_t *ep_small, SE_PRNG *shareable_prng, ZZ *s_small, 112 | ZZ *ntt_pte, ZZ *ntt_roots, ZZ *c0_s, ZZ *c1, ZZ *s_save, ZZ *c1_save); 113 | 114 | /** 115 | Updates parameters to next prime in modulus switching chain for symmetric CKKS encryption. Also 116 | converts secret key polynomial to next prime modulus if used in expanded form (compressed form s 117 | will be reduced later). 118 | 119 | @param[in,out] parms Parameters set by ckks_setup. curr_modulus_idx will be advanced by 1 120 | @param[in,out] s [Optional]. Secret key to convert to next modulus prime 121 | @returns 1 on success, 0 on failure (reached end of modulus chain) 122 | */ 123 | bool ckks_next_prime_sym(Parms *parms, ZZ *s); 124 | -------------------------------------------------------------------------------- /device/lib/fft.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file fft.h 6 | 7 | Forward and Inverse Fast Fourier Transform. 8 | 9 | Note: Currently, the fft is only useful for testing, since only the ifft is used in the main 10 | algorithm. Leave both here for future use. 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include "defines.h" 18 | 19 | /* 20 | static inline size_t bitrev(size_t input, size_t numbits) 21 | { 22 | size_t res = 0; 23 | for (size_t i = 0; i < numbits; i++) 24 | { 25 | // -- Get least significant bit of input and place in result. 26 | // -- Shift result to the left towards msb position. 27 | size_t lsb = input & 1; 28 | res <<= 1; 29 | res |= lsb; 30 | input = input >> 1; 31 | } 32 | return res; 33 | } 34 | */ 35 | 36 | /** 37 | Bit reversal algorithm for the FFT/IFFT. 38 | Ex: bitrev(6, 3): 6 = 0b110 -> (bit reverse) -> 0b011 = 3 39 | 40 | Requires: numbits <= 16 41 | 42 | (This does essentially the same as the commented out code above) 43 | 44 | @param[in] input Value to bit reverse 45 | @param[in] numbits Number of bits required to represent input. Must be <= 16. 46 | @returns 'input' in bit reversed order 47 | */ 48 | static inline size_t bitrev(size_t input, size_t numbits) 49 | { 50 | size_t t = (((input & 0xaaaa) >> 1) | ((input & 0x5555) << 1)); 51 | t = (((t & 0xcccc) >> 2) | ((t & 0x3333) << 2)); 52 | t = (((t & 0xf0f0) >> 4) | ((t & 0x0f0f) << 4)); 53 | t = (((t & 0xff00) >> 8) | ((t & 0x00ff) << 8)); 54 | return numbits == 0 ? 0 : t >> (16 - (size_t)(numbits)); 55 | } 56 | 57 | // =========================== 58 | // Roots 59 | // =========================== 60 | 61 | /** 62 | Generates the roots for the FFT from scratch (in bit-reversed order) 63 | 64 | Space req: 'roots' must have storage for n double complex values. 65 | 66 | @param[in] n FFT transform size (number of roots to generate) 67 | @param[in] logn Minimum number of bits required to represent n (i.e. log2(n)) 68 | @param[out] roots FFT roots (in bit-reversed order) 69 | */ 70 | void calc_fft_roots(size_t n, size_t logn, double complex *roots); 71 | 72 | /** 73 | Generates the roots for the IFFT from scratch (in bit-reversed order) 74 | 75 | Space req: 'ifft_roots' must have storage for n double complex values. 76 | 77 | @param[in] n IFFT transform size (number of roots to generate) 78 | @param[in] logn Minimum number of bits required to represent n (i.e. log2(n)) 79 | @param[out] ifft_roots IFFT roots (in bit-reversed order) 80 | */ 81 | void calc_ifft_roots(size_t n, size_t logn, double complex *ifft_roots); 82 | 83 | // =========================== 84 | // FFT/IFFT 85 | // =========================== 86 | /** 87 | In-place Inverse Fast-Fourier Transform using the Harvey butterfly. 88 | 'roots' is ignored (and may be null) if SE_IFFT_OTF is chosen. 89 | 90 | Note: This function does not divide the final result by n. This step must be performed outside of 91 | this function. 92 | 93 | @param[in,out] vec Input/Output vector of n double complex values 94 | @param[in] n IFFT transform size (i.e. polynomial degree) 95 | @param[in] logn Minimum number of bits required to represent n (i.e. log2(n)) 96 | @param[in] roots [Optional]. As set by calc_ifft_roots or load_ifft_roots 97 | */ 98 | void ifft_inpl(double complex *vec, size_t n, size_t logn, const double complex *roots); 99 | 100 | /** 101 | In-place forward Fast-Fourier Transform using the Harvey butterfly. 102 | 'roots' is ignored (and may be null) if SE_FFT_OTF is chosen. 103 | 104 | @param[in,out] vec Input/Output vector of n double complex values. 105 | @param[in] n FFT transform size (i.e. polynomial degree) 106 | @param[in] logn Minimum number of bits required to represent n (i.e. log2(n)) 107 | @param[in] roots [Optional]. As set by calc_fft_roots or load_fft_roots 108 | */ 109 | void fft_inpl(double complex *vec, size_t n, size_t logn, const double complex *roots); 110 | -------------------------------------------------------------------------------- /device/lib/intt.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file intt.h 6 | 7 | Inverse Number Theoretic Transform. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "defines.h" 13 | #include "parameters.h" 14 | 15 | #ifndef SE_DISABLE_TESTING_CAPABILITY // INTT is only needed for on-device testing 16 | /* 17 | For all "Harvey" butterfly INTTs: 18 | The input is a polynomial of degree n in R_q, where n is assumed to be a power of 2 and q is a prime 19 | such that q = 1 (mod 2n). The output is a vector A such that the following hold: 20 | A[j] = a(psi**(2*bit_reverse(j) + 1)), 0 <= j < n. For more details, see the SEAL-Embedded paper and 21 | Michael Naehrig and Patrick Longa's paper. 22 | */ 23 | 24 | /** 25 | Initializes INTT roots. 26 | 27 | If SE_INTT_ONE_SHOT is defined, will calculate INTT roots one by one. 28 | Else if SE_INTT_FAST is defined, will load "fast"/"lazy" roots from file. 29 | Else (if SE_INTT_REG is defined), will load regular roots from file. 30 | 31 | Space req: If SE_DATA_FROM_CODE_DIRECT is not defined, 'intt_roots' should 32 | have space for n ZZ elements if SE_INTT_ONE_SHOT or SE_INTT_REG is defined, 33 | or 2n ZZ elements (i.e. n MUMO elements) if SE_INTT_FAST is defined. 34 | 35 | @param[in] parms Parameters set by ckks_setup 36 | @param[out] intt_roots INTT roots. Will be null if SE_INTT_OTF is defined. 37 | */ 38 | void intt_roots_initialize(const Parms *parms, ZZ *intt_roots); 39 | 40 | /** 41 | Performs a negacyclic inverse NTT using the Harvey butterfly. 42 | 43 | @param[in] parms Parameters set by ckks_setup 44 | @param[in] intt_roots Roots set by intt_roots_initialize. Ignored if SE_INTT_OTF is defined. 45 | @param[in, out] vec Input/output polynomial of n ZZ elements 46 | */ 47 | void intt_inpl(const Parms *parms, const ZZ *intt_roots, ZZ *vec); 48 | #endif 49 | -------------------------------------------------------------------------------- /device/lib/modulus.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file modulus.c 6 | */ 7 | 8 | #include "modulus.h" 9 | 10 | #include // uint64_t, UINT64_MAX 11 | #include // memcpy 12 | 13 | #include "defines.h" 14 | #include "util_print.h" 15 | 16 | void set_modulus_custom(const ZZ q, ZZ hw, ZZ lw, Modulus *mod) 17 | { 18 | mod->value = q; 19 | mod->const_ratio[1] = hw; 20 | mod->const_ratio[0] = lw; 21 | } 22 | 23 | bool set_modulus(const uint32_t q, Modulus *mod) 24 | { 25 | switch (q) 26 | { 27 | // -- Add cases for custom primes here 28 | 29 | // -- 27 bit primes 30 | case 134176769: set_modulus_custom(q, 0x20, 0x2802e03, mod); return 1; 31 | case 134111233: set_modulus_custom(q, 0x20, 0x6814e43, mod); return 1; 32 | case 134012929: set_modulus_custom(q, 0x20, 0xc84dfe5, mod); return 1; 33 | 34 | // -- 30-bit primes 35 | case 1062535169: set_modulus_custom(q, 0x4, 0xaccdb49, mod); return 1; 36 | case 1062469633: set_modulus_custom(q, 0x4, 0xadd3267, mod); return 1; 37 | case 1061093377: set_modulus_custom(q, 0x4, 0xc34cf30, mod); return 1; 38 | case 1060765697: set_modulus_custom(q, 0x4, 0xc86c0d4, mod); return 1; 39 | case 1060700161: set_modulus_custom(q, 0x4, 0xc9725e9, mod); return 1; 40 | case 1060175873: set_modulus_custom(q, 0x4, 0xd1a6142, mod); return 1; 41 | case 1058209793: set_modulus_custom(q, 0x4, 0xf07a84a, mod); return 1; 42 | case 1056440321: set_modulus_custom(q, 0x4, 0x10c52d4a, mod); return 1; 43 | case 1056178177: set_modulus_custom(q, 0x4, 0x11074e88, mod); return 1; 44 | case 1055260673: set_modulus_custom(q, 0x4, 0x11ef051e, mod); return 1; 45 | case 1054212097: set_modulus_custom(q, 0x4, 0x12f85437, mod); return 1; 46 | case 1054015489: set_modulus_custom(q, 0x4, 0x132a2218, mod); return 1; 47 | case 1053818881: set_modulus_custom(q, 0x4, 0x135bf4ba, mod); return 1; 48 | 49 | default: 50 | printf("Modulus const ratio values not found for "); 51 | print_zz("Modulus value", q); 52 | printf("Please try set_modulus_custom instead."); 53 | return 0; 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /device/lib/modulus.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file modulus.h 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include // uint64_t 12 | 13 | #include "defines.h" 14 | 15 | /** 16 | Struct to store a modulus. 'const_ratio' can be precomputed and used later for faster modular 17 | reduction in some cases. 18 | 19 | @param value Value of the modulus (aka 'q') 20 | @param const_ratio floor(2^64/q) 21 | */ 22 | typedef struct Modulus 23 | { 24 | ZZ value; // Value of the modulus (aka 'q') 25 | 26 | // -- Note: SEAL const_ratio is size 3 to store the remainder, 27 | // but we don't need the remainder so we can use a size 2 array 28 | 29 | ZZ const_ratio[2]; // floor(2^64/q) 30 | } Modulus; 31 | 32 | /** 33 | Sets up the modulus object for a particular modulus value. Useful for setting up a modulus if 34 | const_ratio for modulus value has not been pre-computed by set_modulus' table. 35 | 36 | @param[in] q Modulus value 37 | @param[in] hw High word of const_ratio for 'q' 38 | @param[in] lw Low word of const_ratio for 'q' 39 | @param[out] mod Modulus object to set 40 | */ 41 | void set_modulus_custom(const ZZ q, ZZ hw, ZZ lw, Modulus *mod); 42 | 43 | /** 44 | Sets up the modulus object for a particular modulus value. Implements const_ratio set as a table 45 | lookup. If table does not contain const_ratio for the requested modulus value, returns a failure. In 46 | this case, set_modulus_custom should be used instead. 47 | 48 | @param[in] q Modulus value 49 | @param[out] mod Modulus object to set 50 | @returns 1 on success, 0 on failure 51 | */ 52 | bool set_modulus(const ZZ q, Modulus *mod); 53 | -------------------------------------------------------------------------------- /device/lib/network.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file network.c 6 | */ 7 | 8 | #include "defines.h" 9 | 10 | #ifdef SE_ON_SPHERE_A7 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include // strerror 17 | 18 | #include "network.h" 19 | #include "util_print.h" 20 | 21 | bool is_network_connected(void) 22 | { 23 | Networking_InterfaceConnectionStatus status; 24 | static const char networkInterface[] = "wlan0"; 25 | 26 | int err = Networking_GetInterfaceConnectionStatus(networkInterface, &status); 27 | if (err) 28 | { 29 | if (errno != EAGAIN) 30 | { 31 | printf("ERROR: Networking_GetInterfaceConnectionStatus: %d (%s)\n", errno, 32 | strerror(errno)); 33 | return false; 34 | } 35 | printf("Error: Networking stack is not ready.\n"); 36 | return false; 37 | } 38 | 39 | // -- Use a mask to get bits of the status related to internet connection 40 | uint32_t connected = status & Networking_InterfaceConnectionStatus_ConnectedToInternet; 41 | if (!connected) 42 | { 43 | printf("Error: No internet connectivity.\n"); 44 | return false; 45 | } 46 | 47 | return true; 48 | } 49 | 50 | bool is_curl_error(void *ret, const char *name) 51 | { 52 | if (!ret || (*(CURLcode *)(ret) != CURLE_OK)) 53 | { 54 | // -- Error occured. Print debugging info 55 | if (name) printf("Failed: %s. ", name); 56 | if (ret) 57 | { 58 | CURLcode c = *((CURLcode *)ret); 59 | printf("Error: %s\n", curl_easy_strerror(c)); 60 | } 61 | return true; 62 | } 63 | return false; 64 | } 65 | 66 | void send_over_network(ZZ *data, size_t num_data_bytes) 67 | { 68 | CURL *curl = NULL; 69 | CURLcode ret = CURLE_OK; 70 | 71 | // -- First, check that we are connected to the internet 72 | if (!is_network_connected()) return; 73 | 74 | ret = curl_global_init(CURL_GLOBAL_ALL); 75 | if (is_curl_error(&ret, "init")) return; 76 | 77 | curl = curl_easy_init(); 78 | if (is_curl_error(curl, "init")) { goto cleanup; } 79 | 80 | // -- Specify URL to download. Important: any change 81 | // in the domain name must be reflected in the 82 | // AllowedConnections capability in app_manifest.json. 83 | ret = curl_easy_setopt(curl, CURLOPT_URL, url); 84 | if (is_curl_error(&ret, "url")) { goto cleanup; } 85 | 86 | ret = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 87 | if (is_curl_error(&ret, "verbose")) { goto cleanup; } 88 | 89 | // -- Let cURL follow any HTTP 3xx redirects. Important: 90 | // any redirection to different domain names requires 91 | // that domain name to be added to app_manifest.json. 92 | ret = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); 93 | if (is_curl_error(&ret, "follow")) { goto cleanup; } 94 | 95 | ret = curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); 96 | if (is_curl_error(&ret, "user agent")) { goto cleanup; } 97 | 98 | struct curl_slist *headers = NULL; 99 | headers = curl_slist_append(headers, "Content-Type: vector"); 100 | 101 | printf("Sending the following data over the network: \n"); 102 | print_poly("data", data, num_data_bytes / sizeof(ZZ)); 103 | 104 | ret = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); 105 | if (is_curl_error(&ret, "postfields")) { goto cleanup2; } 106 | 107 | ret = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, num_data_bytes); 108 | if (is_curl_error(&ret, "postfieldsize")) { goto cleanup2; } 109 | 110 | ret = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 111 | if (is_curl_error(&ret, "headers")) { goto cleanup2; } 112 | 113 | ret = curl_easy_perform(curl); 114 | if (is_curl_error(&ret, "post")) { goto cleanup2; } 115 | 116 | cleanup2: 117 | curl_slist_free_all(curl); 118 | 119 | cleanup: 120 | if (curl) curl_easy_cleanup(curl); 121 | curl_global_cleanup(); 122 | } 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /device/lib/network.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file network.h 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "defines.h" 11 | 12 | #ifdef SE_ON_SPHERE_A7 13 | #include 14 | 15 | // static const char *url = "http://neverssl.com"; 16 | static const char *url = "http://httpstat.us"; 17 | 18 | /** 19 | Checks that the interface is connected to the internet. 20 | 21 | @returns True if connected, false otherwise 22 | */ 23 | bool is_network_connected(void); 24 | 25 | /** 26 | Checks if there was an error with curl. Prints a message upon error detection (does not exit upon 27 | error detection). 28 | 29 | @param[in] ret Curl-function returned value to check 30 | @param[in] name A name or message to print upon error detection 31 | @returns True if there was an error detected, false otherwise 32 | */ 33 | bool is_curl_error(void *ret, const char *name); 34 | 35 | /** 36 | Sends 'num_data_bytes' of bytes from location pointed to by 'data' over the network connection using 37 | cURL. Prints a message upon error detection (does not exit upon error detection). 38 | 39 | @param[in] data Pointer to location of data to send over the network 40 | @param[in] num_data_bytes Number of bytes of 'data' to send 41 | */ 42 | void send_over_network(ZZ *data, size_t num_data_bytes); 43 | #endif 44 | -------------------------------------------------------------------------------- /device/lib/ntt.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file ntt.h 6 | 7 | Number Theoretic Transform. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include "defines.h" 13 | #include "fileops.h" 14 | #include "parameters.h" 15 | #include "polymodarith.h" 16 | #include "uintmodarith.h" 17 | 18 | /* 19 | For all "Harvey" butterfly NTTs: 20 | The input is a polynomial of degree n in R_q, where n is assumed to be a power of 2 and q is a prime 21 | such that q = 1 (mod 2n). The output is a vector A such that the following hold: 22 | A[j] = a(psi**(2*bit_reverse(j) + 1)), 0 <= j < n. For more details, see the SEAL-Embedded paper and 23 | Michael Naehrig and Patrick Longa's paper. 24 | */ 25 | 26 | /** 27 | Initializes NTT roots. 28 | 29 | If SE_NTT_FAST is defined, will load "fast"(a.k.a. "lazy") roots from file. 30 | Else, if SE_NTT_REG is defined, will load regular roots from file. 31 | Else, if SE_NTT_ONE_SHOT is defined, will calculate NTT roots one by one. 32 | Else, (SE_NTT_OTF), will do nothing ('ntt_roots' can be null and will be ignored). 33 | 34 | Space req: 'ntt_roots' should have space for 2n ZZ elements if SE_NTT_FAST is defined or n ZZ 35 | elements if SE_NTT_ONE_SHOT or SE_NTT_REG is defined. 36 | 37 | @param[in] parms Parameters set by ckks_setup 38 | @param[out] ntt_roots NTT roots. Will be null if SE_NTT_OTF is defined. 39 | */ 40 | void ntt_roots_initialize(const Parms *parms, ZZ *ntt_roots); 41 | 42 | /** 43 | Negacyclic in-place NTT using the Harvey butterfly. 44 | 45 | If SE_NTT_FAST is defined, will use "fast"(a.k.a. "lazy") NTT computation. 46 | Else, if SE_NTT_REG or SE_NTT_ONE_SHOT is defined, will use regular NTT computation. 47 | Else, (SE_NTT_OTF is defined), will use truly "on-the-fly" NTT computation. In this last 48 | case, 'ntt_roots' may be null (and will be ignored). 49 | 50 | @param[in] parms Parameters set by ckks_setup 51 | @param[in] ntt_roots NTT roots set by ntt_roots_initialize. Ignored if SE_NTT_OTF is defined. 52 | @param[in,out] vec Input/output polynomial of n ZZ elements 53 | */ 54 | void ntt_inpl(const Parms *parms, const ZZ *ntt_roots, ZZ *vec); 55 | 56 | /** 57 | Polynomial multiplication for inputs already in NTT form. 'res' and 'a' may share the same starting 58 | address (see: poly_mult_mod_ntt_form_inpl) 59 | 60 | @param[in] a Input polynomial 1, in NTT form, with n ZZ coefficients 61 | @param[in] b Input polynomial 2, in NTT form, with n ZZ coefficients 62 | @param[in] n Number of coefficients in a, b, and c 63 | @param[in] mod Modulus 64 | @param[out] res Result polynomial, in NTT form, with n ZZ coefficients 65 | */ 66 | static inline void poly_mult_mod_ntt_form(const ZZ *a, const ZZ *b, size_t n, const Modulus *mod, 67 | ZZ *res) 68 | { 69 | // -- Inputs in NTT form can be multiplied component-wise 70 | poly_pointwise_mul_mod(a, b, n, mod, res); 71 | } 72 | 73 | /** 74 | In-place polynomial multiplication for inputs already in NTT form. 75 | 76 | @param[in,out] a In: Input polynomial 1; Out: Result polynomial 77 | @param[in] b Input polynomial 2, in NTT form, with n ZZ coefficients. 78 | @param[in] n Number of coefficients in a and b 79 | @param[in] mod Modulus 80 | */ 81 | static inline void poly_mult_mod_ntt_form_inpl(ZZ *a, const ZZ *b, size_t n, const Modulus *mod) 82 | { 83 | // -- Values in NTT form can be multiplied component-wise 84 | poly_pointwise_mul_mod_inpl(a, b, n, mod); 85 | } 86 | -------------------------------------------------------------------------------- /device/lib/parameters.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file parameters.h 6 | 7 | Functions for creating and modifying a Parameters instance 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include // uint64_t 15 | #include // size_t 16 | 17 | #include "defines.h" 18 | #include "modulo.h" // Modulus 19 | 20 | /** 21 | Storage for encryption parameters. 22 | 23 | @param coeff_count Number of coefficients in polyomial = n = poly_modulus_degree 24 | @param logn log2(n) (number of bits to represent n) 25 | @param moduli Array of moduli that represents the modulus switching chain 26 | @param curr_modulus Pointer to current modulus in switching chain 27 | @param curr_modulus_idx Index of current modulus in 'moduli' vector 28 | @param nprimes Number of 'Modulus' objects in 'moduli' array 29 | @param scale CKKS scale value 30 | @param is_asymmetric Set to 1 if using public key encryption 31 | @param pk_from_file Set to 1 to use a public key from a file 32 | @param sample_s Set to 1 to sample the secret key 33 | @param small_s Set to 1 to store the secret key in small form while processing 34 | Note: SEAL-Embedded currently only works if this is 1 35 | @param small_u Set to 1 to store the 'u' vector in small form while processing 36 | Note: SEAL-Embedded currently only works if this is 1 37 | @param curr_param_direction Set to 1 to operate over primes in reverse order. Only 38 | available if SE_REVERSE_CT_GEN_ENABLED is enabled. 39 | @param skip_ntt_load Set to 1 to skip a load of the NTT roots (if applicable, 40 | based on NTT option chosen.) Only available if 41 | SE_REVERSE_CT_GEN_ENABLED is enabled. 42 | */ 43 | typedef struct 44 | { 45 | size_t coeff_count; // Number of coefficients in polyomial = n = poly_modulus_degree 46 | size_t logn; // log2(n) (number of bits to represent n) 47 | #ifdef SE_USE_MALLOC 48 | Modulus *moduli; // Array of moduli that represents the modulus switching chain 49 | #else 50 | Modulus moduli[SE_NPRIMES]; // Array of moduli that represents the modulus switching 51 | // chain 52 | #endif 53 | Modulus *curr_modulus; // Pointer to current modulus in switching chain 54 | size_t curr_modulus_idx; // Index of current modulus in 'moduli' vector 55 | 56 | size_t nprimes; // Number of 'Modulus' objects in 'moduli' array 57 | double scale; // CKKS scale value 58 | bool is_asymmetric; // Set to 1 if using public key encryption 59 | bool pk_from_file; // Set to 1 to use a public key from a file 60 | bool sample_s; // Set to 1 to sample the secret key 61 | bool small_s; // Set to 1 to store the secret key in small form while processing 62 | bool small_u; // Set to 1 to store the 'u' vector in small form while processing 63 | #ifdef SE_REVERSE_CT_GEN_ENABLED 64 | bool curr_param_direction; // Set to 1 to operate over primes in reverse order 65 | bool skip_ntt_load; // Set to 1 to skip a load of the NTT roots 66 | #endif 67 | } Parms; 68 | 69 | /** 70 | Utility function to get the log2 of a value. 71 | 72 | @param[in] val Value 73 | @returns log2(val) 74 | */ 75 | static inline size_t get_log2(size_t val) 76 | { 77 | switch (val) 78 | { 79 | case 2048: return 11; 80 | case 4096: return 12; 81 | case 8192: return 13; 82 | case 16384: return 14; 83 | default: return (size_t)log2(val); 84 | } 85 | } 86 | 87 | /** 88 | Releases the memory allocated for modulus chain is SE_USE_MALLOC is defined. Does nothing otherwise. 89 | 90 | @param[in,out] parms Parameters instance 91 | */ 92 | void delete_parameters(Parms *parms); 93 | 94 | /** 95 | Resets parameters (sets curr_modulus_idx back to the start of modulus chain) 96 | 97 | @param[in,out] parms Parameters instance 98 | */ 99 | void reset_primes(Parms *parms); 100 | 101 | /** 102 | Updates parms to next modulus in modulus chain. 103 | 104 | @param[in,out] parms Parameters instance 105 | @returns 1 on success, 0 on fail (reached end of chain) 106 | */ 107 | bool next_modulus(Parms *parms); 108 | 109 | /** 110 | Sets up SEAL-Embedded parameters object with default moduli for requested degree for CKKS. 111 | Also sets the scale. 112 | 113 | Req: degree must be a power of 2 (between 1024 and 16384, inclusive) 114 | Note: Moduli should be the same as the default moduli chosen by the SEAL-Embedded adapter 115 | (not including the special prime). 116 | 117 | @param[in] degree Polynomial ring degree 118 | @param[in] nprimes Number of prime moduli 119 | @param[out] parms Parameters instance 120 | */ 121 | void set_parms_ckks(size_t degree, size_t nprimes, Parms *parms); 122 | 123 | /** 124 | Sets up SEAL-Embedded parameters object according to requested custom parameters for CKKS. If either 125 | 'modulus_vals' or 'ratios' is NULL, uses default values. 126 | 127 | @param[in] degree Polynomial ring degree 128 | @param[in] scale Scale to use for encoding/decoding 129 | @param[in] nprimes Number of prime moduli 130 | @param[in] modulus_vals An array of nprimes type-ZZ modulus values. 131 | @param[in] ratios An array of const_ratio values for each custom modulus value 132 | (high word, followed by low word). 133 | @param[out] parms Parameters instance 134 | */ 135 | void set_custom_parms_ckks(size_t degree, double scale, size_t nprimes, const ZZ *modulus_vals, const ZZ *ratios, 136 | Parms *parms); 137 | -------------------------------------------------------------------------------- /device/lib/polymodarith.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file polymodarith.h 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "defines.h" 11 | #include "uintmodarith.h" 12 | 13 | /** 14 | Modular polynomial addition. 'p1' and 'res' may share the same starting address for in-place 15 | computation. 16 | 17 | Space req: 'res' must have space for n ZZ values. 18 | 19 | @param[in] p1 Input polynomial 1 20 | @param[in] p2 Input polynomial 2 21 | @param[in] n Number of elements (ZZ coefficients) in p1 and p2 22 | @param[in] mod Modulus 23 | @param[out] res Result polynomial 24 | */ 25 | static inline void poly_add_mod(const ZZ *p1, const ZZ *p2, PolySizeType n, const Modulus *mod, 26 | ZZ *res) 27 | { 28 | for (PolySizeType i = 0; i < n; i++) { res[i] = add_mod(p1[i], p2[i], mod); } 29 | } 30 | 31 | /** 32 | In-place modular polynomial addition. 33 | 34 | @param[in] p1 In: Input polynomial 1; Out: Result polynomial 35 | @param[in] p2 Input polynomial 2 36 | @param[in] n Number of elements (ZZ coefficients) in p1 and p2 37 | @param[in] mod Modulus 38 | */ 39 | static inline void poly_add_mod_inpl(ZZ *p1, const ZZ *p2, PolySizeType n, const Modulus *mod) 40 | { 41 | for (PolySizeType i = 0; i < n; i++) { add_mod_inpl(&(p1[i]), p2[i], mod); } 42 | } 43 | 44 | /** 45 | Modular polynomial negation. 'p1' and 'res' may share the same starting address for in-place 46 | computation. 47 | 48 | Space req: 'res' must have space for n ZZ values. 49 | 50 | @param[in] p1 Input polynomial 51 | @param[in] n Number of elements (ZZ coefficients) in p1 52 | @param[in] mod Modulus 53 | @param[out] res Result polynomial 54 | */ 55 | static inline void poly_neg_mod(const ZZ *p1, PolySizeType n, const Modulus *mod, ZZ *res) 56 | { 57 | for (PolySizeType i = 0; i < n; i++) { res[i] = neg_mod(p1[i], mod); } 58 | } 59 | 60 | /** 61 | In-place modular polynomial negation. 62 | 63 | @param[in] p1 In: Input polynomial; Out: Result polynomial 64 | @param[in] n Number of elements (ZZ coefficients) in p1 65 | @param[in] mod Modulus 66 | */ 67 | static inline void poly_neg_mod_inpl(ZZ *p1, PolySizeType n, const Modulus *mod) 68 | { 69 | for (PolySizeType i = 0; i < n; i++) { neg_mod_inpl(&(p1[i]), mod); } 70 | } 71 | 72 | /** 73 | Pointwise modular polynomial negation. 'p1' and 'res' may share the same starting address for 74 | in-place computation (see: poly_pointwise_mul_mod_inpl). 75 | 76 | Space req: 'res' must have space for n ZZ values. 77 | 78 | @param[in] p1 Input polynomial 79 | @param[in] n Number of elements (ZZ coefficients) in p1 80 | @param[in] mod Modulus 81 | @param[out] res Result polynomial. 82 | */ 83 | static inline void poly_pointwise_mul_mod(const ZZ *p1, const ZZ *p2, PolySizeType n, 84 | const Modulus *mod, ZZ *res) 85 | { 86 | for (PolySizeType i = 0; i < n; i++) { res[i] = mul_mod(p1[i], p2[i], mod); } 87 | } 88 | 89 | /** 90 | In-place pointwise modular polynomial negation. 91 | 92 | @param[in] p1 In: Input polynomial 1; Out: Result polynomial 93 | @param[in] p2 Input polynomial 2 94 | @param[in] n Number of elements (ZZ coefficients) in p1 95 | @param[in] mod Modulus 96 | */ 97 | static inline void poly_pointwise_mul_mod_inpl(ZZ *p1, const ZZ *p2, PolySizeType n, 98 | const Modulus *mod) 99 | { 100 | poly_pointwise_mul_mod(p1, p2, n, mod, p1); 101 | } 102 | -------------------------------------------------------------------------------- /device/lib/polymodmult.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file polymodmult.c 6 | 7 | Polynomial modular multiplication. 8 | */ 9 | 10 | #include "polymodmult.h" 11 | 12 | #include 13 | 14 | #include "defines.h" 15 | #include "parameters.h" 16 | #include "sample.h" 17 | #include "string.h" // memset 18 | #include "uintmodarith.h" 19 | #include "util_print.h" 20 | 21 | /** 22 | Helper funciton to multiply two ring polynomials using schoolbook multiplication, without the final 23 | polynomial reduction. The result polynomial will be returned in the first n ZZ elements pointed to 24 | by 'res'. 25 | 26 | Note: This function is *not* constant-time, and is mainly useful for testing. 27 | 28 | Space req: 'res' must contain space for 2n ZZ elements, where each input polynomial consists of n ZZ 29 | elements (each). 30 | 31 | @param[in] a Input polynomial 1 32 | @param[in] b Input polynomial 2 33 | @param[in] n Number of coefficients to multiply 34 | @param[in] mod Modulus 35 | @param[out] res Sized-(2*sizeof(ZZ)) result of [a . b]_mod 36 | */ 37 | void poly_mult_mod_sb_not_reduced(const ZZ *a, const ZZ *b, PolySizeType n, const Modulus *mod, 38 | ZZ *res) 39 | { 40 | memset(res, 0, 2 * n * sizeof(ZZ)); // This is necessary 41 | 42 | for (PolySizeType i = 0; i < n; i++) 43 | { 44 | for (PolySizeType j = 0; j < n; j++) 45 | { 46 | // -- Does the following: res[i + j] += a[i] * b[j] (mod p) 47 | mul_add_mod_inpl(&(res[i + j]), a[i], b[j], mod); 48 | } 49 | } 50 | } 51 | 52 | /** 53 | Helper function to perform the final polynomial reduction. 54 | Initial address of 'a' and initial address of 'res' may be the same (see: poly_reduce_inpl). 55 | 56 | Space req: 'res' must contain space for n ZZ elements (for 'a' with 2n coefficients) 57 | 58 | @param[in] a Input polynomial 59 | @param[in] n Degree to reduce by 60 | @param[in] mod Modulus 61 | @param[out] res Result polynomial 62 | */ 63 | void poly_reduce(const ZZ *a, PolySizeType n, const Modulus *mod, ZZ *res) 64 | { 65 | for (PolySizeType i = 0; i < n; i++) 66 | { 67 | // -- Does the following: 68 | // res[i] = (a[i] - a[i + n]) % (ZZ)(mod->value); 69 | res[i] = sub_mod((a[i]), a[i + n], mod); 70 | } 71 | } 72 | 73 | /** 74 | Helper function to perform the final polynomial reduction in place. 75 | 76 | @param[in] a In: Input polynomial (of 2n ZZ values); 77 | Out: Result polynomial (in first n ZZ values). 78 | @param[in] n Degree to reduce by 79 | @param[in] mod Modulus 80 | */ 81 | void poly_reduce_inpl(ZZ *a, PolySizeType n, const Modulus *mod) 82 | { 83 | for (PolySizeType i = 0; i < n; i++) 84 | { 85 | // -- Does the following: a[i] = (a[i] - a[i + n]) % (ZZ)(mod->value); 86 | sub_mod_inpl(&(a[i]), a[i + n], mod); 87 | } 88 | } 89 | 90 | void poly_mult_mod_sb(const ZZ *a, const ZZ *b, PolySizeType n, const Modulus *mod, ZZ *res) 91 | { 92 | // -- Multiplication (not reduced) 93 | poly_mult_mod_sb_not_reduced(a, b, n, mod, res); 94 | // print_poly("not-reduced (expected)", res, 2*n); 95 | // print_poly_ring("not-reduced", res, 2*n); 96 | // print_poly_"not-reduced (expected)", res, 2*n); 97 | 98 | // -- Ring reduction 99 | poly_reduce_inpl(res, n, mod); 100 | // print_poly("reduced (expected) ", res, n); 101 | } 102 | -------------------------------------------------------------------------------- /device/lib/polymodmult.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file polymodmult.h 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #include "defines.h" 13 | #include "inttypes.h" 14 | #include "modulo.h" 15 | 16 | /** 17 | TODO: Move to testing code? 18 | Multiplies two ring polynomials using schoolbook multiplication. The result polynomial will be 19 | returned in the first n ZZ elements pointed to by 'res'. 20 | 21 | Note: This function is *not* constant-time, and is mainly useful for testing. 22 | 23 | Space req: 'res' must constain space for 2n ZZ elements, where each input polynomial consists of n 24 | ZZ elements (each). 25 | 26 | @param[in] a Input polynomial 1 27 | @param[in] b Input polynomial 2 28 | @param[in] n Number of coefficients to multiply 29 | @param[in] mod Modulus 30 | @param[out] res Result of [a . b]_mod (in the first n ZZ elements) 31 | */ 32 | void poly_mult_mod_sb(const ZZ *a, const ZZ *b, PolySizeType n, const Modulus *mod, ZZ *res); 33 | -------------------------------------------------------------------------------- /device/lib/rng.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file rng.c 6 | 7 | Pseudo-random number generator. 8 | */ 9 | 10 | #include "rng.h" 11 | 12 | #include "defines.h" 13 | 14 | // -- Need these to avoid duplicate symbols error 15 | 16 | extern inline void prng_randomize_reset(SE_PRNG *prng, uint8_t *seed_in); 17 | extern inline void prng_fill_buffer(size_t byte_count, SE_PRNG *prng, void *buffer); 18 | extern inline void prng_clear(SE_PRNG *prng); 19 | -------------------------------------------------------------------------------- /device/lib/rng.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file rng.h 6 | 7 | Pseudo-random number generator. 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include // memset 15 | 16 | #include "defines.h" 17 | #include "inttypes.h" 18 | #include "shake256/fips202.h" 19 | 20 | #ifdef SE_RAND_GETRANDOM 21 | #include // getrandom 22 | #elif defined(SE_RAND_NRF5) 23 | #include "nrf_crypto.h" 24 | #endif 25 | 26 | typedef struct SE_PRNG 27 | { 28 | uint8_t seed[SE_PRNG_SEED_BYTE_COUNT]; 29 | uint64_t counter; 30 | } SE_PRNG; 31 | 32 | /** 33 | Randomizes the seed of a PRNG object and resets its internal counter. 34 | 35 | Size req: If seed_in != NULL, seed_in must be SE_PRNG_SEED_BYTE_COUNT long. 36 | 37 | @param[in,out] prng PRNG instance to modify 38 | @param[in] seed_in [Optional]. Seed to seed the prng with. 39 | */ 40 | inline void prng_randomize_reset(SE_PRNG *prng, uint8_t *seed_in) 41 | { 42 | se_assert(prng); 43 | prng->counter = 0; 44 | 45 | if (seed_in) 46 | { 47 | memcpy(&(prng->seed[0]), seed_in, SE_PRNG_SEED_BYTE_COUNT); 48 | return; 49 | } 50 | 51 | #ifdef SE_RAND_GETRANDOM 52 | ssize_t ret = getrandom((void *)(&(prng->seed[0])), SE_PRNG_SEED_BYTE_COUNT, 0); 53 | se_assert(ret == SE_PRNG_SEED_BYTE_COUNT); 54 | #elif defined(SE_RAND_NRF5) 55 | ret_code_t ret_val = nrf_crypto_rng_vector_generate(prng->seed, SE_PRNG_SEED_BYTE_COUNT); 56 | if (ret_val != NRF_SUCCESS) 57 | { 58 | printf("Error: Something went wrong with nrf_crypto_rng_vector_generate()\n"); 59 | while (1) 60 | ; 61 | } 62 | se_assert(ret_val == NRF_SUCCESS); 63 | #else 64 | // -- This should only be used for debugging!! 65 | memset(&(prng->seed[0]), 0, SE_PRNG_SEED_BYTE_COUNT); 66 | // prng->seed[0] = 1; 67 | #endif 68 | } 69 | 70 | /** 71 | Fills a buffer with random bytes expanded from a SE_PRNG's seed (and counter). 72 | A call to this function updates the prng object's internal counter. 73 | 74 | @param[in] byte_count Number of random bytes to generate 75 | @param[in,out] prng PRNG instance 76 | @param[out] buffer Buffer to store the random bytes 77 | */ 78 | inline void prng_fill_buffer(size_t byte_count, SE_PRNG *prng, void *buffer) 79 | { 80 | uint8_t seed_ext[SE_PRNG_SEED_BYTE_COUNT + 8]; 81 | memcpy(&(seed_ext[0]), &(prng->seed[0]), SE_PRNG_SEED_BYTE_COUNT); 82 | memcpy(&(seed_ext[SE_PRNG_SEED_BYTE_COUNT]), &(prng->counter), 8); 83 | shake256(buffer, byte_count, &(seed_ext[0]), SE_PRNG_SEED_BYTE_COUNT + 8); 84 | prng->counter++; 85 | if (prng->counter == 0) // overflow! 86 | { 87 | printf("PRNG counter overflowed."); 88 | printf("Re-randomizing seed and resetting counter to 0.\n"); 89 | prng_randomize_reset(prng, NULL); 90 | } 91 | } 92 | 93 | /** 94 | Clears the values (both seed and counter) of a prng instance to 0. 95 | Clears the bit that ties prng to a custom seed (so next prng_randomize_reset *will* generate a 96 | random seed) 97 | 98 | @param[in,out] prng PRNG instance to clear 99 | */ 100 | inline void prng_clear(SE_PRNG *prng) 101 | { 102 | memset(&(prng->seed[0]), 0, SE_PRNG_SEED_BYTE_COUNT); 103 | prng->counter = 0; 104 | } 105 | -------------------------------------------------------------------------------- /device/lib/seal_embedded.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file seal_embedded.h 6 | 7 | SEAL-Embedded offers an easy to use API for easy development. A user should call the se_setup 8 | function once at the start of library initialization and se_encrypt once for every array of values 9 | to encode/encrypt. 'se_cleanup' exists for completeness to free library memory, but should never 10 | need to be called. SEAL-Embedded offers three types of setup functions for developers, providing 11 | different degrees of library configurability. se_setup_custom allows for the most customization, 12 | while se_setup_default uses default parameter settings. Note: Currently, SEAL-Embedded does not 13 | support reconfiguring parameters to a different parameter set after initial setup. 14 | */ 15 | 16 | #pragma once 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "ckks_common.h" 24 | #include "defines.h" 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /** 31 | Error code values range from 0 to -9999. 32 | Application-specific errors should use values outside this range. 33 | TODO: Use error codes 34 | */ 35 | #define SE_SUCCESS 0 36 | #define SE_ERR_NO_MEMORY -12 37 | #define SE_ERR_INVALD_ARGUMENT -22 38 | #define SE_ERR_UNKNOWN -1000 39 | /** Minimum negative error code value used by SEAL-Embedded */ 40 | #define SE_ERR_MINIMUM -9999 41 | 42 | #ifndef SE_USE_MALLOC 43 | static ZZ **mempool_ptr_global; 44 | #endif 45 | 46 | /** 47 | SEAL-Embedded parameters struct for API. 48 | 49 | @param parms Pointer to internal parameters struct 50 | @param se_ptrs Pointer to SE_PTRS struct 51 | */ 52 | typedef struct 53 | { 54 | Parms *parms; 55 | SE_PTRS *se_ptrs; 56 | } SE_PARMS; 57 | 58 | typedef enum { SE_SYM_ENCR, SE_ASYM_ENCR } EncryptType; 59 | 60 | /** 61 | Network send function pointer. 62 | The first input parameter should represent a pointer to the data to send. 63 | The second input parameter should represent the size of the data to send. 64 | */ 65 | typedef size_t (*SEND_FNCT_PTR)(void *, size_t); 66 | 67 | /** 68 | Randomness generator function pointer. 69 | The first input parameter should represent a pointer to the buffer to store the random values. 70 | The second input parameter should represent the size of randomness to generate. 71 | The third input parameters can specify any required flags. 72 | */ 73 | typedef ssize_t (*RND_FNCT_PTR)(void *, size_t, unsigned int flags); 74 | 75 | /** 76 | Setups up SEAL-Embedded for a particular encryption type for a custom parameter set, including a 77 | custom degree, number of modulus primes, modulus prime values, and scale. If either modulus_vals or 78 | ratios is NULL, reverts to se_setup functionality. 79 | 80 | Note: This function calls calloc. 81 | 82 | @param[in] degree Polynomial ring degree 83 | @param[in] nprimes Number of prime moduli 84 | @param[in] modulus_vals An array of nprimes type-ZZ modulus values. 85 | @param[in] ratios An array of const_ratio values for each custom modulus value 86 | (high word, followed by low word). 87 | @param[in] scale Scale 88 | @param[in] enc_type Encryption type 89 | @returns A handle to the set SE_PARMS instance 90 | */ 91 | SE_PARMS *se_setup_custom(size_t degree, size_t nprimes, const ZZ *modulus_vals, const ZZ *ratios, 92 | double scale, EncryptType encrypt_type); 93 | 94 | /** 95 | Setups up SEAL-Embedded for a particular encryption type for the requested parameter set. 96 | 97 | Note: This function calls calloc. 98 | 99 | @param[in] degree Polynomial ring degree 100 | @param[in] nprimes Number of prime moduli 101 | @param[in] scale Scale 102 | @param[in] enc_type Encryption type 103 | @returns A handle to an SE_PARMS instance 104 | */ 105 | SE_PARMS *se_setup(size_t degree, size_t nprimes, double scale, EncryptType encrypt_type); 106 | 107 | /** 108 | Setups up SEAL-Embedded for a particular encryption type for a parameter set of degree = 4096, a 109 | coefficient modulus of 3 30-bit primes, and a scale of pow(2,25). 110 | 111 | Note: This function calls calloc. 112 | 113 | @param[in] enc_type Encryption type (SE_SYM_ENCR or SE_ASYM_ENCR) 114 | @returns A handle to the set SE_PARMS instance 115 | */ 116 | SE_PARMS *se_setup_default(EncryptType enc_type); 117 | 118 | bool se_encrypt_seeded(uint8_t *shareable_seed, uint8_t *seed, SEND_FNCT_PTR network_send_function, 119 | void *v, size_t vlen_bytes, bool print, SE_PARMS *se_parms); 120 | 121 | bool se_encrypt(SEND_FNCT_PTR network_send_function, void *v, size_t vlen_bytes, bool print, 122 | SE_PARMS *se_parms); 123 | 124 | /** 125 | Frees some library memory and resets parameters object. Should never need to be called by the 126 | typical user. 127 | 128 | @param[in] se_parms SE_PARMS instance to free 129 | */ 130 | void se_cleanup(SE_PARMS *se_parms); 131 | 132 | #ifdef __cplusplus 133 | } 134 | #endif 135 | -------------------------------------------------------------------------------- /device/lib/shake256/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | # Licensed under the MIT license. 3 | 4 | set(SE_LIB_SOURCE_FILES ${SE_LIB_SOURCE_FILES} 5 | ${CMAKE_CURRENT_LIST_DIR}/fips202.c 6 | ) 7 | 8 | if (NOT SE_BUILD_LOCAL) 9 | set(SE_LIB_SOURCE_FILES ${SE_LIB_SOURCE_FILES} 10 | ${CMAKE_CURRENT_LIST_DIR}/keccakf1600.asm 11 | ) 12 | else() 13 | set(SE_LIB_SOURCE_FILES ${SE_LIB_SOURCE_FILES} 14 | ${CMAKE_CURRENT_LIST_DIR}/keccakf1600.c 15 | ) 16 | endif() 17 | 18 | set(SE_LIB_SOURCE_FILES ${SE_LIB_SOURCE_FILES} PARENT_SCOPE) 19 | -------------------------------------------------------------------------------- /device/lib/shake256/cgmanifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "Registrations": [ 3 | { 4 | "component": { 5 | "type": "git", 6 | "git": { 7 | "repositoryUrl": "https://github.com/microsoft/SEAL", 8 | "commitHash": "2d2a25c916047d2f356d45ad50c98f0a9695905a" 9 | } 10 | } 11 | }, 12 | { 13 | "component": { 14 | "type": "git", 15 | "git": { 16 | "repositoryUrl": "https://github.com/mupq/pqm4", 17 | "commitHash": "65f12c6c66f10492eac2b434e93fd1aee742f0e1" 18 | } 19 | } 20 | } 21 | { 22 | "component": { 23 | "type": "other", 24 | "Other": { 25 | "Name": "nRF5 SDK", 26 | "Version": "17.1.0", 27 | "DownloadUrl": "https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v12.x.x/doc/12.3.0/nRF5_Nordic_license.txt" 28 | } 29 | } 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /device/lib/shake256/fips202.c: -------------------------------------------------------------------------------- 1 | /* 2 | Origin: Microsoft SEAL library (https://github.com/microsoft/SEAL) commit 3 | 2d2a25c916047d2f356d45ad50c98f0a9695905a. 4 | */ 5 | 6 | /* 7 | This file is a part of the Kyber library (https://github.com/pq-crystals/kyber) 8 | commit 844057468e69527bd15b17fbe03f4b61f9a22065. The Kyber library is licensed 9 | under CC0 Universal, version 1.0. You can find a copy of this license at 10 | https://creativecommons.org/publicdomain/zero/1.0/legalcode 11 | Minor modifications to the original file have been made and marked 12 | as `Microsoft SEAL edit: ...`. 13 | */ 14 | 15 | /* Based on the public domain implementation in 16 | * crypto_hash/keccakc512/simple/ from http://bench.cr.yp.to/supercop.html 17 | * by Ronny Van Keer 18 | * and the public domain "TweetFips202" implementation 19 | * from https://twitter.com/tweetfips202 20 | * by Gilles Van Assche, Daniel J. Bernstein, and Peter Schwabe */ 21 | 22 | #include 23 | #include 24 | /* Microsoft SEAL edit: changed the header file path */ 25 | #include "fips202.h" 26 | #include "keccakf1600.h" 27 | 28 | /* Microsoft SEAL edit: moved the rate macros here from Kyber header fips202.h 29 | */ 30 | #define SHAKE256_RATE 136 31 | 32 | // Context for non-incremental API 33 | typedef struct 34 | { 35 | uint64_t ctx[25]; 36 | } shake256ctx; 37 | 38 | /************************************************* 39 | * Name: keccak_absorb 40 | * 41 | * Description: Absorb step of Keccak; 42 | * non-incremental, starts by zeroeing the state. 43 | * 44 | * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state 45 | * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) 46 | * - const uint8_t *m: pointer to input to be absorbed into s 47 | * - size_t mlen: length of input in bytes 48 | * - uint8_t p: domain-separation byte for different 49 | *Keccak-derived functions 50 | **************************************************/ 51 | static void keccak_absorb(uint64_t *s, uint32_t r, const uint8_t *m, size_t mlen, uint8_t p) 52 | { 53 | size_t i; 54 | uint8_t t[200]; 55 | 56 | while (mlen >= r) 57 | { 58 | KeccakF1600_StateXORBytes(s, m, 0, r); 59 | KeccakF1600_StatePermute(s); 60 | mlen -= r; 61 | m += r; 62 | } 63 | 64 | for (i = 0; i < r; ++i) t[i] = 0; 65 | for (i = 0; i < mlen; ++i) t[i] = m[i]; 66 | t[i] = p; 67 | t[r - 1] |= 128; 68 | 69 | KeccakF1600_StateXORBytes(s, t, 0, r); 70 | } 71 | 72 | /************************************************* 73 | * Name: keccak_squeezeblocks 74 | * 75 | * Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each. 76 | * Modifies the state. Can be called multiple times to keep squeezing, i.e., is 77 | * incremental. 78 | * 79 | * Arguments: - uint8_t *h: pointer to output blocks 80 | * - size_t nblocks: number of blocks to be squeezed (written to h) 81 | * - uint64_t *s: pointer to in/output Keccak state 82 | * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) 83 | **************************************************/ 84 | static void keccak_squeezeblocks(uint8_t *h, size_t nblocks, uint64_t *s, uint32_t r) 85 | { 86 | while (nblocks > 0) 87 | { 88 | KeccakF1600_StatePermute(s); 89 | KeccakF1600_StateExtractBytes(s, h, 0, r); 90 | h += r; 91 | nblocks--; 92 | } 93 | } 94 | 95 | /************************************************* 96 | * Name: shake256 97 | * 98 | * Description: SHAKE256 XOF with non-incremental API 99 | * 100 | * Arguments: - uint8_t *out: pointer to output 101 | * - size_t outlen: requested output length in bytes 102 | * - const uint8_t *in: pointer to input 103 | * - size_t inlen: length of input in bytes 104 | **************************************************/ 105 | void shake256(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen) 106 | { 107 | shake256ctx state; 108 | uint8_t t[SHAKE256_RATE]; 109 | size_t nblocks = outlen / SHAKE256_RATE; 110 | size_t i; 111 | 112 | for (i = 0; i < 25; ++i) { state.ctx[i] = 0; } 113 | 114 | /* Absorb input */ 115 | keccak_absorb((uint64_t *)state.ctx, SHAKE256_RATE, input, inlen, 0x1F); 116 | 117 | /* Squeeze output */ 118 | keccak_squeezeblocks(output, nblocks, (uint64_t *)state.ctx, SHAKE256_RATE); 119 | 120 | output += nblocks * SHAKE256_RATE; 121 | outlen -= nblocks * SHAKE256_RATE; 122 | 123 | if (outlen) 124 | { 125 | keccak_squeezeblocks(t, 1, (uint64_t *)state.ctx, SHAKE256_RATE); 126 | for (i = 0; i < outlen; i++) output[i] = t[i]; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /device/lib/shake256/fips202.h: -------------------------------------------------------------------------------- 1 | /* 2 | Origin: Microsoft SEAL library (https://github.com/microsoft/SEAL) commit 3 | 2d2a25c916047d2f356d45ad50c98f0a9695905a. 4 | */ 5 | 6 | // Copyright (c) Microsoft Corporation. All rights reserved. 7 | // Licensed under the MIT license. 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen); 15 | -------------------------------------------------------------------------------- /device/lib/shake256/keccakf1600.h: -------------------------------------------------------------------------------- 1 | /* 2 | Origin: pqm4 library (https://github.com/mupq/pqm4) commit 3 | 65f12c6c66f10492eac2b434e93fd1aee742f0e1. 4 | */ 5 | 6 | #ifndef KECCAKF1600_H 7 | #define KECCAKF1600_H 8 | 9 | #include 10 | 11 | void KeccakF1600_StateExtractBytes(uint64_t *state, unsigned char *data, unsigned int offset, 12 | unsigned int length); 13 | void KeccakF1600_StateXORBytes(uint64_t *state, const unsigned char *data, unsigned int offset, 14 | unsigned int length); 15 | void KeccakF1600_StatePermute(uint64_t *state); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /device/lib/timer.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file timer.h 6 | 7 | Timer struct and timing functions. Mainly useful for testing. We leave it as part of the library in 8 | case we want to time internal functions. 9 | */ 10 | 11 | #pragma once 12 | 13 | #include "defines.h" 14 | 15 | #ifdef SE_ENABLE_TIMERS 16 | #include 17 | 18 | #ifdef SE_ON_SPHERE_M4 19 | #include "os_hal_gpt.h" 20 | // -- We set these to the clock we want to use 21 | // There are 5 GPT clocks: {0, 1, 3} --> interrupt based, {2, 4} --> free-run 22 | // GPT2 ~= 32KHz or 1Hz, GPT4 = ~= bus clock speed or (1/2)*bus clockspeed 23 | static const uint8_t global_gpt_timer_id = OS_HAL_GPT4; 24 | static const bool global_gpt_high_speed = 1; 25 | #elif defined(SE_ON_NRF5) 26 | #include "nrf.h" 27 | #include "nrf_drv_timer.h" // TODO: Check if this is needed 28 | #include "sdk_config.h" 29 | #elif !defined(SE_ON_SPHERE_A7) 30 | #include 31 | #endif 32 | 33 | /** 34 | Struct for storing time points. 35 | 36 | @param start Starting time 37 | @param stop End time 38 | @param elapsed_time Elapsed time (start-stop) in nanoseconds 39 | @param timer_instance Timer instance (Used only with SE_ON_NRF5). Equal to NRFX_TIMER_INSTANCE(0) 40 | @param timer_config Timer config (Used only with SE_ON_NRF5). Equal to NRFX_TIMER_DEFAULT_CONFIG 41 | */ 42 | typedef struct Timer 43 | { 44 | #if defined(SE_ON_SPHERE_M4) || defined(SE_ON_NRF5) 45 | uint32_t start; // Starting time 46 | uint32_t stop; // End time 47 | #elif defined(SE_ON_SPHERE_A7) 48 | uint64_t start; // Starting time 49 | uint64_t stop; // End time 50 | #else 51 | struct timespec start; // Starting time 52 | struct timespec stop; // End time 53 | #endif 54 | float elapsed_time; // Elapsed time (start-stop) in nanoseconds 55 | #ifdef SE_ON_NRF5 56 | nrfx_timer_t *timer_instance; // Timer instance (= NRFX_TIMER_INSTANCE(0)) 57 | nrfx_timer_config_t *timer_config; // Timer config (= NRFX_TIMER_DEFAULT_CONFIG) 58 | #endif 59 | } Timer; 60 | 61 | typedef enum TimeUnit { 62 | SEC = 1UL, 63 | MILLI_SEC = 1000UL, 64 | MICRO_SEC = 1000000UL, 65 | NANO_SEC = 1000000000UL 66 | } TimeUnit; 67 | 68 | void start_timer(Timer *timer); 69 | 70 | void stop_timer(Timer *timer); 71 | 72 | void reset_timer(Timer *timer); 73 | 74 | void reset_start_timer(Timer *timer); 75 | 76 | float read_timer(Timer timer, TimeUnit unit); 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /device/lib/uint_arith.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file uint_arith.c 6 | */ 7 | 8 | #include "uint_arith.h" 9 | 10 | #include "defines.h" 11 | 12 | // -- Need these to avoid duplicate symbols error 13 | 14 | extern inline uint8_t add_uint32(uint32_t op1, uint32_t op2, uint32_t *res); 15 | extern inline uint8_t add_uint64(uint64_t op1, uint64_t op2, uint64_t *res); 16 | 17 | extern inline void mul_uint32_wide(uint32_t op1, uint32_t op2, uint32_t *res); 18 | extern inline uint32_t mul_uint32_high(uint32_t op1, uint32_t op2); 19 | extern inline uint32_t mul_uint32_low(uint32_t op1, uint32_t op2); 20 | -------------------------------------------------------------------------------- /device/lib/uint_arith.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file uint_arith.h 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #include "defines.h" 13 | 14 | /** 15 | Adds two uint32_t values. 16 | 17 | @param[in] op1 32-bit Operand 1 18 | @param[in] op2 32-bit Operand 2 19 | @param[out] res Pointer to 64-bit result of op1 + op2 (w/o the carry) 20 | @retuns The carry bit 21 | */ 22 | static inline uint8_t add_uint32(uint32_t op1, uint32_t op2, uint32_t *res) 23 | { 24 | *res = op1 + op2; 25 | return (uint8_t)(*res < op1); 26 | } 27 | 28 | /** 29 | Adds two uint64_t values. 30 | 31 | @param[in] op1 64-bit Operand 1 32 | @param[in] op2 64-bit Operand 2 33 | @param[out] res Pointer to 128-bit result of op1 + op2 (w/o the carry) 34 | @retuns The carry bit 35 | */ 36 | static inline uint8_t add_uint64(uint64_t op1, uint64_t op2, uint64_t *res) 37 | { 38 | *res = op1 + op2; 39 | return (uint8_t)(*res < op1); 40 | } 41 | 42 | /** 43 | Multiplies two uint32_t values. 44 | 45 | @param[in] op1 32-bit Operand 1 46 | @param[in] op2 32-bit Operand 2 47 | @param[out] res Pointer to full 64-bit result of op1 * op2 48 | */ 49 | static inline void mul_uint32_wide(uint32_t op1, uint32_t op2, uint32_t *res) 50 | { 51 | #ifdef SE_USE_ASM_ARITH 52 | __asm("UMULL %0, %1, %2, %3" : "=r"(res[0]), "=r"(res[1]) : "r"(op1), "r"(op2)); 53 | #else 54 | uint64_t res_temp = (uint64_t)op1 * (uint64_t)op2; 55 | res[0] = (uint32_t)(res_temp & 0xFFFFFFFF); 56 | res[1] = (uint32_t)((res_temp >> 32) & 0xFFFFFFFF); 57 | #endif 58 | } 59 | 60 | /** 61 | Multiplies two uint32_t values and returns the upper 32 bits of the 64-bit result. 62 | 63 | @param[in] op1 Operand 1 64 | @param[in] op2 Operand 2 65 | @returns Upper 32 bits of the 64-bit result of op1 * op2 66 | */ 67 | static inline uint32_t mul_uint32_high(uint32_t op1, uint32_t op2) 68 | { 69 | uint32_t res[2]; 70 | mul_uint32_wide(op1, op2, res); 71 | return res[1]; 72 | } 73 | 74 | /** 75 | Multiplies two uint32_t values and returns the lower 32 bits of the 64-bit result. 76 | 77 | @param[in] op1 Operand 1 78 | @param[in] op2 Operand 2 79 | @returns Lower 32 bits of the 64-bit result of op1 * op2 80 | */ 81 | static inline uint32_t mul_uint32_low(uint32_t op1, uint32_t op2) 82 | { 83 | return op1 * op2; 84 | } 85 | -------------------------------------------------------------------------------- /device/lib/uintops.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file uintops.h 6 | */ 7 | 8 | #pragma once 9 | 10 | #include // uint64_t 11 | 12 | #include "defines.h" 13 | #include "uint_arith.h" 14 | 15 | /** 16 | Adds two ZZ-type unsigned integers together but does not keep track of the carry. 17 | 18 | @param[in] op1 A pointer to a ZZ-type value 19 | @param[in] op2 A pointer to another ZZ-type value 20 | @param[out] res Pointer to sizeof(ZZ)-sized result op1 + op2 (w/o the carry) 21 | */ 22 | static inline void add_uint_nocarry(ZZ op1, ZZ op2, ZZ *res) 23 | { 24 | *res = op1 + op2; 25 | } 26 | 27 | /** 28 | Adds two ZZ-type unsigned integers together. 29 | 30 | @param[in] op1 A pointer to a ZZ-type value 31 | @param[in] op2 A pointer to another ZZ-type value 32 | @param[out] res Pointer to sizeof(ZZ)-sized result of op1 + op2 (w/o the carry) 33 | @returns The carry value 34 | */ 35 | static inline uint8_t add_uint(ZZ op1, ZZ op2, ZZ *res) 36 | { 37 | return add_uint32(op1, op2, res); 38 | } 39 | 40 | /** 41 | Multiplies two ZZ-type values and returns the full sized-(2*sizeof(ZZ)) result. 42 | 43 | @param[in] op1 A type-ZZ value 44 | @param[in] op2 Another type-ZZ value 45 | @param[out] res Pointer to full (2*sizeof(ZZ))-sized result of op1 * op2 46 | */ 47 | static inline void mul_uint_wide(ZZ op1, ZZ op2, ZZ *res) 48 | { 49 | return mul_uint32_wide(op1, op2, res); 50 | } 51 | 52 | /** 53 | Multiplies two ZZ-type values and returns the upper sizeof(ZZ) bytes of the 54 | sized-(2*sizeof(ZZ)) result. 55 | 56 | @param[in] op1 A type-ZZ value 57 | @param[in] op2 Another type-ZZ value 58 | @returns Upper sizeof(ZZ) bytes of op1 * op2 59 | */ 60 | static inline ZZ mul_uint_high(ZZ op1, ZZ op2) 61 | { 62 | return mul_uint32_high(op1, op2); 63 | } 64 | 65 | /** 66 | Multiplies two ZZ-type values and returns the lower sizeof(ZZ) bytes of the 67 | sized-(2*sizeof(ZZ)) result. 68 | 69 | @param[in] op1 A type-ZZ value 70 | @param[in] op2 Another type-ZZ value 71 | @returns Lower sizeof(ZZ) bytes of op1 * op2 72 | */ 73 | static inline ZZ mul_uint_low(ZZ op1, ZZ op2) 74 | { 75 | return mul_uint32_low(op1, op2); 76 | } 77 | 78 | /** 79 | Adds two 128-bit unsigned integers together. 80 | 81 | @param[in] op1 A pointer to a 128-bit value 82 | @param[in] op2 A pointer to another 128-bit value 83 | @param[out] res Pointer to the 128-bit result of op1 + op2 (w/o the carry) 84 | @returns The carry value 85 | */ 86 | static inline unsigned char add_uint128(const uint64_t *op1, const uint64_t *op2, uint64_t *res) 87 | { 88 | uint64_t res_right; 89 | uint64_t carry_right = (uint64_t)add_uint64(op1[0], op2[0], (uint64_t *)&res_right); 90 | 91 | uint64_t res_left; 92 | unsigned char carry_left = add_uint64(op1[1], op2[1], (uint64_t *)&res_left); 93 | 94 | // -- Carry for below should be 0, so don't need to save it 95 | add_uint64(res_left, carry_right, (uint64_t *)&res_left); 96 | 97 | res[1] = res_left; 98 | res[0] = res_right; 99 | 100 | return carry_left; 101 | } 102 | -------------------------------------------------------------------------------- /device/lib/user_defines.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file user_defines.h 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include // PRIu32, PRIu64 // not even sure this is needed... 12 | #include // uint64_t, UINT64_MAX 13 | #include 14 | #include // size_t 15 | #include // memset 16 | 17 | #ifdef SE_ON_SPHERE_M4 18 | #include "mt3620.h" 19 | #include "os_hal_dma.h" 20 | #include "os_hal_gpt.h" 21 | #include "os_hal_uart.h" 22 | #endif 23 | 24 | // ============================================================================== 25 | // Basic configurations 26 | // 27 | // Instructions: Configure each of the following by choosing a numbered value. 28 | // These must match the platform's capabilities or library will not work. 29 | // ============================================================================== 30 | /** 31 | Assert type. Will be force-set to 0 if in cmake release mode. 32 | 33 | 0 = none (will define NDEBUG) 34 | 1 = standard using 35 | 2 = custom 36 | */ 37 | #define SE_ASSERT_TYPE 1 38 | 39 | /** 40 | Randomness generation type. 41 | 42 | Note: Tests will only work if set to 0 on the Azure sphere M4 -- Not secure! 43 | To use this library on the Sphere M4, you need to build a partner application 44 | to sample randomness using an A7 application and pass it to this library. 45 | 46 | 0 = none (For debugging only. Will not pass all tests) 47 | 1 = use getrandom() 48 | 2 = nrf5 rng 49 | */ 50 | #define SE_RAND_TYPE 1 51 | 52 | // ============================================================================== 53 | // Basic configurations: Memory 54 | // 55 | // Instructions: Configure each of the following by choosing a numbered value 56 | // for more control over memory allocation. 57 | // ============================================================================== 58 | 59 | /** 60 | Inverse FFT type. 61 | 62 | Note: On the Sphere M4, will not work if this is non-otf for n = 4K and in Debug mode. 63 | 64 | 0 = compute "on-the-fly" 65 | 1 = load 66 | 2 = compute "one-shot" (not yet supported) 67 | */ 68 | #define SE_IFFT_TYPE 0 69 | 70 | /** 71 | NTT type. 72 | 73 | Note: On the Sphere M4, will not work if this is load-fast for n = 4K and in Debug mode. 74 | 75 | 0 = compute "on-the-fly" 76 | 1 = compute "one-shot" 77 | 2 = load 78 | 3 = load fast 79 | */ 80 | #define SE_NTT_TYPE 1 81 | 82 | /** 83 | Index map type. 84 | 85 | If set to load (non-persist) and SK is persistent and IFFT and NTT are on the fly, will be 86 | reset to option 4 (i.e. load persistent for symmetric, load for asymmetric) 87 | 88 | 0 = compute "on-the-fly" 89 | 1 = compute persistent 90 | 2 = load 91 | 3 = load persistent 92 | 4 = load persistent for symmetric, load for asymmetric 93 | */ 94 | #define SE_INDEX_MAP_TYPE 1 95 | 96 | /** 97 | Secret key type. (Ignored in asymmetric mode). 98 | 99 | Note: If SE_IFFT_TYPE is set as 0, a setting of 1 here will be reset to 2 (same amount of 100 | memory for better performance). 101 | 102 | 0 = not persistent 103 | 1 = persistent across primes 104 | 2 = persistent 105 | */ 106 | #define SE_SK_TYPE 2 107 | 108 | /** 109 | Data load type. Load method for precomputed keys, roots, and index map. 110 | 111 | Note: On M4, this will be force set to 1. 112 | 113 | 0 = from file (uses file I/O) 114 | 1 = copy from headers into separate buffer (no file I/O) 115 | 2 = load from code directly (not supported) 116 | */ 117 | #define SE_DATA_LOAD_TYPE 0 118 | 119 | // ============================================================================= 120 | // Optional / Advanced Configurations 121 | // 122 | // Instructions: Configure each of the following by commenting/uncommenting 123 | // ============================================================================= 124 | 125 | /** 126 | Include memory for "values" allocation as part of the initial memory pool. 127 | Uncomment to use. 128 | */ 129 | #define SE_MEMPOOL_ALLOC_VALUES 130 | 131 | /** 132 | Uncomment to use predefine implementation for conj(), creal(), and cimag(). Otherwise, 133 | treats complex values as two doubles (a real part followed by an imaginary part). 134 | */ 135 | #define SE_USE_PREDEF_COMPLEX_FUNCS 136 | 137 | /** 138 | Sometimes malloc is not available or stack memory allocation is more desireable. 139 | Comment out to use stack allocation instead. 140 | */ 141 | #define SE_USE_MALLOC 142 | 143 | /** 144 | Optimization to generate prime components in reverse order every other time. Enables more 145 | optimal memory usage and performance. Will be ignored if IFFT type is "compute on-the-fly" 146 | or NTT type is "compute on-the-fly" or "compute one-shot". Uncomment to use. 147 | TODO: Enable this feature in adapter. 148 | */ 149 | // #define SE_REVERSE_CT_GEN_ENABLED 150 | 151 | /** 152 | Explicitly sets some unnecessary function arguments (i.e., arguments only necessary for 153 | testing) to 0 at the start of the function for better performance. If defined, testing 154 | will no longer function correctly. Uncomment to use. 155 | */ 156 | // #define SE_DISABLE_TESTING_CAPABILITY 157 | 158 | /** 159 | Uncomment to use the 27-bit default for n=4K instead of the 30-bit default 160 | Make sure to uncomment SEALE_DEFAULT_4K_27BIT in the adapter (see: utils.h) as well. 161 | */ 162 | // #define SE_DEFAULT_4K_27BIT 163 | 164 | // ============================================================================= 165 | // Malloc off configurations 166 | // 167 | // Instructions: Configurations that apply when SE_USE_MALLOC is undefined 168 | // Uncomment/comment as needed and set desired values for n, # of primes. 169 | // ============================================================================= 170 | /** 171 | Encryption type to use if malloc is not enabled (uncomment to use asymmetric encryption) 172 | */ 173 | #define SE_ENCRYPT_TYPE_SYMMETRIC 174 | 175 | /** 176 | Number of primes to use if malloc is not enabled. 177 | */ 178 | #define SE_NPRIMES 3 179 | 180 | /** 181 | Polynomial ring degree to use if malloc is not enabled 182 | */ 183 | #define SE_DEGREE_N 4096 184 | 185 | // ============================================================================= 186 | // Bare-metal configurations 187 | // 188 | // Instructions: Configure each of the following by commenting/uncommenting 189 | // These configurations will be ignored if platform type is A7 or none. 190 | // ============================================================================= 191 | /** 192 | Include the code file containing hard-coded public key values. 193 | This file can be generated using the SEAL-Embedded adapter. 194 | (Ignored if SE_DATA_LOAD_TYPE is "from file".) 195 | */ 196 | // #define SE_DEFINE_PK_DATA 197 | 198 | /** 199 | Include the code file containing hard-coded secret key values. 200 | This file can be generated using the SEAL-Embedded adapter. 201 | (Ignored if SE_DATA_LOAD_TYPE is "from file".) 202 | */ 203 | #define SE_DEFINE_SK_DATA 204 | 205 | /** 206 | Print using UART (will be disabled if platform type != NRF5). 207 | 208 | If you are on NRF5 and want output to go to RTT, make sure RETARGET_ENABLED is set to 0 in 209 | sdk_config.h (and that RTT is enabled in the configuration window) and comment out this 210 | preprocessor. 211 | 212 | If you do not want output to go to RTT, do the opposite of above and uncomment this 213 | preprocessor. 214 | */ 215 | // #define SE_NRF5_UART_PRINTF_ENABLED 216 | -------------------------------------------------------------------------------- /device/linker.ld: -------------------------------------------------------------------------------- 1 | /** 2 | * This code is based on a sample from Microsoft (see license below), 3 | * with modifications made by MediaTek. 4 | * Modified version of linker.ld from Microsoft Azure Sphere sample code: 5 | * https://github.com/Azure/azure-sphere-samples/blob/master/Samples/HelloWorld/HelloWorld_RTApp_MT3620_BareMetal/linker.ld 6 | **/ 7 | 8 | /* Copyright (c) Microsoft Corporation. All rights reserved. 9 | Licensed under the MIT License. */ 10 | 11 | MEMORY 12 | { 13 | TCM (rwx) : ORIGIN = 0x00100000, LENGTH = 192K 14 | SYSRAM (rwx) : ORIGIN = 0x22000000, LENGTH = 64K 15 | FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 1M 16 | } 17 | 18 | /* The data and BSS regions can be placed in TCM or SYSRAM. The code and read-only regions can 19 | be placed in TCM, SYSRAM, or FLASH. See 20 | https://docs.microsoft.com/en-us/azure-sphere/app-development/memory-latency for information 21 | about which types of memory which are available to real-time capable applications on the 22 | MT3620, and when they should be used. */ 23 | 24 | /* REGION_ALIAS("CODE_REGION", TCM); */ 25 | REGION_ALIAS("CODE_REGION", FLASH); 26 | /* REGION_ALIAS("CODE_REGION", SYSRAM); */ 27 | 28 | /* REGION_ALIAS("RODATA_REGION", TCM); */ 29 | REGION_ALIAS("RODATA_REGION", FLASH); 30 | /* REGION_ALIAS("RODATA_REGION", SYSRAM); */ 31 | 32 | /* REGION_ALIAS("DATA_REGION", TCM); */ 33 | REGION_ALIAS("DATA_REGION", SYSRAM); 34 | 35 | REGION_ALIAS("BSS_REGION", TCM); 36 | /* REGION_ALIAS("BSS_REGION", SYSRAM); */ 37 | 38 | ENTRY(__isr_vector) 39 | SECTIONS 40 | { 41 | /* The exception vector's virtual address must be aligned to a power of two, 42 | which is determined by its size and set via CODE_REGION. See definition of 43 | ExceptionVectorTable in main.c. 44 | 45 | When the code is run from XIP flash, it must be loaded to virtual address 46 | 0x10000000 and be aligned to a 32-byte offset within the ELF file. */ 47 | .text : ALIGN(32) { 48 | __vector_table_start__ = .; 49 | KEEP(*(.vector_table)) 50 | __vector_table_end__ = .; 51 | *(.text) 52 | } >CODE_REGION 53 | 54 | .isr_vector_tcm : ALIGN(512) { 55 | KEEP(*(.vector_table_tcm)) 56 | } >DATA_REGION 57 | 58 | .rodata : { 59 | *(.rodata) 60 | } >RODATA_REGION 61 | 62 | .data : { 63 | *(.data) 64 | } >DATA_REGION 65 | 66 | .bss : { 67 | __bss_start__ = .; 68 | *(.bss) 69 | __bss_end__ = .; 70 | } >BSS_REGION 71 | 72 | . = ALIGN(4); 73 | end = .; 74 | 75 | .sysram : { 76 | *(.sysram) 77 | } >SYSRAM 78 | 79 | StackTop = ORIGIN(TCM) + LENGTH(TCM); 80 | } 81 | -------------------------------------------------------------------------------- /device/scripts/app_manifest_sphere_a7.txt: -------------------------------------------------------------------------------- 1 | { 2 | "SchemaVersion": 1, 3 | "Name": "SealEmbeddedApp", 4 | "ComponentId": "5a4b43d1-a3b0-4f9f-a9c9-30a4cc52a2f2", 5 | "EntryPoint": "/bin/app", 6 | "CmdArgs": [], 7 | "Capabilities": { 8 | "Gpio": [ 9 ], 9 | "AllowedApplicationConnections": [], 10 | "AllowedConnections": [ "www.neverssl.com", "neverssl.com", "httpstat.us"] 11 | }, 12 | "ApplicationType": "Default" 13 | } 14 | -------------------------------------------------------------------------------- /device/scripts/app_manifest_sphere_m4.txt: -------------------------------------------------------------------------------- 1 | { 2 | "SchemaVersion": 1, 3 | "Name": "SealEmbeddedApp", 4 | "ComponentId": "5a4b43d1-a3b0-4f9f-a9c9-30a4cc52a2f2", 5 | "EntryPoint": "/bin/app", 6 | "CmdArgs": [], 7 | "Capabilities": { 8 | "Gpio": [ 9 ], 9 | "AllowedApplicationConnections": [], 10 | "AllowedConnections": [ "www.neverssl.com", "neverssl.com", "httpstat.us"] 11 | }, 12 | "ApplicationType": "RealTimeCapable" 13 | } 14 | -------------------------------------------------------------------------------- /device/scripts/change_defines.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT license. 5 | 6 | import sys, getopt 7 | 8 | def file_line_rep(filedata, base_string, min_val, max_val, set_val): 9 | #print("In file_line_rep. range: ["+str(min_val)+", "+str(max_val)+"], set_val: "+str(set_val)) 10 | print("Setting "+base_string+" to "+str(set_val)) 11 | 12 | if max_val < min_val: 13 | print("ERROR: max_val or min_val is set incorrectly") 14 | raise 15 | if set_val > max_val or set_val < min_val: 16 | print("ERROR: max_val or min_val or set_val is set incorrectly") 17 | raise 18 | 19 | newfiledata = [] 20 | 21 | for line in filedata: 22 | #print(line) 23 | if line.find(base_string) != -1: 24 | #print(line) 25 | for i in range(min_val, max_val+1): 26 | line = line.replace(base_string+" "+str(i), base_string+" "+str(set_val)) 27 | #print(line) 28 | newfiledata.append(line) 29 | 30 | #for line in newfiledata: 31 | # print(line) 32 | 33 | return newfiledata 34 | 35 | # ------------------------- 36 | # Set the IFFT type 37 | # ------------------------- 38 | def set_ifft_define(set_val): 39 | with open("lib/user_defines.h", "r") as file : 40 | filedata = file.readlines() 41 | 42 | newfiledata = file_line_rep(filedata, "#define SE_IFFT_TYPE", 0, 2, set_val) 43 | 44 | with open("lib/user_defines.h", "w") as file : 45 | file.writelines(newfiledata) 46 | 47 | 48 | # ---------------------- 49 | # Set the NTT type 50 | # ---------------------- 51 | def set_ntt_define(set_val): 52 | with open("lib/user_defines.h", "r") as file : 53 | filedata = file.readlines() 54 | 55 | newfiledata = file_line_rep(filedata, "#define SE_NTT_TYPE", 0, 3, set_val) 56 | 57 | with open("lib/user_defines.h", "w") as file : 58 | file.writelines(newfiledata) 59 | 60 | 61 | # ----------------------------- 62 | # Set the Index Map type 63 | # ----------------------------- 64 | def set_index_map_define(set_val): 65 | with open("lib/user_defines.h", "r") as file : 66 | filedata = file.readlines() 67 | 68 | newfiledata = file_line_rep(filedata, "#define SE_INDEX_MAP_TYPE", 0, 4, set_val) 69 | 70 | with open("lib/user_defines.h", "w") as file : 71 | file.writelines(newfiledata) 72 | 73 | # ----------------------------- 74 | # Set the SK type 75 | # ----------------------------- 76 | def set_sk_define(set_val): 77 | with open("lib/user_defines.h", "r") as file : 78 | filedata = file.readlines() 79 | 80 | newfiledata = file_line_rep(filedata, "#define SE_SK_TYPE", 0, 2, set_val) 81 | 82 | with open("lib/user_defines.h", "w") as file : 83 | file.writelines(newfiledata) 84 | 85 | # ----------------------------- 86 | # Set the Data Load Type 87 | # ----------------------------- 88 | def set_data_load_define(set_val): 89 | with open("lib/user_defines.h", "r") as file : 90 | filedata = file.readlines() 91 | 92 | newfiledata = file_line_rep(filedata, "#define SE_DATA_LOAD_TYPE", 0, 2, set_val) 93 | 94 | with open("lib/user_defines.h", "w") as file : 95 | file.writelines(newfiledata) 96 | 97 | def main(argv): 98 | try: 99 | opts, args = getopt.getopt(argv,"hi:n:m:s:d:",["ifft=", "ntt=", "index_map=", "sk=", "data_load="]) 100 | except getopt.GetoptError: 101 | print("change_defines.py -i -n "\ 102 | "-m -s -d ") 103 | sys.exit(2) 104 | 105 | ifft_set_val = -1 106 | ntt_set_val = -1 107 | index_map_set_val = -1 108 | sk_set_val = -1 109 | data_load_set_val = -1 110 | 111 | for opt, arg in opts: 112 | if opt == '-h': 113 | print("change_defines.py -i -n "\ 114 | "-m -s -d ") 115 | sys.exit() 116 | elif opt in ("-i", "--ifft"): 117 | ifft_set_val = int(arg) 118 | elif opt in ("-n", "--ntt"): 119 | ntt_set_val = int(arg) 120 | elif opt in ("-m", "--index_map"): 121 | index_map_set_val = int(arg) 122 | elif opt in ("-s", "--sk"): 123 | sk_set_val = int(arg) 124 | elif opt in ("-d", "--data_load"): 125 | data_load_set_val = int(arg) 126 | 127 | if ifft_set_val < 0: 128 | print("Error: Need to choose an ifft option") 129 | sys.exit() 130 | elif ntt_set_val < 0: 131 | print("Error: Need to choose an ntt option") 132 | sys.exit() 133 | elif index_map_set_val < 0: 134 | print("Error: Need to choose an index_map option") 135 | sys.exit() 136 | elif sk_set_val < 0: 137 | print("Error: Need to choose an sk option") 138 | sys.exit() 139 | elif data_load_set_val < 0: 140 | print("Error: Need to choose a data load option") 141 | sys.exit() 142 | 143 | set_ifft_define(ifft_set_val) 144 | set_ntt_define(ntt_set_val) 145 | set_index_map_define(index_map_set_val) 146 | set_sk_define(sk_set_val) 147 | set_data_load_define(data_load_set_val) 148 | 149 | if __name__ == '__main__': 150 | main(sys.argv[1:]) 151 | -------------------------------------------------------------------------------- /device/scripts/commands_sphere_a7.gdb: -------------------------------------------------------------------------------- 1 | set tcp connect-timeout unlimited 2 | set pagination off 3 | target remote 192.168.35.2:2345 4 | c 5 | -------------------------------------------------------------------------------- /device/scripts/commands_sphere_m4.gdb: -------------------------------------------------------------------------------- 1 | set tcp connect-timeout unlimited 2 | set pagination off 3 | target remote :4444 4 | -------------------------------------------------------------------------------- /device/scripts/gdb_launch_sphere_a7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT license. 5 | 6 | # ***************************************************************************** 7 | # -- File: gdb_launch_sphere_a7.sh 8 | # 9 | # -- Description: 10 | # This script runs the azure sphere gdb debug tool for debugging SEAL-Embedded 11 | # a SEAL-Embedded application on an azure sphere device and follows the 12 | # instructions listed under 'Debug the Sample' at the following URL: 13 | # 14 | # https://docs.microsoft.com/en-us/azure-sphere/install/qs-blink-application 15 | # 16 | # This script is meant to be run in conjuction with sphere_a7_launch_cl.sh 17 | # (from another terminal) and targets the a7 core. 18 | # 19 | # -- Instructions: 20 | # Navigate to folder with "SEAL_EMBEDDED.out" and run this script. 21 | # Make sure to replace 'sysroot' with the desired sysroot version to use. 22 | # and edit path variables according to your setup as needed. 23 | # ***************************************************************************** 24 | 25 | sysroot=10 26 | 27 | SCRIPT_DIR_PATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 28 | AZSPHERE_SDK_PATH="/opt/azurespheresdk" 29 | IMAGE_DIR_PATH="./build" 30 | 31 | # -- Make sure we are connected 32 | $AZSPHERE_SDK_PATH/DeviceConnection/azsphere_connect.sh 33 | 34 | # -- Lines 1, 2, 3 35 | $AZSPHERE_SDK_PATH/Sysroots/$sysroot/tools/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-musleabi/arm-poky-linux-musleabi-gdb \ 36 | --command=$SCRIPT_DIR_PATH/commands_sphere_a7.gdb \ 37 | $IMAGE_DIR_PATH/SEAL_EMBEDDED.out 38 | -------------------------------------------------------------------------------- /device/scripts/gdb_launch_sphere_m4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT license. 5 | 6 | # ***************************************************************************** 7 | # -- File: gdb_launch_sphere_m4.sh 8 | # 9 | # -- Description: 10 | # This script runs the azure sphere gdb debug tool for debugging SEAL-Embedded 11 | # a SEAL-Embedded application on an azure sphere device and follows the 12 | # instructions listen under 'Debug the Sample' at the following URL: 13 | # 14 | # https://docs.microsoft.com/en-us/azure-sphere/install/qs-real-time-application 15 | 16 | # This script is meant to be run in conjuction with sphere_m4_launch_cl.sh 17 | # (from another terminal) and targets the m4 core. 18 | # 19 | # -- Instructions: 20 | # Navigate to folder with "SEAL_EMBEDDED.out" and run this script. 21 | # Make sure to replace 'sysroot' with the desired sysroot version to use. 22 | # and edit path variables according to your setup as needed. 23 | # ***************************************************************************** 24 | 25 | sysroot=10 26 | 27 | SCRIPT_DIR_PATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 28 | GNU_TOOLCHAIN_PATH="${HOME}/gcc-arm-none-eabi-10.3-2021.07" 29 | IMAGE_DIR_PATH="./build" 30 | 31 | $GNU_TOOLCHAIN_PATH/bin/arm-none-eabi-gdb \ 32 | --command=$SCRIPT_DIR_PATH/commands_sphere_m4.gdb \ 33 | $IMAGE_DIR_PATH/SEAL_EMBEDDED.out 34 | -------------------------------------------------------------------------------- /device/scripts/minirc_sphere_m4.dfl: -------------------------------------------------------------------------------- 1 | # Machine-generated file - use "minicom -s" to change parameters. 2 | pu port /dev/ttyUSB3 3 | pu baudrate 115200 4 | pu bits 8 5 | pu parity N 6 | pu stopbits 1 7 | pu minit 8 | pu rtscts No 9 | -------------------------------------------------------------------------------- /device/scripts/ocd_launch_sphere_m4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT license. 5 | 6 | # ***************************************************************************** 7 | # -- File: gdb_launch_sphere_m4.sh 8 | # 9 | # -- Description: 10 | # This script runs the azure sphere gdb debug tool for debugging SEAL-Embedded 11 | # a SEAL-Embedded application on an azure sphere device and follows the 12 | # instructions listen under 'Debug the Sample' at the following URL: 13 | # 14 | # https://docs.microsoft.com/en-us/azure-sphere/install/qs-real-time-application 15 | 16 | # This script is meant to be run in conjuction with sphere_m4_launch_cl.sh 17 | # (from another terminal) and targets the m4 core. 18 | # 19 | # -- Instructions: 20 | # Navigate to folder with "SEAL_EMBEDDED.out" and run this script. 21 | # Make sure to replace 'sysroot' with the desired sysroot version to use. 22 | # and edit path variables according to your setup as needed. 23 | # ***************************************************************************** 24 | 25 | sysroot=10 26 | AZSPHERE_SDK_PATH="/opt/azurespheresdk" 27 | core="targets io0" 28 | 29 | # -- Replace above line with this if targetting Core 1 instead 30 | # core="targets io1" 31 | 32 | # -- Save current path 33 | # dir=$(pwd) 34 | 35 | # -- Change directories 36 | cd $AZSPHERE_SDK_PATH/Sysroots/$sysroot/tools/sysroots/x86_64-pokysdk-linux/ 37 | 38 | # -- Run the on-chip debugger 39 | ./usr/bin/openocd -f mt3620-rdb-ftdi.cfg -f mt3620-io0.cfg -c "gdb_memory_map disable" -c "gdb_breakpoint_override hard" -c init -c "${core}" -c halt -c "targets" 40 | -------------------------------------------------------------------------------- /device/scripts/sphere_a7_launch_cl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT license. 5 | 6 | # ***************************************************************************** 7 | # -- File: sphere_a7_launch_cl.sh 8 | # 9 | # -- Description: 10 | # This script runs some azure sphere commands to launch a SEAL-Embedded 11 | # application in debug mode on an azure sphere and follows the instructions 12 | # listed under 'Run the Sample' and 'Debug the Sample' at the following URL: 13 | # 14 | # https://docs.microsoft.com/en-us/azure-sphere/install/qs-blink-application 15 | # 16 | # This script is meant to be run in conjuction with gdb_launch_a7.sh (from 17 | # another terminal) and targets the a7 core. 18 | # 19 | # Note that the component ID for the SEAL Embedded image package can be found 20 | # in app_manifest.json or via the following command: 21 | # 22 | # azsphere image-package show --image-package SEAL_EMBEDDED.imagepackage 23 | # 24 | # -- Instructions: 25 | # Nagivate to the folder where SEAL_EMBEDDED.imagepackage is created and run 26 | # this script. 27 | # ***************************************************************************** 28 | 29 | # -- Application component ID, found in app_manifest.json 30 | comp_id=5a4b43d1-a3b0-4f9f-a9c9-30a4cc52a2f2 31 | 32 | AZSPHERE_SDK_PATH="/opt/azurespheresdk" 33 | IMAGE_DIR_PATH="./build" 34 | 35 | SCRIPT_DIR_PATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 36 | 37 | cp $SCRIPT_DIR_PATH/app_manifest_sphere_a7.txt app_manifest.json 38 | 39 | # -- Make sure we are connected 40 | $AZSPHERE_SDK_PATH/DeviceConnection/azsphere_connect.sh 41 | 42 | # -- Uncomment this to delete any applications that were previously loaded 43 | # on the device first 44 | azsphere device sideload delete 45 | 46 | # -- If the application is already running, stop it first 47 | azsphere device app stop --component-id $comp_id 48 | 49 | # -- Load the applicaiton onto the device 50 | azsphere device sideload deploy --image-package $IMAGE_DIR_PATH/SEAL_EMBEDDED.imagepackage 51 | 52 | # -- Start running the application in debug mode 53 | azsphere device app start --debug-mode --component-id $comp_id 54 | #azsphere device app start --component-id $comp_id 55 | 56 | # -- Connect to the output port 57 | telnet 192.168.35.2 2342 58 | -------------------------------------------------------------------------------- /device/scripts/sphere_m4_launch_cl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT license. 5 | 6 | # ***************************************************************************** 7 | # -- File: sphere_m4_launch_cl.sh 8 | # 9 | # -- Description: 10 | # This script runs some azure sphere commands to launch a SEAL-Embedded 11 | # application in debug mode on an azure sphere and follows the instructions 12 | # listed under 'Run the Sample' and 'Debug the Sample' at the following URL: 13 | # 14 | # https://docs.microsoft.com/en-us/azure-sphere/install/qs-blink-application 15 | # 16 | # Note that the component ID for the SEAL Embedded image package can be found 17 | # in app_manifest.json or via the following command: 18 | # 19 | # azsphere image-package show --image-package SEAL_EMBEDDED.imagepackage 20 | # 21 | # -- Instructions: 22 | # Nagivate to the folder where SEAL_EMBEDDED.imagepackage is created and run 23 | # this script. 24 | # ***************************************************************************** 25 | 26 | # -- Application component ID, found in app_manifest.json 27 | comp_id=5a4b43d1-a3b0-4f9f-a9c9-30a4cc52a2f2 28 | 29 | AZSPHERE_SDK_PATH="/opt/azurespheresdk" 30 | IMAGE_DIR_PATH="./build" 31 | 32 | SCRIPT_DIR_PATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 33 | 34 | cp $SCRIPT_DIR_PATH/app_manifest_sphere_m4.txt app_manifest.json 35 | 36 | # -- Make sure we are connected 37 | $AZSPHERE_SDK_PATH/DeviceConnection/azsphere_connect.sh 38 | 39 | # -- Uncomment this to delete any applications that were previously loaded 40 | # on the device first 41 | azsphere device sideload delete 42 | 43 | # -- If the application is already running, stop it first 44 | # azsphere device app stop --component-id $comp_id 45 | 46 | # -- Load the applicaiton onto the device 47 | azsphere device sideload deploy --image-package $IMAGE_DIR_PATH/SEAL_EMBEDDED.imagepackage 48 | 49 | # -- Start running the application in debug mode 50 | azsphere device app start --debug-mode --component-id $comp_id 51 | #azsphere device app start --component-id $comp_id 52 | -------------------------------------------------------------------------------- /device/scripts/test_all_configs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT license. 5 | 6 | CHANGE_DEFINES_SCRIPT=./scripts/change_defines.py 7 | BUILD_DIR=./build 8 | 9 | # ifft 0, 1 10 | # ntt 0, 1, 2, 3 11 | # index_map_type 0, 1, 2, 3, 4 12 | # sk_type 0, 1, 2 13 | # data_load_type 0, 1 14 | 15 | # python3 $CHANGE_DEFINES_SCRIPT -i 0 -n 0 -m 0 -s 0 -d 0 16 | # cmake --build build -j || exit 1 17 | # $BUILD_DIR/bin/seal_embedded_tests 18 | # status=$? 19 | # echo "status = "$status 20 | # if [ $status -ne "0" ] 21 | # then 22 | # echo "THERE WAS AN ERROR." 23 | # exit 24 | # fi 25 | # exit 26 | 27 | for d in 0 1 28 | do 29 | for i in 0 1 30 | do 31 | for n in 0 1 2 3 32 | do 33 | for m in 0 1 2 3 4 34 | do 35 | for s in 0 1 36 | do 37 | python3 $CHANGE_DEFINES_SCRIPT -i $i -n $n -m $m -s $s -d $d 38 | cmake --build $BUILD_DIR -j || exit 1 39 | $BUILD_DIR/bin/seal_embedded_tests 40 | status=$? 41 | echo "status = "$status 42 | if [ $status -ne 0 ] 43 | then 44 | echo "THERE WAS AN ERROR." 45 | exit 46 | fi 47 | done 48 | done 49 | done 50 | done 51 | done 52 | -------------------------------------------------------------------------------- /device/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. All rights reserved. 2 | # Licensed under the MIT license. 3 | 4 | set(SE_TESTS_SOURCE_FILES ${SE_TESTS_SOURCE_FILES} 5 | ${CMAKE_CURRENT_LIST_DIR}/fft_tests.c 6 | ${CMAKE_CURRENT_LIST_DIR}/modulo_tests.c 7 | ${CMAKE_CURRENT_LIST_DIR}/network_tests.c 8 | ${CMAKE_CURRENT_LIST_DIR}/sample_tests.c 9 | ${CMAKE_CURRENT_LIST_DIR}/uintmodarith_tests.c 10 | ${CMAKE_CURRENT_LIST_DIR}/uintops_tests.c 11 | ${CMAKE_CURRENT_LIST_DIR}/ntt_tests.c 12 | ${CMAKE_CURRENT_LIST_DIR}/ckks_tests_encode.c 13 | ${CMAKE_CURRENT_LIST_DIR}/ckks_tests_common.c 14 | ${CMAKE_CURRENT_LIST_DIR}/ckks_tests_asym.c 15 | ${CMAKE_CURRENT_LIST_DIR}/ckks_tests_sym.c 16 | ${CMAKE_CURRENT_LIST_DIR}/api_tests.c 17 | ${CMAKE_CURRENT_LIST_DIR}/main.c 18 | ) 19 | 20 | set(SE_TESTS_SOURCE_FILES ${SE_TESTS_SOURCE_FILES} PARENT_SCOPE) 21 | -------------------------------------------------------------------------------- /device/test/api_tests.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file api_tests.c 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "ckks_tests_common.h" 12 | #include "defines.h" 13 | #include "seal_embedded.h" 14 | #include "test_common.h" 15 | #include "util_print.h" 16 | 17 | // -- Comment out to run true test 18 | // #define SE_API_TESTS_DEBUG 19 | 20 | /** 21 | Function to print ciphertext values with the same function signature as SEND_FNCT_PTR. 22 | Used in place of a networking function for testing. 23 | 24 | Size req: v must be at least vlen_bytes 25 | 26 | @param[in] v Input polynomial (ciphertext) to be printed 27 | @param[in] vlen_bytes Number of bytes of v to print 28 | @returns Then number of bytes of v that were printed (equal to vlen_bytes on success) 29 | */ 30 | size_t test_print_ciphertexts(void *v, size_t vlen_bytes) 31 | { 32 | static int idx = 0; 33 | size_t vlen = vlen_bytes / sizeof(ZZ); 34 | const char *name = idx ? "c1" : "c0"; 35 | #ifdef SE_API_TESTS_DEBUG 36 | print_poly(name, (ZZ *)v, vlen); 37 | #else 38 | print_poly_full(name, (ZZ *)v, vlen); 39 | #endif 40 | idx = idx ? 0 : 1; 41 | return vlen_bytes; 42 | } 43 | 44 | /** 45 | Helper function to tests the default SEAL-Embedded API for by printing values of a ciphertext. 46 | If SE_DISABLE_TESTING_CAPABILITY is not defined, throws an error on failure. 47 | On success, resulting output can be verified with the SEAL-Embedded adapter. 48 | */ 49 | void test_ckks_api_base(SE_PARMS *se_parms) 50 | { 51 | se_assert(se_parms); 52 | se_assert(se_parms->parms); 53 | se_assert(se_parms->se_ptrs); 54 | 55 | SEND_FNCT_PTR fake_network_func = (void *)&test_print_ciphertexts; 56 | 57 | size_t vlen = se_parms->parms->coeff_count / 2; 58 | #ifdef SE_USE_MALLOC 59 | flpt *v = calloc(vlen, sizeof(flpt)); 60 | #else 61 | flpt v[SE_DEGREE_N / 2]; 62 | memset(&v, 0, SE_DEGREE_N * sizeof(flpt) / 2); 63 | se_assert(SE_DEGREE_N / 2 == se_parms->parms->coeff_count / 2); 64 | #endif 65 | 66 | for (size_t testnum = 0; testnum < 9; testnum++) 67 | { 68 | // -- Set up buffer v with testing values 69 | set_encode_encrypt_test(testnum, vlen, &(v[0])); 70 | 71 | // -- Print the expected output. This will help the adapter with verification. 72 | #ifdef SE_API_TESTS_DEBUG 73 | print_poly_flpt("v (cleartext)", v, vlen); 74 | #else 75 | print_poly_flpt_full("v (cleartext)", v, vlen); 76 | #endif 77 | 78 | // -- Call the main encryption function! 79 | /* 80 | // -- Seed for testing 81 | uint8_t share_seed[SE_PRNG_SEED_BYTE_COUNT]; 82 | uint8_t seed[SE_PRNG_SEED_BYTE_COUNT]; 83 | memset(&(share_seed[0]), 0, SE_PRNG_SEED_BYTE_COUNT); 84 | memset(&( seed[0]), 0, SE_PRNG_SEED_BYTE_COUNT); 85 | share_seed[0] = 1; 86 | seed[0] = 1; 87 | bool ret = se_encrypt_seeded(share_seed, seed, fake_network_func, &(v[0]), vlen * 88 | sizeof(flpt), false, se_parms); se_assert(ret); 89 | */ 90 | se_encrypt(fake_network_func, &(v[0]), vlen * sizeof(flpt), false, se_parms); 91 | } 92 | #ifdef SE_USE_MALLOC 93 | if (v) 94 | { 95 | free(v); 96 | v = 0; 97 | } 98 | #endif 99 | delete_parameters(se_parms->parms); 100 | } 101 | 102 | /** 103 | Tests the default SEAL-Embedded API for symmetric encryption by printing values of a ciphertext. 104 | If SE_DISABLE_TESTING_CAPABILITY is not defined, throws an error on failure. 105 | On success, resulting output can be verified with the SEAL-Embedded adapter. 106 | */ 107 | void test_ckks_api_sym(void) 108 | { 109 | printf("Beginning tests for ckks api symmetric encrypt...\n"); 110 | #ifndef SE_USE_MALLOC 111 | static ZZ mempool_local[MEMPOOL_SIZE]; 112 | *mempool_ptr_global = &(mempool_local[0]); 113 | // -- Debugging 114 | // printf("Address of mempool_local: %p\n", &(mempool_local[0])); 115 | // printf("Address of mempool_ptr_global: %p\n", &mempool_ptr_global); 116 | // printf("Value of mempool_ptr_global (should be address of mempool_local): %p\n", 117 | // mempool_ptr_global); 118 | #endif 119 | SE_PARMS *se_parms = se_setup_default(SE_SYM_ENCR); 120 | print_test_banner("Symmetric Encryption (API)", se_parms->parms); 121 | test_ckks_api_base(se_parms); 122 | } 123 | 124 | /** 125 | Tests the default SEAL-Embedded API for asymmetric encryption by printing values of a ciphertext. 126 | If SE_DISABLE_TESTING_CAPABILITY is not defined, throws an error on failure. 127 | On success, resulting output can be verified with the SEAL-Embedded adapter. 128 | */ 129 | void test_ckks_api_asym(void) 130 | { 131 | printf("Beginning tests for ckks api asymmetric encrypt...\n"); 132 | #ifndef SE_USE_MALLOC 133 | static ZZ mempool_local[MEMPOOL_SIZE]; 134 | *mempool_ptr_global = &(mempool_local[0]); 135 | // -- Debugging 136 | // printf("Address of mempool_local: %p\n", &(mempool_local[0])); 137 | // printf("Address of mempool_ptr_global: %p\n", &mempool_ptr_global); 138 | // printf("Value of mempool_ptr_global (should be address of mempool_local): %p\n", 139 | // mempool_ptr_global); 140 | #endif 141 | SE_PARMS *se_parms = se_setup_default(SE_ASYM_ENCR); 142 | print_test_banner("Asymmetric Encryption (API)", se_parms->parms); 143 | test_ckks_api_base(se_parms); 144 | } 145 | -------------------------------------------------------------------------------- /device/test/applibs_versions.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file applibs_versions.h 6 | */ 7 | 8 | #pragma once 9 | 10 | /// 11 | /// This identifier should be defined before including any of the 12 | /// networking-related header files. It indicates which version of the Wi-Fi 13 | /// data structures the application uses. 14 | /// 15 | #define NETWORKING_STRUCTS_VERSION 1 16 | 17 | /// 18 | /// This identifier must be defined before including any of the Wi-Fi related 19 | /// header files. It indicates which version of the Wi-Fi data structures the 20 | /// application uses. 21 | /// 22 | #define WIFICONFIG_STRUCTS_VERSION 1 23 | 24 | /// 25 | /// This identifier must be defined before including any of the UART-related 26 | /// header files. It indicates which version of the UART data structures the 27 | /// application uses. 28 | /// 29 | #define UART_STRUCTS_VERSION 1 30 | 31 | /// 32 | /// This identifier must be defined before including any of the SPI-related 33 | /// header files. It indicates which version of the SPI data structures the 34 | /// application uses. 35 | /// 36 | #define SPI_STRUCTS_VERSION 1 37 | -------------------------------------------------------------------------------- /device/test/ckks_tests_common.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file ckks_tests_common.h 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #include "defines.h" 13 | #include "parameters.h" 14 | #include "test_common.h" 15 | 16 | /** 17 | Sets the values of 'v' according to the particular test number. 18 | If testnum > 8, will set testnum to 8. 19 | 20 | @param[in] testnum Test number in range [0,9] 21 | @param[in] vlen Number of flpt elements in v 22 | @param[out] v Array to set 23 | */ 24 | void set_encode_encrypt_test(size_t testnum, size_t vlen, flpt *v); 25 | 26 | /** 27 | (Pseudo) ckks decode. 'values_decoded' and 'pt' may share the same starting address for in-place 28 | computation (see: ckks_decode_inpl) 29 | 30 | Note: index_map is non-const in case SE_INDEX_MAP_LOAD is defined (or, if 31 | SE_INDEX_MAP_LOAD_PERSIST_SYM_LOAD_ASYM is defined and asymmetric encryption is used). 32 | 33 | Size req: 'temp' must contain space for n double complex values 34 | 'values_decoded' must contain space for n/2 flpt elements. 35 | If index map needs to be loaded (see 'Note' above), index_map must constain space for n uint16_t 36 | elements. 37 | 38 | @param[in] pt Plaintext to decode 39 | @param[in] values_len True number of entries in initial values message. Must be <= n/2 40 | @param[in] index_map [Optional]. If passed in, can avoid 1 flash read 41 | @param[in] parms Parameters set by ckks_setup 42 | @param temp Scratch space 43 | @param[out] values_decoded Decoded message 44 | */ 45 | void ckks_decode(const ZZ *pt, size_t values_len, uint16_t *index_map, const Parms *parms, 46 | double complex *temp, flpt *values_decoded); 47 | 48 | /** 49 | (Pseudo) in-place ckks decode. 50 | 51 | Note: index_map is non-const in case SE_INDEX_MAP_LOAD is defined (or, if 52 | SE_INDEX_MAP_LOAD_PERSIST_SYM_LOAD_ASYM is defined and asymmetric encryption is used). 53 | 54 | Size req: 'temp' must contain space for n double complex values 55 | 'values_decoded' must contain space for n/2 flpt elements 56 | If index map needs to be loaded (see 'Note' above), index_map must constain space for n uint16_t 57 | elements. 58 | 59 | @param[in,out] pt In: Plaintext to decode; Out: Decoded message 60 | @param[in] values_len True number of entries in initial values message. Must be <= n/2 61 | @param[in] index_map [Optional]. If passed in, can avoid 1 flash read 62 | @param[in] parms Parameters set by ckks_setup 63 | @param temp Scratch space 64 | */ 65 | static inline void ckks_decode_inpl(ZZ *pt, size_t values_len, uint16_t *index_map, 66 | const Parms *parms, double complex *temp) 67 | { 68 | ckks_decode(pt, values_len, index_map, parms, temp, (flpt *)pt); 69 | } 70 | 71 | /** 72 | Checks that the pseudo-decoding of a ciphertext is correct. 73 | 74 | Note: index_map is non-const in case SE_INDEX_MAP_LOAD is defined (or, if 75 | SE_INDEX_MAP_LOAD_PERSIST_SYM_LOAD_ASYM is defined and asymmetric encryption is used). 76 | 77 | Size req: 'temp' must contain space for n double complex values 78 | If index map needs to be loaded (see 'Note' above), index_map must constain space for n uint16_t 79 | elements. 80 | 81 | @param[in,out] pt In: Plaintext to decode; Out: Decoded message 82 | @param[in] values Cleartext input message 83 | @param[in] values_len True number of entries in initial values message. Must be <= n/2 84 | @param[in] index_map [Optional]. If passed in, can avoid 1 flash read 85 | @param[in] parms Parameters instance 86 | @param temp Scratch space 87 | */ 88 | void check_decode_inpl(ZZ *pt, const flpt *values, size_t values_len, uint16_t *index_map, 89 | const Parms *parms, ZZ *temp); 90 | 91 | /** 92 | Pseudo-decrypts a ciphertext in place (for a particular prime component). Currently only works if 93 | 'small_s' is 0. 'c0' and 'pt' may share the same starting address for in-place computation (see: 94 | ckks_decrypt_inpl). 95 | 96 | Size req: 'pt' must have space for n elements 97 | 98 | @param[in] c0 1st ciphertext component for this prime 99 | @param[in] c1 2nd ciphertext component for this prime 100 | @param[in] s Secret key. Must be in expanded form! 101 | @param[in] small_s If true, secret key is in small form; Else, is in expanded form 102 | @param[in] parms Parameters instance 103 | @param[out] pt Decypted result (a ckks plaintext) 104 | */ 105 | void ckks_decrypt(const ZZ *c0, const ZZ *c1, const ZZ *s, bool small_s, const Parms *parms, 106 | ZZ *pt); 107 | 108 | /** 109 | Pseudo-decrypts a ciphertext in place (for a particular prime component). Currently only works if 110 | small_s is 0. Note that this function will also corrupt the memory pointed to by c1. 111 | 112 | @param[in,out] c0 In: First ciphertext component for this prime; 113 | Out: Decrypted result (a CKKS plaintext) 114 | @param[in] c1 Second ciphertext component for this prime. Will be corrupted 115 | @param[in] s Secret key. Must be in expanded form! 116 | @param[in] small_s If true, secret key is in small form; Else, is in expanded form 117 | @param[in] parms Parameters instance 118 | */ 119 | void ckks_decrypt_inpl(ZZ *c0, ZZ *c1, const ZZ *s, bool small_s, const Parms *parms); 120 | 121 | /** 122 | Checks that the pseudo-decoding and pseudo-decryption of a ciphertext is correct (for a particular 123 | prime ciphertext component). Currently only works if 'small_s' is 0. 124 | 125 | Correctness: 'small_s' must be true (and 's' must be in small form) 126 | 127 | Note: index_map is non-const in case SE_INDEX_MAP_LOAD is defined (or, if 128 | SE_INDEX_MAP_LOAD_PERSIST_SYM_LOAD_ASYM is defined and asymmetric encryption is used). 129 | 130 | Size req: 'temp' must contain space for n double complex values 131 | If index map needs to be loaded (see 'Note' above), index_map must constain space for n uint16_t 132 | elements. 133 | 134 | @param[in] c0 In: 1st component of ciphertext to check; 135 | Out: Decrypted and decoded message 136 | @param[in] c1 2nd component of ciphertext to check. Will be corrupted! 137 | @param[in] values Cleartext input message 138 | @param[in] values_len True number of entries in initial values message. Must be <= n/2 139 | @param[in] s Secret key. Must be in expanded form! 140 | @param[in] small_s If true, secret key is in small form; Else, is in expanded form 141 | @param[in] pte_calc Plaintext + error (in NTT form) (output by ckks_encode for testing) 142 | @param[in] index_map [Optional]. If passed in, can avoid 1 flash read 143 | @param[in] parms Parameters instance 144 | @param temp Scratch space 145 | */ 146 | void check_decode_decrypt_inpl(ZZ *c0, ZZ *c1, const flpt *values, size_t values_len, const ZZ *s, 147 | bool small_s, const ZZ *pte_calc, uint16_t *index_map, 148 | const Parms *parms, ZZ *temp); 149 | -------------------------------------------------------------------------------- /device/test/ckks_tests_encode.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file ckks_tests_encode.c 6 | */ 7 | 8 | #include // pow 9 | #include 10 | #include 11 | 12 | #include "ckks_common.h" 13 | #include "ckks_sym.h" 14 | #include "ckks_tests_common.h" 15 | #include "defines.h" 16 | #include "fft.h" 17 | #include "fileops.h" 18 | #include "ntt.h" 19 | #include "polymodarith.h" 20 | #include "polymodmult.h" 21 | #include "sample.h" 22 | #include "test_common.h" 23 | #include "util_print.h" 24 | 25 | /** 26 | Test CKKS encoding 27 | 28 | @param[in] n Polynomial ring degree (ignored if SE_USE_MALLOC is defined) 29 | */ 30 | void test_ckks_encode(size_t n) 31 | { 32 | #ifndef SE_USE_MALLOC 33 | se_assert(n == SE_DEGREE_N); // sanity check 34 | if (n != SE_DEGREE_N) n = SE_DEGREE_N; 35 | #endif 36 | 37 | Parms parms; 38 | #ifdef SE_USE_MALLOC 39 | print_ckks_mempool_size(n, 1); 40 | ZZ *mempool = ckks_mempool_setup_sym(n); 41 | #else 42 | print_ckks_mempool_size(); 43 | ZZ mempool_local[MEMPOOL_SIZE]; 44 | memset(&(mempool_local), 0, MEMPOOL_SIZE * sizeof(ZZ)); 45 | ZZ *mempool = &(mempool_local[0]); 46 | #endif 47 | // TODO: Make a malloc function to include test memory 48 | 49 | // -- Get pointers 50 | SE_PTRS se_ptrs_local; 51 | ckks_set_ptrs_sym(n, mempool, &se_ptrs_local); 52 | double complex *conj_vals = se_ptrs_local.conj_vals; 53 | int64_t *conj_vals_int = se_ptrs_local.conj_vals_int_ptr; 54 | double complex *ifft_roots = se_ptrs_local.ifft_roots; 55 | uint16_t *index_map = se_ptrs_local.index_map_ptr; 56 | // -- Note that, since we are not adding the error, the pt will not be in NTT form. 57 | ZZ *pt = se_ptrs_local.ntt_pte_ptr; 58 | flpt *v = se_ptrs_local.values; 59 | size_t vlen = n / 2; 60 | 61 | // -- Additional pointers required for testing. 62 | #ifdef SE_USE_MALLOC 63 | ZZ *temp = calloc(n, sizeof(double complex)); 64 | #else 65 | ZZ temp[SE_DEGREE_N * sizeof(double complex) / sizeof(ZZ)]; 66 | memset(&temp, 0, SE_DEGREE_N * sizeof(double complex)); 67 | #endif 68 | 69 | // -- Set up parameters and index_map if applicable 70 | ckks_setup(n, 1, index_map, &parms); 71 | print_test_banner("Encode", &parms); 72 | 73 | for (size_t testnum = 0; testnum < 9; testnum++) 74 | { 75 | printf("-------------------- Test %zu -----------------------\n", testnum); 76 | const Modulus *mod = parms.curr_modulus; 77 | print_zz("\n ***** Modulus", mod->value); 78 | 79 | // -- Get test values 80 | set_encode_encrypt_test(testnum, vlen, v); 81 | print_poly_flpt("v ", v, vlen); 82 | 83 | // -- Begin encode-encrypt sequence 84 | // -- First, encode base. Afer this, we should only use the pointer values 85 | bool ret = ckks_encode_base(&parms, v, vlen, index_map, ifft_roots, conj_vals); 86 | se_assert(ret); 87 | // print_poly_int64_full("conj_vals_int ", conj_vals_int, n); 88 | 89 | // -- Now, need to reduce the plaintext 90 | reduce_set_pte(&parms, conj_vals_int, pt); 91 | // print_poly_int64_full("conj_vals_int ", conj_vals_int, n); 92 | 93 | // -- Check that decoding works 94 | check_decode_inpl(pt, v, vlen, index_map, &parms, temp); 95 | } 96 | #ifdef SE_USE_MALLOC 97 | // clang-format off 98 | if (mempool) { free(mempool); mempool = 0; } 99 | if (temp) { free(temp); temp = 0; } 100 | // clang-format on 101 | #endif 102 | delete_parameters(&parms); 103 | } 104 | -------------------------------------------------------------------------------- /device/test/main.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file main.c 6 | 7 | Note: While the tests can run back-to-back, on device it is best to run only one test at a time 8 | (i.e., uncomment the test you want to run and uncomment all others before compiling.) 9 | Note: Not all the tests may run on the devices since tests may consume much more memory than regular 10 | API usage. 11 | */ 12 | 13 | #include "defines.h" 14 | 15 | #ifndef SE_DISABLE_TESTING_CAPABILITY 16 | #include "util_print.h" 17 | 18 | extern void test_add_uint(void); 19 | extern void test_mult_uint(void); 20 | extern void test_add_mod(void); 21 | extern void test_neg_mod(void); 22 | extern void test_mul_mod(void); 23 | extern void test_sample_poly_uniform(size_t n); 24 | extern void test_sample_poly_ternary(size_t n); 25 | extern void test_sample_poly_ternary_small(size_t n); 26 | extern void test_barrett_reduce(void); 27 | extern void test_barrett_reduce_wide(void); 28 | extern void test_poly_mult_ntt(size_t n, size_t nprimes); 29 | extern void test_fft(size_t n); 30 | extern void test_enc_zero_sym(size_t n, size_t nprimes); 31 | extern void test_enc_zero_asym(size_t n, size_t nprimes); 32 | extern void test_ckks_encode(size_t n); 33 | extern void test_ckks_encode_encrypt_sym(size_t n, size_t nprimes); 34 | extern void test_ckks_encode_encrypt_asym(size_t n, size_t nprimes); 35 | extern void test_ckks_api_sym(void); 36 | extern void test_ckks_api_asym(void); 37 | 38 | #ifdef SE_ON_SPHERE_M4 39 | #include "mt3620.h" 40 | #include "os_hal_gpt.h" 41 | #include "os_hal_uart.h" 42 | 43 | static const uint8_t uart_port_num = OS_HAL_UART_PORT0; 44 | // static const uint8_t uart_port_num = OS_HAL_UART_ISU0; 45 | 46 | /** 47 | Hook for "printf" 48 | @param[in] character Character to print 49 | */ 50 | // /* 51 | void _putchar(char character) 52 | { 53 | mtk_os_hal_uart_put_char(uart_port_num, character); 54 | if (character == '\n') mtk_os_hal_uart_put_char(uart_port_num, '\r'); 55 | } 56 | // */ 57 | 58 | void RTCoreMain(void) 59 | { 60 | // -- Init Vector Table -- 61 | NVIC_SetupVectorTable(); 62 | 63 | // -- Init UART -- 64 | mtk_os_hal_uart_ctlr_init(uart_port_num); 65 | printf("\nUART Inited (port_num=%d)\n", uart_port_num); 66 | 67 | // -- Init GPT -- 68 | // gpt0_int.gpt_cb_hdl = Gpt0Callback; 69 | // gpt0_int.gpt_cb_data = (void *)gpt_cb_data; 70 | mtk_os_hal_gpt_init(); 71 | #else 72 | 73 | extern int test_network_basic(void); 74 | extern void test_network(void); 75 | 76 | int main(void) 77 | { 78 | #ifdef SE_NRF5_UART_PRINTF_ENABLED 79 | se_setup_uart(); 80 | #endif 81 | #endif 82 | // while(1) 83 | // { 84 | // printf("Beginning tests...\n"); 85 | // } 86 | printf("Beginning tests...\n"); 87 | #ifdef SE_RAND_NRF5 88 | se_randomness_init(); // required for nrf 89 | #endif 90 | 91 | #ifdef SE_USE_MALLOC 92 | // const size_t n = 1024, nprimes = 1; 93 | // const size_t n = 2048, nprimes = 1; 94 | const size_t n = 4096, nprimes = 3; 95 | // const size_t n = 8192, nprimes = 6; 96 | // const size_t n = 16384, nprimes = 13; 97 | #else 98 | const size_t n = SE_DEGREE_N; 99 | const size_t nprimes = SE_NPRIMES; 100 | #endif 101 | 102 | test_sample_poly_uniform(n); 103 | test_sample_poly_ternary(n); 104 | test_sample_poly_ternary_small(n); // Only useful when SE_USE_MALLOC is defined 105 | 106 | test_add_uint(); 107 | test_mult_uint(); 108 | 109 | test_barrett_reduce(); 110 | test_barrett_reduce_wide(); 111 | 112 | test_add_mod(); 113 | test_neg_mod(); 114 | test_mul_mod(); 115 | 116 | // -- Note: This test sometimes takes a while to run 117 | // because it uses schoolbook multiplication 118 | // -- Comment it out unless you need to test it 119 | // test_poly_mult_ntt(n, nprimes); 120 | 121 | test_fft(n); 122 | 123 | test_enc_zero_sym(n, nprimes); 124 | test_enc_zero_asym(n, nprimes); 125 | 126 | test_ckks_encode(n); 127 | 128 | // -- Main tests 129 | test_ckks_encode_encrypt_sym(n, nprimes); 130 | test_ckks_encode_encrypt_asym(n, nprimes); 131 | 132 | // -- Run these tests to verify api 133 | // -- Check the result with the adapter by writing output to a text file 134 | // and passing that to the adapter "verify ciphertexts" functionality 135 | // test_ckks_api_sym(); 136 | // test_ckks_api_asym(); 137 | 138 | // test_network_basic(); 139 | // test_network(); 140 | 141 | printf("...done with all tests. All tests passed.\n"); 142 | exit(0); 143 | } 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /device/test/modulo_tests.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file modulo_tests.c 6 | */ 7 | 8 | #include 9 | 10 | #include "defines.h" 11 | #include "inttypes.h" // PRIu64 12 | #include "modulo.h" 13 | #include "modulus.h" 14 | #include "test_common.h" 15 | #include "util_print.h" 16 | 17 | /** 18 | Helper function to test barret wide reduction. Note that this tests the '%' operator too, which may 19 | not always be desirable. 20 | 21 | @param input 22 | @param modulus 23 | @param res_exp 24 | */ 25 | void test_barrett_reduce_wide_helper(ZZ *input, const Modulus *modulus, ZZ res_exp) 26 | { 27 | ZZ q = modulus->value; 28 | printf("-------------------------------------\n"); 29 | ZZ res = barrett_reduce_wide(input, modulus); 30 | 31 | printf("{ %" PRIuZZ " , %" PRIuZZ "} mod %" PRIuZZ "\n", input[1], input[0], q); 32 | 33 | uint64_t actual_input = (uint64_t)(((uint64_t)input[1] << 32) | ((input[0]) & 0xFFFFFFFF)); 34 | printf("--> input = %" PRIu64 "\n", actual_input); 35 | 36 | // -- If you don't want to test '%', must comment this out 37 | ZZ res_default = (ZZ)(actual_input % q); 38 | print_zz("Result default", res_default); 39 | se_assert(res == res_default); 40 | 41 | print_zz("Result expected", res_exp); 42 | print_zz("Result barrett", res); 43 | se_assert(res == res_exp); 44 | } 45 | 46 | /** 47 | Helper function to test barret reduction. Note that this tests the '%' operator too, which may not 48 | always be desirable. 49 | 50 | @param input 51 | @param modulus 52 | @param res_exp 53 | */ 54 | void test_barrett_reduce_helper(ZZ input, const Modulus *modulus, ZZ res_exp) 55 | { 56 | ZZ q = modulus->value; 57 | printf("-------------------------------------\n"); 58 | ZZ res = barrett_reduce(input, modulus); 59 | 60 | printf("%" PRIuZZ " mod %" PRIuZZ "\n", input, q); 61 | 62 | // -- If you don't want to test '%', comment this out 63 | ZZ res_default = input % q; 64 | print_zz("Result default", res_default); 65 | se_assert(res == res_default); 66 | 67 | print_zz("Result expected", res_exp); 68 | print_zz("Result barrett", res); 69 | se_assert(res == res_exp); 70 | } 71 | 72 | void test_barrett_reduce(void) 73 | { 74 | printf("\n**************************************\n"); 75 | printf("Beginning tests for barrett_reduce...\n\n"); 76 | Modulus modulus; // value = q, const_ratio = floor(2^64, q) 77 | 78 | set_modulus(134012929, &modulus); // 27 bits 79 | 80 | test_barrett_reduce_helper(0, &modulus, 0); 81 | test_barrett_reduce_helper(1, &modulus, 1); 82 | test_barrett_reduce_helper(134012928, &modulus, 134012928); 83 | test_barrett_reduce_helper(134012929, &modulus, 0); 84 | test_barrett_reduce_helper(134012930, &modulus, 1); 85 | test_barrett_reduce_helper((ZZ)(134012929) << 1, &modulus, 0); // 28 bits 86 | test_barrett_reduce_helper((ZZ)(134012929) << 2, &modulus, 0); // 29 bits 87 | test_barrett_reduce_helper(0x36934613, &modulus, 111543821); // random 88 | test_barrett_reduce_helper(MAX_ZZ, &modulus, 6553567); 89 | 90 | set_modulus(1053818881, &modulus); // 30 bits 91 | 92 | test_barrett_reduce_helper(0, &modulus, 0); 93 | test_barrett_reduce_helper(1, &modulus, 1); 94 | test_barrett_reduce_helper(1053818880, &modulus, 1053818880); 95 | test_barrett_reduce_helper(1053818881, &modulus, 0); 96 | test_barrett_reduce_helper(1053818882, &modulus, 1); 97 | test_barrett_reduce_helper((ZZ)(1053818881) << 1, &modulus, 0); // 31 bits 98 | test_barrett_reduce_helper((ZZ)(1053818881) << 2, &modulus, 0); // 32 bits 99 | test_barrett_reduce_helper(0x36934613, &modulus, 915621395); // random 100 | test_barrett_reduce_helper(MAX_ZZ, &modulus, 79691771); 101 | 102 | printf("\n... all tests for barrett_reduce passed.\n"); 103 | printf("**************************************\n"); 104 | } 105 | 106 | void test_barrett_reduce_wide(void) 107 | { 108 | printf("\n***************************************\n"); 109 | printf("Beginning tests for barrett_reduce_wide...\n\n"); 110 | 111 | ZZ input[2]; 112 | Modulus modulus; // value = q, const_ratio = floor(2^64, q) 113 | 114 | set_modulus(134012929, &modulus); // 27 bits 115 | 116 | input[1] = 0; 117 | input[0] = 0; 118 | test_barrett_reduce_wide_helper(input, &modulus, 0); 119 | input[1] = 0; 120 | input[0] = 1; 121 | test_barrett_reduce_wide_helper(input, &modulus, 1); 122 | input[1] = 0; 123 | input[0] = 134012928; 124 | test_barrett_reduce_wide_helper(input, &modulus, 134012928); 125 | input[1] = 0; 126 | input[1] = 0; 127 | input[0] = 134012929; 128 | test_barrett_reduce_wide_helper(input, &modulus, 0); 129 | input[1] = 0; 130 | input[0] = 134012930; 131 | test_barrett_reduce_wide_helper(input, &modulus, 1); 132 | input[1] = 0; 133 | input[0] = 134012929 << 1; // 28 bits 134 | test_barrett_reduce_wide_helper(input, &modulus, 0); 135 | input[1] = 0; 136 | input[0] = 134012929 << 2; // 29 bits 137 | test_barrett_reduce_wide_helper(input, &modulus, 0); 138 | input[1] = 0; 139 | input[0] = MAX_ZZ; 140 | test_barrett_reduce_wide_helper(input, &modulus, 6553567); 141 | input[1] = 0x33345624; // random 142 | input[0] = 0x47193658; // random 143 | test_barrett_reduce_wide_helper(input, &modulus, 77416961); 144 | input[1] = MAX_ZZ; 145 | input[0] = MAX_ZZ; 146 | test_barrett_reduce_wide_helper(input, &modulus, 119980058); 147 | 148 | set_modulus(1053818881, &modulus); // 30 bits 149 | 150 | input[1] = 0; 151 | input[0] = 0; 152 | test_barrett_reduce_wide_helper(input, &modulus, 0); 153 | input[1] = 0; 154 | input[0] = 1; 155 | test_barrett_reduce_wide_helper(input, &modulus, 1); 156 | input[1] = 0; 157 | input[0] = 1053818880; 158 | test_barrett_reduce_wide_helper(input, &modulus, 1053818880); 159 | input[1] = 0; 160 | input[0] = 1053818881; 161 | test_barrett_reduce_wide_helper(input, &modulus, 0); 162 | input[1] = 0; 163 | input[0] = 1053818882; 164 | test_barrett_reduce_wide_helper(input, &modulus, 1); 165 | input[1] = 0; 166 | input[0] = (ZZ)(1053818881) << 1; // 31 bits 167 | test_barrett_reduce_wide_helper(input, &modulus, 0); 168 | input[1] = 0; 169 | input[0] = (ZZ)(1053818881) << 2; // 32 bits 170 | test_barrett_reduce_wide_helper(input, &modulus, 0); 171 | input[1] = 0; 172 | input[0] = MAX_ZZ; 173 | test_barrett_reduce_wide_helper(input, &modulus, 79691771); 174 | input[1] = 0x33345624; // random 175 | input[0] = 0x47193658; // random 176 | test_barrett_reduce_wide_helper(input, &modulus, 569939669); 177 | input[1] = MAX_ZZ; 178 | input[0] = MAX_ZZ; 179 | test_barrett_reduce_wide_helper(input, &modulus, 159648581); 180 | } 181 | -------------------------------------------------------------------------------- /device/test/network_tests.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file network_tests.c 6 | 7 | Adapted from Sphere example 8 | */ 9 | 10 | #include "defines.h" 11 | #ifdef SE_ON_SPHERE_A7 12 | #ifdef SE_USE_MALLOC 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include // strerror 19 | 20 | #include "network.h" 21 | #include "util_print.h" 22 | 23 | void test_network_basic(void) 24 | { 25 | CURL *curl = NULL; 26 | CURLcode res = CURLE_OK; 27 | 28 | // First, check if we are connected to the internet 29 | if (!is_network_connected()) return; 30 | 31 | res = curl_global_init(CURL_GLOBAL_ALL); 32 | if (is_curl_error(&res, "init")) return; 33 | 34 | curl = curl_easy_init(); 35 | if (is_curl_error(curl, "init")) { goto cleanup; } 36 | 37 | // Specify URL to download. Important: any change 38 | // in the domain name must be reflected in the 39 | // AllowedConnections capability in app_manifest.json. 40 | res = curl_easy_setopt(curl, CURLOPT_URL, url); 41 | if (is_curl_error(&res, "url")) { goto cleanup; } 42 | 43 | res = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 44 | if (is_curl_error(&res, "verbose")) { goto cleanup; } 45 | 46 | // Let cURL follow any HTTP 3xx redirects.Important: 47 | // any redirection to different domain names requires 48 | // that domain name to be added to app_manifest.json. 49 | res = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); 50 | if (is_curl_error(&res, "follow")) { goto cleanup; } 51 | 52 | res = curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); 53 | if (is_curl_error(&res, "user agent")) { goto cleanup; } 54 | 55 | // 56 | // First, try a GET 57 | // 58 | res = curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); 59 | if (is_curl_error(&res, "httpget")) { goto cleanup; } 60 | 61 | res = curl_easy_perform(curl); 62 | if (is_curl_error(&res, "get")) { goto cleanup; } 63 | 64 | // 65 | // Then, try a POST 66 | // 67 | const size_t num_data_bytes = 1 * sizeof(ZZ); 68 | ZZ *data = malloc(num_data_bytes); 69 | data[0] = 5; 70 | 71 | struct curl_slist *headers = NULL; 72 | headers = curl_slist_append(headers, "Content-Type: vector"); 73 | 74 | res = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); 75 | if (is_curl_error(&res, "postfields")) { goto cleanup2; } 76 | 77 | res = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, num_data_bytes); 78 | if (is_curl_error(&res, "postfieldsize")) { goto cleanup2; } 79 | 80 | res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 81 | if (is_curl_error(&res, "headers")) { goto cleanup2; } 82 | 83 | res = curl_easy_perform(curl); 84 | if (is_curl_error(&res, "post")) { goto cleanup2; } 85 | 86 | cleanup2: 87 | if (data) 88 | { 89 | free(data); 90 | data = 0; 91 | } 92 | curl_slist_free_all(curl); 93 | 94 | cleanup: 95 | if (curl) curl_easy_cleanup(curl); 96 | curl_global_cleanup(); 97 | } 98 | 99 | void test_network(size_t len) 100 | { 101 | const size_t num_data_bytes = len * sizeof(ZZ); 102 | ZZ *data = malloc(num_data_bytes); 103 | 104 | for (size_t i = 0; i < len; i++) data[i] = (ZZ)i; 105 | send_over_network(data, num_data_bytes); 106 | if (data) 107 | { 108 | free(data); 109 | data = 0; 110 | } 111 | } 112 | #endif 113 | #endif 114 | -------------------------------------------------------------------------------- /device/test/uintmodarith_tests.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file uintmodarith_tests.c 6 | */ 7 | 8 | #include "defines.h" 9 | #include "modulo.h" 10 | #include "modulus.h" 11 | #include "test_common.h" 12 | #include "uintmodarith.h" 13 | #include "util_print.h" 14 | 15 | // -- Note: This uses % to check 16 | void test_add_mod_helper(ZZ val1, ZZ val2, Modulus *modulus, ZZ res_exp) 17 | { 18 | // -- Recall correctness requirement: val1 + val2 < 2q-1 19 | se_assert(modulus && modulus->value); 20 | ZZ q = modulus->value; 21 | printf("---------------------------------\n"); 22 | for (int i = 0; i < 2; i++) 23 | { 24 | printf("( %" PRIuZZ " + %" PRIuZZ " ) %% %" PRIuZZ "\n", val1, val2, q); 25 | se_assert((val1 + val2) < (((modulus->value) * 2) - 1)); 26 | ZZ res = add_mod(val1, val2, modulus); 27 | ZZ res_default = (val1 + val2) % q; 28 | 29 | print_zz("Result ", res); 30 | print_zz("Result expected", res_exp); 31 | print_zz("Result default ", res_default); 32 | 33 | se_assert(res == res_exp); 34 | se_assert(res == res_default); 35 | 36 | // -- Swap val1 and val2 and try again 37 | ZZ temp = val1; 38 | val1 = val2; 39 | val2 = temp; 40 | printf("(After swap)\n"); 41 | } 42 | } 43 | 44 | // -- Note: This uses % to check 45 | void test_mul_mod_helper(ZZ val1, ZZ val2, Modulus *modulus, ZZ res_exp) 46 | { 47 | ZZ q = modulus->value; 48 | printf("---------------------------------\n"); 49 | for (int i = 0; i < 2; i++) 50 | { 51 | printf("( %" PRIuZZ " * %" PRIuZZ " ) %% %" PRIuZZ "\n", val1, val2, q); 52 | ZZ res = mul_mod(val1, val2, modulus); 53 | 54 | print_zz("Result ", res); 55 | print_zz("Result expected", res_exp); 56 | se_assert(res == res_exp); 57 | 58 | if (val1 < 0xFFFF && val2 < 0xFFFF) 59 | { 60 | ZZ res_default = (val1 * val2) % q; 61 | print_zz("Result default ", res_default); 62 | se_assert(res == res_default); 63 | } 64 | 65 | // -- Swap val1 and val2 and try again 66 | ZZ temp = val1; 67 | val1 = val2; 68 | val2 = temp; 69 | printf("(After swap)\n"); 70 | } 71 | } 72 | 73 | void test_neg_mod_helper(ZZ input, const Modulus *modulus, ZZ res_exp) 74 | { 75 | ZZ q = modulus->value; 76 | printf("---------------------------------\n"); 77 | printf("( -%" PRIuZZ ") %% %" PRIuZZ "\n", input, q); 78 | se_assert(input <= q); 79 | 80 | // -- Recall correctness requirement: input must be < q 81 | ZZ res = neg_mod(input, modulus); 82 | print_zz("Result ", res); 83 | print_zz("Result expected", res_exp); 84 | 85 | // -- Don't use the remainder operator, it does not work well for modular negation 86 | // -- Check the slow way 87 | ZZ temp = input; 88 | while (temp > q) temp -= q; 89 | size_t res_basic = (input == 0) ? 0 : q - temp; 90 | print_zz("Result basic ", res_basic); 91 | 92 | se_assert(res == res_exp); 93 | se_assert(res == res_basic); 94 | } 95 | 96 | void test_add_mod_basic(Modulus *modulus) 97 | { 98 | // -- Recall correctness requirement: val1 + val2 < 2q-1 99 | ZZ q = modulus->value; 100 | 101 | test_add_mod_helper(0, 0, modulus, 0); // 0+0 = 0 (mod q) 102 | test_add_mod_helper(0, 1, modulus, 1); // 0+1 = 1 (mod q) 103 | test_add_mod_helper(0, q, modulus, 0); // 0+q = 0 (mod q) 104 | test_add_mod_helper(1, q, modulus, 1); // 1+q = 1 (mod q) 105 | 106 | test_add_mod_helper(1, q - 1, modulus, 0); // 1+q-1 = 0 (mod q) 107 | test_add_mod_helper(q, q - 2, modulus, q - 2); // q+q-2 = q-2 (mod q) 108 | 109 | test_add_mod_helper(q - 1, q - 1, modulus, q - 2); // q-1+q-1 = q-2 (mod q) 110 | test_add_mod_helper(0, 2 * q - 2, modulus, q - 2); // 0+2q-2 = q-2 (mod q) 111 | } 112 | 113 | void test_mul_mod_basic(Modulus *modulus) 114 | { 115 | ZZ q = modulus->value; 116 | test_mul_mod_helper(0, 0, modulus, 0); // 0*0 % q = 0 117 | test_mul_mod_helper(1, 1, modulus, 1); // 1*1 % q = 1 118 | 119 | test_mul_mod_helper(1, q, modulus, 0); // 1*q % q = 0 120 | test_mul_mod_helper(q + 1, 1, modulus, 1); // (q + 1)*1 % q = 1 121 | test_mul_mod_helper(q - 1, 1, modulus, q - 1); // (q - 1)*1 % q = q - 1 122 | test_mul_mod_helper(0, 12345, modulus, 0); // 0*x % q = 0 123 | 124 | // -- Can't really calculate expected for these... 125 | test_mul_mod_helper(1, MAX_ZZ, modulus, 126 | MAX_ZZ % q); // 1*MAX64 % q = MAX64 % q 127 | test_mul_mod_helper(1, 12345, modulus, 12345 % q); // 1*x % q = x % q 128 | } 129 | 130 | void test_neg_mod_basic(Modulus *modulus) 131 | { 132 | ZZ q = modulus->value; 133 | test_neg_mod_helper(0, modulus, 0); // -0 % q = 0 134 | test_neg_mod_helper(1, modulus, q - 1); // -1 % q = q-1 135 | test_neg_mod_helper(q - 1, modulus, 1); // -(q-1) % q = 1 136 | test_neg_mod_helper(q, modulus, 0); // -q % q = 0 137 | } 138 | 139 | void test_add_mod(void) 140 | { 141 | printf("\n*******************************************\n"); 142 | printf("Beginning tests for add_mod...\n\n"); 143 | Modulus modulus; 144 | 145 | set_modulus(134012929, &modulus); // 27 bit 146 | test_add_mod_basic(&modulus); 147 | test_add_mod_helper(134012929 - 10, 134012929, &modulus, 134012929 - 10); 148 | test_add_mod_helper(134012929 + 10, 134012929 - 12, &modulus, 134012929 - 2); 149 | 150 | set_modulus(1053818881, &modulus); // 30 bit 151 | test_add_mod_basic(&modulus); 152 | test_add_mod_helper(1053818881 - 10, 1053818881, &modulus, 1053818881 - 10); 153 | test_add_mod_helper(1053818881 + 10, 1053818881 - 12, &modulus, 1053818881 - 2); 154 | 155 | printf("\n...all tests for add_mod passed.\n"); 156 | printf("*******************************************\n"); 157 | } 158 | 159 | void test_neg_mod(void) 160 | { 161 | printf("\n*******************************************\n"); 162 | printf("Beginning tests for neg_mod...\n\n"); 163 | Modulus modulus; 164 | 165 | set_modulus(134012929, &modulus); // 27 bit 166 | test_neg_mod_basic(&modulus); 167 | test_neg_mod_helper(10, &modulus, 134012929 - 10); 168 | test_neg_mod_helper(134012929 - 10, &modulus, 10); 169 | 170 | set_modulus(1053818881, &modulus); // 30 bit 171 | test_neg_mod_basic(&modulus); 172 | test_neg_mod_helper(10, &modulus, 1053818881 - 10); 173 | test_neg_mod_helper(1053818881 - 10, &modulus, 10); 174 | 175 | printf("\n...all tests for neg_mod passed.\n"); 176 | printf("*******************************************\n"); 177 | } 178 | 179 | void test_mul_mod(void) 180 | { 181 | printf("\n*******************************************\n"); 182 | printf("Beginning tests for mul_mod...\n\n"); 183 | Modulus modulus; 184 | 185 | set_modulus(134012929, &modulus); // 27 bit 186 | test_mul_mod_basic(&modulus); 187 | test_mul_mod_helper(0x38573475, 0x83748563, &modulus, 4025350); // random 188 | 189 | set_modulus(1053818881, &modulus); // 30 bit 190 | test_mul_mod_basic(&modulus); 191 | test_mul_mod_helper(0x38573475, 0x83748563, &modulus, 65334256); // random 192 | 193 | printf("\n...all tests for mul_mod passed.\n"); 194 | printf("*******************************************\n"); 195 | } 196 | 197 | // TODO: Add this test 198 | // void test_mod_mumo_helper(); 199 | -------------------------------------------------------------------------------- /device/test/uintops_tests.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | /** 5 | @file uintops_tests.c 6 | */ 7 | 8 | #include 9 | #include // memset 10 | 11 | #include "defines.h" 12 | #include "test_common.h" 13 | #include "uint_arith.h" 14 | #include "uintops.h" 15 | #include "util_print.h" 16 | 17 | void test_add_uint_helper(ZZ val1, ZZ val2, ZZ sum_exp, uint8_t carry_exp) 18 | { 19 | for (int i = 0; i < 2; i++) 20 | { 21 | ZZ sum; 22 | uint8_t carry = add_uint(val1, val2, &sum); 23 | se_assert(carry == carry_exp); 24 | se_assert(sum == sum_exp); 25 | 26 | if (i == 0) 27 | { 28 | // -- Swap val1 and val2 and try again 29 | ZZ temp = val1; 30 | val1 = val2; 31 | val2 = temp; 32 | } 33 | } 34 | } 35 | 36 | void test_add_uint(void) 37 | { 38 | printf("\n**********************************\n"); 39 | printf("\nBeginnning tests for add_uint...\n\n"); 40 | ZZ val1, val2, sum_exp; 41 | uint8_t c_exp; 42 | 43 | test_add_uint_helper(0, 0, 0, 0); 44 | test_add_uint_helper(1, 1, 2, 0); 45 | test_add_uint_helper(MAX_ZZ, 0, MAX_ZZ, 0); 46 | test_add_uint_helper(MAX_ZZ, 1, 0, 1); 47 | test_add_uint_helper(MAX_ZZ, MAX_ZZ, MAX_ZZ - 1, 1); 48 | test_add_uint_helper(MAX_ZZ - 1, 1, MAX_ZZ, 0); 49 | test_add_uint_helper(MAX_ZZ - 1, 2, 0, 1); 50 | 51 | ZZ val = random_zz(); 52 | test_add_uint_helper(val, 0, val, 0); 53 | 54 | // -- Test that regular addition still works 55 | for (size_t i = 0; i < 5; i++) 56 | { 57 | printf("\n-------------\n"); 58 | printf("\nTest number: %zu\n\n", i); 59 | switch (i) 60 | { 61 | case 0: // max half * 2 = shift everything by 1 62 | val1 = 0xFFFF; 63 | val2 = 0xFFFF; 64 | sum_exp = val1 << 1; 65 | c_exp = 0; 66 | break; 67 | case 1: 68 | val1 = 0xFFFFF; 69 | val2 = 0xFFFFF; 70 | sum_exp = val1 << 1; 71 | c_exp = 0; 72 | break; 73 | case 2: 74 | val1 = 0x0F00F00F; 75 | val2 = ~val1; 76 | sum_exp = 0xFFFFFFFF; 77 | c_exp = 0; 78 | case 3: 79 | val1 = 0x37281295; 80 | val2 = 0x15720382; 81 | sum_exp = 0x4c9a1617; 82 | c_exp = 0; 83 | case 4: 84 | val1 = 0xd7281295; 85 | val2 = 0xa5720382; 86 | sum_exp = 0x7c9a1617; 87 | c_exp = 1; 88 | } 89 | test_add_uint_helper(val1, val2, sum_exp, c_exp); 90 | } 91 | printf("**********************************\n"); 92 | } 93 | 94 | void test_mult_uint_helper(ZZ val1, ZZ val2, ZZ *result_exp) 95 | { 96 | ZZ result[2]; 97 | for (int i = 0; i < 2; i++) 98 | { 99 | mul_uint_wide(val1, val2, result); 100 | se_assert(result[0] == result_exp[0]); 101 | se_assert(result[1] == result_exp[1]); 102 | 103 | if (i == 0) 104 | { 105 | // -- Swap inputs and try again 106 | memset(&result, 0, sizeof(result)); 107 | ZZ temp = val1; 108 | val1 = val2; 109 | val2 = temp; 110 | } 111 | } 112 | } 113 | 114 | void test_mult_uint(void) 115 | { 116 | printf("\n************************************\n"); 117 | printf("\nBeginnning tests for mult_uint...\n\n"); 118 | ZZ val1, val2; 119 | ZZ result_exp[2]; 120 | 121 | memset(result_exp, 0, sizeof(result_exp)); 122 | test_mult_uint_helper(0, 0, result_exp); 123 | 124 | memset(result_exp, 0, sizeof(result_exp)); 125 | test_mult_uint_helper(1, 0, result_exp); 126 | 127 | for (size_t i = 0; i < 3; i++) 128 | { 129 | printf("\n-------------\n"); 130 | printf("\nTest number: %zu\n\n", i); 131 | switch (i) 132 | { 133 | case 0: 134 | val1 = 0x10000; 135 | val2 = 0x0FABA; 136 | result_exp[1] = 0; 137 | result_exp[0] = 0xFABA0000; 138 | break; 139 | case 1: 140 | val1 = 0x100000; 141 | val2 = 0x00FABA; 142 | result_exp[1] = 0xF; 143 | result_exp[0] = 0xABA00000; 144 | break; 145 | 146 | case 2: 147 | val1 = 11223344; 148 | val2 = 55667788; 149 | result_exp[1] = 0x2383b; 150 | result_exp[0] = 0xa2879a40; 151 | break; 152 | } 153 | test_mult_uint_helper(val1, val2, result_exp); 154 | } 155 | printf("************************************\n"); 156 | } 157 | -------------------------------------------------------------------------------- /pipelines/device_docker.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | batch: true 3 | branches: 4 | include: 5 | - main 6 | paths: 7 | exclude: 8 | - 'tools/*' 9 | - CODE_OF_CONDUCT.md 10 | - CONTRIBUTING.md 11 | - ISSUES.md 12 | - LICENSE 13 | - NOTICE 14 | - README.md 15 | - SECURITY.md 16 | 17 | stages: 18 | - stage: adapter 19 | displayName: 'adapter' 20 | jobs: 21 | - job: build 22 | displayName: 'Build SEAL-Embedded test image' 23 | pool: 24 | vmImage: 'ubuntu-latest' 25 | steps: 26 | - task: CMake@1 27 | displayName: 'CMake SEAL-Embedded Adapter' 28 | inputs: 29 | workingDirectory: '$(Build.SourcesDirectory)' 30 | cmakeArgs: '-DCMAKE_BUILD_TYPE=Release adapter' 31 | - script: | 32 | cd $BUILD_SOURCESDIRECTORY 33 | make 34 | displayName: 'Build SEAL-Embedded Adapter' 35 | - script: | 36 | cd $BUILD_SOURCESDIRECTORY 37 | ./bin/se_adapter <<< 1 38 | displayName: 'Run SEAL-Embedded Adapter' 39 | - bash: docker build --target build -t hlbuildimage -f .devcontainer/Dockerfile . && docker run --name hlbuildcontainer hlbuildimage && docker cp hlbuildcontainer:/out $(Build.ArtifactStagingDirectory)/HLOutput 40 | displayName: Build SEAL-Embedded image 41 | -------------------------------------------------------------------------------- /pipelines/device_local.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | batch: true 3 | branches: 4 | include: 5 | - main 6 | paths: 7 | exclude: 8 | - 'tools/*' 9 | - CODE_OF_CONDUCT.md 10 | - CONTRIBUTING.md 11 | - ISSUES.md 12 | - LICENSE 13 | - NOTICE 14 | - README.md 15 | - SECURITY.md 16 | 17 | stages: 18 | - stage: adapter 19 | displayName: 'adapter' 20 | jobs: 21 | - job: build 22 | displayName: 'Build SEAL-Embedded test image' 23 | pool: 24 | vmImage: 'windows-latest' 25 | steps: 26 | - task: CMake@1 27 | displayName: 'CMake SEAL-Embedded Adapter' 28 | inputs: 29 | workingDirectory: '$(Build.SourcesDirectory)/build-adapter' 30 | cmakeArgs: '-DCMAKE_BUILD_TYPE=Release ../adapter' 31 | - task: MSBuild@1 32 | displayName: 'Build SEAL-Embedded Adapter' 33 | inputs: 34 | solution: '$(Build.SourcesDirectory)/build-adapter/seal_embedded_adapter.sln' 35 | msbuildArchitecture: 'x64' 36 | platform: 'x64' 37 | configuration: 'Release' 38 | - task: CmdLine@2 39 | displayName: 'Run SEAL-Embedded Adapter' 40 | inputs: 41 | script: | 42 | echo 1 >> test.txt 43 | $(Build.SourcesDirectory)/build-adapter/bin/Release/se_adapter.exe < test.txt 44 | # - task: CMake@1 45 | # displayName: 'CMake SEAL-Embedded' 46 | # inputs: 47 | # workingDirectory: '$(Build.SourcesDirectory)/build-device' 48 | # cmakeArgs: '-DCMAKE_BUILD_TYPE=Release -DSE_BUILD_LOCAL=ON -DSE_BUILD_M4=OFF -DSE_M4_IS_SPHERE=OFF -DSE_BUILD_TYPE="Tests" ../device' 49 | # - task: MSBuild@1 50 | # displayName: 'Build SEAL-Embedded' 51 | # inputs: 52 | # solution: '$(Build.SourcesDirectory)/build-device/seal_embedded.sln' 53 | # msbuildArchitecture: 'x64' 54 | # platform: 'x64' 55 | # configuration: 'Release' 56 | - task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@2 57 | displayName: 'Run CredScan' 58 | inputs: 59 | toolMajorVersion: 'V2' 60 | outputFormat: sarif 61 | debugMode: false 62 | - task: securedevelopmentteam.vss-secure-development-tools.build-task-roslynanalyzers.RoslynAnalyzers@2 63 | displayName: 'Run Roslyn Analyzers' 64 | - task: Semmle@0 65 | env: 66 | SYSTEM_ACCESSTOKEN: $(System.AccessToken) 67 | inputs: 68 | sourceCodeDirectory: '$(Build.SourcesDirectory)' 69 | language: 'cpp' 70 | includeNodeModules: true 71 | querySuite: 'Recommended' 72 | timeout: '1800' 73 | ram: '16384' 74 | addProjectDirToScanningExclusionList: true 75 | buildCommands: '"%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsMSBuildCmd.bat" && msbuild $(Build.SourcesDirectory)/build-adapter/seal_embedded_adapter.sln' 76 | cleanupBuildCommands: '"%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsMSBuildCmd.bat" && msbuild $(Build.SourcesDirectory)/build-adapter/seal_embedded_adapter.sln /t:Clean' 77 | - task: ComponentGovernanceComponentDetection@0 78 | inputs: 79 | scanType: 'Register' 80 | verbosity: 'Verbose' 81 | alertWarningLevel: 'High' 82 | - task: PublishSecurityAnalysisLogs@2 83 | inputs: 84 | ArtifactName: 'CodeAnalysisLogs' 85 | ArtifactType: 'Container' 86 | AllTools: true 87 | ToolLogsNotFoundAction: 'Standard' 88 | -------------------------------------------------------------------------------- /tools/scripts/clang-format-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) Microsoft Corporation. All rights reserved. 4 | # Licensed under the MIT license. 5 | 6 | BASE_DIR=$(dirname "$0") 7 | SE_ROOT_DIR=$BASE_DIR/../../ 8 | shopt -s globstar 9 | clang-format -i $SE_ROOT_DIR/device/**/*.h 10 | clang-format -i $SE_ROOT_DIR/device/**/*.c 11 | clang-format -i $SE_ROOT_DIR/adapter/**/*.h 12 | clang-format -i $SE_ROOT_DIR/adapter/**/*.cpp 13 | clang-format -i $SE_ROOT_DIR/example/**/*.h 14 | clang-format -i $SE_ROOT_DIR/example/**/*.cpp 15 | --------------------------------------------------------------------------------