Skip to content

Commit

Permalink
Use StringId for type in cryptoHash() and cryptoHmacOne().
Browse files Browse the repository at this point in the history
This brings hash types in line with cipher types (i.e. a StringId enum) and allows removal of some Strings.
  • Loading branch information
dwsteele committed May 25, 2022
1 parent 38ad283 commit 8c2b3a0
Show file tree
Hide file tree
Showing 22 changed files with 96 additions and 100 deletions.
2 changes: 1 addition & 1 deletion src/command/archive/push/file.c
Expand Up @@ -157,7 +157,7 @@ archivePushFile(

// Generate a sha1 checksum for the wal segment
IoRead *read = storageReadIo(storageNewReadP(storageLocal(), walSource));
ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(HASH_TYPE_SHA1_STR));
ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(hashTypeSha1));
ioReadDrain(read);

const String *walSegmentChecksum = pckReadStrP(
Expand Down
2 changes: 1 addition & 1 deletion src/command/backup/backup.c
Expand Up @@ -940,7 +940,7 @@ backupFilePut(BackupData *backupData, Manifest *manifest, const String *name, ti
IoFilterGroup *filterGroup = ioWriteFilterGroup(storageWriteIo(write));

// Add SHA1 filter
ioFilterGroupAdd(filterGroup, cryptoHashNew(HASH_TYPE_SHA1_STR));
ioFilterGroupAdd(filterGroup, cryptoHashNew(hashTypeSha1));

// Add compression
if (compressType != compressTypeNone)
Expand Down
6 changes: 3 additions & 3 deletions src/command/backup/file.c
Expand Up @@ -90,7 +90,7 @@ backupFile(
storageNewReadP(
storagePg(), file->pgFile, .ignoreMissing = file->pgFileIgnoreMissing,
.limit = file->pgFileCopyExactSize ? VARUINT64(file->pgFileSize) : NULL));
ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(HASH_TYPE_SHA1_STR));
ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(hashTypeSha1));
ioFilterGroupAdd(ioReadFilterGroup(read), ioSizeNew());

// If the pg file exists check the checksum/size
Expand Down Expand Up @@ -154,7 +154,7 @@ backupFile(
if (repoFileCompressType != compressTypeNone)
ioFilterGroupAdd(ioReadFilterGroup(read), decompressFilter(repoFileCompressType));

ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(HASH_TYPE_SHA1_STR));
ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(hashTypeSha1));
ioFilterGroupAdd(ioReadFilterGroup(read), ioSizeNew());

ioReadDrain(read);
Expand Down Expand Up @@ -210,7 +210,7 @@ backupFile(
StorageRead *read = storageNewReadP(
storagePg(), file->pgFile, .ignoreMissing = file->pgFileIgnoreMissing, .compressible = compressible,
.limit = file->pgFileCopyExactSize ? VARUINT64(file->pgFileSize) : NULL);
ioFilterGroupAdd(ioReadFilterGroup(storageReadIo(read)), cryptoHashNew(HASH_TYPE_SHA1_STR));
ioFilterGroupAdd(ioReadFilterGroup(storageReadIo(read)), cryptoHashNew(hashTypeSha1));
ioFilterGroupAdd(ioReadFilterGroup(storageReadIo(read)), ioSizeNew());

// Add page checksum filter
Expand Down
4 changes: 2 additions & 2 deletions src/command/restore/file.c
Expand Up @@ -112,7 +112,7 @@ List *restoreFile(
if (file->size != 0)
{
read = storageReadIo(storageNewReadP(storagePgWrite(), file->name));
ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(HASH_TYPE_SHA1_STR));
ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(hashTypeSha1));
ioReadDrain(read);
}

