1# What is this? 2 3Implementations of XTS and LDT for Nearby Presence "v0" advertisements. 4 5See the appendix below for more details on XTS and LDT. 6 7## Project structure 8 9*Note all new crates follow the convention of using underscore `_` instead of 10hyphen `-` in crate names 11 12### `ldt` 13 14An implementation 15of [`LDT`](https://luca-giuzzi.unibs.it/corsi/Support/papers-cryptography/1619-2007-NIST-Submission.pdf) 16which can use `xts-aes` as its tweakable block cipher. 17 18### `ldt_tbc` 19 20The Tweakable Block Cipher traits for use in LDT. These traits have 21implementations in the `xts_aes` 22 23### `ldt_np_adv` 24 25Higher-level wrapper around the core LDT algorithm that does key derivation and 26payload validation the way Nearby Presence advertisements need. 27 28### `ldt_np_adv_ffi` 29 30C API for rust library, currently exposes C/C++ clients the needed API's to use 31the NP specific LDT rust implementation. 32For an example of how to integrate with these API's see program 33in `ldt_np_c_sample` 34 35### `ldt_np_c_sample` 36 37Sample c program which provides its own OpenSSL based AES implementation to 38encrypt data through the LDT rust implementation 39An example of how to interface with the `ldt_np_adv_ffi` API's 40 41### `np_hkdf` 42 43The Key Derivation functions used for creating keys used by nearby presence from 44a key_seed 45 46### `xts_aes` 47 48An implementation 49of [`XTS-AES`](https://luca-giuzzi.unibs.it/corsi/Support/papers-cryptography/1619-2007-NIST-Submission.pdf) 50 51## Setup for MacOS local development 52 53Dependencies: 54 55``` 56brew install protobuf rapidjson google-benchmark 57``` 58 59We depend on OpenSSL of version at least 3.0.5 being installed on your machine 60to build the fuzzers, for macOS run: 61 62The in-box version of Clang which comes from XCode developer tools does not have 63a fuzzer runtime so we will have to use our own 64 65``` 66brew install llvm 67``` 68 69then to override the default version it needs to come before it in $PATH. first 70find your path: 71 72``` 73$(brew --prefix llvm)/bin 74``` 75 76then add this to the beginning of your path 77 78``` 79echo 'export PATH="/opt/homebrew/opt/llvm/bin:$PATH"' >> ~/.bash_profile 80export PATH="/opt/homebrew/opt/llvm/bin:$PATH" 81``` 82 83verify success with: 84 85``` 86clang --version 87``` 88 89it should display the path to the homebrew version and not the xcode version. 90 91Some other dependencies you may need include: 92 93``` 94brew install ninja bindgen 95``` 96 97## Examples 98 99Examples use [clap](https://docs.rs/clap/latest/clap/) for nice CLIs, so try 100running with `--help` to see all args. 101 102*Note:* the examples are in the `ldt` crate, so `cd` into that first. 103 104### `ldt_prp` 105 106Confirm that LDT is, in fact, behaving as a PRP. That is, flipping one bit in 107the ciphertext is on average going to flip half of the bits in the decrypted 108plaintext, and that a change to the first `n` bytes of plaintext is increasingly 109likely to be detected as `n` increases. 110 111``` 112cargo run --release --example ldt_prp -- \ 113 --trials 1000000 \ 114 --check-leading-bytes 16 115``` 116 117### `ldt_benchmark` 118 119For interactive exploration of LDT performance looking for a needle in a 120haystack of ciphertexts. 121 122``` 123cargo run --release --example ldt_benchmark -- \ 124 --trials 500 \ 125 --keys 1000 126``` 127 128### `ldt_np_c_sample` 129 130From the root directory run the following commands to build and run the C 131sample. 132 133``` 134mkdir -p cmake-build && cd cmake-build 135cmake .. 136make 137./ldt_np_c_sample/sample 138``` 139 140### `ldt_np_c_sample/tests` 141 142Test cases for the ldt_np_adv_ffi C API which are built alongside the sample, 143use the following commands to run the tests, from root of repo: 144 145``` 146mkdir -p cmake-build && cd cmake-build 147cmake .. -DENABLE_TESTS=TRUE 148make 149cd ldt_np_c_sample/tests && ctest 150``` 151 152you can then view the output of the tests 153in `ldt_np_c_sample/tests/Testing/Temporary/LastTest.log` 154 155To run the benchmarks: 156 157`ldt_np_c_sample/tests/benchmarks` 158 159## Fuzzing 160 161To build all the fuzzers, run `scripts/build-fuzzers.sh`. 162 163### Rust 164 165Crates with fuzzers: `ldt`, `ldt_np_adv`, `xts_aes` 166 167- `cd` to a crate's directory 168- `cargo fuzz list` to list available fuzzers 169- `cargo fuzz run [fuzzer name]` to run a fuzzer 170 171### C 172 173Build cmake project with `-DENABLE_FUZZ=true`<br> 174Fuzz targets will be output to the build dir for:<br> 175 176- `ldt_np_adv_ffi_fuzz`<br> 177- `np_cpp_ffi/fuzz` 178 - To run `fuzzer_np_cpp_deserialize` 179 use: `./fuzzer_np_cpp_deserialize -max_len=255 corpus` 180 - The `corpus` directory provides seed data to help the fuzzer generate 181 more relevant data to input 182 183## Cross-compilation for Android 184 185- Add the 64bit ARM target to the stable and nightly toolchains: 186 - `rustup target add aarch64-linux-android` 187 - `rustup target add aarch64-linux-android --toolchain nightly` 188 189- Install the v22 NDK that still links against `libgcc` the way rust's stdlib 190 expects. 191 - Newer NDKs use `libunwind` instead, which can be used just fine if you 192 build your own rust stdlib, but for our purposes there's no problem with 193 just using NDK 22 194 - `./sdkmanager --install platform-tools 'ndk;22.0.7026061'` 195 196- Configure the linker used for the ARMv8 Android target to be the NDK's linker. 197 - `export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=$ANDROID_HOME/ndk/22.0.7026061/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang` 198 - `export PKG_CONFIG_SYSROOT_DIR=$ANDROID_HOME/ndk/22.0.7026061/toolchains/llvm/prebuilt/linux-x86_64/sysroot` 199 200- See if everything builds, using the nightly toolchain for the moment to 201 convince the `aes` crate to use intrinsics on aarch64 202 - `cargo +nightly build --workspace --all-targets --target aarch64-linux-android` 203 - `cargo +nightly bench --workspace --no-run --target aarch64-linux-android` 204 205- Prepare a place for the benchmark to be on the phone 206 207 - `adb shell` 208 - then 209 - `mkdir -p /data/local/tmp/np && cd /data/local/tmp/np` 210 - Leave the shell on the phone open so you can use it to run the benchmark. 211 212- Find the benchmark binary in the build products 213 214 - Use whatever directory you configured as the `target-dir` in 215 `.cargo/config.toml` initially, and look for the file without the 216 trailing `.d`. 217 - `find TARGET_DIR -name 'ldt_scan*' | grep android` 218 - Copy the file to the phone 219 - `adb push FILE_FOUND_ABOVE /data/local/tmp/np/` 220 221- In your `adb shell`, run the benchmark 222 223 - `./ldt_scan-... --bench` 224 225### Building min-sized release cross-compiled for Android 226 227- Copy and paste the following into your `~/.cargo/config.toml`, replacing with 228 a path to your NDK and Host OS 229 230``` 231[target.aarch64-linux-android] 232# Replace this with a path to your ndk version and the prebuilt toolchain for your Host OS 233linker = "Library/Android/sdk/ndk/23.2.8568313/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android21-clang" 234``` 235 236- then run: 237 `cargo +nightly build -Z build-std=core,alloc -Z build-std-features=panic_immediate_abort --target aarch64-linux-android --profile release-min-size` 238 239## Appendix 240 241### XTS 242 243XTS-AES has a NIST 244spec: [The XTS-AES Tweakable Block Cipher - An Extract from IEEE Std 1619-2007](https://luca-giuzzi.unibs.it/corsi/Support/papers-cryptography/1619-2007-NIST-Submission.pdf) 245 246XTS is a scheme for turning a block cipher (AES in this case) into a _tweakable_ 247block cipher. Tweakable block ciphers incorporate a _tweak_ which is cheaper to 248change than the key, with the assumption being that the tweak will change with 249each block or sequence of blocks. XTS-AES in particular is used in disk 250encryption, where the sector number or the like might be incorporated into the 251tweak to prevent the same data in different places on the disk being encrypted 252into the same ciphertext. 253 254### LDT 255 256LDT is the current state of the art in length 257doublers: [Efficient Length Doubling From Tweakable Block Ciphers](https://eprint.iacr.org/2017/841.pdf) 258. It builds on top of a tweakable block cipher, which is why we also have an XTS 259implementation. 260 261A length doubler is a way of adapting a block cipher to act as a secure PRP ( 262pseudo random permutation) on data of lengths in `[block size, 2 * block size)`. 263For comparison, block ciphers act as PRPs on one block at a time rather than the 264whole message. Wide block modes would also work, but have higher overhead. 265 266We use a length doubler in Nearby Presence so that changing any ciphertext bit 267should flip each bit in the decrypted plaintext with 50% probability for each 268bit, making it possible to detect changes anywhere because it is very unlikely 269for none of the bit flips to affect the metadata key (which has a known digest). 270