Added generic PBKDF2 implementation.

This commit is contained in:
Christoffer Lerno
2024-09-30 00:07:49 +02:00
parent 071bd0ebf2
commit c8018c5543
6 changed files with 92 additions and 1 deletions

View File

@@ -281,6 +281,11 @@ fn bool ptr_is_aligned(void* ptr, usz alignment) @inline
return (uptr)ptr & ((uptr)alignment - 1) == 0;
}
macro void zero_volatile(char[] data)
{
$$memset(data.ptr, (char)0, data.len, true, (usz)1);
}
macro void clear(void* dst, usz len, usz $dst_align = 0, bool $is_volatile = false, bool $inlined = false)
{
$$memset(dst, (char)0, len, $is_volatile, $dst_align);

View File

@@ -1,4 +1,5 @@
module std::hash::hmac(<HashAlg, HASH_BYTES, BLOCK_BYTES>);
import std::crypto;
struct Hmac
{
@@ -13,6 +14,34 @@ fn char[HASH_BYTES] hash(char[] key, char[] message)
return hmac.final();
}
/**
* @require output.len > 0 "Output must be greater than zero"
* @require output.len < int.max / HASH_BYTES "Output is too large"
**/
fn void pbkdf2(char[] pw, char[] salt, uint iterations, char[] output)
{
usz l = output.len / HASH_BYTES;
usz r = output.len % HASH_BYTES;
Hmac hmac;
hmac.init(pw);
char[] dst_curr = output;
for (usz i = 1; i <= l; i++)
{
@derive(&hmac, salt, iterations, i, dst_curr[:HASH_BYTES]);
dst_curr = dst_curr[HASH_BYTES..];
}
if (r > 0)
{
char[HASH_BYTES] tmp;
@derive(&hmac, salt, iterations, l + 1, &tmp);
dst_curr[..] = tmp[:dst_curr.len];
mem::zero_volatile(&tmp);
}
}
fn void Hmac.init(&self, char[] key)
{
char[BLOCK_BYTES] buffer;
@@ -37,7 +66,7 @@ fn void Hmac.init(&self, char[] key)
self.b.init();
self.b.update(&buffer);
buffer = {};
mem::zero_volatile(&buffer);
}
fn void Hmac.update(&self, char[] data)
@@ -53,3 +82,26 @@ fn char[HASH_BYTES] Hmac.final(&self)
const IPAD @private = 0x36;
const OPAD @private = 0x5C;
macro @derive(Hmac *hmac_start, char[] salt, uint iterations, usz index, char[] out)
{
assert(out.len == HASH_BYTES);
char[HASH_BYTES] tmp @noinit;
defer mem::zero_volatile(&tmp);
Hmac hmac = *hmac_start;
hmac.update(salt);
UIntBE be = { (uint)index };
hmac.update(&&bitcast(be, char[4]));
tmp = hmac.final();
out[..] = tmp;
for (int it = 1; it < iterations; it++)
{
hmac = *hmac_start;
hmac.update(&tmp);
tmp = hmac.final();
foreach (i, v : tmp)
{
out[i] ^= v;
}
}
}

View File

@@ -15,6 +15,7 @@ struct Md5
def HmacMd5 = Hmac(<Md5, HASH_BYTES, BLOCK_BYTES>);
def hmac = hmac::hash(<Md5, HASH_BYTES, BLOCK_BYTES>);
def pbkdf2 = hmac::pbkdf2(<Md5, HASH_BYTES, BLOCK_BYTES>);
fn char[HASH_BYTES] hash(char[] data)
{

View File

@@ -20,6 +20,7 @@ struct Sha1
def HmacSha1 = Hmac(<Sha1, HASH_BYTES, BLOCK_BYTES>);
def hmac = hmac::hash(<Sha1, HASH_BYTES, BLOCK_BYTES>);
def pbkdf2 = hmac::pbkdf2(<Sha1, HASH_BYTES, BLOCK_BYTES>);
fn char[HASH_BYTES] hash(char[] data)
{