Spectre integration WIP

This commit is contained in:
Jakub Hlusička 2026-01-19 20:13:25 +01:00
parent 24daa0ad29
commit c98acc4da4
25 changed files with 1334 additions and 25 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "firmware2/libxkbcommon"] [submodule "firmware2/libxkbcommon"]
path = firmware2/libxkbcommon path = firmware2/libxkbcommon
url = https://github.com/xkbcommon/libxkbcommon url = https://github.com/xkbcommon/libxkbcommon
[submodule "firmware2/spectre-api-c"]
path = firmware2/spectre-api-c
url = https://github.com/Limeth/spectre-api.git

View file

@ -13,18 +13,26 @@ rustflags = [
[env] [env]
LIBXKBCOMMON_BUILD_DIR = "libxkbcommon/build" LIBXKBCOMMON_BUILD_DIR = "libxkbcommon/build"
SPECTRE_API_BUILD_DIR = "spectre-api/build"
SPECTRE_API_SYS_CC = "xtensa-esp32s3-elf-cc.exe"
ESP_LOG = "warn" ESP_LOG = "warn"
# This is overkill, but we can afford it. # This is overkill, but we can afford it.
SLINT_FONT_SIZES = "8,11,10,12,13,14,15,16,18,20,22,24,32" SLINT_FONT_SIZES = "8,11,10,12,13,14,15,16,18,20,22,24,32"
# Xtensa only: # Xtensa only:
# Needed for nightly, until llvm upstream has support for Rust Xtensa. # Needed for nightly, until llvm upstream has support for Rust Xtensa.
[unstable] # TODO: RE-ENABLE WHEN acid-firmware IS MOVED TO ITS OWN SUBDIRECTORY.
build-std = ["alloc", "core"] # For now, `-Zbuild-std="core,alloc"` can be used instead.
# [unstable]
# build-std = ["alloc", "core"]
[patch."https://github.com/Limeth/spectre-api-sys"]
spectre-api-sys = { path = "../../../rust/spectre-api-sys" }
[patch.crates-io] [patch.crates-io]
rmk = { path = "../../../rust/rmk/rmk" } rmk = { path = "../../../rust/rmk/rmk" }
xkbcommon = { path = "../../../rust/xkbcommon-rs-ffi" } xkbcommon = { path = "../../../rust/xkbcommon-rs-ffi" }
scrypt = { path = "../../../rust/password-hashes/scrypt" }
# [patch.crates-io] # [patch.crates-io]
# esp-backtrace = { path = "../../../rust/esp-hal/esp-backtrace" } # esp-backtrace = { path = "../../../rust/esp-hal/esp-backtrace" }

164
firmware2/Cargo.lock generated
View file

@ -38,13 +38,16 @@ dependencies = [
"log", "log",
"mutually_exclusive_features", "mutually_exclusive_features",
"panic-rtt-target", "panic-rtt-target",
"password-hash 0.1.0",
"paste", "paste",
"printf-compat", "printf-compat",
"rand_core 0.6.4", "rand_core 0.6.4",
"rmk", "rmk",
"rtt-target", "rtt-target",
"sha2",
"slint", "slint",
"slint-build", "slint-build",
"spectre-api-sys",
"static_cell", "static_cell",
"xkbcommon 0.9.0 (git+https://github.com/Limeth/xkbcommon-rs?branch=esp32s3)", "xkbcommon 0.9.0 (git+https://github.com/Limeth/xkbcommon-rs?branch=esp32s3)",
"xz2", "xz2",
@ -186,6 +189,18 @@ dependencies = [
"syn 2.0.114", "syn 2.0.114",
] ]
[[package]]
name = "argon2"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072"
dependencies = [
"base64ct",
"blake2",
"cpufeatures",
"password-hash 0.5.0",
]
[[package]] [[package]]
name = "arraydeque" name = "arraydeque"
version = "0.5.1" version = "0.5.1"
@ -447,6 +462,12 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64ct"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]] [[package]]
name = "bincode" name = "bincode"
version = "2.0.1" version = "2.0.1"
@ -550,6 +571,15 @@ dependencies = [
"core2", "core2",
] ]
[[package]]
name = "blake2"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
dependencies = [
"digest",
]
[[package]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.10.4" version = "0.10.4"
@ -1482,6 +1512,18 @@ dependencies = [
"linux-raw-sys 0.6.5", "linux-raw-sys 0.6.5",
] ]
[[package]]
name = "duct"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e66e9c0c03d094e1a0ba1be130b849034aa80c3a2ab8ee94316bc809f3fa684"
dependencies = [
"libc",
"os_pipe",
"shared_child",
"shared_thread",
]
[[package]] [[package]]
name = "dunce" name = "dunce"
version = "1.0.5" version = "1.0.5"
@ -5245,6 +5287,16 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
] ]
[[package]]
name = "os_pipe"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
dependencies = [
"libc",
"windows-sys 0.61.2",
]
[[package]] [[package]]
name = "p256" name = "p256"
version = "0.13.2" version = "0.13.2"
@ -5309,6 +5361,27 @@ dependencies = [
"swash", "swash",
] ]
[[package]]
name = "password-hash"
version = "0.1.0"
dependencies = [
"argon2",
"itertools 0.14.0",
"scrypt",
"spectre-api-sys",
]
[[package]]
name = "password-hash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
dependencies = [
"base64ct",
"rand_core 0.6.4",
"subtle",
]
[[package]] [[package]]
name = "paste" name = "paste"
version = "1.0.15" version = "1.0.15"
@ -5327,6 +5400,16 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
[[package]]
name = "pbkdf2"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest",
"hmac",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.3.2" version = "2.3.2"
@ -6178,7 +6261,7 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys 0.4.15", "linux-raw-sys 0.4.15",
"windows-sys 0.59.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -6224,6 +6307,15 @@ version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984"
[[package]]
name = "salsa20"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213"
dependencies = [
"cipher",
]
[[package]] [[package]]
name = "same-file" name = "same-file"
version = "1.0.6" version = "1.0.6"
@ -6245,6 +6337,17 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "scrypt"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f"
dependencies = [
"pbkdf2",
"salsa20",
"sha2",
]
[[package]] [[package]]
name = "sec1" name = "sec1"
version = "0.7.3" version = "0.7.3"
@ -6425,6 +6528,23 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "shared_child"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e362d9935bc50f019969e2f9ecd66786612daae13e8f277be7bfb66e8bed3f7"
dependencies = [
"libc",
"sigchld",
"windows-sys 0.60.2",
]
[[package]]
name = "shared_thread"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52b86057fcb5423f5018e331ac04623e32d6b5ce85e33300f92c79a1973928b0"
[[package]] [[package]]
name = "shell-words" name = "shell-words"
version = "1.1.1" version = "1.1.1"
@ -6437,6 +6557,27 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "sigchld"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47106eded3c154e70176fc83df9737335c94ce22f821c32d17ed1db1f83badb1"
dependencies = [
"libc",
"os_pipe",
"signal-hook",
]
[[package]]
name = "signal-hook"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.8" version = "1.4.8"
@ -6635,6 +6776,14 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0f368519fc6c85fc1afdb769fb5a51123f6158013e143656e25a3485a0d401c" checksum = "a0f368519fc6c85fc1afdb769fb5a51123f6158013e143656e25a3485a0d401c"
[[package]]
name = "spectre-api-sys"
version = "0.1.0"
dependencies = [
"bindgen",
"duct",
]
[[package]] [[package]]
name = "spin" name = "spin"
version = "0.9.8" version = "0.9.8"
@ -7807,15 +7956,6 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.60.2" version = "0.60.2"
@ -8553,3 +8693,7 @@ dependencies = [
"syn 2.0.114", "syn 2.0.114",
"winnow", "winnow",
] ]
[[patch.unused]]
name = "scrypt"
version = "0.12.0-rc.8"

