xchacha20_pl/chacha20_prim.pl

33 lines
1.0 KiB
Prolog

:- module(chacha20_prim, [chacha20_prim_u32/2]).
chacha20_prim_u32(B0, B1) :-
assertion(is_chacha20_block(B0)),
chacha(10, B0, B1).
chacha(0, D, D).
chacha(N1) --> {N1 > 0, succ(N0, N1)}, round, chacha(N0).
round -->
qround([0, 4, 8, 12]), qround([1, 5, 9, 13]),
qround([2, 6, 10, 14]), qround([3, 7, 11, 15]),
qround([0, 5, 10, 15]), qround([1, 6, 11, 12]),
qround([2, 7, 8, 13]), qround([3, 4, 9, 14]).
qround([A, B, C, D]) -->
at([A, B], qadd), at([D, A], qxor), at([D], rot_l32(16)),
at([C, D], qadd), at([B, C], qxor), at([B], rot_l32(12)),
at([A, B], qadd), at([D, A], qxor), at([D], rot_l32(8)),
at([C, D], qadd), at([B, C], qxor), at([B], rot_l32(7)).
at([IxA], Pred, L0, LN) :-
nth0(IxA, L0, A0, LRem),
call(Pred, A0, A1), trunc_32(A1, A2),
nth0(IxA, LN, A2, LRem), !.
at([IxA, IxB], Pred, L0, LN) :-
nth0(IxB, L0, B),
at([IxA], call(Pred, B), L0, LN).
qadd(B, A0, A1) :- A1 is A0 + B.
qxor(B, A0, A1) :- A1 is A0 xor B.
rot_l32(Amt, A0, A1) :- A1 is (A0 << Amt) \/ (A0 >> (32 - Amt)).