Expand Down Expand Up @@ -232,7 +232,7 @@ List *restoreFile(
ioFilterGroupAdd(filterGroup, decompressFilter(repoFileCompressType));

// Add sha1 filter
ioFilterGroupAdd(filterGroup, cryptoHashNew(HASH_TYPE_SHA1_STR));
ioFilterGroupAdd(filterGroup, cryptoHashNew(hashTypeSha1));

// Add size filter
ioFilterGroupAdd(filterGroup, ioSizeNew());
Expand Down
2 changes: 1 addition & 1 deletion src/command/verify/file.c
Expand Up @@ -53,7 +53,7 @@ verifyFile(
ioFilterGroupAdd(filterGroup, decompressFilter(compressType));

// Add sha1 filter
ioFilterGroupAdd(filterGroup, cryptoHashNew(HASH_TYPE_SHA1_STR));
ioFilterGroupAdd(filterGroup, cryptoHashNew(hashTypeSha1));

// Add size filter
ioFilterGroupAdd(filterGroup, ioSizeNew());
Expand Down
2 changes: 1 addition & 1 deletion src/command/verify/verify.c
Expand Up @@ -180,7 +180,7 @@ verifyFileLoad(const String *pathFileName, const String *cipherPass)
IoRead *read = storageReadIo(result);
cipherBlockFilterGroupAdd(
ioReadFilterGroup(read), cfgOptionStrId(cfgOptRepoCipherType), cipherModeDecrypt, cipherPass);
ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(HASH_TYPE_SHA1_STR));
ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(hashTypeSha1));

// If the file is compressed, add a decompression filter
if (compressTypeFromName(pathFileName) != compressTypeNone)
Expand Down
10 changes: 10 additions & 0 deletions src/common/crypto/common.h
Expand Up @@ -24,6 +24,16 @@ typedef enum
cipherTypeAes256Cbc = STRID5("aes-256-cbc", 0xc43dfbbcdcca10),
} CipherType;

/***********************************************************************************************************************************
Hash types
***********************************************************************************************************************************/
typedef enum
{
hashTypeMd5 = STRID5("md5", 0x748d0),
hashTypeSha1 = STRID6("sha1", 0x7412131),
hashTypeSha256 = STRID5("sha256", 0x3dde05130),
} HashType;

/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
Expand Down
44 changes: 22 additions & 22 deletions src/common/crypto/hash.c
Expand Up @@ -17,13 +17,6 @@ Cryptographic Hash
#include "common/type/pack.h"
#include "common/crypto/common.h"

/***********************************************************************************************************************************
Hash types
***********************************************************************************************************************************/
STRING_EXTERN(HASH_TYPE_MD5_STR, HASH_TYPE_MD5);
STRING_EXTERN(HASH_TYPE_SHA1_STR, HASH_TYPE_SHA1);
STRING_EXTERN(HASH_TYPE_SHA256_STR, HASH_TYPE_SHA256);

/***********************************************************************************************************************************
Hashes for zero-length files (i.e., seed value)
***********************************************************************************************************************************/
Expand Down Expand Up @@ -171,13 +164,13 @@ cryptoHashResult(THIS_VOID)

/**********************************************************************************************************************************/
IoFilter *
cryptoHashNew(const String *type)
cryptoHashNew(const HashType type)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STRING, type);
FUNCTION_LOG_PARAM(STRING_ID, type);
FUNCTION_LOG_END();

ASSERT(type != NULL);
ASSERT(type != 0);

