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"
26 static int nixio_crypto_hash__init(lua_State *L, int hmac) {
27 const char *type = luaL_checkstring(L, 1);
28 nixio_hash *hash = lua_newuserdata(L, sizeof(nixio_hash));
30 if (!strcmp(type, "md5")) {
31 hash->type = NIXIO_HASH_MD5;
32 hash->digest_size = MD5_DIGEST_LENGTH;
33 hash->block_size = 64;
34 hash->ctx = malloc(sizeof(MD5_CTX));
36 return luaL_error(L, NIXIO_OOM);
38 MD5_Init((MD5_CTX*)hash->ctx);
39 hash->init = (nixio_hash_initcb)MD5_Init;
40 hash->update = (nixio_hash_updatecb)MD5_Update;
41 hash->final = (nixio_hash_finalcb)MD5_Final;
42 } else if (!strcmp(type, "sha1")) {
43 hash->type = NIXIO_HASH_SHA1;
44 hash->digest_size = SHA_DIGEST_LENGTH;
45 hash->block_size = 64;
46 hash->ctx = malloc(sizeof(SHA_CTX));
48 return luaL_error(L, NIXIO_OOM);
50 SHA1_Init((SHA_CTX*)hash->ctx);
51 hash->init = (nixio_hash_initcb)SHA1_Init;
52 hash->update = (nixio_hash_updatecb)SHA1_Update;
53 hash->final = (nixio_hash_finalcb)SHA1_Final;
55 luaL_argerror(L, 1, "supported values: md5, sha1");
58 luaL_getmetatable(L, NIXIO_CRYPTO_HASH_META);
59 lua_setmetatable(L, -2);
62 const char *key = luaL_checklstring(L, 2, &hash->key_size);
63 if (hash->key_size > hash->block_size) {
64 hash->update(hash->ctx, key, hash->key_size);
65 hash->final(hash->digest, hash->ctx);
66 hash->init(hash->ctx);
67 hash->key_size = hash->digest_size;
68 memcpy(hash->key, hash->digest, hash->key_size);
70 memcpy(hash->key, key, hash->key_size);
73 unsigned char pad[NIXIO_CRYPTO_BLOCK_SIZE];
74 for (uint i = 0; i < hash->block_size; i++) {
75 pad[i] = (i < hash->key_size) ? (0x36 ^ hash->key[i]) : 0x36;
77 hash->update(hash->ctx, pad, hash->block_size);
78 hash->type |= NIXIO_HMAC_BIT;
84 static int nixio_crypto_hash(lua_State *L) {
85 return nixio_crypto_hash__init(L, 0);
88 static int nixio_crypto_hmac(lua_State *L) {
89 return nixio_crypto_hash__init(L, 1);
92 static int nixio_crypto_hash_update(lua_State *L) {
93 nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
96 const char *chunk = luaL_checklstring(L, 2, &len);
97 hash->update(hash->ctx, chunk, len);
101 return luaL_error(L, "Tried to update finalized hash object.");
105 static int nixio_crypto_hash_final(lua_State *L) {
106 nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
107 if (hash->type & NIXIO_HMAC_BIT) {
108 hash->final(hash->digest, hash->ctx);
109 hash->init(hash->ctx);
111 unsigned char pad[NIXIO_CRYPTO_BLOCK_SIZE];
112 for (uint i = 0; i < hash->block_size; i++) {
113 pad[i] = (i < hash->key_size) ? (0x5c ^ hash->key[i]) : 0x5c;
116 hash->update(hash->ctx, pad, hash->block_size);
117 hash->update(hash->ctx, hash->digest, hash->digest_size);
121 hash->type = NIXIO_HASH_NONE;
122 hash->final(hash->digest, hash->ctx);
126 char hashdigest[NIXIO_DIGEST_SIZE*2];
127 for (uint i=0; i < hash->digest_size; i++) {
128 hashdigest[2*i] = nixio__bin2hex[(hash->digest[i] & 0xf0) >> 4];
129 hashdigest[2*i+1] = nixio__bin2hex[(hash->digest[i] & 0x0f)];
132 lua_pushlstring(L, hashdigest, hash->digest_size * 2);
133 memcpy(hashdigest, hash->digest, hash->digest_size);
134 lua_pushlstring(L, hashdigest, hash->digest_size);
139 static int nixio_crypto_hash__gc(lua_State *L) {
140 nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
142 hash->final(hash->digest, hash->ctx);
144 hash->type = NIXIO_HASH_NONE;
149 static int nixio_crypto_hash__tostring(lua_State *L) {
150 nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
151 lua_pushfstring(L, "nixio hash object: %p", hash);
157 static const luaL_reg R[] = {
158 {"hash", nixio_crypto_hash},
159 {"hmac", nixio_crypto_hmac},
164 static const luaL_reg M[] = {
165 {"update", nixio_crypto_hash_update},
166 {"final", nixio_crypto_hash_final},
167 {"__gc", nixio_crypto_hash__gc},
168 {"__tostring", nixio_crypto_hash__tostring},
174 void nixio_open_tls_crypto(lua_State *L) {
175 luaL_newmetatable(L, NIXIO_CRYPTO_HASH_META);
176 luaL_register(L, NULL, M);
177 lua_pushvalue(L, -1);
178 lua_setfield(L, -2, "__index");
182 luaL_register(L, NULL, R);
184 lua_setfield(L, -2, "crypto");