2 * nixio - Linux I/O library for lua
4 * Copyright (C) 2009 Steven Barth <steven@midlink.org>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 #include "nixio-tls.h"
25 static char nixio__bin2hex[] = {
26 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
29 static int nixio_crypto_hash__init(lua_State *L, int hmac) {
30 const char *type = luaL_checkstring(L, 1);
31 nixio_hash *hash = lua_newuserdata(L, sizeof(nixio_hash));
33 if (!strcmp(type, "md5")) {
34 hash->type = NIXIO_HASH_MD5;
35 hash->digest_size = MD5_DIGEST_LENGTH;
36 hash->block_size = 64;
37 hash->ctx = malloc(sizeof(MD5_CTX));
39 return luaL_error(L, NIXIO_OOM);
41 MD5_Init((MD5_CTX*)hash->ctx);
42 hash->init = (nixio_hash_initcb)MD5_Init;
43 hash->update = (nixio_hash_updatecb)MD5_Update;
44 hash->final = (nixio_hash_finalcb)MD5_Final;
45 } else if (!strcmp(type, "sha1")) {
46 hash->type = NIXIO_HASH_SHA1;
47 hash->digest_size = SHA_DIGEST_LENGTH;
48 hash->block_size = 64;
49 hash->ctx = malloc(sizeof(SHA_CTX));
51 return luaL_error(L, NIXIO_OOM);
53 SHA1_Init((SHA_CTX*)hash->ctx);
54 hash->init = (nixio_hash_initcb)SHA1_Init;
55 hash->update = (nixio_hash_updatecb)SHA1_Update;
56 hash->final = (nixio_hash_finalcb)SHA1_Final;
58 luaL_argerror(L, 1, "supported values: md5, sha1");
61 luaL_getmetatable(L, NIXIO_CRYPTO_HASH_META);
62 lua_setmetatable(L, -2);
65 const char *key = luaL_checklstring(L, 2, &hash->key_size);
66 if (hash->key_size > hash->block_size) {
67 hash->update(hash->ctx, key, hash->key_size);
68 hash->final(hash->digest, hash->ctx);
69 hash->init(hash->ctx);
70 hash->key_size = hash->digest_size;
71 memcpy(hash->key, hash->digest, hash->key_size);
73 memcpy(hash->key, key, hash->key_size);
76 unsigned char pad[NIXIO_CRYPTO_BLOCK_SIZE];
77 for (uint i = 0; i < hash->block_size; i++) {
78 pad[i] = (i < hash->key_size) ? (0x36 ^ hash->key[i]) : 0x36;
80 hash->update(hash->ctx, pad, hash->block_size);
81 hash->type |= NIXIO_HMAC_BIT;
87 static int nixio_crypto_hash(lua_State *L) {
88 return nixio_crypto_hash__init(L, 0);
91 static int nixio_crypto_hmac(lua_State *L) {
92 return nixio_crypto_hash__init(L, 1);
95 static int nixio_crypto_hash_update(lua_State *L) {
96 nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
99 const char *chunk = luaL_checklstring(L, 2, &len);
100 hash->update(hash->ctx, chunk, len);
104 return luaL_error(L, "Tried to update finalized hash object.");
108 static int nixio_crypto_hash_final(lua_State *L) {
109 nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
110 if (hash->type & NIXIO_HMAC_BIT) {
111 hash->final(hash->digest, hash->ctx);
112 hash->init(hash->ctx);
114 unsigned char pad[NIXIO_CRYPTO_BLOCK_SIZE];
115 for (uint i = 0; i < hash->block_size; i++) {
116 pad[i] = (i < hash->key_size) ? (0x5c ^ hash->key[i]) : 0x5c;
119 hash->update(hash->ctx, pad, hash->block_size);
120 hash->update(hash->ctx, hash->digest, hash->digest_size);
124 hash->type = NIXIO_HASH_NONE;
125 hash->final(hash->digest, hash->ctx);
129 char hashdigest[NIXIO_DIGEST_SIZE*2];
130 for (uint i=0; i < hash->digest_size; i++) {
131 hashdigest[2*i] = nixio__bin2hex[(hash->digest[i] & 0xf0) >> 4];
132 hashdigest[2*i+1] = nixio__bin2hex[(hash->digest[i] & 0x0f)];
135 lua_pushlstring(L, hashdigest, hash->digest_size * 2);
136 memcpy(hashdigest, hash->digest, hash->digest_size);
137 lua_pushlstring(L, hashdigest, hash->digest_size);
142 static int nixio_crypto_hash__gc(lua_State *L) {
143 nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
145 hash->final(hash->digest, hash->ctx);
147 hash->type = NIXIO_HASH_NONE;
152 static int nixio_crypto_hash__tostring(lua_State *L) {
153 nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
154 lua_pushfstring(L, "nixio hash object: %p", hash);
160 static const luaL_reg R[] = {
161 {"hash", nixio_crypto_hash},
162 {"hmac", nixio_crypto_hmac},
167 static const luaL_reg M[] = {
168 {"update", nixio_crypto_hash_update},
169 {"final", nixio_crypto_hash_final},
170 {"__gc", nixio_crypto_hash__gc},
171 {"__tostring", nixio_crypto_hash__tostring},
177 void nixio_open_tls_crypto(lua_State *L) {
178 luaL_newmetatable(L, NIXIO_CRYPTO_HASH_META);
179 luaL_register(L, NULL, M);
180 lua_pushvalue(L, -1);
181 lua_setfield(L, -2, "__index");
185 luaL_register(L, NULL, R);
187 lua_setfield(L, -2, "crypto");