1%% -*- mode: erlang; tab-width: 4; indent-tabs-mode: 1; st-rulers: [70] -*-
2%% vim: ts=4 sw=4 ft=erlang noet
3%%%-------------------------------------------------------------------
4%%% @author Andrew Bennett <potatosaladx@gmail.com>
5%%% @copyright 2014-2019, Andrew Bennett
6%%% @doc XChaCha: eXtended-nonce ChaCha and AEAD_XChaCha20_Poly1305
7%%% See https://tools.ietf.org/html/draft-irtf-cfrg-xchacha
8%%% @end
9%%% Created :  14 Sep 2019 by Andrew Bennett <potatosaladx@gmail.com>
10%%%-------------------------------------------------------------------
11-module(jose_jwa_hchacha20).
12
13%% API
14-export([hash/2]).
15
16%%====================================================================
17%% API functions
18%%====================================================================
19
20hash(Key, Nonce)
21		when is_binary(Key)
22		andalso bit_size(Key) =:= 256
23		andalso is_binary(Nonce)
24		andalso bit_size(Nonce) =:= 128 ->
25	State = <<
26		"expand 32-byte k",
27		Key:256/bitstring,
28		Nonce:128/bitstring
29	>>,
30	WS0 = list_to_tuple([Word || << Word:32/unsigned-little-integer-unit:1 >> <= State]),
31	WS1 = rounds(WS0, 10),
32	serialize(WS1).
33
34%%%-------------------------------------------------------------------
35%%% Internal functions
36%%%-------------------------------------------------------------------
37
38%% @private
39inner_block(State0)
40		when is_tuple(State0)
41		andalso tuple_size(State0) =:= 16 ->
42	State1 = jose_jwa_chacha20:column_round(State0),
43	State2 = jose_jwa_chacha20:diagonal_round(State1),
44	State2.
45
46%% @private
47rounds(S, 0) ->
48	S;
49rounds(S, N)
50		when is_integer(N)
51		andalso N > 0 ->
52	rounds(inner_block(S), N - 1).
53
54%% @private
55serialize({Z00, Z01, Z02, Z03, _Z04, _Z05, _Z06, _Z07, _Z08, _Z09, _Z10, _Z11, Z12, Z13, Z14, Z15}) ->
56	<<
57		Z00:32/unsigned-little-integer-unit:1,
58		Z01:32/unsigned-little-integer-unit:1,
59		Z02:32/unsigned-little-integer-unit:1,
60		Z03:32/unsigned-little-integer-unit:1,
61		Z12:32/unsigned-little-integer-unit:1,
62		Z13:32/unsigned-little-integer-unit:1,
63		Z14:32/unsigned-little-integer-unit:1,
64		Z15:32/unsigned-little-integer-unit:1
65	>>.
66