From 250ede4f32a14f566fbafd634e2024c93677cf19 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 19 Nov 2009 21:54:01 +0100
Subject: Added missing files of previous commit.


diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp
new file mode 100644
index 0000000..b2e85e9
--- /dev/null
+++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp
@@ -0,0 +1,56 @@
+#include "Swiften/SASL/SCRAMSHA1ClientAuthenticator.h"
+
+#include <cassert>
+
+#include "Swiften/StringCodecs/SHA1.h"
+#include "Swiften/StringCodecs/HMACSHA1.h"
+
+namespace Swift {
+
+SCRAMSHA1ClientAuthenticator::SCRAMSHA1ClientAuthenticator(const String& authcid, const String& password, const String& authzid, const ByteArray& nonce) : step(Initial), authcid(authcid), password(password), authzid(authzid), clientnonce(nonce) {
+}
+
+ByteArray SCRAMSHA1ClientAuthenticator::getMessage() const {
+	if (step == Initial) {
+		return getInitialClientMessage();
+	}
+	else {
+		ByteArray mask = HMACSHA1::getResult(getClientVerifier(), initialServerMessage + getInitialClientMessage());
+		ByteArray p = SHA1::getBinaryHash(password);
+		for (unsigned int i = 0; i < p.getSize(); ++i) {
+			p[i] ^= mask[i];
+		}
+		return p;
+	}
+}
+
+bool SCRAMSHA1ClientAuthenticator::setResponse(const ByteArray& response) {
+	if (step == Initial) {
+		initialServerMessage = response;
+		step = Proof;
+		return getSalt().getSize() > 0;
+	}
+	else {
+		return response == HMACSHA1::getResult(getClientVerifier(), getInitialClientMessage() + initialServerMessage);
+	}
+}
+
+ByteArray SCRAMSHA1ClientAuthenticator::getSalt() const {
+	if (initialServerMessage.getSize() < 8) {
+		std::cerr << "ERROR: SCRAM-SHA1: Invalid server response" << std::endl;
+		return ByteArray();
+	}
+	else {
+		return ByteArray(initialServerMessage.getData(), 8);
+	}
+}
+
+ByteArray SCRAMSHA1ClientAuthenticator::getClientVerifier() const {
+	return HMACSHA1::getResult(SHA1::getBinaryHash(password), getSalt());
+}
+
+ByteArray SCRAMSHA1ClientAuthenticator::getInitialClientMessage() const {
+	return ByteArray(authzid) + '\0' + ByteArray(authcid) + '\0' + ByteArray(clientnonce);
+}
+
+}
diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h
new file mode 100644
index 0000000..d129468
--- /dev/null
+++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "Swiften/Base/String.h"
+#include "Swiften/Base/ByteArray.h"
+
+namespace Swift {
+	class SCRAMSHA1ClientAuthenticator {
+		public:
+			SCRAMSHA1ClientAuthenticator(const String& authcid, const String& password, const String& authzid, const ByteArray& nonce);
+
+			ByteArray getMessage() const;
+			bool setResponse(const ByteArray&);
+
+		private:
+			ByteArray getInitialClientMessage() const;
+			ByteArray getSalt() const;
+			ByteArray getClientVerifier() const;
+
+		private:
+			enum Step {
+				Initial,
+				Proof
+			} step;
+			String authcid;
+			String password;
+			String authzid;
+			ByteArray clientnonce;
+			ByteArray initialServerMessage;
+	};
+}
diff --git a/Swiften/StringCodecs/HMACSHA1.cpp b/Swiften/StringCodecs/HMACSHA1.cpp
new file mode 100644
index 0000000..59f1482
--- /dev/null
+++ b/Swiften/StringCodecs/HMACSHA1.cpp
@@ -0,0 +1,39 @@
+#include "Swiften/StringCodecs/HMACSHA1.h"
+
+#include <cassert>
+
+#include "Swiften/StringCodecs/SHA1.h"
+#include "Swiften/Base/ByteArray.h"
+
+namespace Swift {
+
+static const unsigned int B = 64;
+
+ByteArray HMACSHA1::getResult(const ByteArray& key, const ByteArray& data) {
+	assert(key.getSize() <= B);
+
+	// Create the padded key
+	ByteArray paddedKey(key);
+	paddedKey.resize(B);
+	for (unsigned int i = key.getSize(); i < paddedKey.getSize(); ++i) {
+		paddedKey[i] = 0x0;
+	}
+
+	// Create the first value
+	ByteArray x(paddedKey);
+	for (unsigned int i = 0; i < x.getSize(); ++i) {
+		x[i] ^= 0x36;
+	}
+	x += data;
+
+	// Create the second value
+	ByteArray y(paddedKey);
+	for (unsigned int i = 0; i < y.getSize(); ++i) {
+		y[i] ^= 0x5c;
+	}
+	y += SHA1::getBinaryHash(x);
+
+	return SHA1::getBinaryHash(y);
+}
+
+}
diff --git a/Swiften/StringCodecs/HMACSHA1.h b/Swiften/StringCodecs/HMACSHA1.h
new file mode 100644
index 0000000..698e4bc
--- /dev/null
+++ b/Swiften/StringCodecs/HMACSHA1.h
@@ -0,0 +1,10 @@
+#pragma once
+
+namespace Swift {
+	class ByteArray;
+
+	class HMACSHA1 {
+		public:
+			static ByteArray getResult(const ByteArray& key, const ByteArray& data);
+	};
+}
diff --git a/Swiften/StringCodecs/UnitTest/HMACSHA1Test.cpp b/Swiften/StringCodecs/UnitTest/HMACSHA1Test.cpp
new file mode 100644
index 0000000..edfae10
--- /dev/null
+++ b/Swiften/StringCodecs/UnitTest/HMACSHA1Test.cpp
@@ -0,0 +1,21 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/Base/ByteArray.h"
+#include "Swiften/StringCodecs/HMACSHA1.h"
+
+using namespace Swift;
+
+class HMACSHA1Test : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(HMACSHA1Test);
+		CPPUNIT_TEST(testGetResult);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		void testGetResult() {
+			ByteArray result(HMACSHA1::getResult("foo", "foobar"));
+			CPPUNIT_ASSERT_EQUAL(ByteArray("\xa4\xee\xba\x8e\x63\x3d\x77\x88\x69\xf5\x68\xd0\x5a\x1b\x3d\xc7\x2b\xfd\x4\xdd"), result);
+		}
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HMACSHA1Test);
-- 
cgit v0.10.2-6-g49f6