From b9b58a17db0b475b2d1178ebfacae18c6c1849d9 Mon Sep 17 00:00:00 2001 From: David Steele Date: Tue, 18 Aug 2026 10:23:25 +0700 Subject: [PATCH] Pass a cipher spec rather than a type and passphrase. The cipher type and passphrase were separate parameters in every function that reads or writes an encrypted file, every info file load and save, and every protocol message that hands a file to a local process. Anything added alongside them meant changing all of it again. A cipher spec keeps them together. The pass is a buffer rather than a string so an absent pass is simply NULL, and it is copied into the object so the caller is free to release whatever it was read from. The spec is packed and unpacked as a unit for the protocol and writes nothing but the type when there is no cipher. The digest the key derives with was a parameter of the block cipher filter, packed with every filter that crossed the protocol, and nothing but the tests ever set it. It is gone and the key derives with SHA-1 where that happens, since the spec is where the choice would go if there is ever more than one. The specs form a chain. cfgCipherSpecMainIdx() builds one from the options and caches it per repository, the info files are read with that, and each info file carries the spec for the files that depend on it, so nothing below the info files consults the options again. The cache is filled the first time a spec is asked for, so a command has to get the repo storage before then, since that is what pulls the cipher options down from a remote repository. An info file stores a pass but not a type, so the spec it carries takes the type of the spec the file was read with. That spec is never NULL, and is none when the file has no pass, so it can be handed on without a check. A spec is named for what it opens: cipherSpecMain from the configuration, cipherSpecArchive from archive.info, cipherSpecManifest from backup.info, and cipherSpecBackup from the manifest. That turned up names that said the opposite of what they held, since what backup called the backup passphrase is what opens manifests, and restore documented the passphrase it loads the manifest with as being for backup files. The test harness takes a spec as well, so the storage and backup harnesses no longer accept a type and pass pair, and the rule that a missing pass meant the main test pass is now spelled out in TEST_CIPHER_SPEC. --- doc/xml/release/2020s/2026/2.60.0.xml | 11 +++ src/command/annotate/annotate.c | 9 +- src/command/archive/get/file.c | 4 +- src/command/archive/get/file.h | 5 +- src/command/archive/get/get.c | 20 ++-- src/command/archive/get/protocol.c | 3 +- src/command/archive/push/file.c | 4 +- src/command/archive/push/file.h | 5 +- src/command/archive/push/protocol.c | 3 +- src/command/archive/push/push.c | 12 +-- src/command/backup/backup.c | 19 ++-- src/command/backup/complete.c.inc | 38 +++----- src/command/backup/db.c.inc | 6 +- src/command/backup/file.c.inc | 19 ++-- src/command/backup/incr.c.inc | 4 +- src/command/backup/process.c.inc | 15 ++- src/command/backup/protocol.c | 5 +- src/command/backup/resume.c.inc | 15 ++- src/command/check/check.c | 7 +- src/command/check/common.c | 10 +- src/command/check/common.h | 4 +- src/command/expire/expire.c | 13 +-- src/command/info/info.c | 10 +- src/command/manifest/manifest.c | 13 +-- src/command/repo/get.c | 43 +++++---- src/command/restore/blockDelta.c | 18 ++-- src/command/restore/blockDelta.h | 6 +- src/command/restore/file.c.inc | 23 +++-- src/command/restore/process.c.inc | 4 +- src/command/restore/protocol.c | 4 +- src/command/restore/restore.c | 14 ++- src/command/restore/select.c.inc | 18 ++-- src/command/restore/timeline.c | 16 ++-- src/command/restore/timeline.h | 7 +- src/command/stanza/common.c | 24 +++-- src/command/stanza/common.h | 4 +- src/command/stanza/create.c | 22 ++--- src/command/stanza/upgrade.c | 18 +--- src/command/verify/file.c | 8 +- src/command/verify/file.h | 4 +- src/command/verify/protocol.c | 4 +- src/command/verify/verify.c | 79 +++++++--------- src/common/crypto/cipherBlock.c | 51 ++++------ src/common/crypto/cipherBlock.h | 14 ++- src/common/crypto/spec.c | 96 +++++++++++++++++++ src/common/crypto/spec.h | 101 ++++++++++++++++++++ src/config/config.c | 36 +++++++ src/config/config.h | 16 ++++ src/config/config.intern.h | 2 + src/info/info.c | 32 +++++-- src/info/info.h | 23 +++-- src/info/infoArchive.c | 39 ++++---- src/info/infoArchive.h | 19 ++-- src/info/infoBackup.c | 52 +++++------ src/info/infoBackup.h | 20 ++-- src/info/infoPg.c | 13 ++- src/info/infoPg.h | 13 +-- src/info/manifest/manifest.c | 5 +- src/info/manifest/manifest.h | 19 ++-- src/info/manifest/serialize.c.inc | 17 ++-- src/meson.build | 1 + test/define.yaml | 1 + test/src/harness/backup.c | 13 ++- test/src/harness/backup.h | 3 +- test/src/harness/blockIncr.c | 2 +- test/src/harness/config.h | 4 + test/src/harness/host.c | 26 ++---- test/src/harness/host.h | 8 +- test/src/harness/storage.c | 22 ++--- test/src/harness/storage.h | 7 +- test/src/module/command/archive/getTest.c | 4 +- test/src/module/command/archive/pushTest.c | 18 ++-- test/src/module/command/backupTest.c | 103 +++++++++------------ test/src/module/command/checkTest.c | 10 +- test/src/module/command/expireTest.c | 63 +++++++------ test/src/module/command/infoTest.c | 12 +-- test/src/module/command/manifestTest.c | 8 +- test/src/module/command/repoTest.c | 19 ++-- test/src/module/command/restoreTest.c | 60 ++++++------ test/src/module/command/stanzaTest.c | 37 +++++--- test/src/module/command/verifyTest.c | 69 ++++++++------ test/src/module/common/cryptoTest.c | 65 +++++++++---- test/src/module/config/loadTest.c | 14 +++ test/src/module/config/parseTest.c | 11 +++ test/src/module/info/infoArchiveTest.c | 31 ++++--- test/src/module/info/infoBackupTest.c | 70 +++++++------- test/src/module/info/infoPgTest.c | 24 +++-- test/src/module/info/infoTest.c | 41 ++++---- test/src/module/info/manifestTest.c | 34 ++++--- test/src/module/integration/allTest.c | 6 +- test/src/module/performance/typeTest.c | 2 +- test/src/module/storage/remoteTest.c | 4 +- 92 files changed, 1087 insertions(+), 843 deletions(-) create mode 100644 src/common/crypto/spec.c create mode 100644 src/common/crypto/spec.h diff --git a/doc/xml/release/2020s/2026/2.60.0.xml b/doc/xml/release/2020s/2026/2.60.0.xml index b329f37da..3a5b46f35 100644 --- a/doc/xml/release/2020s/2026/2.60.0.xml +++ b/doc/xml/release/2020s/2026/2.60.0.xml @@ -52,6 +52,17 @@ + + + + + + + + +

Pass a cipher spec rather than a type and passphrase.

