/******************************************************************************
* $Id: crypto_lua.c,v 1.12 2006/01/13 21:46:54 gareuselesinge Exp $
* This file is part of FreePOPs (http://www.freepops.org) *
* This file is distributed under the terms of GNU GPL license. *
******************************************************************************/
/******************************************************************************
* File description:
* some of crypto lib to lua
* Notes:
*
* Authors:
* Name <gareuselesinge@users.sourceforge.net>
******************************************************************************/
#include "lua.h"
#include "luabind.h"
#include "lauxlib.h"
#include "compat-5.1.h"
#include <stdlib.h>
#define CRYPTO_ALGO_MD "crypto.ALGO_md.type"
#define CRYPTO_GCRYPT 1
#define CRYPTO_OPENSSL 2
#ifndef CRYPTO_IMPLEMENTATION
#define CRYPTO_IMPLEMENTATION CRYPTO_OPENSSL
#endif
#if CRYPTO_IMPLEMENTATION == CRYPTO_OPENSSL
#include <openssl/opensslconf.h>
#include <openssl/md5.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#elif CRYPTO_IMPLEMENTATION == CRYPTO_GCRYPT
#include <gcrypt.h>
#else
#error "CRYPTO_IMPLEMENTATION not supported"
#endif
// =================== MD5 ==================
static int lmd5(lua_State* L){
size_t len;
const char *data = luaL_checklstring(L,1,&len);
#if CRYPTO_IMPLEMENTATION == CRYPTO_OPENSSL
size_t digest_len = MD5_DIGEST_LENGTH;
#elif CRYPTO_IMPLEMENTATION == CRYPTO_GCRYPT
size_t digest_len = gcry_md_get_algo_dlen(GCRY_MD_MD5);
#endif
char md[digest_len];
#if CRYPTO_IMPLEMENTATION == CRYPTO_OPENSSL
MD5_CTX C;
MD5_Init(&C);
MD5_Update(&C, (const void *)data,(unsigned long) len);
MD5_Final((unsigned char *)md, &C);
#elif CRYPTO_IMPLEMENTATION == CRYPTO_GCRYPT
gcry_md_hash_buffer(GCRY_MD_MD5,md,data,len);
#endif
lua_pushlstring(L,md,digest_len);
return 1;
}
// ============================ generic HMAC ==============================
static int lhmac(lua_State* L){
const char *data;
const char *key;
size_t len_sizet;
size_t klen;
#if CRYPTO_IMPLEMENTATION == CRYPTO_OPENSSL
unsigned int len_uint;
HMAC_CTX C;
const EVP_MD *evp;
char md[EVP_MAX_MD_SIZE];
#elif CRYPTO_IMPLEMENTATION == CRYPTO_GCRYPT
int (*algo_f)(void) = NULL;
int algo;
gcry_md_hd_t hd;
unsigned char * tmp;
#endif
data = luaL_checklstring(L,1,&len_sizet);
key = luaL_checklstring(L,2,&klen);
#if CRYPTO_IMPLEMENTATION == CRYPTO_OPENSSL
evp = *(const EVP_MD **) luaL_checkudata(L,3,CRYPTO_ALGO_MD);
luaL_argcheck(L,evp != NULL,3,"crypto.ALGO_* expected");
#elif CRYPTO_IMPLEMENTATION == CRYPTO_GCRYPT
algo_f = *(int (**)(void))luaL_checkudata(L,3,CRYPTO_ALGO_MD);
algo = algo_f();
luaL_argcheck(L,algo != GCRY_MD_NONE,3,"crypto.ALGO_* expected");
#endif
#if CRYPTO_IMPLEMENTATION == CRYPTO_OPENSSL
len_uint = len_sizet;
HMAC_Init(&C,key,klen,((const EVP_MD *(*)(void))evp)());
HMAC_Update(&C,(const void *)data,len_uint);
len_uint = EVP_MAX_MD_SIZE;
HMAC_Final(&C,(unsigned char *)md,&len_uint);
HMAC_cleanup(&C);
len_sizet = len_uint;
lua_pushlstring(L,md,len_sizet);
#elif CRYPTO_IMPLEMENTATION == CRYPTO_GCRYPT
gcry_md_open(&hd,algo,GCRY_MD_FLAG_HMAC);
gcry_md_setkey(hd,key,klen);
gcry_md_write(hd,data,len_sizet);
gcry_md_final(hd);
tmp = gcry_md_read(hd,algo);
lua_pushlstring(L,(char*)tmp,gcry_md_get_algo_dlen(algo));
gcry_md_close(hd);
#endif
return 1;
}
static const char *hex = "0123456789abcdef";
static int lbin2hex(lua_State* L){
const char *data;
size_t len;
size_t i,o;
char * enc;
data = luaL_checklstring(L,1,&len);
enc = calloc(len*2+1,sizeof(char));
if (enc == NULL)
L_error(L,"Out of memory");
enc[len*2] = '\0';
for(i = 0, o = 0 ; i < len ; i++, o+=2) {
char cur = data[i];
unsigned up,down;
up = (cur & 0xF0) >> 4;
down = cur & 0x0F;
enc[o] = hex[up];
enc[o+1] = hex[down];
}
lua_pushstring(L,enc);
free(enc);
return 1;
}
static int my_free(lua_State* L){/* nothing to do */ return 0;}
static const struct luaL_reg crypto_t [] = {
{"md5",lmd5},
{"hmac",lhmac},
{"bin2hex",lbin2hex},
{NULL,NULL}
};
#if CRYPTO_IMPLEMENTATION == CRYPTO_GCRYPT
static int algno_of_GCRY_MD_NONE() { return GCRY_MD_NONE;}
static int algno_of_GCRY_MD_MD2() { return GCRY_MD_MD2;}
static int algno_of_GCRY_MD_MD4() { return GCRY_MD_MD4;}
static int algno_of_GCRY_MD_MD5() { return GCRY_MD_MD5;}
static int algno_of_GCRY_MD_SHA1() { return GCRY_MD_SHA1;}
static int algno_of_GCRY_MD_SHA256() { return GCRY_MD_SHA256;}
static int algno_of_GCRY_MD_SHA384() { return GCRY_MD_SHA384;}
static int algno_of_GCRY_MD_SHA512() { return GCRY_MD_SHA512;}
static int algno_of_GCRY_MD_RMD160() { return GCRY_MD_RMD160;}
#endif
static const struct L_Tuserdata crypto_ALGO [] = {
// ======= NULL ====
#if CRYPTO_IMPLEMENTATION == CRYPTO_OPENSSL
{"ALGO_md_null",EVP_md_null},
#elif CRYPTO_IMPLEMENTATION == CRYPTO_GCRYPT
{"ALGO_md_null", algno_of_GCRY_MD_NONE},
#endif
// ====== MD* =====
#if CRYPTO_IMPLEMENTATION == CRYPTO_OPENSSL
#ifndef OPENSSL_NO_MD2
{"ALGO_md2",EVP_md2},
#endif
#ifndef OPENSSL_NO_MD4
{"ALGO_md4",EVP_md4},
#endif
#ifndef OPENSSL_NO_MD5
{"ALGO_md5",EVP_md5},
#endif
#elif CRYPTO_IMPLEMENTATION == CRYPTO_GCRYPT
{"ALGO_md2", algno_of_GCRY_MD_MD2},
{"ALGO_md4", algno_of_GCRY_MD_MD4},
{"ALGO_md5", algno_of_GCRY_MD_MD5},
#endif
// ====== SHA* =====
#if CRYPTO_IMPLEMENTATION == CRYPTO_OPENSSL
#ifndef OPENSSL_NO_SHA
{"ALGO_sha",EVP_sha},
{"ALGO_sha1",EVP_sha1},
{"ALGO_dss",EVP_dss},
{"ALGO_dss1",EVP_dss1},
#endif
#elif CRYPTO_IMPLEMENTATION == CRYPTO_GCRYPT
{"ALGO_sha1", algno_of_GCRY_MD_SHA1},
{"ALGO_sha256", algno_of_GCRY_MD_SHA256},
{"ALGO_sha384", algno_of_GCRY_MD_SHA384},
{"ALGO_sha512", algno_of_GCRY_MD_SHA512},
#endif
// ====== MDC2 & RIPE160 =====
#if CRYPTO_IMPLEMENTATION == CRYPTO_OPENSSL
#if defined(HEADER_MDC2_H)
#ifndef OPENSSL_NO_MDC2
{"ALGO_mdc2",EVP_mdc2},
#endif
#endif
#ifndef OPENSSL_NO_RIPEMD
{"ALGO_ripemd160",EVP_ripemd160},
#endif
#elif CRYPTO_IMPLEMENTATION == CRYPTO_GCRYPT
{"ALGO_ripemd160", algno_of_GCRY_MD_RMD160},
#endif
{NULL,NULL}
};
int luaopen_crypto(lua_State* L){
luaL_newmetatable(L,CRYPTO_ALGO_MD);
lua_pushstring(L,"__gc");
lua_pushcfunction(L,my_free);
lua_settable(L,-3);
luaL_openlib(L,"crypto",crypto_t,0);
L_openTconst(L,crypto_ALGO,CRYPTO_ALGO_MD);
return 2;
}
syntax highlighted by Code2HTML, v. 0.9.1