mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-01-11 01:58:33 +08:00
Update id48lib
* Add its own CMakeLists.txt * Add id48 unit tests for its recovery API * Add id48 unit tests for its generator API * Add id48 espresso files, generator for those files, and validation test * Proxmark3-specific: * update client/Makefile * update client/deps/id48lib.cmake *
This commit is contained in:
parent
c1441eb2ab
commit
563abf66ed
33 changed files with 2284 additions and 75 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -45,13 +45,15 @@ Makefile.platform.*
|
|||
|
||||
# cmake
|
||||
CMakeFiles/
|
||||
deps/
|
||||
client/CMakeFiles/
|
||||
client/deps/
|
||||
client/deps/**
|
||||
!client/deps/id48/
|
||||
!client/deps/id48/**
|
||||
client/build/
|
||||
client/android/build/
|
||||
CMakeCache.txt
|
||||
*.cmake
|
||||
.cache
|
||||
|
||||
# Coverity
|
||||
cov-int/
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Updated id48lib (adds unit tests, better build management)
|
||||
- Added two trace files for Ultralight AES (@iceman1001)
|
||||
- Added support for Ultralight AES secure messaing in `hf 14a raw` (@iceman1001)
|
||||
- Added support for Ultralight AES secure messaging in `hf mfu info/rdbl/wrbl/dump/ndefread/wipe/setkey` (@iceman1001)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ endif
|
|||
ifeq ($(DEFSBEENHERE),)
|
||||
-include ../../../Makefile.defs
|
||||
endif
|
||||
ifeq ($(DEFSBEENHERE),)
|
||||
-include ../../../../Makefile.defs
|
||||
endif
|
||||
ifeq ($(DEFSBEENHERE),)
|
||||
$(error Can't find Makefile.defs)
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -74,8 +74,9 @@ HARDNESTEDLIB = $(HARDNESTEDLIBPATH)/libhardnested.a
|
|||
HARDNESTEDLIBLD =
|
||||
|
||||
## ID48
|
||||
ID48LIBPATH = ./deps/id48
|
||||
ID48LIBINC = -I$(ID48LIBPATH)
|
||||
## must be manually kept in sync with updates to deps/id48/CMakeLists.txt
|
||||
ID48LIBPATH = ./deps/id48/src
|
||||
ID48LIBINC = -I$(ID48LIBPATH)/../public
|
||||
ID48LIB = $(ID48LIBPATH)/libid48.a
|
||||
ID48LIBLD =
|
||||
|
||||
|
|
|
|||
52
client/deps/id48/.gitignore
vendored
Normal file
52
client/deps/id48/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Now ignore any "build" directory anywhere under this directory
|
||||
build/
|
||||
**/build/
|
||||
|
||||
*.log
|
||||
*.eml
|
||||
*.html
|
||||
*.o
|
||||
*.a
|
||||
*.d
|
||||
*.elf
|
||||
*.s19
|
||||
*.map
|
||||
*.bin
|
||||
*.dll
|
||||
*.moc.cpp
|
||||
*.z
|
||||
*.gz
|
||||
*.Td
|
||||
*.DS_Store
|
||||
*.exe
|
||||
*.dsym
|
||||
*.json
|
||||
*.old
|
||||
*.swp
|
||||
*.json.bak
|
||||
*.pyc
|
||||
*.bmp
|
||||
|
||||
|
||||
# cmake
|
||||
CMakeFiles/
|
||||
client/CMakeFiles/
|
||||
client/deps/**
|
||||
!client/deps/id48/
|
||||
!client/deps/id48/**
|
||||
client/build/
|
||||
client/android/build/
|
||||
CMakeCache.txt
|
||||
*.cmake
|
||||
.cache
|
||||
|
||||
# Coverity
|
||||
cov-int/
|
||||
.coverity.conf
|
||||
|
||||
# .tmp files are created during compilation
|
||||
*.tmp
|
||||
|
||||
# local codeql
|
||||
_codeql*
|
||||
/codeql
|
||||
13
client/deps/id48/CMakeLists.txt
Normal file
13
client/deps/id48/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
project(id48_project LANGUAGES C CXX ASM)
|
||||
|
||||
# Project-wide language standards (subdirectories inherit if not overridden)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(tests)
|
||||
|
||||
|
|
@ -48,3 +48,25 @@ provided the first half of the key, and at least one successful
|
|||
authentication trio of nonce, challenge, and response, then
|
||||
the library can recover all potentially valid values for the
|
||||
second half of the key.
|
||||
|
||||
## Building
|
||||
|
||||
This project uses CMake, and thus should be easy to integrate
|
||||
into any existing project using CMake.
|
||||
|
||||
The following commands can be run from the root of this depot,
|
||||
and places all build artifacts into `./build`:
|
||||
|
||||
```bash
|
||||
# Configure cmake for the current environment
|
||||
# -S: explicitly specify the source directory
|
||||
# -B: explicitly specify the directory for build artifacts
|
||||
cmake -S . -B build
|
||||
|
||||
# Optionally (recommended) do a clean build each time
|
||||
cmake --build ./build --parallel --target clean
|
||||
|
||||
# build everything
|
||||
cmake --build ./build --parallel --target all
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -160,63 +160,63 @@ of the key influences a given output bit.
|
|||
Start state + key bit --> output
|
||||
|
||||
|
||||
| Start state | Key bit | Output |
|
||||
|-------|-------|----------------|
|
||||
| `s₀₀` | `K₃₉` | << hidden >> |
|
||||
| `s₀₁` | `K₃₈` | << hidden >> |
|
||||
| `s₀₂` | `K₃₇` | << hidden >> |
|
||||
| `s₀₃` | `K₃₆` | << hidden >> |
|
||||
| `s₀₄` | `K₃₅` | << hidden >> |
|
||||
| `s₀₅` | `K₃₄` | << hidden >> |
|
||||
| `s₀₆` | `K₃₃` | << hidden >> |
|
||||
| `s₀₇` | `K₃₂` | `O₀₀ == frn₀₀` |
|
||||
| `s₀₈` | `K₃₁` | `O₀₁ == frn₀₁` |
|
||||
| `s₀₉` | `K₃₀` | `O₀₂ == frn₀₂` |
|
||||
| `s₁₀` | `K₂₉` | `O₀₃ == frn₀₃` |
|
||||
| `s₁₁` | `K₂₈` | `O₀₄ == frn₀₄` |
|
||||
| `s₁₂` | `K₂₇` | `O₀₅ == frn₀₅` |
|
||||
| `s₁₃` | `K₂₆` | `O₀₆ == frn₀₆` |
|
||||
| `s₁₄` | `K₂₅` | `O₀₇ == frn₀₇` |
|
||||
| `s₁₅` | `K₂₄` | `O₀₈ == frn₀₈` |
|
||||
| `s₁₆` | `K₂₃` | `O₀₉ == frn₀₉` |
|
||||
| `s₁₇` | `K₂₂` | `O₁₀ == frn₁₀` |
|
||||
| `s₁₈` | `K₂₁` | `O₁₁ == frn₁₁` |
|
||||
| `s₁₉` | `K₂₀` | `O₁₂ == frn₁₂` |
|
||||
| `s₂₀` | `K₁₉` | `O₁₃ == frn₁₃` |
|
||||
| `s₂₁` | `K₁₈` | `O₁₄ == frn₁₄` |
|
||||
| `s₂₂` | `K₁₇` | `O₁₅ == frn₁₅` |
|
||||
| `s₂₃` | `K₁₆` | `O₁₆ == frn₁₆` |
|
||||
| `s₂₄` | `K₁₅` | `O₁₇ == frn₁₇` |
|
||||
| `s₂₅` | `K₁₄` | `O₁₈ == frn₁₈` |
|
||||
| `s₂₆` | `K₁₃` | `O₁₉ == frn₁₉` |
|
||||
| `s₂₇` | `K₁₂` | `O₂₀ == frn₂₀` |
|
||||
| `s₂₈` | `K₁₁` | `O₂₁ == frn₂₁` |
|
||||
| `s₂₉` | `K₁₀` | `O₂₂ == frn₂₂` |
|
||||
| `s₃₀` | `K₀₉` | `O₂₃ == frn₂₃` |
|
||||
| `s₃₁` | `K₀₈` | `O₂₄ == frn₂₄` |
|
||||
| `s₃₂` | `K₀₇` | `O₂₅ == frn₂₅` |
|
||||
| `s₃₃` | `K₀₆` | `O₂₆ == frn₂₆` |
|
||||
| `s₃₄` | `K₀₅` | `O₂₇ == frn₂₇` |
|
||||
| `s₃₅` | `K₀₄` | `O₂₈ == grn₀₀` |
|
||||
| `s₃₆` | `K₀₃` | `O₂₉ == grn₀₁` |
|
||||
| `s₃₇` | `K₀₂` | `O₃₀ == grn₀₂` |
|
||||
| `s₃₈` | `K₀₁` | `O₃₁ == grn₀₃` |
|
||||
| `s₃₉` | `K₀₀` | `O₃₂ == grn₀₄` |
|
||||
| `s₄₀` | `0₁₄` | `O₃₃ == grn₀₅` |
|
||||
| `s₄₁` | `0₁₃` | `O₃₄ == grn₀₆` |
|
||||
| `s₄₂` | `0₁₂` | `O₃₅ == grn₀₇` |
|
||||
| `s₄₃` | `0₁₁` | `O₃₆ == grn₀₈` |
|
||||
| `s₄₄` | `0₁₀` | `O₃₇ == grn₀₉` |
|
||||
| `s₄₅` | `0₀₉` | `O₃₈ == grn₁₀` |
|
||||
| `s₄₆` | `0₀₈` | `O₃₉ == grn₁₁` |
|
||||
| `s₄₇` | `0₀₇` | `O₄₀ == grn₁₂` |
|
||||
| `s₄₈` | `0₀₆` | `O₄₁ == grn₁₃` |
|
||||
| `s₄₉` | `0₀₅` | `O₄₂ == grn₁₄` |
|
||||
| `s₅₀` | `0₀₄` | `O₄₃ == grn₁₅` |
|
||||
| `s₅₁` | `0₀₃` | `O₄₄ == grn₁₆` |
|
||||
| `s₅₂` | `0₀₂` | `O₄₅ == grn₁₇` |
|
||||
| `s₅₃` | `0₀₁` | `O₄₆ == grn₁₈` |
|
||||
| `s₅₄` | `0₀₀` | `O₄₇ == grn₁₉` |
|
||||
| Start state | Key bit | Output | Notes |
|
||||
|-------|-------|----------------|-------|
|
||||
| `s₀₀` | `K₃₉` | << hidden >> | Seven ... |
|
||||
| `s₀₁` | `K₃₈` | << hidden >> | .. iterations ... |
|
||||
| `s₀₂` | `K₃₇` | << hidden >> | .. before ... |
|
||||
| `s₀₃` | `K₃₆` | << hidden >> | .. any ... |
|
||||
| `s₀₄` | `K₃₅` | << hidden >> | .. output ... |
|
||||
| `s₀₅` | `K₃₄` | << hidden >> | .. bits ... |
|
||||
| `s₀₆` | `K₃₃` | << hidden >> | .. seen. |
|
||||
| `s₀₇` | `K₃₂` | `O₀₀ == frn₀₀` | |
|
||||
| `s₀₈` | `K₃₁` | `O₀₁ == frn₀₁` | |
|
||||
| `s₀₉` | `K₃₀` | `O₀₂ == frn₀₂` | |
|
||||
| `s₁₀` | `K₂₉` | `O₀₃ == frn₀₃` | |
|
||||
| `s₁₁` | `K₂₈` | `O₀₄ == frn₀₄` | |
|
||||
| `s₁₂` | `K₂₇` | `O₀₅ == frn₀₅` | |
|
||||
| `s₁₃` | `K₂₆` | `O₀₆ == frn₀₆` | |
|
||||
| `s₁₄` | `K₂₅` | `O₀₇ == frn₀₇` | |
|
||||
| `s₁₅` | `K₂₄` | `O₀₈ == frn₀₈` | |
|
||||
| `s₁₆` | `K₂₃` | `O₀₉ == frn₀₉` | |
|
||||
| `s₁₇` | `K₂₂` | `O₁₀ == frn₁₀` | |
|
||||
| `s₁₈` | `K₂₁` | `O₁₁ == frn₁₁` | |
|
||||
| `s₁₉` | `K₂₀` | `O₁₂ == frn₁₂` | |
|
||||
| `s₂₀` | `K₁₉` | `O₁₃ == frn₁₃` | |
|
||||
| `s₂₁` | `K₁₈` | `O₁₄ == frn₁₄` | |
|
||||
| `s₂₂` | `K₁₇` | `O₁₅ == frn₁₅` | |
|
||||
| `s₂₃` | `K₁₆` | `O₁₆ == frn₁₆` | |
|
||||
| `s₂₄` | `K₁₅` | `O₁₇ == frn₁₇` | |
|
||||
| `s₂₅` | `K₁₄` | `O₁₈ == frn₁₈` | |
|
||||
| `s₂₆` | `K₁₃` | `O₁₉ == frn₁₉` | |
|
||||
| `s₂₇` | `K₁₂` | `O₂₀ == frn₂₀` | |
|
||||
| `s₂₈` | `K₁₁` | `O₂₁ == frn₂₁` | |
|
||||
| `s₂₉` | `K₁₀` | `O₂₂ == frn₂₂` | |
|
||||
| `s₃₀` | `K₀₉` | `O₂₃ == frn₂₃` | |
|
||||
| `s₃₁` | `K₀₈` | `O₂₄ == frn₂₄` | |
|
||||
| `s₃₂` | `K₀₇` | `O₂₅ == frn₂₅` | |
|
||||
| `s₃₃` | `K₀₆` | `O₂₆ == frn₂₆` | |
|
||||
| `s₃₄` | `K₀₅` | `O₂₇ == frn₂₇` | Last key bit that affects `frn` |
|
||||
| `s₃₅` | `K₀₄` | `O₂₈ == grn₀₀` | Five bits of key affect `grn` |
|
||||
| `s₃₆` | `K₀₃` | `O₂₉ == grn₀₁` | |
|
||||
| `s₃₇` | `K₀₂` | `O₃₀ == grn₀₂` | |
|
||||
| `s₃₈` | `K₀₁` | `O₃₁ == grn₀₃` | |
|
||||
| `s₃₉` | `K₀₀` | `O₃₂ == grn₀₄` | |
|
||||
| `s₄₀` | `0₁₄` | `O₃₃ == grn₀₅` | Zero-fill start |
|
||||
| `s₄₁` | `0₁₃` | `O₃₄ == grn₀₆` | |
|
||||
| `s₄₂` | `0₁₂` | `O₃₅ == grn₀₇` | |
|
||||
| `s₄₃` | `0₁₁` | `O₃₆ == grn₀₈` | |
|
||||
| `s₄₄` | `0₁₀` | `O₃₇ == grn₀₉` | |
|
||||
| `s₄₅` | `0₀₉` | `O₃₈ == grn₁₀` | |
|
||||
| `s₄₆` | `0₀₈` | `O₃₉ == grn₁₁` | |
|
||||
| `s₄₇` | `0₀₇` | `O₄₀ == grn₁₂` | |
|
||||
| `s₄₈` | `0₀₆` | `O₄₁ == grn₁₃` | |
|
||||
| `s₄₉` | `0₀₅` | `O₄₂ == grn₁₄` | |
|
||||
| `s₅₀` | `0₀₄` | `O₄₃ == grn₁₅` | |
|
||||
| `s₅₁` | `0₀₃` | `O₄₄ == grn₁₆` | |
|
||||
| `s₅₂` | `0₀₂` | `O₄₅ == grn₁₇` | |
|
||||
| `s₅₃` | `0₀₁` | `O₄₆ == grn₁₈` | |
|
||||
| `s₅₄` | `0₀₀` | `O₄₇ == grn₁₉` | |
|
||||
|
||||
|
||||
|
||||
|
|
@ -525,7 +525,7 @@ FPGA logic if desired.
|
|||
|
||||
There are sixteen (`16x`) blocks of memory, each storing a 16-bit value.
|
||||
Blocks may be protected (`P` column) as read-only (`RO`) or write-only (`WO`).
|
||||
`Lock₀` === Disable writingPermanent write-prevention when set to 1.
|
||||
`Lock₀` === Disable writing ... (?) write-prevention when set to 1.
|
||||
`Lock₁` === Pin-code lock
|
||||
|
||||
| `Block` | `P` | `Purpose` | Bits (LSB first) | Bits (MSB first) |
|
||||
|
|
|
|||
46
client/deps/id48/espresso/output_g1.pla
Normal file
46
client/deps/id48/espresso/output_g1.pla
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# ###################
|
||||
# Generating .PLA
|
||||
# ###################
|
||||
|
||||
|
||||
.i 5
|
||||
.o 1
|
||||
.ilb a l2 l3 l0 l6
|
||||
.ob g1
|
||||
00000 1
|
||||
00001 1
|
||||
00010 1
|
||||
00011 1
|
||||
00100 0
|
||||
00101 0
|
||||
00110 1
|
||||
00111 0
|
||||
01000 0
|
||||
01001 1
|
||||
01010 0
|
||||
01011 0
|
||||
01100 1
|
||||
01101 0
|
||||
01110 0
|
||||
01111 1
|
||||
10000 1
|
||||
10001 0
|
||||
10010 0
|
||||
10011 0
|
||||
10100 0
|
||||
10101 1
|
||||
10110 0
|
||||
10111 1
|
||||
11000 0
|
||||
11001 0
|
||||
11010 1
|
||||
11011 1
|
||||
11100 1
|
||||
11101 1
|
||||
11110 1
|
||||
11111 0
|
||||
.e
|
||||
|
||||
# ###################
|
||||
# END OF .PLA
|
||||
# ###################
|
||||
46
client/deps/id48/espresso/output_g2.pla
Normal file
46
client/deps/id48/espresso/output_g2.pla
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# ###################
|
||||
# Generating .PLA
|
||||
# ###################
|
||||
|
||||
|
||||
.i 5
|
||||
.o 1
|
||||
.ilb l5 b m0 l4 m1
|
||||
.ob g2
|
||||
00000 1
|
||||
00001 1
|
||||
00010 1
|
||||
00011 1
|
||||
00100 0
|
||||
00101 0
|
||||
00110 0
|
||||
00111 1
|
||||
01000 0
|
||||
01001 1
|
||||
01010 0
|
||||
01011 0
|
||||
01100 1
|
||||
01101 0
|
||||
01110 1
|
||||
01111 0
|
||||
10000 1
|
||||
10001 0
|
||||
10010 0
|
||||
10011 0
|
||||
10100 0
|
||||
10101 1
|
||||
10110 1
|
||||
10111 0
|
||||
11000 0
|
||||
11001 0
|
||||
11010 1
|
||||
11011 1
|
||||
11100 1
|
||||
11101 1
|
||||
11110 0
|
||||
11111 1
|
||||
.e
|
||||
|
||||
# ###################
|
||||
# END OF .PLA
|
||||
# ###################
|
||||
46
client/deps/id48/espresso/output_g3.pla
Normal file
46
client/deps/id48/espresso/output_g3.pla
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# ###################
|
||||
# Generating .PLA
|
||||
# ###################
|
||||
|
||||
|
||||
.i 5
|
||||
.o 1
|
||||
.ilb m5 c r1 m3 r3
|
||||
.ob g3
|
||||
00000 1
|
||||
00001 1
|
||||
00010 1
|
||||
00011 1
|
||||
00100 0
|
||||
00101 0
|
||||
00110 0
|
||||
00111 1
|
||||
01000 0
|
||||
01001 0
|
||||
01010 1
|
||||
01011 0
|
||||
01100 1
|
||||
01101 1
|
||||
01110 0
|
||||
01111 0
|
||||
10000 1
|
||||
10001 0
|
||||
10010 0
|
||||
10011 0
|
||||
10100 0
|
||||
10101 1
|
||||
10110 1
|
||||
10111 0
|
||||
11000 0
|
||||
11001 1
|
||||
11010 0
|
||||
11011 1
|
||||
11100 1
|
||||
11101 0
|
||||
11110 1
|
||||
11111 1
|
||||
.e
|
||||
|
||||
# ###################
|
||||
# END OF .PLA
|
||||
# ###################
|
||||
46
client/deps/id48/espresso/output_g4.pla
Normal file
46
client/deps/id48/espresso/output_g4.pla
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# ###################
|
||||
# Generating .PLA
|
||||
# ###################
|
||||
|
||||
|
||||
.i 5
|
||||
.o 1
|
||||
.ilb r2 r4 r6 r0 r5
|
||||
.ob g4
|
||||
00000 1
|
||||
00001 1
|
||||
00010 1
|
||||
00011 1
|
||||
00100 0
|
||||
00101 0
|
||||
00110 0
|
||||
00111 1
|
||||
01000 0
|
||||
01001 0
|
||||
01010 1
|
||||
01011 0
|
||||
01100 1
|
||||
01101 1
|
||||
01110 0
|
||||
01111 0
|
||||
10000 0
|
||||
10001 1
|
||||
10010 0
|
||||
10011 0
|
||||
10100 1
|
||||
10101 0
|
||||
10110 1
|
||||
10111 0
|
||||
11000 1
|
||||
11001 0
|
||||
11010 0
|
||||
11011 1
|
||||
11100 0
|
||||
11101 1
|
||||
11110 1
|
||||
11111 1
|
||||
.e
|
||||
|
||||
# ###################
|
||||
# END OF .PLA
|
||||
# ###################
|
||||
270
client/deps/id48/espresso/output_xx.pla
Normal file
270
client/deps/id48/espresso/output_xx.pla
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
# ###################
|
||||
# Generating .PLA
|
||||
# ###################
|
||||
|
||||
|
||||
.i 8
|
||||
.o 1
|
||||
.ilb l0 l4 l6 m1 m3 r0 r3 r5
|
||||
.ob XX
|
||||
00000000 0
|
||||
00000001 0
|
||||
00000010 1
|
||||
00000011 0
|
||||
00000100 0
|
||||
00000101 0
|
||||
00000110 1
|
||||
00000111 0
|
||||
00001000 1
|
||||
00001001 1
|
||||
00001010 1
|
||||
00001011 1
|
||||
00001100 1
|
||||
00001101 1
|
||||
00001110 1
|
||||
00001111 1
|
||||
00010000 1
|
||||
00010001 1
|
||||
00010010 1
|
||||
00010011 1
|
||||
00010100 0
|
||||
00010101 0
|
||||
00010110 1
|
||||
00010111 0
|
||||
00011000 1
|
||||
00011001 1
|
||||
00011010 1
|
||||
00011011 1
|
||||
00011100 0
|
||||
00011101 0
|
||||
00011110 1
|
||||
00011111 0
|
||||
00100000 1
|
||||
00100001 0
|
||||
00100010 1
|
||||
00100011 0
|
||||
00100100 1
|
||||
00100101 0
|
||||
00100110 1
|
||||
00100111 0
|
||||
00101000 1
|
||||
00101001 1
|
||||
00101010 1
|
||||
00101011 1
|
||||
00101100 1
|
||||
00101101 1
|
||||
00101110 1
|
||||
00101111 1
|
||||
00110000 1
|
||||
00110001 0
|
||||
00110010 1
|
||||
00110011 0
|
||||
00110100 1
|
||||
00110101 0
|
||||
00110110 1
|
||||
00110111 0
|
||||
00111000 1
|
||||
00111001 0
|
||||
00111010 1
|
||||
00111011 0
|
||||
00111100 1
|
||||
00111101 0
|
||||
00111110 1
|
||||
00111111 0
|
||||
01000000 0
|
||||
01000001 0
|
||||
01000010 1
|
||||
01000011 1
|
||||
01000100 0
|
||||
01000101 0
|
||||
01000110 1
|
||||
01000111 1
|
||||
01001000 1
|
||||
01001001 1
|
||||
01001010 1
|
||||
01001011 1
|
||||
01001100 1
|
||||
01001101 1
|
||||
01001110 1
|
||||
01001111 1
|
||||
01010000 1
|
||||
01010001 1
|
||||
01010010 1
|
||||
01010011 1
|
||||
01010100 0
|
||||
01010101 0
|
||||
01010110 1
|
||||
01010111 1
|
||||
01011000 1
|
||||
01011001 1
|
||||
01011010 1
|
||||
01011011 1
|
||||
01011100 0
|
||||
01011101 0
|
||||
01011110 1
|
||||
01011111 0
|
||||
01100000 0
|
||||
01100001 0
|
||||
01100010 1
|
||||
01100011 1
|
||||
01100100 0
|
||||
01100101 0
|
||||
01100110 1
|
||||
01100111 1
|
||||
01101000 1
|
||||
01101001 1
|
||||
01101010 1
|
||||
01101011 1
|
||||
01101100 1
|
||||
01101101 1
|
||||
01101110 1
|
||||
01101111 1
|
||||
01110000 0
|
||||
01110001 0
|
||||
01110010 1
|
||||
01110011 1
|
||||
01110100 0
|
||||
01110101 0
|
||||
01110110 1
|
||||
01110111 1
|
||||
01111000 0
|
||||
01111001 0
|
||||
01111010 1
|
||||
01111011 0
|
||||
01111100 0
|
||||
01111101 0
|
||||
01111110 1
|
||||
01111111 0
|
||||
10000000 0
|
||||
10000001 0
|
||||
10000010 0
|
||||
10000011 0
|
||||
10000100 0
|
||||
10000101 0
|
||||
10000110 0
|
||||
10000111 0
|
||||
10001000 0
|
||||
10001001 0
|
||||
10001010 0
|
||||
10001011 0
|
||||
10001100 0
|
||||
10001101 0
|
||||
10001110 0
|
||||
10001111 0
|
||||
10010000 1
|
||||
10010001 1
|
||||
10010010 1
|
||||
10010011 1
|
||||
10010100 0
|
||||
10010101 0
|
||||
10010110 0
|
||||
10010111 0
|
||||
10011000 1
|
||||
10011001 1
|
||||
10011010 1
|
||||
10011011 1
|
||||
10011100 0
|
||||
10011101 0
|
||||
10011110 0
|
||||
10011111 0
|
||||
10100000 1
|
||||
10100001 0
|
||||
10100010 1
|
||||
10100011 0
|
||||
10100100 1
|
||||
10100101 0
|
||||
10100110 1
|
||||
10100111 0
|
||||
10101000 1
|
||||
10101001 0
|
||||
10101010 1
|
||||
10101011 0
|
||||
10101100 1
|
||||
10101101 0
|
||||
10101110 1
|
||||
10101111 0
|
||||
10110000 1
|
||||
10110001 0
|
||||
10110010 1
|
||||
10110011 0
|
||||
10110100 1
|
||||
10110101 0
|
||||
10110110 1
|
||||
10110111 0
|
||||
10111000 1
|
||||
10111001 0
|
||||
10111010 1
|
||||
10111011 0
|
||||
10111100 1
|
||||
10111101 0
|
||||
10111110 1
|
||||
10111111 0
|
||||
11000000 0
|
||||
11000001 0
|
||||
11000010 1
|
||||
11000011 1
|
||||
11000100 0
|
||||
11000101 0
|
||||
11000110 1
|
||||
11000111 1
|
||||
11001000 0
|
||||
11001001 0
|
||||
11001010 0
|
||||
11001011 0
|
||||
11001100 0
|
||||
11001101 0
|
||||
11001110 0
|
||||
11001111 0
|
||||
11010000 1
|
||||
11010001 1
|
||||
11010010 1
|
||||
11010011 1
|
||||
11010100 0
|
||||
11010101 0
|
||||
11010110 1
|
||||
11010111 1
|
||||
11011000 1
|
||||
11011001 1
|
||||
11011010 1
|
||||
11011011 1
|
||||
11011100 0
|
||||
11011101 0
|
||||
11011110 0
|
||||
11011111 0
|
||||
11100000 0
|
||||
11100001 0
|
||||
11100010 1
|
||||
11100011 1
|
||||
11100100 0
|
||||
11100101 0
|
||||
11100110 1
|
||||
11100111 1
|
||||
11101000 0
|
||||
11101001 0
|
||||
11101010 0
|
||||
11101011 0
|
||||
11101100 0
|
||||
11101101 0
|
||||
11101110 0
|
||||
11101111 0
|
||||
11110000 0
|
||||
11110001 0
|
||||
11110010 1
|
||||
11110011 1
|
||||
11110100 0
|
||||
11110101 0
|
||||
11110110 1
|
||||
11110111 1
|
||||
11111000 0
|
||||
11111001 0
|
||||
11111010 0
|
||||
11111011 0
|
||||
11111100 0
|
||||
11111101 0
|
||||
11111110 0
|
||||
11111111 0
|
||||
.e
|
||||
|
||||
# ###################
|
||||
# END OF .PLA
|
||||
# ###################
|
||||
|
|
@ -31,13 +31,13 @@
|
|||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#if defined(NDEBUG)
|
||||
#define ASSERT(x) ((void)0)
|
||||
#define ASSERT(x) ((void)0)
|
||||
#elif defined(ID48_NO_STDIO)
|
||||
#define ASSERT(x) ((void)0)
|
||||
#define ASSERT(x) ((void)0)
|
||||
#else // neither NDEBUG nor ID48_NO_STDIO defined
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#define ASSERT(x) assert((x))
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#define ASSERT(x) assert((x))
|
||||
#endif
|
||||
|
||||
|
||||
25
client/deps/id48/src/CMakeLists.txt
Normal file
25
client/deps/id48/src/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
project(id48lib LANGUAGES C CXX ASM)
|
||||
|
||||
add_library(id48lib STATIC
|
||||
id48_data.c
|
||||
id48_generator.c
|
||||
id48_recover.c
|
||||
)
|
||||
|
||||
# Compile options/warnings for C sources only (use generator expression)
|
||||
target_compile_options(id48lib PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:C>:-Wpedantic -Wall -Werror -O3 -Wno-unknown-pragmas -Wno-inline -Wno-unused-function>
|
||||
)
|
||||
|
||||
# Prefer compile_definitions over embedding -D in compile options
|
||||
target_compile_definitions(id48lib PRIVATE ID48_NO_STDIO)
|
||||
|
||||
# Private include dirs for internal headers, PUBLIC for the library API
|
||||
target_include_directories(id48lib
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/id48
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../public
|
||||
)
|
||||
|
||||
set_property(TARGET id48lib PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Makefile for ID48LIB library
|
||||
# Proxmark3-specific Makefile for ID48LIB library
|
||||
MYSRCPATHS =
|
||||
MYINCLUDES = -I.
|
||||
MYINCLUDES = -I../public
|
||||
MYCFLAGS = -Wpedantic -Wall -Werror -O3 -Wno-unknown-pragmas -Wno-inline -Wno-unused-function
|
||||
MYDEFS = -DID48_NO_STDIO
|
||||
MYSRCS = \
|
||||
|
|
@ -10,4 +10,4 @@ MYSRCS = \
|
|||
|
||||
LIB_A = libid48.a
|
||||
|
||||
include ../../../Makefile.host
|
||||
include ../../../../Makefile.host
|
||||
6
client/deps/id48/tests/CMakeLists.txt
Normal file
6
client/deps/id48/tests/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
add_subdirectory(espresso)
|
||||
add_subdirectory(generator)
|
||||
add_subdirectory(recovery)
|
||||
|
||||
18
client/deps/id48/tests/espresso/CMakeLists.txt
Normal file
18
client/deps/id48/tests/espresso/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
add_executable(
|
||||
id48lib_test_espresso
|
||||
main.c
|
||||
verify_espresso.c
|
||||
)
|
||||
|
||||
target_link_libraries(id48lib_test_espresso PRIVATE id48lib)
|
||||
|
||||
target_include_directories(id48lib_test_espresso PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
target_compile_options(id48lib_test_espresso PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:C>:-O0>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-O0>
|
||||
)
|
||||
157
client/deps/id48/tests/espresso/array_size2.h
Normal file
157
client/deps/id48/tests/espresso/array_size2.h
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/**
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) SimpleHacks, Henry Gabryjelski
|
||||
https://github.com/SimpleHacks/UtilHeaders
|
||||
|
||||
All rights reserved.
|
||||
|
||||
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 ARRAYSIZE2_H
|
||||
#define ARRAYSIZE2_H
|
||||
|
||||
/**
|
||||
The following, if defined prior to inclusion of this header file,
|
||||
will modify its behavior as noted:
|
||||
|
||||
ARRAYSIZE2_SHOW_VERSION_MESSAGE
|
||||
-- if defined, will show which version of ARRAY_SIZE2 macro is selected
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
see example source at:
|
||||
https://godbolt.org/z/zzYoeK6Mf
|
||||
*/
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0 /* Compatibility with non-clang compilers. */
|
||||
#endif
|
||||
|
||||
#if (defined(__cplusplus) && __cplusplus >= 201103L) || /* any compiler claiming C++11 support */ \
|
||||
(defined(__cplusplus) && _MSC_VER >= 1900 && __cplusplus != 199711L) || /* Visual C++ 2015 or higher */ \
|
||||
__has_feature(cxx_constexpr) /* CLang versions supporting constexp */
|
||||
|
||||
#include <stddef.h> /* required for size_t */
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message( "ARRAY_SIZE2 -- Using C++11 version" )
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, size_t N>
|
||||
constexpr size_t ARRAY_SIZE2_ARGUMENT_CANNOT_BE_POINTER(T const (&)[N]) noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
} /* namespace detail */
|
||||
#define ARRAY_SIZE2(arr) detail::ARRAY_SIZE2_ARGUMENT_CANNOT_BE_POINTER(arr)
|
||||
|
||||
#elif defined(__cplusplus) && __cplusplus >= 199711L && ( /* C++ 98 trick */ \
|
||||
defined(__INTEL_COMPILER) || \
|
||||
defined(__clang__) || \
|
||||
(defined(__GNUC__) && ( \
|
||||
(__GNUC__ > 4) || \
|
||||
(__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
|
||||
)))
|
||||
|
||||
#include <stddef.h> /* required for size_t */
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message "ARRAY_SIZE2 -- Using C++98 version"
|
||||
#endif
|
||||
template <typename T, size_t N>
|
||||
char(&_ArraySizeHelperRequiresArray(T(&)[N]))[N];
|
||||
#define ARRAY_SIZE2(x) sizeof(_ArraySizeHelperRequiresArray(x))
|
||||
|
||||
#elif defined(__cplusplus) /* && ((__cplusplus >= 199711L) || defined(__INTEL_COMPILER) || defined(__clang__)) */
|
||||
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message( "ARRAY_SIZE2 -- Using Ivan J. Johnson's C++ version" )
|
||||
#endif
|
||||
/*
|
||||
Works on older compilers, even Visual C++ 6....
|
||||
Created by Ivan J. Johnson, March 06, 2007
|
||||
See http://drdobbs.com/cpp/197800525?pgno=1
|
||||
|
||||
Full description is in markdown file array_size2.md
|
||||
*/
|
||||
#define ARRAY_SIZE2(arr) ( \
|
||||
0 * sizeof(reinterpret_cast<const ::Bad_arg_to_ARRAY_SIZE2*>(arr)) + /*check1*/ \
|
||||
0 * sizeof(::Bad_arg_to_ARRAY_SIZE2::check_type((arr), &(arr))) + /*check2*/ \
|
||||
sizeof(arr) / sizeof((arr)[0]) /* eval */ \
|
||||
)
|
||||
|
||||
struct Bad_arg_to_ARRAY_SIZE2 {
|
||||
class Is_pointer; /* incomplete */
|
||||
class Is_array {};
|
||||
template <typename T>
|
||||
static Is_pointer check_type(T const *, T const * const *);
|
||||
static Is_array check_type(void const *, void const *);
|
||||
};
|
||||
|
||||
#elif !defined(__cplusplus) && defined(__GNUC__)
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
Even C can have type-safety for equivalent of ARRAY_SIZE() macro,
|
||||
when using the following two GCC extensions:
|
||||
typeof()
|
||||
__builtin_types_compatible_p()
|
||||
*/
|
||||
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message( "ARRAY_SIZE2 -- Using GNUC version" )
|
||||
#endif
|
||||
|
||||
/**
|
||||
validated using:
|
||||
MSP430 gcc 4.5.3
|
||||
x86-64 icc 16.0.3
|
||||
x86-64 gcc 4.1.2
|
||||
x86-64 clang 3.0.0
|
||||
AVR gcc 4.5.4
|
||||
ARM gcc 4.5.4
|
||||
*/
|
||||
|
||||
#define __SIMPLEHACKS_COMPATIBLE_TYPES__(a,b) __builtin_types_compatible_p(__typeof__(a), __typeof__(b)) /* GCC extensions */
|
||||
#define __SIMPLEHACKS_BUILD_ERROR_ON_NONZERO__(x) (sizeof(struct { uint8_t q: (-!!(x)*0x1ee7)+1u;})-1u) /* if x is zero, reports "error: negative width in bit-field '<anonymous>'" */
|
||||
#define __SIMPLEHACKS_MUST_BE_ARRAY__(x) __SIMPLEHACKS_BUILD_ERROR_ON_NONZERO__(__SIMPLEHACKS_COMPATIBLE_TYPES__((x), &(*x)))
|
||||
#define ARRAY_SIZE2(_arr) ( (sizeof(_arr) / sizeof((_arr)[0])) + __SIMPLEHACKS_MUST_BE_ARRAY__(_arr) ) /* compile-time error if not an array */
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
The good news is that all compilers (as of 20202-05-08)
|
||||
on godbolt.org are fully supported. Therefore, if some
|
||||
other compiler does not support any of the above method,
|
||||
it's important to force a compile-time error, to avoid
|
||||
any suggestion that this provides a safe macro.
|
||||
*/
|
||||
|
||||
#error "Unable to provide type-safe ARRAY_SIZE2 macro"
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ARRAYSIZE2_H
|
||||
25
client/deps/id48/tests/espresso/main.c
Normal file
25
client/deps/id48/tests/espresso/main.c
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "verify_espresso.h"
|
||||
#include "id48.h"
|
||||
|
||||
int main(void) {
|
||||
bool result = true;
|
||||
|
||||
if (result) {
|
||||
printf("Verifying Espresso Results...\n");
|
||||
result = verify_espresso_results();
|
||||
printf("Verifying Espresso Results: %s\n",
|
||||
result ? "SUCCESS" : "----> FAILURE <----"
|
||||
);
|
||||
}
|
||||
// if (result) {
|
||||
// printf("Hello2...\n");
|
||||
// generate_all_lut_espresso_files();
|
||||
// }
|
||||
|
||||
return result ? 0 : -120;
|
||||
}
|
||||
817
client/deps/id48/tests/espresso/verify_espresso.c
Normal file
817
client/deps/id48/tests/espresso/verify_espresso.c
Normal file
|
|
@ -0,0 +1,817 @@
|
|||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "array_size2.h"
|
||||
#include "id48.h"
|
||||
#include "verify_espresso.h"
|
||||
|
||||
#if !defined true
|
||||
#define true ((bool)1u)
|
||||
#endif
|
||||
#if !defined false
|
||||
#define false ((bool)0u)
|
||||
#endif
|
||||
|
||||
#if 1 // constant names for use in LUT_PLA_NAMES_xx
|
||||
static const char * const NAME_A = "a";
|
||||
static const char * const NAME_B = "b";
|
||||
static const char * const NAME_C = "c";
|
||||
static const char * const NAME_L0 = "l0";
|
||||
static const char * const NAME_L2 = "l2";
|
||||
static const char * const NAME_L3 = "l3";
|
||||
static const char * const NAME_L4 = "l4";
|
||||
static const char * const NAME_L5 = "l5";
|
||||
static const char * const NAME_L6 = "l6";
|
||||
static const char * const NAME_M0 = "m0";
|
||||
static const char * const NAME_M1 = "m1";
|
||||
static const char * const NAME_M3 = "m3";
|
||||
static const char * const NAME_M5 = "m5";
|
||||
static const char * const NAME_R0 = "r0";
|
||||
static const char * const NAME_R1 = "r1";
|
||||
static const char * const NAME_R2 = "r2";
|
||||
static const char * const NAME_R3 = "r3";
|
||||
static const char * const NAME_R4 = "r4";
|
||||
static const char * const NAME_R5 = "r5";
|
||||
static const char * const NAME_R6 = "r6";
|
||||
#endif // constant names for use in LUT_PLA_NAMES_xx
|
||||
#if 1 // LUT_PLA_NAMES_xx -- name arrays for generating espresso input files
|
||||
// NOTE: these arrays are in order of the most significant to least significant bit.
|
||||
// did i get confused by that?
|
||||
const char * const LUT_PLA_NAMES_g1[5] = { NAME_A , NAME_L2, NAME_L3, NAME_L0, NAME_L6, };
|
||||
const char * const LUT_PLA_NAMES_g2[5] = { NAME_L5, NAME_B , NAME_M0, NAME_L4, NAME_M1, };
|
||||
const char * const LUT_PLA_NAMES_g3[5] = { NAME_M5, NAME_C , NAME_R1, NAME_M3, NAME_R3, };
|
||||
const char * const LUT_PLA_NAMES_g4[5] = { NAME_R2, NAME_R4, NAME_R6, NAME_R0, NAME_R5, };
|
||||
const char * const LUT_PLA_NAMES_XX[8] = {
|
||||
NAME_L0, NAME_L4, NAME_L6, NAME_M1,
|
||||
NAME_M3, NAME_R0, NAME_R3, NAME_R5,
|
||||
};
|
||||
#endif // LUT_PLA_NAMES_xx -- name arrays for generating espresso input files
|
||||
|
||||
#if 1 // actual lookup tables
|
||||
// LUTs were internal-only, and not even exposed to library internals.
|
||||
// so just copy/paste here for now for initial testing
|
||||
/// initial_idx = (l0 << 7) | (l4 << 6) | (l6 << 5) | (m1 << 4) | (m3 << 3) | (r0 << 2) | (r3 << 1) | (r5 << 0)
|
||||
static const uint8_t small_lut_XX[32] = { // aka 256 bits
|
||||
0x44, 0xff, 0x4f, 0x4f, 0x55, 0xff, 0x55, 0x55,
|
||||
0xcc, 0xff, 0xcf, 0x4f, 0xcc, 0xff, 0xcc, 0x44,
|
||||
0x00, 0x00, 0x0f, 0x0f, 0x55, 0x55, 0x55, 0x55,
|
||||
0xcc, 0x00, 0xcf, 0x0f, 0xcc, 0x00, 0xcc, 0x00,
|
||||
};
|
||||
/// g1_idx = (a << 4) | (l2 << 3) | (l3 << 2) | (l0 << 1) | (l6 << 0)
|
||||
static const uint8_t small_lut_group1[4] = { // aka 32 bits
|
||||
0x4f, 0x92, 0xa1, 0x7c,
|
||||
};
|
||||
/// g2_idx = (l5 << 4) | (b << 3) | (m0 << 2) | (l4 << 1) | (m1 << 0)
|
||||
static const uint8_t small_lut_group2[4] = { // aka 32 bits
|
||||
0x8f, 0x52, 0x61, 0xbc,
|
||||
};
|
||||
/// g3_idx = (m5 << 4) | (c << 3) | (r1 << 2) | (m3 << 1) | (r3 << 0)
|
||||
static const uint8_t small_lut_group3[4] = { // aka 32 bits
|
||||
0x8f, 0x34, 0x61, 0xda,
|
||||
};
|
||||
/// g4_idx = (r2 << 4) | (r4 << 3) | (r6 << 2) | (r0 << 1) | (r5 << 0)
|
||||
static const uint8_t small_lut_group4[4] = { // aka 32 bits
|
||||
0x8f, 0x34, 0x52, 0xe9,
|
||||
};
|
||||
static inline bool get_bit(const uint8_t *table_start, uint32_t bit_idx) {
|
||||
const uint32_t byte = bit_idx / 8u;
|
||||
const uint8_t mask = 1u << (bit_idx % 8u);
|
||||
return (table_start[byte] & mask) != 0;
|
||||
}
|
||||
#endif // actual lookup tables
|
||||
|
||||
|
||||
|
||||
// 1. validated by hand that LUT --> PLA generation was accurate for all five LUTs
|
||||
// 2. Ran the generated PLA through WASM-based espresso:
|
||||
// https://nudelerde.github.io/Espresso-Wasm-Web/index.html
|
||||
// 3. Copied the output to each validation function
|
||||
// 4. Converted the output to C-style boolean logic, and column-aligned formatting for easier review
|
||||
//
|
||||
// Same process used for each, but only g1 validates against the lookup table.
|
||||
// Maybe just use the LUTs in an FPGA instead of trying to minimize to two-level logic?
|
||||
// However, performance will be best with two-level, glitch-free logic....
|
||||
//
|
||||
// WHAT IS GOING WRONG WITH ESPRESSO OUTPUT (OR MY VALIDATION)?
|
||||
//
|
||||
// After adding a whole set of secondary validation functions... the root cause was ....
|
||||
// Accidentally initializing any_failures to true instead of false in the other functions.
|
||||
//
|
||||
// :-P
|
||||
//
|
||||
// I'll check this comment into my dev branch, even if I squash-merge it out later.
|
||||
//
|
||||
typedef struct _OUTPUT_INDEX3 {
|
||||
// the index is calculated from unstable ID48LIBX_STATE_REGISTERS
|
||||
// by function calculate_output_index(), which creates a single
|
||||
// 20-bit result:
|
||||
// Fₒ( abc l₀l₂l₃l₄l₅l₆ m₀m₁m₃m₅ r₀r₁r₂r₃r₄r₅r₆ )
|
||||
// msb 19 ---^ lsb 00 ---^^
|
||||
// This union allows debugger to view the individual bit values more easily.
|
||||
union {
|
||||
uint32_t Raw32;
|
||||
struct {
|
||||
// seven bits from r: r₀..r₆
|
||||
uint32_t r6 : 1; // bit 00
|
||||
uint32_t r5 : 1; // bit 01
|
||||
uint32_t r4 : 1; // bit 02
|
||||
uint32_t r3 : 1; // bit 03
|
||||
uint32_t r2 : 1; // bit 04
|
||||
uint32_t r1 : 1; // bit 05
|
||||
uint32_t r0 : 1; // bit 06
|
||||
// four bits from m: m₀m₁m₃m₅
|
||||
uint32_t m5 : 1; // bit 07
|
||||
uint32_t m3 : 1; // bit 08
|
||||
uint32_t m1 : 1; // bit 09
|
||||
uint32_t m0 : 1; // bit 10
|
||||
// six bits from l: l₀l₂l₃l₄l₅l₆
|
||||
uint32_t l6 : 1; // bit 11
|
||||
uint32_t l5 : 1; // bit 12
|
||||
uint32_t l4 : 1; // bit 13
|
||||
uint32_t l3 : 1; // bit 14
|
||||
uint32_t l2 : 1; // bit 15
|
||||
uint32_t l0 : 1; // bit 16
|
||||
// and finally, the three bits a, b, c
|
||||
uint32_t c : 1; // bit 17
|
||||
uint32_t b : 1; // bit 18
|
||||
uint32_t a : 1; // bit 19
|
||||
};
|
||||
};
|
||||
} OUTPUT_INDEX3;
|
||||
|
||||
|
||||
|
||||
#if 1 // structures for mapping LUT indices to named fields
|
||||
/// g1_idx = (a << 4) | (l2 << 3) | (l3 << 2) | (l0 << 1) | (l6 << 0)
|
||||
typedef struct _INDEX_G1 {
|
||||
union {
|
||||
uint8_t as_uint8_t;
|
||||
struct {
|
||||
uint8_t l6 : 1; // least significant bit
|
||||
uint8_t l0 : 1;
|
||||
uint8_t l3 : 1;
|
||||
uint8_t l2 : 1;
|
||||
uint8_t a : 1;
|
||||
};
|
||||
};
|
||||
} INDEX_G1;
|
||||
/// g2_idx = (l5 << 4) | (b << 3) | (m0 << 2) | (l4 << 1) | (m1 << 0)
|
||||
typedef struct _INDEX_G2 {
|
||||
union {
|
||||
uint8_t as_uint8_t;
|
||||
struct {
|
||||
uint8_t m1 : 1;
|
||||
uint8_t l4 : 1;
|
||||
uint8_t m0 : 1;
|
||||
uint8_t b : 1;
|
||||
uint8_t l5 : 1;
|
||||
};
|
||||
};
|
||||
} INDEX_G2;
|
||||
/// g3_idx = (m5 << 4) | (c << 3) | (r1 << 2) | (m3 << 1) | (r3 << 0)
|
||||
typedef struct _INDEX_G3 {
|
||||
union {
|
||||
uint8_t as_uint8_t;
|
||||
struct {
|
||||
uint8_t r3 : 1;
|
||||
uint8_t m3 : 1;
|
||||
uint8_t r1 : 1;
|
||||
uint8_t c : 1;
|
||||
uint8_t m5 : 1;
|
||||
};
|
||||
};
|
||||
} INDEX_G3;
|
||||
/// g4_idx = (r2 << 4) | (r4 << 3) | (r6 << 2) | (r0 << 1) | (r5 << 0)
|
||||
typedef struct _INDEX_G4 {
|
||||
union {
|
||||
uint8_t as_uint8_t;
|
||||
struct {
|
||||
uint8_t r5 : 1;
|
||||
uint8_t r0 : 1;
|
||||
uint8_t r6 : 1;
|
||||
uint8_t r4 : 1;
|
||||
uint8_t r2 : 1;
|
||||
};
|
||||
};
|
||||
} INDEX_G4;
|
||||
/// initial_idx = (l0 << 7) | (l4 << 6) | (l6 << 5) | (m1 << 4) | (m3 << 3) | (r0 << 2) | (r3 << 1) | (r5 << 0)
|
||||
typedef struct _INDEX_XX {
|
||||
union {
|
||||
uint8_t as_uint8_t;
|
||||
struct {
|
||||
uint8_t r5 : 1;
|
||||
uint8_t r3 : 1;
|
||||
uint8_t r0 : 1;
|
||||
uint8_t m3 : 1;
|
||||
uint8_t m1 : 1;
|
||||
uint8_t l6 : 1;
|
||||
uint8_t l4 : 1;
|
||||
uint8_t l0 : 1;
|
||||
};
|
||||
};
|
||||
} INDEX_XX;
|
||||
#endif // structures for mapping LUT indices to named fields
|
||||
|
||||
typedef struct _ESPRESSO_GENERATOR_ARGUMENTS {
|
||||
uint8_t const input_count;
|
||||
char const * const * names;
|
||||
char const * const output_name;
|
||||
uint8_t const * lut_start;
|
||||
} ESPRESSO_GENERATOR_ARGUMENTS;
|
||||
|
||||
static bool verify_lut_g1(void);
|
||||
static bool verify_lut_g2(void);
|
||||
static bool verify_lut_g3(void);
|
||||
static bool verify_lut_g4(void);
|
||||
static bool verify_lut_XX(void);
|
||||
|
||||
// Later, define a struct with functions for each thing to be validated
|
||||
typedef bool (*lookuptable_func_t)(uint8_t);
|
||||
|
||||
|
||||
/// g1_idx = (a << 4) | (l2 << 3) | (l3 << 2) | (l0 << 1) | (l6 << 0)
|
||||
static bool espresso_implementation_g1_alt0(uint8_t idx) {
|
||||
// output_g1 = (a&l2&l0&!l6) | (a&l3&!l0&l6) | (!a&!l2&!l3) | (!l2&!l3&!l0&!l6) | (l2&l3&!l0&!l6) | (!a&!l2&l0&!l6) | (!a&!l3&!l0&l6) | (a&l2&!l3&l0) | (a&!l2&l3&l6) | (!a&l2&l3&l0&l6);
|
||||
|
||||
static const bool _ = true;
|
||||
bool a = idx & (1u << 4);
|
||||
bool l2 = idx & (1u << 3);
|
||||
bool l3 = idx & (1u << 2);
|
||||
bool l0 = idx & (1u << 1);
|
||||
bool l6 = idx & (1u << 0);
|
||||
return
|
||||
( a && l2 && _ && l0 && !(l6) ) ||
|
||||
( a && _ && l3 && !(l0) && l6 ) ||
|
||||
( !(a) && !(l2) && !(l3) && _ && _ ) ||
|
||||
( _ && !(l2) && !(l3) && !(l0) && !(l6) ) ||
|
||||
( _ && l2 && l3 && !(l0) && !(l6) ) ||
|
||||
( !(a) && !(l2) && _ && l0 && !(l6) ) ||
|
||||
( !(a) && _ && !(l3) && !(l0) && l6 ) ||
|
||||
( a && l2 && !(l3) && l0 && _ ) ||
|
||||
( a && !(l2) && l3 && _ && l6 ) ||
|
||||
( !(a) && l2 && l3 && l0 && l6 ) ;
|
||||
}
|
||||
static bool espresso_implementation_g1_alt1(uint8_t idx) {
|
||||
// output_g1 = (a&l2&l0&!l6) | (a&l3&!l0&l6) | (!a&!l2&!l3) | (!l2&!l3&!l0&!l6) | (l2&l3&!l0&!l6) | (!a&!l2&l0&!l6) | (!a&!l3&!l0&l6) | (a&l2&!l3&l0) | (a&!l2&l3&l6) | (!a&l2&l3&l0&l6);
|
||||
static const bool _ = true;
|
||||
INDEX_G1 t = { .as_uint8_t = idx };
|
||||
bool a = t.a;
|
||||
bool l2 = t.l2;
|
||||
bool l3 = t.l3;
|
||||
bool l0 = t.l0;
|
||||
bool l6 = t.l6;
|
||||
return
|
||||
( a && l0 && l2 && _ && !(l6) ) ||
|
||||
( a && !(l0) && _ && l3 && l6 ) ||
|
||||
( !(a) && _ && !(l2) && !(l3) && _ ) ||
|
||||
( _ && !(l0) && !(l2) && !(l3) && !(l6) ) ||
|
||||
( _ && !(l0) && l2 && l3 && !(l6) ) ||
|
||||
( !(a) && l0 && !(l2) && _ && !(l6) ) ||
|
||||
( !(a) && !(l0) && _ && !(l3) && l6 ) ||
|
||||
( a && l0 && l2 && !(l3) && _ ) ||
|
||||
( a && _ && !(l2) && l3 && l6 ) ||
|
||||
( !(a) && l0 && l2 && l3 && l6 ) ;
|
||||
}
|
||||
static const lookuptable_func_t alt_for_g1[] = {
|
||||
espresso_implementation_g1_alt0,
|
||||
espresso_implementation_g1_alt1,
|
||||
};
|
||||
|
||||
|
||||
static bool espresso_implementation_g2_alt0(uint8_t idx) {
|
||||
// output_g2 = (b&m0&!l4&!m1) | (l5&b&l4&m1) | (!l5&!b&!m0) | (!b&!m0&!l4&!m1) | (l5&b&!m0&l4) | (l5&!b&m0&l4&!m1) | (!l5&b&m0&!m1) | (!l5&!m0&!l4&m1) | (l5&m0&!l4&m1) | (!l5&!b&l4&m1);
|
||||
// g2_idx = (l5 << 4) | (b << 3) | (m0 << 2) | (l4 << 1) | (m1 << 0)
|
||||
bool l5 = idx & (1u << 4);
|
||||
bool b = idx & (1u << 3);
|
||||
bool m0 = idx & (1u << 2);
|
||||
bool l4 = idx & (1u << 1);
|
||||
bool m1 = idx & (1u << 0);
|
||||
static const bool _ = true;
|
||||
return
|
||||
( _ && b && m0 && !(l4) && !(m1) ) |
|
||||
( l5 && b && _ && l4 && m1 ) |
|
||||
( !(l5) && !(b) && !(m0) && _ && _ ) |
|
||||
( _ && !(b) && !(m0) && !(l4) && !(m1) ) |
|
||||
( l5 && b && !(m0) && l4 && _ ) |
|
||||
( l5 && !(b) && m0 && l4 && !(m1) ) |
|
||||
( !(l5) && b && m0 && _ && !(m1) ) |
|
||||
( !(l5) && _ && !(m0) && !(l4) && m1 ) |
|
||||
( l5 && _ && m0 && !(l4) && m1 ) |
|
||||
( !(l5) && !(b) && _ && l4 && m1 ) ;
|
||||
}
|
||||
static bool espresso_implementation_g2_alt1(uint8_t idx) {
|
||||
// output_g2 = (b&m0&!l4&!m1) | (l5&b&l4&m1) | (!l5&!b&!m0) | (!b&!m0&!l4&!m1) | (l5&b&!m0&l4) | (l5&!b&m0&l4&!m1) | (!l5&b&m0&!m1) | (!l5&!m0&!l4&m1) | (l5&m0&!l4&m1) | (!l5&!b&l4&m1);
|
||||
INDEX_G2 t = { .as_uint8_t = idx };
|
||||
bool l5 = t.l5;
|
||||
bool b = t.b;
|
||||
bool m0 = t.m0;
|
||||
bool l4 = t.l4;
|
||||
bool m1 = t.m1;
|
||||
static const bool _ = true;
|
||||
return
|
||||
( _ && b && m0 && !(l4) && !(m1) ) |
|
||||
( l5 && b && _ && l4 && m1 ) |
|
||||
( !(l5) && !(b) && !(m0) && _ && _ ) |
|
||||
( _ && !(b) && !(m0) && !(l4) && !(m1) ) |
|
||||
( l5 && b && !(m0) && l4 && _ ) |
|
||||
( l5 && !(b) && m0 && l4 && !(m1) ) |
|
||||
( !(l5) && b && m0 && _ && !(m1) ) |
|
||||
( !(l5) && _ && !(m0) && !(l4) && m1 ) |
|
||||
( l5 && _ && m0 && !(l4) && m1 ) |
|
||||
( !(l5) && !(b) && _ && l4 && m1 ) ;
|
||||
}
|
||||
|
||||
static const lookuptable_func_t alt_for_g2[] = {
|
||||
espresso_implementation_g2_alt0,
|
||||
espresso_implementation_g2_alt1,
|
||||
// espresso_implementation_g1_alt2, // fails ... generated via https://github.com/omritriki/espresso-py ...
|
||||
};
|
||||
|
||||
|
||||
static bool espresso_implementation_g3_alt0(uint8_t idx) {
|
||||
// output_g3 = (c&r1&!m3&!r3) | (m5&c&m3&r3) | (!m5&!c&!r1) | (!c&!r1&!m3&!r3) | (!m5&!r1&m3&!r3) | (m5&r1&m3&!r3) | (m5&c&!r1&r3) | (m5&!c&r1&!m3&r3) | (!m5&c&r1&!m3) | (!m5&!c&m3&r3);
|
||||
// g3_idx = (m5 << 4) | (c << 3) | (r1 << 2) | (m3 << 1) | (r3 << 0)
|
||||
bool m5 = idx & (1u << 4);
|
||||
bool c = idx & (1u << 3);
|
||||
bool r1 = idx & (1u << 2);
|
||||
bool m3 = idx & (1u << 1);
|
||||
bool r3 = idx & (1u << 0);
|
||||
static const bool _ = true;
|
||||
return
|
||||
( _ && c && r1 && !(m3) && !(r3) ) ||
|
||||
( m5 && c && _ && m3 && r3 ) ||
|
||||
( !(m5) && !(c) && !(r1) && _ && _ ) ||
|
||||
( _ && !(c) && !(r1) && !(m3) && !(r3) ) ||
|
||||
( !(m5) && _ && !(r1) && m3 && !(r3) ) ||
|
||||
( m5 && _ && r1 && m3 && !(r3) ) ||
|
||||
( m5 && c && !(r1) && _ && r3 ) ||
|
||||
( m5 && !(c) && r1 && !(m3) && r3 ) ||
|
||||
( !(m5) && c && r1 && !(m3) && _ ) ||
|
||||
( !(m5) && !(c) && _ && m3 && r3 ) ;
|
||||
}
|
||||
static bool espresso_implementation_g3_alt1(uint8_t idx) {
|
||||
// output_g3 = (c&r1&!m3&!r3) | (m5&c&m3&r3) | (!m5&!c&!r1) | (!c&!r1&!m3&!r3) | (!m5&!r1&m3&!r3) | (m5&r1&m3&!r3) | (m5&c&!r1&r3) | (m5&!c&r1&!m3&r3) | (!m5&c&r1&!m3) | (!m5&!c&m3&r3);
|
||||
INDEX_G3 t = { .as_uint8_t = idx };
|
||||
bool c = t.c;
|
||||
bool r1 = t.r1;
|
||||
bool r3 = t.r3;
|
||||
bool m3 = t.m3;
|
||||
bool m5 = t.m5;
|
||||
static const bool _ = true;
|
||||
return
|
||||
( _ && c && r1 && !(m3) && !(r3) ) ||
|
||||
( m5 && c && _ && m3 && r3 ) ||
|
||||
( !(m5) && !(c) && !(r1) && _ && _ ) ||
|
||||
( _ && !(c) && !(r1) && !(m3) && !(r3) ) ||
|
||||
( !(m5) && _ && !(r1) && m3 && !(r3) ) ||
|
||||
( m5 && _ && r1 && m3 && !(r3) ) ||
|
||||
( m5 && c && !(r1) && _ && r3 ) ||
|
||||
( m5 && !(c) && r1 && !(m3) && r3 ) ||
|
||||
( !(m5) && c && r1 && !(m3) && _ ) ||
|
||||
( !(m5) && !(c) && _ && m3 && r3 ) ;
|
||||
}
|
||||
|
||||
static const lookuptable_func_t alt_for_g3[] = {
|
||||
espresso_implementation_g3_alt0,
|
||||
espresso_implementation_g3_alt1,
|
||||
};
|
||||
|
||||
static bool espresso_implementation_g4_alt0(uint8_t idx) {
|
||||
// output_g4 = (r2&r6&r0&!r5) | (r4&r6&!r0&r5) | (!r2&!r4&!r6) | (r2&r4&!r6&!r0&!r5) | (r2&!r4&r6&!r5) | (!r2&r4&r6&!r0) | (!r2&!r6&r0&!r5) | (!r4&!r6&!r0&r5) | (r2&r4&r0&r5) | (!r2&!r4&r0&r5);
|
||||
// g4_idx = (r2 << 4) | (r4 << 3) | (r6 << 2) | (r0 << 1) | (r5 << 0)
|
||||
bool r2 = idx & (1u << 4);
|
||||
bool r4 = idx & (1u << 3);
|
||||
bool r6 = idx & (1u << 2);
|
||||
bool r0 = idx & (1u << 1);
|
||||
bool r5 = idx & (1u << 0);
|
||||
static const bool _ = true;
|
||||
return
|
||||
( r2 && _ && r6 && r0 && !(r5) ) |
|
||||
( _ && r4 && r6 && !(r0) && r5 ) |
|
||||
( !(r2) && !(r4) && !(r6) && _ && _ ) |
|
||||
( r2 && r4 && !(r6) && !(r0) && !(r5) ) |
|
||||
( r2 && !(r4) && r6 && _ && !(r5) ) |
|
||||
( !(r2) && r4 && r6 && !(r0) && _ ) |
|
||||
( !(r2) && _ && !(r6) && r0 && !(r5) ) |
|
||||
( _ && !(r4) && !(r6) && !(r0) && r5 ) |
|
||||
( r2 && r4 && _ && r0 && r5 ) |
|
||||
( !(r2) && !(r4) && _ && r0 && r5 ) ;
|
||||
}
|
||||
static bool espresso_implementation_g4_alt1(uint8_t idx) {
|
||||
// output_g4 = (r2&r6&r0&!r5) | (r4&r6&!r0&r5) | (!r2&!r4&!r6) | (r2&r4&!r6&!r0&!r5) | (r2&!r4&r6&!r5) | (!r2&r4&r6&!r0) | (!r2&!r6&r0&!r5) | (!r4&!r6&!r0&r5) | (r2&r4&r0&r5) | (!r2&!r4&r0&r5);
|
||||
// g4_idx = (r2 << 4) | (r4 << 3) | (r6 << 2) | (r0 << 1) | (r5 << 0)
|
||||
INDEX_G4 t = { .as_uint8_t = idx };
|
||||
bool r2 = t.r2;
|
||||
bool r4 = t.r4;
|
||||
bool r6 = t.r6;
|
||||
bool r0 = t.r0;
|
||||
bool r5 = t.r5;
|
||||
static const bool _ = true;
|
||||
return
|
||||
( r2 && _ && r6 && r0 && !(r5) ) |
|
||||
( _ && r4 && r6 && !(r0) && r5 ) |
|
||||
( !(r2) && !(r4) && !(r6) && _ && _ ) |
|
||||
( r2 && r4 && !(r6) && !(r0) && !(r5) ) |
|
||||
( r2 && !(r4) && r6 && _ && !(r5) ) |
|
||||
( !(r2) && r4 && r6 && !(r0) && _ ) |
|
||||
( !(r2) && _ && !(r6) && r0 && !(r5) ) |
|
||||
( _ && !(r4) && !(r6) && !(r0) && r5 ) |
|
||||
( r2 && r4 && _ && r0 && r5 ) |
|
||||
( !(r2) && !(r4) && _ && r0 && r5 ) ;
|
||||
}
|
||||
|
||||
static const lookuptable_func_t alt_for_g4[] = {
|
||||
espresso_implementation_g4_alt0,
|
||||
espresso_implementation_g4_alt1,
|
||||
};
|
||||
|
||||
static bool espresso_implementation_xx_alt0(uint8_t idx) {
|
||||
// output_xx = (!l6&m1&!r0) | (l4&!m3&r3) | (!l4&l6&!r5) | (!l0&!m1&m3) | (!l0&r3&!r5);
|
||||
/// xx_idx = (l0 << 7) | (l4 << 6) | (l6 << 5) | (m1 << 4) | (m3 << 3) | (r0 << 2) | (r3 << 1) | (r5 << 0)
|
||||
static const bool _ = true;
|
||||
bool l0 = idx & (1u << 7);
|
||||
bool l4 = idx & (1u << 6);
|
||||
bool l6 = idx & (1u << 5);
|
||||
bool m1 = idx & (1u << 4);
|
||||
bool m3 = idx & (1u << 3);
|
||||
bool r0 = idx & (1u << 2);
|
||||
bool r3 = idx & (1u << 1);
|
||||
bool r5 = idx & (1u << 0);
|
||||
|
||||
return
|
||||
( _ && _ && !(l6) && m1 && _ && !(r0) && _ && _ ) ||
|
||||
( _ && l4 && _ && _ && !(m3) && _ && r3 && _ ) ||
|
||||
( _ && !(l4) && l6 && _ && _ && _ && _ && !(r5) ) ||
|
||||
( !(l0) && _ && _ && !(m1) && m3 && _ && _ && _ ) ||
|
||||
( !(l0) && _ && _ && _ && _ && _ && r3 && !(r5) ) ;
|
||||
}
|
||||
static bool espresso_implementation_xx_alt1(uint8_t idx) {
|
||||
// output_XX = (!l6&m1&!r0) | (l4&!m3&r3) | (!l4&l6&!r5) | (!l0&!m1&m3) | (!l0&r3&!r5);
|
||||
static const bool _ = true;
|
||||
/// xx_idx = (l0 << 7) | (l4 << 6) | (l6 << 5) | (m1 << 4) | (m3 << 3) | (r0 << 2) | (r3 << 1) | (r5 << 0)
|
||||
INDEX_XX t = { .as_uint8_t = idx };
|
||||
bool l0 = t.l0;
|
||||
bool l4 = t.l4;
|
||||
bool l6 = t.l6;
|
||||
bool m1 = t.m1;
|
||||
bool m3 = t.m3;
|
||||
bool r0 = t.r0;
|
||||
bool r3 = t.r3;
|
||||
bool r5 = t.r5;
|
||||
return
|
||||
( _ && _ && !(l6) && m1 && _ && !(r0) && _ && _ ) ||
|
||||
( _ && l4 && _ && _ && !(m3) && _ && r3 && _ ) ||
|
||||
( _ && !(l4) && l6 && _ && _ && _ && _ && !(r5) ) ||
|
||||
( !(l0) && _ && _ && !(m1) && m3 && _ && _ && _ ) ||
|
||||
( !(l0) && _ && _ && _ && _ && _ && r3 && !(r5) ) ;
|
||||
}
|
||||
|
||||
static const lookuptable_func_t alt_for_xx[] = {
|
||||
espresso_implementation_xx_alt0,
|
||||
espresso_implementation_xx_alt1,
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef struct _VERIFICATION_T {
|
||||
uint8_t const input_count;
|
||||
char const * const * names;
|
||||
char const * const output_name;
|
||||
uint8_t const * lut_start;
|
||||
lookuptable_func_t const * const altFns;
|
||||
size_t const altFnCount;
|
||||
} VERIFICATION_T;
|
||||
|
||||
|
||||
VERIFICATION_T const verification_table[] = {
|
||||
{ .input_count = 5, .names = LUT_PLA_NAMES_g1, .output_name = "g1", .lut_start = small_lut_group1, .altFns = alt_for_g1, .altFnCount = ARRAY_SIZE2(alt_for_g1) },
|
||||
{ .input_count = 5, .names = LUT_PLA_NAMES_g2, .output_name = "g2", .lut_start = small_lut_group2, .altFns = alt_for_g2, .altFnCount = ARRAY_SIZE2(alt_for_g2) },
|
||||
{ .input_count = 5, .names = LUT_PLA_NAMES_g3, .output_name = "g3", .lut_start = small_lut_group3, .altFns = alt_for_g3, .altFnCount = ARRAY_SIZE2(alt_for_g3) },
|
||||
{ .input_count = 5, .names = LUT_PLA_NAMES_g4, .output_name = "g4", .lut_start = small_lut_group4, .altFns = alt_for_g4, .altFnCount = ARRAY_SIZE2(alt_for_g4) },
|
||||
{ .input_count = 8, .names = LUT_PLA_NAMES_XX, .output_name = "xx", .lut_start = small_lut_XX , .altFns = alt_for_xx, .altFnCount = ARRAY_SIZE2(alt_for_xx) },
|
||||
};
|
||||
|
||||
|
||||
static bool espresso_implementation_g1(bool a, bool l0, bool l2, bool l3, bool l6) {
|
||||
// output_g1 = (a&l2&l0&!l6) | (a&l3&!l0&l6) | (!a&!l2&!l3) | (!l2&!l3&!l0&!l6) | (l2&l3&!l0&!l6) | (!a&!l2&l0&!l6) | (!a&!l3&!l0&l6) | (a&l2&!l3&l0) | (a&!l2&l3&l6) | (!a&l2&l3&l0&l6);
|
||||
static const bool _ = true;
|
||||
return
|
||||
( a && l0 && l2 && _ && !(l6) ) |
|
||||
( a && !(l0) && _ && l3 && l6 ) |
|
||||
( !(a) && _ && !(l2) && !(l3) && _ ) |
|
||||
( _ && !(l0) && !(l2) && !(l3) && !(l6) ) |
|
||||
( _ && !(l0) && l2 && l3 && !(l6) ) |
|
||||
( !(a) && l0 && !(l2) && _ && !(l6) ) |
|
||||
( !(a) && !(l0) && _ && !(l3) && l6 ) |
|
||||
( a && l0 && l2 && !(l3) && _ ) |
|
||||
( a && _ && !(l2) && l3 && l6 ) |
|
||||
( !(a) && l0 && l2 && l3 && l6 ) ;
|
||||
}
|
||||
static bool espresso_implementation_g2(bool b, bool l4, bool l5, bool m0, bool m1) {
|
||||
// output_g2 = (b&m0&!l4&!m1) | (l5&b&l4&m1) | (!l5&!b&!m0) | (!b&!m0&!l4&!m1) | (l5&b&!m0&l4) | (l5&!b&m0&l4&!m1) | (!l5&b&m0&!m1) | (!l5&!m0&!l4&m1) | (l5&m0&!l4&m1) | (!l5&!b&l4&m1);
|
||||
static const bool _ = true;
|
||||
return
|
||||
( _ && b && m0 && !(l4) && !(m1) ) |
|
||||
( l5 && b && _ && l4 && m1 ) |
|
||||
( !(l5) && !(b) && !(m0) && _ && _ ) |
|
||||
( _ && !(b) && !(m0) && !(l4) && !(m1) ) |
|
||||
( l5 && b && !(m0) && l4 && _ ) |
|
||||
( l5 && !(b) && m0 && l4 && !(m1) ) |
|
||||
( !(l5) && b && m0 && _ && !(m1) ) |
|
||||
( !(l5) && _ && !(m0) && !(l4) && m1 ) |
|
||||
( l5 && _ && m0 && !(l4) && m1 ) |
|
||||
( !(l5) && !(b) && _ && l4 && m1 ) ;
|
||||
}
|
||||
static bool espresso_implementation_g3(bool c, bool r1, bool r3, bool m3, bool m5) {
|
||||
// output_g3 = (c&r1&!m3&!r3) | (m5&c&m3&r3) | (!m5&!c&!r1) | (!c&!r1&!m3&!r3) | (!m5&!r1&m3&!r3) | (m5&r1&m3&!r3) | (m5&c&!r1&r3) | (m5&!c&r1&!m3&r3) | (!m5&c&r1&!m3) | (!m5&!c&m3&r3);
|
||||
static const bool _ = true;
|
||||
return
|
||||
( _ && c && r1 && !(m3) && !(r3) ) |
|
||||
( m5 && c && _ && m3 && r3 ) |
|
||||
( !(m5) && !(c) && !(r1) && _ && _ ) |
|
||||
( _ && !(c) && !(r1) && !(m3) && !(r3) ) |
|
||||
( !(m5) && _ && !(r1) && m3 && !(r3) ) |
|
||||
( m5 && _ && r1 && m3 && !(r3) ) |
|
||||
( m5 && c && !(r1) && _ && r3 ) |
|
||||
( m5 && !(c) && r1 && !(m3) && r3 ) |
|
||||
( !(m5) && c && r1 && !(m3) && _ ) |
|
||||
( !(m5) && !(c) && _ && m3 && r3 ) ;
|
||||
}
|
||||
static bool espresso_implementation_g4(bool r0, bool r2, bool r4, bool r5, bool r6) {
|
||||
// output_g4 = (r2&r6&r0&!r5) | (r4&r6&!r0&r5) | (!r2&!r4&!r6) | (r2&r4&!r6&!r0&!r5) | (r2&!r4&r6&!r5) | (!r2&r4&r6&!r0) | (!r2&!r6&r0&!r5) | (!r4&!r6&!r0&r5) | (r2&r4&r0&r5) | (!r2&!r4&r0&r5);
|
||||
static const bool _ = true;
|
||||
return
|
||||
( r2 && _ && r6 && r0 && !(r5) ) |
|
||||
( _ && r4 && r6 && !(r0) && r5 ) |
|
||||
( !(r2) && !(r4) && !(r6) && _ && _ ) |
|
||||
( r2 && r4 && !(r6) && !(r0) && !(r5) ) |
|
||||
( r2 && !(r4) && r6 && _ && !(r5) ) |
|
||||
( !(r2) && r4 && r6 && !(r0) && _ ) |
|
||||
( !(r2) && _ && !(r6) && r0 && !(r5) ) |
|
||||
( _ && !(r4) && !(r6) && !(r0) && r5 ) |
|
||||
( r2 && r4 && _ && r0 && r5 ) |
|
||||
( !(r2) && !(r4) && _ && r0 && r5 ) ;
|
||||
}
|
||||
static bool espresso_implementation_XX(bool l0, bool l4, bool l6, bool m1, bool m3, bool r0, bool r3, bool r5) {
|
||||
// output_XX = (!l6&m1&!r0) | (l4&!m3&r3) | (!l4&l6&!r5) | (!l0&!m1&m3) | (!l0&r3&!r5);
|
||||
static const bool _ = true;
|
||||
return
|
||||
( _ && _ && !(l6) && m1 && _ && !(r0) && _ && _ ) |
|
||||
( _ && l4 && _ && _ && !(m3) && _ && r3 && _ ) |
|
||||
( _ && !(l4) && l6 && _ && _ && _ && _ && !(r5) ) |
|
||||
( !(l0) && _ && _ && !(m1) && m3 && _ && _ && _ ) |
|
||||
( !(l0) && _ && _ && _ && _ && _ && r3 && !(r5) );
|
||||
}
|
||||
|
||||
static bool verify_alternatives(void)
|
||||
{
|
||||
bool any_failures_overall = false;
|
||||
|
||||
for (uint16_t q = 0; q < ARRAY_SIZE2(verification_table); ++q) {
|
||||
bool any_failures_this_table = false;
|
||||
VERIFICATION_T const * vt = &verification_table[q];
|
||||
const char* fstr = vt->output_name;
|
||||
uint16_t limit = 1u << vt->input_count;
|
||||
|
||||
for (uint16_t fn_idx = 0; fn_idx < vt->altFnCount; ++fn_idx ) {
|
||||
|
||||
bool any_failures_this_table_alts = false;
|
||||
const lookuptable_func_t fn = vt->altFns[fn_idx];
|
||||
|
||||
for (uint16_t ix = 0; ix < limit; ++ix) {
|
||||
uint8_t i = (uint8_t)ix;
|
||||
|
||||
bool lut_result = get_bit(vt->lut_start, i);
|
||||
bool other_result = fn(i);
|
||||
if (lut_result != other_result) {
|
||||
printf("%s: verification failed for fn[ %d ]( %3d )\n", fstr, fn_idx, i);
|
||||
any_failures_this_table_alts = true;
|
||||
}
|
||||
}
|
||||
if (any_failures_this_table_alts) {
|
||||
printf("FAILURE - %s alt %d\n", fstr, fn_idx);
|
||||
} else {
|
||||
printf("SUCCESS - %s alt %d\n", fstr, fn_idx);
|
||||
}
|
||||
|
||||
// percolate to outer variable....
|
||||
any_failures_this_table |= any_failures_this_table_alts;
|
||||
}
|
||||
|
||||
if (vt->altFnCount == 0) {
|
||||
// nothing was tested ...
|
||||
} else if (any_failures_this_table) {
|
||||
printf("FAILURE ---------> At least one of the alt functions for %s \n", fstr);
|
||||
} else {
|
||||
printf("SUCCESS ---------> All alternate for %s \n", fstr);
|
||||
}
|
||||
|
||||
any_failures_overall |= any_failures_this_table;
|
||||
}
|
||||
|
||||
if (any_failures_overall) {
|
||||
printf("=====> FAILURE: Some of the alternate generators are still failing\n");
|
||||
} else {
|
||||
printf("=====> SUCCESS: All alternate generators are succeeding\n");
|
||||
}
|
||||
return !any_failures_overall;
|
||||
}
|
||||
|
||||
static bool verify_lut_g1(void)
|
||||
{
|
||||
static const char* fstr = "verify_lut_g1";
|
||||
bool any_failures = false;
|
||||
for (uint8_t i = 0; i < 32; ++i) {
|
||||
INDEX_G1 t = { .as_uint8_t = i };
|
||||
bool lut_result = get_bit(small_lut_group1, i);
|
||||
bool other_result = espresso_implementation_g1(t.a, t.l0, t.l2, t.l3, t.l6);
|
||||
if (lut_result != other_result) {
|
||||
printf("%s: verification failed for index %d\n", fstr, t.as_uint8_t);
|
||||
any_failures = true;
|
||||
}
|
||||
}
|
||||
if (any_failures) {
|
||||
printf("FAILURE - %s\n", fstr);
|
||||
} else {
|
||||
printf("SUCCESS - %s\n", fstr);
|
||||
}
|
||||
return !any_failures;
|
||||
}
|
||||
static bool verify_lut_g2(void)
|
||||
{
|
||||
static const char* fstr = "verify_lut_g2";
|
||||
bool any_failures = false;
|
||||
for (uint8_t i = 0; i < 32; ++i) {
|
||||
INDEX_G2 t = { .as_uint8_t = i };
|
||||
bool lut_result = get_bit(small_lut_group2, i);
|
||||
bool other_result = espresso_implementation_g2(t.b, t.l4, t.l5, t.m0, t.m1);
|
||||
if (lut_result != other_result) {
|
||||
printf("%s: verification failed for index %d\n", fstr, t.as_uint8_t);
|
||||
any_failures = true;
|
||||
}
|
||||
}
|
||||
if (any_failures) {
|
||||
printf("FAILURE - %s\n", fstr);
|
||||
} else {
|
||||
printf("SUCCESS - %s\n", fstr);
|
||||
}
|
||||
return !any_failures;
|
||||
}
|
||||
static bool verify_lut_g3(void)
|
||||
{
|
||||
static const char* fstr = "verify_lut_g3";
|
||||
bool any_failures = false;
|
||||
for (uint8_t i = 0; i < 32; ++i) {
|
||||
INDEX_G3 t = { .as_uint8_t = i };
|
||||
bool lut_result = get_bit(small_lut_group3, i);
|
||||
bool other_result = espresso_implementation_g3(t.c, t.r1, t.r3, t.m3, t.m5);
|
||||
if (lut_result != other_result) {
|
||||
printf("%s: verification failed for index %d\n", fstr, t.as_uint8_t);
|
||||
any_failures = true;
|
||||
}
|
||||
}
|
||||
if (any_failures) {
|
||||
printf("FAILURE - %s\n", fstr);
|
||||
} else {
|
||||
printf("SUCCESS - %s\n", fstr);
|
||||
}
|
||||
return !any_failures;
|
||||
}
|
||||
static bool verify_lut_g4(void)
|
||||
{
|
||||
static const char* fstr = "verify_lut_g4";
|
||||
bool any_failures = false;
|
||||
for (uint8_t i = 0; i < 32; ++i) {
|
||||
INDEX_G4 t = { .as_uint8_t = i };
|
||||
bool lut_result = get_bit(small_lut_group4, i);
|
||||
bool other_result = espresso_implementation_g4(t.r0, t.r2, t.r4, t.r5, t.r6);
|
||||
if (lut_result != other_result) {
|
||||
printf("%s: verification failed for index %d\n", fstr, t.as_uint8_t);
|
||||
any_failures = true;
|
||||
}
|
||||
}
|
||||
if (any_failures) {
|
||||
printf("FAILURE - %s\n", fstr);
|
||||
} else {
|
||||
printf("SUCCESS - %s\n", fstr);
|
||||
}
|
||||
return !any_failures;
|
||||
}
|
||||
static bool verify_lut_XX(void)
|
||||
{
|
||||
static const char* fstr = "verify_lut_XX";
|
||||
bool any_failures = false;
|
||||
for (uint16_t ix = 0; ix < 256; ++ix) {
|
||||
uint8_t i = (uint8_t)ix;
|
||||
INDEX_XX t = { .as_uint8_t = i };
|
||||
bool lut_result = get_bit(small_lut_XX, i);
|
||||
bool other_result = espresso_implementation_XX(t.l0, t.l4, t.l6, t.m1, t.m3, t.r0, t.r3, t.r5);
|
||||
if (lut_result != other_result) {
|
||||
printf("%s: verification failed for index %d\n", fstr, t.as_uint8_t);
|
||||
any_failures = true;
|
||||
}
|
||||
}
|
||||
if (any_failures) {
|
||||
printf("FAILURE - %s\n", fstr);
|
||||
} else {
|
||||
printf("SUCCESS - %s\n", fstr);
|
||||
}
|
||||
return !any_failures;
|
||||
}
|
||||
|
||||
// order of input_names is based on resulting .PLA output,
|
||||
// so least significant bit is at input_names[input_count-1]
|
||||
static bool generate_espresso_file(uint8_t input_count, const char * const * input_names, const char * output_name, const uint8_t * lut_table_start, FILE* f_output) {
|
||||
if (input_count > 8) {
|
||||
printf("FAILURE - Cannot generate espresso file for more than 8 inputs (code would need update)\n");
|
||||
}
|
||||
fprintf(f_output, "# ###################\n");
|
||||
fprintf(f_output, "# Generating .PLA\n");
|
||||
fprintf(f_output, "# ###################\n");
|
||||
fprintf(f_output, "\n\n");
|
||||
fprintf(f_output, ".i %d\n", input_count);
|
||||
fprintf(f_output, ".o 1\n");
|
||||
const uint16_t iterations = 1u << input_count;
|
||||
fprintf(f_output, ".ilb");
|
||||
for (uint16_t i = 0; i < input_count; ++i) {
|
||||
const char* name = input_names[i];
|
||||
fprintf(f_output, " %s", name);
|
||||
}
|
||||
fprintf(f_output, "\n");
|
||||
fprintf(f_output, ".ob %s\n", output_name);
|
||||
for (uint16_t ix = 0; ix < iterations; ++ix) {
|
||||
|
||||
uint8_t i = (uint8_t)ix;
|
||||
// NOTE: Seems we've handled it properly here, by shifting the bit to be tested appropriately
|
||||
// based on the total number of inputs. So input_names[0] is the most significant bit....
|
||||
for (uint8_t bitmask = (1u << (input_count - 1u)); bitmask != 0; bitmask >>= 1) {
|
||||
fputc(((i & bitmask) != 0) ? '1' : '0', f_output);
|
||||
}
|
||||
bool bit = get_bit(lut_table_start, i);
|
||||
fprintf(f_output, " %c\n", bit ? '1' : '0');
|
||||
}
|
||||
fprintf(f_output, ".e\n\n");
|
||||
|
||||
fprintf(f_output, "# ###################\n");
|
||||
fprintf(f_output, "# END OF .PLA\n");
|
||||
fprintf(f_output, "# ###################\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool generate_all_lut_espresso_files(void)
|
||||
{
|
||||
|
||||
bool any_failures = false;
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE2(verification_table); ++i) {
|
||||
VERIFICATION_T const * args = &verification_table[i];
|
||||
|
||||
bool current_result = false;
|
||||
FILE* file = NULL;
|
||||
char filename[20] = {0}; // needs: 14 for two-letter output name
|
||||
|
||||
// First create the filename to be written
|
||||
// Yes, presumes "safe" output_name ...
|
||||
if (snprintf(NULL, 0, "output_%s.pla", args->output_name) < ARRAY_SIZE2(filename)) {
|
||||
snprintf(filename, ARRAY_SIZE2(filename), "output_%s.pla", args->output_name);
|
||||
file = fopen(filename, "w");
|
||||
if (file == NULL) {
|
||||
printf("failed to open output file '%s'", filename);
|
||||
}
|
||||
}
|
||||
if (file != NULL) {
|
||||
current_result = generate_espresso_file(
|
||||
args->input_count,
|
||||
args->names,
|
||||
args->output_name,
|
||||
args->lut_start,
|
||||
file
|
||||
);
|
||||
if (!current_result) {
|
||||
printf("Failed to generate espresso file for %s\n", args->output_name);
|
||||
}
|
||||
}
|
||||
if (file != NULL) {
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
}
|
||||
any_failures |= !current_result;
|
||||
}
|
||||
|
||||
return !any_failures;
|
||||
}
|
||||
bool verify_espresso_results(void)
|
||||
{
|
||||
//generate_all_lut_espresso_files();
|
||||
|
||||
bool unused = verify_alternatives();
|
||||
bool r_g1 = verify_lut_g1();
|
||||
bool r_g2 = verify_lut_g2();
|
||||
bool r_g3 = verify_lut_g3();
|
||||
bool r_g4 = verify_lut_g4();
|
||||
bool r_xx = verify_lut_XX();
|
||||
return r_g1 && r_g2 && r_g3 && r_g4 && r_xx;
|
||||
}
|
||||
7
client/deps/id48/tests/espresso/verify_espresso.h
Normal file
7
client/deps/id48/tests/espresso/verify_espresso.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool generate_all_lut_espresso_files(void);
|
||||
bool verify_espresso_results(void);
|
||||
12
client/deps/id48/tests/generator/CMakeLists.txt
Normal file
12
client/deps/id48/tests/generator/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
add_executable(
|
||||
id48lib_test_generator
|
||||
main.c
|
||||
)
|
||||
|
||||
target_link_libraries(id48lib_test_generator PRIVATE id48lib)
|
||||
|
||||
target_compile_options(id48lib_test_generator PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:C>:-O0>
|
||||
)
|
||||
157
client/deps/id48/tests/generator/array_size2.h
Normal file
157
client/deps/id48/tests/generator/array_size2.h
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/**
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) SimpleHacks, Henry Gabryjelski
|
||||
https://github.com/SimpleHacks/UtilHeaders
|
||||
|
||||
All rights reserved.
|
||||
|
||||
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 ARRAYSIZE2_H
|
||||
#define ARRAYSIZE2_H
|
||||
|
||||
/**
|
||||
The following, if defined prior to inclusion of this header file,
|
||||
will modify its behavior as noted:
|
||||
|
||||
ARRAYSIZE2_SHOW_VERSION_MESSAGE
|
||||
-- if defined, will show which version of ARRAY_SIZE2 macro is selected
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
see example source at:
|
||||
https://godbolt.org/z/zzYoeK6Mf
|
||||
*/
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0 /* Compatibility with non-clang compilers. */
|
||||
#endif
|
||||
|
||||
#if (defined(__cplusplus) && __cplusplus >= 201103L) || /* any compiler claiming C++11 support */ \
|
||||
(defined(__cplusplus) && _MSC_VER >= 1900 && __cplusplus != 199711L) || /* Visual C++ 2015 or higher */ \
|
||||
__has_feature(cxx_constexpr) /* CLang versions supporting constexp */
|
||||
|
||||
#include <stddef.h> /* required for size_t */
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message( "ARRAY_SIZE2 -- Using C++11 version" )
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, size_t N>
|
||||
constexpr size_t ARRAY_SIZE2_ARGUMENT_CANNOT_BE_POINTER(T const (&)[N]) noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
} /* namespace detail */
|
||||
#define ARRAY_SIZE2(arr) detail::ARRAY_SIZE2_ARGUMENT_CANNOT_BE_POINTER(arr)
|
||||
|
||||
#elif defined(__cplusplus) && __cplusplus >= 199711L && ( /* C++ 98 trick */ \
|
||||
defined(__INTEL_COMPILER) || \
|
||||
defined(__clang__) || \
|
||||
(defined(__GNUC__) && ( \
|
||||
(__GNUC__ > 4) || \
|
||||
(__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
|
||||
)))
|
||||
|
||||
#include <stddef.h> /* required for size_t */
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message "ARRAY_SIZE2 -- Using C++98 version"
|
||||
#endif
|
||||
template <typename T, size_t N>
|
||||
char(&_ArraySizeHelperRequiresArray(T(&)[N]))[N];
|
||||
#define ARRAY_SIZE2(x) sizeof(_ArraySizeHelperRequiresArray(x))
|
||||
|
||||
#elif defined(__cplusplus) /* && ((__cplusplus >= 199711L) || defined(__INTEL_COMPILER) || defined(__clang__)) */
|
||||
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message( "ARRAY_SIZE2 -- Using Ivan J. Johnson's C++ version" )
|
||||
#endif
|
||||
/*
|
||||
Works on older compilers, even Visual C++ 6....
|
||||
Created by Ivan J. Johnson, March 06, 2007
|
||||
See http://drdobbs.com/cpp/197800525?pgno=1
|
||||
|
||||
Full description is in markdown file array_size2.md
|
||||
*/
|
||||
#define ARRAY_SIZE2(arr) ( \
|
||||
0 * sizeof(reinterpret_cast<const ::Bad_arg_to_ARRAY_SIZE2*>(arr)) + /*check1*/ \
|
||||
0 * sizeof(::Bad_arg_to_ARRAY_SIZE2::check_type((arr), &(arr))) + /*check2*/ \
|
||||
sizeof(arr) / sizeof((arr)[0]) /* eval */ \
|
||||
)
|
||||
|
||||
struct Bad_arg_to_ARRAY_SIZE2 {
|
||||
class Is_pointer; /* incomplete */
|
||||
class Is_array {};
|
||||
template <typename T>
|
||||
static Is_pointer check_type(T const *, T const * const *);
|
||||
static Is_array check_type(void const *, void const *);
|
||||
};
|
||||
|
||||
#elif !defined(__cplusplus) && defined(__GNUC__)
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
Even C can have type-safety for equivalent of ARRAY_SIZE() macro,
|
||||
when using the following two GCC extensions:
|
||||
typeof()
|
||||
__builtin_types_compatible_p()
|
||||
*/
|
||||
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message( "ARRAY_SIZE2 -- Using GNUC version" )
|
||||
#endif
|
||||
|
||||
/**
|
||||
validated using:
|
||||
MSP430 gcc 4.5.3
|
||||
x86-64 icc 16.0.3
|
||||
x86-64 gcc 4.1.2
|
||||
x86-64 clang 3.0.0
|
||||
AVR gcc 4.5.4
|
||||
ARM gcc 4.5.4
|
||||
*/
|
||||
|
||||
#define __SIMPLEHACKS_COMPATIBLE_TYPES__(a,b) __builtin_types_compatible_p(__typeof__(a), __typeof__(b)) /* GCC extensions */
|
||||
#define __SIMPLEHACKS_BUILD_ERROR_ON_NONZERO__(x) (sizeof(struct { uint8_t q: (-!!(x)*0x1ee7)+1u;})-1u) /* if x is zero, reports "error: negative width in bit-field '<anonymous>'" */
|
||||
#define __SIMPLEHACKS_MUST_BE_ARRAY__(x) __SIMPLEHACKS_BUILD_ERROR_ON_NONZERO__(__SIMPLEHACKS_COMPATIBLE_TYPES__((x), &(*x)))
|
||||
#define ARRAY_SIZE2(_arr) ( (sizeof(_arr) / sizeof((_arr)[0])) + __SIMPLEHACKS_MUST_BE_ARRAY__(_arr) ) /* compile-time error if not an array */
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
The good news is that all compilers (as of 20202-05-08)
|
||||
on godbolt.org are fully supported. Therefore, if some
|
||||
other compiler does not support any of the above method,
|
||||
it's important to force a compile-time error, to avoid
|
||||
any suggestion that this provides a safe macro.
|
||||
*/
|
||||
|
||||
#error "Unable to provide type-safe ARRAY_SIZE2 macro"
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ARRAYSIZE2_H
|
||||
93
client/deps/id48/tests/generator/main.c
Normal file
93
client/deps/id48/tests/generator/main.c
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#include "id48.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "array_size2.h"
|
||||
|
||||
static bool bytes_equal(const uint8_t *lhs, const uint8_t *rhs, size_t len) {
|
||||
return memcmp(lhs, rhs, len) == 0;
|
||||
}
|
||||
|
||||
typedef struct _TEST_VECTOR_T {
|
||||
const char *description;
|
||||
const ID48LIB_KEY key;
|
||||
const ID48LIB_NONCE nonce;
|
||||
const ID48LIB_FRN expected_frn;
|
||||
const ID48LIB_GRN expected_grn;
|
||||
} TEST_VECTOR_T;
|
||||
|
||||
// Test vectors used in various Proxmark3 client commands:
|
||||
static const TEST_VECTOR_T test_vectors[] = {
|
||||
// PM3 test key
|
||||
{
|
||||
// --key F32AA98CF5BE4ADFA6D3480B
|
||||
// --rnd 45F54ADA252AAC
|
||||
// --frn 4866BB70
|
||||
// --grn 9BD180
|
||||
.description = "PM3 test key",
|
||||
.key = { .k = { 0xF3, 0x2A, 0xA9, 0x8C, 0xF5, 0xBE, 0x4A, 0xDF, 0xA6, 0xD3, 0x48, 0x0B, } },
|
||||
.nonce = { .rn = { 0x45, 0xF5, 0x4A, 0xDA, 0x25, 0x2A, 0xAC, } },
|
||||
.expected_frn = { .frn = { 0x48, 0x66, 0xBB, 0x70, } },
|
||||
.expected_grn = { .grn = { 0x9B, 0xD1, 0x80, } },
|
||||
},
|
||||
// Research paper key
|
||||
{
|
||||
// --key A090A0A02080000000000000
|
||||
// --rnd 3FFE1FB6CC513F
|
||||
// --frn F355F1A0
|
||||
// --grn 609D60
|
||||
.description = "Research paper key",
|
||||
.key = { .k = { 0xA0, 0x90, 0xA0, 0xA0, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } },
|
||||
.nonce = { .rn = { 0x3F, 0xFE, 0x1F, 0xB6, 0xCC, 0x51, 0x3F, } },
|
||||
.expected_frn = { .frn = { 0xF3, 0x55, 0xF1, 0xA0, } },
|
||||
.expected_grn = { .grn = { 0x60, 0x9D, 0x60, } },
|
||||
},
|
||||
// Autorecovery test key
|
||||
{
|
||||
// --key 022A028C02BE000102030405
|
||||
// --rnd 7D5167003571F8
|
||||
// --frn 982DBCC0
|
||||
// --grn 36C0E0
|
||||
.description = "Autorecovery test key",
|
||||
.key = { .k = { 0x02, 0x2A, 0x02, 0x8C, 0x02, 0xBE, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, } },
|
||||
.nonce = { .rn = { 0x7D, 0x51, 0x67, 0x00, 0x35, 0x71, 0xF8, } },
|
||||
.expected_frn = { .frn = { 0x98, 0x2D, 0xBC, 0xC0, } },
|
||||
.expected_grn = { .grn = { 0x36, 0xC0, 0xE0, } },
|
||||
},
|
||||
};
|
||||
|
||||
bool generator_succeeds(const TEST_VECTOR_T *test_vector) {
|
||||
ID48LIB_FRN actual_frn = {0};
|
||||
ID48LIB_GRN actual_grn = {0};
|
||||
|
||||
id48lib_generator(&test_vector->key, &test_vector->nonce, &actual_frn, &actual_grn);
|
||||
|
||||
if (!bytes_equal(actual_frn.frn, test_vector->expected_frn.frn, sizeof(test_vector->expected_frn.frn))) {
|
||||
printf("id48lib_generator: unexpected FRN for test vector '%s'\n", test_vector->description);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bytes_equal(actual_grn.grn, test_vector->expected_grn.grn, sizeof(test_vector->expected_grn.grn))) {
|
||||
printf("id48lib_generator: unexpected GRN for test vector '%s'\n", test_vector->description);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
bool any_failures = false;
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE2(test_vectors); i++) {
|
||||
printf("Testing generator for test vector '%s'\n", test_vectors[i].description);
|
||||
if (!generator_succeeds(&test_vectors[i])) {
|
||||
printf("FAILURE: id48lib_generator: test vector '%s'\n", test_vectors[i].description);
|
||||
any_failures = true;
|
||||
}
|
||||
}
|
||||
if (any_failures) {
|
||||
printf("id48lib_generator: some tests failed\n");
|
||||
} else {
|
||||
printf("id48lib_generator: all tests passed\n");
|
||||
}
|
||||
return any_failures ? 120 : 0;
|
||||
}
|
||||
12
client/deps/id48/tests/recovery/CMakeLists.txt
Normal file
12
client/deps/id48/tests/recovery/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
cmake_minimum_required(VERSION 3.21)
|
||||
|
||||
add_executable(
|
||||
id48lib_test_recovery
|
||||
main.c
|
||||
)
|
||||
|
||||
target_link_libraries(id48lib_test_recovery PRIVATE id48lib)
|
||||
|
||||
target_compile_options(id48lib_test_recovery PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:C>:-O0>
|
||||
)
|
||||
157
client/deps/id48/tests/recovery/array_size2.h
Normal file
157
client/deps/id48/tests/recovery/array_size2.h
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/**
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) SimpleHacks, Henry Gabryjelski
|
||||
https://github.com/SimpleHacks/UtilHeaders
|
||||
|
||||
All rights reserved.
|
||||
|
||||
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 ARRAYSIZE2_H
|
||||
#define ARRAYSIZE2_H
|
||||
|
||||
/**
|
||||
The following, if defined prior to inclusion of this header file,
|
||||
will modify its behavior as noted:
|
||||
|
||||
ARRAYSIZE2_SHOW_VERSION_MESSAGE
|
||||
-- if defined, will show which version of ARRAY_SIZE2 macro is selected
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
see example source at:
|
||||
https://godbolt.org/z/zzYoeK6Mf
|
||||
*/
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0 /* Compatibility with non-clang compilers. */
|
||||
#endif
|
||||
|
||||
#if (defined(__cplusplus) && __cplusplus >= 201103L) || /* any compiler claiming C++11 support */ \
|
||||
(defined(__cplusplus) && _MSC_VER >= 1900 && __cplusplus != 199711L) || /* Visual C++ 2015 or higher */ \
|
||||
__has_feature(cxx_constexpr) /* CLang versions supporting constexp */
|
||||
|
||||
#include <stddef.h> /* required for size_t */
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message( "ARRAY_SIZE2 -- Using C++11 version" )
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename T, size_t N>
|
||||
constexpr size_t ARRAY_SIZE2_ARGUMENT_CANNOT_BE_POINTER(T const (&)[N]) noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
} /* namespace detail */
|
||||
#define ARRAY_SIZE2(arr) detail::ARRAY_SIZE2_ARGUMENT_CANNOT_BE_POINTER(arr)
|
||||
|
||||
#elif defined(__cplusplus) && __cplusplus >= 199711L && ( /* C++ 98 trick */ \
|
||||
defined(__INTEL_COMPILER) || \
|
||||
defined(__clang__) || \
|
||||
(defined(__GNUC__) && ( \
|
||||
(__GNUC__ > 4) || \
|
||||
(__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
|
||||
)))
|
||||
|
||||
#include <stddef.h> /* required for size_t */
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message "ARRAY_SIZE2 -- Using C++98 version"
|
||||
#endif
|
||||
template <typename T, size_t N>
|
||||
char(&_ArraySizeHelperRequiresArray(T(&)[N]))[N];
|
||||
#define ARRAY_SIZE2(x) sizeof(_ArraySizeHelperRequiresArray(x))
|
||||
|
||||
#elif defined(__cplusplus) /* && ((__cplusplus >= 199711L) || defined(__INTEL_COMPILER) || defined(__clang__)) */
|
||||
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message( "ARRAY_SIZE2 -- Using Ivan J. Johnson's C++ version" )
|
||||
#endif
|
||||
/*
|
||||
Works on older compilers, even Visual C++ 6....
|
||||
Created by Ivan J. Johnson, March 06, 2007
|
||||
See http://drdobbs.com/cpp/197800525?pgno=1
|
||||
|
||||
Full description is in markdown file array_size2.md
|
||||
*/
|
||||
#define ARRAY_SIZE2(arr) ( \
|
||||
0 * sizeof(reinterpret_cast<const ::Bad_arg_to_ARRAY_SIZE2*>(arr)) + /*check1*/ \
|
||||
0 * sizeof(::Bad_arg_to_ARRAY_SIZE2::check_type((arr), &(arr))) + /*check2*/ \
|
||||
sizeof(arr) / sizeof((arr)[0]) /* eval */ \
|
||||
)
|
||||
|
||||
struct Bad_arg_to_ARRAY_SIZE2 {
|
||||
class Is_pointer; /* incomplete */
|
||||
class Is_array {};
|
||||
template <typename T>
|
||||
static Is_pointer check_type(T const *, T const * const *);
|
||||
static Is_array check_type(void const *, void const *);
|
||||
};
|
||||
|
||||
#elif !defined(__cplusplus) && defined(__GNUC__)
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
Even C can have type-safety for equivalent of ARRAY_SIZE() macro,
|
||||
when using the following two GCC extensions:
|
||||
typeof()
|
||||
__builtin_types_compatible_p()
|
||||
*/
|
||||
|
||||
#if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
|
||||
#pragma message( "ARRAY_SIZE2 -- Using GNUC version" )
|
||||
#endif
|
||||
|
||||
/**
|
||||
validated using:
|
||||
MSP430 gcc 4.5.3
|
||||
x86-64 icc 16.0.3
|
||||
x86-64 gcc 4.1.2
|
||||
x86-64 clang 3.0.0
|
||||
AVR gcc 4.5.4
|
||||
ARM gcc 4.5.4
|
||||
*/
|
||||
|
||||
#define __SIMPLEHACKS_COMPATIBLE_TYPES__(a,b) __builtin_types_compatible_p(__typeof__(a), __typeof__(b)) /* GCC extensions */
|
||||
#define __SIMPLEHACKS_BUILD_ERROR_ON_NONZERO__(x) (sizeof(struct { uint8_t q: (-!!(x)*0x1ee7)+1u;})-1u) /* if x is zero, reports "error: negative width in bit-field '<anonymous>'" */
|
||||
#define __SIMPLEHACKS_MUST_BE_ARRAY__(x) __SIMPLEHACKS_BUILD_ERROR_ON_NONZERO__(__SIMPLEHACKS_COMPATIBLE_TYPES__((x), &(*x)))
|
||||
#define ARRAY_SIZE2(_arr) ( (sizeof(_arr) / sizeof((_arr)[0])) + __SIMPLEHACKS_MUST_BE_ARRAY__(_arr) ) /* compile-time error if not an array */
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
The good news is that all compilers (as of 20202-05-08)
|
||||
on godbolt.org are fully supported. Therefore, if some
|
||||
other compiler does not support any of the above method,
|
||||
it's important to force a compile-time error, to avoid
|
||||
any suggestion that this provides a safe macro.
|
||||
*/
|
||||
|
||||
#error "Unable to provide type-safe ARRAY_SIZE2 macro"
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ARRAYSIZE2_H
|
||||
173
client/deps/id48/tests/recovery/main.c
Normal file
173
client/deps/id48/tests/recovery/main.c
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
#include "id48.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "array_size2.h"
|
||||
|
||||
static bool bytes_equal(const uint8_t *lhs, const uint8_t *rhs, size_t len) {
|
||||
return memcmp(lhs, rhs, len) == 0;
|
||||
}
|
||||
|
||||
typedef struct _TEST_VECTOR_T {
|
||||
const char *description;
|
||||
const ID48LIB_KEY key;
|
||||
const ID48LIB_NONCE nonce;
|
||||
const ID48LIB_FRN expected_frn;
|
||||
const ID48LIB_GRN expected_grn;
|
||||
} TEST_VECTOR_T;
|
||||
|
||||
// Test vectors used in various Proxmark3 client commands:
|
||||
static const TEST_VECTOR_T test_vectors[] = {
|
||||
// PM3 test key
|
||||
{
|
||||
// --key F32AA98CF5BE4ADFA6D3480B
|
||||
// --rnd 45F54ADA252AAC
|
||||
// --frn 4866BB70
|
||||
// --grn 9BD180
|
||||
.description = "PM3 test key",
|
||||
.key = { .k = { 0xF3, 0x2A, 0xA9, 0x8C, 0xF5, 0xBE, 0x4A, 0xDF, 0xA6, 0xD3, 0x48, 0x0B, } },
|
||||
.nonce = { .rn = { 0x45, 0xF5, 0x4A, 0xDA, 0x25, 0x2A, 0xAC, } },
|
||||
.expected_frn = { .frn = { 0x48, 0x66, 0xBB, 0x70, } },
|
||||
.expected_grn = { .grn = { 0x9B, 0xD1, 0x80, } },
|
||||
},
|
||||
// Research paper key
|
||||
{
|
||||
// --key A090A0A02080000000000000
|
||||
// --rnd 3FFE1FB6CC513F
|
||||
// --frn F355F1A0
|
||||
// --grn 609D60
|
||||
.description = "Research paper key",
|
||||
.key = { .k = { 0xA0, 0x90, 0xA0, 0xA0, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } },
|
||||
.nonce = { .rn = { 0x3F, 0xFE, 0x1F, 0xB6, 0xCC, 0x51, 0x3F, } },
|
||||
.expected_frn = { .frn = { 0xF3, 0x55, 0xF1, 0xA0, } },
|
||||
.expected_grn = { .grn = { 0x60, 0x9D, 0x60, } },
|
||||
},
|
||||
// Autorecovery test key
|
||||
{
|
||||
// --key 022A028C02BE000102030405
|
||||
// --rnd 7D5167003571F8
|
||||
// --frn 982DBCC0
|
||||
// --grn 36C0E0
|
||||
.description = "Autorecovery test key",
|
||||
.key = { .k = { 0x02, 0x2A, 0x02, 0x8C, 0x02, 0xBE, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, } },
|
||||
.nonce = { .rn = { 0x7D, 0x51, 0x67, 0x00, 0x35, 0x71, 0xF8, } },
|
||||
.expected_frn = { .frn = { 0x98, 0x2D, 0xBC, 0xC0, } },
|
||||
.expected_grn = { .grn = { 0x36, 0xC0, 0xE0, } },
|
||||
},
|
||||
};
|
||||
|
||||
// Comment
|
||||
/// <summary>
|
||||
/// Initializes to allow iterative recovery
|
||||
/// of multiple potential keys. After calling
|
||||
/// this init() function, can repeatedly call
|
||||
/// the next() function until it returns false
|
||||
/// to obtain all potential keys.
|
||||
/// </summary>
|
||||
/// <param name="input_partial_key">
|
||||
/// Top 48 bits of the key, such as those discovered
|
||||
/// using the proxmark3 command `lf em 4x70 brute`.
|
||||
/// Only k[0..5] are used from this parameter,
|
||||
/// corresponding to K₉₅..K₄₈.
|
||||
/// </param>
|
||||
/// <param name="input_nonce">
|
||||
/// The nonce value.
|
||||
/// Typically from a sniffed authentication.
|
||||
/// </param>
|
||||
/// <param name="input_frn">
|
||||
/// The challenge sent from the reader (e.g., car)
|
||||
/// to the tag (e.g., key).
|
||||
/// Typically from a sniffed authentication.
|
||||
/// </param>
|
||||
/// <param name="input_grn">
|
||||
/// The response sent from the tag (e.g., key)
|
||||
/// to the car (e.g., car).
|
||||
/// Typically from a sniffed authentication.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// Note: In C++, each parameter would be a reference (not pointer).
|
||||
/// </remarks>
|
||||
|
||||
// void id48lib_key_recovery_init(
|
||||
// const ID48LIB_KEY *input_partial_key,
|
||||
// const ID48LIB_NONCE *input_nonce,
|
||||
// const ID48LIB_FRN *input_frn,
|
||||
// const ID48LIB_GRN *input_grn
|
||||
// );
|
||||
|
||||
// Comment
|
||||
/// <summary>
|
||||
/// This can be repeated called (after calling init())
|
||||
/// to find the next potential key for the given
|
||||
/// partial key + nonce + frn + grn values.
|
||||
/// I've seen combinations that have up to six
|
||||
/// potential keys available, although typically
|
||||
/// there are 1-3 results.
|
||||
/// Each call to this function will return a single
|
||||
/// value. Call repeatedly until the function returns
|
||||
/// false to get all potential keys.
|
||||
/// </summary>
|
||||
/// <param name="potential_key_output">
|
||||
/// When the function returns true, this caller-provided
|
||||
/// value will be filled with the 96-bit key that, when
|
||||
/// programmed to the tag, should authenticate against
|
||||
/// the nonce+frn values, with tag returning the grn value.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// true when another potential key has been found.
|
||||
/// false if no additional potential keys have been found.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Note: In C++, each parameter would be a reference (not pointer).
|
||||
/// </remarks>
|
||||
// bool id48lib_key_recovery_next(
|
||||
// ID48LIB_KEY *potential_key_output
|
||||
// );
|
||||
|
||||
|
||||
|
||||
bool recovery_succeeds(const TEST_VECTOR_T *test_vector, bool zero_partial_key) {
|
||||
|
||||
ID48LIB_KEY partial_key = {0};
|
||||
memcpy(&partial_key, &test_vector->key, sizeof(partial_key));
|
||||
if (zero_partial_key) {
|
||||
// API is only supposed to be looking at the first 6 bytes of the key
|
||||
memset(&partial_key.k[6], 0, sizeof(partial_key.k) - 6);
|
||||
}
|
||||
|
||||
id48lib_key_recovery_init(&partial_key, &test_vector->nonce, &test_vector->expected_frn, &test_vector->expected_grn);
|
||||
|
||||
bool key_found = false;
|
||||
uint32_t potential_keys_found = 0;
|
||||
ID48LIB_KEY potential_key = {0};
|
||||
while (id48lib_key_recovery_next(&potential_key)) {
|
||||
potential_keys_found++;
|
||||
// just verify that the potential key matches the test vector
|
||||
if (bytes_equal(potential_key.k, test_vector->key.k, sizeof(test_vector->key.k))) {
|
||||
key_found = true;
|
||||
}
|
||||
}
|
||||
return key_found;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
bool any_failures = false;
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE2(test_vectors); i++) {
|
||||
printf("Testing recovery for test vector '%s'\n", test_vectors[i].description);
|
||||
if (!recovery_succeeds(&test_vectors[i], false)) {
|
||||
printf("FAILURE: id48lib_recovery: test vector '%s'\n", test_vectors[i].description);
|
||||
any_failures = true;
|
||||
}
|
||||
printf("Testing recovery for test vector '%s' (partially-zero'd key)\n", test_vectors[i].description);
|
||||
if (!recovery_succeeds(&test_vectors[i], true)) {
|
||||
printf("FAILURE: id48lib_recovery: test vector '%s' (partially-zero'd key)\n", test_vectors[i].description);
|
||||
any_failures = true;
|
||||
}
|
||||
}
|
||||
if (any_failures) {
|
||||
printf("id48lib_recovery: some tests failed\n");
|
||||
} else {
|
||||
printf("id48lib_recovery: all tests passed\n");
|
||||
}
|
||||
return any_failures ? 120 : 0;
|
||||
}
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
# This is manually re-creating the contents of id48/src/CMakeLists.txt
|
||||
# and thus must be manually kept in sync with updates to id48/src.
|
||||
add_library(pm3rrg_rdv4_id48 STATIC
|
||||
id48/id48_data.c
|
||||
id48/id48_generator.c
|
||||
id48/id48_recover.c
|
||||
id48/src/id48_data.c
|
||||
id48/src/id48_generator.c
|
||||
id48/src/id48_recover.c
|
||||
)
|
||||
target_compile_options( pm3rrg_rdv4_id48 PRIVATE -Wpedantic -Wall -Werror -O3 -Wno-unknown-pragmas -Wno-inline -Wno-unused-function -DID48_NO_STDIO)
|
||||
target_include_directories(pm3rrg_rdv4_id48 PRIVATE id48)
|
||||
target_include_directories(pm3rrg_rdv4_id48 INTERFACE id48)
|
||||
target_include_directories(pm3rrg_rdv4_id48 PRIVATE id48/public)
|
||||
target_include_directories(pm3rrg_rdv4_id48 INTERFACE id48/public)
|
||||
set_property(TARGET pm3rrg_rdv4_id48 PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue