hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

hmac_drbg.ha (2526B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use bytes;
      5 use crypto::hmac;
      6 use crypto::mac;
      7 use crypto::sha1;
      8 use hash;
      9 
     10 // Partial HMAC_DRBG implementation as describe in RFC6979 Section 3.1.1
     11 
     12 type drbg = struct {
     13 	h: *hash::hash,
     14 	k: []u8,
     15 	v: []u8,
     16 	initgen: bool,
     17 	buf: []u8,
     18 };
     19 
     20 // 'buf' must be at least 2 * hash::sz(h) + hash::bsz(h)
     21 fn hmac_drbg(h: *hash::hash, seed: const []u8, buf: []u8) drbg = {
     22 	const hlen = hash::sz(h);
     23 	assert(len(buf) >= 2 * hlen + hash::bsz(h));
     24 
     25 	let s = drbg {
     26 		h = h,
     27 		k = buf[..hlen],
     28 		v = buf[hlen..2*hlen],
     29 		initgen = true,
     30 		buf = buf[2*hlen..],
     31 	};
     32 
     33 	s.k[..] = [0...];
     34 	s.v[..] = [1...];
     35 
     36 	hash::reset(h);
     37 	let hm = hmac::hmac(h, s.k, s.buf);
     38 	mac::write(&hm, s.v);
     39 	mac::write(&hm, [0x00]);
     40 	mac::write(&hm, seed);
     41 	mac::sum(&hm, s.k);
     42 
     43 	hmac_drbg_update(&s);
     44 
     45 	hash::reset(h);
     46 	let hm = hmac::hmac(h, s.k, s.buf);
     47 	mac::write(&hm, s.v);
     48 	mac::write(&hm, [0x01]);
     49 	mac::write(&hm, seed);
     50 	mac::sum(&hm, s.k);
     51 
     52 	hmac_drbg_update(&s);
     53 
     54 	return s;
     55 };
     56 
     57 fn hmac_drbg_update(s: *drbg) void = {
     58 	hash::reset(s.h);
     59 	let hm = hmac::hmac(s.h, s.k, s.buf);
     60 	mac::write(&hm, s.v);
     61 	mac::sum(&hm, s.v);
     62 };
     63 
     64 fn hmac_drbg_generate(s: *drbg, dest: []u8) void = {
     65 	if (!s.initgen) {
     66 		hash::reset(s.h);
     67 		let hm = hmac::hmac(s.h, s.k, s.buf);
     68 		mac::write(&hm, s.v);
     69 		mac::write(&hm, [0x00]);
     70 		mac::sum(&hm, s.k);
     71 
     72 		hmac_drbg_update(s);
     73 	};
     74 	s.initgen = false;
     75 
     76 	let n = 0z;
     77 	for (n < len(dest)) {
     78 		hmac_drbg_update(s);
     79 
     80 		const remain = len(dest) - n;
     81 		let max = if (remain > len(s.v)) len(s.v) else remain;
     82 
     83 		dest[n..n+max] = s.v[..max];
     84 		n += max;
     85 	};
     86 };
     87 
     88 @test fn hmac_drbg() void = {
     89 	const seed: [_]u8 = [
     90 		0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57,
     91 		0x86, 0x66, 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a,
     92 		0xbf, 0x8c, 0x35, 0xc8,
     93 	];
     94 
     95 	let h = sha1::sha1();
     96 	let buf: [sha1::SZ * 2 + sha1::BLOCKSZ]u8 = [0...];
     97 	let s = hmac_drbg(&h, seed, buf);
     98 
     99 	let dest: [30]u8 = [0...];
    100 	hmac_drbg_generate(&s, dest);
    101 	const expect: [_]u8 = [
    102 		0x4e, 0xea, 0xad, 0x22, 0xb1, 0xbc, 0x51, 0x9e, 0xe6, 0xaa,
    103 		0x5a, 0x56, 0xd7, 0xab, 0x29, 0xc3, 0x39, 0xc4, 0xea, 0x10,
    104 		0x11, 0x2e, 0xe5, 0x4e, 0x2a, 0x6f, 0x81, 0xcd, 0x19, 0x7a,
    105 	];
    106 	assert(bytes::equal(expect, dest));
    107 
    108 	const expect: [_]u8 = [
    109 		0xe2, 0x1f, 0x3a, 0x90, 0x38, 0xc4, 0xc6, 0xe1, 0xa5, 0x0c,
    110 		0x72, 0x6c, 0x04, 0x90, 0xe0, 0x6a, 0xa3, 0xcb, 0x8c, 0xce,
    111 		0xd2, 0x89, 0x1d, 0x01, 0xf3,
    112 	];
    113 	hmac_drbg_generate(&s, dest);
    114 	assert(bytes::equal(expect, dest[..25]));
    115 };