// Init crypto subsystem
cryptoInit();
Expand All @@ -193,7 +186,7 @@ cryptoHashNew(const String *type)
// Use local MD5 implementation since FIPS-enabled systems do not allow MD5. This is a bit misguided since there are valid
// cases for using MD5 which do not involve, for example, password hashes. Since popular object stores, e.g. S3, require
// MD5 for verifying payload integrity we are simply forced to provide MD5 functionality.
if (strEq(type, HASH_TYPE_MD5_STR))
if (type == hashTypeMd5)
{
driver->md5Context = memNew(sizeof(MD5_CTX));

Expand All @@ -203,8 +196,11 @@ cryptoHashNew(const String *type)
else
{
// Lookup digest
if ((driver->hashType = EVP_get_digestbyname(strZ(type))) == NULL)
THROW_FMT(AssertError, "unable to load hash '%s'", strZ(type));
char typeZ[STRID_MAX + 1];
strIdToZ(type, typeZ);

if ((driver->hashType = EVP_get_digestbyname(typeZ)) == NULL)
THROW_FMT(AssertError, "unable to load hash '%s'", typeZ);

// Create context
cryptoError((driver->hashContext = EVP_MD_CTX_create()) == NULL, "unable to create hash context");
Expand All @@ -223,7 +219,7 @@ cryptoHashNew(const String *type)
{
PackWrite *const packWrite = pckWriteNewP();

pckWriteStrP(packWrite, type);
pckWriteStrIdP(packWrite, type);
pckWriteEndP(packWrite);

paramList = pckMove(pckWriteResult(packWrite), memContextPrior());
Expand All @@ -249,7 +245,7 @@ cryptoHashNewPack(const Pack *const paramList)

MEM_CONTEXT_TEMP_BEGIN()
{
result = ioFilterMove(cryptoHashNew(pckReadStrP(pckReadNew(paramList))), memContextPrior());
result = ioFilterMove(cryptoHashNew(pckReadStrIdP(pckReadNew(paramList))), memContextPrior());
}
MEM_CONTEXT_TEMP_END();

Expand All @@ -258,14 +254,14 @@ cryptoHashNewPack(const Pack *const paramList)

/**********************************************************************************************************************************/
Buffer *
cryptoHashOne(const String *type, const Buffer *message)
cryptoHashOne(const HashType type, const Buffer *message)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STRING, type);
FUNCTION_LOG_PARAM(STRING_ID, type);
FUNCTION_LOG_PARAM(BUFFER, message);
FUNCTION_LOG_END();

ASSERT(type != NULL);
ASSERT(type != 0);
ASSERT(message != NULL);

Buffer *result = NULL;
Expand All @@ -292,22 +288,26 @@ cryptoHashOne(const String *type, const Buffer *message)

/**********************************************************************************************************************************/
Buffer *
cryptoHmacOne(const String *type, const Buffer *key, const Buffer *message)
cryptoHmacOne(const HashType type, const Buffer *const key, const Buffer *const message)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STRING, type);
FUNCTION_LOG_PARAM(STRING_ID, type);
FUNCTION_LOG_PARAM(BUFFER, key);
FUNCTION_LOG_PARAM(BUFFER, message);
FUNCTION_LOG_END();

ASSERT(type != NULL);
ASSERT(type != 0);
ASSERT(key != NULL);
ASSERT(message != NULL);

// Init crypto subsystem
cryptoInit();

const EVP_MD *hashType = EVP_get_digestbyname(strZ(type));
// Lookup digest
char typeZ[STRID_MAX + 1];
strIdToZ(type, typeZ);

const EVP_MD *hashType = EVP_get_digestbyname(typeZ);
ASSERT(hashType != NULL);

// Allocate a buffer to hold the hmac
Expand Down
17 changes: 4 additions & 13 deletions src/common/crypto/hash.h
Expand Up @@ -6,6 +6,7 @@ Generate a hash (sha1, md5, etc.) from a string, Buffer, or using an IoFilter.
#ifndef COMMON_CRYPTO_HASH_H
#define COMMON_CRYPTO_HASH_H

#include "common/crypto/common.h"
#include "common/io/filter/filter.h"
#include "common/type/string.h"

Expand All @@ -14,16 +15,6 @@ Filter type constant
***********************************************************************************************************************************/
#define CRYPTO_HASH_FILTER_TYPE STRID5("hash", 0x44c280)

/***********************************************************************************************************************************
Hash types
***********************************************************************************************************************************/
#define HASH_TYPE_MD5 "md5"
STRING_DECLARE(HASH_TYPE_MD5_STR);
#define HASH_TYPE_SHA1 "sha1"
STRING_DECLARE(HASH_TYPE_SHA1_STR);
#define HASH_TYPE_SHA256 "sha256"
STRING_DECLARE(HASH_TYPE_SHA256_STR);

/***********************************************************************************************************************************
Hashes for zero-length files (i.e., starting hash)
***********************************************************************************************************************************/
Expand All @@ -49,16 +40,16 @@ Hash type sizes
/***********************************************************************************************************************************
Constructors
***********************************************************************************************************************************/
IoFilter *cryptoHashNew(const String *type);
IoFilter *cryptoHashNew(HashType type);
IoFilter *cryptoHashNewPack(const Pack *paramList);

/***********************************************************************************************************************************
Helper functions
***********************************************************************************************************************************/
// Get hash for one buffer
Buffer *cryptoHashOne(const String *type, const Buffer *message);
Buffer *cryptoHashOne(HashType type, const Buffer *message);

// Get hmac for one message/key
Buffer *cryptoHmacOne(const String *type, const Buffer *key, const Buffer *message);
Buffer *cryptoHmacOne(HashType type, const Buffer *key, const Buffer *message);

#endif
4 changes: 2 additions & 2 deletions src/info/info.c
Expand Up @@ -269,7 +269,7 @@ infoNewLoad(IoRead *read, InfoLoadNewCallback *callbackFunction, void *callbackD
.callbackFunction = callbackFunction,
.callbackData = callbackData,
.info = this,
.checksumActual = cryptoHashNew(HASH_TYPE_SHA1_STR),
.checksumActual = cryptoHashNew(hashTypeSha1),
};

INFO_CHECKSUM_BEGIN(data.checksumActual);
Expand Down Expand Up @@ -404,7 +404,7 @@ infoSave(Info *this, IoWrite *write, InfoSaveCallback *callbackFunction, void *c
ioWriteOpen(data.write);

// Begin checksum calculation
data.checksum = cryptoHashNew(HASH_TYPE_SHA1_STR);
data.checksum = cryptoHashNew(hashTypeSha1);
INFO_CHECKSUM_BEGIN(data.checksum);

// Add version and format
Expand Down
5 changes: 2 additions & 3 deletions src/storage/azure/storage.c
Expand Up @@ -167,7 +167,7 @@ storageAzureAuth(
// Generate authorization header
httpHeaderPut(
httpHeader, HTTP_HEADER_AUTHORIZATION_STR, strNewFmt("SharedKey %s:%s", strZ(this->account),
strZ(strNewEncode(encodeBase64, cryptoHmacOne(HASH_TYPE_SHA256_STR, this->sharedKey, BUFSTR(stringToSign))))));
strZ(strNewEncode(encodeBase64, cryptoHmacOne(hashTypeSha256, this->sharedKey, BUFSTR(stringToSign))))));
}
// SAS authentication
else
Expand Down Expand Up @@ -216,8 +216,7 @@ storageAzureRequestAsync(StorageAzure *this, const String *verb, StorageAzureReq
if (param.content != NULL)
{
httpHeaderAdd(
requestHeader, HTTP_HEADER_CONTENT_MD5_STR,
strNewEncode(encodeBase64, cryptoHashOne(HASH_TYPE_MD5_STR, param.content)));
requestHeader, HTTP_HEADER_CONTENT_MD5_STR, strNewEncode(encodeBase64, cryptoHashOne(hashTypeMd5, param.content)));
}

