diff --git a/builds/install/misc/firebird.conf.in b/builds/install/misc/firebird.conf.in
index 248c9480ef..d117bc5e0a 100644
--- a/builds/install/misc/firebird.conf.in
+++ b/builds/install/misc/firebird.conf.in
@@ -422,13 +422,19 @@
#
# Type: string
-# AuthServer and AuthClient determine what authentication methods will be used
-# by network server and client redirector. Secure remote passwords plugin
-# is default one. Except configured by default SRP plugin firebird also has
-# Legacy_Auth plugin which is used to emulate pre-FB3 login protocol making it
-# possible for client to talk to old servers and for server to listen to requests
-# from old clients. Legacy_Auth is VERY unsecure. On windows Win_Sspi plugin may
-# be also used - it implements windows trusted authentication and backward
+# AuthServer and AuthClient determine which authentication methods will be used
+# by network server and client redirector. The Secure remote password plugin
+# using SHA-256 for the client proof is the default for both client and Server.
+# Additionally, the default client configuration (AuthClient) also supports old Srp
+# plugin using SHA-1 for the client proof. This enables backwards compatibility
+# with old Firebird 3 servers but does not comply with NIST security requirements.
+#
+# The default client configuration (AuthClient) also supports the pre-Firebird 3 legacy
+# authentication protocol (Legacy_Auth). This is again for backwards
+# compatibility but has many known weaknesses and is deprecated for current use.
+#
+# The default Windows client configuration (AuthClient) also includes support for
+# the Win_Sspi plugin. This implements windows trusted authentication and is backward
# compatible with 2.1 and 2.5 clients and servers running on windows.
#
# Per-database configurable.
@@ -437,7 +443,8 @@
#
# Per-connection and per-database configurable.
#
-#AuthClient = Srp, Win_Sspi, Legacy_Auth
+#AuthClient = Srp, Srp256, Legacy_Auth #Non Windows clients
+#AuthClient = Srp, Srp256, Win_Sspi, Legacy_Auth #Windows clients
#
# If you need to use server plugins that do not provide encryption key (both Legacy_Auth
# & Win_Sspi) you should also turn off required encryption on the wire with WireCrypt
diff --git a/builds/posix/make.shared.variables b/builds/posix/make.shared.variables
index df3982913e..e04c53f2bf 100644
--- a/builds/posix/make.shared.variables
+++ b/builds/posix/make.shared.variables
@@ -27,7 +27,7 @@ AllObjects=
CO1:= $(call dirObjects,common)
CO2:= $(call dirObjects,common/classes)
CO3:= $(call dirObjects,common/config)
-CO4:= $(call dirObjects,common/tomcrypt)
+CO4:= $(call dirObjects,common/sha2)
#CO5:= $(call dirObjects,common/exceptions)
#CO6:= $(call dirObjects,common/sync)
Common_Objects:= $(CO1) $(CO2) $(CO3) $(CO4)
diff --git a/doc/README.SecureRemotePassword.html b/doc/README.SecureRemotePassword.html
new file mode 100644
index 0000000000..5f03793514
--- /dev/null
+++ b/doc/README.SecureRemotePassword.html
@@ -0,0 +1,204 @@
+
+
+
+
+ - no title specified
+
+
+
+
+
+
+
+
+
+
+
+
+
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+Replacement of use of SHA-1 in the SRP Client Proof with a SHA-2
+Message Digest
+The Firebird implementation of the Secure Remote
+Protocol (SRP) for password based user authentication has been
+updated following a security review of the original Firebird SRP-6a
+implementation taking into account current NIST guidance on the use
+of SHA-1 – see NIST Special Publication 800-131A, Revision 1,
+Transitions: Recommendation for Transitioning the Use of
+Cryptographic Algorithms and Key Lengths
+(http://dx.doi.org/10.6028/NIST.SP.800-131Ar1)
+chapter 9. This guidance disallows the general use of SHA-1 for
+“Digital Signature Generation” whilst permitting continued use
+for “Digital Signature Verification”. The background to making
+this change is given below.
+By default, the SHA-256 message digest is now used
+instead of SHA-1 for generating the Client Proof. Alternatively,
+SHA-1 (deprecated and for legacy use only) may be used for the Client
+Proof. Separate AuthServer and AuthClient plugins are available for
+each supported message digest, with the following names:
+
+
+
+
+
+
+ |
+
+ SHA-1 Client Proof
+ |
+
+
+
+
+ |
+
+ SHA-256 Client Proof
+ |
+
+
+Both client and server must have an SRP authentication
+plugin in common in order to enable successfully authentication of a
+user's password.
+
+There is no change to the SRP User Manager. This is
+still called (“Srp”) and the User Manager and the security
+database are not affected by the choice of message digest used to
+compute the client proof.
+The “firebird.conf” default configuration file
+entries for AuthServer and AuthClient are now:
+AuthServer = Srp256
+AuthClient = Srp256, Srp,
+Legacy_Auth (Non -windows clients)
+AuthClient = Srp256, Srp,
+Win_Sspi, Legacy_Auth (windows clients)
+With these settings, a Firebird Server is using Srp256
+to authenticate a client using SHA-256 to compute the client proof
+and is thus compatible with Firebird 3.0.4 or newer clients. On the
+other hand, a Firebird client will authenticate the user with any
+server version down to at least 2.5.
+A deployment where both client and servers support the
+legacy Srp (using SHA-1) and one or more of the SHA-2 authentication
+plugins (e.g. Srp256) should be avoided. This is because an attacker
+might be able to disrupt the Srp256 authentication thereby forcing
+Firebird to use the weaker Srp SHA-1 client proof without the user
+being aware.
+REASON FOR
+CHANGE
+Review of the Firebird SRP implementation appears to
+indicate that most uses of SHA-1 continue to be permitted under NIST
+guidance except for its use in generating the client proof. The SRP
+client proof may be characterised as a “Poor Man's Digital
+Signature” in that it provides a two party proof of identity rather
+than the third party proof normally expected from a Digital Signature
+i.e. it is not a non-repudiable proof. Nevertheless, it is believed
+that generation of the client proof falls under the heading of
+“Digital Signature Generation” when considering the NIST
+Guidance.
+Continued use of SHA-1 in order to generate the client
+proof appears to risk leakage of the encryption key used to encrypt
+“over-the-wire” encryption and which hence also provides peer
+entity authentication during the lifetime of the connection. This may
+result in an attacker being able to monitor confidential
+communication either during the connection or at some later date and
+this could include leakage of an encryption key used to encrypt the
+user database, if this is passed from client to server during the
+connection.
+Such an attack is viable if weaknesses in SHA-1 can be
+exploited to allow a brute force attack on the client proof to be
+computationally feasible. All parts of the message on which the
+client proof is based may be known to an attacker with the exception
+of the shared session key and such an attack would concentrate on
+revealing this key. If it were possible to reveal the shared session
+key in real time then additionally a man-in-the-middle attack would
+be feasible.
+The severity of this issue is viewed as Important but
+not Critical. Users that rely on SRP (using SHA-1)/over the wire
+encryption to protect confidential communication have a long term
+risk that the confidentiality of their data may be compromised.
+The attack may also be mitigated through the use of other procedures
+to protect communications (e.g. a secure VPN).
+The update adds a new directory to the source code tree
+(src/common/sha2) containing an implementation of the SHA-2 family of
+message digests derived from the implementation published by Olivier
+Gay <olivier.gay@a3.epfl.ch>
+(see https://github.com/ouah/sha2). The following copyright notice is
+included at the request of the original author and applies to the
+files in src/common/sha2:
+FIPS 180-2
+SHA-224/256/384/512 implementation
+Last update: 02/02/2007
+Issue date: 04/30/2005
+https://github.com/ouah/sha2
+
+Copyright (C) 2005, 2007
+Olivier Gay <olivier.gay@a3.epfl.ch>
+All rights reserved.
+
+Redistribution and use in
+source and binary forms, with or without
+modification, are
+permitted provided that the following conditions
+are met:
+1. Redistributions of
+source code must retain the above copyright
+ notice, this
+list of conditions and the following disclaimer.
+2. Redistributions in
+binary form must reproduce the above copyright
+ notice, this
+list of conditions and the following disclaimer in the
+ documentation
+and/or other materials provided with the distribution.
+3. Neither the name of
+the project nor the names of its contributors
+ may be used
+to endorse or promote products derived from this software
+ without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED
+BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN
+NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+
\ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d09f102a5b..417cbdb321 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -364,7 +364,7 @@ add_library (burp ${burp_src} ${burp_generated_src_master})
# LIBRARY common
########################################
-file(GLOB common_src "common/*.cpp" "common/classes/*.cpp" "common/config/*.cpp" "common/os/${OS_DIR}/*.cpp")
+file(GLOB common_src "common/*.cpp" "common/classes/*.cpp" "common/config/*.cpp" "common/os/${OS_DIR}/*.cpp" "common/sha2/*.cpp")
file(GLOB_RECURSE common_include "common/*.h")
if (APPLE)
diff --git a/src/auth/SecureRemotePassword/client/SrpClient.cpp b/src/auth/SecureRemotePassword/client/SrpClient.cpp
index 4752f8cd28..d206a0f7c5 100644
--- a/src/auth/SecureRemotePassword/client/SrpClient.cpp
+++ b/src/auth/SecureRemotePassword/client/SrpClient.cpp
@@ -34,7 +34,7 @@ using namespace Firebird;
namespace Auth {
-class SrpClient FB_FINAL : public StdPlugin >
+class SrpClient : public StdPlugin >
{
public:
explicit SrpClient(IPluginConfig*)
@@ -55,6 +55,20 @@ private:
RemotePassword* client;
string data;
UCharBuffer sessionKey;
+protected:
+ virtual RemotePassword* RemotePasswordFactory()=0;
+};
+
+template class SrpClientImpl FB_FINAL : public SrpClient
+{
+public:
+ explicit SrpClientImpl(IPluginConfig* ipc)
+ : SrpClient(ipc) {}
+protected:
+ RemotePassword* RemotePasswordFactory()
+ {
+ return FB_NEW RemotePasswordImpl;
+ }
};
int SrpClient::authenticate(CheckStatusWrapper* status, IClientBlock* cb)
@@ -76,7 +90,7 @@ int SrpClient::authenticate(CheckStatusWrapper* status, IClientBlock* cb)
return AUTH_CONTINUE;
}
- client = FB_NEW RemotePassword;
+ client = RemotePasswordFactory();
client->genClientKey(data);
dumpIt("Clnt: clientPubKey", data);
cb->putData(status, data.length(), data.begin());
@@ -130,7 +144,7 @@ int SrpClient::authenticate(CheckStatusWrapper* status, IClientBlock* cb)
BigInteger cProof = client->clientProof(cb->getLogin(), salt.c_str(), sessionKey);
cProof.getText(data);
-
+ dumpIt("Clnt: Client Proof",cProof);
cb->putData(status, data.length(), data.c_str());
if (status->getState() & IStatus::STATE_ERRORS)
{
@@ -170,12 +184,20 @@ int SrpClient::release()
namespace
{
- SimpleFactory factory;
+ SimpleFactory > factory_sha1;
+ SimpleFactory > factory_sha224;
+ SimpleFactory > factory_sha256;
+ SimpleFactory > factory_sha384;
+ SimpleFactory > factory_sha512;
}
void registerSrpClient(IPluginManager* iPlugin)
{
- iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::plugName, &factory);
+ iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::plugName, &factory_sha1);
+ iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::pluginName(224).c_str(), &factory_sha224);
+ iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::pluginName(256).c_str(), &factory_sha256);
+ iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::pluginName(384).c_str(), &factory_sha384);
+ iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::pluginName(512).c_str(), &factory_sha512);
}
} // namespace Auth
diff --git a/src/auth/SecureRemotePassword/manage/SrpManagement.cpp b/src/auth/SecureRemotePassword/manage/SrpManagement.cpp
index ae1fac37e4..9c6774f867 100644
--- a/src/auth/SecureRemotePassword/manage/SrpManagement.cpp
+++ b/src/auth/SecureRemotePassword/manage/SrpManagement.cpp
@@ -688,7 +688,7 @@ private:
Firebird::RefPtr config;
Firebird::RefPtr att;
Firebird::RefPtr tra;
- RemotePassword server;
+ RemotePasswordImpl server;
int upCount, delCount;
bool checkCount(Firebird::CheckStatusWrapper* status, int* count, UCHAR item)
diff --git a/src/auth/SecureRemotePassword/misc/test.sh b/src/auth/SecureRemotePassword/misc/test.sh
index 40fb2f7a67..5429ee7bfa 100755
--- a/src/auth/SecureRemotePassword/misc/test.sh
+++ b/src/auth/SecureRemotePassword/misc/test.sh
@@ -4,9 +4,8 @@ compile()
file=test_${1}
g++ -I../../../include -DLINUX -DAMD64 -DDEV_BUILD ${file}.cpp \
../../../../temp/Debug/auth/SecureRemotePassword/srp.o \
- ../../../../temp/Debug/auth/SecureRemotePassword/BigInteger.o \
../../../../temp/Debug/common.a -ltommath ../../../../gen/Debug/firebird/lib/libfbclient.so \
- -Wl,-rpath,../../../../gen/Debug/firebird/lib -lrt -o ${file} && ./${file}
+ -lpthread -Wl,-rpath,../../../../gen/Debug/firebird/lib -lrt -o ${file} && ./${file}
}
compile srp
diff --git a/src/auth/SecureRemotePassword/misc/test_srp.cpp b/src/auth/SecureRemotePassword/misc/test_srp.cpp
index 763d18c732..6247f508ff 100644
--- a/src/auth/SecureRemotePassword/misc/test_srp.cpp
+++ b/src/auth/SecureRemotePassword/misc/test_srp.cpp
@@ -2,19 +2,19 @@
using namespace Auth;
-int main(int argc, char** argv)
+templatevoid runTest(int argc, char** argv)
{
Firebird::string salt;
#if SRP_DEBUG > 1
- BigInteger s("02E268803000000079A478A700000002D1A6979000000026E1601C000000054F");
+ Firebird::BigInteger s("02E268803000000079A478A700000002D1A6979000000026E1601C000000054F");
#else
- BigInteger s;
+ Firebird::BigInteger s;
s.random(128);
#endif
s.getText(salt);
- RemotePassword* server = FB_NEW RemotePassword();
- RemotePassword* client = FB_NEW RemotePassword();
+ RemotePassword* server = FB_NEW RemotePasswordImpl();
+ RemotePassword* client = FB_NEW RemotePasswordImpl();
const char* account = "SYSDBA";
const char* password = "masterkey";
@@ -37,8 +37,20 @@ int main(int argc, char** argv)
client->clientSessionKey(key1, account, salt.c_str(), argc > 1 ? argv[1] : password, serverPubKey.c_str());
server->serverSessionKey(key2, clientPubKey.c_str(), verifier);
- BigInteger cProof = client->clientProof(account, salt.c_str(), key1);
- BigInteger sProof = server->clientProof(account, salt.c_str(), key2);
+ Firebird::BigInteger cProof = client->clientProof(account, salt.c_str(), key1);
+ Firebird::BigInteger sProof = server->clientProof(account, salt.c_str(), key2);
+ printf("Proof length = %d\n",cProof.length());
printf("%s\n", cProof == sProof ? "OK" : "differ");
+
}
+
+int main(int argc, char** argv)
+{
+ runTest(argc,argv);
+ runTest(argc,argv);
+ runTest(argc,argv);
+ runTest(argc,argv);
+ runTest(argc,argv);
+}
+
diff --git a/src/auth/SecureRemotePassword/server/SrpServer.cpp b/src/auth/SecureRemotePassword/server/SrpServer.cpp
index 7a2f53a712..9e2cb7f7e4 100644
--- a/src/auth/SecureRemotePassword/server/SrpServer.cpp
+++ b/src/auth/SecureRemotePassword/server/SrpServer.cpp
@@ -48,7 +48,7 @@ const unsigned int SZ_LOGIN = 31;
namespace Auth {
-class SrpServer FB_FINAL : public StdPlugin >
+class SrpServer : public StdPlugin >
{
public:
explicit SrpServer(IPluginConfig* par)
@@ -68,12 +68,12 @@ public:
void setDbCryptCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback);
int release();
-private:
~SrpServer()
{
delete server;
}
+private:
RemotePassword* server;
string data;
string account;
@@ -84,6 +84,20 @@ private:
RefPtr config;
const char* secDbName;
ICryptKeyCallback* cryptCallback;
+protected:
+ virtual RemotePassword* RemotePasswordFactory()=0;
+};
+
+template class SrpServerImpl FB_FINAL : public SrpServer
+{
+public:
+ explicit SrpServerImpl(IPluginConfig* ipc)
+ : SrpServer(ipc) {}
+protected:
+ RemotePassword* RemotePasswordFactory()
+ {
+ return FB_NEW RemotePasswordImpl;
+ }
};
int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWriter* writerInterface)
@@ -215,7 +229,7 @@ int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWrite
throw;
}
- server = FB_NEW RemotePassword;
+ server = RemotePasswordFactory();
server->genServerKey(serverPubKey, verifier);
// Ready to prepare data for client and calculate session key
@@ -248,6 +262,9 @@ int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWrite
proof.assign(val, length);
BigInteger clientProof(proof.c_str());
BigInteger serverProof = server->clientProof(account.c_str(), salt.c_str(), sessionKey);
+ HANDSHAKE_DEBUG(fprintf(stderr, "Client Proof Received, Length = %d\n", clientProof.length()));
+ dumpIt("Srv: Client Proof",clientProof);
+ dumpIt("Srv: Server Proof",serverProof);
if (clientProof == serverProof)
{
// put the record into authentication block
@@ -311,12 +328,20 @@ int SrpServer::release()
namespace
{
- SimpleFactory factory;
+ SimpleFactory > factory_sha1;
+ SimpleFactory > factory_sha224;
+ SimpleFactory > factory_sha256;
+ SimpleFactory > factory_sha384;
+ SimpleFactory > factory_sha512;
}
void registerSrpServer(IPluginManager* iPlugin)
{
- iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::plugName, &factory);
+ iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::plugName, &factory_sha1);
+ iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::pluginName(224).c_str(), &factory_sha224);
+ iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::pluginName(256).c_str(), &factory_sha256);
+ iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::pluginName(384).c_str(), &factory_sha384);
+ iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::pluginName(512).c_str(), &factory_sha512);
}
} // namespace Auth
diff --git a/src/auth/SecureRemotePassword/srp.cpp b/src/auth/SecureRemotePassword/srp.cpp
index c4057bce8e..96f76251d6 100644
--- a/src/auth/SecureRemotePassword/srp.cpp
+++ b/src/auth/SecureRemotePassword/srp.cpp
@@ -29,7 +29,7 @@ public:
explicit RemoteGroup(Firebird::MemoryPool&)
: prime(primeStr), generator(genStr), k()
{
- Auth::Sha1 hash;
+ Auth::SecureHash hash;
hash.processInt(prime);
if (prime.length() > generator.length())
@@ -59,6 +59,13 @@ InitInstance RemoteGroup::group;
const char* RemotePassword::plugName = "Srp";
+string RemotePassword::pluginName(unsigned bits)
+{
+ string plg;
+ plg.printf("%s%u", plugName, bits);
+ return plg;
+}
+
RemotePassword::RemotePassword()
: group(RemoteGroup::getGroup())
{
@@ -187,18 +194,7 @@ BigInteger RemotePassword::clientProof(const char* account, const char* salt, co
hash.reset();
hash.process(account);
hash.getInt(n2);
-
- hash.reset();
- hash.processInt(n1); // H(prime) ^ H(g)
- hash.processInt(n2); // H(I)
- hash.process(salt); // s
- hash.processInt(clientPublicKey); // A
- hash.processInt(serverPublicKey); // B
- hash.process(sessionKey); // K
-
- BigInteger rc;
- hash.getInt(rc);
- return rc;
+ return MakeProof(n1,n2,salt,sessionKey);
}
#if SRP_DEBUG > 0
diff --git a/src/auth/SecureRemotePassword/srp.h b/src/auth/SecureRemotePassword/srp.h
index b84e9e7b49..4db87c810b 100644
--- a/src/auth/SecureRemotePassword/srp.h
+++ b/src/auth/SecureRemotePassword/srp.h
@@ -2,6 +2,7 @@
#include "../common/classes/alloc.h"
#include "../common/classes/fb_string.h"
#include "../common/sha.h"
+#include "../common/sha2/sha2.h"
#define SRP_DEBUG 0 // >0 - prints some debug info
// >1 - uses consts instead randoms, NEVER use in PRODUCTION!
@@ -46,13 +47,13 @@ namespace Auth {
class RemoteGroup;
-class Sha1 : public Firebird::Sha1
+template class SecureHash : public SHA
{
public:
void getInt(Firebird::BigInteger& hash)
{
Firebird::UCharBuffer tmp;
- getHash(tmp);
+ SHA::getHash(tmp);
hash.assign(tmp.getCount(), tmp.begin());
}
@@ -60,7 +61,7 @@ public:
{
Firebird::UCharBuffer bytes;
data.getBytes(bytes);
- process(bytes);
+ SHA::process(bytes);
}
void processStrippedInt(const Firebird::BigInteger& data)
@@ -70,19 +71,24 @@ public:
if (bytes.getCount())
{
unsigned int n = (bytes[0] == 0) ? 1u : 0;
- process(bytes.getCount() - n, bytes.begin() + n);
+ SHA::process(bytes.getCount() - n, bytes.begin() + n);
}
}
};
+
class RemotePassword : public Firebird::GlobalStorage
{
private:
const RemoteGroup* group;
- Auth::Sha1 hash;
+ Auth::SecureHash hash;
Firebird::BigInteger privateKey;
Firebird::BigInteger scramble;
+protected:
+ virtual Firebird::BigInteger MakeProof(const Firebird::BigInteger n1, const Firebird::BigInteger n2,
+ const char* salt, const Firebird::UCharBuffer& sessionKey) = 0;
+
public:
Firebird::BigInteger clientPublicKey;
Firebird::BigInteger serverPublicKey;
@@ -95,6 +101,8 @@ public:
static const unsigned SRP_VERIFIER_SIZE = SRP_KEY_SIZE;
static const unsigned SRP_SALT_SIZE = 32;
+ static Firebird::string pluginName(unsigned bits);
+
Firebird::BigInteger getUserHash(const char* account,
const char* salt,
const char* password);
@@ -115,6 +123,27 @@ public:
const Firebird::UCharBuffer& sessionKey);
};
+template class RemotePasswordImpl : public RemotePassword
+{
+protected:
+ Firebird::BigInteger MakeProof(const Firebird::BigInteger n1, const Firebird::BigInteger n2,
+ const char* salt, const Firebird::UCharBuffer& sessionKey)
+ {
+ Auth::SecureHash digest;
+ digest.processInt(n1); // H(prime) ^ H(g)
+ digest.processInt(n2); // H(I)
+ digest.process(salt); // s
+ digest.processInt(clientPublicKey); // A
+ digest.processInt(serverPublicKey); // B
+ digest.process(sessionKey); // K
+
+ Firebird::BigInteger rc;
+ digest.getInt(rc);
+ return rc;
+ }
+};
+
+
#if SRP_DEBUG > 0
void dumpIt(const char* name, const Firebird::BigInteger& bi);
diff --git a/src/common/config/config.cpp b/src/common/config/config.cpp
index 1047cf79c6..535bcf0d8e 100644
--- a/src/common/config/config.cpp
+++ b/src/common/config/config.cpp
@@ -181,11 +181,11 @@ const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
{TYPE_INTEGER, "MaxUserTraceLogSize", (ConfigValue) 10}, // maximum size of user session trace log
{TYPE_INTEGER, "FileSystemCacheSize", (ConfigValue) 0}, // percent
{TYPE_STRING, "Providers", (ConfigValue) "Remote, " CURRENT_ENGINE ", Loopback"},
- {TYPE_STRING, "AuthServer", (ConfigValue) "Srp"},
+ {TYPE_STRING, "AuthServer", (ConfigValue) "Srp256"},
#ifdef WIN_NT
- {TYPE_STRING, "AuthClient", (ConfigValue) "Srp, Win_Sspi, Legacy_Auth"},
+ {TYPE_STRING, "AuthClient", (ConfigValue) "Srp256, Srp, Win_Sspi, Legacy_Auth"},
#else
- {TYPE_STRING, "AuthClient", (ConfigValue) "Srp, Legacy_Auth"},
+ {TYPE_STRING, "AuthClient", (ConfigValue) "Srp256, Srp, Legacy_Auth"},
#endif
{TYPE_STRING, "UserManager", (ConfigValue) "Srp"},
{TYPE_STRING, "TracePlugin", (ConfigValue) "fbtrace"},
diff --git a/src/common/sha2/ChangeLog b/src/common/sha2/ChangeLog
new file mode 100644
index 0000000000..bea33e8ba0
--- /dev/null
+++ b/src/common/sha2/ChangeLog
@@ -0,0 +1,17 @@
+2007-02-02 Olivier Gay
+
+ * sha2.c (sha512_transf) [UNROLL_LOOPS]: Group together SHA512_EXP calls
+ in a loop to optimize speed in SHA-384 and SHA-512.
+
+ * sha2.h, sha2.c: Remove HAVE_STDINT and use new typedef for fixed-width
+ integer types.
+
+2007-02-02 Tad
+
+ * sha2.c (sha224_update, sha256_update, sha384_update, sha512_update): Check
+ the read size is within the buffer limits when updating small data.
+
+2005-05-23 Olivier Gay
+
+ * sha2.h, sha2.c: Support of SHA-224 functions.
+
diff --git a/src/common/sha2/sha2.cpp b/src/common/sha2/sha2.cpp
new file mode 100644
index 0000000000..cef82584d0
--- /dev/null
+++ b/src/common/sha2/sha2.cpp
@@ -0,0 +1,954 @@
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ * https://github.com/ouah/sha2
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Updated for use in Firebird by Tony Whyman
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#define UNROLL_LOOPS /* Enable loops unrolling */
+#endif
+
+#include "sha2.h"
+
+#define SHFR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z) ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
+#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
+
+#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
+#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
+#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
+#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
+
+#define UNPACK32(x, str) \
+{ \
+ *((str) + 3) = (uint8) ((x) ); \
+ *((str) + 2) = (uint8) ((x) >> 8); \
+ *((str) + 1) = (uint8) ((x) >> 16); \
+ *((str) + 0) = (uint8) ((x) >> 24); \
+}
+
+#define PACK32(str, x) \
+{ \
+ *(x) = ((uint32) *((str) + 3) ) \
+ | ((uint32) *((str) + 2) << 8) \
+ | ((uint32) *((str) + 1) << 16) \
+ | ((uint32) *((str) + 0) << 24); \
+}
+
+#define UNPACK64(x, str) \
+{ \
+ *((str) + 7) = (uint8) ((x) ); \
+ *((str) + 6) = (uint8) ((x) >> 8); \
+ *((str) + 5) = (uint8) ((x) >> 16); \
+ *((str) + 4) = (uint8) ((x) >> 24); \
+ *((str) + 3) = (uint8) ((x) >> 32); \
+ *((str) + 2) = (uint8) ((x) >> 40); \
+ *((str) + 1) = (uint8) ((x) >> 48); \
+ *((str) + 0) = (uint8) ((x) >> 56); \
+}
+
+#define PACK64(str, x) \
+{ \
+ *(x) = ((uint64) *((str) + 7) ) \
+ | ((uint64) *((str) + 6) << 8) \
+ | ((uint64) *((str) + 5) << 16) \
+ | ((uint64) *((str) + 4) << 24) \
+ | ((uint64) *((str) + 3) << 32) \
+ | ((uint64) *((str) + 2) << 40) \
+ | ((uint64) *((str) + 1) << 48) \
+ | ((uint64) *((str) + 0) << 56); \
+}
+
+/* Macros used for loops unrolling */
+
+#define SHA256_SCR(i) \
+{ \
+ w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
+ + SHA256_F3(w[i - 15]) + w[i - 16]; \
+}
+
+#define SHA512_SCR(i) \
+{ \
+ w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \
+ + SHA512_F3(w[i - 15]) + w[i - 16]; \
+}
+
+#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
+{ \
+ t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
+ + sha256_k[j] + w[j]; \
+ t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+}
+
+#define SHA512_EXP(a, b, c, d, e, f, g ,h, j) \
+{ \
+ t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
+ + sha512_k[j] + w[j]; \
+ t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+}
+
+namespace Firebird {
+
+
+sha2_base::uint32 sha224_h0[8] =
+ {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
+ 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
+
+sha2_base::uint32 sha256_h0[8] =
+ {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
+
+sha2_base::uint64 sha384_h0[8] =
+ {0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL,
+ 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
+ 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
+ 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL};
+
+sha2_base::uint64 sha512_h0[8] =
+ {0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL};
+
+sha2_base::uint32 sha256_k[64] =
+ {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
+
+sha2_base::uint64 sha512_k[80] =
+ {0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
+
+/* sha2_base */
+
+void sha2_base::getHash(unsigned char *digest)
+{
+ sha_final(digest);
+ reset();
+};
+
+#ifndef NIST_COMPLIANCY_TESTS
+void sha2_base::getHash(UCharBuffer& h)
+{
+ sha_final(h.getBuffer(get_DigestSize()));
+ reset();
+};
+#endif
+
+
+/* SHA-256 functions */
+
+sha256::sha256() : sha2_base()
+{
+ sha256_init(&ctx);
+}
+
+void sha256::sha256_transf(sha256_ctx * ctx, const unsigned char *message,
+ unsigned int block_nb)
+{
+ uint32 w[64];
+ uint32 wv[8];
+ uint32 t1, t2;
+ const unsigned char *sub_block;
+ int i;
+
+#ifndef UNROLL_LOOPS
+ int j;
+#endif
+
+ for (i = 0; i < (int) block_nb; i++) {
+ sub_block = message + (i << 6);
+
+#ifndef UNROLL_LOOPS
+ for (j = 0; j < 16; j++) {
+ PACK32(&sub_block[j << 2], &w[j]);
+ }
+
+ for (j = 16; j < 64; j++) {
+ SHA256_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 64; j++) {
+ t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+ + sha256_k[j] + w[j];
+ t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++) {
+ ctx->h[j] += wv[j];
+ }
+#else
+ PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
+ PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
+ PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
+ PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
+ PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
+ PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
+ PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
+ PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
+
+ SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
+ SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
+ SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
+ SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
+ SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
+ SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
+ SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
+ SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
+ SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
+ SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
+ SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
+ SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
+
+ wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
+
+ SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
+ SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
+ SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
+ SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
+ SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
+ SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
+ SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
+ SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
+ SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
+ SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
+ SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
+ SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
+ SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
+ SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
+ SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
+ SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
+ SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
+ SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
+ SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
+ SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
+ SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
+ SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
+ SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
+ SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
+ SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
+ SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
+ SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
+ SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
+ SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
+ SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
+ SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
+ SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
+
+ ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+ }
+}
+
+void sha256::sha256_init(sha256_ctx * ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha256_h0[i];
+ }
+#else
+ ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
+ ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
+ ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
+ ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha256::sha256_update(sha256_ctx * ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA256_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA256_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA256_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha256_transf(ctx, ctx->block, 1);
+ sha256_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA256_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 6],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+void sha256::sha256_final(sha256_ctx * ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
+ < (ctx->len % SHA256_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 6;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha256_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 8; i++) {
+ UNPACK32(ctx->h[i], &digest[i << 2]);
+ }
+#else
+ UNPACK32(ctx->h[0], &digest[ 0]);
+ UNPACK32(ctx->h[1], &digest[ 4]);
+ UNPACK32(ctx->h[2], &digest[ 8]);
+ UNPACK32(ctx->h[3], &digest[12]);
+ UNPACK32(ctx->h[4], &digest[16]);
+ UNPACK32(ctx->h[5], &digest[20]);
+ UNPACK32(ctx->h[6], &digest[24]);
+ UNPACK32(ctx->h[7], &digest[28]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-512 functions */
+
+sha512::sha512() : sha2_base()
+{
+ sha512_init(&ctx);
+}
+
+void sha512::sha512_transf(sha512_ctx *ctx, const unsigned char *message,
+ unsigned int block_nb)
+{
+ uint64 w[80];
+ uint64 wv[8];
+ uint64 t1, t2;
+ const unsigned char *sub_block;
+ int i, j;
+
+ for (i = 0; i < (int) block_nb; i++) {
+ sub_block = message + (i << 7);
+
+#ifndef UNROLL_LOOPS
+ for (j = 0; j < 16; j++) {
+ PACK64(&sub_block[j << 3], &w[j]);
+ }
+
+ for (j = 16; j < 80; j++) {
+ SHA512_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 80; j++) {
+ t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+ + sha512_k[j] + w[j];
+ t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++) {
+ ctx->h[j] += wv[j];
+ }
+#else
+ PACK64(&sub_block[ 0], &w[ 0]); PACK64(&sub_block[ 8], &w[ 1]);
+ PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]);
+ PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]);
+ PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]);
+ PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]);
+ PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]);
+ PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]);
+ PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]);
+
+ SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
+ SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
+ SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
+ SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
+ SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
+ SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
+ SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
+ SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
+ SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
+ SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
+ SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
+ SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
+ SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
+ SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
+ SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
+ SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
+
+ wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
+
+ j = 0;
+
+ do {
+ SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
+ SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
+ SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
+ SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
+ SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
+ SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
+ SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
+ SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
+ } while (j < 80);
+
+ ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+ }
+}
+
+void sha512::sha512_init(sha512_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha512_h0[i];
+ }
+#else
+ ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
+ ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
+ ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
+ ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha512::sha512_update(sha512_ctx *ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA512_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA512_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA512_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha512_transf(ctx, ctx->block, 1);
+ sha512_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA512_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 7],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 7;
+}
+
+void sha512::sha512_final(sha512_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = 1 + ((SHA512_BLOCK_SIZE - 17)
+ < (ctx->len % SHA512_BLOCK_SIZE));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 7;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha512_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 8; i++) {
+ UNPACK64(ctx->h[i], &digest[i << 3]);
+ }
+#else
+ UNPACK64(ctx->h[0], &digest[ 0]);
+ UNPACK64(ctx->h[1], &digest[ 8]);
+ UNPACK64(ctx->h[2], &digest[16]);
+ UNPACK64(ctx->h[3], &digest[24]);
+ UNPACK64(ctx->h[4], &digest[32]);
+ UNPACK64(ctx->h[5], &digest[40]);
+ UNPACK64(ctx->h[6], &digest[48]);
+ UNPACK64(ctx->h[7], &digest[56]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-384 functions */
+
+sha384::sha384() : sha512()
+{
+ sha384_init(&ctx);
+}
+
+void sha384::sha384_init(sha384_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha384_h0[i];
+ }
+#else
+ ctx->h[0] = sha384_h0[0]; ctx->h[1] = sha384_h0[1];
+ ctx->h[2] = sha384_h0[2]; ctx->h[3] = sha384_h0[3];
+ ctx->h[4] = sha384_h0[4]; ctx->h[5] = sha384_h0[5];
+ ctx->h[6] = sha384_h0[6]; ctx->h[7] = sha384_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha384::sha384_update(sha384_ctx *ctx,const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA384_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA384_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA384_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha512_transf(ctx, ctx->block, 1);
+ sha512_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA384_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 7],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 7;
+}
+
+void sha384::sha384_final(sha384_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SHA384_BLOCK_SIZE - 17)
+ < (ctx->len % SHA384_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 7;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha512_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 6; i++) {
+ UNPACK64(ctx->h[i], &digest[i << 3]);
+ }
+#else
+ UNPACK64(ctx->h[0], &digest[ 0]);
+ UNPACK64(ctx->h[1], &digest[ 8]);
+ UNPACK64(ctx->h[2], &digest[16]);
+ UNPACK64(ctx->h[3], &digest[24]);
+ UNPACK64(ctx->h[4], &digest[32]);
+ UNPACK64(ctx->h[5], &digest[40]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-224 functions */
+
+sha224::sha224() : sha256()
+{
+ sha224_init(&ctx);
+}
+
+void sha224::sha224_init(sha224_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha224_h0[i];
+ }
+#else
+ ctx->h[0] = sha224_h0[0]; ctx->h[1] = sha224_h0[1];
+ ctx->h[2] = sha224_h0[2]; ctx->h[3] = sha224_h0[3];
+ ctx->h[4] = sha224_h0[4]; ctx->h[5] = sha224_h0[5];
+ ctx->h[6] = sha224_h0[6]; ctx->h[7] = sha224_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha224::sha224_update(sha224_ctx *ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA224_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA224_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA224_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha256_transf(ctx,ctx->block, 1);
+ sha256_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA224_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 6],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+void sha224::sha224_final(sha224_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SHA224_BLOCK_SIZE - 9)
+ < (ctx->len % SHA224_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 6;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha256_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 7; i++) {
+ UNPACK32(ctx->h[i], &digest[i << 2]);
+ }
+#else
+ UNPACK32(ctx->h[0], &digest[ 0]);
+ UNPACK32(ctx->h[1], &digest[ 4]);
+ UNPACK32(ctx->h[2], &digest[ 8]);
+ UNPACK32(ctx->h[3], &digest[12]);
+ UNPACK32(ctx->h[4], &digest[16]);
+ UNPACK32(ctx->h[5], &digest[20]);
+ UNPACK32(ctx->h[6], &digest[24]);
+#endif /* !UNROLL_LOOPS */
+}
+
+} // namespace Firebird
+
+#ifdef NIST_COMPLIANCY_TESTS
+
+/* FIPS 180-2 Validation tests */
+
+#include
+#include
+
+void test(const char *vector, unsigned char *digest,
+ unsigned int digest_size)
+{
+ char output[2 * SHA_MAX_DIGEST_SIZE + 1];
+ int i;
+
+ output[2 * digest_size] = '\0';
+
+ for (i = 0; i < (int) digest_size ; i++) {
+ sprintf(output + 2 * i, "%02x", digest[i]);
+ }
+
+ printf("H: %s\n", output);
+ if (strcmp(vector, output)) {
+ fprintf(stderr, "Test failed.\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
+using namespace Firebird;
+
+int main(void)
+{
+ static const char *vectors[4][3] =
+ { /* SHA-224 */
+ {
+ "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
+ "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525",
+ "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67",
+ },
+ /* SHA-256 */
+ {
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
+ "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0",
+ },
+ /* SHA-384 */
+ {
+ "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
+ "8086072ba1e7cc2358baeca134c825a7",
+ "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
+ "fcc7c71a557e2db966c3e9fa91746039",
+ "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b"
+ "07b8b3dc38ecc4ebae97ddd87f3d8985",
+ },
+ /* SHA-512 */
+ {
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
+ "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
+ "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
+ "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909",
+ "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
+ "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
+ }
+ };
+
+ static const char message1[] = "abc";
+ static const char message2a[] = "abcdbcdecdefdefgefghfghighijhi"
+ "jkijkljklmklmnlmnomnopnopq";
+ static const char message2b[] = "abcdefghbcdefghicdefghijdefghijkefghij"
+ "klfghijklmghijklmnhijklmnoijklmnopjklm"
+ "nopqklmnopqrlmnopqrsmnopqrstnopqrstu";
+ unsigned char *message3;
+ unsigned int message3_len = 1000000;
+ unsigned char digest[SHA512_DIGEST_SIZE];
+
+ message3 = (unsigned char *) malloc(message3_len);
+ if (message3 == NULL) {
+ fprintf(stderr, "Can't allocate memory\n");
+ return -1;
+ }
+ memset(message3, 'a', message3_len);
+ printf("SHA-2 FIPS 180-2 Validation tests\n\n");
+ printf("SHA-224 Test vectors\n");
+
+ get_digest((const unsigned char *) message1, strlen(message1), digest);
+ test(vectors[0][0], digest, SHA224_DIGEST_SIZE);
+ get_digest((const unsigned char *) message2a, strlen(message2a), digest);
+ test(vectors[0][1], digest, SHA224_DIGEST_SIZE);
+ get_digest(message3, message3_len, digest);
+ test(vectors[0][2], digest, SHA224_DIGEST_SIZE);
+ printf("\n");
+
+ printf("SHA-256 Test vectors\n");
+
+ get_digest((const unsigned char *) message1, strlen(message1), digest);
+ test(vectors[1][0], digest, SHA256_DIGEST_SIZE);
+ get_digest((const unsigned char *) message2a, strlen(message2a), digest);
+ test(vectors[1][1], digest, SHA256_DIGEST_SIZE);
+ get_digest(message3, message3_len, digest);
+ test(vectors[1][2], digest, SHA256_DIGEST_SIZE);
+ printf("\n");
+
+ printf("SHA-384 Test vectors\n");
+
+ get_digest((const unsigned char *) message1, strlen(message1), digest);
+ test(vectors[2][0], digest, SHA384_DIGEST_SIZE);
+ get_digest((const unsigned char *)message2b, strlen(message2b), digest);
+ test(vectors[2][1], digest, SHA384_DIGEST_SIZE);
+ get_digest(message3, message3_len, digest);
+ test(vectors[2][2], digest, SHA384_DIGEST_SIZE);
+ printf("\n");
+
+ printf("SHA-512 Test vectors\n");
+
+ get_digest((const unsigned char *) message1, strlen(message1), digest);
+ test(vectors[3][0], digest, SHA512_DIGEST_SIZE);
+ get_digest((const unsigned char *) message2b, strlen(message2b), digest);
+ test(vectors[3][1], digest, SHA512_DIGEST_SIZE);
+ get_digest(message3, message3_len, digest);
+ test(vectors[3][2], digest, SHA512_DIGEST_SIZE);
+ printf("\n");
+
+ printf("All tests passed.\n");
+
+ return 0;
+}
+
+#endif /* TEST_VECTORS */
+
diff --git a/src/common/sha2/sha2.h b/src/common/sha2/sha2.h
new file mode 100644
index 0000000000..1ee06e7ae4
--- /dev/null
+++ b/src/common/sha2/sha2.h
@@ -0,0 +1,276 @@
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ * https://github.com/ouah/sha2
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Updated for use in Firebird by Tony Whyman
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ /*
+ * This update is intended to make available the SHA-2 family of message
+ * digests as C++ classes for use in Firebird. sha224, sha256, sha384 and
+ * sha512 are each implemented as separate classes. The class methods are
+ * intended to be as similar as possible to the legacy class sha1 in order
+ * to facilitate straightforward replacement.
+ *
+ * This implementation also comes with a NIST compliancy test for each
+ * digest. This is enabled by building with the NIST_COMPLIANCY_TESTS symbol
+ * defined.
+ */
+
+#ifndef _SHA2_H
+#define _SHA2_H
+
+#include
+#include
+#ifndef NIST_COMPLIANCY_TESTS
+#include "firebird.h"
+#include "../../common/classes/alloc.h"
+#include "../../common/classes/array.h"
+#include "../../common/classes/fb_string.h"
+#include "../../common/utils_proto.h"
+#endif
+
+
+#define SHA224_DIGEST_SIZE ( 224 / 8)
+#define SHA256_DIGEST_SIZE ( 256 / 8)
+#define SHA384_DIGEST_SIZE ( 384 / 8)
+#define SHA512_DIGEST_SIZE ( 512 / 8)
+#define SHA_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
+
+#define SHA256_BLOCK_SIZE ( 512 / 8)
+#define SHA512_BLOCK_SIZE (1024 / 8)
+#define SHA384_BLOCK_SIZE SHA512_BLOCK_SIZE
+#define SHA224_BLOCK_SIZE SHA256_BLOCK_SIZE
+
+namespace Firebird {
+
+/* This template function provides a simple one line means of computing a SHA-2
+ * digest from an arbitrary length message.
+ */
+
+templatevoid get_digest(const unsigned char *message, size_t len, unsigned char *digest)
+{
+ SHA sha;
+ sha.process(len, message);
+ sha.getHash(digest);
+}
+
+
+#ifndef NIST_COMPLIANCY_TESTS
+/* This template class provides a simple one line means of computing a SHA-2
+ * digest from an arbitrary length message, and encoding the result in BASE64.
+ */
+template void hashBased64(Firebird::string& hash, const Firebird::string& data)
+{
+ SHA digest;
+ digest.process(data.length(), data.c_str());
+ UCharBuffer b;
+ digest.getHash(b);
+ fb_utils::base64(hash, b);
+}
+
+/* The sha2_base class is an abstract class that is the ancestor for all
+ * the SHA-2 classes. It defines all public methods for the classes and
+ * a common model of use.
+ *
+ * When instatiated a SHA-2 class is already initialized for use. The message
+ * for which a digest is required is then fed to the class using one of
+ * the "process" methods, either as a single action or accumulatively.
+ *
+ * When the entire message has been input, the resulting digest is returned
+ * by a "getHash" method. Calling "getHash" also clears the digest and
+ * re-initializes the SHA-2 generator ready to compute a new digest.
+ *
+ * A SHA-2 generator can be cleared down and re-initialized at any time
+ * by calling the "reset" method.
+ */
+
+class sha2_base : public GlobalStorage {
+#else
+class sha2_base {
+#endif
+public:
+ sha2_base() {};
+ virtual ~sha2_base() {};
+
+ virtual const unsigned int get_DigestSize()=0;
+ virtual const unsigned int get_BlockSize()=0;
+
+ typedef unsigned char uint8;
+ typedef unsigned int uint32;
+ typedef unsigned long long uint64;
+
+protected:
+ virtual void sha_init() {};
+ virtual void sha_update(const unsigned char *message, unsigned int len)=0;
+ virtual void sha_final(unsigned char *digest)=0;
+
+public:
+ void reset() {sha_init();};
+
+ void process(size_t length, const void* bytes)
+ {
+ sha_update(static_cast(bytes), length);
+ }
+
+ void process(size_t length, const unsigned char* message)
+ {
+ sha_update(message, length);
+ }
+
+ void process(const std::string& str)
+ {
+ process(str.length(), str.c_str());
+ }
+
+ void process(const char* str)
+ {
+ process(strlen(str), str);
+ }
+
+ void getHash(unsigned char *digest);
+
+#ifndef NIST_COMPLIANCY_TESTS
+ void process(const UCharBuffer& bytes)
+ {
+ process(bytes.getCount(), bytes.begin());
+ }
+
+ void getHash(UCharBuffer& h);
+#endif
+
+};
+
+class sha256 : public sha2_base {
+public:
+ sha256();
+ const unsigned int get_DigestSize() {return SHA256_DIGEST_SIZE;};
+ const unsigned int get_BlockSize() {return SHA256_BLOCK_SIZE;};
+
+protected:
+ typedef struct {
+ unsigned int tot_len;
+ unsigned int len;
+ unsigned char block[2 * SHA256_BLOCK_SIZE];
+ uint32 h[8];
+ } sha256_ctx;
+
+private:
+ void sha256_init(sha256_ctx * ctx);
+ void sha256_update(sha256_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+ void sha256_final(sha256_ctx *ctx, unsigned char *digest);
+
+protected:
+ sha256_ctx ctx;
+
+ void sha256_transf(sha256_ctx * ctx, const unsigned char *message,
+ unsigned int block_nb);
+ void sha_init() {sha256_init(&ctx);};
+ void sha_update(const unsigned char *message, unsigned int len) {sha256_update(&ctx,message,len);};
+ void sha_final(unsigned char *digest) {sha256_final(&ctx,digest);};
+};
+
+class sha224 : public sha256 {
+public:
+ sha224();
+ const unsigned int get_DigestSize() {return SHA224_DIGEST_SIZE;};
+ const unsigned int get_BlockSize() {return SHA224_BLOCK_SIZE;};
+
+private:
+ typedef sha256_ctx sha224_ctx;
+ void sha224_init(sha224_ctx *ctx);
+ void sha224_update(sha224_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+ void sha224_final(sha224_ctx *ctx, unsigned char *digest);
+
+protected:
+ void sha_init() {sha224_init(&ctx);};
+ void sha_update(const unsigned char *message, unsigned int len) {sha224_update(&ctx, message, len);};
+ void sha_final(unsigned char *digest) {sha224_final(&ctx,digest);};
+};
+
+class sha512 : public sha2_base {
+public:
+ sha512();
+ const unsigned int get_DigestSize() {return SHA512_DIGEST_SIZE;};
+ const unsigned int get_BlockSize() {return SHA512_BLOCK_SIZE;};
+
+protected:
+ typedef struct {
+ unsigned int tot_len;
+ unsigned int len;
+ unsigned char block[2 * SHA512_BLOCK_SIZE];
+ uint64 h[8];
+ } sha512_ctx;
+
+private:
+ void sha512_init(sha512_ctx *ctx);
+ void sha512_update(sha512_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+ void sha512_final(sha512_ctx *ctx, unsigned char *digest);
+protected:
+
+ sha512_ctx ctx;
+
+ void sha512_transf(sha512_ctx *ctx, const unsigned char *message,
+ unsigned int block_nb);
+ void sha_init() {sha512_init(&ctx);};
+ void sha_update(const unsigned char *message, unsigned int len) {sha512_update(&ctx, message, len);};
+ void sha_final(unsigned char *digest) {sha512_final(&ctx, digest);};
+
+};
+
+class sha384 : public sha512 {
+public:
+ sha384();
+ const unsigned int get_DigestSize() {return SHA384_DIGEST_SIZE;};
+ const unsigned int get_BlockSize() {return SHA384_BLOCK_SIZE;};
+
+private:
+ typedef sha512_ctx sha384_ctx;
+ void sha384_init(sha384_ctx *ctx);
+ void sha384_update(sha384_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+ void sha384_final(sha384_ctx *ctx, unsigned char *digest);
+
+protected:
+ void sha_init() {sha384_init(&ctx);};
+ void sha_update(const unsigned char *message, unsigned int len) {sha384_update(&ctx,message,len);};
+ void sha_final(unsigned char *digest) {sha384_final(&ctx, digest);};
+
+};
+
+} //Firebird
+
+#endif /* !_SHA2_H */
+