CSPRNG_Lua.c (8682B)
1 /* 2 * CSPRNG_Lua.c - Lua bindings for Cryptographically Secure PRNG 3 */ 4 5 #include "CSPRNG_Lua.h" 6 #include "CSPRNG.h" 7 #include <stdlib.h> 8 #include <string.h> 9 10 /* Base64 encoding/decoding functions (provided by crypto.c) */ 11 extern char* base64_encode(const uint8_t *data, size_t len, size_t *out_len); 12 extern uint8_t* base64_decode(const char *data, size_t len, size_t *out_len); 13 14 /* Metatable name for CSPRNG instances */ 15 #define CSPRNG_MT "CSPRNG" 16 17 /* ============================================================================ 18 * Helper Functions 19 * ========================================================================= */ 20 21 /* Get CSPRNG context from Lua userdata */ 22 static csprng_context* get_csprng_context(lua_State *L, int index) { 23 return (csprng_context*)luaL_checkudata(L, index, CSPRNG_MT); 24 } 25 26 /* ============================================================================ 27 * Global CSPRNG Functions (using default instance) 28 * ========================================================================= */ 29 30 /** 31 * Generate a cryptographically secure random key (global instance) 32 * Usage: key_b64 = crypto.CSPRNG.newKey() -- defaults to 256-bit (32 bytes) 33 * key_b64 = crypto.CSPRNG.newKey(128) -- 128-bit (16 bytes) 34 * key_b64 = crypto.CSPRNG.newKey(256) -- 256-bit (32 bytes) 35 * key_b64 = crypto.CSPRNG.newKey(512) -- 512-bit (64 bytes) 36 */ 37 int l_csprng_new_key(lua_State *L) { 38 /* Default to 256-bit key */ 39 int bits = 256; 40 41 /* Check if user specified a key size */ 42 if (lua_gettop(L) >= 1) { 43 bits = luaL_checkinteger(L, 1); 44 45 /* Validate key size */ 46 if (bits <= 0 || bits % 8 != 0) { 47 return luaL_error(L, "Key size must be a positive multiple of 8 bits"); 48 } 49 50 if (bits > 4096) { 51 return luaL_error(L, "Key size too large (max 4096 bits)"); 52 } 53 } 54 55 /* Convert bits to bytes */ 56 size_t key_bytes = bits / 8; 57 58 /* Generate random key */ 59 uint8_t *key = malloc(key_bytes); 60 if (!key) { 61 return luaL_error(L, "Memory allocation failed"); 62 } 63 64 random_bytes(key, key_bytes); 65 66 /* Encode to base64 */ 67 size_t b64_len; 68 char *b64 = base64_encode(key, key_bytes, &b64_len); 69 70 /* Clean up key from memory */ 71 memset(key, 0, key_bytes); 72 free(key); 73 74 if (!b64) { 75 return luaL_error(L, "Base64 encoding failed"); 76 } 77 78 lua_pushlstring(L, b64, b64_len); 79 free(b64); 80 81 return 1; 82 } 83 84 /** 85 * Generate random bytes (global instance) 86 * Usage: bytes_b64 = crypto.CSPRNG.randomBytes(32) -- 32 random bytes 87 */ 88 int l_csprng_random_bytes(lua_State *L) { 89 size_t num_bytes = luaL_checkinteger(L, 1); 90 91 /* Validate byte count */ 92 if (num_bytes <= 0) { 93 return luaL_error(L, "Byte count must be positive"); 94 } 95 96 if (num_bytes > 1048576) { /* 1MB limit */ 97 return luaL_error(L, "Byte count too large (max 1MB)"); 98 } 99 100 /* Generate random bytes */ 101 uint8_t *bytes = malloc(num_bytes); 102 if (!bytes) { 103 return luaL_error(L, "Memory allocation failed"); 104 } 105 106 random_bytes(bytes, num_bytes); 107 108 /* Encode to base64 */ 109 size_t b64_len; 110 char *b64 = base64_encode(bytes, num_bytes, &b64_len); 111 112 /* Clean up bytes from memory */ 113 memset(bytes, 0, num_bytes); 114 free(bytes); 115 116 if (!b64) { 117 return luaL_error(L, "Base64 encoding failed"); 118 } 119 120 lua_pushlstring(L, b64, b64_len); 121 free(b64); 122 123 return 1; 124 } 125 126 /* ============================================================================ 127 * Instance CSPRNG Functions 128 * ========================================================================= */ 129 130 /** 131 * Create new CSPRNG instance with seed 132 * Usage: csprng = crypto.CSPRNG.new(seed_b64) 133 */ 134 int l_csprng_new_instance(lua_State *L) { 135 size_t seed_b64_len; 136 const char *seed_b64 = luaL_checklstring(L, 1, &seed_b64_len); 137 138 /* Decode seed */ 139 size_t seed_len; 140 uint8_t *seed = base64_decode(seed_b64, seed_b64_len, &seed_len); 141 if (!seed || seed_len != 32) { 142 free(seed); 143 return luaL_error(L, "Seed must be 32 bytes (256 bits) when base64-decoded"); 144 } 145 146 /* Create userdata for CSPRNG context */ 147 csprng_context *ctx = (csprng_context*)lua_newuserdata(L, sizeof(csprng_context)); 148 if (!ctx) { 149 memset(seed, 0, seed_len); 150 free(seed); 151 return luaL_error(L, "Failed to allocate CSPRNG context"); 152 } 153 154 /* Initialize with seed */ 155 if (csprng_init_with_seed(ctx, seed) != 0) { 156 memset(seed, 0, seed_len); 157 free(seed); 158 return luaL_error(L, "Failed to initialize CSPRNG"); 159 } 160 161 /* Clean up seed */ 162 memset(seed, 0, seed_len); 163 free(seed); 164 165 /* Set metatable */ 166 luaL_getmetatable(L, CSPRNG_MT); 167 lua_setmetatable(L, -2); 168 169 return 1; 170 } 171 172 /** 173 * Generate key from CSPRNG instance 174 * Usage: key_b64 = csprng:newKey() 175 * key_b64 = csprng:newKey(128) 176 */ 177 static int l_csprng_instance_new_key(lua_State *L) { 178 csprng_context *ctx = get_csprng_context(L, 1); 179 180 /* Default to 256-bit key */ 181 int bits = 256; 182 183 /* Check if user specified a key size */ 184 if (lua_gettop(L) >= 2) { 185 bits = luaL_checkinteger(L, 2); 186 187 /* Validate key size */ 188 if (bits <= 0 || bits % 8 != 0) { 189 return luaL_error(L, "Key size must be a positive multiple of 8 bits"); 190 } 191 192 if (bits > 4096) { 193 return luaL_error(L, "Key size too large (max 4096 bits)"); 194 } 195 } 196 197 /* Convert bits to bytes */ 198 size_t key_bytes = bits / 8; 199 200 /* Generate random key */ 201 uint8_t *key = malloc(key_bytes); 202 if (!key) { 203 return luaL_error(L, "Memory allocation failed"); 204 } 205 206 if (csprng_generate(ctx, key, key_bytes) != 0) { 207 memset(key, 0, key_bytes); 208 free(key); 209 return luaL_error(L, "Failed to generate random data"); 210 } 211 212 /* Encode to base64 */ 213 size_t b64_len; 214 char *b64 = base64_encode(key, key_bytes, &b64_len); 215 216 /* Clean up key from memory */ 217 memset(key, 0, key_bytes); 218 free(key); 219 220 if (!b64) { 221 return luaL_error(L, "Base64 encoding failed"); 222 } 223 224 lua_pushlstring(L, b64, b64_len); 225 free(b64); 226 227 return 1; 228 } 229 230 /** 231 * Generate random bytes from CSPRNG instance 232 * Usage: bytes_b64 = csprng:randomBytes(32) 233 */ 234 static int l_csprng_instance_random_bytes(lua_State *L) { 235 csprng_context *ctx = get_csprng_context(L, 1); 236 size_t num_bytes = luaL_checkinteger(L, 2); 237 238 /* Validate byte count */ 239 if (num_bytes <= 0) { 240 return luaL_error(L, "Byte count must be positive"); 241 } 242 243 if (num_bytes > 1048576) { /* 1MB limit */ 244 return luaL_error(L, "Byte count too large (max 1MB)"); 245 } 246 247 /* Generate random bytes */ 248 uint8_t *bytes = malloc(num_bytes); 249 if (!bytes) { 250 return luaL_error(L, "Memory allocation failed"); 251 } 252 253 if (csprng_generate(ctx, bytes, num_bytes) != 0) { 254 memset(bytes, 0, num_bytes); 255 free(bytes); 256 return luaL_error(L, "Failed to generate random data"); 257 } 258 259 /* Encode to base64 */ 260 size_t b64_len; 261 char *b64 = base64_encode(bytes, num_bytes, &b64_len); 262 263 /* Clean up bytes from memory */ 264 memset(bytes, 0, num_bytes); 265 free(bytes); 266 267 if (!b64) { 268 return luaL_error(L, "Base64 encoding failed"); 269 } 270 271 lua_pushlstring(L, b64, b64_len); 272 free(b64); 273 274 return 1; 275 } 276 277 /** 278 * Garbage collection for CSPRNG instance 279 */ 280 static int l_csprng_instance_gc(lua_State *L) { 281 csprng_context *ctx = get_csprng_context(L, 1); 282 csprng_cleanup(ctx); 283 return 0; 284 } 285 286 /* ============================================================================ 287 * Registration 288 * ========================================================================= */ 289 290 /* Instance methods */ 291 static const luaL_Reg csprng_instance_methods[] = { 292 {"newKey", l_csprng_instance_new_key}, 293 {"randomBytes", l_csprng_instance_random_bytes}, 294 {NULL, NULL} 295 }; 296 297 /* Instance metamethods */ 298 static const luaL_Reg csprng_instance_metamethods[] = { 299 {"__gc", l_csprng_instance_gc}, 300 {NULL, NULL} 301 }; 302 303 /** 304 * Register CSPRNG metatable 305 * Called from luaopen_crypto 306 */ 307 void register_csprng_metatable(lua_State *L) { 308 /* Create metatable for CSPRNG instances */ 309 luaL_newmetatable(L, CSPRNG_MT); 310 311 /* Set __index to point to methods table */ 312 lua_pushvalue(L, -1); /* Push metatable */ 313 lua_setfield(L, -2, "__index"); /* mt.__index = mt */ 314 315 /* Register instance methods */ 316 luaL_setfuncs(L, csprng_instance_methods, 0); 317 318 /* Register metamethods */ 319 luaL_setfuncs(L, csprng_instance_metamethods, 0); 320 321 lua_pop(L, 1); /* Pop metatable */ 322 }