// Encode path
Expand Down
2 changes: 1 addition & 1 deletion src/storage/gcs/write.c
Expand Up @@ -63,7 +63,7 @@ storageWriteGcsOpen(THIS_VOID)
MEM_CONTEXT_OBJ_BEGIN(this)
{
this->chunkBuffer = bufNew(this->chunkSize);
this->md5hash = cryptoHashNew(HASH_TYPE_MD5_STR);
this->md5hash = cryptoHashNew(hashTypeMd5);
}
MEM_CONTEXT_OBJ_END();

Expand Down
17 changes: 8 additions & 9 deletions src/storage/s3/storage.c
Expand Up @@ -202,22 +202,22 @@ storageS3Auth(
// Generate string to sign
const String *stringToSign = strNewFmt(
AWS4_HMAC_SHA256 "\n%s\n%s/%s/" S3 "/" AWS4_REQUEST "\n%s", strZ(dateTime), strZ(date), strZ(this->region),
strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA256_STR, BUFSTR(canonicalRequest)))));
strZ(bufHex(cryptoHashOne(hashTypeSha256, BUFSTR(canonicalRequest)))));

// Generate signing key. This key only needs to be regenerated every seven days but we'll do it once a day to keep the
// logic simple. It's a relatively expensive operation so we'd rather not do it for every request.
// If the cached signing key has expired (or has none been generated) then regenerate it
if (!strEq(date, this->signingKeyDate))
{
const Buffer *dateKey = cryptoHmacOne(
HASH_TYPE_SHA256_STR, BUFSTR(strNewFmt(AWS4 "%s", strZ(this->secretAccessKey))), BUFSTR(date));
const Buffer *regionKey = cryptoHmacOne(HASH_TYPE_SHA256_STR, dateKey, BUFSTR(this->region));
const Buffer *serviceKey = cryptoHmacOne(HASH_TYPE_SHA256_STR, regionKey, S3_BUF);
hashTypeSha256, BUFSTR(strNewFmt(AWS4 "%s", strZ(this->secretAccessKey))), BUFSTR(date));
const Buffer *regionKey = cryptoHmacOne(hashTypeSha256, dateKey, BUFSTR(this->region));
const Buffer *serviceKey = cryptoHmacOne(hashTypeSha256, regionKey, S3_BUF);

