summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@anytun.org>2009-01-15 01:00:19 +0000
committerChristian Pointner <equinox@anytun.org>2009-01-15 01:00:19 +0000
commitbb9f6547ad858b11fb29c7f1e23eddb1573bff1c (patch)
tree39eb1d0f0bc4e20dadd03518b0af5a689a639031
parentported authAlgo from uanytun to anytun (diff)
ported uanytun key derivation to anytun
no key store until now (ld_kdr gets ignored) no multi kd until now (WritersLock instead of ReadersLock @ generate) finally removed creepy mpi class
-rw-r--r--src/Makefile2
-rw-r--r--src/anytun.cpp10
-rw-r--r--src/authAlgo.cpp12
-rw-r--r--src/authAlgo.h12
-rw-r--r--src/cipher.cpp71
-rw-r--r--src/cipher.h20
-rw-r--r--src/cryptinit.hpp37
-rw-r--r--src/keyDerivation.cpp255
-rw-r--r--src/keyDerivation.h71
-rw-r--r--src/mpi.cpp203
-rw-r--r--src/mpi.h84
-rw-r--r--src/threadUtils.hpp5
12 files changed, 334 insertions, 448 deletions
diff --git a/src/Makefile b/src/Makefile
index 5dae026..64dd5b8 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -55,7 +55,6 @@ OBJS = tunDevice.o \
cipher.o \
authAlgo.o \
keyDerivation.o \
- mpi.o \
cipherFactory.o \
authAlgoFactory.o \
keyDerivationFactory.o \
@@ -87,7 +86,6 @@ ANYCTROBJS = signalController.o \
ANYCONFOBJS = log.o \
buffer.o \
keyDerivation.o \
- mpi.o \
keyDerivationFactory.o \
networkAddress.o \
networkPrefix.o \
diff --git a/src/anytun.cpp b/src/anytun.cpp
index e46731a..c0cb03b 100644
--- a/src/anytun.cpp
+++ b/src/anytun.cpp
@@ -169,13 +169,13 @@ void sender(void* p)
}
// encrypt packet
- c->encrypt(conn.kd_, plain_packet, encrypted_packet, conn.seq_nr_, gOpt.getSenderId(), mux);
+ c->encrypt(conn.kd_, KD_OUTBOUND, plain_packet, encrypted_packet, conn.seq_nr_, gOpt.getSenderId(), mux);
encrypted_packet.setHeader(conn.seq_nr_, gOpt.getSenderId(), mux);
conn.seq_nr_++;
// add authentication tag
- a->generate(conn.kd_, encrypted_packet);
+ a->generate(conn.kd_, KD_OUTBOUND, encrypted_packet);
try
{
@@ -276,7 +276,7 @@ void receiver(void* p)
ConnectionParam & conn = cit->second;
// check whether auth tag is ok or not
- if(!a->checkTag(conn.kd_, encrypted_packet)) {
+ if(!a->checkTag(conn.kd_, KD_INBOUND, encrypted_packet)) {
cLog.msg(Log::PRIO_NOTICE) << "wrong Authentication Tag!" << std::endl;
continue;
}
@@ -302,7 +302,7 @@ void receiver(void* p)
}
// decrypt packet
- c->decrypt(conn.kd_, encrypted_packet, plain_packet);
+ c->decrypt(conn.kd_, KD_INBOUND, encrypted_packet, plain_packet);
// check payload_type
if((param->dev.getType() == TYPE_TUN && plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN4 &&
@@ -418,10 +418,12 @@ int main(int argc, char* argv[])
ThreadParam p(dev, *src, *(new OptionConnectTo()));
#ifndef NOCRYPT
+#ifndef USE_SSL_CRYPTO
// this must be called before any other libgcrypt call
if(!initLibGCrypt())
return -1;
#endif
+#endif
boost::thread senderThread(boost::bind(sender,&p));
#ifndef NOSIGNALCONTROLLER
diff --git a/src/authAlgo.cpp b/src/authAlgo.cpp
index 669308b..a0b9193 100644
--- a/src/authAlgo.cpp
+++ b/src/authAlgo.cpp
@@ -38,11 +38,11 @@
#include <cstring>
//****** NullAuthAlgo ******
-void NullAuthAlgo::generate(KeyDerivation& kd, EncryptedPacket& packet)
+void NullAuthAlgo::generate(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet)
{
}
-bool NullAuthAlgo::checkTag(KeyDerivation& kd, EncryptedPacket& packet)
+bool NullAuthAlgo::checkTag(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet)
{
return true;
}
@@ -74,13 +74,13 @@ Sha1AuthAlgo::~Sha1AuthAlgo()
#endif
}
-void Sha1AuthAlgo::generate(KeyDerivation& kd, EncryptedPacket& packet)
+void Sha1AuthAlgo::generate(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet)
{
packet.addAuthTag();
if(!packet.getAuthTagLength())
return;
- bool result = kd.generate(LABEL_SATP_MSG_AUTH, packet.getSeqNr(), key_);
+ bool result = kd.generate(dir, LABEL_SATP_MSG_AUTH, packet.getSeqNr(), key_);
if(result) { // a new key got generated
#ifndef USE_SSL_CRYPTO
gcry_error_t err = gcry_md_setkey(handle_, key_.getBuf(), key_.getLength());
@@ -118,13 +118,13 @@ void Sha1AuthAlgo::generate(KeyDerivation& kd, EncryptedPacket& packet)
std::memcpy(&tag[packet.getAuthTagLength() - length], &hmac[DIGEST_LENGTH - length], length);
}
-bool Sha1AuthAlgo::checkTag(KeyDerivation& kd, EncryptedPacket& packet)
+bool Sha1AuthAlgo::checkTag(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet)
{
packet.withAuthTag(true);
if(!packet.getAuthTagLength())
return true;
- bool result = kd.generate(LABEL_SATP_MSG_AUTH, packet.getSeqNr(), key_);
+ bool result = kd.generate(dir, LABEL_SATP_MSG_AUTH, packet.getSeqNr(), key_);
if(result) { // a new key got generated
#ifndef USE_SSL_CRYPTO
gcry_error_t err = gcry_md_setkey(handle_, key_.getBuf(), key_.getLength());
diff --git a/src/authAlgo.h b/src/authAlgo.h
index be8d158..5728426 100644
--- a/src/authAlgo.h
+++ b/src/authAlgo.h
@@ -55,13 +55,13 @@ public:
* generate the mac
* @param packet the packet to be authenticated
*/
- virtual void generate(KeyDerivation& kd, EncryptedPacket& packet) = 0;
+ virtual void generate(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet) = 0;
/**
* check the mac
* @param packet the packet to be authenticated
*/
- virtual bool checkTag(KeyDerivation& kd, EncryptedPacket& packet) = 0;
+ virtual bool checkTag(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet) = 0;
};
//****** NullAuthAlgo ******
@@ -69,8 +69,8 @@ public:
class NullAuthAlgo : public AuthAlgo
{
public:
- void generate(KeyDerivation& kd, EncryptedPacket& packet);
- bool checkTag(KeyDerivation& kd, EncryptedPacket& packet);
+ void generate(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet);
+ bool checkTag(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet);
};
#ifndef NOCRYPT
@@ -83,8 +83,8 @@ public:
Sha1AuthAlgo();
~Sha1AuthAlgo();
- void generate(KeyDerivation& kd, EncryptedPacket& packet);
- bool checkTag(KeyDerivation& kd, EncryptedPacket& packet);
+ void generate(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet);
+ bool checkTag(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet);
static const u_int32_t DIGEST_LENGTH = 20;
diff --git a/src/cipher.cpp b/src/cipher.cpp
index 8db6256..3d86fc5 100644
--- a/src/cipher.cpp
+++ b/src/cipher.cpp
@@ -40,31 +40,31 @@
#include "cipher.h"
#include "log.h"
-void Cipher::encrypt(KeyDerivation& kd, PlainPacket & in, EncryptedPacket & out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
+void Cipher::encrypt(KeyDerivation& kd, kd_dir dir, PlainPacket & in, EncryptedPacket & out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
{
- u_int32_t len = cipher(kd, in, in.getLength(), out.getPayload(), out.getPayloadLength(), seq_nr, sender_id, mux);
+ u_int32_t len = cipher(kd, dir, in, in.getLength(), out.getPayload(), out.getPayloadLength(), seq_nr, sender_id, mux);
out.setSenderId(sender_id);
out.setSeqNr(seq_nr);
out.setMux(mux);
out.setPayloadLength(len);
}
-void Cipher::decrypt(KeyDerivation& kd, EncryptedPacket & in, PlainPacket & out)
+void Cipher::decrypt(KeyDerivation& kd, kd_dir dir, EncryptedPacket & in, PlainPacket & out)
{
- u_int32_t len = decipher(kd, in.getPayload() , in.getPayloadLength(), out, out.getLength(), in.getSeqNr(), in.getSenderId(), in.getMux());
+ u_int32_t len = decipher(kd, dir, in.getPayload() , in.getPayloadLength(), out, out.getLength(), in.getSeqNr(), in.getSenderId(), in.getMux());
out.setLength(len);
}
//******* NullCipher *******
-u_int32_t NullCipher::cipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
+u_int32_t NullCipher::cipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
{
std::memcpy(out, in, (ilen < olen) ? ilen : olen);
return (ilen < olen) ? ilen : olen;
}
-u_int32_t NullCipher::decipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
+u_int32_t NullCipher::decipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
{
std::memcpy(out, in, (ilen < olen) ? ilen : olen);
return (ilen < olen) ? ilen : olen;
@@ -118,21 +118,21 @@ AesIcmCipher::~AesIcmCipher()
#endif
}
-u_int32_t AesIcmCipher::cipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
+u_int32_t AesIcmCipher::cipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
{
- calc(kd, in, ilen, out, olen, seq_nr, sender_id, mux);
+ calc(kd, dir, in, ilen, out, olen, seq_nr, sender_id, mux);
return (ilen < olen) ? ilen : olen;
}
-u_int32_t AesIcmCipher::decipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
+u_int32_t AesIcmCipher::decipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
{
- calc(kd, in, ilen, out, olen, seq_nr, sender_id, mux);
+ calc(kd, dir, in, ilen, out, olen, seq_nr, sender_id, mux);
return (ilen < olen) ? ilen : olen;
}
-void AesIcmCipher::calc_ctr(KeyDerivation& kd, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
+void AesIcmCipher::calcCtr(KeyDerivation& kd, kd_dir dir, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
{
- kd.generate(LABEL_SATP_SALT, seq_nr, salt_);
+ kd.generate(dir, LABEL_SATP_SALT, seq_nr, salt_);
#ifdef ANYTUN_02_COMPAT
if(!salt_[int32_t(0)])
@@ -148,47 +148,36 @@ void AesIcmCipher::calc_ctr(KeyDerivation& kd, seq_nr_t seq_nr, sender_id_t send
return;
}
-void AesIcmCipher::calc(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
+void AesIcmCipher::calc(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
{
#ifndef USE_SSL_CRYPTO
if(!handle_)
return;
#endif
- bool result = kd.generate(LABEL_SATP_ENCRYPTION, seq_nr, key_);
- if(result) { // a new key got generated
+ kd.generate(dir, LABEL_SATP_ENCRYPTION, seq_nr, key_);
#ifdef USE_SSL_CRYPTO
- int ret = AES_set_encrypt_key(key_.getBuf(), key_.getLength()*8, &aes_key_);
- if(ret) {
- char buf[STERROR_TEXT_MAX];
- buf[0] = 0;
- cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to set cipher ssl key (code: " << ret << ")";
- return;
- }
+ int ret = AES_set_encrypt_key(key_.getBuf(), key_.getLength()*8, &aes_key_);
+ if(ret) {
+ char buf[STERROR_TEXT_MAX];
+ buf[0] = 0;
+ cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to set cipher ssl key (code: " << ret << ")";
+ return;
+ }
#else
- gcry_error_t err = gcry_cipher_setkey(handle_, key_.getBuf(), key_.getLength());
- if(err) {
- char buf[STERROR_TEXT_MAX];
- buf[0] = 0;
- cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to set cipher key: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
- return;
- }
- } // no new key got generated
- else {
- gcry_error_t err = gcry_cipher_reset(handle_);
- if(err) {
- char buf[STERROR_TEXT_MAX];
- buf[0] = 0;
- cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to reset cipher: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
- return;
- }
-#endif
+ gcry_error_t err = gcry_cipher_setkey(handle_, key_.getBuf(), key_.getLength());
+ if(err) {
+ char buf[STERROR_TEXT_MAX];
+ buf[0] = 0;
+ cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to set cipher key: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
+ return;
}
+#endif
- calc_ctr(kd, seq_nr, sender_id, mux);
+ calcCtr(kd, dir, seq_nr, sender_id, mux);
#ifndef USE_SSL_CRYPTO
- gcry_error_t err = gcry_cipher_setctr(handle_, ctr_.buf_, CTR_LENGTH);
+ err = gcry_cipher_setctr(handle_, ctr_.buf_, CTR_LENGTH);
if(err) {
char buf[STERROR_TEXT_MAX];
buf[0] = 0;
diff --git a/src/cipher.h b/src/cipher.h
index f930bc4..30bbeed 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -51,12 +51,12 @@ class Cipher
public:
virtual ~Cipher() {};
- void encrypt(KeyDerivation& kd, PlainPacket & in, EncryptedPacket & out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
- void decrypt(KeyDerivation& kd, EncryptedPacket & in, PlainPacket & out);
+ void encrypt(KeyDerivation& kd, kd_dir dir, PlainPacket & in, EncryptedPacket & out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
+ void decrypt(KeyDerivation& kd, kd_dir dir, EncryptedPacket & in, PlainPacket & out);
protected:
- virtual u_int32_t cipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) = 0;
- virtual u_int32_t decipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) = 0;
+ virtual u_int32_t cipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) = 0;
+ virtual u_int32_t decipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) = 0;
};
//****** NullCipher ******
@@ -64,8 +64,8 @@ protected:
class NullCipher : public Cipher
{
protected:
- u_int32_t cipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
- u_int32_t decipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
+ u_int32_t cipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
+ u_int32_t decipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
};
#ifndef NOCRYPT
@@ -83,14 +83,14 @@ public:
static const u_int16_t SALT_LENGTH = 14;
protected:
- u_int32_t cipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
- u_int32_t decipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
+ u_int32_t cipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
+ u_int32_t decipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
private:
void init(u_int16_t key_length = DEFAULT_KEY_LENGTH);
- void calc_ctr(KeyDerivation& kd, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
- void calc(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
+ void calcCtr(KeyDerivation& kd, kd_dir dir, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
+ void calc(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
#ifndef USE_SSL_CRYPTO
gcry_cipher_hd_t handle_;
diff --git a/src/cryptinit.hpp b/src/cryptinit.hpp
index 567a374..dd878cd 100644
--- a/src/cryptinit.hpp
+++ b/src/cryptinit.hpp
@@ -1,7 +1,39 @@
+/*
+ * anytun
+ *
+ * The secure anycast tunneling protocol (satp) defines a protocol used
+ * for communication between any combination of unicast and anycast
+ * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
+ * mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ * ethernet, ip, arp ...). satp directly includes cryptography and
+ * message authentication based on the methodes used by SRTP. It is
+ * intended to deliver a generic, scaleable and secure solution for
+ * tunneling and relaying of packets of any protocol.
+ *
+ *
+ * Copyright (C) 2007-2008 Othmar Gsenger, Erwin Nindl,
+ * Christian Pointner <satp@wirdorange.org>
+ *
+ * This file is part of Anytun.
+ *
+ * Anytun is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Anytun 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 anytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
#ifndef _CRYPTINIT_HPP
#define _CRYPTINIT_HPP
-#ifndef NOCRYPT
+#ifndef NOCRYPT
+#ifndef USE_SSL_CRYPTO
// boost thread callbacks for libgcrypt
#if defined(BOOST_HAS_PTHREADS)
@@ -76,7 +108,8 @@ bool initLibGCrypt()
cLog.msg(Log::PRIO_NOTICE) << "initLibGCrypt: libgcrypt init finished";
return true;
}
-
#endif
#endif
+#endif
+
diff --git a/src/keyDerivation.cpp b/src/keyDerivation.cpp
index 0bf74a7..459d6c9 100644
--- a/src/keyDerivation.cpp
+++ b/src/keyDerivation.cpp
@@ -34,142 +34,241 @@
#include "keyDerivation.h"
#include "threadUtils.hpp"
#include "datatypes.h"
+#include "endian.h"
#include <stdexcept>
#include <iostream>
+#include <sstream>
#include <string>
-#ifndef NOCRYPT
-#include <gcrypt.h>
-#include "mpi.h"
-#endif
-
-void KeyDerivation::setLogKDRate(const u_int8_t log_rate)
+void KeyDerivation::setLogKDRate(const int8_t log_rate)
{
- Lock lock(mutex_);
- if( log_rate < 49 )
- ld_kdr_ = log_rate;
+ WritersLock lock(mutex_);
+ ld_kdr_ = log_rate;
+ if(ld_kdr_ > (int8_t)(sizeof(seq_nr_t) * 8))
+ ld_kdr_ = sizeof(seq_nr_t) * 8;
}
//****** NullKeyDerivation ******
-bool NullKeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key)
+bool NullKeyDerivation::generate(kd_dir dir, satp_prf_label label, seq_nr_t seq_nr, Buffer& key)
{
- for(u_int32_t i=0; i < key.getLength(); ++i) key[i] = 0;
+ std::memset(key.getBuf(), 0, key.getLength());
return true;
}
#ifndef NOCRYPT
//****** AesIcmKeyDerivation ******
+AesIcmKeyDerivation::AesIcmKeyDerivation() : KeyDerivation(DEFAULT_KEY_LENGTH)
+{
+#ifndef USE_SSL_CRYPTO
+ handle_ = NULL;
+#endif
+}
+
+AesIcmKeyDerivation::AesIcmKeyDerivation(u_int16_t key_length) : KeyDerivation(key_length)
+{
+#ifndef USE_SSL_CRYPTO
+ handle_ = NULL;
+#endif
+}
+
AesIcmKeyDerivation::~AesIcmKeyDerivation()
{
- Lock lock(mutex_);
- if(cipher_)
- gcry_cipher_close( cipher_ );
+ WritersLock lock(mutex_);
+#ifndef USE_SSL_CRYPTO
+ if(handle_)
+ gcry_cipher_close(handle_);
+#endif
+}
+
+void AesIcmKeyDerivation::init(Buffer key, Buffer salt)
+{
+ WritersLock lock(mutex_);
+
+ master_salt_ = SyncBuffer(salt);
+ master_key_ = SyncBuffer(key);
+
+ updateMasterKey();
}
void AesIcmKeyDerivation::updateMasterKey()
{
- if(!cipher_)
+ if(master_key_.getLength()*8 != key_length_) {
+ char buf[STERROR_TEXT_MAX];
+ buf[0] = 0;
+ cLog.msg(Log::PRIO_CRIT) << "KeyDerivation::updateMasterKey: key lengths don't match";
return;
+ }
- gcry_error_t err = gcry_cipher_setkey( cipher_, master_key_.getBuf(), master_key_.getLength() );
- if( err ) {
+ if(master_salt_.getLength() != SALT_LENGTH) {
char buf[STERROR_TEXT_MAX];
buf[0] = 0;
- cLog.msg(Log::PRIO_ERR) << "KeyDerivation::updateMasterKey: Failed to set cipher key: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
+ cLog.msg(Log::PRIO_CRIT) << "KeyDerivation::updateMasterKey: salt lengths don't match";
+ return;
}
-}
-void AesIcmKeyDerivation::init(Buffer key, Buffer salt)
-{
- Lock lock(mutex_);
- if(cipher_)
- gcry_cipher_close( cipher_ );
+#ifndef USE_SSL_CRYPTO
+ int algo;
+ switch(key_length_) {
+ case 128: algo = GCRY_CIPHER_AES128; break;
+ case 192: algo = GCRY_CIPHER_AES192; break;
+ case 256: algo = GCRY_CIPHER_AES256; break;
+ default: {
+ char buf[STERROR_TEXT_MAX];
+ buf[0] = 0;
+ cLog.msg(Log::PRIO_CRIT) << "KeyDerivation::updateMasterKey: cipher key length of " << key_length_ << " Bits is not supported";
+ return;
+ }
+ }
+
+ if(handle_)
+ gcry_cipher_close(handle_);
+
+ gcry_error_t err = gcry_cipher_open(&handle_, algo, GCRY_CIPHER_MODE_CTR, 0);
+ if(err) {
+ char buf[STERROR_TEXT_MAX];
+ buf[0] = 0;
+ cLog.msg(Log::PRIO_ERR) << "KeyDerivation::updateMasterKey: Failed to open cipher: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
+ return;
+ }
- // TODO: hardcoded size
- gcry_error_t err = gcry_cipher_open( &cipher_, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0 );
- if( err ) {
+ err = gcry_cipher_setkey(handle_, master_key_.getBuf(), master_key_.getLength());
+ if(err) {
char buf[STERROR_TEXT_MAX];
buf[0] = 0;
- cLog.msg(Log::PRIO_ERR) << "KeyDerivation::init: Failed to open cipher: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
+ cLog.msg(Log::PRIO_ERR) << "KeyDerivation::updateMasterKey: Failed to set cipher key: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
return;
}
-
- master_salt_ = SyncBuffer(salt);
- master_key_ = SyncBuffer(key);
+#else
+ int ret = AES_set_encrypt_key(master_key_.getBuf(), master_key_.getLength()*8, &aes_key_);
+ if(ret) {
+ char buf[STERROR_TEXT_MAX];
+ buf[0] = 0;
+ cLog.msg(Log::PRIO_ERR) << "KeyDerivation::updateMasterKey: Failed to set ssl key (code: " << ret << ")";
+ return;
+ }
+#endif
+}
- updateMasterKey();
+std::string AesIcmKeyDerivation::printType()
+{
+ ReadersLock lock(mutex_);
+
+ std::stringstream sstr;
+ sstr << "AesIcm" << key_length_ << "KeyDerivation";
+ return sstr.str();
}
-bool AesIcmKeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key)
+bool AesIcmKeyDerivation::calcCtr(kd_dir dir, seq_nr_t* r, satp_prf_label label, seq_nr_t seq_nr)
{
- Lock lock(mutex_);
- if(!cipher_)
- {
- cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: cipher not opened";
- return false;
- }
+ *r = 0;
+ if(ld_kdr_ >= 0)
+ *r = seq_nr >> ld_kdr_;
- gcry_error_t err = gcry_cipher_reset( cipher_ );
- if( err ) {
+// TODO: determine whether to generate a key or not
+// if(key_store_[dir][label].key_.getBuf() && key_store_[dir][label].r_ == *r) {
+// if(!(*r) || (seq_nr % (*r)))
+// return false;
+// }
+
+ if(master_salt_.getLength() != SALT_LENGTH) {
char buf[STERROR_TEXT_MAX];
buf[0] = 0;
- cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: Failed to reset cipher: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
+ cLog.msg(Log::PRIO_CRIT) << "KeyDerivation::calcCtr: salt lengths don't match";
+ return false;
}
+ memcpy(ctr_.salt_.buf_, master_salt_.getBuf(), SALT_LENGTH);
+ ctr_.salt_.zero_ = 0;
+ ctr_.params_.label_ ^= label;
+ ctr_.params_.r_ ^= SEQ_NR_T_HTON(*r);
- // see at: http://tools.ietf.org/html/rfc3711#section-4.3
- // * Let r = index DIV key_derivation_rate (with DIV as defined above).
- // * Let key_id = <label> || r.
- // * Let x = key_id XOR master_salt, where key_id and master_salt are
- // aligned so that their least significant bits agree (right-
- // alignment).
- //
-
- Mpi r(48); // ld(kdr) <= 48
- if( ld_kdr_ == -1 ) // means key_derivation_rate = 0
- r = 0; // TODO: no new key should be generated if r == 0, except it is the first time
- else
- {
- Mpi seq(32);
- seq = seq_nr;
- Mpi rate(48);
- rate = 1;
- rate = rate.mul2exp(ld_kdr_);
- r = seq / rate;
- }
- // TODO: generate key only if index % r == 0, except it is the first time
+ return true;
+}
+
+bool AesIcmKeyDerivation::generate(kd_dir dir, satp_prf_label label, seq_nr_t seq_nr, Buffer& key)
+{
+// ReadersLock lock(mutex_);
+ WritersLock lock(mutex_);
- Mpi key_id(128); // TODO: hardcoded size
- Mpi l(128); // TODO: hardcoded size
- l = label;
- key_id = l.mul2exp(48) + r;
+ seq_nr_t r;
+ calcCtr(dir, &r, label, seq_nr);
+// TODO: return stored key
+// bool result = calcCtr(dir, &r, label, seq_nr);
+// if(!result) {
+// if(len > kd->key_store_[dir][label].key_.length_) {
+// log_printf(WARNING, "stored (old) key for label 0x%02X is too short, filling with zeros", label);
+// memset(key, 0, len);
+// len = kd->key_store_[dir][label].key_.length_;
+// }
+// memcpy(key, kd->key_store_[dir][label].key_.buf_, len);
+// return false;
+// }
- Mpi salt(master_salt_.getBuf(), master_salt_.getLength());
- Mpi x(128); // TODO: hardcoded size
- x = key_id ^ salt;
- size_t written;
- u_int8_t *ctr_buf = x.mul2exp(16).getNewBuf(&written); // TODO: hardcoded size
- err = gcry_cipher_setctr( cipher_ , ctr_buf, written );
- delete[] ctr_buf;
+#ifndef USE_SSL_CRYPTO
+ gcry_error_t err = gcry_cipher_reset(handle_);
+ if(err) {
+ char buf[STERROR_TEXT_MAX];
+ buf[0] = 0;
+ cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: Failed to reset cipher: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
+ }
- if( err ) {
+ err = gcry_cipher_setctr(handle_, ctr_.buf_, CTR_LENGTH);
+ if(err) {
char buf[STERROR_TEXT_MAX];
buf[0] = 0;
cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: Failed to set CTR: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
return false;
}
- for(u_int32_t i=0; i < key.getLength(); ++i) key[i] = 0;
- err = gcry_cipher_encrypt( cipher_, key, key.getLength(), NULL, 0);
- if( err ) {
+ std::memset(key.getBuf(), 0, key.getLength());
+ err = gcry_cipher_encrypt(handle_, key, key.getLength(), NULL, 0);
+ if(err) {
char buf[STERROR_TEXT_MAX];
buf[0] = 0;
cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: Failed to generate cipher bitstream: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
}
return true;
+#else
+ if(CTR_LENGTH != AES_BLOCK_SIZE) {
+ char buf[STERROR_TEXT_MAX];
+ buf[0] = 0;
+ cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to set cipher CTR: size don't fits";
+ return false;
+ }
+ u_int32_t num = 0;
+ std::memset(ecount_buf_, 0, AES_BLOCK_SIZE);
+ std::memset(key.getBuf(), 0, key.getLength());
+ AES_ctr128_encrypt(key.getBuf(), key.getBuf(), key.getLength(), &aes_key_, ctr_.buf_, ecount_buf_, &num);
+#endif
+
+// TODO: store key if key derivation rate is != 0
+// if(!ld_kdr_)
+// return true;
+
+// if(!kd->key_store_[dir][label].key_.buf_) {
+// kd->key_store_[dir][label].key_.length_ = 0;
+// kd->key_store_[dir][label].key_.buf_ = malloc(len);
+// if(!kd->key_store_[dir][label].key_.buf_)
+// return -2;
+
+// kd->key_store_[dir][label].key_.length_ = len;
+// }
+// else if(kd->key_store_[dir][label].key_.length_ < len) {
+// u_int8_t* tmp = realloc(kd->key_store_[dir][label].key_.buf_, len);
+// if(!tmp)
+// return -2;
+
+// kd->key_store_[dir][label].key_.buf_ = tmp;
+// kd->key_store_[dir][label].key_.length_ = len;
+// }
+
+// memcpy(kd->key_store_[dir][label].key_.buf_, key, len);
+// kd->key_store_[dir][label].r_ = r;
+
+ return true;
}
#endif
diff --git a/src/keyDerivation.h b/src/keyDerivation.h
index 6dd8080..6b20983 100644
--- a/src/keyDerivation.h
+++ b/src/keyDerivation.h
@@ -38,7 +38,11 @@
#include "syncBuffer.h"
#ifndef NOCRYPT
+#ifndef USE_SSL_CRYPTO
#include <gcrypt.h>
+#else
+#include <openssl/aes.h>
+#endif
#endif
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
@@ -50,19 +54,24 @@ typedef enum {
LABEL_SATP_SALT = 0x02,
} satp_prf_label;
+typedef enum {
+ KD_INBOUND = 0,
+ KD_OUTBOUND = 1
+} kd_dir;
class KeyDerivation
{
public:
- KeyDerivation() : ld_kdr_(0), master_salt_(0), master_key_(0) {};
+ KeyDerivation() : ld_kdr_(0), key_length_(0), master_salt_(0), master_key_(0) {};
+ KeyDerivation(u_int16_t key_length) : ld_kdr_(0), key_length_(key_length), master_salt_(0), master_key_(0) {};
virtual ~KeyDerivation() {};
- void setLogKDRate(const u_int8_t ld_rate);
+ void setLogKDRate(const int8_t ld_rate);
virtual void init(Buffer key, Buffer salt) = 0;
- virtual bool generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key) = 0;
+ virtual bool generate(kd_dir dir, satp_prf_label label, seq_nr_t seq_nr, Buffer& key) = 0;
- virtual std::string printType() { return "KeyDerivation"; };
+ virtual std::string printType() { return "GenericKeyDerivation"; };
protected:
virtual void updateMasterKey() = 0;
@@ -72,18 +81,20 @@ protected:
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
- Lock lock(mutex_);
+ WritersLock lock(mutex_);
ar & ld_kdr_;
+ ar & key_length_;
ar & master_salt_;
ar & master_key_;
updateMasterKey();
}
int8_t ld_kdr_; // ld(key_derivation_rate)
+ u_int16_t key_length_;
SyncBuffer master_salt_;
SyncBuffer master_key_;
- Mutex mutex_;
+ SharedMutex mutex_;
};
BOOST_IS_ABSTRACT(KeyDerivation)
@@ -97,7 +108,7 @@ public:
~NullKeyDerivation() {};
void init(Buffer key, Buffer salt) {};
- bool generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key);
+ bool generate(kd_dir dir, satp_prf_label label, seq_nr_t seq_nr, Buffer& key);
std::string printType() { return "NullKeyDerivation"; };
@@ -119,17 +130,24 @@ private:
class AesIcmKeyDerivation : public KeyDerivation
{
public:
- AesIcmKeyDerivation() : cipher_(NULL) {};
+ AesIcmKeyDerivation();
+ AesIcmKeyDerivation(u_int16_t key_length);
~AesIcmKeyDerivation();
-
+
+ static const u_int16_t DEFAULT_KEY_LENGTH = 128;
+ static const u_int16_t CTR_LENGTH = 16;
+ static const u_int16_t SALT_LENGTH = 14;
+
void init(Buffer key, Buffer salt);
- bool generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key);
+ bool generate(kd_dir dir, satp_prf_label label, seq_nr_t seq_nr, Buffer& key);
- std::string printType() { return "AesIcmKeyDerivation"; };
+ std::string printType();
private:
void updateMasterKey();
+ bool calcCtr(kd_dir dir, seq_nr_t* r, satp_prf_label label, seq_nr_t seq_nr);
+
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
@@ -137,7 +155,36 @@ private:
ar & boost::serialization::base_object<KeyDerivation>(*this);
}
- gcry_cipher_hd_t cipher_;
+#ifndef USE_SSL_CRYPTO
+ gcry_cipher_hd_t handle_;
+#else
+ AES_KEY aes_key_;
+ u_int8_t ecount_buf_[AES_BLOCK_SIZE];
+#endif
+
+ union __attribute__((__packed__)) key_derivation_aesctr_ctr_union {
+ u_int8_t buf_[CTR_LENGTH];
+ struct __attribute__ ((__packed__)) {
+ u_int8_t buf_[SALT_LENGTH];
+ u_int16_t zero_;
+ } salt_;
+#ifndef ANYTUN_02_COMPAT
+ struct __attribute__((__packed__)) {
+ u_int8_t fill_[SALT_LENGTH - sizeof(u_int8_t) - sizeof(seq_nr_t)];
+ u_int8_t label_;
+ seq_nr_t r_;
+ u_int16_t zero_;
+ } params_;
+#else
+ struct __attribute__((__packed__)) {
+ u_int8_t fill_[SALT_LENGTH - sizeof(u_int8_t) - 2 - sizeof(seq_nr_t)];
+ u_int8_t label_;
+ u_int8_t r_fill_[2];
+ seq_nr_t r_;
+ u_int16_t zero_;
+ } params_;
+#endif
+ } ctr_;
};
#endif
diff --git a/src/mpi.cpp b/src/mpi.cpp
deleted file mode 100644
index 0a240fd..0000000
--- a/src/mpi.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * anytun
- *
- * The secure anycast tunneling protocol (satp) defines a protocol used
- * for communication between any combination of unicast and anycast
- * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
- * mode and allows tunneling of every ETHER TYPE protocol (e.g.
- * ethernet, ip, arp ...). satp directly includes cryptography and
- * message authentication based on the methodes used by SRTP. It is
- * intended to deliver a generic, scaleable and secure solution for
- * tunneling and relaying of packets of any protocol.
- *
- *
- * Copyright (C) 2007-2008 Othmar Gsenger, Erwin Nindl,
- * Christian Pointner <satp@wirdorange.org>
- *
- * This file is part of Anytun.
- *
- * Anytun is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * Anytun 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 anytun. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "mpi.h"
-
-#include "datatypes.h"
-#include "cipher.h"
-
-#include <stdexcept>
-#include <gcrypt.h>
-
-#include <iostream>
-#include <cstring>
-
-Mpi::Mpi() : val_(NULL)
-{
- val_ = gcry_mpi_set_ui(NULL, 0);
- if(!val_)
- throw std::bad_alloc();
-}
-
-Mpi::Mpi(u_int8_t length) : val_(NULL)
-{
- val_ = gcry_mpi_new(length);
- if(!val_)
- throw std::bad_alloc();
-}
-
-Mpi::Mpi(const Mpi &src) : val_(NULL)
-{
- val_ = gcry_mpi_copy(src.val_);
- if(!val_)
- throw std::bad_alloc();
-}
-
-Mpi::Mpi(const u_int8_t* src, u_int32_t len) : val_(NULL)
-{
- u_int8_t* src_cpy = new u_int8_t[len+1];
- if(!src_cpy)
- throw std::bad_alloc();
-
- u_int8_t* buf = src_cpy;
- u_int32_t buf_len = len;
- if(src[0] & 0x80) // this would be a negative number, scan can't handle this :(
- {
- src_cpy[0] = 0;
- buf++;
- buf_len++;
- }
- std::memcpy(buf, src, len);
-
- gcry_mpi_scan( &val_, GCRYMPI_FMT_STD, src_cpy, buf_len, NULL );
- delete[] src_cpy;
- if(!val_)
- throw std::bad_alloc();
-}
-
-Mpi::~Mpi()
-{
- gcry_mpi_release( val_ );
-}
-
-
-void Mpi::operator=(const Mpi &src)
-{
- gcry_mpi_release( val_ );
- val_ = gcry_mpi_copy(src.val_);
- if(!val_)
- throw std::bad_alloc();
-}
-
-void Mpi::operator=(const u_int32_t src)
-{
- gcry_mpi_release( val_ );
- val_ = gcry_mpi_set_ui(NULL, src);
- if(!val_)
- throw std::bad_alloc();
-}
-
-Mpi Mpi::operator+(const Mpi &b) const
-{
- Mpi res;
- gcry_mpi_add(res.val_, val_, b.val_);
- return res;
-}
-
-Mpi Mpi::operator+(const u_int32_t &b) const
-{
- Mpi res;
- gcry_mpi_add_ui(res.val_, val_, b);
- return res;
-}
-
-Mpi Mpi::operator*(const u_int32_t n) const
-{
- Mpi res;
- gcry_mpi_mul_ui(res.val_, val_, n);
- return res;
-}
-
-Mpi Mpi::operator/(const Mpi &b) const
-{
- Mpi res;
- gcry_mpi_div(res.val_, NULL, val_, b.val_, 0);
- return res;
-}
-
-//TODO: this is outstandingly ugly!!!!!!!!
-Mpi Mpi::operator^(const Mpi &b) const
-{
- u_int32_t a_len = gcry_mpi_get_nbits(val_);
- u_int32_t b_len = gcry_mpi_get_nbits(b.val_);
-
- Mpi res = (a_len >= b_len) ? Mpi(*this) : Mpi(b);
-
- for(u_int32_t i=0; i<a_len && i<b_len; i++) {
- if(gcry_mpi_test_bit(val_, i) ^ gcry_mpi_test_bit(b.val_, i))
- gcry_mpi_set_bit(res.val_, i);
- else
- gcry_mpi_clear_bit(res.val_, i);
- }
- return res;
-}
-
-Mpi Mpi::mul2exp(u_int32_t e) const
-{
- Mpi res;
- gcry_mpi_mul_2exp( res.val_, val_, e );
- return res;
-}
-
-//TODO: problem, seems as gcry_mpi_(a)print doesn't work for mpi values of '0'
-u_int8_t* Mpi::getNewBuf(size_t* written) const
-{
- u_int8_t* res_cpy;
- gcry_mpi_aprint( GCRYMPI_FMT_STD, &res_cpy, written, val_ );
- if(!res_cpy)
- throw std::bad_alloc();
-
- u_int8_t* buf = res_cpy;
- if(*written > 1 && ! (res_cpy[0])) // positive number with highestBit set
- {
- buf++;
- (*written)--;
- }
-
- u_int8_t* res = new u_int8_t[*written];
- if(!res)
- throw std::bad_alloc();
-
- std::memcpy(res, buf, *written);
-
- gcry_free(res_cpy);
-
- return res;
-}
-
-//TODO: why does this not work ?????
-std::string Mpi::getHexDump() const
-{
-// u_int8_t *buf;
-// u_int32_t len;
-// gcry_mpi_aprint( GCRYMPI_FMT_HEX, &buf, &len, val_ );
-// std::string res(buf, len);
-// delete[] buf;
-
- gcry_mpi_dump( val_ );
- std::string res("\n");
- return res;
-}
-
-u_int32_t Mpi::getLength() const
-{
- return gcry_mpi_get_nbits( val_ );
-}
diff --git a/src/mpi.h b/src/mpi.h
deleted file mode 100644
index d85be2f..0000000
--- a/src/mpi.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * anytun
- *
- * The secure anycast tunneling protocol (satp) defines a protocol used
- * for communication between any combination of unicast and anycast
- * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
- * mode and allows tunneling of every ETHER TYPE protocol (e.g.
- * ethernet, ip, arp ...). satp directly includes cryptography and
- * message authentication based on the methodes used by SRTP. It is
- * intended to deliver a generic, scaleable and secure solution for
- * tunneling and relaying of packets of any protocol.
- *
- *
- * Copyright (C) 2007-2008 Othmar Gsenger, Erwin Nindl,
- * Christian Pointner <satp@wirdorange.org>
- *
- * This file is part of Anytun.
- *
- * Anytun is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * Anytun 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 anytun. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _MPI_H_
-#define _MPI_H_
-
-#include "datatypes.h"
-#include "buffer.h"
-
-#include <gcrypt.h>
-
-
-/**
- * This class is a wrapper for the libgcrypt multi precision integer library [1]
- * [1] http://www.gnupg.org/documentation/manuals/gcrypt/MPI-library.html
- *
- */
-
-class Mpi
-{
-public:
- Mpi();
- virtual ~Mpi();
- Mpi(u_int8_t length);
- Mpi(const Mpi &src);
- Mpi(const u_int8_t * src, u_int32_t len);
-
- void operator=(const Mpi &src);
- void operator=(u_int32_t src);
- Mpi operator+(const Mpi &b) const;
- Mpi operator+(const u_int32_t &b) const;
- Mpi operator*(const u_int32_t n) const;
- Mpi operator/(const Mpi &b) const;
-
- Mpi operator^(const Mpi &b) const;
-
- Mpi mul2exp(u_int32_t e) const; // value * 2^e
-
- /**
- * returns a new[] u_int8_t* buffer with the MPI value in the
- * GCRYMPI_FMT_STD (2-complement stored without a length header).<br>
- * you have to delete it by hand with delete[]!
- * @param buf_len size of the new buffer that is returned
- * @return a byte buffer of size buf_len
- */
- u_int8_t *getNewBuf(size_t* written) const;
- std::string getHexDump() const;
- u_int32_t getLength() const;
-
-protected:
- gcry_mpi_t val_;
-};
-
-
-
-#endif
diff --git a/src/threadUtils.hpp b/src/threadUtils.hpp
index 960e757..85500c1 100644
--- a/src/threadUtils.hpp
+++ b/src/threadUtils.hpp
@@ -30,12 +30,17 @@
*/
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
+#include <boost/thread/shared_mutex.hpp>
#include "datatypes.h"
#ifndef __THREADUTILS__
#define __THREADUTILS__
typedef boost::mutex::scoped_lock Lock;
typedef boost::mutex Mutex;
+typedef boost::shared_mutex SharedMutex;
+typedef boost::shared_lock<SharedMutex> ReadersLock;
+typedef boost::unique_lock<SharedMutex> WritersLock;
+
class Semaphore
{
public: