Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFelix Geyer <debfx@fobos.de>2010-11-21 18:19:27 +0300
committerFelix Geyer <debfx@fobos.de>2010-11-21 18:19:27 +0300
commita428464573b0d99e07e2752bbd89b650889af2e8 (patch)
tree1c7d5f5aae28a74773bd569bd85bcb2fabca1c45 /src
parent3b9982c0a3f177fd4e0fcd7bc439b6bbe62f47d8 (diff)
Add Salsa20 cipher.
Restructure SymmetricCipher implementation to allow multiple backends.
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt8
-rw-r--r--src/crypto/Crypto.cpp1
-rw-r--r--src/crypto/SymmetricCipher.cpp113
-rw-r--r--src/crypto/SymmetricCipher.h12
-rw-r--r--src/crypto/SymmetricCipherBackend.h41
-rw-r--r--src/crypto/SymmetricCipherGcrypt.cpp137
-rw-r--r--src/crypto/SymmetricCipherGcrypt.h52
-rw-r--r--src/crypto/SymmetricCipherSalsa20.cpp88
-rw-r--r--src/crypto/SymmetricCipherSalsa20.h47
-rw-r--r--src/crypto/salsa20/ecrypt-config.h297
-rw-r--r--src/crypto/salsa20/ecrypt-machine.h49
-rw-r--r--src/crypto/salsa20/ecrypt-portable.h310
-rw-r--r--src/crypto/salsa20/ecrypt-sync.h287
-rw-r--r--src/crypto/salsa20/salsa20.c133
14 files changed, 1473 insertions, 102 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 302b753ab..fbd7ebe97 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -29,7 +29,15 @@ set(keepassx_SOURCES
crypto/Crypto.cpp
crypto/CryptoHash.cpp
crypto/Random.cpp
+ crypto/salsa20/ecrypt-config.h
+ crypto/salsa20/ecrypt-machine.h
+ crypto/salsa20/ecrypt-portable.h
+ crypto/salsa20/ecrypt-sync.h
+ crypto/salsa20/salsa20.c
crypto/SymmetricCipher.cpp
+ crypto/SymmetricCipherBackend.h
+ crypto/SymmetricCipherGcrypt.cpp
+ crypto/SymmetricCipherSalsa20.cpp
format/KeePass2.h
format/KeePass2Reader.cpp
format/KeePass2Writer.cpp
diff --git a/src/crypto/Crypto.cpp b/src/crypto/Crypto.cpp
index bee190f81..856a597c1 100644
--- a/src/crypto/Crypto.cpp
+++ b/src/crypto/Crypto.cpp
@@ -65,6 +65,7 @@ Crypto::Crypto()
void Crypto::init()
{
if (m_initalized) {
+ qWarning("Crypto::init: already initalized");
return;
}
diff --git a/src/crypto/SymmetricCipher.cpp b/src/crypto/SymmetricCipher.cpp
index 90b77ce05..ecbb19887 100644
--- a/src/crypto/SymmetricCipher.cpp
+++ b/src/crypto/SymmetricCipher.cpp
@@ -17,49 +17,19 @@
#include "SymmetricCipher.h"
-#include <gcrypt.h>
-
-class SymmetricCipherPrivate
-{
-public:
- gcry_cipher_hd_t ctx;
- SymmetricCipher::Direction direction;
- QByteArray key;
- QByteArray iv;
- int blockSize;
-};
+#include "SymmetricCipherGcrypt.h"
+#include "SymmetricCipherSalsa20.h"
SymmetricCipher::SymmetricCipher(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
SymmetricCipher::Direction direction, const QByteArray& key, const QByteArray& iv)
- : d_ptr(new SymmetricCipherPrivate())
{
- Q_D(SymmetricCipher);
-
- d->direction = direction;
- d->key = key;
- d->iv = iv;
-
- int algoGcrypt;
-
switch (algo) {
case SymmetricCipher::Aes256:
- algoGcrypt = GCRY_CIPHER_AES256;
+ m_backend = new SymmetricCipherGcrypt();
break;
- default:
- Q_ASSERT(false);
- break;
- }
-
- int modeGcrypt;
-
- switch (mode) {
- case SymmetricCipher::Ecb:
- modeGcrypt = GCRY_CIPHER_MODE_ECB;
- break;
-
- case SymmetricCipher::Cbc:
- modeGcrypt = GCRY_CIPHER_MODE_CBC;
+ case SymmetricCipher::Salsa20:
+ m_backend = new SymmetricCipherSalsa20();
break;
default:
@@ -67,86 +37,35 @@ SymmetricCipher::SymmetricCipher(SymmetricCipher::Algorithm algo, SymmetricCiphe
break;
}
- gcry_error_t error;
-
- error = gcry_cipher_open(&d->ctx, algoGcrypt, modeGcrypt, 0);
- Q_ASSERT(error == 0); // TODO real error checking
- error = gcry_cipher_setkey(d->ctx, d->key.constData(), d->key.size());
- Q_ASSERT(error == 0);
- error = gcry_cipher_setiv(d->ctx, d->iv.constData(), d->iv.size());
- Q_ASSERT(error == 0);
-
- size_t blockSizeT;
- error = gcry_cipher_algo_info(algoGcrypt, GCRYCTL_GET_BLKLEN, 0, &blockSizeT);
- Q_ASSERT(error == 0);
- d->blockSize = blockSizeT;
+ m_backend->setAlgorithm(algo);
+ m_backend->setMode(mode);
+ m_backend->setDirection(direction);
+ m_backend->init();
+ m_backend->setKey(key);
+ m_backend->setIv(iv);
}
SymmetricCipher::~SymmetricCipher()
{
- Q_D(SymmetricCipher);
-
- gcry_cipher_close(d->ctx);
-
- delete d_ptr;
+ delete m_backend;
}
QByteArray SymmetricCipher::process(const QByteArray& data)
{
- Q_D(SymmetricCipher);
-
- // TODO check block size
-
- QByteArray result;
- result.resize(data.size());
-
- gcry_error_t error;
-
- if (d->direction == SymmetricCipher::Decrypt) {
- error = gcry_cipher_decrypt(d->ctx, result.data(), data.size(), data.constData(), data.size());
- }
- else {
- error = gcry_cipher_encrypt(d->ctx, result.data(), data.size(), data.constData(), data.size());
- }
-
- Q_ASSERT(error == 0);
-
- return result;
+ return m_backend->process(data);
}
void SymmetricCipher::processInPlace(QByteArray& data)
{
- Q_D(SymmetricCipher);
-
- // TODO check block size
-
- gcry_error_t error;
-
- if (d->direction == SymmetricCipher::Decrypt) {
- error = gcry_cipher_decrypt(d->ctx, data.data(), data.size(), 0, 0);
- }
- else {
- error = gcry_cipher_encrypt(d->ctx, data.data(), data.size(), 0, 0);
- }
-
- Q_ASSERT(error == 0);
+ m_backend->processInPlace(data);
}
void SymmetricCipher::reset()
{
- Q_D(SymmetricCipher);
-
- gcry_error_t error;
-
- error = gcry_cipher_reset(d->ctx);
- Q_ASSERT(error == 0);
- error = gcry_cipher_setiv(d->ctx, d->iv.constData(), d->iv.size());
- Q_ASSERT(error == 0);
+ m_backend->reset();
}
int SymmetricCipher::blockSize() const
{
- Q_D(const SymmetricCipher);
-
- return d->blockSize;
+ return m_backend->blockSize();
}
diff --git a/src/crypto/SymmetricCipher.h b/src/crypto/SymmetricCipher.h
index 6c1ca7205..2f744520b 100644
--- a/src/crypto/SymmetricCipher.h
+++ b/src/crypto/SymmetricCipher.h
@@ -20,20 +20,22 @@
#include <QtCore/QByteArray>
-class SymmetricCipherPrivate;
+class SymmetricCipherBackend;
class SymmetricCipher
{
public:
enum Algorithm
{
- Aes256
+ Aes256,
+ Salsa20
};
enum Mode
{
Cbc,
- Ecb
+ Ecb,
+ Stream
};
enum Direction
@@ -53,8 +55,8 @@ public:
int blockSize() const;
private:
- SymmetricCipherPrivate* const d_ptr;
- Q_DECLARE_PRIVATE(SymmetricCipher);
+ Q_DISABLE_COPY(SymmetricCipher)
+ SymmetricCipherBackend* m_backend;
};
#endif // KEEPASSX_SYMMETRICCIPHER_H
diff --git a/src/crypto/SymmetricCipherBackend.h b/src/crypto/SymmetricCipherBackend.h
new file mode 100644
index 000000000..4b9467e67
--- /dev/null
+++ b/src/crypto/SymmetricCipherBackend.h
@@ -0,0 +1,41 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 or (at your option)
+* version 3 of the License.
+*
+* 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
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KEEPASSX_SYMMETRICCIPHERBACKEND_H
+#define KEEPASSX_SYMMETRICCIPHERBACKEND_H
+
+#include "SymmetricCipher.h"
+
+class SymmetricCipherBackend
+{
+public:
+ virtual ~SymmetricCipherBackend() {};
+ virtual void setAlgorithm(SymmetricCipher::Algorithm algo) = 0;
+ virtual void setMode(SymmetricCipher::Mode mode) = 0;
+ virtual void setDirection(SymmetricCipher::Direction direction) = 0;
+ virtual void init() = 0;
+ virtual void setKey(const QByteArray& key) = 0;
+ virtual void setIv(const QByteArray& iv) = 0;
+
+ virtual QByteArray process(const QByteArray& data) = 0;
+ virtual void processInPlace(QByteArray& data) = 0;
+
+ virtual void reset() = 0;
+ virtual int blockSize() const = 0;
+};
+
+#endif // KEEPASSX_SYMMETRICCIPHERBACKEND_H
diff --git a/src/crypto/SymmetricCipherGcrypt.cpp b/src/crypto/SymmetricCipherGcrypt.cpp
new file mode 100644
index 000000000..2b32bff17
--- /dev/null
+++ b/src/crypto/SymmetricCipherGcrypt.cpp
@@ -0,0 +1,137 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 or (at your option)
+* version 3 of the License.
+*
+* 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
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "SymmetricCipherGcrypt.h"
+
+SymmetricCipherGcrypt::~SymmetricCipherGcrypt()
+{
+ gcry_cipher_close(m_ctx);
+}
+
+void SymmetricCipherGcrypt::setAlgorithm(SymmetricCipher::Algorithm algo)
+{
+ switch (algo) {
+ case SymmetricCipher::Aes256:
+ m_algo = GCRY_CIPHER_AES256;
+ break;
+
+ default:
+ Q_ASSERT(false);
+ break;
+ }
+}
+
+void SymmetricCipherGcrypt::setMode(SymmetricCipher::Mode mode)
+{
+ switch (mode) {
+ case SymmetricCipher::Ecb:
+ m_mode = GCRY_CIPHER_MODE_ECB;
+ break;
+
+ case SymmetricCipher::Cbc:
+ m_mode = GCRY_CIPHER_MODE_CBC;
+ break;
+
+ default:
+ Q_ASSERT(false);
+ break;
+ }
+}
+
+void SymmetricCipherGcrypt::setDirection(SymmetricCipher::Direction direction)
+{
+ m_direction = direction;
+}
+
+void SymmetricCipherGcrypt::init()
+{
+ gcry_error_t error;
+
+ error = gcry_cipher_open(&m_ctx, m_algo, m_mode, 0);
+ Q_ASSERT(error == 0); // TODO real error checking
+
+ size_t blockSizeT;
+ error = gcry_cipher_algo_info(m_algo, GCRYCTL_GET_BLKLEN, 0, &blockSizeT);
+ Q_ASSERT(error == 0);
+ m_blockSize = blockSizeT;
+}
+
+void SymmetricCipherGcrypt::setKey(const QByteArray& key)
+{
+ m_key = key;
+ gcry_error_t error = gcry_cipher_setkey(m_ctx, m_key.constData(), m_key.size());
+ Q_ASSERT(error == 0);
+}
+
+void SymmetricCipherGcrypt::setIv(const QByteArray& iv)
+{
+ m_iv = iv;
+ gcry_error_t error = gcry_cipher_setiv(m_ctx, m_iv.constData(), m_iv.size());
+ Q_ASSERT(error == 0);
+}
+
+QByteArray SymmetricCipherGcrypt::process(const QByteArray& data)
+{
+ // TODO check block size
+
+ QByteArray result;
+ result.resize(data.size());
+
+ gcry_error_t error;
+
+ if (m_direction == SymmetricCipher::Decrypt) {
+ error = gcry_cipher_decrypt(m_ctx, result.data(), data.size(), data.constData(), data.size());
+ }
+ else {
+ error = gcry_cipher_encrypt(m_ctx, result.data(), data.size(), data.constData(), data.size());
+ }
+
+ Q_ASSERT(error == 0);
+
+ return result;
+}
+
+void SymmetricCipherGcrypt::processInPlace(QByteArray& data)
+{
+ // TODO check block size
+
+ gcry_error_t error;
+
+ if (m_direction == SymmetricCipher::Decrypt) {
+ error = gcry_cipher_decrypt(m_ctx, data.data(), data.size(), 0, 0);
+ }
+ else {
+ error = gcry_cipher_encrypt(m_ctx, data.data(), data.size(), 0, 0);
+ }
+
+ Q_ASSERT(error == 0);
+}
+
+void SymmetricCipherGcrypt::reset()
+{
+ gcry_error_t error;
+
+ error = gcry_cipher_reset(m_ctx);
+ Q_ASSERT(error == 0);
+ error = gcry_cipher_setiv(m_ctx, m_iv.constData(), m_iv.size());
+ Q_ASSERT(error == 0);
+}
+
+int SymmetricCipherGcrypt::blockSize() const
+{
+ return m_blockSize;
+}
diff --git a/src/crypto/SymmetricCipherGcrypt.h b/src/crypto/SymmetricCipherGcrypt.h
new file mode 100644
index 000000000..6ac0d1173
--- /dev/null
+++ b/src/crypto/SymmetricCipherGcrypt.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 or (at your option)
+* version 3 of the License.
+*
+* 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
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KEEPASSX_SYMMETRICCIPHERGCRYPT_H
+#define KEEPASSX_SYMMETRICCIPHERGCRYPT_H
+
+#include "SymmetricCipherBackend.h"
+
+#include <gcrypt.h>
+
+class SymmetricCipherGcrypt : public SymmetricCipherBackend
+{
+public:
+ ~SymmetricCipherGcrypt();
+ void setAlgorithm(SymmetricCipher::Algorithm algo);
+ void setMode(SymmetricCipher::Mode mode);
+ void setDirection(SymmetricCipher::Direction direction);
+ void init();
+ void setKey(const QByteArray& key);
+ void setIv(const QByteArray& iv);
+
+ QByteArray process(const QByteArray& data);
+ void processInPlace(QByteArray& data);
+
+ void reset();
+ int blockSize() const;
+
+private:
+ gcry_cipher_hd_t m_ctx;
+ int m_algo;
+ int m_mode;
+ SymmetricCipher::Direction m_direction;
+ QByteArray m_key;
+ QByteArray m_iv;
+ int m_blockSize;
+};
+
+#endif // KEEPASSX_SYMMETRICCIPHERGCRYPT_H
diff --git a/src/crypto/SymmetricCipherSalsa20.cpp b/src/crypto/SymmetricCipherSalsa20.cpp
new file mode 100644
index 000000000..d5cc48729
--- /dev/null
+++ b/src/crypto/SymmetricCipherSalsa20.cpp
@@ -0,0 +1,88 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 or (at your option)
+* version 3 of the License.
+*
+* 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
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "SymmetricCipherSalsa20.h"
+
+SymmetricCipherSalsa20::~SymmetricCipherSalsa20()
+{
+}
+
+void SymmetricCipherSalsa20::setAlgorithm(SymmetricCipher::Algorithm algo)
+{
+ Q_ASSERT(algo == SymmetricCipher::Salsa20);
+}
+
+void SymmetricCipherSalsa20::setMode(SymmetricCipher::Mode mode)
+{
+ Q_ASSERT(mode == SymmetricCipher::Stream);
+}
+
+void SymmetricCipherSalsa20::setDirection(SymmetricCipher::Direction direction)
+{
+ Q_UNUSED(direction);
+}
+
+void SymmetricCipherSalsa20::init()
+{
+}
+
+void SymmetricCipherSalsa20::setKey(const QByteArray& key)
+{
+ Q_ASSERT( (key.size() == 16) || (key.size() == 32) );
+
+ m_key = key;
+ ECRYPT_keysetup(&m_ctx, reinterpret_cast<const u8*>(m_key.constData()), m_key.size()*8, 64);
+}
+
+void SymmetricCipherSalsa20::setIv(const QByteArray& iv)
+{
+ Q_ASSERT(iv.size() == 8);
+
+ m_iv = iv;
+ ECRYPT_ivsetup(&m_ctx, reinterpret_cast<const u8*>(m_iv.constData()));
+}
+
+QByteArray SymmetricCipherSalsa20::process(const QByteArray& data)
+{
+ Q_ASSERT( (data.size() < blockSize()) || ((data.size() % blockSize())==0) );
+
+ QByteArray result;
+ result.resize(data.size());
+
+ ECRYPT_encrypt_bytes(&m_ctx, reinterpret_cast<const u8*>(data.constData()),
+ reinterpret_cast<u8*>(result.data()), data.size());
+
+ return result;
+}
+
+void SymmetricCipherSalsa20::processInPlace(QByteArray& data)
+{
+ Q_ASSERT( (data.size() < blockSize()) || ((data.size() % blockSize())==0) );
+
+ ECRYPT_encrypt_bytes(&m_ctx, reinterpret_cast<const u8*>(data.constData()),
+ reinterpret_cast<u8*>(data.data()), data.size());
+}
+
+void SymmetricCipherSalsa20::reset()
+{
+ ECRYPT_ivsetup(&m_ctx, reinterpret_cast<const u8*>(m_iv.constData()));
+}
+
+int SymmetricCipherSalsa20::blockSize() const
+{
+ return 64;
+}
diff --git a/src/crypto/SymmetricCipherSalsa20.h b/src/crypto/SymmetricCipherSalsa20.h
new file mode 100644
index 000000000..af31c329e
--- /dev/null
+++ b/src/crypto/SymmetricCipherSalsa20.h
@@ -0,0 +1,47 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 or (at your option)
+* version 3 of the License.
+*
+* 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
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KEEPASSX_SYMMETRICCIPHERSALSA20_H
+#define KEEPASSX_SYMMETRICCIPHERSALSA20_H
+
+#include "SymmetricCipherBackend.h"
+#include "salsa20/ecrypt-sync.h"
+
+class SymmetricCipherSalsa20 : public SymmetricCipherBackend
+{
+public:
+ ~SymmetricCipherSalsa20();
+ void setAlgorithm(SymmetricCipher::Algorithm algo);
+ void setMode(SymmetricCipher::Mode mode);
+ void setDirection(SymmetricCipher::Direction direction);
+ void init();
+ void setKey(const QByteArray& key);
+ void setIv(const QByteArray& iv);
+
+ QByteArray process(const QByteArray& data);
+ void processInPlace(QByteArray& data);
+
+ void reset();
+ int blockSize() const;
+
+private:
+ ECRYPT_ctx m_ctx;
+ QByteArray m_key;
+ QByteArray m_iv;
+};
+
+#endif // KEEPASSX_SYMMETRICCIPHERSALSA20_H
diff --git a/src/crypto/salsa20/ecrypt-config.h b/src/crypto/salsa20/ecrypt-config.h
new file mode 100644
index 000000000..57c33a42c
--- /dev/null
+++ b/src/crypto/salsa20/ecrypt-config.h
@@ -0,0 +1,297 @@
+/* ecrypt-config.h */
+
+/* *** Normally, it should not be necessary to edit this file. *** */
+
+#ifndef ECRYPT_CONFIG
+#define ECRYPT_CONFIG
+
+/* ------------------------------------------------------------------------- */
+
+/* Guess the endianness of the target architecture. */
+
+/*
+ * The LITTLE endian machines:
+ */
+#if defined(__ultrix) /* Older MIPS */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(__alpha) /* Alpha */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(i386) /* x86 (gcc) */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(__i386) /* x86 (gcc) */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(__x86_64) /* x86_64 (gcc) */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(_M_IX86) /* x86 (MSC, Borland) */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(_MSC_VER) /* x86 (surely MSC) */
+#define ECRYPT_LITTLE_ENDIAN
+#elif defined(__INTEL_COMPILER) /* x86 (surely Intel compiler icl.exe) */
+#define ECRYPT_LITTLE_ENDIAN
+
+/*
+ * The BIG endian machines:
+ */
+#elif defined(__sparc) /* Newer Sparc's */
+#define ECRYPT_BIG_ENDIAN
+#elif defined(__powerpc__) /* PowerPC */
+#define ECRYPT_BIG_ENDIAN
+#elif defined(__ppc__) /* PowerPC */
+#define ECRYPT_BIG_ENDIAN
+#elif defined(__hppa) /* HP-PA */
+#define ECRYPT_BIG_ENDIAN
+
+/*
+ * Finally machines with UNKNOWN endianness:
+ */
+#elif defined (_AIX) /* RS6000 */
+#define ECRYPT_UNKNOWN
+#elif defined(__aux) /* 68K */
+#define ECRYPT_UNKNOWN
+#elif defined(__dgux) /* 88K (but P6 in latest boxes) */
+#define ECRYPT_UNKNOWN
+#elif defined(__sgi) /* Newer MIPS */
+#define ECRYPT_UNKNOWN
+#else /* Any other processor */
+#define ECRYPT_UNKNOWN
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Find minimal-width types to store 8-bit, 16-bit, 32-bit, and 64-bit
+ * integers.
+ *
+ * Note: to enable 64-bit types on 32-bit compilers, it might be
+ * necessary to switch from ISO C90 mode to ISO C99 mode (e.g., gcc
+ * -std=c99), or to allow compiler-specific extensions.
+ */
+
+#include <limits.h>
+
+/* --- check char --- */
+
+#if (UCHAR_MAX / 0xFU > 0xFU)
+#ifndef I8T
+#define I8T char
+#define U8C(v) (v##U)
+
+#if (UCHAR_MAX == 0xFFU)
+#define ECRYPT_I8T_IS_BYTE
+#endif
+
+#endif
+
+#if (UCHAR_MAX / 0xFFU > 0xFFU)
+#ifndef I16T
+#define I16T char
+#define U16C(v) (v##U)
+#endif
+
+#if (UCHAR_MAX / 0xFFFFU > 0xFFFFU)
+#ifndef I32T
+#define I32T char
+#define U32C(v) (v##U)
+#endif
+
+#if (UCHAR_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU)
+#ifndef I64T
+#define I64T char
+#define U64C(v) (v##U)
+#define ECRYPT_NATIVE64
+#endif
+
+#endif
+#endif
+#endif
+#endif
+
+/* --- check short --- */
+
+#if (USHRT_MAX / 0xFU > 0xFU)
+#ifndef I8T
+#define I8T short
+#define U8C(v) (v##U)
+
+#if (USHRT_MAX == 0xFFU)
+#define ECRYPT_I8T_IS_BYTE
+#endif
+
+#endif
+
+#if (USHRT_MAX / 0xFFU > 0xFFU)
+#ifndef I16T
+#define I16T short
+#define U16C(v) (v##U)
+#endif
+
+#if (USHRT_MAX / 0xFFFFU > 0xFFFFU)
+#ifndef I32T
+#define I32T short
+#define U32C(v) (v##U)
+#endif
+
+#if (USHRT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU)
+#ifndef I64T
+#define I64T short
+#define U64C(v) (v##U)
+#define ECRYPT_NATIVE64
+#endif
+
+#endif
+#endif
+#endif
+#endif
+
+/* --- check int --- */
+
+#if (UINT_MAX / 0xFU > 0xFU)
+#ifndef I8T
+#define I8T int
+#define U8C(v) (v##U)
+
+#if (ULONG_MAX == 0xFFU)
+#define ECRYPT_I8T_IS_BYTE
+#endif
+
+#endif
+
+#if (UINT_MAX / 0xFFU > 0xFFU)
+#ifndef I16T
+#define I16T int
+#define U16C(v) (v##U)
+#endif
+
+#if (UINT_MAX / 0xFFFFU > 0xFFFFU)
+#ifndef I32T
+#define I32T int
+#define U32C(v) (v##U)
+#endif
+
+#if (UINT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU)
+#ifndef I64T
+#define I64T int
+#define U64C(v) (v##U)
+#define ECRYPT_NATIVE64
+#endif
+
+#endif
+#endif
+#endif
+#endif
+
+/* --- check long --- */
+
+#if (ULONG_MAX / 0xFUL > 0xFUL)
+#ifndef I8T
+#define I8T long
+#define U8C(v) (v##UL)
+
+#if (ULONG_MAX == 0xFFUL)
+#define ECRYPT_I8T_IS_BYTE
+#endif
+
+#endif
+
+#if (ULONG_MAX / 0xFFUL > 0xFFUL)
+#ifndef I16T
+#define I16T long
+#define U16C(v) (v##UL)
+#endif
+
+#if (ULONG_MAX / 0xFFFFUL > 0xFFFFUL)
+#ifndef I32T
+#define I32T long
+#define U32C(v) (v##UL)
+#endif
+
+#if (ULONG_MAX / 0xFFFFFFFFUL > 0xFFFFFFFFUL)
+#ifndef I64T
+#define I64T long
+#define U64C(v) (v##UL)
+#define ECRYPT_NATIVE64
+#endif
+
+#endif
+#endif
+#endif
+#endif
+
+/* --- check long long --- */
+
+#ifdef ULLONG_MAX
+
+#if (ULLONG_MAX / 0xFULL > 0xFULL)
+#ifndef I8T
+#define I8T long long
+#define U8C(v) (v##ULL)
+
+#if (ULLONG_MAX == 0xFFULL)
+#define ECRYPT_I8T_IS_BYTE
+#endif
+
+#endif
+
+#if (ULLONG_MAX / 0xFFULL > 0xFFULL)
+#ifndef I16T
+#define I16T long long
+#define U16C(v) (v##ULL)
+#endif
+
+#if (ULLONG_MAX / 0xFFFFULL > 0xFFFFULL)
+#ifndef I32T
+#define I32T long long
+#define U32C(v) (v##ULL)
+#endif
+
+#if (ULLONG_MAX / 0xFFFFFFFFULL > 0xFFFFFFFFULL)
+#ifndef I64T
+#define I64T long long
+#define U64C(v) (v##ULL)
+#endif
+
+#endif
+#endif
+#endif
+#endif
+
+#endif
+
+/* --- check __int64 --- */
+
+#if !defined(__STDC__) && defined(_UI64_MAX)
+
+#ifndef I64T
+#define I64T __int64
+#define U64C(v) (v##ui64)
+#endif
+
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+/* find the largest type on this platform (used for alignment) */
+
+#if defined(__SSE__) || (defined(_MSC_VER) && (_MSC_VER >= 1300))
+
+#include <xmmintrin.h>
+#define MAXT __m128
+
+#elif defined(__MMX__)
+
+#include <mmintrin.h>
+#define MAXT __m64
+
+#elif defined(__ALTIVEC__)
+
+#define MAXT __vector int
+
+#else
+
+#define MAXT long
+
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#endif
diff --git a/src/crypto/salsa20/ecrypt-machine.h b/src/crypto/salsa20/ecrypt-machine.h
new file mode 100644
index 000000000..d006bedec
--- /dev/null
+++ b/src/crypto/salsa20/ecrypt-machine.h
@@ -0,0 +1,49 @@
+/* ecrypt-machine.h */
+
+/*
+ * This file is included by 'ecrypt-portable.h'. It allows to override
+ * the default macros for specific platforms. Please carefully check
+ * the machine code generated by your compiler (with optimisations
+ * turned on) before deciding to edit this file.
+ */
+
+/* ------------------------------------------------------------------------- */
+
+#if (defined(ECRYPT_DEFAULT_ROT) && !defined(ECRYPT_MACHINE_ROT))
+
+#define ECRYPT_MACHINE_ROT
+
+#if (defined(WIN32) && defined(_MSC_VER))
+
+#undef ROTL32
+#undef ROTR32
+#undef ROTL64
+#undef ROTR64
+
+#include <stdlib.h>
+
+#pragma intrinsic(_lrotl) /* compile rotations "inline" */
+#pragma intrinsic(_lrotr)
+
+#define ROTL32(v, n) _lrotl(v, n)
+#define ROTR32(v, n) _lrotr(v, n)
+#define ROTL64(v, n) _rotl64(v, n)
+#define ROTR64(v, n) _rotr64(v, n)
+
+#endif
+
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#if (defined(ECRYPT_DEFAULT_SWAP) && !defined(ECRYPT_MACHINE_SWAP))
+
+#define ECRYPT_MACHINE_SWAP
+
+/*
+ * If you want to overwrite the default swap macros, put it here. And so on.
+ */
+
+#endif
+
+/* ------------------------------------------------------------------------- */
diff --git a/src/crypto/salsa20/ecrypt-portable.h b/src/crypto/salsa20/ecrypt-portable.h
new file mode 100644
index 000000000..438a464a7
--- /dev/null
+++ b/src/crypto/salsa20/ecrypt-portable.h
@@ -0,0 +1,310 @@
+/* ecrypt-portable.h */
+
+/*
+ * WARNING: the conversions defined below are implemented as macros,
+ * and should be used carefully. They should NOT be used with
+ * parameters which perform some action. E.g., the following two lines
+ * are not equivalent:
+ *
+ * 1) ++x; y = ROTL32(x, n);
+ * 2) y = ROTL32(++x, n);
+ */
+
+/*
+ * *** Please do not edit this file. ***
+ *
+ * The default macros can be overridden for specific architectures by
+ * editing 'ecrypt-machine.h'.
+ */
+
+#ifndef ECRYPT_PORTABLE
+#define ECRYPT_PORTABLE
+
+#include "ecrypt-config.h"
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * The following types are defined (if available):
+ *
+ * u8: unsigned integer type, at least 8 bits
+ * u16: unsigned integer type, at least 16 bits
+ * u32: unsigned integer type, at least 32 bits
+ * u64: unsigned integer type, at least 64 bits
+ *
+ * s8, s16, s32, s64 -> signed counterparts of u8, u16, u32, u64
+ *
+ * The selection of minimum-width integer types is taken care of by
+ * 'ecrypt-config.h'. Note: to enable 64-bit types on 32-bit
+ * compilers, it might be necessary to switch from ISO C90 mode to ISO
+ * C99 mode (e.g., gcc -std=c99).
+ */
+
+#ifdef I8T
+typedef signed I8T s8;
+typedef unsigned I8T u8;
+#endif
+
+#ifdef I16T
+typedef signed I16T s16;
+typedef unsigned I16T u16;
+#endif
+
+#ifdef I32T
+typedef signed I32T s32;
+typedef unsigned I32T u32;
+#endif
+
+#ifdef I64T
+typedef signed I64T s64;
+typedef unsigned I64T u64;
+#endif
+
+/*
+ * The following macros are used to obtain exact-width results.
+ */
+
+#define U8V(v) ((u8)(v) & U8C(0xFF))
+#define U16V(v) ((u16)(v) & U16C(0xFFFF))
+#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
+#define U64V(v) ((u64)(v) & U64C(0xFFFFFFFFFFFFFFFF))
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * The following macros return words with their bits rotated over n
+ * positions to the left/right.
+ */
+
+#define ECRYPT_DEFAULT_ROT
+
+#define ROTL8(v, n) \
+ (U8V((v) << (n)) | ((v) >> (8 - (n))))
+
+#define ROTL16(v, n) \
+ (U16V((v) << (n)) | ((v) >> (16 - (n))))
+
+#define ROTL32(v, n) \
+ (U32V((v) << (n)) | ((v) >> (32 - (n))))
+
+#define ROTL64(v, n) \
+ (U64V((v) << (n)) | ((v) >> (64 - (n))))
+
+#define ROTR8(v, n) ROTL8(v, 8 - (n))
+#define ROTR16(v, n) ROTL16(v, 16 - (n))
+#define ROTR32(v, n) ROTL32(v, 32 - (n))
+#define ROTR64(v, n) ROTL64(v, 64 - (n))
+
+#include "ecrypt-machine.h"
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * The following macros return a word with bytes in reverse order.
+ */
+
+#define ECRYPT_DEFAULT_SWAP
+
+#define SWAP16(v) \
+ ROTL16(v, 8)
+
+#define SWAP32(v) \
+ ((ROTL32(v, 8) & U32C(0x00FF00FF)) | \
+ (ROTL32(v, 24) & U32C(0xFF00FF00)))
+
+#ifdef ECRYPT_NATIVE64
+#define SWAP64(v) \
+ ((ROTL64(v, 8) & U64C(0x000000FF000000FF)) | \
+ (ROTL64(v, 24) & U64C(0x0000FF000000FF00)) | \
+ (ROTL64(v, 40) & U64C(0x00FF000000FF0000)) | \
+ (ROTL64(v, 56) & U64C(0xFF000000FF000000)))
+#else
+#define SWAP64(v) \
+ (((u64)SWAP32(U32V(v)) << 32) | (u64)SWAP32(U32V(v >> 32)))
+#endif
+
+#include "ecrypt-machine.h"
+
+#define ECRYPT_DEFAULT_WTOW
+
+#ifdef ECRYPT_LITTLE_ENDIAN
+#define U16TO16_LITTLE(v) (v)
+#define U32TO32_LITTLE(v) (v)
+#define U64TO64_LITTLE(v) (v)
+
+#define U16TO16_BIG(v) SWAP16(v)
+#define U32TO32_BIG(v) SWAP32(v)
+#define U64TO64_BIG(v) SWAP64(v)
+#endif
+
+#ifdef ECRYPT_BIG_ENDIAN
+#define U16TO16_LITTLE(v) SWAP16(v)
+#define U32TO32_LITTLE(v) SWAP32(v)
+#define U64TO64_LITTLE(v) SWAP64(v)
+
+#define U16TO16_BIG(v) (v)
+#define U32TO32_BIG(v) (v)
+#define U64TO64_BIG(v) (v)
+#endif
+
+#include "ecrypt-machine.h"
+
+/*
+ * The following macros load words from an array of bytes with
+ * different types of endianness, and vice versa.
+ */
+
+#define ECRYPT_DEFAULT_BTOW
+
+#if (!defined(ECRYPT_UNKNOWN) && defined(ECRYPT_I8T_IS_BYTE))
+
+#define U8TO16_LITTLE(p) U16TO16_LITTLE(((u16*)(p))[0])
+#define U8TO32_LITTLE(p) U32TO32_LITTLE(((u32*)(p))[0])
+#define U8TO64_LITTLE(p) U64TO64_LITTLE(((u64*)(p))[0])
+
+#define U8TO16_BIG(p) U16TO16_BIG(((u16*)(p))[0])
+#define U8TO32_BIG(p) U32TO32_BIG(((u32*)(p))[0])
+#define U8TO64_BIG(p) U64TO64_BIG(((u64*)(p))[0])
+
+#define U16TO8_LITTLE(p, v) (((u16*)(p))[0] = U16TO16_LITTLE(v))
+#define U32TO8_LITTLE(p, v) (((u32*)(p))[0] = U32TO32_LITTLE(v))
+#define U64TO8_LITTLE(p, v) (((u64*)(p))[0] = U64TO64_LITTLE(v))
+
+#define U16TO8_BIG(p, v) (((u16*)(p))[0] = U16TO16_BIG(v))
+#define U32TO8_BIG(p, v) (((u32*)(p))[0] = U32TO32_BIG(v))
+#define U64TO8_BIG(p, v) (((u64*)(p))[0] = U64TO64_BIG(v))
+
+#else
+
+#define U8TO16_LITTLE(p) \
+ (((u16)((p)[0]) ) | \
+ ((u16)((p)[1]) << 8))
+
+#define U8TO32_LITTLE(p) \
+ (((u32)((p)[0]) ) | \
+ ((u32)((p)[1]) << 8) | \
+ ((u32)((p)[2]) << 16) | \
+ ((u32)((p)[3]) << 24))
+
+#ifdef ECRYPT_NATIVE64
+#define U8TO64_LITTLE(p) \
+ (((u64)((p)[0]) ) | \
+ ((u64)((p)[1]) << 8) | \
+ ((u64)((p)[2]) << 16) | \
+ ((u64)((p)[3]) << 24) | \
+ ((u64)((p)[4]) << 32) | \
+ ((u64)((p)[5]) << 40) | \
+ ((u64)((p)[6]) << 48) | \
+ ((u64)((p)[7]) << 56))
+#else
+#define U8TO64_LITTLE(p) \
+ ((u64)U8TO32_LITTLE(p) | ((u64)U8TO32_LITTLE((p) + 4) << 32))
+#endif
+
+#define U8TO16_BIG(p) \
+ (((u16)((p)[0]) << 8) | \
+ ((u16)((p)[1]) ))
+
+#define U8TO32_BIG(p) \
+ (((u32)((p)[0]) << 24) | \
+ ((u32)((p)[1]) << 16) | \
+ ((u32)((p)[2]) << 8) | \
+ ((u32)((p)[3]) ))
+
+#ifdef ECRYPT_NATIVE64
+#define U8TO64_BIG(p) \
+ (((u64)((p)[0]) << 56) | \
+ ((u64)((p)[1]) << 48) | \
+ ((u64)((p)[2]) << 40) | \
+ ((u64)((p)[3]) << 32) | \
+ ((u64)((p)[4]) << 24) | \
+ ((u64)((p)[5]) << 16) | \
+ ((u64)((p)[6]) << 8) | \
+ ((u64)((p)[7]) ))
+#else
+#define U8TO64_BIG(p) \
+ (((u64)U8TO32_BIG(p) << 32) | (u64)U8TO32_BIG((p) + 4))
+#endif
+
+#define U16TO8_LITTLE(p, v) \
+ do { \
+ (p)[0] = U8V((v) ); \
+ (p)[1] = U8V((v) >> 8); \
+ } while (0)
+
+#define U32TO8_LITTLE(p, v) \
+ do { \
+ (p)[0] = U8V((v) ); \
+ (p)[1] = U8V((v) >> 8); \
+ (p)[2] = U8V((v) >> 16); \
+ (p)[3] = U8V((v) >> 24); \
+ } while (0)
+
+#ifdef ECRYPT_NATIVE64
+#define U64TO8_LITTLE(p, v) \
+ do { \
+ (p)[0] = U8V((v) ); \
+ (p)[1] = U8V((v) >> 8); \
+ (p)[2] = U8V((v) >> 16); \
+ (p)[3] = U8V((v) >> 24); \
+ (p)[4] = U8V((v) >> 32); \
+ (p)[5] = U8V((v) >> 40); \
+ (p)[6] = U8V((v) >> 48); \
+ (p)[7] = U8V((v) >> 56); \
+ } while (0)
+#else
+#define U64TO8_LITTLE(p, v) \
+ do { \
+ U32TO8_LITTLE((p), U32V((v) )); \
+ U32TO8_LITTLE((p) + 4, U32V((v) >> 32)); \
+ } while (0)
+#endif
+
+#define U16TO8_BIG(p, v) \
+ do { \
+ (p)[0] = U8V((v) ); \
+ (p)[1] = U8V((v) >> 8); \
+ } while (0)
+
+#define U32TO8_BIG(p, v) \
+ do { \
+ (p)[0] = U8V((v) >> 24); \
+ (p)[1] = U8V((v) >> 16); \
+ (p)[2] = U8V((v) >> 8); \
+ (p)[3] = U8V((v) ); \
+ } while (0)
+
+#ifdef ECRYPT_NATIVE64
+#define U64TO8_BIG(p, v) \
+ do { \
+ (p)[0] = U8V((v) >> 56); \
+ (p)[1] = U8V((v) >> 48); \
+ (p)[2] = U8V((v) >> 40); \
+ (p)[3] = U8V((v) >> 32); \
+ (p)[4] = U8V((v) >> 24); \
+ (p)[5] = U8V((v) >> 16); \
+ (p)[6] = U8V((v) >> 8); \
+ (p)[7] = U8V((v) ); \
+ } while (0)
+#else
+#define U64TO8_BIG(p, v) \
+ do { \
+ U32TO8_BIG((p), U32V((v) >> 32)); \
+ U32TO8_BIG((p) + 4, U32V((v) )); \
+ } while (0)
+#endif
+
+#endif
+
+#include "ecrypt-machine.h"
+
+/* ------------------------------------------------------------------------- */
+
+#define AT_LEAST_ONE(n) (((n) < 1) ? 1 : (n))
+
+#define ALIGN(t, v, n) \
+ union { t b[n]; MAXT l[AT_LEAST_ONE(n * sizeof(t) / sizeof(MAXT))]; } v
+
+/* ------------------------------------------------------------------------- */
+
+#endif
diff --git a/src/crypto/salsa20/ecrypt-sync.h b/src/crypto/salsa20/ecrypt-sync.h
new file mode 100644
index 000000000..245793e19
--- /dev/null
+++ b/src/crypto/salsa20/ecrypt-sync.h
@@ -0,0 +1,287 @@
+/* ecrypt-sync.h */
+
+/*
+ * Header file for synchronous stream ciphers without authentication
+ * mechanism.
+ *
+ * *** Please only edit parts marked with "[edit]". ***
+ */
+
+#ifndef ECRYPT_SYNC
+#define ECRYPT_SYNC
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ecrypt-portable.h"
+
+/* ------------------------------------------------------------------------- */
+
+/* Cipher parameters */
+
+/*
+ * The name of your cipher.
+ */
+#define ECRYPT_NAME "Salsa20" /* [edit] */
+#define ECRYPT_PROFILE "S!_H."
+
+/*
+ * Specify which key and IV sizes are supported by your cipher. A user
+ * should be able to enumerate the supported sizes by running the
+ * following code:
+ *
+ * for (i = 0; ECRYPT_KEYSIZE(i) <= ECRYPT_MAXKEYSIZE; ++i)
+ * {
+ * keysize = ECRYPT_KEYSIZE(i);
+ *
+ * ...
+ * }
+ *
+ * All sizes are in bits.
+ */
+
+#define ECRYPT_MAXKEYSIZE 256 /* [edit] */
+#define ECRYPT_KEYSIZE(i) (128 + (i)*128) /* [edit] */
+
+#define ECRYPT_MAXIVSIZE 64 /* [edit] */
+#define ECRYPT_IVSIZE(i) (64 + (i)*64) /* [edit] */
+
+/* ------------------------------------------------------------------------- */
+
+/* Data structures */
+
+/*
+ * ECRYPT_ctx is the structure containing the representation of the
+ * internal state of your cipher.
+ */
+
+typedef struct
+{
+ u32 input[16]; /* could be compressed */
+ /*
+ * [edit]
+ *
+ * Put here all state variable needed during the encryption process.
+ */
+} ECRYPT_ctx;
+
+/* ------------------------------------------------------------------------- */
+
+/* Mandatory functions */
+
+/*
+ * Key and message independent initialization. This function will be
+ * called once when the program starts (e.g., to build expanded S-box
+ * tables).
+ */
+void ECRYPT_init();
+
+/*
+ * Key setup. It is the user's responsibility to select the values of
+ * keysize and ivsize from the set of supported values specified
+ * above.
+ */
+void ECRYPT_keysetup(
+ ECRYPT_ctx* ctx,
+ const u8* key,
+ u32 keysize, /* Key size in bits. */
+ u32 ivsize); /* IV size in bits. */
+
+/*
+ * IV setup. After having called ECRYPT_keysetup(), the user is
+ * allowed to call ECRYPT_ivsetup() different times in order to
+ * encrypt/decrypt different messages with the same key but different
+ * IV's.
+ */
+void ECRYPT_ivsetup(
+ ECRYPT_ctx* ctx,
+ const u8* iv);
+
+/*
+ * Encryption/decryption of arbitrary length messages.
+ *
+ * For efficiency reasons, the API provides two types of
+ * encrypt/decrypt functions. The ECRYPT_encrypt_bytes() function
+ * (declared here) encrypts byte strings of arbitrary length, while
+ * the ECRYPT_encrypt_blocks() function (defined later) only accepts
+ * lengths which are multiples of ECRYPT_BLOCKLENGTH.
+ *
+ * The user is allowed to make multiple calls to
+ * ECRYPT_encrypt_blocks() to incrementally encrypt a long message,
+ * but he is NOT allowed to make additional encryption calls once he
+ * has called ECRYPT_encrypt_bytes() (unless he starts a new message
+ * of course). For example, this sequence of calls is acceptable:
+ *
+ * ECRYPT_keysetup();
+ *
+ * ECRYPT_ivsetup();
+ * ECRYPT_encrypt_blocks();
+ * ECRYPT_encrypt_blocks();
+ * ECRYPT_encrypt_bytes();
+ *
+ * ECRYPT_ivsetup();
+ * ECRYPT_encrypt_blocks();
+ * ECRYPT_encrypt_blocks();
+ *
+ * ECRYPT_ivsetup();
+ * ECRYPT_encrypt_bytes();
+ *
+ * The following sequence is not:
+ *
+ * ECRYPT_keysetup();
+ * ECRYPT_ivsetup();
+ * ECRYPT_encrypt_blocks();
+ * ECRYPT_encrypt_bytes();
+ * ECRYPT_encrypt_blocks();
+ */
+
+void ECRYPT_encrypt_bytes(
+ ECRYPT_ctx* ctx,
+ const u8* plaintext,
+ u8* ciphertext,
+ u32 msglen); /* Message length in bytes. */
+
+void ECRYPT_decrypt_bytes(
+ ECRYPT_ctx* ctx,
+ const u8* ciphertext,
+ u8* plaintext,
+ u32 msglen); /* Message length in bytes. */
+
+/* ------------------------------------------------------------------------- */
+
+/* Optional features */
+
+/*
+ * For testing purposes it can sometimes be useful to have a function
+ * which immediately generates keystream without having to provide it
+ * with a zero plaintext. If your cipher cannot provide this function
+ * (e.g., because it is not strictly a synchronous cipher), please
+ * reset the ECRYPT_GENERATES_KEYSTREAM flag.
+ */
+
+#define ECRYPT_GENERATES_KEYSTREAM
+#ifdef ECRYPT_GENERATES_KEYSTREAM
+
+void ECRYPT_keystream_bytes(
+ ECRYPT_ctx* ctx,
+ u8* keystream,
+ u32 length); /* Length of keystream in bytes. */
+
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+/* Optional optimizations */
+
+/*
+ * By default, the functions in this section are implemented using
+ * calls to functions declared above. However, you might want to
+ * implement them differently for performance reasons.
+ */
+
+/*
+ * All-in-one encryption/decryption of (short) packets.
+ *
+ * The default definitions of these functions can be found in
+ * "ecrypt-sync.c". If you want to implement them differently, please
+ * undef the ECRYPT_USES_DEFAULT_ALL_IN_ONE flag.
+ */
+#define ECRYPT_USES_DEFAULT_ALL_IN_ONE /* [edit] */
+
+void ECRYPT_encrypt_packet(
+ ECRYPT_ctx* ctx,
+ const u8* iv,
+ const u8* plaintext,
+ u8* ciphertext,
+ u32 msglen);
+
+void ECRYPT_decrypt_packet(
+ ECRYPT_ctx* ctx,
+ const u8* iv,
+ const u8* ciphertext,
+ u8* plaintext,
+ u32 msglen);
+
+/*
+ * Encryption/decryption of blocks.
+ *
+ * By default, these functions are defined as macros. If you want to
+ * provide a different implementation, please undef the
+ * ECRYPT_USES_DEFAULT_BLOCK_MACROS flag and implement the functions
+ * declared below.
+ */
+
+#define ECRYPT_BLOCKLENGTH 64 /* [edit] */
+
+#define ECRYPT_USES_DEFAULT_BLOCK_MACROS /* [edit] */
+#ifdef ECRYPT_USES_DEFAULT_BLOCK_MACROS
+
+#define ECRYPT_encrypt_blocks(ctx, plaintext, ciphertext, blocks) \
+ ECRYPT_encrypt_bytes(ctx, plaintext, ciphertext, \
+ (blocks) * ECRYPT_BLOCKLENGTH)
+
+#define ECRYPT_decrypt_blocks(ctx, ciphertext, plaintext, blocks) \
+ ECRYPT_decrypt_bytes(ctx, ciphertext, plaintext, \
+ (blocks) * ECRYPT_BLOCKLENGTH)
+
+#ifdef ECRYPT_GENERATES_KEYSTREAM
+
+#define ECRYPT_keystream_blocks(ctx, keystream, blocks) \
+ ECRYPT_keystream_bytes(ctx, keystream, \
+ (blocks) * ECRYPT_BLOCKLENGTH)
+
+#endif
+
+#else
+
+void ECRYPT_encrypt_blocks(
+ ECRYPT_ctx* ctx,
+ const u8* plaintext,
+ u8* ciphertext,
+ u32 blocks); /* Message length in blocks. */
+
+void ECRYPT_decrypt_blocks(
+ ECRYPT_ctx* ctx,
+ const u8* ciphertext,
+ u8* plaintext,
+ u32 blocks); /* Message length in blocks. */
+
+#ifdef ECRYPT_GENERATES_KEYSTREAM
+
+void ECRYPT_keystream_blocks(
+ ECRYPT_ctx* ctx,
+ const u8* keystream,
+ u32 blocks); /* Keystream length in blocks. */
+
+#endif
+
+#endif
+
+/*
+ * If your cipher can be implemented in different ways, you can use
+ * the ECRYPT_VARIANT parameter to allow the user to choose between
+ * them at compile time (e.g., gcc -DECRYPT_VARIANT=3 ...). Please
+ * only use this possibility if you really think it could make a
+ * significant difference and keep the number of variants
+ * (ECRYPT_MAXVARIANT) as small as possible (definitely not more than
+ * 10). Note also that all variants should have exactly the same
+ * external interface (i.e., the same ECRYPT_BLOCKLENGTH, etc.).
+ */
+#define ECRYPT_MAXVARIANT 1 /* [edit] */
+
+#ifndef ECRYPT_VARIANT
+#define ECRYPT_VARIANT 1
+#endif
+
+#if (ECRYPT_VARIANT > ECRYPT_MAXVARIANT)
+#error this variant does not exist
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/crypto/salsa20/salsa20.c b/src/crypto/salsa20/salsa20.c
new file mode 100644
index 000000000..74f806cad
--- /dev/null
+++ b/src/crypto/salsa20/salsa20.c
@@ -0,0 +1,133 @@
+/*
+salsa20-ref.c version 20051118
+D. J. Bernstein
+Public domain.
+*/
+
+#include "ecrypt-sync.h"
+
+#define ROTATE(v,c) (ROTL32(v,c))
+#define XOR(v,w) ((v) ^ (w))
+#define PLUS(v,w) (U32V((v) + (w)))
+#define PLUSONE(v) (PLUS((v),1))
+
+static void salsa20_wordtobyte(u8 output[64],const u32 input[16])
+{
+ u32 x[16];
+ int i;
+
+ for (i = 0;i < 16;++i) x[i] = input[i];
+ for (i = 20;i > 0;i -= 2) {
+ x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 0],x[12]), 7));
+ x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[ 4],x[ 0]), 9));
+ x[12] = XOR(x[12],ROTATE(PLUS(x[ 8],x[ 4]),13));
+ x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[12],x[ 8]),18));
+ x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 5],x[ 1]), 7));
+ x[13] = XOR(x[13],ROTATE(PLUS(x[ 9],x[ 5]), 9));
+ x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[13],x[ 9]),13));
+ x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 1],x[13]),18));
+ x[14] = XOR(x[14],ROTATE(PLUS(x[10],x[ 6]), 7));
+ x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[14],x[10]), 9));
+ x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 2],x[14]),13));
+ x[10] = XOR(x[10],ROTATE(PLUS(x[ 6],x[ 2]),18));
+ x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[15],x[11]), 7));
+ x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 3],x[15]), 9));
+ x[11] = XOR(x[11],ROTATE(PLUS(x[ 7],x[ 3]),13));
+ x[15] = XOR(x[15],ROTATE(PLUS(x[11],x[ 7]),18));
+ x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[ 0],x[ 3]), 7));
+ x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[ 1],x[ 0]), 9));
+ x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[ 2],x[ 1]),13));
+ x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[ 3],x[ 2]),18));
+ x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 5],x[ 4]), 7));
+ x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 6],x[ 5]), 9));
+ x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 7],x[ 6]),13));
+ x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 4],x[ 7]),18));
+ x[11] = XOR(x[11],ROTATE(PLUS(x[10],x[ 9]), 7));
+ x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[11],x[10]), 9));
+ x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 8],x[11]),13));
+ x[10] = XOR(x[10],ROTATE(PLUS(x[ 9],x[ 8]),18));
+ x[12] = XOR(x[12],ROTATE(PLUS(x[15],x[14]), 7));
+ x[13] = XOR(x[13],ROTATE(PLUS(x[12],x[15]), 9));
+ x[14] = XOR(x[14],ROTATE(PLUS(x[13],x[12]),13));
+ x[15] = XOR(x[15],ROTATE(PLUS(x[14],x[13]),18));
+ }
+ for (i = 0;i < 16;++i) x[i] = PLUS(x[i],input[i]);
+ for (i = 0;i < 16;++i) U32TO8_LITTLE(output + 4 * i,x[i]);
+}
+
+void ECRYPT_init(void)
+{
+ return;
+}
+
+static const char sigma[16] = "expand 32-byte k";
+static const char tau[16] = "expand 16-byte k";
+
+void ECRYPT_keysetup(ECRYPT_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
+{
+ (void)ivbits;
+ const char *constants;
+
+ x->input[1] = U8TO32_LITTLE(k + 0);
+ x->input[2] = U8TO32_LITTLE(k + 4);
+ x->input[3] = U8TO32_LITTLE(k + 8);
+ x->input[4] = U8TO32_LITTLE(k + 12);
+ if (kbits == 256) { /* recommended */
+ k += 16;
+ constants = sigma;
+ } else { /* kbits == 128 */
+ constants = tau;
+ }
+ x->input[11] = U8TO32_LITTLE(k + 0);
+ x->input[12] = U8TO32_LITTLE(k + 4);
+ x->input[13] = U8TO32_LITTLE(k + 8);
+ x->input[14] = U8TO32_LITTLE(k + 12);
+ x->input[0] = U8TO32_LITTLE(constants + 0);
+ x->input[5] = U8TO32_LITTLE(constants + 4);
+ x->input[10] = U8TO32_LITTLE(constants + 8);
+ x->input[15] = U8TO32_LITTLE(constants + 12);
+}
+
+void ECRYPT_ivsetup(ECRYPT_ctx *x,const u8 *iv)
+{
+ x->input[6] = U8TO32_LITTLE(iv + 0);
+ x->input[7] = U8TO32_LITTLE(iv + 4);
+ x->input[8] = 0;
+ x->input[9] = 0;
+}
+
+void ECRYPT_encrypt_bytes(ECRYPT_ctx *x,const u8 *m,u8 *c,u32 bytes)
+{
+ u8 output[64];
+ u32 i;
+
+ if (!bytes) return;
+ for (;;) {
+ salsa20_wordtobyte(output,x->input);
+ x->input[8] = PLUSONE(x->input[8]);
+ if (!x->input[8]) {
+ x->input[9] = PLUSONE(x->input[9]);
+ /* stopping at 2^70 bytes per nonce is user's responsibility */
+ }
+ if (bytes <= 64) {
+ for (i = 0;i < bytes;++i) c[i] = m[i] ^ output[i];
+ return;
+ }
+ for (i = 0;i < 64;++i) c[i] = m[i] ^ output[i];
+ bytes -= 64;
+ c += 64;
+ m += 64;
+ }
+}
+
+void ECRYPT_decrypt_bytes(ECRYPT_ctx *x,const u8 *c,u8 *m,u32 bytes)
+{
+ ECRYPT_encrypt_bytes(x,c,m,bytes);
+}
+
+void ECRYPT_keystream_bytes(ECRYPT_ctx *x,u8 *stream,u32 bytes)
+{
+ u32 i;
+ for (i = 0;i < bytes;++i) stream[i] = 0;
+ ECRYPT_encrypt_bytes(x,stream,stream,bytes);
+}