summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--README1
-rw-r--r--buffer.cpp74
-rw-r--r--buffer.h13
-rw-r--r--cypher.cpp196
-rw-r--r--cypher.h21
-rw-r--r--keyDerivation.cpp113
-rw-r--r--keyDerivation.h16
-rw-r--r--tunDevice.cpp2
-rw-r--r--tunDevice.h2
10 files changed, 273 insertions, 169 deletions
diff --git a/Makefile b/Makefile
index b1ef755..c95b630 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ CFLAGS = -g -Wall
C++ = g++
CCFLAGS = -g -Wall
LD = g++
-LDFLAGS = -g -O2 -ldl -lpthread -lsrtp -lgcrypt
+LDFLAGS = -g -Wall -O2 -ldl -lpthread -lsrtp -lgcrypt
OPENVPNDEPS = openvpn/tun.o \
openvpn/error.o \
@@ -97,6 +97,8 @@ anytun.o: anytun.cpp
clean:
rm -f *.o
rm -f $(EXECUTABLE)
+ rm -f -r doc/html/*
+ rm -f -r doc/latex/*
doxygen:
doxygen Doxyfile
diff --git a/README b/README
index 830500b..b1ecf0b 100644
--- a/README
+++ b/README
@@ -2,6 +2,7 @@ Building
========
* install libSRTP (as seen below)
+* install libgcrypt
* install libgcrypt11-dev
* ./configure
* make
diff --git a/buffer.cpp b/buffer.cpp
index 6d16467..4bcb9b8 100644
--- a/buffer.cpp
+++ b/buffer.cpp
@@ -87,6 +87,43 @@ void Buffer::operator=(const Buffer &src)
length_ = 0;
}
+void Buffer::operator=(const seq_nr_t &src)
+{
+ if(buf_)
+ delete[] buf_;
+
+ length_ = sizeof(src);
+
+ buf_ = new u_int8_t[length_];
+
+ if( buf_ )
+ {
+ for( u_int32_t index = 0; index <= length_; index++ )
+ buf_[index] = (src>>index) & 0xFF;
+ }
+ else
+ length_ = 0;
+}
+
+
+void Buffer::operator=(const sender_id_t &src)
+{
+ if(buf_)
+ delete[] buf_;
+
+ length_ = sizeof(src);
+
+ buf_ = new u_int8_t[length_];
+
+ if( buf_ )
+ {
+ for( u_int32_t index = 0; index <= length_; index++ )
+ buf_[index] = (src>>index) & 0xFF;
+ }
+ else
+ length_ = 0;
+}
+
u_int32_t Buffer::resizeFront(u_int32_t new_length)
{
if(length_ == new_length)
@@ -171,7 +208,42 @@ void Buffer::printHexDump() const
for( u_int32_t index = 0; index < length_; index++ )
{
- std::sprintf(text, "%#x", buf_[index]);
+ std::sprintf(text, "%#4x", buf_[index]);
std::cout << text << " ";
+ if( ((index+1) % 10) == 0 )
+ std::cout << std::endl;
}
}
+
+Buffer Buffer::operator^(const Buffer &xor_by) const
+{
+ Buffer res(length_);
+ if( xor_by.getLength() > length_ )
+ throw std::out_of_range("buffer::operator^ const");
+
+ for( u_int32_t index = 0; index < xor_by.getLength(); index++ )
+ res[index] = buf_[index] ^ xor_by[index];
+
+ return res;
+}
+
+Buffer Buffer::leftByteShift(u_int32_t width) const
+{
+ Buffer res(length_+width);
+
+ for( u_int32_t index = 0; index < length_; index++ )
+ res[index+width] = buf_[index];
+
+ return res;
+}
+
+Buffer Buffer::rightByteShift(u_int32_t width) const
+{
+ Buffer res(length_);
+
+ for( u_int32_t index = 0; index < length_-width; index++ )
+ res[index] = buf_[index+width];
+
+ return res;
+}
+
diff --git a/buffer.h b/buffer.h
index 0506e98..37bbc29 100644
--- a/buffer.h
+++ b/buffer.h
@@ -45,6 +45,13 @@ public:
virtual ~Buffer();
Buffer(const Buffer &src);
void operator=(const Buffer &src);
+ void operator=(const seq_nr_t &src);
+ void operator=(const sender_id_t &src);
+
+ // math operations to calculate IVs and keys
+ virtual Buffer operator^(const Buffer &xor_by) const;
+ virtual Buffer leftByteShift(u_int32_t width) const;
+ virtual Buffer rightByteShift(u_int32_t width) const;
u_int32_t resizeFront(u_int32_t new_length);
u_int32_t resizeBack(u_int32_t new_length);
@@ -54,12 +61,12 @@ public:
u_int8_t operator[](u_int32_t index) const;
void printHexDump() const;
-protected:
operator u_int8_t*(); // just for write/read tun and packetSource
+protected:
friend class TunDevice;
friend class UDPPacketSource;
- friend class AesIcmCypher;
- friend class KeyDerivation; //
+// friend class AesIcmCypher;
+// friend class KeyDerivation; //
u_int8_t *buf_;
u_int32_t length_;
diff --git a/cypher.cpp b/cypher.cpp
index 6ad656b..f180745 100644
--- a/cypher.cpp
+++ b/cypher.cpp
@@ -29,15 +29,15 @@
*/
#include <stdexcept>
-#include <vector>
#include <iostream>
+#include <string>
#include "cypher.h"
#include "keyDerivation.h"
extern "C" {
-#include <srtp/crypto_kernel.h>
+#include <gcrypt.h>
}
void Cypher::cypher(Buffer& buf, seq_nr_t seq_nr, sender_id_t sender_id)
@@ -65,129 +65,109 @@ Buffer NullCypher::getBitStream(u_int32_t length, seq_nr_t seq_nr, sender_id_t s
}
+const char* AesIcmCypher::MIN_GCRYPT_VERSION = "1.2.3";
+bool AesIcmCypher::gcrypt_initialized_ = false;
+
+
+AesIcmCypher::AesIcmCypher() : salt_(Buffer(14))
+{
+ gcry_error_t err;
+ if( !gcry_check_version( MIN_GCRYPT_VERSION ) )
+ {
+ std::cerr << "Invalid Version of libgcrypt, should be >= ";
+ std::cerr << MIN_GCRYPT_VERSION << std::endl;
+ return;
+ }
+
+ if( !gcrypt_initialized_ )
+ {
+ /* Allocate a pool of secure memory. This also drops priviliges
+ on some systems. */
+ err = gcry_control(GCRYCTL_INIT_SECMEM, GCRYPT_SEC_MEM, 0);
+ if( err )
+ {
+ std::cerr << "Failed to allocate " << GCRYPT_SEC_MEM << "bytes of secure memory: ";
+ std::cerr << gpg_strerror( err ) << std::endl;
+ return;
+ }
+ gcrypt_initialized_ = true;
+ }
+
+ /* Tell Libgcrypt that initialization has completed. */
+ err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED);
+ if( err )
+ {
+ std::cerr << "Failed to finish the initialization of libgcrypt";
+ std::cerr << gpg_strerror( err ) << std::endl;
+ return;
+ }
+
+ gcry_cipher_open( &cipher_, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0 );
+
+ std::cout << "Keysize: " << gcry_cipher_get_algo_keylen( GCRY_CIPHER_AES128 ) << std::endl;
+}
+
+
+AesIcmCypher::~AesIcmCypher()
+{
+ gcry_cipher_close( cipher_ );
+}
+
+
void AesIcmCypher::setKey(Buffer key)
{
- key_ = key;
+ gcry_error_t err;
+ err = gcry_cipher_setkey( cipher_, key.getBuf(), 16 );
+ if( err )
+ std::cerr << "Failed to set cipher key: " << gpg_strerror( err ) << std::endl;
}
void AesIcmCypher::setSalt(Buffer salt)
{
- salt = salt;
+ salt_ = salt;
}
Buffer AesIcmCypher::getBitStream(u_int32_t length, seq_nr_t seq_nr, sender_id_t sender_id)
{
+ gcry_error_t err;
+
Buffer buf(length);
- extern cipher_type_t aes_icm;
- err_status_t status = err_status_ok;
- cipher_t* cipher = NULL;
- v128_t iv, sid, seq, salt;
-
- v128_set_to_zero(&iv);
- v128_set_to_zero(&sid);
- v128_set_to_zero(&seq);
- v128_set_to_zero(&salt);
-
- // allocate cipher
- // FIXXME: why we do not can do this???
-// status = cipher_type_alloc(&aes_icm, &cipher, key_.getLength());
- status = cipher_type_alloc(&aes_icm, &cipher, 30);
- if( status )
+
+// // set IV
+// // where the 128-bit integer value IV SHALL be defined by the SSRC, the
+// // SRTP packet index i, and the SRTP session salting key k_s, as below.
+// //
+// // IV = (k_s * 2^16) XOR (SSRC * 2^64) XOR (i * 2^16)
+// // sizeof(k_s) = 112 bit, random
+
+ Buffer iv(16), seq, sid;
+
+ sid = sender_id;
+ seq = seq_nr;
+
+ iv = (salt_.leftByteShift(2) ^ sid.leftByteShift(8)) ^ sid.leftByteShift(2);
+
+ err = gcry_cipher_setiv( cipher_, iv.getBuf(), 0 );
+ if( err )
+ {
+ std::cerr << "Failed to set cipher IV: " << gpg_strerror( err ) << std::endl;
return Buffer(0);
+ }
+
+ err = gcry_cipher_reset( cipher_ );
+ if( err )
+ {
+ std::cerr << "Failed to reset cipher: " << gpg_strerror( err ) << std::endl;
+ return Buffer(0);
+ }
- // init cipher
- status = cipher_init(cipher, key_.getBuf(), direction_any);
- if( status )
+ err = gcry_cipher_encrypt( cipher_, buf, buf.getLength(), 0, 0 );
+ if( err )
{
- cipher_dealloc(cipher);
+ std::cerr << "Failed to generate cipher bitstream: " << gpg_strerror( err ) << std::endl;
return Buffer(0);
}
- // set IV
- // where the 128-bit integer value IV SHALL be defined by the SSRC, the
- // SRTP packet index i, and the SRTP session salting key k_s, as below.
- //
- // IV = (k_s * 2^16) XOR (SSRC * 2^64) XOR (i * 2^16)
- // sizeof(k_s) = 112 bit, random
-
- seq.v64[0] = seq_nr;
- sid.v64[0] = sender_id;
- v128_copy_octet_string(&salt, salt_.getBuf());
- v128_left_shift(&salt, 16);
- v128_left_shift(&sid, 64);
- v128_left_shift(&seq, 16);
-
- v128_xor(&iv, &salt, &sid);
- v128_xor(&iv, &iv, &seq);
-
- status = cipher_set_iv(cipher, &iv);
- if( status )
- cipher_dealloc(cipher);
-
- status = cipher_output(cipher, buf, length);
- status = cipher_dealloc(cipher);
return buf;
}
-//
-//void AesIcmCypher::cypher(Buffer& buf, seq_nr_t seq_nr, sender_id_t sender_id)
-//{
-// extern cipher_type_t aes_icm;
-// err_status_t status = err_status_ok;
-// cipher_t* cipher = NULL;
-// uint32_t length = 0;
-// v128_t iv, sid, seq, salt;
-//
-// v128_set_to_zero(&iv);
-// v128_set_to_zero(&sid);
-// v128_set_to_zero(&seq);
-// v128_set_to_zero(&salt);
-//
-// std::cout << "AesIcmCypher::cypher called" << std::endl;
-// // allocate cipher
-// // FIXXME: why we do not can do this???
-//// status = cipher_type_alloc(&aes_icm, &cipher, key_.getLength());
-// status = cipher_type_alloc(&aes_icm, &cipher, 30);
-// if( status )
-// return;
-//
-// // init cipher
-// status = cipher_init(cipher, key_.getBuf(), direction_any);
-// if( status )
-// {
-// cipher_dealloc(cipher);
-// return;
-// }
-//
-// // set IV
-// // where the 128-bit integer value IV SHALL be defined by the SSRC, the
-// // SRTP packet index i, and the SRTP session salting key k_s, as below.
-// //
-// // IV = (k_s * 2^16) XOR (SSRC * 2^64) XOR (i * 2^16)
-// // sizeof(k_s) = 112 bit, random
-//
-//// iv.v32[0] ^= 0;
-//// iv.v32[1] ^= sender_id;
-//// iv.v32[2] ^= (seq_nr >> 16);
-//// iv.v32[3] ^= (seq_nr << 16);
-//
-// seq.v64[0] = seq_nr;
-// sid.v64[0] = sender_id;
-// v128_copy_octet_string(&salt, salt_.getBuf());
-// v128_left_shift(&salt, 16);
-// v128_left_shift(&sid, 64);
-// v128_left_shift(&seq, 16);
-//
-// v128_xor(&iv, &salt, &sid);
-// v128_xor(&iv, &iv, &seq);
-//
-// status = cipher_set_iv(cipher, &iv);
-// if( status )
-// cipher_dealloc(cipher);
-//
-// length = buf.getLength();
-//
-// status = cipher_encrypt(cipher, buf, &length);
-// status = cipher_dealloc(cipher);
-//}
-//
diff --git a/cypher.h b/cypher.h
index c42b79b..ae56881 100644
--- a/cypher.h
+++ b/cypher.h
@@ -31,9 +31,15 @@
#ifndef _CYPHER_H_
#define _CYPHER_H_
+
+
#include "datatypes.h"
#include "buffer.h"
+extern "C" {
+#include <gcrypt.h>
+}
+
class Cypher
{
@@ -59,17 +65,22 @@ protected:
class AesIcmCypher : public Cypher
{
public:
- AesIcmCypher() : key_(Buffer(0)), salt_(Buffer(14)) {};
+ AesIcmCypher();
+ ~AesIcmCypher();
void setKey(Buffer key);
void setSalt(Buffer salt);
-// void cypher(Buffer& buf, seq_nr_t seq_nr, sender_id_t sender_id);
+
+ static const char* MIN_GCRYPT_VERSION;
+ static const u_int32_t GCRYPT_SEC_MEM = 16384; // 16k secure memory
protected:
- Buffer getBitStream(u_int32_t length, seq_nr_t seq_nr, sender_id_t sender_id);
+ Buffer getBitStream(u_int32_t length, seq_nr_t seq_nr, sender_id_t sender_id);
+ gcry_cipher_hd_t cipher_;
+ Buffer salt_;
private:
- Buffer key_;
- Buffer salt_; // size: 112 bit
+ static bool gcrypt_initialized_;
};
+
#endif
diff --git a/keyDerivation.cpp b/keyDerivation.cpp
index 95b94d2..f8e3c55 100644
--- a/keyDerivation.cpp
+++ b/keyDerivation.cpp
@@ -31,82 +31,109 @@
#include "keyDerivation.h"
+#include <stdexcept>
+#include <iostream>
+#include <string>
+
extern "C" {
-#include <srtp/crypto_kernel.h>
+#include <gcrypt.h>
}
-err_status_t KeyDerivation::init(Buffer key, Buffer salt)
+const char* KeyDerivation::MIN_GCRYPT_VERSION = "1.2.3";
+
+void KeyDerivation::init(Buffer key, Buffer salt)
{
- extern cipher_type_t aes_icm;
- err_status_t status = err_status_ok;
+ gcry_error_t err;
+ if( !gcry_check_version( MIN_GCRYPT_VERSION ) )
+ {
+ std::cerr << "Invalid Version of libgcrypt, should be >= " << MIN_GCRYPT_VERSION << std::endl;
+ return;
+ }
- salt_ = salt;
+ /* Allocate a pool of 16k secure memory. This also drops priviliges
+ * on some systems. */
+ err = gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0);
+ if( err )
+ {
+ std::cerr << "Failed to allocate 16k secure memory: " << gpg_strerror( err ) << std::endl;
+ return;
+ }
- // allocate cipher
- // FIXXME: why we do not can do this??
-// status = cipher_type_alloc(&aes_icm, &cipher_, key.getLength());
- status = cipher_type_alloc(&aes_icm, &cipher_, 30);
- if( status )
- return status;
+ /* Tell Libgcrypt that initialization has completed. */
+ err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED);
+ if( err )
+ {
+ std::cerr << "Failed to finish the initialization of libgcrypt" << gpg_strerror( err ) << std::endl;
+ return;
+ }
- // init cipher
- status = cipher_init(cipher_, key.getBuf(), direction_any);
- if( status )
- cipher_dealloc(cipher_);
+ err = gcry_cipher_open( &cipher_, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0 );
+ if( err )
+ {
+ std::cerr << "Failed to open cipher: " << gpg_strerror( err ) << std::endl;
+ return;
+ }
- return status;
}
-err_status_t KeyDerivation::setLogKDRate(const uint8_t log_rate)
+void KeyDerivation::setLogKDRate(const uint8_t log_rate)
{
if( log_rate < 49 )
- {
ld_kdr_ = log_rate;
- return err_status_ok;
- }
- return err_status_bad_param;
}
-err_status_t KeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key, uint32_t length)
+void KeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key, u_int32_t length)
{
- err_status_t status = err_status_ok;
- v128_t iv, salt, key_id;
- uint8_t r = 0;
+ gcry_error_t err;
+ u_int8_t r = 0;
+ Buffer iv(16);
+
+ u_int8_t tmp_key_id[16];
- v128_set_to_zero(&iv);
- v128_set_to_zero(&salt);
- v128_set_to_zero(&key_id);
+ // 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).
+ //
- // look at: http://tools.ietf.org/html/rfc3711#section-4.3
if( ld_kdr_ == -1 ) // means key_derivation_rate = 0
r = 0;
else
// FIXXME: kdr can be greater than 2^32 (= 2^48)
r = seq_nr / ( 0x01 << ld_kdr_ );
- key_id.v32[0] = (label << 8);
- key_id.v32[0] += r;
- v128_copy_octet_string(&salt, salt_.getBuf());
- v128_xor(&iv, &salt, &key_id);
- status = cipher_set_iv(cipher_, &iv);
- if( status )
+ // FIXXME: why i cant access key_id via operator []?
+ for(u_int8_t i=0; i<sizeof(tmp_key_id); i++)
+ tmp_key_id[i] = 0x00;
+
+ tmp_key_id[0] = r;
+ tmp_key_id[1] = label;
+
+ Buffer key_id(tmp_key_id, 16);
+
+ iv = key_id ^ salt_;
+
+ err = gcry_cipher_reset( cipher_ );
+ if( err )
{
- KeyDerivation::clear();
- return status;
+ std::cerr << "Failed to reset cipher: " << gpg_strerror( err ) << std::endl;
}
- /* generate keystream output */
- status = cipher_output(cipher_, key, length);
-
- return status;
+ err = gcry_cipher_encrypt( cipher_, key, key.getLength(), 0, 0 );
+ if( err )
+ {
+ std::cerr << "Failed to generate cipher bitstream: " << gpg_strerror( err ) << std::endl;
+ }
}
-err_status_t KeyDerivation::clear()
+void KeyDerivation::clear()
{
- return cipher_dealloc(cipher_);
+ gcry_cipher_close( cipher_ );
}
diff --git a/keyDerivation.h b/keyDerivation.h
index c65df0e..a0c1a01 100644
--- a/keyDerivation.h
+++ b/keyDerivation.h
@@ -36,7 +36,7 @@
extern "C" {
- #include <srtp/crypto_kernel.h>
+ #include <gcrypt.h>
}
@@ -52,16 +52,20 @@ public:
KeyDerivation() : ld_kdr_(-1), cipher_(NULL) {};
virtual ~KeyDerivation() {};
- err_status_t init(Buffer key, Buffer salt);
- err_status_t setLogKDRate(const uint8_t ld_rate);
- err_status_t generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key, uint32_t length);
- err_status_t clear();
+ void init(Buffer key, Buffer salt);
+ void setLogKDRate(const u_int8_t ld_rate);
+ void generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key, u_int32_t length);
+ void clear();
+
protected:
int8_t ld_kdr_; // ld(key_derivation_rate)
Buffer salt_;
+ static const char* MIN_GCRYPT_VERSION;
- cipher_t* cipher_;
+ gcry_cipher_hd_t cipher_;
};
+
#endif
+
diff --git a/tunDevice.cpp b/tunDevice.cpp
index 40d0f9d..81f4cbb 100644
--- a/tunDevice.cpp
+++ b/tunDevice.cpp
@@ -153,7 +153,7 @@ u_int32_t TunDevice::getType()
return TYPE_UNDEF;
}
-char* TunDevice::getTypeString()
+const char* TunDevice::getTypeString()
{
if(!dev_)
return NULL;
diff --git a/tunDevice.h b/tunDevice.h
index 8be2050..7e4493c 100644
--- a/tunDevice.h
+++ b/tunDevice.h
@@ -53,7 +53,7 @@ public:
char* getActualName();
u_int32_t getType();
- char* getTypeString();
+ const char* getTypeString();
private:
void operator=(const TunDevice &src);