lua-symmetric

Symmetric crypto for Lua
Log | Files | Refs

main.c (3937B)


      1 /*
      2  * Copyright (c) 2015, Michael Savage <mike@mikejsavage.co.uk>
      3  *
      4  * Permission to use, copy, modify, and/or distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15 */
     16 
     17 #include <string.h>
     18 
     19 #include <sodium.h>
     20 #include <lua.h>
     21 #include <lualib.h>
     22 #include <lauxlib.h>
     23 
     24 #if LUA_VERSION_NUM < 502
     25 	#define luaL_newlib( L, l ) ( lua_newtable( L ), luaL_register( L, NULL, l ) )
     26 #endif
     27 
     28 #define stringify_helper( x ) #x
     29 #define stringify( x ) stringify_helper( x )
     30 
     31 static int luasymmetric_encrypt( lua_State * const L ) {
     32 	size_t message_len;
     33 	size_t key_len;
     34 	const char * const message = luaL_checklstring( L, 1, &message_len );
     35 	const char * const key = luaL_checklstring( L, 2, &key_len );
     36 
     37 	if( key_len != crypto_secretbox_KEYBYTES ) {
     38 		lua_pushliteral( L, "key should be " stringify( crypto_secretbox_KEYBYTES ) " bytes" );
     39 		return lua_error( L );
     40 	}
     41 
     42 	const size_t ciphertext_len = message_len + crypto_secretbox_NONCEBYTES + crypto_secretbox_MACBYTES;
     43 
     44 	/* overflow */
     45 	if( ciphertext_len < message_len ) {
     46 		lua_pushliteral( L, "message too long" );
     47 		return lua_error( L );
     48 	}
     49 
     50 	char * const ciphertext = malloc( ciphertext_len );
     51 
     52 	if( ciphertext == NULL ) {
     53 		lua_pushliteral( L, "out of memory" );
     54 		return lua_error( L );
     55 	}
     56 
     57 	/* prepend iv */
     58 	arc4random_buf( ciphertext, crypto_secretbox_NONCEBYTES );
     59 
     60 	/*
     61 	 * the only failure case is the ciphertext not fitting in memory
     62 	 * but we already tested for that
     63 	 */
     64 	( void ) crypto_secretbox_easy( ciphertext + crypto_secretbox_NONCEBYTES,
     65 		message, message_len, ciphertext, key );
     66 
     67 	lua_pushlstring( L, ciphertext, ciphertext_len );
     68 
     69 	explicit_bzero( ciphertext, ciphertext_len );
     70 	free( ciphertext );
     71 
     72 	return 1;
     73 }
     74 
     75 static int luasymmetric_decrypt( lua_State * const L ) {
     76 	size_t ciphertext_len;
     77 	size_t key_len;
     78 	const char * const ciphertext = luaL_checklstring( L, 1, &ciphertext_len );
     79 	const char * const key = luaL_checklstring( L, 2, &key_len );
     80 
     81 	if( key_len != crypto_secretbox_KEYBYTES ) {
     82 		lua_pushliteral( L, "key should be " stringify( crypto_secretbox_KEYBYTES ) " bytes" );
     83 		return lua_error( L );
     84 	}
     85 
     86 	if( ciphertext_len < crypto_secretbox_NONCEBYTES + crypto_secretbox_MACBYTES ) {
     87 		lua_pushnil( L );
     88 		return 1;
     89 	}
     90 
     91 	const size_t message_len = ciphertext_len - crypto_secretbox_NONCEBYTES - crypto_secretbox_MACBYTES;
     92 	char * const message = malloc( message_len );
     93 
     94 	if( message == NULL ) {
     95 		lua_pushliteral( L, "out of memory" );
     96 		return lua_error( L );
     97 	}
     98 
     99 	const int ok = crypto_secretbox_open_easy( message,
    100 		ciphertext + crypto_secretbox_NONCEBYTES, ciphertext_len - crypto_secretbox_NONCEBYTES,
    101 		ciphertext, key );
    102 
    103 	if( ok == 0 ) {
    104 		lua_pushlstring( L, message, message_len );
    105 	}
    106 	else {
    107 		lua_pushnil( L );
    108 	}
    109 
    110 	explicit_bzero( message, message_len );
    111 	free( message );
    112 
    113 	return 1;
    114 }
    115 
    116 static int luasymmetric_key( lua_State * const L ) {
    117 	char key[ crypto_secretbox_KEYBYTES ];
    118 	arc4random_buf( key, sizeof( key ) );
    119 
    120 	lua_pushlstring( L, key, sizeof( key ) );
    121 	explicit_bzero( key, sizeof( key ) );
    122 
    123 	return 1;
    124 }
    125 
    126 static const struct luaL_Reg luasymmetric_lib[] = {
    127 	{ "encrypt", luasymmetric_encrypt },
    128 	{ "decrypt", luasymmetric_decrypt },
    129 	{ "key", luasymmetric_key },
    130 	{ NULL, NULL },
    131 };
    132 
    133 LUALIB_API int luaopen_symmetric( lua_State * const L ) {
    134 	luaL_newlib( L, luasymmetric_lib );
    135 
    136 	return 1;
    137 }