Stabilize Conan build and remove stale TLS code
Simplifies the active Windows build path around Boost.Beast/OpenSSL, fixes VS2017/clang-cl compatibility, and removes unused BearSSL/WinHTTP remnants so the project builds and tests cleanly. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -29,3 +29,4 @@ tools/.venv/
|
||||
*.user
|
||||
config.toml
|
||||
*.local.toml
|
||||
build-script.log
|
||||
|
||||
@@ -2,11 +2,15 @@ cmake_minimum_required(VERSION 3.21)
|
||||
project(dstalk VERSION 0.1.0 LANGUAGES C CXX)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
if(MSVC_VERSION LESS 1920)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
endif()
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
option(DSTALK_BUILD_GUI "Build the SDL3 GUI frontend" ON)
|
||||
option(DSTALK_BUILD_GUI "Build the SDL3 GUI frontend" OFF)
|
||||
option(DSTALK_BUILD_TESTS "Build dstalk tests" ON)
|
||||
|
||||
add_subdirectory(dstalk-core)
|
||||
|
||||
@@ -29,7 +29,7 @@ dstalk 是一款 AI 编程助手命令行工具。通过调用 DeepSeek V4 大
|
||||
│ 核心层 (dstalk-core.dll) │
|
||||
│ ┌────────────┐ ┌────────────┐ ┌──────────────────────┐ │
|
||||
│ │ 网络通讯 │ │ 文件读写 │ │ AI 接口适配 │ │
|
||||
│ │ Boost.Asio │ │ C++ 标准库 │ │ DeepSeek / OpenAI │ │
|
||||
│ │ Boost.Beast│ │ C++ 标准库 │ │ DeepSeek / OpenAI │ │
|
||||
│ │ + OpenSSL │ │ │ │ / Anthropic │ │
|
||||
│ └────────────┘ └────────────┘ └──────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
@@ -98,7 +98,7 @@ build.bat # 一键: Conan拉依赖 → CMake配置 → Ninja编译
|
||||
|
||||
```bash
|
||||
build/dstalk-cli/dstalk-cli.exe # 命令行模式
|
||||
build/dstalk-gui/dstalk-gui.exe # 图形模式(默认启用,可用 -DDSTALK_BUILD_GUI=OFF 关闭)
|
||||
# 图形模式默认关闭;需要 SDL3 时用 -DDSTALK_BUILD_GUI=ON 重新配置
|
||||
```
|
||||
|
||||
---
|
||||
@@ -300,8 +300,8 @@ model = "deepseek-v4"
|
||||
| 风险 | 对策 |
|
||||
|------|------|
|
||||
| C++ 开发效率低于脚本语言 | Boost 库弥补;核心 API 稳定后开发速度不会慢于竞品 |
|
||||
| OpenSSL 跨版本兼容性 | Conan2 锁定版本,消除环境差异 |
|
||||
| SDL3 仍在迭代 | 锁定具体版本 (3.2.14),升级前充分测试 |
|
||||
| OpenSSL 跨平台兼容性 | Conan2 锁定版本,统一 Windows/Linux/macOS HTTPS 后端 |
|
||||
| SDL3 依赖体积较大 | GUI 默认关闭,需要图形前端时再启用 `DSTALK_BUILD_GUI` |
|
||||
| AI API 协议变更 | 适配层独立模块,变更时只改一处 |
|
||||
|
||||
---
|
||||
|
||||
98
build.bat
98
build.bat
@@ -3,47 +3,71 @@ chcp 65001 >nul
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
set "ROOT=%~dp0"
|
||||
set "TOOLS=%ROOT%tools\"
|
||||
if "%ROOT:~-1%"=="\" set "ROOT=%ROOT:~0,-1%"
|
||||
set "TOOLS=%ROOT%\tools\"
|
||||
set "CMAKE_EXE=%TOOLS%cmake\bin\cmake.exe"
|
||||
set "NINJA_EXE=%TOOLS%ninja\ninja.exe"
|
||||
set "CLANG_EXE=%TOOLS%llvm\bin\clang-cl.exe"
|
||||
set "CLANGXX_EXE=%TOOLS%llvm\bin\clang-cl.exe"
|
||||
set "CONAN_EXE=%TOOLS%.venv\Scripts\conan.exe"
|
||||
|
||||
:: ============================================================
|
||||
:: 1. 检查 tools\ 工具链
|
||||
:: 1. 检查工具链,优先使用 tools\,缺失时回退到 PATH
|
||||
:: ============================================================
|
||||
echo [dstalk] 检查工具链...
|
||||
|
||||
if not exist "%TOOLS%cmake\bin\cmake.exe" (
|
||||
echo [ERROR] CMake 未找到,请先运行: tools\setup.bat
|
||||
if not exist "%CMAKE_EXE%" set "CMAKE_EXE=cmake"
|
||||
if not exist "%NINJA_EXE%" set "NINJA_EXE=ninja"
|
||||
if not exist "%CLANG_EXE%" (
|
||||
set "CLANG_EXE=clang-cl.exe"
|
||||
set "CLANGXX_EXE=clang-cl.exe"
|
||||
)
|
||||
if not exist "%CONAN_EXE%" set "CONAN_EXE=conan"
|
||||
|
||||
"%CMAKE_EXE%" --version >nul 2>&1 || (
|
||||
echo [ERROR] CMake 未找到,请先运行 tools\setup.bat 或加入 PATH
|
||||
pause & exit /b 1
|
||||
)
|
||||
if not exist "%TOOLS%ninja\ninja.exe" (
|
||||
echo [ERROR] Ninja 未找到,请先运行: tools\setup.bat
|
||||
"%NINJA_EXE%" --version >nul 2>&1 || (
|
||||
echo [ERROR] Ninja 未找到,请先运行 tools\setup.bat 或加入 PATH
|
||||
pause & exit /b 1
|
||||
)
|
||||
if not exist "%TOOLS%llvm\bin\clang.exe" (
|
||||
echo [ERROR] LLVM/Clang 未找到,请先运行: tools\setup.bat
|
||||
"%CLANG_EXE%" --version >nul 2>&1 || (
|
||||
echo [ERROR] LLVM/Clang 未找到,请先运行 tools\setup.bat 或加入 PATH
|
||||
pause & exit /b 1
|
||||
)
|
||||
if not exist "%TOOLS%.venv\Scripts\conan.exe" (
|
||||
echo [ERROR] Conan2 未找到,请先运行: tools\setup.bat
|
||||
for /f "tokens=1,2,3" %%a in ('"%CLANG_EXE%" --version 2^>nul') do (
|
||||
if "%%a %%b"=="clang version" set "CLANG_VERSION=%%c"
|
||||
)
|
||||
for /f "tokens=1 delims=." %%v in ("!CLANG_VERSION!") do set "CLANG_MAJOR=%%v"
|
||||
if "!CLANG_MAJOR!"=="" (
|
||||
echo [ERROR] 无法检测 Clang 版本
|
||||
pause & exit /b 1
|
||||
)
|
||||
"%CONAN_EXE%" --version >nul 2>&1 || (
|
||||
echo [ERROR] Conan2 未找到,请先运行 tools\setup.bat 或加入 PATH
|
||||
echo 需要已安装 Python 3.10+
|
||||
pause & exit /b 1
|
||||
)
|
||||
|
||||
:: ============================================================
|
||||
:: 2. 加载 tools\ 环境
|
||||
:: ============================================================
|
||||
call "%TOOLS%env.bat"
|
||||
if exist "%TOOLS%env.bat" call "%TOOLS%env.bat"
|
||||
|
||||
:: ============================================================
|
||||
:: 3. 检测并加载 MSVC 环境
|
||||
:: 2. 检测并加载 MSVC 环境
|
||||
:: ============================================================
|
||||
set "VCVARS="
|
||||
set "VS_YEAR="
|
||||
for %%v in (2022 2019 2017) do (
|
||||
if not defined VCVARS (
|
||||
for %%e in (Professional Community Enterprise BuildTools) do (
|
||||
if exist "C:\Program Files (x86)\Microsoft Visual Studio\%%v\%%e\VC\Auxiliary\Build\vcvarsall.bat" (
|
||||
if not defined VCVARS if exist "C:\Program Files (x86)\Microsoft Visual Studio\%%v\%%e\VC\Auxiliary\Build\vcvarsall.bat" (
|
||||
set "VCVARS=C:\Program Files (x86)\Microsoft Visual Studio\%%v\%%e\VC\Auxiliary\Build\vcvarsall.bat"
|
||||
set "VS_YEAR=%%v"
|
||||
)
|
||||
if exist "C:\Program Files\Microsoft Visual Studio\%%v\%%e\VC\Auxiliary\Build\vcvarsall.bat" (
|
||||
if not defined VCVARS if exist "C:\Program Files\Microsoft Visual Studio\%%v\%%e\VC\Auxiliary\Build\vcvarsall.bat" (
|
||||
set "VCVARS=C:\Program Files\Microsoft Visual Studio\%%v\%%e\VC\Auxiliary\Build\vcvarsall.bat"
|
||||
set "VS_YEAR=%%v"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -55,43 +79,59 @@ if "%VCVARS%"=="" (
|
||||
)
|
||||
echo [dstalk] 加载 MSVC 环境...
|
||||
call "%VCVARS%" x64 >nul 2>&1
|
||||
set "MSVC_RUNTIME_VERSION=v143"
|
||||
set "MSVC_CONAN_VERSION=193"
|
||||
set "CONAN_CPPSTD=20"
|
||||
if "!VS_YEAR!"=="2019" (
|
||||
set "MSVC_RUNTIME_VERSION=v142"
|
||||
set "MSVC_CONAN_VERSION=192"
|
||||
)
|
||||
if "!VS_YEAR!"=="2017" (
|
||||
set "MSVC_RUNTIME_VERSION=v141"
|
||||
set "MSVC_CONAN_VERSION=191"
|
||||
set "CONAN_CPPSTD=17"
|
||||
)
|
||||
|
||||
echo [dstalk] MSVC runtime: !MSVC_RUNTIME_VERSION!
|
||||
|
||||
:: ============================================================
|
||||
:: 4. 强制使用 tools\ 内的编译器 (覆盖 MSVC 的 cl.exe)
|
||||
:: 3. 使用 Clang 编译器
|
||||
:: ============================================================
|
||||
set "CC=%TOOLS%llvm\bin\clang.exe"
|
||||
set "CXX=%TOOLS%llvm\bin\clang++.exe"
|
||||
set "CC=%CLANG_EXE%"
|
||||
set "CXX=%CLANGXX_EXE%"
|
||||
|
||||
cd /d "%ROOT%"
|
||||
|
||||
:: ============================================================
|
||||
:: 5. Conan 安装依赖
|
||||
:: 4. Conan 安装依赖
|
||||
:: ============================================================
|
||||
echo [dstalk] Conan 安装/刷新依赖...
|
||||
call "%TOOLS%.venv\Scripts\conan.exe" install deps/ -of build --build=missing -s compiler.cppstd=20 -c tools.cmake.cmaketoolchain:generator=Ninja
|
||||
call "%CONAN_EXE%" install deps/ -of build --build=missing -s compiler=msvc -s compiler.version=!MSVC_CONAN_VERSION! -s compiler.cppstd=!CONAN_CPPSTD! -s compiler.runtime=dynamic -s compiler.runtime_type=Release -c tools.cmake.cmaketoolchain:generator=Ninja
|
||||
if !errorlevel! neq 0 (
|
||||
echo [ERROR] Conan 安装失败
|
||||
pause & exit /b 1
|
||||
)
|
||||
|
||||
set "CONAN_GENERATORS=%ROOT%build\build\Release\generators"
|
||||
set "CONAN_GENERATORS=%ROOT%\build\build\Release\generators"
|
||||
|
||||
:: ============================================================
|
||||
:: 6. CMake 配置 + Ninja 编译
|
||||
:: 5. CMake 配置 + Ninja 编译
|
||||
:: ============================================================
|
||||
echo [dstalk] CMake 配置 + 编译...
|
||||
"%TOOLS%cmake\bin\cmake.exe" -S "%ROOT%" -B "%ROOT%build" -G Ninja ^
|
||||
-DCMAKE_C_COMPILER="%TOOLS%llvm\bin\clang.exe" ^
|
||||
-DCMAKE_CXX_COMPILER="%TOOLS%llvm\bin\clang++.exe" ^
|
||||
"%CMAKE_EXE%" -S "%ROOT%" -B "%ROOT%\build" -G Ninja ^
|
||||
-DCMAKE_MAKE_PROGRAM="%NINJA_EXE%" ^
|
||||
-DCMAKE_C_COMPILER="%CLANG_EXE%" ^
|
||||
-DCMAKE_CXX_COMPILER="%CLANGXX_EXE%" ^
|
||||
-DCMAKE_TOOLCHAIN_FILE="%CONAN_GENERATORS%\conan_toolchain.cmake" ^
|
||||
-DCMAKE_PREFIX_PATH="%CONAN_GENERATORS%" ^
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DDSTALK_BUILD_GUI=OFF
|
||||
if !errorlevel! neq 0 (
|
||||
echo [ERROR] CMake 配置失败
|
||||
pause & exit /b 1
|
||||
)
|
||||
|
||||
"%TOOLS%cmake\bin\cmake.exe" --build "%ROOT%build"
|
||||
"%CMAKE_EXE%" --build "%ROOT%\build"
|
||||
if !errorlevel! neq 0 (
|
||||
echo [ERROR] 编译失败
|
||||
pause & exit /b 1
|
||||
|
||||
4
deps/conanfile.txt
vendored
4
deps/conanfile.txt
vendored
@@ -1,7 +1,9 @@
|
||||
[requires]
|
||||
boost/1.86.0
|
||||
openssl/3.4.1
|
||||
sdl/3.2.14
|
||||
|
||||
[options]
|
||||
boost/*:header_only=True
|
||||
|
||||
[generators]
|
||||
CMakeDeps
|
||||
|
||||
@@ -3,14 +3,15 @@
|
||||
# 包含: 网络通讯 / AI接口 / 文件读写
|
||||
# ============================================================
|
||||
|
||||
find_package(Boost CONFIG REQUIRED)
|
||||
find_package(OpenSSL CONFIG REQUIRED)
|
||||
find_package(Boost REQUIRED CONFIG)
|
||||
find_package(OpenSSL REQUIRED CONFIG)
|
||||
|
||||
add_library(dstalk SHARED
|
||||
src/api.cpp
|
||||
src/file/file_io.cpp
|
||||
src/net/http_client.cpp
|
||||
src/ai/deepseek_api.cpp
|
||||
src/boost_json.cpp
|
||||
)
|
||||
|
||||
target_include_directories(dstalk
|
||||
@@ -20,15 +21,17 @@ target_include_directories(dstalk
|
||||
|
||||
target_link_libraries(dstalk
|
||||
PRIVATE
|
||||
Boost::boost
|
||||
Boost::system
|
||||
Boost::json
|
||||
OpenSSL::SSL
|
||||
OpenSSL::Crypto
|
||||
boost::boost
|
||||
openssl::openssl
|
||||
)
|
||||
|
||||
# 导出 DLL 符号宏
|
||||
target_compile_definitions(dstalk
|
||||
PRIVATE DSTALK_BUILD_DLL
|
||||
INTERFACE DSTALK_USE_DLL
|
||||
PRIVATE
|
||||
DSTALK_BUILD_DLL
|
||||
BOOST_ALL_NO_LIB
|
||||
BOOST_ERROR_CODE_HEADER_ONLY
|
||||
BOOST_JSON_HEADER_ONLY
|
||||
INTERFACE
|
||||
DSTALK_USE_DLL
|
||||
)
|
||||
|
||||
@@ -3,14 +3,17 @@
|
||||
#include "file/file_io.hpp"
|
||||
#include "net/http_client.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <boost/json.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// ---- 内部状态 ----
|
||||
namespace json = boost::json;
|
||||
|
||||
namespace {
|
||||
|
||||
bool g_initialized = false;
|
||||
@@ -92,6 +95,14 @@ void parse_config_file(const char* path)
|
||||
}
|
||||
}
|
||||
|
||||
char* copy_to_c_string(const std::string& value)
|
||||
{
|
||||
char* output = static_cast<char*>(std::malloc(value.size() + 1));
|
||||
if (!output) return nullptr;
|
||||
std::memcpy(output, value.c_str(), value.size() + 1);
|
||||
return output;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// ---- 初始化 / 销毁 ----
|
||||
@@ -153,25 +164,20 @@ DSTALK_API void dstalk_set_model(const char* model)
|
||||
DSTALK_API int dstalk_chat(const char* input, char** output)
|
||||
{
|
||||
if (!g_initialized || !input || !output) return -1;
|
||||
*output = nullptr;
|
||||
|
||||
auto result = g_ai.chat(g_history, input);
|
||||
if (!result.ok) {
|
||||
// 返回错误信息
|
||||
*output = static_cast<char*>(std::malloc(result.error.size() + 1));
|
||||
if (*output) {
|
||||
std::memcpy(*output, result.error.c_str(), result.error.size() + 1);
|
||||
}
|
||||
*output = copy_to_c_string(result.error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 更新历史
|
||||
char* reply = copy_to_c_string(result.content);
|
||||
if (!reply) return -1;
|
||||
|
||||
g_history.push_back({"user", input});
|
||||
g_history.push_back({"assistant", result.content});
|
||||
|
||||
*output = static_cast<char*>(std::malloc(result.content.size() + 1));
|
||||
if (*output) {
|
||||
std::memcpy(*output, result.content.c_str(), result.content.size() + 1);
|
||||
}
|
||||
*output = reply;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -228,37 +234,14 @@ DSTALK_API void dstalk_session_clear(void)
|
||||
DSTALK_API int dstalk_session_save(const char* path)
|
||||
{
|
||||
if (!g_initialized || !path) return -1;
|
||||
// 简单格式: 每行 JSON {"role":"...","content":"..."}
|
||||
|
||||
std::string data;
|
||||
for (const auto& m : g_history) {
|
||||
// 转义 JSON 特殊字符和控制字符
|
||||
auto escape = [](const std::string& s) -> std::string {
|
||||
std::string out;
|
||||
for (char c : s) {
|
||||
switch (c) {
|
||||
case '"': out += "\\\""; break;
|
||||
case '\\': out += "\\\\"; break;
|
||||
case '\n': out += "\\n"; break;
|
||||
case '\r': out += "\\r"; break;
|
||||
case '\t': out += "\\t"; break;
|
||||
case '\b': out += "\\b"; break;
|
||||
case '\f': out += "\\f"; break;
|
||||
default:
|
||||
if (static_cast<unsigned char>(c) < 0x20) {
|
||||
char buf[8];
|
||||
std::snprintf(buf, sizeof(buf), "\\u%04x",
|
||||
static_cast<unsigned char>(c));
|
||||
out += buf;
|
||||
} else {
|
||||
out += c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
};
|
||||
data += "{\"role\":\"" + escape(m.role) + "\",\"content\":\""
|
||||
+ escape(m.content) + "\"}\n";
|
||||
json::object entry;
|
||||
entry["role"] = m.role;
|
||||
entry["content"] = m.content;
|
||||
data += json::serialize(entry);
|
||||
data += '\n';
|
||||
}
|
||||
return file_write_all(path, data.c_str());
|
||||
}
|
||||
@@ -275,7 +258,6 @@ DSTALK_API int dstalk_session_load(const char* path)
|
||||
|
||||
std::vector<dstalk::ai::Message> parsed;
|
||||
|
||||
// 逐行解析简化的 JSON
|
||||
size_t pos = 0;
|
||||
while (pos < data.size()) {
|
||||
size_t nl = data.find('\n', pos);
|
||||
@@ -284,24 +266,16 @@ DSTALK_API int dstalk_session_load(const char* path)
|
||||
pos = (nl != std::string::npos) ? nl + 1 : data.size();
|
||||
if (line.empty()) continue;
|
||||
|
||||
// 简陋 JSON 解析: 找 "role":"..." 和 "content":"..."
|
||||
auto extract = [&](const std::string& key) -> std::string {
|
||||
std::string search = "\"" + key + "\":\"";
|
||||
size_t start = line.find(search);
|
||||
if (start == std::string::npos) return "";
|
||||
start += search.size();
|
||||
size_t end = start;
|
||||
while (end < line.size()) {
|
||||
if (line[end] == '"' && (end == 0 || line[end-1] != '\\')) break;
|
||||
end++;
|
||||
try {
|
||||
auto obj = json::parse(line).as_object();
|
||||
auto* role = obj.if_contains("role");
|
||||
auto* content_val = obj.if_contains("content");
|
||||
if (role && content_val && role->is_string() && content_val->is_string()) {
|
||||
parsed.push_back({json::value_to<std::string>(*role),
|
||||
json::value_to<std::string>(*content_val)});
|
||||
}
|
||||
return line.substr(start, end - start);
|
||||
};
|
||||
|
||||
std::string role = extract("role");
|
||||
std::string content_val = extract("content");
|
||||
if (!role.empty() && !content_val.empty()) {
|
||||
parsed.push_back({role, content_val});
|
||||
} catch (const std::exception&) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,14 +289,18 @@ DSTALK_API int dstalk_session_load(const char* path)
|
||||
DSTALK_API int dstalk_file_read(const char* path, char** content)
|
||||
{
|
||||
if (!g_initialized || !path || !content) return -1;
|
||||
*content = nullptr;
|
||||
|
||||
size_t len = 0;
|
||||
char* buf = file_read_all(path, &len);
|
||||
if (!buf) return -1;
|
||||
|
||||
*content = buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DSTALK_API int dstalk_file_write(const char* path, const char* content)
|
||||
{
|
||||
if (!g_initialized || !path || !content) return -1;
|
||||
return file_write_all(path, content);
|
||||
}
|
||||
|
||||
1
dstalk-core/src/boost_json.cpp
Normal file
1
dstalk-core/src/boost_json.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include <boost/json/src.hpp>
|
||||
@@ -1,146 +0,0 @@
|
||||
#pragma once
|
||||
// BearSSL TLS stream adapter — Beast SyncStream compatible
|
||||
// Replaces boost::asio::ssl::stream<boost::asio::ip::tcp::socket>
|
||||
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <bearssl.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace dstalk {
|
||||
namespace net {
|
||||
|
||||
// Platform-specific system trust anchor loader
|
||||
std::vector<br_x509_trust_anchor> load_system_trust_anchors();
|
||||
|
||||
// Beast-compatible TLS stream backed by BearSSL (MIT license)
|
||||
class BearSSLStream {
|
||||
public:
|
||||
using next_layer_type = boost::asio::ip::tcp::socket;
|
||||
using executor_type = next_layer_type::executor_type;
|
||||
using lowest_layer_type = next_layer_type;
|
||||
|
||||
explicit BearSSLStream(boost::asio::io_context& ioc);
|
||||
~BearSSLStream();
|
||||
|
||||
// Non-copyable
|
||||
BearSSLStream(const BearSSLStream&) = delete;
|
||||
BearSSLStream& operator=(const BearSSLStream&) = delete;
|
||||
|
||||
// Perform TLS handshake with SNI hostname
|
||||
void handshake(const std::string& host);
|
||||
|
||||
// Beast SyncStream requirements
|
||||
template<typename MutableBufferSequence>
|
||||
size_t read_some(const MutableBufferSequence& buffers);
|
||||
|
||||
template<typename MutableBufferSequence>
|
||||
size_t read_some(const MutableBufferSequence& buffers,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
template<typename ConstBufferSequence>
|
||||
size_t write_some(const ConstBufferSequence& buffers);
|
||||
|
||||
template<typename ConstBufferSequence>
|
||||
size_t write_some(const ConstBufferSequence& buffers,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
next_layer_type& next_layer() { return socket_; }
|
||||
lowest_layer_type& lowest_layer() { return socket_; }
|
||||
executor_type get_executor() { return socket_.get_executor(); }
|
||||
|
||||
private:
|
||||
// BearSSL I/O callbacks (static, receive 'this' as ctx)
|
||||
static int s_read(void* ctx, unsigned char* buf, size_t len);
|
||||
static int s_write(void* ctx, const unsigned char* buf, size_t len);
|
||||
|
||||
// Low-level socket I/O used by BearSSL callbacks
|
||||
int low_read(unsigned char* buf, size_t len);
|
||||
int low_write(const unsigned char* buf, size_t len);
|
||||
|
||||
// Reset engine for re-handshake
|
||||
void reset_engine(const std::string& host);
|
||||
|
||||
boost::asio::ip::tcp::socket socket_;
|
||||
bool handshake_done_ = false;
|
||||
|
||||
// BearSSL client state
|
||||
br_ssl_client_context sc_;
|
||||
br_x509_minimal_context xc_;
|
||||
std::vector<unsigned char> iobuf_;
|
||||
br_sslio_context sslioc_;
|
||||
std::vector<br_x509_trust_anchor> anchors_;
|
||||
};
|
||||
|
||||
// ====== template implementations ======
|
||||
|
||||
template<typename MutableBufferSequence>
|
||||
size_t BearSSLStream::read_some(const MutableBufferSequence& buffers)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
size_t n = read_some(buffers, ec);
|
||||
if (ec) throw boost::system::system_error(ec);
|
||||
return n;
|
||||
}
|
||||
|
||||
template<typename MutableBufferSequence>
|
||||
size_t BearSSLStream::read_some(const MutableBufferSequence& buffers,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
namespace asio = boost::asio;
|
||||
// Gather buffer into contiguous memory for BearSSL
|
||||
size_t total = asio::buffer_size(buffers);
|
||||
if (total == 0) return 0;
|
||||
|
||||
std::vector<unsigned char> tmp(total);
|
||||
int ret = br_sslio_read(&sslioc_, tmp.data(), (int)total);
|
||||
|
||||
if (ret < 0) {
|
||||
ec = boost::system::error_code(ret, boost::system::system_category());
|
||||
return 0;
|
||||
}
|
||||
if (ret == 0) {
|
||||
ec = boost::asio::error::eof;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Copy to output buffers
|
||||
asio::buffer_copy(buffers, asio::buffer(tmp.data(), (size_t)ret));
|
||||
ec.assign(0, ec.category());
|
||||
return (size_t)ret;
|
||||
}
|
||||
|
||||
template<typename ConstBufferSequence>
|
||||
size_t BearSSLStream::write_some(const ConstBufferSequence& buffers)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
size_t n = write_some(buffers, ec);
|
||||
if (ec) throw boost::system::system_error(ec);
|
||||
return n;
|
||||
}
|
||||
|
||||
template<typename ConstBufferSequence>
|
||||
size_t BearSSLStream::write_some(const ConstBufferSequence& buffers,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
namespace asio = boost::asio;
|
||||
size_t total = asio::buffer_size(buffers);
|
||||
if (total == 0) return 0;
|
||||
|
||||
// Gather into contiguous buffer
|
||||
std::vector<unsigned char> tmp(total);
|
||||
asio::buffer_copy(asio::buffer(tmp), buffers);
|
||||
|
||||
int ret = br_sslio_write_all(&sslioc_, tmp.data(), (int)total);
|
||||
|
||||
if (ret < 0) {
|
||||
ec = boost::system::error_code(ret, boost::system::system_category());
|
||||
return 0;
|
||||
}
|
||||
ec.assign(0, ec.category());
|
||||
return total;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace dstalk
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <boost/beast/ssl.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace beast = boost::beast;
|
||||
namespace http = beast::http;
|
||||
namespace asio = boost::asio;
|
||||
@@ -97,12 +99,12 @@ HttpResponse HttpClient::post_stream(
|
||||
http::read_header(stream, buffer, parser);
|
||||
|
||||
result.status_code = parser.get().result_int();
|
||||
result.body = parser.get().body();
|
||||
|
||||
beast::error_code ec;
|
||||
|
||||
if (on_line) {
|
||||
std::string fragment = result.body;
|
||||
std::string fragment = parser.get().body();
|
||||
auto emit_lines = [&]() -> bool {
|
||||
size_t pos = 0;
|
||||
while (pos < fragment.size()) {
|
||||
size_t nl = fragment.find('\n', pos);
|
||||
@@ -110,36 +112,28 @@ HttpResponse HttpClient::post_stream(
|
||||
std::string line = fragment.substr(pos, nl - pos);
|
||||
if (!line.empty() && line.back() == '\r')
|
||||
line.pop_back();
|
||||
if (!on_line(line)) goto done;
|
||||
if (!on_line(line)) return false;
|
||||
pos = nl + 1;
|
||||
}
|
||||
if (pos > 0)
|
||||
fragment = fragment.substr(pos);
|
||||
return true;
|
||||
};
|
||||
if (!emit_lines()) goto done;
|
||||
|
||||
size_t processed = result.body.size();
|
||||
size_t processed = parser.get().body().size();
|
||||
while (!parser.is_done()) {
|
||||
http::read_some(stream, buffer, parser, ec);
|
||||
if (ec) break;
|
||||
|
||||
const std::string& full_body = parser.get().body();
|
||||
if (full_body.size() > processed) {
|
||||
std::string new_data = full_body.substr(processed);
|
||||
result.body += new_data;
|
||||
std::string_view new_data(full_body.data() + processed,
|
||||
full_body.size() - processed);
|
||||
processed = full_body.size();
|
||||
|
||||
fragment += new_data;
|
||||
pos = 0;
|
||||
while (pos < fragment.size()) {
|
||||
size_t nl = fragment.find('\n', pos);
|
||||
if (nl == std::string::npos) break;
|
||||
std::string line = fragment.substr(pos, nl - pos);
|
||||
if (!line.empty() && line.back() == '\r')
|
||||
line.pop_back();
|
||||
if (!on_line(line)) goto done;
|
||||
pos = nl + 1;
|
||||
}
|
||||
if (pos > 0)
|
||||
fragment = fragment.substr(pos);
|
||||
fragment.append(new_data.data(), new_data.size());
|
||||
if (!emit_lines()) goto done;
|
||||
}
|
||||
}
|
||||
if (!fragment.empty()) {
|
||||
@@ -152,10 +146,10 @@ HttpResponse HttpClient::post_stream(
|
||||
while (!parser.is_done()) {
|
||||
http::read_some(stream, buffer, parser, ec);
|
||||
if (ec) break;
|
||||
result.body = parser.get().body();
|
||||
}
|
||||
}
|
||||
done:
|
||||
result.body = parser.get().body();
|
||||
beast::get_lowest_layer(stream).cancel();
|
||||
stream.shutdown(ec);
|
||||
} catch (std::exception& e) {
|
||||
|
||||
@@ -15,8 +15,7 @@ struct HttpResponse {
|
||||
|
||||
/*
|
||||
* HTTPS 客户端统一接口
|
||||
* Windows: WinHTTP 实现 (零依赖)
|
||||
* 其他平台: Boost.Beast + OpenSSL 实现
|
||||
* 所有平台统一使用 Boost.Beast + OpenSSL 实现
|
||||
*/
|
||||
class HttpClient {
|
||||
public:
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
/*
|
||||
* 纯 WinHTTP 实现 (Windows 内置, 零第三方依赖)
|
||||
* 与 net/http_client.hpp 接口兼容
|
||||
*/
|
||||
|
||||
namespace dstalk {
|
||||
namespace net {
|
||||
|
||||
struct HttpResponse {
|
||||
int status_code = 0;
|
||||
std::string body;
|
||||
std::unordered_map<std::string, std::string> headers;
|
||||
};
|
||||
|
||||
class HttpClient {
|
||||
public:
|
||||
HttpClient();
|
||||
~HttpClient();
|
||||
|
||||
void set_timeout(int connect_sec, int request_sec);
|
||||
|
||||
HttpResponse post_json(
|
||||
const std::string& host,
|
||||
const std::string& port,
|
||||
const std::string& target,
|
||||
const std::string& json_body,
|
||||
const std::unordered_map<std::string, std::string>& extra_headers
|
||||
);
|
||||
|
||||
// 流式 POST (SSE 回调)
|
||||
HttpResponse post_stream(
|
||||
const std::string& host,
|
||||
const std::string& port,
|
||||
const std::string& target,
|
||||
const std::string& json_body,
|
||||
const std::unordered_map<std::string, std::string>& extra_headers,
|
||||
bool (*on_line)(const std::string& line, void* userdata),
|
||||
void* userdata = nullptr
|
||||
);
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
Impl* impl_;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace dstalk
|
||||
43
dstalk-core/thirdparty/bearssl/CMakeLists.txt
vendored
43
dstalk-core/thirdparty/bearssl/CMakeLists.txt
vendored
@@ -1,43 +0,0 @@
|
||||
# BearSSL static library (vendored, MIT license)
|
||||
# All .c files compiled as a single translation unit for best optimization
|
||||
|
||||
add_library(bearssl STATIC)
|
||||
|
||||
target_include_directories(bearssl
|
||||
PUBLIC inc
|
||||
PRIVATE src
|
||||
)
|
||||
|
||||
# Collect all C source files
|
||||
file(GLOB_RECURSE BEARSSL_SOURCES "src/*.c")
|
||||
target_sources(bearssl PRIVATE ${BEARSSL_SOURCES})
|
||||
|
||||
# x86_64 Windows optimizations
|
||||
if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
target_compile_definitions(bearssl PRIVATE
|
||||
BR_64
|
||||
BR_INT128
|
||||
BR_LE_UNALIGNED
|
||||
BR_USE_WIN32_RAND
|
||||
BR_USE_WIN32_TIME
|
||||
)
|
||||
# AES-NI and SSE2 are auto-detected by BearSSL on x86
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
|
||||
target_compile_options(bearssl PRIVATE -maes -msse2)
|
||||
endif()
|
||||
elseif(UNIX)
|
||||
target_compile_definitions(bearssl PRIVATE
|
||||
BR_USE_URANDOM
|
||||
BR_USE_UNIX_TIME
|
||||
)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
target_compile_definitions(bearssl PRIVATE BR_64 BR_INT128 BR_LE_UNALIGNED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Suppress warnings for vendored code
|
||||
if(MSVC)
|
||||
target_compile_options(bearssl PRIVATE /W0)
|
||||
else()
|
||||
target_compile_options(bearssl PRIVATE -w)
|
||||
endif()
|
||||
170
dstalk-core/thirdparty/bearssl/inc/bearssl.h
vendored
170
dstalk-core/thirdparty/bearssl/inc/bearssl.h
vendored
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_H__
|
||||
#define BR_BEARSSL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** \mainpage BearSSL API
|
||||
*
|
||||
* # API Layout
|
||||
*
|
||||
* The functions and structures defined by the BearSSL API are located
|
||||
* in various header files:
|
||||
*
|
||||
* | Header file | Elements |
|
||||
* | :-------------- | :------------------------------------------------ |
|
||||
* | bearssl_hash.h | Hash functions |
|
||||
* | bearssl_hmac.h | HMAC |
|
||||
* | bearssl_kdf.h | Key Derivation Functions |
|
||||
* | bearssl_rand.h | Pseudorandom byte generators |
|
||||
* | bearssl_prf.h | PRF implementations (for SSL/TLS) |
|
||||
* | bearssl_block.h | Symmetric encryption |
|
||||
* | bearssl_aead.h | AEAD algorithms (combined encryption + MAC) |
|
||||
* | bearssl_rsa.h | RSA encryption and signatures |
|
||||
* | bearssl_ec.h | Elliptic curves support (including ECDSA) |
|
||||
* | bearssl_ssl.h | SSL/TLS engine interface |
|
||||
* | bearssl_x509.h | X.509 certificate decoding and validation |
|
||||
* | bearssl_pem.h | Base64/PEM decoding support functions |
|
||||
*
|
||||
* Applications using BearSSL are supposed to simply include `bearssl.h`
|
||||
* as follows:
|
||||
*
|
||||
* #include <bearssl.h>
|
||||
*
|
||||
* The `bearssl.h` file itself includes all the other header files. It is
|
||||
* possible to include specific header files, but it has no practical
|
||||
* advantage for the application. The API is separated into separate
|
||||
* header files only for documentation convenience.
|
||||
*
|
||||
*
|
||||
* # Conventions
|
||||
*
|
||||
* ## MUST and SHALL
|
||||
*
|
||||
* In all descriptions, the usual "MUST", "SHALL", "MAY",... terminology
|
||||
* is used. Failure to meet requirements expressed with a "MUST" or
|
||||
* "SHALL" implies undefined behaviour, which means that segmentation
|
||||
* faults, buffer overflows, and other similar adverse events, may occur.
|
||||
*
|
||||
* In general, BearSSL is not very forgiving of programming errors, and
|
||||
* does not include much failsafes or error reporting when the problem
|
||||
* does not arise from external transient conditions, and can be fixed
|
||||
* only in the application code. This is done so in order to make the
|
||||
* total code footprint lighter.
|
||||
*
|
||||
*
|
||||
* ## `NULL` values
|
||||
*
|
||||
* Function parameters with a pointer type shall not be `NULL` unless
|
||||
* explicitly authorised by the documentation. As an exception, when
|
||||
* the pointer aims at a sequence of bytes and is accompanied with
|
||||
* a length parameter, and the length is zero (meaning that there is
|
||||
* no byte at all to retrieve), then the pointer may be `NULL` even if
|
||||
* not explicitly allowed.
|
||||
*
|
||||
*
|
||||
* ## Memory Allocation
|
||||
*
|
||||
* BearSSL does not perform dynamic memory allocation. This implies that
|
||||
* for any functionality that requires a non-transient state, the caller
|
||||
* is responsible for allocating the relevant context structure. Such
|
||||
* allocation can be done in any appropriate area, including static data
|
||||
* segments, the heap, and the stack, provided that proper alignment is
|
||||
* respected. The header files define these context structures
|
||||
* (including size and contents), so the C compiler should handle
|
||||
* alignment automatically.
|
||||
*
|
||||
* Since there is no dynamic resource allocation, there is also nothing to
|
||||
* release. When the calling code is done with a BearSSL feature, it
|
||||
* may simple release the context structures it allocated itself, with
|
||||
* no "close function" to call. If the context structures were allocated
|
||||
* on the stack (as local variables), then even that release operation is
|
||||
* implicit.
|
||||
*
|
||||
*
|
||||
* ## Structure Contents
|
||||
*
|
||||
* Except when explicitly indicated, structure contents are opaque: they
|
||||
* are included in the header files so that calling code may know the
|
||||
* structure sizes and alignment requirements, but callers SHALL NOT
|
||||
* access individual fields directly. For fields that are supposed to
|
||||
* be read from or written to, the API defines accessor functions (the
|
||||
* simplest of these accessor functions are defined as `static inline`
|
||||
* functions, and the C compiler will optimise them away).
|
||||
*
|
||||
*
|
||||
* # API Usage
|
||||
*
|
||||
* BearSSL usage for running a SSL/TLS client or server is described
|
||||
* on the [BearSSL Web site](https://www.bearssl.org/api1.html). The
|
||||
* BearSSL source archive also comes with sample code.
|
||||
*/
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
#include "bearssl_hmac.h"
|
||||
#include "bearssl_kdf.h"
|
||||
#include "bearssl_rand.h"
|
||||
#include "bearssl_prf.h"
|
||||
#include "bearssl_block.h"
|
||||
#include "bearssl_aead.h"
|
||||
#include "bearssl_rsa.h"
|
||||
#include "bearssl_ec.h"
|
||||
#include "bearssl_ssl.h"
|
||||
#include "bearssl_x509.h"
|
||||
#include "bearssl_pem.h"
|
||||
|
||||
/** \brief Type for a configuration option.
|
||||
*
|
||||
* A "configuration option" is a value that is selected when the BearSSL
|
||||
* library itself is compiled. Most options are boolean; their value is
|
||||
* then either 1 (option is enabled) or 0 (option is disabled). Some
|
||||
* values have other integer values. Option names correspond to macro
|
||||
* names. Some of the options can be explicitly set in the internal
|
||||
* `"config.h"` file.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Configurable option name. */
|
||||
const char *name;
|
||||
/** \brief Configurable option value. */
|
||||
long value;
|
||||
} br_config_option;
|
||||
|
||||
/** \brief Get configuration report.
|
||||
*
|
||||
* This function returns compiled configuration options, each as a
|
||||
* 'long' value. Names match internal macro names, in particular those
|
||||
* that can be set in the `"config.h"` inner file. For boolean options,
|
||||
* the numerical value is 1 if enabled, 0 if disabled. For maximum
|
||||
* key sizes, values are expressed in bits.
|
||||
*
|
||||
* The returned array is terminated by an entry whose `name` is `NULL`.
|
||||
*
|
||||
* \return the configuration report.
|
||||
*/
|
||||
const br_config_option *br_get_config(void);
|
||||
|
||||
#endif
|
||||
1059
dstalk-core/thirdparty/bearssl/inc/bearssl_aead.h
vendored
1059
dstalk-core/thirdparty/bearssl/inc/bearssl_aead.h
vendored
File diff suppressed because it is too large
Load Diff
2618
dstalk-core/thirdparty/bearssl/inc/bearssl_block.h
vendored
2618
dstalk-core/thirdparty/bearssl/inc/bearssl_block.h
vendored
File diff suppressed because it is too large
Load Diff
883
dstalk-core/thirdparty/bearssl/inc/bearssl_ec.h
vendored
883
dstalk-core/thirdparty/bearssl/inc/bearssl_ec.h
vendored
@@ -1,883 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_EC_H__
|
||||
#define BR_BEARSSL_EC_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_rand.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_ec.h
|
||||
*
|
||||
* # Elliptic Curves
|
||||
*
|
||||
* This file documents the EC implementations provided with BearSSL, and
|
||||
* ECDSA.
|
||||
*
|
||||
* ## Elliptic Curve API
|
||||
*
|
||||
* Only "named curves" are supported. Each EC implementation supports
|
||||
* one or several named curves, identified by symbolic identifiers.
|
||||
* These identifiers are small integers, that correspond to the values
|
||||
* registered by the
|
||||
* [IANA](http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8).
|
||||
*
|
||||
* Since all currently defined elliptic curve identifiers are in the 0..31
|
||||
* range, it is convenient to encode support of some curves in a 32-bit
|
||||
* word, such that bit x corresponds to curve of identifier x.
|
||||
*
|
||||
* An EC implementation is incarnated by a `br_ec_impl` instance, that
|
||||
* offers the following fields:
|
||||
*
|
||||
* - `supported_curves`
|
||||
*
|
||||
* A 32-bit word that documents the identifiers of the curves supported
|
||||
* by this implementation.
|
||||
*
|
||||
* - `generator()`
|
||||
*
|
||||
* Callback method that returns a pointer to the conventional generator
|
||||
* point for that curve.
|
||||
*
|
||||
* - `order()`
|
||||
*
|
||||
* Callback method that returns a pointer to the subgroup order for
|
||||
* that curve. That value uses unsigned big-endian encoding.
|
||||
*
|
||||
* - `xoff()`
|
||||
*
|
||||
* Callback method that returns the offset and length of the X
|
||||
* coordinate in an encoded point.
|
||||
*
|
||||
* - `mul()`
|
||||
*
|
||||
* Multiply a curve point with an integer.
|
||||
*
|
||||
* - `mulgen()`
|
||||
*
|
||||
* Multiply the curve generator with an integer. This may be faster
|
||||
* than the generic `mul()`.
|
||||
*
|
||||
* - `muladd()`
|
||||
*
|
||||
* Multiply two curve points by two integers, and return the sum of
|
||||
* the two products.
|
||||
*
|
||||
* All curve points are represented in uncompressed format. The `mul()`
|
||||
* and `muladd()` methods take care to validate that the provided points
|
||||
* are really part of the relevant curve subgroup.
|
||||
*
|
||||
* For all point multiplication functions, the following holds:
|
||||
*
|
||||
* - Functions validate that the provided points are valid members
|
||||
* of the relevant curve subgroup. An error is reported if that is
|
||||
* not the case.
|
||||
*
|
||||
* - Processing is constant-time, even if the point operands are not
|
||||
* valid. This holds for both the source and resulting points, and
|
||||
* the multipliers (integers). Only the byte length of the provided
|
||||
* multiplier arrays (not their actual value length in bits) may
|
||||
* leak through timing-based side channels.
|
||||
*
|
||||
* - The multipliers (integers) MUST be lower than the subgroup order.
|
||||
* If this property is not met, then the result is indeterminate,
|
||||
* but an error value is not ncessearily returned.
|
||||
*
|
||||
*
|
||||
* ## ECDSA
|
||||
*
|
||||
* ECDSA signatures have two standard formats, called "raw" and "asn1".
|
||||
* Internally, such a signature is a pair of modular integers `(r,s)`.
|
||||
* The "raw" format is the concatenation of the unsigned big-endian
|
||||
* encodings of these two integers, possibly left-padded with zeros so
|
||||
* that they have the same encoded length. The "asn1" format is the
|
||||
* DER encoding of an ASN.1 structure that contains the two integer
|
||||
* values:
|
||||
*
|
||||
* ECDSASignature ::= SEQUENCE {
|
||||
* r INTEGER,
|
||||
* s INTEGER
|
||||
* }
|
||||
*
|
||||
* In general, in all of X.509 and SSL/TLS, the "asn1" format is used.
|
||||
* BearSSL offers ECDSA implementations for both formats; conversion
|
||||
* functions between the two formats are also provided. Conversion of a
|
||||
* "raw" format signature into "asn1" may enlarge a signature by no more
|
||||
* than 9 bytes for all supported curves; conversely, conversion of an
|
||||
* "asn1" signature to "raw" may expand the signature but the "raw"
|
||||
* length will never be more than twice the length of the "asn1" length
|
||||
* (and usually it will be shorter).
|
||||
*
|
||||
* Note that for a given signature, the "raw" format is not fully
|
||||
* deterministic, in that it does not enforce a minimal common length.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Standard curve ID. These ID are equal to the assigned numerical
|
||||
* identifiers assigned to these curves for TLS:
|
||||
* http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
|
||||
*/
|
||||
|
||||
/** \brief Identifier for named curve sect163k1. */
|
||||
#define BR_EC_sect163k1 1
|
||||
|
||||
/** \brief Identifier for named curve sect163r1. */
|
||||
#define BR_EC_sect163r1 2
|
||||
|
||||
/** \brief Identifier for named curve sect163r2. */
|
||||
#define BR_EC_sect163r2 3
|
||||
|
||||
/** \brief Identifier for named curve sect193r1. */
|
||||
#define BR_EC_sect193r1 4
|
||||
|
||||
/** \brief Identifier for named curve sect193r2. */
|
||||
#define BR_EC_sect193r2 5
|
||||
|
||||
/** \brief Identifier for named curve sect233k1. */
|
||||
#define BR_EC_sect233k1 6
|
||||
|
||||
/** \brief Identifier for named curve sect233r1. */
|
||||
#define BR_EC_sect233r1 7
|
||||
|
||||
/** \brief Identifier for named curve sect239k1. */
|
||||
#define BR_EC_sect239k1 8
|
||||
|
||||
/** \brief Identifier for named curve sect283k1. */
|
||||
#define BR_EC_sect283k1 9
|
||||
|
||||
/** \brief Identifier for named curve sect283r1. */
|
||||
#define BR_EC_sect283r1 10
|
||||
|
||||
/** \brief Identifier for named curve sect409k1. */
|
||||
#define BR_EC_sect409k1 11
|
||||
|
||||
/** \brief Identifier for named curve sect409r1. */
|
||||
#define BR_EC_sect409r1 12
|
||||
|
||||
/** \brief Identifier for named curve sect571k1. */
|
||||
#define BR_EC_sect571k1 13
|
||||
|
||||
/** \brief Identifier for named curve sect571r1. */
|
||||
#define BR_EC_sect571r1 14
|
||||
|
||||
/** \brief Identifier for named curve secp160k1. */
|
||||
#define BR_EC_secp160k1 15
|
||||
|
||||
/** \brief Identifier for named curve secp160r1. */
|
||||
#define BR_EC_secp160r1 16
|
||||
|
||||
/** \brief Identifier for named curve secp160r2. */
|
||||
#define BR_EC_secp160r2 17
|
||||
|
||||
/** \brief Identifier for named curve secp192k1. */
|
||||
#define BR_EC_secp192k1 18
|
||||
|
||||
/** \brief Identifier for named curve secp192r1. */
|
||||
#define BR_EC_secp192r1 19
|
||||
|
||||
/** \brief Identifier for named curve secp224k1. */
|
||||
#define BR_EC_secp224k1 20
|
||||
|
||||
/** \brief Identifier for named curve secp224r1. */
|
||||
#define BR_EC_secp224r1 21
|
||||
|
||||
/** \brief Identifier for named curve secp256k1. */
|
||||
#define BR_EC_secp256k1 22
|
||||
|
||||
/** \brief Identifier for named curve secp256r1. */
|
||||
#define BR_EC_secp256r1 23
|
||||
|
||||
/** \brief Identifier for named curve secp384r1. */
|
||||
#define BR_EC_secp384r1 24
|
||||
|
||||
/** \brief Identifier for named curve secp521r1. */
|
||||
#define BR_EC_secp521r1 25
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP256r1. */
|
||||
#define BR_EC_brainpoolP256r1 26
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP384r1. */
|
||||
#define BR_EC_brainpoolP384r1 27
|
||||
|
||||
/** \brief Identifier for named curve brainpoolP512r1. */
|
||||
#define BR_EC_brainpoolP512r1 28
|
||||
|
||||
/** \brief Identifier for named curve Curve25519. */
|
||||
#define BR_EC_curve25519 29
|
||||
|
||||
/** \brief Identifier for named curve Curve448. */
|
||||
#define BR_EC_curve448 30
|
||||
|
||||
/**
|
||||
* \brief Structure for an EC public key.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Identifier for the curve used by this key. */
|
||||
int curve;
|
||||
/** \brief Public curve point (uncompressed format). */
|
||||
unsigned char *q;
|
||||
/** \brief Length of public curve point (in bytes). */
|
||||
size_t qlen;
|
||||
} br_ec_public_key;
|
||||
|
||||
/**
|
||||
* \brief Structure for an EC private key.
|
||||
*
|
||||
* The private key is an integer modulo the curve subgroup order. The
|
||||
* encoding below tolerates extra leading zeros. In general, it is
|
||||
* recommended that the private key has the same length as the curve
|
||||
* subgroup order.
|
||||
*/
|
||||
typedef struct {
|
||||
/** \brief Identifier for the curve used by this key. */
|
||||
int curve;
|
||||
/** \brief Private key (integer, unsigned big-endian encoding). */
|
||||
unsigned char *x;
|
||||
/** \brief Private key length (in bytes). */
|
||||
size_t xlen;
|
||||
} br_ec_private_key;
|
||||
|
||||
/**
|
||||
* \brief Type for an EC implementation.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Supported curves.
|
||||
*
|
||||
* This word is a bitfield: bit `x` is set if the curve of ID `x`
|
||||
* is supported. E.g. an implementation supporting both NIST P-256
|
||||
* (secp256r1, ID 23) and NIST P-384 (secp384r1, ID 24) will have
|
||||
* value `0x01800000` in this field.
|
||||
*/
|
||||
uint32_t supported_curves;
|
||||
|
||||
/**
|
||||
* \brief Get the conventional generator.
|
||||
*
|
||||
* This function returns the conventional generator (encoded
|
||||
* curve point) for the specified curve. This function MUST NOT
|
||||
* be called if the curve is not supported.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the encoded generator length (in bytes).
|
||||
* \return the encoded generator.
|
||||
*/
|
||||
const unsigned char *(*generator)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Get the subgroup order.
|
||||
*
|
||||
* This function returns the order of the subgroup generated by
|
||||
* the conventional generator, for the specified curve. Unsigned
|
||||
* big-endian encoding is used. This function MUST NOT be called
|
||||
* if the curve is not supported.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the encoded order length (in bytes).
|
||||
* \return the encoded order.
|
||||
*/
|
||||
const unsigned char *(*order)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Get the offset and length for the X coordinate.
|
||||
*
|
||||
* This function returns the offset and length (in bytes) of
|
||||
* the X coordinate in an encoded non-zero point.
|
||||
*
|
||||
* \param curve curve identifier.
|
||||
* \param len receiver for the X coordinate length (in bytes).
|
||||
* \return the offset for the X coordinate (in bytes).
|
||||
*/
|
||||
size_t (*xoff)(int curve, size_t *len);
|
||||
|
||||
/**
|
||||
* \brief Multiply a curve point by an integer.
|
||||
*
|
||||
* The source point is provided in array `G` (of size `Glen` bytes);
|
||||
* the multiplication result is written over it. The multiplier
|
||||
* `x` (of size `xlen` bytes) uses unsigned big-endian encoding.
|
||||
*
|
||||
* Rules:
|
||||
*
|
||||
* - The specified curve MUST be supported.
|
||||
*
|
||||
* - The source point must be a valid point on the relevant curve
|
||||
* subgroup (and not the "point at infinity" either). If this is
|
||||
* not the case, then this function returns an error (0).
|
||||
*
|
||||
* - The multiplier integer MUST be non-zero and less than the
|
||||
* curve subgroup order. If this property does not hold, then
|
||||
* the result is indeterminate and an error code is not
|
||||
* guaranteed.
|
||||
*
|
||||
* Returned value is 1 on success, 0 on error. On error, the
|
||||
* contents of `G` are indeterminate.
|
||||
*
|
||||
* \param G point to multiply.
|
||||
* \param Glen length of the encoded point (in bytes).
|
||||
* \param x multiplier (unsigned big-endian).
|
||||
* \param xlen multiplier length (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t (*mul)(unsigned char *G, size_t Glen,
|
||||
const unsigned char *x, size_t xlen, int curve);
|
||||
|
||||
/**
|
||||
* \brief Multiply the generator by an integer.
|
||||
*
|
||||
* The multiplier MUST be non-zero and less than the curve
|
||||
* subgroup order. Results are indeterminate if this property
|
||||
* does not hold.
|
||||
*
|
||||
* \param R output buffer for the point.
|
||||
* \param x multiplier (unsigned big-endian).
|
||||
* \param xlen multiplier length (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return encoded result point length (in bytes).
|
||||
*/
|
||||
size_t (*mulgen)(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve);
|
||||
|
||||
/**
|
||||
* \brief Multiply two points by two integers and add the
|
||||
* results.
|
||||
*
|
||||
* The point `x*A + y*B` is computed and written back in the `A`
|
||||
* array.
|
||||
*
|
||||
* Rules:
|
||||
*
|
||||
* - The specified curve MUST be supported.
|
||||
*
|
||||
* - The source points (`A` and `B`) must be valid points on
|
||||
* the relevant curve subgroup (and not the "point at
|
||||
* infinity" either). If this is not the case, then this
|
||||
* function returns an error (0).
|
||||
*
|
||||
* - If the `B` pointer is `NULL`, then the conventional
|
||||
* subgroup generator is used. With some implementations,
|
||||
* this may be faster than providing a pointer to the
|
||||
* generator.
|
||||
*
|
||||
* - The multiplier integers (`x` and `y`) MUST be non-zero
|
||||
* and less than the curve subgroup order. If either integer
|
||||
* is zero, then an error is reported, but if one of them is
|
||||
* not lower than the subgroup order, then the result is
|
||||
* indeterminate and an error code is not guaranteed.
|
||||
*
|
||||
* - If the final result is the point at infinity, then an
|
||||
* error is returned.
|
||||
*
|
||||
* Returned value is 1 on success, 0 on error. On error, the
|
||||
* contents of `A` are indeterminate.
|
||||
*
|
||||
* \param A first point to multiply.
|
||||
* \param B second point to multiply (`NULL` for the generator).
|
||||
* \param len common length of the encoded points (in bytes).
|
||||
* \param x multiplier for `A` (unsigned big-endian).
|
||||
* \param xlen length of multiplier for `A` (in bytes).
|
||||
* \param y multiplier for `A` (unsigned big-endian).
|
||||
* \param ylen length of multiplier for `A` (in bytes).
|
||||
* \param curve curve identifier.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve);
|
||||
} br_ec_impl;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i31".
|
||||
*
|
||||
* This implementation internally uses generic code for modular integers,
|
||||
* with a representation as sequences of 31-bit words. It supports secp256r1,
|
||||
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_prime_i31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i15".
|
||||
*
|
||||
* This implementation internally uses generic code for modular integers,
|
||||
* with a representation as sequences of 15-bit words. It supports secp256r1,
|
||||
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_prime_i15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m15" for P-256.
|
||||
*
|
||||
* This implementation uses specialised code for curve secp256r1 (also
|
||||
* known as NIST P-256), with optional Karatsuba decomposition, and fast
|
||||
* modular reduction thanks to the field modulus special format. Only
|
||||
* 32-bit multiplications are used (with 32-bit results, not 64-bit).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m31" for P-256.
|
||||
*
|
||||
* This implementation uses specialised code for curve secp256r1 (also
|
||||
* known as NIST P-256), relying on multiplications of 31-bit values
|
||||
* (MUL31).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_p256_m31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i15" (generic code) for Curve25519.
|
||||
*
|
||||
* This implementation uses the generic code for modular integers (with
|
||||
* 15-bit words) to support Curve25519. Due to the specificities of the
|
||||
* curve definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_i15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "i31" (generic code) for Curve25519.
|
||||
*
|
||||
* This implementation uses the generic code for modular integers (with
|
||||
* 31-bit words) to support Curve25519. Due to the specificities of the
|
||||
* curve definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_i31;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m15" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 15 bits. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m15;
|
||||
|
||||
/**
|
||||
* \brief EC implementation "m31" (specialised code) for Curve25519.
|
||||
*
|
||||
* This implementation uses custom code relying on multiplication of
|
||||
* integers up to 31 bits. Due to the specificities of the curve
|
||||
* definition, the following applies:
|
||||
*
|
||||
* - `muladd()` is not implemented (the function returns 0 systematically).
|
||||
* - `order()` returns 2^255-1, since the point multiplication algorithm
|
||||
* accepts any 32-bit integer as input (it clears the top bit and low
|
||||
* three bits systematically).
|
||||
*/
|
||||
extern const br_ec_impl br_ec_c25519_m31;
|
||||
|
||||
/**
|
||||
* \brief Aggregate EC implementation "m15".
|
||||
*
|
||||
* This implementation is a wrapper for:
|
||||
*
|
||||
* - `br_ec_c25519_m15` for Curve25519
|
||||
* - `br_ec_p256_m15` for NIST P-256
|
||||
* - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512)
|
||||
*/
|
||||
extern const br_ec_impl br_ec_all_m15;
|
||||
|
||||
/**
|
||||
* \brief Aggregate EC implementation "m31".
|
||||
*
|
||||
* This implementation is a wrapper for:
|
||||
*
|
||||
* - `br_ec_c25519_m31` for Curve25519
|
||||
* - `br_ec_p256_m31` for NIST P-256
|
||||
* - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512)
|
||||
*/
|
||||
extern const br_ec_impl br_ec_all_m31;
|
||||
|
||||
/**
|
||||
* \brief Get the "default" EC implementation for the current system.
|
||||
*
|
||||
* This returns a pointer to the preferred implementation on the
|
||||
* current system.
|
||||
*
|
||||
* \return the default EC implementation.
|
||||
*/
|
||||
const br_ec_impl *br_ec_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Convert a signature from "raw" to "asn1".
|
||||
*
|
||||
* Conversion is done "in place" and the new length is returned.
|
||||
* Conversion may enlarge the signature, but by no more than 9 bytes at
|
||||
* most. On error, 0 is returned (error conditions include an odd raw
|
||||
* signature length, or an oversized integer).
|
||||
*
|
||||
* \param sig signature to convert.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return the new signature length, or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Convert a signature from "asn1" to "raw".
|
||||
*
|
||||
* Conversion is done "in place" and the new length is returned.
|
||||
* Conversion may enlarge the signature, but the new signature length
|
||||
* will be less than twice the source length at most. On error, 0 is
|
||||
* returned (error conditions include an invalid ASN.1 structure or an
|
||||
* oversized integer).
|
||||
*
|
||||
* \param sig signature to convert.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return the new signature length, or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Type for an ECDSA signer function.
|
||||
*
|
||||
* A pointer to the EC implementation is provided. The hash value is
|
||||
* assumed to have the length inferred from the designated hash function
|
||||
* class.
|
||||
*
|
||||
* Signature is written in the buffer pointed to by `sig`, and the length
|
||||
* (in bytes) is returned. On error, nothing is written in the buffer,
|
||||
* and 0 is returned. This function returns 0 if the specified curve is
|
||||
* not supported by the provided EC implementation.
|
||||
*
|
||||
* The signature format is either "raw" or "asn1", depending on the
|
||||
* implementation; maximum length is predictable from the implemented
|
||||
* curve:
|
||||
*
|
||||
* | curve | raw | asn1 |
|
||||
* | :--------- | --: | ---: |
|
||||
* | NIST P-256 | 64 | 72 |
|
||||
* | NIST P-384 | 96 | 104 |
|
||||
* | NIST P-521 | 132 | 139 |
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
typedef size_t (*br_ecdsa_sign)(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief Type for an ECDSA signature verification function.
|
||||
*
|
||||
* A pointer to the EC implementation is provided. The hashed value,
|
||||
* computed over the purportedly signed data, is also provided with
|
||||
* its length.
|
||||
*
|
||||
* The signature format is either "raw" or "asn1", depending on the
|
||||
* implementation.
|
||||
*
|
||||
* Returned value is 1 on success (valid signature), 0 on error. This
|
||||
* function returns 0 if the specified curve is not supported by the
|
||||
* provided EC implementation.
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
typedef uint32_t (*br_ecdsa_vrfy)(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i31" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i31_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i31" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i31_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i31" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i31" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i15" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature generator, "i15" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_sign()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hf hash function used to process the data.
|
||||
* \param hash_value signed data (hashed).
|
||||
* \param sk EC private key.
|
||||
* \param sig destination buffer.
|
||||
* \return the signature length (in bytes), or 0 on error.
|
||||
*/
|
||||
size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i15" implementation, "asn1" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief ECDSA signature verifier, "i15" implementation, "raw" format.
|
||||
*
|
||||
* \see br_ecdsa_vrfy()
|
||||
*
|
||||
* \param impl EC implementation to use.
|
||||
* \param hash signed data (hashed).
|
||||
* \param hash_len hash value length (in bytes).
|
||||
* \param pk EC public key.
|
||||
* \param sig signature.
|
||||
* \param sig_len signature length (in bytes).
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk, const void *sig, size_t sig_len);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (signer, asn1 format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature generation
|
||||
* ("asn1" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (signer, raw format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature generation
|
||||
* ("raw" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_sign br_ecdsa_sign_raw_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (verifier, asn1 format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature verification
|
||||
* ("asn1" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Get "default" ECDSA implementation (verifier, raw format).
|
||||
*
|
||||
* This returns the preferred implementation of ECDSA signature verification
|
||||
* ("raw" output format) on the current system.
|
||||
*
|
||||
* \return the default implementation.
|
||||
*/
|
||||
br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void);
|
||||
|
||||
/**
|
||||
* \brief Maximum size for EC private key element buffer.
|
||||
*
|
||||
* This is the largest number of bytes that `br_ec_keygen()` may need or
|
||||
* ever return.
|
||||
*/
|
||||
#define BR_EC_KBUF_PRIV_MAX_SIZE 72
|
||||
|
||||
/**
|
||||
* \brief Maximum size for EC public key element buffer.
|
||||
*
|
||||
* This is the largest number of bytes that `br_ec_compute_public()` may
|
||||
* need or ever return.
|
||||
*/
|
||||
#define BR_EC_KBUF_PUB_MAX_SIZE 145
|
||||
|
||||
/**
|
||||
* \brief Generate a new EC private key.
|
||||
*
|
||||
* If the specified `curve` is not supported by the elliptic curve
|
||||
* implementation (`impl`), then this function returns zero.
|
||||
*
|
||||
* The `sk` structure fields are set to the new private key data. In
|
||||
* particular, `sk.x` is made to point to the provided key buffer (`kbuf`),
|
||||
* in which the actual private key data is written. That buffer is assumed
|
||||
* to be large enough. The `BR_EC_KBUF_PRIV_MAX_SIZE` defines the maximum
|
||||
* size for all supported curves.
|
||||
*
|
||||
* The number of bytes used in `kbuf` is returned. If `kbuf` is `NULL`, then
|
||||
* the private key is not actually generated, and `sk` may also be `NULL`;
|
||||
* the minimum length for `kbuf` is still computed and returned.
|
||||
*
|
||||
* If `sk` is `NULL` but `kbuf` is not `NULL`, then the private key is
|
||||
* still generated and stored in `kbuf`.
|
||||
*
|
||||
* \param rng_ctx source PRNG context (already initialized).
|
||||
* \param impl the elliptic curve implementation.
|
||||
* \param sk the private key structure to fill, or `NULL`.
|
||||
* \param kbuf the key element buffer, or `NULL`.
|
||||
* \param curve the curve identifier.
|
||||
* \return the key data length (in bytes), or zero.
|
||||
*/
|
||||
size_t br_ec_keygen(const br_prng_class **rng_ctx,
|
||||
const br_ec_impl *impl, br_ec_private_key *sk,
|
||||
void *kbuf, int curve);
|
||||
|
||||
/**
|
||||
* \brief Compute EC public key from EC private key.
|
||||
*
|
||||
* This function uses the provided elliptic curve implementation (`impl`)
|
||||
* to compute the public key corresponding to the private key held in `sk`.
|
||||
* The public key point is written into `kbuf`, which is then linked from
|
||||
* the `*pk` structure. The size of the public key point, i.e. the number
|
||||
* of bytes used in `kbuf`, is returned.
|
||||
*
|
||||
* If `kbuf` is `NULL`, then the public key point is NOT computed, and
|
||||
* the public key structure `*pk` is unmodified (`pk` may be `NULL` in
|
||||
* that case). The size of the public key point is still returned.
|
||||
*
|
||||
* If `pk` is `NULL` but `kbuf` is not `NULL`, then the public key
|
||||
* point is computed and stored in `kbuf`, and its size is returned.
|
||||
*
|
||||
* If the curve used by the private key is not supported by the curve
|
||||
* implementation, then this function returns zero.
|
||||
*
|
||||
* The private key MUST be valid. An off-range private key value is not
|
||||
* necessarily detected, and leads to unpredictable results.
|
||||
*
|
||||
* \param impl the elliptic curve implementation.
|
||||
* \param pk the public key structure to fill (or `NULL`).
|
||||
* \param kbuf the public key point buffer (or `NULL`).
|
||||
* \param sk the source private key.
|
||||
* \return the public key point length (in bytes), or zero.
|
||||
*/
|
||||
size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk,
|
||||
void *kbuf, const br_ec_private_key *sk);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1346
dstalk-core/thirdparty/bearssl/inc/bearssl_hash.h
vendored
1346
dstalk-core/thirdparty/bearssl/inc/bearssl_hash.h
vendored
File diff suppressed because it is too large
Load Diff
241
dstalk-core/thirdparty/bearssl/inc/bearssl_hmac.h
vendored
241
dstalk-core/thirdparty/bearssl/inc/bearssl_hmac.h
vendored
@@ -1,241 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_HMAC_H__
|
||||
#define BR_BEARSSL_HMAC_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_hmac.h
|
||||
*
|
||||
* # HMAC
|
||||
*
|
||||
* HMAC is initialized with a key and an underlying hash function; it
|
||||
* then fills a "key context". That context contains the processed
|
||||
* key.
|
||||
*
|
||||
* With the key context, a HMAC context can be initialized to process
|
||||
* the input bytes and obtain the MAC output. The key context is not
|
||||
* modified during that process, and can be reused.
|
||||
*
|
||||
* IMPORTANT: HMAC shall be used only with functions that have the
|
||||
* following properties:
|
||||
*
|
||||
* - hash output size does not exceed 64 bytes;
|
||||
* - hash internal state size does not exceed 64 bytes;
|
||||
* - internal block length is a power of 2 between 16 and 256 bytes.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief HMAC key context.
|
||||
*
|
||||
* The HMAC key context is initialised with a hash function implementation
|
||||
* and a secret key. Contents are opaque (callers should not access them
|
||||
* directly). The caller is responsible for allocating the context where
|
||||
* appropriate. Context initialisation and usage incurs no dynamic
|
||||
* allocation, so there is no release function.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
const br_hash_class *dig_vtable;
|
||||
unsigned char ksi[64], kso[64];
|
||||
#endif
|
||||
} br_hmac_key_context;
|
||||
|
||||
/**
|
||||
* \brief HMAC key context initialisation.
|
||||
*
|
||||
* Initialise the key context with the provided key, using the hash function
|
||||
* identified by `digest_vtable`. This supports arbitrary key lengths.
|
||||
*
|
||||
* \param kc HMAC key context to initialise.
|
||||
* \param digest_vtable pointer to the hash function implementation vtable.
|
||||
* \param key pointer to the HMAC secret key.
|
||||
* \param key_len HMAC secret key length (in bytes).
|
||||
*/
|
||||
void br_hmac_key_init(br_hmac_key_context *kc,
|
||||
const br_hash_class *digest_vtable, const void *key, size_t key_len);
|
||||
|
||||
/*
|
||||
* \brief Get the underlying hash function.
|
||||
*
|
||||
* This function returns a pointer to the implementation vtable of the
|
||||
* hash function used for this HMAC key context.
|
||||
*
|
||||
* \param kc HMAC key context.
|
||||
* \return the hash function implementation.
|
||||
*/
|
||||
static inline const br_hash_class *br_hmac_key_get_digest(
|
||||
const br_hmac_key_context *kc)
|
||||
{
|
||||
return kc->dig_vtable;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief HMAC computation context.
|
||||
*
|
||||
* The HMAC computation context maintains the state for a single HMAC
|
||||
* computation. It is modified as input bytes are injected. The context
|
||||
* is caller-allocated and has no release function since it does not
|
||||
* dynamically allocate external resources. Its contents are opaque.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
br_hash_compat_context dig;
|
||||
unsigned char kso[64];
|
||||
size_t out_len;
|
||||
#endif
|
||||
} br_hmac_context;
|
||||
|
||||
/**
|
||||
* \brief HMAC computation initialisation.
|
||||
*
|
||||
* Initialise a HMAC context with a key context. The key context is
|
||||
* unmodified. Relevant data from the key context is immediately copied;
|
||||
* the key context can thus be independently reused, modified or released
|
||||
* without impacting this HMAC computation.
|
||||
*
|
||||
* An explicit output length can be specified; the actual output length
|
||||
* will be the minimum of that value and the natural HMAC output length.
|
||||
* If `out_len` is 0, then the natural HMAC output length is selected. The
|
||||
* "natural output length" is the output length of the underlying hash
|
||||
* function.
|
||||
*
|
||||
* \param ctx HMAC context to initialise.
|
||||
* \param kc HMAC key context (already initialised with the key).
|
||||
* \param out_len HMAC output length (0 to select "natural length").
|
||||
*/
|
||||
void br_hmac_init(br_hmac_context *ctx,
|
||||
const br_hmac_key_context *kc, size_t out_len);
|
||||
|
||||
/**
|
||||
* \brief Get the HMAC output size.
|
||||
*
|
||||
* The HMAC output size is the number of bytes that will actually be
|
||||
* produced with `br_hmac_out()` with the provided context. This function
|
||||
* MUST NOT be called on a non-initialised HMAC computation context.
|
||||
* The returned value is the minimum of the HMAC natural length (output
|
||||
* size of the underlying hash function) and the `out_len` parameter which
|
||||
* was used with the last `br_hmac_init()` call on that context (if the
|
||||
* initialisation `out_len` parameter was 0, then this function will
|
||||
* return the HMAC natural length).
|
||||
*
|
||||
* \param ctx the (already initialised) HMAC computation context.
|
||||
* \return the HMAC actual output size.
|
||||
*/
|
||||
static inline size_t
|
||||
br_hmac_size(br_hmac_context *ctx)
|
||||
{
|
||||
return ctx->out_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Get the underlying hash function.
|
||||
*
|
||||
* This function returns a pointer to the implementation vtable of the
|
||||
* hash function used for this HMAC context.
|
||||
*
|
||||
* \param hc HMAC context.
|
||||
* \return the hash function implementation.
|
||||
*/
|
||||
static inline const br_hash_class *br_hmac_get_digest(
|
||||
const br_hmac_context *hc)
|
||||
{
|
||||
return hc->dig.vtable;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Inject some bytes in HMAC.
|
||||
*
|
||||
* The provided `len` bytes are injected as extra input in the HMAC
|
||||
* computation incarnated by the `ctx` HMAC context. It is acceptable
|
||||
* that `len` is zero, in which case `data` is ignored (and may be
|
||||
* `NULL`) and this function does nothing.
|
||||
*/
|
||||
void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Compute the HMAC output.
|
||||
*
|
||||
* The destination buffer MUST be large enough to accommodate the result;
|
||||
* its length is at most the "natural length" of HMAC (i.e. the output
|
||||
* length of the underlying hash function). The context is NOT modified;
|
||||
* further bytes may be processed. Thus, "partial HMAC" values can be
|
||||
* efficiently obtained.
|
||||
*
|
||||
* Returned value is the output length (in bytes).
|
||||
*
|
||||
* \param ctx HMAC computation context.
|
||||
* \param out destination buffer for the HMAC output.
|
||||
* \return the produced value length (in bytes).
|
||||
*/
|
||||
size_t br_hmac_out(const br_hmac_context *ctx, void *out);
|
||||
|
||||
/**
|
||||
* \brief Constant-time HMAC computation.
|
||||
*
|
||||
* This function compute the HMAC output in constant time. Some extra
|
||||
* input bytes are processed, then the output is computed. The extra
|
||||
* input consists in the `len` bytes pointed to by `data`. The `len`
|
||||
* parameter must lie between `min_len` and `max_len` (inclusive);
|
||||
* `max_len` bytes are actually read from `data`. Computing time (and
|
||||
* memory access pattern) will not depend upon the data byte contents or
|
||||
* the value of `len`.
|
||||
*
|
||||
* The output is written in the `out` buffer, that MUST be large enough
|
||||
* to receive it.
|
||||
*
|
||||
* The difference `max_len - min_len` MUST be less than 2<sup>30</sup>
|
||||
* (i.e. about one gigabyte).
|
||||
*
|
||||
* This function computes the output properly only if the underlying
|
||||
* hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256,
|
||||
* SHA-384 or SHA-512).
|
||||
*
|
||||
* The provided context is NOT modified.
|
||||
*
|
||||
* \param ctx the (already initialised) HMAC computation context.
|
||||
* \param data the extra input bytes.
|
||||
* \param len the extra input length (in bytes).
|
||||
* \param min_len minimum extra input length (in bytes).
|
||||
* \param max_len maximum extra input length (in bytes).
|
||||
* \param out destination buffer for the HMAC output.
|
||||
* \return the produced value length (in bytes).
|
||||
*/
|
||||
size_t br_hmac_outCT(const br_hmac_context *ctx,
|
||||
const void *data, size_t len, size_t min_len, size_t max_len,
|
||||
void *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
185
dstalk-core/thirdparty/bearssl/inc/bearssl_kdf.h
vendored
185
dstalk-core/thirdparty/bearssl/inc/bearssl_kdf.h
vendored
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_KDF_H__
|
||||
#define BR_BEARSSL_KDF_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_hash.h"
|
||||
#include "bearssl_hmac.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_kdf.h
|
||||
*
|
||||
* # Key Derivation Functions
|
||||
*
|
||||
* KDF are functions that takes a variable length input, and provide a
|
||||
* variable length output, meant to be used to derive subkeys from a
|
||||
* master key.
|
||||
*
|
||||
* ## HKDF
|
||||
*
|
||||
* HKDF is a KDF defined by [RFC 5869](https://tools.ietf.org/html/rfc5869).
|
||||
* It is based on HMAC, itself using an underlying hash function. Any
|
||||
* hash function can be used, as long as it is compatible with the rules
|
||||
* for the HMAC implementation (i.e. output size is 64 bytes or less, hash
|
||||
* internal state size is 64 bytes or less, and the internal block length is
|
||||
* a power of 2 between 16 and 256 bytes). HKDF has two phases:
|
||||
*
|
||||
* - HKDF-Extract: the input data in ingested, along with a "salt" value.
|
||||
*
|
||||
* - HKDF-Expand: the output is produced, from the result of processing
|
||||
* the input and salt, and using an extra non-secret parameter called
|
||||
* "info".
|
||||
*
|
||||
* The "salt" and "info" strings are non-secret and can be empty. Their role
|
||||
* is normally to bind the input and output, respectively, to conventional
|
||||
* identifiers that qualifu them within the used protocol or application.
|
||||
*
|
||||
* The implementation defined in this file uses the following functions:
|
||||
*
|
||||
* - `br_hkdf_init()`: initialize an HKDF context, with a hash function,
|
||||
* and the salt. This starts the HKDF-Extract process.
|
||||
*
|
||||
* - `br_hkdf_inject()`: inject more input bytes. This function may be
|
||||
* called repeatedly if the input data is provided by chunks.
|
||||
*
|
||||
* - `br_hkdf_flip()`: end the HKDF-Extract process, and start the
|
||||
* HKDF-Expand process.
|
||||
*
|
||||
* - `br_hkdf_produce()`: get the next bytes of output. This function
|
||||
* may be called several times to obtain the full output by chunks.
|
||||
* For correct HKDF processing, the same "info" string must be
|
||||
* provided for each call.
|
||||
*
|
||||
* Note that the HKDF total output size (the number of bytes that
|
||||
* HKDF-Expand is willing to produce) is limited: if the hash output size
|
||||
* is _n_ bytes, then the maximum output size is _255*n_.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief HKDF context.
|
||||
*
|
||||
* The HKDF context is initialized with a hash function implementation
|
||||
* and a salt value. Contents are opaque (callers should not access them
|
||||
* directly). The caller is responsible for allocating the context where
|
||||
* appropriate. Context initialisation and usage incurs no dynamic
|
||||
* allocation, so there is no release function.
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
union {
|
||||
br_hmac_context hmac_ctx;
|
||||
br_hmac_key_context prk_ctx;
|
||||
} u;
|
||||
unsigned char buf[64];
|
||||
size_t ptr;
|
||||
size_t dig_len;
|
||||
unsigned chunk_num;
|
||||
#endif
|
||||
} br_hkdf_context;
|
||||
|
||||
/**
|
||||
* \brief HKDF context initialization.
|
||||
*
|
||||
* The underlying hash function and salt value are provided. Arbitrary
|
||||
* salt lengths can be used.
|
||||
*
|
||||
* HKDF makes a difference between a salt of length zero, and an
|
||||
* absent salt (the latter being equivalent to a salt consisting of
|
||||
* bytes of value zero, of the same length as the hash function output).
|
||||
* If `salt_len` is zero, then this function assumes that the salt is
|
||||
* present but of length zero. To specify an _absent_ salt, use
|
||||
* `BR_HKDF_NO_SALT` as `salt` parameter (`salt_len` is then ignored).
|
||||
*
|
||||
* \param hc HKDF context to initialise.
|
||||
* \param digest_vtable pointer to the hash function implementation vtable.
|
||||
* \param salt HKDF-Extract salt.
|
||||
* \param salt_len HKDF-Extract salt length (in bytes).
|
||||
*/
|
||||
void br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable,
|
||||
const void *salt, size_t salt_len);
|
||||
|
||||
/**
|
||||
* \brief The special "absent salt" value for HKDF.
|
||||
*/
|
||||
#define BR_HKDF_NO_SALT (&br_hkdf_no_salt)
|
||||
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
extern const unsigned char br_hkdf_no_salt;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief HKDF input injection (HKDF-Extract).
|
||||
*
|
||||
* This function injects some more input bytes ("key material") into
|
||||
* HKDF. This function may be called several times, after `br_hkdf_init()`
|
||||
* but before `br_hkdf_flip()`.
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
* \param ikm extra input bytes.
|
||||
* \param ikm_len number of extra input bytes.
|
||||
*/
|
||||
void br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len);
|
||||
|
||||
/**
|
||||
* \brief HKDF switch to the HKDF-Expand phase.
|
||||
*
|
||||
* This call terminates the HKDF-Extract process (input injection), and
|
||||
* starts the HKDF-Expand process (output production).
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
*/
|
||||
void br_hkdf_flip(br_hkdf_context *hc);
|
||||
|
||||
/**
|
||||
* \brief HKDF output production (HKDF-Expand).
|
||||
*
|
||||
* Produce more output bytes from the current state. This function may be
|
||||
* called several times, but only after `br_hkdf_flip()`.
|
||||
*
|
||||
* Returned value is the number of actually produced bytes. The total
|
||||
* output length is limited to 255 times the output length of the
|
||||
* underlying hash function.
|
||||
*
|
||||
* \param hc HKDF context.
|
||||
* \param info application specific information string.
|
||||
* \param info_len application specific information string length (in bytes).
|
||||
* \param out destination buffer for the HKDF output.
|
||||
* \param out_len the length of the requested output (in bytes).
|
||||
* \return the produced output length (in bytes).
|
||||
*/
|
||||
size_t br_hkdf_produce(br_hkdf_context *hc,
|
||||
const void *info, size_t info_len, void *out, size_t out_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
294
dstalk-core/thirdparty/bearssl/inc/bearssl_pem.h
vendored
294
dstalk-core/thirdparty/bearssl/inc/bearssl_pem.h
vendored
@@ -1,294 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_PEM_H__
|
||||
#define BR_BEARSSL_PEM_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_pem.h
|
||||
*
|
||||
* # PEM Support
|
||||
*
|
||||
* PEM is a traditional encoding layer use to store binary objects (in
|
||||
* particular X.509 certificates, and private keys) in text files. While
|
||||
* the acronym comes from an old, defunct standard ("Privacy Enhanced
|
||||
* Mail"), the format has been reused, with some variations, by many
|
||||
* systems, and is a _de facto_ standard, even though it is not, actually,
|
||||
* specified in all clarity anywhere.
|
||||
*
|
||||
* ## Format Details
|
||||
*
|
||||
* BearSSL contains a generic, streamed PEM decoder, which handles the
|
||||
* following format:
|
||||
*
|
||||
* - The input source (a sequence of bytes) is assumed to be the
|
||||
* encoding of a text file in an ASCII-compatible charset. This
|
||||
* includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each
|
||||
* line ends on a newline character (U+000A LINE FEED). The
|
||||
* U+000D CARRIAGE RETURN characters are ignored, so the code
|
||||
* accepts both Windows-style and Unix-style line endings.
|
||||
*
|
||||
* - Each object begins with a banner that occurs at the start of
|
||||
* a line; the first banner characters are "`-----BEGIN `" (five
|
||||
* dashes, the word "BEGIN", and a space). The banner matching is
|
||||
* not case-sensitive.
|
||||
*
|
||||
* - The _object name_ consists in the characters that follow the
|
||||
* banner start sequence, up to the end of the line, but without
|
||||
* trailing dashes (in "normal" PEM, there are five trailing
|
||||
* dashes, but this implementation is not picky about these dashes).
|
||||
* The BearSSL decoder normalises the name characters to uppercase
|
||||
* (for ASCII letters only) and accepts names up to 127 characters.
|
||||
*
|
||||
* - The object ends with a banner that again occurs at the start of
|
||||
* a line, and starts with "`-----END `" (again case-insensitive).
|
||||
*
|
||||
* - Between that start and end banner, only Base64 data shall occur.
|
||||
* Base64 converts each sequence of three bytes into four
|
||||
* characters; the four characters are ASCII letters, digits, "`+`"
|
||||
* or "`-`" signs, and one or two "`=`" signs may occur in the last
|
||||
* quartet. Whitespace is ignored (whitespace is any ASCII character
|
||||
* of code 32 or less, so control characters are whitespace) and
|
||||
* lines may have arbitrary length; the only restriction is that the
|
||||
* four characters of a quartet must appear on the same line (no
|
||||
* line break inside a quartet).
|
||||
*
|
||||
* - A single file may contain more than one PEM object. Bytes that
|
||||
* occur between objects are ignored.
|
||||
*
|
||||
*
|
||||
* ## PEM Decoder API
|
||||
*
|
||||
* The PEM decoder offers a state-machine API. The caller allocates a
|
||||
* decoder context, then injects source bytes. Source bytes are pushed
|
||||
* with `br_pem_decoder_push()`. The decoder stops accepting bytes when
|
||||
* it reaches an "event", which is either the start of an object, the
|
||||
* end of an object, or a decoding error within an object.
|
||||
*
|
||||
* The `br_pem_decoder_event()` function is used to obtain the current
|
||||
* event; it also clears it, thus allowing the decoder to accept more
|
||||
* bytes. When a object start event is raised, the decoder context
|
||||
* offers the found object name (normalised to ASCII uppercase).
|
||||
*
|
||||
* When an object is reached, the caller must set an appropriate callback
|
||||
* function, which will receive (by chunks) the decoded object data.
|
||||
*
|
||||
* Since the decoder context makes no dynamic allocation, it requires
|
||||
* no explicit deallocation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief PEM decoder context.
|
||||
*
|
||||
* Contents are opaque (they should not be accessed directly).
|
||||
*/
|
||||
typedef struct {
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
/* CPU for the T0 virtual machine. */
|
||||
struct {
|
||||
uint32_t *dp;
|
||||
uint32_t *rp;
|
||||
const unsigned char *ip;
|
||||
} cpu;
|
||||
uint32_t dp_stack[32];
|
||||
uint32_t rp_stack[32];
|
||||
int err;
|
||||
|
||||
const unsigned char *hbuf;
|
||||
size_t hlen;
|
||||
|
||||
void (*dest)(void *dest_ctx, const void *src, size_t len);
|
||||
void *dest_ctx;
|
||||
|
||||
unsigned char event;
|
||||
char name[128];
|
||||
unsigned char buf[255];
|
||||
size_t ptr;
|
||||
#endif
|
||||
} br_pem_decoder_context;
|
||||
|
||||
/**
|
||||
* \brief Initialise a PEM decoder structure.
|
||||
*
|
||||
* \param ctx decoder context to initialise.
|
||||
*/
|
||||
void br_pem_decoder_init(br_pem_decoder_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Push some bytes into the decoder.
|
||||
*
|
||||
* Returned value is the number of bytes actually consumed; this may be
|
||||
* less than the number of provided bytes if an event is raised. When an
|
||||
* event is raised, it must be read (with `br_pem_decoder_event()`);
|
||||
* until the event is read, this function will return 0.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \param data new data bytes.
|
||||
* \param len number of new data bytes.
|
||||
* \return the number of bytes actually received (may be less than `len`).
|
||||
*/
|
||||
size_t br_pem_decoder_push(br_pem_decoder_context *ctx,
|
||||
const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Set the receiver for decoded data.
|
||||
*
|
||||
* When an object is entered, the provided function (with opaque context
|
||||
* pointer) will be called repeatedly with successive chunks of decoded
|
||||
* data for that object. If `dest` is set to 0, then decoded data is
|
||||
* simply ignored. The receiver can be set at any time, but, in practice,
|
||||
* it should be called immediately after receiving a "start of object"
|
||||
* event.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \param dest callback for receiving decoded data.
|
||||
* \param dest_ctx opaque context pointer for the `dest` callback.
|
||||
*/
|
||||
static inline void
|
||||
br_pem_decoder_setdest(br_pem_decoder_context *ctx,
|
||||
void (*dest)(void *dest_ctx, const void *src, size_t len),
|
||||
void *dest_ctx)
|
||||
{
|
||||
ctx->dest = dest;
|
||||
ctx->dest_ctx = dest_ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the last event.
|
||||
*
|
||||
* If an event was raised, then this function returns the event value, and
|
||||
* also clears it, thereby allowing the decoder to proceed. If no event
|
||||
* was raised since the last call to `br_pem_decoder_event()`, then this
|
||||
* function returns 0.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \return the raised event, or 0.
|
||||
*/
|
||||
int br_pem_decoder_event(br_pem_decoder_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief Event: start of object.
|
||||
*
|
||||
* This event is raised when the start of a new object has been detected.
|
||||
* The object name (normalised to uppercase) can be accessed with
|
||||
* `br_pem_decoder_name()`.
|
||||
*/
|
||||
#define BR_PEM_BEGIN_OBJ 1
|
||||
|
||||
/**
|
||||
* \brief Event: end of object.
|
||||
*
|
||||
* This event is raised when the end of the current object is reached
|
||||
* (normally, i.e. with no decoding error).
|
||||
*/
|
||||
#define BR_PEM_END_OBJ 2
|
||||
|
||||
/**
|
||||
* \brief Event: decoding error.
|
||||
*
|
||||
* This event is raised when decoding fails within an object.
|
||||
* This formally closes the current object and brings the decoder back
|
||||
* to the "out of any object" state. The offending line in the source
|
||||
* is consumed.
|
||||
*/
|
||||
#define BR_PEM_ERROR 3
|
||||
|
||||
/**
|
||||
* \brief Get the name of the encountered object.
|
||||
*
|
||||
* The encountered object name is defined only when the "start of object"
|
||||
* event is raised. That name is normalised to uppercase (for ASCII letters
|
||||
* only) and does not include trailing dashes.
|
||||
*
|
||||
* \param ctx decoder context.
|
||||
* \return the current object name.
|
||||
*/
|
||||
static inline const char *
|
||||
br_pem_decoder_name(br_pem_decoder_context *ctx)
|
||||
{
|
||||
return ctx->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Encode an object in PEM.
|
||||
*
|
||||
* This function encodes the provided binary object (`data`, of length `len`
|
||||
* bytes) into PEM. The `banner` text will be included in the header and
|
||||
* footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header).
|
||||
*
|
||||
* The length (in characters) of the PEM output is returned; that length
|
||||
* does NOT include the terminating zero, that this function nevertheless
|
||||
* adds. If using the returned value for allocation purposes, the allocated
|
||||
* buffer size MUST be at least one byte larger than the returned size.
|
||||
*
|
||||
* If `dest` is `NULL`, then the encoding does not happen; however, the
|
||||
* length of the encoded object is still computed and returned.
|
||||
*
|
||||
* The `data` pointer may be `NULL` only if `len` is zero (when encoding
|
||||
* an object of length zero, which is not very useful), or when `dest`
|
||||
* is `NULL` (in that case, source data bytes are ignored).
|
||||
*
|
||||
* Some `flags` can be specified to alter the encoding behaviour:
|
||||
*
|
||||
* - If `BR_PEM_LINE64` is set, then line-breaking will occur after
|
||||
* every 64 characters of output, instead of the default of 76.
|
||||
*
|
||||
* - If `BR_PEM_CRLF` is set, then end-of-line sequence will use
|
||||
* CR+LF instead of a single LF.
|
||||
*
|
||||
* The `data` and `dest` buffers may overlap, in which case the source
|
||||
* binary data is destroyed in the process. Note that the PEM-encoded output
|
||||
* is always larger than the source binary.
|
||||
*
|
||||
* \param dest the destination buffer (or `NULL`).
|
||||
* \param data the source buffer (can be `NULL` in some cases).
|
||||
* \param len the source length (in bytes).
|
||||
* \param banner the PEM banner expression.
|
||||
* \param flags the behavioural flags.
|
||||
* \return the PEM object length (in characters), EXCLUDING the final zero.
|
||||
*/
|
||||
size_t br_pem_encode(void *dest, const void *data, size_t len,
|
||||
const char *banner, unsigned flags);
|
||||
|
||||
/**
|
||||
* \brief PEM encoding flag: split lines at 64 characters.
|
||||
*/
|
||||
#define BR_PEM_LINE64 0x0001
|
||||
|
||||
/**
|
||||
* \brief PEM encoding flag: use CR+LF line endings.
|
||||
*/
|
||||
#define BR_PEM_CRLF 0x0002
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
150
dstalk-core/thirdparty/bearssl/inc/bearssl_prf.h
vendored
150
dstalk-core/thirdparty/bearssl/inc/bearssl_prf.h
vendored
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_PRF_H__
|
||||
#define BR_BEARSSL_PRF_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_prf.h
|
||||
*
|
||||
* # The TLS PRF
|
||||
*
|
||||
* The "PRF" is the pseudorandom function used internally during the
|
||||
* SSL/TLS handshake, notably to expand negotiated shared secrets into
|
||||
* the symmetric encryption keys that will be used to process the
|
||||
* application data.
|
||||
*
|
||||
* TLS 1.0 and 1.1 define a PRF that is based on both MD5 and SHA-1. This
|
||||
* is implemented by the `br_tls10_prf()` function.
|
||||
*
|
||||
* TLS 1.2 redefines the PRF, using an explicit hash function. The
|
||||
* `br_tls12_sha256_prf()` and `br_tls12_sha384_prf()` functions apply that
|
||||
* PRF with, respectively, SHA-256 and SHA-384. Most standard cipher suites
|
||||
* rely on the SHA-256 based PRF, but some use SHA-384.
|
||||
*
|
||||
* The PRF always uses as input three parameters: a "secret" (some
|
||||
* bytes), a "label" (ASCII string), and a "seed" (again some bytes). An
|
||||
* arbitrary output length can be produced. The "seed" is provided as an
|
||||
* arbitrary number of binary chunks, that gets internally concatenated.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Type for a seed chunk.
|
||||
*
|
||||
* Each chunk may have an arbitrary length, and may be empty (no byte at
|
||||
* all). If the chunk length is zero, then the pointer to the chunk data
|
||||
* may be `NULL`.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the chunk data.
|
||||
*/
|
||||
const void *data;
|
||||
|
||||
/**
|
||||
* \brief Chunk length (in bytes).
|
||||
*/
|
||||
size_t len;
|
||||
} br_tls_prf_seed_chunk;
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.0 and 1.1.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.0 and 1.1. It internally uses
|
||||
* MD5 and SHA-1.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls10_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.2, with SHA-256.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.2, when the underlying hash
|
||||
* function is SHA-256.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls12_sha256_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* \brief PRF implementation for TLS 1.2, with SHA-384.
|
||||
*
|
||||
* This PRF is the one specified by TLS 1.2, when the underlying hash
|
||||
* function is SHA-384.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
void br_tls12_sha384_prf(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
/**
|
||||
* brief A convenient type name for a PRF implementation.
|
||||
*
|
||||
* \param dst destination buffer.
|
||||
* \param len output length (in bytes).
|
||||
* \param secret secret value (key) for this computation.
|
||||
* \param secret_len length of "secret" (in bytes).
|
||||
* \param label PRF label (zero-terminated ASCII string).
|
||||
* \param seed_num number of seed chunks.
|
||||
* \param seed seed chnks for this computation (usually non-secret).
|
||||
*/
|
||||
typedef void (*br_tls_prf_impl)(void *dst, size_t len,
|
||||
const void *secret, size_t secret_len, const char *label,
|
||||
size_t seed_num, const br_tls_prf_seed_chunk *seed);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
397
dstalk-core/thirdparty/bearssl/inc/bearssl_rand.h
vendored
397
dstalk-core/thirdparty/bearssl/inc/bearssl_rand.h
vendored
@@ -1,397 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BR_BEARSSL_RAND_H__
|
||||
#define BR_BEARSSL_RAND_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bearssl_block.h"
|
||||
#include "bearssl_hash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \file bearssl_rand.h
|
||||
*
|
||||
* # Pseudo-Random Generators
|
||||
*
|
||||
* A PRNG is a state-based engine that outputs pseudo-random bytes on
|
||||
* demand. It is initialized with an initial seed, and additional seed
|
||||
* bytes can be added afterwards. Bytes produced depend on the seeds and
|
||||
* also on the exact sequence of calls (including sizes requested for
|
||||
* each call).
|
||||
*
|
||||
*
|
||||
* ## Procedural and OOP API
|
||||
*
|
||||
* For the PRNG of name "`xxx`", two API are provided. The _procedural_
|
||||
* API defined a context structure `br_xxx_context` and three functions:
|
||||
*
|
||||
* - `br_xxx_init()`
|
||||
*
|
||||
* Initialise the context with an initial seed.
|
||||
*
|
||||
* - `br_xxx_generate()`
|
||||
*
|
||||
* Produce some pseudo-random bytes.
|
||||
*
|
||||
* - `br_xxx_update()`
|
||||
*
|
||||
* Inject some additional seed.
|
||||
*
|
||||
* The initialisation function sets the first context field (`vtable`)
|
||||
* to a pointer to the vtable that supports the OOP API. The OOP API
|
||||
* provides access to the same functions through function pointers,
|
||||
* named `init()`, `generate()` and `update()`.
|
||||
*
|
||||
* Note that the context initialisation method may accept additional
|
||||
* parameters, provided as a 'const void *' pointer at API level. These
|
||||
* additional parameters depend on the implemented PRNG.
|
||||
*
|
||||
*
|
||||
* ## HMAC_DRBG
|
||||
*
|
||||
* HMAC_DRBG is defined in [NIST SP 800-90A Revision
|
||||
* 1](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf).
|
||||
* It uses HMAC repeatedly, over some configurable underlying hash
|
||||
* function. In BearSSL, it is implemented under the "`hmac_drbg`" name.
|
||||
* The "extra parameters" pointer for context initialisation should be
|
||||
* set to a pointer to the vtable for the underlying hash function (e.g.
|
||||
* pointer to `br_sha256_vtable` to use HMAC_DRBG with SHA-256).
|
||||
*
|
||||
* According to the NIST standard, each request shall produce up to
|
||||
* 2<sup>19</sup> bits (i.e. 64 kB of data); moreover, the context shall
|
||||
* be reseeded at least once every 2<sup>48</sup> requests. This
|
||||
* implementation does not maintain the reseed counter (the threshold is
|
||||
* too high to be reached in practice) and does not object to producing
|
||||
* more than 64 kB in a single request; thus, the code cannot fail,
|
||||
* which corresponds to the fact that the API has no room for error
|
||||
* codes. However, this implies that requesting more than 64 kB in one
|
||||
* `generate()` request, or making more than 2<sup>48</sup> requests
|
||||
* without reseeding, is formally out of NIST specification. There is
|
||||
* no currently known security penalty for exceeding the NIST limits,
|
||||
* and, in any case, HMAC_DRBG usage in implementing SSL/TLS always
|
||||
* stays much below these thresholds.
|
||||
*
|
||||
*
|
||||
* ## AESCTR_DRBG
|
||||
*
|
||||
* AESCTR_DRBG is a custom PRNG based on AES-128 in CTR mode. This is
|
||||
* meant to be used only in situations where you are desperate for
|
||||
* speed, and have an hardware-optimized AES/CTR implementation. Whether
|
||||
* this will yield perceptible improvements depends on what you use the
|
||||
* pseudorandom bytes for, and how many you want; for instance, RSA key
|
||||
* pair generation uses a substantial amount of randomness, and using
|
||||
* AESCTR_DRBG instead of HMAC_DRBG yields a 15 to 20% increase in key
|
||||
* generation speed on a recent x86 CPU (Intel Core i7-6567U at 3.30 GHz).
|
||||
*
|
||||
* Internally, it uses CTR mode with successive counter values, starting
|
||||
* at zero (counter value expressed over 128 bits, big-endian convention).
|
||||
* The counter is not allowed to reach 32768; thus, every 32768*16 bytes
|
||||
* at most, the `update()` function is run (on an empty seed, if none is
|
||||
* provided). The `update()` function computes the new AES-128 key by
|
||||
* applying a custom hash function to the concatenation of a state-dependent
|
||||
* word (encryption of an all-one block with the current key) and the new
|
||||
* seed. The custom hash function uses Hirose's construction over AES-256;
|
||||
* see the comments in `aesctr_drbg.c` for details.
|
||||
*
|
||||
* This DRBG does not follow an existing standard, and thus should be
|
||||
* considered as inadequate for production use until it has been properly
|
||||
* analysed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Class type for PRNG implementations.
|
||||
*
|
||||
* A `br_prng_class` instance references the methods implementing a PRNG.
|
||||
* Constant instances of this structure are defined for each implemented
|
||||
* PRNG. Such instances are also called "vtables".
|
||||
*/
|
||||
typedef struct br_prng_class_ br_prng_class;
|
||||
struct br_prng_class_ {
|
||||
/**
|
||||
* \brief Size (in bytes) of the context structure appropriate for
|
||||
* running this PRNG.
|
||||
*/
|
||||
size_t context_size;
|
||||
|
||||
/**
|
||||
* \brief Initialisation method.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its
|
||||
* first field (the vtable pointer); this function sets that
|
||||
* first field to a pointer to the vtable.
|
||||
*
|
||||
* The extra parameters depend on the implementation; each
|
||||
* implementation defines what kind of extra parameters it
|
||||
* expects (if any).
|
||||
*
|
||||
* Requirements on the initial seed depend on the implemented
|
||||
* PRNG.
|
||||
*
|
||||
* \param ctx PRNG context to initialise.
|
||||
* \param params extra parameters for the PRNG.
|
||||
* \param seed initial seed.
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void (*init)(const br_prng_class **ctx, const void *params,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly.
|
||||
*
|
||||
* \param ctx PRNG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void (*generate)(const br_prng_class **ctx, void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes.
|
||||
*
|
||||
* The provided seed bytes are added into the PRNG internal
|
||||
* entropy pool.
|
||||
*
|
||||
* \param ctx PRNG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void (*update)(const br_prng_class **ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Context for HMAC_DRBG.
|
||||
*
|
||||
* The context contents are opaque, except the first field, which
|
||||
* supports OOP.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the vtable.
|
||||
*
|
||||
* This field is set with the initialisation method/function.
|
||||
*/
|
||||
const br_prng_class *vtable;
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
unsigned char K[64];
|
||||
unsigned char V[64];
|
||||
const br_hash_class *digest_class;
|
||||
#endif
|
||||
} br_hmac_drbg_context;
|
||||
|
||||
/**
|
||||
* \brief Statically allocated, constant vtable for HMAC_DRBG.
|
||||
*/
|
||||
extern const br_prng_class br_hmac_drbg_vtable;
|
||||
|
||||
/**
|
||||
* \brief HMAC_DRBG initialisation.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its first field
|
||||
* (the vtable pointer); this function sets that first field to a
|
||||
* pointer to the vtable.
|
||||
*
|
||||
* The `seed` value is what is called, in NIST terminology, the
|
||||
* concatenation of the "seed", "nonce" and "personalization string", in
|
||||
* that order.
|
||||
*
|
||||
* The `digest_class` parameter defines the underlying hash function.
|
||||
* Formally, the NIST standard specifies that the hash function shall
|
||||
* be only SHA-1 or one of the SHA-2 functions. This implementation also
|
||||
* works with any other implemented hash function (such as MD5), but
|
||||
* this is non-standard and therefore not recommended.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context to initialise.
|
||||
* \param digest_class vtable for the underlying hash function.
|
||||
* \param seed initial seed.
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void br_hmac_drbg_init(br_hmac_drbg_context *ctx,
|
||||
const br_hash_class *digest_class, const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation with HMAC_DRBG.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly. Formally, requesting
|
||||
* more than 65536 bytes in one request falls out of specification
|
||||
* limits (but it won't fail).
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes in HMAC_DRBG.
|
||||
*
|
||||
* The provided seed bytes are added into the HMAC_DRBG internal
|
||||
* entropy pool. The process does not _replace_ existing entropy,
|
||||
* thus pushing non-random bytes (i.e. bytes which are known to the
|
||||
* attackers) does not degrade the overall quality of generated bytes.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void br_hmac_drbg_update(br_hmac_drbg_context *ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Get the hash function implementation used by a given instance of
|
||||
* HMAC_DRBG.
|
||||
*
|
||||
* This calls MUST NOT be performed on a context which was not
|
||||
* previously initialised.
|
||||
*
|
||||
* \param ctx HMAC_DRBG context.
|
||||
* \return the hash function vtable.
|
||||
*/
|
||||
static inline const br_hash_class *
|
||||
br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx)
|
||||
{
|
||||
return ctx->digest_class;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Type for a provider of entropy seeds.
|
||||
*
|
||||
* A "seeder" is a function that is able to obtain random values from
|
||||
* some source and inject them as entropy seed in a PRNG. A seeder
|
||||
* shall guarantee that the total entropy of the injected seed is large
|
||||
* enough to seed a PRNG for purposes of cryptographic key generation
|
||||
* (i.e. at least 128 bits).
|
||||
*
|
||||
* A seeder may report a failure to obtain adequate entropy. Seeders
|
||||
* shall endeavour to fix themselves transient errors by trying again;
|
||||
* thus, callers may consider reported errors as permanent.
|
||||
*
|
||||
* \param ctx PRNG context to seed.
|
||||
* \return 1 on success, 0 on error.
|
||||
*/
|
||||
typedef int (*br_prng_seeder)(const br_prng_class **ctx);
|
||||
|
||||
/**
|
||||
* \brief Get a seeder backed by the operating system or hardware.
|
||||
*
|
||||
* Get a seeder that feeds on RNG facilities provided by the current
|
||||
* operating system or hardware. If no such facility is known, then 0
|
||||
* is returned.
|
||||
*
|
||||
* If `name` is not `NULL`, then `*name` is set to a symbolic string
|
||||
* that identifies the seeder implementation. If no seeder is returned
|
||||
* and `name` is not `NULL`, then `*name` is set to a pointer to the
|
||||
* constant string `"none"`.
|
||||
*
|
||||
* \param name receiver for seeder name, or `NULL`.
|
||||
* \return the system seeder, if available, or 0.
|
||||
*/
|
||||
br_prng_seeder br_prng_seeder_system(const char **name);
|
||||
|
||||
/**
|
||||
* \brief Context for AESCTR_DRBG.
|
||||
*
|
||||
* The context contents are opaque, except the first field, which
|
||||
* supports OOP.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Pointer to the vtable.
|
||||
*
|
||||
* This field is set with the initialisation method/function.
|
||||
*/
|
||||
const br_prng_class *vtable;
|
||||
#ifndef BR_DOXYGEN_IGNORE
|
||||
br_aes_gen_ctr_keys sk;
|
||||
uint32_t cc;
|
||||
#endif
|
||||
} br_aesctr_drbg_context;
|
||||
|
||||
/**
|
||||
* \brief Statically allocated, constant vtable for AESCTR_DRBG.
|
||||
*/
|
||||
extern const br_prng_class br_aesctr_drbg_vtable;
|
||||
|
||||
/**
|
||||
* \brief AESCTR_DRBG initialisation.
|
||||
*
|
||||
* The context to initialise is provided as a pointer to its first field
|
||||
* (the vtable pointer); this function sets that first field to a
|
||||
* pointer to the vtable.
|
||||
*
|
||||
* The internal AES key is first set to the all-zero key; then, the
|
||||
* `br_aesctr_drbg_update()` function is called with the provided `seed`.
|
||||
* The call is performed even if the seed length (`seed_len`) is zero.
|
||||
*
|
||||
* The `aesctr` parameter defines the underlying AES/CTR implementation.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context to initialise.
|
||||
* \param aesctr vtable for the AES/CTR implementation.
|
||||
* \param seed initial seed (can be `NULL` if `seed_len` is zero).
|
||||
* \param seed_len initial seed length (in bytes).
|
||||
*/
|
||||
void br_aesctr_drbg_init(br_aesctr_drbg_context *ctx,
|
||||
const br_block_ctr_class *aesctr, const void *seed, size_t seed_len);
|
||||
|
||||
/**
|
||||
* \brief Random bytes generation with AESCTR_DRBG.
|
||||
*
|
||||
* This method produces `len` pseudorandom bytes, in the `out`
|
||||
* buffer. The context is updated accordingly.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context.
|
||||
* \param out output buffer.
|
||||
* \param len number of pseudorandom bytes to produce.
|
||||
*/
|
||||
void br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx,
|
||||
void *out, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Inject additional seed bytes in AESCTR_DRBG.
|
||||
*
|
||||
* The provided seed bytes are added into the AESCTR_DRBG internal
|
||||
* entropy pool. The process does not _replace_ existing entropy,
|
||||
* thus pushing non-random bytes (i.e. bytes which are known to the
|
||||
* attackers) does not degrade the overall quality of generated bytes.
|
||||
*
|
||||
* \param ctx AESCTR_DRBG context.
|
||||
* \param seed additional seed.
|
||||
* \param seed_len additional seed length (in bytes).
|
||||
*/
|
||||
void br_aesctr_drbg_update(br_aesctr_drbg_context *ctx,
|
||||
const void *seed, size_t seed_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1366
dstalk-core/thirdparty/bearssl/inc/bearssl_rsa.h
vendored
1366
dstalk-core/thirdparty/bearssl/inc/bearssl_rsa.h
vendored
File diff suppressed because it is too large
Load Diff
4296
dstalk-core/thirdparty/bearssl/inc/bearssl_ssl.h
vendored
4296
dstalk-core/thirdparty/bearssl/inc/bearssl_ssl.h
vendored
File diff suppressed because it is too large
Load Diff
1397
dstalk-core/thirdparty/bearssl/inc/bearssl_x509.h
vendored
1397
dstalk-core/thirdparty/bearssl/inc/bearssl_x509.h
vendored
File diff suppressed because it is too large
Load Diff
346
dstalk-core/thirdparty/bearssl/src/aead/ccm.c
vendored
346
dstalk-core/thirdparty/bearssl/src/aead/ccm.c
vendored
@@ -1,346 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Implementation Notes
|
||||
* ====================
|
||||
*
|
||||
* The combined CTR + CBC-MAC functions can only handle full blocks,
|
||||
* so some buffering is necessary.
|
||||
*
|
||||
* - 'ptr' contains a value from 0 to 15, which is the number of bytes
|
||||
* accumulated in buf[] that still needs to be processed with the
|
||||
* current CBC-MAC computation.
|
||||
*
|
||||
* - When processing the message itself, CTR encryption/decryption is
|
||||
* also done at the same time. The first 'ptr' bytes of buf[] then
|
||||
* contains the plaintext bytes, while the last '16 - ptr' bytes of
|
||||
* buf[] are the remnants of the stream block, to be used against
|
||||
* the next input bytes, when available. When 'ptr' is 0, the
|
||||
* contents of buf[] are to be ignored.
|
||||
*
|
||||
* - The current counter and running CBC-MAC values are kept in 'ctr'
|
||||
* and 'cbcmac', respectively.
|
||||
*/
|
||||
|
||||
/* see bearssl_block.h */
|
||||
void
|
||||
br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx)
|
||||
{
|
||||
ctx->bctx = bctx;
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
int
|
||||
br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len,
|
||||
uint64_t aad_len, uint64_t data_len, size_t tag_len)
|
||||
{
|
||||
unsigned char tmp[16];
|
||||
unsigned u, q;
|
||||
|
||||
if (nonce_len < 7 || nonce_len > 13) {
|
||||
return 0;
|
||||
}
|
||||
if (tag_len < 4 || tag_len > 16 || (tag_len & 1) != 0) {
|
||||
return 0;
|
||||
}
|
||||
q = 15 - (unsigned)nonce_len;
|
||||
ctx->tag_len = tag_len;
|
||||
|
||||
/*
|
||||
* Block B0, to start CBC-MAC.
|
||||
*/
|
||||
tmp[0] = (aad_len > 0 ? 0x40 : 0x00)
|
||||
| (((unsigned)tag_len - 2) << 2)
|
||||
| (q - 1);
|
||||
memcpy(tmp + 1, nonce, nonce_len);
|
||||
for (u = 0; u < q; u ++) {
|
||||
tmp[15 - u] = (unsigned char)data_len;
|
||||
data_len >>= 8;
|
||||
}
|
||||
if (data_len != 0) {
|
||||
/*
|
||||
* If the data length was not entirely consumed in the
|
||||
* loop above, then it exceeds the maximum limit of
|
||||
* q bytes (when encoded).
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start CBC-MAC.
|
||||
*/
|
||||
memset(ctx->cbcmac, 0, sizeof ctx->cbcmac);
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, tmp, sizeof tmp);
|
||||
|
||||
/*
|
||||
* Assemble AAD length header.
|
||||
*/
|
||||
if ((aad_len >> 32) != 0) {
|
||||
ctx->buf[0] = 0xFF;
|
||||
ctx->buf[1] = 0xFF;
|
||||
br_enc64be(ctx->buf + 2, aad_len);
|
||||
ctx->ptr = 10;
|
||||
} else if (aad_len >= 0xFF00) {
|
||||
ctx->buf[0] = 0xFF;
|
||||
ctx->buf[1] = 0xFE;
|
||||
br_enc32be(ctx->buf + 2, (uint32_t)aad_len);
|
||||
ctx->ptr = 6;
|
||||
} else if (aad_len > 0) {
|
||||
br_enc16be(ctx->buf, (unsigned)aad_len);
|
||||
ctx->ptr = 2;
|
||||
} else {
|
||||
ctx->ptr = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make initial counter value and compute tag mask.
|
||||
*/
|
||||
ctx->ctr[0] = q - 1;
|
||||
memcpy(ctx->ctr + 1, nonce, nonce_len);
|
||||
memset(ctx->ctr + 1 + nonce_len, 0, q);
|
||||
memset(ctx->tagmask, 0, sizeof ctx->tagmask);
|
||||
(*ctx->bctx)->ctr(ctx->bctx, ctx->ctr,
|
||||
ctx->tagmask, sizeof ctx->tagmask);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
void
|
||||
br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *dbuf;
|
||||
size_t ptr;
|
||||
|
||||
dbuf = data;
|
||||
|
||||
/*
|
||||
* Complete partial block, if needed.
|
||||
*/
|
||||
ptr = ctx->ptr;
|
||||
if (ptr != 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = (sizeof ctx->buf) - ptr;
|
||||
if (clen > len) {
|
||||
memcpy(ctx->buf + ptr, dbuf, len);
|
||||
ctx->ptr = ptr + len;
|
||||
return;
|
||||
}
|
||||
memcpy(ctx->buf + ptr, dbuf, clen);
|
||||
dbuf += clen;
|
||||
len -= clen;
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process complete blocks.
|
||||
*/
|
||||
ptr = len & 15;
|
||||
len -= ptr;
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, dbuf, len);
|
||||
dbuf += len;
|
||||
|
||||
/*
|
||||
* Copy last partial block in the context buffer.
|
||||
*/
|
||||
memcpy(ctx->buf, dbuf, ptr);
|
||||
ctx->ptr = ptr;
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
void
|
||||
br_ccm_flip(br_ccm_context *ctx)
|
||||
{
|
||||
size_t ptr;
|
||||
|
||||
/*
|
||||
* Complete AAD partial block with zeros, if necessary.
|
||||
*/
|
||||
ptr = ctx->ptr;
|
||||
if (ptr != 0) {
|
||||
memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr);
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
ctx->ptr = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Counter was already set by br_ccm_reset().
|
||||
*/
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
void
|
||||
br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len)
|
||||
{
|
||||
unsigned char *dbuf;
|
||||
size_t ptr;
|
||||
|
||||
dbuf = data;
|
||||
|
||||
/*
|
||||
* Complete a partial block, if any: ctx->buf[] contains
|
||||
* ctx->ptr plaintext bytes (already reported), and the other
|
||||
* bytes are CTR stream output.
|
||||
*/
|
||||
ptr = ctx->ptr;
|
||||
if (ptr != 0) {
|
||||
size_t clen;
|
||||
size_t u;
|
||||
|
||||
clen = (sizeof ctx->buf) - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
if (encrypt) {
|
||||
for (u = 0; u < clen; u ++) {
|
||||
unsigned w, x;
|
||||
|
||||
w = ctx->buf[ptr + u];
|
||||
x = dbuf[u];
|
||||
ctx->buf[ptr + u] = x;
|
||||
dbuf[u] = w ^ x;
|
||||
}
|
||||
} else {
|
||||
for (u = 0; u < clen; u ++) {
|
||||
unsigned w;
|
||||
|
||||
w = ctx->buf[ptr + u] ^ dbuf[u];
|
||||
dbuf[u] = w;
|
||||
ctx->buf[ptr + u] = w;
|
||||
}
|
||||
}
|
||||
dbuf += clen;
|
||||
len -= clen;
|
||||
ptr += clen;
|
||||
if (ptr < sizeof ctx->buf) {
|
||||
ctx->ptr = ptr;
|
||||
return;
|
||||
}
|
||||
(*ctx->bctx)->mac(ctx->bctx,
|
||||
ctx->cbcmac, ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process all complete blocks. Note that the ctrcbc API is for
|
||||
* encrypt-then-MAC (CBC-MAC is computed over the encrypted
|
||||
* blocks) while CCM uses MAC-and-encrypt (CBC-MAC is computed
|
||||
* over the plaintext blocks). Therefore, we need to use the
|
||||
* _decryption_ function for encryption, and the encryption
|
||||
* function for decryption (this works because CTR encryption
|
||||
* and decryption are identical, so the choice really is about
|
||||
* computing the CBC-MAC before or after XORing with the CTR
|
||||
* stream).
|
||||
*/
|
||||
ptr = len & 15;
|
||||
len -= ptr;
|
||||
if (encrypt) {
|
||||
(*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
|
||||
dbuf, len);
|
||||
} else {
|
||||
(*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
|
||||
dbuf, len);
|
||||
}
|
||||
dbuf += len;
|
||||
|
||||
/*
|
||||
* If there is some remaining data, then we need to compute an
|
||||
* extra block of CTR stream.
|
||||
*/
|
||||
if (ptr != 0) {
|
||||
size_t u;
|
||||
|
||||
memset(ctx->buf, 0, sizeof ctx->buf);
|
||||
(*ctx->bctx)->ctr(ctx->bctx, ctx->ctr,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
if (encrypt) {
|
||||
for (u = 0; u < ptr; u ++) {
|
||||
unsigned w, x;
|
||||
|
||||
w = ctx->buf[u];
|
||||
x = dbuf[u];
|
||||
ctx->buf[u] = x;
|
||||
dbuf[u] = w ^ x;
|
||||
}
|
||||
} else {
|
||||
for (u = 0; u < ptr; u ++) {
|
||||
unsigned w;
|
||||
|
||||
w = ctx->buf[u] ^ dbuf[u];
|
||||
dbuf[u] = w;
|
||||
ctx->buf[u] = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx->ptr = ptr;
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
size_t
|
||||
br_ccm_get_tag(br_ccm_context *ctx, void *tag)
|
||||
{
|
||||
size_t ptr;
|
||||
size_t u;
|
||||
|
||||
/*
|
||||
* If there is some buffered data, then we need to pad it with
|
||||
* zeros and finish up CBC-MAC.
|
||||
*/
|
||||
ptr = ctx->ptr;
|
||||
if (ptr != 0) {
|
||||
memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr);
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* XOR the tag mask into the CBC-MAC output.
|
||||
*/
|
||||
for (u = 0; u < ctx->tag_len; u ++) {
|
||||
ctx->cbcmac[u] ^= ctx->tagmask[u];
|
||||
}
|
||||
memcpy(tag, ctx->cbcmac, ctx->tag_len);
|
||||
return ctx->tag_len;
|
||||
}
|
||||
|
||||
/* see bearssl_block.h */
|
||||
uint32_t
|
||||
br_ccm_check_tag(br_ccm_context *ctx, const void *tag)
|
||||
{
|
||||
unsigned char tmp[16];
|
||||
size_t u, tag_len;
|
||||
uint32_t z;
|
||||
|
||||
tag_len = br_ccm_get_tag(ctx, tmp);
|
||||
z = 0;
|
||||
for (u = 0; u < tag_len; u ++) {
|
||||
z |= tmp[u] ^ ((const unsigned char *)tag)[u];
|
||||
}
|
||||
return EQ0(z);
|
||||
}
|
||||
525
dstalk-core/thirdparty/bearssl/src/aead/eax.c
vendored
525
dstalk-core/thirdparty/bearssl/src/aead/eax.c
vendored
@@ -1,525 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Implementation Notes
|
||||
* ====================
|
||||
*
|
||||
* The combined CTR + CBC-MAC functions can only handle full blocks,
|
||||
* so some buffering is necessary. Moreover, EAX has a special padding
|
||||
* rule for CBC-MAC, which implies that we cannot compute the MAC over
|
||||
* the last received full block until we know whether we are at the
|
||||
* end of the data or not.
|
||||
*
|
||||
* - 'ptr' contains a value from 1 to 16, which is the number of bytes
|
||||
* accumulated in buf[] that still needs to be processed with the
|
||||
* current OMAC computation. Beware that this can go to 16: a
|
||||
* complete block cannot be processed until it is known whether it
|
||||
* is the last block or not. However, it can never be 0, because
|
||||
* OMAC^t works on an input that is at least one-block long.
|
||||
*
|
||||
* - When processing the message itself, CTR encryption/decryption is
|
||||
* also done at the same time. The first 'ptr' bytes of buf[] then
|
||||
* contains the encrypted bytes, while the last '16 - ptr' bytes of
|
||||
* buf[] are the remnants of the stream block, to be used against
|
||||
* the next input bytes, when available.
|
||||
*
|
||||
* - The current counter and running CBC-MAC values are kept in 'ctr'
|
||||
* and 'cbcmac', respectively.
|
||||
*
|
||||
* - The derived keys for padding are kept in L2 and L4 (double and
|
||||
* quadruple of Enc_K(0^n), in GF(2^128), respectively).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Start an OMAC computation; the first block is the big-endian
|
||||
* representation of the provided value ('val' must fit on one byte).
|
||||
* We make it a delayed block because it may also be the last one,
|
||||
*/
|
||||
static void
|
||||
omac_start(br_eax_context *ctx, unsigned val)
|
||||
{
|
||||
memset(ctx->cbcmac, 0, sizeof ctx->cbcmac);
|
||||
memset(ctx->buf, 0, sizeof ctx->buf);
|
||||
ctx->buf[15] = val;
|
||||
ctx->ptr = 16;
|
||||
}
|
||||
|
||||
/*
|
||||
* Double a value in finite field GF(2^128), defined with modulus
|
||||
* X^128+X^7+X^2+X+1.
|
||||
*/
|
||||
static void
|
||||
double_gf128(unsigned char *dst, const unsigned char *src)
|
||||
{
|
||||
unsigned cc;
|
||||
int i;
|
||||
|
||||
cc = 0x87 & -((unsigned)src[0] >> 7);
|
||||
for (i = 15; i >= 0; i --) {
|
||||
unsigned z;
|
||||
|
||||
z = (src[i] << 1) ^ cc;
|
||||
cc = z >> 8;
|
||||
dst[i] = (unsigned char)z;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply padding to the last block, currently in ctx->buf (with
|
||||
* ctx->ptr bytes), and finalize OMAC computation.
|
||||
*/
|
||||
static void
|
||||
do_pad(br_eax_context *ctx)
|
||||
{
|
||||
unsigned char *pad;
|
||||
size_t ptr, u;
|
||||
|
||||
ptr = ctx->ptr;
|
||||
if (ptr == 16) {
|
||||
pad = ctx->L2;
|
||||
} else {
|
||||
ctx->buf[ptr ++] = 0x80;
|
||||
memset(ctx->buf + ptr, 0x00, 16 - ptr);
|
||||
pad = ctx->L4;
|
||||
}
|
||||
for (u = 0; u < sizeof ctx->buf; u ++) {
|
||||
ctx->buf[u] ^= pad[u];
|
||||
}
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply CBC-MAC on the provided data, with buffering management.
|
||||
*
|
||||
* Upon entry, two situations are acceptable:
|
||||
*
|
||||
* ctx->ptr == 0: there is no data to process in ctx->buf
|
||||
* ctx->ptr == 16: there is a full block of unprocessed data in ctx->buf
|
||||
*
|
||||
* Upon exit, ctx->ptr may be zero only if it was already zero on entry,
|
||||
* and len == 0. In all other situations, ctx->ptr will be non-zero on
|
||||
* exit (and may have value 16).
|
||||
*/
|
||||
static void
|
||||
do_cbcmac_chunk(br_eax_context *ctx, const void *data, size_t len)
|
||||
{
|
||||
size_t ptr;
|
||||
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
ptr = len & (size_t)15;
|
||||
if (ptr == 0) {
|
||||
len -= 16;
|
||||
ptr = 16;
|
||||
} else {
|
||||
len -= ptr;
|
||||
}
|
||||
if (ctx->ptr == 16) {
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, data, len);
|
||||
memcpy(ctx->buf, (const unsigned char *)data + len, ptr);
|
||||
ctx->ptr = ptr;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx)
|
||||
{
|
||||
unsigned char tmp[16], iv[16];
|
||||
|
||||
ctx->vtable = &br_eax_vtable;
|
||||
ctx->bctx = bctx;
|
||||
|
||||
/*
|
||||
* Encrypt a whole-zero block to compute L2 and L4.
|
||||
*/
|
||||
memset(tmp, 0, sizeof tmp);
|
||||
memset(iv, 0, sizeof iv);
|
||||
(*bctx)->ctr(bctx, iv, tmp, sizeof tmp);
|
||||
double_gf128(ctx->L2, tmp);
|
||||
double_gf128(ctx->L4, ctx->L2);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_capture(const br_eax_context *ctx, br_eax_state *st)
|
||||
{
|
||||
/*
|
||||
* We capture the three OMAC* states _after_ processing the
|
||||
* initial block (assuming that nonce, message and AAD are
|
||||
* all non-empty).
|
||||
*/
|
||||
int i;
|
||||
|
||||
memset(st->st, 0, sizeof st->st);
|
||||
for (i = 0; i < 3; i ++) {
|
||||
unsigned char tmp[16];
|
||||
|
||||
memset(tmp, 0, sizeof tmp);
|
||||
tmp[15] = (unsigned char)i;
|
||||
(*ctx->bctx)->mac(ctx->bctx, st->st[i], tmp, sizeof tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len)
|
||||
{
|
||||
/*
|
||||
* Process nonce with OMAC^0.
|
||||
*/
|
||||
omac_start(ctx, 0);
|
||||
do_cbcmac_chunk(ctx, nonce, len);
|
||||
do_pad(ctx);
|
||||
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
|
||||
|
||||
/*
|
||||
* Start OMAC^1 for the AAD ("header" in the EAX specification).
|
||||
*/
|
||||
omac_start(ctx, 1);
|
||||
|
||||
/*
|
||||
* We use ctx->head[0] as temporary flag to mark that we are
|
||||
* using a "normal" reset().
|
||||
*/
|
||||
ctx->head[0] = 0;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st,
|
||||
const void *nonce, size_t len)
|
||||
{
|
||||
if (len == 0) {
|
||||
omac_start(ctx, 0);
|
||||
} else {
|
||||
memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac);
|
||||
ctx->ptr = 0;
|
||||
do_cbcmac_chunk(ctx, nonce, len);
|
||||
}
|
||||
do_pad(ctx);
|
||||
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
|
||||
|
||||
memcpy(ctx->cbcmac, st->st[1], sizeof ctx->cbcmac);
|
||||
ctx->ptr = 0;
|
||||
|
||||
memcpy(ctx->ctr, st->st[2], sizeof ctx->ctr);
|
||||
|
||||
/*
|
||||
* We use ctx->head[0] as a flag to indicate that we use a
|
||||
* a recorded state, with ctx->ctr containing the preprocessed
|
||||
* first block for OMAC^2.
|
||||
*/
|
||||
ctx->head[0] = 1;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st,
|
||||
const void *nonce, size_t len)
|
||||
{
|
||||
if (len == 0) {
|
||||
omac_start(ctx, 0);
|
||||
} else {
|
||||
memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac);
|
||||
ctx->ptr = 0;
|
||||
do_cbcmac_chunk(ctx, nonce, len);
|
||||
}
|
||||
do_pad(ctx);
|
||||
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
|
||||
memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce);
|
||||
|
||||
memcpy(ctx->head, st->st[1], sizeof ctx->head);
|
||||
|
||||
memcpy(ctx->cbcmac, st->st[2], sizeof ctx->cbcmac);
|
||||
ctx->ptr = 0;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len)
|
||||
{
|
||||
size_t ptr;
|
||||
|
||||
ptr = ctx->ptr;
|
||||
|
||||
/*
|
||||
* If there is a partial block, first complete it.
|
||||
*/
|
||||
if (ptr < 16) {
|
||||
size_t clen;
|
||||
|
||||
clen = 16 - ptr;
|
||||
if (len <= clen) {
|
||||
memcpy(ctx->buf + ptr, data, len);
|
||||
ctx->ptr = ptr + len;
|
||||
return;
|
||||
}
|
||||
memcpy(ctx->buf + ptr, data, clen);
|
||||
data = (const unsigned char *)data + clen;
|
||||
len -= clen;
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have a full block in buf[], and this is not the last
|
||||
* block.
|
||||
*/
|
||||
do_cbcmac_chunk(ctx, data, len);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_flip(br_eax_context *ctx)
|
||||
{
|
||||
int from_capture;
|
||||
|
||||
/*
|
||||
* ctx->head[0] may be non-zero if the context was reset with
|
||||
* a pre-AAD captured state. In that case, ctx->ctr[] contains
|
||||
* the state for OMAC^2 _after_ processing the first block.
|
||||
*/
|
||||
from_capture = ctx->head[0];
|
||||
|
||||
/*
|
||||
* Complete the OMAC computation on the AAD.
|
||||
*/
|
||||
do_pad(ctx);
|
||||
memcpy(ctx->head, ctx->cbcmac, sizeof ctx->cbcmac);
|
||||
|
||||
/*
|
||||
* Start OMAC^2 for the encrypted data.
|
||||
* If the context was initialized from a captured state, then
|
||||
* the OMAC^2 value is in the ctr[] array.
|
||||
*/
|
||||
if (from_capture) {
|
||||
memcpy(ctx->cbcmac, ctx->ctr, sizeof ctx->cbcmac);
|
||||
ctx->ptr = 0;
|
||||
} else {
|
||||
omac_start(ctx, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initial counter value for CTR is the processed nonce.
|
||||
*/
|
||||
memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len)
|
||||
{
|
||||
unsigned char *dbuf;
|
||||
size_t ptr;
|
||||
|
||||
/*
|
||||
* Ensure that there is actual data to process.
|
||||
*/
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
dbuf = data;
|
||||
ptr = ctx->ptr;
|
||||
|
||||
/*
|
||||
* We may have ptr == 0 here if we initialized from a captured
|
||||
* state. In that case, there is no partially consumed block
|
||||
* or unprocessed data.
|
||||
*/
|
||||
if (ptr != 0 && ptr != 16) {
|
||||
/*
|
||||
* We have a partially consumed block.
|
||||
*/
|
||||
size_t u, clen;
|
||||
|
||||
clen = 16 - ptr;
|
||||
if (len <= clen) {
|
||||
clen = len;
|
||||
}
|
||||
if (encrypt) {
|
||||
for (u = 0; u < clen; u ++) {
|
||||
ctx->buf[ptr + u] ^= dbuf[u];
|
||||
}
|
||||
memcpy(dbuf, ctx->buf + ptr, clen);
|
||||
} else {
|
||||
for (u = 0; u < clen; u ++) {
|
||||
unsigned dx, sx;
|
||||
|
||||
sx = ctx->buf[ptr + u];
|
||||
dx = dbuf[u];
|
||||
ctx->buf[ptr + u] = dx;
|
||||
dbuf[u] = sx ^ dx;
|
||||
}
|
||||
}
|
||||
|
||||
if (len <= clen) {
|
||||
ctx->ptr = ptr + clen;
|
||||
return;
|
||||
}
|
||||
dbuf += clen;
|
||||
len -= clen;
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have a complete encrypted block in buf[] that must still
|
||||
* be processed with OMAC, and this is not the final buf.
|
||||
* Exception: when ptr == 0, no block has been produced yet.
|
||||
*/
|
||||
if (ptr != 0) {
|
||||
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
|
||||
ctx->buf, sizeof ctx->buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do CTR encryption or decryption and CBC-MAC for all full blocks
|
||||
* except the last.
|
||||
*/
|
||||
ptr = len & (size_t)15;
|
||||
if (ptr == 0) {
|
||||
len -= 16;
|
||||
ptr = 16;
|
||||
} else {
|
||||
len -= ptr;
|
||||
}
|
||||
if (encrypt) {
|
||||
(*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
|
||||
dbuf, len);
|
||||
} else {
|
||||
(*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
|
||||
dbuf, len);
|
||||
}
|
||||
dbuf += len;
|
||||
|
||||
/*
|
||||
* Compute next block of CTR stream, and use it to finish
|
||||
* encrypting or decrypting the data.
|
||||
*/
|
||||
memset(ctx->buf, 0, sizeof ctx->buf);
|
||||
(*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, ctx->buf, sizeof ctx->buf);
|
||||
if (encrypt) {
|
||||
size_t u;
|
||||
|
||||
for (u = 0; u < ptr; u ++) {
|
||||
ctx->buf[u] ^= dbuf[u];
|
||||
}
|
||||
memcpy(dbuf, ctx->buf, ptr);
|
||||
} else {
|
||||
size_t u;
|
||||
|
||||
for (u = 0; u < ptr; u ++) {
|
||||
unsigned dx, sx;
|
||||
|
||||
sx = ctx->buf[u];
|
||||
dx = dbuf[u];
|
||||
ctx->buf[u] = dx;
|
||||
dbuf[u] = sx ^ dx;
|
||||
}
|
||||
}
|
||||
ctx->ptr = ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Complete tag computation. The final tag is written in ctx->cbcmac.
|
||||
*/
|
||||
static void
|
||||
do_final(br_eax_context *ctx)
|
||||
{
|
||||
size_t u;
|
||||
|
||||
do_pad(ctx);
|
||||
|
||||
/*
|
||||
* Authentication tag is the XOR of the three OMAC outputs for
|
||||
* the nonce, AAD and encrypted data.
|
||||
*/
|
||||
for (u = 0; u < 16; u ++) {
|
||||
ctx->cbcmac[u] ^= ctx->nonce[u] ^ ctx->head[u];
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_get_tag(br_eax_context *ctx, void *tag)
|
||||
{
|
||||
do_final(ctx);
|
||||
memcpy(tag, ctx->cbcmac, sizeof ctx->cbcmac);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len)
|
||||
{
|
||||
do_final(ctx);
|
||||
memcpy(tag, ctx->cbcmac, len);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
uint32_t
|
||||
br_eax_check_tag_trunc(br_eax_context *ctx, const void *tag, size_t len)
|
||||
{
|
||||
unsigned char tmp[16];
|
||||
size_t u;
|
||||
int x;
|
||||
|
||||
br_eax_get_tag(ctx, tmp);
|
||||
x = 0;
|
||||
for (u = 0; u < len; u ++) {
|
||||
x |= tmp[u] ^ ((const unsigned char *)tag)[u];
|
||||
}
|
||||
return EQ0(x);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
uint32_t
|
||||
br_eax_check_tag(br_eax_context *ctx, const void *tag)
|
||||
{
|
||||
return br_eax_check_tag_trunc(ctx, tag, 16);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
const br_aead_class br_eax_vtable = {
|
||||
16,
|
||||
(void (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_eax_reset,
|
||||
(void (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_eax_aad_inject,
|
||||
(void (*)(const br_aead_class **))
|
||||
&br_eax_flip,
|
||||
(void (*)(const br_aead_class **, int, void *, size_t))
|
||||
&br_eax_run,
|
||||
(void (*)(const br_aead_class **, void *))
|
||||
&br_eax_get_tag,
|
||||
(uint32_t (*)(const br_aead_class **, const void *))
|
||||
&br_eax_check_tag,
|
||||
(void (*)(const br_aead_class **, void *, size_t))
|
||||
&br_eax_get_tag_trunc,
|
||||
(uint32_t (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_eax_check_tag_trunc
|
||||
};
|
||||
318
dstalk-core/thirdparty/bearssl/src/aead/gcm.c
vendored
318
dstalk-core/thirdparty/bearssl/src/aead/gcm.c
vendored
@@ -1,318 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Implementation Notes
|
||||
* ====================
|
||||
*
|
||||
* Since CTR and GHASH implementations can handle only full blocks, a
|
||||
* 16-byte buffer (buf[]) is maintained in the context:
|
||||
*
|
||||
* - When processing AAD, buf[] contains the 0-15 unprocessed bytes.
|
||||
*
|
||||
* - When doing CTR encryption / decryption, buf[] contains the AES output
|
||||
* for the last partial block, to be used with the next few bytes of
|
||||
* data, as well as the already encrypted bytes. For instance, if the
|
||||
* processed data length so far is 21 bytes, then buf[0..4] contains
|
||||
* the five last encrypted bytes, and buf[5..15] contains the next 11
|
||||
* AES output bytes to be XORed with the next 11 bytes of input.
|
||||
*
|
||||
* The recorded AES output bytes are used to complete the block when
|
||||
* the corresponding bytes are obtained. Note that buf[] always
|
||||
* contains the _encrypted_ bytes, whether we apply encryption or
|
||||
* decryption: these bytes are used as input to GHASH when the block
|
||||
* is complete.
|
||||
*
|
||||
* In both cases, the low bits of the data length counters (count_aad,
|
||||
* count_ctr) are used to work out the current situation.
|
||||
*/
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_init(br_gcm_context *ctx, const br_block_ctr_class **bctx, br_ghash gh)
|
||||
{
|
||||
unsigned char iv[12];
|
||||
|
||||
ctx->vtable = &br_gcm_vtable;
|
||||
ctx->bctx = bctx;
|
||||
ctx->gh = gh;
|
||||
|
||||
/*
|
||||
* The GHASH key h[] is the raw encryption of the all-zero
|
||||
* block. Since we only have a CTR implementation, we use it
|
||||
* with an all-zero IV and a zero counter, to CTR-encrypt an
|
||||
* all-zero block.
|
||||
*/
|
||||
memset(ctx->h, 0, sizeof ctx->h);
|
||||
memset(iv, 0, sizeof iv);
|
||||
(*bctx)->run(bctx, iv, 0, ctx->h, sizeof ctx->h);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len)
|
||||
{
|
||||
/*
|
||||
* If the provided nonce is 12 bytes, then this is the initial
|
||||
* IV for CTR mode; it will be used with a counter that starts
|
||||
* at 2 (value 1 is for encrypting the GHASH output into the tag).
|
||||
*
|
||||
* If the provided nonce has any other length, then it is hashed
|
||||
* (with GHASH) into a 16-byte value that will be the IV for CTR
|
||||
* (both 12-byte IV and 32-bit counter).
|
||||
*/
|
||||
if (len == 12) {
|
||||
memcpy(ctx->j0_1, iv, 12);
|
||||
ctx->j0_2 = 1;
|
||||
} else {
|
||||
unsigned char ty[16], tmp[16];
|
||||
|
||||
memset(ty, 0, sizeof ty);
|
||||
ctx->gh(ty, ctx->h, iv, len);
|
||||
memset(tmp, 0, 8);
|
||||
br_enc64be(tmp + 8, (uint64_t)len << 3);
|
||||
ctx->gh(ty, ctx->h, tmp, 16);
|
||||
memcpy(ctx->j0_1, ty, 12);
|
||||
ctx->j0_2 = br_dec32be(ty + 12);
|
||||
}
|
||||
ctx->jc = ctx->j0_2 + 1;
|
||||
memset(ctx->y, 0, sizeof ctx->y);
|
||||
ctx->count_aad = 0;
|
||||
ctx->count_ctr = 0;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len)
|
||||
{
|
||||
size_t ptr, dlen;
|
||||
|
||||
ptr = (size_t)ctx->count_aad & (size_t)15;
|
||||
if (ptr != 0) {
|
||||
/*
|
||||
* If there is a partial block, then we first try to
|
||||
* complete it.
|
||||
*/
|
||||
size_t clen;
|
||||
|
||||
clen = 16 - ptr;
|
||||
if (len < clen) {
|
||||
memcpy(ctx->buf + ptr, data, len);
|
||||
ctx->count_aad += (uint64_t)len;
|
||||
return;
|
||||
}
|
||||
memcpy(ctx->buf + ptr, data, clen);
|
||||
ctx->gh(ctx->y, ctx->h, ctx->buf, 16);
|
||||
data = (const unsigned char *)data + clen;
|
||||
len -= clen;
|
||||
ctx->count_aad += (uint64_t)clen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now AAD is aligned on a 16-byte block (with regards to GHASH).
|
||||
* We process all complete blocks, and save the last partial
|
||||
* block.
|
||||
*/
|
||||
dlen = len & ~(size_t)15;
|
||||
ctx->gh(ctx->y, ctx->h, data, dlen);
|
||||
memcpy(ctx->buf, (const unsigned char *)data + dlen, len - dlen);
|
||||
ctx->count_aad += (uint64_t)len;
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_flip(br_gcm_context *ctx)
|
||||
{
|
||||
/*
|
||||
* We complete the GHASH computation if there is a partial block.
|
||||
* The GHASH implementation automatically applies padding with
|
||||
* zeros.
|
||||
*/
|
||||
size_t ptr;
|
||||
|
||||
ptr = (size_t)ctx->count_aad & (size_t)15;
|
||||
if (ptr != 0) {
|
||||
ctx->gh(ctx->y, ctx->h, ctx->buf, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t ptr, dlen;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)ctx->count_ctr & (size_t)15;
|
||||
if (ptr != 0) {
|
||||
/*
|
||||
* If we have a partial block, then we try to complete it.
|
||||
*/
|
||||
size_t u, clen;
|
||||
|
||||
clen = 16 - ptr;
|
||||
if (len < clen) {
|
||||
clen = len;
|
||||
}
|
||||
for (u = 0; u < clen; u ++) {
|
||||
unsigned x, y;
|
||||
|
||||
x = buf[u];
|
||||
y = x ^ ctx->buf[ptr + u];
|
||||
ctx->buf[ptr + u] = encrypt ? y : x;
|
||||
buf[u] = y;
|
||||
}
|
||||
ctx->count_ctr += (uint64_t)clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
if (ptr + clen < 16) {
|
||||
return;
|
||||
}
|
||||
ctx->gh(ctx->y, ctx->h, ctx->buf, 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process full blocks.
|
||||
*/
|
||||
dlen = len & ~(size_t)15;
|
||||
if (!encrypt) {
|
||||
ctx->gh(ctx->y, ctx->h, buf, dlen);
|
||||
}
|
||||
ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->jc, buf, dlen);
|
||||
if (encrypt) {
|
||||
ctx->gh(ctx->y, ctx->h, buf, dlen);
|
||||
}
|
||||
buf += dlen;
|
||||
len -= dlen;
|
||||
ctx->count_ctr += (uint64_t)dlen;
|
||||
|
||||
if (len > 0) {
|
||||
/*
|
||||
* There is a partial block.
|
||||
*/
|
||||
size_t u;
|
||||
|
||||
memset(ctx->buf, 0, sizeof ctx->buf);
|
||||
ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1,
|
||||
ctx->jc, ctx->buf, 16);
|
||||
for (u = 0; u < len; u ++) {
|
||||
unsigned x, y;
|
||||
|
||||
x = buf[u];
|
||||
y = x ^ ctx->buf[u];
|
||||
ctx->buf[u] = encrypt ? y : x;
|
||||
buf[u] = y;
|
||||
}
|
||||
ctx->count_ctr += (uint64_t)len;
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_get_tag(br_gcm_context *ctx, void *tag)
|
||||
{
|
||||
size_t ptr;
|
||||
unsigned char tmp[16];
|
||||
|
||||
ptr = (size_t)ctx->count_ctr & (size_t)15;
|
||||
if (ptr > 0) {
|
||||
/*
|
||||
* There is a partial block: encrypted/decrypted data has
|
||||
* been produced, but the encrypted bytes must still be
|
||||
* processed by GHASH.
|
||||
*/
|
||||
ctx->gh(ctx->y, ctx->h, ctx->buf, ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final block for GHASH: the AAD and plaintext lengths (in bits).
|
||||
*/
|
||||
br_enc64be(tmp, ctx->count_aad << 3);
|
||||
br_enc64be(tmp + 8, ctx->count_ctr << 3);
|
||||
ctx->gh(ctx->y, ctx->h, tmp, 16);
|
||||
|
||||
/*
|
||||
* Tag is the GHASH output XORed with the encryption of the
|
||||
* nonce with the initial counter value.
|
||||
*/
|
||||
memcpy(tag, ctx->y, 16);
|
||||
(*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->j0_2, tag, 16);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
void
|
||||
br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len)
|
||||
{
|
||||
unsigned char tmp[16];
|
||||
|
||||
br_gcm_get_tag(ctx, tmp);
|
||||
memcpy(tag, tmp, len);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
uint32_t
|
||||
br_gcm_check_tag_trunc(br_gcm_context *ctx, const void *tag, size_t len)
|
||||
{
|
||||
unsigned char tmp[16];
|
||||
size_t u;
|
||||
int x;
|
||||
|
||||
br_gcm_get_tag(ctx, tmp);
|
||||
x = 0;
|
||||
for (u = 0; u < len; u ++) {
|
||||
x |= tmp[u] ^ ((const unsigned char *)tag)[u];
|
||||
}
|
||||
return EQ0(x);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
uint32_t
|
||||
br_gcm_check_tag(br_gcm_context *ctx, const void *tag)
|
||||
{
|
||||
return br_gcm_check_tag_trunc(ctx, tag, 16);
|
||||
}
|
||||
|
||||
/* see bearssl_aead.h */
|
||||
const br_aead_class br_gcm_vtable = {
|
||||
16,
|
||||
(void (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_gcm_reset,
|
||||
(void (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_gcm_aad_inject,
|
||||
(void (*)(const br_aead_class **))
|
||||
&br_gcm_flip,
|
||||
(void (*)(const br_aead_class **, int, void *, size_t))
|
||||
&br_gcm_run,
|
||||
(void (*)(const br_aead_class **, void *))
|
||||
&br_gcm_get_tag,
|
||||
(uint32_t (*)(const br_aead_class **, const void *))
|
||||
&br_gcm_check_tag,
|
||||
(void (*)(const br_aead_class **, void *, size_t))
|
||||
&br_gcm_get_tag_trunc,
|
||||
(uint32_t (*)(const br_aead_class **, const void *, size_t))
|
||||
&br_gcm_check_tag_trunc
|
||||
};
|
||||
44
dstalk-core/thirdparty/bearssl/src/codec/ccopy.c
vendored
44
dstalk-core/thirdparty/bearssl/src/codec/ccopy.c
vendored
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len)
|
||||
{
|
||||
unsigned char *d;
|
||||
const unsigned char *s;
|
||||
|
||||
d = dst;
|
||||
s = src;
|
||||
while (len -- > 0) {
|
||||
uint32_t x, y;
|
||||
|
||||
x = *s ++;
|
||||
y = *d;
|
||||
*d = MUX(ctl, x, y);
|
||||
d ++;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec16be(uint16_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec16be(buf);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec16le(uint16_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec16le(buf);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec32be(uint32_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec32be(buf);
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec32le(uint32_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec32le(buf);
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec64be(uint64_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec64be(buf);
|
||||
buf += 8;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_dec64le(uint64_t *v, size_t num, const void *src)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = src;
|
||||
while (num -- > 0) {
|
||||
*v ++ = br_dec64le(buf);
|
||||
buf += 8;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc16be(void *dst, const uint16_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc16be(buf, *v ++);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc16le(void *dst, const uint16_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc16le(buf, *v ++);
|
||||
buf += 2;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc32be(void *dst, const uint32_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc32be(buf, *v ++);
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc32le(void *dst, const uint32_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc32le(buf, *v ++);
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc64be(void *dst, const uint64_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc64be(buf, *v ++);
|
||||
buf += 8;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_range_enc64le(void *dst, const uint64_t *v, size_t num)
|
||||
{
|
||||
unsigned char *buf;
|
||||
|
||||
buf = dst;
|
||||
while (num -- > 0) {
|
||||
br_enc64le(buf, *v ++);
|
||||
buf += 8;
|
||||
}
|
||||
}
|
||||
526
dstalk-core/thirdparty/bearssl/src/codec/pemdec.c
vendored
526
dstalk-core/thirdparty/bearssl/src/codec/pemdec.c
vendored
@@ -1,526 +0,0 @@
|
||||
/* Automatically generated code; do not modify directly. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t *dp;
|
||||
uint32_t *rp;
|
||||
const unsigned char *ip;
|
||||
} t0_context;
|
||||
|
||||
static uint32_t
|
||||
t0_parse7E_unsigned(const unsigned char **p)
|
||||
{
|
||||
uint32_t x;
|
||||
|
||||
x = 0;
|
||||
for (;;) {
|
||||
unsigned y;
|
||||
|
||||
y = *(*p) ++;
|
||||
x = (x << 7) | (uint32_t)(y & 0x7F);
|
||||
if (y < 0x80) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t
|
||||
t0_parse7E_signed(const unsigned char **p)
|
||||
{
|
||||
int neg;
|
||||
uint32_t x;
|
||||
|
||||
neg = ((**p) >> 6) & 1;
|
||||
x = (uint32_t)-neg;
|
||||
for (;;) {
|
||||
unsigned y;
|
||||
|
||||
y = *(*p) ++;
|
||||
x = (x << 7) | (uint32_t)(y & 0x7F);
|
||||
if (y < 0x80) {
|
||||
if (neg) {
|
||||
return -(int32_t)~x - 1;
|
||||
} else {
|
||||
return (int32_t)x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
|
||||
#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
|
||||
#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
|
||||
#define T0_INT1(x) T0_FBYTE(x, 0)
|
||||
#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
|
||||
#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
|
||||
#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
|
||||
#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
|
||||
|
||||
/* static const unsigned char t0_datablock[]; */
|
||||
|
||||
|
||||
void br_pem_decoder_init_main(void *t0ctx);
|
||||
|
||||
void br_pem_decoder_run(void *t0ctx);
|
||||
|
||||
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define CTX ((br_pem_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu)))
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
void
|
||||
br_pem_decoder_init(br_pem_decoder_context *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof *ctx);
|
||||
ctx->cpu.dp = &ctx->dp_stack[0];
|
||||
ctx->cpu.rp = &ctx->rp_stack[0];
|
||||
br_pem_decoder_init_main(&ctx->cpu);
|
||||
br_pem_decoder_run(&ctx->cpu);
|
||||
}
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
size_t
|
||||
br_pem_decoder_push(br_pem_decoder_context *ctx,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
if (ctx->event) {
|
||||
return 0;
|
||||
}
|
||||
ctx->hbuf = data;
|
||||
ctx->hlen = len;
|
||||
br_pem_decoder_run(&ctx->cpu);
|
||||
return len - ctx->hlen;
|
||||
}
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
int
|
||||
br_pem_decoder_event(br_pem_decoder_context *ctx)
|
||||
{
|
||||
int event;
|
||||
|
||||
event = ctx->event;
|
||||
ctx->event = 0;
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const unsigned char t0_datablock[] = {
|
||||
0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20,
|
||||
0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x00
|
||||
};
|
||||
|
||||
static const unsigned char t0_codeblock[] = {
|
||||
0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x01,
|
||||
0x01, 0x08, 0x00, 0x00, 0x13, 0x13, 0x00, 0x00, 0x01,
|
||||
T0_INT2(offsetof(br_pem_decoder_context, event)), 0x00, 0x00, 0x01,
|
||||
T0_INT2(offsetof(br_pem_decoder_context, name)), 0x00, 0x00, 0x05,
|
||||
0x14, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x03, 0x13, 0x04, 0x76, 0x01,
|
||||
0x2D, 0x0C, 0x06, 0x05, 0x2E, 0x01, 0x03, 0x2D, 0x00, 0x01, 0x0D, 0x27,
|
||||
0x05, 0x04, 0x01, 0x03, 0x2D, 0x00, 0x15, 0x2E, 0x01, 0x02, 0x2D, 0x00,
|
||||
0x01, 0x01, 0x7F, 0x03, 0x00, 0x25, 0x01, 0x00, 0x18, 0x0D, 0x06, 0x03,
|
||||
0x13, 0x04, 0x3C, 0x01, 0x7F, 0x18, 0x0D, 0x06, 0x13, 0x13, 0x02, 0x00,
|
||||
0x05, 0x06, 0x2E, 0x01, 0x03, 0x2D, 0x04, 0x03, 0x01, 0x7F, 0x23, 0x01,
|
||||
0x00, 0x00, 0x04, 0x23, 0x01, 0x01, 0x18, 0x0D, 0x06, 0x09, 0x13, 0x01,
|
||||
0x00, 0x23, 0x01, 0x00, 0x00, 0x04, 0x14, 0x01, 0x02, 0x18, 0x0D, 0x06,
|
||||
0x06, 0x13, 0x01, 0x7F, 0x00, 0x04, 0x08, 0x13, 0x01, 0x03, 0x2D, 0x01,
|
||||
0x00, 0x00, 0x13, 0x01, 0x00, 0x03, 0x00, 0x04, 0xFF, 0x33, 0x01, 0x2C,
|
||||
0x14, 0x01, 0x2D, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x7F, 0x00, 0x14, 0x31,
|
||||
0x06, 0x02, 0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01,
|
||||
0x02, 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00,
|
||||
0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03,
|
||||
0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02,
|
||||
0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D,
|
||||
0x06, 0x04, 0x13, 0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x2E,
|
||||
0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03, 0x00,
|
||||
0x2F, 0x05, 0x04, 0x13, 0x01, 0x03, 0x00, 0x01, 0x3D, 0x0C, 0x06, 0x03,
|
||||
0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x0F, 0x10, 0x06, 0x03, 0x01, 0x03,
|
||||
0x00, 0x02, 0x00, 0x01, 0x04, 0x0F, 0x1C, 0x01, 0x01, 0x00, 0x16, 0x14,
|
||||
0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06,
|
||||
0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13,
|
||||
0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x20, 0x13, 0x2F, 0x05,
|
||||
0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x03, 0x10, 0x06, 0x03, 0x01,
|
||||
0x03, 0x00, 0x02, 0x00, 0x01, 0x0A, 0x0F, 0x1C, 0x02, 0x00, 0x01, 0x02,
|
||||
0x0F, 0x1C, 0x01, 0x01, 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E,
|
||||
0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x02,
|
||||
0x00, 0x01, 0x10, 0x0F, 0x1C, 0x02, 0x00, 0x01, 0x08, 0x0F, 0x1C, 0x02,
|
||||
0x00, 0x1C, 0x01, 0x00, 0x00, 0x00, 0x28, 0x01, 0x01, 0x2D, 0x24, 0x06,
|
||||
0x02, 0x04, 0x7B, 0x04, 0x75, 0x00, 0x14, 0x12, 0x2A, 0x14, 0x05, 0x04,
|
||||
0x20, 0x01, 0x7F, 0x00, 0x2C, 0x2A, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x05,
|
||||
0x13, 0x20, 0x01, 0x00, 0x00, 0x0D, 0x05, 0x05, 0x13, 0x2E, 0x01, 0x00,
|
||||
0x00, 0x1E, 0x04, 0x5E, 0x00, 0x01, 0x01, 0x27, 0x06, 0x0B, 0x22, 0x01,
|
||||
0x80, 0x7F, 0x2B, 0x14, 0x06, 0x02, 0x30, 0x00, 0x13, 0x04, 0x6E, 0x00,
|
||||
0x2C, 0x14, 0x31, 0x05, 0x01, 0x00, 0x13, 0x04, 0x77, 0x00, 0x14, 0x14,
|
||||
0x01, 0x80, 0x61, 0x0E, 0x1B, 0x01, 0x80, 0x7A, 0x0B, 0x10, 0x06, 0x03,
|
||||
0x01, 0x20, 0x08, 0x00, 0x01, 0x14, 0x03, 0x00, 0x1B, 0x18, 0x05, 0x05,
|
||||
0x20, 0x2E, 0x01, 0x00, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x06,
|
||||
0x20, 0x02, 0x00, 0x1B, 0x08, 0x00, 0x14, 0x01, 0x0D, 0x0D, 0x06, 0x03,
|
||||
0x13, 0x04, 0x03, 0x2A, 0x18, 0x1A, 0x1E, 0x1B, 0x1F, 0x1B, 0x04, 0x59,
|
||||
0x00, 0x19, 0x14, 0x1D, 0x05, 0x01, 0x00, 0x13, 0x11, 0x04, 0x76, 0x00,
|
||||
0x21, 0x1A, 0x11, 0x00, 0x00, 0x2C, 0x01, 0x0A, 0x0C, 0x06, 0x02, 0x04,
|
||||
0x78, 0x00, 0x01, 0x01, 0x7F, 0x03, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0C,
|
||||
0x06, 0x09, 0x31, 0x05, 0x04, 0x01, 0x00, 0x03, 0x00, 0x04, 0x70, 0x13,
|
||||
0x02, 0x00, 0x00, 0x00, 0x14, 0x06, 0x14, 0x1F, 0x14, 0x22, 0x07, 0x17,
|
||||
0x01, 0x2D, 0x0C, 0x06, 0x08, 0x22, 0x07, 0x1E, 0x01, 0x00, 0x1B, 0x1A,
|
||||
0x00, 0x04, 0x69, 0x22, 0x1A, 0x00, 0x00, 0x14, 0x01, 0x0A, 0x0C, 0x1B,
|
||||
0x01, 0x20, 0x0B, 0x10, 0x00
|
||||
};
|
||||
|
||||
static const uint16_t t0_caddr[] = {
|
||||
0,
|
||||
5,
|
||||
10,
|
||||
15,
|
||||
19,
|
||||
24,
|
||||
29,
|
||||
67,
|
||||
149,
|
||||
384,
|
||||
396,
|
||||
431,
|
||||
450,
|
||||
460,
|
||||
479,
|
||||
523,
|
||||
534,
|
||||
539,
|
||||
549,
|
||||
574,
|
||||
601
|
||||
};
|
||||
|
||||
#define T0_INTERPRETED 29
|
||||
|
||||
#define T0_ENTER(ip, rp, slot) do { \
|
||||
const unsigned char *t0_newip; \
|
||||
uint32_t t0_lnum; \
|
||||
t0_newip = &t0_codeblock[t0_caddr[(slot) - T0_INTERPRETED]]; \
|
||||
t0_lnum = t0_parse7E_unsigned(&t0_newip); \
|
||||
(rp) += t0_lnum; \
|
||||
*((rp) ++) = (uint32_t)((ip) - &t0_codeblock[0]) + (t0_lnum << 16); \
|
||||
(ip) = t0_newip; \
|
||||
} while (0)
|
||||
|
||||
#define T0_DEFENTRY(name, slot) \
|
||||
void \
|
||||
name(void *ctx) \
|
||||
{ \
|
||||
t0_context *t0ctx = ctx; \
|
||||
t0ctx->ip = &t0_codeblock[0]; \
|
||||
T0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
|
||||
}
|
||||
|
||||
T0_DEFENTRY(br_pem_decoder_init_main, 38)
|
||||
|
||||
#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++)
|
||||
|
||||
void
|
||||
br_pem_decoder_run(void *t0ctx)
|
||||
{
|
||||
uint32_t *dp, *rp;
|
||||
const unsigned char *ip;
|
||||
|
||||
#define T0_LOCAL(x) (*(rp - 2 - (x)))
|
||||
#define T0_POP() (*-- dp)
|
||||
#define T0_POPi() (*(int32_t *)(-- dp))
|
||||
#define T0_PEEK(x) (*(dp - 1 - (x)))
|
||||
#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x)))
|
||||
#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0)
|
||||
#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0)
|
||||
#define T0_RPOP() (*-- rp)
|
||||
#define T0_RPOPi() (*(int32_t *)(-- rp))
|
||||
#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0)
|
||||
#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0)
|
||||
#define T0_ROLL(x) do { \
|
||||
size_t t0len = (size_t)(x); \
|
||||
uint32_t t0tmp = *(dp - 1 - t0len); \
|
||||
memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \
|
||||
*(dp - 1) = t0tmp; \
|
||||
} while (0)
|
||||
#define T0_SWAP() do { \
|
||||
uint32_t t0tmp = *(dp - 2); \
|
||||
*(dp - 2) = *(dp - 1); \
|
||||
*(dp - 1) = t0tmp; \
|
||||
} while (0)
|
||||
#define T0_ROT() do { \
|
||||
uint32_t t0tmp = *(dp - 3); \
|
||||
*(dp - 3) = *(dp - 2); \
|
||||
*(dp - 2) = *(dp - 1); \
|
||||
*(dp - 1) = t0tmp; \
|
||||
} while (0)
|
||||
#define T0_NROT() do { \
|
||||
uint32_t t0tmp = *(dp - 1); \
|
||||
*(dp - 1) = *(dp - 2); \
|
||||
*(dp - 2) = *(dp - 3); \
|
||||
*(dp - 3) = t0tmp; \
|
||||
} while (0)
|
||||
#define T0_PICK(x) do { \
|
||||
uint32_t t0depth = (x); \
|
||||
T0_PUSH(T0_PEEK(t0depth)); \
|
||||
} while (0)
|
||||
#define T0_CO() do { \
|
||||
goto t0_exit; \
|
||||
} while (0)
|
||||
#define T0_RET() goto t0_next
|
||||
|
||||
dp = ((t0_context *)t0ctx)->dp;
|
||||
rp = ((t0_context *)t0ctx)->rp;
|
||||
ip = ((t0_context *)t0ctx)->ip;
|
||||
goto t0_next;
|
||||
for (;;) {
|
||||
uint32_t t0x;
|
||||
|
||||
t0_next:
|
||||
t0x = T0_NEXT(&ip);
|
||||
if (t0x < T0_INTERPRETED) {
|
||||
switch (t0x) {
|
||||
int32_t t0off;
|
||||
|
||||
case 0: /* ret */
|
||||
t0x = T0_RPOP();
|
||||
rp -= (t0x >> 16);
|
||||
t0x &= 0xFFFF;
|
||||
if (t0x == 0) {
|
||||
ip = NULL;
|
||||
goto t0_exit;
|
||||
}
|
||||
ip = &t0_codeblock[t0x];
|
||||
break;
|
||||
case 1: /* literal constant */
|
||||
T0_PUSHi(t0_parse7E_signed(&ip));
|
||||
break;
|
||||
case 2: /* read local */
|
||||
T0_PUSH(T0_LOCAL(t0_parse7E_unsigned(&ip)));
|
||||
break;
|
||||
case 3: /* write local */
|
||||
T0_LOCAL(t0_parse7E_unsigned(&ip)) = T0_POP();
|
||||
break;
|
||||
case 4: /* jump */
|
||||
t0off = t0_parse7E_signed(&ip);
|
||||
ip += t0off;
|
||||
break;
|
||||
case 5: /* jump if */
|
||||
t0off = t0_parse7E_signed(&ip);
|
||||
if (T0_POP()) {
|
||||
ip += t0off;
|
||||
}
|
||||
break;
|
||||
case 6: /* jump if not */
|
||||
t0off = t0_parse7E_signed(&ip);
|
||||
if (!T0_POP()) {
|
||||
ip += t0off;
|
||||
}
|
||||
break;
|
||||
case 7: {
|
||||
/* + */
|
||||
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a + b);
|
||||
|
||||
}
|
||||
break;
|
||||
case 8: {
|
||||
/* - */
|
||||
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a - b);
|
||||
|
||||
}
|
||||
break;
|
||||
case 9: {
|
||||
/* < */
|
||||
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a < b));
|
||||
|
||||
}
|
||||
break;
|
||||
case 10: {
|
||||
/* << */
|
||||
|
||||
int c = (int)T0_POPi();
|
||||
uint32_t x = T0_POP();
|
||||
T0_PUSH(x << c);
|
||||
|
||||
}
|
||||
break;
|
||||
case 11: {
|
||||
/* <= */
|
||||
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a <= b));
|
||||
|
||||
}
|
||||
break;
|
||||
case 12: {
|
||||
/* <> */
|
||||
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a != b));
|
||||
|
||||
}
|
||||
break;
|
||||
case 13: {
|
||||
/* = */
|
||||
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(-(uint32_t)(a == b));
|
||||
|
||||
}
|
||||
break;
|
||||
case 14: {
|
||||
/* >= */
|
||||
|
||||
int32_t b = T0_POPi();
|
||||
int32_t a = T0_POPi();
|
||||
T0_PUSH(-(uint32_t)(a >= b));
|
||||
|
||||
}
|
||||
break;
|
||||
case 15: {
|
||||
/* >> */
|
||||
|
||||
int c = (int)T0_POPi();
|
||||
int32_t x = T0_POPi();
|
||||
T0_PUSHi(x >> c);
|
||||
|
||||
}
|
||||
break;
|
||||
case 16: {
|
||||
/* and */
|
||||
|
||||
uint32_t b = T0_POP();
|
||||
uint32_t a = T0_POP();
|
||||
T0_PUSH(a & b);
|
||||
|
||||
}
|
||||
break;
|
||||
case 17: {
|
||||
/* co */
|
||||
T0_CO();
|
||||
}
|
||||
break;
|
||||
case 18: {
|
||||
/* data-get8 */
|
||||
|
||||
size_t addr = T0_POP();
|
||||
T0_PUSH(t0_datablock[addr]);
|
||||
|
||||
}
|
||||
break;
|
||||
case 19: {
|
||||
/* drop */
|
||||
(void)T0_POP();
|
||||
}
|
||||
break;
|
||||
case 20: {
|
||||
/* dup */
|
||||
T0_PUSH(T0_PEEK(0));
|
||||
}
|
||||
break;
|
||||
case 21: {
|
||||
/* flush-buf */
|
||||
|
||||
if (CTX->ptr > 0) {
|
||||
if (CTX->dest) {
|
||||
CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr);
|
||||
}
|
||||
CTX->ptr = 0;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 22: {
|
||||
/* from-base64 */
|
||||
|
||||
uint32_t c = T0_POP();
|
||||
uint32_t p, q, r, z;
|
||||
p = c - 0x41;
|
||||
q = c - 0x61;
|
||||
r = c - 0x30;
|
||||
|
||||
z = ((p + 2) & -LT(p, 26))
|
||||
| ((q + 28) & -LT(q, 26))
|
||||
| ((r + 54) & -LT(r, 10))
|
||||
| (64 & -EQ(c, 0x2B))
|
||||
| (65 & -EQ(c, 0x2F))
|
||||
| EQ(c, 0x3D);
|
||||
T0_PUSHi((int32_t)z - 2);
|
||||
|
||||
}
|
||||
break;
|
||||
case 23: {
|
||||
/* get8 */
|
||||
|
||||
size_t addr = T0_POP();
|
||||
T0_PUSH(*((unsigned char *)CTX + addr));
|
||||
|
||||
}
|
||||
break;
|
||||
case 24: {
|
||||
/* over */
|
||||
T0_PUSH(T0_PEEK(1));
|
||||
}
|
||||
break;
|
||||
case 25: {
|
||||
/* read8-native */
|
||||
|
||||
if (CTX->hlen > 0) {
|
||||
T0_PUSH(*CTX->hbuf ++);
|
||||
CTX->hlen --;
|
||||
} else {
|
||||
T0_PUSHi(-1);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 26: {
|
||||
/* set8 */
|
||||
|
||||
size_t addr = T0_POP();
|
||||
unsigned x = T0_POP();
|
||||
*((unsigned char *)CTX + addr) = x;
|
||||
|
||||
}
|
||||
break;
|
||||
case 27: {
|
||||
/* swap */
|
||||
T0_SWAP();
|
||||
}
|
||||
break;
|
||||
case 28: {
|
||||
/* write8 */
|
||||
|
||||
unsigned char x = (unsigned char)T0_POP();
|
||||
CTX->buf[CTX->ptr ++] = x;
|
||||
if (CTX->ptr == sizeof CTX->buf) {
|
||||
if (CTX->dest) {
|
||||
CTX->dest(CTX->dest_ctx, CTX->buf, sizeof CTX->buf);
|
||||
}
|
||||
CTX->ptr = 0;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
T0_ENTER(ip, rp, t0x);
|
||||
}
|
||||
}
|
||||
t0_exit:
|
||||
((t0_context *)t0ctx)->dp = dp;
|
||||
((t0_context *)t0ctx)->rp = rp;
|
||||
((t0_context *)t0ctx)->ip = ip;
|
||||
}
|
||||
314
dstalk-core/thirdparty/bearssl/src/codec/pemdec.t0
vendored
314
dstalk-core/thirdparty/bearssl/src/codec/pemdec.t0
vendored
@@ -1,314 +0,0 @@
|
||||
\ Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
\
|
||||
\ Permission is hereby granted, free of charge, to any person obtaining
|
||||
\ a copy of this software and associated documentation files (the
|
||||
\ "Software"), to deal in the Software without restriction, including
|
||||
\ without limitation the rights to use, copy, modify, merge, publish,
|
||||
\ distribute, sublicense, and/or sell copies of the Software, and to
|
||||
\ permit persons to whom the Software is furnished to do so, subject to
|
||||
\ the following conditions:
|
||||
\
|
||||
\ The above copyright notice and this permission notice shall be
|
||||
\ included in all copies or substantial portions of the Software.
|
||||
\
|
||||
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
\ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
\ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
\ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
\ SOFTWARE.
|
||||
|
||||
preamble {
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define CTX ((br_pem_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu)))
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
void
|
||||
br_pem_decoder_init(br_pem_decoder_context *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof *ctx);
|
||||
ctx->cpu.dp = &ctx->dp_stack[0];
|
||||
ctx->cpu.rp = &ctx->rp_stack[0];
|
||||
br_pem_decoder_init_main(&ctx->cpu);
|
||||
br_pem_decoder_run(&ctx->cpu);
|
||||
}
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
size_t
|
||||
br_pem_decoder_push(br_pem_decoder_context *ctx,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
if (ctx->event) {
|
||||
return 0;
|
||||
}
|
||||
ctx->hbuf = data;
|
||||
ctx->hlen = len;
|
||||
br_pem_decoder_run(&ctx->cpu);
|
||||
return len - ctx->hlen;
|
||||
}
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
int
|
||||
br_pem_decoder_event(br_pem_decoder_context *ctx)
|
||||
{
|
||||
int event;
|
||||
|
||||
event = ctx->event;
|
||||
ctx->event = 0;
|
||||
return event;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
\ Define a word that evaluates to the address of a field within the
|
||||
\ decoder context.
|
||||
: addr:
|
||||
next-word { field }
|
||||
"addr-" field + 0 1 define-word
|
||||
0 8191 "offsetof(br_pem_decoder_context, " field + ")" + make-CX
|
||||
postpone literal postpone ; ;
|
||||
|
||||
addr: event
|
||||
addr: name
|
||||
addr: buf
|
||||
addr: ptr
|
||||
|
||||
\ Set a byte at a specific address (offset within the context).
|
||||
cc: set8 ( value addr -- ) {
|
||||
size_t addr = T0_POP();
|
||||
unsigned x = T0_POP();
|
||||
*((unsigned char *)CTX + addr) = x;
|
||||
}
|
||||
|
||||
\ Get a byte at a specific address (offset within the context).
|
||||
cc: get8 ( addr -- value ) {
|
||||
size_t addr = T0_POP();
|
||||
T0_PUSH(*((unsigned char *)CTX + addr));
|
||||
}
|
||||
|
||||
\ Send an event.
|
||||
: send-event ( event -- )
|
||||
addr-event set8 co ;
|
||||
|
||||
\ Low-level function to read a single byte. Returned value is the byte
|
||||
\ (0 to 255), or -1 if there is no available data.
|
||||
cc: read8-native ( -- x ) {
|
||||
if (CTX->hlen > 0) {
|
||||
T0_PUSH(*CTX->hbuf ++);
|
||||
CTX->hlen --;
|
||||
} else {
|
||||
T0_PUSHi(-1);
|
||||
}
|
||||
}
|
||||
|
||||
\ Read next byte. Block until the next byte is available.
|
||||
: read8 ( -- x )
|
||||
begin read8-native dup 0< ifnot ret then drop co again ;
|
||||
|
||||
\ Read bytes until next end-of-line.
|
||||
: skip-newline ( -- )
|
||||
begin read8 `\n <> while repeat ;
|
||||
|
||||
\ Read bytes until next end-of-line; verify that they are all whitespace.
|
||||
\ This returns -1 if they were all whitespace, 0 otherwise.
|
||||
: skip-newline-ws ( -- bool )
|
||||
-1 { r }
|
||||
begin read8 dup `\n <> while ws? ifnot 0 >r then repeat
|
||||
drop r ;
|
||||
|
||||
\ Normalise a byte to uppercase (ASCII only).
|
||||
: norm-upper ( x -- x )
|
||||
dup dup `a >= swap `z <= and if 32 - then ;
|
||||
|
||||
\ Read bytes and compare with the provided string. On mismatch, the
|
||||
\ rest of the line is consumed. Matching is not case sensitive.
|
||||
: match-string ( str -- bool )
|
||||
begin
|
||||
dup data-get8 norm-upper dup ifnot 2drop -1 ret then
|
||||
read8 norm-upper dup `\n = if drop 2drop 0 ret then
|
||||
= ifnot drop skip-newline 0 ret then
|
||||
1+
|
||||
again ;
|
||||
|
||||
\ Read bytes into the provided buffer, but no more than the provided
|
||||
\ count. Reading stops when end-of-line is reached. Returned value
|
||||
\ is the count of bytes written to the buffer, or 0 if the buffer size
|
||||
\ was exceeded. All bytes are normalised to uppercase (ASCII only).
|
||||
: read-bytes ( addr len -- len )
|
||||
dup { orig-len }
|
||||
swap
|
||||
begin
|
||||
over ifnot 2drop skip-newline 0 ret then
|
||||
read8 dup `\n = if 2drop orig-len swap - ret then
|
||||
dup `\r = if drop else norm-upper over set8 then
|
||||
1+ swap 1- swap
|
||||
again ;
|
||||
|
||||
\ Remove trailing dashes from the name buffer.
|
||||
: trim-dashes ( len -- )
|
||||
begin dup while
|
||||
1-
|
||||
dup addr-name + get8 `- <> if
|
||||
addr-name + 1+ 0 swap set8 ret
|
||||
then
|
||||
repeat
|
||||
addr-name set8 ;
|
||||
|
||||
\ Scan input for next "begin" banner.
|
||||
: next-banner-begin ( -- )
|
||||
begin
|
||||
"-----BEGIN " match-string if
|
||||
addr-name 127 read-bytes
|
||||
dup if trim-dashes ret then
|
||||
drop
|
||||
then
|
||||
again ;
|
||||
|
||||
\ Convert a Base64 character to its numerical value. Returned value is
|
||||
\ 0 to 63 for Base64 characters, -1 for '=', and -2 for all other characters.
|
||||
cc: from-base64 ( char -- x ) {
|
||||
uint32_t c = T0_POP();
|
||||
uint32_t p, q, r, z;
|
||||
p = c - 0x41;
|
||||
q = c - 0x61;
|
||||
r = c - 0x30;
|
||||
|
||||
z = ((p + 2) & -LT(p, 26))
|
||||
| ((q + 28) & -LT(q, 26))
|
||||
| ((r + 54) & -LT(r, 10))
|
||||
| (64 & -EQ(c, 0x2B))
|
||||
| (65 & -EQ(c, 0x2F))
|
||||
| EQ(c, 0x3D);
|
||||
T0_PUSHi((int32_t)z - 2);
|
||||
}
|
||||
|
||||
\ Test whether a character is whitespace (but not a newline).
|
||||
: ws? ( x -- bool )
|
||||
dup `\n <> swap 32 <= and ;
|
||||
|
||||
\ Read next character, skipping whitespace (except newline).
|
||||
: next-nonws ( -- x )
|
||||
begin
|
||||
read8 dup ws? ifnot ret then
|
||||
drop
|
||||
again ;
|
||||
|
||||
\ Write one byte in the output buffer.
|
||||
cc: write8 ( x -- ) {
|
||||
unsigned char x = (unsigned char)T0_POP();
|
||||
CTX->buf[CTX->ptr ++] = x;
|
||||
if (CTX->ptr == sizeof CTX->buf) {
|
||||
if (CTX->dest) {
|
||||
CTX->dest(CTX->dest_ctx, CTX->buf, sizeof CTX->buf);
|
||||
}
|
||||
CTX->ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
\ Flush the output buffer.
|
||||
cc: flush-buf ( -- ) {
|
||||
if (CTX->ptr > 0) {
|
||||
if (CTX->dest) {
|
||||
CTX->dest(CTX->dest_ctx, CTX->buf, CTX->ptr);
|
||||
}
|
||||
CTX->ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
\ Decode the four next Base64 characters. Returned value is:
|
||||
\ 0 quartet processed, three bytes produced.
|
||||
\ -1 dash encountered as first character (no leading whitespace).
|
||||
\ 1 quartet processed, one or two bytes produced, terminator reached.
|
||||
\ 2 end-of-line reached.
|
||||
\ 3 error.
|
||||
\ For all positive return values, the remaining of the current line has been
|
||||
\ consumed.
|
||||
: decode-next-quartet ( -- r )
|
||||
\ Process first character. It may be a dash.
|
||||
read8 dup `- = if drop -1 ret then
|
||||
dup ws? if drop next-nonws then
|
||||
dup `\n = if drop 2 ret then
|
||||
from-base64 dup 0< if drop skip-newline 3 ret then
|
||||
{ acc }
|
||||
|
||||
\ Second character.
|
||||
next-nonws dup `\n = if drop 3 ret then
|
||||
from-base64 dup 0< if drop skip-newline 3 ret then
|
||||
acc 6 << + >acc
|
||||
|
||||
\ Third character: may be an equal sign.
|
||||
next-nonws dup `\n = if drop 3 ret then
|
||||
dup `= = if
|
||||
\ Fourth character must be an equal sign.
|
||||
drop
|
||||
next-nonws dup `\n = if drop 3 ret then
|
||||
skip-newline-ws ifnot drop 3 ret then
|
||||
`= <> if 3 ret then
|
||||
acc 0x0F and if 3 ret then
|
||||
acc 4 >> write8
|
||||
1 ret
|
||||
then
|
||||
from-base64 dup 0< if drop skip-newline 3 ret then
|
||||
acc 6 << + >acc
|
||||
|
||||
\ Fourth character: may be an equal sign.
|
||||
next-nonws dup `\n = if drop 3 ret then
|
||||
dup `= = if
|
||||
drop skip-newline-ws ifnot 3 ret then
|
||||
acc 0x03 and if 3 ret then
|
||||
acc 10 >> write8
|
||||
acc 2 >> write8
|
||||
1 ret
|
||||
then
|
||||
from-base64 dup 0< if drop skip-newline 3 ret then
|
||||
acc 6 << + >acc
|
||||
acc 16 >> write8
|
||||
acc 8 >> write8
|
||||
acc write8
|
||||
0 ;
|
||||
|
||||
\ Check trailer line (possibly, the leading dash has been read). This
|
||||
\ sends the appropriate event.
|
||||
: check-trailer ( bool -- )
|
||||
ifnot
|
||||
begin read8 dup `\n = while drop repeat
|
||||
`- <> if skip-newline 3 send-event ret then
|
||||
then
|
||||
"----END " match-string ifnot 3 send-event ret then
|
||||
flush-buf
|
||||
skip-newline 2 send-event ;
|
||||
|
||||
\ Decode one line worth of characters. Returned value is 0 if the end of the
|
||||
\ object is reached, -1 otherwise. The end of object or error event is sent.
|
||||
: decode-line ( -- bool )
|
||||
-1 { first }
|
||||
begin
|
||||
decode-next-quartet
|
||||
case
|
||||
0 of endof
|
||||
-1 of
|
||||
first ifnot
|
||||
skip-newline 3 send-event
|
||||
else
|
||||
-1 check-trailer
|
||||
then
|
||||
0 ret
|
||||
endof
|
||||
1 of 0 check-trailer 0 ret endof
|
||||
2 of -1 ret endof
|
||||
|
||||
\ On decoding error
|
||||
drop 3 send-event 0 ret
|
||||
endcase
|
||||
0 >first
|
||||
again ;
|
||||
|
||||
: main ( -- ! )
|
||||
begin
|
||||
next-banner-begin 1 send-event
|
||||
begin decode-line while repeat
|
||||
again ;
|
||||
173
dstalk-core/thirdparty/bearssl/src/codec/pemenc.c
vendored
173
dstalk-core/thirdparty/bearssl/src/codec/pemenc.c
vendored
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Get the appropriate Base64 character for a numeric value in the
|
||||
* 0..63 range. This is constant-time.
|
||||
*/
|
||||
static char
|
||||
b64char(uint32_t x)
|
||||
{
|
||||
/*
|
||||
* Values 0 to 25 map to 0x41..0x5A ('A' to 'Z')
|
||||
* Values 26 to 51 map to 0x61..0x7A ('a' to 'z')
|
||||
* Values 52 to 61 map to 0x30..0x39 ('0' to '9')
|
||||
* Value 62 maps to 0x2B ('+')
|
||||
* Value 63 maps to 0x2F ('/')
|
||||
*/
|
||||
uint32_t a, b, c;
|
||||
|
||||
a = x - 26;
|
||||
b = x - 52;
|
||||
c = x - 62;
|
||||
|
||||
/*
|
||||
* Looking at bits 8..15 of values a, b and c:
|
||||
*
|
||||
* x a b c
|
||||
* ---------------------
|
||||
* 0..25 FF FF FF
|
||||
* 26..51 00 FF FF
|
||||
* 52..61 00 00 FF
|
||||
* 62..63 00 00 00
|
||||
*/
|
||||
return (char)(((x + 0x41) & ((a & b & c) >> 8))
|
||||
| ((x + (0x61 - 26)) & ((~a & b & c) >> 8))
|
||||
| ((x - (52 - 0x30)) & ((~a & ~b & c) >> 8))
|
||||
| ((0x2B + ((x & 1) << 2)) & (~(a | b | c) >> 8)));
|
||||
}
|
||||
|
||||
/* see bearssl_pem.h */
|
||||
size_t
|
||||
br_pem_encode(void *dest, const void *data, size_t len,
|
||||
const char *banner, unsigned flags)
|
||||
{
|
||||
size_t dlen, banner_len, lines;
|
||||
char *d;
|
||||
unsigned char *buf;
|
||||
size_t u;
|
||||
int off, lim;
|
||||
|
||||
banner_len = strlen(banner);
|
||||
/* FIXME: try to avoid divisions here, as they may pull
|
||||
an extra libc function. */
|
||||
if ((flags & BR_PEM_LINE64) != 0) {
|
||||
lines = (len + 47) / 48;
|
||||
} else {
|
||||
lines = (len + 56) / 57;
|
||||
}
|
||||
dlen = (banner_len << 1) + 30 + (((len + 2) / 3) << 2)
|
||||
+ lines + 2;
|
||||
if ((flags & BR_PEM_CRLF) != 0) {
|
||||
dlen += lines + 2;
|
||||
}
|
||||
|
||||
if (dest == NULL) {
|
||||
return dlen;
|
||||
}
|
||||
|
||||
d = dest;
|
||||
|
||||
/*
|
||||
* We always move the source data to the end of output buffer;
|
||||
* the encoding process never "catches up" except at the very
|
||||
* end. This also handles all conditions of partial or total
|
||||
* overlap.
|
||||
*/
|
||||
buf = (unsigned char *)d + dlen - len;
|
||||
memmove(buf, data, len);
|
||||
|
||||
memcpy(d, "-----BEGIN ", 11);
|
||||
d += 11;
|
||||
memcpy(d, banner, banner_len);
|
||||
d += banner_len;
|
||||
memcpy(d, "-----", 5);
|
||||
d += 5;
|
||||
if ((flags & BR_PEM_CRLF) != 0) {
|
||||
*d ++ = 0x0D;
|
||||
}
|
||||
*d ++ = 0x0A;
|
||||
|
||||
off = 0;
|
||||
lim = (flags & BR_PEM_LINE64) != 0 ? 16 : 19;
|
||||
for (u = 0; (u + 2) < len; u += 3) {
|
||||
uint32_t w;
|
||||
|
||||
w = ((uint32_t)buf[u] << 16)
|
||||
| ((uint32_t)buf[u + 1] << 8)
|
||||
| (uint32_t)buf[u + 2];
|
||||
*d ++ = b64char(w >> 18);
|
||||
*d ++ = b64char((w >> 12) & 0x3F);
|
||||
*d ++ = b64char((w >> 6) & 0x3F);
|
||||
*d ++ = b64char(w & 0x3F);
|
||||
if (++ off == lim) {
|
||||
off = 0;
|
||||
if ((flags & BR_PEM_CRLF) != 0) {
|
||||
*d ++ = 0x0D;
|
||||
}
|
||||
*d ++ = 0x0A;
|
||||
}
|
||||
}
|
||||
if (u < len) {
|
||||
uint32_t w;
|
||||
|
||||
w = (uint32_t)buf[u] << 16;
|
||||
if (u + 1 < len) {
|
||||
w |= (uint32_t)buf[u + 1] << 8;
|
||||
}
|
||||
*d ++ = b64char(w >> 18);
|
||||
*d ++ = b64char((w >> 12) & 0x3F);
|
||||
if (u + 1 < len) {
|
||||
*d ++ = b64char((w >> 6) & 0x3F);
|
||||
} else {
|
||||
*d ++ = 0x3D;
|
||||
}
|
||||
*d ++ = 0x3D;
|
||||
off ++;
|
||||
}
|
||||
if (off != 0) {
|
||||
if ((flags & BR_PEM_CRLF) != 0) {
|
||||
*d ++ = 0x0D;
|
||||
}
|
||||
*d ++ = 0x0A;
|
||||
}
|
||||
|
||||
memcpy(d, "-----END ", 9);
|
||||
d += 9;
|
||||
memcpy(d, banner, banner_len);
|
||||
d += banner_len;
|
||||
memcpy(d, "-----", 5);
|
||||
d += 5;
|
||||
if ((flags & BR_PEM_CRLF) != 0) {
|
||||
*d ++ = 0x0D;
|
||||
}
|
||||
*d ++ = 0x0A;
|
||||
|
||||
/* Final zero, not counted in returned length. */
|
||||
*d ++ = 0x00;
|
||||
|
||||
return dlen;
|
||||
}
|
||||
229
dstalk-core/thirdparty/bearssl/src/config.h
vendored
229
dstalk-core/thirdparty/bearssl/src/config.h
vendored
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H__
|
||||
#define CONFIG_H__
|
||||
|
||||
/*
|
||||
* This file contains compile-time flags that can override the
|
||||
* autodetection performed in relevant files. Each flag is a macro; it
|
||||
* deactivates the feature if defined to 0, activates it if defined to a
|
||||
* non-zero integer (normally 1). If the macro is not defined, then
|
||||
* autodetection applies.
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_64 is enabled, 64-bit integer types are assumed to be
|
||||
* efficient (i.e. the architecture has 64-bit registers and can
|
||||
* do 64-bit operations as fast as 32-bit operations).
|
||||
*
|
||||
#define BR_64 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_LOMUL is enabled, then multiplications of 32-bit values whose
|
||||
* result are truncated to the low 32 bits are assumed to be
|
||||
* substantially more efficient than 32-bit multiplications that yield
|
||||
* 64-bit results. This is typically the case on low-end ARM Cortex M
|
||||
* systems (M0, M0+, M1, and arguably M3 and M4 as well).
|
||||
*
|
||||
#define BR_LOMUL 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_SLOW_MUL is enabled, multiplications are assumed to be
|
||||
* substantially slow with regards to other integer operations, thus
|
||||
* making it worth to make more operations for a given task if it allows
|
||||
* using less multiplications.
|
||||
*
|
||||
#define BR_SLOW_MUL 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_SLOW_MUL15 is enabled, short multplications (on 15-bit words)
|
||||
* are assumed to be substantially slow with regards to other integer
|
||||
* operations, thus making it worth to make more integer operations if
|
||||
* it allows using less multiplications.
|
||||
*
|
||||
#define BR_SLOW_MUL15 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_CT_MUL31 is enabled, multiplications of 31-bit values (used
|
||||
* in the "i31" big integer implementation) use an alternate implementation
|
||||
* which is slower and larger than the normal multiplication, but should
|
||||
* ensure constant-time multiplications even on architectures where the
|
||||
* multiplication opcode takes a variable number of cycles to complete.
|
||||
*
|
||||
#define BR_CT_MUL31 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_CT_MUL15 is enabled, multiplications of 15-bit values (held
|
||||
* in 32-bit words) use an alternate implementation which is slower and
|
||||
* larger than the normal multiplication, but should ensure
|
||||
* constant-time multiplications on most/all architectures where the
|
||||
* basic multiplication is not constant-time.
|
||||
#define BR_CT_MUL15 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_NO_ARITH_SHIFT is enabled, arithmetic right shifts (with sign
|
||||
* extension) are performed with a sequence of operations which is bigger
|
||||
* and slower than a simple right shift on a signed value. This avoids
|
||||
* relying on an implementation-defined behaviour. However, most if not
|
||||
* all C compilers use sign extension for right shifts on signed values,
|
||||
* so this alternate macro is disabled by default.
|
||||
#define BR_NO_ARITH_SHIFT 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_RDRAND is enabled, the SSL engine will use the RDRAND opcode
|
||||
* to automatically obtain quality randomness for seeding its internal
|
||||
* PRNG. Since that opcode is present only in recent x86 CPU, its
|
||||
* support is dynamically tested; if the current CPU does not support
|
||||
* it, then another random source will be used, such as /dev/urandom or
|
||||
* CryptGenRandom().
|
||||
*
|
||||
#define BR_RDRAND 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_USE_URANDOM is enabled, the SSL engine will use /dev/urandom
|
||||
* to automatically obtain quality randomness for seedings its internal
|
||||
* PRNG.
|
||||
*
|
||||
#define BR_USE_URANDOM 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_USE_WIN32_RAND is enabled, the SSL engine will use the Win32
|
||||
* (CryptoAPI) functions (CryptAcquireContext(), CryptGenRandom()...) to
|
||||
* automatically obtain quality randomness for seedings its internal PRNG.
|
||||
*
|
||||
* Note: if both BR_USE_URANDOM and BR_USE_WIN32_RAND are defined, the
|
||||
* former takes precedence.
|
||||
*
|
||||
#define BR_USE_WIN32_RAND 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_USE_UNIX_TIME is enabled, the X.509 validation engine obtains
|
||||
* the current time from the OS by calling time(), and assuming that the
|
||||
* returned value (a 'time_t') is an integer that counts time in seconds
|
||||
* since the Unix Epoch (Jan 1st, 1970, 00:00 UTC).
|
||||
*
|
||||
#define BR_USE_UNIX_TIME 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_USE_WIN32_TIME is enabled, the X.509 validation engine obtains
|
||||
* the current time from the OS by calling the Win32 function
|
||||
* GetSystemTimeAsFileTime().
|
||||
*
|
||||
* Note: if both BR_USE_UNIX_TIME and BR_USE_WIN32_TIME are defined, the
|
||||
* former takes precedence.
|
||||
*
|
||||
#define BR_USE_WIN32_TIME 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_ARMEL_CORTEXM_GCC is enabled, some operations are replaced with
|
||||
* inline assembly which is shorter and/or faster. This should be used
|
||||
* only when all of the following are true:
|
||||
* - target architecture is ARM in Thumb mode
|
||||
* - target endianness is little-endian
|
||||
* - compiler is GCC (or GCC-compatible for inline assembly syntax)
|
||||
*
|
||||
* This is meant for the low-end cores (Cortex M0, M0+, M1, M3).
|
||||
* Note: if BR_LOMUL is not explicitly enabled or disabled, then
|
||||
* enabling BR_ARMEL_CORTEXM_GCC also enables BR_LOMUL.
|
||||
*
|
||||
#define BR_ARMEL_CORTEXM_GCC 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_AES_X86NI is enabled, the AES implementation using the x86 "NI"
|
||||
* instructions (dedicated AES opcodes) will be compiled. If this is not
|
||||
* enabled explicitly, then that AES implementation will be compiled only
|
||||
* if a compatible compiler is detected. If set explicitly to 0, the
|
||||
* implementation will not be compiled at all.
|
||||
*
|
||||
#define BR_AES_X86NI 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_SSE2 is enabled, SSE2 intrinsics will be used for some
|
||||
* algorithm implementations that use them (e.g. chacha20_sse2). If this
|
||||
* is not enabled explicitly, then support for SSE2 intrinsics will be
|
||||
* automatically detected. If set explicitly to 0, then SSE2 code will
|
||||
* not be compiled at all.
|
||||
*
|
||||
#define BR_SSE2 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_POWER8 is enabled, the AES implementation using the POWER ISA
|
||||
* 2.07 opcodes (available on POWER8 processors and later) is compiled.
|
||||
* If this is not enabled explicitly, then that implementation will be
|
||||
* compiled only if a compatible compiler is detected, _and_ the target
|
||||
* architecture is POWER8 or later.
|
||||
*
|
||||
#define BR_POWER8 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_INT128 is enabled, then code using the 'unsigned __int64'
|
||||
* and 'unsigned __int128' types will be used to leverage 64x64->128
|
||||
* unsigned multiplications. This should work with GCC and compatible
|
||||
* compilers on 64-bit architectures.
|
||||
*
|
||||
#define BR_INT128 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_UMUL128 is enabled, then code using the '_umul128()' and
|
||||
* '_addcarry_u64()' intrinsics will be used to implement 64x64->128
|
||||
* unsigned multiplications. This should work on Visual C on x64 systems.
|
||||
*
|
||||
#define BR_UMUL128 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_LE_UNALIGNED is enabled, then the current architecture is
|
||||
* assumed to use little-endian encoding for integers, and to tolerate
|
||||
* unaligned accesses with no or minimal time penalty.
|
||||
*
|
||||
#define BR_LE_UNALIGNED 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* When BR_BE_UNALIGNED is enabled, then the current architecture is
|
||||
* assumed to use big-endian encoding for integers, and to tolerate
|
||||
* unaligned accesses with no or minimal time penalty.
|
||||
*
|
||||
#define BR_BE_UNALIGNED 1
|
||||
*/
|
||||
|
||||
#endif
|
||||
121
dstalk-core/thirdparty/bearssl/src/ec/ec_all_m15.c
vendored
121
dstalk-core/thirdparty/bearssl/src/ec/ec_all_m15.c
vendored
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.generator(curve, len);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.generator(curve, len);
|
||||
default:
|
||||
return br_ec_prime_i15.generator(curve, len);
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.order(curve, len);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.order(curve, len);
|
||||
default:
|
||||
return br_ec_prime_i15.order(curve, len);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_xoff(int curve, size_t *len)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.xoff(curve, len);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.xoff(curve, len);
|
||||
default:
|
||||
return br_ec_prime_i15.xoff(curve, len);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *kb, size_t kblen, int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.mul(G, Glen, kb, kblen, curve);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.mul(G, Glen, kb, kblen, curve);
|
||||
default:
|
||||
return br_ec_prime_i15.mul(G, Glen, kb, kblen, curve);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_mulgen(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.mulgen(R, x, xlen, curve);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.mulgen(R, x, xlen, curve);
|
||||
default:
|
||||
return br_ec_prime_i15.mulgen(R, x, xlen, curve);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m15.muladd(A, B, len,
|
||||
x, xlen, y, ylen, curve);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m15.muladd(A, B, len,
|
||||
x, xlen, y, ylen, curve);
|
||||
default:
|
||||
return br_ec_prime_i15.muladd(A, B, len,
|
||||
x, xlen, y, ylen, curve);
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_all_m15 = {
|
||||
(uint32_t)0x23800000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_xoff,
|
||||
&api_mul,
|
||||
&api_mulgen,
|
||||
&api_muladd
|
||||
};
|
||||
121
dstalk-core/thirdparty/bearssl/src/ec/ec_all_m31.c
vendored
121
dstalk-core/thirdparty/bearssl/src/ec/ec_all_m31.c
vendored
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m31.generator(curve, len);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m31.generator(curve, len);
|
||||
default:
|
||||
return br_ec_prime_i31.generator(curve, len);
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m31.order(curve, len);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m31.order(curve, len);
|
||||
default:
|
||||
return br_ec_prime_i31.order(curve, len);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_xoff(int curve, size_t *len)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m31.xoff(curve, len);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m31.xoff(curve, len);
|
||||
default:
|
||||
return br_ec_prime_i31.xoff(curve, len);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *kb, size_t kblen, int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m31.mul(G, Glen, kb, kblen, curve);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m31.mul(G, Glen, kb, kblen, curve);
|
||||
default:
|
||||
return br_ec_prime_i31.mul(G, Glen, kb, kblen, curve);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_mulgen(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m31.mulgen(R, x, xlen, curve);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m31.mulgen(R, x, xlen, curve);
|
||||
default:
|
||||
return br_ec_prime_i31.mulgen(R, x, xlen, curve);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return br_ec_p256_m31.muladd(A, B, len,
|
||||
x, xlen, y, ylen, curve);
|
||||
case BR_EC_curve25519:
|
||||
return br_ec_c25519_m31.muladd(A, B, len,
|
||||
x, xlen, y, ylen, curve);
|
||||
default:
|
||||
return br_ec_prime_i31.muladd(A, B, len,
|
||||
x, xlen, y, ylen, curve);
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_all_m31 = {
|
||||
(uint32_t)0x23800000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_xoff,
|
||||
&api_mul,
|
||||
&api_mulgen,
|
||||
&api_muladd
|
||||
};
|
||||
@@ -1,398 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Parameters for the field:
|
||||
* - field modulus p = 2^255-19
|
||||
* - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p)
|
||||
*/
|
||||
|
||||
static const uint16_t C255_P[] = {
|
||||
0x0110,
|
||||
0x7FED, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF
|
||||
};
|
||||
|
||||
#define P0I 0x4A1B
|
||||
|
||||
static const uint16_t C255_R2[] = {
|
||||
0x0110,
|
||||
0x0169, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000
|
||||
};
|
||||
|
||||
/* obsolete
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
static void
|
||||
print_int_mont(const char *name, const uint16_t *x)
|
||||
{
|
||||
uint16_t y[18];
|
||||
unsigned char tmp[32];
|
||||
size_t u;
|
||||
|
||||
printf("%s = ", name);
|
||||
memcpy(y, x, sizeof y);
|
||||
br_i15_from_monty(y, C255_P, P0I);
|
||||
br_i15_encode(tmp, sizeof tmp, y);
|
||||
for (u = 0; u < sizeof tmp; u ++) {
|
||||
printf("%02X", tmp[u]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
*/
|
||||
|
||||
static const uint16_t C255_A24[] = {
|
||||
0x0110,
|
||||
0x45D3, 0x0046, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000
|
||||
};
|
||||
|
||||
static const unsigned char GEN[] = {
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const unsigned char ORDER[] = {
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return GEN;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return ORDER;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_xoff(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cswap(uint16_t *a, uint16_t *b, uint32_t ctl)
|
||||
{
|
||||
int i;
|
||||
|
||||
ctl = -ctl;
|
||||
for (i = 0; i < 18; i ++) {
|
||||
uint32_t aw, bw, tw;
|
||||
|
||||
aw = a[i];
|
||||
bw = b[i];
|
||||
tw = ctl & (aw ^ bw);
|
||||
a[i] = aw ^ tw;
|
||||
b[i] = bw ^ tw;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
c255_add(uint16_t *d, const uint16_t *a, const uint16_t *b)
|
||||
{
|
||||
uint32_t ctl;
|
||||
uint16_t t[18];
|
||||
|
||||
memcpy(t, a, sizeof t);
|
||||
ctl = br_i15_add(t, b, 1);
|
||||
ctl |= NOT(br_i15_sub(t, C255_P, 0));
|
||||
br_i15_sub(t, C255_P, ctl);
|
||||
memcpy(d, t, sizeof t);
|
||||
}
|
||||
|
||||
static void
|
||||
c255_sub(uint16_t *d, const uint16_t *a, const uint16_t *b)
|
||||
{
|
||||
uint16_t t[18];
|
||||
|
||||
memcpy(t, a, sizeof t);
|
||||
br_i15_add(t, C255_P, br_i15_sub(t, b, 1));
|
||||
memcpy(d, t, sizeof t);
|
||||
}
|
||||
|
||||
static void
|
||||
c255_mul(uint16_t *d, const uint16_t *a, const uint16_t *b)
|
||||
{
|
||||
uint16_t t[18];
|
||||
|
||||
br_i15_montymul(t, a, b, C255_P, P0I);
|
||||
memcpy(d, t, sizeof t);
|
||||
}
|
||||
|
||||
static void
|
||||
byteswap(unsigned char *G)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i ++) {
|
||||
unsigned char t;
|
||||
|
||||
t = G[i];
|
||||
G[i] = G[31 - i];
|
||||
G[31 - i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *kb, size_t kblen, int curve)
|
||||
{
|
||||
#define ILEN (18 * sizeof(uint16_t))
|
||||
|
||||
/*
|
||||
* The a[] and b[] arrays have an extra word to allow for
|
||||
* decoding without using br_i15_decode_reduce().
|
||||
*/
|
||||
uint16_t x1[18], x2[18], x3[18], z2[18], z3[18];
|
||||
uint16_t a[19], aa[18], b[19], bb[18];
|
||||
uint16_t c[18], d[18], e[18], da[18], cb[18];
|
||||
unsigned char k[32];
|
||||
uint32_t swap;
|
||||
int i;
|
||||
|
||||
(void)curve;
|
||||
|
||||
/*
|
||||
* Points are encoded over exactly 32 bytes. Multipliers must fit
|
||||
* in 32 bytes as well.
|
||||
* RFC 7748 mandates that the high bit of the last point byte must
|
||||
* be ignored/cleared.
|
||||
*/
|
||||
if (Glen != 32 || kblen > 32) {
|
||||
return 0;
|
||||
}
|
||||
G[31] &= 0x7F;
|
||||
|
||||
/*
|
||||
* Byteswap the point encoding, because it uses little-endian, and
|
||||
* the generic decoding routine uses big-endian.
|
||||
*/
|
||||
byteswap(G);
|
||||
|
||||
/*
|
||||
* Decode the point ('u' coordinate). This should be reduced
|
||||
* modulo p, but we prefer to avoid the dependency on
|
||||
* br_i15_decode_reduce(). Instead, we use br_i15_decode_mod()
|
||||
* with a synthetic modulus of value 2^255 (this must work
|
||||
* since G was truncated to 255 bits), then use a conditional
|
||||
* subtraction. We use br_i15_decode_mod() and not
|
||||
* br_i15_decode(), because the ec_prime_i15 implementation uses
|
||||
* the former but not the latter.
|
||||
* br_i15_decode_reduce(a, G, 32, C255_P);
|
||||
*/
|
||||
br_i15_zero(b, 0x111);
|
||||
b[18] = 1;
|
||||
br_i15_decode_mod(a, G, 32, b);
|
||||
a[0] = 0x110;
|
||||
br_i15_sub(a, C255_P, NOT(br_i15_sub(a, C255_P, 0)));
|
||||
|
||||
/*
|
||||
* Initialise variables x1, x2, z2, x3 and z3. We set all of them
|
||||
* into Montgomery representation.
|
||||
*/
|
||||
br_i15_montymul(x1, a, C255_R2, C255_P, P0I);
|
||||
memcpy(x3, x1, ILEN);
|
||||
br_i15_zero(z2, C255_P[0]);
|
||||
memcpy(x2, z2, ILEN);
|
||||
x2[1] = 19;
|
||||
memcpy(z3, x2, ILEN);
|
||||
|
||||
memcpy(k, kb, kblen);
|
||||
memset(k + kblen, 0, (sizeof k) - kblen);
|
||||
k[0] &= 0xF8;
|
||||
k[31] &= 0x7F;
|
||||
k[31] |= 0x40;
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("x1", x1);
|
||||
*/
|
||||
|
||||
swap = 0;
|
||||
for (i = 254; i >= 0; i --) {
|
||||
uint32_t kt;
|
||||
|
||||
kt = (k[i >> 3] >> (i & 7)) & 1;
|
||||
swap ^= kt;
|
||||
cswap(x2, x3, swap);
|
||||
cswap(z2, z3, swap);
|
||||
swap = kt;
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("x2", x2);
|
||||
print_int_mont("z2", z2);
|
||||
print_int_mont("x3", x3);
|
||||
print_int_mont("z3", z3);
|
||||
*/
|
||||
|
||||
c255_add(a, x2, z2);
|
||||
c255_mul(aa, a, a);
|
||||
c255_sub(b, x2, z2);
|
||||
c255_mul(bb, b, b);
|
||||
c255_sub(e, aa, bb);
|
||||
c255_add(c, x3, z3);
|
||||
c255_sub(d, x3, z3);
|
||||
c255_mul(da, d, a);
|
||||
c255_mul(cb, c, b);
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("a ", a);
|
||||
print_int_mont("aa", aa);
|
||||
print_int_mont("b ", b);
|
||||
print_int_mont("bb", bb);
|
||||
print_int_mont("e ", e);
|
||||
print_int_mont("c ", c);
|
||||
print_int_mont("d ", d);
|
||||
print_int_mont("da", da);
|
||||
print_int_mont("cb", cb);
|
||||
*/
|
||||
|
||||
c255_add(x3, da, cb);
|
||||
c255_mul(x3, x3, x3);
|
||||
c255_sub(z3, da, cb);
|
||||
c255_mul(z3, z3, z3);
|
||||
c255_mul(z3, z3, x1);
|
||||
c255_mul(x2, aa, bb);
|
||||
c255_mul(z2, C255_A24, e);
|
||||
c255_add(z2, z2, aa);
|
||||
c255_mul(z2, e, z2);
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("x2", x2);
|
||||
print_int_mont("z2", z2);
|
||||
print_int_mont("x3", x3);
|
||||
print_int_mont("z3", z3);
|
||||
*/
|
||||
}
|
||||
cswap(x2, x3, swap);
|
||||
cswap(z2, z3, swap);
|
||||
|
||||
/*
|
||||
* Inverse z2 with a modular exponentiation. This is a simple
|
||||
* square-and-multiply algorithm; we mutualise most non-squarings
|
||||
* since the exponent contains almost only ones.
|
||||
*/
|
||||
memcpy(a, z2, ILEN);
|
||||
for (i = 0; i < 15; i ++) {
|
||||
c255_mul(a, a, a);
|
||||
c255_mul(a, a, z2);
|
||||
}
|
||||
memcpy(b, a, ILEN);
|
||||
for (i = 0; i < 14; i ++) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < 16; j ++) {
|
||||
c255_mul(b, b, b);
|
||||
}
|
||||
c255_mul(b, b, a);
|
||||
}
|
||||
for (i = 14; i >= 0; i --) {
|
||||
c255_mul(b, b, b);
|
||||
if ((0xFFEB >> i) & 1) {
|
||||
c255_mul(b, z2, b);
|
||||
}
|
||||
}
|
||||
c255_mul(b, x2, b);
|
||||
|
||||
/*
|
||||
* To avoid a dependency on br_i15_from_monty(), we use a
|
||||
* Montgomery multiplication with 1.
|
||||
* memcpy(x2, b, ILEN);
|
||||
* br_i15_from_monty(x2, C255_P, P0I);
|
||||
*/
|
||||
br_i15_zero(a, C255_P[0]);
|
||||
a[1] = 1;
|
||||
br_i15_montymul(x2, a, b, C255_P, P0I);
|
||||
|
||||
br_i15_encode(G, 32, x2);
|
||||
byteswap(G);
|
||||
return 1;
|
||||
|
||||
#undef ILEN
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_mulgen(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
const unsigned char *G;
|
||||
size_t Glen;
|
||||
|
||||
G = api_generator(curve, &Glen);
|
||||
memcpy(R, G, Glen);
|
||||
api_mul(R, Glen, x, xlen, curve);
|
||||
return Glen;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
/*
|
||||
* We don't implement this method, since it is used for ECDSA
|
||||
* only, and there is no ECDSA over Curve25519 (which instead
|
||||
* uses EdDSA).
|
||||
*/
|
||||
(void)A;
|
||||
(void)B;
|
||||
(void)len;
|
||||
(void)x;
|
||||
(void)xlen;
|
||||
(void)y;
|
||||
(void)ylen;
|
||||
(void)curve;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_c25519_i15 = {
|
||||
(uint32_t)0x20000000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_xoff,
|
||||
&api_mul,
|
||||
&api_mulgen,
|
||||
&api_muladd
|
||||
};
|
||||
@@ -1,387 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Parameters for the field:
|
||||
* - field modulus p = 2^255-19
|
||||
* - R^2 mod p (R = 2^(31k) for the smallest k such that R >= p)
|
||||
*/
|
||||
|
||||
static const uint32_t C255_P[] = {
|
||||
0x00000107,
|
||||
0x7FFFFFED, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0000007F
|
||||
};
|
||||
|
||||
#define P0I 0x286BCA1B
|
||||
|
||||
static const uint32_t C255_R2[] = {
|
||||
0x00000107,
|
||||
0x00000000, 0x02D20000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t C255_A24[] = {
|
||||
0x00000107,
|
||||
0x53000000, 0x0000468B, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
/* obsolete
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
static void
|
||||
print_int_mont(const char *name, const uint32_t *x)
|
||||
{
|
||||
uint32_t y[10];
|
||||
unsigned char tmp[32];
|
||||
size_t u;
|
||||
|
||||
printf("%s = ", name);
|
||||
memcpy(y, x, sizeof y);
|
||||
br_i31_from_monty(y, C255_P, P0I);
|
||||
br_i31_encode(tmp, sizeof tmp, y);
|
||||
for (u = 0; u < sizeof tmp; u ++) {
|
||||
printf("%02X", tmp[u]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
*/
|
||||
|
||||
static const unsigned char GEN[] = {
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const unsigned char ORDER[] = {
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return GEN;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return ORDER;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_xoff(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cswap(uint32_t *a, uint32_t *b, uint32_t ctl)
|
||||
{
|
||||
int i;
|
||||
|
||||
ctl = -ctl;
|
||||
for (i = 0; i < 10; i ++) {
|
||||
uint32_t aw, bw, tw;
|
||||
|
||||
aw = a[i];
|
||||
bw = b[i];
|
||||
tw = ctl & (aw ^ bw);
|
||||
a[i] = aw ^ tw;
|
||||
b[i] = bw ^ tw;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
c255_add(uint32_t *d, const uint32_t *a, const uint32_t *b)
|
||||
{
|
||||
uint32_t ctl;
|
||||
uint32_t t[10];
|
||||
|
||||
memcpy(t, a, sizeof t);
|
||||
ctl = br_i31_add(t, b, 1);
|
||||
ctl |= NOT(br_i31_sub(t, C255_P, 0));
|
||||
br_i31_sub(t, C255_P, ctl);
|
||||
memcpy(d, t, sizeof t);
|
||||
}
|
||||
|
||||
static void
|
||||
c255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b)
|
||||
{
|
||||
uint32_t t[10];
|
||||
|
||||
memcpy(t, a, sizeof t);
|
||||
br_i31_add(t, C255_P, br_i31_sub(t, b, 1));
|
||||
memcpy(d, t, sizeof t);
|
||||
}
|
||||
|
||||
static void
|
||||
c255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b)
|
||||
{
|
||||
uint32_t t[10];
|
||||
|
||||
br_i31_montymul(t, a, b, C255_P, P0I);
|
||||
memcpy(d, t, sizeof t);
|
||||
}
|
||||
|
||||
static void
|
||||
byteswap(unsigned char *G)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i ++) {
|
||||
unsigned char t;
|
||||
|
||||
t = G[i];
|
||||
G[i] = G[31 - i];
|
||||
G[31 - i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *kb, size_t kblen, int curve)
|
||||
{
|
||||
uint32_t x1[10], x2[10], x3[10], z2[10], z3[10];
|
||||
uint32_t a[10], aa[10], b[10], bb[10];
|
||||
uint32_t c[10], d[10], e[10], da[10], cb[10];
|
||||
unsigned char k[32];
|
||||
uint32_t swap;
|
||||
int i;
|
||||
|
||||
(void)curve;
|
||||
|
||||
/*
|
||||
* Points are encoded over exactly 32 bytes. Multipliers must fit
|
||||
* in 32 bytes as well.
|
||||
* RFC 7748 mandates that the high bit of the last point byte must
|
||||
* be ignored/cleared.
|
||||
*/
|
||||
if (Glen != 32 || kblen > 32) {
|
||||
return 0;
|
||||
}
|
||||
G[31] &= 0x7F;
|
||||
|
||||
/*
|
||||
* Byteswap the point encoding, because it uses little-endian, and
|
||||
* the generic decoding routine uses big-endian.
|
||||
*/
|
||||
byteswap(G);
|
||||
|
||||
/*
|
||||
* Decode the point ('u' coordinate). This should be reduced
|
||||
* modulo p, but we prefer to avoid the dependency on
|
||||
* br_i31_decode_reduce(). Instead, we use br_i31_decode_mod()
|
||||
* with a synthetic modulus of value 2^255 (this must work
|
||||
* since G was truncated to 255 bits), then use a conditional
|
||||
* subtraction. We use br_i31_decode_mod() and not
|
||||
* br_i31_decode(), because the ec_prime_i31 implementation uses
|
||||
* the former but not the latter.
|
||||
* br_i31_decode_reduce(a, G, 32, C255_P);
|
||||
*/
|
||||
br_i31_zero(b, 0x108);
|
||||
b[9] = 0x0100;
|
||||
br_i31_decode_mod(a, G, 32, b);
|
||||
a[0] = 0x107;
|
||||
br_i31_sub(a, C255_P, NOT(br_i31_sub(a, C255_P, 0)));
|
||||
|
||||
/*
|
||||
* Initialise variables x1, x2, z2, x3 and z3. We set all of them
|
||||
* into Montgomery representation.
|
||||
*/
|
||||
br_i31_montymul(x1, a, C255_R2, C255_P, P0I);
|
||||
memcpy(x3, x1, sizeof x1);
|
||||
br_i31_zero(z2, C255_P[0]);
|
||||
memcpy(x2, z2, sizeof z2);
|
||||
x2[1] = 0x13000000;
|
||||
memcpy(z3, x2, sizeof x2);
|
||||
|
||||
memcpy(k, kb, kblen);
|
||||
memset(k + kblen, 0, (sizeof k) - kblen);
|
||||
k[0] &= 0xF8;
|
||||
k[31] &= 0x7F;
|
||||
k[31] |= 0x40;
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("x1", x1);
|
||||
*/
|
||||
|
||||
swap = 0;
|
||||
for (i = 254; i >= 0; i --) {
|
||||
uint32_t kt;
|
||||
|
||||
kt = (k[i >> 3] >> (i & 7)) & 1;
|
||||
swap ^= kt;
|
||||
cswap(x2, x3, swap);
|
||||
cswap(z2, z3, swap);
|
||||
swap = kt;
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("x2", x2);
|
||||
print_int_mont("z2", z2);
|
||||
print_int_mont("x3", x3);
|
||||
print_int_mont("z3", z3);
|
||||
*/
|
||||
|
||||
c255_add(a, x2, z2);
|
||||
c255_mul(aa, a, a);
|
||||
c255_sub(b, x2, z2);
|
||||
c255_mul(bb, b, b);
|
||||
c255_sub(e, aa, bb);
|
||||
c255_add(c, x3, z3);
|
||||
c255_sub(d, x3, z3);
|
||||
c255_mul(da, d, a);
|
||||
c255_mul(cb, c, b);
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("a ", a);
|
||||
print_int_mont("aa", aa);
|
||||
print_int_mont("b ", b);
|
||||
print_int_mont("bb", bb);
|
||||
print_int_mont("e ", e);
|
||||
print_int_mont("c ", c);
|
||||
print_int_mont("d ", d);
|
||||
print_int_mont("da", da);
|
||||
print_int_mont("cb", cb);
|
||||
*/
|
||||
|
||||
c255_add(x3, da, cb);
|
||||
c255_mul(x3, x3, x3);
|
||||
c255_sub(z3, da, cb);
|
||||
c255_mul(z3, z3, z3);
|
||||
c255_mul(z3, z3, x1);
|
||||
c255_mul(x2, aa, bb);
|
||||
c255_mul(z2, C255_A24, e);
|
||||
c255_add(z2, z2, aa);
|
||||
c255_mul(z2, e, z2);
|
||||
|
||||
/* obsolete
|
||||
print_int_mont("x2", x2);
|
||||
print_int_mont("z2", z2);
|
||||
print_int_mont("x3", x3);
|
||||
print_int_mont("z3", z3);
|
||||
*/
|
||||
}
|
||||
cswap(x2, x3, swap);
|
||||
cswap(z2, z3, swap);
|
||||
|
||||
/*
|
||||
* Inverse z2 with a modular exponentiation. This is a simple
|
||||
* square-and-multiply algorithm; we mutualise most non-squarings
|
||||
* since the exponent contains almost only ones.
|
||||
*/
|
||||
memcpy(a, z2, sizeof z2);
|
||||
for (i = 0; i < 15; i ++) {
|
||||
c255_mul(a, a, a);
|
||||
c255_mul(a, a, z2);
|
||||
}
|
||||
memcpy(b, a, sizeof a);
|
||||
for (i = 0; i < 14; i ++) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < 16; j ++) {
|
||||
c255_mul(b, b, b);
|
||||
}
|
||||
c255_mul(b, b, a);
|
||||
}
|
||||
for (i = 14; i >= 0; i --) {
|
||||
c255_mul(b, b, b);
|
||||
if ((0xFFEB >> i) & 1) {
|
||||
c255_mul(b, z2, b);
|
||||
}
|
||||
}
|
||||
c255_mul(b, x2, b);
|
||||
|
||||
/*
|
||||
* To avoid a dependency on br_i31_from_monty(), we use
|
||||
* a Montgomery multiplication with 1.
|
||||
* memcpy(x2, b, sizeof b);
|
||||
* br_i31_from_monty(x2, C255_P, P0I);
|
||||
*/
|
||||
br_i31_zero(a, C255_P[0]);
|
||||
a[1] = 1;
|
||||
br_i31_montymul(x2, a, b, C255_P, P0I);
|
||||
|
||||
br_i31_encode(G, 32, x2);
|
||||
byteswap(G);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_mulgen(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
const unsigned char *G;
|
||||
size_t Glen;
|
||||
|
||||
G = api_generator(curve, &Glen);
|
||||
memcpy(R, G, Glen);
|
||||
api_mul(R, Glen, x, xlen, curve);
|
||||
return Glen;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
/*
|
||||
* We don't implement this method, since it is used for ECDSA
|
||||
* only, and there is no ECDSA over Curve25519 (which instead
|
||||
* uses EdDSA).
|
||||
*/
|
||||
(void)A;
|
||||
(void)B;
|
||||
(void)len;
|
||||
(void)x;
|
||||
(void)xlen;
|
||||
(void)y;
|
||||
(void)ylen;
|
||||
(void)curve;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_c25519_i31 = {
|
||||
(uint32_t)0x20000000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_xoff,
|
||||
&api_mul,
|
||||
&api_mulgen,
|
||||
&api_muladd
|
||||
};
|
||||
1478
dstalk-core/thirdparty/bearssl/src/ec/ec_c25519_m15.c
vendored
1478
dstalk-core/thirdparty/bearssl/src/ec/ec_c25519_m15.c
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,769 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* obsolete
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
static void
|
||||
print_int(const char *name, const uint32_t *x)
|
||||
{
|
||||
size_t u;
|
||||
unsigned char tmp[40];
|
||||
|
||||
printf("%s = ", name);
|
||||
for (u = 0; u < 9; u ++) {
|
||||
if (x[u] > 0x3FFFFFFF) {
|
||||
printf("INVALID:");
|
||||
for (u = 0; u < 9; u ++) {
|
||||
printf(" %08X", x[u]);
|
||||
}
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
memset(tmp, 0, sizeof tmp);
|
||||
for (u = 0; u < 9; u ++) {
|
||||
uint64_t w;
|
||||
int j, k;
|
||||
|
||||
w = x[u];
|
||||
j = 30 * (int)u;
|
||||
k = j & 7;
|
||||
if (k != 0) {
|
||||
w <<= k;
|
||||
j -= k;
|
||||
}
|
||||
k = j >> 3;
|
||||
for (j = 0; j < 8; j ++) {
|
||||
tmp[39 - k - j] |= (unsigned char)w;
|
||||
w >>= 8;
|
||||
}
|
||||
}
|
||||
for (u = 8; u < 40; u ++) {
|
||||
printf("%02X", tmp[u]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_
|
||||
* that right-shifting a signed negative integer copies the sign bit
|
||||
* (arithmetic right-shift). This is "implementation-defined behaviour",
|
||||
* i.e. it is not undefined, but it may differ between compilers. Each
|
||||
* compiler is supposed to document its behaviour in that respect. GCC
|
||||
* explicitly defines that an arithmetic right shift is used. We expect
|
||||
* all other compilers to do the same, because underlying CPU offer an
|
||||
* arithmetic right shift opcode that could not be used otherwise.
|
||||
*/
|
||||
#if BR_NO_ARITH_SHIFT
|
||||
#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
|
||||
| ((-((uint32_t)(x) >> 31)) << (32 - (n))))
|
||||
#else
|
||||
#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convert an integer from unsigned little-endian encoding to a sequence of
|
||||
* 30-bit words in little-endian order. The final "partial" word is
|
||||
* returned.
|
||||
*/
|
||||
static uint32_t
|
||||
le8_to_le30(uint32_t *dst, const unsigned char *src, size_t len)
|
||||
{
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
while (len -- > 0) {
|
||||
uint32_t b;
|
||||
|
||||
b = *src ++;
|
||||
if (acc_len < 22) {
|
||||
acc |= b << acc_len;
|
||||
acc_len += 8;
|
||||
} else {
|
||||
*dst ++ = (acc | (b << acc_len)) & 0x3FFFFFFF;
|
||||
acc = b >> (30 - acc_len);
|
||||
acc_len -= 22;
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an integer (30-bit words, little-endian) to unsigned
|
||||
* little-endian encoding. The total encoding length is provided; all
|
||||
* the destination bytes will be filled.
|
||||
*/
|
||||
static void
|
||||
le30_to_le8(unsigned char *dst, size_t len, const uint32_t *src)
|
||||
{
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
while (len -- > 0) {
|
||||
if (acc_len < 8) {
|
||||
uint32_t w;
|
||||
|
||||
w = *src ++;
|
||||
*dst ++ = (unsigned char)(acc | (w << acc_len));
|
||||
acc = w >> (8 - acc_len);
|
||||
acc_len += 22;
|
||||
} else {
|
||||
*dst ++ = (unsigned char)acc;
|
||||
acc >>= 8;
|
||||
acc_len -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply two integers. Source integers are represented as arrays of
|
||||
* nine 30-bit words, for values up to 2^270-1. Result is encoded over
|
||||
* 18 words of 30 bits each.
|
||||
*/
|
||||
static void
|
||||
mul9(uint32_t *d, const uint32_t *a, const uint32_t *b)
|
||||
{
|
||||
/*
|
||||
* Maximum intermediate result is no more than
|
||||
* 10376293531797946367, which fits in 64 bits. Reason:
|
||||
*
|
||||
* 10376293531797946367 = 9 * (2^30-1)^2 + 9663676406
|
||||
* 10376293531797946367 < 9663676407 * 2^30
|
||||
*
|
||||
* Thus, adding together 9 products of 30-bit integers, with
|
||||
* a carry of at most 9663676406, yields an integer that fits
|
||||
* on 64 bits and generates a carry of at most 9663676406.
|
||||
*/
|
||||
uint64_t t[17];
|
||||
uint64_t cc;
|
||||
int i;
|
||||
|
||||
t[ 0] = MUL31(a[0], b[0]);
|
||||
t[ 1] = MUL31(a[0], b[1])
|
||||
+ MUL31(a[1], b[0]);
|
||||
t[ 2] = MUL31(a[0], b[2])
|
||||
+ MUL31(a[1], b[1])
|
||||
+ MUL31(a[2], b[0]);
|
||||
t[ 3] = MUL31(a[0], b[3])
|
||||
+ MUL31(a[1], b[2])
|
||||
+ MUL31(a[2], b[1])
|
||||
+ MUL31(a[3], b[0]);
|
||||
t[ 4] = MUL31(a[0], b[4])
|
||||
+ MUL31(a[1], b[3])
|
||||
+ MUL31(a[2], b[2])
|
||||
+ MUL31(a[3], b[1])
|
||||
+ MUL31(a[4], b[0]);
|
||||
t[ 5] = MUL31(a[0], b[5])
|
||||
+ MUL31(a[1], b[4])
|
||||
+ MUL31(a[2], b[3])
|
||||
+ MUL31(a[3], b[2])
|
||||
+ MUL31(a[4], b[1])
|
||||
+ MUL31(a[5], b[0]);
|
||||
t[ 6] = MUL31(a[0], b[6])
|
||||
+ MUL31(a[1], b[5])
|
||||
+ MUL31(a[2], b[4])
|
||||
+ MUL31(a[3], b[3])
|
||||
+ MUL31(a[4], b[2])
|
||||
+ MUL31(a[5], b[1])
|
||||
+ MUL31(a[6], b[0]);
|
||||
t[ 7] = MUL31(a[0], b[7])
|
||||
+ MUL31(a[1], b[6])
|
||||
+ MUL31(a[2], b[5])
|
||||
+ MUL31(a[3], b[4])
|
||||
+ MUL31(a[4], b[3])
|
||||
+ MUL31(a[5], b[2])
|
||||
+ MUL31(a[6], b[1])
|
||||
+ MUL31(a[7], b[0]);
|
||||
t[ 8] = MUL31(a[0], b[8])
|
||||
+ MUL31(a[1], b[7])
|
||||
+ MUL31(a[2], b[6])
|
||||
+ MUL31(a[3], b[5])
|
||||
+ MUL31(a[4], b[4])
|
||||
+ MUL31(a[5], b[3])
|
||||
+ MUL31(a[6], b[2])
|
||||
+ MUL31(a[7], b[1])
|
||||
+ MUL31(a[8], b[0]);
|
||||
t[ 9] = MUL31(a[1], b[8])
|
||||
+ MUL31(a[2], b[7])
|
||||
+ MUL31(a[3], b[6])
|
||||
+ MUL31(a[4], b[5])
|
||||
+ MUL31(a[5], b[4])
|
||||
+ MUL31(a[6], b[3])
|
||||
+ MUL31(a[7], b[2])
|
||||
+ MUL31(a[8], b[1]);
|
||||
t[10] = MUL31(a[2], b[8])
|
||||
+ MUL31(a[3], b[7])
|
||||
+ MUL31(a[4], b[6])
|
||||
+ MUL31(a[5], b[5])
|
||||
+ MUL31(a[6], b[4])
|
||||
+ MUL31(a[7], b[3])
|
||||
+ MUL31(a[8], b[2]);
|
||||
t[11] = MUL31(a[3], b[8])
|
||||
+ MUL31(a[4], b[7])
|
||||
+ MUL31(a[5], b[6])
|
||||
+ MUL31(a[6], b[5])
|
||||
+ MUL31(a[7], b[4])
|
||||
+ MUL31(a[8], b[3]);
|
||||
t[12] = MUL31(a[4], b[8])
|
||||
+ MUL31(a[5], b[7])
|
||||
+ MUL31(a[6], b[6])
|
||||
+ MUL31(a[7], b[5])
|
||||
+ MUL31(a[8], b[4]);
|
||||
t[13] = MUL31(a[5], b[8])
|
||||
+ MUL31(a[6], b[7])
|
||||
+ MUL31(a[7], b[6])
|
||||
+ MUL31(a[8], b[5]);
|
||||
t[14] = MUL31(a[6], b[8])
|
||||
+ MUL31(a[7], b[7])
|
||||
+ MUL31(a[8], b[6]);
|
||||
t[15] = MUL31(a[7], b[8])
|
||||
+ MUL31(a[8], b[7]);
|
||||
t[16] = MUL31(a[8], b[8]);
|
||||
|
||||
/*
|
||||
* Propagate carries.
|
||||
*/
|
||||
cc = 0;
|
||||
for (i = 0; i < 17; i ++) {
|
||||
uint64_t w;
|
||||
|
||||
w = t[i] + cc;
|
||||
d[i] = (uint32_t)w & 0x3FFFFFFF;
|
||||
cc = w >> 30;
|
||||
}
|
||||
d[17] = (uint32_t)cc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Square a 270-bit integer, represented as an array of nine 30-bit words.
|
||||
* Result uses 18 words of 30 bits each.
|
||||
*/
|
||||
static void
|
||||
square9(uint32_t *d, const uint32_t *a)
|
||||
{
|
||||
uint64_t t[17];
|
||||
uint64_t cc;
|
||||
int i;
|
||||
|
||||
t[ 0] = MUL31(a[0], a[0]);
|
||||
t[ 1] = ((MUL31(a[0], a[1])) << 1);
|
||||
t[ 2] = MUL31(a[1], a[1])
|
||||
+ ((MUL31(a[0], a[2])) << 1);
|
||||
t[ 3] = ((MUL31(a[0], a[3])
|
||||
+ MUL31(a[1], a[2])) << 1);
|
||||
t[ 4] = MUL31(a[2], a[2])
|
||||
+ ((MUL31(a[0], a[4])
|
||||
+ MUL31(a[1], a[3])) << 1);
|
||||
t[ 5] = ((MUL31(a[0], a[5])
|
||||
+ MUL31(a[1], a[4])
|
||||
+ MUL31(a[2], a[3])) << 1);
|
||||
t[ 6] = MUL31(a[3], a[3])
|
||||
+ ((MUL31(a[0], a[6])
|
||||
+ MUL31(a[1], a[5])
|
||||
+ MUL31(a[2], a[4])) << 1);
|
||||
t[ 7] = ((MUL31(a[0], a[7])
|
||||
+ MUL31(a[1], a[6])
|
||||
+ MUL31(a[2], a[5])
|
||||
+ MUL31(a[3], a[4])) << 1);
|
||||
t[ 8] = MUL31(a[4], a[4])
|
||||
+ ((MUL31(a[0], a[8])
|
||||
+ MUL31(a[1], a[7])
|
||||
+ MUL31(a[2], a[6])
|
||||
+ MUL31(a[3], a[5])) << 1);
|
||||
t[ 9] = ((MUL31(a[1], a[8])
|
||||
+ MUL31(a[2], a[7])
|
||||
+ MUL31(a[3], a[6])
|
||||
+ MUL31(a[4], a[5])) << 1);
|
||||
t[10] = MUL31(a[5], a[5])
|
||||
+ ((MUL31(a[2], a[8])
|
||||
+ MUL31(a[3], a[7])
|
||||
+ MUL31(a[4], a[6])) << 1);
|
||||
t[11] = ((MUL31(a[3], a[8])
|
||||
+ MUL31(a[4], a[7])
|
||||
+ MUL31(a[5], a[6])) << 1);
|
||||
t[12] = MUL31(a[6], a[6])
|
||||
+ ((MUL31(a[4], a[8])
|
||||
+ MUL31(a[5], a[7])) << 1);
|
||||
t[13] = ((MUL31(a[5], a[8])
|
||||
+ MUL31(a[6], a[7])) << 1);
|
||||
t[14] = MUL31(a[7], a[7])
|
||||
+ ((MUL31(a[6], a[8])) << 1);
|
||||
t[15] = ((MUL31(a[7], a[8])) << 1);
|
||||
t[16] = MUL31(a[8], a[8]);
|
||||
|
||||
/*
|
||||
* Propagate carries.
|
||||
*/
|
||||
cc = 0;
|
||||
for (i = 0; i < 17; i ++) {
|
||||
uint64_t w;
|
||||
|
||||
w = t[i] + cc;
|
||||
d[i] = (uint32_t)w & 0x3FFFFFFF;
|
||||
cc = w >> 30;
|
||||
}
|
||||
d[17] = (uint32_t)cc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a "final reduction" in field F255 (field for Curve25519)
|
||||
* The source value must be less than twice the modulus. If the value
|
||||
* is not lower than the modulus, then the modulus is subtracted and
|
||||
* this function returns 1; otherwise, it leaves it untouched and it
|
||||
* returns 0.
|
||||
*/
|
||||
static uint32_t
|
||||
reduce_final_f255(uint32_t *d)
|
||||
{
|
||||
uint32_t t[9];
|
||||
uint32_t cc;
|
||||
int i;
|
||||
|
||||
memcpy(t, d, sizeof t);
|
||||
cc = 19;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
uint32_t w;
|
||||
|
||||
w = t[i] + cc;
|
||||
cc = w >> 30;
|
||||
t[i] = w & 0x3FFFFFFF;
|
||||
}
|
||||
cc = t[8] >> 15;
|
||||
t[8] &= 0x7FFF;
|
||||
CCOPY(cc, d, t, sizeof t);
|
||||
return cc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a multiplication of two integers modulo 2^255-19.
|
||||
* Operands are arrays of 9 words, each containing 30 bits of data, in
|
||||
* little-endian order. Input value may be up to 2^256-1; on output, value
|
||||
* fits on 256 bits and is lower than twice the modulus.
|
||||
*/
|
||||
static void
|
||||
f255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b)
|
||||
{
|
||||
uint32_t t[18];
|
||||
uint64_t cc, w;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Compute raw multiplication. All result words fit in 30 bits
|
||||
* each; upper word (t[17]) must fit on 2 bits, since the product
|
||||
* of two 256-bit integers must fit on 512 bits.
|
||||
*/
|
||||
mul9(t, a, b);
|
||||
|
||||
/*
|
||||
* Modular reduction: each high word is added where necessary.
|
||||
* Since the modulus is 2^255-19 and word 9 corresponds to
|
||||
* offset 9*30 = 270, word 9+k must be added to word k with
|
||||
* a factor of 19*2^15 = 622592. The extra bits in word 8 are also
|
||||
* added that way.
|
||||
*/
|
||||
cc = MUL31(t[8] >> 15, 19);
|
||||
t[8] &= 0x7FFF;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
w = (uint64_t)t[i] + cc + MUL31(t[i + 9], 622592);
|
||||
t[i] = (uint32_t)w & 0x3FFFFFFF;
|
||||
cc = w >> 30;
|
||||
}
|
||||
cc = MUL31(w >> 15, 19);
|
||||
t[8] &= 0x7FFF;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
w = t[i] + cc;
|
||||
d[i] = (uint32_t)w & 0x3FFFFFFF;
|
||||
cc = w >> 30;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a squaring of an integer modulo 2^255-19.
|
||||
* Operands are arrays of 9 words, each containing 30 bits of data, in
|
||||
* little-endian order. Input value may be up to 2^256-1; on output, value
|
||||
* fits on 256 bits and is lower than twice the modulus.
|
||||
*/
|
||||
static void
|
||||
f255_square(uint32_t *d, const uint32_t *a)
|
||||
{
|
||||
uint32_t t[18];
|
||||
uint64_t cc, w;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Compute raw squaring. All result words fit in 30 bits
|
||||
* each; upper word (t[17]) must fit on 2 bits, since the square
|
||||
* of a 256-bit integers must fit on 512 bits.
|
||||
*/
|
||||
square9(t, a);
|
||||
|
||||
/*
|
||||
* Modular reduction: each high word is added where necessary.
|
||||
* Since the modulus is 2^255-19 and word 9 corresponds to
|
||||
* offset 9*30 = 270, word 9+k must be added to word k with
|
||||
* a factor of 19*2^15 = 622592. The extra bits in word 8 are also
|
||||
* added that way.
|
||||
*/
|
||||
cc = MUL31(t[8] >> 15, 19);
|
||||
t[8] &= 0x7FFF;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
w = (uint64_t)t[i] + cc + MUL31(t[i + 9], 622592);
|
||||
t[i] = (uint32_t)w & 0x3FFFFFFF;
|
||||
cc = w >> 30;
|
||||
}
|
||||
cc = MUL31(w >> 15, 19);
|
||||
t[8] &= 0x7FFF;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
w = t[i] + cc;
|
||||
d[i] = (uint32_t)w & 0x3FFFFFFF;
|
||||
cc = w >> 30;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add two values in F255. Partial reduction is performed (down to less
|
||||
* than twice the modulus).
|
||||
*/
|
||||
static void
|
||||
f255_add(uint32_t *d, const uint32_t *a, const uint32_t *b)
|
||||
{
|
||||
/*
|
||||
* Since operand words fit on 30 bits, we can use 32-bit
|
||||
* variables throughout.
|
||||
*/
|
||||
int i;
|
||||
uint32_t cc, w;
|
||||
|
||||
cc = 0;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
w = a[i] + b[i] + cc;
|
||||
d[i] = w & 0x3FFFFFFF;
|
||||
cc = w >> 30;
|
||||
}
|
||||
cc = MUL15(w >> 15, 19);
|
||||
d[8] &= 0x7FFF;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
w = d[i] + cc;
|
||||
d[i] = w & 0x3FFFFFFF;
|
||||
cc = w >> 30;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Subtract one value from another in F255. Partial reduction is
|
||||
* performed (down to less than twice the modulus).
|
||||
*/
|
||||
static void
|
||||
f255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b)
|
||||
{
|
||||
/*
|
||||
* We actually compute a - b + 2*p, so that the final value is
|
||||
* necessarily positive.
|
||||
*/
|
||||
int i;
|
||||
uint32_t cc, w;
|
||||
|
||||
cc = (uint32_t)-38;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
w = a[i] - b[i] + cc;
|
||||
d[i] = w & 0x3FFFFFFF;
|
||||
cc = ARSH(w, 30);
|
||||
}
|
||||
cc = MUL15((w + 0x10000) >> 15, 19);
|
||||
d[8] &= 0x7FFF;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
w = d[i] + cc;
|
||||
d[i] = w & 0x3FFFFFFF;
|
||||
cc = w >> 30;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiply an integer by the 'A24' constant (121665). Partial reduction
|
||||
* is performed (down to less than twice the modulus).
|
||||
*/
|
||||
static void
|
||||
f255_mul_a24(uint32_t *d, const uint32_t *a)
|
||||
{
|
||||
int i;
|
||||
uint64_t cc, w;
|
||||
|
||||
cc = 0;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
w = MUL31(a[i], 121665) + cc;
|
||||
d[i] = (uint32_t)w & 0x3FFFFFFF;
|
||||
cc = w >> 30;
|
||||
}
|
||||
cc = MUL31((uint32_t)(w >> 15), 19);
|
||||
d[8] &= 0x7FFF;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
w = (uint64_t)d[i] + cc;
|
||||
d[i] = w & 0x3FFFFFFF;
|
||||
cc = w >> 30;
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char GEN[] = {
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const unsigned char ORDER[] = {
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return GEN;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return ORDER;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_xoff(int curve, size_t *len)
|
||||
{
|
||||
(void)curve;
|
||||
*len = 32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cswap(uint32_t *a, uint32_t *b, uint32_t ctl)
|
||||
{
|
||||
int i;
|
||||
|
||||
ctl = -ctl;
|
||||
for (i = 0; i < 9; i ++) {
|
||||
uint32_t aw, bw, tw;
|
||||
|
||||
aw = a[i];
|
||||
bw = b[i];
|
||||
tw = ctl & (aw ^ bw);
|
||||
a[i] = aw ^ tw;
|
||||
b[i] = bw ^ tw;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *kb, size_t kblen, int curve)
|
||||
{
|
||||
uint32_t x1[9], x2[9], x3[9], z2[9], z3[9];
|
||||
uint32_t a[9], aa[9], b[9], bb[9];
|
||||
uint32_t c[9], d[9], e[9], da[9], cb[9];
|
||||
unsigned char k[32];
|
||||
uint32_t swap;
|
||||
int i;
|
||||
|
||||
(void)curve;
|
||||
|
||||
/*
|
||||
* Points are encoded over exactly 32 bytes. Multipliers must fit
|
||||
* in 32 bytes as well.
|
||||
* RFC 7748 mandates that the high bit of the last point byte must
|
||||
* be ignored/cleared.
|
||||
*/
|
||||
if (Glen != 32 || kblen > 32) {
|
||||
return 0;
|
||||
}
|
||||
G[31] &= 0x7F;
|
||||
|
||||
/*
|
||||
* Initialise variables x1, x2, z2, x3 and z3. We set all of them
|
||||
* into Montgomery representation.
|
||||
*/
|
||||
x1[8] = le8_to_le30(x1, G, 32);
|
||||
memcpy(x3, x1, sizeof x1);
|
||||
memset(z2, 0, sizeof z2);
|
||||
memset(x2, 0, sizeof x2);
|
||||
x2[0] = 1;
|
||||
memset(z3, 0, sizeof z3);
|
||||
z3[0] = 1;
|
||||
|
||||
memcpy(k, kb, kblen);
|
||||
memset(k + kblen, 0, (sizeof k) - kblen);
|
||||
k[0] &= 0xF8;
|
||||
k[31] &= 0x7F;
|
||||
k[31] |= 0x40;
|
||||
|
||||
/* obsolete
|
||||
print_int("x1", x1);
|
||||
*/
|
||||
|
||||
swap = 0;
|
||||
for (i = 254; i >= 0; i --) {
|
||||
uint32_t kt;
|
||||
|
||||
kt = (k[i >> 3] >> (i & 7)) & 1;
|
||||
swap ^= kt;
|
||||
cswap(x2, x3, swap);
|
||||
cswap(z2, z3, swap);
|
||||
swap = kt;
|
||||
|
||||
/* obsolete
|
||||
print_int("x2", x2);
|
||||
print_int("z2", z2);
|
||||
print_int("x3", x3);
|
||||
print_int("z3", z3);
|
||||
*/
|
||||
|
||||
f255_add(a, x2, z2);
|
||||
f255_square(aa, a);
|
||||
f255_sub(b, x2, z2);
|
||||
f255_square(bb, b);
|
||||
f255_sub(e, aa, bb);
|
||||
f255_add(c, x3, z3);
|
||||
f255_sub(d, x3, z3);
|
||||
f255_mul(da, d, a);
|
||||
f255_mul(cb, c, b);
|
||||
|
||||
/* obsolete
|
||||
print_int("a ", a);
|
||||
print_int("aa", aa);
|
||||
print_int("b ", b);
|
||||
print_int("bb", bb);
|
||||
print_int("e ", e);
|
||||
print_int("c ", c);
|
||||
print_int("d ", d);
|
||||
print_int("da", da);
|
||||
print_int("cb", cb);
|
||||
*/
|
||||
|
||||
f255_add(x3, da, cb);
|
||||
f255_square(x3, x3);
|
||||
f255_sub(z3, da, cb);
|
||||
f255_square(z3, z3);
|
||||
f255_mul(z3, z3, x1);
|
||||
f255_mul(x2, aa, bb);
|
||||
f255_mul_a24(z2, e);
|
||||
f255_add(z2, z2, aa);
|
||||
f255_mul(z2, e, z2);
|
||||
|
||||
/* obsolete
|
||||
print_int("x2", x2);
|
||||
print_int("z2", z2);
|
||||
print_int("x3", x3);
|
||||
print_int("z3", z3);
|
||||
*/
|
||||
}
|
||||
cswap(x2, x3, swap);
|
||||
cswap(z2, z3, swap);
|
||||
|
||||
/*
|
||||
* Inverse z2 with a modular exponentiation. This is a simple
|
||||
* square-and-multiply algorithm; we mutualise most non-squarings
|
||||
* since the exponent contains almost only ones.
|
||||
*/
|
||||
memcpy(a, z2, sizeof z2);
|
||||
for (i = 0; i < 15; i ++) {
|
||||
f255_square(a, a);
|
||||
f255_mul(a, a, z2);
|
||||
}
|
||||
memcpy(b, a, sizeof a);
|
||||
for (i = 0; i < 14; i ++) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < 16; j ++) {
|
||||
f255_square(b, b);
|
||||
}
|
||||
f255_mul(b, b, a);
|
||||
}
|
||||
for (i = 14; i >= 0; i --) {
|
||||
f255_square(b, b);
|
||||
if ((0xFFEB >> i) & 1) {
|
||||
f255_mul(b, z2, b);
|
||||
}
|
||||
}
|
||||
f255_mul(x2, x2, b);
|
||||
reduce_final_f255(x2);
|
||||
le30_to_le8(G, 32, x2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_mulgen(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
const unsigned char *G;
|
||||
size_t Glen;
|
||||
|
||||
G = api_generator(curve, &Glen);
|
||||
memcpy(R, G, Glen);
|
||||
api_mul(R, Glen, x, xlen, curve);
|
||||
return Glen;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
/*
|
||||
* We don't implement this method, since it is used for ECDSA
|
||||
* only, and there is no ECDSA over Curve25519 (which instead
|
||||
* uses EdDSA).
|
||||
*/
|
||||
(void)A;
|
||||
(void)B;
|
||||
(void)len;
|
||||
(void)x;
|
||||
(void)xlen;
|
||||
(void)y;
|
||||
(void)ylen;
|
||||
(void)curve;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_c25519_m31 = {
|
||||
(uint32_t)0x20000000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_xoff,
|
||||
&api_mul,
|
||||
&api_mulgen,
|
||||
&api_muladd
|
||||
};
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char GEN[] = {
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const unsigned char ORDER[] = {
|
||||
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_curve_def br_curve25519 = {
|
||||
BR_EC_curve25519,
|
||||
ORDER, sizeof ORDER,
|
||||
GEN, sizeof GEN
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl *
|
||||
br_ec_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_ec_all_m15;
|
||||
#else
|
||||
return &br_ec_all_m31;
|
||||
#endif
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ec_keygen(const br_prng_class **rng_ctx,
|
||||
const br_ec_impl *impl, br_ec_private_key *sk,
|
||||
void *kbuf, int curve)
|
||||
{
|
||||
const unsigned char *order;
|
||||
unsigned char *buf;
|
||||
size_t len;
|
||||
unsigned mask;
|
||||
|
||||
if (curve < 0 || curve >= 32
|
||||
|| ((impl->supported_curves >> curve) & 1) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
order = impl->order(curve, &len);
|
||||
while (len > 0 && *order == 0) {
|
||||
order ++;
|
||||
len --;
|
||||
}
|
||||
if (kbuf == NULL || len == 0) {
|
||||
return len;
|
||||
}
|
||||
mask = order[0];
|
||||
mask |= (mask >> 1);
|
||||
mask |= (mask >> 2);
|
||||
mask |= (mask >> 4);
|
||||
|
||||
/*
|
||||
* We generate sequences of random bits of the right size, until
|
||||
* the value is strictly lower than the curve order (we also
|
||||
* check for all-zero values, which are invalid).
|
||||
*/
|
||||
buf = kbuf;
|
||||
for (;;) {
|
||||
size_t u;
|
||||
unsigned cc, zz;
|
||||
|
||||
(*rng_ctx)->generate(rng_ctx, buf, len);
|
||||
buf[0] &= mask;
|
||||
cc = 0;
|
||||
u = len;
|
||||
zz = 0;
|
||||
while (u -- > 0) {
|
||||
cc = ((unsigned)(buf[u] - order[u] - cc) >> 8) & 1;
|
||||
zz |= buf[u];
|
||||
}
|
||||
if (cc != 0 && zz != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sk != NULL) {
|
||||
sk->curve = curve;
|
||||
sk->x = buf;
|
||||
sk->xlen = len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
2130
dstalk-core/thirdparty/bearssl/src/ec/ec_p256_m15.c
vendored
2130
dstalk-core/thirdparty/bearssl/src/ec/ec_p256_m15.c
vendored
File diff suppressed because it is too large
Load Diff
1475
dstalk-core/thirdparty/bearssl/src/ec/ec_p256_m31.c
vendored
1475
dstalk-core/thirdparty/bearssl/src/ec/ec_p256_m31.c
vendored
File diff suppressed because it is too large
Load Diff
820
dstalk-core/thirdparty/bearssl/src/ec/ec_prime_i15.c
vendored
820
dstalk-core/thirdparty/bearssl/src/ec/ec_prime_i15.c
vendored
@@ -1,820 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Parameters for supported curves:
|
||||
* - field modulus p
|
||||
* - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p)
|
||||
* - b*R mod p (b is the second curve equation parameter)
|
||||
*/
|
||||
|
||||
static const uint16_t P256_P[] = {
|
||||
0x0111,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x003F, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x4000, 0x7FFF,
|
||||
0x7FFF, 0x0001
|
||||
};
|
||||
|
||||
static const uint16_t P256_R2[] = {
|
||||
0x0111,
|
||||
0x0000, 0x6000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFC, 0x7FFF,
|
||||
0x7FBF, 0x7FFF, 0x7FBF, 0x7FFF, 0x7FFF, 0x7FFF, 0x77FF, 0x7FFF,
|
||||
0x4FFF, 0x0000
|
||||
};
|
||||
|
||||
static const uint16_t P256_B[] = {
|
||||
0x0111,
|
||||
0x770C, 0x5EEF, 0x29C4, 0x3EC4, 0x6273, 0x0486, 0x4543, 0x3993,
|
||||
0x3C01, 0x6B56, 0x212E, 0x57EE, 0x4882, 0x204B, 0x7483, 0x3C16,
|
||||
0x0187, 0x0000
|
||||
};
|
||||
|
||||
static const uint16_t P384_P[] = {
|
||||
0x0199,
|
||||
0x7FFF, 0x7FFF, 0x0003, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FFF,
|
||||
0x7EFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x01FF
|
||||
};
|
||||
|
||||
static const uint16_t P384_R2[] = {
|
||||
0x0199,
|
||||
0x1000, 0x0000, 0x0000, 0x7FFF, 0x7FFF, 0x0001, 0x0000, 0x0010,
|
||||
0x0000, 0x0000, 0x0000, 0x7F00, 0x7FFF, 0x01FF, 0x0000, 0x1000,
|
||||
0x0000, 0x2000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000
|
||||
};
|
||||
|
||||
static const uint16_t P384_B[] = {
|
||||
0x0199,
|
||||
0x7333, 0x2096, 0x70D1, 0x2310, 0x3020, 0x6197, 0x1464, 0x35BB,
|
||||
0x70CA, 0x0117, 0x1920, 0x4136, 0x5FC8, 0x5713, 0x4938, 0x7DD2,
|
||||
0x4DD2, 0x4A71, 0x0220, 0x683E, 0x2C87, 0x4DB1, 0x7BFF, 0x6C09,
|
||||
0x0452, 0x0084
|
||||
};
|
||||
|
||||
static const uint16_t P521_P[] = {
|
||||
0x022B,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||
0x7FFF, 0x7FFF, 0x07FF
|
||||
};
|
||||
|
||||
static const uint16_t P521_R2[] = {
|
||||
0x022B,
|
||||
0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||
0x0000, 0x0000, 0x0000
|
||||
};
|
||||
|
||||
static const uint16_t P521_B[] = {
|
||||
0x022B,
|
||||
0x7002, 0x6A07, 0x751A, 0x228F, 0x71EF, 0x5869, 0x20F4, 0x1EFC,
|
||||
0x7357, 0x37E0, 0x4EEC, 0x605E, 0x1652, 0x26F6, 0x31FA, 0x4A8F,
|
||||
0x6193, 0x3C2A, 0x3C42, 0x48C7, 0x3489, 0x6771, 0x4C57, 0x5CCD,
|
||||
0x2725, 0x545B, 0x503B, 0x5B42, 0x21A0, 0x2534, 0x687E, 0x70E4,
|
||||
0x1618, 0x27D7, 0x0465
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const uint16_t *p;
|
||||
const uint16_t *b;
|
||||
const uint16_t *R2;
|
||||
uint16_t p0i;
|
||||
size_t point_len;
|
||||
} curve_params;
|
||||
|
||||
static inline const curve_params *
|
||||
id_to_curve(int curve)
|
||||
{
|
||||
static const curve_params pp[] = {
|
||||
{ P256_P, P256_B, P256_R2, 0x0001, 65 },
|
||||
{ P384_P, P384_B, P384_R2, 0x0001, 97 },
|
||||
{ P521_P, P521_B, P521_R2, 0x0001, 133 }
|
||||
};
|
||||
|
||||
return &pp[curve - BR_EC_secp256r1];
|
||||
}
|
||||
|
||||
#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
|
||||
|
||||
/*
|
||||
* Type for a point in Jacobian coordinates:
|
||||
* -- three values, x, y and z, in Montgomery representation
|
||||
* -- affine coordinates are X = x / z^2 and Y = y / z^3
|
||||
* -- for the point at infinity, z = 0
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t c[3][I15_LEN];
|
||||
} jacobian;
|
||||
|
||||
/*
|
||||
* We use a custom interpreter that uses a dozen registers, and
|
||||
* only six operations:
|
||||
* MSET(d, a) copy a into d
|
||||
* MADD(d, a) d = d+a (modular)
|
||||
* MSUB(d, a) d = d-a (modular)
|
||||
* MMUL(d, a, b) d = a*b (Montgomery multiplication)
|
||||
* MINV(d, a, b) invert d modulo p; a and b are used as scratch registers
|
||||
* MTZ(d) clear return value if d = 0
|
||||
* Destination of MMUL (d) must be distinct from operands (a and b).
|
||||
* There is no such constraint for MSUB and MADD.
|
||||
*
|
||||
* Registers include the operand coordinates, and temporaries.
|
||||
*/
|
||||
#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4))
|
||||
#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4))
|
||||
#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4))
|
||||
#define MMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b))
|
||||
#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b))
|
||||
#define MTZ(d) (0x5000 + ((d) << 8))
|
||||
#define ENDCODE 0
|
||||
|
||||
/*
|
||||
* Registers for the input operands.
|
||||
*/
|
||||
#define P1x 0
|
||||
#define P1y 1
|
||||
#define P1z 2
|
||||
#define P2x 3
|
||||
#define P2y 4
|
||||
#define P2z 5
|
||||
|
||||
/*
|
||||
* Alternate names for the first input operand.
|
||||
*/
|
||||
#define Px 0
|
||||
#define Py 1
|
||||
#define Pz 2
|
||||
|
||||
/*
|
||||
* Temporaries.
|
||||
*/
|
||||
#define t1 6
|
||||
#define t2 7
|
||||
#define t3 8
|
||||
#define t4 9
|
||||
#define t5 10
|
||||
#define t6 11
|
||||
#define t7 12
|
||||
|
||||
/*
|
||||
* Extra scratch registers available when there is no second operand (e.g.
|
||||
* for "double" and "affine").
|
||||
*/
|
||||
#define t8 3
|
||||
#define t9 4
|
||||
#define t10 5
|
||||
|
||||
/*
|
||||
* Doubling formulas are:
|
||||
*
|
||||
* s = 4*x*y^2
|
||||
* m = 3*(x + z^2)*(x - z^2)
|
||||
* x' = m^2 - 2*s
|
||||
* y' = m*(s - x') - 8*y^4
|
||||
* z' = 2*y*z
|
||||
*
|
||||
* If y = 0 (P has order 2) then this yields infinity (z' = 0), as it
|
||||
* should. This case should not happen anyway, because our curves have
|
||||
* prime order, and thus do not contain any point of order 2.
|
||||
*
|
||||
* If P is infinity (z = 0), then again the formulas yield infinity,
|
||||
* which is correct. Thus, this code works for all points.
|
||||
*
|
||||
* Cost: 8 multiplications
|
||||
*/
|
||||
static const uint16_t code_double[] = {
|
||||
/*
|
||||
* Compute z^2 (in t1).
|
||||
*/
|
||||
MMUL(t1, Pz, Pz),
|
||||
|
||||
/*
|
||||
* Compute x-z^2 (in t2) and then x+z^2 (in t1).
|
||||
*/
|
||||
MSET(t2, Px),
|
||||
MSUB(t2, t1),
|
||||
MADD(t1, Px),
|
||||
|
||||
/*
|
||||
* Compute m = 3*(x+z^2)*(x-z^2) (in t1).
|
||||
*/
|
||||
MMUL(t3, t1, t2),
|
||||
MSET(t1, t3),
|
||||
MADD(t1, t3),
|
||||
MADD(t1, t3),
|
||||
|
||||
/*
|
||||
* Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3).
|
||||
*/
|
||||
MMUL(t3, Py, Py),
|
||||
MADD(t3, t3),
|
||||
MMUL(t2, Px, t3),
|
||||
MADD(t2, t2),
|
||||
|
||||
/*
|
||||
* Compute x' = m^2 - 2*s.
|
||||
*/
|
||||
MMUL(Px, t1, t1),
|
||||
MSUB(Px, t2),
|
||||
MSUB(Px, t2),
|
||||
|
||||
/*
|
||||
* Compute z' = 2*y*z.
|
||||
*/
|
||||
MMUL(t4, Py, Pz),
|
||||
MSET(Pz, t4),
|
||||
MADD(Pz, t4),
|
||||
|
||||
/*
|
||||
* Compute y' = m*(s - x') - 8*y^4. Note that we already have
|
||||
* 2*y^2 in t3.
|
||||
*/
|
||||
MSUB(t2, Px),
|
||||
MMUL(Py, t1, t2),
|
||||
MMUL(t4, t3, t3),
|
||||
MSUB(Py, t4),
|
||||
MSUB(Py, t4),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Addtions formulas are:
|
||||
*
|
||||
* u1 = x1 * z2^2
|
||||
* u2 = x2 * z1^2
|
||||
* s1 = y1 * z2^3
|
||||
* s2 = y2 * z1^3
|
||||
* h = u2 - u1
|
||||
* r = s2 - s1
|
||||
* x3 = r^2 - h^3 - 2 * u1 * h^2
|
||||
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
|
||||
* z3 = h * z1 * z2
|
||||
*
|
||||
* If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that
|
||||
* z3 == 0, so the result is correct.
|
||||
* If either of P1 or P2 is infinity, but not both, then z3 == 0, which is
|
||||
* not correct.
|
||||
* h == 0 only if u1 == u2; this happens in two cases:
|
||||
* -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2
|
||||
* -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity)
|
||||
*
|
||||
* Thus, the following situations are not handled correctly:
|
||||
* -- P1 = 0 and P2 != 0
|
||||
* -- P1 != 0 and P2 = 0
|
||||
* -- P1 = P2
|
||||
* All other cases are properly computed. However, even in "incorrect"
|
||||
* situations, the three coordinates still are properly formed field
|
||||
* elements.
|
||||
*
|
||||
* The returned flag is cleared if r == 0. This happens in the following
|
||||
* cases:
|
||||
* -- Both points are on the same horizontal line (same Y coordinate).
|
||||
* -- Both points are infinity.
|
||||
* -- One point is infinity and the other is on line Y = 0.
|
||||
* The third case cannot happen with our curves (there is no valid point
|
||||
* on line Y = 0 since that would be a point of order 2). If the two
|
||||
* source points are non-infinity, then remains only the case where the
|
||||
* two points are on the same horizontal line.
|
||||
*
|
||||
* This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and
|
||||
* P2 != 0:
|
||||
* -- If the returned value is not the point at infinity, then it was properly
|
||||
* computed.
|
||||
* -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result
|
||||
* is indeed the point at infinity.
|
||||
* -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should
|
||||
* use the 'double' code.
|
||||
*
|
||||
* Cost: 16 multiplications
|
||||
*/
|
||||
static const uint16_t code_add[] = {
|
||||
/*
|
||||
* Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
|
||||
*/
|
||||
MMUL(t3, P2z, P2z),
|
||||
MMUL(t1, P1x, t3),
|
||||
MMUL(t4, P2z, t3),
|
||||
MMUL(t3, P1y, t4),
|
||||
|
||||
/*
|
||||
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
|
||||
*/
|
||||
MMUL(t4, P1z, P1z),
|
||||
MMUL(t2, P2x, t4),
|
||||
MMUL(t5, P1z, t4),
|
||||
MMUL(t4, P2y, t5),
|
||||
|
||||
/*
|
||||
* Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4).
|
||||
*/
|
||||
MSUB(t2, t1),
|
||||
MSUB(t4, t3),
|
||||
|
||||
/*
|
||||
* Report cases where r = 0 through the returned flag.
|
||||
*/
|
||||
MTZ(t4),
|
||||
|
||||
/*
|
||||
* Compute u1*h^2 (in t6) and h^3 (in t5).
|
||||
*/
|
||||
MMUL(t7, t2, t2),
|
||||
MMUL(t6, t1, t7),
|
||||
MMUL(t5, t7, t2),
|
||||
|
||||
/*
|
||||
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
|
||||
* t1 and t7 can be used as scratch registers.
|
||||
*/
|
||||
MMUL(P1x, t4, t4),
|
||||
MSUB(P1x, t5),
|
||||
MSUB(P1x, t6),
|
||||
MSUB(P1x, t6),
|
||||
|
||||
/*
|
||||
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
|
||||
*/
|
||||
MSUB(t6, P1x),
|
||||
MMUL(P1y, t4, t6),
|
||||
MMUL(t1, t5, t3),
|
||||
MSUB(P1y, t1),
|
||||
|
||||
/*
|
||||
* Compute z3 = h*z1*z2.
|
||||
*/
|
||||
MMUL(t1, P1z, P2z),
|
||||
MMUL(P1z, t1, t2),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Check that the point is on the curve. This code snippet assumes the
|
||||
* following conventions:
|
||||
* -- Coordinates x and y have been freshly decoded in P1 (but not
|
||||
* converted to Montgomery coordinates yet).
|
||||
* -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1.
|
||||
*/
|
||||
static const uint16_t code_check[] = {
|
||||
|
||||
/* Convert x and y to Montgomery representation. */
|
||||
MMUL(t1, P1x, P2x),
|
||||
MMUL(t2, P1y, P2x),
|
||||
MSET(P1x, t1),
|
||||
MSET(P1y, t2),
|
||||
|
||||
/* Compute x^3 in t1. */
|
||||
MMUL(t2, P1x, P1x),
|
||||
MMUL(t1, P1x, t2),
|
||||
|
||||
/* Subtract 3*x from t1. */
|
||||
MSUB(t1, P1x),
|
||||
MSUB(t1, P1x),
|
||||
MSUB(t1, P1x),
|
||||
|
||||
/* Add b. */
|
||||
MADD(t1, P2y),
|
||||
|
||||
/* Compute y^2 in t2. */
|
||||
MMUL(t2, P1y, P1y),
|
||||
|
||||
/* Compare y^2 with x^3 - 3*x + b; they must match. */
|
||||
MSUB(t1, t2),
|
||||
MTZ(t1),
|
||||
|
||||
/* Set z to 1 (in Montgomery representation). */
|
||||
MMUL(P1z, P2x, P2z),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Conversion back to affine coordinates. This code snippet assumes that
|
||||
* the z coordinate of P2 is set to 1 (not in Montgomery representation).
|
||||
*/
|
||||
static const uint16_t code_affine[] = {
|
||||
|
||||
/* Save z*R in t1. */
|
||||
MSET(t1, P1z),
|
||||
|
||||
/* Compute z^3 in t2. */
|
||||
MMUL(t2, P1z, P1z),
|
||||
MMUL(t3, P1z, t2),
|
||||
MMUL(t2, t3, P2z),
|
||||
|
||||
/* Invert to (1/z^3) in t2. */
|
||||
MINV(t2, t3, t4),
|
||||
|
||||
/* Compute y. */
|
||||
MSET(t3, P1y),
|
||||
MMUL(P1y, t2, t3),
|
||||
|
||||
/* Compute (1/z^2) in t3. */
|
||||
MMUL(t3, t2, t1),
|
||||
|
||||
/* Compute x. */
|
||||
MSET(t2, P1x),
|
||||
MMUL(P1x, t2, t3),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
run_code(jacobian *P1, const jacobian *P2,
|
||||
const curve_params *cc, const uint16_t *code)
|
||||
{
|
||||
uint32_t r;
|
||||
uint16_t t[13][I15_LEN];
|
||||
size_t u;
|
||||
|
||||
r = 1;
|
||||
|
||||
/*
|
||||
* Copy the two operands in the dedicated registers.
|
||||
*/
|
||||
memcpy(t[P1x], P1->c, 3 * I15_LEN * sizeof(uint16_t));
|
||||
memcpy(t[P2x], P2->c, 3 * I15_LEN * sizeof(uint16_t));
|
||||
|
||||
/*
|
||||
* Run formulas.
|
||||
*/
|
||||
for (u = 0;; u ++) {
|
||||
unsigned op, d, a, b;
|
||||
|
||||
op = code[u];
|
||||
if (op == 0) {
|
||||
break;
|
||||
}
|
||||
d = (op >> 8) & 0x0F;
|
||||
a = (op >> 4) & 0x0F;
|
||||
b = op & 0x0F;
|
||||
op >>= 12;
|
||||
switch (op) {
|
||||
uint32_t ctl;
|
||||
size_t plen;
|
||||
unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
|
||||
case 0:
|
||||
memcpy(t[d], t[a], I15_LEN * sizeof(uint16_t));
|
||||
break;
|
||||
case 1:
|
||||
ctl = br_i15_add(t[d], t[a], 1);
|
||||
ctl |= NOT(br_i15_sub(t[d], cc->p, 0));
|
||||
br_i15_sub(t[d], cc->p, ctl);
|
||||
break;
|
||||
case 2:
|
||||
br_i15_add(t[d], cc->p, br_i15_sub(t[d], t[a], 1));
|
||||
break;
|
||||
case 3:
|
||||
br_i15_montymul(t[d], t[a], t[b], cc->p, cc->p0i);
|
||||
break;
|
||||
case 4:
|
||||
plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
|
||||
br_i15_encode(tp, plen, cc->p);
|
||||
tp[plen - 1] -= 2;
|
||||
br_i15_modpow(t[d], tp, plen,
|
||||
cc->p, cc->p0i, t[a], t[b]);
|
||||
break;
|
||||
default:
|
||||
r &= ~br_i15_iszero(t[d]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy back result.
|
||||
*/
|
||||
memcpy(P1->c, t[P1x], 3 * I15_LEN * sizeof(uint16_t));
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
set_one(uint16_t *x, const uint16_t *p)
|
||||
{
|
||||
size_t plen;
|
||||
|
||||
plen = (p[0] + 31) >> 4;
|
||||
memset(x, 0, plen * sizeof *x);
|
||||
x[0] = p[0];
|
||||
x[1] = 0x0001;
|
||||
}
|
||||
|
||||
static void
|
||||
point_zero(jacobian *P, const curve_params *cc)
|
||||
{
|
||||
memset(P, 0, sizeof *P);
|
||||
P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0];
|
||||
}
|
||||
|
||||
static inline void
|
||||
point_double(jacobian *P, const curve_params *cc)
|
||||
{
|
||||
run_code(P, P, cc, code_double);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
point_add(jacobian *P1, const jacobian *P2, const curve_params *cc)
|
||||
{
|
||||
return run_code(P1, P2, cc, code_add);
|
||||
}
|
||||
|
||||
static void
|
||||
point_mul(jacobian *P, const unsigned char *x, size_t xlen,
|
||||
const curve_params *cc)
|
||||
{
|
||||
/*
|
||||
* We do a simple double-and-add ladder with a 2-bit window
|
||||
* to make only one add every two doublings. We thus first
|
||||
* precompute 2P and 3P in some local buffers.
|
||||
*
|
||||
* We always perform two doublings and one addition; the
|
||||
* addition is with P, 2P and 3P and is done in a temporary
|
||||
* array.
|
||||
*
|
||||
* The addition code cannot handle cases where one of the
|
||||
* operands is infinity, which is the case at the start of the
|
||||
* ladder. We therefore need to maintain a flag that controls
|
||||
* this situation.
|
||||
*/
|
||||
uint32_t qz;
|
||||
jacobian P2, P3, Q, T, U;
|
||||
|
||||
memcpy(&P2, P, sizeof P2);
|
||||
point_double(&P2, cc);
|
||||
memcpy(&P3, P, sizeof P3);
|
||||
point_add(&P3, &P2, cc);
|
||||
|
||||
point_zero(&Q, cc);
|
||||
qz = 1;
|
||||
while (xlen -- > 0) {
|
||||
int k;
|
||||
|
||||
for (k = 6; k >= 0; k -= 2) {
|
||||
uint32_t bits;
|
||||
uint32_t bnz;
|
||||
|
||||
point_double(&Q, cc);
|
||||
point_double(&Q, cc);
|
||||
memcpy(&T, P, sizeof T);
|
||||
memcpy(&U, &Q, sizeof U);
|
||||
bits = (*x >> k) & (uint32_t)3;
|
||||
bnz = NEQ(bits, 0);
|
||||
CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
|
||||
CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
|
||||
point_add(&U, &T, cc);
|
||||
CCOPY(bnz & qz, &Q, &T, sizeof Q);
|
||||
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
|
||||
qz &= ~bnz;
|
||||
}
|
||||
x ++;
|
||||
}
|
||||
memcpy(P, &Q, sizeof Q);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode point into Jacobian coordinates. This function does not support
|
||||
* the point at infinity. If the point is invalid then this returns 0, but
|
||||
* the coordinates are still set to properly formed field elements.
|
||||
*/
|
||||
static uint32_t
|
||||
point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc)
|
||||
{
|
||||
/*
|
||||
* Points must use uncompressed format:
|
||||
* -- first byte is 0x04;
|
||||
* -- coordinates X and Y use unsigned big-endian, with the same
|
||||
* length as the field modulus.
|
||||
*
|
||||
* We don't support hybrid format (uncompressed, but first byte
|
||||
* has value 0x06 or 0x07, depending on the least significant bit
|
||||
* of Y) because it is rather useless, and explicitly forbidden
|
||||
* by PKIX (RFC 5480, section 2.2).
|
||||
*
|
||||
* We don't support compressed format either, because it is not
|
||||
* much used in practice (there are or were patent-related
|
||||
* concerns about point compression, which explains the lack of
|
||||
* generalised support). Also, point compression support would
|
||||
* need a bit more code.
|
||||
*/
|
||||
const unsigned char *buf;
|
||||
size_t plen, zlen;
|
||||
uint32_t r;
|
||||
jacobian Q;
|
||||
|
||||
buf = src;
|
||||
point_zero(P, cc);
|
||||
plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
|
||||
if (len != 1 + (plen << 1)) {
|
||||
return 0;
|
||||
}
|
||||
r = br_i15_decode_mod(P->c[0], buf + 1, plen, cc->p);
|
||||
r &= br_i15_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p);
|
||||
|
||||
/*
|
||||
* Check first byte.
|
||||
*/
|
||||
r &= EQ(buf[0], 0x04);
|
||||
/* obsolete
|
||||
r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06)
|
||||
& ~(uint32_t)(buf[0] ^ buf[plen << 1]));
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert coordinates and check that the point is valid.
|
||||
*/
|
||||
zlen = ((cc->p[0] + 31) >> 4) * sizeof(uint16_t);
|
||||
memcpy(Q.c[0], cc->R2, zlen);
|
||||
memcpy(Q.c[1], cc->b, zlen);
|
||||
set_one(Q.c[2], cc->p);
|
||||
r &= ~run_code(P, &Q, cc, code_check);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a point. This method assumes that the point is correct and is
|
||||
* not the point at infinity. Encoded size is always 1+2*plen, where
|
||||
* plen is the field modulus length, in bytes.
|
||||
*/
|
||||
static void
|
||||
point_encode(void *dst, const jacobian *P, const curve_params *cc)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t plen;
|
||||
jacobian Q, T;
|
||||
|
||||
buf = dst;
|
||||
plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
|
||||
buf[0] = 0x04;
|
||||
memcpy(&Q, P, sizeof *P);
|
||||
set_one(T.c[2], cc->p);
|
||||
run_code(&Q, &T, cc, code_affine);
|
||||
br_i15_encode(buf + 1, plen, Q.c[0]);
|
||||
br_i15_encode(buf + 1 + plen, plen, Q.c[1]);
|
||||
}
|
||||
|
||||
static const br_ec_curve_def *
|
||||
id_to_curve_def(int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return &br_secp256r1;
|
||||
case BR_EC_secp384r1:
|
||||
return &br_secp384r1;
|
||||
case BR_EC_secp521r1:
|
||||
return &br_secp521r1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
const br_ec_curve_def *cd;
|
||||
|
||||
cd = id_to_curve_def(curve);
|
||||
*len = cd->generator_len;
|
||||
return cd->generator;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
const br_ec_curve_def *cd;
|
||||
|
||||
cd = id_to_curve_def(curve);
|
||||
*len = cd->order_len;
|
||||
return cd->order;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_xoff(int curve, size_t *len)
|
||||
{
|
||||
api_generator(curve, len);
|
||||
*len >>= 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
uint32_t r;
|
||||
const curve_params *cc;
|
||||
jacobian P;
|
||||
|
||||
cc = id_to_curve(curve);
|
||||
r = point_decode(&P, G, Glen, cc);
|
||||
point_mul(&P, x, xlen, cc);
|
||||
if (Glen == cc->point_len) {
|
||||
point_encode(G, &P, cc);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_mulgen(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
const unsigned char *G;
|
||||
size_t Glen;
|
||||
|
||||
G = api_generator(curve, &Glen);
|
||||
memcpy(R, G, Glen);
|
||||
api_mul(R, Glen, x, xlen, curve);
|
||||
return Glen;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
uint32_t r, t, z;
|
||||
const curve_params *cc;
|
||||
jacobian P, Q;
|
||||
|
||||
/*
|
||||
* TODO: see about merging the two ladders. Right now, we do
|
||||
* two independent point multiplications, which is a bit
|
||||
* wasteful of CPU resources (but yields short code).
|
||||
*/
|
||||
|
||||
cc = id_to_curve(curve);
|
||||
r = point_decode(&P, A, len, cc);
|
||||
if (B == NULL) {
|
||||
size_t Glen;
|
||||
|
||||
B = api_generator(curve, &Glen);
|
||||
}
|
||||
r &= point_decode(&Q, B, len, cc);
|
||||
point_mul(&P, x, xlen, cc);
|
||||
point_mul(&Q, y, ylen, cc);
|
||||
|
||||
/*
|
||||
* We want to compute P+Q. Since the base points A and B are distinct
|
||||
* from infinity, and the multipliers are non-zero and lower than the
|
||||
* curve order, then we know that P and Q are non-infinity. This
|
||||
* leaves two special situations to test for:
|
||||
* -- If P = Q then we must use point_double().
|
||||
* -- If P+Q = 0 then we must report an error.
|
||||
*/
|
||||
t = point_add(&P, &Q, cc);
|
||||
point_double(&Q, cc);
|
||||
z = br_i15_iszero(P.c[2]);
|
||||
|
||||
/*
|
||||
* If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
|
||||
* have the following:
|
||||
*
|
||||
* z = 0, t = 0 return P (normal addition)
|
||||
* z = 0, t = 1 return P (normal addition)
|
||||
* z = 1, t = 0 return Q (a 'double' case)
|
||||
* z = 1, t = 1 report an error (P+Q = 0)
|
||||
*/
|
||||
CCOPY(z & ~t, &P, &Q, sizeof Q);
|
||||
point_encode(A, &P, cc);
|
||||
r &= ~(z & t);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_prime_i15 = {
|
||||
(uint32_t)0x03800000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_xoff,
|
||||
&api_mul,
|
||||
&api_mulgen,
|
||||
&api_muladd
|
||||
};
|
||||
819
dstalk-core/thirdparty/bearssl/src/ec/ec_prime_i31.c
vendored
819
dstalk-core/thirdparty/bearssl/src/ec/ec_prime_i31.c
vendored
@@ -1,819 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Parameters for supported curves (field modulus, and 'b' equation
|
||||
* parameter; both values use the 'i31' format, and 'b' is in Montgomery
|
||||
* representation).
|
||||
*/
|
||||
|
||||
static const uint32_t P256_P[] = {
|
||||
0x00000108,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000007,
|
||||
0x00000000, 0x00000000, 0x00000040, 0x7FFFFF80,
|
||||
0x000000FF
|
||||
};
|
||||
|
||||
static const uint32_t P256_R2[] = {
|
||||
0x00000108,
|
||||
0x00014000, 0x00018000, 0x00000000, 0x7FF40000,
|
||||
0x7FEFFFFF, 0x7FF7FFFF, 0x7FAFFFFF, 0x005FFFFF,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t P256_B[] = {
|
||||
0x00000108,
|
||||
0x6FEE1803, 0x6229C4BD, 0x21B139BE, 0x327150AA,
|
||||
0x3567802E, 0x3F7212ED, 0x012E4355, 0x782DD38D,
|
||||
0x0000000E
|
||||
};
|
||||
|
||||
static const uint32_t P384_P[] = {
|
||||
0x0000018C,
|
||||
0x7FFFFFFF, 0x00000001, 0x00000000, 0x7FFFFFF8,
|
||||
0x7FFFFFEF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x00000FFF
|
||||
};
|
||||
|
||||
static const uint32_t P384_R2[] = {
|
||||
0x0000018C,
|
||||
0x00000000, 0x00000080, 0x7FFFFE00, 0x000001FF,
|
||||
0x00000800, 0x00000000, 0x7FFFE000, 0x00001FFF,
|
||||
0x00008000, 0x00008000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t P384_B[] = {
|
||||
0x0000018C,
|
||||
0x6E666840, 0x070D0392, 0x5D810231, 0x7651D50C,
|
||||
0x17E218D6, 0x1B192002, 0x44EFE441, 0x3A524E2B,
|
||||
0x2719BA5F, 0x41F02209, 0x36C5643E, 0x5813EFFE,
|
||||
0x000008A5
|
||||
};
|
||||
|
||||
static const uint32_t P521_P[] = {
|
||||
0x00000219,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x01FFFFFF
|
||||
};
|
||||
|
||||
static const uint32_t P521_R2[] = {
|
||||
0x00000219,
|
||||
0x00001000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t P521_B[] = {
|
||||
0x00000219,
|
||||
0x540FC00A, 0x228FEA35, 0x2C34F1EF, 0x67BF107A,
|
||||
0x46FC1CD5, 0x1605E9DD, 0x6937B165, 0x272A3D8F,
|
||||
0x42785586, 0x44C8C778, 0x15F3B8B4, 0x64B73366,
|
||||
0x03BA8B69, 0x0D05B42A, 0x21F929A2, 0x2C31C393,
|
||||
0x00654FAE
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const uint32_t *p;
|
||||
const uint32_t *b;
|
||||
const uint32_t *R2;
|
||||
uint32_t p0i;
|
||||
} curve_params;
|
||||
|
||||
static inline const curve_params *
|
||||
id_to_curve(int curve)
|
||||
{
|
||||
static const curve_params pp[] = {
|
||||
{ P256_P, P256_B, P256_R2, 0x00000001 },
|
||||
{ P384_P, P384_B, P384_R2, 0x00000001 },
|
||||
{ P521_P, P521_B, P521_R2, 0x00000001 }
|
||||
};
|
||||
|
||||
return &pp[curve - BR_EC_secp256r1];
|
||||
}
|
||||
|
||||
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
|
||||
|
||||
/*
|
||||
* Type for a point in Jacobian coordinates:
|
||||
* -- three values, x, y and z, in Montgomery representation
|
||||
* -- affine coordinates are X = x / z^2 and Y = y / z^3
|
||||
* -- for the point at infinity, z = 0
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t c[3][I31_LEN];
|
||||
} jacobian;
|
||||
|
||||
/*
|
||||
* We use a custom interpreter that uses a dozen registers, and
|
||||
* only six operations:
|
||||
* MSET(d, a) copy a into d
|
||||
* MADD(d, a) d = d+a (modular)
|
||||
* MSUB(d, a) d = d-a (modular)
|
||||
* MMUL(d, a, b) d = a*b (Montgomery multiplication)
|
||||
* MINV(d, a, b) invert d modulo p; a and b are used as scratch registers
|
||||
* MTZ(d) clear return value if d = 0
|
||||
* Destination of MMUL (d) must be distinct from operands (a and b).
|
||||
* There is no such constraint for MSUB and MADD.
|
||||
*
|
||||
* Registers include the operand coordinates, and temporaries.
|
||||
*/
|
||||
#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4))
|
||||
#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4))
|
||||
#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4))
|
||||
#define MMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b))
|
||||
#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b))
|
||||
#define MTZ(d) (0x5000 + ((d) << 8))
|
||||
#define ENDCODE 0
|
||||
|
||||
/*
|
||||
* Registers for the input operands.
|
||||
*/
|
||||
#define P1x 0
|
||||
#define P1y 1
|
||||
#define P1z 2
|
||||
#define P2x 3
|
||||
#define P2y 4
|
||||
#define P2z 5
|
||||
|
||||
/*
|
||||
* Alternate names for the first input operand.
|
||||
*/
|
||||
#define Px 0
|
||||
#define Py 1
|
||||
#define Pz 2
|
||||
|
||||
/*
|
||||
* Temporaries.
|
||||
*/
|
||||
#define t1 6
|
||||
#define t2 7
|
||||
#define t3 8
|
||||
#define t4 9
|
||||
#define t5 10
|
||||
#define t6 11
|
||||
#define t7 12
|
||||
|
||||
/*
|
||||
* Extra scratch registers available when there is no second operand (e.g.
|
||||
* for "double" and "affine").
|
||||
*/
|
||||
#define t8 3
|
||||
#define t9 4
|
||||
#define t10 5
|
||||
|
||||
/*
|
||||
* Doubling formulas are:
|
||||
*
|
||||
* s = 4*x*y^2
|
||||
* m = 3*(x + z^2)*(x - z^2)
|
||||
* x' = m^2 - 2*s
|
||||
* y' = m*(s - x') - 8*y^4
|
||||
* z' = 2*y*z
|
||||
*
|
||||
* If y = 0 (P has order 2) then this yields infinity (z' = 0), as it
|
||||
* should. This case should not happen anyway, because our curves have
|
||||
* prime order, and thus do not contain any point of order 2.
|
||||
*
|
||||
* If P is infinity (z = 0), then again the formulas yield infinity,
|
||||
* which is correct. Thus, this code works for all points.
|
||||
*
|
||||
* Cost: 8 multiplications
|
||||
*/
|
||||
static const uint16_t code_double[] = {
|
||||
/*
|
||||
* Compute z^2 (in t1).
|
||||
*/
|
||||
MMUL(t1, Pz, Pz),
|
||||
|
||||
/*
|
||||
* Compute x-z^2 (in t2) and then x+z^2 (in t1).
|
||||
*/
|
||||
MSET(t2, Px),
|
||||
MSUB(t2, t1),
|
||||
MADD(t1, Px),
|
||||
|
||||
/*
|
||||
* Compute m = 3*(x+z^2)*(x-z^2) (in t1).
|
||||
*/
|
||||
MMUL(t3, t1, t2),
|
||||
MSET(t1, t3),
|
||||
MADD(t1, t3),
|
||||
MADD(t1, t3),
|
||||
|
||||
/*
|
||||
* Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3).
|
||||
*/
|
||||
MMUL(t3, Py, Py),
|
||||
MADD(t3, t3),
|
||||
MMUL(t2, Px, t3),
|
||||
MADD(t2, t2),
|
||||
|
||||
/*
|
||||
* Compute x' = m^2 - 2*s.
|
||||
*/
|
||||
MMUL(Px, t1, t1),
|
||||
MSUB(Px, t2),
|
||||
MSUB(Px, t2),
|
||||
|
||||
/*
|
||||
* Compute z' = 2*y*z.
|
||||
*/
|
||||
MMUL(t4, Py, Pz),
|
||||
MSET(Pz, t4),
|
||||
MADD(Pz, t4),
|
||||
|
||||
/*
|
||||
* Compute y' = m*(s - x') - 8*y^4. Note that we already have
|
||||
* 2*y^2 in t3.
|
||||
*/
|
||||
MSUB(t2, Px),
|
||||
MMUL(Py, t1, t2),
|
||||
MMUL(t4, t3, t3),
|
||||
MSUB(Py, t4),
|
||||
MSUB(Py, t4),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Addtions formulas are:
|
||||
*
|
||||
* u1 = x1 * z2^2
|
||||
* u2 = x2 * z1^2
|
||||
* s1 = y1 * z2^3
|
||||
* s2 = y2 * z1^3
|
||||
* h = u2 - u1
|
||||
* r = s2 - s1
|
||||
* x3 = r^2 - h^3 - 2 * u1 * h^2
|
||||
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
|
||||
* z3 = h * z1 * z2
|
||||
*
|
||||
* If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that
|
||||
* z3 == 0, so the result is correct.
|
||||
* If either of P1 or P2 is infinity, but not both, then z3 == 0, which is
|
||||
* not correct.
|
||||
* h == 0 only if u1 == u2; this happens in two cases:
|
||||
* -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2
|
||||
* -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity)
|
||||
*
|
||||
* Thus, the following situations are not handled correctly:
|
||||
* -- P1 = 0 and P2 != 0
|
||||
* -- P1 != 0 and P2 = 0
|
||||
* -- P1 = P2
|
||||
* All other cases are properly computed. However, even in "incorrect"
|
||||
* situations, the three coordinates still are properly formed field
|
||||
* elements.
|
||||
*
|
||||
* The returned flag is cleared if r == 0. This happens in the following
|
||||
* cases:
|
||||
* -- Both points are on the same horizontal line (same Y coordinate).
|
||||
* -- Both points are infinity.
|
||||
* -- One point is infinity and the other is on line Y = 0.
|
||||
* The third case cannot happen with our curves (there is no valid point
|
||||
* on line Y = 0 since that would be a point of order 2). If the two
|
||||
* source points are non-infinity, then remains only the case where the
|
||||
* two points are on the same horizontal line.
|
||||
*
|
||||
* This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and
|
||||
* P2 != 0:
|
||||
* -- If the returned value is not the point at infinity, then it was properly
|
||||
* computed.
|
||||
* -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result
|
||||
* is indeed the point at infinity.
|
||||
* -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should
|
||||
* use the 'double' code.
|
||||
*
|
||||
* Cost: 16 multiplications
|
||||
*/
|
||||
static const uint16_t code_add[] = {
|
||||
/*
|
||||
* Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
|
||||
*/
|
||||
MMUL(t3, P2z, P2z),
|
||||
MMUL(t1, P1x, t3),
|
||||
MMUL(t4, P2z, t3),
|
||||
MMUL(t3, P1y, t4),
|
||||
|
||||
/*
|
||||
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
|
||||
*/
|
||||
MMUL(t4, P1z, P1z),
|
||||
MMUL(t2, P2x, t4),
|
||||
MMUL(t5, P1z, t4),
|
||||
MMUL(t4, P2y, t5),
|
||||
|
||||
/*
|
||||
* Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4).
|
||||
*/
|
||||
MSUB(t2, t1),
|
||||
MSUB(t4, t3),
|
||||
|
||||
/*
|
||||
* Report cases where r = 0 through the returned flag.
|
||||
*/
|
||||
MTZ(t4),
|
||||
|
||||
/*
|
||||
* Compute u1*h^2 (in t6) and h^3 (in t5).
|
||||
*/
|
||||
MMUL(t7, t2, t2),
|
||||
MMUL(t6, t1, t7),
|
||||
MMUL(t5, t7, t2),
|
||||
|
||||
/*
|
||||
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
|
||||
* t1 and t7 can be used as scratch registers.
|
||||
*/
|
||||
MMUL(P1x, t4, t4),
|
||||
MSUB(P1x, t5),
|
||||
MSUB(P1x, t6),
|
||||
MSUB(P1x, t6),
|
||||
|
||||
/*
|
||||
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
|
||||
*/
|
||||
MSUB(t6, P1x),
|
||||
MMUL(P1y, t4, t6),
|
||||
MMUL(t1, t5, t3),
|
||||
MSUB(P1y, t1),
|
||||
|
||||
/*
|
||||
* Compute z3 = h*z1*z2.
|
||||
*/
|
||||
MMUL(t1, P1z, P2z),
|
||||
MMUL(P1z, t1, t2),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Check that the point is on the curve. This code snippet assumes the
|
||||
* following conventions:
|
||||
* -- Coordinates x and y have been freshly decoded in P1 (but not
|
||||
* converted to Montgomery coordinates yet).
|
||||
* -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1.
|
||||
*/
|
||||
static const uint16_t code_check[] = {
|
||||
|
||||
/* Convert x and y to Montgomery representation. */
|
||||
MMUL(t1, P1x, P2x),
|
||||
MMUL(t2, P1y, P2x),
|
||||
MSET(P1x, t1),
|
||||
MSET(P1y, t2),
|
||||
|
||||
/* Compute x^3 in t1. */
|
||||
MMUL(t2, P1x, P1x),
|
||||
MMUL(t1, P1x, t2),
|
||||
|
||||
/* Subtract 3*x from t1. */
|
||||
MSUB(t1, P1x),
|
||||
MSUB(t1, P1x),
|
||||
MSUB(t1, P1x),
|
||||
|
||||
/* Add b. */
|
||||
MADD(t1, P2y),
|
||||
|
||||
/* Compute y^2 in t2. */
|
||||
MMUL(t2, P1y, P1y),
|
||||
|
||||
/* Compare y^2 with x^3 - 3*x + b; they must match. */
|
||||
MSUB(t1, t2),
|
||||
MTZ(t1),
|
||||
|
||||
/* Set z to 1 (in Montgomery representation). */
|
||||
MMUL(P1z, P2x, P2z),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Conversion back to affine coordinates. This code snippet assumes that
|
||||
* the z coordinate of P2 is set to 1 (not in Montgomery representation).
|
||||
*/
|
||||
static const uint16_t code_affine[] = {
|
||||
|
||||
/* Save z*R in t1. */
|
||||
MSET(t1, P1z),
|
||||
|
||||
/* Compute z^3 in t2. */
|
||||
MMUL(t2, P1z, P1z),
|
||||
MMUL(t3, P1z, t2),
|
||||
MMUL(t2, t3, P2z),
|
||||
|
||||
/* Invert to (1/z^3) in t2. */
|
||||
MINV(t2, t3, t4),
|
||||
|
||||
/* Compute y. */
|
||||
MSET(t3, P1y),
|
||||
MMUL(P1y, t2, t3),
|
||||
|
||||
/* Compute (1/z^2) in t3. */
|
||||
MMUL(t3, t2, t1),
|
||||
|
||||
/* Compute x. */
|
||||
MSET(t2, P1x),
|
||||
MMUL(P1x, t2, t3),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
run_code(jacobian *P1, const jacobian *P2,
|
||||
const curve_params *cc, const uint16_t *code)
|
||||
{
|
||||
uint32_t r;
|
||||
uint32_t t[13][I31_LEN];
|
||||
size_t u;
|
||||
|
||||
r = 1;
|
||||
|
||||
/*
|
||||
* Copy the two operands in the dedicated registers.
|
||||
*/
|
||||
memcpy(t[P1x], P1->c, 3 * I31_LEN * sizeof(uint32_t));
|
||||
memcpy(t[P2x], P2->c, 3 * I31_LEN * sizeof(uint32_t));
|
||||
|
||||
/*
|
||||
* Run formulas.
|
||||
*/
|
||||
for (u = 0;; u ++) {
|
||||
unsigned op, d, a, b;
|
||||
|
||||
op = code[u];
|
||||
if (op == 0) {
|
||||
break;
|
||||
}
|
||||
d = (op >> 8) & 0x0F;
|
||||
a = (op >> 4) & 0x0F;
|
||||
b = op & 0x0F;
|
||||
op >>= 12;
|
||||
switch (op) {
|
||||
uint32_t ctl;
|
||||
size_t plen;
|
||||
unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
|
||||
case 0:
|
||||
memcpy(t[d], t[a], I31_LEN * sizeof(uint32_t));
|
||||
break;
|
||||
case 1:
|
||||
ctl = br_i31_add(t[d], t[a], 1);
|
||||
ctl |= NOT(br_i31_sub(t[d], cc->p, 0));
|
||||
br_i31_sub(t[d], cc->p, ctl);
|
||||
break;
|
||||
case 2:
|
||||
br_i31_add(t[d], cc->p, br_i31_sub(t[d], t[a], 1));
|
||||
break;
|
||||
case 3:
|
||||
br_i31_montymul(t[d], t[a], t[b], cc->p, cc->p0i);
|
||||
break;
|
||||
case 4:
|
||||
plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3;
|
||||
br_i31_encode(tp, plen, cc->p);
|
||||
tp[plen - 1] -= 2;
|
||||
br_i31_modpow(t[d], tp, plen,
|
||||
cc->p, cc->p0i, t[a], t[b]);
|
||||
break;
|
||||
default:
|
||||
r &= ~br_i31_iszero(t[d]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy back result.
|
||||
*/
|
||||
memcpy(P1->c, t[P1x], 3 * I31_LEN * sizeof(uint32_t));
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
set_one(uint32_t *x, const uint32_t *p)
|
||||
{
|
||||
size_t plen;
|
||||
|
||||
plen = (p[0] + 63) >> 5;
|
||||
memset(x, 0, plen * sizeof *x);
|
||||
x[0] = p[0];
|
||||
x[1] = 0x00000001;
|
||||
}
|
||||
|
||||
static void
|
||||
point_zero(jacobian *P, const curve_params *cc)
|
||||
{
|
||||
memset(P, 0, sizeof *P);
|
||||
P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0];
|
||||
}
|
||||
|
||||
static inline void
|
||||
point_double(jacobian *P, const curve_params *cc)
|
||||
{
|
||||
run_code(P, P, cc, code_double);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
point_add(jacobian *P1, const jacobian *P2, const curve_params *cc)
|
||||
{
|
||||
return run_code(P1, P2, cc, code_add);
|
||||
}
|
||||
|
||||
static void
|
||||
point_mul(jacobian *P, const unsigned char *x, size_t xlen,
|
||||
const curve_params *cc)
|
||||
{
|
||||
/*
|
||||
* We do a simple double-and-add ladder with a 2-bit window
|
||||
* to make only one add every two doublings. We thus first
|
||||
* precompute 2P and 3P in some local buffers.
|
||||
*
|
||||
* We always perform two doublings and one addition; the
|
||||
* addition is with P, 2P and 3P and is done in a temporary
|
||||
* array.
|
||||
*
|
||||
* The addition code cannot handle cases where one of the
|
||||
* operands is infinity, which is the case at the start of the
|
||||
* ladder. We therefore need to maintain a flag that controls
|
||||
* this situation.
|
||||
*/
|
||||
uint32_t qz;
|
||||
jacobian P2, P3, Q, T, U;
|
||||
|
||||
memcpy(&P2, P, sizeof P2);
|
||||
point_double(&P2, cc);
|
||||
memcpy(&P3, P, sizeof P3);
|
||||
point_add(&P3, &P2, cc);
|
||||
|
||||
point_zero(&Q, cc);
|
||||
qz = 1;
|
||||
while (xlen -- > 0) {
|
||||
int k;
|
||||
|
||||
for (k = 6; k >= 0; k -= 2) {
|
||||
uint32_t bits;
|
||||
uint32_t bnz;
|
||||
|
||||
point_double(&Q, cc);
|
||||
point_double(&Q, cc);
|
||||
memcpy(&T, P, sizeof T);
|
||||
memcpy(&U, &Q, sizeof U);
|
||||
bits = (*x >> k) & (uint32_t)3;
|
||||
bnz = NEQ(bits, 0);
|
||||
CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
|
||||
CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
|
||||
point_add(&U, &T, cc);
|
||||
CCOPY(bnz & qz, &Q, &T, sizeof Q);
|
||||
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
|
||||
qz &= ~bnz;
|
||||
}
|
||||
x ++;
|
||||
}
|
||||
memcpy(P, &Q, sizeof Q);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode point into Jacobian coordinates. This function does not support
|
||||
* the point at infinity. If the point is invalid then this returns 0, but
|
||||
* the coordinates are still set to properly formed field elements.
|
||||
*/
|
||||
static uint32_t
|
||||
point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc)
|
||||
{
|
||||
/*
|
||||
* Points must use uncompressed format:
|
||||
* -- first byte is 0x04;
|
||||
* -- coordinates X and Y use unsigned big-endian, with the same
|
||||
* length as the field modulus.
|
||||
*
|
||||
* We don't support hybrid format (uncompressed, but first byte
|
||||
* has value 0x06 or 0x07, depending on the least significant bit
|
||||
* of Y) because it is rather useless, and explicitly forbidden
|
||||
* by PKIX (RFC 5480, section 2.2).
|
||||
*
|
||||
* We don't support compressed format either, because it is not
|
||||
* much used in practice (there are or were patent-related
|
||||
* concerns about point compression, which explains the lack of
|
||||
* generalised support). Also, point compression support would
|
||||
* need a bit more code.
|
||||
*/
|
||||
const unsigned char *buf;
|
||||
size_t plen, zlen;
|
||||
uint32_t r;
|
||||
jacobian Q;
|
||||
|
||||
buf = src;
|
||||
point_zero(P, cc);
|
||||
plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3;
|
||||
if (len != 1 + (plen << 1)) {
|
||||
return 0;
|
||||
}
|
||||
r = br_i31_decode_mod(P->c[0], buf + 1, plen, cc->p);
|
||||
r &= br_i31_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p);
|
||||
|
||||
/*
|
||||
* Check first byte.
|
||||
*/
|
||||
r &= EQ(buf[0], 0x04);
|
||||
/* obsolete
|
||||
r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06)
|
||||
& ~(uint32_t)(buf[0] ^ buf[plen << 1]));
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert coordinates and check that the point is valid.
|
||||
*/
|
||||
zlen = ((cc->p[0] + 63) >> 5) * sizeof(uint32_t);
|
||||
memcpy(Q.c[0], cc->R2, zlen);
|
||||
memcpy(Q.c[1], cc->b, zlen);
|
||||
set_one(Q.c[2], cc->p);
|
||||
r &= ~run_code(P, &Q, cc, code_check);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a point. This method assumes that the point is correct and is
|
||||
* not the point at infinity. Encoded size is always 1+2*plen, where
|
||||
* plen is the field modulus length, in bytes.
|
||||
*/
|
||||
static void
|
||||
point_encode(void *dst, const jacobian *P, const curve_params *cc)
|
||||
{
|
||||
unsigned char *buf;
|
||||
uint32_t xbl;
|
||||
size_t plen;
|
||||
jacobian Q, T;
|
||||
|
||||
buf = dst;
|
||||
xbl = cc->p[0];
|
||||
xbl -= (xbl >> 5);
|
||||
plen = (xbl + 7) >> 3;
|
||||
buf[0] = 0x04;
|
||||
memcpy(&Q, P, sizeof *P);
|
||||
set_one(T.c[2], cc->p);
|
||||
run_code(&Q, &T, cc, code_affine);
|
||||
br_i31_encode(buf + 1, plen, Q.c[0]);
|
||||
br_i31_encode(buf + 1 + plen, plen, Q.c[1]);
|
||||
}
|
||||
|
||||
static const br_ec_curve_def *
|
||||
id_to_curve_def(int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return &br_secp256r1;
|
||||
case BR_EC_secp384r1:
|
||||
return &br_secp384r1;
|
||||
case BR_EC_secp521r1:
|
||||
return &br_secp521r1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
const br_ec_curve_def *cd;
|
||||
|
||||
cd = id_to_curve_def(curve);
|
||||
*len = cd->generator_len;
|
||||
return cd->generator;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
const br_ec_curve_def *cd;
|
||||
|
||||
cd = id_to_curve_def(curve);
|
||||
*len = cd->order_len;
|
||||
return cd->order;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_xoff(int curve, size_t *len)
|
||||
{
|
||||
api_generator(curve, len);
|
||||
*len >>= 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
uint32_t r;
|
||||
const curve_params *cc;
|
||||
jacobian P;
|
||||
|
||||
cc = id_to_curve(curve);
|
||||
r = point_decode(&P, G, Glen, cc);
|
||||
point_mul(&P, x, xlen, cc);
|
||||
point_encode(G, &P, cc);
|
||||
return r;
|
||||
}
|
||||
|
||||
static size_t
|
||||
api_mulgen(unsigned char *R,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
const unsigned char *G;
|
||||
size_t Glen;
|
||||
|
||||
G = api_generator(curve, &Glen);
|
||||
memcpy(R, G, Glen);
|
||||
api_mul(R, Glen, x, xlen, curve);
|
||||
return Glen;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
uint32_t r, t, z;
|
||||
const curve_params *cc;
|
||||
jacobian P, Q;
|
||||
|
||||
/*
|
||||
* TODO: see about merging the two ladders. Right now, we do
|
||||
* two independent point multiplications, which is a bit
|
||||
* wasteful of CPU resources (but yields short code).
|
||||
*/
|
||||
|
||||
cc = id_to_curve(curve);
|
||||
r = point_decode(&P, A, len, cc);
|
||||
if (B == NULL) {
|
||||
size_t Glen;
|
||||
|
||||
B = api_generator(curve, &Glen);
|
||||
}
|
||||
r &= point_decode(&Q, B, len, cc);
|
||||
point_mul(&P, x, xlen, cc);
|
||||
point_mul(&Q, y, ylen, cc);
|
||||
|
||||
/*
|
||||
* We want to compute P+Q. Since the base points A and B are distinct
|
||||
* from infinity, and the multipliers are non-zero and lower than the
|
||||
* curve order, then we know that P and Q are non-infinity. This
|
||||
* leaves two special situations to test for:
|
||||
* -- If P = Q then we must use point_double().
|
||||
* -- If P+Q = 0 then we must report an error.
|
||||
*/
|
||||
t = point_add(&P, &Q, cc);
|
||||
point_double(&Q, cc);
|
||||
z = br_i31_iszero(P.c[2]);
|
||||
|
||||
/*
|
||||
* If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
|
||||
* have the following:
|
||||
*
|
||||
* z = 0, t = 0 return P (normal addition)
|
||||
* z = 0, t = 1 return P (normal addition)
|
||||
* z = 1, t = 0 return Q (a 'double' case)
|
||||
* z = 1, t = 1 report an error (P+Q = 0)
|
||||
*/
|
||||
CCOPY(z & ~t, &P, &Q, sizeof Q);
|
||||
point_encode(A, &P, cc);
|
||||
r &= ~(z & t);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_prime_i31 = {
|
||||
(uint32_t)0x03800000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_xoff,
|
||||
&api_mul,
|
||||
&api_mulgen,
|
||||
&api_muladd
|
||||
};
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char POINT_LEN[] = {
|
||||
0, /* 0: not a valid curve ID */
|
||||
43, /* sect163k1 */
|
||||
43, /* sect163r1 */
|
||||
43, /* sect163r2 */
|
||||
51, /* sect193r1 */
|
||||
51, /* sect193r2 */
|
||||
61, /* sect233k1 */
|
||||
61, /* sect233r1 */
|
||||
61, /* sect239k1 */
|
||||
73, /* sect283k1 */
|
||||
73, /* sect283r1 */
|
||||
105, /* sect409k1 */
|
||||
105, /* sect409r1 */
|
||||
145, /* sect571k1 */
|
||||
145, /* sect571r1 */
|
||||
41, /* secp160k1 */
|
||||
41, /* secp160r1 */
|
||||
41, /* secp160r2 */
|
||||
49, /* secp192k1 */
|
||||
49, /* secp192r1 */
|
||||
57, /* secp224k1 */
|
||||
57, /* secp224r1 */
|
||||
65, /* secp256k1 */
|
||||
65, /* secp256r1 */
|
||||
97, /* secp384r1 */
|
||||
133, /* secp521r1 */
|
||||
65, /* brainpoolP256r1 */
|
||||
97, /* brainpoolP384r1 */
|
||||
129, /* brainpoolP512r1 */
|
||||
32, /* curve25519 */
|
||||
56, /* curve448 */
|
||||
};
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk,
|
||||
void *kbuf, const br_ec_private_key *sk)
|
||||
{
|
||||
int curve;
|
||||
size_t len;
|
||||
|
||||
curve = sk->curve;
|
||||
if (curve < 0 || curve >= 32 || curve >= (int)(sizeof POINT_LEN)
|
||||
|| ((impl->supported_curves >> curve) & 1) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (kbuf == NULL) {
|
||||
return POINT_LEN[curve];
|
||||
}
|
||||
len = impl->mulgen(kbuf, sk->x, sk->xlen, curve);
|
||||
if (pk != NULL) {
|
||||
pk->curve = curve;
|
||||
pk->q = kbuf;
|
||||
pk->qlen = len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char P256_N[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
|
||||
0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
|
||||
};
|
||||
|
||||
static const unsigned char P256_G[] = {
|
||||
0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42,
|
||||
0x47, 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40,
|
||||
0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33,
|
||||
0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
|
||||
0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
|
||||
0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E,
|
||||
0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E,
|
||||
0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51,
|
||||
0xF5
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_curve_def br_secp256r1 = {
|
||||
BR_EC_secp256r1,
|
||||
P256_N, sizeof P256_N,
|
||||
P256_G, sizeof P256_G
|
||||
};
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char P384_N[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF,
|
||||
0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A,
|
||||
0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73
|
||||
};
|
||||
|
||||
static const unsigned char P384_G[] = {
|
||||
0x04, 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05,
|
||||
0x37, 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD,
|
||||
0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B,
|
||||
0x98, 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A,
|
||||
0x38, 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29,
|
||||
0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A,
|
||||
0xB7, 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C,
|
||||
0x6F, 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC,
|
||||
0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14,
|
||||
0x7C, 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8,
|
||||
0xC0, 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81,
|
||||
0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E,
|
||||
0x5F
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_curve_def br_secp384r1 = {
|
||||
BR_EC_secp384r1,
|
||||
P384_N, sizeof P384_N,
|
||||
P384_G, sizeof P384_G
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char P521_N[] = {
|
||||
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F,
|
||||
0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
|
||||
0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C,
|
||||
0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38,
|
||||
0x64, 0x09
|
||||
};
|
||||
|
||||
static const unsigned char P521_G[] = {
|
||||
0x04, 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04,
|
||||
0x04, 0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23,
|
||||
0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05,
|
||||
0x3F, 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B,
|
||||
0x4D, 0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF,
|
||||
0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2,
|
||||
0xFF, 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85,
|
||||
0x6A, 0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2,
|
||||
0xE5, 0xBD, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6A,
|
||||
0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A, 0x5F,
|
||||
0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44,
|
||||
0x49, 0x57, 0x9B, 0x44, 0x68, 0x17, 0xAF, 0xBD,
|
||||
0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE, 0x72,
|
||||
0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9,
|
||||
0x01, 0x3F, 0xAD, 0x07, 0x61, 0x35, 0x3C, 0x70,
|
||||
0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE, 0x94,
|
||||
0x76, 0x9F, 0xD1, 0x66, 0x50
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_curve_def br_secp521r1 = {
|
||||
BR_EC_secp521r1,
|
||||
P521_N, sizeof P521_N,
|
||||
P521_G, sizeof P521_G
|
||||
};
|
||||
134
dstalk-core/thirdparty/bearssl/src/ec/ecdsa_atr.c
vendored
134
dstalk-core/thirdparty/bearssl/src/ec/ecdsa_atr.c
vendored
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_asn1_to_raw(void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* Note: this code is a bit lenient in that it accepts a few
|
||||
* deviations to DER with regards to minimality of encoding of
|
||||
* lengths and integer values. These deviations are still
|
||||
* unambiguous.
|
||||
*
|
||||
* Signature format is a SEQUENCE of two INTEGER values. We
|
||||
* support only integers of less than 127 bytes each (signed
|
||||
* encoding) so the resulting raw signature will have length
|
||||
* at most 254 bytes.
|
||||
*/
|
||||
|
||||
unsigned char *buf, *r, *s;
|
||||
size_t zlen, rlen, slen, off;
|
||||
unsigned char tmp[254];
|
||||
|
||||
buf = sig;
|
||||
if (sig_len < 8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* First byte is SEQUENCE tag.
|
||||
*/
|
||||
if (buf[0] != 0x30) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The SEQUENCE length will be encoded over one or two bytes. We
|
||||
* limit the total SEQUENCE contents to 255 bytes, because it
|
||||
* makes things simpler; this is enough for subgroup orders up
|
||||
* to 999 bits.
|
||||
*/
|
||||
zlen = buf[1];
|
||||
if (zlen > 0x80) {
|
||||
if (zlen != 0x81) {
|
||||
return 0;
|
||||
}
|
||||
zlen = buf[2];
|
||||
if (zlen != sig_len - 3) {
|
||||
return 0;
|
||||
}
|
||||
off = 3;
|
||||
} else {
|
||||
if (zlen != sig_len - 2) {
|
||||
return 0;
|
||||
}
|
||||
off = 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* First INTEGER (r).
|
||||
*/
|
||||
if (buf[off ++] != 0x02) {
|
||||
return 0;
|
||||
}
|
||||
rlen = buf[off ++];
|
||||
if (rlen >= 0x80) {
|
||||
return 0;
|
||||
}
|
||||
r = buf + off;
|
||||
off += rlen;
|
||||
|
||||
/*
|
||||
* Second INTEGER (s).
|
||||
*/
|
||||
if (off + 2 > sig_len) {
|
||||
return 0;
|
||||
}
|
||||
if (buf[off ++] != 0x02) {
|
||||
return 0;
|
||||
}
|
||||
slen = buf[off ++];
|
||||
if (slen >= 0x80 || slen != sig_len - off) {
|
||||
return 0;
|
||||
}
|
||||
s = buf + off;
|
||||
|
||||
/*
|
||||
* Removing leading zeros from r and s.
|
||||
*/
|
||||
while (rlen > 0 && *r == 0) {
|
||||
rlen --;
|
||||
r ++;
|
||||
}
|
||||
while (slen > 0 && *s == 0) {
|
||||
slen --;
|
||||
s ++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute common length for the two integers, then copy integers
|
||||
* into the temporary buffer, and finally copy it back over the
|
||||
* signature buffer.
|
||||
*/
|
||||
zlen = rlen > slen ? rlen : slen;
|
||||
sig_len = zlen << 1;
|
||||
memset(tmp, 0, sig_len);
|
||||
memcpy(tmp + zlen - rlen, r, rlen);
|
||||
memcpy(tmp + sig_len - slen, s, slen);
|
||||
memcpy(sig, tmp, sig_len);
|
||||
return sig_len;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
br_ecdsa_sign
|
||||
br_ecdsa_sign_asn1_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_ecdsa_i15_sign_asn1;
|
||||
#else
|
||||
return &br_ecdsa_i31_sign_asn1;
|
||||
#endif
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
br_ecdsa_sign
|
||||
br_ecdsa_sign_raw_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_ecdsa_i15_sign_raw;
|
||||
#else
|
||||
return &br_ecdsa_i31_sign_raw;
|
||||
#endif
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
br_ecdsa_vrfy
|
||||
br_ecdsa_vrfy_asn1_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_ecdsa_i15_vrfy_asn1;
|
||||
#else
|
||||
return &br_ecdsa_i31_vrfy_asn1;
|
||||
#endif
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
br_ecdsa_vrfy
|
||||
br_ecdsa_vrfy_raw_get_default(void)
|
||||
{
|
||||
#if BR_LOMUL
|
||||
return &br_ecdsa_i15_vrfy_raw;
|
||||
#else
|
||||
return &br_ecdsa_i31_vrfy_raw;
|
||||
#endif
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_ecdsa_i15_bits2int(uint16_t *x,
|
||||
const void *src, size_t len, uint32_t ebitlen)
|
||||
{
|
||||
uint32_t bitlen, hbitlen;
|
||||
int sc;
|
||||
|
||||
bitlen = ebitlen - (ebitlen >> 4);
|
||||
hbitlen = (uint32_t)len << 3;
|
||||
if (hbitlen > bitlen) {
|
||||
len = (bitlen + 7) >> 3;
|
||||
sc = (int)((hbitlen - bitlen) & 7);
|
||||
} else {
|
||||
sc = 0;
|
||||
}
|
||||
br_i15_zero(x, ebitlen);
|
||||
br_i15_decode(x, src, len);
|
||||
br_i15_rshift(x, sc);
|
||||
x[0] = ebitlen;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_i15_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig)
|
||||
{
|
||||
unsigned char rsig[(ORDER_LEN << 1) + 12];
|
||||
size_t sig_len;
|
||||
|
||||
sig_len = br_ecdsa_i15_sign_raw(impl, hf, hash_value, sk, rsig);
|
||||
if (sig_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len);
|
||||
memcpy(sig, rsig, sig_len);
|
||||
return sig_len;
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
|
||||
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
|
||||
#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_i15_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig)
|
||||
{
|
||||
/*
|
||||
* IMPORTANT: this code is fit only for curves with a prime
|
||||
* order. This is needed so that modular reduction of the X
|
||||
* coordinate of a point can be done with a simple subtraction.
|
||||
* We also rely on the last byte of the curve order to be distinct
|
||||
* from 0 and 1.
|
||||
*/
|
||||
const br_ec_curve_def *cd;
|
||||
uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], x[I15_LEN];
|
||||
uint16_t m[I15_LEN], k[I15_LEN], t1[I15_LEN], t2[I15_LEN];
|
||||
unsigned char tt[ORDER_LEN << 1];
|
||||
unsigned char eU[POINT_LEN];
|
||||
size_t hash_len, nlen, ulen;
|
||||
uint16_t n0i;
|
||||
uint32_t ctl;
|
||||
br_hmac_drbg_context drbg;
|
||||
|
||||
/*
|
||||
* If the curve is not supported, then exit with an error.
|
||||
*/
|
||||
if (((impl->supported_curves >> sk->curve) & 1) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the curve parameters (generator and order).
|
||||
*/
|
||||
switch (sk->curve) {
|
||||
case BR_EC_secp256r1:
|
||||
cd = &br_secp256r1;
|
||||
break;
|
||||
case BR_EC_secp384r1:
|
||||
cd = &br_secp384r1;
|
||||
break;
|
||||
case BR_EC_secp521r1:
|
||||
cd = &br_secp521r1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get modulus.
|
||||
*/
|
||||
nlen = cd->order_len;
|
||||
br_i15_decode(n, cd->order, nlen);
|
||||
n0i = br_i15_ninv15(n[1]);
|
||||
|
||||
/*
|
||||
* Get private key as an i15 integer. This also checks that the
|
||||
* private key is well-defined (not zero, and less than the
|
||||
* curve order).
|
||||
*/
|
||||
if (!br_i15_decode_mod(x, sk->x, sk->xlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (br_i15_iszero(x)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get hash length.
|
||||
*/
|
||||
hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
|
||||
|
||||
/*
|
||||
* Truncate and reduce the hash value modulo the curve order.
|
||||
*/
|
||||
br_ecdsa_i15_bits2int(m, hash_value, hash_len, n[0]);
|
||||
br_i15_sub(m, n, br_i15_sub(m, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* RFC 6979 generation of the "k" value.
|
||||
*
|
||||
* The process uses HMAC_DRBG (with the hash function used to
|
||||
* process the message that is to be signed). The seed is the
|
||||
* concatenation of the encodings of the private key and
|
||||
* the hash value (after truncation and modular reduction).
|
||||
*/
|
||||
br_i15_encode(tt, nlen, x);
|
||||
br_i15_encode(tt + nlen, nlen, m);
|
||||
br_hmac_drbg_init(&drbg, hf, tt, nlen << 1);
|
||||
for (;;) {
|
||||
br_hmac_drbg_generate(&drbg, tt, nlen);
|
||||
br_ecdsa_i15_bits2int(k, tt, nlen, n[0]);
|
||||
if (br_i15_iszero(k)) {
|
||||
continue;
|
||||
}
|
||||
if (br_i15_sub(k, n, 0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute k*G and extract the X coordinate, then reduce it
|
||||
* modulo the curve order. Since we support only curves with
|
||||
* prime order, that reduction is only a matter of computing
|
||||
* a subtraction.
|
||||
*/
|
||||
br_i15_encode(tt, nlen, k);
|
||||
ulen = impl->mulgen(eU, tt, nlen, sk->curve);
|
||||
br_i15_zero(r, n[0]);
|
||||
br_i15_decode(r, &eU[1], ulen >> 1);
|
||||
r[0] = n[0];
|
||||
br_i15_sub(r, n, br_i15_sub(r, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* Compute 1/k in double-Montgomery representation. We do so by
|
||||
* first converting _from_ Montgomery representation (twice),
|
||||
* then using a modular exponentiation.
|
||||
*/
|
||||
br_i15_from_monty(k, n, n0i);
|
||||
br_i15_from_monty(k, n, n0i);
|
||||
memcpy(tt, cd->order, nlen);
|
||||
tt[nlen - 1] -= 2;
|
||||
br_i15_modpow(k, tt, nlen, n, n0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Compute s = (m+xr)/k (mod n).
|
||||
* The k[] array contains R^2/k (double-Montgomery representation);
|
||||
* we thus can use direct Montgomery multiplications and conversions
|
||||
* from Montgomery, avoiding any call to br_i15_to_monty() (which
|
||||
* is slower).
|
||||
*/
|
||||
br_i15_from_monty(m, n, n0i);
|
||||
br_i15_montymul(t1, x, r, n, n0i);
|
||||
ctl = br_i15_add(t1, m, 1);
|
||||
ctl |= br_i15_sub(t1, n, 0) ^ 1;
|
||||
br_i15_sub(t1, n, ctl);
|
||||
br_i15_montymul(s, t1, k, n, n0i);
|
||||
|
||||
/*
|
||||
* Encode r and s in the signature.
|
||||
*/
|
||||
br_i15_encode(sig, nlen, r);
|
||||
br_i15_encode((unsigned char *)sig + nlen, nlen, s);
|
||||
return nlen << 1;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
uint32_t
|
||||
br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk,
|
||||
const void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* We use a double-sized buffer because a malformed ASN.1 signature
|
||||
* may trigger a size expansion when converting to "raw" format.
|
||||
*/
|
||||
unsigned char rsig[(FIELD_LEN << 2) + 24];
|
||||
|
||||
if (sig_len > ((sizeof rsig) >> 1)) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(rsig, sig, sig_len);
|
||||
sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len);
|
||||
return br_ecdsa_i15_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len);
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
|
||||
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
uint32_t
|
||||
br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk,
|
||||
const void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* IMPORTANT: this code is fit only for curves with a prime
|
||||
* order. This is needed so that modular reduction of the X
|
||||
* coordinate of a point can be done with a simple subtraction.
|
||||
*/
|
||||
const br_ec_curve_def *cd;
|
||||
uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], t1[I15_LEN], t2[I15_LEN];
|
||||
unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
unsigned char eU[POINT_LEN];
|
||||
size_t nlen, rlen, ulen;
|
||||
uint16_t n0i;
|
||||
uint32_t res;
|
||||
|
||||
/*
|
||||
* If the curve is not supported, then report an error.
|
||||
*/
|
||||
if (((impl->supported_curves >> pk->curve) & 1) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the curve parameters (generator and order).
|
||||
*/
|
||||
switch (pk->curve) {
|
||||
case BR_EC_secp256r1:
|
||||
cd = &br_secp256r1;
|
||||
break;
|
||||
case BR_EC_secp384r1:
|
||||
cd = &br_secp384r1;
|
||||
break;
|
||||
case BR_EC_secp521r1:
|
||||
cd = &br_secp521r1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Signature length must be even.
|
||||
*/
|
||||
if (sig_len & 1) {
|
||||
return 0;
|
||||
}
|
||||
rlen = sig_len >> 1;
|
||||
|
||||
/*
|
||||
* Public key point must have the proper size for this curve.
|
||||
*/
|
||||
if (pk->qlen != cd->generator_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get modulus; then decode the r and s values. They must be
|
||||
* lower than the modulus, and s must not be null.
|
||||
*/
|
||||
nlen = cd->order_len;
|
||||
br_i15_decode(n, cd->order, nlen);
|
||||
n0i = br_i15_ninv15(n[1]);
|
||||
if (!br_i15_decode_mod(r, sig, rlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (!br_i15_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (br_i15_iszero(s)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert s. We do that with a modular exponentiation; we use
|
||||
* the fact that for all the curves we support, the least
|
||||
* significant byte is not 0 or 1, so we can subtract 2 without
|
||||
* any carry to process.
|
||||
* We also want 1/s in Montgomery representation, which can be
|
||||
* done by converting _from_ Montgomery representation before
|
||||
* the inversion (because (1/s)*R = 1/(s/R)).
|
||||
*/
|
||||
br_i15_from_monty(s, n, n0i);
|
||||
memcpy(tx, cd->order, nlen);
|
||||
tx[nlen - 1] -= 2;
|
||||
br_i15_modpow(s, tx, nlen, n, n0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Truncate the hash to the modulus length (in bits) and reduce
|
||||
* it modulo the curve order. The modular reduction can be done
|
||||
* with a subtraction since the truncation already reduced the
|
||||
* value to the modulus bit length.
|
||||
*/
|
||||
br_ecdsa_i15_bits2int(t1, hash, hash_len, n[0]);
|
||||
br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* Multiply the (truncated, reduced) hash value with 1/s, result in
|
||||
* t2, encoded in ty.
|
||||
*/
|
||||
br_i15_montymul(t2, t1, s, n, n0i);
|
||||
br_i15_encode(ty, nlen, t2);
|
||||
|
||||
/*
|
||||
* Multiply r with 1/s, result in t1, encoded in tx.
|
||||
*/
|
||||
br_i15_montymul(t1, r, s, n, n0i);
|
||||
br_i15_encode(tx, nlen, t1);
|
||||
|
||||
/*
|
||||
* Compute the point x*Q + y*G.
|
||||
*/
|
||||
ulen = cd->generator_len;
|
||||
memcpy(eU, pk->q, ulen);
|
||||
res = impl->muladd(eU, NULL, ulen,
|
||||
tx, nlen, ty, nlen, cd->curve);
|
||||
|
||||
/*
|
||||
* Get the X coordinate, reduce modulo the curve order, and
|
||||
* compare with the 'r' value.
|
||||
*
|
||||
* The modular reduction can be done with subtractions because
|
||||
* we work with curves of prime order, so the curve order is
|
||||
* close to the field order (Hasse's theorem).
|
||||
*/
|
||||
br_i15_zero(t1, n[0]);
|
||||
br_i15_decode(t1, &eU[1], ulen >> 1);
|
||||
t1[0] = n[0];
|
||||
br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1);
|
||||
res &= ~br_i15_sub(t1, r, 1);
|
||||
res &= br_i15_iszero(t1);
|
||||
return res;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_ecdsa_i31_bits2int(uint32_t *x,
|
||||
const void *src, size_t len, uint32_t ebitlen)
|
||||
{
|
||||
uint32_t bitlen, hbitlen;
|
||||
int sc;
|
||||
|
||||
bitlen = ebitlen - (ebitlen >> 5);
|
||||
hbitlen = (uint32_t)len << 3;
|
||||
if (hbitlen > bitlen) {
|
||||
len = (bitlen + 7) >> 3;
|
||||
sc = (int)((hbitlen - bitlen) & 7);
|
||||
} else {
|
||||
sc = 0;
|
||||
}
|
||||
br_i31_zero(x, ebitlen);
|
||||
br_i31_decode(x, src, len);
|
||||
br_i31_rshift(x, sc);
|
||||
x[0] = ebitlen;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_i31_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig)
|
||||
{
|
||||
unsigned char rsig[(ORDER_LEN << 1) + 12];
|
||||
size_t sig_len;
|
||||
|
||||
sig_len = br_ecdsa_i31_sign_raw(impl, hf, hash_value, sk, rsig);
|
||||
if (sig_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len);
|
||||
memcpy(sig, rsig, sig_len);
|
||||
return sig_len;
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
|
||||
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
|
||||
#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_i31_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig)
|
||||
{
|
||||
/*
|
||||
* IMPORTANT: this code is fit only for curves with a prime
|
||||
* order. This is needed so that modular reduction of the X
|
||||
* coordinate of a point can be done with a simple subtraction.
|
||||
* We also rely on the last byte of the curve order to be distinct
|
||||
* from 0 and 1.
|
||||
*/
|
||||
const br_ec_curve_def *cd;
|
||||
uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], x[I31_LEN];
|
||||
uint32_t m[I31_LEN], k[I31_LEN], t1[I31_LEN], t2[I31_LEN];
|
||||
unsigned char tt[ORDER_LEN << 1];
|
||||
unsigned char eU[POINT_LEN];
|
||||
size_t hash_len, nlen, ulen;
|
||||
uint32_t n0i, ctl;
|
||||
br_hmac_drbg_context drbg;
|
||||
|
||||
/*
|
||||
* If the curve is not supported, then exit with an error.
|
||||
*/
|
||||
if (((impl->supported_curves >> sk->curve) & 1) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the curve parameters (generator and order).
|
||||
*/
|
||||
switch (sk->curve) {
|
||||
case BR_EC_secp256r1:
|
||||
cd = &br_secp256r1;
|
||||
break;
|
||||
case BR_EC_secp384r1:
|
||||
cd = &br_secp384r1;
|
||||
break;
|
||||
case BR_EC_secp521r1:
|
||||
cd = &br_secp521r1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get modulus.
|
||||
*/
|
||||
nlen = cd->order_len;
|
||||
br_i31_decode(n, cd->order, nlen);
|
||||
n0i = br_i31_ninv31(n[1]);
|
||||
|
||||
/*
|
||||
* Get private key as an i31 integer. This also checks that the
|
||||
* private key is well-defined (not zero, and less than the
|
||||
* curve order).
|
||||
*/
|
||||
if (!br_i31_decode_mod(x, sk->x, sk->xlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (br_i31_iszero(x)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get hash length.
|
||||
*/
|
||||
hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
|
||||
|
||||
/*
|
||||
* Truncate and reduce the hash value modulo the curve order.
|
||||
*/
|
||||
br_ecdsa_i31_bits2int(m, hash_value, hash_len, n[0]);
|
||||
br_i31_sub(m, n, br_i31_sub(m, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* RFC 6979 generation of the "k" value.
|
||||
*
|
||||
* The process uses HMAC_DRBG (with the hash function used to
|
||||
* process the message that is to be signed). The seed is the
|
||||
* concatenation of the encodings of the private key and
|
||||
* the hash value (after truncation and modular reduction).
|
||||
*/
|
||||
br_i31_encode(tt, nlen, x);
|
||||
br_i31_encode(tt + nlen, nlen, m);
|
||||
br_hmac_drbg_init(&drbg, hf, tt, nlen << 1);
|
||||
for (;;) {
|
||||
br_hmac_drbg_generate(&drbg, tt, nlen);
|
||||
br_ecdsa_i31_bits2int(k, tt, nlen, n[0]);
|
||||
if (br_i31_iszero(k)) {
|
||||
continue;
|
||||
}
|
||||
if (br_i31_sub(k, n, 0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute k*G and extract the X coordinate, then reduce it
|
||||
* modulo the curve order. Since we support only curves with
|
||||
* prime order, that reduction is only a matter of computing
|
||||
* a subtraction.
|
||||
*/
|
||||
br_i31_encode(tt, nlen, k);
|
||||
ulen = impl->mulgen(eU, tt, nlen, sk->curve);
|
||||
br_i31_zero(r, n[0]);
|
||||
br_i31_decode(r, &eU[1], ulen >> 1);
|
||||
r[0] = n[0];
|
||||
br_i31_sub(r, n, br_i31_sub(r, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* Compute 1/k in double-Montgomery representation. We do so by
|
||||
* first converting _from_ Montgomery representation (twice),
|
||||
* then using a modular exponentiation.
|
||||
*/
|
||||
br_i31_from_monty(k, n, n0i);
|
||||
br_i31_from_monty(k, n, n0i);
|
||||
memcpy(tt, cd->order, nlen);
|
||||
tt[nlen - 1] -= 2;
|
||||
br_i31_modpow(k, tt, nlen, n, n0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Compute s = (m+xr)/k (mod n).
|
||||
* The k[] array contains R^2/k (double-Montgomery representation);
|
||||
* we thus can use direct Montgomery multiplications and conversions
|
||||
* from Montgomery, avoiding any call to br_i31_to_monty() (which
|
||||
* is slower).
|
||||
*/
|
||||
br_i31_from_monty(m, n, n0i);
|
||||
br_i31_montymul(t1, x, r, n, n0i);
|
||||
ctl = br_i31_add(t1, m, 1);
|
||||
ctl |= br_i31_sub(t1, n, 0) ^ 1;
|
||||
br_i31_sub(t1, n, ctl);
|
||||
br_i31_montymul(s, t1, k, n, n0i);
|
||||
|
||||
/*
|
||||
* Encode r and s in the signature.
|
||||
*/
|
||||
br_i31_encode(sig, nlen, r);
|
||||
br_i31_encode((unsigned char *)sig + nlen, nlen, s);
|
||||
return nlen << 1;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
uint32_t
|
||||
br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk,
|
||||
const void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* We use a double-sized buffer because a malformed ASN.1 signature
|
||||
* may trigger a size expansion when converting to "raw" format.
|
||||
*/
|
||||
unsigned char rsig[(FIELD_LEN << 2) + 24];
|
||||
|
||||
if (sig_len > ((sizeof rsig) >> 1)) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(rsig, sig, sig_len);
|
||||
sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len);
|
||||
return br_ecdsa_i31_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len);
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
|
||||
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
uint32_t
|
||||
br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk,
|
||||
const void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* IMPORTANT: this code is fit only for curves with a prime
|
||||
* order. This is needed so that modular reduction of the X
|
||||
* coordinate of a point can be done with a simple subtraction.
|
||||
*/
|
||||
const br_ec_curve_def *cd;
|
||||
uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], t1[I31_LEN], t2[I31_LEN];
|
||||
unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
unsigned char eU[POINT_LEN];
|
||||
size_t nlen, rlen, ulen;
|
||||
uint32_t n0i, res;
|
||||
|
||||
/*
|
||||
* If the curve is not supported, then report an error.
|
||||
*/
|
||||
if (((impl->supported_curves >> pk->curve) & 1) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the curve parameters (generator and order).
|
||||
*/
|
||||
switch (pk->curve) {
|
||||
case BR_EC_secp256r1:
|
||||
cd = &br_secp256r1;
|
||||
break;
|
||||
case BR_EC_secp384r1:
|
||||
cd = &br_secp384r1;
|
||||
break;
|
||||
case BR_EC_secp521r1:
|
||||
cd = &br_secp521r1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Signature length must be even.
|
||||
*/
|
||||
if (sig_len & 1) {
|
||||
return 0;
|
||||
}
|
||||
rlen = sig_len >> 1;
|
||||
|
||||
/*
|
||||
* Public key point must have the proper size for this curve.
|
||||
*/
|
||||
if (pk->qlen != cd->generator_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get modulus; then decode the r and s values. They must be
|
||||
* lower than the modulus, and s must not be null.
|
||||
*/
|
||||
nlen = cd->order_len;
|
||||
br_i31_decode(n, cd->order, nlen);
|
||||
n0i = br_i31_ninv31(n[1]);
|
||||
if (!br_i31_decode_mod(r, sig, rlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (!br_i31_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (br_i31_iszero(s)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert s. We do that with a modular exponentiation; we use
|
||||
* the fact that for all the curves we support, the least
|
||||
* significant byte is not 0 or 1, so we can subtract 2 without
|
||||
* any carry to process.
|
||||
* We also want 1/s in Montgomery representation, which can be
|
||||
* done by converting _from_ Montgomery representation before
|
||||
* the inversion (because (1/s)*R = 1/(s/R)).
|
||||
*/
|
||||
br_i31_from_monty(s, n, n0i);
|
||||
memcpy(tx, cd->order, nlen);
|
||||
tx[nlen - 1] -= 2;
|
||||
br_i31_modpow(s, tx, nlen, n, n0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Truncate the hash to the modulus length (in bits) and reduce
|
||||
* it modulo the curve order. The modular reduction can be done
|
||||
* with a subtraction since the truncation already reduced the
|
||||
* value to the modulus bit length.
|
||||
*/
|
||||
br_ecdsa_i31_bits2int(t1, hash, hash_len, n[0]);
|
||||
br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* Multiply the (truncated, reduced) hash value with 1/s, result in
|
||||
* t2, encoded in ty.
|
||||
*/
|
||||
br_i31_montymul(t2, t1, s, n, n0i);
|
||||
br_i31_encode(ty, nlen, t2);
|
||||
|
||||
/*
|
||||
* Multiply r with 1/s, result in t1, encoded in tx.
|
||||
*/
|
||||
br_i31_montymul(t1, r, s, n, n0i);
|
||||
br_i31_encode(tx, nlen, t1);
|
||||
|
||||
/*
|
||||
* Compute the point x*Q + y*G.
|
||||
*/
|
||||
ulen = cd->generator_len;
|
||||
memcpy(eU, pk->q, ulen);
|
||||
res = impl->muladd(eU, NULL, ulen,
|
||||
tx, nlen, ty, nlen, cd->curve);
|
||||
|
||||
/*
|
||||
* Get the X coordinate, reduce modulo the curve order, and
|
||||
* compare with the 'r' value.
|
||||
*
|
||||
* The modular reduction can be done with subtractions because
|
||||
* we work with curves of prime order, so the curve order is
|
||||
* close to the field order (Hasse's theorem).
|
||||
*/
|
||||
br_i31_zero(t1, n[0]);
|
||||
br_i31_decode(t1, &eU[1], ulen >> 1);
|
||||
t1[0] = n[0];
|
||||
br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);
|
||||
res &= ~br_i31_sub(t1, r, 1);
|
||||
res &= br_i31_iszero(t1);
|
||||
return res;
|
||||
}
|
||||
121
dstalk-core/thirdparty/bearssl/src/ec/ecdsa_rta.c
vendored
121
dstalk-core/thirdparty/bearssl/src/ec/ecdsa_rta.c
vendored
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Compute ASN.1 encoded length for the provided integer. The ASN.1
|
||||
* encoding is signed, so its leading bit must have value 0; it must
|
||||
* also be of minimal length (so leading bytes of value 0 must be
|
||||
* removed, except if that would contradict the rule about the sign
|
||||
* bit).
|
||||
*/
|
||||
static size_t
|
||||
asn1_int_length(const unsigned char *x, size_t xlen)
|
||||
{
|
||||
while (xlen > 0 && *x == 0) {
|
||||
x ++;
|
||||
xlen --;
|
||||
}
|
||||
if (xlen == 0 || *x >= 0x80) {
|
||||
xlen ++;
|
||||
}
|
||||
return xlen;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_raw_to_asn1(void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* Internal buffer is large enough to accommodate a signature
|
||||
* such that r and s fit on 125 bytes each (signed encoding),
|
||||
* meaning a curve order of up to 999 bits. This is the limit
|
||||
* that ensures "simple" length encodings.
|
||||
*/
|
||||
unsigned char *buf;
|
||||
size_t hlen, rlen, slen, zlen, off;
|
||||
unsigned char tmp[257];
|
||||
|
||||
buf = sig;
|
||||
if ((sig_len & 1) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute lengths for the two integers.
|
||||
*/
|
||||
hlen = sig_len >> 1;
|
||||
rlen = asn1_int_length(buf, hlen);
|
||||
slen = asn1_int_length(buf + hlen, hlen);
|
||||
if (rlen > 125 || slen > 125) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SEQUENCE header.
|
||||
*/
|
||||
tmp[0] = 0x30;
|
||||
zlen = rlen + slen + 4;
|
||||
if (zlen >= 0x80) {
|
||||
tmp[1] = 0x81;
|
||||
tmp[2] = zlen;
|
||||
off = 3;
|
||||
} else {
|
||||
tmp[1] = zlen;
|
||||
off = 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* First INTEGER (r).
|
||||
*/
|
||||
tmp[off ++] = 0x02;
|
||||
tmp[off ++] = rlen;
|
||||
if (rlen > hlen) {
|
||||
tmp[off] = 0x00;
|
||||
memcpy(tmp + off + 1, buf, hlen);
|
||||
} else {
|
||||
memcpy(tmp + off, buf + hlen - rlen, rlen);
|
||||
}
|
||||
off += rlen;
|
||||
|
||||
/*
|
||||
* Second INTEGER (s).
|
||||
*/
|
||||
tmp[off ++] = 0x02;
|
||||
tmp[off ++] = slen;
|
||||
if (slen > hlen) {
|
||||
tmp[off] = 0x00;
|
||||
memcpy(tmp + off + 1, buf + hlen, hlen);
|
||||
} else {
|
||||
memcpy(tmp + off, buf + sig_len - slen, slen);
|
||||
}
|
||||
off += slen;
|
||||
|
||||
/*
|
||||
* Return ASN.1 signature.
|
||||
*/
|
||||
memcpy(sig, tmp, off);
|
||||
return off;
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* This file contains the encoded OID for the standard hash functions.
|
||||
* Such OID appear in, for instance, the PKCS#1 v1.5 padding for RSA
|
||||
* signatures.
|
||||
*/
|
||||
|
||||
static const unsigned char md5_OID[] = {
|
||||
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05
|
||||
};
|
||||
|
||||
static const unsigned char sha1_OID[] = {
|
||||
0x2B, 0x0E, 0x03, 0x02, 0x1A
|
||||
};
|
||||
|
||||
static const unsigned char sha224_OID[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
|
||||
};
|
||||
|
||||
static const unsigned char sha256_OID[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
|
||||
};
|
||||
|
||||
static const unsigned char sha384_OID[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
|
||||
};
|
||||
|
||||
static const unsigned char sha512_OID[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const unsigned char *
|
||||
br_digest_OID(int digest_id, size_t *len)
|
||||
{
|
||||
switch (digest_id) {
|
||||
case br_md5_ID:
|
||||
*len = sizeof md5_OID;
|
||||
return md5_OID;
|
||||
case br_sha1_ID:
|
||||
*len = sizeof sha1_OID;
|
||||
return sha1_OID;
|
||||
case br_sha224_ID:
|
||||
*len = sizeof sha224_OID;
|
||||
return sha224_OID;
|
||||
case br_sha256_ID:
|
||||
*len = sizeof sha256_OID;
|
||||
return sha256_OID;
|
||||
case br_sha384_ID:
|
||||
*len = sizeof sha384_OID;
|
||||
return sha384_OID;
|
||||
case br_sha512_ID:
|
||||
*len = sizeof sha512_OID;
|
||||
return sha512_OID;
|
||||
default:
|
||||
*len = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
size_t
|
||||
br_digest_size_by_ID(int digest_id)
|
||||
{
|
||||
switch (digest_id) {
|
||||
case br_md5sha1_ID:
|
||||
return br_md5_SIZE + br_sha1_SIZE;
|
||||
case br_md5_ID:
|
||||
return br_md5_SIZE;
|
||||
case br_sha1_ID:
|
||||
return br_sha1_SIZE;
|
||||
case br_sha224_ID:
|
||||
return br_sha224_SIZE;
|
||||
case br_sha256_ID:
|
||||
return br_sha256_SIZE;
|
||||
case br_sha384_ID:
|
||||
return br_sha384_SIZE;
|
||||
case br_sha512_ID:
|
||||
return br_sha512_SIZE;
|
||||
default:
|
||||
/* abort(); */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,345 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* We compute "carryless multiplications" through normal integer
|
||||
* multiplications, masking out enough bits to create "holes" in which
|
||||
* carries may expand without altering our bits; we really use 8 data
|
||||
* bits per 32-bit word, spaced every fourth bit. Accumulated carries
|
||||
* may not exceed 8 in total, which fits in 4 bits.
|
||||
*
|
||||
* It would be possible to use a 3-bit spacing, allowing two operands,
|
||||
* one with 7 non-zero data bits, the other one with 10 or 11 non-zero
|
||||
* data bits; this asymmetric splitting makes the overall code more
|
||||
* complex with thresholds and exceptions, and does not appear to be
|
||||
* worth the effort.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We cannot really autodetect whether multiplications are "slow" or
|
||||
* not. A typical example is the ARM Cortex M0+, which exists in two
|
||||
* versions: one with a 1-cycle multiplication opcode, the other with
|
||||
* a 32-cycle multiplication opcode. They both use exactly the same
|
||||
* architecture and ABI, and cannot be distinguished from each other
|
||||
* at compile-time.
|
||||
*
|
||||
* Since most modern CPU (even embedded CPU) still have fast
|
||||
* multiplications, we use the "fast mul" code by default.
|
||||
*/
|
||||
|
||||
#if BR_SLOW_MUL
|
||||
|
||||
/*
|
||||
* This implementation uses Karatsuba-like reduction to make fewer
|
||||
* integer multiplications (9 instead of 16), at the expense of extra
|
||||
* logical operations (XOR, shifts...). On modern x86 CPU that offer
|
||||
* fast, pipelined multiplications, this code is about twice slower than
|
||||
* the simpler code with 16 multiplications. This tendency may be
|
||||
* reversed on low-end platforms with expensive multiplications.
|
||||
*/
|
||||
|
||||
#define MUL32(h, l, x, y) do { \
|
||||
uint64_t mul32tmp = MUL(x, y); \
|
||||
(h) = (uint32_t)(mul32tmp >> 32); \
|
||||
(l) = (uint32_t)mul32tmp; \
|
||||
} while (0)
|
||||
|
||||
static inline void
|
||||
bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3;
|
||||
uint32_t y0, y1, y2, y3;
|
||||
uint32_t a0, a1, a2, a3, a4, a5, a6, a7, a8;
|
||||
uint32_t b0, b1, b2, b3, b4, b5, b6, b7, b8;
|
||||
|
||||
x0 = x & (uint32_t)0x11111111;
|
||||
x1 = x & (uint32_t)0x22222222;
|
||||
x2 = x & (uint32_t)0x44444444;
|
||||
x3 = x & (uint32_t)0x88888888;
|
||||
y0 = y & (uint32_t)0x11111111;
|
||||
y1 = y & (uint32_t)0x22222222;
|
||||
y2 = y & (uint32_t)0x44444444;
|
||||
y3 = y & (uint32_t)0x88888888;
|
||||
|
||||
/*
|
||||
* (x0+W*x1)*(y0+W*y1) -> a0:b0
|
||||
* (x2+W*x3)*(y2+W*y3) -> a3:b3
|
||||
* ((x0+x2)+W*(x1+x3))*((y0+y2)+W*(y1+y3)) -> a6:b6
|
||||
*/
|
||||
a0 = x0;
|
||||
b0 = y0;
|
||||
a1 = x1 >> 1;
|
||||
b1 = y1 >> 1;
|
||||
a2 = a0 ^ a1;
|
||||
b2 = b0 ^ b1;
|
||||
a3 = x2 >> 2;
|
||||
b3 = y2 >> 2;
|
||||
a4 = x3 >> 3;
|
||||
b4 = y3 >> 3;
|
||||
a5 = a3 ^ a4;
|
||||
b5 = b3 ^ b4;
|
||||
a6 = a0 ^ a3;
|
||||
b6 = b0 ^ b3;
|
||||
a7 = a1 ^ a4;
|
||||
b7 = b1 ^ b4;
|
||||
a8 = a6 ^ a7;
|
||||
b8 = b6 ^ b7;
|
||||
|
||||
MUL32(b0, a0, b0, a0);
|
||||
MUL32(b1, a1, b1, a1);
|
||||
MUL32(b2, a2, b2, a2);
|
||||
MUL32(b3, a3, b3, a3);
|
||||
MUL32(b4, a4, b4, a4);
|
||||
MUL32(b5, a5, b5, a5);
|
||||
MUL32(b6, a6, b6, a6);
|
||||
MUL32(b7, a7, b7, a7);
|
||||
MUL32(b8, a8, b8, a8);
|
||||
|
||||
a0 &= (uint32_t)0x11111111;
|
||||
a1 &= (uint32_t)0x11111111;
|
||||
a2 &= (uint32_t)0x11111111;
|
||||
a3 &= (uint32_t)0x11111111;
|
||||
a4 &= (uint32_t)0x11111111;
|
||||
a5 &= (uint32_t)0x11111111;
|
||||
a6 &= (uint32_t)0x11111111;
|
||||
a7 &= (uint32_t)0x11111111;
|
||||
a8 &= (uint32_t)0x11111111;
|
||||
b0 &= (uint32_t)0x11111111;
|
||||
b1 &= (uint32_t)0x11111111;
|
||||
b2 &= (uint32_t)0x11111111;
|
||||
b3 &= (uint32_t)0x11111111;
|
||||
b4 &= (uint32_t)0x11111111;
|
||||
b5 &= (uint32_t)0x11111111;
|
||||
b6 &= (uint32_t)0x11111111;
|
||||
b7 &= (uint32_t)0x11111111;
|
||||
b8 &= (uint32_t)0x11111111;
|
||||
|
||||
a2 ^= a0 ^ a1;
|
||||
b2 ^= b0 ^ b1;
|
||||
a0 ^= (a2 << 1) ^ (a1 << 2);
|
||||
b0 ^= (b2 << 1) ^ (b1 << 2);
|
||||
a5 ^= a3 ^ a4;
|
||||
b5 ^= b3 ^ b4;
|
||||
a3 ^= (a5 << 1) ^ (a4 << 2);
|
||||
b3 ^= (b5 << 1) ^ (b4 << 2);
|
||||
a8 ^= a6 ^ a7;
|
||||
b8 ^= b6 ^ b7;
|
||||
a6 ^= (a8 << 1) ^ (a7 << 2);
|
||||
b6 ^= (b8 << 1) ^ (b7 << 2);
|
||||
a6 ^= a0 ^ a3;
|
||||
b6 ^= b0 ^ b3;
|
||||
*lo = a0 ^ (a6 << 2) ^ (a3 << 4);
|
||||
*hi = b0 ^ (b6 << 2) ^ (b3 << 4) ^ (a6 >> 30) ^ (a3 >> 28);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Simple multiplication in GF(2)[X], using 16 integer multiplications.
|
||||
*/
|
||||
|
||||
static inline void
|
||||
bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3;
|
||||
uint32_t y0, y1, y2, y3;
|
||||
uint64_t z0, z1, z2, z3;
|
||||
uint64_t z;
|
||||
|
||||
x0 = x & (uint32_t)0x11111111;
|
||||
x1 = x & (uint32_t)0x22222222;
|
||||
x2 = x & (uint32_t)0x44444444;
|
||||
x3 = x & (uint32_t)0x88888888;
|
||||
y0 = y & (uint32_t)0x11111111;
|
||||
y1 = y & (uint32_t)0x22222222;
|
||||
y2 = y & (uint32_t)0x44444444;
|
||||
y3 = y & (uint32_t)0x88888888;
|
||||
z0 = MUL(x0, y0) ^ MUL(x1, y3) ^ MUL(x2, y2) ^ MUL(x3, y1);
|
||||
z1 = MUL(x0, y1) ^ MUL(x1, y0) ^ MUL(x2, y3) ^ MUL(x3, y2);
|
||||
z2 = MUL(x0, y2) ^ MUL(x1, y1) ^ MUL(x2, y0) ^ MUL(x3, y3);
|
||||
z3 = MUL(x0, y3) ^ MUL(x1, y2) ^ MUL(x2, y1) ^ MUL(x3, y0);
|
||||
z0 &= (uint64_t)0x1111111111111111;
|
||||
z1 &= (uint64_t)0x2222222222222222;
|
||||
z2 &= (uint64_t)0x4444444444444444;
|
||||
z3 &= (uint64_t)0x8888888888888888;
|
||||
z = z0 | z1 | z2 | z3;
|
||||
*lo = (uint32_t)z;
|
||||
*hi = (uint32_t)(z >> 32);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_ghash_ctmul(void *y, const void *h, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf, *hb;
|
||||
unsigned char *yb;
|
||||
uint32_t yw[4];
|
||||
uint32_t hw[4];
|
||||
|
||||
/*
|
||||
* Throughout the loop we handle the y and h values as arrays
|
||||
* of 32-bit words.
|
||||
*/
|
||||
buf = data;
|
||||
yb = y;
|
||||
hb = h;
|
||||
yw[3] = br_dec32be(yb);
|
||||
yw[2] = br_dec32be(yb + 4);
|
||||
yw[1] = br_dec32be(yb + 8);
|
||||
yw[0] = br_dec32be(yb + 12);
|
||||
hw[3] = br_dec32be(hb);
|
||||
hw[2] = br_dec32be(hb + 4);
|
||||
hw[1] = br_dec32be(hb + 8);
|
||||
hw[0] = br_dec32be(hb + 12);
|
||||
while (len > 0) {
|
||||
const unsigned char *src;
|
||||
unsigned char tmp[16];
|
||||
int i;
|
||||
uint32_t a[9], b[9], zw[8];
|
||||
uint32_t c0, c1, c2, c3, d0, d1, d2, d3, e0, e1, e2, e3;
|
||||
|
||||
/*
|
||||
* Get the next 16-byte block (using zero-padding if
|
||||
* necessary).
|
||||
*/
|
||||
if (len >= 16) {
|
||||
src = buf;
|
||||
buf += 16;
|
||||
len -= 16;
|
||||
} else {
|
||||
memcpy(tmp, buf, len);
|
||||
memset(tmp + len, 0, (sizeof tmp) - len);
|
||||
src = tmp;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the block. The GHASH standard mandates
|
||||
* big-endian encoding.
|
||||
*/
|
||||
yw[3] ^= br_dec32be(src);
|
||||
yw[2] ^= br_dec32be(src + 4);
|
||||
yw[1] ^= br_dec32be(src + 8);
|
||||
yw[0] ^= br_dec32be(src + 12);
|
||||
|
||||
/*
|
||||
* We multiply two 128-bit field elements. We use
|
||||
* Karatsuba to turn that into three 64-bit
|
||||
* multiplications, which are themselves done with a
|
||||
* total of nine 32-bit multiplications.
|
||||
*/
|
||||
|
||||
/*
|
||||
* y[0,1]*h[0,1] -> 0..2
|
||||
* y[2,3]*h[2,3] -> 3..5
|
||||
* (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6..8
|
||||
*/
|
||||
a[0] = yw[0];
|
||||
b[0] = hw[0];
|
||||
a[1] = yw[1];
|
||||
b[1] = hw[1];
|
||||
a[2] = a[0] ^ a[1];
|
||||
b[2] = b[0] ^ b[1];
|
||||
|
||||
a[3] = yw[2];
|
||||
b[3] = hw[2];
|
||||
a[4] = yw[3];
|
||||
b[4] = hw[3];
|
||||
a[5] = a[3] ^ a[4];
|
||||
b[5] = b[3] ^ b[4];
|
||||
|
||||
a[6] = a[0] ^ a[3];
|
||||
b[6] = b[0] ^ b[3];
|
||||
a[7] = a[1] ^ a[4];
|
||||
b[7] = b[1] ^ b[4];
|
||||
a[8] = a[6] ^ a[7];
|
||||
b[8] = b[6] ^ b[7];
|
||||
|
||||
for (i = 0; i < 9; i ++) {
|
||||
bmul(&b[i], &a[i], b[i], a[i]);
|
||||
}
|
||||
|
||||
c0 = a[0];
|
||||
c1 = b[0] ^ a[2] ^ a[0] ^ a[1];
|
||||
c2 = a[1] ^ b[2] ^ b[0] ^ b[1];
|
||||
c3 = b[1];
|
||||
d0 = a[3];
|
||||
d1 = b[3] ^ a[5] ^ a[3] ^ a[4];
|
||||
d2 = a[4] ^ b[5] ^ b[3] ^ b[4];
|
||||
d3 = b[4];
|
||||
e0 = a[6];
|
||||
e1 = b[6] ^ a[8] ^ a[6] ^ a[7];
|
||||
e2 = a[7] ^ b[8] ^ b[6] ^ b[7];
|
||||
e3 = b[7];
|
||||
|
||||
e0 ^= c0 ^ d0;
|
||||
e1 ^= c1 ^ d1;
|
||||
e2 ^= c2 ^ d2;
|
||||
e3 ^= c3 ^ d3;
|
||||
c2 ^= e0;
|
||||
c3 ^= e1;
|
||||
d0 ^= e2;
|
||||
d1 ^= e3;
|
||||
|
||||
/*
|
||||
* GHASH specification has the bits "reversed" (most
|
||||
* significant is in fact least significant), which does
|
||||
* not matter for a carryless multiplication, except that
|
||||
* the 255-bit result must be shifted by 1 bit.
|
||||
*/
|
||||
zw[0] = c0 << 1;
|
||||
zw[1] = (c1 << 1) | (c0 >> 31);
|
||||
zw[2] = (c2 << 1) | (c1 >> 31);
|
||||
zw[3] = (c3 << 1) | (c2 >> 31);
|
||||
zw[4] = (d0 << 1) | (c3 >> 31);
|
||||
zw[5] = (d1 << 1) | (d0 >> 31);
|
||||
zw[6] = (d2 << 1) | (d1 >> 31);
|
||||
zw[7] = (d3 << 1) | (d2 >> 31);
|
||||
|
||||
/*
|
||||
* We now do the reduction modulo the field polynomial
|
||||
* to get back to 128 bits.
|
||||
*/
|
||||
for (i = 0; i < 4; i ++) {
|
||||
uint32_t lw;
|
||||
|
||||
lw = zw[i];
|
||||
zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7);
|
||||
zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25);
|
||||
}
|
||||
memcpy(yw, zw + 4, sizeof yw);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode back the result.
|
||||
*/
|
||||
br_enc32be(yb, yw[3]);
|
||||
br_enc32be(yb + 4, yw[2]);
|
||||
br_enc32be(yb + 8, yw[1]);
|
||||
br_enc32be(yb + 12, yw[0]);
|
||||
}
|
||||
@@ -1,251 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* This implementation uses 32-bit multiplications, and only the low
|
||||
* 32 bits for each multiplication result. This is meant primarily for
|
||||
* the ARM Cortex M0 and M0+, whose multiplication opcode does not yield
|
||||
* the upper 32 bits; but it might also be useful on architectures where
|
||||
* access to the upper 32 bits requires use of specific registers that
|
||||
* create contention (e.g. on i386, "mul" necessarily outputs the result
|
||||
* in edx:eax, while "imul" can use any registers but is limited to the
|
||||
* low 32 bits).
|
||||
*
|
||||
* The implementation trick that is used here is bit-reversing (bit 0
|
||||
* is swapped with bit 31, bit 1 with bit 30, and so on). In GF(2)[X],
|
||||
* for all values x and y, we have:
|
||||
* rev32(x) * rev32(y) = rev64(x * y)
|
||||
* In other words, if we bit-reverse (over 32 bits) the operands, then we
|
||||
* bit-reverse (over 64 bits) the result.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Multiplication in GF(2)[X], truncated to its low 32 bits.
|
||||
*/
|
||||
static inline uint32_t
|
||||
bmul32(uint32_t x, uint32_t y)
|
||||
{
|
||||
uint32_t x0, x1, x2, x3;
|
||||
uint32_t y0, y1, y2, y3;
|
||||
uint32_t z0, z1, z2, z3;
|
||||
|
||||
x0 = x & (uint32_t)0x11111111;
|
||||
x1 = x & (uint32_t)0x22222222;
|
||||
x2 = x & (uint32_t)0x44444444;
|
||||
x3 = x & (uint32_t)0x88888888;
|
||||
y0 = y & (uint32_t)0x11111111;
|
||||
y1 = y & (uint32_t)0x22222222;
|
||||
y2 = y & (uint32_t)0x44444444;
|
||||
y3 = y & (uint32_t)0x88888888;
|
||||
z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1);
|
||||
z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2);
|
||||
z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3);
|
||||
z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0);
|
||||
z0 &= (uint32_t)0x11111111;
|
||||
z1 &= (uint32_t)0x22222222;
|
||||
z2 &= (uint32_t)0x44444444;
|
||||
z3 &= (uint32_t)0x88888888;
|
||||
return z0 | z1 | z2 | z3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bit-reverse a 32-bit word.
|
||||
*/
|
||||
static uint32_t
|
||||
rev32(uint32_t x)
|
||||
{
|
||||
#define RMS(m, s) do { \
|
||||
x = ((x & (uint32_t)(m)) << (s)) \
|
||||
| ((x >> (s)) & (uint32_t)(m)); \
|
||||
} while (0)
|
||||
|
||||
RMS(0x55555555, 1);
|
||||
RMS(0x33333333, 2);
|
||||
RMS(0x0F0F0F0F, 4);
|
||||
RMS(0x00FF00FF, 8);
|
||||
return (x << 16) | (x >> 16);
|
||||
|
||||
#undef RMS
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len)
|
||||
{
|
||||
/*
|
||||
* This implementation is similar to br_ghash_ctmul() except
|
||||
* that we have to do the multiplication twice, with the
|
||||
* "normal" and "bit reversed" operands. Hence we end up with
|
||||
* eighteen 32-bit multiplications instead of nine.
|
||||
*/
|
||||
|
||||
const unsigned char *buf, *hb;
|
||||
unsigned char *yb;
|
||||
uint32_t yw[4];
|
||||
uint32_t hw[4], hwr[4];
|
||||
|
||||
buf = data;
|
||||
yb = y;
|
||||
hb = h;
|
||||
yw[3] = br_dec32be(yb);
|
||||
yw[2] = br_dec32be(yb + 4);
|
||||
yw[1] = br_dec32be(yb + 8);
|
||||
yw[0] = br_dec32be(yb + 12);
|
||||
hw[3] = br_dec32be(hb);
|
||||
hw[2] = br_dec32be(hb + 4);
|
||||
hw[1] = br_dec32be(hb + 8);
|
||||
hw[0] = br_dec32be(hb + 12);
|
||||
hwr[3] = rev32(hw[3]);
|
||||
hwr[2] = rev32(hw[2]);
|
||||
hwr[1] = rev32(hw[1]);
|
||||
hwr[0] = rev32(hw[0]);
|
||||
while (len > 0) {
|
||||
const unsigned char *src;
|
||||
unsigned char tmp[16];
|
||||
int i;
|
||||
uint32_t a[18], b[18], c[18];
|
||||
uint32_t d0, d1, d2, d3, d4, d5, d6, d7;
|
||||
uint32_t zw[8];
|
||||
|
||||
if (len >= 16) {
|
||||
src = buf;
|
||||
buf += 16;
|
||||
len -= 16;
|
||||
} else {
|
||||
memcpy(tmp, buf, len);
|
||||
memset(tmp + len, 0, (sizeof tmp) - len);
|
||||
src = tmp;
|
||||
len = 0;
|
||||
}
|
||||
yw[3] ^= br_dec32be(src);
|
||||
yw[2] ^= br_dec32be(src + 4);
|
||||
yw[1] ^= br_dec32be(src + 8);
|
||||
yw[0] ^= br_dec32be(src + 12);
|
||||
|
||||
/*
|
||||
* We are using Karatsuba: the 128x128 multiplication is
|
||||
* reduced to three 64x64 multiplications, hence nine
|
||||
* 32x32 multiplications. With the bit-reversal trick,
|
||||
* we have to perform 18 32x32 multiplications.
|
||||
*/
|
||||
|
||||
/*
|
||||
* y[0,1]*h[0,1] -> 0,1,4
|
||||
* y[2,3]*h[2,3] -> 2,3,5
|
||||
* (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,7,8
|
||||
*/
|
||||
|
||||
a[0] = yw[0];
|
||||
a[1] = yw[1];
|
||||
a[2] = yw[2];
|
||||
a[3] = yw[3];
|
||||
a[4] = a[0] ^ a[1];
|
||||
a[5] = a[2] ^ a[3];
|
||||
a[6] = a[0] ^ a[2];
|
||||
a[7] = a[1] ^ a[3];
|
||||
a[8] = a[6] ^ a[7];
|
||||
|
||||
a[ 9] = rev32(yw[0]);
|
||||
a[10] = rev32(yw[1]);
|
||||
a[11] = rev32(yw[2]);
|
||||
a[12] = rev32(yw[3]);
|
||||
a[13] = a[ 9] ^ a[10];
|
||||
a[14] = a[11] ^ a[12];
|
||||
a[15] = a[ 9] ^ a[11];
|
||||
a[16] = a[10] ^ a[12];
|
||||
a[17] = a[15] ^ a[16];
|
||||
|
||||
b[0] = hw[0];
|
||||
b[1] = hw[1];
|
||||
b[2] = hw[2];
|
||||
b[3] = hw[3];
|
||||
b[4] = b[0] ^ b[1];
|
||||
b[5] = b[2] ^ b[3];
|
||||
b[6] = b[0] ^ b[2];
|
||||
b[7] = b[1] ^ b[3];
|
||||
b[8] = b[6] ^ b[7];
|
||||
|
||||
b[ 9] = hwr[0];
|
||||
b[10] = hwr[1];
|
||||
b[11] = hwr[2];
|
||||
b[12] = hwr[3];
|
||||
b[13] = b[ 9] ^ b[10];
|
||||
b[14] = b[11] ^ b[12];
|
||||
b[15] = b[ 9] ^ b[11];
|
||||
b[16] = b[10] ^ b[12];
|
||||
b[17] = b[15] ^ b[16];
|
||||
|
||||
for (i = 0; i < 18; i ++) {
|
||||
c[i] = bmul32(a[i], b[i]);
|
||||
}
|
||||
|
||||
c[4] ^= c[0] ^ c[1];
|
||||
c[5] ^= c[2] ^ c[3];
|
||||
c[8] ^= c[6] ^ c[7];
|
||||
|
||||
c[13] ^= c[ 9] ^ c[10];
|
||||
c[14] ^= c[11] ^ c[12];
|
||||
c[17] ^= c[15] ^ c[16];
|
||||
|
||||
/*
|
||||
* y[0,1]*h[0,1] -> 0,9^4,1^13,10
|
||||
* y[2,3]*h[2,3] -> 2,11^5,3^14,12
|
||||
* (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,15^8,7^17,16
|
||||
*/
|
||||
d0 = c[0];
|
||||
d1 = c[4] ^ (rev32(c[9]) >> 1);
|
||||
d2 = c[1] ^ c[0] ^ c[2] ^ c[6] ^ (rev32(c[13]) >> 1);
|
||||
d3 = c[4] ^ c[5] ^ c[8]
|
||||
^ (rev32(c[10] ^ c[9] ^ c[11] ^ c[15]) >> 1);
|
||||
d4 = c[2] ^ c[1] ^ c[3] ^ c[7]
|
||||
^ (rev32(c[13] ^ c[14] ^ c[17]) >> 1);
|
||||
d5 = c[5] ^ (rev32(c[11] ^ c[10] ^ c[12] ^ c[16]) >> 1);
|
||||
d6 = c[3] ^ (rev32(c[14]) >> 1);
|
||||
d7 = rev32(c[12]) >> 1;
|
||||
|
||||
zw[0] = d0 << 1;
|
||||
zw[1] = (d1 << 1) | (d0 >> 31);
|
||||
zw[2] = (d2 << 1) | (d1 >> 31);
|
||||
zw[3] = (d3 << 1) | (d2 >> 31);
|
||||
zw[4] = (d4 << 1) | (d3 >> 31);
|
||||
zw[5] = (d5 << 1) | (d4 >> 31);
|
||||
zw[6] = (d6 << 1) | (d5 >> 31);
|
||||
zw[7] = (d7 << 1) | (d6 >> 31);
|
||||
|
||||
for (i = 0; i < 4; i ++) {
|
||||
uint32_t lw;
|
||||
|
||||
lw = zw[i];
|
||||
zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7);
|
||||
zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25);
|
||||
}
|
||||
memcpy(yw, zw + 4, sizeof yw);
|
||||
}
|
||||
br_enc32be(yb, yw[3]);
|
||||
br_enc32be(yb + 4, yw[2]);
|
||||
br_enc32be(yb + 8, yw[1]);
|
||||
br_enc32be(yb + 12, yw[0]);
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* This is the 64-bit variant of br_ghash_ctmul32(), with 64-bit operands
|
||||
* and bit reversal of 64-bit words.
|
||||
*/
|
||||
|
||||
static inline uint64_t
|
||||
bmul64(uint64_t x, uint64_t y)
|
||||
{
|
||||
uint64_t x0, x1, x2, x3;
|
||||
uint64_t y0, y1, y2, y3;
|
||||
uint64_t z0, z1, z2, z3;
|
||||
|
||||
x0 = x & (uint64_t)0x1111111111111111;
|
||||
x1 = x & (uint64_t)0x2222222222222222;
|
||||
x2 = x & (uint64_t)0x4444444444444444;
|
||||
x3 = x & (uint64_t)0x8888888888888888;
|
||||
y0 = y & (uint64_t)0x1111111111111111;
|
||||
y1 = y & (uint64_t)0x2222222222222222;
|
||||
y2 = y & (uint64_t)0x4444444444444444;
|
||||
y3 = y & (uint64_t)0x8888888888888888;
|
||||
z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1);
|
||||
z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2);
|
||||
z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3);
|
||||
z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0);
|
||||
z0 &= (uint64_t)0x1111111111111111;
|
||||
z1 &= (uint64_t)0x2222222222222222;
|
||||
z2 &= (uint64_t)0x4444444444444444;
|
||||
z3 &= (uint64_t)0x8888888888888888;
|
||||
return z0 | z1 | z2 | z3;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
rev64(uint64_t x)
|
||||
{
|
||||
#define RMS(m, s) do { \
|
||||
x = ((x & (uint64_t)(m)) << (s)) \
|
||||
| ((x >> (s)) & (uint64_t)(m)); \
|
||||
} while (0)
|
||||
|
||||
RMS(0x5555555555555555, 1);
|
||||
RMS(0x3333333333333333, 2);
|
||||
RMS(0x0F0F0F0F0F0F0F0F, 4);
|
||||
RMS(0x00FF00FF00FF00FF, 8);
|
||||
RMS(0x0000FFFF0000FFFF, 16);
|
||||
return (x << 32) | (x >> 32);
|
||||
|
||||
#undef RMS
|
||||
}
|
||||
|
||||
/* see bearssl_ghash.h */
|
||||
void
|
||||
br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf, *hb;
|
||||
unsigned char *yb;
|
||||
uint64_t y0, y1;
|
||||
uint64_t h0, h1, h2, h0r, h1r, h2r;
|
||||
|
||||
buf = data;
|
||||
yb = y;
|
||||
hb = h;
|
||||
y1 = br_dec64be(yb);
|
||||
y0 = br_dec64be(yb + 8);
|
||||
h1 = br_dec64be(hb);
|
||||
h0 = br_dec64be(hb + 8);
|
||||
h0r = rev64(h0);
|
||||
h1r = rev64(h1);
|
||||
h2 = h0 ^ h1;
|
||||
h2r = h0r ^ h1r;
|
||||
while (len > 0) {
|
||||
const unsigned char *src;
|
||||
unsigned char tmp[16];
|
||||
uint64_t y0r, y1r, y2, y2r;
|
||||
uint64_t z0, z1, z2, z0h, z1h, z2h;
|
||||
uint64_t v0, v1, v2, v3;
|
||||
|
||||
if (len >= 16) {
|
||||
src = buf;
|
||||
buf += 16;
|
||||
len -= 16;
|
||||
} else {
|
||||
memcpy(tmp, buf, len);
|
||||
memset(tmp + len, 0, (sizeof tmp) - len);
|
||||
src = tmp;
|
||||
len = 0;
|
||||
}
|
||||
y1 ^= br_dec64be(src);
|
||||
y0 ^= br_dec64be(src + 8);
|
||||
|
||||
y0r = rev64(y0);
|
||||
y1r = rev64(y1);
|
||||
y2 = y0 ^ y1;
|
||||
y2r = y0r ^ y1r;
|
||||
|
||||
z0 = bmul64(y0, h0);
|
||||
z1 = bmul64(y1, h1);
|
||||
z2 = bmul64(y2, h2);
|
||||
z0h = bmul64(y0r, h0r);
|
||||
z1h = bmul64(y1r, h1r);
|
||||
z2h = bmul64(y2r, h2r);
|
||||
z2 ^= z0 ^ z1;
|
||||
z2h ^= z0h ^ z1h;
|
||||
z0h = rev64(z0h) >> 1;
|
||||
z1h = rev64(z1h) >> 1;
|
||||
z2h = rev64(z2h) >> 1;
|
||||
|
||||
v0 = z0;
|
||||
v1 = z0h ^ z2;
|
||||
v2 = z1 ^ z2h;
|
||||
v3 = z1h;
|
||||
|
||||
v3 = (v3 << 1) | (v2 >> 63);
|
||||
v2 = (v2 << 1) | (v1 >> 63);
|
||||
v1 = (v1 << 1) | (v0 >> 63);
|
||||
v0 = (v0 << 1);
|
||||
|
||||
v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7);
|
||||
v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57);
|
||||
v3 ^= v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7);
|
||||
v2 ^= (v1 << 63) ^ (v1 << 62) ^ (v1 << 57);
|
||||
|
||||
y0 = v2;
|
||||
y1 = v3;
|
||||
}
|
||||
|
||||
br_enc64be(yb, y1);
|
||||
br_enc64be(yb + 8, y0);
|
||||
}
|
||||
@@ -1,389 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#define BR_ENABLE_INTRINSICS 1
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* This is the GHASH implementation that leverages the pclmulqdq opcode
|
||||
* (from the AES-NI instructions).
|
||||
*/
|
||||
|
||||
#if BR_AES_X86NI
|
||||
|
||||
/*
|
||||
* Test CPU support for PCLMULQDQ.
|
||||
*/
|
||||
static inline int
|
||||
pclmul_supported(void)
|
||||
{
|
||||
/*
|
||||
* Bit mask for features in ECX:
|
||||
* 1 PCLMULQDQ support
|
||||
*/
|
||||
return br_cpuid(0, 0, 0x00000002, 0);
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
br_ghash
|
||||
br_ghash_pclmul_get(void)
|
||||
{
|
||||
return pclmul_supported() ? &br_ghash_pclmul : 0;
|
||||
}
|
||||
|
||||
BR_TARGETS_X86_UP
|
||||
|
||||
/*
|
||||
* GHASH is defined over elements of GF(2^128) with "full little-endian"
|
||||
* representation: leftmost byte is least significant, and, within each
|
||||
* byte, leftmost _bit_ is least significant. The natural ordering in
|
||||
* x86 is "mixed little-endian": bytes are ordered from least to most
|
||||
* significant, but bits within a byte are in most-to-least significant
|
||||
* order. Going to full little-endian representation would require
|
||||
* reversing bits within each byte, which is doable but expensive.
|
||||
*
|
||||
* Instead, we go to full big-endian representation, by swapping bytes
|
||||
* around, which is done with a single _mm_shuffle_epi8() opcode (it
|
||||
* comes with SSSE3; all CPU that offer pclmulqdq also have SSSE3). We
|
||||
* can use a full big-endian representation because in a carryless
|
||||
* multiplication, we have a nice bit reversal property:
|
||||
*
|
||||
* rev_128(x) * rev_128(y) = rev_255(x * y)
|
||||
*
|
||||
* So by using full big-endian, we still get the right result, except
|
||||
* that it is right-shifted by 1 bit. The left-shift is relatively
|
||||
* inexpensive, and it can be mutualised.
|
||||
*
|
||||
*
|
||||
* Since SSE2 opcodes do not have facilities for shitfting full 128-bit
|
||||
* values with bit precision, we have to break down values into 64-bit
|
||||
* chunks. We number chunks from 0 to 3 in left to right order.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Byte-swap a complete 128-bit value. This normally uses
|
||||
* _mm_shuffle_epi8(), which gets translated to pshufb (an SSSE3 opcode).
|
||||
* However, this crashes old Clang versions, so, for Clang before 3.8,
|
||||
* we use an alternate (and less efficient) version.
|
||||
*/
|
||||
#if BR_CLANG && !BR_CLANG_3_8
|
||||
#define BYTESWAP_DECL
|
||||
#define BYTESWAP_PREP (void)0
|
||||
#define BYTESWAP(x) do { \
|
||||
__m128i byteswap1, byteswap2; \
|
||||
byteswap1 = (x); \
|
||||
byteswap2 = _mm_srli_epi16(byteswap1, 8); \
|
||||
byteswap1 = _mm_slli_epi16(byteswap1, 8); \
|
||||
byteswap1 = _mm_or_si128(byteswap1, byteswap2); \
|
||||
byteswap1 = _mm_shufflelo_epi16(byteswap1, 0x1B); \
|
||||
byteswap1 = _mm_shufflehi_epi16(byteswap1, 0x1B); \
|
||||
(x) = _mm_shuffle_epi32(byteswap1, 0x4E); \
|
||||
} while (0)
|
||||
#else
|
||||
#define BYTESWAP_DECL __m128i byteswap_index;
|
||||
#define BYTESWAP_PREP do { \
|
||||
byteswap_index = _mm_set_epi8( \
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \
|
||||
} while (0)
|
||||
#define BYTESWAP(x) do { \
|
||||
(x) = _mm_shuffle_epi8((x), byteswap_index); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Call pclmulqdq. Clang appears to have trouble with the intrinsic, so,
|
||||
* for that compiler, we use inline assembly. Inline assembly is
|
||||
* potentially a bit slower because the compiler does not understand
|
||||
* what the opcode does, and thus cannot optimize instruction
|
||||
* scheduling.
|
||||
*
|
||||
* We use a target of "sse2" only, so that Clang may still handle the
|
||||
* '__m128i' type and allocate SSE2 registers.
|
||||
*/
|
||||
#if BR_CLANG
|
||||
BR_TARGET("sse2")
|
||||
static inline __m128i
|
||||
pclmulqdq00(__m128i x, __m128i y)
|
||||
{
|
||||
__asm__ ("pclmulqdq $0x00, %1, %0" : "+x" (x) : "x" (y));
|
||||
return x;
|
||||
}
|
||||
BR_TARGET("sse2")
|
||||
static inline __m128i
|
||||
pclmulqdq11(__m128i x, __m128i y)
|
||||
{
|
||||
__asm__ ("pclmulqdq $0x11, %1, %0" : "+x" (x) : "x" (y));
|
||||
return x;
|
||||
}
|
||||
#else
|
||||
#define pclmulqdq00(x, y) _mm_clmulepi64_si128(x, y, 0x00)
|
||||
#define pclmulqdq11(x, y) _mm_clmulepi64_si128(x, y, 0x11)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* From a 128-bit value kw, compute kx as the XOR of the two 64-bit
|
||||
* halves of kw (into the right half of kx; left half is unspecified).
|
||||
*/
|
||||
#define BK(kw, kx) do { \
|
||||
kx = _mm_xor_si128(kw, _mm_shuffle_epi32(kw, 0x0E)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Combine two 64-bit values (k0:k1) into a 128-bit (kw) value and
|
||||
* the XOR of the two values (kx).
|
||||
*/
|
||||
#define PBK(k0, k1, kw, kx) do { \
|
||||
kw = _mm_unpacklo_epi64(k1, k0); \
|
||||
kx = _mm_xor_si128(k0, k1); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Left-shift by 1 bit a 256-bit value (in four 64-bit words).
|
||||
*/
|
||||
#define SL_256(x0, x1, x2, x3) do { \
|
||||
x0 = _mm_or_si128( \
|
||||
_mm_slli_epi64(x0, 1), \
|
||||
_mm_srli_epi64(x1, 63)); \
|
||||
x1 = _mm_or_si128( \
|
||||
_mm_slli_epi64(x1, 1), \
|
||||
_mm_srli_epi64(x2, 63)); \
|
||||
x2 = _mm_or_si128( \
|
||||
_mm_slli_epi64(x2, 1), \
|
||||
_mm_srli_epi64(x3, 63)); \
|
||||
x3 = _mm_slli_epi64(x3, 1); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Perform reduction in GF(2^128). The 256-bit value is in x0..x3;
|
||||
* result is written in x0..x1.
|
||||
*/
|
||||
#define REDUCE_F128(x0, x1, x2, x3) do { \
|
||||
x1 = _mm_xor_si128( \
|
||||
x1, \
|
||||
_mm_xor_si128( \
|
||||
_mm_xor_si128( \
|
||||
x3, \
|
||||
_mm_srli_epi64(x3, 1)), \
|
||||
_mm_xor_si128( \
|
||||
_mm_srli_epi64(x3, 2), \
|
||||
_mm_srli_epi64(x3, 7)))); \
|
||||
x2 = _mm_xor_si128( \
|
||||
_mm_xor_si128( \
|
||||
x2, \
|
||||
_mm_slli_epi64(x3, 63)), \
|
||||
_mm_xor_si128( \
|
||||
_mm_slli_epi64(x3, 62), \
|
||||
_mm_slli_epi64(x3, 57))); \
|
||||
x0 = _mm_xor_si128( \
|
||||
x0, \
|
||||
_mm_xor_si128( \
|
||||
_mm_xor_si128( \
|
||||
x2, \
|
||||
_mm_srli_epi64(x2, 1)), \
|
||||
_mm_xor_si128( \
|
||||
_mm_srli_epi64(x2, 2), \
|
||||
_mm_srli_epi64(x2, 7)))); \
|
||||
x1 = _mm_xor_si128( \
|
||||
_mm_xor_si128( \
|
||||
x1, \
|
||||
_mm_slli_epi64(x2, 63)), \
|
||||
_mm_xor_si128( \
|
||||
_mm_slli_epi64(x2, 62), \
|
||||
_mm_slli_epi64(x2, 57))); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Square value kw into (dw,dx).
|
||||
*/
|
||||
#define SQUARE_F128(kw, dw, dx) do { \
|
||||
__m128i z0, z1, z2, z3; \
|
||||
z1 = pclmulqdq11(kw, kw); \
|
||||
z3 = pclmulqdq00(kw, kw); \
|
||||
z0 = _mm_shuffle_epi32(z1, 0x0E); \
|
||||
z2 = _mm_shuffle_epi32(z3, 0x0E); \
|
||||
SL_256(z0, z1, z2, z3); \
|
||||
REDUCE_F128(z0, z1, z2, z3); \
|
||||
PBK(z0, z1, dw, dx); \
|
||||
} while (0)
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
BR_TARGET("ssse3,pclmul")
|
||||
void
|
||||
br_ghash_pclmul(void *y, const void *h, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf1, *buf2;
|
||||
unsigned char tmp[64];
|
||||
size_t num4, num1;
|
||||
__m128i yw, h1w, h1x;
|
||||
BYTESWAP_DECL
|
||||
|
||||
/*
|
||||
* We split data into two chunks. First chunk starts at buf1
|
||||
* and contains num4 blocks of 64-byte values. Second chunk
|
||||
* starts at buf2 and contains num1 blocks of 16-byte values.
|
||||
* We want the first chunk to be as large as possible.
|
||||
*/
|
||||
buf1 = data;
|
||||
num4 = len >> 6;
|
||||
len &= 63;
|
||||
buf2 = buf1 + (num4 << 6);
|
||||
num1 = (len + 15) >> 4;
|
||||
if ((len & 15) != 0) {
|
||||
memcpy(tmp, buf2, len);
|
||||
memset(tmp + len, 0, (num1 << 4) - len);
|
||||
buf2 = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preparatory step for endian conversions.
|
||||
*/
|
||||
BYTESWAP_PREP;
|
||||
|
||||
/*
|
||||
* Load y and h.
|
||||
*/
|
||||
yw = _mm_loadu_si128(y);
|
||||
h1w = _mm_loadu_si128(h);
|
||||
BYTESWAP(yw);
|
||||
BYTESWAP(h1w);
|
||||
BK(h1w, h1x);
|
||||
|
||||
if (num4 > 0) {
|
||||
__m128i h2w, h2x, h3w, h3x, h4w, h4x;
|
||||
__m128i t0, t1, t2, t3;
|
||||
|
||||
/*
|
||||
* Compute h2 = h^2.
|
||||
*/
|
||||
SQUARE_F128(h1w, h2w, h2x);
|
||||
|
||||
/*
|
||||
* Compute h3 = h^3 = h*(h^2).
|
||||
*/
|
||||
t1 = pclmulqdq11(h1w, h2w);
|
||||
t3 = pclmulqdq00(h1w, h2w);
|
||||
t2 = _mm_xor_si128(pclmulqdq00(h1x, h2x),
|
||||
_mm_xor_si128(t1, t3));
|
||||
t0 = _mm_shuffle_epi32(t1, 0x0E);
|
||||
t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E));
|
||||
t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E));
|
||||
SL_256(t0, t1, t2, t3);
|
||||
REDUCE_F128(t0, t1, t2, t3);
|
||||
PBK(t0, t1, h3w, h3x);
|
||||
|
||||
/*
|
||||
* Compute h4 = h^4 = (h^2)^2.
|
||||
*/
|
||||
SQUARE_F128(h2w, h4w, h4x);
|
||||
|
||||
while (num4 -- > 0) {
|
||||
__m128i aw0, aw1, aw2, aw3;
|
||||
__m128i ax0, ax1, ax2, ax3;
|
||||
|
||||
aw0 = _mm_loadu_si128((void *)(buf1 + 0));
|
||||
aw1 = _mm_loadu_si128((void *)(buf1 + 16));
|
||||
aw2 = _mm_loadu_si128((void *)(buf1 + 32));
|
||||
aw3 = _mm_loadu_si128((void *)(buf1 + 48));
|
||||
BYTESWAP(aw0);
|
||||
BYTESWAP(aw1);
|
||||
BYTESWAP(aw2);
|
||||
BYTESWAP(aw3);
|
||||
buf1 += 64;
|
||||
|
||||
aw0 = _mm_xor_si128(aw0, yw);
|
||||
BK(aw1, ax1);
|
||||
BK(aw2, ax2);
|
||||
BK(aw3, ax3);
|
||||
BK(aw0, ax0);
|
||||
|
||||
t1 = _mm_xor_si128(
|
||||
_mm_xor_si128(
|
||||
pclmulqdq11(aw0, h4w),
|
||||
pclmulqdq11(aw1, h3w)),
|
||||
_mm_xor_si128(
|
||||
pclmulqdq11(aw2, h2w),
|
||||
pclmulqdq11(aw3, h1w)));
|
||||
t3 = _mm_xor_si128(
|
||||
_mm_xor_si128(
|
||||
pclmulqdq00(aw0, h4w),
|
||||
pclmulqdq00(aw1, h3w)),
|
||||
_mm_xor_si128(
|
||||
pclmulqdq00(aw2, h2w),
|
||||
pclmulqdq00(aw3, h1w)));
|
||||
t2 = _mm_xor_si128(
|
||||
_mm_xor_si128(
|
||||
pclmulqdq00(ax0, h4x),
|
||||
pclmulqdq00(ax1, h3x)),
|
||||
_mm_xor_si128(
|
||||
pclmulqdq00(ax2, h2x),
|
||||
pclmulqdq00(ax3, h1x)));
|
||||
t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3));
|
||||
t0 = _mm_shuffle_epi32(t1, 0x0E);
|
||||
t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E));
|
||||
t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E));
|
||||
SL_256(t0, t1, t2, t3);
|
||||
REDUCE_F128(t0, t1, t2, t3);
|
||||
yw = _mm_unpacklo_epi64(t1, t0);
|
||||
}
|
||||
}
|
||||
|
||||
while (num1 -- > 0) {
|
||||
__m128i aw, ax;
|
||||
__m128i t0, t1, t2, t3;
|
||||
|
||||
aw = _mm_loadu_si128((void *)buf2);
|
||||
BYTESWAP(aw);
|
||||
buf2 += 16;
|
||||
|
||||
aw = _mm_xor_si128(aw, yw);
|
||||
BK(aw, ax);
|
||||
|
||||
t1 = pclmulqdq11(aw, h1w);
|
||||
t3 = pclmulqdq00(aw, h1w);
|
||||
t2 = pclmulqdq00(ax, h1x);
|
||||
t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3));
|
||||
t0 = _mm_shuffle_epi32(t1, 0x0E);
|
||||
t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E));
|
||||
t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E));
|
||||
SL_256(t0, t1, t2, t3);
|
||||
REDUCE_F128(t0, t1, t2, t3);
|
||||
yw = _mm_unpacklo_epi64(t1, t0);
|
||||
}
|
||||
|
||||
BYTESWAP(yw);
|
||||
_mm_storeu_si128(y, yw);
|
||||
}
|
||||
|
||||
BR_TARGETS_X86_DOWN
|
||||
|
||||
#else
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
br_ghash
|
||||
br_ghash_pclmul_get(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
411
dstalk-core/thirdparty/bearssl/src/hash/ghash_pwr8.c
vendored
411
dstalk-core/thirdparty/bearssl/src/hash/ghash_pwr8.c
vendored
@@ -1,411 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#define BR_POWER_ASM_MACROS 1
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* This is the GHASH implementation that leverages the POWER8 opcodes.
|
||||
*/
|
||||
|
||||
#if BR_POWER8
|
||||
|
||||
/*
|
||||
* Some symbolic names for registers.
|
||||
* HB0 = 16 bytes of value 0
|
||||
* HB1 = 16 bytes of value 1
|
||||
* HB2 = 16 bytes of value 2
|
||||
* HB6 = 16 bytes of value 6
|
||||
* HB7 = 16 bytes of value 7
|
||||
* TT0, TT1 and TT2 are temporaries
|
||||
*
|
||||
* BSW holds the pattern for byteswapping 32-bit words; this is set only
|
||||
* on little-endian systems. XBSW is the same register with the +32 offset
|
||||
* for access with the VSX opcodes.
|
||||
*/
|
||||
#define HB0 0
|
||||
#define HB1 1
|
||||
#define HB2 2
|
||||
#define HB6 3
|
||||
#define HB7 4
|
||||
#define TT0 5
|
||||
#define TT1 6
|
||||
#define TT2 7
|
||||
|
||||
#define BSW 8
|
||||
#define XBSW 40
|
||||
|
||||
/*
|
||||
* Macro to initialise the constants.
|
||||
*/
|
||||
#define INIT \
|
||||
vxor(HB0, HB0, HB0) \
|
||||
vspltisb(HB1, 1) \
|
||||
vspltisb(HB2, 2) \
|
||||
vspltisb(HB6, 6) \
|
||||
vspltisb(HB7, 7) \
|
||||
INIT_BSW
|
||||
|
||||
/*
|
||||
* Fix endianness of a value after reading it or before writing it, if
|
||||
* necessary.
|
||||
*/
|
||||
#if BR_POWER8_LE
|
||||
#define INIT_BSW lxvw4x(XBSW, 0, %[idx2be])
|
||||
#define FIX_ENDIAN(xx) vperm(xx, xx, xx, BSW)
|
||||
#else
|
||||
#define INIT_BSW
|
||||
#define FIX_ENDIAN(xx)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Left-shift x0:x1 by one bit to the left. This is a corrective action
|
||||
* needed because GHASH is defined in full little-endian specification,
|
||||
* while the opcodes use full big-endian convention, so the 255-bit product
|
||||
* ends up one bit to the right.
|
||||
*/
|
||||
#define SL_256(x0, x1) \
|
||||
vsldoi(TT0, HB0, x1, 1) \
|
||||
vsl(x0, x0, HB1) \
|
||||
vsr(TT0, TT0, HB7) \
|
||||
vsl(x1, x1, HB1) \
|
||||
vxor(x0, x0, TT0)
|
||||
|
||||
/*
|
||||
* Reduce x0:x1 in GF(2^128), result in xd (register xd may be the same as
|
||||
* x0 or x1, or a different register). x0 and x1 are modified.
|
||||
*/
|
||||
#define REDUCE_F128(xd, x0, x1) \
|
||||
vxor(x0, x0, x1) \
|
||||
vsr(TT0, x1, HB1) \
|
||||
vsr(TT1, x1, HB2) \
|
||||
vsr(TT2, x1, HB7) \
|
||||
vxor(x0, x0, TT0) \
|
||||
vxor(TT1, TT1, TT2) \
|
||||
vxor(x0, x0, TT1) \
|
||||
vsldoi(x1, x1, HB0, 15) \
|
||||
vsl(TT1, x1, HB6) \
|
||||
vsl(TT2, x1, HB1) \
|
||||
vxor(x1, TT1, TT2) \
|
||||
vsr(TT0, x1, HB1) \
|
||||
vsr(TT1, x1, HB2) \
|
||||
vsr(TT2, x1, HB7) \
|
||||
vxor(x0, x0, x1) \
|
||||
vxor(x0, x0, TT0) \
|
||||
vxor(TT1, TT1, TT2) \
|
||||
vxor(xd, x0, TT1)
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_ghash_pwr8(void *y, const void *h, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf1, *buf2;
|
||||
size_t num4, num1;
|
||||
unsigned char tmp[64];
|
||||
long cc0, cc1, cc2, cc3;
|
||||
|
||||
#if BR_POWER8_LE
|
||||
static const uint32_t idx2be[] = {
|
||||
0x03020100, 0x07060504, 0x0B0A0908, 0x0F0E0D0C
|
||||
};
|
||||
#endif
|
||||
|
||||
buf1 = data;
|
||||
|
||||
/*
|
||||
* Assembly code requires data into two chunks; first chunk
|
||||
* must contain a number of blocks which is a multiple of 4.
|
||||
* Since the processing for the first chunk is faster, we want
|
||||
* to make it as big as possible.
|
||||
*
|
||||
* For the remainder, there are two possibilities:
|
||||
* -- if the remainder size is a multiple of 16, then use it
|
||||
* in place;
|
||||
* -- otherwise, copy it to the tmp[] array and pad it with
|
||||
* zeros.
|
||||
*/
|
||||
num4 = len >> 6;
|
||||
buf2 = buf1 + (num4 << 6);
|
||||
len &= 63;
|
||||
num1 = (len + 15) >> 4;
|
||||
if ((len & 15) != 0) {
|
||||
memcpy(tmp, buf2, len);
|
||||
memset(tmp + len, 0, (num1 << 4) - len);
|
||||
buf2 = tmp;
|
||||
}
|
||||
|
||||
cc0 = 0;
|
||||
cc1 = 16;
|
||||
cc2 = 32;
|
||||
cc3 = 48;
|
||||
asm volatile (
|
||||
INIT
|
||||
|
||||
/*
|
||||
* Load current h (denoted hereafter h1) in v9.
|
||||
*/
|
||||
lxvw4x(41, 0, %[h])
|
||||
FIX_ENDIAN(9)
|
||||
|
||||
/*
|
||||
* Load current y into v28.
|
||||
*/
|
||||
lxvw4x(60, 0, %[y])
|
||||
FIX_ENDIAN(28)
|
||||
|
||||
/*
|
||||
* Split h1 into three registers:
|
||||
* v17 = h1_1:h1_0
|
||||
* v18 = 0:h1_0
|
||||
* v19 = h1_1:0
|
||||
*/
|
||||
xxpermdi(49, 41, 41, 2)
|
||||
vsldoi(18, HB0, 9, 8)
|
||||
vsldoi(19, 9, HB0, 8)
|
||||
|
||||
/*
|
||||
* If num4 is 0, skip directly to the second chunk.
|
||||
*/
|
||||
cmpldi(%[num4], 0)
|
||||
beq(chunk1)
|
||||
|
||||
/*
|
||||
* Compute h2 = h*h in v10.
|
||||
*/
|
||||
vpmsumd(10, 18, 18)
|
||||
vpmsumd(11, 19, 19)
|
||||
SL_256(10, 11)
|
||||
REDUCE_F128(10, 10, 11)
|
||||
|
||||
/*
|
||||
* Compute h3 = h*h*h in v11.
|
||||
* We first split h2 into:
|
||||
* v10 = h2_0:h2_1
|
||||
* v11 = 0:h2_0
|
||||
* v12 = h2_1:0
|
||||
* Then we do the product with h1, and reduce into v11.
|
||||
*/
|
||||
vsldoi(11, HB0, 10, 8)
|
||||
vsldoi(12, 10, HB0, 8)
|
||||
vpmsumd(13, 10, 17)
|
||||
vpmsumd(11, 11, 18)
|
||||
vpmsumd(12, 12, 19)
|
||||
vsldoi(14, HB0, 13, 8)
|
||||
vsldoi(15, 13, HB0, 8)
|
||||
vxor(11, 11, 14)
|
||||
vxor(12, 12, 15)
|
||||
SL_256(11, 12)
|
||||
REDUCE_F128(11, 11, 12)
|
||||
|
||||
/*
|
||||
* Compute h4 = h*h*h*h in v12. This is done by squaring h2.
|
||||
*/
|
||||
vsldoi(12, HB0, 10, 8)
|
||||
vsldoi(13, 10, HB0, 8)
|
||||
vpmsumd(12, 12, 12)
|
||||
vpmsumd(13, 13, 13)
|
||||
SL_256(12, 13)
|
||||
REDUCE_F128(12, 12, 13)
|
||||
|
||||
/*
|
||||
* Repack h1, h2, h3 and h4:
|
||||
* v13 = h4_0:h3_0
|
||||
* v14 = h4_1:h3_1
|
||||
* v15 = h2_0:h1_0
|
||||
* v16 = h2_1:h1_1
|
||||
*/
|
||||
xxpermdi(45, 44, 43, 0)
|
||||
xxpermdi(46, 44, 43, 3)
|
||||
xxpermdi(47, 42, 41, 0)
|
||||
xxpermdi(48, 42, 41, 3)
|
||||
|
||||
/*
|
||||
* Loop for each group of four blocks.
|
||||
*/
|
||||
mtctr(%[num4])
|
||||
label(loop4)
|
||||
/*
|
||||
* Read the four next blocks.
|
||||
* v20 = y + a0 = b0
|
||||
* v21 = a1 = b1
|
||||
* v22 = a2 = b2
|
||||
* v23 = a3 = b3
|
||||
*/
|
||||
lxvw4x(52, %[cc0], %[buf1])
|
||||
lxvw4x(53, %[cc1], %[buf1])
|
||||
lxvw4x(54, %[cc2], %[buf1])
|
||||
lxvw4x(55, %[cc3], %[buf1])
|
||||
FIX_ENDIAN(20)
|
||||
FIX_ENDIAN(21)
|
||||
FIX_ENDIAN(22)
|
||||
FIX_ENDIAN(23)
|
||||
addi(%[buf1], %[buf1], 64)
|
||||
vxor(20, 20, 28)
|
||||
|
||||
/*
|
||||
* Repack the blocks into v9, v10, v11 and v12.
|
||||
* v9 = b0_0:b1_0
|
||||
* v10 = b0_1:b1_1
|
||||
* v11 = b2_0:b3_0
|
||||
* v12 = b2_1:b3_1
|
||||
*/
|
||||
xxpermdi(41, 52, 53, 0)
|
||||
xxpermdi(42, 52, 53, 3)
|
||||
xxpermdi(43, 54, 55, 0)
|
||||
xxpermdi(44, 54, 55, 3)
|
||||
|
||||
/*
|
||||
* Compute the products.
|
||||
* v20 = b0_0*h4_0 + b1_0*h3_0
|
||||
* v21 = b0_1*h4_0 + b1_1*h3_0
|
||||
* v22 = b0_0*h4_1 + b1_0*h3_1
|
||||
* v23 = b0_1*h4_1 + b1_1*h3_1
|
||||
* v24 = b2_0*h2_0 + b3_0*h1_0
|
||||
* v25 = b2_1*h2_0 + b3_1*h1_0
|
||||
* v26 = b2_0*h2_1 + b3_0*h1_1
|
||||
* v27 = b2_1*h2_1 + b3_1*h1_1
|
||||
*/
|
||||
vpmsumd(20, 13, 9)
|
||||
vpmsumd(21, 13, 10)
|
||||
vpmsumd(22, 14, 9)
|
||||
vpmsumd(23, 14, 10)
|
||||
vpmsumd(24, 15, 11)
|
||||
vpmsumd(25, 15, 12)
|
||||
vpmsumd(26, 16, 11)
|
||||
vpmsumd(27, 16, 12)
|
||||
|
||||
/*
|
||||
* Sum products into a single 256-bit result in v11:v12.
|
||||
*/
|
||||
vxor(11, 20, 24)
|
||||
vxor(12, 23, 27)
|
||||
vxor( 9, 21, 22)
|
||||
vxor(10, 25, 26)
|
||||
vxor(20, 9, 10)
|
||||
vsldoi( 9, HB0, 20, 8)
|
||||
vsldoi(10, 20, HB0, 8)
|
||||
vxor(11, 11, 9)
|
||||
vxor(12, 12, 10)
|
||||
|
||||
/*
|
||||
* Fix and reduce in GF(2^128); this is the new y (in v28).
|
||||
*/
|
||||
SL_256(11, 12)
|
||||
REDUCE_F128(28, 11, 12)
|
||||
|
||||
/*
|
||||
* Loop for next group of four blocks.
|
||||
*/
|
||||
bdnz(loop4)
|
||||
|
||||
/*
|
||||
* Process second chunk, one block at a time.
|
||||
*/
|
||||
label(chunk1)
|
||||
cmpldi(%[num1], 0)
|
||||
beq(done)
|
||||
|
||||
mtctr(%[num1])
|
||||
label(loop1)
|
||||
/*
|
||||
* Load next data block and XOR it into y.
|
||||
*/
|
||||
lxvw4x(41, 0, %[buf2])
|
||||
#if BR_POWER8_LE
|
||||
FIX_ENDIAN(9)
|
||||
#endif
|
||||
addi(%[buf2], %[buf2], 16)
|
||||
vxor(9, 28, 9)
|
||||
|
||||
/*
|
||||
* Split y into doublewords:
|
||||
* v9 = y_0:y_1
|
||||
* v10 = 0:y_0
|
||||
* v11 = y_1:0
|
||||
*/
|
||||
vsldoi(10, HB0, 9, 8)
|
||||
vsldoi(11, 9, HB0, 8)
|
||||
|
||||
/*
|
||||
* Compute products with h:
|
||||
* v12 = y_0 * h_0
|
||||
* v13 = y_1 * h_1
|
||||
* v14 = y_1 * h_0 + y_0 * h_1
|
||||
*/
|
||||
vpmsumd(14, 9, 17)
|
||||
vpmsumd(12, 10, 18)
|
||||
vpmsumd(13, 11, 19)
|
||||
|
||||
/*
|
||||
* Propagate v14 into v12:v13 to finalise product.
|
||||
*/
|
||||
vsldoi(10, HB0, 14, 8)
|
||||
vsldoi(11, 14, HB0, 8)
|
||||
vxor(12, 12, 10)
|
||||
vxor(13, 13, 11)
|
||||
|
||||
/*
|
||||
* Fix result and reduce into v28 (next value for y).
|
||||
*/
|
||||
SL_256(12, 13)
|
||||
REDUCE_F128(28, 12, 13)
|
||||
bdnz(loop1)
|
||||
|
||||
label(done)
|
||||
/*
|
||||
* Write back the new y.
|
||||
*/
|
||||
FIX_ENDIAN(28)
|
||||
stxvw4x(60, 0, %[y])
|
||||
|
||||
: [buf1] "+b" (buf1), [buf2] "+b" (buf2)
|
||||
: [y] "b" (y), [h] "b" (h), [num4] "b" (num4), [num1] "b" (num1),
|
||||
[cc0] "b" (cc0), [cc1] "b" (cc1), [cc2] "b" (cc2), [cc3] "b" (cc3)
|
||||
#if BR_POWER8_LE
|
||||
, [idx2be] "b" (idx2be)
|
||||
#endif
|
||||
: "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
|
||||
"v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19",
|
||||
"v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29",
|
||||
"ctr", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
br_ghash
|
||||
br_ghash_pwr8_get(void)
|
||||
{
|
||||
return &br_ghash_pwr8;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
br_ghash
|
||||
br_ghash_pwr8_get(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
208
dstalk-core/thirdparty/bearssl/src/hash/md5.c
vendored
208
dstalk-core/thirdparty/bearssl/src/hash/md5.c
vendored
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D))
|
||||
#define G(B, C, D) ((((C) ^ (B)) & (D)) ^ (C))
|
||||
#define H(B, C, D) ((B) ^ (C) ^ (D))
|
||||
#define I(B, C, D) ((C) ^ ((B) | ~(D)))
|
||||
|
||||
#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* see inner.h */
|
||||
const uint32_t br_md5_IV[4] = {
|
||||
0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476
|
||||
};
|
||||
|
||||
static const uint32_t K[64] = {
|
||||
0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE,
|
||||
0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
|
||||
0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,
|
||||
0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
|
||||
|
||||
0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,
|
||||
0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
|
||||
0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,
|
||||
0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
|
||||
|
||||
0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C,
|
||||
0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
|
||||
0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,
|
||||
0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
|
||||
|
||||
0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039,
|
||||
0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
|
||||
0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1,
|
||||
0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
|
||||
};
|
||||
|
||||
static const unsigned char MP[48] = {
|
||||
1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,
|
||||
5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
|
||||
0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_md5_round(const unsigned char *buf, uint32_t *val)
|
||||
{
|
||||
uint32_t m[16];
|
||||
uint32_t a, b, c, d;
|
||||
int i;
|
||||
|
||||
a = val[0];
|
||||
b = val[1];
|
||||
c = val[2];
|
||||
d = val[3];
|
||||
/* obsolete
|
||||
for (i = 0; i < 16; i ++) {
|
||||
m[i] = br_dec32le(buf + (i << 2));
|
||||
}
|
||||
*/
|
||||
br_range_dec32le(m, 16, buf);
|
||||
|
||||
for (i = 0; i < 16; i += 4) {
|
||||
a = b + ROTL(a + F(b, c, d) + m[i + 0] + K[i + 0], 7);
|
||||
d = a + ROTL(d + F(a, b, c) + m[i + 1] + K[i + 1], 12);
|
||||
c = d + ROTL(c + F(d, a, b) + m[i + 2] + K[i + 2], 17);
|
||||
b = c + ROTL(b + F(c, d, a) + m[i + 3] + K[i + 3], 22);
|
||||
}
|
||||
for (i = 16; i < 32; i += 4) {
|
||||
a = b + ROTL(a + G(b, c, d) + m[MP[i - 16]] + K[i + 0], 5);
|
||||
d = a + ROTL(d + G(a, b, c) + m[MP[i - 15]] + K[i + 1], 9);
|
||||
c = d + ROTL(c + G(d, a, b) + m[MP[i - 14]] + K[i + 2], 14);
|
||||
b = c + ROTL(b + G(c, d, a) + m[MP[i - 13]] + K[i + 3], 20);
|
||||
}
|
||||
for (i = 32; i < 48; i += 4) {
|
||||
a = b + ROTL(a + H(b, c, d) + m[MP[i - 16]] + K[i + 0], 4);
|
||||
d = a + ROTL(d + H(a, b, c) + m[MP[i - 15]] + K[i + 1], 11);
|
||||
c = d + ROTL(c + H(d, a, b) + m[MP[i - 14]] + K[i + 2], 16);
|
||||
b = c + ROTL(b + H(c, d, a) + m[MP[i - 13]] + K[i + 3], 23);
|
||||
}
|
||||
for (i = 48; i < 64; i += 4) {
|
||||
a = b + ROTL(a + I(b, c, d) + m[MP[i - 16]] + K[i + 0], 6);
|
||||
d = a + ROTL(d + I(a, b, c) + m[MP[i - 15]] + K[i + 1], 10);
|
||||
c = d + ROTL(c + I(d, a, b) + m[MP[i - 14]] + K[i + 2], 15);
|
||||
b = c + ROTL(b + I(c, d, a) + m[MP[i - 13]] + K[i + 3], 21);
|
||||
}
|
||||
|
||||
val[0] += a;
|
||||
val[1] += b;
|
||||
val[2] += c;
|
||||
val[3] += d;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5_init(br_md5_context *cc)
|
||||
{
|
||||
cc->vtable = &br_md5_vtable;
|
||||
memcpy(cc->val, br_md5_IV, sizeof cc->val);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5_update(br_md5_context *cc, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)cc->count & 63;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 64 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(cc->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
cc->count += (uint64_t)clen;
|
||||
if (ptr == 64) {
|
||||
br_md5_round(cc->buf, cc->val);
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5_out(const br_md5_context *cc, void *dst)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
uint32_t val[4];
|
||||
size_t ptr;
|
||||
|
||||
ptr = (size_t)cc->count & 63;
|
||||
memcpy(buf, cc->buf, ptr);
|
||||
memcpy(val, cc->val, sizeof val);
|
||||
buf[ptr ++] = 0x80;
|
||||
if (ptr > 56) {
|
||||
memset(buf + ptr, 0, 64 - ptr);
|
||||
br_md5_round(buf, val);
|
||||
memset(buf, 0, 56);
|
||||
} else {
|
||||
memset(buf + ptr, 0, 56 - ptr);
|
||||
}
|
||||
br_enc64le(buf + 56, cc->count << 3);
|
||||
br_md5_round(buf, val);
|
||||
br_range_enc32le(dst, val, 4);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
uint64_t
|
||||
br_md5_state(const br_md5_context *cc, void *dst)
|
||||
{
|
||||
br_range_enc32le(dst, cc->val, 4);
|
||||
return cc->count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5_set_state(br_md5_context *cc, const void *stb, uint64_t count)
|
||||
{
|
||||
br_range_dec32le(cc->val, 4, stb);
|
||||
cc->count = count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_md5_vtable = {
|
||||
sizeof(br_md5_context),
|
||||
BR_HASHDESC_ID(br_md5_ID)
|
||||
| BR_HASHDESC_OUT(16)
|
||||
| BR_HASHDESC_STATE(16)
|
||||
| BR_HASHDESC_LBLEN(6)
|
||||
| BR_HASHDESC_MD_PADDING,
|
||||
(void (*)(const br_hash_class **))&br_md5_init,
|
||||
(void (*)(const br_hash_class **, const void *, size_t))&br_md5_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_md5_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_md5_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_md5_set_state
|
||||
};
|
||||
141
dstalk-core/thirdparty/bearssl/src/hash/md5sha1.c
vendored
141
dstalk-core/thirdparty/bearssl/src/hash/md5sha1.c
vendored
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5sha1_init(br_md5sha1_context *cc)
|
||||
{
|
||||
cc->vtable = &br_md5sha1_vtable;
|
||||
memcpy(cc->val_md5, br_md5_IV, sizeof cc->val_md5);
|
||||
memcpy(cc->val_sha1, br_sha1_IV, sizeof cc->val_sha1);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5sha1_update(br_md5sha1_context *cc, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)cc->count & 63;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 64 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(cc->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
cc->count += (uint64_t)clen;
|
||||
if (ptr == 64) {
|
||||
br_md5_round(cc->buf, cc->val_md5);
|
||||
br_sha1_round(cc->buf, cc->val_sha1);
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5sha1_out(const br_md5sha1_context *cc, void *dst)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
uint32_t val_md5[4];
|
||||
uint32_t val_sha1[5];
|
||||
size_t ptr;
|
||||
unsigned char *out;
|
||||
uint64_t count;
|
||||
|
||||
count = cc->count;
|
||||
ptr = (size_t)count & 63;
|
||||
memcpy(buf, cc->buf, ptr);
|
||||
memcpy(val_md5, cc->val_md5, sizeof val_md5);
|
||||
memcpy(val_sha1, cc->val_sha1, sizeof val_sha1);
|
||||
buf[ptr ++] = 0x80;
|
||||
if (ptr > 56) {
|
||||
memset(buf + ptr, 0, 64 - ptr);
|
||||
br_md5_round(buf, val_md5);
|
||||
br_sha1_round(buf, val_sha1);
|
||||
memset(buf, 0, 56);
|
||||
} else {
|
||||
memset(buf + ptr, 0, 56 - ptr);
|
||||
}
|
||||
count <<= 3;
|
||||
br_enc64le(buf + 56, count);
|
||||
br_md5_round(buf, val_md5);
|
||||
br_enc64be(buf + 56, count);
|
||||
br_sha1_round(buf, val_sha1);
|
||||
out = dst;
|
||||
br_range_enc32le(out, val_md5, 4);
|
||||
br_range_enc32be(out + 16, val_sha1, 5);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
uint64_t
|
||||
br_md5sha1_state(const br_md5sha1_context *cc, void *dst)
|
||||
{
|
||||
unsigned char *out;
|
||||
|
||||
out = dst;
|
||||
br_range_enc32le(out, cc->val_md5, 4);
|
||||
br_range_enc32be(out + 16, cc->val_sha1, 5);
|
||||
return cc->count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_md5sha1_set_state(br_md5sha1_context *cc, const void *stb, uint64_t count)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
|
||||
buf = stb;
|
||||
br_range_dec32le(cc->val_md5, 4, buf);
|
||||
br_range_dec32be(cc->val_sha1, 5, buf + 16);
|
||||
cc->count = count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_md5sha1_vtable = {
|
||||
sizeof(br_md5sha1_context),
|
||||
BR_HASHDESC_ID(br_md5sha1_ID)
|
||||
| BR_HASHDESC_OUT(36)
|
||||
| BR_HASHDESC_STATE(36)
|
||||
| BR_HASHDESC_LBLEN(6),
|
||||
(void (*)(const br_hash_class **))&br_md5sha1_init,
|
||||
(void (*)(const br_hash_class **, const void *, size_t))
|
||||
&br_md5sha1_update,
|
||||
(void (*)(const br_hash_class *const *, void *))
|
||||
&br_md5sha1_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))
|
||||
&br_md5sha1_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_md5sha1_set_state
|
||||
};
|
||||
56
dstalk-core/thirdparty/bearssl/src/hash/mgf1.c
vendored
56
dstalk-core/thirdparty/bearssl/src/hash/mgf1.c
vendored
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_mgf1_xor(void *data, size_t len,
|
||||
const br_hash_class *dig, const void *seed, size_t seed_len)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t u, hlen;
|
||||
uint32_t c;
|
||||
|
||||
buf = data;
|
||||
hlen = br_digest_size(dig);
|
||||
for (u = 0, c = 0; u < len; u += hlen, c ++) {
|
||||
br_hash_compat_context hc;
|
||||
unsigned char tmp[64];
|
||||
size_t v;
|
||||
|
||||
hc.vtable = dig;
|
||||
dig->init(&hc.vtable);
|
||||
dig->update(&hc.vtable, seed, seed_len);
|
||||
br_enc32be(tmp, c);
|
||||
dig->update(&hc.vtable, tmp, 4);
|
||||
dig->out(&hc.vtable, tmp);
|
||||
for (v = 0; v < hlen; v ++) {
|
||||
if ((u + v) >= len) {
|
||||
break;
|
||||
}
|
||||
buf[u + v] ^= tmp[v];
|
||||
}
|
||||
}
|
||||
}
|
||||
166
dstalk-core/thirdparty/bearssl/src/hash/multihash.c
vendored
166
dstalk-core/thirdparty/bearssl/src/hash/multihash.c
vendored
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* An aggregate context that is large enough for all supported hash
|
||||
* functions.
|
||||
*/
|
||||
typedef union {
|
||||
const br_hash_class *vtable;
|
||||
br_md5_context md5;
|
||||
br_sha1_context sha1;
|
||||
br_sha224_context sha224;
|
||||
br_sha256_context sha256;
|
||||
br_sha384_context sha384;
|
||||
br_sha512_context sha512;
|
||||
} gen_hash_context;
|
||||
|
||||
/*
|
||||
* Get the offset to the state for a specific hash function within the
|
||||
* context structure. This shall be called only for the supported hash
|
||||
* functions,
|
||||
*/
|
||||
static size_t
|
||||
get_state_offset(int id)
|
||||
{
|
||||
if (id >= 5) {
|
||||
/*
|
||||
* SHA-384 has id 5, and SHA-512 has id 6. Both use
|
||||
* eight 64-bit words for their state.
|
||||
*/
|
||||
return offsetof(br_multihash_context, val_64)
|
||||
+ ((size_t)(id - 5) * (8 * sizeof(uint64_t)));
|
||||
} else {
|
||||
/*
|
||||
* MD5 has id 1, SHA-1 has id 2, SHA-224 has id 3 and
|
||||
* SHA-256 has id 4. They use 32-bit words for their
|
||||
* states (4 words for MD5, 5 for SHA-1, 8 for SHA-224
|
||||
* and 8 for SHA-256).
|
||||
*/
|
||||
unsigned x;
|
||||
|
||||
x = id - 1;
|
||||
x = ((x + (x & (x >> 1))) << 2) + (x >> 1);
|
||||
return offsetof(br_multihash_context, val_32)
|
||||
+ x * sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_multihash_zero(br_multihash_context *ctx)
|
||||
{
|
||||
/*
|
||||
* This is not standard, but yields very short and efficient code,
|
||||
* and it works "everywhere".
|
||||
*/
|
||||
memset(ctx, 0, sizeof *ctx);
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_multihash_init(br_multihash_context *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
ctx->count = 0;
|
||||
for (i = 1; i <= 6; i ++) {
|
||||
const br_hash_class *hc;
|
||||
|
||||
hc = ctx->impl[i - 1];
|
||||
if (hc != NULL) {
|
||||
gen_hash_context g;
|
||||
|
||||
hc->init(&g.vtable);
|
||||
hc->state(&g.vtable,
|
||||
(unsigned char *)ctx + get_state_offset(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
void
|
||||
br_multihash_update(br_multihash_context *ctx, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)ctx->count & 127;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 128 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(ctx->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
ctx->count += (uint64_t)clen;
|
||||
if (ptr == 128) {
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= 6; i ++) {
|
||||
const br_hash_class *hc;
|
||||
|
||||
hc = ctx->impl[i - 1];
|
||||
if (hc != NULL) {
|
||||
gen_hash_context g;
|
||||
unsigned char *state;
|
||||
|
||||
state = (unsigned char *)ctx
|
||||
+ get_state_offset(i);
|
||||
hc->set_state(&g.vtable,
|
||||
state, ctx->count - 128);
|
||||
hc->update(&g.vtable, ctx->buf, 128);
|
||||
hc->state(&g.vtable, state);
|
||||
}
|
||||
}
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl_hash.h */
|
||||
size_t
|
||||
br_multihash_out(const br_multihash_context *ctx, int id, void *dst)
|
||||
{
|
||||
const br_hash_class *hc;
|
||||
gen_hash_context g;
|
||||
const unsigned char *state;
|
||||
|
||||
hc = ctx->impl[id - 1];
|
||||
if (hc == NULL) {
|
||||
return 0;
|
||||
}
|
||||
state = (const unsigned char *)ctx + get_state_offset(id);
|
||||
hc->set_state(&g.vtable, state, ctx->count & ~(uint64_t)127);
|
||||
hc->update(&g.vtable, ctx->buf, ctx->count & (uint64_t)127);
|
||||
hc->out(&g.vtable, dst);
|
||||
return (hc->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
|
||||
}
|
||||
191
dstalk-core/thirdparty/bearssl/src/hash/sha1.c
vendored
191
dstalk-core/thirdparty/bearssl/src/hash/sha1.c
vendored
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D))
|
||||
#define G(B, C, D) ((B) ^ (C) ^ (D))
|
||||
#define H(B, C, D) (((D) & (C)) | (((D) | (C)) & (B)))
|
||||
#define I(B, C, D) G(B, C, D)
|
||||
|
||||
#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
#define K1 ((uint32_t)0x5A827999)
|
||||
#define K2 ((uint32_t)0x6ED9EBA1)
|
||||
#define K3 ((uint32_t)0x8F1BBCDC)
|
||||
#define K4 ((uint32_t)0xCA62C1D6)
|
||||
|
||||
/* see inner.h */
|
||||
const uint32_t br_sha1_IV[5] = {
|
||||
0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_sha1_round(const unsigned char *buf, uint32_t *val)
|
||||
{
|
||||
uint32_t m[80];
|
||||
uint32_t a, b, c, d, e;
|
||||
int i;
|
||||
|
||||
a = val[0];
|
||||
b = val[1];
|
||||
c = val[2];
|
||||
d = val[3];
|
||||
e = val[4];
|
||||
br_range_dec32be(m, 16, buf);
|
||||
for (i = 16; i < 80; i ++) {
|
||||
uint32_t x = m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16];
|
||||
m[i] = ROTL(x, 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < 20; i += 5) {
|
||||
e += ROTL(a, 5) + F(b, c, d) + K1 + m[i + 0]; b = ROTL(b, 30);
|
||||
d += ROTL(e, 5) + F(a, b, c) + K1 + m[i + 1]; a = ROTL(a, 30);
|
||||
c += ROTL(d, 5) + F(e, a, b) + K1 + m[i + 2]; e = ROTL(e, 30);
|
||||
b += ROTL(c, 5) + F(d, e, a) + K1 + m[i + 3]; d = ROTL(d, 30);
|
||||
a += ROTL(b, 5) + F(c, d, e) + K1 + m[i + 4]; c = ROTL(c, 30);
|
||||
}
|
||||
for (i = 20; i < 40; i += 5) {
|
||||
e += ROTL(a, 5) + G(b, c, d) + K2 + m[i + 0]; b = ROTL(b, 30);
|
||||
d += ROTL(e, 5) + G(a, b, c) + K2 + m[i + 1]; a = ROTL(a, 30);
|
||||
c += ROTL(d, 5) + G(e, a, b) + K2 + m[i + 2]; e = ROTL(e, 30);
|
||||
b += ROTL(c, 5) + G(d, e, a) + K2 + m[i + 3]; d = ROTL(d, 30);
|
||||
a += ROTL(b, 5) + G(c, d, e) + K2 + m[i + 4]; c = ROTL(c, 30);
|
||||
}
|
||||
for (i = 40; i < 60; i += 5) {
|
||||
e += ROTL(a, 5) + H(b, c, d) + K3 + m[i + 0]; b = ROTL(b, 30);
|
||||
d += ROTL(e, 5) + H(a, b, c) + K3 + m[i + 1]; a = ROTL(a, 30);
|
||||
c += ROTL(d, 5) + H(e, a, b) + K3 + m[i + 2]; e = ROTL(e, 30);
|
||||
b += ROTL(c, 5) + H(d, e, a) + K3 + m[i + 3]; d = ROTL(d, 30);
|
||||
a += ROTL(b, 5) + H(c, d, e) + K3 + m[i + 4]; c = ROTL(c, 30);
|
||||
}
|
||||
for (i = 60; i < 80; i += 5) {
|
||||
e += ROTL(a, 5) + I(b, c, d) + K4 + m[i + 0]; b = ROTL(b, 30);
|
||||
d += ROTL(e, 5) + I(a, b, c) + K4 + m[i + 1]; a = ROTL(a, 30);
|
||||
c += ROTL(d, 5) + I(e, a, b) + K4 + m[i + 2]; e = ROTL(e, 30);
|
||||
b += ROTL(c, 5) + I(d, e, a) + K4 + m[i + 3]; d = ROTL(d, 30);
|
||||
a += ROTL(b, 5) + I(c, d, e) + K4 + m[i + 4]; c = ROTL(c, 30);
|
||||
}
|
||||
|
||||
val[0] += a;
|
||||
val[1] += b;
|
||||
val[2] += c;
|
||||
val[3] += d;
|
||||
val[4] += e;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha1_init(br_sha1_context *cc)
|
||||
{
|
||||
cc->vtable = &br_sha1_vtable;
|
||||
memcpy(cc->val, br_sha1_IV, sizeof cc->val);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha1_update(br_sha1_context *cc, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)cc->count & 63;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 64 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(cc->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
cc->count += (uint64_t)clen;
|
||||
if (ptr == 64) {
|
||||
br_sha1_round(cc->buf, cc->val);
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha1_out(const br_sha1_context *cc, void *dst)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
uint32_t val[5];
|
||||
size_t ptr;
|
||||
|
||||
ptr = (size_t)cc->count & 63;
|
||||
memcpy(buf, cc->buf, ptr);
|
||||
memcpy(val, cc->val, sizeof val);
|
||||
buf[ptr ++] = 0x80;
|
||||
if (ptr > 56) {
|
||||
memset(buf + ptr, 0, 64 - ptr);
|
||||
br_sha1_round(buf, val);
|
||||
memset(buf, 0, 56);
|
||||
} else {
|
||||
memset(buf + ptr, 0, 56 - ptr);
|
||||
}
|
||||
br_enc64be(buf + 56, cc->count << 3);
|
||||
br_sha1_round(buf, val);
|
||||
br_range_enc32be(dst, val, 5);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
uint64_t
|
||||
br_sha1_state(const br_sha1_context *cc, void *dst)
|
||||
{
|
||||
br_range_enc32be(dst, cc->val, 5);
|
||||
return cc->count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha1_set_state(br_sha1_context *cc, const void *stb, uint64_t count)
|
||||
{
|
||||
br_range_dec32be(cc->val, 5, stb);
|
||||
cc->count = count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_sha1_vtable = {
|
||||
sizeof(br_sha1_context),
|
||||
BR_HASHDESC_ID(br_sha1_ID)
|
||||
| BR_HASHDESC_OUT(20)
|
||||
| BR_HASHDESC_STATE(20)
|
||||
| BR_HASHDESC_LBLEN(6)
|
||||
| BR_HASHDESC_MD_PADDING
|
||||
| BR_HASHDESC_MD_PADDING_BE,
|
||||
(void (*)(const br_hash_class **))&br_sha1_init,
|
||||
(void (*)(const br_hash_class **, const void *, size_t))&br_sha1_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_sha1_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_sha1_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_sha1_set_state
|
||||
};
|
||||
285
dstalk-core/thirdparty/bearssl/src/hash/sha2big.c
vendored
285
dstalk-core/thirdparty/bearssl/src/hash/sha2big.c
vendored
@@ -1,285 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z))
|
||||
#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X)))
|
||||
|
||||
#define ROTR(x, n) (((uint64_t)(x) << (64 - (n))) | ((uint64_t)(x) >> (n)))
|
||||
|
||||
#define BSG5_0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
|
||||
#define BSG5_1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
|
||||
#define SSG5_0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ (uint64_t)((x) >> 7))
|
||||
#define SSG5_1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ (uint64_t)((x) >> 6))
|
||||
|
||||
static const uint64_t IV384[8] = {
|
||||
0xCBBB9D5DC1059ED8, 0x629A292A367CD507,
|
||||
0x9159015A3070DD17, 0x152FECD8F70E5939,
|
||||
0x67332667FFC00B31, 0x8EB44A8768581511,
|
||||
0xDB0C2E0D64F98FA7, 0x47B5481DBEFA4FA4
|
||||
};
|
||||
|
||||
static const uint64_t IV512[8] = {
|
||||
0x6A09E667F3BCC908, 0xBB67AE8584CAA73B,
|
||||
0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1,
|
||||
0x510E527FADE682D1, 0x9B05688C2B3E6C1F,
|
||||
0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179
|
||||
};
|
||||
|
||||
static const uint64_t K[80] = {
|
||||
0x428A2F98D728AE22, 0x7137449123EF65CD,
|
||||
0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC,
|
||||
0x3956C25BF348B538, 0x59F111F1B605D019,
|
||||
0x923F82A4AF194F9B, 0xAB1C5ED5DA6D8118,
|
||||
0xD807AA98A3030242, 0x12835B0145706FBE,
|
||||
0x243185BE4EE4B28C, 0x550C7DC3D5FFB4E2,
|
||||
0x72BE5D74F27B896F, 0x80DEB1FE3B1696B1,
|
||||
0x9BDC06A725C71235, 0xC19BF174CF692694,
|
||||
0xE49B69C19EF14AD2, 0xEFBE4786384F25E3,
|
||||
0x0FC19DC68B8CD5B5, 0x240CA1CC77AC9C65,
|
||||
0x2DE92C6F592B0275, 0x4A7484AA6EA6E483,
|
||||
0x5CB0A9DCBD41FBD4, 0x76F988DA831153B5,
|
||||
0x983E5152EE66DFAB, 0xA831C66D2DB43210,
|
||||
0xB00327C898FB213F, 0xBF597FC7BEEF0EE4,
|
||||
0xC6E00BF33DA88FC2, 0xD5A79147930AA725,
|
||||
0x06CA6351E003826F, 0x142929670A0E6E70,
|
||||
0x27B70A8546D22FFC, 0x2E1B21385C26C926,
|
||||
0x4D2C6DFC5AC42AED, 0x53380D139D95B3DF,
|
||||
0x650A73548BAF63DE, 0x766A0ABB3C77B2A8,
|
||||
0x81C2C92E47EDAEE6, 0x92722C851482353B,
|
||||
0xA2BFE8A14CF10364, 0xA81A664BBC423001,
|
||||
0xC24B8B70D0F89791, 0xC76C51A30654BE30,
|
||||
0xD192E819D6EF5218, 0xD69906245565A910,
|
||||
0xF40E35855771202A, 0x106AA07032BBD1B8,
|
||||
0x19A4C116B8D2D0C8, 0x1E376C085141AB53,
|
||||
0x2748774CDF8EEB99, 0x34B0BCB5E19B48A8,
|
||||
0x391C0CB3C5C95A63, 0x4ED8AA4AE3418ACB,
|
||||
0x5B9CCA4F7763E373, 0x682E6FF3D6B2B8A3,
|
||||
0x748F82EE5DEFB2FC, 0x78A5636F43172F60,
|
||||
0x84C87814A1F0AB72, 0x8CC702081A6439EC,
|
||||
0x90BEFFFA23631E28, 0xA4506CEBDE82BDE9,
|
||||
0xBEF9A3F7B2C67915, 0xC67178F2E372532B,
|
||||
0xCA273ECEEA26619C, 0xD186B8C721C0C207,
|
||||
0xEADA7DD6CDE0EB1E, 0xF57D4F7FEE6ED178,
|
||||
0x06F067AA72176FBA, 0x0A637DC5A2C898A6,
|
||||
0x113F9804BEF90DAE, 0x1B710B35131C471B,
|
||||
0x28DB77F523047D84, 0x32CAAB7B40C72493,
|
||||
0x3C9EBE0A15C9BEBC, 0x431D67C49C100D4C,
|
||||
0x4CC5D4BECB3E42B6, 0x597F299CFC657E2A,
|
||||
0x5FCB6FAB3AD6FAEC, 0x6C44198C4A475817
|
||||
};
|
||||
|
||||
static void
|
||||
sha2big_round(const unsigned char *buf, uint64_t *val)
|
||||
{
|
||||
|
||||
#define SHA2BIG_STEP(A, B, C, D, E, F, G, H, j) do { \
|
||||
uint64_t T1, T2; \
|
||||
T1 = H + BSG5_1(E) + CH(E, F, G) + K[j] + w[j]; \
|
||||
T2 = BSG5_0(A) + MAJ(A, B, C); \
|
||||
D += T1; \
|
||||
H = T1 + T2; \
|
||||
} while (0)
|
||||
|
||||
int i;
|
||||
uint64_t a, b, c, d, e, f, g, h;
|
||||
uint64_t w[80];
|
||||
|
||||
br_range_dec64be(w, 16, buf);
|
||||
for (i = 16; i < 80; i ++) {
|
||||
w[i] = SSG5_1(w[i - 2]) + w[i - 7]
|
||||
+ SSG5_0(w[i - 15]) + w[i - 16];
|
||||
}
|
||||
a = val[0];
|
||||
b = val[1];
|
||||
c = val[2];
|
||||
d = val[3];
|
||||
e = val[4];
|
||||
f = val[5];
|
||||
g = val[6];
|
||||
h = val[7];
|
||||
for (i = 0; i < 80; i += 8) {
|
||||
SHA2BIG_STEP(a, b, c, d, e, f, g, h, i + 0);
|
||||
SHA2BIG_STEP(h, a, b, c, d, e, f, g, i + 1);
|
||||
SHA2BIG_STEP(g, h, a, b, c, d, e, f, i + 2);
|
||||
SHA2BIG_STEP(f, g, h, a, b, c, d, e, i + 3);
|
||||
SHA2BIG_STEP(e, f, g, h, a, b, c, d, i + 4);
|
||||
SHA2BIG_STEP(d, e, f, g, h, a, b, c, i + 5);
|
||||
SHA2BIG_STEP(c, d, e, f, g, h, a, b, i + 6);
|
||||
SHA2BIG_STEP(b, c, d, e, f, g, h, a, i + 7);
|
||||
}
|
||||
val[0] += a;
|
||||
val[1] += b;
|
||||
val[2] += c;
|
||||
val[3] += d;
|
||||
val[4] += e;
|
||||
val[5] += f;
|
||||
val[6] += g;
|
||||
val[7] += h;
|
||||
}
|
||||
|
||||
static void
|
||||
sha2big_update(br_sha384_context *cc, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)cc->count & 127;
|
||||
cc->count += (uint64_t)len;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 128 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(cc->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
if (ptr == 128) {
|
||||
sha2big_round(cc->buf, cc->val);
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sha2big_out(const br_sha384_context *cc, void *dst, int num)
|
||||
{
|
||||
unsigned char buf[128];
|
||||
uint64_t val[8];
|
||||
size_t ptr;
|
||||
|
||||
ptr = (size_t)cc->count & 127;
|
||||
memcpy(buf, cc->buf, ptr);
|
||||
memcpy(val, cc->val, sizeof val);
|
||||
buf[ptr ++] = 0x80;
|
||||
if (ptr > 112) {
|
||||
memset(buf + ptr, 0, 128 - ptr);
|
||||
sha2big_round(buf, val);
|
||||
memset(buf, 0, 112);
|
||||
} else {
|
||||
memset(buf + ptr, 0, 112 - ptr);
|
||||
}
|
||||
br_enc64be(buf + 112, cc->count >> 61);
|
||||
br_enc64be(buf + 120, cc->count << 3);
|
||||
sha2big_round(buf, val);
|
||||
br_range_enc64be(dst, val, num);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha384_init(br_sha384_context *cc)
|
||||
{
|
||||
cc->vtable = &br_sha384_vtable;
|
||||
memcpy(cc->val, IV384, sizeof IV384);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha384_update(br_sha384_context *cc, const void *data, size_t len)
|
||||
{
|
||||
sha2big_update(cc, data, len);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha384_out(const br_sha384_context *cc, void *dst)
|
||||
{
|
||||
sha2big_out(cc, dst, 6);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
uint64_t
|
||||
br_sha384_state(const br_sha384_context *cc, void *dst)
|
||||
{
|
||||
br_range_enc64be(dst, cc->val, 8);
|
||||
return cc->count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha384_set_state(br_sha384_context *cc, const void *stb, uint64_t count)
|
||||
{
|
||||
br_range_dec64be(cc->val, 8, stb);
|
||||
cc->count = count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha512_init(br_sha512_context *cc)
|
||||
{
|
||||
cc->vtable = &br_sha512_vtable;
|
||||
memcpy(cc->val, IV512, sizeof IV512);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha512_out(const br_sha512_context *cc, void *dst)
|
||||
{
|
||||
sha2big_out(cc, dst, 8);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_sha384_vtable = {
|
||||
sizeof(br_sha384_context),
|
||||
BR_HASHDESC_ID(br_sha384_ID)
|
||||
| BR_HASHDESC_OUT(48)
|
||||
| BR_HASHDESC_STATE(64)
|
||||
| BR_HASHDESC_LBLEN(7)
|
||||
| BR_HASHDESC_MD_PADDING
|
||||
| BR_HASHDESC_MD_PADDING_BE
|
||||
| BR_HASHDESC_MD_PADDING_128,
|
||||
(void (*)(const br_hash_class **))&br_sha384_init,
|
||||
(void (*)(const br_hash_class **, const void *, size_t))
|
||||
&br_sha384_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_sha384_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_sha384_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_sha384_set_state
|
||||
};
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_sha512_vtable = {
|
||||
sizeof(br_sha512_context),
|
||||
BR_HASHDESC_ID(br_sha512_ID)
|
||||
| BR_HASHDESC_OUT(64)
|
||||
| BR_HASHDESC_STATE(64)
|
||||
| BR_HASHDESC_LBLEN(7)
|
||||
| BR_HASHDESC_MD_PADDING
|
||||
| BR_HASHDESC_MD_PADDING_BE
|
||||
| BR_HASHDESC_MD_PADDING_128,
|
||||
(void (*)(const br_hash_class **))&br_sha512_init,
|
||||
(void (*)(const br_hash_class **, const void *, size_t))
|
||||
&br_sha512_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_sha512_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_sha512_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_sha512_set_state
|
||||
};
|
||||
341
dstalk-core/thirdparty/bearssl/src/hash/sha2small.c
vendored
341
dstalk-core/thirdparty/bearssl/src/hash/sha2small.c
vendored
@@ -1,341 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z))
|
||||
#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X)))
|
||||
|
||||
#define ROTR(x, n) (((uint32_t)(x) << (32 - (n))) | ((uint32_t)(x) >> (n)))
|
||||
|
||||
#define BSG2_0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define BSG2_1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define SSG2_0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ (uint32_t)((x) >> 3))
|
||||
#define SSG2_1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ (uint32_t)((x) >> 10))
|
||||
|
||||
/* see inner.h */
|
||||
const uint32_t br_sha224_IV[8] = {
|
||||
0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
|
||||
0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const uint32_t br_sha256_IV[8] = {
|
||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
||||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
|
||||
};
|
||||
|
||||
static const uint32_t K[64] = {
|
||||
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
|
||||
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
|
||||
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
|
||||
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
|
||||
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
|
||||
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
|
||||
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
|
||||
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
|
||||
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
|
||||
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
|
||||
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
|
||||
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
|
||||
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
|
||||
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
|
||||
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
|
||||
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_sha2small_round(const unsigned char *buf, uint32_t *val)
|
||||
{
|
||||
|
||||
#define SHA2_STEP(A, B, C, D, E, F, G, H, j) do { \
|
||||
uint32_t T1, T2; \
|
||||
T1 = H + BSG2_1(E) + CH(E, F, G) + K[j] + w[j]; \
|
||||
T2 = BSG2_0(A) + MAJ(A, B, C); \
|
||||
D += T1; \
|
||||
H = T1 + T2; \
|
||||
} while (0)
|
||||
|
||||
int i;
|
||||
uint32_t a, b, c, d, e, f, g, h;
|
||||
uint32_t w[64];
|
||||
|
||||
br_range_dec32be(w, 16, buf);
|
||||
for (i = 16; i < 64; i ++) {
|
||||
w[i] = SSG2_1(w[i - 2]) + w[i - 7]
|
||||
+ SSG2_0(w[i - 15]) + w[i - 16];
|
||||
}
|
||||
a = val[0];
|
||||
b = val[1];
|
||||
c = val[2];
|
||||
d = val[3];
|
||||
e = val[4];
|
||||
f = val[5];
|
||||
g = val[6];
|
||||
h = val[7];
|
||||
for (i = 0; i < 64; i += 8) {
|
||||
SHA2_STEP(a, b, c, d, e, f, g, h, i + 0);
|
||||
SHA2_STEP(h, a, b, c, d, e, f, g, i + 1);
|
||||
SHA2_STEP(g, h, a, b, c, d, e, f, i + 2);
|
||||
SHA2_STEP(f, g, h, a, b, c, d, e, i + 3);
|
||||
SHA2_STEP(e, f, g, h, a, b, c, d, i + 4);
|
||||
SHA2_STEP(d, e, f, g, h, a, b, c, i + 5);
|
||||
SHA2_STEP(c, d, e, f, g, h, a, b, i + 6);
|
||||
SHA2_STEP(b, c, d, e, f, g, h, a, i + 7);
|
||||
}
|
||||
val[0] += a;
|
||||
val[1] += b;
|
||||
val[2] += c;
|
||||
val[3] += d;
|
||||
val[4] += e;
|
||||
val[5] += f;
|
||||
val[6] += g;
|
||||
val[7] += h;
|
||||
|
||||
#if 0
|
||||
/* obsolete */
|
||||
#define SHA2_MEXP1(pc) do { \
|
||||
W[pc] = br_dec32be(buf + ((pc) << 2)); \
|
||||
} while (0)
|
||||
|
||||
#define SHA2_MEXP2(pc) do { \
|
||||
W[(pc) & 0x0F] = SSG2_1(W[((pc) - 2) & 0x0F]) \
|
||||
+ W[((pc) - 7) & 0x0F] \
|
||||
+ SSG2_0(W[((pc) - 15) & 0x0F]) + W[(pc) & 0x0F]; \
|
||||
} while (0)
|
||||
|
||||
#define SHA2_STEPn(n, a, b, c, d, e, f, g, h, pc) do { \
|
||||
uint32_t t1, t2; \
|
||||
SHA2_MEXP ## n(pc); \
|
||||
t1 = h + BSG2_1(e) + CH(e, f, g) \
|
||||
+ K[pcount + (pc)] + W[(pc) & 0x0F]; \
|
||||
t2 = BSG2_0(a) + MAJ(a, b, c); \
|
||||
d += t1; \
|
||||
h = t1 + t2; \
|
||||
} while (0)
|
||||
|
||||
#define SHA2_STEP1(a, b, c, d, e, f, g, h, pc) \
|
||||
SHA2_STEPn(1, a, b, c, d, e, f, g, h, pc)
|
||||
#define SHA2_STEP2(a, b, c, d, e, f, g, h, pc) \
|
||||
SHA2_STEPn(2, a, b, c, d, e, f, g, h, pc)
|
||||
|
||||
uint32_t A, B, C, D, E, F, G, H;
|
||||
uint32_t W[16];
|
||||
unsigned pcount;
|
||||
|
||||
A = val[0];
|
||||
B = val[1];
|
||||
C = val[2];
|
||||
D = val[3];
|
||||
E = val[4];
|
||||
F = val[5];
|
||||
G = val[6];
|
||||
H = val[7];
|
||||
pcount = 0;
|
||||
SHA2_STEP1(A, B, C, D, E, F, G, H, 0);
|
||||
SHA2_STEP1(H, A, B, C, D, E, F, G, 1);
|
||||
SHA2_STEP1(G, H, A, B, C, D, E, F, 2);
|
||||
SHA2_STEP1(F, G, H, A, B, C, D, E, 3);
|
||||
SHA2_STEP1(E, F, G, H, A, B, C, D, 4);
|
||||
SHA2_STEP1(D, E, F, G, H, A, B, C, 5);
|
||||
SHA2_STEP1(C, D, E, F, G, H, A, B, 6);
|
||||
SHA2_STEP1(B, C, D, E, F, G, H, A, 7);
|
||||
SHA2_STEP1(A, B, C, D, E, F, G, H, 8);
|
||||
SHA2_STEP1(H, A, B, C, D, E, F, G, 9);
|
||||
SHA2_STEP1(G, H, A, B, C, D, E, F, 10);
|
||||
SHA2_STEP1(F, G, H, A, B, C, D, E, 11);
|
||||
SHA2_STEP1(E, F, G, H, A, B, C, D, 12);
|
||||
SHA2_STEP1(D, E, F, G, H, A, B, C, 13);
|
||||
SHA2_STEP1(C, D, E, F, G, H, A, B, 14);
|
||||
SHA2_STEP1(B, C, D, E, F, G, H, A, 15);
|
||||
for (pcount = 16; pcount < 64; pcount += 16) {
|
||||
SHA2_STEP2(A, B, C, D, E, F, G, H, 0);
|
||||
SHA2_STEP2(H, A, B, C, D, E, F, G, 1);
|
||||
SHA2_STEP2(G, H, A, B, C, D, E, F, 2);
|
||||
SHA2_STEP2(F, G, H, A, B, C, D, E, 3);
|
||||
SHA2_STEP2(E, F, G, H, A, B, C, D, 4);
|
||||
SHA2_STEP2(D, E, F, G, H, A, B, C, 5);
|
||||
SHA2_STEP2(C, D, E, F, G, H, A, B, 6);
|
||||
SHA2_STEP2(B, C, D, E, F, G, H, A, 7);
|
||||
SHA2_STEP2(A, B, C, D, E, F, G, H, 8);
|
||||
SHA2_STEP2(H, A, B, C, D, E, F, G, 9);
|
||||
SHA2_STEP2(G, H, A, B, C, D, E, F, 10);
|
||||
SHA2_STEP2(F, G, H, A, B, C, D, E, 11);
|
||||
SHA2_STEP2(E, F, G, H, A, B, C, D, 12);
|
||||
SHA2_STEP2(D, E, F, G, H, A, B, C, 13);
|
||||
SHA2_STEP2(C, D, E, F, G, H, A, B, 14);
|
||||
SHA2_STEP2(B, C, D, E, F, G, H, A, 15);
|
||||
}
|
||||
val[0] += A;
|
||||
val[1] += B;
|
||||
val[2] += C;
|
||||
val[3] += D;
|
||||
val[4] += E;
|
||||
val[5] += F;
|
||||
val[6] += G;
|
||||
val[7] += H;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
sha2small_update(br_sha224_context *cc, const void *data, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t ptr;
|
||||
|
||||
buf = data;
|
||||
ptr = (size_t)cc->count & 63;
|
||||
cc->count += (uint64_t)len;
|
||||
while (len > 0) {
|
||||
size_t clen;
|
||||
|
||||
clen = 64 - ptr;
|
||||
if (clen > len) {
|
||||
clen = len;
|
||||
}
|
||||
memcpy(cc->buf + ptr, buf, clen);
|
||||
ptr += clen;
|
||||
buf += clen;
|
||||
len -= clen;
|
||||
if (ptr == 64) {
|
||||
br_sha2small_round(cc->buf, cc->val);
|
||||
ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sha2small_out(const br_sha224_context *cc, void *dst, int num)
|
||||
{
|
||||
unsigned char buf[64];
|
||||
uint32_t val[8];
|
||||
size_t ptr;
|
||||
|
||||
ptr = (size_t)cc->count & 63;
|
||||
memcpy(buf, cc->buf, ptr);
|
||||
memcpy(val, cc->val, sizeof val);
|
||||
buf[ptr ++] = 0x80;
|
||||
if (ptr > 56) {
|
||||
memset(buf + ptr, 0, 64 - ptr);
|
||||
br_sha2small_round(buf, val);
|
||||
memset(buf, 0, 56);
|
||||
} else {
|
||||
memset(buf + ptr, 0, 56 - ptr);
|
||||
}
|
||||
br_enc64be(buf + 56, cc->count << 3);
|
||||
br_sha2small_round(buf, val);
|
||||
br_range_enc32be(dst, val, num);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha224_init(br_sha224_context *cc)
|
||||
{
|
||||
cc->vtable = &br_sha224_vtable;
|
||||
memcpy(cc->val, br_sha224_IV, sizeof cc->val);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha224_update(br_sha224_context *cc, const void *data, size_t len)
|
||||
{
|
||||
sha2small_update(cc, data, len);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha224_out(const br_sha224_context *cc, void *dst)
|
||||
{
|
||||
sha2small_out(cc, dst, 7);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
uint64_t
|
||||
br_sha224_state(const br_sha224_context *cc, void *dst)
|
||||
{
|
||||
br_range_enc32be(dst, cc->val, 8);
|
||||
return cc->count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha224_set_state(br_sha224_context *cc, const void *stb, uint64_t count)
|
||||
{
|
||||
br_range_dec32be(cc->val, 8, stb);
|
||||
cc->count = count;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha256_init(br_sha256_context *cc)
|
||||
{
|
||||
cc->vtable = &br_sha256_vtable;
|
||||
memcpy(cc->val, br_sha256_IV, sizeof cc->val);
|
||||
cc->count = 0;
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
void
|
||||
br_sha256_out(const br_sha256_context *cc, void *dst)
|
||||
{
|
||||
sha2small_out(cc, dst, 8);
|
||||
}
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_sha224_vtable = {
|
||||
sizeof(br_sha224_context),
|
||||
BR_HASHDESC_ID(br_sha224_ID)
|
||||
| BR_HASHDESC_OUT(28)
|
||||
| BR_HASHDESC_STATE(32)
|
||||
| BR_HASHDESC_LBLEN(6)
|
||||
| BR_HASHDESC_MD_PADDING
|
||||
| BR_HASHDESC_MD_PADDING_BE,
|
||||
(void (*)(const br_hash_class **))&br_sha224_init,
|
||||
(void (*)(const br_hash_class **,
|
||||
const void *, size_t))&br_sha224_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_sha224_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_sha224_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_sha224_set_state
|
||||
};
|
||||
|
||||
/* see bearssl.h */
|
||||
const br_hash_class br_sha256_vtable = {
|
||||
sizeof(br_sha256_context),
|
||||
BR_HASHDESC_ID(br_sha256_ID)
|
||||
| BR_HASHDESC_OUT(32)
|
||||
| BR_HASHDESC_STATE(32)
|
||||
| BR_HASHDESC_LBLEN(6)
|
||||
| BR_HASHDESC_MD_PADDING
|
||||
| BR_HASHDESC_MD_PADDING_BE,
|
||||
(void (*)(const br_hash_class **))&br_sha256_init,
|
||||
(void (*)(const br_hash_class **,
|
||||
const void *, size_t))&br_sha256_update,
|
||||
(void (*)(const br_hash_class *const *, void *))&br_sha256_out,
|
||||
(uint64_t (*)(const br_hash_class *const *, void *))&br_sha256_state,
|
||||
(void (*)(const br_hash_class **, const void *, uint64_t))
|
||||
&br_sha256_set_state
|
||||
};
|
||||
2532
dstalk-core/thirdparty/bearssl/src/inner.h
vendored
2532
dstalk-core/thirdparty/bearssl/src/inner.h
vendored
File diff suppressed because it is too large
Load Diff
46
dstalk-core/thirdparty/bearssl/src/int/i15_add.c
vendored
46
dstalk-core/thirdparty/bearssl/src/int/i15_add.c
vendored
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl)
|
||||
{
|
||||
uint32_t cc;
|
||||
size_t u, m;
|
||||
|
||||
cc = 0;
|
||||
m = (a[0] + 31) >> 4;
|
||||
for (u = 1; u < m; u ++) {
|
||||
uint32_t aw, bw, naw;
|
||||
|
||||
aw = a[u];
|
||||
bw = b[u];
|
||||
naw = aw + bw + cc;
|
||||
cc = naw >> 15;
|
||||
a[u] = MUX(ctl, naw & 0x7FFF, aw);
|
||||
}
|
||||
return cc;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i15_bit_length(uint16_t *x, size_t xlen)
|
||||
{
|
||||
uint32_t tw, twk;
|
||||
|
||||
tw = 0;
|
||||
twk = 0;
|
||||
while (xlen -- > 0) {
|
||||
uint32_t w, c;
|
||||
|
||||
c = EQ(tw, 0);
|
||||
w = x[xlen];
|
||||
tw = MUX(c, w, tw);
|
||||
twk = MUX(c, (uint32_t)xlen, twk);
|
||||
}
|
||||
return (twk << 4) + BIT_LENGTH(tw);
|
||||
}
|
||||
124
dstalk-core/thirdparty/bearssl/src/int/i15_decmod.c
vendored
124
dstalk-core/thirdparty/bearssl/src/int/i15_decmod.c
vendored
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
uint32_t
|
||||
br_i15_decode_mod(uint16_t *x, const void *src, size_t len, const uint16_t *m)
|
||||
{
|
||||
/*
|
||||
* Two-pass algorithm: in the first pass, we determine whether the
|
||||
* value fits; in the second pass, we do the actual write.
|
||||
*
|
||||
* During the first pass, 'r' contains the comparison result so
|
||||
* far:
|
||||
* 0x00000000 value is equal to the modulus
|
||||
* 0x00000001 value is greater than the modulus
|
||||
* 0xFFFFFFFF value is lower than the modulus
|
||||
*
|
||||
* Since we iterate starting with the least significant bytes (at
|
||||
* the end of src[]), each new comparison overrides the previous
|
||||
* except when the comparison yields 0 (equal).
|
||||
*
|
||||
* During the second pass, 'r' is either 0xFFFFFFFF (value fits)
|
||||
* or 0x00000000 (value does not fit).
|
||||
*
|
||||
* We must iterate over all bytes of the source, _and_ possibly
|
||||
* some extra virtual bytes (with value 0) so as to cover the
|
||||
* complete modulus as well. We also add 4 such extra bytes beyond
|
||||
* the modulus length because it then guarantees that no accumulated
|
||||
* partial word remains to be processed.
|
||||
*/
|
||||
const unsigned char *buf;
|
||||
size_t mlen, tlen;
|
||||
int pass;
|
||||
uint32_t r;
|
||||
|
||||
buf = src;
|
||||
mlen = (m[0] + 15) >> 4;
|
||||
tlen = (mlen << 1);
|
||||
if (tlen < len) {
|
||||
tlen = len;
|
||||
}
|
||||
tlen += 4;
|
||||
r = 0;
|
||||
for (pass = 0; pass < 2; pass ++) {
|
||||
size_t u, v;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
v = 1;
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
for (u = 0; u < tlen; u ++) {
|
||||
uint32_t b;
|
||||
|
||||
if (u < len) {
|
||||
b = buf[len - 1 - u];
|
||||
} else {
|
||||
b = 0;
|
||||
}
|
||||
acc |= (b << acc_len);
|
||||
acc_len += 8;
|
||||
if (acc_len >= 15) {
|
||||
uint32_t xw;
|
||||
|
||||
xw = acc & (uint32_t)0x7FFF;
|
||||
acc_len -= 15;
|
||||
acc = b >> (8 - acc_len);
|
||||
if (v <= mlen) {
|
||||
if (pass) {
|
||||
x[v] = r & xw;
|
||||
} else {
|
||||
uint32_t cc;
|
||||
|
||||
cc = (uint32_t)CMP(xw, m[v]);
|
||||
r = MUX(EQ(cc, 0), r, cc);
|
||||
}
|
||||
} else {
|
||||
if (!pass) {
|
||||
r = MUX(EQ(xw, 0), r, 1);
|
||||
}
|
||||
}
|
||||
v ++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* When we reach this point at the end of the first pass:
|
||||
* r is either 0, 1 or -1; we want to set r to 0 if it
|
||||
* is equal to 0 or 1, and leave it to -1 otherwise.
|
||||
*
|
||||
* When we reach this point at the end of the second pass:
|
||||
* r is either 0 or -1; we want to leave that value
|
||||
* untouched. This is a subcase of the previous.
|
||||
*/
|
||||
r >>= 1;
|
||||
r |= (r << 1);
|
||||
}
|
||||
|
||||
x[0] = m[0];
|
||||
return r & (uint32_t)1;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_decode(uint16_t *x, const void *src, size_t len)
|
||||
{
|
||||
const unsigned char *buf;
|
||||
size_t v;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
buf = src;
|
||||
v = 1;
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
while (len -- > 0) {
|
||||
uint32_t b;
|
||||
|
||||
b = buf[len];
|
||||
acc |= (b << acc_len);
|
||||
acc_len += 8;
|
||||
if (acc_len >= 15) {
|
||||
x[v ++] = acc & 0x7FFF;
|
||||
acc_len -= 15;
|
||||
acc >>= 15;
|
||||
}
|
||||
}
|
||||
if (acc_len != 0) {
|
||||
x[v ++] = acc;
|
||||
}
|
||||
x[0] = br_i15_bit_length(x + 1, v - 1);
|
||||
}
|
||||
100
dstalk-core/thirdparty/bearssl/src/int/i15_decred.c
vendored
100
dstalk-core/thirdparty/bearssl/src/int/i15_decred.c
vendored
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_decode_reduce(uint16_t *x,
|
||||
const void *src, size_t len, const uint16_t *m)
|
||||
{
|
||||
uint32_t m_ebitlen, m_rbitlen;
|
||||
size_t mblen, k;
|
||||
const unsigned char *buf;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
/*
|
||||
* Get the encoded bit length.
|
||||
*/
|
||||
m_ebitlen = m[0];
|
||||
|
||||
/*
|
||||
* Special case for an invalid (null) modulus.
|
||||
*/
|
||||
if (m_ebitlen == 0) {
|
||||
x[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the destination.
|
||||
*/
|
||||
br_i15_zero(x, m_ebitlen);
|
||||
|
||||
/*
|
||||
* First decode directly as many bytes as possible. This requires
|
||||
* computing the actual bit length.
|
||||
*/
|
||||
m_rbitlen = m_ebitlen >> 4;
|
||||
m_rbitlen = (m_ebitlen & 15) + (m_rbitlen << 4) - m_rbitlen;
|
||||
mblen = (m_rbitlen + 7) >> 3;
|
||||
k = mblen - 1;
|
||||
if (k >= len) {
|
||||
br_i15_decode(x, src, len);
|
||||
x[0] = m_ebitlen;
|
||||
return;
|
||||
}
|
||||
buf = src;
|
||||
br_i15_decode(x, buf, k);
|
||||
x[0] = m_ebitlen;
|
||||
|
||||
/*
|
||||
* Input remaining bytes, using 15-bit words.
|
||||
*/
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
while (k < len) {
|
||||
uint32_t v;
|
||||
|
||||
v = buf[k ++];
|
||||
acc = (acc << 8) | v;
|
||||
acc_len += 8;
|
||||
if (acc_len >= 15) {
|
||||
br_i15_muladd_small(x, acc >> (acc_len - 15), m);
|
||||
acc_len -= 15;
|
||||
acc &= ~((uint32_t)-1 << acc_len);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We may have some bits accumulated. We then perform a shift to
|
||||
* be able to inject these bits as a full 15-bit word.
|
||||
*/
|
||||
if (acc_len != 0) {
|
||||
acc = (acc | (x[1] << acc_len)) & 0x7FFF;
|
||||
br_i15_rshift(x, 15 - acc_len);
|
||||
br_i15_muladd_small(x, acc, m);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_i15_encode(void *dst, size_t len, const uint16_t *x)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t u, xlen;
|
||||
uint32_t acc;
|
||||
int acc_len;
|
||||
|
||||
xlen = (x[0] + 15) >> 4;
|
||||
if (xlen == 0) {
|
||||
memset(dst, 0, len);
|
||||
return;
|
||||
}
|
||||
u = 1;
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
buf = dst;
|
||||
while (len -- > 0) {
|
||||
if (acc_len < 8) {
|
||||
if (u <= xlen) {
|
||||
acc += (uint32_t)x[u ++] << acc_len;
|
||||
}
|
||||
acc_len += 15;
|
||||
}
|
||||
buf[len] = (unsigned char)acc;
|
||||
acc >>= 8;
|
||||
acc_len -= 8;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user