diff --git a/app/include/rom.h b/app/include/rom.h new file mode 100644 index 00000000..fed433ab --- /dev/null +++ b/app/include/rom.h @@ -0,0 +1,25 @@ +// Headers to the various functions in the rom (as we discover them) + +// SHA1 is assumed to match the netbsd sha1.h headers +#define SHA1_DIGEST_LENGTH 20 +#define SHA1_DIGEST_STRING_LENGTH 41 + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + uint8_t buffer[64]; +} SHA1_CTX; + +extern void SHA1Transform(uint32_t[5], const uint8_t[64]); +extern void SHA1Init(SHA1_CTX *); +extern void SHA1Final(uint8_t[SHA1_DIGEST_LENGTH], SHA1_CTX *); +extern void SHA1Update(SHA1_CTX *, const uint8_t *, unsigned int); + +// base64_encode/decode derived by Cal +// Appears to match base64.h from netbsd wpa utils. +extern unsigned char * base64_encode(const unsigned char *src, size_t len, size_t *out_len); +extern unsigned char * base64_decode(const unsigned char *src, size_t len, size_t *out_len); +// Unfortunately it that seems to require the ROM memory management to be +// initialized because it uses mem_malloc + +extern void mem_init(void * start_addr); diff --git a/app/include/user_modules.h b/app/include/user_modules.h index d8ddc654..e0d0b40c 100644 --- a/app/include/user_modules.h +++ b/app/include/user_modules.h @@ -31,6 +31,7 @@ #define LUA_USE_MODULES_U8G #define LUA_USE_MODULES_WS2812 #define LUA_USE_MODULES_CJSON +#define LUA_USE_MODULES_CRYPTO #endif /* LUA_USE_MODULES */ #endif /* __USER_MODULES_H__ */ diff --git a/app/modules/crypto.c b/app/modules/crypto.c new file mode 100644 index 00000000..98f69bb6 --- /dev/null +++ b/app/modules/crypto.c @@ -0,0 +1,134 @@ +// Module for cryptography + +//#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +#include "platform.h" +#include "auxmods.h" +#include "lrotable.h" +#include "c_types.h" +#include "c_stdlib.h" + +#include "user_interface.h" + +#include "rom.h" + +/** + * hash = crypto.sha1(input) + * + * Calculates raw SHA1 hash of input string. + * Input is arbitrary string, output is raw 20-byte hash as string. + */ +static int crypto_sha1( lua_State* L ) +{ + SHA1_CTX ctx; + uint8_t digest[20]; + // Read the string from lua (with length) + int len; + const char* msg = luaL_checklstring(L, 1, &len); + // Use the SHA* functions in the rom + SHA1Init(&ctx); + SHA1Update(&ctx, msg, len); + SHA1Final(digest, &ctx); + + // Push the result as a lua string + lua_pushlstring(L, digest, 20); + return 1; +} + + +static const char* bytes64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +/** + * encoded = crypto.base64Encode(raw) + * + * Encodes raw binary string as base64 string. + */ +static int crypto_base64_encode( lua_State* L ) +{ + int len; + const char* msg = luaL_checklstring(L, 1, &len); + int blen = (len + 2) / 3 * 4; + char* out = (char*)c_malloc(blen); + int j = 0, i; + for (i = 0; i < len; i += 3) { + int a = msg[i]; + int b = (i + 1 < len) ? msg[i + 1] : 0; + int c = (i + 2 < len) ? msg[i + 2] : 0; + out[j++] = bytes64[a >> 2]; + out[j++] = bytes64[((a & 3) << 4) | (b >> 4)]; + out[j++] = (i + 1 < len) ? bytes64[((b & 15) << 2) | (c >> 6)] : 61; + out[j++] = (i + 2 < len) ? bytes64[(c & 63)] : 61; + } + lua_pushlstring(L, out, j); + c_free(out); + return 1; +} + +static const char* byteshex = "0123456789abcdef"; +/** + * encoded = crypto.hexEncode(raw) + * + * Encodes raw binary string as hex string. + */ +static int crypto_hex_encode( lua_State* L) +{ + int len; + const char* msg = luaL_checklstring(L, 1, &len); + char* out = (char*)c_malloc(len * 2); + int i, j = 0; + for (i = 0; i < len; i++) { + out[j++] = byteshex[msg[i] >> 4]; + out[j++] = byteshex[msg[i] & 0xf]; + } + lua_pushlstring(L, out, len*2); + c_free(out); + return 1; +} + +/** + * masked = crypto.mask(message, mask) + * + * Apply a mask (repeated if shorter than message) as XOR to each byte. + */ +static int crypto_mask( lua_State* L ) +{ + int len, mask_len; + const char* msg = luaL_checklstring(L, 1, &len); + const char* mask = luaL_checklstring(L, 2, &mask_len); + int i; + char* copy = (char*)c_malloc(len); + for (i = 0; i < len; i++) { + copy[i] = msg[i] ^ mask[i % 4]; + } + lua_pushlstring(L, copy, len); + c_free(copy); + return 1; +} + +// Module function map +#define MIN_OPT_LEVEL 2 +#include "lrodefs.h" +const LUA_REG_TYPE crypto_map[] = +{ + { LSTRKEY( "sha1" ), LFUNCVAL( crypto_sha1 ) }, + { LSTRKEY( "toBase64" ), LFUNCVAL( crypto_base64_encode ) }, + { LSTRKEY( "toHex" ), LFUNCVAL( crypto_hex_encode ) }, + { LSTRKEY( "mask" ), LFUNCVAL( crypto_mask ) }, + +#if LUA_OPTIMIZE_MEMORY > 0 + +#endif + { LNILKEY, LNILVAL } +}; + +LUALIB_API int luaopen_crypto( lua_State *L ) +{ +#if LUA_OPTIMIZE_MEMORY > 0 + return 0; +#else // #if LUA_OPTIMIZE_MEMORY > 0 + luaL_register( L, AUXLIB_CRYPTO, crypto_map ); + // Add constants + + return 1; +#endif // #if LUA_OPTIMIZE_MEMORY > 0 +} diff --git a/app/modules/modules.h b/app/modules/modules.h index fddc45cc..a823d360 100644 --- a/app/modules/modules.h +++ b/app/modules/modules.h @@ -149,6 +149,14 @@ #define ROM_MODULES_CJSON #endif +#if defined(LUA_USE_MODULES_CRYPTO) +#define MODULES_CRYPTO "crypto" +#define ROM_MODULES_CRYPTO \ + _ROM(MODULES_CRYPTO, luaopen_crypto, crypto_map) +#else +#define ROM_MODULES_CRYPTO +#endif + #define LUA_MODULES_ROM \ ROM_MODULES_GPIO \ ROM_MODULES_PWM \ @@ -167,7 +175,8 @@ ROM_MODULES_OW \ ROM_MODULES_BIT \ ROM_MODULES_WS2812 \ - ROM_MODULES_CJSON + ROM_MODULES_CJSON \ + ROM_MODULES_CRYPTO #endif