Skip to content

Commit

Permalink
Move cryptographic hash functions to C using OpenSSL.
Browse files Browse the repository at this point in the history
  • Loading branch information
dwsteele committed Jun 11, 2018
1 parent 064ec75 commit 350b30f
Show file tree
Hide file tree
Showing 29 changed files with 774 additions and 103 deletions.
4 changes: 4 additions & 0 deletions doc/xml/release.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
</release-feature-list>

<release-development-list>
<release-item>
<p>Move cryptographic hash functions to C using <proper>OpenSSL</proper>.</p>
</release-item>

<release-item>
<p>Split log levels into separate header file. Many modules that use <code>debug.h</code> do not need to do logging so this reduces dependencies for those modules.</p>
</release-item>
Expand Down
14 changes: 4 additions & 10 deletions lib/pgBackRest/Common/Ini.pm
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,16 @@ use warnings FATAL => qw(all);
use Carp qw(confess);
use English '-no_match_vars';

use Digest::SHA;
use Exporter qw(import);
our @EXPORT = qw();
use Fcntl qw(:mode O_WRONLY O_CREAT O_TRUNC);
use File::Basename qw(dirname basename);
use IO::Handle;
use File::Basename qw(dirname);
use JSON::PP;
use Storable qw(dclone);

use pgBackRest::Common::Exception;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::LibC qw(:crypto);
use pgBackRest::Version;

####################################################################################################################################
Expand Down Expand Up @@ -550,13 +548,9 @@ sub hash
# Remove the old checksum
delete($self->{oContent}{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM});

# Calculate the checksum
my $oSHA = Digest::SHA->new('sha1');
my $oJSON = JSON::PP->new()->canonical()->allow_nonref();
$oSHA->add($oJSON->encode($self->{oContent}));

# Set the new checksum
$self->{oContent}{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} = $oSHA->hexdigest();
$self->{oContent}{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM} =
cryptoHashOne('sha1', JSON::PP->new()->canonical()->allow_nonref()->encode($self->{oContent}));

return $self->{oContent}{&INI_SECTION_BACKREST}{&INI_KEY_CHECKSUM};
}
Expand Down
13 changes: 7 additions & 6 deletions lib/pgBackRest/LibCAuto.pm
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,6 @@ sub libcAutoExportTag
'pageChecksumTest',
],

cipher =>
[
'CIPHER_MODE_ENCRYPT',
'CIPHER_MODE_DECRYPT',
],

config =>
[
'CFGOPTVAL_INFO_OUTPUT_TEXT',
Expand Down Expand Up @@ -350,6 +344,13 @@ sub libcAutoExportTag
'cfgOptionTotal',
],

crypto =>
[
'CIPHER_MODE_ENCRYPT',
'CIPHER_MODE_DECRYPT',
'cryptoHashOne',
],

debug =>
[
'libcUvSize',
Expand Down
1 change: 0 additions & 1 deletion lib/pgBackRest/Manifest.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use Carp qw(confess);
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname basename);
use Digest::SHA;
use Time::Local qw(timelocal);

use pgBackRest::DbVersion;
Expand Down
2 changes: 1 addition & 1 deletion lib/pgBackRest/Storage/Filter/CipherBlock.pm
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use Exporter qw(import);
use pgBackRest::Common::Exception;
use pgBackRest::Common::Io::Base;
use pgBackRest::Common::Log;
use pgBackRest::LibC qw(:cipher);
use pgBackRest::LibC qw(:crypto);
use pgBackRest::Storage::Base;

####################################################################################################################################
Expand Down
8 changes: 4 additions & 4 deletions lib/pgBackRest/Storage/Filter/Sha.pm
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ sub new
$self->{strAlgorithm} = $strAlgorithm;

# Create SHA object
$self->{oSha} = Digest::SHA->new($self->{strAlgorithm});
$self->{oSha} = new pgBackRest::LibC::Crypto::Hash($self->{strAlgorithm});

# Return from function and log return values if any
return logDebugReturn
Expand All @@ -76,7 +76,7 @@ sub read
# Calculate sha for the returned buffer
if ($iActualSize > 0)
{
$self->{oSha}->add($tShaBuffer);
$self->{oSha}->process($tShaBuffer);
$$rtBuffer .= $tShaBuffer;
}