+
+ diff --git a/src/command/annotate/annotate.c b/src/command/annotate/annotate.c index 64bf60219..08ef35629 100644 --- a/src/command/annotate/annotate.c +++ b/src/command/annotate/annotate.c @@ -56,11 +56,8 @@ cmdAnnotate(void) storageRepoIdx(repoIdx); // Attempt to load the backup info file - const CipherType repoCipherType = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx); - InfoBackup *infoBackup = infoBackupLoadFileReconstruct( - storageRepoIdx(repoIdx), INFO_BACKUP_PATH_FILE_STR, repoCipherType, - cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + storageRepoIdx(repoIdx), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); if (infoBackupLabelExists(infoBackup, backupLabel)) { @@ -75,9 +72,7 @@ cmdAnnotate(void) infoBackupDataAnnotationSet(infoBackup, backupLabel, cfgOptionKv(cfgOptAnnotation)); // Write the updated backup info - infoBackupSaveFile( - infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, repoCipherType, - cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); } } CATCH_ANY() diff --git a/src/command/archive/get/file.c b/src/command/archive/get/file.c index e784b2028..990c56346 100644 --- a/src/command/archive/get/file.c +++ b/src/command/archive/get/file.c @@ -54,11 +54,11 @@ archiveGetFile( storage, walDestination, .noCreatePath = true, .noSyncFile = true, .noSyncPath = true, .noAtomic = true); // If there is a cipher then add the decrypt filter - if (actual->cipherType != cipherTypeNone) + if (cipherSpecType(actual->cipherSpecArchive) != cipherTypeNone) { ioFilterGroupAdd( ioWriteFilterGroup(storageWriteIo(destination)), - cipherBlockNewP(cipherModeDecrypt, actual->cipherType, BUFSTR(actual->cipherPassArchive))); + cipherBlockNewP(cipherModeDecrypt, actual->cipherSpecArchive)); compressible = false; } diff --git a/src/command/archive/get/file.h b/src/command/archive/get/file.h index 63ea2d61c..f8045641b 100644 --- a/src/command/archive/get/file.h +++ b/src/command/archive/get/file.h @@ -4,7 +4,7 @@ Archive Get File #ifndef COMMAND_ARCHIVE_GET_FILE_H #define COMMAND_ARCHIVE_GET_FILE_H -#include "common/crypto/common.h" +#include "common/crypto/spec.h" #include "common/type/string.h" #include "storage/storage.h" @@ -17,8 +17,7 @@ typedef struct ArchiveGetFile const String *file; // File in the repo (with path, checksum, ext, etc.) unsigned int repoIdx; // Repo idx const String *archiveId; // Repo archive id - CipherType cipherType; // Repo cipher type - const String *cipherPassArchive; // Repo archive cipher pass + const CipherSpec *cipherSpecArchive; // Repo archive cipher spec } ArchiveGetFile; typedef struct ArchiveGetFileResult diff --git a/src/command/archive/get/get.c b/src/command/archive/get/get.c index d808cb16d..9425e956f 100644 --- a/src/command/archive/get/get.c +++ b/src/command/archive/get/get.c @@ -94,8 +94,7 @@ typedef struct ArchiveGetFindCacheArchive typedef struct ArchiveGetFindCacheRepo { unsigned int repoIdx; - CipherType cipherType; // Repo cipher type - const String *cipherPassArchive; // Repo archive cipher pass + const CipherSpec *cipherSpecArchive; // Repo archive cipher spec List *archiveList; // Cached list of archiveIds and associated paths StringList *warnList; // Track repo warnings so each is only reported once } ArchiveGetFindCacheRepo; @@ -213,8 +212,7 @@ archiveGetFind( strZ(strLstGet(segmentList, segmentIdx))), .repoIdx = cacheRepo->repoIdx, .archiveId = cacheArchive->archiveId, - .cipherType = cacheRepo->cipherType, - .cipherPassArchive = cacheRepo->cipherPassArchive, + .cipherSpecArchive = cacheRepo->cipherSpecArchive, }; lstAdd(matchList, &archiveGetFile); @@ -235,8 +233,7 @@ archiveGetFind( .file = strNewFmt("%s/%s", strZ(cacheArchive->archiveId), strZ(archiveFileRequest)), .repoIdx = cacheRepo->repoIdx, .archiveId = cacheArchive->archiveId, - .cipherType = cacheRepo->cipherType, - .cipherPassArchive = cacheRepo->cipherPassArchive, + .cipherSpecArchive = cacheRepo->cipherSpecArchive, }; lstAdd(matchList, &archiveGetFile); @@ -408,20 +405,18 @@ archiveGetCheck(const StringList *const archiveRequestList) ArchiveGetFindCacheRepo cacheRepo = { .repoIdx = repoIdx, - .cipherType = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), .archiveList = lstNewP(sizeof(ArchiveGetFindCacheArchive)), .warnList = strLstNew(), }; // Attempt to load the archive info file const InfoArchive *const info = infoArchiveLoadFile( - storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cacheRepo.cipherType, - cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); - // Copy cipher pass into the result list context once rather than making a copy per candidate file later + // Build cipher spec in the result list context once rather than rebuilding it per candidate file later MEM_CONTEXT_BEGIN(lstMemContext(result.archiveFileMapList)) { - cacheRepo.cipherPassArchive = strDup(infoArchiveCipherPass(info)); + cacheRepo.cipherSpecArchive = cipherSpecDup(infoArchiveCipherSpec(info)); } MEM_CONTEXT_END(); @@ -933,8 +928,7 @@ archiveGetAsyncCallback(void *const data, const unsigned int clientIdx) pckWriteStrP(param, actual->file); pckWriteU32P(param, actual->repoIdx); pckWriteStrP(param, actual->archiveId); - pckWriteU64P(param, actual->cipherType); - pckWriteStrP(param, actual->cipherPassArchive); + cipherSpecPack(param, actual->cipherSpecArchive); } MEM_CONTEXT_PRIOR_BEGIN() diff --git a/src/command/archive/get/protocol.c b/src/command/archive/get/protocol.c index 210e0368c..9def22757 100644 --- a/src/command/archive/get/protocol.c +++ b/src/command/archive/get/protocol.c @@ -38,8 +38,7 @@ archiveGetFileProtocol(PackRead *const param) ArchiveGetFile actual = {.file = pckReadStrP(param)}; actual.repoIdx = pckReadU32P(param); actual.archiveId = pckReadStrP(param); - actual.cipherType = pckReadU64P(param); - actual.cipherPassArchive = pckReadStrP(param); + actual.cipherSpecArchive = cipherSpecNewPack(param); lstAdd(actualList, &actual); } diff --git a/src/command/archive/push/file.c b/src/command/archive/push/file.c index a31fe0872..bf745df6b 100644 --- a/src/command/archive/push/file.c +++ b/src/command/archive/push/file.c @@ -266,11 +266,11 @@ archivePushFile( .compressible = compressible); // If there is a cipher then add the encrypt filter - if (repoData->cipherType != cipherTypeNone) + if (cipherSpecType(repoData->cipherSpecArchive) != cipherTypeNone) { ioFilterGroupAdd( ioWriteFilterGroup(storageWriteIo(destination[repoListIdx])), - cipherBlockNewP(cipherModeEncrypt, repoData->cipherType, BUFSTR(repoData->cipherPass))); + cipherBlockNewP(cipherModeEncrypt, repoData->cipherSpecArchive)); } } } diff --git a/src/command/archive/push/file.h b/src/command/archive/push/file.h index b63b5cdb1..c6635ac06 100644 --- a/src/command/archive/push/file.h +++ b/src/command/archive/push/file.h @@ -5,7 +5,7 @@ Archive Push File #define COMMAND_ARCHIVE_PUSH_FILE_H #include "common/compress/helper.h" -#include "common/crypto/common.h" +#include "common/crypto/spec.h" #include "common/type/string.h" #include "storage/storage.h" @@ -17,8 +17,7 @@ typedef struct ArchivePushFileRepoData { unsigned int repoIdx; const String *archiveId; - CipherType cipherType; - const String *cipherPass; + const CipherSpec *cipherSpecArchive; // Repo archive cipher spec } ArchivePushFileRepoData; /*********************************************************************************************************************************** diff --git a/src/command/archive/push/protocol.c b/src/command/archive/push/protocol.c index de34db84a..c564d13b4 100644 --- a/src/command/archive/push/protocol.c +++ b/src/command/archive/push/protocol.c @@ -48,8 +48,7 @@ archivePushFileProtocol(PackRead *const param) ArchivePushFileRepoData repo = {.repoIdx = pckReadU32P(param)}; repo.archiveId = pckReadStrP(param); - repo.cipherType = pckReadU64P(param); - repo.cipherPass = pckReadStrP(param); + repo.cipherSpecArchive = cipherSpecNewPack(param); pckReadObjEndP(param); lstAdd(repoList, &repo); diff --git a/src/command/archive/push/push.c b/src/command/archive/push/push.c index cd6c34f82..67f8a8805 100644 --- a/src/command/archive/push/push.c +++ b/src/command/archive/push/push.c @@ -230,13 +230,9 @@ archivePushCheck(const bool pgPathSet) // Get the repo storage in case it is remote and encryption settings need to be pulled down storageRepoIdx(repoIdx); - // Get cipher type - const CipherType repoCipherType = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx); - // Attempt to load the archive info file const InfoArchive *const info = infoArchiveLoadFile( - storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, repoCipherType, - cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); // Get archive id for the most recent version -- archive-push will only operate against the most recent version const String *const archiveId = infoPgArchiveId(infoArchivePg(info), infoPgDataCurrentId(infoArchivePg(info))); @@ -268,8 +264,7 @@ archivePushCheck(const bool pgPathSet) { .repoIdx = repoIdx, .archiveId = strDup(archiveId), - .cipherType = repoCipherType, - .cipherPass = strDup(infoArchiveCipherPass(info)), + .cipherSpecArchive = cipherSpecDup(infoArchiveCipherSpec(info)), }; lstAdd(result.repoList, &archivePushFileRepoData); @@ -493,8 +488,7 @@ archivePushAsyncCallback(void *const data, const unsigned int clientIdx) pckWriteObjBeginP(param); pckWriteU32P(param, data->repoIdx); pckWriteStrP(param, data->archiveId); - pckWriteU64P(param, data->cipherType); - pckWriteStrP(param, data->cipherPass); + cipherSpecPack(param, data->cipherSpecArchive); pckWriteObjEndP(param); } diff --git a/src/command/backup/backup.c b/src/command/backup/backup.c index 20a92b640..d37fa129c 100644 --- a/src/command/backup/backup.c +++ b/src/command/backup/backup.c @@ -165,9 +165,7 @@ backupInit(const InfoBackup *const infoBackup) // Get archive info if (cfgOptionBool(cfgOptArchiveCheck)) { - result->archiveInfo = infoArchiveLoadFile( - storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType), - cfgOptionStrNull(cfgOptRepoCipherPass)); + result->archiveInfo = infoArchiveLoadFile(storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMain()); result->archiveId = infoArchiveId(result->archiveInfo); } @@ -207,10 +205,9 @@ cmdBackup(void) storageRepo(); // Load backup.info - InfoBackup *const infoBackup = infoBackupLoadFileReconstruct( - storageRepo(), INFO_BACKUP_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType), cfgOptionStrNull(cfgOptRepoCipherPass)); + InfoBackup *const infoBackup = infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMain()); const InfoPgData infoPg = infoPgDataCurrent(infoBackupPg(infoBackup)); - const String *const cipherPassBackup = infoPgCipherPass(infoBackupPg(infoBackup)); + const CipherSpec *const cipherSpecManifest = infoBackupCipherSpec(infoBackup); // Get pg storage and database objects BackupData *const backupData = backupInit(infoBackup); @@ -239,14 +236,14 @@ cmdBackup(void) // Build an incremental backup if type is not full (manifestPrior will be freed in this call) if (!backupBuildIncr(infoBackup, manifest, manifestPrior, backupStartResult.walSegmentName)) - manifestCipherSubPassSet(manifest, cipherPassGen(cfgOptionStrId(cfgOptRepoCipherType))); + manifestCipherSpecSet(manifest, cipherSpecGen(cfgOptionStrId(cfgOptRepoCipherType))); // Set delta if it is not already set and the manifest requires it if (!cfgOptionBool(cfgOptDelta) && varBool(manifestData(manifest)->backupOptionDelta)) cfgOptionSet(cfgOptDelta, cfgSourceParam, BOOL_TRUE_VAR); // Resume a backup when possible - if (!backupResume(manifest, cipherPassBackup)) + if (!backupResume(manifest, cipherSpecManifest)) { manifestBackupLabelSet( manifest, @@ -255,10 +252,10 @@ cmdBackup(void) } // Save the manifest before processing starts - backupManifestSaveCopy(manifest, cipherPassBackup, false); + backupManifestSaveCopy(manifest, cipherSpecManifest, false); // Process the backup manifest - backupProcess(backupData, manifest, cipherPassBackup); + backupProcess(backupData, manifest, cipherSpecManifest); // Check that the clusters are alive and correctly configured after the backup backupDbPing(backupData, true); @@ -286,7 +283,7 @@ cmdBackup(void) dbFree(backupData->dbPrimary); // Check and copy WAL segments required to make the backup consistent - backupArchiveCheckCopy(backupData, manifest, cipherPassBackup); + backupArchiveCheckCopy(backupData, manifest, cipherSpecManifest); // The primary protocol connection won't be used anymore so free it. This needs to happen after backupArchiveCheckCopy() so // the backup lock is held on the remote which allows conditional archiving based on the backup lock. Any further access to diff --git a/src/command/backup/complete.c.inc b/src/command/backup/complete.c.inc index 34b6023c8..777f7e26c 100644 --- a/src/command/backup/complete.c.inc +++ b/src/command/backup/complete.c.inc @@ -3,11 +3,11 @@ Save a copy of the backup manifest during processing to preserve checksums for a resume is disabled since an incremental copy will not be used in a future backup unless resume is enabled beforehand. ***********************************************************************************************************************************/ static void -backupManifestSaveCopy(Manifest *const manifest, const String *const cipherPassBackup, const bool final) +backupManifestSaveCopy(Manifest *const manifest, const CipherSpec *const cipherSpecManifest, const bool final) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(MANIFEST, manifest); - FUNCTION_TEST_PARAM(STRING, cipherPassBackup); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest); FUNCTION_LOG_PARAM(BOOL, final); FUNCTION_LOG_END(); @@ -25,8 +25,7 @@ backupManifestSaveCopy(Manifest *const manifest, const String *const cipherPassB STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE INFO_COPY_EXT, strZ(manifestData(manifest)->backupLabel)))); // Add encryption filter if required - cipherBlockFilterGroupAdd( - ioWriteFilterGroup(write), cfgOptionStrId(cfgOptRepoCipherType), cipherModeEncrypt, cipherPassBackup); + cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherModeEncrypt, cipherSpecManifest); // Save file manifestSave(manifest, write); @@ -41,12 +40,12 @@ backupManifestSaveCopy(Manifest *const manifest, const String *const cipherPassB Check and copy WAL segments required to make the backup consistent ***********************************************************************************************************************************/ static void -backupArchiveCheckCopy(const BackupData *const backupData, Manifest *const manifest, const String *const cipherPassBackup) +backupArchiveCheckCopy(const BackupData *const backupData, Manifest *const manifest, const CipherSpec *const cipherSpecManifest) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(BACKUP_DATA, backupData); FUNCTION_LOG_PARAM(MANIFEST, manifest); - FUNCTION_TEST_PARAM(STRING, cipherPassBackup); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest); FUNCTION_LOG_END(); ASSERT(manifest != NULL); @@ -67,7 +66,7 @@ backupArchiveCheckCopy(const BackupData *const backupData, Manifest *const manif strZ(pgLsnToWalSegment(backupData->timeline, lsnStop, backupData->walSegmentSize))); // Save the backup manifest before getting archive logs in case of failure - backupManifestSaveCopy(manifest, cipherPassBackup, false); + backupManifestSaveCopy(manifest, cipherSpecManifest, false); // Use base path to set ownership and mode const ManifestPath *const basePath = manifestPathFind(manifest, MANIFEST_TARGET_PGDATA_STR); @@ -103,8 +102,7 @@ backupArchiveCheckCopy(const BackupData *const backupData, Manifest *const manif // Decrypt with archive key if encrypted cipherBlockFilterGroupAdd( - filterGroup, cfgOptionStrId(cfgOptRepoCipherType), cipherModeDecrypt, - infoArchiveCipherPass(backupData->archiveInfo)); + filterGroup, cipherModeDecrypt, infoArchiveCipherSpec(backupData->archiveInfo)); // Compress/decompress if archive and backup do not have the same compression settings if (archiveCompressType != backupCompressType) @@ -121,7 +119,7 @@ backupArchiveCheckCopy(const BackupData *const backupData, Manifest *const manif // Encrypt with backup key if encrypted cipherBlockFilterGroupAdd( - filterGroup, cfgOptionStrId(cfgOptRepoCipherType), cipherModeEncrypt, manifestCipherSubPass(manifest)); + filterGroup, cipherModeEncrypt, manifestCipherSpec(manifest)); // Add size filter last to calculate repo size ioFilterGroupAdd(filterGroup, ioSizeNew()); @@ -188,7 +186,7 @@ backupComplete(InfoBackup *const infoBackup, Manifest *const manifest) // ------------------------------------------------------------------------------------------------------------------------- manifestValidate(manifest, true); - backupManifestSaveCopy(manifest, infoPgCipherPass(infoBackupPg(infoBackup)), true); + backupManifestSaveCopy(manifest, infoBackupCipherSpec(infoBackup), true); storageCopy( storageNewReadP( @@ -204,8 +202,7 @@ backupComplete(InfoBackup *const infoBackup, Manifest *const manifest) storageRepo(), strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupLabel))); cipherBlockFilterGroupAdd( - ioReadFilterGroup(storageReadIo(manifestRead)), cfgOptionStrId(cfgOptRepoCipherType), cipherModeDecrypt, - infoPgCipherPass(infoBackupPg(infoBackup))); + ioReadFilterGroup(storageReadIo(manifestRead)), cipherModeDecrypt, infoBackupCipherSpec(infoBackup)); StorageWrite *const manifestWrite = storageNewWriteP( storageRepoWrite(), @@ -216,8 +213,7 @@ backupComplete(InfoBackup *const infoBackup, Manifest *const manifest) ioFilterGroupAdd(ioWriteFilterGroup(storageWriteIo(manifestWrite)), compressFilterP(compressTypeGz, 9)); cipherBlockFilterGroupAdd( - ioWriteFilterGroup(storageWriteIo(manifestWrite)), cfgOptionStrId(cfgOptRepoCipherType), cipherModeEncrypt, - infoPgCipherPass(infoBackupPg(infoBackup))); + ioWriteFilterGroup(storageWriteIo(manifestWrite)), cipherModeEncrypt, infoBackupCipherSpec(infoBackup)); storageCopyP(manifestRead, manifestWrite); @@ -233,19 +229,13 @@ backupComplete(InfoBackup *const infoBackup, Manifest *const manifest) // Add manifest and save backup.info (infoBackupSaveFile() is responsible for proper syncing) // ------------------------------------------------------------------------------------------------------------------------- infoBackupDataAdd(infoBackup, manifest); - - infoBackupSaveFile( - infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType), - cfgOptionStrNull(cfgOptRepoCipherPass)); + infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMain()); // Save archive.info/copy so the timestamps will be updated to prevent lifecycle settings from removing the files early // ------------------------------------------------------------------------------------------------------------------------- infoArchiveSaveFile( - infoArchiveLoadFile( - storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType), - cfgOptionStrNull(cfgOptRepoCipherPass)), - storageRepoWrite(), INFO_ARCHIVE_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType), - cfgOptionStrNull(cfgOptRepoCipherPass)); + infoArchiveLoadFile(storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMain()), storageRepoWrite(), + INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMain()); } MEM_CONTEXT_TEMP_END(); diff --git a/src/command/backup/db.c.inc b/src/command/backup/db.c.inc index 9ad7ba7f5..989d61f7f 100644 --- a/src/command/backup/db.c.inc +++ b/src/command/backup/db.c.inc @@ -221,12 +221,10 @@ backupFilePut( } // Add encryption filter if required - if (manifestCipherSubPass(manifest) != NULL) + if (cipherSpecType(manifestCipherSpec(manifest)) != cipherTypeNone) { ioFilterGroupAdd( - ioWriteFilterGroup(storageWriteIo(write)), - cipherBlockNewP( - cipherModeEncrypt, cfgOptionStrId(cfgOptRepoCipherType), BUFSTR(manifestCipherSubPass(manifest)))); + ioWriteFilterGroup(storageWriteIo(write)), cipherBlockNewP(cipherModeEncrypt, manifestCipherSpec(manifest))); repoChecksum = true; } diff --git a/src/command/backup/file.c.inc b/src/command/backup/file.c.inc index a4a93d005..0b93e9d2c 100644 --- a/src/command/backup/file.c.inc +++ b/src/command/backup/file.c.inc @@ -56,8 +56,8 @@ typedef struct BackupFileResult static List * backupFile( const String *const repoFile, const uint64_t bundleId, const bool bundleRaw, const unsigned int blockIncrReference, - const CompressType repoFileCompressType, const int repoFileCompressLevel, const CipherType cipherType, - const String *const cipherPass, const String *const pgVersionForce, const PgPageSize pageSize, const List *const fileList) + const CompressType repoFileCompressType, const int repoFileCompressLevel, const CipherSpec *const cipherSpecBackup, + const String *const pgVersionForce, const PgPageSize pageSize, const List *const fileList) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(STRING, repoFile); // Repo file @@ -66,15 +66,14 @@ backupFile( FUNCTION_LOG_PARAM(UINT, blockIncrReference); // Block incremental reference to use in map FUNCTION_LOG_PARAM(ENUM, repoFileCompressType); // Compress type for repo file FUNCTION_LOG_PARAM(INT, repoFileCompressLevel); // Compression level for repo file - FUNCTION_LOG_PARAM(STRING_ID, cipherType); // Encryption type - FUNCTION_TEST_PARAM(STRING, cipherPass); // Password to access the repo file if encrypted + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecBackup); // Cipher spec to encrypt the backup file FUNCTION_LOG_PARAM(ENUM, pageSize); // Page size FUNCTION_LOG_PARAM(STRING, pgVersionForce); // Force pg version FUNCTION_LOG_PARAM(LIST, fileList); // List of files to backup FUNCTION_LOG_END(); ASSERT(repoFile != NULL); - ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL)); + ASSERT(cipherSpecBackup != NULL); ASSERT(fileList != NULL && !lstEmpty(fileList)); ASSERT(pgPageSizeValid(pageSize)); @@ -217,7 +216,7 @@ backupFile( } // Are the files compressible during the copy? - const bool compressible = repoFileCompressType == compressTypeNone && cipherType == cipherTypeNone; + const bool compressible = repoFileCompressType == compressTypeNone && cipherSpecType(cipherSpecBackup) == cipherTypeNone; // Copy files that need to be copied StorageWrite *write = NULL; @@ -276,9 +275,9 @@ backupFile( // Encrypt filter IoFilter *const encrypt = - cipherType != cipherTypeNone ? + cipherSpecType(cipherSpecBackup) != cipherTypeNone ? cipherBlockNewP( - cipherModeEncrypt, cipherType, BUFSTR(cipherPass), .raw = bundleRaw || file->blockIncrSize != 0) : + cipherModeEncrypt, cipherSpecBackup, .raw = bundleRaw || file->blockIncrSize != 0) : NULL; // If block incremental then add the filter and pass compress/encrypt filters to it since each block is @@ -293,11 +292,11 @@ backupFile( blockMap = bufNew(0); IoWrite *const blockMapWrite = ioBufferWriteNew(blockMap); - if (cipherType != cipherTypeNone) + if (cipherSpecType(cipherSpecBackup) != cipherTypeNone) { ioFilterGroupAdd( ioWriteFilterGroup(blockMapWrite), - cipherBlockNewP(cipherModeDecrypt, cipherType, BUFSTR(cipherPass), .raw = true)); + cipherBlockNewP(cipherModeDecrypt, cipherSpecBackup, .raw = true)); } ioWriteOpen(blockMapWrite); diff --git a/src/command/backup/incr.c.inc b/src/command/backup/incr.c.inc index d0f542145..18a8ff8ee 100644 --- a/src/command/backup/incr.c.inc +++ b/src/command/backup/incr.c.inc @@ -46,7 +46,7 @@ backupBuildIncrPrior(const InfoBackup *const infoBackup) { result = manifestLoadFile( storageRepo(), strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupLabelPrior)), - cfgOptionStrId(cfgOptRepoCipherType), infoPgCipherPass(infoBackupPg(infoBackup))); + infoBackupCipherSpec(infoBackup)); const ManifestData *const manifestPriorData = manifestData(result); LOG_INFO_FMT( @@ -144,7 +144,7 @@ backupBuildIncr( manifestBuildIncr(manifest, manifestPrior, (BackupType)cfgOptionStrId(cfgOptType), archiveStart); // Set the cipher subpass from prior manifest since we want a single subpass for the entire backup set - manifestCipherSubPassSet(manifest, manifestCipherSubPass(manifestPrior)); + manifestCipherSpecSet(manifest, manifestCipherSpec(manifestPrior)); // Incremental was built result = true; diff --git a/src/command/backup/process.c.inc b/src/command/backup/process.c.inc index ddb16bdae..de3d9525d 100644 --- a/src/command/backup/process.c.inc +++ b/src/command/backup/process.c.inc @@ -333,8 +333,7 @@ typedef struct BackupJobData const String *const backupLabel; // Backup label (defines the backup path) const bool backupStandby; // Backup from standby RegExp *standbyExp; // Identify files that may be copied from the standby - const CipherType cipherType; // Cipher type - const String *const cipherSubPass; // Passphrase used to encrypt files in the backup + const CipherSpec *const cipherSpecBackup; // Cipher spec used to encrypt files in the backup const PgPageSize pageSize; // Page size const CompressType compressType; // Backup compression type const int compressLevel; // Compress level if backup is compressed @@ -685,8 +684,7 @@ backupJobCallback(void *const data, const unsigned int clientIdx) pckWriteU32P(param, jobData->compressType); pckWriteI32P(param, jobData->compressLevel); - pckWriteU64P(param, jobData->cipherSubPass == NULL ? cipherTypeNone : cipherTypeAes256Cbc); - pckWriteStrP(param, jobData->cipherSubPass); + cipherSpecPack(param, jobData->cipherSpecBackup); pckWriteU32P(param, jobData->pageSize); pckWriteStrP(param, cfgOptionStrNull(cfgOptPgVersionForce)); } @@ -771,12 +769,12 @@ backupJobCallback(void *const data, const unsigned int clientIdx) Process the backup manifest ***********************************************************************************************************************************/ static void -backupProcess(const BackupData *const backupData, Manifest *const manifest, const String *const cipherPassBackup) +backupProcess(const BackupData *const backupData, Manifest *const manifest, const CipherSpec *const cipherSpecManifest) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(BACKUP_DATA, backupData); FUNCTION_LOG_PARAM(MANIFEST, manifest); - FUNCTION_TEST_PARAM(STRING, cipherPassBackup); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest); FUNCTION_LOG_END(); ASSERT(manifest != NULL); @@ -799,8 +797,7 @@ backupProcess(const BackupData *const backupData, Manifest *const manifest, cons .backupStandby = backupData->dbStandby != NULL, .compressType = compressTypeEnum(cfgOptionStrId(cfgOptCompressType)), .compressLevel = cfgOptionInt(cfgOptCompressLevel), - .cipherType = cfgOptionStrId(cfgOptRepoCipherType), - .cipherSubPass = manifestCipherSubPass(manifest), + .cipherSpecBackup = manifestCipherSpec(manifest), .pageSize = backupData->pageSize, .delta = cfgOptionBool(cfgOptDelta), .bundle = cfgOptionBool(cfgOptRepoBundle), @@ -929,7 +926,7 @@ backupProcess(const BackupData *const backupData, Manifest *const manifest, cons // Save the manifest periodically to preserve checksums for resume if (sizeProgress - manifestSaveLast >= manifestSaveSize) { - backupManifestSaveCopy(manifest, cipherPassBackup, false); + backupManifestSaveCopy(manifest, cipherSpecManifest, false); manifestSaveLast = sizeProgress; } diff --git a/src/command/backup/protocol.c b/src/command/backup/protocol.c index aab9b77c8..88c0ed848 100644 --- a/src/command/backup/protocol.c +++ b/src/command/backup/protocol.c @@ -115,8 +115,7 @@ backupFileProtocol(PackRead *const param) const unsigned int blockIncrReference = (unsigned int)pckReadU64P(param); const CompressType repoFileCompressType = (CompressType)pckReadU32P(param); const int repoFileCompressLevel = pckReadI32P(param); - const CipherType cipherType = (CipherType)pckReadU64P(param); - const String *const cipherPass = pckReadStrP(param); + const CipherSpec *const cipherSpecBackup = cipherSpecNewPack(param); const PgPageSize pageSize = pckReadU32P(param); const String *const pgVersionForce = pckReadStrP(param); @@ -163,7 +162,7 @@ backupFileProtocol(PackRead *const param) // Backup file const List *const resultList = backupFile( - repoFile, bundleId, bundleRaw, blockIncrReference, repoFileCompressType, repoFileCompressLevel, cipherType, cipherPass, + repoFile, bundleId, bundleRaw, blockIncrReference, repoFileCompressType, repoFileCompressLevel, cipherSpecBackup, pgVersionForce, pageSize, fileList); // Return result diff --git a/src/command/backup/resume.c.inc b/src/command/backup/resume.c.inc index c3f896918..520d870b8 100644 --- a/src/command/backup/resume.c.inc +++ b/src/command/backup/resume.c.inc @@ -169,11 +169,11 @@ backupResumeClean( // Helper to find a resumable backup static const Manifest * -backupResumeFind(const Manifest *const manifest, const String *const cipherPassBackup) +backupResumeFind(const Manifest *const manifest, const CipherSpec *const cipherSpecManifest) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(MANIFEST, manifest); - FUNCTION_TEST_PARAM(STRING, cipherPassBackup); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest); FUNCTION_LOG_END(); ASSERT(manifest != NULL); @@ -217,8 +217,7 @@ backupResumeFind(const Manifest *const manifest, const String *const cipherPassB { TRY_BEGIN() { - manifestResume = manifestLoadFile( - storageRepo(), manifestFile, cfgOptionStrId(cfgOptRepoCipherType), cipherPassBackup); + manifestResume = manifestLoadFile(storageRepo(), manifestFile, cipherSpecManifest); } CATCH_ANY() { @@ -296,11 +295,11 @@ backupResumeFind(const Manifest *const manifest, const String *const cipherPassB } static bool -backupResume(Manifest *const manifest, const String *const cipherPassBackup) +backupResume(Manifest *const manifest, const CipherSpec *const cipherSpecManifest) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(MANIFEST, manifest); - FUNCTION_TEST_PARAM(STRING, cipherPassBackup); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest); FUNCTION_LOG_END(); ASSERT(manifest != NULL); @@ -309,7 +308,7 @@ backupResume(Manifest *const manifest, const String *const cipherPassBackup) MEM_CONTEXT_TEMP_BEGIN() { - const Manifest *const manifestResume = backupResumeFind(manifest, cipherPassBackup); + const Manifest *const manifestResume = backupResumeFind(manifest, cipherSpecManifest); // If a resumable backup was found set the label and cipher subpass if (manifestResume) @@ -325,7 +324,7 @@ backupResume(Manifest *const manifest, const String *const cipherPassBackup) strZ(manifestData(manifest)->backupLabel)); // Copy cipher subpass since it was used to encrypt the resumable files - manifestCipherSubPassSet(manifest, manifestCipherSubPass(manifestResume)); + manifestCipherSpecSet(manifest, manifestCipherSpec(manifestResume)); // Clean resumed backup const String *const backupPath = strNewFmt(STORAGE_REPO_BACKUP "/%s", strZ(manifestData(manifest)->backupLabel)); diff --git a/src/command/check/check.c b/src/command/check/check.c index de30e053c..28259223b 100644 --- a/src/command/check/check.c +++ b/src/command/check/check.c @@ -92,7 +92,7 @@ checkStandby(const DbGetResult dbGroup, const unsigned int pgPathDefinedTotal) // Check that the backup and archive info files exist and are valid for the current database of the stanza checkStanzaInfoPg( storageRepo, dbPgControl(dbGroup.standby).version, dbPgControl(dbGroup.standby).systemId, - cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + cfgCipherSpecMainIdx(repoIdx)); } LOG_INFO("switch wal not performed because this is a standby"); @@ -137,12 +137,11 @@ checkPrimary(const DbGetResult dbGroup) // Check that the backup and archive info files exist and are valid for the current database of the stanza checkStanzaInfoPg( storageRepo, dbPgControl(dbGroup.primary).version, dbPgControl(dbGroup.primary).systemId, - cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + cfgCipherSpecMainIdx(repoIdx)); // Attempt to load the archive info file and retrieve the archiveId const InfoArchive *const archiveInfo = infoArchiveLoadFile( - storageRepo, INFO_ARCHIVE_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), - cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + storageRepo, INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); repoArchiveId[repoIdx] = infoArchiveId(archiveInfo); } diff --git a/src/command/check/common.c b/src/command/check/common.c index e7f92cd71..d6f5e8e4b 100644 --- a/src/command/check/common.c +++ b/src/command/check/common.c @@ -124,15 +124,13 @@ checkStanzaInfo(const InfoPgData *const archiveInfo, const InfoPgData *const bac /**********************************************************************************************************************************/ FN_EXTERN void checkStanzaInfoPg( - const Storage *const storage, const unsigned int pgVersion, const uint64_t pgSystemId, const CipherType cipherType, - const String *const cipherPass) + const Storage *const storage, const unsigned int pgVersion, const uint64_t pgSystemId, const CipherSpec *const cipherSpecMain) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(STORAGE, storage); FUNCTION_TEST_PARAM(UINT, pgVersion); FUNCTION_TEST_PARAM(UINT64, pgSystemId); - FUNCTION_TEST_PARAM(STRING_ID, cipherType); - FUNCTION_TEST_PARAM(STRING, cipherPass); + FUNCTION_TEST_PARAM(CIPHER_SPEC, cipherSpecMain); FUNCTION_TEST_END(); ASSERT(storage != NULL); @@ -140,9 +138,9 @@ checkStanzaInfoPg( MEM_CONTEXT_TEMP_BEGIN() { // Check that the backup and archive info files exist - const InfoArchive *const infoArchive = infoArchiveLoadFile(storage, INFO_ARCHIVE_PATH_FILE_STR, cipherType, cipherPass); + const InfoArchive *const infoArchive = infoArchiveLoadFile(storage, INFO_ARCHIVE_PATH_FILE_STR, cipherSpecMain); const InfoPgData archiveInfoPg = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive))); - const InfoBackup *const infoBackup = infoBackupLoadFile(storage, INFO_BACKUP_PATH_FILE_STR, cipherType, cipherPass); + const InfoBackup *const infoBackup = infoBackupLoadFile(storage, INFO_BACKUP_PATH_FILE_STR, cipherSpecMain); const InfoPgData backupInfoPg = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup))); // Check that the info files pg data match each other diff --git a/src/command/check/common.h b/src/command/check/common.h index b926775db..6879b1fb3 100644 --- a/src/command/check/common.h +++ b/src/command/check/common.h @@ -4,6 +4,7 @@ Check Command Common #ifndef COMMAND_CHECK_COMMON_H #define COMMAND_CHECK_COMMON_H +#include "common/crypto/spec.h" #include "common/type/string.h" #include "db/db.h" #include "info/infoPg.h" @@ -19,7 +20,6 @@ FN_EXTERN void checkStanzaInfo(const InfoPgData *archiveInfo, const InfoPgData * // Load and validate the database data of the info files against each other and the current database FN_EXTERN void checkStanzaInfoPg( - const Storage *storage, const unsigned int pgVersion, const uint64_t pgSystemId, CipherType cipherType, - const String *cipherPass); + const Storage *storage, const unsigned int pgVersion, const uint64_t pgSystemId, const CipherSpec *cipherSpecMain); #endif diff --git a/src/command/expire/expire.c b/src/command/expire/expire.c index 6c018b2ff..eb78104b2 100644 --- a/src/command/expire/expire.c +++ b/src/command/expire/expire.c @@ -585,8 +585,7 @@ removeExpiredArchive(const InfoBackup *const infoBackup, const bool timeBasedFul { // Attempt to load the archive info file const InfoArchive *const infoArchive = infoArchiveLoadFile( - storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), - cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); const InfoPg *const infoArchivePgData = infoArchivePg(infoArchive); // Get a list of archive directories (e.g. 9.6-1, 10-2, etc) sorted by the db-id (number after the dash). @@ -897,8 +896,7 @@ removeExpiredBackup(const InfoBackup *const infoBackup, const String *const adho if (adhocBackupLabel != NULL && strBeginsWith(strLstGet(backupList, 0), strSubN(adhocBackupLabel, 0, 16))) { const Manifest *const manifestResume = manifestLoadFile( - storageRepoIdx(repoIdx), manifestFileName, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), - infoPgCipherPass(infoBackupPg(infoBackup))); + storageRepoIdx(repoIdx), manifestFileName, infoBackupCipherSpec(infoBackup)); // If the ancestor of the resumable backup no longer exists in backup.info then it can be removed if (!infoBackupLabelExists(infoBackup, manifestData(manifestResume)->backupLabelPrior)) @@ -1096,9 +1094,7 @@ cmdExpire(void) TRY_BEGIN() { // Load backup.info for this repo - infoBackup = infoBackupLoadFileReconstruct( - storageRepo, INFO_BACKUP_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), - cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + infoBackup = infoBackupLoadFileReconstruct(storageRepo, INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); // When expire oldest requested, expire the oldest full backup by lowering retention for this execution if (expireOldest) @@ -1180,8 +1176,7 @@ cmdExpire(void) if (!cfgOptionValid(cfgOptDryRun) || !cfgOptionBool(cfgOptDryRun)) { infoBackupSaveFile( - infoBackup, storageRepoIdxWrite(repoIdx), INFO_BACKUP_PATH_FILE_STR, - cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + infoBackup, storageRepoIdxWrite(repoIdx), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); } // Remove all files on disk that are now expired diff --git a/src/command/info/info.c b/src/command/info/info.c index 141e553c5..50be72ef1 100644 --- a/src/command/info/info.c +++ b/src/command/info/info.c @@ -132,7 +132,6 @@ typedef struct InfoRepoData { unsigned int key; // User-defined repo key CipherType cipher; // Encryption type - const String *cipherPass; // Passphrase if the repo is encrypted (else NULL) int stanzaStatus; // Status code of the stanza on this repo unsigned int backupIdx; // Index of the next backup that may be a candidate for sorting InfoBackup *backupInfo; // Contents of the backup.info file of the stanza on this repo @@ -1478,7 +1477,7 @@ infoUpdateStanza( // Attempt to load the backup info file stanzaRepo->repoList[repoIdx].backupInfo = infoBackupLoadFile( storage, strNewFmt(STORAGE_PATH_BACKUP "/%s/%s", strZ(stanzaRepo->name), INFO_BACKUP_FILE), - stanzaRepo->repoList[repoIdx].cipher, stanzaRepo->repoList[repoIdx].cipherPass); + cfgCipherSpecMainIdx(repoIdx)); } CATCH(FileMissingError) { @@ -1502,15 +1501,14 @@ infoUpdateStanza( { stanzaRepo->repoList[repoIdx].archiveInfo = infoArchiveLoadFile( storage, strNewFmt(STORAGE_PATH_ARCHIVE "/%s/%s", strZ(stanzaRepo->name), INFO_ARCHIVE_FILE), - stanzaRepo->repoList[repoIdx].cipher, stanzaRepo->repoList[repoIdx].cipherPass); + cfgCipherSpecMainIdx(repoIdx)); // If a specific backup exists on this repo then attempt to load the manifest if (backupLabel != NULL) { stanzaRepo->repoList[repoIdx].manifest = manifestLoadFile( storage, strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupLabel)), - stanzaRepo->repoList[repoIdx].cipher, - infoPgCipherPass(infoBackupPg(stanzaRepo->repoList[repoIdx].backupInfo))); + infoBackupCipherSpec(stanzaRepo->repoList[repoIdx].backupInfo)); } } } @@ -1600,7 +1598,6 @@ infoRender(void) { .key = cfgOptionGroupIdxToKey(cfgOptGrpRepo, repoIdx), .cipher = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), - .cipherPass = cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx), .error = NULL, }; @@ -1673,7 +1670,6 @@ infoRender(void) { .key = cfgOptionGroupIdxToKey(cfgOptGrpRepo, repoListIdx), .cipher = cfgOptionIdxStrId(cfgOptRepoCipherType, repoListIdx), - .cipherPass = cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoListIdx), .error = NULL, }; } diff --git a/src/command/manifest/manifest.c b/src/command/manifest/manifest.c index 35d83b449..20550db7e 100644 --- a/src/command/manifest/manifest.c +++ b/src/command/manifest/manifest.c @@ -231,12 +231,11 @@ cmdManifestBlockDeltaRender(const Manifest *const manifest, const ManifestFile * .offset = file->bundleOffset + file->sizeRepo - file->blockIncrMapSize, .limit = VARUINT64(file->blockIncrMapSize)); - if (manifestCipherSubPass(manifest) != NULL) + if (cipherSpecType(manifestCipherSpec(manifest)) != cipherTypeNone) { ioFilterGroupAdd( ioReadFilterGroup(storageReadIo(read)), - cipherBlockNewP( - cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTR(manifestCipherSubPass(manifest)), .raw = true)); + cipherBlockNewP(cipherModeDecrypt, manifestCipherSpec(manifest), .raw = true)); } ioReadOpen(storageReadIo(read)); @@ -442,16 +441,12 @@ cmdManifestRender(void) storageRepo(); // Load backup.info and cipher - const InfoBackup *const infoBackup = infoBackupLoadFile( - storageRepo(), INFO_BACKUP_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType), - cfgOptionStrNull(cfgOptRepoCipherPass)); - const String *const cipherPass = infoPgCipherPass(infoBackupPg(infoBackup)); - const CipherType cipherType = cipherPass == NULL ? cipherTypeNone : cipherTypeAes256Cbc; + const InfoBackup *const infoBackup = infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMain()); // Load manifest const Manifest *const manifest = manifestLoadFile( storageRepo(), strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(cfgOptionStr(cfgOptSet))), - cipherType, cipherPass); + infoBackupCipherSpec(infoBackup)); // Manifest info const ManifestData *const data = manifestData(manifest); diff --git a/src/command/repo/get.c b/src/command/repo/get.c index 5142e0a40..81a42e28a 100644 --- a/src/command/repo/get.c +++ b/src/command/repo/get.c @@ -56,18 +56,18 @@ storageGetProcess(IoWrite *const destination) { // Determine the passphrase using the following pattern: // - // REPO / (repo passphrase) - // / archive / (repo passphrase) + // REPO / (main passphrase) + // / archive / (main passphrase) // / archive / stanza / (archive passphrase) - // / backup / (repo passphrase) - // / backup / stanza / (backup passphrase) - // / backup / stanza / set / (manifest passphrase) - // / backup / stanza / backup.history / (backup passphrase) + // / backup / (main passphrase) + // / backup / stanza / (manifest passphrase) + // / backup / stanza / set / (backup passphrase) + // / backup / stanza / backup.history / (manifest passphrase) // // Nothing should be stored at the top level of the repo except the backup/archive paths. The backup/archive paths // should contain only stanza paths. // ----------------------------------------------------------------------------------------------------------------- - const String *cipherPass = NULL; + const CipherSpec *cipherSpec = NULL; const StringList *const filePathSplitLst = strLstNewSplit(file, FSLASH_STR); // At a minimum the path must contain archive/backup, a stanza, and a file @@ -86,32 +86,32 @@ storageGetProcess(IoWrite *const destination) // Archive path if (strEq(strLstGet(filePathSplitLst, 0), STORAGE_PATH_ARCHIVE_STR)) { - cipherPass = cfgOptionStr(cfgOptRepoCipherPass); + cipherSpec = cfgCipherSpecMain(); // Find the archive passphrase if (!strEndsWithZ(file, INFO_ARCHIVE_FILE) && !strEndsWithZ(file, INFO_ARCHIVE_FILE INFO_COPY_EXT)) { const InfoArchive *const info = infoArchiveLoadFile( storageRepo(), strNewFmt(STORAGE_PATH_ARCHIVE "/%s/%s", strZ(stanza), INFO_ARCHIVE_FILE), - repoCipherType, cipherPass); - cipherPass = infoArchiveCipherPass(info); + cfgCipherSpecMain()); + cipherSpec = infoArchiveCipherSpec(info); } } // Backup path if (strEq(strLstGet(filePathSplitLst, 0), STORAGE_PATH_BACKUP_STR)) { - cipherPass = cfgOptionStr(cfgOptRepoCipherPass); + cipherSpec = cfgCipherSpecMain(); if (!strEndsWithZ(file, INFO_BACKUP_FILE) && !strEndsWithZ(file, INFO_BACKUP_FILE INFO_COPY_EXT)) { - // Find the backup passphrase + // Find the manifest passphrase const InfoBackup *const info = infoBackupLoadFile( storageRepo(), strNewFmt(STORAGE_PATH_BACKUP "/%s/%s", strZ(stanza), INFO_BACKUP_FILE), - repoCipherType, cipherPass); - cipherPass = infoBackupCipherPass(info); + cfgCipherSpecMain()); + const CipherSpec *const cipherSpecManifest = infoBackupCipherSpec(info); - // Find the manifest passphrase + // Find the backup passphrase if not a manifest if (!strEq(strLstGet(filePathSplitLst, 2), STRDEF(BACKUP_PATH_HISTORY)) && !strEndsWithZ(file, BACKUP_MANIFEST_FILE) && !strEndsWithZ(file, BACKUP_MANIFEST_FILE INFO_COPY_EXT)) @@ -121,19 +121,24 @@ storageGetProcess(IoWrite *const destination) strNewFmt( STORAGE_PATH_BACKUP "/%s/%s/%s", strZ(stanza), strZ(strLstGet(filePathSplitLst, 2)), BACKUP_MANIFEST_FILE), - repoCipherType, cipherPass); - cipherPass = manifestCipherSubPass(manifest); + cipherSpecManifest); + cipherSpec = manifestCipherSpec(manifest); } + // Else use the manifest passphrase + else + cipherSpec = cipherSpecManifest; } } } // Error when unable to determine cipher passphrase - if (cipherPass == NULL) + if (cipherSpec == NULL) THROW_FMT(OptionInvalidValueError, "unable to determine cipher passphrase for '%s'", strZ(file)); + ASSERT(cipherSpecType(cipherSpec) != cipherTypeNone); + // Add encryption filter - cipherBlockFilterGroupAdd(ioReadFilterGroup(source), repoCipherType, cipherModeDecrypt, cipherPass); + cipherBlockFilterGroupAdd(ioReadFilterGroup(source), cipherModeDecrypt, cipherSpec); } } diff --git a/src/command/restore/blockDelta.c b/src/command/restore/blockDelta.c index 344e69049..ff83b9993 100644 --- a/src/command/restore/blockDelta.c +++ b/src/command/restore/blockDelta.c @@ -32,8 +32,7 @@ struct BlockDelta BlockDeltaPub pub; // Publicly accessible variables size_t blockSize; // Block size size_t checksumSize; // Checksum size - CipherType cipherType; // Cipher type - String *cipherPass; // Cipher passphrase + const CipherSpec *cipherSpecBackup; // Cipher spec CompressType compressType; // Compress type const BlockDeltaSuperBlock *superBlockData; // Current super block data @@ -57,21 +56,20 @@ typedef struct BlockDeltaReference FN_EXTERN BlockDelta * blockDeltaNew( const BlockMap *const blockMap, const size_t blockSize, const size_t checksumSize, const Buffer *const blockChecksum, - const CipherType cipherType, const String *const cipherPass, const CompressType compressType) + const CipherSpec *const cipherSpecBackup, const CompressType compressType) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(BLOCK_MAP, blockMap); FUNCTION_TEST_PARAM(SIZE, blockSize); FUNCTION_TEST_PARAM(SIZE, checksumSize); FUNCTION_TEST_PARAM(BUFFER, blockChecksum); - FUNCTION_TEST_PARAM(STRING_ID, cipherType); - FUNCTION_TEST_PARAM(STRING, cipherPass); + FUNCTION_TEST_PARAM(CIPHER_SPEC, cipherSpecBackup); FUNCTION_TEST_PARAM(ENUM, compressType); FUNCTION_TEST_END(); ASSERT(blockMap != NULL); ASSERT(blockSize > 0); - ASSERT(cipherType == cipherTypeNone || cipherPass != NULL); + ASSERT(cipherSpecBackup != NULL); OBJ_NEW_BEGIN(BlockDelta, .childQty = MEM_CONTEXT_QTY_MAX) { @@ -83,8 +81,7 @@ blockDeltaNew( }, .blockSize = blockSize, .checksumSize = checksumSize, - .cipherType = cipherType, - .cipherPass = strDup(cipherPass), + .cipherSpecBackup = cipherSpecDup(cipherSpecBackup), .compressType = compressType, .write = { @@ -237,11 +234,10 @@ blockDeltaNext(BlockDelta *const this, const BlockDeltaRead *const readDelta, Io } MEM_CONTEXT_OBJ_END(); - if (this->cipherType != cipherTypeNone) + if (cipherSpecType(this->cipherSpecBackup) != cipherTypeNone) { ioFilterGroupAdd( - ioReadFilterGroup(this->limitRead), - cipherBlockNewP(cipherModeDecrypt, this->cipherType, BUFSTR(this->cipherPass), .raw = true)); + ioReadFilterGroup(this->limitRead), cipherBlockNewP(cipherModeDecrypt, this->cipherSpecBackup, .raw = true)); } if (this->compressType != compressTypeNone) diff --git a/src/command/restore/blockDelta.h b/src/command/restore/blockDelta.h index 5cacf03c2..d2c4f345f 100644 --- a/src/command/restore/blockDelta.h +++ b/src/command/restore/blockDelta.h @@ -9,7 +9,7 @@ optional because the file to restore may not exist so all the blocks will need t #include "command/backup/blockMap.h" #include "common/compress/helper.h" -#include "common/crypto/common.h" +#include "common/crypto/spec.h" /*********************************************************************************************************************************** Object type @@ -37,8 +37,8 @@ typedef struct BlockDeltaWrite Constructors ***********************************************************************************************************************************/ FN_EXTERN BlockDelta *blockDeltaNew( - const BlockMap *blockMap, size_t blockSize, size_t checksumSize, const Buffer *blockChecksum, CipherType cipherType, - const String *cipherPass, const CompressType compressType); + const BlockMap *blockMap, size_t blockSize, size_t checksumSize, const Buffer *blockChecksum, + const CipherSpec *cipherSpecBackup, const CompressType compressType); /*********************************************************************************************************************************** Functions diff --git a/src/command/restore/file.c.inc b/src/command/restore/file.c.inc index 29eabae75..fd98327ea 100644 --- a/src/command/restore/file.c.inc +++ b/src/command/restore/file.c.inc @@ -30,7 +30,7 @@ typedef struct RestoreFileResult static List * restoreFile( const String *const repoFile, const unsigned int repoIdx, const CompressType repoFileCompressType, const time_t copyTimeBegin, - const bool delta, const bool deltaForce, const bool bundleRaw, const String *const cipherPass, + const bool delta, const bool deltaForce, const bool bundleRaw, const CipherSpec *const cipherSpecBackup, const StringList *const referenceList, List *const fileList) { FUNCTION_LOG_BEGIN(logLevelDebug); @@ -41,7 +41,7 @@ restoreFile( FUNCTION_LOG_PARAM(BOOL, delta); FUNCTION_LOG_PARAM(BOOL, deltaForce); FUNCTION_LOG_PARAM(BOOL, bundleRaw); - FUNCTION_TEST_PARAM(STRING, cipherPass); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecBackup); FUNCTION_LOG_PARAM(STRING_LIST, referenceList); // List of references (for block incremental) FUNCTION_LOG_PARAM(LIST, fileList); // List of files to restore FUNCTION_LOG_END(); @@ -220,7 +220,9 @@ restoreFile( if (fileResult->result == restoreResultCopy) { storageReadMultiAddP( - repoFileRead, repoFile, .compressible = repoFileCompressType == compressTypeNone && cipherPass == NULL, + repoFileRead, repoFile, + .compressible = + repoFileCompressType == compressTypeNone && cipherSpecType(cipherSpecBackup) == cipherTypeNone, .offset = file->offset, .limit = file->limit); } } @@ -259,11 +261,10 @@ restoreFile( // blocks need to be fetched from the repository. If we got here there must be at least one block to fetch. IoRead *const blockMapRead = ioLimitReadNew(storageReadMultiIo(repoFileRead), varUInt64(file->limit)); - if (cipherPass != NULL) + if (cipherSpecType(cipherSpecBackup) != cipherTypeNone) { ioFilterGroupAdd( - ioReadFilterGroup(blockMapRead), - cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTR(cipherPass), .raw = true)); + ioReadFilterGroup(blockMapRead), cipherBlockNewP(cipherModeDecrypt, cipherSpecBackup, .raw = true)); } ioReadOpen(blockMapRead); @@ -278,8 +279,8 @@ restoreFile( // Apply delta to file BlockDelta *const blockDelta = blockDeltaNew( - blockMap, file->blockIncrSize, file->blockIncrChecksumSize, file->blockChecksum, - cipherPass == NULL ? cipherTypeNone : cipherTypeAes256Cbc, cipherPass, repoFileCompressType); + blockMap, file->blockIncrSize, file->blockIncrChecksumSize, file->blockChecksum, cipherSpecBackup, + repoFileCompressType); for (unsigned int readIdx = 0; readIdx < blockDeltaReadSize(blockDelta); readIdx++) { @@ -333,11 +334,9 @@ restoreFile( IoFilterGroup *const filterGroup = ioWriteFilterGroup(storageWriteIo(pgFileWrite)); // Add decryption filter - if (cipherPass != NULL) + if (cipherSpecType(cipherSpecBackup) != cipherTypeNone) { - ioFilterGroupAdd( - filterGroup, - cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTR(cipherPass), .raw = bundleRaw)); + ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, cipherSpecBackup, .raw = bundleRaw)); } // Add decompression filter diff --git a/src/command/restore/process.c.inc b/src/command/restore/process.c.inc index 5667d9c78..84ab1bbab 100644 --- a/src/command/restore/process.c.inc +++ b/src/command/restore/process.c.inc @@ -336,7 +336,7 @@ typedef struct RestoreJobData Manifest *manifest; // Backup manifest List *queueList; // List of processing queues RegExp *zeroExp; // Identify files that should be sparse zeroed - const String *cipherSubPass; // Passphrase used to decrypt files in the backup + const CipherSpec *cipherSpecBackup; // Cipher spec used to decrypt files in the backup const String *rootReplaceUser; // User to replace invalid users when root const String *rootReplaceGroup; // Group to replace invalid group when root } RestoreJobData; @@ -429,7 +429,7 @@ restoreJobCallback(void *const data, const unsigned int clientIdx) pckWriteBoolP(param, cfgOptionBool(cfgOptDelta)); pckWriteBoolP(param, cfgOptionBool(cfgOptDelta) && cfgOptionBool(cfgOptForce)); pckWriteBoolP(param, file.bundleId != 0 && manifestData(jobData->manifest)->bundleRaw); - pckWriteStrP(param, jobData->cipherSubPass); + cipherSpecPack(param, jobData->cipherSpecBackup); pckWriteStrLstP(param, manifestReferenceList(jobData->manifest)); fileAdded = true; diff --git a/src/command/restore/protocol.c b/src/command/restore/protocol.c index f75a9dab1..79958bea9 100644 --- a/src/command/restore/protocol.c +++ b/src/command/restore/protocol.c @@ -46,7 +46,7 @@ restoreFileProtocol(PackRead *const param) const bool delta = pckReadBoolP(param); const bool deltaForce = pckReadBoolP(param); const bool bundleRaw = pckReadBoolP(param); - const String *const cipherPass = pckReadStrP(param); + const CipherSpec *const cipherSpecBackup = cipherSpecNewPack(param); const StringList *const referenceList = pckReadStrLstP(param); // Build the file list @@ -85,7 +85,7 @@ restoreFileProtocol(PackRead *const param) // Restore files const List *const resultList = restoreFile( - repoFile, repoIdx, repoFileCompressType, copyTimeBegin, delta, deltaForce, bundleRaw, cipherPass, referenceList, + repoFile, repoIdx, repoFileCompressType, copyTimeBegin, delta, deltaForce, bundleRaw, cipherSpecBackup, referenceList, fileList); // Return result diff --git a/src/command/restore/restore.c b/src/command/restore/restore.c index 6e11f6ec0..80936082d 100644 --- a/src/command/restore/restore.c +++ b/src/command/restore/restore.c @@ -11,6 +11,7 @@ Restore Command #include "command/restore/timeline.h" #include "common/regExp.h" #include "common/user.h" +#include "config/config.h" #include "config/exec.h" #include "info/infoArchive.h" #include "info/infoBackup.h" @@ -58,24 +59,21 @@ cmdRestore(void) jobData.manifest = manifestLoadFile( storageRepoIdx(backupData.repoIdx), - strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupData.backupSet)), backupData.repoCipherType, - backupData.backupCipherPass); + strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupData.backupSet)), backupData.cipherSpecManifest); // Verify that the selected timeline is valid for the backup -- including current and latest timelines if (manifestData(jobData.manifest)->backupOptionOnline) { const ManifestData *const data = manifestData(jobData.manifest); const InfoArchive *const archiveInfo = infoArchiveLoadFile( - storageRepoIdx(backupData.repoIdx), INFO_ARCHIVE_PATH_FILE_STR, - cfgOptionIdxStrId(cfgOptRepoCipherType, backupData.repoIdx), - cfgOptionIdxStrNull(cfgOptRepoCipherPass, backupData.repoIdx)); + storageRepoIdx(backupData.repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(backupData.repoIdx)); timelineVerify( storageRepoIdx(backupData.repoIdx), strNewFmt("%s-%u", strZ(pgVersionToStr(data->pgVersion)), data->pgId), data->pgVersion, cvtZToUIntBase(strZ(strSubN(data->archiveStart, 0, 8)), 16), pgLsnFromStr(data->lsnStart), cfgOptionStrNull(cfgOptTargetTimeline), cfgOptionSeq(cfgOptType), - cfgOptionIdxStrId(cfgOptRepoCipherType, backupData.repoIdx), infoArchiveCipherPass(archiveInfo)); + infoArchiveCipherSpec(archiveInfo)); } // Remotes (if any) are no longer needed since the rest of the repository reads will be done by the local processes @@ -91,8 +89,8 @@ cmdRestore(void) // Validate manifest. Don't use strict mode because we'd rather ignore problems that won't affect a restore. manifestValidate(jobData.manifest, false); - // Get the cipher subpass used to decrypt files in the backup - jobData.cipherSubPass = manifestCipherSubPass(jobData.manifest); + // Get the cipher spec used to decrypt files in the backup + jobData.cipherSpecBackup = manifestCipherSpec(jobData.manifest); // Validate the manifest restoreManifestValidate(jobData.manifest, backupData.backupSet); diff --git a/src/command/restore/select.c.inc b/src/command/restore/select.c.inc index 5dba02f90..0acbae549 100644 --- a/src/command/restore/select.c.inc +++ b/src/command/restore/select.c.inc @@ -4,8 +4,7 @@ Get the backup set to restore typedef struct RestoreBackupData { unsigned int repoIdx; // Internal repo index - CipherType repoCipherType; // Repo encryption type (0 = none) - const String *backupCipherPass; // Passphrase of backup files if repo is encrypted (else NULL) + const CipherSpec *cipherSpecManifest; // Cipher spec to open the manifest, none when not encrypted const String *backupSet; // Backup set to restore } RestoreBackupData; @@ -16,7 +15,7 @@ typedef struct RestoreBackupData // Helper function for restoreBackupSet static RestoreBackupData -restoreBackupData(const String *const backupLabel, const unsigned int repoIdx, const String *const backupCipherPass) +restoreBackupData(const String *const backupLabel, const unsigned int repoIdx, const CipherSpec *const cipherSpecManifest) { ASSERT(backupLabel != NULL); @@ -26,8 +25,7 @@ restoreBackupData(const String *const backupLabel, const unsigned int repoIdx, c { restoreBackup.backupSet = strDup(backupLabel); restoreBackup.repoIdx = repoIdx; - restoreBackup.repoCipherType = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx); - restoreBackup.backupCipherPass = strDup(backupCipherPass); + restoreBackup.cipherSpecManifest = cipherSpecDup(cipherSpecManifest); } MEM_CONTEXT_PRIOR_END(); @@ -103,9 +101,7 @@ restoreBackupSet(void) // Attempt to load backup.info TRY_BEGIN() { - infoBackup = infoBackupLoadFile( - storageRepoIdx(repoIdx), INFO_BACKUP_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), - cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + infoBackup = infoBackupLoadFile(storageRepoIdx(repoIdx), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); } CATCH_ANY() { @@ -160,7 +156,7 @@ restoreBackupSet(void) { found = true; - result = restoreBackupData(backupData.backupLabel, repoIdx, infoPgCipherPass(infoBackupPg(infoBackup))); + result = restoreBackupData(backupData.backupLabel, repoIdx, infoBackupCipherSpec(infoBackup)); break; } } @@ -187,7 +183,7 @@ restoreBackupSet(void) strZ(latestBackup.backupLabel)); } - result = restoreBackupData(latestBackup.backupLabel, repoIdx, infoPgCipherPass(infoBackupPg(infoBackup))); + result = restoreBackupData(latestBackup.backupLabel, repoIdx, infoBackupCipherSpec(infoBackup)); break; } } @@ -198,7 +194,7 @@ restoreBackupSet(void) { if (strEq(infoBackupData(infoBackup, backupIdx).backupLabel, backupSetRequested)) { - result = restoreBackupData(backupSetRequested, repoIdx, infoPgCipherPass(infoBackupPg(infoBackup))); + result = restoreBackupData(backupSetRequested, repoIdx, infoBackupCipherSpec(infoBackup)); break; } } diff --git a/src/command/restore/timeline.c b/src/command/restore/timeline.c index e9fe5086b..dd7f71289 100644 --- a/src/command/restore/timeline.c +++ b/src/command/restore/timeline.c @@ -78,15 +78,14 @@ Load history file ***********************************************************************************************************************************/ static List * historyLoad( - const Storage *const storageRepo, const String *const archiveId, const unsigned int timeline, const CipherType cipherType, - const String *const cipherPass) + const Storage *const storageRepo, const String *const archiveId, const unsigned int timeline, + const CipherSpec *const cipherSpecArchive) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(STORAGE, storageRepo); FUNCTION_LOG_PARAM(STRING, archiveId); FUNCTION_LOG_PARAM(UINT, timeline); - FUNCTION_LOG_PARAM(STRING_ID, cipherType); - FUNCTION_LOG_PARAM(STRING, cipherPass); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecArchive); FUNCTION_LOG_END(); List *result; @@ -95,7 +94,7 @@ historyLoad( { const String *const historyFile = strNewFmt(STORAGE_REPO_ARCHIVE "/%s/%08X.history", strZ(archiveId), timeline); StorageRead *const storageRead = storageNewReadP(storageRepo, historyFile); - cipherBlockFilterGroupAdd(ioReadFilterGroup(storageReadIo(storageRead)), cipherType, cipherModeDecrypt, cipherPass); + cipherBlockFilterGroupAdd(ioReadFilterGroup(storageReadIo(storageRead)), cipherModeDecrypt, cipherSpecArchive); const Buffer *const history = storageGetP(storageRead); TRY_BEGIN() @@ -159,7 +158,7 @@ FN_EXTERN void timelineVerify( const Storage *const storageRepo, const String *const archiveId, const unsigned int pgVersion, const unsigned int timelineBackup, const uint64_t lsnBackup, const String *timelineTargetStr, const unsigned int recoveryType, - const CipherType cipherType, const String *const cipherPass) + const CipherSpec *const cipherSpecArchive) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(STORAGE, storageRepo); @@ -169,8 +168,7 @@ timelineVerify( FUNCTION_LOG_PARAM(UINT64, lsnBackup); FUNCTION_LOG_PARAM(STRING, timelineTargetStr); FUNCTION_LOG_PARAM(UINT, recoveryType); - FUNCTION_LOG_PARAM(STRING_ID, cipherType); - FUNCTION_LOG_PARAM(STRING, cipherPass); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecArchive); FUNCTION_LOG_END(); ASSERT(storageRepo != NULL); @@ -223,7 +221,7 @@ timelineVerify( { // Search through the history for the target timeline to make sure it includes the backup timeline. This follows // the logic in PostgreSQL's readTimeLineHistory() and tliOfPointInHistory() but is a bit simplified for our usage. - const List *const historyList = historyLoad(storageRepo, archiveId, timelineTarget, cipherType, cipherPass); + const List *const historyList = historyLoad(storageRepo, archiveId, timelineTarget, cipherSpecArchive); unsigned int timelineFound = 0; for (unsigned int historyIdx = 0; historyIdx < lstSize(historyList); historyIdx++) diff --git a/src/command/restore/timeline.h b/src/command/restore/timeline.h index 312522205..8b8fc4528 100644 --- a/src/command/restore/timeline.h +++ b/src/command/restore/timeline.h @@ -4,7 +4,7 @@ Timeline Management #ifndef COMMAND_RESTORE_TIMELINE_H #define COMMAND_RESTORE_TIMELINE_H -#include "common/crypto/common.h" +#include "common/crypto/spec.h" #include "storage/storage.h" /*********************************************************************************************************************************** @@ -12,8 +12,7 @@ Functions ***********************************************************************************************************************************/ // Verify that target timeline is valid for a backup FN_EXTERN void timelineVerify( - const Storage *storageRepo, const String *archiveId, unsigned int pgVersion, unsigned int timelineBackup, - uint64_t lsnBackup, const String *timelineTargetStr, unsigned int recoveryType, CipherType cipherType, - const String *cipherPass); + const Storage *storageRepo, const String *archiveId, unsigned int pgVersion, unsigned int timelineBackup, uint64_t lsnBackup, + const String *timelineTargetStr, unsigned int recoveryType, const CipherSpec *cipherSpecArchive); #endif diff --git a/src/command/stanza/common.c b/src/command/stanza/common.c index 9bcb32792..cdb7feb38 100644 --- a/src/command/stanza/common.c +++ b/src/command/stanza/common.c @@ -15,24 +15,32 @@ Stanza Commands Handler #include "storage/helper.h" /**********************************************************************************************************************************/ -FN_EXTERN String * -cipherPassGen(const CipherType cipherType) +FN_EXTERN CipherSpec * +cipherSpecGen(const CipherType cipherType) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(STRING_ID, cipherType); FUNCTION_TEST_END(); - String *result = NULL; + CipherSpec *result; - if (cipherType != cipherTypeNone) + if (cipherType == cipherTypeNone) + result = cipherSpecNewNone(); + else { - uint8_t buffer[48]; // 48 is the amount of entropy needed to get a 64 base key - cryptoRandomBytes(buffer, sizeof(buffer)); + MEM_CONTEXT_TEMP_BEGIN() + { + uint8_t buffer[48]; // 48 is the amount of entropy needed to get a 64 base key + cryptoRandomBytes(buffer, sizeof(buffer)); - result = strNewEncode(encodingBase64, BUF(buffer, sizeof(buffer))); + // The pass is the encoded text rather than the bytes it encodes, so it is stored and derived from as that text + result = cipherSpecNew(cipherType, BUFSTR(strNewEncode(encodingBase64, BUF(buffer, sizeof(buffer))))); + cipherSpecMove(result, memContextPrior()); + } + MEM_CONTEXT_TEMP_END(); } - FUNCTION_TEST_RETURN(STRING, result); + FUNCTION_TEST_RETURN(CIPHER_SPEC, result); } /**********************************************************************************************************************************/ diff --git a/src/command/stanza/common.h b/src/command/stanza/common.h index 6cd3cc083..225ca5ee3 100644 --- a/src/command/stanza/common.h +++ b/src/command/stanza/common.h @@ -10,8 +10,8 @@ Stanza Commands Handler /*********************************************************************************************************************************** Functions ***********************************************************************************************************************************/ -// Generate a cipher -FN_EXTERN String *cipherPassGen(CipherType cipherType); +// Generate cipher spec with a new pass, none when the type is none +FN_EXTERN CipherSpec *cipherSpecGen(CipherType cipherType); // Validate and return database information FN_EXTERN PgControl pgValidate(void); diff --git a/src/command/stanza/create.c b/src/command/stanza/create.c index e147bcf8d..f40f43778 100644 --- a/src/command/stanza/create.c +++ b/src/command/stanza/create.c @@ -75,33 +75,27 @@ cmdStanzaCreate(void) } // If the repo is encrypted, generate a cipher passphrase for encrypting subsequent archive files - const String *cipherPassSub = cipherPassGen(cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx)); + const CipherSpec *const cipherSpecArchive = cipherSpecGen(cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx)); // Create and save archive info - infoArchive = infoArchiveNew(pgControl.version, pgControl.systemId, cipherPassSub); + infoArchive = infoArchiveNew(pgControl.version, pgControl.systemId, cipherSpecArchive); - infoArchiveSaveFile( - infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR, - cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + infoArchiveSaveFile(infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); - // If the repo is encrypted, generate a cipher passphrase for encrypting subsequent backup files - cipherPassSub = cipherPassGen(cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx)); + // If the repo is encrypted, generate a cipher passphrase for encrypting subsequent manifests + const CipherSpec *const cipherSpecManifest = cipherSpecGen(cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx)); // Create and save backup info - infoBackup = infoBackupNew(pgControl.version, pgControl.systemId, pgControl.catalogVersion, cipherPassSub); + infoBackup = infoBackupNew(pgControl.version, pgControl.systemId, pgControl.catalogVersion, cipherSpecManifest); - infoBackupSaveFile( - infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, - cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + infoBackupSaveFile(infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); } // Else if at least one archive and one backup info file exists, then ensure both are valid else if ((archiveInfoFileExists || archiveInfoFileCopyExists) && (backupInfoFileExists || backupInfoFileCopyExists)) { // Error if there is a mismatch between the archive and backup info files or the database version/system Id matches // current database - checkStanzaInfoPg( - storageRepoReadStanza, pgControl.version, pgControl.systemId, - cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + checkStanzaInfoPg(storageRepoReadStanza, pgControl.version, pgControl.systemId, cfgCipherSpecMainIdx(repoIdx)); // The files are valid - upgrade const String *sourceFile = NULL; diff --git a/src/command/stanza/upgrade.c b/src/command/stanza/upgrade.c index b9b16d4c0..45a3cb81f 100644 --- a/src/command/stanza/upgrade.c +++ b/src/command/stanza/upgrade.c @@ -51,13 +51,11 @@ cmdStanzaUpgrade(void) // Load the info files (errors if missing) InfoArchive *const infoArchive = infoArchiveLoadFile( - storageRepoReadStanza, INFO_ARCHIVE_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), - cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + storageRepoReadStanza, INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); InfoPgData archiveInfo = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive))); InfoBackup *const infoBackup = infoBackupLoadFile( - storageRepoReadStanza, INFO_BACKUP_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), - cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); + storageRepoReadStanza, INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); InfoPgData backupInfo = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup))); // Since the file save of archive.info and backup.info are not atomic, then check and update each separately. @@ -83,19 +81,11 @@ cmdStanzaUpgrade(void) // Save archive info if (infoArchiveUpgrade) - { - infoArchiveSaveFile( - infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR, - cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); - } + infoArchiveSaveFile(infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); // Save backup info if (infoBackupUpgrade) - { - infoBackupSaveFile( - infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), - cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx)); - } + infoBackupSaveFile(infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx)); if (!(infoArchiveUpgrade || infoBackupUpgrade)) { diff --git a/src/command/verify/file.c b/src/command/verify/file.c index c05d0edbe..3566a7e4c 100644 --- a/src/command/verify/file.c +++ b/src/command/verify/file.c @@ -18,7 +18,7 @@ Verify File FN_EXTERN VerifyResult verifyFile( const String *const filePathName, const uint64_t offset, const Variant *const limit, const CompressType compressType, - const Buffer *const fileChecksum, const uint64_t fileSize, const String *const cipherPass) + const Buffer *const fileChecksum, const uint64_t fileSize, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(STRING, filePathName); // Fully qualified file name @@ -27,7 +27,7 @@ verifyFile( FUNCTION_LOG_PARAM(ENUM, compressType); // Compression type FUNCTION_LOG_PARAM(BUFFER, fileChecksum); // Checksum for the file FUNCTION_LOG_PARAM(UINT64, fileSize); // Size of file - FUNCTION_TEST_PARAM(STRING, cipherPass); // Password to access the repo file if encrypted + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); // Cipher spec to access the repo file if encrypted FUNCTION_LOG_END(); ASSERT(filePathName != NULL); @@ -45,8 +45,8 @@ verifyFile( IoFilterGroup *const filterGroup = ioReadFilterGroup(read); // Add decryption filter - if (cipherPass != NULL) - ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTR(cipherPass))); + if (cipherSpecType(cipherSpec) != cipherTypeNone) + ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, cipherSpec)); // Add decompression filter if (compressType != compressTypeNone) diff --git a/src/command/verify/file.h b/src/command/verify/file.h index a330ba714..0d5def6d3 100644 --- a/src/command/verify/file.h +++ b/src/command/verify/file.h @@ -5,7 +5,7 @@ Verify File #define COMMAND_VERIFY_FILE_H #include "common/compress/helper.h" -#include "common/crypto/common.h" +#include "common/crypto/spec.h" /*********************************************************************************************************************************** File result @@ -25,6 +25,6 @@ Functions // Verify a file in the pgBackRest repository FN_EXTERN VerifyResult verifyFile( const String *filePathName, uint64_t offset, const Variant *limit, CompressType compressType, const Buffer *fileChecksum, - uint64_t fileSize, const String *cipherPass); + uint64_t fileSize, const CipherSpec *cipherSpec); #endif diff --git a/src/command/verify/protocol.c b/src/command/verify/protocol.c index 3e55f2f42..e63149111 100644 --- a/src/command/verify/protocol.c +++ b/src/command/verify/protocol.c @@ -41,12 +41,12 @@ verifyFileProtocol(PackRead *const param) const CompressType compressType = (CompressType)pckReadU32P(param); const Buffer *const fileChecksum = pckReadBinP(param); const uint64_t fileSize = pckReadU64P(param); - const String *const cipherPass = pckReadStrP(param); + const CipherSpec *const cipherSpec = cipherSpecNewPack(param); // Return result pckWriteU32P( protocolServerResultData(result), - verifyFile(filePathName, offset, limit, compressType, fileChecksum, fileSize, cipherPass)); + verifyFile(filePathName, offset, limit, compressType, fileChecksum, fileSize, cipherSpec)); } MEM_CONTEXT_TEMP_END(); diff --git a/src/command/verify/verify.c b/src/command/verify/verify.c index 51111b4f6..dd045b53f 100644 --- a/src/command/verify/verify.c +++ b/src/command/verify/verify.c @@ -123,9 +123,8 @@ typedef struct VerifyJobData String *currentBackup; // In progress backup, if any const InfoPg *pgHistory; // Database history list bool backupProcessing; // Are we processing WAL or are we processing backups - const String *manifestCipherPass; // Cipher pass for reading backup manifests - const String *walCipherPass; // Cipher pass for reading WAL files - const String *backupCipherPass; // Cipher pass for reading backup files referenced in a manifest + const CipherSpec *cipherSpecManifest; // Cipher spec for reading backup manifests + const CipherSpec *cipherSpecArchive; // Cipher spec for reading WAL files unsigned int jobErrorTotal; // Total errors that occurred during the job execution List *archiveIdResultList; // Archive results List *backupResultList; // Backup results @@ -168,11 +167,11 @@ verifyInvalidFileAdd(List *const invalidFileList, const VerifyResult reason, con Load a file into memory ***********************************************************************************************************************************/ static StorageRead * -verifyFileLoad(const String *const pathFileName, const String *const cipherPass) +verifyFileLoad(const String *const pathFileName, const CipherSpec *const cipherSpec) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(STRING, pathFileName); // Fully qualified path/file name - FUNCTION_TEST_PARAM(STRING, cipherPass); // Password to open file if encrypted + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); // Cipher spec to open file if encrypted FUNCTION_TEST_END(); ASSERT(pathFileName != NULL); @@ -183,8 +182,7 @@ verifyFileLoad(const String *const pathFileName, const String *const cipherPass) // *read points to a location within result so update result with contents based on necessary filters IoRead *const read = storageReadIo(result); - cipherBlockFilterGroupAdd( - ioReadFilterGroup(read), cfgOptionStrId(cfgOptRepoCipherType), cipherModeDecrypt, cipherPass); + cipherBlockFilterGroupAdd(ioReadFilterGroup(read), cipherModeDecrypt, cipherSpec); ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(hashTypeSha1)); // If the file is compressed, add a decompression filter @@ -198,12 +196,12 @@ verifyFileLoad(const String *const pathFileName, const String *const cipherPass) Get status of info files in the repository ***********************************************************************************************************************************/ static VerifyInfoFile -verifyInfoFile(const String *const pathFileName, const bool keepFile, const String *const cipherPass) +verifyInfoFile(const String *const pathFileName, const bool keepFile, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(STRING, pathFileName); // Fully qualified path/file name FUNCTION_LOG_PARAM(BOOL, keepFile); // Should the file be kept in memory? - FUNCTION_TEST_PARAM(STRING, cipherPass); // Password to open file if encrypted + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); // Cipher spec to open file if encrypted FUNCTION_LOG_END(); FUNCTION_AUDIT_STRUCT(); @@ -216,17 +214,17 @@ verifyInfoFile(const String *const pathFileName, const bool keepFile, const Stri { TRY_BEGIN() { - IoRead *const infoRead = storageReadIo(verifyFileLoad(pathFileName, cipherPass)); + IoRead *const infoRead = storageReadIo(verifyFileLoad(pathFileName, cipherSpec)); // If directed to keep the loaded file in memory, then move the file into the result, else drain the io and close it if (keepFile) { if (strBeginsWith(pathFileName, INFO_BACKUP_PATH_FILE_STR)) - result.backup = infoBackupMove(infoBackupNewLoad(infoRead), memContextPrior()); + result.backup = infoBackupMove(infoBackupNewLoad(infoRead, cipherSpec), memContextPrior()); else if (strBeginsWith(pathFileName, INFO_ARCHIVE_PATH_FILE_STR)) - result.archive = infoArchiveMove(infoArchiveNewLoad(infoRead), memContextPrior()); + result.archive = infoArchiveMove(infoArchiveNewLoad(infoRead, cipherSpec), memContextPrior()); else - result.manifest = manifestMove(manifestNewLoad(infoRead), memContextPrior()); + result.manifest = manifestMove(manifestNewLoad(infoRead, cipherSpec), memContextPrior()); } else ioReadDrain(infoRead); @@ -270,8 +268,7 @@ verifyArchiveInfoFile(void) MEM_CONTEXT_TEMP_BEGIN() { // Get the main info file - const VerifyInfoFile verifyArchiveInfo = verifyInfoFile( - INFO_ARCHIVE_PATH_FILE_STR, true, cfgOptionStrNull(cfgOptRepoCipherPass)); + const VerifyInfoFile verifyArchiveInfo = verifyInfoFile(INFO_ARCHIVE_PATH_FILE_STR, true, cfgCipherSpecMain()); // If the main file did not error, then report on the copy's status and check checksums if (verifyArchiveInfo.errorCode == 0) @@ -281,7 +278,7 @@ verifyArchiveInfoFile(void) // Attempt to load the copy and report on it's status but don't keep it in memory const VerifyInfoFile verifyArchiveInfoCopy = verifyInfoFile( - INFO_ARCHIVE_PATH_FILE_COPY_STR, false, cfgOptionStrNull(cfgOptRepoCipherPass)); + INFO_ARCHIVE_PATH_FILE_COPY_STR, false, cfgCipherSpecMain()); // If the copy loaded successfully, then check the checksums if (verifyArchiveInfoCopy.errorCode == 0) @@ -295,8 +292,7 @@ verifyArchiveInfoFile(void) else { // Attempt to load the copy - const VerifyInfoFile verifyArchiveInfoCopy = verifyInfoFile( - INFO_ARCHIVE_PATH_FILE_COPY_STR, true, cfgOptionStrNull(cfgOptRepoCipherPass)); + const VerifyInfoFile verifyArchiveInfoCopy = verifyInfoFile(INFO_ARCHIVE_PATH_FILE_COPY_STR, true, cfgCipherSpecMain()); // If loaded successfully, then return the copy as usable if (verifyArchiveInfoCopy.errorCode == 0) @@ -324,8 +320,7 @@ verifyBackupInfoFile(void) MEM_CONTEXT_TEMP_BEGIN() { // Get the main info file - const VerifyInfoFile verifyBackupInfo = verifyInfoFile( - INFO_BACKUP_PATH_FILE_STR, true, cfgOptionStrNull(cfgOptRepoCipherPass)); + const VerifyInfoFile verifyBackupInfo = verifyInfoFile(INFO_BACKUP_PATH_FILE_STR, true, cfgCipherSpecMain()); // If the main file did not error, then report on the copy's status and check checksums if (verifyBackupInfo.errorCode == 0) @@ -334,8 +329,7 @@ verifyBackupInfoFile(void) infoBackupMove(result, memContextPrior()); // Attempt to load the copy and report on it's status but don't keep it in memory - const VerifyInfoFile verifyBackupInfoCopy = verifyInfoFile( - INFO_BACKUP_PATH_FILE_COPY_STR, false, cfgOptionStrNull(cfgOptRepoCipherPass)); + const VerifyInfoFile verifyBackupInfoCopy = verifyInfoFile(INFO_BACKUP_PATH_FILE_COPY_STR, false, cfgCipherSpecMain()); // If the copy loaded successfully, then check the checksums if (verifyBackupInfoCopy.errorCode == 0) @@ -349,8 +343,7 @@ verifyBackupInfoFile(void) else { // Attempt to load the copy - const VerifyInfoFile verifyBackupInfoCopy = verifyInfoFile( - INFO_BACKUP_PATH_FILE_COPY_STR, true, cfgOptionStrNull(cfgOptRepoCipherPass)); + const VerifyInfoFile verifyBackupInfoCopy = verifyInfoFile(INFO_BACKUP_PATH_FILE_COPY_STR, true, cfgCipherSpecMain()); // If loaded successfully, then return the copy as usable if (verifyBackupInfoCopy.errorCode == 0) @@ -370,12 +363,12 @@ Get the manifest file ***********************************************************************************************************************************/ static Manifest * verifyManifestFile( - VerifyBackupResult *const backupResult, const String *const cipherPass, bool currentBackup, const InfoPg *const pgHistory, - unsigned int *const jobErrorTotal) + VerifyBackupResult *const backupResult, const CipherSpec *const cipherSpecManifest, bool currentBackup, + const InfoPg *const pgHistory, unsigned int *const jobErrorTotal) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM_P(VERIFY_BACKUP_RESULT, backupResult); // The result set for the backup being processed - FUNCTION_TEST_PARAM(STRING, cipherPass); // Passphrase to access the manifest file + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest); // Cipher spec to access the manifest file FUNCTION_LOG_PARAM(BOOL, currentBackup); // Is this possibly a backup currently in progress? FUNCTION_LOG_PARAM(INFO_PG, pgHistory); // Database history FUNCTION_LOG_PARAM_P(UINT, jobErrorTotal); // Pointer to the overall job error total @@ -388,7 +381,7 @@ verifyManifestFile( const String *const fileName = strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupResult->backupLabel)); // Get the main manifest file - const VerifyInfoFile verifyManifestInfo = verifyInfoFile(fileName, true, cipherPass); + const VerifyInfoFile verifyManifestInfo = verifyInfoFile(fileName, true, cipherSpecManifest); // If the main file did not error, then report on the copy's status and check checksums if (verifyManifestInfo.errorCode == 0) @@ -402,7 +395,7 @@ verifyManifestFile( // Attempt to load the copy and report on it's status but don't keep it in memory const VerifyInfoFile verifyManifestInfoCopy = verifyInfoFile( - strNewFmt("%s%s", strZ(fileName), INFO_COPY_EXT), false, cipherPass); + strNewFmt("%s%s", strZ(fileName), INFO_COPY_EXT), false, cipherSpecManifest); // If the copy loaded successfully, then check the checksums if (verifyManifestInfoCopy.errorCode == 0) @@ -423,7 +416,7 @@ verifyManifestFile( currentBackup = false; const VerifyInfoFile verifyManifestInfoCopy = verifyInfoFile( - strNewFmt("%s%s", strZ(fileName), INFO_COPY_EXT), true, cipherPass); + strNewFmt("%s%s", strZ(fileName), INFO_COPY_EXT), true, cipherSpecManifest); // If loaded successfully, then return the copy as usable if (verifyManifestInfoCopy.errorCode == 0) @@ -662,7 +655,7 @@ verifyBackupSet(VerifyJobData *const jobData, const String *const backupLabel) { const Manifest *const manifest = manifestLoadFile( storageRepo(), strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupLabel)), - cfgOptionStrId(cfgOptRepoCipherType), jobData->manifestCipherPass); + jobData->cipherSpecManifest); // Check files for block incremental bool hasBlockIncr = false; @@ -836,7 +829,7 @@ verifyArchive(VerifyJobData *const jobData) strNewFmt( STORAGE_REPO_ARCHIVE "/%s/%s/%s", strZ(archiveResult->archiveId), strZ(walPath), strZ(strLstGet(jobData->walFileList, 0))), - jobData->walCipherPass); + jobData->cipherSpecArchive); const PgWal walInfo = pgWalFromBuffer( storageGetP(walRead, .exactSize = PG_WAL_HEADER_SIZE), cfgOptionStrNull(cfgOptPgVersionForce)); @@ -872,7 +865,7 @@ verifyArchive(VerifyJobData *const jobData) pckWriteU32P(param, compressTypeFromName(filePathName)); pckWriteBinP(param, checksum); pckWriteU64P(param, archiveResult->pgWalInfo.size); - pckWriteStrP(param, jobData->walCipherPass); + cipherSpecPack(param, jobData->cipherSpecArchive); // Assign job to result, prepending the archiveId to the key for consistency with backup processing const String *const jobKey = strNewFmt("%s/%s", strZ(archiveResult->archiveId), strZ(filePathName)); @@ -973,7 +966,7 @@ verifyBackup(VerifyJobData *const jobData) // Get a usable backup manifest file Manifest *const manifest = verifyManifestFile( - backupResult, jobData->manifestCipherPass, inProgressBackup, jobData->pgHistory, &jobData->jobErrorTotal); + backupResult, jobData->cipherSpecManifest, inProgressBackup, jobData->pgHistory, &jobData->jobErrorTotal); // If a usable backup.manifest file is not found if (manifest == NULL) @@ -989,15 +982,7 @@ verifyBackup(VerifyJobData *const jobData) { // Move the manifest to the jobData for processing jobData->manifest = manifestMove(manifest, jobData->memContext); - - // Initialize the jobData - MEM_CONTEXT_BEGIN(jobData->memContext) - { - // Get the cipher subpass used to decrypt files in the backup and initialize the file list index - jobData->backupCipherPass = strDup(manifestCipherSubPass(jobData->manifest)); - jobData->manifestFileIdx = 0; - } - MEM_CONTEXT_END(); + jobData->manifestFileIdx = 0; const ManifestData *const manData = manifestData(jobData->manifest); @@ -1114,7 +1099,7 @@ verifyBackup(VerifyJobData *const jobData) pckWriteU32P(param, compressTypeNone); pckWriteBinP(param, BUF(fileData.checksumRepoSha1, HASH_TYPE_SHA1_SIZE)); pckWriteU64P(param, fileData.sizeRepo); - pckWriteStrP(param, NULL); + cipherSpecPack(param, cipherSpecNewNone()); } // Else use the file checksum, which may require additional filters, e.g. decompression else @@ -1122,7 +1107,7 @@ verifyBackup(VerifyJobData *const jobData) pckWriteU32P(param, manifestData(jobData->manifest)->backupOptionCompressType); pckWriteBinP(param, BUF(fileData.checksumSha1, HASH_TYPE_SHA1_SIZE)); pckWriteU64P(param, fileData.size); - pckWriteStrP(param, jobData->backupCipherPass); + cipherSpecPack(param, manifestCipherSpec(jobData->manifest)); } // Assign job to result (prepend backup label being processed to the key since some files are in a prior @@ -1639,8 +1624,8 @@ verifyProcess(const bool verboseText) .walPathList = NULL, .walFileList = strLstNew(), .pgHistory = infoArchivePg(archiveInfo), - .manifestCipherPass = infoPgCipherPass(infoBackupPg(backupInfo)), - .walCipherPass = infoPgCipherPass(infoArchivePg(archiveInfo)), + .cipherSpecManifest = infoBackupCipherSpec(backupInfo), + .cipherSpecArchive = infoArchiveCipherSpec(archiveInfo), .archiveIdResultList = lstNewP(sizeof(VerifyArchiveResult), .comparator = archiveIdComparator), .backupResultList = lstNewP(sizeof(VerifyBackupResult), .comparator = lstComparatorStr), }; diff --git a/src/common/crypto/cipherBlock.c b/src/common/crypto/cipherBlock.c index a087c4de0..bd3ff3557 100644 --- a/src/common/crypto/cipherBlock.c +++ b/src/common/crypto/cipherBlock.c @@ -384,25 +384,24 @@ cipherBlockInputSame(const THIS_VOID) /**********************************************************************************************************************************/ FN_EXTERN IoFilter * -cipherBlockNew(const CipherMode mode, const CipherType cipherType, const Buffer *const pass, const CipherBlockNewParam param) +cipherBlockNew(const CipherMode mode, const CipherSpec *const cipherSpec, const CipherBlockNewParam param) { FUNCTION_LOG_BEGIN(logLevelTrace); FUNCTION_LOG_PARAM(STRING_ID, mode); - FUNCTION_LOG_PARAM(STRING_ID, cipherType); - FUNCTION_TEST_PARAM(BUFFER, pass); // Use FUNCTION_TEST so passphrase is not logged - FUNCTION_LOG_PARAM(STRING, param.digest); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_PARAM(BOOL, param.raw); FUNCTION_LOG_END(); - ASSERT(pass != NULL); - ASSERT(!bufEmpty(pass)); + ASSERT(cipherSpec != NULL); + ASSERT(cipherSpecType(cipherSpec) != cipherTypeNone); + ASSERT(cipherSpecPass(cipherSpec) != NULL && !bufEmpty(cipherSpecPass(cipherSpec))); // Init crypto subsystem cryptoInit(); // Lookup cipher by name. This means the ciphers passed in must exactly match a name expected by OpenSSL. This is a good thing // since the name required by the openssl command-line tool will match what is used by pgBackRest. - char *const cipherTypeZ = zNewStrId(cipherType); + char *const cipherTypeZ = zNewStrId(cipherSpecType(cipherSpec)); const EVP_CIPHER *cipher = EVP_get_cipherbyname(cipherTypeZ); if (!cipher) @@ -410,17 +409,6 @@ cipherBlockNew(const CipherMode mode, const CipherType cipherType, const Buffer zFree(cipherTypeZ); - // Lookup digest. If not defined it will be set to sha1. - const EVP_MD *digest = NULL; - - if (param.digest) - digest = EVP_get_digestbyname(strZ(param.digest)); - else - digest = EVP_sha1(); - - if (!digest) - THROW_FMT(AssertError, "unable to load digest '%s'", strZ(param.digest)); - OBJ_NEW_BEGIN(CipherBlock, .childQty = MEM_CONTEXT_QTY_MAX, .callbackQty = 1) { *this = (CipherBlock) @@ -428,8 +416,10 @@ cipherBlockNew(const CipherMode mode, const CipherType cipherType, const Buffer .mode = mode, .raw = param.raw, .cipher = cipher, - .digest = digest, - .pass = bufDup(pass), + + // The key is always derived with SHA-1. Deriving it with anything else is not supported yet. + .digest = EVP_sha1(), + .pass = bufDup(cipherSpecPass(cipherSpec)), }; } OBJ_NEW_END(); @@ -442,9 +432,7 @@ cipherBlockNew(const CipherMode mode, const CipherType cipherType, const Buffer PackWrite *const packWrite = pckWriteNewP(); pckWriteU64P(packWrite, mode); - pckWriteU64P(packWrite, cipherType); - pckWriteBinP(packWrite, pass); - pckWriteStrP(packWrite, param.digest); + cipherSpecPack(packWrite, cipherSpec); pckWriteBoolP(packWrite, param.raw); pckWriteEndP(packWrite); @@ -468,12 +456,10 @@ cipherBlockNewPack(const Pack *const paramList) { PackRead *const paramListPack = pckReadNew(paramList); const CipherMode cipherMode = (CipherMode)pckReadU64P(paramListPack); - const CipherType cipherType = (CipherType)pckReadU64P(paramListPack); - const Buffer *const pass = pckReadBinP(paramListPack); - const String *const digest = pckReadStrP(paramListPack); + const CipherSpec *const cipherSpec = cipherSpecNewPack(paramListPack); const bool raw = pckReadBoolP(paramListPack); - result = ioFilterMove(cipherBlockNewP(cipherMode, cipherType, pass, .digest = digest, .raw = raw), memContextPrior()); + result = ioFilterMove(cipherBlockNewP(cipherMode, cipherSpec, .raw = raw), memContextPrior()); } MEM_CONTEXT_TEMP_END(); @@ -482,20 +468,19 @@ cipherBlockNewPack(const Pack *const paramList) /**********************************************************************************************************************************/ FN_EXTERN IoFilterGroup * -cipherBlockFilterGroupAdd(IoFilterGroup *const filterGroup, const CipherType type, const CipherMode mode, const String *const pass) +cipherBlockFilterGroupAdd(IoFilterGroup *const filterGroup, const CipherMode mode, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelTrace); FUNCTION_LOG_PARAM(IO_FILTER_GROUP, filterGroup); - FUNCTION_LOG_PARAM(STRING_ID, type); FUNCTION_LOG_PARAM(STRING_ID, mode); - FUNCTION_TEST_PARAM(STRING, pass); // Use FUNCTION_TEST so passphrase is not logged + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_END(); ASSERT(filterGroup != NULL); - ASSERT((type == cipherTypeNone && pass == NULL) || (type != cipherTypeNone && pass != NULL)); + ASSERT(cipherSpec != NULL); - if (type != cipherTypeNone) - ioFilterGroupAdd(filterGroup, cipherBlockNewP(mode, type, BUFSTR(pass))); + if (cipherSpecType(cipherSpec) != cipherTypeNone) + ioFilterGroupAdd(filterGroup, cipherBlockNewP(mode, cipherSpec)); FUNCTION_LOG_RETURN(IO_FILTER_GROUP, filterGroup); } diff --git a/src/common/crypto/cipherBlock.h b/src/common/crypto/cipherBlock.h index af9659270..ad28a2614 100644 --- a/src/common/crypto/cipherBlock.h +++ b/src/common/crypto/cipherBlock.h @@ -4,7 +4,7 @@ Block Cipher Header #ifndef COMMON_CRYPTO_CIPHERBLOCK_H #define COMMON_CRYPTO_CIPHERBLOCK_H -#include "common/crypto/common.h" +#include "common/crypto/spec.h" #include "common/io/filter/group.h" /*********************************************************************************************************************************** @@ -18,21 +18,19 @@ Constructors typedef struct CipherBlockNewParam { VAR_PARAM_HEADER; - const String *digest; // Digest to use (defaults to SHA-1) bool raw; // Omit header magic to save space } CipherBlockNewParam; -#define cipherBlockNewP(mode, cipherType, pass, ...) \ - cipherBlockNew(mode, cipherType, pass, (CipherBlockNewParam){VAR_PARAM_INIT, __VA_ARGS__}) +#define cipherBlockNewP(mode, cipherSpec, ...) \ + cipherBlockNew(mode, cipherSpec, (CipherBlockNewParam){VAR_PARAM_INIT, __VA_ARGS__}) -FN_EXTERN IoFilter *cipherBlockNew(CipherMode mode, CipherType cipherType, const Buffer *pass, CipherBlockNewParam param); +FN_EXTERN IoFilter *cipherBlockNew(CipherMode mode, const CipherSpec *cipherSpec, CipherBlockNewParam param); FN_EXTERN IoFilter *cipherBlockNewPack(const Pack *paramList); /*********************************************************************************************************************************** Helper functions ***********************************************************************************************************************************/ -// Add a block cipher to an io object -FN_EXTERN IoFilterGroup *cipherBlockFilterGroupAdd( - IoFilterGroup *filterGroup, CipherType type, CipherMode mode, const String *pass); +// Add a block cipher to an io object. Nothing is added when the repository is not encrypted. +FN_EXTERN IoFilterGroup *cipherBlockFilterGroupAdd(IoFilterGroup *filterGroup, CipherMode mode, const CipherSpec *cipherSpec); #endif diff --git a/src/common/crypto/spec.c b/src/common/crypto/spec.c new file mode 100644 index 000000000..76627b8af --- /dev/null +++ b/src/common/crypto/spec.c @@ -0,0 +1,96 @@ +/*********************************************************************************************************************************** +Cipher Spec +***********************************************************************************************************************************/ +#include + +#include "common/crypto/spec.h" +#include "common/debug.h" +#include "common/log.h" + +/*********************************************************************************************************************************** +Object type +***********************************************************************************************************************************/ +struct CipherSpec +{ + CipherSpecPub pub; // Publicly accessible variables +}; + +/**********************************************************************************************************************************/ +FN_EXTERN CipherSpec * +cipherSpecNew(const CipherType type, const Buffer *const pass) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(STRING_ID, type); + FUNCTION_TEST_PARAM(BUFFER, pass); + FUNCTION_TEST_END(); + + ASSERT((type == cipherTypeNone) == (pass == NULL)); + ASSERT(pass == NULL || !bufEmpty(pass)); + + OBJ_NEW_BEGIN(CipherSpec, .childQty = MEM_CONTEXT_QTY_MAX) + { + *this = (CipherSpec){.pub = {.type = type}}; + + if (this->pub.type != cipherTypeNone) + this->pub.pass = bufDup(pass); + } + OBJ_NEW_END(); + + FUNCTION_TEST_RETURN(CIPHER_SPEC, this); +} + +/**********************************************************************************************************************************/ +FN_EXTERN CipherSpec * +cipherSpecNewPack(PackRead *const packRead) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(PACK_READ, packRead); + FUNCTION_TEST_END(); + + ASSERT(packRead != NULL); + + OBJ_NEW_BEGIN(CipherSpec, .childQty = MEM_CONTEXT_QTY_MAX) + { + *this = (CipherSpec){.pub = {.type = (CipherType)pckReadStrIdP(packRead)}}; + + // Nothing else was written when there is no cipher. The pass is read here rather than copied in since this context is the + // one it belongs in. + if (this->pub.type != cipherTypeNone) + this->pub.pass = pckReadBinP(packRead); + } + OBJ_NEW_END(); + + FUNCTION_TEST_RETURN(CIPHER_SPEC, this); +} + +/**********************************************************************************************************************************/ +FN_EXTERN void +cipherSpecPack(PackWrite *const packWrite, const CipherSpec *const this) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(PACK_WRITE, packWrite); + FUNCTION_TEST_PARAM(CIPHER_SPEC, this); + FUNCTION_TEST_END(); + + ASSERT(packWrite != NULL); + ASSERT(this != NULL); + + pckWriteStrIdP(packWrite, cipherSpecType(this)); + + // Nothing else is needed when there is no cipher + if (cipherSpecType(this) != cipherTypeNone) + pckWriteBinP(packWrite, cipherSpecPass(this)); + + FUNCTION_TEST_RETURN_VOID(); +} + +/**********************************************************************************************************************************/ +FN_EXTERN void +cipherSpecToLog(const CipherSpec *const this, StringStatic *const debugLog) +{ + char typeZ[STRID_MAX + 1]; + strIdToZ(cipherSpecType(this), typeZ); + + // The pass is never logged + strStcFmt(debugLog, "{type: %s}", typeZ); +} diff --git a/src/common/crypto/spec.h b/src/common/crypto/spec.h new file mode 100644 index 000000000..003c9ca2b --- /dev/null +++ b/src/common/crypto/spec.h @@ -0,0 +1,101 @@ +/*********************************************************************************************************************************** +Cipher Spec + +Everything needed to encrypt or decrypt, kept together so that adding to it does not mean changing every function and protocol +message that carries it. + +The passphrase (pass) contains the bytes the key is derived from. There is no pass when the type is none, and the pass is never +logged. +***********************************************************************************************************************************/ +#ifndef COMMON_CRYPTO_SPEC_H +#define COMMON_CRYPTO_SPEC_H + +/*********************************************************************************************************************************** +Object type +***********************************************************************************************************************************/ +typedef struct CipherSpec CipherSpec; + +#include "common/crypto/common.h" +#include "common/type/buffer.h" +#include "common/type/object.h" +#include "common/type/pack.h" + +/*********************************************************************************************************************************** +Constructors +***********************************************************************************************************************************/ +// Create from a pass +FN_EXTERN CipherSpec *cipherSpecNew(CipherType type, const Buffer *pass); + +// Create for no encryption +FN_INLINE_ALWAYS CipherSpec * +cipherSpecNewNone(void) +{ + return cipherSpecNew(cipherTypeNone, NULL); +} + +// Create from a pack written by cipherSpecPack() +FN_EXTERN CipherSpec *cipherSpecNewPack(PackRead *packRead); + +/*********************************************************************************************************************************** +Getters/Setters +***********************************************************************************************************************************/ +typedef struct CipherSpecPub +{ + CipherType type; // Cipher type, none when not encrypted + const Buffer *pass; // Passphrase text or key bytes +} CipherSpecPub; + +// Cipher type +FN_INLINE_ALWAYS CipherType +cipherSpecType(const CipherSpec *const this) +{ + return THIS_PUB(CipherSpec)->type; +} + +// Passphrase text or key bytes +FN_INLINE_ALWAYS const Buffer * +cipherSpecPass(const CipherSpec *const this) +{ + return THIS_PUB(CipherSpec)->pass; +} + +/*********************************************************************************************************************************** +Functions +***********************************************************************************************************************************/ +// Duplicate +FN_INLINE_ALWAYS CipherSpec * +cipherSpecDup(const CipherSpec *const this) +{ + return cipherSpecNew(cipherSpecType(this), cipherSpecPass(this)); +} + +// Write to a pack so it can be passed over a protocol +FN_EXTERN void cipherSpecPack(PackWrite *packWrite, const CipherSpec *this); + +// Move to a new parent mem context +FN_INLINE_ALWAYS CipherSpec * +cipherSpecMove(CipherSpec *const this, MemContext *const parentNew) +{ + return objMove(this, parentNew); +} + +/*********************************************************************************************************************************** +Destructor +***********************************************************************************************************************************/ +FN_INLINE_ALWAYS void +cipherSpecFree(CipherSpec *const this) +{ + objFree(this); +} + +/*********************************************************************************************************************************** +Macros for function logging +***********************************************************************************************************************************/ +FN_EXTERN void cipherSpecToLog(const CipherSpec *this, StringStatic *debugLog); + +#define FUNCTION_LOG_CIPHER_SPEC_TYPE \ + CipherSpec * +#define FUNCTION_LOG_CIPHER_SPEC_FORMAT(value, buffer, bufferSize) \ + FUNCTION_LOG_OBJECT_FORMAT(value, cipherSpecToLog, buffer, bufferSize) + +#endif diff --git a/src/config/config.c b/src/config/config.c index fcb737b9a..1d38522a6 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -1078,3 +1078,39 @@ cfgOptionInvalidate(const ConfigOption optionId) FUNCTION_TEST_RETURN_VOID(); } + +/**********************************************************************************************************************************/ +FN_EXTERN const CipherSpec * +cfgCipherSpecMainIdx(const unsigned int repoIdx) +{ + FUNCTION_TEST_BEGIN(); + FUNCTION_TEST_PARAM(UINT, repoIdx); + FUNCTION_TEST_END(); + + ASSERT(repoIdx < cfgOptionGroupIdxTotal(cfgOptGrpRepo)); + + // Allocate a slot per repo. Each repo has its own cipher type and passphrase so cipher spec cannot be shared between them. + if (configLocal->cipherSpecMain == NULL) + { + MEM_CONTEXT_BEGIN(configLocal->memContext) + { + configLocal->cipherSpecMain = memNewPtrArray(cfgOptionGroupIdxTotal(cfgOptGrpRepo)); + } + MEM_CONTEXT_END(); + } + + // Get cipher spec if it doesn't exist + if (configLocal->cipherSpecMain[repoIdx] == NULL) + { + MEM_CONTEXT_BEGIN(configLocal->memContext) + { + const CipherType cipherType = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx); + + configLocal->cipherSpecMain[repoIdx] = cipherSpecNew( + cipherType, cipherType == cipherTypeNone ? NULL : BUFSTR(cfgOptionIdxStr(cfgOptRepoCipherPass, repoIdx))); + } + MEM_CONTEXT_END(); + } + + FUNCTION_TEST_RETURN_CONST(CIPHER_SPEC, configLocal->cipherSpecMain[repoIdx]); +} diff --git a/src/config/config.h b/src/config/config.h index d86f113e1..7d65723aa 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -7,6 +7,7 @@ sets the command and options and determines which options are valid for a comman #ifndef CONFIG_CONFIG_H #define CONFIG_CONFIG_H +#include "common/crypto/spec.h" #include "common/log.h" #include "common/type/stringId.h" #include "common/type/stringList.h" @@ -238,6 +239,21 @@ FN_EXTERN bool cfgOptionValid(ConfigOption optionId); FN_EXTERN bool cfgOptionTest(ConfigOption optionId); FN_EXTERN bool cfgOptionIdxTest(ConfigOption optionId, unsigned int optionIdx); +/*********************************************************************************************************************************** +Cipher Functions + +Main cipher spec for a repository, built from the cipher options and cached per repo since the options cannot change while a command +runs. This is the top of the chain. The info files are read with it and each of those carries the cipher spec for the files that +depend on it, so nothing further down needs to consult the options again. +***********************************************************************************************************************************/ +FN_EXTERN const CipherSpec *cfgCipherSpecMainIdx(unsigned int repoIdx); + +FN_INLINE_ALWAYS const CipherSpec * +cfgCipherSpecMain(void) +{ + return cfgCipherSpecMainIdx(cfgOptionIdxDefault(cfgOptRepoCipherType)); +} + /*********************************************************************************************************************************** Option Source Enum diff --git a/src/config/config.intern.h b/src/config/config.intern.h index 9f4874a9f..5cef3e328 100644 --- a/src/config/config.intern.h +++ b/src/config/config.intern.h @@ -82,6 +82,8 @@ typedef struct Config ConfigOptionGroupData optionGroup[CFG_OPTION_GROUP_TOTAL]; // Option group data ConfigOptionData option[CFG_OPTION_TOTAL]; // Option data + + CipherSpec **cipherSpecMain; // Main cipher spec for the cipher options by repo index } Config; /*********************************************************************************************************************************** diff --git a/src/info/info.c b/src/info/info.c index a1e7f8d53..ad135054e 100644 --- a/src/info/info.c +++ b/src/info/info.c @@ -94,10 +94,10 @@ BUFFER_STRDEF_STATIC(INFO_CHECKSUM_END_BUF, "}}"); /**********************************************************************************************************************************/ FN_EXTERN Info * -infoNew(const String *const cipherPass) +infoNew(const CipherSpec *const cipherSpecSub) { FUNCTION_LOG_BEGIN(logLevelDebug); - FUNCTION_TEST_PARAM(STRING, cipherPass); // Use FUNCTION_TEST so cipher is not logged + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecSub); FUNCTION_LOG_END(); OBJ_NEW_BEGIN(Info, .childQty = MEM_CONTEXT_QTY_MAX) @@ -105,7 +105,7 @@ infoNew(const String *const cipherPass) *this = (Info){}; // Cipher used to encrypt/decrypt subsequent dependent files. Value may be NULL. - infoCipherPassSet(this, cipherPass); + infoCipherSpecSet(this, cipherSpecSub); this->pub.backrestVersion = STRDEF(PROJECT_VERSION); } OBJ_NEW_END(); @@ -120,10 +120,12 @@ infoNew(const String *const cipherPass) #define INFO_KEY_CIPHER_PASS "cipher-pass" FN_EXTERN Info * -infoNewLoad(IoRead *const read, InfoLoadNewCallback *const callbackFunction, void *const callbackData) +infoNewLoad( + IoRead *const read, const CipherSpec *const cipherSpec, InfoLoadNewCallback *const callbackFunction, void *const callbackData) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(IO_READ, read); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_PARAM(FUNCTIONP, callbackFunction); FUNCTION_LOG_PARAM_P(VOID, callbackData); FUNCTION_LOG_END(); @@ -131,6 +133,7 @@ infoNewLoad(IoRead *const read, InfoLoadNewCallback *const callbackFunction, voi FUNCTION_AUDIT_CALLBACK(); ASSERT(read != NULL); + ASSERT(cipherSpec != NULL); ASSERT(callbackFunction != NULL); ASSERT(callbackData != NULL); @@ -213,7 +216,9 @@ infoNewLoad(IoRead *const read, InfoLoadNewCallback *const callbackFunction, voi { MEM_CONTEXT_OBJ_BEGIN(this) { - this->pub.cipherPass = varStr(jsonToVar(value->value)); + // The dependent files are encrypted with the same cipher type as this one + this->pub.cipherSpec = cipherSpecNew( + cipherSpecType(cipherSpec), BUFSTR(varStr(jsonToVar(value->value)))); } MEM_CONTEXT_OBJ_END(); } @@ -250,6 +255,10 @@ infoNewLoad(IoRead *const read, InfoLoadNewCallback *const callbackFunction, voi } } MEM_CONTEXT_TEMP_END(); + + // A file with no cipher section has no encrypted dependent files + if (this->pub.cipherSpec == NULL) + infoCipherSpecSet(this, NULL); } OBJ_NEW_END(); @@ -366,10 +375,12 @@ infoSave(Info *const this, IoWrite *const write, InfoSaveCallback *const callbac infoSaveValue(&data, INFO_SECTION_BACKREST, INFO_KEY_VERSION, jsonFromVar(VARSTRDEF(PROJECT_VERSION))); // Add cipher passphrase if defined - if (infoCipherPass(this) != NULL) + if (cipherSpecType(infoCipherSpec(this)) != cipherTypeNone) { callbackFunction(callbackData, STRDEF(INFO_SECTION_CIPHER), &data); - infoSaveValue(&data, INFO_SECTION_CIPHER, INFO_KEY_CIPHER_PASS, jsonFromVar(VARSTR(infoCipherPass(this)))); + infoSaveValue( + &data, INFO_SECTION_CIPHER, INFO_KEY_CIPHER_PASS, + jsonFromVar(VARSTR(strNewBuf(cipherSpecPass(infoCipherSpec(this)))))); } // Flush out any additional sections @@ -395,11 +406,11 @@ infoSave(Info *const this, IoWrite *const write, InfoSaveCallback *const callbac Getters/Setters ***********************************************************************************************************************************/ FN_EXTERN void -infoCipherPassSet(Info *const this, const String *const cipherPass) +infoCipherSpecSet(Info *const this, const CipherSpec *const cipherSpec) { FUNCTION_TEST_BEGIN(); FUNCTION_TEST_PARAM(INFO, this); - FUNCTION_TEST_PARAM(STRING, cipherPass); + FUNCTION_TEST_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_TEST_END(); FUNCTION_AUDIT_IF(memContextCurrent() != objMemContext(this)); // Do not audit calls from within the object @@ -408,7 +419,8 @@ infoCipherPassSet(Info *const this, const String *const cipherPass) MEM_CONTEXT_OBJ_BEGIN(this) { - this->pub.cipherPass = strDup(cipherPass); + // Copy so the caller is free to release what was passed in, and so the getter never returns NULL + this->pub.cipherSpec = cipherSpec == NULL ? cipherSpecNewNone() : cipherSpecDup(cipherSpec); } MEM_CONTEXT_OBJ_END(); diff --git a/src/info/info.h b/src/info/info.h index 8a875c082..2901ad65c 100644 --- a/src/info/info.h +++ b/src/info/info.h @@ -10,6 +10,7 @@ Object type typedef struct Info Info; typedef struct InfoSave InfoSave; +#include "common/crypto/spec.h" #include "common/ini.h" #include "common/type/json.h" #include "storage/storage.h" @@ -38,10 +39,12 @@ typedef void InfoSaveCallback(void *data, const String *sectionNext, InfoSave *i /*********************************************************************************************************************************** Constructors ***********************************************************************************************************************************/ -FN_EXTERN Info *infoNew(const String *cipherPassSub); +FN_EXTERN Info *infoNew(const CipherSpec *cipherSpecSub); -// Create new object and load contents from a file -FN_EXTERN Info *infoNewLoad(IoRead *read, InfoLoadNewCallback *callbackFunction, void *callbackData); +// Create new object and load contents from a file. The cipher spec the file is read with supplies the type for the cipher spec +// built from the pass stored in it. +FN_EXTERN Info *infoNewLoad( + IoRead *read, const CipherSpec *cipherSpec, InfoLoadNewCallback *callbackFunction, void *callbackData); /*********************************************************************************************************************************** Getters/Setters @@ -49,17 +52,19 @@ Getters/Setters typedef struct InfoPub { const String *backrestVersion; // pgBackRest version - const String *cipherPass; // Cipher passphrase if set + const CipherSpec *cipherSpec; // Cipher spec for dependent files } InfoPub; -// Cipher passphrase if set -FN_INLINE_ALWAYS const String * -infoCipherPass(const Info *const this) +// Cipher spec for the files that depend on this one, e.g. the manifest for backup.info. Never NULL, so it can be handed on +// without a check, and none when there is no pass. +FN_INLINE_ALWAYS const CipherSpec * +infoCipherSpec(const Info *const this) { - return THIS_PUB(Info)->cipherPass; + return THIS_PUB(Info)->cipherSpec; } -FN_EXTERN void infoCipherPassSet(Info *this, const String *cipherPass); +// Set cipher spec for dependent files. NULL means they are not encrypted. +FN_EXTERN void infoCipherSpecSet(Info *this, const CipherSpec *cipherSpec); // pgBackRest version FN_INLINE_ALWAYS const String * diff --git a/src/info/infoArchive.c b/src/info/infoArchive.c index 94278f4c1..959bdaa7d 100644 --- a/src/info/infoArchive.c +++ b/src/info/infoArchive.c @@ -57,12 +57,12 @@ infoArchiveNewInternal(void) /**********************************************************************************************************************************/ FN_EXTERN InfoArchive * -infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const String *const cipherPassSub) +infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const CipherSpec *const cipherSpecSub) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(UINT, pgVersion); FUNCTION_LOG_PARAM(UINT64, pgSystemId); - FUNCTION_TEST_PARAM(STRING, cipherPassSub); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecSub); FUNCTION_LOG_END(); ASSERT(pgVersion > 0 && pgSystemId > 0); @@ -74,7 +74,7 @@ infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const St this = infoArchiveNewInternal(); // Initialize the pg data - this->pub.infoPg = infoPgNew(infoPgArchive, cipherPassSub); + this->pub.infoPg = infoPgNew(infoPgArchive, cipherSpecSub); infoArchivePgSet(this, pgVersion, pgSystemId); } OBJ_NEW_END(); @@ -84,10 +84,11 @@ infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const St /**********************************************************************************************************************************/ FN_EXTERN InfoArchive * -infoArchiveNewLoad(IoRead *const read) +infoArchiveNewLoad(IoRead *const read, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(IO_READ, read); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_END(); ASSERT(read != NULL); @@ -97,7 +98,7 @@ infoArchiveNewLoad(IoRead *const read) OBJ_NEW_BASE_BEGIN(InfoArchive, .childQty = MEM_CONTEXT_QTY_MAX) { this = infoArchiveNewInternal(); - this->pub.infoPg = infoPgNewLoad(read, infoPgArchive, NULL, NULL); + this->pub.infoPg = infoPgNewLoad(read, infoPgArchive, cipherSpec, NULL, NULL); } OBJ_NEW_END(); @@ -207,8 +208,7 @@ typedef struct InfoArchiveLoadFileData MemContext *memContext; // Mem context const Storage *storage; // Storage to load from const String *fileName; // Base filename - CipherType cipherType; // Cipher type - const String *cipherPass; // Cipher passphrase + const CipherSpec *cipherSpec; // Cipher spec InfoArchive *infoArchive; // Loaded infoArchive object } InfoArchiveLoadFileData; @@ -234,11 +234,12 @@ infoArchiveLoadFileCallback(void *const data, const unsigned int try) // Attempt to load the file IoRead *const read = storageReadIo(storageNewReadP(loadData->storage, fileName)); - cipherBlockFilterGroupAdd(ioReadFilterGroup(read), loadData->cipherType, cipherModeDecrypt, loadData->cipherPass); + cipherBlockFilterGroupAdd( + ioReadFilterGroup(read), cipherModeDecrypt, loadData->cipherSpec); MEM_CONTEXT_BEGIN(loadData->memContext) { - loadData->infoArchive = infoArchiveNewLoad(read); + loadData->infoArchive = infoArchiveNewLoad(read, loadData->cipherSpec); result = true; } MEM_CONTEXT_END(); @@ -251,26 +252,24 @@ infoArchiveLoadFileCallback(void *const data, const unsigned int try) FN_EXTERN InfoArchive * infoArchiveLoadFile( - const Storage *const storage, const String *const fileName, const CipherType cipherType, const String *const cipherPass) + const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(STORAGE, storage); FUNCTION_LOG_PARAM(STRING, fileName); - FUNCTION_LOG_PARAM(STRING_ID, cipherType); - FUNCTION_TEST_PARAM(STRING, cipherPass); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_END(); ASSERT(storage != NULL); ASSERT(fileName != NULL); - ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL)); + ASSERT(cipherSpec != NULL); InfoArchiveLoadFileData data = { .memContext = memContextCurrent(), .storage = storage, .fileName = fileName, - .cipherType = cipherType, - .cipherPass = cipherPass, + .cipherSpec = cipherSpec, }; MEM_CONTEXT_TEMP_BEGIN() @@ -304,28 +303,26 @@ infoArchiveLoadFile( /**********************************************************************************************************************************/ FN_EXTERN void infoArchiveSaveFile( - InfoArchive *const infoArchive, const Storage *const storage, const String *const fileName, const CipherType cipherType, - const String *const cipherPass) + InfoArchive *const infoArchive, const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(INFO_ARCHIVE, infoArchive); FUNCTION_LOG_PARAM(STORAGE, storage); FUNCTION_LOG_PARAM(STRING, fileName); - FUNCTION_LOG_PARAM(STRING_ID, cipherType); - FUNCTION_TEST_PARAM(STRING, cipherPass); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_END(); ASSERT(infoArchive != NULL); ASSERT(storage != NULL); ASSERT(fileName != NULL); - ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL)); + ASSERT(cipherSpec != NULL); MEM_CONTEXT_TEMP_BEGIN() { // Write output into a buffer since it needs to be saved to storage twice Buffer *const buffer = bufNew(ioBufferSize()); IoWrite *const write = ioBufferWriteNew(buffer); - cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherType, cipherModeEncrypt, cipherPass); + cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherModeEncrypt, cipherSpec); infoArchiveSave(infoArchive, write); // Save the file and make a copy diff --git a/src/info/infoArchive.h b/src/info/infoArchive.h index f28692336..15647d0ff 100644 --- a/src/info/infoArchive.h +++ b/src/info/infoArchive.h @@ -9,7 +9,7 @@ Object type ***********************************************************************************************************************************/ typedef struct InfoArchive InfoArchive; -#include "common/crypto/common.h" +#include "common/crypto/spec.h" #include "common/type/object.h" #include "common/type/string.h" #include "info/infoPg.h" @@ -29,10 +29,10 @@ STRING_DECLARE(INFO_ARCHIVE_PATH_FILE_COPY_STR); /*********************************************************************************************************************************** Constructors ***********************************************************************************************************************************/ -FN_EXTERN InfoArchive *infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const String *cipherPassSub); +FN_EXTERN InfoArchive *infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const CipherSpec *cipherSpecSub); // Create new object and load contents from IoRead -FN_EXTERN InfoArchive *infoArchiveNewLoad(IoRead *read); +FN_EXTERN InfoArchive *infoArchiveNewLoad(IoRead *read, const CipherSpec *cipherSpec); /*********************************************************************************************************************************** Getters/Setters @@ -59,11 +59,11 @@ infoArchiveId(const InfoArchive *const this) return infoPgArchiveId(infoArchivePg(this), infoPgDataCurrentId(infoArchivePg(this))); } -// Cipher passphrase -FN_INLINE_ALWAYS const String * -infoArchiveCipherPass(const InfoArchive *const this) +// Cipher spec for dependent files +FN_INLINE_ALWAYS const CipherSpec * +infoArchiveCipherSpec(const InfoArchive *const this) { - return infoPgCipherPass(infoArchivePg(this)); + return infoPgCipherSpec(infoArchivePg(this)); } /*********************************************************************************************************************************** @@ -93,12 +93,11 @@ infoArchiveFree(InfoArchive *const this) Helper functions ***********************************************************************************************************************************/ // Load archive info -FN_EXTERN InfoArchive *infoArchiveLoadFile( - const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass); +FN_EXTERN InfoArchive *infoArchiveLoadFile(const Storage *storage, const String *fileName, const CipherSpec *cipherSpec); // Save archive info FN_EXTERN void infoArchiveSaveFile( - InfoArchive *infoArchive, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass); + InfoArchive *infoArchive, const Storage *storage, const String *fileName, const CipherSpec *cipherSpec); /*********************************************************************************************************************************** Macros for function logging diff --git a/src/info/infoBackup.c b/src/info/infoBackup.c index 27f76946f..2d63638f1 100644 --- a/src/info/infoBackup.c +++ b/src/info/infoBackup.c @@ -66,13 +66,14 @@ infoBackupNewInternal(void) /**********************************************************************************************************************************/ FN_EXTERN InfoBackup * infoBackupNew( - const unsigned int pgVersion, const uint64_t pgSystemId, const unsigned int pgCatalogVersion, const String *const cipherPassSub) + const unsigned int pgVersion, const uint64_t pgSystemId, const unsigned int pgCatalogVersion, + const CipherSpec *const cipherSpecSub) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(UINT, pgVersion); FUNCTION_LOG_PARAM(UINT64, pgSystemId); FUNCTION_LOG_PARAM(UINT, pgCatalogVersion); - FUNCTION_TEST_PARAM(STRING, cipherPassSub); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecSub); FUNCTION_LOG_END(); ASSERT(pgVersion > 0 && pgSystemId > 0 && pgCatalogVersion > 0); @@ -84,7 +85,7 @@ infoBackupNew( this = infoBackupNewInternal(); // Initialize the pg data - this->pub.infoPg = infoPgNew(infoPgBackup, cipherPassSub); + this->pub.infoPg = infoPgNew(infoPgBackup, cipherSpecSub); infoBackupPgSet(this, pgVersion, pgSystemId, pgCatalogVersion); } OBJ_NEW_END(); @@ -233,10 +234,11 @@ infoBackupLoadCallback(void *const data, const String *const section, const Stri /**********************************************************************************************************************************/ FN_EXTERN InfoBackup * -infoBackupNewLoad(IoRead *const read) +infoBackupNewLoad(IoRead *const read, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(IO_READ, read); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_END(); ASSERT(read != NULL); @@ -246,7 +248,7 @@ infoBackupNewLoad(IoRead *const read) OBJ_NEW_BASE_BEGIN(InfoBackup, .childQty = MEM_CONTEXT_QTY_MAX) { this = infoBackupNewInternal(); - this->pub.infoPg = infoPgNewLoad(read, infoPgBackup, infoBackupLoadCallback, this); + this->pub.infoPg = infoPgNewLoad(read, infoPgBackup, cipherSpec, infoBackupLoadCallback, this); this->pub.updated = false; } OBJ_NEW_END(); @@ -670,8 +672,7 @@ typedef struct InfoBackupLoadFileData MemContext *memContext; // Mem context const Storage *storage; // Storage to load from const String *fileName; // Base filename - CipherType cipherType; // Cipher type - const String *cipherPass; // Cipher passphrase + const CipherSpec *cipherSpec; // Cipher spec InfoBackup *infoBackup; // Loaded infoBackup object } InfoBackupLoadFileData; @@ -697,11 +698,12 @@ infoBackupLoadFileCallback(void *const data, const unsigned int try) // Attempt to load the file IoRead *const read = storageReadIo(storageNewReadP(loadData->storage, fileName)); - cipherBlockFilterGroupAdd(ioReadFilterGroup(read), loadData->cipherType, cipherModeDecrypt, loadData->cipherPass); + cipherBlockFilterGroupAdd( + ioReadFilterGroup(read), cipherModeDecrypt, loadData->cipherSpec); MEM_CONTEXT_BEGIN(loadData->memContext) { - loadData->infoBackup = infoBackupNewLoad(read); + loadData->infoBackup = infoBackupNewLoad(read, loadData->cipherSpec); result = true; } MEM_CONTEXT_END(); @@ -714,26 +716,24 @@ infoBackupLoadFileCallback(void *const data, const unsigned int try) FN_EXTERN InfoBackup * infoBackupLoadFile( - const Storage *const storage, const String *const fileName, const CipherType cipherType, const String *const cipherPass) + const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(STORAGE, storage); FUNCTION_LOG_PARAM(STRING, fileName); - FUNCTION_LOG_PARAM(STRING_ID, cipherType); - FUNCTION_TEST_PARAM(STRING, cipherPass); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_END(); ASSERT(storage != NULL); ASSERT(fileName != NULL); - ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL)); + ASSERT(cipherSpec != NULL); InfoBackupLoadFileData data = { .memContext = memContextCurrent(), .storage = storage, .fileName = fileName, - .cipherType = cipherType, - .cipherPass = cipherPass, + .cipherSpec = cipherSpec, }; MEM_CONTEXT_TEMP_BEGIN() @@ -786,20 +786,19 @@ infoBackupSetExists(const InfoBackup *const this, const String *const backupSet) FN_EXTERN InfoBackup * infoBackupLoadFileReconstruct( - const Storage *const storage, const String *const fileName, const CipherType cipherType, const String *const cipherPass) + const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(STORAGE, storage); FUNCTION_LOG_PARAM(STRING, fileName); - FUNCTION_LOG_PARAM(STRING_ID, cipherType); - FUNCTION_TEST_PARAM(STRING, cipherPass); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_END(); ASSERT(storage != NULL); ASSERT(fileName != NULL); - ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL)); + ASSERT(cipherSpec != NULL); - InfoBackup *const infoBackup = infoBackupLoadFile(storage, fileName, cipherType, cipherPass); + InfoBackup *const infoBackup = infoBackupLoadFile(storage, fileName, cipherSpec); MEM_CONTEXT_TEMP_BEGIN() { @@ -865,8 +864,7 @@ infoBackupLoadFileReconstruct( if (storageExistsP(storage, manifestFileName)) { bool found = false; - const Manifest *const manifest = manifestLoadFile( - storage, manifestFileName, cipherType, infoPgCipherPass(infoBackupPg(infoBackup))); + const Manifest *const manifest = manifestLoadFile(storage, manifestFileName, infoBackupCipherSpec(infoBackup)); const ManifestData *const manData = manifestData(manifest); // If the pg data for the manifest exists in the history, then add it to current, but if something doesn't match @@ -902,21 +900,19 @@ infoBackupLoadFileReconstruct( /**********************************************************************************************************************************/ FN_EXTERN void infoBackupSaveFile( - InfoBackup *const infoBackup, const Storage *const storage, const String *const fileName, const CipherType cipherType, - const String *const cipherPass) + InfoBackup *const infoBackup, const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(INFO_BACKUP, infoBackup); FUNCTION_LOG_PARAM(STORAGE, storage); FUNCTION_LOG_PARAM(STRING, fileName); - FUNCTION_LOG_PARAM(STRING_ID, cipherType); - FUNCTION_TEST_PARAM(STRING, cipherPass); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_END(); ASSERT(infoBackup != NULL); ASSERT(storage != NULL); ASSERT(fileName != NULL); - ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL)); + ASSERT(cipherSpec != NULL); if (infoBackup->pub.updated) { @@ -925,7 +921,7 @@ infoBackupSaveFile( // Write output into a buffer since it needs to be saved to storage twice Buffer *const buffer = bufNew(ioBufferSize()); IoWrite *const write = ioBufferWriteNew(buffer); - cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherType, cipherModeEncrypt, cipherPass); + cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherModeEncrypt, cipherSpec); infoBackupSave(infoBackup, write); // Save the file and make a copy diff --git a/src/info/infoBackup.h b/src/info/infoBackup.h index 308a420eb..e1ca7e7ac 100644 --- a/src/info/infoBackup.h +++ b/src/info/infoBackup.h @@ -21,6 +21,7 @@ typedef enum backupTypeIncr = STRID5("incr", 0x90dc90), } BackupType; +#include "common/crypto/spec.h" #include "common/type/object.h" #include "common/type/string.h" #include "common/type/stringList.h" @@ -77,10 +78,10 @@ typedef struct InfoBackupData Constructors ***********************************************************************************************************************************/ FN_EXTERN InfoBackup *infoBackupNew( - unsigned int pgVersion, uint64_t pgSystemId, unsigned int pgCatalogVersion, const String *cipherPassSub); + unsigned int pgVersion, uint64_t pgSystemId, unsigned int pgCatalogVersion, const CipherSpec *cipherSpecSub); // Create new object and load contents from IoRead -FN_EXTERN InfoBackup *infoBackupNewLoad(IoRead *read); +FN_EXTERN InfoBackup *infoBackupNewLoad(IoRead *read, const CipherSpec *cipherSpec); /*********************************************************************************************************************************** Getters/Setters @@ -102,11 +103,11 @@ infoBackupPg(const InfoBackup *const this) FN_EXTERN InfoBackup *infoBackupPgSet(InfoBackup *this, unsigned int pgVersion, uint64_t pgSystemId, unsigned int pgCatalogVersion); -// Cipher passphrase -FN_INLINE_ALWAYS const String * -infoBackupCipherPass(const InfoBackup *const this) +// Cipher spec for dependent files +FN_INLINE_ALWAYS const CipherSpec * +infoBackupCipherSpec(const InfoBackup *const this) { - return infoPgCipherPass(infoBackupPg(this)); + return infoPgCipherSpec(infoBackupPg(this)); } // Return a structure of the backup data from a specific index @@ -173,16 +174,15 @@ infoBackupFree(InfoBackup *const this) Helper functions ***********************************************************************************************************************************/ // Load backup info -FN_EXTERN InfoBackup *infoBackupLoadFile( - const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass); +FN_EXTERN InfoBackup *infoBackupLoadFile(const Storage *storage, const String *fileName, const CipherSpec *cipherSpec); // Load backup info and update it by adding valid backups from the repo or removing backups no longer in the repo FN_EXTERN InfoBackup *infoBackupLoadFileReconstruct( - const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass); + const Storage *storage, const String *fileName, const CipherSpec *cipherSpec); // Save backup info FN_EXTERN void infoBackupSaveFile( - InfoBackup *infoBackup, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass); + InfoBackup *infoBackup, const Storage *storage, const String *fileName, const CipherSpec *cipherSpec); /*********************************************************************************************************************************** Macros for function logging diff --git a/src/info/infoPg.c b/src/info/infoPg.c index c3c36da13..8c613c6ba 100644 --- a/src/info/infoPg.c +++ b/src/info/infoPg.c @@ -62,11 +62,11 @@ infoPgNewInternal(const InfoPgType type) /**********************************************************************************************************************************/ FN_EXTERN InfoPg * -infoPgNew(const InfoPgType type, const String *const cipherPassSub) +infoPgNew(const InfoPgType type, const CipherSpec *const cipherSpecSub) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(STRING_ID, type); - FUNCTION_TEST_PARAM(STRING, cipherPassSub); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecSub); FUNCTION_LOG_END(); InfoPg *this; @@ -74,7 +74,7 @@ infoPgNew(const InfoPgType type, const String *const cipherPassSub) OBJ_NEW_BASE_BEGIN(InfoPg, .childQty = MEM_CONTEXT_QTY_MAX) { this = infoPgNewInternal(type); - this->pub.info = infoNew(cipherPassSub); + this->pub.info = infoNew(cipherSpecSub); } OBJ_NEW_END(); @@ -155,11 +155,14 @@ infoPgLoadCallback(void *const data, const String *const section, const String * } FN_EXTERN InfoPg * -infoPgNewLoad(IoRead *const read, const InfoPgType type, InfoLoadNewCallback *const callbackFunction, void *const callbackData) +infoPgNewLoad( + IoRead *const read, const InfoPgType type, const CipherSpec *const cipherSpec, InfoLoadNewCallback *const callbackFunction, + void *const callbackData) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(IO_READ, read); FUNCTION_LOG_PARAM(STRING_ID, type); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_PARAM(FUNCTIONP, callbackFunction); FUNCTION_LOG_PARAM_P(VOID, callbackData); FUNCTION_LOG_END(); @@ -185,7 +188,7 @@ infoPgNewLoad(IoRead *const read, const InfoPgType type, InfoLoadNewCallback *co .infoPg = this, }; - this->pub.info = infoNewLoad(read, infoPgLoadCallback, &loadData); + this->pub.info = infoNewLoad(read, cipherSpec, infoPgLoadCallback, &loadData); CHECK(FormatError, !lstEmpty(this->pub.history), "history is missing"); CHECK(FormatError, loadData.currentId > 0, "current id is missing"); diff --git a/src/info/infoPg.h b/src/info/infoPg.h index 62c624728..77bb89bad 100644 --- a/src/info/infoPg.h +++ b/src/info/infoPg.h @@ -47,10 +47,11 @@ typedef enum /*********************************************************************************************************************************** Constructors ***********************************************************************************************************************************/ -FN_EXTERN InfoPg *infoPgNew(InfoPgType type, const String *cipherPassSub); +FN_EXTERN InfoPg *infoPgNew(InfoPgType type, const CipherSpec *cipherSpecSub); // Create new object and load contents from a file -FN_EXTERN InfoPg *infoPgNewLoad(IoRead *read, InfoPgType type, InfoLoadNewCallback *callbackFunction, void *callbackData); +FN_EXTERN InfoPg *infoPgNewLoad( + IoRead *read, InfoPgType type, const CipherSpec *cipherSpec, InfoLoadNewCallback *callbackFunction, void *callbackData); /*********************************************************************************************************************************** Getters/Setters @@ -71,11 +72,11 @@ infoPgInfo(const InfoPg *const this) return THIS_PUB(InfoPg)->info; } -// Return the cipher passphrase -FN_INLINE_ALWAYS const String * -infoPgCipherPass(const InfoPg *const this) +// Cipher spec for dependent files +FN_INLINE_ALWAYS const CipherSpec * +infoPgCipherSpec(const InfoPg *const this) { - return infoCipherPass(infoPgInfo(this)); + return infoCipherSpec(infoPgInfo(this)); } // Return current pgId from the history diff --git a/src/info/manifest/manifest.c b/src/info/manifest/manifest.c index b223601ef..d3759f5b8 100644 --- a/src/info/manifest/manifest.c +++ b/src/info/manifest/manifest.c @@ -669,10 +669,11 @@ manifestBuildComplete( /**********************************************************************************************************************************/ FN_EXTERN Manifest * -manifestNewLoad(IoRead *const read) +manifestNewLoad(IoRead *const read, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(IO_READ, read); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_END(); ASSERT(read != NULL); @@ -703,7 +704,7 @@ manifestNewLoad(IoRead *const read) } MEM_CONTEXT_END(); - this->pub.info = infoNewLoad(read, manifestLoadCallback, &loadData); + this->pub.info = infoNewLoad(read, cipherSpec, manifestLoadCallback, &loadData); this->pub.data.backrestVersion = infoBackrestVersion(this->pub.info); // Add the label to the reference list in case the manifest was created before 2.42 when the explicit reference list was diff --git a/src/info/manifest/manifest.h b/src/info/manifest/manifest.h index 1817a1e67..78507cdbe 100644 --- a/src/info/manifest/manifest.h +++ b/src/info/manifest/manifest.h @@ -37,8 +37,8 @@ typedef struct Manifest Manifest; #include "command/backup/common.h" #include "common/compress/helper.h" -#include "common/crypto/common.h" #include "common/crypto/hash.h" +#include "common/crypto/spec.h" #include "common/type/object.h" #include "common/type/variant.h" #include "info/info.h" @@ -218,7 +218,7 @@ FN_EXTERN Manifest *manifestNewBuild( const Pack *tablespaceList); // Load a manifest from IO -FN_EXTERN Manifest *manifestNewLoad(IoRead *read); +FN_EXTERN Manifest *manifestNewLoad(IoRead *read, const CipherSpec *cipherSpec); /*********************************************************************************************************************************** Getters/Setters @@ -236,17 +236,17 @@ typedef struct ManifestPub StringList *referenceList; // List of file references } ManifestPub; -// Get/set the cipher subpassphrase -FN_INLINE_ALWAYS const String * -manifestCipherSubPass(const Manifest *const this) +// Get cipher spec for the files this manifest describes, set the pass they are encrypted with +FN_INLINE_ALWAYS const CipherSpec * +manifestCipherSpec(const Manifest *const this) { - return infoCipherPass(THIS_PUB(Manifest)->info); + return infoCipherSpec(THIS_PUB(Manifest)->info); } FN_INLINE_ALWAYS void -manifestCipherSubPassSet(Manifest *const this, const String *const cipherSubPass) +manifestCipherSpecSet(Manifest *const this, const CipherSpec *const cipherSpec) { - infoCipherPassSet(THIS_PUB(Manifest)->info, cipherSubPass); + infoCipherSpecSet(THIS_PUB(Manifest)->info, cipherSpec); } // Get manifest configuration and options @@ -507,8 +507,7 @@ manifestFree(Manifest *const this) Helper functions ***********************************************************************************************************************************/ // Load backup manifest -FN_EXTERN Manifest *manifestLoadFile( - const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass); +FN_EXTERN Manifest *manifestLoadFile(const Storage *storage, const String *fileName, const CipherSpec *cipherSpec); /*********************************************************************************************************************************** Macros for function logging diff --git a/src/info/manifest/serialize.c.inc b/src/info/manifest/serialize.c.inc index b6eca3fee..64bf889b7 100644 --- a/src/info/manifest/serialize.c.inc +++ b/src/info/manifest/serialize.c.inc @@ -1013,8 +1013,7 @@ typedef struct ManifestLoadFileData MemContext *memContext; // Mem context const Storage *storage; // Storage to load from const String *fileName; // Base filename - CipherType cipherType; // Cipher type - const String *cipherPass; // Cipher passphrase + const CipherSpec *cipherSpec; // Cipher spec Manifest *manifest; // Loaded manifest object } ManifestLoadFileData; @@ -1040,11 +1039,11 @@ manifestLoadFileCallback(void *const data, const unsigned int try) // Attempt to load the file IoRead *const read = storageReadIo(storageNewReadP(loadData->storage, fileName)); - cipherBlockFilterGroupAdd(ioReadFilterGroup(read), loadData->cipherType, cipherModeDecrypt, loadData->cipherPass); + cipherBlockFilterGroupAdd(ioReadFilterGroup(read), cipherModeDecrypt, loadData->cipherSpec); MEM_CONTEXT_BEGIN(loadData->memContext) { - loadData->manifest = manifestNewLoad(read); + loadData->manifest = manifestNewLoad(read, loadData->cipherSpec); result = true; } MEM_CONTEXT_END(); @@ -1057,26 +1056,24 @@ manifestLoadFileCallback(void *const data, const unsigned int try) FN_EXTERN Manifest * manifestLoadFile( - const Storage *const storage, const String *const fileName, const CipherType cipherType, const String *const cipherPass) + const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(STORAGE, storage); FUNCTION_LOG_PARAM(STRING, fileName); - FUNCTION_LOG_PARAM(STRING_ID, cipherType); - FUNCTION_TEST_PARAM(STRING, cipherPass); + FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); FUNCTION_LOG_END(); ASSERT(storage != NULL); ASSERT(fileName != NULL); - ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL)); + ASSERT(cipherSpec != NULL); ManifestLoadFileData data = { .memContext = memContextCurrent(), .storage = storage, .fileName = fileName, - .cipherType = cipherType, - .cipherPass = cipherPass, + .cipherSpec = cipherSpec, }; MEM_CONTEXT_TEMP_BEGIN() diff --git a/src/meson.build b/src/meson.build index 46b58a86a..a5c1c19d5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -123,6 +123,7 @@ src_pgbackrest = [ 'common/crypto/cipherBlock.c', 'common/crypto/common.c', 'common/crypto/hash.c', + 'common/crypto/spec.c', 'common/crypto/xxhash.c', 'common/debug.c', 'common/encode.c', diff --git a/test/define.yaml b/test/define.yaml index fedd03dda..36ea93f94 100644 --- a/test/define.yaml +++ b/test/define.yaml @@ -372,6 +372,7 @@ unit: - common/crypto/common - common/crypto/hash - common/crypto/md5.vendor: included + - common/crypto/spec - common/crypto/xxhash # -------------------------------------------------------------------------------------------------------------------------------- diff --git a/test/src/harness/backup.c b/test/src/harness/backup.c index 61ce11d17..2c442d795 100644 --- a/test/src/harness/backup.c +++ b/test/src/harness/backup.c @@ -96,12 +96,12 @@ hrnBackupScriptSet(const HrnBackupScript *const script, const unsigned int scrip /**********************************************************************************************************************************/ static void -backupProcess(const BackupData *const backupData, Manifest *const manifest, const String *const cipherPassBackup) +backupProcess(const BackupData *const backupData, Manifest *const manifest, const CipherSpec *const cipherSpecManifest) { FUNCTION_HARNESS_BEGIN(); FUNCTION_HARNESS_PARAM(BACKUP_DATA, backupData); FUNCTION_HARNESS_PARAM(MANIFEST, manifest); - FUNCTION_HARNESS_PARAM(STRING, cipherPassBackup); + FUNCTION_HARNESS_PARAM(CIPHER_SPEC, cipherSpecManifest); FUNCTION_HARNESS_END(); // If any file changes are scripted then make them @@ -142,7 +142,7 @@ backupProcess(const BackupData *const backupData, Manifest *const manifest, cons hrnBackupLocal.scriptSize = 0; } - backupProcess_SHIMMED(backupData, manifest, cipherPassBackup); + backupProcess_SHIMMED(backupData, manifest, cipherSpecManifest); FUNCTION_HARNESS_RETURN_VOID(); } @@ -216,8 +216,8 @@ hrnBackupPqScript(const unsigned int pgVersion, const time_t backupTimeStart, Hr if (!param.noPriorWal) { InfoArchive *infoArchive = infoArchiveLoadFile( - storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, param.cipherType == 0 ? cipherTypeNone : param.cipherType, - param.cipherPass == NULL ? NULL : STR(param.cipherPass)); + storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, + param.cipherSpecMain == NULL ? cipherSpecNewNone() : param.cipherSpecMain); const String *archiveId = infoArchiveId(infoArchive); StringList *walSegmentList = pgLsnRangeToWalSegmentList( param.timeline, lsnStart - pgControl.walSegmentSize, param.noWal ? lsnStart - pgControl.walSegmentSize : lsnStop, @@ -244,8 +244,7 @@ hrnBackupPqScript(const unsigned int pgVersion, const time_t backupTimeStart, Hr // Encrypt with the archive passphrase, which is what archive-push writes WAL with cipherBlockFilterGroupAdd( - ioWriteFilterGroup(storageWriteIo(write)), param.cipherType == 0 ? cipherTypeNone : param.cipherType, - cipherModeEncrypt, infoArchiveCipherPass(infoArchive)); + ioWriteFilterGroup(storageWriteIo(write)), cipherModeEncrypt, infoArchiveCipherSpec(infoArchive)); storagePutP(write, walBuffer); } diff --git a/test/src/harness/backup.h b/test/src/harness/backup.h index 0053aa3f0..ea6ff1ab5 100644 --- a/test/src/harness/backup.h +++ b/test/src/harness/backup.h @@ -47,8 +47,7 @@ typedef struct HrnBackupPqScriptParam bool noArchiveCheck; // Do not check archive bool walSwitch; // WAL switch is required CompressType walCompressType; // Compress type for the archive files - CipherType cipherType; // Cipher type - const char *cipherPass; // Cipher pass + const CipherSpec *cipherSpecMain; // Cipher spec the repo is configured with unsigned int walTotal; // Total WAL to write unsigned int timeline; // Timeline to use for WAL files const String *pgVersionForce; // PG version to use when control/catalog not found diff --git a/test/src/harness/blockIncr.c b/test/src/harness/blockIncr.c index e2cca4fdc..8bb97243b 100644 --- a/test/src/harness/blockIncr.c +++ b/test/src/harness/blockIncr.c @@ -27,7 +27,7 @@ hrnBlockDeltaRender(const BlockMap *const blockMap, const size_t blockSize, cons ASSERT(blockSize > 0); String *const result = strNew(); - BlockDelta *const blockDelta = blockDeltaNew(blockMap, blockSize, checksumSize, NULL, cipherTypeNone, NULL, compressTypeNone); + BlockDelta *const blockDelta = blockDeltaNew(blockMap, blockSize, checksumSize, NULL, cipherSpecNewNone(), compressTypeNone); for (unsigned int readIdx = 0; readIdx < blockDeltaReadSize(blockDelta); readIdx++) { diff --git a/test/src/harness/config.h b/test/src/harness/config.h index b25d624de..c12931645 100644 --- a/test/src/harness/config.h +++ b/test/src/harness/config.h @@ -17,6 +17,10 @@ Config option constants #define TEST_CIPHER_PASS "xmainx" #define TEST_CIPHER_PASS_ARCHIVE "xarchivex" +// Cipher spec for a test pass, defaulting to the main pass, since most tests encrypt with that +#define TEST_CIPHER_SPEC_PASS(pass) cipherSpecNew(cipherTypeAes256Cbc, BUFSTRZ(pass)) +#define TEST_CIPHER_SPEC TEST_CIPHER_SPEC_PASS(TEST_CIPHER_PASS) + /*********************************************************************************************************************************** Load a test configuration diff --git a/test/src/harness/host.c b/test/src/harness/host.c index 970a79417..faa84d508 100644 --- a/test/src/harness/host.c +++ b/test/src/harness/host.c @@ -82,8 +82,7 @@ static struct HrnHostLocal StringId repoHost; // Host acting as repository StringId storage; // Storage type CompressType compressType; // Compress type - CipherType cipherType; // Cipher type - const String *cipherPass; // Cipher passphrase + const CipherSpec *cipherSpecMain; // Cipher spec the repo is configured with unsigned int repoTotal; // Repository total unsigned int restoreTotal; // Restore counter used to name spool path bool tls; // Use TLS instead of SSH? @@ -705,10 +704,10 @@ hrnHostConfig(HrnHost *const this) strCatFmt(config, "repo1-path=%s\n", strZ(hrnHostRepo1Path(this))); strCatZ(config, "repo1-retention-full=2\n"); - if (hrnHostLocal.cipherType != cipherTypeNone) + if (cipherSpecType(hrnHostLocal.cipherSpecMain) != cipherTypeNone) { - strCatFmt(config, "repo1-cipher-type=%s\n", zNewStrId(hrnHostLocal.cipherType)); - strCatFmt(config, "repo1-cipher-pass=%s\n", strZ(hrnHostLocal.cipherPass)); + strCatFmt(config, "repo1-cipher-type=%s\n", zNewStrId(cipherSpecType(hrnHostLocal.cipherSpecMain))); + strCatFmt(config, "repo1-cipher-pass=%s\n", strZ(strNewBuf(cipherSpecPass(hrnHostLocal.cipherSpecMain)))); } if (hrnHostLocal.bundle) @@ -1030,18 +1029,11 @@ hrnHostGet(const StringId id) } /**********************************************************************************************************************************/ -CipherType -hrnHostCipherType(void) +const CipherSpec * +hrnHostCipherSpec(void) { FUNCTION_HARNESS_VOID(); - FUNCTION_HARNESS_RETURN(STRING_ID, hrnHostLocal.cipherType); -} - -const String * -hrnHostCipherPass(void) -{ - FUNCTION_HARNESS_VOID(); - FUNCTION_HARNESS_RETURN(UINT, hrnHostLocal.cipherPass); + FUNCTION_HARNESS_RETURN(CIPHER_SPEC, hrnHostLocal.cipherSpecMain); } CompressType @@ -1235,8 +1227,8 @@ hrnHostBuild(const int line, const HrnHostTestDefine *const testMatrix, const si hrnHostLocal.repoHost = strIdFromZ(testDef->repo); hrnHostLocal.storage = strIdFromZ(testDef->stg); hrnHostLocal.compressType = compressTypeEnum(strIdFromZ(testDef->cmp)); - hrnHostLocal.cipherType = testDef->enc ? cipherTypeAes256Cbc : cipherTypeNone; - hrnHostLocal.cipherPass = testDef->enc ? strNewZ(HRN_CIPHER_PASSPHRASE) : NULL; + hrnHostLocal.cipherSpecMain = + testDef->enc ? cipherSpecNew(cipherTypeAes256Cbc, BUFSTRZ(HRN_CIPHER_PASSPHRASE)) : cipherSpecNewNone(); hrnHostLocal.repoTotal = testDef->rt; hrnHostLocal.tls = testDef->tls; hrnHostLocal.bundle = testDef->bnd; diff --git a/test/src/harness/host.h b/test/src/harness/host.h index b73089414..deba2a959 100644 --- a/test/src/harness/host.h +++ b/test/src/harness/host.h @@ -9,6 +9,7 @@ Object type ***********************************************************************************************************************************/ typedef struct HrnHost HrnHost; +#include "common/crypto/spec.h" #include "common/type/object.h" #include "common/type/string.h" #include "postgres/client.h" @@ -433,11 +434,8 @@ hrnHostSqlCommit(HrnHost *const this) /*********************************************************************************************************************************** Helper functions ***********************************************************************************************************************************/ -// Cipher Type -CipherType hrnHostCipherType(void); - -// Cipher Passphrase -const String *hrnHostCipherPass(void); +// Cipher Spec +const CipherSpec *hrnHostCipherSpec(void); // Compress Type CompressType hrnHostCompressType(void); diff --git a/test/src/harness/storage.c b/test/src/harness/storage.c index 7f2498b15..89a5dbdd7 100644 --- a/test/src/harness/storage.c +++ b/test/src/harness/storage.c @@ -67,15 +67,13 @@ testStorageGet(const Storage *const storage, const char *const file, const char IoFilterGroup *filterGroup = ioReadFilterGroup(storageReadIo(read)); // Add decrypt filter - if (param.cipherType != 0 && param.cipherType != cipherTypeNone) + if (param.cipherSpec != NULL && cipherSpecType(param.cipherSpec) != cipherTypeNone) { - // Default to main cipher pass - if (param.cipherPass == NULL) - param.cipherPass = TEST_CIPHER_PASS; + ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, param.cipherSpec)); - ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, param.cipherType, BUFSTRZ(param.cipherPass))); - - strCatFmt(filter, "enc[%s,%s] ", zNewStrId(param.cipherType), param.cipherPass); + strCatFmt( + filter, "enc[%s,%s] ", zNewStrId(cipherSpecType(param.cipherSpec)), + strZ(strNewBuf(cipherSpecPass(param.cipherSpec)))); } // Add decompress filter @@ -394,14 +392,8 @@ hrnStoragePut( } // Add encrypted filter - if (param.cipherType != 0 && param.cipherType != cipherTypeNone) - { - // Default to main cipher pass - if (param.cipherPass == NULL) - param.cipherPass = TEST_CIPHER_PASS; - - ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeEncrypt, param.cipherType, BUFSTRZ(param.cipherPass))); - } + if (param.cipherSpec != NULL && cipherSpecType(param.cipherSpec) != cipherTypeNone) + ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeEncrypt, param.cipherSpec)); // Add file name printf( diff --git a/test/src/harness/storage.h b/test/src/harness/storage.h index 324fb828e..e987be68e 100644 --- a/test/src/harness/storage.h +++ b/test/src/harness/storage.h @@ -8,6 +8,7 @@ Helper functions for testing storage and related functions. #include "common/compress/helper.h" #include "common/crypto/common.h" +#include "common/crypto/spec.h" #include "storage/storage.intern.h" /*********************************************************************************************************************************** @@ -19,8 +20,7 @@ typedef struct TestStorageGetParam bool remove; // Remove file after testing? bool nullOnMissing; // NULL when file is missing CompressType compressType; // Compression extension added to file name (limited gz and bz2) - CipherType cipherType; - const char *cipherPass; // If pass=null but cipherType set, defaults to TEST_CIPHER_PASS + const CipherSpec *cipherSpec; // Cipher spec the file is encrypted with const char *comment; // Comment } TestStorageGetParam; @@ -202,8 +202,7 @@ typedef struct HrnStoragePutParam mode_t modeFile; // File mode if not the default time_t timeModified; // Time file was last modified CompressType compressType; // Limited to gz and bz2 (lz4 and zstd are not always available) - CipherType cipherType; - const char *cipherPass; + const CipherSpec *cipherSpec; // Cipher spec to encrypt the file with const char *comment; // Comment } HrnStoragePutParam; diff --git a/test/src/module/command/archive/getTest.c b/test/src/module/command/archive/getTest.c index 636f342c2..c4e72464a 100644 --- a/test/src/module/command/archive/getTest.c +++ b/test/src/module/command/archive/getTest.c @@ -1057,11 +1057,11 @@ testRun(void) "\n" "[db:history]\n" "1={\"db-id\":" HRN_PG_SYSTEMID_10_Z ",\"db-version\":\"10\"}", - .cipherType = cipherTypeAes256Cbc); + .cipherSpec = TEST_CIPHER_SPEC); HRN_STORAGE_PUT( storageRepoWrite(), STORAGE_REPO_ARCHIVE "/10-1/01ABCDEF01ABCDEF01ABCDEF-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - buffer, .compressType = compressTypeGz, .cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS_ARCHIVE); + buffer, .compressType = compressTypeGz, .cipherSpec = TEST_CIPHER_SPEC_PASS(TEST_CIPHER_PASS_ARCHIVE)); // Add encryption options argList = strLstNew(); diff --git a/test/src/module/command/archive/pushTest.c b/test/src/module/command/archive/pushTest.c index 62f3c860b..5dacac7bf 100644 --- a/test/src/module/command/archive/pushTest.c +++ b/test/src/module/command/archive/pushTest.c @@ -179,8 +179,8 @@ testRun(void) ArchivePushFileRepoData *repoData = lstGet(result.repoList, 0); TEST_RESULT_UINT(repoData->repoIdx, 0, "check repo idx"); TEST_RESULT_STR_Z(repoData->archiveId, "9.6-1", "check archive id"); - TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check cipher type"); - TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check cipher pass (not set in this test)"); + TEST_RESULT_UINT(cipherSpecType(repoData->cipherSpecArchive), cipherTypeNone, "check cipher type"); + TEST_RESULT_PTR(cipherSpecPass(repoData->cipherSpecArchive), NULL, "check cipher pass (not set in this test)"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("mismatched repos when pg-path not present"); @@ -223,8 +223,8 @@ testRun(void) repoData = lstGet(result.repoList, 0); TEST_RESULT_UINT(repoData->repoIdx, 0, "check repo idx"); TEST_RESULT_STR_Z(repoData->archiveId, "9.6-1", "check archive id"); - TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check cipher type"); - TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check cipher pass (not set in this test)"); + TEST_RESULT_UINT(cipherSpecType(repoData->cipherSpecArchive), cipherTypeNone, "check cipher type"); + TEST_RESULT_PTR(cipherSpecPass(repoData->cipherSpecArchive), NULL, "check cipher pass (not set in this test)"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("matched repos when pg-path not present"); @@ -247,14 +247,14 @@ testRun(void) repoData = lstGet(result.repoList, 0); TEST_RESULT_UINT(repoData->repoIdx, 0, "check repo idx"); TEST_RESULT_STR_Z(repoData->archiveId, "9.6-1", "check repo2 archive id"); - TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check repo2 cipher pass"); - TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check repo2 cipher pass (not set in this test)"); + TEST_RESULT_UINT(cipherSpecType(repoData->cipherSpecArchive), cipherTypeNone, "check repo2 cipher pass"); + TEST_RESULT_PTR(cipherSpecPass(repoData->cipherSpecArchive), NULL, "check repo2 cipher pass (not set in this test)"); repoData = lstGet(result.repoList, 1); TEST_RESULT_UINT(repoData->repoIdx, 1, "check repo idx"); TEST_RESULT_STR_Z(repoData->archiveId, "9.6-2", "check repo4 archive id"); - TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check repo4 cipher type"); - TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check repo4 cipher pass (not set in this test)"); + TEST_RESULT_UINT(cipherSpecType(repoData->cipherSpecArchive), cipherTypeNone, "check repo4 cipher type"); + TEST_RESULT_PTR(cipherSpecPass(repoData->cipherSpecArchive), NULL, "check repo4 cipher pass (not set in this test)"); } // ***************************************************************************************************************************** @@ -544,7 +544,7 @@ testRun(void) "\n" "[db:history]\n" "1={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}", - .cipherType = cipherTypeAes256Cbc, .cipherPass = "badpassphrase"); + .cipherSpec = TEST_CIPHER_SPEC_PASS("badpassphrase")); // repo3 is not encrypted HRN_INFO_PUT( diff --git a/test/src/module/command/backupTest.c b/test/src/module/command/backupTest.c index 858c5c6e1..3ce8c2475 100644 --- a/test/src/module/command/backupTest.c +++ b/test/src/module/command/backupTest.c @@ -27,8 +27,7 @@ Get a list of all files in the backup and a redacted version of the manifest tha static String * testBackupValidateFile( const Storage *const storage, const String *const path, Manifest *const manifest, const ManifestData *const manifestData, - const String *const fileName, uint64_t fileSize, ManifestFilePack **const filePack, const CipherType cipherType, - const String *const cipherPass) + const String *const fileName, uint64_t fileSize, ManifestFilePack **const filePack) { FUNCTION_HARNESS_BEGIN(); FUNCTION_HARNESS_PARAM(STORAGE, storage); @@ -38,13 +37,14 @@ testBackupValidateFile( FUNCTION_HARNESS_PARAM(STRING, fileName); FUNCTION_HARNESS_PARAM(UINT64, fileSize); FUNCTION_HARNESS_PARAM_P(VOID, filePack); - FUNCTION_HARNESS_PARAM(STRING_ID, cipherType); - FUNCTION_HARNESS_PARAM(STRING, cipherPass); FUNCTION_HARNESS_END(); String *const result = strNew(); ManifestFile file = manifestFileUnpack(manifest, *filePack); + // Every backup in a set shares the passphrase stored in the manifest, including files referenced from a prior backup + const CipherSpec *const cipherSpecBackup = manifestCipherSpec(manifest); + // Output name and size // ------------------------------------------------------------------------------------------------------------- if (file.bundleId != 0) @@ -89,11 +89,10 @@ testBackupValidateFile( .offset = file.bundleOffset + file.sizeRepo - file.blockIncrMapSize, .limit = VARUINT64(file.blockIncrMapSize)); - if (cipherType != cipherTypeNone) + if (cipherSpecType(cipherSpecBackup) != cipherTypeNone) { ioFilterGroupAdd( - ioReadFilterGroup(storageReadIo(read)), - cipherBlockNewP(cipherModeDecrypt, cipherType, BUFSTR(cipherPass), .raw = true)); + ioReadFilterGroup(storageReadIo(read)), cipherBlockNewP(cipherModeDecrypt, cipherSpecBackup, .raw = true)); } ioReadOpen(storageReadIo(read)); @@ -129,7 +128,7 @@ testBackupValidateFile( bufUsedSet(fileBuffer, bufSize(fileBuffer)); BlockDelta *const blockDelta = blockDeltaNew( - blockMap, file.blockIncrSize, file.blockIncrChecksumSize, NULL, cipherType, cipherPass, + blockMap, file.blockIncrSize, file.blockIncrChecksumSize, NULL, cipherSpecBackup, manifestData->backupOptionCompressType); for (unsigned int readIdx = 0; readIdx < blockDeltaReadSize(blockDelta); readIdx++) @@ -170,11 +169,10 @@ testBackupValidateFile( .limit = VARUINT64(file.sizeRepo)); const bool raw = file.bundleId != 0 && manifest->pub.data.bundleRaw; - if (cipherType != cipherTypeNone) + if (cipherSpecType(cipherSpecBackup) != cipherTypeNone) { ioFilterGroupAdd( - ioReadFilterGroup(storageReadIo(read)), - cipherBlockNewP(cipherModeDecrypt, cipherType, BUFSTR(cipherPass), .raw = raw)); + ioReadFilterGroup(storageReadIo(read)), cipherBlockNewP(cipherModeDecrypt, cipherSpecBackup, .raw = raw)); } if (manifestData->backupOptionCompressType != compressTypeNone) @@ -255,7 +253,7 @@ testBackupValidateFile( static String * testBackupValidateList( const Storage *const storage, const String *const path, Manifest *const manifest, const ManifestData *const manifestData, - StringList *const manifestFileList, const CipherType cipherType, const String *const cipherPass, String *const result) + StringList *const manifestFileList, String *const result) { FUNCTION_HARNESS_BEGIN(); FUNCTION_HARNESS_PARAM(STORAGE, storage); @@ -263,8 +261,6 @@ testBackupValidateList( FUNCTION_HARNESS_PARAM(MANIFEST, manifest); FUNCTION_HARNESS_PARAM_P(VOID, manifestData); FUNCTION_HARNESS_PARAM(STRING_LIST, manifestFileList); - FUNCTION_HARNESS_PARAM(STRING_ID, cipherType); - FUNCTION_HARNESS_PARAM(STRING, cipherPass); FUNCTION_HARNESS_PARAM(STRING, result); FUNCTION_HARNESS_END(); @@ -353,10 +349,7 @@ testBackupValidateList( manifestFileList, (String *const)*filePack, .required = true); strLstRemoveIdx(manifestFileList, manifestFileIdx); - strCat( - result, - testBackupValidateFile( - storage, path, manifest, manifestData, info.name, info.size, filePack, cipherType, cipherPass)); + strCat(result, testBackupValidateFile(storage, path, manifest, manifestData, info.name, info.size, filePack)); } break; @@ -402,8 +395,7 @@ testBackupValidateList( typedef struct TestBackupValidateParam { VAR_PARAM_HEADER; - CipherType cipherType; // Cipher type - const char *cipherPass; // Cipher pass + const CipherSpec *cipherSpecMain; // Cipher spec the repo is configured with } TestBackupValidateParam; #define testBackupValidateP(storage, path, ...) \ @@ -415,8 +407,7 @@ testBackupValidate(const Storage *const storage, const String *const path, const FUNCTION_HARNESS_BEGIN(); FUNCTION_HARNESS_PARAM(STORAGE, storage); FUNCTION_HARNESS_PARAM(STRING, path); - FUNCTION_HARNESS_PARAM(UINT64, param.cipherType); - FUNCTION_HARNESS_PARAM(STRINGZ, param.cipherPass); + FUNCTION_HARNESS_PARAM(CIPHER_SPEC, param.cipherSpecMain); FUNCTION_HARNESS_END(); ASSERT(storage != NULL); @@ -429,11 +420,9 @@ testBackupValidate(const Storage *const storage, const String *const path, const // Build a list of files in the backup path and verify against the manifest // ------------------------------------------------------------------------------------------------------------------------- const InfoBackup *const infoBackup = infoBackupLoadFile( - storageRepo(), INFO_BACKUP_PATH_FILE_STR, param.cipherType == 0 ? cipherTypeNone : param.cipherType, - param.cipherPass == NULL ? NULL : STR(param.cipherPass)); + storageRepo(), INFO_BACKUP_PATH_FILE_STR, param.cipherSpecMain == NULL ? cipherSpecNewNone() : param.cipherSpecMain); Manifest *manifest = manifestLoadFile( - storage, strNewFmt("%s/" BACKUP_MANIFEST_FILE, strZ(path)), param.cipherType == 0 ? cipherTypeNone : param.cipherType, - param.cipherPass == NULL ? NULL : infoBackupCipherPass(infoBackup)); + storage, strNewFmt("%s/" BACKUP_MANIFEST_FILE, strZ(path)), infoBackupCipherSpec(infoBackup)); // Build list of files in the manifest StringList *const manifestFileList = strLstNew(); @@ -442,10 +431,7 @@ testBackupValidate(const Storage *const storage, const String *const path, const strLstAdd(manifestFileList, manifestFileUnpack(manifest, manifestFilePackGet(manifest, fileIdx)).name); // Validate files on disk against the manifest - const CipherType cipherType = param.cipherType == 0 ? cipherTypeNone : param.cipherType; - const String *const cipherPass = param.cipherPass == NULL ? NULL : manifestCipherSubPass(manifest); - - testBackupValidateList(storage, path, manifest, manifestData(manifest), manifestFileList, cipherType, cipherPass, result); + testBackupValidateList(storage, path, manifest, manifestData(manifest), manifestFileList, result); // Check remaining files in the manifest -- these should all be references for (unsigned int manifestFileIdx = 0; manifestFileIdx < strLstSize(manifestFileList); manifestFileIdx++) @@ -473,7 +459,7 @@ testBackupValidate(const Storage *const storage, const String *const path, const .compressType = manifestData(manifest)->backupOptionCompressType, .blockIncr = file.blockIncrMapSize != 0), sizeof(STORAGE_REPO_BACKUP)), - file.sizeRepo, filePack, cipherType, cipherPass)); + file.sizeRepo, filePack)); } // Make sure both backup.manifest files exist since we skipped them in the callback above @@ -1326,7 +1312,8 @@ testRun(void) ioFilterParamList( blockIncrNew( 3, 3, 8, 2, 4, 5, NULL, compressFilterP(compressTypeGz, 1, .raw = true), - cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, BUFSTRDEF(TEST_CIPHER_PASS), .raw = true)))), + cipherBlockNewP( + cipherModeEncrypt, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF(TEST_CIPHER_PASS)), .raw = true)))), "block incr pack"); } @@ -1690,7 +1677,7 @@ testRun(void) HRN_STORAGE_PATH_CREATE(storageRepoWrite(), STORAGE_REPO_BACKUP "/20191003-105320F"); - TEST_RESULT_PTR(backupResumeFind((Manifest *)1, NULL), NULL, "find resumable backup"); + TEST_RESULT_PTR(backupResumeFind((Manifest *)1, cipherSpecNewNone()), NULL, "find resumable backup"); TEST_RESULT_LOG( "P00 WARN: backup '20191003-105320F' cannot be resumed: partially deleted by prior resume or invalid"); @@ -1704,7 +1691,7 @@ testRun(void) HRN_STORAGE_PUT_EMPTY(storageRepoWrite(), STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT); - TEST_RESULT_PTR(backupResumeFind((Manifest *)1, NULL), NULL, "find resumable backup"); + TEST_RESULT_PTR(backupResumeFind((Manifest *)1, cipherSpecNewNone()), NULL, "find resumable backup"); TEST_RESULT_LOG("P00 INFO: backup '20191003-105320F' cannot be resumed: resume is disabled"); @@ -1727,7 +1714,7 @@ testRun(void) HRN_STORAGE_PUT_Z(storageRepoWrite(), STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT, "X"); - TEST_RESULT_PTR(backupResumeFind(manifest, NULL), NULL, "find resumable backup"); + TEST_RESULT_PTR(backupResumeFind(manifest, cipherSpecNewNone()), NULL, "find resumable backup"); TEST_RESULT_LOG( "P00 WARN: backup '20191003-105320F' cannot be resumed: unable to read" @@ -1759,7 +1746,7 @@ testRun(void) storageNewWriteP( storageRepoWrite(), STRDEF(STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT)))); - TEST_RESULT_PTR(backupResumeFind(manifest, NULL), NULL, "find resumable backup"); + TEST_RESULT_PTR(backupResumeFind(manifest, cipherSpecNewNone()), NULL, "find resumable backup"); TEST_RESULT_LOG( "P00 WARN: backup '20191003-105320F' cannot be resumed:" @@ -1781,7 +1768,7 @@ testRun(void) storageNewWriteP( storageRepoWrite(), STRDEF(STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT)))); - TEST_RESULT_PTR(backupResumeFind(manifest, NULL), NULL, "find resumable backup"); + TEST_RESULT_PTR(backupResumeFind(manifest, cipherSpecNewNone()), NULL, "find resumable backup"); TEST_RESULT_LOG( "P00 WARN: backup '20191003-105320F' cannot be resumed:" @@ -1803,7 +1790,7 @@ testRun(void) storageNewWriteP( storageRepoWrite(), STRDEF(STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT)))); - TEST_RESULT_PTR(backupResumeFind(manifest, NULL), NULL, "find resumable backup"); + TEST_RESULT_PTR(backupResumeFind(manifest, cipherSpecNewNone()), NULL, "find resumable backup"); TEST_RESULT_LOG( "P00 WARN: backup '20191003-105320F' cannot be resumed:" @@ -1824,7 +1811,7 @@ testRun(void) storageNewWriteP( storageRepoWrite(), STRDEF(STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT)))); - TEST_RESULT_PTR(backupResumeFind(manifest, NULL), NULL, "find resumable backup"); + TEST_RESULT_PTR(backupResumeFind(manifest, cipherSpecNewNone()), NULL, "find resumable backup"); TEST_RESULT_LOG( "P00 WARN: backup '20191003-105320F' cannot be resumed:" @@ -3663,7 +3650,8 @@ testRun(void) { // Load the previous manifest and null out the checksum-page option to be sure it gets set to false in this backup const String *manifestPriorFile = STRDEF(STORAGE_REPO_BACKUP "/20191103-165320F/" BACKUP_MANIFEST_FILE); - Manifest *manifestPrior = manifestNewLoad(storageReadIo(storageNewReadP(storageRepo(), manifestPriorFile))); + Manifest *manifestPrior = manifestNewLoad( + storageReadIo(storageNewReadP(storageRepo(), manifestPriorFile)), cipherSpecNewNone()); manifestPrior->pub.data.backupOptionChecksumPage = NULL; manifestSave(manifestPrior, storageWriteIo(storageNewWriteP(storageRepoWrite(), manifestPriorFile))); @@ -3853,8 +3841,8 @@ testRun(void) // Run backup hrnBackupPqScriptP( - PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS, .walTotal = 2, .walSwitch = true); + PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherSpecMain = TEST_CIPHER_SPEC, + .walTotal = 2, .walSwitch = true); TEST_RESULT_VOID(hrnCmdBackup(), "backup"); TEST_RESULT_LOG( @@ -3874,8 +3862,7 @@ testRun(void) TEST_RESULT_STR_Z( testBackupValidateP( - storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS), + storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherSpecMain = TEST_CIPHER_SPEC), ".> {d=20191108-080000F}\n" "bundle/1/pg_data/PG_VERSION {s=2, ts=-400000}\n" "bundle/1/pg_data/global/pg_control {s=8192}\n" @@ -3932,8 +3919,8 @@ testRun(void) // Run backup hrnBackupPqScriptP( - PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS, .walTotal = 2, .walSwitch = true); + PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherSpecMain = TEST_CIPHER_SPEC, + .walTotal = 2, .walSwitch = true); TEST_RESULT_VOID(hrnCmdBackup(), "backup"); TEST_RESULT_LOG( @@ -3960,8 +3947,7 @@ testRun(void) TEST_RESULT_STR_Z( testBackupValidateP( - storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS), + storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherSpecMain = TEST_CIPHER_SPEC), ".> {d=20191108-080000F}\n" "bundle/1/pg_data/PG_VERSION {s=2, ts=-500000}\n" "bundle/1/pg_data/global/pg_control {s=8192}\n" @@ -4029,8 +4015,8 @@ testRun(void) // Run backup hrnBackupPqScriptP( - PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS, .walTotal = 2, .walSwitch = true); + PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherSpecMain = TEST_CIPHER_SPEC, + .walTotal = 2, .walSwitch = true); TEST_RESULT_VOID(hrnCmdBackup(), "backup"); TEST_RESULT_LOG( @@ -4058,8 +4044,7 @@ testRun(void) TEST_RESULT_STR_Z( testBackupValidateP( - storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS), + storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherSpecMain = TEST_CIPHER_SPEC), ".> {d=20191108-080000F_20191110-153320D}\n" "bundle/1/pg_data/block-age-multiplier {s=32768, m=1:{0,1}, ts=-86400}\n" "bundle/1/pg_data/block-age-to-zero {s=16384, ts=-172800}\n" @@ -4095,8 +4080,8 @@ testRun(void) // Run backup hrnBackupPqScriptP( - PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS, .walTotal = 1, .walSwitch = false); + PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherSpecMain = TEST_CIPHER_SPEC, + .walTotal = 1, .walSwitch = false); TEST_RESULT_VOID(hrnCmdBackup(), "backup"); TEST_RESULT_LOG( @@ -4121,8 +4106,7 @@ testRun(void) TEST_RESULT_STR_Z( testBackupValidateP( - storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS), + storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherSpecMain = TEST_CIPHER_SPEC), ".> {d=20191108-080000F_20191111-052640I}\n" "pg_data/backup_label.gz {s=17, ts=+2}\n" "pg_data/global/pg_control.gz {s=8192}\n" @@ -4186,8 +4170,8 @@ testRun(void) {.op = hrnBackupScriptOpUpdate, .file = storagePathP(storagePg(), STRDEF("global/1")), .time = backupTimeStart + 1, .content = fileGrow}); hrnBackupPqScriptP( - PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS, .walTotal = 2, .walSwitch = true); + PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherSpecMain = TEST_CIPHER_SPEC, + .walTotal = 2, .walSwitch = true); TEST_RESULT_VOID(hrnCmdBackup(), "backup"); // Make sure that global/1 grew as expected but the extra bytes were not copied @@ -4211,8 +4195,7 @@ testRun(void) TEST_RESULT_STR_Z( testBackupValidateP( - storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS), + storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherSpecMain = TEST_CIPHER_SPEC), ".> {d=20191111-192000F}\n" "bundle/1/pg_data/PG_VERSION {s=2}\n" "bundle/1/pg_data/global/pg_control {s=8192}\n" diff --git a/test/src/module/command/checkTest.c b/test/src/module/command/checkTest.c index 4cffcfb6d..629877ec5 100644 --- a/test/src/module/command/checkTest.c +++ b/test/src/module/command/checkTest.c @@ -753,10 +753,7 @@ testRun(void) // Version mismatch TEST_ERROR( - checkStanzaInfoPg( - storageRepoIdx(0), PG_VERSION_18, HRN_PG_SYSTEMID_18, cfgOptionIdxStrId(cfgOptRepoCipherType, 0), - cfgOptionIdxStr(cfgOptRepoCipherPass, 0)), - FileInvalidError, + checkStanzaInfoPg(storageRepoIdx(0), PG_VERSION_18, HRN_PG_SYSTEMID_18, cfgCipherSpecMainIdx(0)), FileInvalidError, "backup and archive info files exist but do not match the database\n" "HINT: is this the correct stanza?\n" "HINT: did an error occur during stanza-upgrade?"); @@ -766,10 +763,7 @@ testRun(void) // SystemId mismatch TEST_ERROR( - checkStanzaInfoPg( - storageRepoIdx(0), PG_VERSION_96, 6569239123849665699, cfgOptionIdxStrId(cfgOptRepoCipherType, 0), - cfgOptionIdxStr(cfgOptRepoCipherPass, 0)), - FileInvalidError, + checkStanzaInfoPg(storageRepoIdx(0), PG_VERSION_96, 6569239123849665699, cfgCipherSpecMainIdx(0)), FileInvalidError, "backup and archive info files exist but do not match the database\n" "HINT: is this the correct stanza?\n" "HINT: did an error occur during stanza-upgrade?"); diff --git a/test/src/module/command/expireTest.c b/test/src/module/command/expireTest.c index a4e7e3bfb..fb25001a9 100644 --- a/test/src/module/command/expireTest.c +++ b/test/src/module/command/expireTest.c @@ -156,7 +156,7 @@ testRun(void) // Create backup.info InfoBackup *infoBackup = NULL; - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info"); + TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase), cipherSpecNewNone()), "get backup.info"); // Load Parameters StringList *argList = strLstDup(argListAvoidWarn); @@ -190,7 +190,7 @@ testRun(void) { // Create backup.info InfoBackup *infoBackup = NULL; - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info"); + TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase), cipherSpecNewNone()), "get backup.info"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("retention-full not set - nothing expired"); @@ -251,7 +251,7 @@ testRun(void) { // Create backup.info InfoBackup *infoBackup = NULL; - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info"); + TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase), cipherSpecNewNone()), "get backup.info"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("retention-diff not set - nothing expired"); @@ -334,7 +334,7 @@ testRun(void) "1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702" ",\"db-version\":\"9.4\"}"); - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent)), "get backup.info"); + TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent), cipherSpecNewNone()), "get backup.info"); // Load parameters argList = strLstDup(argListAvoidWarn); @@ -386,7 +386,8 @@ testRun(void) InfoBackup *infoBackup = NULL; TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info"); + infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), + "get backup.info"); // Put some files in the backup directories HRN_STORAGE_PUT_Z(storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152100F/" BOGUS_STR, BOGUS_STR); @@ -429,7 +430,7 @@ testRun(void) "1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702" ",\"db-version\":\"9.4\"}"); - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent)), "get backup.info"); + TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent), cipherSpecNewNone()), "get backup.info"); TEST_RESULT_VOID(removeExpiredBackup(infoBackup, NULL, 0), "remove backups - backup.info current empty"); @@ -477,7 +478,8 @@ testRun(void) ",\"db-version\":\"9.4\"}"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info"); + infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), + "get backup.info"); // Committed backup (in backup.info) and an older orphan backup that is not in backup.info and has no manifest copy HRN_STORAGE_PUT_Z(storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152138F/" BOGUS_STR, BOGUS_STR); @@ -537,7 +539,7 @@ testRun(void) ",\"db-version\":\"9.4\"}"); InfoBackup *infoBackup = NULL; - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent)), "get backup.info"); + TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent), cipherSpecNewNone()), "get backup.info"); TEST_RESULT_VOID(removeExpiredArchive(infoBackup, false, 0), "archive retention not set"); TEST_RESULT_LOG( @@ -644,7 +646,8 @@ testRun(void) ",\"db-version\":\"10\"}\n"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info"); + infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), + "get backup.info"); HRN_INFO_PUT( storageRepoWrite(), INFO_ARCHIVE_PATH_FILE, @@ -885,13 +888,13 @@ testRun(void) "archive sub path repo1 not removed"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackup, infoBackupLoadFile(storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "get backup.info repo2"); TEST_RESULT_BOOL( strLstExists(infoBackupDataLabelList(infoBackup, NULL), STRDEF("20181119-152138F")), false, "backup removed from repo2"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepoIdx(0), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackup, infoBackupLoadFile(storageRepoIdx(0), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "get backup.info repo1"); TEST_RESULT_BOOL( strLstExists(infoBackupDataLabelList(infoBackup, NULL), STRDEF("20181119-152138F")), true, "backup exists repo1"); @@ -1125,7 +1128,7 @@ testRun(void) "P00 INFO: repo2: 10-2 no archive to remove"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "repo1: get backup.info"); TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 2, "repo1: backup.info updated on disk"); TEST_RESULT_STRLST_Z( @@ -1133,7 +1136,7 @@ testRun(void) "20181119-152900F\n20181119-152900F_20181119-152500I\n", "repo1: remaining current backups correct"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackup, infoBackupLoadFile(storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "repo2: get backup.info"); TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 4, "repo2: backup.info updated on disk"); TEST_RESULT_STRLST_Z( @@ -1256,7 +1259,8 @@ testRun(void) ",\"db-version\":\"10\"}\n"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info"); + infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), + "get backup.info"); archiveGenerate(storageRepoWrite(), STORAGE_REPO_ARCHIVE, 1, 5, "9.4-1", "0000000100000000"); @@ -1338,7 +1342,8 @@ testRun(void) ",\"db-version\":\"10\"}\n"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info"); + infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), + "get backup.info"); HRN_STORAGE_PUT_EMPTY(storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152138F/" BACKUP_MANIFEST_FILE); @@ -1601,7 +1606,8 @@ testRun(void) ",\"db-version\":\"10\"}\n"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info"); + infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), + "get backup.info"); HRN_INFO_PUT( storageRepoWrite(), INFO_ARCHIVE_PATH_FILE, @@ -1669,7 +1675,8 @@ testRun(void) ",\"db-version\":\"10\"}\n"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info"); + infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), + "get backup.info"); archiveGenerate(storageRepoWrite(), STORAGE_REPO_ARCHIVE, 1, 10, "9.4-1", "0000000100000000"); @@ -2064,7 +2071,8 @@ testRun(void) InfoBackup *infoBackup = NULL; TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info"); + infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), + "get backup.info"); // Create "latest" symlink const String *latestLink = storagePathP(storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest")); @@ -2302,7 +2310,8 @@ testRun(void) // Load the backup info. Do not store a manifest file for the adhoc backup for code coverage TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info"); + infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), + "get backup.info"); HRN_STORAGE_PATH_CREATE( storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152850F_20181119-152252D", @@ -2451,7 +2460,7 @@ testRun(void) "[db:history]\n" "1={\"db-id\":6625592122879095702,\"db-version\":\"9.4\"}\n" "2={\"db-id\":6626363367545678089,\"db-version\":\"12\"}", - .cipherType = cipherTypeAes256Cbc); + .cipherSpec = TEST_CIPHER_SPEC); const String *backupInfoContent = STRDEF( TEST_BACKUP_CURRENT @@ -2460,16 +2469,16 @@ testRun(void) "cipher-pass=\"somepass\"\n" TEST_BACKUP_DB); - HRN_INFO_PUT(storageRepoIdxWrite(1), INFO_BACKUP_PATH_FILE, strZ(backupInfoContent), .cipherType = cipherTypeAes256Cbc); + HRN_INFO_PUT(storageRepoIdxWrite(1), INFO_BACKUP_PATH_FILE, strZ(backupInfoContent), .cipherSpec = TEST_CIPHER_SPEC); HRN_INFO_PUT( storageRepoIdxWrite(1), STORAGE_REPO_BACKUP "/20181119-152850F/" BACKUP_MANIFEST_FILE, - "[backup]\nbackup-type=\"full\"\n", .cipherType = cipherTypeAes256Cbc, .cipherPass = "somepass"); + "[backup]\nbackup-type=\"full\"\n", .cipherSpec = TEST_CIPHER_SPEC_PASS("somepass")); HRN_INFO_PUT( storageRepoIdxWrite(1), STORAGE_REPO_BACKUP "/20181119-152850F_20181119-152252D/" BACKUP_MANIFEST_FILE, - "[backup]\nbackup-type=\"diff\"\n", .cipherType = cipherTypeAes256Cbc, .cipherPass = "somepass"); + "[backup]\nbackup-type=\"diff\"\n", .cipherSpec = TEST_CIPHER_SPEC_PASS("somepass")); HRN_INFO_PUT( storageRepoIdxWrite(1), STORAGE_REPO_BACKUP "/20181119-152850F_20181200-152252D/" BACKUP_MANIFEST_FILE INFO_COPY_EXT, - strZ(manifestContent), .cipherType = cipherTypeAes256Cbc, .cipherPass = "somepass", .comment = "resumable backup"); + strZ(manifestContent), .cipherSpec = TEST_CIPHER_SPEC_PASS("somepass"), .comment = "resumable backup"); // archives to repo2 archiveGenerate(storageRepoIdxWrite(1), STORAGE_REPO_ARCHIVE, 2, 10, "12-2", "0000000100000000"); @@ -2530,7 +2539,7 @@ testRun(void) "\n" "[db:history]\n" "1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702" - ",\"db-version\":\"9.4\"}"))), + ",\"db-version\":\"9.4\"}")), cipherSpecNewNone()), "empty backup.info"); TEST_RESULT_UINT(expireTimeBasedBackup(infoBackup, (time_t)(timeNow - (40 * SEC_PER_DAY)), 0), 0, "no backups to expire"); @@ -2569,7 +2578,7 @@ testRun(void) // Set the log level to detail so archive expiration messages are seen harnessLogLevelSet(logLevelDetail); - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info"); + TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase), cipherSpecNewNone()), "get backup.info"); TEST_RESULT_VOID(cmdExpire(), "repo-retention-full not set for time-based"); TEST_RESULT_LOG( "P00 WARN: option 'repo1-retention-full' is not set for 'repo1-retention-full-type=time', the repository may run out" @@ -2712,7 +2721,7 @@ testRun(void) // Expire oldest from backup.info only, leaving the backup and archives on disk then save backup.info without oldest backup TEST_RESULT_UINT(expireTimeBasedBackup(infoBackup, (time_t)(timeNow - (25 * SEC_PER_DAY)), 0), 1, "expire oldest backup"); TEST_RESULT_VOID( - infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "save backup.info without oldest"); TEST_RESULT_LOG("P00 INFO: repo1: expire time-based backup 20181119-152138F"); TEST_RESULT_VOID(cmdExpire(), "only oldest backup expired"); diff --git a/test/src/module/command/infoTest.c b/test/src/module/command/infoTest.c index 7b4a218bd..dd156e1b7 100644 --- a/test/src/module/command/infoTest.c +++ b/test/src/module/command/infoTest.c @@ -1045,7 +1045,7 @@ testRun(void) "\n" "[db:history]\n" "1={\"db-id\":6626363367545678089,\"db-version\":\"9.5\"}\n", - .cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS, + .cipherSpec = TEST_CIPHER_SPEC, .comment = "write encrypted archive.info, stanza1, repo2"); HRN_INFO_PUT( storageTest, TEST_PATH "/repo2/" STORAGE_PATH_BACKUP "/stanza1/" INFO_BACKUP_FILE, @@ -1072,7 +1072,7 @@ testRun(void) "[db:history]\n" "1={\"db-catalog-version\":201510051,\"db-control-version\":942,\"db-system-id\":6626363367545678089" ",\"db-version\":\"9.5\"}\n", - .cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS, + .cipherSpec = TEST_CIPHER_SPEC, .comment = "write encrypted backup.info, stanza1, repo2"); // Add WAL on repo1 and encrypted repo2 for stanza1 @@ -1143,7 +1143,7 @@ testRun(void) TEST_MANIFEST_LINK_DEFAULT TEST_MANIFEST_PATH TEST_MANIFEST_PATH_DEFAULT, - .cipherType = cipherTypeAes256Cbc, .cipherPass = "somepass", + .cipherSpec = TEST_CIPHER_SPEC_PASS("somepass"), .comment = "write encrypted manifest, stanza1, repo2"); // Create a stanza on repo2 that is not on repo1 @@ -1159,7 +1159,7 @@ testRun(void) "\n" "[db:history]\n" "1={\"db-id\":6626363367545678089,\"db-version\":\"9.4\"}\n", - .cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS, + .cipherSpec = TEST_CIPHER_SPEC, .comment = "write encrypted archive.info, repo2, stanza3"); HRN_INFO_PUT( storageTest, TEST_PATH "/repo2/" STORAGE_PATH_BACKUP "/stanza3/" INFO_BACKUP_FILE, @@ -1185,7 +1185,7 @@ testRun(void) "[db:history]\n" "1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6626363367545678089" ",\"db-version\":\"9.4\"}\n", - .cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS, + .cipherSpec = TEST_CIPHER_SPEC, .comment = "write encrypted backup.info, repo2, stanza3"); // Store some WAL in stanza on repo2 that is not on repo1 @@ -3069,7 +3069,7 @@ testRun(void) "[db:history]\n" "1={\"db-catalog-version\":201510051,\"db-control-version\":942,\"db-system-id\":6626363367545678089" ",\"db-version\":\"9.5\"}\n", - .cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS, + .cipherSpec = TEST_CIPHER_SPEC, .comment = "backup.info without current, repo2, stanza1"); TEST_RESULT_STR_Z( diff --git a/test/src/module/command/manifestTest.c b/test/src/module/command/manifestTest.c index c7c959f30..fa7a56f02 100644 --- a/test/src/module/command/manifestTest.c +++ b/test/src/module/command/manifestTest.c @@ -108,8 +108,7 @@ testRun(void) HRN_CFG_LOAD(cfgCmdBackup, argList); hrnBackupPqScriptP( - PG_VERSION_14, backupTimeStart, .noArchiveCheck = true, .noWal = true, .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS); + PG_VERSION_14, backupTimeStart, .noArchiveCheck = true, .noWal = true, .cipherSpecMain = TEST_CIPHER_SPEC); TEST_RESULT_VOID(hrnCmdBackup(), "backup repo2"); } @@ -137,7 +136,7 @@ testRun(void) // Munge the pg_control checksum since it will vary by architecture Manifest *manifest = manifestLoadFile( storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/20191002-070640F_20191003-105320D/" BACKUP_MANIFEST_FILE), - cipherTypeNone, NULL); + cipherSpecNewNone()); ManifestFile file = manifestFileFind(manifest, STRDEF(MANIFEST_TARGET_PGDATA "/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL)); file.checksumSha1 = bufPtr(bufNewDecode(encodingHex, STRDEF("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))); @@ -155,8 +154,7 @@ testRun(void) HRN_CFG_LOAD(cfgCmdBackup, argList); hrnBackupPqScriptP( - PG_VERSION_14, backupTimeStart, .noArchiveCheck = true, .noWal = true, .cipherType = cipherTypeAes256Cbc, - .cipherPass = TEST_CIPHER_PASS); + PG_VERSION_14, backupTimeStart, .noArchiveCheck = true, .noWal = true, .cipherSpecMain = TEST_CIPHER_SPEC); TEST_RESULT_VOID(hrnCmdBackup(), "backup repo2"); } diff --git a/test/src/module/command/repoTest.c b/test/src/module/command/repoTest.c index adbeed99c..4507f039f 100644 --- a/test/src/module/command/repoTest.c +++ b/test/src/module/command/repoTest.c @@ -402,31 +402,30 @@ testRun(void) HRN_STORAGE_PUT(storageFixture, strZ(fileName), fileBuffer); HRN_STORAGE_PUT_Z(storageFixture, strZ(fileRawName), fileRawContent); HRN_STORAGE_PUT( - storageFixture, STORAGE_PATH_ARCHIVE "/test/" INFO_ARCHIVE_FILE, archiveInfoFileBuffer, - .cipherType = cipherTypeAes256Cbc); + storageFixture, STORAGE_PATH_ARCHIVE "/test/" INFO_ARCHIVE_FILE, archiveInfoFileBuffer, .cipherSpec = TEST_CIPHER_SPEC); HRN_STORAGE_PUT( storageFixture, STORAGE_PATH_ARCHIVE "/test/" INFO_ARCHIVE_FILE ".copy", archiveInfoFileBuffer, - .cipherType = cipherTypeAes256Cbc); + .cipherSpec = TEST_CIPHER_SPEC); HRN_STORAGE_PUT( - storageFixture, STORAGE_PATH_BACKUP "/test/" INFO_BACKUP_FILE, backupInfoFileBuffer, .cipherType = cipherTypeAes256Cbc); + storageFixture, STORAGE_PATH_BACKUP "/test/" INFO_BACKUP_FILE, backupInfoFileBuffer, .cipherSpec = TEST_CIPHER_SPEC); HRN_STORAGE_PUT( storageFixture, STORAGE_PATH_BACKUP "/test/" INFO_BACKUP_FILE ".copy", backupInfoFileBuffer, - .cipherType = cipherTypeAes256Cbc); + .cipherSpec = TEST_CIPHER_SPEC); HRN_STORAGE_PUT( storageFixture, STORAGE_PATH_ARCHIVE "/test/12-1/000000010000000100000001-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - archiveFileBuffer, .cipherType = cipherTypeAes256Cbc, .cipherPass = "custom"); + archiveFileBuffer, .cipherSpec = TEST_CIPHER_SPEC_PASS("custom")); HRN_STORAGE_PUT( storageFixture, STORAGE_PATH_BACKUP "/test/latest/" BACKUP_MANIFEST_FILE, manifestFileBuffer, - .cipherType = cipherTypeAes256Cbc, .cipherPass = "custom"); + .cipherSpec = TEST_CIPHER_SPEC_PASS("custom")); HRN_STORAGE_PUT( storageFixture, STORAGE_PATH_BACKUP "/test/latest/" BACKUP_MANIFEST_FILE ".copy", manifestFileBuffer, - .cipherType = cipherTypeAes256Cbc, .cipherPass = "custom"); + .cipherSpec = TEST_CIPHER_SPEC_PASS("custom")); HRN_STORAGE_PUT( storageFixture, STORAGE_PATH_BACKUP "/test/backup.history/2020/label.manifest.gz", manifestFileBuffer, - .cipherType = cipherTypeAes256Cbc, .cipherPass = "custom"); + .cipherSpec = TEST_CIPHER_SPEC_PASS("custom")); HRN_STORAGE_PUT( storageFixture, STORAGE_PATH_BACKUP "/test/latest/pg_data/backup_label", backupLabelBuffer, - .cipherType = cipherTypeAes256Cbc, .cipherPass = "custom2"); + .cipherSpec = TEST_CIPHER_SPEC_PASS("custom2")); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("error when missing source"); diff --git a/test/src/module/command/restoreTest.c b/test/src/module/command/restoreTest.c index 83837b97d..ae43bff13 100644 --- a/test/src/module/command/restoreTest.c +++ b/test/src/module/command/restoreTest.c @@ -236,7 +236,7 @@ testRun(void) ioBufferReadNewOpen(BUF(bufPtr(destination) + (bufUsed(destination) - (size_t)mapSize), (size_t)mapSize)), 3, 5); // Perform block delta - BlockDelta *blockDelta = blockDeltaNew(blockMap, 3, 5, NULL, cipherTypeNone, NULL, compressTypeGz); + BlockDelta *blockDelta = blockDeltaNew(blockMap, 3, 5, NULL, cipherSpecNewNone(), compressTypeGz); const BlockDeltaRead *blockDeltaRead = blockDeltaReadGet(blockDelta, 0); IoRead *read = ioBufferReadNewOpen(destination); @@ -289,7 +289,7 @@ testRun(void) HRN_STORAGE_PUT_Z( storageRepoWrite(), zNewFmt(STORAGE_REPO_BACKUP "/%s/%s", strZ(repoFileReferenceFull), strZ(repoFile1)), - "acefile", .compressType = compressTypeGz, .cipherType = cipherTypeAes256Cbc, .cipherPass = "badpass", + "acefile", .compressType = compressTypeGz, .cipherSpec = TEST_CIPHER_SPEC_PASS("badpass"), .comment = "create a compressed encrypted repo file"); List *fileList = lstNewP(sizeof(RestoreFile)); @@ -311,7 +311,7 @@ testRun(void) TEST_ERROR( restoreFile( strNewFmt(STORAGE_REPO_BACKUP "/%s/%s.gz", strZ(repoFileReferenceFull), strZ(repoFile1)), repoIdx, compressTypeGz, - 0, false, false, false, STRDEF("badpass"), NULL, fileList), + 0, false, false, false, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("badpass")), NULL, fileList), ChecksumError, "error restoring 'normal': actual checksum 'd1cd8a7d11daa26814b93eb604e1d49ab4b43770' does not match expected checksum" " 'ffffffffffffffffffffffffffffffffffffffff'"); @@ -2070,45 +2070,45 @@ testRun(void) TEST_RESULT_VOID( timelineVerify( - storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_11, 1, 0xA1, NULL, CFGOPTVAL_RESTORE_TYPE_DEFAULT, cipherTypeNone, - NULL), + storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_11, 1, 0xA1, NULL, CFGOPTVAL_RESTORE_TYPE_DEFAULT, + cipherSpecNewNone()), "follow current timeline because of version"); TEST_RESULT_VOID( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_11, 1, 0xA1, STRDEF("latest"), CFGOPTVAL_RESTORE_TYPE_DEFAULT, - cipherTypeNone, NULL), + cipherSpecNewNone()), "follow latest timeline as requested"); TEST_RESULT_VOID( timelineVerify( - storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 1, 0xA1, NULL, cipherTypeNone, CFGOPTVAL_RESTORE_TYPE_DEFAULT, - NULL), + storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 1, 0xA1, NULL, CFGOPTVAL_RESTORE_TYPE_DEFAULT, + cipherSpecNewNone()), "follow latest timeline because of version"); TEST_RESULT_VOID( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 1, 0xA1, STRDEF("current"), CFGOPTVAL_RESTORE_TYPE_DEFAULT, - cipherTypeNone, NULL), + cipherSpecNewNone()), "follow current timeline as requested"); TEST_RESULT_VOID( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 1, 0xA1, STRDEF("1"), CFGOPTVAL_RESTORE_TYPE_DEFAULT, - cipherTypeNone, NULL), + cipherSpecNewNone()), "follow requested timeline (same as current)"); TEST_RESULT_VOID( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 0x10, 0xA1, STRDEF("0x10"), CFGOPTVAL_RESTORE_TYPE_DEFAULT, - cipherTypeNone, NULL), + cipherSpecNewNone()), "follow requested hex timeline (same as current)"); TEST_ERROR( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 0x10, 0xA1, STRDEF("bogus"), CFGOPTVAL_RESTORE_TYPE_DEFAULT, - cipherTypeNone, NULL), + cipherSpecNewNone()), DbMismatchError, "invalid target timeline 'bogus'"); HRN_STORAGE_PUT_Z(storageTest, "repo/archive/test1/17-1/00000009.history", "8"); TEST_ERROR( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 8, 0xA1, STRDEF("9"), CFGOPTVAL_RESTORE_TYPE_DEFAULT, - cipherTypeNone, NULL), + cipherSpecNewNone()), FormatError, "invalid timeline '9' at '" TEST_PATH "/repo/archive/test1/17-1/00000009.history':" " invalid history line format '8'"); @@ -2121,27 +2121,27 @@ testRun(void) TEST_RESULT_VOID( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 10, 0x4FFFFFF, NULL, CFGOPTVAL_RESTORE_TYPE_DEFAULT, - cipherTypeNone, NULL), + cipherSpecNewNone()), "follow current timeline"); TEST_RESULT_VOID( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 9, 0x4FFFFFF, NULL, CFGOPTVAL_RESTORE_TYPE_IMMEDIATE, - cipherTypeNone, NULL), + cipherSpecNewNone()), "follow current timeline (based on type immediate)"); TEST_RESULT_VOID( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 9, 0x4FFFFFF, NULL, CFGOPTVAL_RESTORE_TYPE_DEFAULT, - cipherTypeNone, NULL), + cipherSpecNewNone()), "follow latest timeline"); TEST_RESULT_VOID( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 9, 0x4FFFFFF, STRDEF("10"), CFGOPTVAL_RESTORE_TYPE_DEFAULT, - cipherTypeNone, NULL), + cipherSpecNewNone()), "target timeline found"); TEST_ERROR( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 9, 0x6000000, STRDEF("10"), CFGOPTVAL_RESTORE_TYPE_DEFAULT, - cipherTypeNone, NULL), + cipherSpecNewNone()), DbMismatchError, "target timeline A forked from backup timeline 9 at 0/5000000 which is before backup lsn of 0/6000000\n" "HINT: was the target timeline created by accidentally promoting a standby?\n" @@ -2155,7 +2155,7 @@ testRun(void) TEST_ERROR( timelineVerify( storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 6, 0x4FFFFFF, STRDEF("11"), CFGOPTVAL_RESTORE_TYPE_DEFAULT, - cipherTypeNone, NULL), + cipherSpecNewNone()), DbMismatchError, "backup timeline 6, lsn 0/4ffffff is not in the history of target timeline B\n" "HINT: was the target timeline created by promoting from a timeline < latest?"); } @@ -2287,7 +2287,7 @@ testRun(void) // Store the file also to the encrypted repo HRN_STORAGE_PUT_Z( storageRepoIdxWrite(1), TEST_REPO_PATH PG_FILE_PGVERSION, PG_VERSION_11_Z "\n", - .cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS_ARCHIVE); + .cipherSpec = TEST_CIPHER_SPEC_PASS(TEST_CIPHER_PASS_ARCHIVE)); // pg_tblspc HRN_MANIFEST_PATH_ADD(manifest, .name = MANIFEST_TARGET_PGDATA "/" MANIFEST_TARGET_PGTBLSPC); @@ -2307,8 +2307,9 @@ testRun(void) // Read the manifest, set a cipher passphrase and store it to the encrypted repo Manifest *manifestEncrypted = manifestLoadFile( - storageRepoIdxWrite(0), STRDEF(STORAGE_REPO_BACKUP "/" TEST_LABEL "/" BACKUP_MANIFEST_FILE), cipherTypeNone, NULL); - manifestCipherSubPassSet(manifestEncrypted, STRDEF(TEST_CIPHER_PASS_ARCHIVE)); + storageRepoIdxWrite(0), STRDEF(STORAGE_REPO_BACKUP "/" TEST_LABEL "/" BACKUP_MANIFEST_FILE), + cipherSpecNewNone()); + manifestCipherSpecSet(manifestEncrypted, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF(TEST_CIPHER_PASS_ARCHIVE))); // Open file for write IoWrite *write = storageWriteIo( @@ -2319,19 +2320,21 @@ testRun(void) // Add encryption filter and save the encrypted manifest #define TEST_CIPHER_PASS_MANIFEST "backpass" cipherBlockFilterGroupAdd( - ioWriteFilterGroup(write), cfgOptionIdxStrId(cfgOptRepoCipherType, 1), cipherModeEncrypt, - STRDEF(TEST_CIPHER_PASS_MANIFEST)); + ioWriteFilterGroup(write), cipherModeEncrypt, + cipherSpecNew(cfgOptionIdxStrId(cfgOptRepoCipherType, 1), BUFSTRDEF(TEST_CIPHER_PASS_MANIFEST))); manifestSave(manifestEncrypted, write); // Write backup.info to the encrypted repo HRN_INFO_PUT( storageRepoIdxWrite(1), INFO_BACKUP_PATH_FILE, TEST_RESTORE_BACKUP_INFO "\n[cipher]\ncipher-pass=\"" - TEST_CIPHER_PASS_MANIFEST "\"\n\n" TEST_RESTORE_BACKUP_INFO_DB, .cipherType = cipherTypeAes256Cbc); + TEST_CIPHER_PASS_MANIFEST "\"\n\n" TEST_RESTORE_BACKUP_INFO_DB, .cipherSpec = TEST_CIPHER_SPEC); // Write archive.info to the encrypted repo - InfoArchive *infoArchive = infoArchiveNew(PG_VERSION_11, 6569239123849665679, STRDEF(TEST_CIPHER_PASS_ARCHIVE)); + InfoArchive *infoArchive = infoArchiveNew( + PG_VERSION_11, 6569239123849665679, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF(TEST_CIPHER_PASS_ARCHIVE))); infoArchiveSaveFile( - infoArchive, storageRepoIdxWrite(1), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF(TEST_CIPHER_PASS)); + infoArchive, storageRepoIdxWrite(1), INFO_ARCHIVE_PATH_FILE_STR, + cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF(TEST_CIPHER_PASS))); TEST_RESULT_VOID(hrnCmdRestore(), "successful restore"); @@ -2376,7 +2379,8 @@ testRun(void) // Store archive.info to repo1 - repo1 will be selected because of the priority order infoArchive = infoArchiveNew(PG_VERSION_11, 6569239123849665679, NULL); - infoArchiveSaveFile(infoArchive, storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeNone, NULL); + infoArchiveSaveFile( + infoArchive, storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE_STR, cipherSpecNewNone()); hrnCfgArgRawZ(argList, cfgOptTargetTimeline, "0xff"); HRN_CFG_LOAD(cfgCmdRestore, argList); diff --git a/test/src/module/command/stanzaTest.c b/test/src/module/command/stanzaTest.c index 46d85b771..0154e0653 100644 --- a/test/src/module/command/stanzaTest.c +++ b/test/src/module/command/stanzaTest.c @@ -133,42 +133,53 @@ testRun(void) InfoArchive *infoArchive = NULL; TEST_ASSIGN( infoArchive, - infoArchiveLoadFile(storageRepoIdx(1), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF("12345678")), + infoArchiveLoadFile( + storageRepoIdx(1), INFO_ARCHIVE_PATH_FILE_STR, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("12345678"))), "load archive info from encrypted repo2"); - TEST_RESULT_PTR_NE(infoArchiveCipherPass(infoArchive), NULL, "cipher sub set"); + TEST_RESULT_UINT(cipherSpecType(infoArchiveCipherSpec(infoArchive)), cipherTypeAes256Cbc, "cipher sub set"); InfoBackup *infoBackup = NULL; TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF("12345678")), + infoBackup, + infoBackupLoadFile( + storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("12345678"))), "load backup info from encrypted repo2"); - TEST_RESULT_PTR_NE(infoBackupCipherPass(infoBackup), NULL, "cipher sub set"); + TEST_RESULT_UINT(cipherSpecType(infoBackupCipherSpec(infoBackup)), cipherTypeAes256Cbc, "cipher sub set"); TEST_RESULT_BOOL( - strEq(infoArchiveCipherPass(infoArchive), infoBackupCipherPass(infoBackup)), false, + bufEq(cipherSpecPass(infoArchiveCipherSpec(infoArchive)), cipherSpecPass(infoBackupCipherSpec(infoBackup))), false, "cipher sub different for archive and backup"); // Confirm non-encrypted repo created successfully TEST_ASSIGN( - infoArchive, infoArchiveLoadFile(storageRepoIdx(2), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeNone, NULL), + infoArchive, + infoArchiveLoadFile(storageRepoIdx(2), INFO_ARCHIVE_PATH_FILE_STR, cipherSpecNewNone()), "load archive info from repo3"); - TEST_RESULT_PTR(infoArchiveCipherPass(infoArchive), NULL, "archive cipher sub not set on non-encrypted repo"); + TEST_RESULT_UINT( + cipherSpecType(infoArchiveCipherSpec(infoArchive)), cipherTypeNone, + "archive cipher sub not set on non-encrypted repo"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepoIdx(2), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackup, infoBackupLoadFile(storageRepoIdx(2), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "load backup info from repo3"); - TEST_RESULT_PTR(infoBackupCipherPass(infoBackup), NULL, "backup cipher sub not set on non-encrypted repo"); + TEST_RESULT_UINT( + cipherSpecType(infoBackupCipherSpec(infoBackup)), cipherTypeNone, + "backup cipher sub not set on non-encrypted repo"); // Confirm other repo encrypted with different password TEST_ASSIGN( infoArchive, - infoArchiveLoadFile(storageRepoIdx(3), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF("87654321")), + infoArchiveLoadFile( + storageRepoIdx(3), INFO_ARCHIVE_PATH_FILE_STR, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("87654321"))), "load archive info from encrypted repo4"); - TEST_RESULT_PTR_NE(infoArchiveCipherPass(infoArchive), NULL, "cipher sub set"); + TEST_RESULT_UINT(cipherSpecType(infoArchiveCipherSpec(infoArchive)), cipherTypeAes256Cbc, "cipher sub set"); TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepoIdx(3), INFO_BACKUP_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF("87654321")), + infoBackup, + infoBackupLoadFile( + storageRepoIdx(3), INFO_BACKUP_PATH_FILE_STR, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("87654321"))), "load backup info from encrypted repo4"); - TEST_RESULT_PTR_NE(infoBackupCipherPass(infoBackup), NULL, "cipher sub set"); + TEST_RESULT_UINT(cipherSpecType(infoBackupCipherSpec(infoBackup)), cipherTypeAes256Cbc, "cipher sub set"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("cmdStanzaCreate missing files - multi-repo and encryption"); diff --git a/test/src/module/command/verifyTest.c b/test/src/module/command/verifyTest.c index 0c2987536..51d6f4257 100644 --- a/test/src/module/command/verifyTest.c +++ b/test/src/module/command/verifyTest.c @@ -238,7 +238,8 @@ testRun(void) InfoPg *infoPg = NULL; TEST_ASSIGN( - infoPg, infoArchivePg(infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_ARCHIVE_INFO_BASE)))), + infoPg, + infoArchivePg(infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_ARCHIVE_INFO_BASE)), cipherSpecNewNone())), "infoPg from archive.info"); // ------------------------------------------------------------------------------------------------------------------------- @@ -268,7 +269,8 @@ testRun(void) harnessLogLevelSet(logLevelDetail); backupResult.status = backupValid; - TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest"); + TEST_ASSIGN( + manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), false, infoPg, &jobErrorTotal), "verify manifest"); TEST_RESULT_PTR(manifest, NULL, "manifest not set - pg version mismatch"); TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid"); TEST_RESULT_LOG( @@ -303,7 +305,8 @@ testRun(void) .comment = "manifest copy - invalid system-id"); backupResult.status = backupValid; - TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest"); + TEST_ASSIGN( + manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), false, infoPg, &jobErrorTotal), "verify manifest"); TEST_RESULT_PTR(manifest, NULL, "manifest not set - pg system-id mismatch"); TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid"); TEST_RESULT_LOG( @@ -337,7 +340,8 @@ testRun(void) .comment = "manifest copy - invalid db-id"); backupResult.status = backupValid; - TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest"); + TEST_ASSIGN( + manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), false, infoPg, &jobErrorTotal), "verify manifest"); TEST_RESULT_PTR(manifest, NULL, "manifest not set - pg db-id mismatch"); TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid"); TEST_RESULT_LOG( @@ -355,7 +359,8 @@ testRun(void) storageRepoWrite(), TEST_PATH "/repo/" STORAGE_PATH_BACKUP "/db/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE INFO_COPY_EXT, TEST_INVALID_BACKREST_INFO, .comment = "invalid manifest copy"); - TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest"); + TEST_ASSIGN( + manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), false, infoPg, &jobErrorTotal), "verify manifest"); TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid"); TEST_RESULT_LOG( "P00 DETAIL: unable to open missing file '" TEST_PATH "/repo/backup/db/20181119-152138F/backup.manifest' for read\n" @@ -369,7 +374,8 @@ testRun(void) storageRepoWrite(), TEST_PATH "/repo/" STORAGE_PATH_BACKUP "/db/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE, TEST_INVALID_BACKREST_INFO, .comment = "invalid manifest"); - TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, true, infoPg, &jobErrorTotal), "verify manifest"); + TEST_ASSIGN( + manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), true, infoPg, &jobErrorTotal), "verify manifest"); TEST_RESULT_PTR(manifest, NULL, "manifest not set"); TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid"); TEST_RESULT_LOG( @@ -395,7 +401,8 @@ testRun(void) .comment = "valid manifest"); backupResult.status = backupValid; - TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, true, infoPg, &jobErrorTotal), "verify manifest"); + TEST_ASSIGN( + manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), true, infoPg, &jobErrorTotal), "verify manifest"); TEST_RESULT_PTR_NE(manifest, NULL, "manifest set"); TEST_RESULT_UINT(backupResult.status, backupValid, "manifest usable"); TEST_RESULT_LOG("P00 DETAIL: backup '20181119-152138F' manifest.copy does not match manifest"); @@ -485,7 +492,8 @@ testRun(void) // Create backup.info InfoBackup *backupInfo = NULL; TEST_ASSIGN( - backupInfo, infoBackupNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_BACKUP_INFO_MULTI_HISTORY_BASE))), + backupInfo, + infoBackupNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_BACKUP_INFO_MULTI_HISTORY_BASE)), cipherSpecNewNone()), "backup.info multi-history"); // ------------------------------------------------------------------------------------------------------------------------- @@ -504,7 +512,7 @@ testRun(void) "db-version=\"11\"\n" "\n" "[db:history]\n" - "2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))), + "2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}")), cipherSpecNewNone()), "archive.info missing history"); TEST_ERROR( @@ -526,7 +534,7 @@ testRun(void) "\n" "[db:history]\n" "1={\"db-id\":6625592122879095777,\"db-version\":\"9.6\"}\n" - "2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))), + "2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}")), cipherSpecNewNone()), "archive.info history system id mismatch"); TEST_ERROR( @@ -548,7 +556,7 @@ testRun(void) "\n" "[db:history]\n" "1={\"db-id\":" HRN_PG_SYSTEMID_96_Z ",\"db-version\":\"18\"}\n" - "2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))), + "2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}")), cipherSpecNewNone()), "archive.info history version mismatch"); TEST_ERROR( @@ -570,7 +578,7 @@ testRun(void) "\n" "[db:history]\n" "3={\"db-id\":" HRN_PG_SYSTEMID_96_Z ",\"db-version\":\"10\"}\n" - "2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))), + "2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}")), cipherSpecNewNone()), "archive.info history id mismatch"); TEST_ERROR( @@ -587,10 +595,12 @@ testRun(void) InfoBackup *backupInfo = NULL; InfoArchive *archiveInfo = NULL; TEST_ASSIGN( - backupInfo, infoBackupNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_BACKUP_INFO_MULTI_HISTORY_BASE))), + backupInfo, + infoBackupNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_BACKUP_INFO_MULTI_HISTORY_BASE)), cipherSpecNewNone()), "backup.info multi-history"); TEST_ASSIGN( - archiveInfo, infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE))), + archiveInfo, + infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE)), cipherSpecNewNone()), "archive.info multi-history"); InfoPg *pgHistory = infoArchivePg(archiveInfo); @@ -867,17 +877,17 @@ testRun(void) HRN_CFG_LOAD(cfgCmdVerify, argList); HRN_INFO_PUT( - storageRepoWrite(), INFO_BACKUP_PATH_FILE, TEST_NO_CURRENT_BACKUP, .cipherType = cipherTypeAes256Cbc, + storageRepoWrite(), INFO_BACKUP_PATH_FILE, TEST_NO_CURRENT_BACKUP, .cipherSpec = TEST_CIPHER_SPEC, .comment = "encrypted backup.info"); HRN_INFO_PUT( storageRepoWrite(), INFO_BACKUP_PATH_FILE INFO_COPY_EXT, TEST_NO_CURRENT_BACKUP, - .cipherType = cipherTypeAes256Cbc, .comment = "encrypted backup.info.copy"); + .cipherSpec = TEST_CIPHER_SPEC, .comment = "encrypted backup.info.copy"); HRN_INFO_PUT( storageRepoWrite(), INFO_ARCHIVE_PATH_FILE, TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE, - .cipherType = cipherTypeAes256Cbc, .comment = "encrypted archive.info"); + .cipherSpec = TEST_CIPHER_SPEC, .comment = "encrypted archive.info"); HRN_INFO_PUT( storageRepoWrite(), INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT, TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE, - .cipherType = cipherTypeAes256Cbc, .comment = "encrypted archive.info.copy"); + .cipherSpec = TEST_CIPHER_SPEC, .comment = "encrypted archive.info.copy"); TEST_RESULT_VOID(cmdVerify(), "usable encrypted backup and archive info files"); TEST_RESULT_LOG(""); @@ -899,20 +909,23 @@ testRun(void) String *filePathName = strNewZ(STORAGE_REPO_ARCHIVE "/testfile"); HRN_STORAGE_PUT_EMPTY(storageRepoWrite(), strZ(filePathName)); TEST_RESULT_UINT( - verifyFile(filePathName, 0, NULL, compressTypeNone, HASH_TYPE_SHA1_ZERO_BUF, 0, NULL), verifyOk, "file ok"); + verifyFile(filePathName, 0, NULL, compressTypeNone, HASH_TYPE_SHA1_ZERO_BUF, 0, cipherSpecNewNone()), + verifyOk, "file ok"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("file size invalid in archive"); HRN_STORAGE_PUT_Z(storageRepoWrite(), strZ(filePathName), fileContents); TEST_RESULT_UINT( - verifyFile(filePathName, 0, NULL, compressTypeNone, fileChecksum, 0, NULL), verifySizeInvalid, "file size invalid"); + verifyFile(filePathName, 0, NULL, compressTypeNone, fileChecksum, 0, cipherSpecNewNone()), + verifySizeInvalid, "file size invalid"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("file missing in archive"); TEST_RESULT_UINT( - verifyFile(strNewFmt(STORAGE_REPO_ARCHIVE "/missingFile"), 0, NULL, compressTypeNone, fileChecksum, 0, NULL), + verifyFile( + strNewFmt(STORAGE_REPO_ARCHIVE "/missingFile"), 0, NULL, compressTypeNone, fileChecksum, 0, cipherSpecNewNone()), verifyFileMissing, "file missing"); // ------------------------------------------------------------------------------------------------------------------------- @@ -921,15 +934,19 @@ testRun(void) // Create a compressed encrypted repo file in backup filePathName = strCatZ(strNew(), STORAGE_REPO_BACKUP "/testfile"); HRN_STORAGE_PUT_Z( - storageRepoWrite(), strZ(filePathName), fileContents, .compressType = compressTypeGz, .cipherType = cipherTypeAes256Cbc, - .cipherPass = "pass"); + storageRepoWrite(), strZ(filePathName), fileContents, .compressType = compressTypeGz, + .cipherSpec = TEST_CIPHER_SPEC_PASS("pass")); strCatZ(filePathName, ".gz"); TEST_RESULT_UINT( - verifyFile(filePathName, 0, NULL, compressTypeGz, fileChecksum, fileSize, STRDEF("pass")), + verifyFile( + filePathName, 0, NULL, compressTypeGz, fileChecksum, fileSize, + cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("pass"))), verifyOk, "file encrypted compressed ok"); TEST_RESULT_UINT( - verifyFile(filePathName, 0, NULL, compressTypeGz, bufNewDecode(encodingHex, STRDEF("aa")), fileSize, STRDEF("pass")), + verifyFile( + filePathName, 0, NULL, compressTypeGz, bufNewDecode(encodingHex, STRDEF("aa")), fileSize, + cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("pass"))), verifyChecksumMismatch, "file encrypted compressed checksum mismatch"); } @@ -2497,7 +2514,7 @@ testRun(void) HRN_CFG_LOAD(cfgCmdBackup, argList); hrnBackupPqScriptP( - PG_VERSION_11, BACKUP_EPOCH + 200000, .cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS); + PG_VERSION_11, BACKUP_EPOCH + 200000, .cipherSpecMain = TEST_CIPHER_SPEC); TEST_RESULT_VOID(hrnCmdBackup(), "backup"); TEST_RESULT_LOG( "P00 INFO: execute backup start: backup begins after the next regular checkpoint completes\n" diff --git a/test/src/module/common/cryptoTest.c b/test/src/module/common/cryptoTest.c index 221105736..400060249 100644 --- a/test/src/module/common/cryptoTest.c +++ b/test/src/module/common/cryptoTest.c @@ -72,18 +72,43 @@ testRun(void) // ***************************************************************************************************************************** if (testBegin("CipherBlock")) { - // Cipher and digest errors + // Cipher error // ------------------------------------------------------------------------------------------------------------------------- TEST_ERROR( - cipherBlockNewP(cipherModeEncrypt, cipherTypeNone, BUFSTRZ(TEST_PASS)), AssertError, "unable to load cipher 'none'"); - TEST_ERROR( - cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, testPass, .digest = STRDEF(BOGUS_STR)), AssertError, - "unable to load digest 'BOGUS'"); + cipherBlockNewP(cipherModeEncrypt, cipherSpecNew(strIdFromZ(BOGUS_STR), testPass)), AssertError, + "unable to load cipher 'BOGUS'"); // Initialization of object // ------------------------------------------------------------------------------------------------------------------------- - CipherBlock *cipherBlock = (CipherBlock *)ioFilterDriver( - cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, BUFSTRZ(TEST_PASS))); + // Build from a duplicate to show the copy carries the type and pass of the original + TEST_RESULT_UINT(cipherSpecType(cipherSpecDup(cipherSpecNewNone())), cipherTypeNone, "dup of none"); + + const CipherSpec *const cipherSpec = cipherSpecDup(cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF(TEST_PASS))); + + TEST_RESULT_UINT(cipherSpecType(cipherSpec), cipherTypeAes256Cbc, "dup type"); + TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(cipherSpec)), TEST_PASS, "dup pass"); + + // A pack carries nothing but the type when there is no cipher + PackWrite *packWrite = pckWriteNewP(); + + cipherSpecPack(packWrite, cipherSpecNewNone()); + pckWriteEndP(packWrite); + + TEST_RESULT_UINT( + cipherSpecType(cipherSpecNewPack(pckReadNew(pckWriteResult(packWrite)))), cipherTypeNone, "unpack none"); + + // Else it carries the type and pass + packWrite = pckWriteNewP(); + + cipherSpecPack(packWrite, cipherSpecNew(cipherTypeAes256Cbc, testPass)); + pckWriteEndP(packWrite); + + const CipherSpec *const cipherSpecUnpack = cipherSpecNewPack(pckReadNew(pckWriteResult(packWrite))); + + TEST_RESULT_UINT(cipherSpecType(cipherSpecUnpack), cipherTypeAes256Cbc, "unpack type"); + TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(cipherSpecUnpack)), TEST_PASS, "unpack pass"); + + CipherBlock *cipherBlock = (CipherBlock *)ioFilterDriver(cipherBlockNewP(cipherModeEncrypt, cipherSpec)); TEST_RESULT_INT(cipherBlock->mode, cipherModeEncrypt, "mode is valid"); TEST_RESULT_UINT(bufSize(cipherBlock->pass), strlen(TEST_PASS), "passphrase size is valid"); TEST_RESULT_BOOL(memcmp(bufPtrConst(cipherBlock->pass), TEST_PASS, strlen(TEST_PASS)) == 0, true, "passphrase is valid"); @@ -98,7 +123,7 @@ testRun(void) // ------------------------------------------------------------------------------------------------------------------------- Buffer *encryptBuffer = bufNew(TEST_BUFFER_SIZE); - IoFilter *blockEncryptFilter = cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, testPass); + IoFilter *blockEncryptFilter = cipherBlockNewP(cipherModeEncrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass)); blockEncryptFilter = cipherBlockNewPack(ioFilterParamList(blockEncryptFilter)); CipherBlock *blockEncrypt = (CipherBlock *)ioFilterDriver(blockEncryptFilter); @@ -149,7 +174,7 @@ testRun(void) // ------------------------------------------------------------------------------------------------------------------------- Buffer *decryptBuffer = bufNew(TEST_BUFFER_SIZE); - IoFilter *blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass, .digest = STRDEF("sha1")); + IoFilter *blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass)); blockDecryptFilter = cipherBlockNewPack(ioFilterParamList(blockDecryptFilter)); CipherBlock *blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter); @@ -169,7 +194,7 @@ testRun(void) // Decrypt in small chunks to test buffering // ------------------------------------------------------------------------------------------------------------------------- - blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass); + blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass)); blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter); bufUsedZero(decryptBuffer); @@ -210,7 +235,7 @@ testRun(void) // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("encrypt zero byte file with no magic"); - blockEncryptFilter = cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, testPass, .raw = true); + blockEncryptFilter = cipherBlockNewP(cipherModeEncrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass), .raw = true); blockEncrypt = (CipherBlock *)ioFilterDriver(blockEncryptFilter); bufUsedZero(encryptBuffer); @@ -223,13 +248,13 @@ testRun(void) // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("error on decrypt expecting magic"); - blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass); + blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass)); TEST_ERROR(ioFilterProcessInOut(blockDecryptFilter, encryptBuffer, decryptBuffer), CryptoError, "cipher header invalid"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("decrypt zero byte file with no magic"); - blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass, .raw = true); + blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass), .raw = true); blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter); bufUsedZero(decryptBuffer); @@ -243,7 +268,7 @@ testRun(void) // Invalid cipher header // ------------------------------------------------------------------------------------------------------------------------- - blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass); + blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass)); blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter); TEST_ERROR( @@ -254,7 +279,7 @@ testRun(void) // Invalid encrypted data cannot be flushed // ------------------------------------------------------------------------------------------------------------------------- - blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass); + blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass)); blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter); bufUsedZero(decryptBuffer); @@ -268,7 +293,7 @@ testRun(void) // File with no header should not flush // ------------------------------------------------------------------------------------------------------------------------- - blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass); + blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass)); blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter); bufUsedZero(decryptBuffer); @@ -279,7 +304,7 @@ testRun(void) // File with header only should error // ------------------------------------------------------------------------------------------------------------------------- - blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass); + blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass)); blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter); bufUsedZero(decryptBuffer); @@ -294,11 +319,13 @@ testRun(void) IoFilterGroup *filterGroup = ioFilterGroupNew(); TEST_RESULT_PTR( - cipherBlockFilterGroupAdd(filterGroup, cipherTypeNone, cipherModeEncrypt, NULL), filterGroup, " no filter add"); + cipherBlockFilterGroupAdd( + filterGroup, cipherModeEncrypt, cipherSpecNewNone()), filterGroup, " no filter add"); TEST_RESULT_UINT(ioFilterGroupSize(filterGroup), 0, " check no filter add"); TEST_RESULT_VOID( - cipherBlockFilterGroupAdd(filterGroup, cipherTypeAes256Cbc, cipherModeEncrypt, STRDEF("X")), " filter add"); + cipherBlockFilterGroupAdd( + filterGroup, cipherModeEncrypt, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("X"))), " filter add"); TEST_RESULT_UINT(ioFilterGroupSize(filterGroup), 1, " check filter add"); } diff --git a/test/src/module/config/loadTest.c b/test/src/module/config/loadTest.c index fb3fc74de..ab1ed2eba 100644 --- a/test/src/module/config/loadTest.c +++ b/test/src/module/config/loadTest.c @@ -936,6 +936,10 @@ testRun(void) hrnCfgArgRawZ(argList, cfgOptStanza, "db"); hrnCfgArgRawZ(argList, cfgOptPgPath, "/path"); hrnCfgArgRawZ(argList, cfgOptRepoRetentionFull, "1"); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 1, TEST_PATH "/repo1"); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo2"); + hrnCfgArgKeyRawStrId(argList, cfgOptRepoCipherType, 2, cipherTypeAes256Cbc); + hrnCfgEnvKeyRawZ(cfgOptRepoCipherPass, 2, "passphrase"); hrnCfgArgRawZ(argList, cfgOptLockPath, HRN_PATH "/lock"); hrnCfgArgRawZ(argList, cfgOptLogPath, TEST_PATH); hrnCfgArgRawZ(argList, cfgOptLogLevelConsole, "off"); @@ -958,6 +962,16 @@ testRun(void) TEST_RESULT_INT(socketLocal.tcpKeepAliveInterval, 888, "check socketLocal.tcpKeepAliveInterval"); TEST_RESULT_INT(getpriority(PRIO_PROCESS, (id_t)getpid()), 19, "check priority"); + hrnCfgEnvKeyRemoveRaw(cfgOptRepoCipherPass, 2); + + // Cipher spec is cached per repo since each repo has its own cipher type and passphrase + TEST_RESULT_UINT(cipherSpecType(cfgCipherSpecMainIdx(0)), cipherTypeNone, "repo1 cipher spec"); + + const CipherSpec *const cipherSpecMain = cfgCipherSpecMainIdx(1); + + TEST_RESULT_UINT(cipherSpecType(cipherSpecMain), cipherTypeAes256Cbc, "repo2 cipher spec"); + TEST_RESULT_PTR(cfgCipherSpecMainIdx(1), cipherSpecMain, "repo2 cipher spec is cached"); + cmdLockReleaseP(); // ------------------------------------------------------------------------------------------------------------------------- diff --git a/test/src/module/config/parseTest.c b/test/src/module/config/parseTest.c index ee6dceac9..c2ae5c92f 100644 --- a/test/src/module/config/parseTest.c +++ b/test/src/module/config/parseTest.c @@ -1781,6 +1781,8 @@ testRun(void) hrnCfgArgKeyRawZ(argList, cfgOptRepoS3Bucket, 1, " test "); hrnCfgArgKeyRawZ(argList, cfgOptRepoS3Endpoint, 1, "test"); hrnCfgArgKeyRawZ(argList, cfgOptRepoS3Region, 1, "test"); + hrnCfgArgKeyRawStrId(argList, cfgOptRepoCipherType, 1, cipherTypeAes256Cbc); + hrnCfgEnvKeyRawZ(cfgOptRepoCipherPass, 1, "xxx-cipher"); strLstAddZ(argList, TEST_COMMAND_BACKUP); hrnCfgEnvKeyRawZ(cfgOptRepoS3Key, 1, "xxx"); hrnCfgEnvKeyRawZ(cfgOptRepoS3KeySecret, 1, "xxx"); @@ -1820,8 +1822,16 @@ testRun(void) TEST_RESULT_INT(cfgOptionSource(cfgOptBufferSize), cfgSourceDefault, "buffer-size is source default"); TEST_RESULT_Z(cfgOptionName(cfgOptBufferSize), "buffer-size", "buffer-size name"); + // Cipher spec is built once per repo and then cached + const CipherSpec *const cipherSpecMain = cfgCipherSpecMain(); + + TEST_RESULT_UINT(cipherSpecType(cipherSpecMain), cipherTypeAes256Cbc, "repo1 cipher spec type"); + TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(cipherSpecMain)), "xxx-cipher", "repo1 cipher spec pass"); + TEST_RESULT_PTR(cfgCipherSpecMainIdx(0), cipherSpecMain, "repo1 cipher spec is cached"); + hrnCfgEnvKeyRemoveRaw(cfgOptRepoS3Key, 1); hrnCfgEnvKeyRemoveRaw(cfgOptRepoS3KeySecret, 1); + hrnCfgEnvKeyRemoveRaw(cfgOptRepoCipherPass, 1); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("global is a valid stanza prefix"); @@ -1841,6 +1851,7 @@ testRun(void) TEST_RESULT_VOID(cfgParseP(storageTest, strLstSize(argList), strLstPtr(argList), .noResetLogLevel = true), "parse config"); TEST_RESULT_STR_Z(cfgOptionStr(cfgOptPgPath), "/path/to/global/stanza", "default pg-path"); + TEST_RESULT_UINT(cipherSpecType(cfgCipherSpecMainIdx(0)), cipherTypeNone, "no cipher spec when repo is not encrypted"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("warnings for environment variables, command-line and config file options"); diff --git a/test/src/module/info/infoArchiveTest.c b/test/src/module/info/infoArchiveTest.c index 9e155d564..c6e0c37be 100644 --- a/test/src/module/info/infoArchiveTest.c +++ b/test/src/module/info/infoArchiveTest.c @@ -38,14 +38,14 @@ testRun(void) // Load and test move function MEM_CONTEXT_TEMP_BEGIN() { - TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentLoad)), "load new archive info"); + TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone()), "load new archive info"); TEST_RESULT_VOID(infoArchiveMove(info, memContextPrior()), "move info"); } MEM_CONTEXT_TEMP_END(); TEST_RESULT_STR_Z(infoArchiveId(info), "9.6-1", "archiveId set"); TEST_RESULT_PTR(infoArchivePg(info), info->pub.infoPg, "infoPg set"); - TEST_RESULT_STR(infoArchiveCipherPass(info), NULL, "no cipher sub"); + TEST_RESULT_UINT(cipherSpecType(infoArchiveCipherSpec(info)), cipherTypeNone, "no cipher sub"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("infoArchive save (in memory)"); @@ -64,7 +64,7 @@ testRun(void) info, infoArchiveNew(PG_VERSION_96, 6569239123849665679, NULL), "infoArchiveNew() - no sub cipher"); TEST_RESULT_STR_Z(infoArchiveId(info), "9.6-1", "archiveId set"); TEST_RESULT_PTR(infoArchivePg(info), info->pub.infoPg, "infoPg set"); - TEST_RESULT_STR(infoArchiveCipherPass(info), NULL, "no cipher sub"); + TEST_RESULT_UINT(cipherSpecType(infoArchiveCipherSpec(info)), cipherTypeNone, "no cipher sub"); TEST_RESULT_INT(infoPgDataTotal(infoArchivePg(info)), 1, "history set"); Buffer *contentCompare = bufNew(0); @@ -79,18 +79,22 @@ testRun(void) TEST_ASSIGN( info, infoArchiveNew( - PG_VERSION_10, 6569239123849665999, STRDEF("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO")), + PG_VERSION_10, 6569239123849665999, + cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO"))), "infoArchiveNew() - cipher sub"); contentSave = bufNew(0); TEST_RESULT_VOID(infoArchiveSave(info, ioBufferWriteNew(contentSave)), "save new with cipher"); - TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentSave)), "load encrypted archive info"); + TEST_ASSIGN( + info, infoArchiveNewLoad(ioBufferReadNew(contentSave), cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x"))), + "load encrypted archive info"); TEST_RESULT_STR_Z(infoArchiveId(info), "10-1", "archiveId set"); TEST_RESULT_PTR(infoArchivePg(info), infoArchivePg(info), "infoPg set"); TEST_RESULT_STR_Z( - infoArchiveCipherPass(info), "zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", "cipher sub set"); + strNewBuf(cipherSpecPass(infoArchiveCipherSpec(info))), + "zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", "cipher sub set"); TEST_RESULT_INT(infoPgDataTotal(infoArchivePg(info)), 1, "history set"); // ------------------------------------------------------------------------------------------------------------------------- @@ -121,7 +125,7 @@ testRun(void) "1={\"db-id\":6625592122879095702,\"db-version\":\"9.6\"}\n" "2={\"db-id\":6626363367545678089,\"db-version\":\"17\"}\n"); - TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentLoad)), "new archive info"); + TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone()), "new archive info"); TEST_RESULT_STR_Z(infoArchiveIdHistoryMatch(info, 2, 170000, 6626363367545678089), "17-2", "full match found"); TEST_RESULT_STR_Z(infoArchiveIdHistoryMatch(info, 2, 90600, 6625592122879095702), "9.6-1", "partial match found"); @@ -142,7 +146,7 @@ testRun(void) TEST_TITLE("load archive info file - error"); TEST_ERROR( - infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), FileMissingError, + infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherSpecNewNone()), FileMissingError, "unable to load info file '" TEST_PATH "/archive.info' or '" TEST_PATH "/archive.info.copy':\n" "FileMissingError: unable to open missing file '" TEST_PATH "/archive.info' for read\n" "FileMissingError: unable to open missing file '" TEST_PATH "/archive.info.copy' for read\n" @@ -156,13 +160,18 @@ testRun(void) InfoArchive *infoArchive = infoArchiveNew(PG_VERSION_10, 6569239123849665999, NULL); TEST_RESULT_VOID( - infoArchiveSaveFile(infoArchive, storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), "save archive info"); + infoArchiveSaveFile(infoArchive, storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherSpecNewNone()), + "save archive info"); - TEST_ASSIGN(infoArchive, infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), "load main"); + TEST_ASSIGN( + infoArchive, infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherSpecNewNone()), + "load main"); TEST_RESULT_UINT(infoPgDataCurrent(infoArchivePg(infoArchive)).systemId, 6569239123849665999, "check file loaded"); HRN_STORAGE_REMOVE(storageTest, INFO_ARCHIVE_FILE, .errorOnMissing = true, .comment = "remove main so only copy exists"); - TEST_ASSIGN(infoArchive, infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), "load copy"); + TEST_ASSIGN( + infoArchive, infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherSpecNewNone()), + "load copy"); TEST_RESULT_UINT(infoPgDataCurrent(infoArchivePg(infoArchive)).systemId, 6569239123849665999, "check file loaded"); } } diff --git a/test/src/module/info/infoBackupTest.c b/test/src/module/info/infoBackupTest.c index 5b9cca340..12de0bba6 100644 --- a/test/src/module/info/infoBackupTest.c +++ b/test/src/module/info/infoBackupTest.c @@ -46,7 +46,7 @@ testRun(void) // Load and test move function then make sure ignore-section is ignored MEM_CONTEXT_TEMP_BEGIN() { - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad)), "new backup info"); + TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone()), "new backup info"); TEST_RESULT_VOID(infoBackupMove(infoBackup, memContextPrior()), "move info"); } MEM_CONTEXT_TEMP_END(); @@ -68,9 +68,9 @@ testRun(void) TEST_RESULT_VOID(infoBackupSave(infoBackup, ioBufferWriteNew(contentCompare)), "save backup info from new"); TEST_RESULT_STR(strNewBuf(contentCompare), strNewBuf(contentSave), "check save"); - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentCompare)), "load backup info"); + TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentCompare), cipherSpecNewNone()), "load backup info"); TEST_RESULT_PTR(infoBackupPg(infoBackup), infoBackup->pub.infoPg, "infoPg set"); - TEST_RESULT_STR(infoBackupCipherPass(infoBackup), NULL, "cipher sub not set"); + TEST_RESULT_UINT(cipherSpecType(infoBackupCipherSpec(infoBackup)), cipherTypeNone, "cipher sub not set"); TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 0, "infoBackupDataTotal returns 0"); // ------------------------------------------------------------------------------------------------------------------------- @@ -80,7 +80,7 @@ testRun(void) infoBackup, infoBackupNew( PG_VERSION_10, 6569239123849665999, hrnPgCatalogVersion(PG_VERSION_10), - STRDEF("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO")), + cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO"))), "infoBackupNew() - cipher sub"); contentSave = bufNew(0); @@ -88,10 +88,13 @@ testRun(void) TEST_RESULT_VOID(infoBackupSave(infoBackup, ioBufferWriteNew(contentSave)), "save new with cipher sub"); infoBackup = NULL; - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentSave)), "load backup info with cipher sub"); + TEST_ASSIGN( + infoBackup, infoBackupNewLoad(ioBufferReadNew(contentSave), cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x"))), + "load backup info with cipher sub"); TEST_RESULT_PTR(infoBackupPg(infoBackup), infoBackupPg(infoBackup), "infoPg set"); TEST_RESULT_STR_Z( - infoBackupCipherPass(infoBackup), "zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", "cipher sub set"); + strNewBuf(cipherSpecPass(infoBackupCipherSpec(infoBackup))), + "zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", "cipher sub set"); TEST_RESULT_INT(infoPgDataTotal(infoBackupPg(infoBackup)), 1, "history set"); // ------------------------------------------------------------------------------------------------------------------------- @@ -154,7 +157,7 @@ testRun(void) "1={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665679" ",\"db-version\":\"9.6\"}\n"); - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad)), "new backup info"); + TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone()), "new backup info"); TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 3, "backup list contains backups"); @@ -312,9 +315,6 @@ testRun(void) "[backup:target]\n" "pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n" "\n" - "[cipher]\n" - "cipher-pass=\"somepass\"\n" - "\n" "[target:file]\n" "pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n" "pg_data/postgresql.conf={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"repo-size\":24,\"size\":7," @@ -325,7 +325,7 @@ testRun(void) "pg_data={}\n" TEST_MANIFEST_PATH_DEFAULT); - TEST_ASSIGN(manifest, manifestNewLoad(ioBufferReadNew(manifestContent)), "load manifest"); + TEST_ASSIGN(manifest, manifestNewLoad(ioBufferReadNew(manifestContent), cipherSpecNewNone()), "load manifest"); TEST_RESULT_VOID(infoBackupDataAdd(infoBackup, manifest), "add a backup"); TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 1, "backup added to current"); TEST_ASSIGN(backupData, infoBackupData(infoBackup, 0), "get added backup"); @@ -433,7 +433,9 @@ testRun(void) "pg_data/base/65536={\"user\":false}\n" \ TEST_MANIFEST_PATH_DEFAULT - TEST_ASSIGN(manifest, manifestNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_MANIFEST_INCR))), "load manifest"); + TEST_ASSIGN( + manifest, manifestNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_MANIFEST_INCR)), cipherSpecNewNone()), + "load manifest"); TEST_RESULT_VOID(infoBackupDataAdd(infoBackup, manifest), "add a backup"); TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 2, "backup added to current"); TEST_ASSIGN(backupData, infoBackupData(infoBackup, 1), "get added backup"); @@ -568,9 +570,6 @@ testRun(void) "[backup:target]\n" "pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n" "\n" - "[cipher]\n" - "cipher-pass=\"somepass\"\n" - "\n" "[target:file]\n" "pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n" "pg_data/postgresql.conf={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"repo-size\":24,\"size\":7," @@ -608,9 +607,6 @@ testRun(void) "[backup:target]\n" "pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n" "\n" - "[cipher]\n" - "cipher-pass=\"somepass\"\n" - "\n" "[target:file]\n" "pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n" TEST_MANIFEST_FILE_DEFAULT @@ -646,9 +642,6 @@ testRun(void) "[backup:target]\n" "pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n" "\n" - "[cipher]\n" - "cipher-pass=\"somepass\"\n" - "\n" "[target:file]\n" "pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n" TEST_MANIFEST_FILE_DEFAULT @@ -684,9 +677,6 @@ testRun(void) "[backup:target]\n" "pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n" "\n" - "[cipher]\n" - "cipher-pass=\"somepass\"\n" - "\n" "[target:file]\n" "pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n" TEST_MANIFEST_FILE_DEFAULT @@ -722,7 +712,7 @@ testRun(void) "upgrade db"); TEST_RESULT_BOOL(infoBackup->pub.updated, true, "info updated"); TEST_RESULT_VOID( - infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "save backup info"); TEST_RESULT_BOOL(infoBackup->pub.updated, false, "info not updated"); @@ -731,7 +721,7 @@ testRun(void) HRN_STORAGE_TIME(storageRepo(), INFO_BACKUP_PATH_FILE, timeBeforeSave); TEST_RESULT_VOID( - infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "save backup again"); // Check that timestamp was not updated @@ -741,13 +731,14 @@ testRun(void) // Reload infoBackup to be sure it was updated infoBackup = NULL; TEST_ASSIGN( - infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "get saved backup info"); TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 2, "backup list contains backups to be removed"); TEST_RESULT_INT(infoPgDataTotal(infoBackupPg(infoBackup)), 2, "multiple DB history"); TEST_ASSIGN( - infoBackup, infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackup, + infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "reconstruct"); TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 1, "backup list contains 1 backup"); TEST_ASSIGN(backupData, infoBackupData(infoBackup, 0), "get the backup"); @@ -769,7 +760,8 @@ testRun(void) storageRepoWrite(), STORAGE_REPO_BACKUP "/20190818-084502F_20190820-084502I", .recurse = true, .comment = "remove dependent backup from disk"); TEST_ASSIGN( - infoBackup, infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackup, + infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "reconstruct does not attempt to add back dependent backup"); TEST_RESULT_LOG( "P00 WARN: backup '20190818-084502F_20190820-084502I' missing manifest removed from backup.info\n" @@ -869,12 +861,13 @@ testRun(void) .comment = "write manifest for backup in a set that is in backup.info but whose prior backup is not"); TEST_RESULT_VOID( - infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "save updated backup info"); infoBackup = NULL; TEST_ASSIGN( - infoBackup, infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), + infoBackup, + infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()), "reconstruct"); TEST_RESULT_STRLST_Z( infoBackupDataLabelList(infoBackup, NULL), @@ -896,7 +889,7 @@ testRun(void) TEST_TITLE("load backup info file - error"); TEST_ERROR( - infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), FileMissingError, + infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherSpecNewNone()), FileMissingError, "unable to load info file '" TEST_PATH "/backup.info' or '" TEST_PATH "/backup.info.copy':\n" "FileMissingError: unable to open missing file '" TEST_PATH "/backup.info' for read\n" "FileMissingError: unable to open missing file '" TEST_PATH "/backup.info.copy' for read\n" @@ -908,13 +901,18 @@ testRun(void) InfoBackup *infoBackup = infoBackupNew(PG_VERSION_10, 6569239123849665999, hrnPgCatalogVersion(PG_VERSION_10), NULL); TEST_RESULT_VOID( - infoBackupSaveFile(infoBackup, storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), "save backup info"); + infoBackupSaveFile( + infoBackup, storageTest, STRDEF(INFO_BACKUP_FILE), cipherSpecNewNone()), "save backup info"); - TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), "load main"); + TEST_ASSIGN( + infoBackup, infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherSpecNewNone()), + "load main"); TEST_RESULT_UINT(infoPgDataCurrent(infoBackupPg(infoBackup)).systemId, 6569239123849665999, "check file loaded"); HRN_STORAGE_REMOVE(storageTest, INFO_BACKUP_FILE, .errorOnMissing = true, .comment = "remove main so only copy exists"); - TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), "load copy"); + TEST_ASSIGN( + infoBackup, infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherSpecNewNone()), + "load copy"); TEST_RESULT_UINT(infoPgDataCurrent(infoBackupPg(infoBackup)).systemId, 6569239123849665999, "check file loaded"); } @@ -998,7 +996,7 @@ testRun(void) // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("check dependency lists"); - TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad)), "new backup info"); + TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone()), "new backup info"); TEST_ASSIGN(dependencyList, infoBackupDataDependentList(infoBackup, STRDEF("20200317-181625F")), "full"); TEST_RESULT_STRLST_Z( diff --git a/test/src/module/info/infoPgTest.c b/test/src/module/info/infoPgTest.c index 679ffc331..628a72ff0 100644 --- a/test/src/module/info/infoPgTest.c +++ b/test/src/module/info/infoPgTest.c @@ -38,12 +38,14 @@ testRun(void) TEST_ASSIGN(infoPg, infoPgNew(infoPgBackup, NULL), "infoPgNew(cipherTypeNone, NULL)"); TEST_RESULT_INT(infoPgDataTotal(infoPg), 0, " 0 history"); - TEST_RESULT_STR(infoCipherPass(infoPgInfo(infoPg)), NULL, " cipherPass NULL"); + TEST_RESULT_UINT(cipherSpecType(infoCipherSpec(infoPgInfo(infoPg))), cipherTypeNone, " cipher spec none"); TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent"); - TEST_ASSIGN(infoPg, infoPgNew(infoPgArchive, STRDEF("123xyz")), "infoPgNew(cipherTypeAes256Cbc, 123xyz)"); + TEST_ASSIGN( + infoPg, infoPgNew(infoPgArchive, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("123xyz"))), + "infoPgNew(cipherTypeAes256Cbc, 123xyz)"); TEST_RESULT_INT(infoPgDataTotal(infoPg), 0, " 0 history"); - TEST_RESULT_STR_Z(infoCipherPass(infoPgInfo(infoPg)), "123xyz", " cipherPass set"); + TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(infoCipherSpec(infoPgInfo(infoPg)))), "123xyz", " cipherPass set"); TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent"); // ------------------------------------------------------------------------------------------------------------------------- @@ -71,13 +73,14 @@ testRun(void) TEST_RESULT_UINT(pgData.systemId, 6569239123849665999, " system-id updated"); TEST_RESULT_UINT(pgData.version, PG_VERSION_18, " version updated"); TEST_RESULT_UINT(pgData.catalogVersion, 0, " catalog version not set for archive"); - TEST_RESULT_STR(infoCipherPass(infoPgInfo(infoPg)), NULL, " cipherPass not set"); + TEST_RESULT_UINT(cipherSpecType(infoCipherSpec(infoPgInfo(infoPg))), cipherTypeNone, " cipher spec none"); // ------------------------------------------------------------------------------------------------------------------------- TEST_ASSIGN( infoPg, infoPgSet( - infoPgNew(infoPgBackup, STRDEF("123xyz")), infoPgBackup, PG_VERSION_18, 6569239123849665679, + infoPgNew(infoPgBackup, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("123xyz"))), infoPgBackup, + PG_VERSION_18, 6569239123849665679, hrnPgCatalogVersion(PG_VERSION_18)), "infoPgSet - infoPgBackup"); TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " 1 history"); @@ -87,7 +90,7 @@ testRun(void) TEST_RESULT_UINT(pgData.systemId, 6569239123849665679, " system-id set"); TEST_RESULT_UINT(pgData.version, PG_VERSION_18, " version set"); TEST_RESULT_UINT(pgData.catalogVersion, 202506291, " catalog version updated"); - TEST_RESULT_STR_Z(infoCipherPass(infoPgInfo(infoPg)), "123xyz", " cipherPass set"); + TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(infoCipherSpec(infoPgInfo(infoPg)))), "123xyz", " cipherPass set"); } // ***************************************************************************************************************************** @@ -117,7 +120,9 @@ testRun(void) InfoPg *infoPg = NULL; TEST_ASSIGN( - infoPg, infoPgNewLoad(ioBufferReadNew(contentLoad), infoPgArchive, harnessInfoLoadNewCallback, callbackContent), + infoPg, + infoPgNewLoad( + ioBufferReadNew(contentLoad), infoPgArchive, cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent), "load file"); TEST_RESULT_STR_Z( callbackContent, @@ -133,7 +138,7 @@ testRun(void) TEST_RESULT_UINT(pgData.systemId, 6569239123849665679, " system-id set"); TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " check pg data total"); TEST_RESULT_STR_Z(infoPgArchiveId(infoPg, 0), "18-1", " check pg archive id"); - TEST_RESULT_STR(infoPgCipherPass(infoPg), NULL, " no cipher passphrase"); + TEST_RESULT_UINT(cipherSpecType(infoPgCipherSpec(infoPg)), cipherTypeNone, " no cipher passphrase"); Buffer *contentSave = bufNew(0); @@ -167,7 +172,8 @@ testRun(void) callbackContent = strNew(); - TEST_ASSIGN(infoPg, infoPgNewLoad(ioBufferReadNew(contentLoad), infoPgBackup, NULL, NULL), "load file"); + TEST_ASSIGN( + infoPg, infoPgNewLoad(ioBufferReadNew(contentLoad), infoPgBackup, cipherSpecNewNone(), NULL, NULL), "load file"); TEST_RESULT_STR_Z(callbackContent, "", " check callback content"); TEST_RESULT_INT(infoPgDataTotal(infoPg), 2, " check pg data total"); diff --git a/test/src/module/info/infoTest.c b/test/src/module/info/infoTest.c index 2c0779ac4..82aeea4bc 100644 --- a/test/src/module/info/infoTest.c +++ b/test/src/module/info/infoTest.c @@ -78,11 +78,11 @@ testRun(void) { Info *info = NULL; - TEST_ASSIGN(info, infoNew(STRDEF("123xyz")), "infoNew(cipher)"); - TEST_RESULT_STR_Z(infoCipherPass(info), "123xyz", " cipherPass is set"); + TEST_ASSIGN(info, infoNew(cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("123xyz"))), "infoNew(cipher)"); + TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(infoCipherSpec(info))), "123xyz", " cipherPass is set"); TEST_ASSIGN(info, infoNew(NULL), "infoNew(NULL)"); - TEST_RESULT_STR(infoCipherPass(info), NULL, " cipherPass is NULL"); + TEST_RESULT_UINT(cipherSpecType(infoCipherSpec(info)), cipherTypeNone, " cipher spec is none"); } // ***************************************************************************************************************************** @@ -97,8 +97,8 @@ testRun(void) String *callbackContent = strNew(); TEST_ERROR( - infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), FormatError, - "expected format 5 but found 4"); + infoNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent), + FormatError, "expected format 5 but found 4"); TEST_RESULT_STR_Z(callbackContent, "", " check callback content"); // Checksum not found @@ -108,8 +108,8 @@ testRun(void) "backrest-format=5\n"); TEST_ERROR( - infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), ChecksumError, - "invalid checksum, actual 'a3765a8c2c1e5d35274a0b0ce118f4031faff0bd' but no checksum found"); + infoNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent), + ChecksumError, "invalid checksum, actual 'a3765a8c2c1e5d35274a0b0ce118f4031faff0bd' but no checksum found"); TEST_RESULT_STR_Z(callbackContent, "", " check callback content"); // Checksum invalid @@ -122,8 +122,8 @@ testRun(void) "bogus=\"BOGUS\"\n"); TEST_ERROR( - infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), ChecksumError, - "invalid checksum, actual 'fe989a75dcf7a0261e57d210707c0db741462763' but expected 'BOGUS'"); + infoNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent), + ChecksumError, "invalid checksum, actual 'fe989a75dcf7a0261e57d210707c0db741462763' but expected 'BOGUS'"); TEST_RESULT_STR_Z(callbackContent, "", " check callback content"); // Crypto expected @@ -135,10 +135,12 @@ testRun(void) "backrest-version=\"2.17\"\n"); IoRead *read = ioBufferReadNew(contentLoad); - ioFilterGroupAdd(ioReadFilterGroup(read), cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTRDEF("X"))); + ioFilterGroupAdd( + ioReadFilterGroup(read), + cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("X")))); TEST_ERROR( - infoNewLoad(read, harnessInfoLoadNewCallback, callbackContent), CryptoError, + infoNewLoad(read, cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent), CryptoError, "cipher header invalid\n" "HINT: is or was the repo encrypted?"); TEST_RESULT_STR_Z(callbackContent, "", " check callback content"); @@ -153,9 +155,10 @@ testRun(void) callbackContent = strNew(); TEST_ASSIGN( - info, infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), "info with other cipher"); + info, infoNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent), + "info with other cipher"); TEST_RESULT_STR_Z(callbackContent, "", " check callback content"); - TEST_RESULT_STR(infoCipherPass(info), NULL, " check cipher pass not set"); + TEST_RESULT_UINT(cipherSpecType(infoCipherSpec(info)), cipherTypeNone, " check cipher pass not set"); // Base file with content // ------------------------------------------------------------------------------------------------------------------------- @@ -169,9 +172,10 @@ testRun(void) callbackContent = strNew(); TEST_ASSIGN( - info, infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), "info with content"); + info, infoNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent), + "info with content"); TEST_RESULT_STR_Z(callbackContent, "[c] key=1\n[d] key=1\n", " check callback content"); - TEST_RESULT_STR(infoCipherPass(info), NULL, " check cipher pass not set"); + TEST_RESULT_UINT(cipherSpecType(infoCipherSpec(info)), cipherTypeNone, " check cipher pass not set"); Buffer *contentSave = bufNew(0); @@ -194,9 +198,12 @@ testRun(void) TEST_ASSIGN( info, - infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), "info with content and cipher"); + infoNewLoad( + ioBufferReadNew(contentLoad), cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x")), harnessInfoLoadNewCallback, + callbackContent), + "info with content and cipher"); TEST_RESULT_STR_Z(callbackContent, "[c] key=1\n[d] key=1\n", " check callback content"); - TEST_RESULT_STR_Z(infoCipherPass(info), "somepass", " check cipher pass set"); + TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(infoCipherSpec(info))), "somepass", " check cipher pass set"); TEST_RESULT_STR_Z(infoBackrestVersion(info), PROJECT_VERSION, " check backrest version"); contentSave = bufNew(0); diff --git a/test/src/module/info/manifestTest.c b/test/src/module/info/manifestTest.c index 048972bad..277ab17ba 100644 --- a/test/src/module/info/manifestTest.c +++ b/test/src/module/info/manifestTest.c @@ -1469,7 +1469,9 @@ testRun(void) MEM_CONTEXT_TEMP_BEGIN() { - TEST_ASSIGN(manifest, manifestNewLoad(ioBufferReadNew(contentLoad)), "load manifest"); + TEST_ASSIGN( + manifest, manifestNewLoad(ioBufferReadNew(contentLoad), cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x"))), + "load manifest"); TEST_RESULT_VOID(manifestMove(manifest, memContextPrior()), "move manifest"); } MEM_CONTEXT_TEMP_END(); @@ -1481,7 +1483,7 @@ testRun(void) manifestTargetFind(manifest, STRDEF("bogus")), AssertError, "unable to find 'bogus' in manifest target list"); TEST_RESULT_STR_Z(manifestData(manifest)->backupLabel, "20190808-163540F", "check manifest data"); - TEST_RESULT_STR_Z(manifestCipherSubPass(manifest), "somepass", "check cipher subpass"); + TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(manifestCipherSpec(manifest))), "somepass", "check cipher subpass"); TEST_RESULT_VOID( manifestTargetUpdate(manifest, MANIFEST_TARGET_PGDATA_STR, STRDEF("/pg/base"), NULL), "update target no change"); @@ -1671,7 +1673,7 @@ testRun(void) TEST_MANIFEST_LINK TEST_MANIFEST_LINK_DEFAULT TEST_MANIFEST_PATH - TEST_MANIFEST_PATH_DEFAULT))), + TEST_MANIFEST_PATH_DEFAULT)), cipherSpecNewNone()), "load manifest"); // ------------------------------------------------------------------------------------------------------------------------- @@ -1768,9 +1770,11 @@ testRun(void) TEST_RESULT_STR_Z(manifestPathPg(STRDEF("pg_data/PG_VERSION")), "PG_VERSION", "check pg_data path/file"); TEST_RESULT_STR_Z(manifestPathPg(STRDEF("pg_tblspc/1")), "pg_tblspc/1", "check pg_tblspc path/file"); - TEST_RESULT_STR_Z(manifestCipherSubPass(manifest), NULL, "check cipher subpass"); - TEST_RESULT_VOID(manifestCipherSubPassSet(manifest, STRDEF("supersecret")), "cipher subpass set"); - TEST_RESULT_STR_Z(manifestCipherSubPass(manifest), "supersecret", "check cipher subpass"); + TEST_RESULT_UINT(cipherSpecType(manifestCipherSpec(manifest)), cipherTypeNone, "check cipher subpass"); + TEST_RESULT_VOID( + manifestCipherSpecSet(manifest, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("supersecret"))), + "cipher subpass set"); + TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(manifestCipherSpec(manifest))), "supersecret", "check cipher subpass"); // Absolute target paths TEST_RESULT_STR_Z(manifestTargetPath(manifest, manifestTargetBase(manifest)), "/pg/base", "base target path"); @@ -1957,11 +1961,11 @@ testRun(void) TEST_TITLE("load validation errors"); TEST_ERROR( - manifestNewLoad(ioBufferReadNew(BUFSTRDEF("[target:file]\npg_data/bogus={\"size\":0}"))), FormatError, - "missing timestamp for file 'pg_data/bogus'"); + manifestNewLoad(ioBufferReadNew(BUFSTRDEF("[target:file]\npg_data/bogus={\"size\":0}")), cipherSpecNewNone()), + FormatError, "missing timestamp for file 'pg_data/bogus'"); TEST_ERROR( - manifestNewLoad(ioBufferReadNew(BUFSTRDEF("[target:file]\npg_data/bogus={\"timestamp\":0}"))), FormatError, - "missing size for file 'pg_data/bogus'"); + manifestNewLoad(ioBufferReadNew(BUFSTRDEF("[target:file]\npg_data/bogus={\"timestamp\":0}")), cipherSpecNewNone()), + FormatError, "missing size for file 'pg_data/bogus'"); } // ***************************************************************************************************************************** @@ -1970,7 +1974,7 @@ testRun(void) Manifest *manifest = NULL; TEST_ERROR( - manifestLoadFile(storageTest, BACKUP_MANIFEST_FILE_STR, cipherTypeNone, NULL), FileMissingError, + manifestLoadFile(storageTest, BACKUP_MANIFEST_FILE_STR, cipherSpecNewNone()), FileMissingError, "unable to load backup manifest file '" TEST_PATH "/backup.manifest' or '" TEST_PATH "/backup.manifest.copy':\n" "FileMissingError: unable to open missing file '" TEST_PATH "/backup.manifest' for read\n" "FileMissingError: unable to open missing file '" TEST_PATH "/backup.manifest.copy' for read"); @@ -2034,14 +2038,18 @@ testRun(void) "user=\"user1\"\n" HRN_INFO_PUT(storageTest, BACKUP_MANIFEST_FILE INFO_COPY_EXT, TEST_MANIFEST_CONTENT, .comment = "write manifest copy"); - TEST_ASSIGN(manifest, manifestLoadFile(storageTest, STRDEF(BACKUP_MANIFEST_FILE), cipherTypeNone, NULL), "load copy"); + TEST_ASSIGN( + manifest, manifestLoadFile(storageTest, STRDEF(BACKUP_MANIFEST_FILE), cipherSpecNewNone()), + "load copy"); TEST_RESULT_UINT(manifestData(manifest)->pgSystemId, 1000000000000000094, "check file loaded"); TEST_RESULT_STR_Z(manifestData(manifest)->backrestVersion, PROJECT_VERSION, "check backrest version"); HRN_STORAGE_REMOVE(storageTest, BACKUP_MANIFEST_FILE INFO_COPY_EXT, .errorOnMissing = true); HRN_INFO_PUT(storageTest, BACKUP_MANIFEST_FILE, TEST_MANIFEST_CONTENT, .comment = "write main manifest"); - TEST_ASSIGN(manifest, manifestLoadFile(storageTest, STRDEF(BACKUP_MANIFEST_FILE), cipherTypeNone, NULL), "load main"); + TEST_ASSIGN( + manifest, manifestLoadFile(storageTest, STRDEF(BACKUP_MANIFEST_FILE), cipherSpecNewNone()), + "load main"); TEST_RESULT_UINT(manifestData(manifest)->pgSystemId, 1000000000000000094, "check file loaded"); TEST_RESULT_VOID(manifestFree(manifest), "free manifest"); diff --git a/test/src/module/integration/allTest.c b/test/src/module/integration/allTest.c index 295cbdbc5..b9be2c9b2 100644 --- a/test/src/module/integration/allTest.c +++ b/test/src/module/integration/allTest.c @@ -200,14 +200,14 @@ testRun(void) { // Check backups before the backup so we know how many will exist after const InfoBackup *infoBackup = infoBackupLoadFile( - hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherType(), hrnHostCipherPass()); + hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherSpec()); TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 1, "backup total = 1"); TEST_HOST_BR(repo, CFGCMD_BACKUP, .option = "--type=full --backup-standby --repo1-retention-full=1 --no-expire-auto"); // Expire was disabled so the backup total has increased infoBackup = infoBackupLoadFile( - hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherType(), hrnHostCipherPass()); + hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherSpec()); TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 2, "backup total = 2"); // Now force an expire @@ -215,7 +215,7 @@ testRun(void) // Backup has been expired infoBackup = infoBackupLoadFile( - hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherType(), hrnHostCipherPass()); + hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherSpec()); TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 1, "backup total = 1"); // Stop the standby since restores to primary will break it diff --git a/test/src/module/performance/typeTest.c b/test/src/module/performance/typeTest.c index 1a58358cc..aa387df72 100644 --- a/test/src/module/performance/typeTest.c +++ b/test/src/module/performance/typeTest.c @@ -302,7 +302,7 @@ testRun(void) MEM_CONTEXT_BEGIN(testContext) { - manifest = manifestNewLoad(ioBufferReadNew(contentSave)); + manifest = manifestNewLoad(ioBufferReadNew(contentSave), cipherSpecNewNone()); } MEM_CONTEXT_END(); diff --git a/test/src/module/storage/remoteTest.c b/test/src/module/storage/remoteTest.c index c278b56bc..b3047f305 100644 --- a/test/src/module/storage/remoteTest.c +++ b/test/src/module/storage/remoteTest.c @@ -381,8 +381,8 @@ testRun(void) IoFilterGroup *filterGroup = ioReadFilterGroup(storageReadIo(fileRead)); ioFilterGroupAdd(filterGroup, ioSizeNew()); ioFilterGroupAdd(filterGroup, cryptoHashNew(hashTypeSha1)); - ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, BUFSTRZ("x"))); - ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTRZ("x"))); + ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeEncrypt, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x")))); + ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x")))); ioFilterGroupAdd(filterGroup, compressFilterP(compressTypeGz, 3)); ioFilterGroupAdd(filterGroup, decompressFilterP(compressTypeGz));