case '1': /* SHA1 */
case '2': /* SHA256 */
case '3': /* SHA512 */
+ case '6': /* XXHASH64 */
+ case '7': /* XXH3_64 */
+ case '8': /* XXH3_128 */
if (in_block) {
Dmsg0(50, "Checksum will be sent to FD\n");
return true;
len = CRYPTO_DIGEST_SHA512_SIZE;
type = CRYPTO_DIGEST_SHA512;
break;
+ case STREAM_XXHASH64_DIGEST:
+ len = CRYPTO_DIGEST_XXHASH64_SIZE;
+ type = CRYPTO_DIGEST_XXHASH64;
+ break;
+ case STREAM_XXH3_64_DIGEST:
+ len = CRYPTO_DIGEST_XXH3_64_SIZE;
+ type = CRYPTO_DIGEST_XXH3_64;
+ break;
+ case STREAM_XXH3_128_DIGEST:
+ len = CRYPTO_DIGEST_XXH3_128_SIZE;
+ type = CRYPTO_DIGEST_XXH3_128;
+ break;
default:
/* Never reached ... */
Jmsg(jcr, M_ERROR, 0, _("Catalog error updating file digest. Unsupported digest stream type: %d"),
{"Sha256", INC_KW_DIGEST, "S2"},
{"Sha512", INC_KW_DIGEST, "S3"},
{"Sha1", INC_KW_DIGEST, "S"},
+ {"Xxhash64", INC_KW_DIGEST, "S5"},
+ {"Xxh3_64", INC_KW_DIGEST, "S6"},
+ {"Xxh3_128", INC_KW_DIGEST, "S7"},
{"Gzip", INC_KW_COMPRESSION, "Z6"},
{"Gzip1", INC_KW_COMPRESSION, "Z1"},
{"Gzip2", INC_KW_COMPRESSION, "Z2"},
case '3': /* compare SHA512 */
do_Digest = CRYPTO_DIGEST_SHA512;
break;
+ case '6': /* compare XXHASH64 */
+ do_Digest = CRYPTO_DIGEST_XXHASH64;
+ break;
+ case '7': /* compare XXH3_64 */
+ do_Digest = CRYPTO_DIGEST_XXH3_64;
+ break;
+ case '8': /* compare XXH3_128 */
+ do_Digest = CRYPTO_DIGEST_XXH3_128;
+ break;
case ':':
case 'V':
default:
} else if (ff_pkt->flags & FO_SHA512) {
digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA512);
digest_stream = STREAM_SHA512_DIGEST;
+
+ } else if (ff_pkt->flags & FO_XXHASH64) {
+ digest = crypto_digest_new(jcr, CRYPTO_DIGEST_XXHASH64);
+ digest_stream = STREAM_XXHASH64_DIGEST;
+
+ } else if (ff_pkt->flags & FO_XXH3_64) {
+ digest = crypto_digest_new(jcr, CRYPTO_DIGEST_XXH3_64);
+ digest_stream = STREAM_XXH3_64_DIGEST;
+
+ } else if (ff_pkt->flags & FO_XXH3_128) {
+ digest = crypto_digest_new(jcr, CRYPTO_DIGEST_XXH3_128);
+ digest_stream = STREAM_XXH3_128_DIGEST;
}
/* Did digest initialization fail? */
case '1': /* compare SHA1 */
case '2': /* compare SHA256 */
case '3': /* compare SHA512 */
+ case '6': /* compare XXHASH64 */
+ case '7': /* compare XXH3_64 */
+ case '8': /* compare XXH3_128 */
if (ff_pkt->type != FT_LNKSAVED &&
(S_ISREG(ff_pkt->statp.st_mode) &&
ff_pkt->flags & (FO_MD5|FO_SHA1|FO_SHA256|FO_SHA512))) {
} else if (ff_pkt->flags & FO_SHA512) {
bctx.digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA512);
bctx.digest_stream = STREAM_SHA512_DIGEST;
- }
+ } else if (ff_pkt->flags & FO_XXHASH64) {
+ bctx.digest = crypto_digest_new(jcr, CRYPTO_DIGEST_XXHASH64);
+ bctx.digest_stream = STREAM_XXHASH64_DIGEST;
+
+ } else if (ff_pkt->flags & FO_XXH3_64) {
+ bctx.digest = crypto_digest_new(jcr, CRYPTO_DIGEST_XXH3_64);
+ bctx.digest_stream = STREAM_XXH3_64_DIGEST;
+
+ } else if (ff_pkt->flags & FO_XXH3_128) {
+ bctx.digest = crypto_digest_new(jcr, CRYPTO_DIGEST_XXH3_128);
+ bctx.digest_stream = STREAM_XXH3_128_DIGEST;
+ }
/** Did digest initialization fail? */
if (bctx.digest_stream != STREAM_NONE && bctx.digest == NULL) {
Jmsg(jcr, M_WARNING, 0, _("%s digest initialization failed\n"),
{"sha1", CRYPTO_DIGEST_SHA1},
{"sha256", CRYPTO_DIGEST_SHA256},
// {"sha512", CRYPTO_DIGEST_SHA512}, /* Not working yet */
+ {"xxhash64", CRYPTO_DIGEST_XXHASH64},
+ {"xxh3_128", CRYPTO_DIGEST_XXH3_128},
+// {"xxh3_64", CRYPTO_DIGEST_XXH3_64}, /* Never released, maybe already deprecated ? */
{NULL, 0}
};
p++;
break;
#endif
+ case '5':
+ fo->flags |= FO_XXHASH64;
+ p++;
+ break;
+ case '6':
+ fo->flags |= FO_XXH3_64;
+ p++;
+ break;
+ case '7':
+ fo->flags |= FO_XXH3_128;
+ p++;
+ break;
default:
/*
* If 2 or 3 is seen here, SHA2 is not configured, so
case STREAM_SHA1_DIGEST:
case STREAM_SHA256_DIGEST:
case STREAM_SHA512_DIGEST:
+ case STREAM_XXHASH64_DIGEST:
+ case STREAM_XXH3_64_DIGEST:
+ case STREAM_XXH3_128_DIGEST:
break;
case STREAM_PROGRAM_NAMES:
} else if (ff_pkt->flags & FO_SHA512) {
digest = crypto_digest_new(jcr, CRYPTO_DIGEST_SHA512);
digest_stream = STREAM_SHA512_DIGEST;
+
+ } else if (ff_pkt->flags & FO_XXHASH64) {
+ digest = crypto_digest_new(jcr, CRYPTO_DIGEST_XXHASH64);
+ digest_stream = STREAM_XXHASH64_DIGEST;
+
+ } else if (ff_pkt->flags & FO_XXH3_64) {
+ digest = crypto_digest_new(jcr, CRYPTO_DIGEST_XXH3_64);
+ digest_stream = STREAM_XXH3_64_DIGEST;
+
+ } else if (ff_pkt->flags & FO_XXH3_128) {
+ digest = crypto_digest_new(jcr, CRYPTO_DIGEST_XXH3_128);
+ digest_stream = STREAM_XXH3_128_DIGEST;
}
/* Did digest initialization fail? */
stream_to_ascii(digest_stream));
}
- /* compute MD5 or SHA1 hash */
+ /* compute MD5 or SHA??? or XXH??? hash */
if (digest) {
char md[CRYPTO_DIGEST_MAX_SIZE];
uint32_t size;
if ((strchr(fo->VerifyOpts, '1') != NULL) ||
(strchr(fo->VerifyOpts, '2') != NULL) ||
(strchr(fo->VerifyOpts, '3') != NULL) ||
- (strchr(fo->VerifyOpts, '5') != NULL))
+ (strchr(fo->VerifyOpts, '5') != NULL) ||
+ (strchr(fo->VerifyOpts, '6') != NULL) ||
+ (strchr(fo->VerifyOpts, '7') != NULL) ||
+ (strchr(fo->VerifyOpts, '8') != NULL))
{
check_chksum = true;
}
digesttype = CRYPTO_DIGEST_SHA512;
return;
}
+ if (fo->flags & FO_XXHASH64) {
+ digesttype = CRYPTO_DIGEST_XXHASH64;
+ return;
+ }
+ if (fo->flags & FO_XXH3_64) {
+ digesttype = CRYPTO_DIGEST_XXH3_64;
+ return;
+ }
+ if (fo->flags & FO_XXH3_128) {
+ digesttype = CRYPTO_DIGEST_XXH3_128;
+ return;
+ }
}
}
digesttype = CRYPTO_DIGEST_NONE;
digest_code = "SHA512";
break;
+ case STREAM_XXHASH64_DIGEST:
+ bin_to_base64(digest, sizeof(digest), (char *)bmsg->rbuf, CRYPTO_DIGEST_XXHASH64_SIZE, true);
+ digest_code = "XXHASH64";
+ break;
+
+ case STREAM_XXH3_64_DIGEST:
+ bin_to_base64(digest, sizeof(digest), (char *)bmsg->rbuf, CRYPTO_DIGEST_XXH3_64_SIZE, true);
+ digest_code = "XXH3_64";
+ break;
+
+ case STREAM_XXH3_128_DIGEST:
+ bin_to_base64(digest, sizeof(digest), (char *)bmsg->rbuf, CRYPTO_DIGEST_XXH3_128_SIZE, true);
+ digest_code = "XXH3_128";
+ break;
+
default:
*digest = 0;
break;
#define FO_OFFSETS (1<<30) /* Keep I/O file offsets */
#define FO_DEDUPLICATION (1ULL<<31) /* Do deduplication */
+#define FO_XXHASH64 (1ULL<<32) /* Do XXHASH64 checksum */
+#define FO_XXH3_64 (1ULL<<33) /* Do XXH3_H64 checksum */
+#define FO_XXH3_128 (1ULL<<34) /* Do XXH3_128 checksum */
+
#endif /* __BFILEOPTSS_H */
return _("SHA256 digest");
case STREAM_SHA512_DIGEST:
return _("SHA512 digest");
+ case STREAM_XXHASH64_DIGEST:
+ return _("XXHASH64 digest");
+ case STREAM_XXH3_64_DIGEST:
+ return _("XXH3_64 digest");
+ case STREAM_XXH3_128_DIGEST:
+ return _("XXH3_128 digest");
case STREAM_SIGNED_DIGEST:
return _("Signed digest");
case STREAM_ENCRYPTED_FILE_DATA:
#ifdef HAVE_OPENSSL /* How about OpenSSL? */
#include "openssl-compat.h"
+#include "xxhash.h"
/* ASN.1 Declarations */
#define BACULA_ASN1_VERSION 0
free(keypair);
}
-/*
- * Create a new message digest context of the specified type
- * Returns: A pointer to a DIGEST object on success.
- * NULL on failure.
- */
-DIGEST *crypto_digest_new(JCR *jcr, crypto_digest_t type)
+/* called by crypto_digest_new() to create an xxhash digest context */
+static DIGEST *xxhash_crypto_digest_new(JCR *jcr, crypto_digest_t type)
{
- DIGEST *digest;
- const EVP_MD *md = NULL; /* Quell invalid uninitialized warnings */
+ void *state;
- if (!crypto_check_digest(jcr, type)) {
+ switch (type) {
+ case CRYPTO_DIGEST_XXHASH64:
+ state = (void*)XXH64_createState();
+ XXH64_reset((XXH64_state_t *)state, 0);
+ break;
+ case CRYPTO_DIGEST_XXH3_64:
+ state = (void*)XXH3_createState();
+ XXH3_64bits_reset((XXH3_state_t *)state);
+ break;
+ case CRYPTO_DIGEST_XXH3_128:
+ state = (void*)XXH3_createState();
+ XXH3_128bits_reset((XXH3_state_t *)state);
+ break;
+ default:
+ Jmsg1(jcr, M_ERROR, 0, _("Unsupported digest type: %d\n"), type);
return NULL;
}
+ DIGEST *digest;
+
+ digest = (DIGEST *)malloc(sizeof(DIGEST));
+ digest->type = type;
+ digest->jcr = jcr;
+ digest->ctx = (EVP_MD_CTX *)state; // TODO remove the trans-typage
+ Dmsg1(150, "crypto_digest_new jcr=%p\n", jcr);
+
+ return digest;
+}
+
+/* called by crypto_digest_new() to create an openssl digest context */
+static DIGEST *openssl_crypto_digest_new(JCR *jcr, crypto_digest_t type)
+{
+ DIGEST *digest;
+ const EVP_MD *md = NULL; /* Quell invalid uninitialized warnings */
+
digest = (DIGEST *)malloc(sizeof(DIGEST));
digest->type = type;
digest->jcr = jcr;
return NULL;
}
+/*
+ * Create a new message digest context of the specified type
+ * Returns: A pointer to a DIGEST object on success.
+ * NULL on failure.
+ */
+DIGEST *crypto_digest_new(JCR *jcr, crypto_digest_t type)
+{
+ if (!crypto_check_digest(jcr, type)) {
+ return NULL;
+ }
+ if (IS_XXHASH_DIGEST(type)) {
+ return xxhash_crypto_digest_new(jcr, type);
+ }
+ return openssl_crypto_digest_new(jcr, type);
+}
+
/*
* Hash length bytes of data into the provided digest context.
* Returns: true on success
*/
bool crypto_digest_update(DIGEST *digest, const uint8_t *data, uint32_t length)
{
- if (EVP_DigestUpdate(digest->ctx, data, length) == 0) {
- Dmsg0(150, "digest update failed\n");
- openssl_post_errors(digest->jcr, M_ERROR, _("OpenSSL digest update failed"));
- return false;
+ if (IS_XXHASH_DIGEST(digest->type)) {
+ int ret;
+ switch (digest->type) {
+ case CRYPTO_DIGEST_XXHASH64:
+ ret = XXH64_update((XXH64_state_t *)digest->ctx, data, length);
+ break;
+ case CRYPTO_DIGEST_XXH3_64:
+ ret = XXH3_64bits_update((XXH3_state_t *)digest->ctx, data, length);
+ break;
+ case CRYPTO_DIGEST_XXH3_128:
+ ret = XXH3_128bits_update((XXH3_state_t *)digest->ctx, data, length);
+ break;
+ default:
+ Dmsg1(150, "unknown digest %d\n", digest->type);
+ ret = XXH_ERROR;
+ break;
+ }
+ if (ret != XXH_OK) {
+ Dmsg0(150, "digest update failed\n");
+ }
+ return (ret == XXH_OK);
} else {
- return true;
+ if (EVP_DigestUpdate((EVP_MD_CTX *)digest->ctx, data, length) == 0) {
+ Dmsg0(150, "digest update failed\n");
+ openssl_post_errors(digest->jcr, M_ERROR, _("OpenSSL digest update failed"));
+ return false;
+ } else {
+ return true;
+ }
}
}
*/
bool crypto_digest_finalize(DIGEST *digest, uint8_t *dest, uint32_t *length)
{
- if (!EVP_DigestFinal(digest->ctx, dest, (unsigned int *)length)) {
- Dmsg0(150, "digest finalize failed\n");
- openssl_post_errors(digest->jcr, M_ERROR, _("OpenSSL digest finalize failed"));
- return false;
+ if (IS_XXHASH_DIGEST(digest->type)) {
+ bool ret = true;
+ XXH64_hash_t val64;
+ XXH128_hash_t val128; /* this is a struct */
+ switch (digest->type) {
+ case CRYPTO_DIGEST_XXHASH64:
+ *length = CRYPTO_DIGEST_XXHASH64_SIZE;
+ val64 = XXH64_digest((XXH64_state_t *)digest->ctx);
+ XXH64_canonicalFromHash((XXH64_canonical_t*)dest, val64);
+ break;
+ case CRYPTO_DIGEST_XXH3_64:
+ *length = CRYPTO_DIGEST_XXH3_64_SIZE;
+ val64 = XXH3_64bits_digest((XXH3_state_t *)digest->ctx);
+ XXH64_canonicalFromHash((XXH64_canonical_t*)dest, val64);
+ case CRYPTO_DIGEST_XXH3_128:
+ *length = CRYPTO_DIGEST_XXH3_128_SIZE;
+ val128 = XXH3_128bits_digest((XXH3_state_t *)digest->ctx);
+ XXH128_canonicalFromHash((XXH128_canonical_t *)dest, val128);
+ break;
+ default:
+ Dmsg1(150, "unknown digest %d\n", digest->type);
+ ret = false;
+ break;
+ }
+ return ret;
} else {
- return true;
+ unsigned int v;
+ if (!EVP_DigestFinal(digest->ctx, dest, &v)) {
+ Dmsg0(150, "digest finalize failed\n");
+ openssl_post_errors(digest->jcr, M_ERROR, _("OpenSSL digest finalize failed"));
+ return false;
+ } else {
+ *length = v;
+ return true;
+ }
}
}
*/
void crypto_digest_free(DIGEST *digest)
{
- EVP_MD_CTX_free(digest->ctx);
- free(digest);
+ switch (digest->type) {
+ case CRYPTO_DIGEST_MD5:
+ case CRYPTO_DIGEST_SHA1:
+#ifdef HAVE_SHA2
+ case CRYPTO_DIGEST_SHA256:
+ case CRYPTO_DIGEST_SHA512:
+#endif
+ EVP_MD_CTX_free((EVP_MD_CTX *)digest->ctx);
+ break;
+ case CRYPTO_DIGEST_XXHASH64:
+ XXH64_freeState((XXH64_state_t *)digest->ctx);
+ break;
+ case CRYPTO_DIGEST_XXH3_64:
+ case CRYPTO_DIGEST_XXH3_128:
+ XXH3_freeState((XXH3_state_t *)digest->ctx);
+ break;
+ default:
+ Dmsg1(150, "UNKNOWN digest %d !!!\n", digest->type);
+ break;
+ }
+ free(digest);
}
/*
return "SHA256";
case CRYPTO_DIGEST_SHA512:
return "SHA512";
+ case CRYPTO_DIGEST_XXHASH64:
+ return "XXHASH64";
+ case CRYPTO_DIGEST_XXH3_64:
+ return "XXH3_64";
+ case CRYPTO_DIGEST_XXH3_128:
+ return "XXH3_128";
case CRYPTO_DIGEST_NONE:
return "None";
default:
return CRYPTO_DIGEST_SHA256;
case STREAM_SHA512_DIGEST:
return CRYPTO_DIGEST_SHA512;
+ case STREAM_XXHASH64_DIGEST:
+ return CRYPTO_DIGEST_XXHASH64;
+ case STREAM_XXH3_64_DIGEST:
+ return CRYPTO_DIGEST_XXH3_64;
+ case STREAM_XXH3_128_DIGEST:
+ return CRYPTO_DIGEST_XXH3_128;
default:
return CRYPTO_DIGEST_NONE;
}
CRYPTO_DIGEST_MD5 = 1,
CRYPTO_DIGEST_SHA1 = 2,
CRYPTO_DIGEST_SHA256 = 3,
- CRYPTO_DIGEST_SHA512 = 4
+ CRYPTO_DIGEST_SHA512 = 4,
+ CRYPTO_DIGEST_XXHASH64 = 5,
+ CRYPTO_DIGEST_XXH3_128 = 6,
+ CRYPTO_DIGEST_XXH3_64 = 7 /* Never released, maybe already deprecated ? */
} crypto_digest_t;
+#define IS_XXHASH_DIGEST(type) (CRYPTO_DIGEST_XXHASH64<=(type) && (type)<=CRYPTO_DIGEST_XXH3_128)
#ifdef HAVE_SHA2
# define CRYPTO_DIGEST_DEFAULT CRYPTO_DIGEST_SHA256
#define CRYPTO_DIGEST_SHA1_SIZE 20 /* 160 bits */
#define CRYPTO_DIGEST_SHA256_SIZE 32 /* 256 bits */
#define CRYPTO_DIGEST_SHA512_SIZE 64 /* 512 bits */
+#define CRYPTO_DIGEST_XXHASH64_SIZE 8 /* 64bits */
+#define CRYPTO_DIGEST_XXH3_64_SIZE 8 /* 64bits */
+#define CRYPTO_DIGEST_XXH3_128_SIZE 16 /* 128bits */
/* Maximum Message Digest Size */
#ifdef HAVE_OPENSSL
case STREAM_SHA1_DIGEST:
case STREAM_SHA256_DIGEST:
case STREAM_SHA512_DIGEST:
+ case STREAM_XXHASH64_DIGEST:
+ case STREAM_XXH3_64_DIGEST:
+ case STREAM_XXH3_128_DIGEST:
break;
case STREAM_SIGNED_DIGEST:
update_digest_record(db, digest, rec, CRYPTO_DIGEST_SHA512);
break;
+ case STREAM_XXHASH64_DIGEST:
+ bin_to_base64(digest, sizeof(digest), (char *)rec->data, CRYPTO_DIGEST_XXHASH64_SIZE, true);
+ if (verbose > 1) {
+ Pmsg1(000, _("Got XXHASH64 record: %s\n"), digest);
+ }
+ update_digest_record(db, digest, rec, CRYPTO_DIGEST_XXHASH64);
+ break;
+
+ case STREAM_XXH3_64_DIGEST:
+ bin_to_base64(digest, sizeof(digest), (char *)rec->data, CRYPTO_DIGEST_XXH3_64_SIZE, true);
+ if (verbose > 1) {
+ Pmsg1(000, _("Got XXH3_64 record: %s\n"), digest);
+ }
+ update_digest_record(db, digest, rec, CRYPTO_DIGEST_XXH3_64);
+ break;
+
+ case STREAM_XXH3_128_DIGEST:
+ bin_to_base64(digest, sizeof(digest), (char *)rec->data, CRYPTO_DIGEST_XXH3_128_SIZE, true);
+ if (verbose > 1) {
+ Pmsg1(000, _("Got XXH3_128 record: %s\n"), digest);
+ }
+ update_digest_record(db, digest, rec, CRYPTO_DIGEST_XXH3_128);
+ break;
+
case STREAM_ENCRYPTED_SESSION_DATA:
// TODO landonf: Investigate crypto support in bscan
if (verbose > 1) {
return "contADATA-RECORD-HEADER";
case STREAM_FILEEVENT:
return _("FileEvent");
+ case STREAM_XXHASH64_DIGEST:
+ return "contXXHASH64";
+ case STREAM_XXH3_64_DIGEST:
+ return "contXXH3_63";
+ case STREAM_XXH3_128_DIGEST:
+ return "contXXH3_128";
default:
sprintf(buf, "%d", -stream);
return buf;
return "ADATA-RECORD-HEADER";
case STREAM_FILEEVENT:
return _("FileEvent");
+ case STREAM_XXHASH64_DIGEST:
+ return "XXHASH64";
+ case STREAM_XXH3_64_DIGEST:
+ return "XXH3_63";
+ case STREAM_XXH3_128_DIGEST:
+ return "XXH3_128";
default:
sprintf(buf, "%d", stream);
return buf;
#define STREAM_PLUGIN_META_CATALOG 36 /* Plugin metadata (to be stored in catalog) for file being backed up */
#define STREAM_UNIX_ATTRIBUTE_UPDATE 37 /* File's updated metadata */
#define STREAM_FILEEVENT 38 /* FileEvent associated with the current object */
+#define STREAM_XXHASH64_DIGEST 39 /* XXHASH64 digest for the file */
+#define STREAM_XXH3_64_DIGEST 40 /* XXH3_64 digest for the file */
+#define STREAM_XXH3_128_DIGEST 41 /* XXH3_128 digest for the file */
#define STREAM_ADATA_BLOCK_HEADER 200 /* Adata block header */
#define STREAM_ADATA_RECORD_HEADER 201 /* Adata record header */