Expand All @@ -93,7 +93,7 @@ sub write
my $rtBuffer = shift;

# Calculate sha for the buffer
$self->{oSha}->add($$rtBuffer);
$self->{oSha}->process($$rtBuffer);

# Call the io method
return $self->parent()->write($rtBuffer);
Expand All @@ -109,7 +109,7 @@ sub close
if (defined($self->{oSha}))
{
# Set result
$self->resultSet(STORAGE_FILTER_SHA, $self->{oSha}->hexdigest());
$self->resultSet(STORAGE_FILTER_SHA, $self->{oSha}->result());

# Delete the sha object
delete($self->{oSha});
Expand Down
7 changes: 4 additions & 3 deletions lib/pgBackRest/Storage/S3/Auth.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ use warnings FATAL => qw(all);
use Carp qw(confess);
use English '-no_match_vars';

use Digest::SHA qw(hmac_sha256 hmac_sha256_hex sha256_hex);
use Digest::SHA qw(hmac_sha256 hmac_sha256_hex);
use Exporter qw(import);
our @EXPORT = qw();
use POSIX qw(strftime);

use pgBackRest::Common::Log;
use pgBackRest::LibC qw(:crypto);

####################################################################################################################################
# Constants
Expand All @@ -37,7 +38,7 @@ use constant S3_HEADER_HOST => 'host';
use constant S3_HEADER_TOKEN => 'x-amz-security-token';
push @EXPORT, qw(S3_HEADER_TOKEN);

use constant PAYLOAD_DEFAULT_HASH => sha256_hex('');
use constant PAYLOAD_DEFAULT_HASH => cryptoHashOne('sha256', '');
push @EXPORT, qw(PAYLOAD_DEFAULT_HASH);

####################################################################################################################################
Expand Down Expand Up @@ -257,7 +258,7 @@ sub s3AuthorizationHeader

# Create authorization string
my ($strCanonicalRequest, $strSignedHeaders) = s3CanonicalRequest($strVerb, $strUri, $strQuery, $hHeader, $strPayloadHash);
my $strStringToSign = s3StringToSign($strDateTime, $strRegion, sha256_hex($strCanonicalRequest));
my $strStringToSign = s3StringToSign($strDateTime, $strRegion, cryptoHashOne('sha256', $strCanonicalRequest));

$hHeader->{&S3_HEADER_AUTHORIZATION} =
AWS4_HMAC_SHA256 . " Credential=${strAccessKeyId}/" . substr($strDateTime, 0, 8) . "/${strRegion}/" . S3 . qw(/) .
Expand Down
4 changes: 2 additions & 2 deletions lib/pgBackRest/Storage/S3/Request.pm
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use warnings FATAL => qw(all);
use Carp qw(confess);
use English '-no_match_vars';

use Digest::SHA qw(hmac_sha256 hmac_sha256_hex sha256_hex);
use Exporter qw(import);
our @EXPORT = qw();
use IO::Socket::SSL;
Expand All @@ -20,6 +19,7 @@ use pgBackRest::Common::Io::Base;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Common::Xml;
use pgBackRest::LibC qw(:crypto);
use pgBackRest::Storage::S3::Auth;

####################################################################################################################################
Expand Down Expand Up @@ -152,7 +152,7 @@ sub request
$bRetry = false;

# Set content length and hash
$hHeader->{&S3_HEADER_CONTENT_SHA256} = defined($rstrBody) ? sha256_hex($$rstrBody) : PAYLOAD_DEFAULT_HASH;
$hHeader->{&S3_HEADER_CONTENT_SHA256} = defined($rstrBody) ? cryptoHashOne('sha256', $$rstrBody) : PAYLOAD_DEFAULT_HASH;
$hHeader->{&S3_HEADER_CONTENT_LENGTH} = defined($rstrBody) ? length($$rstrBody) : 0;

# Generate authorization header
Expand Down
2 changes: 2 additions & 0 deletions libc/LibC.xs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ XSH includes
These includes define data structures that are required for the C to Perl interface but are not part of the regular C source.
***********************************************************************************************************************************/
#include "xs/crypto/cipherBlock.xsh"
#include "xs/crypto/hash.xsh"
#include "xs/common/encode.xsh"

/***********************************************************************************************************************************
Expand Down Expand Up @@ -95,6 +96,7 @@ INCLUDE: xs/config/config.xs
INCLUDE: xs/config/configTest.xs
INCLUDE: xs/config/define.xs
INCLUDE: xs/crypto/cipherBlock.xs
INCLUDE: xs/crypto/hash.xs
INCLUDE: xs/crypto/random.xs
INCLUDE: xs/postgres/pageChecksum.xs
INCLUDE: xs/storage/storage.xs
1 change: 1 addition & 0 deletions libc/Makefile.PL
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ my @stryCFile =
'config/parse.c',
'crypto/cipherBlock.c',
'crypto/crypto.c',
'crypto/hash.c',
'crypto/random.c',
'perl/config.c',
'postgres/pageChecksum.c',
Expand Down
17 changes: 9 additions & 8 deletions libc/build/lib/pgBackRestLibC/Build.pm
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,6 @@ my $rhExport =
)],
},

'cipher' =>
{
&BLD_EXPORTTYPE_SUB => [qw(
CIPHER_MODE_ENCRYPT
CIPHER_MODE_DECRYPT
)],
},

'config' =>
{
&BLD_EXPORTTYPE_SUB => [qw(
Expand All @@ -82,6 +74,15 @@ my $rhExport =
)],
},

'crypto' =>
{
&BLD_EXPORTTYPE_SUB => [qw(
CIPHER_MODE_ENCRYPT
CIPHER_MODE_DECRYPT
cryptoHashOne
)],
},

'debug' =>
{
&BLD_EXPORTTYPE_SUB => [qw(
Expand Down
1 change: 1 addition & 0 deletions libc/typemap
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pgBackRest::LibC::Cipher::Block T_PTROBJ
pgBackRest::LibC::Crypto::Hash T_PTROBJ
96 changes: 96 additions & 0 deletions libc/xs/crypto/hash.xs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
####################################################################################################################################
# Cryptographic Hashes Perl Exports
#
# XS wrapper for functions in cipher/hash.c.
####################################################################################################################################

MODULE = pgBackRest::LibC PACKAGE = pgBackRest::LibC::Crypto::Hash

####################################################################################################################################
pgBackRest::LibC::Crypto::Hash
new(class, type)
const char *class
const char *type
CODE:
RETVAL = NULL;

// Don't warn when class param is used
(void)class;

MEM_CONTEXT_XS_NEW_BEGIN("cryptoHashXs")
{
RETVAL = memNew(sizeof(CryptoHashXs));
RETVAL->memContext = MEM_COMTEXT_XS();
RETVAL->pxPayload = cryptoHashNew(strNew(type));
}
MEM_CONTEXT_XS_NEW_END();
OUTPUT:
RETVAL

####################################################################################################################################
void
process(self, message)
pgBackRest::LibC::Crypto::Hash self
SV *message
CODE:
MEM_CONTEXT_XS_TEMP_BEGIN()
{
STRLEN messageSize;
const unsigned char *messagePtr = (const unsigned char *)SvPV(message, messageSize);

cryptoHashProcessC(self->pxPayload, messagePtr, messageSize);
}
MEM_CONTEXT_XS_TEMP_END();

####################################################################################################################################
SV *
result(self)
pgBackRest::LibC::Crypto::Hash self
CODE:
RETVAL = NULL;

MEM_CONTEXT_XS_TEMP_BEGIN()
{
String *hash = cryptoHashHex(self->pxPayload);

RETVAL = newSV(strSize(hash));
SvPOK_only(RETVAL);
strcpy((char *)SvPV_nolen(RETVAL), strPtr(hash));
SvCUR_set(RETVAL, strSize(hash));
}
MEM_CONTEXT_XS_TEMP_END();
OUTPUT:
RETVAL

####################################################################################################################################
void
DESTROY(self)
pgBackRest::LibC::Crypto::Hash self
CODE:
MEM_CONTEXT_XS_DESTROY(self->memContext);

MODULE = pgBackRest::LibC PACKAGE = pgBackRest::LibC

####################################################################################################################################
SV *
cryptoHashOne(type, message)
const char *type
SV *message
CODE:
RETVAL = NULL;

MEM_CONTEXT_XS_TEMP_BEGIN()
{
STRLEN messageSize;
const unsigned char *messagePtr = (const unsigned char *)SvPV(message, messageSize);

String *hash = cryptoHashOneC(strNew(type), messagePtr, messageSize);

RETVAL = newSV(strSize(hash));
SvPOK_only(RETVAL);
strcpy((char *)SvPV_nolen(RETVAL), strPtr(hash));
SvCUR_set(RETVAL, strSize(hash));
}
MEM_CONTEXT_XS_TEMP_END();
OUTPUT:
RETVAL
11 changes: 11 additions & 0 deletions libc/xs/crypto/hash.xsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/***********************************************************************************************************************************
Cryptographic Hashes XS Header
***********************************************************************************************************************************/
#include "common/memContext.h"
#include "crypto/hash.h"

typedef struct CryptoHashXs
{
MemContext *memContext;
CryptoHash *pxPayload;
} CryptoHashXs, *pgBackRest__LibC__Crypto__Hash;
6 changes: 5 additions & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ SRCS = \
config/load.c \
config/parse.c \
crypto/cipherBlock.c \
crypto/hash.c \
crypto/crypto.c \
crypto/random.c \
perl/config.c \
Expand Down Expand Up @@ -224,6 +225,9 @@ crypto/cipherBlock.o: crypto/cipherBlock.c common/debug.h common/error.auto.h co
crypto/crypto.o: crypto/crypto.c common/debug.h common/log.h common/logLevel.h common/stackTrace.h common/type/convert.h crypto/crypto.h
$(CC) $(CFLAGS) -c crypto/crypto.c -o crypto/crypto.o

crypto/hash.o: crypto/hash.c common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/string.h crypto/crypto.h crypto/hash.h
$(CC) $(CFLAGS) -c crypto/hash.c -o crypto/hash.o

crypto/random.o: crypto/random.c common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/stackTrace.h common/type/convert.h crypto/random.h
$(CC) $(CFLAGS) -c crypto/random.c -o crypto/random.o

Expand All @@ -233,7 +237,7 @@ main.o: main.c command/archive/get/get.h command/archive/push/push.h command/com
perl/config.o: perl/config.c common/debug.h common/error.auto.h common/error.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h
$(CC) $(CFLAGS) -c perl/config.c -o perl/config.o

perl/exec.o: perl/exec.c ../libc/LibC.h common/debug.h common/encode.h common/error.auto.h common/error.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h config/parse.h crypto/cipher.h crypto/cipherBlock.h crypto/random.h perl/config.h perl/embed.auto.c perl/exec.h perl/libc.auto.c postgres/pageChecksum.h storage/driver/posix/driver.h storage/driver/posix/driverRead.h storage/driver/posix/driverWrite.h storage/info.h version.h ../libc/xs/common/encode.xsh ../libc/xs/crypto/cipherBlock.xsh
perl/exec.o: perl/exec.c ../libc/LibC.h common/debug.h common/encode.h common/error.auto.h common/error.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h config/parse.h crypto/cipher.h crypto/cipherBlock.h crypto/hash.h crypto/random.h perl/config.h perl/embed.auto.c perl/exec.h perl/libc.auto.c postgres/pageChecksum.h storage/driver/posix/driver.h storage/driver/posix/driverRead.h storage/driver/posix/driverWrite.h storage/info.h version.h ../libc/xs/common/encode.xsh ../libc/xs/crypto/cipherBlock.xsh ../libc/xs/crypto/hash.xsh
$(CC) $(CFLAGS) -c perl/exec.c -o perl/exec.o

postgres/info.o: postgres/info.c common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h postgres/info.h postgres/type.h postgres/version.h storage/driver/posix/driverRead.h storage/driver/posix/driverWrite.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h version.h
Expand Down
Loading

0 comments on commit 350b30f

Please sign in to comment.