// Switch to the object context so signing key and date are not lost
MEM_CONTEXT_OBJ_BEGIN(this)
{
this->signingKey = cryptoHmacOne(HASH_TYPE_SHA256_STR, serviceKey, AWS4_REQUEST_BUF);
this->signingKey = cryptoHmacOne(hashTypeSha256, serviceKey, AWS4_REQUEST_BUF);
this->signingKeyDate = strDup(date);
}
MEM_CONTEXT_OBJ_END();
Expand All @@ -227,7 +227,7 @@ storageS3Auth(
const String *authorization = strNewFmt(
AWS4_HMAC_SHA256 " Credential=%s/%s/%s/" S3 "/" AWS4_REQUEST ",SignedHeaders=%s,Signature=%s",
strZ(this->accessKey), strZ(date), strZ(this->region), strZ(signedHeaders),
strZ(bufHex(cryptoHmacOne(HASH_TYPE_SHA256_STR, this->signingKey, BUFSTR(stringToSign)))));
strZ(bufHex(cryptoHmacOne(hashTypeSha256, this->signingKey, BUFSTR(stringToSign)))));

httpHeaderPut(httpHeader, HTTP_HEADER_AUTHORIZATION_STR, authorization);
}
Expand Down Expand Up @@ -474,8 +474,7 @@ storageS3RequestAsync(StorageS3 *this, const String *verb, const String *path, S
if (param.content != NULL)
{
httpHeaderAdd(
requestHeader, HTTP_HEADER_CONTENT_MD5_STR,
strNewEncode(encodeBase64, cryptoHashOne(HASH_TYPE_MD5_STR, param.content)));
requestHeader, HTTP_HEADER_CONTENT_MD5_STR, strNewEncode(encodeBase64, cryptoHashOne(hashTypeMd5, param.content)));
}

// Set KMS headers when requested
Expand Down Expand Up @@ -531,7 +530,7 @@ storageS3RequestAsync(StorageS3 *this, const String *verb, const String *path, S
storageS3Auth(
this, verb, path, param.query, storageS3DateTime(time(NULL)), requestHeader,
param.content == NULL || bufEmpty(param.content) ?
HASH_TYPE_SHA256_ZERO_STR : bufHex(cryptoHashOne(HASH_TYPE_SHA256_STR, param.content)));
HASH_TYPE_SHA256_ZERO_STR : bufHex(cryptoHashOne(hashTypeSha256, param.content)));

// Send request
MEM_CONTEXT_PRIOR_BEGIN()
Expand Down
2 changes: 1 addition & 1 deletion test/src/common/harnessInfo.c
Expand Up @@ -76,7 +76,7 @@ harnessInfoChecksum(const String *info)
HarnessInfoChecksumData data =
{
.memContext = MEM_CONTEXT_TEMP(),
.checksum = cryptoHashNew(HASH_TYPE_SHA1_STR),
.checksum = cryptoHashNew(hashTypeSha1),
};

// Create buffer with space for data, header, and checksum
Expand Down

0 comments on commit 8c2b3a0

Please sign in to comment.