Skip to content

Commit adaddb9

Browse files
authored
Merge pull request #4133 from akyrtzi/stable-cherry-blake3
[stable/20211026] Cherry-pick the `BLAKE3` hashing function implementation
2 parents 1da24da + 1276d75 commit adaddb9

30 files changed

+31836
-0
lines changed

llvm/include/llvm-c/blake3.h

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*===-- llvm-c/blake3.h - BLAKE3 C Interface ----------------------*- C -*-===*\
2+
|* *|
3+
|* Released into the public domain with CC0 1.0 *|
4+
|* See 'llvm/lib/Support/BLAKE3/LICENSE' for info. *|
5+
|* SPDX-License-Identifier: CC0-1.0 *|
6+
|* *|
7+
|*===----------------------------------------------------------------------===*|
8+
|* *|
9+
|* This header declares the C interface to LLVM's BLAKE3 implementation. *|
10+
|* Original BLAKE3 C API: https://github.com/BLAKE3-team/BLAKE3/tree/1.3.1/c *|
11+
|* *|
12+
|* Symbols are prefixed with 'llvm' to avoid a potential conflict with *|
13+
|* another BLAKE3 version within the same program. *|
14+
|* *|
15+
\*===----------------------------------------------------------------------===*/
16+
17+
#ifndef LLVM_C_BLAKE3_H
18+
#define LLVM_C_BLAKE3_H
19+
20+
#include <stddef.h>
21+
#include <stdint.h>
22+
23+
#ifdef __cplusplus
24+
extern "C" {
25+
#endif
26+
27+
#define LLVM_BLAKE3_VERSION_STRING "1.3.1"
28+
#define LLVM_BLAKE3_KEY_LEN 32
29+
#define LLVM_BLAKE3_OUT_LEN 32
30+
#define LLVM_BLAKE3_BLOCK_LEN 64
31+
#define LLVM_BLAKE3_CHUNK_LEN 1024
32+
#define LLVM_BLAKE3_MAX_DEPTH 54
33+
34+
// This struct is a private implementation detail. It has to be here because
35+
// it's part of llvm_blake3_hasher below.
36+
typedef struct {
37+
uint32_t cv[8];
38+
uint64_t chunk_counter;
39+
uint8_t buf[LLVM_BLAKE3_BLOCK_LEN];
40+
uint8_t buf_len;
41+
uint8_t blocks_compressed;
42+
uint8_t flags;
43+
} llvm_blake3_chunk_state;
44+
45+
typedef struct {
46+
uint32_t key[8];
47+
llvm_blake3_chunk_state chunk;
48+
uint8_t cv_stack_len;
49+
// The stack size is MAX_DEPTH + 1 because we do lazy merging. For example,
50+
// with 7 chunks, we have 3 entries in the stack. Adding an 8th chunk
51+
// requires a 4th entry, rather than merging everything down to 1, because we
52+
// don't know whether more input is coming. This is different from how the
53+
// reference implementation does things.
54+
uint8_t cv_stack[(LLVM_BLAKE3_MAX_DEPTH + 1) * LLVM_BLAKE3_OUT_LEN];
55+
} llvm_blake3_hasher;
56+
57+
const char *llvm_blake3_version(void);
58+
void llvm_blake3_hasher_init(llvm_blake3_hasher *self);
59+
void llvm_blake3_hasher_init_keyed(llvm_blake3_hasher *self,
60+
const uint8_t key[LLVM_BLAKE3_KEY_LEN]);
61+
void llvm_blake3_hasher_init_derive_key(llvm_blake3_hasher *self,
62+
const char *context);
63+
void llvm_blake3_hasher_init_derive_key_raw(llvm_blake3_hasher *self,
64+
const void *context,
65+
size_t context_len);
66+
void llvm_blake3_hasher_update(llvm_blake3_hasher *self, const void *input,
67+
size_t input_len);
68+
void llvm_blake3_hasher_finalize(const llvm_blake3_hasher *self, uint8_t *out,
69+
size_t out_len);
70+
void llvm_blake3_hasher_finalize_seek(const llvm_blake3_hasher *self,
71+
uint64_t seek, uint8_t *out,
72+
size_t out_len);
73+
void llvm_blake3_hasher_reset(llvm_blake3_hasher *self);
74+
75+
#ifdef __cplusplus
76+
}
77+
#endif
78+
79+
#endif /* LLVM_C_BLAKE3_H */

