luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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 }