-
Notifications
You must be signed in to change notification settings - Fork 0
/
sha3_384.hpp
96 lines (85 loc) · 3.45 KB
/
sha3_384.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#pragma once
#include "sha3.hpp"
namespace sha3_384 {
// SHA3-384 specific input/ output width constants, taken from
// table 4's in section A.1 of http://dx.doi.org/10.6028/NIST.FIPS.202
constexpr size_t IN_LEN_BITS = 768;
constexpr size_t IN_LEN_BYTES = IN_LEN_BITS >> 3;
constexpr size_t OUT_LEN_BITS = IN_LEN_BITS >> 1;
constexpr size_t OUT_LEN_BYTES = IN_LEN_BYTES >> 1;
// From input byte array ( = 96 bytes ) preparing 5 x 5 x 64 keccak state array
// as twenty five 64 -bit unsigned integers
//
// Combined techniques adapted from section 3.1.2 of
// http://dx.doi.org/10.6028/NIST.FIPS.202; algorithm 10
// defined in section B.1 of above linked document
void
to_state_array(const sycl::uchar* __restrict in,
sycl::ulong* const __restrict state)
{
#pragma unroll 6
for (size_t i = 0; i < (IN_LEN_BYTES >> 3); i++) {
state[i] = static_cast<sycl::ulong>(in[(i << 3) + 7]) << 56 |
static_cast<sycl::ulong>(in[(i << 3) + 6]) << 48 |
static_cast<sycl::ulong>(in[(i << 3) + 5]) << 40 |
static_cast<sycl::ulong>(in[(i << 3) + 4]) << 32 |
static_cast<sycl::ulong>(in[(i << 3) + 3]) << 24 |
static_cast<sycl::ulong>(in[(i << 3) + 2]) << 16 |
static_cast<sycl::ulong>(in[(i << 3) + 1]) << 8 |
static_cast<sycl::ulong>(in[(i << 3) + 0]) << 0;
}
// see how 0b01 is appended to input message bits in section
// 6.1 of http://dx.doi.org/10.6028/NIST.FIPS.202
//
// also see padding requirement ( pad10*1 ) written in section 5.1 of
// http://dx.doi.org/10.6028/NIST.FIPS.202
//
// ! read right to left !
//
// = 0b1000000000000000000000000000000000000000000000000000000000000110
state[12] = 9223372036854775814ull;
#pragma unroll 6
for (size_t i = 13; i < 25; i++) {
state[i] = 0ull;
}
}
// From absorbed hash state array of dimension 5 x 5 x 64, produces 48 -bytes
// digest using method defined in section 3.1.3 of
// http://dx.doi.org/10.6028/NIST.FIPS.202 and algorithm 11 defined in section
// B.1 of above hyperlinked document
void
to_digest_bytes(const sycl::ulong* __restrict in,
sycl::uchar* const __restrict digest)
{
#pragma unroll 3
for (size_t i = 0; i < 6; i++) {
const sycl::ulong lane = in[i];
digest[(i << 3) + 0] = static_cast<sycl::uchar>((lane >> 0) & 0xffull);
digest[(i << 3) + 1] = static_cast<sycl::uchar>((lane >> 8) & 0xffull);
digest[(i << 3) + 2] = static_cast<sycl::uchar>((lane >> 16) & 0xffull);
digest[(i << 3) + 3] = static_cast<sycl::uchar>((lane >> 24) & 0xffull);
digest[(i << 3) + 4] = static_cast<sycl::uchar>((lane >> 32) & 0xffull);
digest[(i << 3) + 5] = static_cast<sycl::uchar>((lane >> 40) & 0xffull);
digest[(i << 3) + 6] = static_cast<sycl::uchar>((lane >> 48) & 0xffull);
digest[(i << 3) + 7] = static_cast<sycl::uchar>((lane >> 56) & 0xffull);
}
}
// SHA3-384 2-to-1 hasher, where input is 96 contiguous bytes which is hashed
// to produce 48 -bytes output
//
// This function itself doesn't do much instead of calling other functions
// which actually
// - prepares state bit array from input byte array
// - permutes input using `keccak-p[b, n_r]`
// - truncates first 224 -bits from state bit array
//
// See section 6.1 of http://dx.doi.org/10.6028/NIST.FIPS.202
void
hash(const sycl::uchar* __restrict in, sycl::uchar* const __restrict digest)
{
sycl::ulong state[25];
to_state_array(in, state);
keccak_p(state);
to_digest_bytes(state, digest);
}
}