llvm/include/llvm/Support/BLAKE3.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//==- BLAKE3.h - BLAKE3 C++ wrapper for LLVM ---------------------*- C++ -*-==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This is a C++ wrapper of the BLAKE3 C interface.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_SUPPORT_BLAKE3_H
14+
#define LLVM_SUPPORT_BLAKE3_H
15+
16+
#include "llvm-c/blake3.h"
17+
#include "llvm/ADT/ArrayRef.h"
18+
#include "llvm/ADT/StringRef.h"
19+
20+
namespace llvm {
21+
22+
/// The constant \p LLVM_BLAKE3_OUT_LEN provides the default output length,
23+
/// 32 bytes, which is recommended for most callers.
24+
///
25+
/// Outputs shorter than the default length of 32 bytes (256 bits) provide
26+
/// less security. An N-bit BLAKE3 output is intended to provide N bits of
27+
/// first and second preimage resistance and N/2 bits of collision
28+
/// resistance, for any N up to 256. Longer outputs don't provide any
29+
/// additional security.
30+
///
31+
/// Shorter BLAKE3 outputs are prefixes of longer ones. Explicitly
32+
/// requesting a short output is equivalent to truncating the default-length
33+
/// output.
34+
template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN>
35+
using BLAKE3Result = std::array<uint8_t, NumBytes>;
36+
37+
/// A class that wrap the BLAKE3 algorithm.
38+
class BLAKE3 {
39+
public:
40+
BLAKE3() { init(); }
41+
42+
/// Reinitialize the internal state
43+
void init() { llvm_blake3_hasher_init(&Hasher); }
44+
45+
/// Digest more data.
46+
void update(ArrayRef<uint8_t> Data) {
47+
llvm_blake3_hasher_update(&Hasher, Data.data(), Data.size());
48+
}
49+
50+
/// Digest more data.
51+
void update(StringRef Str) {
52+
llvm_blake3_hasher_update(&Hasher, Str.data(), Str.size());
53+
}
54+
55+
/// Finalize the hasher and put the result in \p Result.
56+
/// This doesn't modify the hasher itself, and it's possible to finalize again
57+
/// after adding more input.
58+
template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN>
59+
void final(BLAKE3Result<NumBytes> &Result) {
60+
llvm_blake3_hasher_finalize(&Hasher, Result.data(), Result.size());
61+
}
62+
63+
/// Finalize the hasher and return an output of any length, given in bytes.
64+
/// This doesn't modify the hasher itself, and it's possible to finalize again
65+
/// after adding more input.
66+
template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN>
67+
BLAKE3Result<NumBytes> final() {
68+
BLAKE3Result<NumBytes> Result;
69+
llvm_blake3_hasher_finalize(&Hasher, Result.data(), Result.size());
70+
return Result;
71+
}
72+
73+
/// Returns a BLAKE3 hash for the given data.
74+
template <size_t NumBytes = LLVM_BLAKE3_OUT_LEN>
75+
static BLAKE3Result<NumBytes> hash(ArrayRef<uint8_t> Data) {
76+
BLAKE3 Hasher;
77+
Hasher.update(Data);
78+
return Hasher.final<NumBytes>();
79+
}
80+
81+
private:
82+
llvm_blake3_hasher Hasher;
83+
};
84+
85+
} // namespace llvm
86+
87+
#endif

llvm/lib/Support/BLAKE3/.clang-format

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
DisableFormat: true
2+
SortIncludes: Never
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
set(LLVM_BLAKE3_FILES
2+
blake3.c
3+
blake3_dispatch.c
4+
blake3_portable.c
5+
)
6+
7+
# The BLAKE3 team recommends using the assembly versions, from the README:
8+
#
9+
# "For each of the x86 SIMD instruction sets, four versions are available:
10+
# three flavors of assembly (Unix, Windows MSVC, and Windows GNU) and one
11+
# version using C intrinsics. The assembly versions are generally
12+
# preferred. They perform better, they perform more consistently across
13+
# different compilers, and they build more quickly."
14+
15+
if (MSVC)
16+
check_symbol_exists(_M_X64 "" IS_X64)
17+
check_symbol_exists(_M_ARM64 "" IS_ARM64)
18+
else()
19+
check_symbol_exists(__x86_64__ "" IS_X64)
20+
check_symbol_exists(__aarch64__ "" IS_ARM64)
21+
endif()
22+
23+
if (IS_X64)
24+
if (MSVC)
25+
enable_language(ASM_MASM)
26+
list(APPEND LLVM_BLAKE3_FILES
27+
blake3_sse2_x86-64_windows_msvc.asm
28+
blake3_sse41_x86-64_windows_msvc.asm
29+
blake3_avx2_x86-64_windows_msvc.asm
30+
blake3_avx512_x86-64_windows_msvc.asm
31+
)
32+
elseif(WIN32)
33+
list(APPEND LLVM_BLAKE3_FILES
34+
blake3_sse2_x86-64_windows_gnu.S
35+
blake3_sse41_x86-64_windows_gnu.S
36+
blake3_avx2_x86-64_windows_gnu.S
37+
blake3_avx512_x86-64_windows_gnu.S
38+
)
39+
else()
40+
list(APPEND LLVM_BLAKE3_FILES
41+
blake3_sse2_x86-64_unix.S
42+
blake3_sse41_x86-64_unix.S
43+
blake3_avx2_x86-64_unix.S
44+
blake3_avx512_x86-64_unix.S
45+
)
46+
endif()
47+
endif()
48+
49+
if (IS_ARM64)
50+
list(APPEND LLVM_BLAKE3_FILES
51+
blake3_neon.c
52+
)
53+
endif()
54+
55+
add_library(LLVMSupportBlake3 OBJECT EXCLUDE_FROM_ALL ${LLVM_BLAKE3_FILES})
56+
llvm_update_compile_flags(LLVMSupportBlake3)

0 commit comments

Comments
 (0)