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 }