summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShreyas Kalyan <shreyas.kalyan@10gen.com>2019-03-05 13:02:35 -0500
committerShreyas Kalyan <shreyas.kalyan@10gen.com>2019-03-21 12:02:43 -0400
commit0adb2f088e4326c35d82afa42e9e5d5969530c5a (patch)
tree8ea58ec95409ae9206a1975f56acf25ba0f8dcfa /src
parent9dc7556e1f02e09956ec60118fa7a1bfa3edad98 (diff)
downloadmongo-0adb2f088e4326c35d82afa42e9e5d5969530c5a.tar.gz
SERVER-39893 Implement AEAD_AES_256_CBC_HMAC_SHA_512
Diffstat (limited to 'src')
-rw-r--r--src/mongo/crypto/SConscript4
-rw-r--r--src/mongo/crypto/sha1_block.h5
-rw-r--r--src/mongo/crypto/sha256_block.h3
-rw-r--r--src/mongo/crypto/sha512_block.h60
-rw-r--r--src/mongo/crypto/sha512_block.idl46
-rw-r--r--src/mongo/crypto/sha512_block_test.cpp216
-rw-r--r--src/mongo/crypto/sha_block.h21
-rw-r--r--src/mongo/crypto/sha_block_apple.cpp43
-rw-r--r--src/mongo/crypto/sha_block_openssl.cpp59
-rw-r--r--src/mongo/crypto/sha_block_tom.cpp45
-rw-r--r--src/mongo/crypto/sha_block_windows.cpp56
-rwxr-xr-x[-rw-r--r--]src/third_party/scripts/tomcrypt_get_sources.sh1
-rw-r--r--src/third_party/tomcrypt-1.18.2/SConscript1
-rw-r--r--src/third_party/tomcrypt-1.18.2/src/hashes/sha2/sha512.c313
14 files changed, 825 insertions, 48 deletions
diff --git a/src/mongo/crypto/SConscript b/src/mongo/crypto/SConscript
index 8f6e35d7b60..97f73e3356a 100644
--- a/src/mongo/crypto/SConscript
+++ b/src/mongo/crypto/SConscript
@@ -65,6 +65,10 @@ env.CppUnitTest('sha256_block_test',
['sha256_block_test.cpp'],
LIBDEPS=['sha_block_${MONGO_CRYPTO}'])
+env.CppUnitTest('sha512_block_test',
+ ['sha512_block_test.cpp'],
+ LIBDEPS=['sha_block_${MONGO_CRYPTO}'])
+
env.CppUnitTest('mechanism_scram_test',
['mechanism_scram_test.cpp'],
LIBDEPS_PRIVATE=[
diff --git a/src/mongo/crypto/sha1_block.h b/src/mongo/crypto/sha1_block.h
index 79fa3ca8af0..fcebf441869 100644
--- a/src/mongo/crypto/sha1_block.h
+++ b/src/mongo/crypto/sha1_block.h
@@ -36,7 +36,7 @@
namespace mongo {
/**
- * A Traits type for adapting SHABlock to sha256 hashes.
+ * A Traits type for adapting SHABlock to sha1 hashes.
*/
struct SHA1BlockTraits {
using HashType = MakeArrayType<std::uint8_t, 20, SHA1BlockTraits>;
@@ -47,8 +47,7 @@ struct SHA1BlockTraits {
static void computeHmac(const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ std::initializer_list<ConstDataRange> input,
HashType* const output);
};
diff --git a/src/mongo/crypto/sha256_block.h b/src/mongo/crypto/sha256_block.h
index ce8793c8bd8..7514e33bd82 100644
--- a/src/mongo/crypto/sha256_block.h
+++ b/src/mongo/crypto/sha256_block.h
@@ -47,8 +47,7 @@ struct SHA256BlockTraits {
static void computeHmac(const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ std::initializer_list<ConstDataRange> input,
HashType* const output);
};
diff --git a/src/mongo/crypto/sha512_block.h b/src/mongo/crypto/sha512_block.h
new file mode 100644
index 00000000000..af8350d19e3
--- /dev/null
+++ b/src/mongo/crypto/sha512_block.h
@@ -0,0 +1,60 @@
+/**
+ * Copyright (C) 2019-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/crypto/sha_block.h"
+
+#include "mongo/util/make_array_type.h"
+
+namespace mongo {
+
+/**
+ * A Traits type for adapting SHABlock to sha512 hashes.
+ */
+struct SHA512BlockTraits {
+ using HashType = MakeArrayType<std::uint8_t, 64, SHA512BlockTraits>;
+
+ static constexpr StringData name = "SHA512Block"_sd;
+
+ static HashType computeHash(std::initializer_list<ConstDataRange> input);
+
+ static void computeHmac(const uint8_t* key,
+ size_t keyLen,
+ std::initializer_list<ConstDataRange> input,
+ HashType* const output);
+
+ static HashType computeHmac(const uint8_t* key,
+ size_t keyLen,
+ std::initializer_list<ConstDataRange> input);
+};
+
+using SHA512Block = SHABlock<SHA512BlockTraits>;
+
+} // namespace mongo
diff --git a/src/mongo/crypto/sha512_block.idl b/src/mongo/crypto/sha512_block.idl
new file mode 100644
index 00000000000..46b35d13613
--- /dev/null
+++ b/src/mongo/crypto/sha512_block.idl
@@ -0,0 +1,46 @@
+# Copyright (C) 2019-present MongoDB, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the Server Side Public License, version 1,
+# as published by MongoDB, Inc.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# Server Side Public License for more details.
+#
+# You should have received a copy of the Server Side Public License
+# along with this program. If not, see
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# As a special exception, the copyright holders give permission to link the
+# code of portions of this program with the OpenSSL library under certain
+# conditions as described in each individual source file and distribute
+# linked combinations including the program with the OpenSSL library. You
+# must comply with the Server Side Public License in all respects for
+# all of the code used other than as permitted herein. If you modify file(s)
+# with this exception, you may extend this exception to your version of the
+# file(s), but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version. If you delete this
+# exception statement from all source files in the program, then also delete
+# it in the license file.
+#
+
+# SHA512Block type
+
+global:
+ cpp_namespace: "mongo"
+ cpp_includes:
+ - "mongo/crypto/sha512_block.h"
+
+imports:
+ - "mongo/idl/basic_types.idl"
+
+types:
+ sha512Block:
+ bson_serialization_type: bindata
+ bindata_subtype: generic
+ description: "A fixed-size byte array that holds the result of a SHA512 computation"
+ cpp_type: mongo::SHA512Block
+ serializer: "mongo::SHA512Block::toCDR"
+ deserializer: "mongo::SHA512Block::fromBinData"
diff --git a/src/mongo/crypto/sha512_block_test.cpp b/src/mongo/crypto/sha512_block_test.cpp
new file mode 100644
index 00000000000..79ef4e3ffcc
--- /dev/null
+++ b/src/mongo/crypto/sha512_block_test.cpp
@@ -0,0 +1,216 @@
+/**
+ * Copyright (C) 2019-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/bson/bsonmisc.h"
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/crypto/sha512_block.h"
+#include "mongo/unittest/unittest.h"
+
+namespace mongo {
+namespace {
+
+ConstDataRange makeTestItem(StringData sd) {
+ return ConstDataRange(sd.rawData(), sd.size());
+}
+
+// SHA-512 test vectors from http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
+const struct {
+ std::initializer_list<ConstDataRange> msg;
+ SHA512Block hash;
+} sha512Tests[] = {
+ {{makeTestItem("abc")},
+ SHA512Block::HashType{0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73,
+ 0x49, 0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9,
+ 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21,
+ 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23,
+ 0xa3, 0xfe, 0xeb, 0xbd, 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8,
+ 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f}},
+
+ {{makeTestItem("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjkl"
+ "mnopqklmnopqrlmnopqrsmnopqrstnopqrstu")},
+ SHA512Block::HashType{0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 0x8c, 0xf4, 0xf7,
+ 0x28, 0x14, 0xfc, 0x14, 0x3f, 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f,
+ 0x7f, 0xa1, 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, 0x50,
+ 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 0x33, 0x1b, 0x99, 0xde,
+ 0xc4, 0xb5, 0x43, 0x3a, 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26,
+ 0x54, 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09}},
+
+ {{makeTestItem("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopj"),
+ makeTestItem("klmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")},
+ SHA512Block::HashType{0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 0x8c, 0xf4, 0xf7,
+ 0x28, 0x14, 0xfc, 0x14, 0x3f, 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f,
+ 0x7f, 0xa1, 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, 0x50,
+ 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 0x33, 0x1b, 0x99, 0xde,
+ 0xc4, 0xb5, 0x43, 0x3a, 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26,
+ 0x54, 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09}},
+
+};
+
+TEST(CryptoVectors, SHA512) {
+ size_t numTests = sizeof(sha512Tests) / sizeof(sha512Tests[0]);
+ for (size_t i = 0; i < numTests; i++) {
+ SHA512Block result = SHA512Block::computeHash(sha512Tests[i].msg);
+ ASSERT(sha512Tests[i].hash == result) << "Failed SHA512 iteration " << i;
+ }
+}
+
+const int maxKeySize = 80;
+const int maxDataSize = 54;
+// HMAC-SHA-512 test vectors from https://tools.ietf.org/html/rfc4231#section-4.2
+const struct {
+ unsigned char key[maxKeySize];
+ int keyLen;
+ unsigned char data[maxDataSize];
+ int dataLen;
+ SHA512Block hash;
+} hmacSha512Tests[] = {
+ // RFC test case 1
+ {{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b},
+ 20,
+ {0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65},
+ 8,
+ SHA512Block::HashType{0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 0x4f, 0xf0, 0xb4,
+ 0x24, 0x1a, 0x1d, 0x6c, 0xb0, 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e,
+ 0xc2, 0x78, 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, 0xda,
+ 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02, 0x03, 0x8b, 0x27, 0x4e,
+ 0xae, 0xa3, 0xf4, 0xe4, 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1,
+ 0x70, 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54}},
+
+ // RFC test case 3
+ {{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa},
+ 20,
+ {0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd},
+ 50,
+ SHA512Block::HashType{0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 0xef, 0xb0, 0xf0,
+ 0x75, 0x6c, 0x89, 0x0b, 0xe9, 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8,
+ 0x1a, 0x36, 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, 0xbf,
+ 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8, 0x06, 0xb4, 0x85, 0xa4,
+ 0x7e, 0x67, 0xc8, 0x07, 0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94,
+ 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb}},
+
+ // RFC test case 4
+ {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
+ 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19},
+ 25,
+ {0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+ 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd},
+ 50,
+ SHA512Block::HashType{0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, 0x90, 0xe5, 0xa8,
+ 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b,
+ 0x87, 0x2d, 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, 0xa9,
+ 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4, 0xd6, 0x79, 0x27, 0x5c,
+ 0xc5, 0x78, 0x80, 0x63, 0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f,
+ 0x2d, 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd}},
+};
+
+TEST(CryptoVectors, HMACSHA512) {
+ size_t numTests = sizeof(hmacSha512Tests) / sizeof(hmacSha512Tests[0]);
+ for (size_t i = 0; i < numTests; i++) {
+ SHA512Block result = SHA512Block::computeHmac(hmacSha512Tests[i].key,
+ hmacSha512Tests[i].keyLen,
+ hmacSha512Tests[i].data,
+ hmacSha512Tests[i].dataLen);
+ ASSERT(hmacSha512Tests[i].hash == result) << "Failed HMAC-SHA512 iteration " << i;
+ }
+}
+
+TEST(SHA512Block, BinDataRoundTrip) {
+ SHA512Block::HashType rawHash;
+ rawHash.fill(0);
+ for (size_t i = 0; i < rawHash.size(); i++) {
+ rawHash[i] = i;
+ }
+
+ SHA512Block testHash(rawHash);
+
+ BSONObjBuilder builder;
+ testHash.appendAsBinData(builder, "hash");
+ auto newObj = builder.done();
+
+ auto hashElem = newObj["hash"];
+ ASSERT_EQ(BinData, hashElem.type());
+ ASSERT_EQ(BinDataGeneral, hashElem.binDataType());
+
+ int binLen = 0;
+ auto rawBinData = hashElem.binData(binLen);
+ ASSERT_EQ(SHA512Block::kHashLength, static_cast<size_t>(binLen));
+
+ auto newHashStatus =
+ SHA512Block::fromBinData(BSONBinData(rawBinData, binLen, hashElem.binDataType()));
+ ASSERT_OK(newHashStatus.getStatus());
+ ASSERT_TRUE(testHash == newHashStatus.getValue());
+}
+
+TEST(SHA512Block, CanOnlyConstructFromBinGeneral) {
+ std::string dummy(SHA512Block::kHashLength, 'x');
+
+ auto newHashStatus =
+ SHA512Block::fromBinData(BSONBinData(dummy.c_str(), dummy.size(), newUUID));
+ ASSERT_EQ(ErrorCodes::UnsupportedFormat, newHashStatus.getStatus());
+}
+
+TEST(SHA512Block, FromBinDataShouldRejectWrongSize) {
+ std::string dummy(SHA512Block::kHashLength - 1, 'x');
+
+ auto newHashStatus =
+ SHA512Block::fromBinData(BSONBinData(dummy.c_str(), dummy.size(), BinDataGeneral));
+ ASSERT_EQ(ErrorCodes::UnsupportedFormat, newHashStatus.getStatus());
+
+ dummy = std::string(SHA512Block::kHashLength - 1, 'x');
+
+ newHashStatus =
+ SHA512Block::fromBinData(BSONBinData(dummy.c_str(), dummy.size(), BinDataGeneral));
+ ASSERT_EQ(ErrorCodes::UnsupportedFormat, newHashStatus.getStatus());
+}
+
+TEST(SHA512Block, FromBufferShouldRejectWrongLength) {
+ std::string dummy(SHA512Block::kHashLength - 1, 'x');
+
+ auto newHashStatus =
+ SHA512Block::fromBuffer(reinterpret_cast<const uint8_t*>(dummy.c_str()), dummy.size());
+ ASSERT_EQ(ErrorCodes::InvalidLength, newHashStatus.getStatus());
+
+ dummy = std::string(SHA512Block::kHashLength + 1, 'x');
+
+ newHashStatus =
+ SHA512Block::fromBuffer(reinterpret_cast<const uint8_t*>(dummy.c_str()), dummy.size());
+ ASSERT_EQ(ErrorCodes::InvalidLength, newHashStatus.getStatus());
+}
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/crypto/sha_block.h b/src/mongo/crypto/sha_block.h
index afd0d3e75e5..e9a0ce338b9 100644
--- a/src/mongo/crypto/sha_block.h
+++ b/src/mongo/crypto/sha_block.h
@@ -99,7 +99,8 @@ public:
const uint8_t* input,
size_t inputLen) {
SHABlock output;
- SHABlock::computeHmac(key, keyLen, input, inputLen, &output);
+ SHABlock::computeHmac(
+ key, keyLen, {ConstDataRange(reinterpret_cast<const char*>(input), inputLen)}, &output);
return output;
}
@@ -112,7 +113,23 @@ public:
const uint8_t* input,
size_t inputLen,
SHABlock* const output) {
- return Traits::computeHmac(key, keyLen, input, inputLen, &(output->_hash));
+ SHABlock::computeHmac(
+ key, keyLen, {ConstDataRange(reinterpret_cast<const char*>(input), inputLen)}, output);
+ }
+
+ static SHABlock computeHmac(const uint8_t* key,
+ size_t keyLen,
+ std::initializer_list<ConstDataRange> input) {
+ SHABlock output;
+ SHABlock::computeHmac(key, keyLen, input, &output);
+ return output;
+ }
+
+ static void computeHmac(const uint8_t* key,
+ size_t keyLen,
+ std::initializer_list<ConstDataRange> input,
+ SHABlock* const output) {
+ Traits::computeHmac(key, keyLen, input, &(output->_hash));
}
const uint8_t* data() const& {
diff --git a/src/mongo/crypto/sha_block_apple.cpp b/src/mongo/crypto/sha_block_apple.cpp
index 3679c3fd339..daa63eb2af9 100644
--- a/src/mongo/crypto/sha_block_apple.cpp
+++ b/src/mongo/crypto/sha_block_apple.cpp
@@ -34,6 +34,7 @@
#include "mongo/crypto/sha1_block.h"
#include "mongo/crypto/sha256_block.h"
+#include "mongo/crypto/sha512_block.h"
namespace mongo {
using CDRinit = std::initializer_list<ConstDataRange>;
@@ -66,29 +67,59 @@ SHA256BlockTraits::HashType SHA256BlockTraits::computeHash(CDRinit input) {
return ret;
}
+SHA512BlockTraits::HashType SHA512BlockTraits::computeHash(CDRinit input) {
+ CC_SHA512_CTX ctx;
+ CC_SHA512_Init(&ctx);
+ for (const auto& range : input) {
+ CC_SHA512_Update(&ctx, range.data(), range.length());
+ }
+
+ SHA512BlockTraits::HashType ret;
+ static_assert(sizeof(ret) == CC_SHA512_DIGEST_LENGTH,
+ "SHA512 HashType size doesn't match expected digest output size");
+ CC_SHA512_Final(ret.data(), &ctx);
+ return ret;
+}
+
void SHA1BlockTraits::computeHmac(const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ CDRinit input,
SHA1BlockTraits::HashType* const output) {
static_assert(sizeof(*output) == CC_SHA1_DIGEST_LENGTH,
"SHA1 HashType size doesn't match expected hmac output size");
CCHmacContext ctx;
CCHmacInit(&ctx, kCCHmacAlgSHA1, key, keyLen);
- CCHmacUpdate(&ctx, input, inputLen);
+ for (const auto& range : input) {
+ CCHmacUpdate(&ctx, range.data(), range.length());
+ }
CCHmacFinal(&ctx, output);
}
void SHA256BlockTraits::computeHmac(const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ CDRinit input,
SHA256BlockTraits::HashType* const output) {
static_assert(sizeof(*output) == CC_SHA256_DIGEST_LENGTH,
"SHA256 HashType size doesn't match expected hmac output size");
CCHmacContext ctx;
CCHmacInit(&ctx, kCCHmacAlgSHA256, key, keyLen);
- CCHmacUpdate(&ctx, input, inputLen);
+ for (const auto& range : input) {
+ CCHmacUpdate(&ctx, range.data(), range.length());
+ }
+ CCHmacFinal(&ctx, output);
+}
+
+void SHA512BlockTraits::computeHmac(const uint8_t* key,
+ size_t keyLen,
+ CDRinit input,
+ SHA512BlockTraits::HashType* const output) {
+ static_assert(sizeof(*output) == CC_SHA512_DIGEST_LENGTH,
+ "SHA512 HashType size doesn't match expected hmac output size");
+ CCHmacContext ctx;
+ CCHmacInit(&ctx, kCCHmacAlgSHA512, key, keyLen);
+ for (const auto& range : input) {
+ CCHmacUpdate(&ctx, range.data(), range.length());
+ }
CCHmacFinal(&ctx, output);
}
diff --git a/src/mongo/crypto/sha_block_openssl.cpp b/src/mongo/crypto/sha_block_openssl.cpp
index 71a73c1266d..9937afba477 100644
--- a/src/mongo/crypto/sha_block_openssl.cpp
+++ b/src/mongo/crypto/sha_block_openssl.cpp
@@ -31,6 +31,7 @@
#include "mongo/crypto/sha1_block.h"
#include "mongo/crypto/sha256_block.h"
+#include "mongo/crypto/sha512_block.h"
#include "mongo/config.h"
#include "mongo/stdx/memory.h"
@@ -63,6 +64,21 @@ void EVP_MD_CTX_free(EVP_MD_CTX* ctx) {
EVP_MD_CTX_cleanup(ctx);
OPENSSL_free(ctx);
}
+
+HMAC_CTX* HMAC_CTX_new() {
+ void* ctx = OPENSSL_malloc(sizeof(HMAC_CTX));
+
+ if (ctx != NULL) {
+ memset(ctx, 0, sizeof(HMAC_CTX));
+ }
+ return static_cast<HMAC_CTX*>(ctx);
+}
+
+void HMAC_CTX_free(HMAC_CTX* ctx) {
+ HMAC_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+}
+
} // namespace
#endif
@@ -91,17 +107,24 @@ HashType computeHashImpl(const EVP_MD* md, std::initializer_list<ConstDataRange>
return output;
}
-/*
- * Computes a HMAC SHA'd keyed hash of 'input' using the key 'key', writes output into 'output'.
- */
template <typename HashType>
void computeHmacImpl(const EVP_MD* md,
const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ std::initializer_list<ConstDataRange> input,
HashType* const output) {
- fassert(40380, HMAC(md, key, keyLen, input, inputLen, output->data(), NULL) != NULL);
+ std::unique_ptr<HMAC_CTX, decltype(&HMAC_CTX_free)> digestCtx(HMAC_CTX_new(), HMAC_CTX_free);
+
+ fassert(40380,
+ HMAC_Init_ex(digestCtx.get(), key, keyLen, md, NULL) == 1 &&
+ std::all_of(begin(input),
+ end(input),
+ [&](const auto& i) {
+ return HMAC_Update(digestCtx.get(),
+ reinterpret_cast<const unsigned char*>(i.data()),
+ i.length()) == 1;
+ }) &&
+ HMAC_Final(digestCtx.get(), output->data(), NULL) == 1);
}
} // namespace
@@ -116,22 +139,30 @@ SHA256BlockTraits::HashType SHA256BlockTraits::computeHash(
return computeHashImpl<SHA256BlockTraits::HashType>(EVP_sha256(), input);
}
+SHA512BlockTraits::HashType SHA512BlockTraits::computeHash(
+ std::initializer_list<ConstDataRange> input) {
+ return computeHashImpl<SHA512BlockTraits::HashType>(EVP_sha512(), input);
+}
+
void SHA1BlockTraits::computeHmac(const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ std::initializer_list<ConstDataRange> input,
SHA1BlockTraits::HashType* const output) {
- return computeHmacImpl<SHA1BlockTraits::HashType>(
- EVP_sha1(), key, keyLen, input, inputLen, output);
+ return computeHmacImpl<SHA1BlockTraits::HashType>(EVP_sha1(), key, keyLen, input, output);
}
void SHA256BlockTraits::computeHmac(const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ std::initializer_list<ConstDataRange> input,
SHA256BlockTraits::HashType* const output) {
- return computeHmacImpl<SHA256BlockTraits::HashType>(
- EVP_sha256(), key, keyLen, input, inputLen, output);
+ return computeHmacImpl<SHA256BlockTraits::HashType>(EVP_sha256(), key, keyLen, input, output);
+}
+
+void SHA512BlockTraits::computeHmac(const uint8_t* key,
+ size_t keyLen,
+ std::initializer_list<ConstDataRange> input,
+ SHA512BlockTraits::HashType* const output) {
+ return computeHmacImpl<SHA512BlockTraits::HashType>(EVP_sha512(), key, keyLen, input, output);
}
} // namespace mongo
diff --git a/src/mongo/crypto/sha_block_tom.cpp b/src/mongo/crypto/sha_block_tom.cpp
index 8a53b91aec9..8f477ad8fad 100644
--- a/src/mongo/crypto/sha_block_tom.cpp
+++ b/src/mongo/crypto/sha_block_tom.cpp
@@ -31,6 +31,7 @@
#include "mongo/crypto/sha1_block.h"
#include "mongo/crypto/sha256_block.h"
+#include "mongo/crypto/sha512_block.h"
#include "mongo/config.h"
#include "mongo/util/assert_util.h"
@@ -76,10 +77,11 @@ template <typename HashType>
void computeHmacImpl(const ltc_hash_descriptor* desc,
const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ std::initializer_list<ConstDataRange> input,
HashType* const output) {
- invariant(key && input);
+ invariant(key);
+ invariant(
+ std::all_of(begin(input), end(input), [&](const auto& i) { return i.data() != nullptr; }));
static const struct Magic {
Magic(const ltc_hash_descriptor* desc) {
@@ -90,10 +92,20 @@ void computeHmacImpl(const ltc_hash_descriptor* desc,
int hashId;
} magic(desc);
+ Hmac_state hmacState;
unsigned long shaHashLen = sizeof(HashType);
+
fassert(40382,
- hmac_memory(magic.hashId, key, keyLen, input, inputLen, output->data(), &shaHashLen) ==
- CRYPT_OK);
+ hmac_init(&hmacState, magic.hashId, key, keyLen) == CRYPT_OK &&
+ std::all_of(begin(input),
+ end(input),
+ [&](const auto& i) {
+ return hmac_process(
+ &hmacState,
+ reinterpret_cast<const unsigned char*>(i.data()),
+ i.length()) == CRYPT_OK;
+ }) &&
+ hmac_done(&hmacState, output->data(), &shaHashLen) == CRYPT_OK);
}
} // namespace
@@ -109,20 +121,31 @@ SHA256BlockTraits::HashType SHA256BlockTraits::computeHash(
input);
}
+SHA512BlockTraits::HashType SHA512BlockTraits::computeHash(
+ std::initializer_list<ConstDataRange> input) {
+ return computeHashImpl<SHA512BlockTraits::HashType, sha512_init, sha512_process, sha512_done>(
+ input);
+}
+
void SHA1BlockTraits::computeHmac(const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ std::initializer_list<ConstDataRange> input,
HashType* const output) {
- return computeHmacImpl<HashType>(&sha1_desc, key, keyLen, input, inputLen, output);
+ return computeHmacImpl<HashType>(&sha1_desc, key, keyLen, input, output);
}
void SHA256BlockTraits::computeHmac(const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ std::initializer_list<ConstDataRange> input,
+ HashType* const output) {
+ return computeHmacImpl<HashType>(&sha256_desc, key, keyLen, input, output);
+}
+
+void SHA512BlockTraits::computeHmac(const uint8_t* key,
+ size_t keyLen,
+ std::initializer_list<ConstDataRange> input,
HashType* const output) {
- return computeHmacImpl<HashType>(&sha256_desc, key, keyLen, input, inputLen, output);
+ return computeHmacImpl<HashType>(&sha512_desc, key, keyLen, input, output);
}
} // namespace mongo
diff --git a/src/mongo/crypto/sha_block_windows.cpp b/src/mongo/crypto/sha_block_windows.cpp
index f4bdcb6857b..78ab4281c55 100644
--- a/src/mongo/crypto/sha_block_windows.cpp
+++ b/src/mongo/crypto/sha_block_windows.cpp
@@ -33,6 +33,7 @@
#include "mongo/crypto/sha1_block.h"
#include "mongo/crypto/sha256_block.h"
+#include "mongo/crypto/sha512_block.h"
#include "mongo/config.h"
#include "mongo/util/assert_util.h"
@@ -49,18 +50,26 @@ public:
BCryptHashLoader() {
loadAlgo(&_algoSHA1, BCRYPT_SHA1_ALGORITHM, false);
loadAlgo(&_algoSHA256, BCRYPT_SHA256_ALGORITHM, false);
+ loadAlgo(&_algoSHA512, BCRYPT_SHA512_ALGORITHM, false);
loadAlgo(&_algoSHA1Hmac, BCRYPT_SHA1_ALGORITHM, true);
loadAlgo(&_algoSHA256Hmac, BCRYPT_SHA256_ALGORITHM, true);
+ loadAlgo(&_algoSHA512Hmac, BCRYPT_SHA512_ALGORITHM, true);
}
~BCryptHashLoader() {
+ invariant(BCryptCloseAlgorithmProvider(_algoSHA512, 0) == STATUS_SUCCESS);
invariant(BCryptCloseAlgorithmProvider(_algoSHA256, 0) == STATUS_SUCCESS);
invariant(BCryptCloseAlgorithmProvider(_algoSHA1, 0) == STATUS_SUCCESS);
+ invariant(BCryptCloseAlgorithmProvider(_algoSHA512Hmac, 0) == STATUS_SUCCESS);
invariant(BCryptCloseAlgorithmProvider(_algoSHA256Hmac, 0) == STATUS_SUCCESS);
invariant(BCryptCloseAlgorithmProvider(_algoSHA1Hmac, 0) == STATUS_SUCCESS);
}
+ BCRYPT_ALG_HANDLE getAlgoSHA512() {
+ return _algoSHA512;
+ }
+
BCRYPT_ALG_HANDLE getAlgoSHA256() {
return _algoSHA256;
}
@@ -69,6 +78,10 @@ public:
return _algoSHA1;
}
+ BCRYPT_ALG_HANDLE getAlgoSHA512Hmac() {
+ return _algoSHA512Hmac;
+ };
+
BCRYPT_ALG_HANDLE getAlgoSHA256Hmac() {
return _algoSHA256Hmac;
};
@@ -86,8 +99,10 @@ private:
}
private:
+ BCRYPT_ALG_HANDLE _algoSHA512;
BCRYPT_ALG_HANDLE _algoSHA256;
BCRYPT_ALG_HANDLE _algoSHA1;
+ BCRYPT_ALG_HANDLE _algoSHA512Hmac;
BCRYPT_ALG_HANDLE _algoSHA256Hmac;
BCRYPT_ALG_HANDLE _algoSHA1Hmac;
};
@@ -133,10 +148,11 @@ template <typename HashType>
void computeHmacImpl(BCRYPT_ALG_HANDLE algo,
const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ std::initializer_list<ConstDataRange> input,
HashType* const output) {
- invariant(key && input);
+ invariant(key);
+ invariant(
+ std::all_of(begin(input), end(input), [&](const auto& i) { return i.data() != nullptr; }));
BCRYPT_HASH_HANDLE hHash;
@@ -144,7 +160,15 @@ void computeHmacImpl(BCRYPT_ALG_HANDLE algo,
BCryptCreateHash(algo, &hHash, NULL, 0, const_cast<PUCHAR>(key), keyLen, 0) ==
STATUS_SUCCESS &&
- BCryptHashData(hHash, const_cast<PUCHAR>(input), inputLen, 0) == STATUS_SUCCESS &&
+ std::all_of(begin(input),
+ end(input),
+ [&](const auto& i) {
+ return BCryptHashData(
+ hHash,
+ reinterpret_cast<PUCHAR>(const_cast<char*>(i.data())),
+ i.length(),
+ 0) == STATUS_SUCCESS;
+ }) &&
BCryptFinishHash(hHash, output->data(), output->size(), 0) == STATUS_SUCCESS &&
@@ -165,22 +189,34 @@ SHA256BlockTraits::HashType SHA256BlockTraits::computeHash(
std::move(input));
}
+SHA512BlockTraits::HashType SHA512BlockTraits::computeHash(
+ std::initializer_list<ConstDataRange> input) {
+ return computeHashImpl<SHA512BlockTraits::HashType>(getBCryptHashLoader().getAlgoSHA512(),
+ std::move(input));
+}
+
void SHA1BlockTraits::computeHmac(const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ std::initializer_list<ConstDataRange> input,
HashType* const output) {
return computeHmacImpl<HashType>(
- getBCryptHashLoader().getAlgoSHA1Hmac(), key, keyLen, input, inputLen, output);
+ getBCryptHashLoader().getAlgoSHA1Hmac(), key, keyLen, input, output);
}
void SHA256BlockTraits::computeHmac(const uint8_t* key,
size_t keyLen,
- const uint8_t* input,
- size_t inputLen,
+ std::initializer_list<ConstDataRange> input,
+ HashType* const output) {
+ return computeHmacImpl<HashType>(
+ getBCryptHashLoader().getAlgoSHA256Hmac(), key, keyLen, input, output);
+}
+
+void SHA512BlockTraits::computeHmac(const uint8_t* key,
+ size_t keyLen,
+ std::initializer_list<ConstDataRange> input,
HashType* const output) {
return computeHmacImpl<HashType>(
- getBCryptHashLoader().getAlgoSHA256Hmac(), key, keyLen, input, inputLen, output);
+ getBCryptHashLoader().getAlgoSHA512Hmac(), key, keyLen, input, output);
}
} // namespace mongo
diff --git a/src/third_party/scripts/tomcrypt_get_sources.sh b/src/third_party/scripts/tomcrypt_get_sources.sh
index b9acffa2c6f..775bdc48621 100644..100755
--- a/src/third_party/scripts/tomcrypt_get_sources.sh
+++ b/src/third_party/scripts/tomcrypt_get_sources.sh
@@ -43,6 +43,7 @@ FILES=(
hashes/helper/hash_memory.c
hashes/sha1.c
hashes/sha2/sha256.c
+ hashes/sha2/sha512.c
mac/hmac/hmac_done.c
mac/hmac/hmac_init.c
mac/hmac/hmac_memory.c
diff --git a/src/third_party/tomcrypt-1.18.2/SConscript b/src/third_party/tomcrypt-1.18.2/SConscript
index ac040bf3dea..e65a117983e 100644
--- a/src/third_party/tomcrypt-1.18.2/SConscript
+++ b/src/third_party/tomcrypt-1.18.2/SConscript
@@ -31,6 +31,7 @@ env.Library(
"src/hashes/helper/hash_memory.c",
"src/hashes/sha1.c",
"src/hashes/sha2/sha256.c",
+ "src/hashes/sha2/sha512.c",
"src/mac/hmac/hmac_done.c",
"src/mac/hmac/hmac_init.c",
"src/mac/hmac/hmac_memory.c",
diff --git a/src/third_party/tomcrypt-1.18.2/src/hashes/sha2/sha512.c b/src/third_party/tomcrypt-1.18.2/src/hashes/sha2/sha512.c
new file mode 100644
index 00000000000..c1c44c0bad6
--- /dev/null
+++ b/src/third_party/tomcrypt-1.18.2/src/hashes/sha2/sha512.c
@@ -0,0 +1,313 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ */
+#include "tomcrypt.h"
+
+/**
+ @param sha512.c
+ LTC_SHA512 by Tom St Denis
+*/
+
+#ifdef LTC_SHA512
+
+const struct ltc_hash_descriptor sha512_desc =
+{
+ "sha512",
+ 5,
+ 64,
+ 128,
+
+ /* OID */
+ { 2, 16, 840, 1, 101, 3, 4, 2, 3, },
+ 9,
+
+ &sha512_init,
+ &sha512_process,
+ &sha512_done,
+ &sha512_test,
+ NULL
+};
+
+/* the K array */
+static const ulong64 K[80] = {
+CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
+CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
+CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
+CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
+CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
+CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
+CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
+CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
+CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
+CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
+CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
+CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
+CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
+CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
+CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
+CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
+CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
+CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
+CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
+CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
+CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
+CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
+CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
+CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
+CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
+CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
+CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
+CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
+CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
+CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
+CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
+CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
+CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
+CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
+CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
+CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
+CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
+CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
+CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
+CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
+};
+
+/* Various logical functions */
+#define Ch(x,y,z) (z ^ (x & (y ^ z)))
+#define Maj(x,y,z) (((x | y) & z) | (x & y))
+#define S(x, n) ROR64c(x, n)
+#define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n))
+#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
+#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
+#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
+#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
+
+/* compress 1024-bits */
+#ifdef LTC_CLEAN_STACK
+static int _sha512_compress(hash_state * md, unsigned char *buf)
+#else
+static int sha512_compress(hash_state * md, unsigned char *buf)
+#endif
+{
+ ulong64 S[8], W[80], t0, t1;
+ int i;
+
+ /* copy state into S */
+ for (i = 0; i < 8; i++) {
+ S[i] = md->sha512.state[i];
+ }
+
+ /* copy the state into 1024-bits into W[0..15] */
+ for (i = 0; i < 16; i++) {
+ LOAD64H(W[i], buf + (8*i));
+ }
+
+ /* fill W[16..79] */
+ for (i = 16; i < 80; i++) {
+ W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
+ }
+
+ /* Compress */
+#ifdef LTC_SMALL_CODE
+ for (i = 0; i < 80; i++) {
+ t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];
+ t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);
+ S[7] = S[6];
+ S[6] = S[5];
+ S[5] = S[4];
+ S[4] = S[3] + t0;
+ S[3] = S[2];
+ S[2] = S[1];
+ S[1] = S[0];
+ S[0] = t0 + t1;
+ }
+#else
+#define RND(a,b,c,d,e,f,g,h,i) \
+ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+ t1 = Sigma0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+ for (i = 0; i < 80; i += 8) {
+ RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
+ RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
+ RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
+ RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
+ RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
+ RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
+ RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
+ RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
+ }
+#endif
+
+
+ /* feedback */
+ for (i = 0; i < 8; i++) {
+ md->sha512.state[i] = md->sha512.state[i] + S[i];
+ }
+
+ return CRYPT_OK;
+}
+
+/* compress 1024-bits */
+#ifdef LTC_CLEAN_STACK
+static int sha512_compress(hash_state * md, unsigned char *buf)
+{
+ int err;
+ err = _sha512_compress(md, buf);
+ burn_stack(sizeof(ulong64) * 90 + sizeof(int));
+ return err;
+}
+#endif
+
+/**
+ Initialize the hash state
+ @param md The hash state you wish to initialize
+ @return CRYPT_OK if successful
+*/
+int sha512_init(hash_state * md)
+{
+ LTC_ARGCHK(md != NULL);
+ md->sha512.curlen = 0;
+ md->sha512.length = 0;
+ md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
+ md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);
+ md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);
+ md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);
+ md->sha512.state[4] = CONST64(0x510e527fade682d1);
+ md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
+ md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
+ md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
+ return CRYPT_OK;
+}
+
+/**
+ Process a block of memory though the hash
+ @param md The hash state
+ @param in The data to hash
+ @param inlen The length of the data (octets)
+ @return CRYPT_OK if successful
+*/
+HASH_PROCESS(sha512_process, sha512_compress, sha512, 128)
+
+/**
+ Terminate the hash to get the digest
+ @param md The hash state
+ @param out [out] The destination of the hash (64 bytes)
+ @return CRYPT_OK if successful
+*/
+int sha512_done(hash_state * md, unsigned char *out)
+{
+ int i;
+
+ LTC_ARGCHK(md != NULL);
+ LTC_ARGCHK(out != NULL);
+
+ if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ /* increase the length of the message */
+ md->sha512.length += md->sha512.curlen * CONST64(8);
+
+ /* append the '1' bit */
+ md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80;
+
+ /* if the length is currently above 112 bytes we append zeros
+ * then compress. Then we can fall back to padding zeros and length
+ * encoding like normal.
+ */
+ if (md->sha512.curlen > 112) {
+ while (md->sha512.curlen < 128) {
+ md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
+ }
+ sha512_compress(md, md->sha512.buf);
+ md->sha512.curlen = 0;
+ }
+
+ /* pad upto 120 bytes of zeroes
+ * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash
+ * > 2^64 bits of data... :-)
+ */
+ while (md->sha512.curlen < 120) {
+ md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
+ }
+
+ /* store length */
+ STORE64H(md->sha512.length, md->sha512.buf+120);
+ sha512_compress(md, md->sha512.buf);
+
+ /* copy output */
+ for (i = 0; i < 8; i++) {
+ STORE64H(md->sha512.state[i], out+(8*i));
+ }
+#ifdef LTC_CLEAN_STACK
+ zeromem(md, sizeof(hash_state));
+#endif
+ return CRYPT_OK;
+}
+
+/**
+ Self-test the hash
+ @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int sha512_test(void)
+{
+ #ifndef LTC_TEST
+ return CRYPT_NOP;
+ #else
+ static const struct {
+ const char *msg;
+ unsigned char hash[64];
+ } tests[] = {
+ { "abc",
+ { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
+ 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+ 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
+ 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
+ 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
+ 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
+ 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
+ 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
+ },
+ { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
+ 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
+ 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
+ 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
+ 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
+ 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
+ 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
+ 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
+ },
+ };
+
+ int i;
+ unsigned char tmp[64];
+ hash_state md;
+
+ for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
+ sha512_init(&md);
+ sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
+ sha512_done(&md, tmp);
+ if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512", i)) {
+ return CRYPT_FAIL_TESTVECTOR;
+ }
+ }
+ return CRYPT_OK;
+ #endif
+}
+
+#endif
+
+
+
+
+/* ref: HEAD -> master, tag: v1.18.2 */
+/* git commit: 7e7eb695d581782f04b24dc444cbfde86af59853 */
+/* commit time: 2018-07-01 22:49:01 +0200 */