Software /
code /
prosody
Comparison
util-src/hashes.c @ 12836:dbe9781fd278
util.hashes: Add HKDF-HMAC-SHA256/HKDF-HMAC-SHA384
These are needed for PASETO v3.local.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Fri, 13 Jan 2023 14:29:08 +0000 |
parent | 12575:1f6f05a98fcd |
child | 12844:a3ec87ad8e48 |
comparison
equal
deleted
inserted
replaced
12835:6a97d448cb1e | 12836:dbe9781fd278 |
---|---|
26 #include <openssl/crypto.h> | 26 #include <openssl/crypto.h> |
27 #include <openssl/sha.h> | 27 #include <openssl/sha.h> |
28 #include <openssl/md5.h> | 28 #include <openssl/md5.h> |
29 #include <openssl/hmac.h> | 29 #include <openssl/hmac.h> |
30 #include <openssl/evp.h> | 30 #include <openssl/evp.h> |
31 #include <openssl/kdf.h> | |
31 #include <openssl/err.h> | 32 #include <openssl/err.h> |
32 | 33 |
34 | |
35 /* Semi-arbitrary limit here. The actual theoretical limit | |
36 * is (255*(hash output octets)), but allocating 16KB on the | |
37 * stack when in practice we only ever request a few dozen | |
38 * bytes seems excessive. | |
39 */ | |
40 #define MAX_HKDF_OUTPUT 256 | |
33 | 41 |
34 static const char *hex_tab = "0123456789abcdef"; | 42 static const char *hex_tab = "0123456789abcdef"; |
35 static void toHex(const unsigned char *in, int length, unsigned char *out) { | 43 static void toHex(const unsigned char *in, int length, unsigned char *out) { |
36 int i; | 44 int i; |
37 | 45 |
210 return Levp_pbkdf2(L, EVP_sha1(), SHA_DIGEST_LENGTH); | 218 return Levp_pbkdf2(L, EVP_sha1(), SHA_DIGEST_LENGTH); |
211 } | 219 } |
212 | 220 |
213 static int Lpbkdf2_sha256(lua_State *L) { | 221 static int Lpbkdf2_sha256(lua_State *L) { |
214 return Levp_pbkdf2(L, EVP_sha256(), SHA256_DIGEST_LENGTH); | 222 return Levp_pbkdf2(L, EVP_sha256(), SHA256_DIGEST_LENGTH); |
223 } | |
224 | |
225 | |
226 /* HKDF(length, input, salt, info) */ | |
227 static int Levp_hkdf(lua_State *L, const EVP_MD *evp) { | |
228 unsigned char out[MAX_HKDF_OUTPUT]; | |
229 | |
230 size_t input_len, salt_len, info_len; | |
231 size_t actual_out_len = luaL_checkinteger(L, 1); | |
232 const char *input = luaL_checklstring(L, 2, &input_len); | |
233 const unsigned char *salt = (unsigned char *)luaL_optlstring(L, 3, NULL, &salt_len); | |
234 const unsigned char *info = (unsigned char *)luaL_checklstring(L, 4, &info_len); | |
235 | |
236 if(actual_out_len > MAX_HKDF_OUTPUT) | |
237 return luaL_error(L, "desired output length %ul exceeds internal limit %ul", actual_out_len, MAX_HKDF_OUTPUT); | |
238 | |
239 EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); | |
240 | |
241 if (EVP_PKEY_derive_init(pctx) <= 0) | |
242 return luaL_error(L, ERR_error_string(ERR_get_error(), NULL)); | |
243 | |
244 if (EVP_PKEY_CTX_set_hkdf_md(pctx, evp) <= 0) | |
245 return luaL_error(L, ERR_error_string(ERR_get_error(), NULL)); | |
246 | |
247 if(salt != NULL) { | |
248 if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, salt_len) <= 0) | |
249 return luaL_error(L, ERR_error_string(ERR_get_error(), NULL)); | |
250 } | |
251 | |
252 if (EVP_PKEY_CTX_set1_hkdf_key(pctx, input, input_len) <= 0) | |
253 return luaL_error(L, ERR_error_string(ERR_get_error(), NULL)); | |
254 | |
255 if (EVP_PKEY_CTX_add1_hkdf_info(pctx, info, info_len) <= 0) | |
256 return luaL_error(L, ERR_error_string(ERR_get_error(), NULL)); | |
257 | |
258 if (EVP_PKEY_derive(pctx, out, &actual_out_len) <= 0) | |
259 return luaL_error(L, ERR_error_string(ERR_get_error(), NULL)); | |
260 | |
261 lua_pushlstring(L, (char *)out, actual_out_len); | |
262 | |
263 return 1; | |
264 } | |
265 | |
266 static int Lhkdf_sha256(lua_State *L) { | |
267 return Levp_hkdf(L, EVP_sha256()); | |
268 } | |
269 | |
270 static int Lhkdf_sha384(lua_State *L) { | |
271 return Levp_hkdf(L, EVP_sha384()); | |
215 } | 272 } |
216 | 273 |
217 static int Lhash_equals(lua_State *L) { | 274 static int Lhash_equals(lua_State *L) { |
218 size_t len1, len2; | 275 size_t len1, len2; |
219 const char *s1 = luaL_checklstring(L, 1, &len1); | 276 const char *s1 = luaL_checklstring(L, 1, &len1); |
248 { "hmac_blake2s256", Lhmac_blake2s256 }, | 305 { "hmac_blake2s256", Lhmac_blake2s256 }, |
249 { "hmac_blake2b512", Lhmac_blake2b512 }, | 306 { "hmac_blake2b512", Lhmac_blake2b512 }, |
250 { "scram_Hi_sha1", Lpbkdf2_sha1 }, /* COMPAT */ | 307 { "scram_Hi_sha1", Lpbkdf2_sha1 }, /* COMPAT */ |
251 { "pbkdf2_hmac_sha1", Lpbkdf2_sha1 }, | 308 { "pbkdf2_hmac_sha1", Lpbkdf2_sha1 }, |
252 { "pbkdf2_hmac_sha256", Lpbkdf2_sha256 }, | 309 { "pbkdf2_hmac_sha256", Lpbkdf2_sha256 }, |
310 { "hkdf_hmac_sha256", Lhkdf_sha256 }, | |
311 { "hkdf_hmac_sha384", Lhkdf_sha384 }, | |
253 { "equals", Lhash_equals }, | 312 { "equals", Lhash_equals }, |
254 { NULL, NULL } | 313 { NULL, NULL } |
255 }; | 314 }; |
256 | 315 |
257 LUALIB_API int luaopen_util_hashes(lua_State *L) { | 316 LUALIB_API int luaopen_util_hashes(lua_State *L) { |