BARE_METAL.md (6887B)
1 # Bare Metal LuaJIT Usage Guide 2 3 This cryptography library can be used in bare metal LuaJIT environments without an operating system. 4 5 ## Requirements 6 7 ### 1. Memory Allocator 8 You must provide a memory allocator. Either: 9 - Link against a minimal libc that provides `malloc()`, `free()`, `calloc()`, `realloc()` 10 - **OR** define `USE_CUSTOM_ALLOCATOR` and provide your own allocator 11 12 ### 2. Time/Entropy Sources 13 You must implement two functions for CSPRNG entropy: 14 15 ```c 16 uint64_t baremetal_get_ticks(void); /* Monotonic tick counter */ 17 uint64_t baremetal_get_cycles(void); /* CPU cycle counter */ 18 ``` 19 20 ### 3. Standard String Functions 21 You need: `memcpy()`, `memset()`, `memmove()`, `memcmp()`, `strlen()` 22 23 Most bare metal environments provide these, or you can implement them easily. 24 25 ## Compilation 26 27 ### Step 1: Define BARE_METAL 28 Compile with `-DBARE_METAL` flag: 29 30 ```bash 31 gcc -DBARE_METAL -c crypto.c CSPRNG.c ... 32 ``` 33 34 ### Step 2: Implement Required Functions 35 36 Create a file `baremetal_impl.c`: 37 38 ```c 39 #include <stdint.h> 40 41 /* Example for x86_64 */ 42 uint64_t baremetal_get_cycles(void) { 43 uint32_t lo, hi; 44 __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); 45 return ((uint64_t)hi << 32) | lo; 46 } 47 48 uint64_t baremetal_get_ticks(void) { 49 /* If you have a timer/PIT/HPET, use it */ 50 /* Otherwise, use CPU cycles as fallback */ 51 return baremetal_get_cycles(); 52 } 53 ``` 54 55 ### Step 3 (Optional): Custom Memory Allocator 56 57 If you don't have malloc/free, define `USE_CUSTOM_ALLOCATOR` and provide: 58 59 ```c 60 void* baremetal_malloc(size_t size); 61 void baremetal_free(void *ptr); 62 void* baremetal_calloc(size_t nmemb, size_t size); 63 void* baremetal_realloc(void *ptr, size_t size); 64 ``` 65 66 Compile with: 67 ```bash 68 gcc -DBARE_METAL -DUSE_CUSTOM_ALLOCATOR ... 69 ``` 70 71 ## Platform-Specific Examples 72 73 ### x86_64 (RDTSC) 74 75 ```c 76 uint64_t baremetal_get_cycles(void) { 77 uint32_t lo, hi; 78 __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); 79 return ((uint64_t)hi << 32) | lo; 80 } 81 82 uint64_t baremetal_get_ticks(void) { 83 /* Use HPET, PIT, or TSC */ 84 return baremetal_get_cycles(); 85 } 86 ``` 87 88 ### ARM64 (Generic Timer) 89 90 ```c 91 uint64_t baremetal_get_cycles(void) { 92 uint64_t val; 93 __asm__ __volatile__("mrs %0, cntvct_el0" : "=r"(val)); 94 return val; 95 } 96 97 uint64_t baremetal_get_ticks(void) { 98 return baremetal_get_cycles(); 99 } 100 ``` 101 102 ### ARM32 (Cortex-A) 103 104 ```c 105 uint64_t baremetal_get_cycles(void) { 106 uint32_t val; 107 __asm__ __volatile__("mrc p15, 0, %0, c9, c13, 0" : "=r"(val)); 108 return val; 109 } 110 111 uint64_t baremetal_get_ticks(void) { 112 return baremetal_get_cycles(); 113 } 114 ``` 115 116 ### RISC-V 117 118 ```c 119 uint64_t baremetal_get_cycles(void) { 120 uint64_t val; 121 __asm__ __volatile__("rdcycle %0" : "=r"(val)); 122 return val; 123 } 124 125 uint64_t baremetal_get_ticks(void) { 126 return baremetal_get_cycles(); 127 } 128 ``` 129 130 ## Usage in LuaJIT 131 132 Once compiled for bare metal, usage from Lua is identical: 133 134 ```lua 135 local crypto = require("crypto") 136 137 -- CSPRNG will auto-initialize using your baremetal_get_ticks() 138 local key = crypto.CSPRNG.newKey() 139 local nonce = crypto.CSPRNG.randomBytes(12) 140 141 -- All crypto functions work normally 142 local plaintext = "Hello, bare metal!" 143 local encrypted = crypto.ChaCha20.encrypt(key, plaintext) 144 local decrypted = crypto.ChaCha20.decrypt(key, encrypted) 145 ``` 146 147 ## What Gets Disabled in Bare Metal Mode 148 149 When `BARE_METAL` is defined: 150 - `fprintf()`, `printf()`, `perror()` → stubbed out (do nothing) 151 - `clock_gettime()` → redirects to your `baremetal_get_ticks()` 152 - `time()` → redirects to your `baremetal_get_ticks()` 153 154 ## Security Considerations 155 156 ### Entropy Quality 157 The security of the CSPRNG depends on your entropy sources: 158 159 **Good entropy sources:** 160 - High-resolution CPU cycle counter (RDTSC, CNTVCT, etc.) 161 - Hardware random number generator (RDRAND, RDSEED on x86) 162 - Timer interrupts with jitter 163 - DMA timing variations 164 - Cache timing 165 166 **Poor entropy sources:** 167 - Simple counters without jitter 168 - Predictable timers 169 - Deterministic values 170 171 ### Example: Using RDRAND (x86) 172 173 ```c 174 uint64_t baremetal_get_cycles(void) { 175 uint64_t val; 176 /* Try RDRAND first */ 177 if (__builtin_cpu_supports("rdrnd")) { 178 __asm__ __volatile__("rdrand %0" : "=r"(val)); 179 return val; 180 } 181 /* Fall back to RDTSC */ 182 uint32_t lo, hi; 183 __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); 184 return ((uint64_t)hi << 32) | lo; 185 } 186 ``` 187 188 ## Testing Bare Metal Build 189 190 ```bash 191 # Compile with bare metal flag 192 gcc -DBARE_METAL -c CSPRNG.c -o CSPRNG.o 193 194 # Link with your bare metal implementation 195 gcc -DBARE_METAL -o test_crypto \ 196 crypto.o CSPRNG.o baremetal_impl.o \ 197 -llua -lgmp -lm 198 199 # Or for LuaJIT shared library 200 gcc -DBARE_METAL -shared -fPIC \ 201 crypto.c CSPRNG.c baremetal_impl.c \ 202 -o crypto.so -lgmp 203 ``` 204 205 ## Minimal Example 206 207 Here's a complete minimal example for x86_64: 208 209 **baremetal_impl.c:** 210 ```c 211 #include <stdint.h> 212 213 uint64_t baremetal_get_cycles(void) { 214 uint32_t lo, hi; 215 __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); 216 return ((uint64_t)hi << 32) | lo; 217 } 218 219 uint64_t baremetal_get_ticks(void) { 220 return baremetal_get_cycles(); 221 } 222 ``` 223 224 **Compile:** 225 ```bash 226 # Compile all crypto sources with BARE_METAL 227 gcc -DBARE_METAL -shared -fPIC \ 228 crypto.c CSPRNG.c CSPRNG_Lua.c \ 229 Hash_Lua.c PBKDF2_Lua.c \ 230 X25519_Lua.c Ed25519_Lua.c \ 231 RSA_Lua.c RSA_production.c \ 232 P256_Lua.c P256.c \ 233 hashing/*.c \ 234 baremetal_impl.c \ 235 -o crypto.so -lluajit -lgmp 236 ``` 237 238 **Use in LuaJIT:** 239 ```lua 240 local crypto = require("crypto") 241 print("Bare metal crypto initialized!") 242 243 local key = crypto.CSPRNG.newKey(256) 244 print("Generated key:", key) 245 ``` 246 247 ## Notes 248 249 1. **Memory**: Ensure you have enough heap space for RSA operations (they can allocate several KB) 250 2. **Stack**: Deep recursion in some algorithms may require larger stack 251 3. **FPU**: Not required - all operations use integer math 252 4. **Threading**: Not thread-safe by default - use locks if needed 253 5. **Performance**: Hardware AES-NI and PCLMULQDQ are used when available 254 255 ## Troubleshooting 256 257 ### "undefined reference to baremetal_get_ticks" 258 You forgot to implement the required functions or link `baremetal_impl.o` 259 260 ### "undefined reference to malloc" 261 Link against a libc or define `USE_CUSTOM_ALLOCATOR` 262 263 ### Weak entropy warnings 264 Your `baremetal_get_ticks()` returns constant values - implement proper timer 265 266 ### Segmentation fault 267 Check your memory allocator and stack size 268 269 ## Summary 270 271 To use this crypto library in bare metal LuaJIT: 272 273 ✅ **Required:** 274 1. Define `BARE_METAL` during compilation 275 2. Implement `baremetal_get_ticks()` and `baremetal_get_cycles()` 276 3. Provide memory allocator (malloc/free) or use custom 277 4. Link against LuaJIT and GMP 278 279 ✅ **Optional:** 280 - Hardware crypto acceleration (AES-NI, PCLMULQDQ) 281 - Hardware RNG (RDRAND, RDSEED) 282 283 ✅ **Result:** 284 - Full cryptographic library in bare metal environment 285 - No OS dependencies 286 - Works with your custom timer/entropy sources