Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

## Changes in this version:

### ENHANCEMENTS:

- Added SHA-3 (FIPS 202) as an opt-in `--checksum-choice` algorithm
family: `sha3-256`, `sha3-384`, and `sha3-512`. The implementation
uses OpenSSL EVP and so requires that rsync be built with OpenSSL
support and linked against libcrypto >= 1.1.1. Like `sha256` and
`sha512`, SHA-3 is never picked by `auto` negotiation; it must be
explicitly requested on both ends (e.g.
`--checksum-choice=sha3-256`) or made part of the
`RSYNC_CHECKSUM_LIST` environment override.

### BUG FIXES:

- Fixed a regression introduced by the 3.4.0 secure_relative_open()
Expand Down
20 changes: 20 additions & 0 deletions checksum.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ struct name_num_item valid_checksums_items[] = {
#ifdef SUPPORT_XXHASH
{ CSUM_XXH64, 0, "xxh64", NULL },
{ CSUM_XXH64, 0, "xxhash", NULL },
#endif
#ifdef USE_OPENSSL
/* SHA-3 is offered only via OpenSSL EVP (sha3-* digests, OpenSSL >= 1.1.1).
* verify_digest() probes each entry at startup and disables any that the
* linked libcrypto does not support, so listing them here is safe even
* when the build environment is older. */
{ CSUM_SHA3_512, NNI_EVP, "sha3-512", NULL },
{ CSUM_SHA3_384, NNI_EVP, "sha3-384", NULL },
{ CSUM_SHA3_256, NNI_EVP, "sha3-256", NULL },
#endif
{ CSUM_MD5, NNI_BUILTIN|NNI_EVP, "md5", NULL },
{ CSUM_MD4, NNI_BUILTIN|NNI_EVP, "md4", NULL },
Expand Down Expand Up @@ -237,6 +246,14 @@ int csum_len_for_type(int cst, BOOL flist_csum)
#ifdef SHA512_DIGEST_LENGTH
case CSUM_SHA512:
return SHA512_DIGEST_LENGTH;
#endif
#ifdef USE_OPENSSL
case CSUM_SHA3_256:
return SHA3_256_DIGEST_LEN;
case CSUM_SHA3_384:
return SHA3_384_DIGEST_LEN;
case CSUM_SHA3_512:
return SHA3_512_DIGEST_LEN;
#endif
case CSUM_XXH64:
case CSUM_XXH3_64:
Expand Down Expand Up @@ -266,6 +283,9 @@ int canonical_checksum(int csum_type)
case CSUM_SHA1:
case CSUM_SHA256:
case CSUM_SHA512:
case CSUM_SHA3_256:
case CSUM_SHA3_384:
case CSUM_SHA3_512:
return -1;
case CSUM_XXH64:
case CSUM_XXH3_64:
Expand Down
12 changes: 12 additions & 0 deletions lib/md-defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@

#define MD4_DIGEST_LEN 16
#define MD5_DIGEST_LEN 16

/* SHA-3 (FIPS 202). OpenSSL exposes these via EVP only, with no
* SHA3_*_DIGEST_LENGTH macros, so define our own. SHA3-512 shares
* its 64-byte digest length with SHA-512, so MAX_DIGEST_LEN is
* unaffected. */
#define SHA3_256_DIGEST_LEN 32
#define SHA3_384_DIGEST_LEN 48
#define SHA3_512_DIGEST_LEN 64

#if defined SHA512_DIGEST_LENGTH
#define MAX_DIGEST_LEN SHA512_DIGEST_LENGTH
#elif defined SHA256_DIGEST_LENGTH
Expand All @@ -35,3 +44,6 @@
#define CSUM_SHA1 9
#define CSUM_SHA256 10
#define CSUM_SHA512 11
#define CSUM_SHA3_256 12
#define CSUM_SHA3_384 13
#define CSUM_SHA3_512 14
7 changes: 7 additions & 0 deletions rsync.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -1781,11 +1781,18 @@ expand it.
- `xxh128`
- `xxh3`
- `xxh64` (aka `xxhash`)
- `sha3-512`
- `sha3-384`
- `sha3-256`
- `md5`
- `md4`
- `sha1`
- `none`

The `sha3-*` choices require an rsync built with OpenSSL support and
a libcrypto that provides SHA-3 (OpenSSL 1.1.1 or newer). They are
never selected by `auto` negotiation and must be requested explicitly.

Run `rsync --version` to see the default checksum list compiled into your
version (which may differ from the list above).

Expand Down
60 changes: 60 additions & 0 deletions testsuite/checksum-sha3.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/sh

# Test SHA-3 checksum support (sha3-256, sha3-384, sha3-512).
#
# Requires rsync to be built with OpenSSL support and linked against a
# libcrypto that exposes the SHA-3 family (OpenSSL 1.1.1 or newer).
# The test probes for SHA-3 by asking rsync to use it on a no-op copy;
# if the local rsync rejects the choice (e.g. no OpenSSL at build time,
# or older libcrypto), the test is skipped rather than failed.

. "$suitedir/rsync.fns"

probe() {
$RSYNC --checksum-choice="$1" --help >/dev/null 2>&1 || return 1
# --help doesn't actually parse the choice; force a real parse.
mkdir -p "$tmpdir/probe.src"
: > "$tmpdir/probe.src/x"
rm -rf "$tmpdir/probe.dst"
$RSYNC -a --checksum-choice="$1" "$tmpdir/probe.src/" "$tmpdir/probe.dst/" 2>"$outfile"
rc=$?
rm -rf "$tmpdir/probe.src" "$tmpdir/probe.dst"
if [ $rc -ne 0 ] && grep -q 'unknown checksum name' "$outfile"; then
return 1
fi
return $rc
}

if ! probe sha3-256; then
test_skipped "rsync was not built with OpenSSL SHA-3 support"
fi

mkdir "$fromdir"
mkdir "$fromdir/sub"
# Mix of empty, small, and chunk-spanning sizes (CHUNK_SIZE is 32k internally).
: > "$fromdir/empty"
echo "hello sha-3" > "$fromdir/small"
dd if=/dev/urandom of="$fromdir/big" bs=1024 count=70 2>/dev/null

for algo in sha3-256 sha3-384 sha3-512; do
rm -rf "$todir"

# Whole-file path (transfer checksum only).
checkit "$RSYNC -a --checksum-choice=$algo '$fromdir/' '$todir/'" "$fromdir" "$todir"

# Pre-transfer + transfer checksum path (-c forces file_checksum to run).
rm -rf "$todir"
checkit "$RSYNC -ac --checksum-choice=$algo '$fromdir/' '$todir/'" "$fromdir" "$todir"

# --checksum-choice with distinct xfer,file pair.
rm -rf "$todir"
checkit "$RSYNC -ac --checksum-choice=$algo,$algo '$fromdir/' '$todir/'" "$fromdir" "$todir"
done

# Delta-update path: mutate the destination, re-sync with SHA-3, confirm match.
rm -rf "$todir"
$RSYNC -a --checksum-choice=sha3-256 "$fromdir/" "$todir/" || test_fail "initial sync failed"
echo "modified locally" >> "$todir/small"
checkit "$RSYNC -a --checksum-choice=sha3-256 '$fromdir/' '$todir/'" "$fromdir" "$todir"

exit 0
Loading