View file

@ -1,3 +1,7 @@
[workspace]
resolver = "3"
members = ["password-hash"]
[package] [package]
name = "acid-firmware" name = "acid-firmware"
version = "0.1.0" version = "0.1.0"
@ -71,6 +75,9 @@ rtt-target = { version = "0.6.2", features = ["log"], optional = true }
panic-rtt-target = { version = "0.2.0", optional = true } panic-rtt-target = { version = "0.2.0", optional = true }
enumset = "1.1.10" enumset = "1.1.10"
printf-compat = { version = "0.2.1", default-features = false } printf-compat = { version = "0.2.1", default-features = false }
spectre-api-sys = { git = "https://github.com/Limeth/spectre-api-sys" }
sha2 = { version = "0.10.9", default-features = false }
password-hash = { path = "password-hash" }
# Crates for serial UART CLI # Crates for serial UART CLI
embedded-cli = { version = "0.2.1", default-features = false, features = ["help", "macros"] } embedded-cli = { version = "0.2.1", default-features = false, features = ["help", "macros"] }

View file

@ -55,6 +55,10 @@ fn main() {
println!("cargo:rustc-link-lib=static=xkbcommon"); println!("cargo:rustc-link-lib=static=xkbcommon");
println!("cargo:rerun-if-changed={libxkbcommon_build_dir}/libxkbcommon.a"); println!("cargo:rerun-if-changed={libxkbcommon_build_dir}/libxkbcommon.a");
println!("cargo:rustc-link-search=native=../../../c/spectre-cli-linux/api/build");
println!("cargo:rustc-link-lib=static=spectre");
println!("cargo:rerun-if-changed=../../../c/spectre-cli-linux/api/build/libspectre.a");
// Slint config and compilation // Slint config and compilation
{ {
// Don't think this does anything: // Don't think this does anything:

View file

@ -0,0 +1,2 @@
#!/usr/bin/env bash
env CC=xtensa-esp32s3-elf-gcc CFLAGS="-ffreestanding -fno-builtin -mlongcalls" LDFLAGS="-nostdlib -static" ./configure --host xtensa-esp32s3 --disable-shared --enable-static --prefix="$PWD/install"

View file

@ -24,7 +24,7 @@ pushd "$LIBXKBCOMMON_DIR" >/dev/null
-Dx-locale-root=/usr/share/X11/locale \ -Dx-locale-root=/usr/share/X11/locale \
$SETUP_ARGS $SETUP_ARGS
meson compile -C "$BUILD_DIR_NAME" meson compile -C "$BUILD_DIR_NAME"
$SCRIPT_DIR/libxkbcommon-redefine-syms.sh "$STATIC_LIB_PATH" "$STATIC_LIB_PATH" $SCRIPT_DIR/redefine-syms.sh "__xkbc_" "$STATIC_LIB_PATH" "$STATIC_LIB_PATH"
popd >/dev/null popd >/dev/null
GREEN='\033[0;32m' GREEN='\033[0;32m'

603
firmware2/password-hash/Cargo.lock generated Normal file
View file

@ -0,0 +1,603 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
dependencies = [
"memchr",
]
[[package]]
name = "argon2"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072"
dependencies = [
"base64ct",
"blake2",
"cpufeatures",
"password-hash 0.5.0",
]
[[package]]
name = "base64ct"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "bindgen"
version = "0.72.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"itertools 0.13.0",
"log",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn",
]
[[package]]
name = "bitflags"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
[[package]]
name = "blake2"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
dependencies = [
"digest",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cipher"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"inout",
]
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
name = "duct"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e66e9c0c03d094e1a0ba1be130b849034aa80c3a2ab8ee94316bc809f3fa684"
dependencies = [
"libc",
"os_pipe",
"shared_child",
"shared_thread",
]
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "errno"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.61.2",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "glob"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]]
name = "inout"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
dependencies = [
"generic-array",
]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
dependencies = [
"either",
]
[[package]]
name = "libc"
version = "0.2.180"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
[[package]]
name = "libloading"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
dependencies = [
"cfg-if",
"windows-link",
]
[[package]]
name = "log"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "memchr"
version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "os_pipe"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
dependencies = [
"libc",
"windows-sys 0.61.2",
]
[[package]]
name = "password-hash"
version = "0.1.0"
dependencies = [
"argon2",
"itertools 0.14.0",
"scrypt",
"spectre-api-sys",
]
[[package]]
name = "password-hash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
dependencies = [
"base64ct",
"rand_core",
"subtle",
]
[[package]]
name = "pbkdf2"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest",
"hmac",
]
[[package]]
name = "prettyplease"
version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "regex"
version = "1.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
[[package]]
name = "rustc-hash"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]]
name = "salsa20"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213"
dependencies = [
"cipher",
]
[[package]]
name = "scrypt"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f"
dependencies = [
"pbkdf2",
"salsa20",
"sha2",
]
[[package]]
name = "sha2"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "shared_child"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e362d9935bc50f019969e2f9ecd66786612daae13e8f277be7bfb66e8bed3f7"
dependencies = [
"libc",
"sigchld",
"windows-sys 0.60.2",
]
[[package]]
name = "shared_thread"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52b86057fcb5423f5018e331ac04623e32d6b5ce85e33300f92c79a1973928b0"
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "sigchld"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47106eded3c154e70176fc83df9737335c94ce22f821c32d17ed1db1f83badb1"
dependencies = [
"libc",
"os_pipe",
"signal-hook",
]
[[package]]
name = "signal-hook"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
dependencies = [
"errno",
"libc",
]
[[package]]
name = "spectre-api-sys"
version = "0.1.0"
dependencies = [
"bindgen",
"duct",
]
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-ident"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-targets"
version = "0.53.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
dependencies = [
"windows-link",
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
[[package]]
name = "windows_i686_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
[[package]]
name = "windows_i686_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[patch.unused]]
name = "rmk"
version = "0.8.2"
[[patch.unused]]
name = "scrypt"
version = "0.12.0-rc.8"
[[patch.unused]]
name = "xkbcommon"
version = "0.9.0"

View file

@ -0,0 +1,24 @@
[package]
name = "password-hash"
version = "0.1.0"
edition = "2024"
[lib]
name = "password_hash"
path = "src/lib.rs"
[[bin]]
name = "password_hash"
path = "src/bin.rs"
required-features = ["cmd"]
[features]
default = ["cmd"]
std = []
cmd = ["std", "dep:scrypt", "dep:itertools", "dep:spectre-api-sys"]
[dependencies]
argon2 = { version = "0.5.3", default-features = false, features = ["alloc"] }
itertools = { version = "0.14.0", optional = true }
scrypt = { version = "0.11.0", default-features = false, optional = true }
spectre-api-sys = { git = "https://github.com/Limeth/spectre-api-sys", optional = true }

View file

@ -0,0 +1,3 @@
# Compiling
Compile on Linux or in WSL.

View file

@ -0,0 +1,27 @@
use std::{env, path::PathBuf};
fn main() {
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
println!(
"cargo:rustc-link-search=native={}",
manifest_dir.join("../spectre-api-c/build-host").display()
);
println!("cargo:rustc-link-lib=static=spectre");
println!(
"cargo:rerun-if-changed={}",
manifest_dir
.join("../spectre-api-c/build-host/libspectre.a")
.display()
);
let libsodium_install_dir = PathBuf::from(env::var("LIBSODIUM_INSTALL_DIR").unwrap());
println!(
"cargo:rustc-link-search=native={}",
libsodium_install_dir.join("lib").display()
);
println!("cargo:rustc-link-lib=static=sodium");
println!(
"cargo:rerun-if-changed={}",
libsodium_install_dir.join("lib/libsodium.a").display()
);
}

View file

@ -0,0 +1,56 @@
#![feature(allocator_api)]
use std::{
alloc::Global,
ffi::CString,
io::{Write, stdin},
iter::zip,
str::FromStr,
};
use itertools::Itertools;
use password_hash::derive_encryption_key;
use spectre_api_sys::SpectreAlgorithm;
macro_rules! read_line {
($lines:expr, $label:expr) => {{
print!("{}: ", $label);
std::io::stdout().flush().unwrap();
CString::from_str(
&$lines
.next()
.transpose()
.ok()
.flatten()
.unwrap_or_else(|| panic!("Expected {}.", $label)),
)
.unwrap()
}};
}
fn main() {
let mut lines = stdin().lines();
let username = read_line!(lines, "username");
let secret = read_line!(lines, "secret");
let user_key = unsafe {
&*spectre_api_sys::spectre_user_key(
username.as_ptr(),
secret.as_ptr(),
SpectreAlgorithm::Current,
)
};
let encryption_key = derive_encryption_key(username.as_bytes(), secret.as_bytes(), Global);
let mut encrypted_user_key = encryption_key;
assert_eq!(encrypted_user_key.len(), user_key.bytes.len());
for (dst_byte, user_byte) in zip(&mut encrypted_user_key, &user_key.bytes) {
*dst_byte ^= *user_byte;
}
println!(
"\nEncrypted User Key:\n{:02x}",
encrypted_user_key.iter().format("")
);
}

View file

@ -0,0 +1,51 @@
use core::slice;
use argon2::Block;
pub(crate) struct Argon2Blocks<A: alloc::alloc::Allocator> {
p: core::ptr::NonNull<Block>,
len: usize,
alloc: A,
}
impl<A: alloc::alloc::Allocator> Argon2Blocks<A> {
/// Each block is 1 KiB.
/// Total size is `len` * 1 KiB
pub fn new_in(len: usize, alloc: A) -> Option<Self> {
use alloc::alloc::Layout;
if len == 0 {
return None;
}
let layout = Layout::array::<Block>(len).ok()?;
// SAFETY: `alloc_zeroed` is used correctly with non-zero layout
let p = alloc.allocate_zeroed(layout).ok()?.cast();
Some(Self { p, len, alloc })
}
}
impl<A: alloc::alloc::Allocator> AsMut<[Block]> for Argon2Blocks<A> {
fn as_mut(&mut self) -> &mut [Block] {
unsafe { slice::from_raw_parts_mut(self.p.as_ptr(), self.len) }
}
}
impl<A: alloc::alloc::Allocator> AsRef<[Block]> for Argon2Blocks<A> {
fn as_ref(&self) -> &[Block] {
unsafe { slice::from_raw_parts(self.p.as_ptr(), self.len) }
}
}
impl<A: alloc::alloc::Allocator> Drop for Argon2Blocks<A> {
fn drop(&mut self) {
use alloc::alloc::Layout;
// SAFETY: layout was checked during construction
let layout = unsafe { Layout::array::<Block>(self.len).unwrap_unchecked() };
// SAFETY: we use `dealloc` correctly with the previously allocated pointer
unsafe {
self.alloc.deallocate(self.p.cast(), layout);
}
}
}

View file

@ -0,0 +1,53 @@
//! scrypt memory requirements scale linearly with parameters `N` and `r`.
//! This makes it unsuitable for embedded environments with the parameters
//! used in Spectre.
//! Our work-around is to derive the Spectre _user key_ using scrypt on the
//! host, encrypt it with XOR using a key derived using argon2, which
//! has parameters for specifying the memory and time requirements separately.
//! This encrypted key is then stored on the keyboard, to be decrypted again.
#![cfg_attr(not(feature = "std"), no_std)]
#![feature(allocator_api)]
extern crate alloc;
use alloc::alloc::Allocator;
use argon2::{Algorithm, Argon2, ParamsBuilder, Version};
use crate::blocks::Argon2Blocks;
pub mod blocks;
pub type Key = [u8; 64];
/// KiB used by the argon2 algorithm.
/// Lower than the default, to fit in the constrained memory of embedded devices.
pub const ARGON2_M_COST: u32 = 1024;
/// Compensate the difficulty by increasing the iterations proportionally.
pub const ARGON2_T_COST: u32 =
argon2::Params::DEFAULT_T_COST * argon2::Params::DEFAULT_M_COST / ARGON2_M_COST;
pub const ARGON2_P_COST: u32 = argon2::Params::DEFAULT_P_COST;
pub const ARGON2_SALT_PREFIX: &[u8] = b"acid-firmware\0";
pub fn derive_encryption_key(username: &[u8], secret: &[u8], allocator: impl Allocator) -> Key {
let argon2 = Argon2::new(
Algorithm::Argon2id,
Version::default(),
ParamsBuilder::default()
.m_cost(ARGON2_M_COST)
.t_cost(ARGON2_T_COST)
.p_cost(ARGON2_P_COST)
.build()
.unwrap(),
);
let mut blocks = Argon2Blocks::new_in(ARGON2_M_COST as usize, &allocator).unwrap();
let mut key: Key = [0u8; _];
// Username is prefixed to form a salt that is long enough for Argon2.
let mut salt = Vec::with_capacity_in(username.len() + ARGON2_SALT_PREFIX.len(), &allocator);
salt.extend_from_slice(ARGON2_SALT_PREFIX);
salt.extend_from_slice(username);
argon2
.hash_password_into_with_memory(secret, &salt, &mut key, &mut blocks)
.unwrap();
key
}

View file

@ -1,10 +1,10 @@
#!/usr/bin/env bash #!/usr/bin/env bash
INPUT_LIB=$1 PREFIX=$1
OUTPUT_LIB=$2 INPUT_LIB=$2
PREFIX="__xkbc_" OUTPUT_LIB=$3
if [ "$#" -ne 2 ]; then if [ "$#" -ne 3 ]; then
echo "Usage: $0 <input_lib.a> <output_lib.a>" echo "Usage: $0 <prefix> <input_lib.a> <output_lib.a>"
exit 1 exit 1
fi fi

@ -0,0 +1 @@
Subproject commit 733e6d6d73bc9462d8ec9528dd96eee23846a3e3

View file

@ -0,0 +1,3 @@
#!/usr/bin/env bash
meson setup build --wipe --cross-file ../../../kicad/acid/firmware2/cross-esp32s3.txt -Dlibsodium-install-dir="$LIBSODIUM_INSTALL_DIR"
meson compile -C build

1
firmware2/src/crypto.rs Normal file
View file

@ -0,0 +1 @@

View file

@ -1,11 +1,13 @@
#![allow(unused_variables)] #![allow(unused_variables)]
use core::ffi::{c_size_t, c_void};
use core::alloc::GlobalAlloc; use core::alloc::GlobalAlloc;
use core::ffi::{c_size_t, c_void};
use enumset::EnumSet; use enumset::EnumSet;
use esp_alloc::EspHeap; use esp_alloc::EspHeap;
use crate::ffi::string::__xkbc_memcpy;
// Here we select the allocator to use for libxkbcommon. // Here we select the allocator to use for libxkbcommon.
static XKBC_ALLOCATOR: &EspHeap = &crate::PSRAM_ALLOCATOR; static XKBC_ALLOCATOR: &EspHeap = &crate::PSRAM_ALLOCATOR;
@ -16,6 +18,11 @@ pub unsafe extern "C" fn __xkbc_malloc(size: c_size_t) -> *mut c_void {
unsafe { malloc_with_caps(size, EnumSet::empty()) as *mut _ } unsafe { malloc_with_caps(size, EnumSet::empty()) as *mut _ }
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_malloc(size: c_size_t) -> *mut c_void {
unsafe { __xkbc_malloc(size) }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_calloc(number: c_size_t, size: c_size_t) -> *mut c_void { pub unsafe extern "C" fn __xkbc_calloc(number: c_size_t, size: c_size_t) -> *mut c_void {
let total_size = number * size; let total_size = number * size;
@ -32,11 +39,21 @@ pub unsafe extern "C" fn __xkbc_calloc(number: c_size_t, size: c_size_t) -> *mut
} }
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_calloc(number: c_size_t, size: c_size_t) -> *mut c_void {
unsafe { __xkbc_calloc(number, size) }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_realloc(ptr: *mut c_void, new_size: c_size_t) -> *mut c_void { pub unsafe extern "C" fn __xkbc_realloc(ptr: *mut c_void, new_size: c_size_t) -> *mut c_void {
unsafe { realloc_with_caps(ptr as *mut _, new_size, EnumSet::empty()) as *mut _ } unsafe { realloc_with_caps(ptr as *mut _, new_size, EnumSet::empty()) as *mut _ }
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_realloc(ptr: *mut c_void, new_size: c_size_t) -> *mut c_void {
unsafe { __xkbc_realloc(ptr, new_size) }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_free(ptr: *mut c_void) { pub unsafe extern "C" fn __xkbc_free(ptr: *mut c_void) {
if ptr.is_null() { if ptr.is_null() {
@ -54,6 +71,13 @@ pub unsafe extern "C" fn __xkbc_free(ptr: *mut c_void) {
} }
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_free(ptr: *mut c_void) {
unsafe {
__xkbc_free(ptr);
}
}
unsafe fn malloc_with_caps(size: usize, caps: EnumSet<crate::MemoryCapability>) -> *mut u8 { unsafe fn malloc_with_caps(size: usize, caps: EnumSet<crate::MemoryCapability>) -> *mut u8 {
let total_size = size + 4; let total_size = size + 4;
@ -77,10 +101,6 @@ unsafe fn realloc_with_caps(
new_size: usize, new_size: usize,
caps: enumset::EnumSet<crate::MemoryCapability>, caps: enumset::EnumSet<crate::MemoryCapability>,
) -> *mut u8 { ) -> *mut u8 {
unsafe extern "C" {
fn memcpy(d: *mut u8, s: *const u8, l: usize);
}
unsafe { unsafe {
let p = malloc_with_caps(new_size, caps); let p = malloc_with_caps(new_size, caps);
if !p.is_null() && !ptr.is_null() { if !p.is_null() && !ptr.is_null() {
@ -88,7 +108,7 @@ unsafe fn realloc_with_caps(
(ptr as *const u32).sub(1).read_volatile() as usize, (ptr as *const u32).sub(1).read_volatile() as usize,
new_size, new_size,
); );
memcpy(p, ptr, len); __xkbc_memcpy(p as *mut _, ptr as *const _, len);
__xkbc_free(ptr as *mut _); __xkbc_free(ptr as *mut _);
} }
p p

137
firmware2/src/ffi/crypto.rs Normal file
View file

@ -0,0 +1,137 @@
use core::ffi::{c_char, c_int, c_size_t, c_uchar, c_ulonglong};
use sha2::{
Digest, Sha256,
digest::{consts::U32, generic_array::GenericArray},
};
// Just a way to mark non-null pointers.
// Rust's `NonNull` is for mutable pointers only.
pub type NonNullPtr<P> = P;
#[unsafe(no_mangle)]
unsafe extern "C" fn __spre_crypto_hash_sha256(
data_out: NonNullPtr<*mut c_uchar>,
data_in: *const c_uchar,
data_in_len: c_ulonglong,
) -> c_int {
unsafe {
let data_out = &mut *(data_out as *mut GenericArray<u8, U32>);
let data_in = core::slice::from_raw_parts(data_in, data_in_len as usize);
let mut digest = Sha256::new();
digest.update(data_in);
digest.finalize_into_reset(data_out);
}
0
}
#[unsafe(no_mangle)]
#[must_use]
unsafe extern "C" fn __spre_crypto_pwhash_scryptsalsa208sha256_ll(
password: NonNullPtr<*const u8>,
password_len: c_size_t,
salt: NonNullPtr<*const u8>,
salt_len: c_size_t,
n: u64,
r: u32,
p: u32,
output: NonNullPtr<*mut u8>,
output_len: c_size_t,
) -> c_int {
unsafe {
let password: &[u8] = core::slice::from_raw_parts(password, password_len);
let salt: &[u8] = core::slice::from_raw_parts(salt, salt_len);
let output: &mut [u8] = core::slice::from_raw_parts_mut(output, output_len);
let log_n = n.ilog2() as u8;
if n != 1 << log_n {
return -1;
}
// TODO: Store encrypted password and decrypt it using argon2
// let params = scrypt::Params::new(log_n, r, p).unwrap();
// match scrypt::scrypt_in(password, salt, &params, output, &PSRAM_ALLOCATOR) {
// Ok(()) => 0,
// Err(_) => -1,
// }
todo!()
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn __spre_crypto_generichash_blake2b_salt_personal(
data_out: NonNullPtr<*mut c_uchar>,
data_out_len: c_size_t,
data_in: *const c_uchar,
data_in_len: c_ulonglong,
key: *const c_uchar,
keylen: c_size_t,
salt: *const c_uchar,
personal: *const c_uchar,
) -> c_int {
todo!()
}
#[repr(C)]
struct crypto_hash_sha256_state {
state: [u32; 8],
count: u64,
buf: [u8; 64],
}
struct crypto_auth_hmacsha256_state {
ictx: crypto_hash_sha256_state,
octx: crypto_hash_sha256_state,
}
#[unsafe(no_mangle)]
unsafe extern "C" fn __spre_crypto_auth_hmacsha256_init(
state: NonNullPtr<*mut crypto_auth_hmacsha256_state>,
key: NonNullPtr<*const c_uchar>,
keylen: c_size_t,
) -> c_int {
todo!()
}
#[unsafe(no_mangle)]
unsafe extern "C" fn __spre_crypto_auth_hmacsha256_update(
state: NonNullPtr<*mut crypto_auth_hmacsha256_state>,
data_in: *const c_uchar,
inlen: c_ulonglong,
) -> c_int {
todo!()
}
#[unsafe(no_mangle)]
unsafe extern "C" fn __spre_crypto_auth_hmacsha256_final(
state: NonNullPtr<*mut crypto_auth_hmacsha256_state>,
out: NonNullPtr<*mut c_uchar>,
) -> c_int {
todo!()
}
#[unsafe(no_mangle)]
unsafe extern "C" fn __spre_sodium_bin2base64(
b64: NonNullPtr<*mut c_char>,
b64_maxlen: c_size_t,
bin: *const c_uchar,
bin_len: c_size_t,
variant: c_int,
) -> *mut c_char {
todo!()
}
#[unsafe(no_mangle)]
unsafe extern "C" fn __spre_sodium_base642bin(
bin: NonNullPtr<*mut c_uchar>,
bin_maxlen: c_size_t,
b64: *const c_char,
b64_len: c_size_t,
ignore: *const c_char,
bin_len: *mut c_size_t,
b64_end: *mut *const c_char,
variant: c_int,
) -> c_int {
todo!()
}

View file

@ -72,6 +72,15 @@ pub unsafe extern "C" fn __xkbc_fprintf(
unsafe { __xkbc_vfprintf(stream, format, args.as_va_list()) } unsafe { __xkbc_vfprintf(stream, format, args.as_va_list()) }
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_fprintf(
stream: *mut FILE,
format: *const c_char,
mut args: ...
) -> c_int {
unsafe { __xkbc_fprintf(stream, format) }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_vfprintf( pub unsafe extern "C" fn __xkbc_vfprintf(
stream: *mut FILE, stream: *mut FILE,
@ -137,3 +146,43 @@ pub unsafe extern "C" fn __xkbc_vsnprintf(
string_length as c_int string_length as c_int
} }
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_sprintf(
string: *mut c_char,
format: *const c_char,
mut args: ...
) -> c_int {
unsafe { vsprintf(string, format, args.as_va_list()) }
}
pub unsafe fn vsprintf(string: *mut c_char, format: *const c_char, ap: VaList) -> c_int {
let mut rust_buffer = String::new();
unsafe {
printf_compat::format(format, ap, fmt_write(&mut rust_buffer));
// __xkbc_strncpy would be preferrable, if it was available
__xkbc_memcpy(
string as *mut _,
rust_buffer.as_ptr() as *mut _,
rust_buffer.len(),
);
*string.add(rust_buffer.len()) = 0; // Add terminating null byte.
rust_buffer.len() as c_int
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_vsnprintf(
string: *mut c_char,
// Length in bytes **including the terminating null byte**.
size: c_size_t,
format: *const c_char,
ap: VaList,
) -> c_int {
unsafe { __xkbc_vsnprintf(string, size, format, ap) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_sscanf(s: *const c_char, format: *const c_char, ...) -> c_int {
todo!()
}

View file

@ -1,6 +1,7 @@
#![allow(unused_variables)] #![allow(unused_variables)]
use core::{ use core::{
error,
ffi::{c_char, c_int, c_long, c_longlong, c_size_t, c_void}, ffi::{c_char, c_int, c_long, c_longlong, c_size_t, c_void},
ptr::null_mut, ptr::null_mut,
}; };
@ -8,9 +9,11 @@ use core::{
use inout::file::{FILE, STDERR, STDIN, STDOUT}; use inout::file::{FILE, STDERR, STDIN, STDOUT};
pub mod alloc; pub mod alloc;
pub mod crypto;
pub mod gcc_runtime; pub mod gcc_runtime;
pub mod inout; pub mod inout;
pub mod string; pub mod string;
pub mod time;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub type c_intmax_t = c_longlong; pub type c_intmax_t = c_longlong;
@ -38,6 +41,11 @@ pub unsafe extern "C" fn __xkbc___errno() -> *mut c_int {
todo!() todo!()
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre___errno() -> *mut c_int {
unsafe { __xkbc___errno() }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_qsort( pub unsafe extern "C" fn __xkbc_qsort(
base: *mut c_void, base: *mut c_void,
@ -76,6 +84,11 @@ pub unsafe extern "C" fn __xkbc___getreent() -> *mut _reent {
} }
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre___getreent() -> *mut _reent {
unsafe { __xkbc___getreent() }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_secure_getenv(name: *const c_char) -> *mut c_char { pub unsafe extern "C" fn __xkbc_secure_getenv(name: *const c_char) -> *mut c_char {
unsafe { __xkbc_getenv(name) } unsafe { __xkbc_getenv(name) }
@ -136,3 +149,12 @@ pub unsafe extern "C" fn __xkbc___assert_func(
pub unsafe extern "C" fn __xkbc_atoi(s: *const c_char) -> c_int { pub unsafe extern "C" fn __xkbc_atoi(s: *const c_char) -> c_int {
todo!() todo!()
} }
// TODO: What is this even for?
#[unsafe(no_mangle)]
pub static __spre__ctype_: [c_char; 0] = [];
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_abort() -> ! {
panic!("`abort()` called.")
}

View file

@ -33,6 +33,15 @@ pub unsafe extern "C" fn __xkbc_memset(
dest_original dest_original
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_memset(
dest_original: *mut c_void,
c: c_int,
n: c_size_t,
) -> *mut c_void {
unsafe { __xkbc_memset(dest_original, c, n) }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_memmove( pub unsafe extern "C" fn __xkbc_memmove(
dst: *mut c_void, dst: *mut c_void,
@ -55,6 +64,15 @@ pub unsafe extern "C" fn __xkbc_memcpy(
dst dst
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_memcpy(
dst: *mut c_void,
src: *const c_void,
count: c_size_t,
) -> *mut c_void {
unsafe { __xkbc_memcpy(dst, src, count) }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_memchr(s: *const c_void, c: c_int, n: c_size_t) -> *mut c_void { pub unsafe extern "C" fn __xkbc_memchr(s: *const c_void, c: c_int, n: c_size_t) -> *mut c_void {
let mut s = s as *const c_uchar; let mut s = s as *const c_uchar;
@ -90,6 +108,11 @@ pub unsafe extern "C" fn __xkbc_memcmp(s1: *const c_char, s2: *const c_char, n:
} }
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_memcmp(s1: *const c_char, s2: *const c_char, n: c_size_t) -> c_int {
unsafe { __xkbc_memcmp(s1, s2, n) }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_strpbrk(s: *const c_char, accept: *const c_char) -> *mut c_char { pub unsafe extern "C" fn __xkbc_strpbrk(s: *const c_char, accept: *const c_char) -> *mut c_char {
todo!() todo!()
@ -100,6 +123,11 @@ pub unsafe extern "C" fn __xkbc_strerror(errnum: c_int) -> *mut c_char {
todo!() todo!()
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_strerror(errnum: c_int) -> *mut c_char {
unsafe { __xkbc_strerror(errnum) }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_strdup(string: *const c_char) -> *mut c_char { pub unsafe extern "C" fn __xkbc_strdup(string: *const c_char) -> *mut c_char {
strndup_inner(string, unsafe { __xkbc_strlen(string) }) strndup_inner(string, unsafe { __xkbc_strlen(string) })
@ -136,6 +164,11 @@ pub unsafe extern "C" fn __xkbc_strlen(mut s: *const c_char) -> c_size_t {
result result
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_strlen(s: *const c_char) -> c_size_t {
unsafe { __xkbc_strlen(s) }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_strnlen(s: *const c_char, maxlen: c_size_t) -> c_size_t { pub unsafe extern "C" fn __xkbc_strnlen(s: *const c_char, maxlen: c_size_t) -> c_size_t {
let found: *const c_char = let found: *const c_char =
@ -168,6 +201,15 @@ pub unsafe extern "C" fn __xkbc_strncmp(
} }
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_strncmp(
s1: *const c_char,
s2: *const c_char,
n: c_size_t,
) -> c_int {
unsafe { __xkbc_strncmp(s1, s2, n) }
}
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub unsafe extern "C" fn __xkbc_strchr(cs: *const c_char, c: c_int) -> *mut c_char { pub unsafe extern "C" fn __xkbc_strchr(cs: *const c_char, c: c_int) -> *mut c_char {
todo!() todo!()
@ -198,3 +240,12 @@ pub unsafe extern "C" fn __xkbc_strtol(
) -> c_long { ) -> c_long {
todo!() todo!()
} }
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_strtol(
nptr: *const c_char,
endptr: *mut *mut c_char,
base: c_int,
) -> c_long {
unsafe { __xkbc_strtol(nptr, endptr, base) }
}

20
firmware2/src/ffi/time.rs Normal file
View file

@ -0,0 +1,20 @@
use embassy_time::Instant;
// TODO: Is this right?
pub type time_t = i64;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __spre_time(time: *mut time_t) -> time_t {
// TODO: This currently measures the time since boot,
// but it should actually measure the time since the unix epoch.
let duration = Instant::now().duration_since(Instant::MIN);
let seconds_since_epoch = duration.as_secs() as time_t;
if !time.is_null() {
unsafe {
*time = seconds_since_epoch;
}
}
seconds_since_epoch
}

View file

@ -22,6 +22,7 @@ use core::sync::atomic::{AtomicBool, Ordering};
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::vec; use alloc::vec;
use argon2::{Algorithm, Argon2};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::Channel; use embassy_sync::channel::Channel;
@ -40,9 +41,10 @@ use esp_hal::mcpwm::{McPwm, PeripheralClockConfig};
use esp_hal::psram::{FlashFreq, PsramConfig, PsramSize, SpiRamFreq, SpiTimingConfigCoreClock}; use esp_hal::psram::{FlashFreq, PsramConfig, PsramSize, SpiRamFreq, SpiTimingConfigCoreClock};
use esp_hal::system::Stack; use esp_hal::system::Stack;
use esp_hal::timer::timg::TimerGroup; use esp_hal::timer::timg::TimerGroup;
use esp_println::println;
use esp_rtos::embassy::Executor; use esp_rtos::embassy::Executor;
use esp_storage::FlashStorage; use esp_storage::FlashStorage;
use log::{error, info}; use log::{error, info, warn};
use rmk::channel::{CONTROLLER_CHANNEL, ControllerSub}; use rmk::channel::{CONTROLLER_CHANNEL, ControllerSub};
use rmk::config::{BehaviorConfig, PositionalConfig, RmkConfig, StorageConfig, VialConfig}; use rmk::config::{BehaviorConfig, PositionalConfig, RmkConfig, StorageConfig, VialConfig};
use rmk::controller::{Controller, EventController}; use rmk::controller::{Controller, EventController};
@ -56,9 +58,11 @@ use rmk::storage::async_flash_wrapper;
use rmk::types::action::{Action, KeyAction}; use rmk::types::action::{Action, KeyAction};
use rmk::{initialize_keymap_and_storage, run_devices, run_rmk}; use rmk::{initialize_keymap_and_storage, run_devices, run_rmk};
use slint::platform::software_renderer::Rgb565Pixel; use slint::platform::software_renderer::Rgb565Pixel;
use spectre_api_sys::SpectreAlgorithm;
use static_cell::StaticCell; use static_cell::StaticCell;
use {esp_alloc as _, esp_backtrace as _}; use {esp_alloc as _, esp_backtrace as _};
use crate::crypto::Argon2Blocks;
use crate::keymap::create_hid_report_interceptor; use crate::keymap::create_hid_report_interceptor;
use crate::logging::LOG_LEVEL_FILTER; use crate::logging::LOG_LEVEL_FILTER;
use crate::matrix::IoeMatrix; use crate::matrix::IoeMatrix;
@ -68,6 +72,7 @@ use crate::vial::{CustomKeycodes, VIAL_KEYBOARD_DEF, VIAL_KEYBOARD_ID};
mutually_exclusive_features::none_or_one_of!["usb-log", "alt-log", "rtt-log"]; mutually_exclusive_features::none_or_one_of!["usb-log", "alt-log", "rtt-log"];
mod crypto;
mod ffi; mod ffi;
mod keymap; mod keymap;
mod logging; mod logging;
@ -379,6 +384,21 @@ async fn main(_spawner: Spawner) {
let mut user_controller = UserController::new(); let mut user_controller = UserController::new();
warn!("Yeet");
let key = password_hash::hash(&PSRAM_ALLOCATOR);
warn!("Argon2 passed. Key = {key:02x?}");
unsafe {
let user_key = &*spectre_api_sys::spectre_user_key(
c"Jakub Hlusička".as_ptr(),
c"test".as_ptr(),
SpectreAlgorithm::Current,
);
warn!("{user_key:?}");
}
info!("Awaiting on all tasks..."); info!("Awaiting on all tasks...");
// TODO: Probably want to select! instead and re-try. // TODO: Probably want to select! instead and re-try.