summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOthmar Gsenger <otti@anytun.org>2014-11-19 19:56:32 +0000
committerOthmar Gsenger <otti@anytun.org>2014-11-19 19:56:32 +0000
commit2d712656364cf982a56fa4e7a8f1eab714240266 (patch)
treea629610fe84386a3e184399a55003736bf9f7569
parentfixed linker error (diff)
openssl crypt new implementation added
-rw-r--r--src/buffer.cpp5
-rw-r--r--src/buffer.h1
-rw-r--r--src/crypto/interface.cpp28
-rw-r--r--src/crypto/interface.h47
-rw-r--r--src/crypto/openssl.cpp49
-rw-r--r--src/crypto/openssl.h4
6 files changed, 133 insertions, 1 deletions
diff --git a/src/buffer.cpp b/src/buffer.cpp
index 60df054..e4626de 100644
--- a/src/buffer.cpp
+++ b/src/buffer.cpp
@@ -222,6 +222,11 @@ uint8_t* Buffer::getBuf()
return buf_;
}
+const uint8_t* Buffer::getConstBuf() const
+{
+ return buf_;
+}
+
uint8_t& Buffer::operator[](uint32_t index)
{
if(index >= length_) {
diff --git a/src/buffer.h b/src/buffer.h
index f4973ce..3299325 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -68,6 +68,7 @@ public:
uint32_t getLength() const;
virtual void setLength(uint32_t new_length);
uint8_t* getBuf();
+ const uint8_t* getConstBuf() const;
uint8_t& operator[](uint32_t index);
uint8_t operator[](uint32_t index) const;
std::string getHexDump() const;
diff --git a/src/crypto/interface.cpp b/src/crypto/interface.cpp
index 3ed929e..2ae9c16 100644
--- a/src/crypto/interface.cpp
+++ b/src/crypto/interface.cpp
@@ -44,6 +44,8 @@
*/
#include "interface.h"
+#include "../log.h"
+#include "../endian.h"
namespace crypto {
@@ -115,4 +117,30 @@ bool Interface::init()
return true;
};
+void Interface::calcCryptCtr(const Buffer& masterkey, const Buffer& mastersalt, kd_dir_t dir, role_t role, satp_prf_label_t label, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux, cipher_aesctr_ctr_t * ctr)
+{
+ Buffer salt( (uint32_t) SALT_LENGTH, false);
+ deriveKey(dir, LABEL_SALT, role, seq_nr, sender_id, mux, masterkey, mastersalt, salt);
+ std::memcpy(ctr->salt_.buf_, salt.getConstBuf(), SALT_LENGTH);
+ ctr->salt_.zero_ = 0;
+ ctr->params_.mux_ ^= MUX_T_HTON(mux);
+ ctr->params_.sender_id_ ^= SENDER_ID_T_HTON(sender_id);
+ ctr->params_.seq_nr_ ^= SEQ_NR_T_HTON(seq_nr);
+
+ return;
+}
+
+void Interface::calcKeyCtr(const Buffer& mastersalt, kd_dir_t dir, role_t role, satp_prf_label_t label, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux, key_derivation_aesctr_ctr_t * ctr)
+{
+
+ if(mastersalt.getLength() != SALT_LENGTH) {
+ cLog.msg(Log::PRIO_ERROR) << "Interface::calcKeyCtr: salt lengths don't match";
+ throw std::runtime_error ("Interface::calcKeyCtr: salt lengths don't match");
+ }
+ std::memcpy(ctr->salt_.buf_, mastersalt.getConstBuf(), SALT_LENGTH);
+ ctr->salt_.zero_ = 0;
+ ctr->params_.label_ ^= SATP_PRF_LABEL_T_HTON(convertLabel(dir, role, label));
+ ctr->params_.seq_ ^= SEQ_NR_T_HTON(seq_nr);
+}
+
}
diff --git a/src/crypto/interface.h b/src/crypto/interface.h
index 6d25b5a..0ca52fb 100644
--- a/src/crypto/interface.h
+++ b/src/crypto/interface.h
@@ -64,8 +64,51 @@
#define LABEL_RIGHT_AUTH 0xC1DFD96E
namespace crypto {
+ static const uint16_t DEFAULT_KEY_LENGTH = 128;
+ static const uint16_t CTR_LENGTH = 16;
+ static const uint16_t SALT_LENGTH = 14;
typedef enum { KD_INBOUND, KD_OUTBOUND } kd_dir_t;
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif
+ typedef union ATTR_PACKED {
+ uint8_t buf_[CTR_LENGTH];
+ struct ATTR_PACKED {
+ uint8_t buf_[SALT_LENGTH];
+ uint16_t zero_;
+ } salt_;
+ struct ATTR_PACKED {
+ uint8_t fill_[SALT_LENGTH - sizeof(mux_t) - sizeof(sender_id_t) - 2*sizeof(uint8_t) - sizeof(seq_nr_t)];
+ mux_t mux_;
+ sender_id_t sender_id_;
+ uint8_t empty_[2];
+ seq_nr_t seq_nr_;
+ uint16_t zero_;
+ } params_;
+ } cipher_aesctr_ctr_t;
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif
+ typedef union ATTR_PACKED {
+ uint8_t buf_[CTR_LENGTH];
+ struct ATTR_PACKED {
+ uint8_t buf_[SALT_LENGTH];
+ uint16_t zero_;
+ } salt_;
+ struct ATTR_PACKED {
+ uint8_t fill_[SALT_LENGTH - sizeof(satp_prf_label_t) - sizeof(seq_nr_t)];
+ satp_prf_label_t label_;
+ seq_nr_t seq_;
+ uint16_t zero_;
+ } params_;
+ } key_derivation_aesctr_ctr_t;
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif
class Interface
{
@@ -73,11 +116,15 @@ namespace crypto {
// implemented
void encrypt(PlainPacket& in, EncryptedPacket& out, const Buffer& masterkey, const Buffer& mastersalt, role_t role, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
void decrypt(EncryptedPacket& in, PlainPacket& out, const Buffer& masterkey, const Buffer& mastersalt, role_t role);
+ void calcCryptCtr(const Buffer& masterkey, const Buffer& mastersalt, kd_dir_t dir, role_t role, satp_prf_label_t label, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux, cipher_aesctr_ctr_t * ctr);
+ void calcKeyCtr(const Buffer& mastersalt, kd_dir_t dir, role_t role, satp_prf_label_t label, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux, key_derivation_aesctr_ctr_t * ctr);
+
// pure virtual
virtual void calcMasterKeySalt(std::string passphrase, uint16_t length, Buffer& masterkey , Buffer& mastersalt) = 0;
virtual uint32_t cipher(uint8_t* in, uint32_t ilen, uint8_t* out, uint32_t olen, const Buffer& masterkey, const Buffer& mastersalt, role_t role, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) = 0;
virtual uint32_t decipher(uint8_t* in, uint32_t ilen, uint8_t* out, uint32_t olen, const Buffer& masterkey, const Buffer& mastersalt, role_t role, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) = 0;
+ virtual void deriveKey(kd_dir_t dir, satp_prf_label_t label, role_t role, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux, const Buffer& masterkey, const Buffer& mastersalt, Buffer& key) = 0;
// virtual
virtual ~Interface();
diff --git a/src/crypto/openssl.cpp b/src/crypto/openssl.cpp
index 088e2b5..20dcff7 100644
--- a/src/crypto/openssl.cpp
+++ b/src/crypto/openssl.cpp
@@ -44,7 +44,9 @@
*/
#include "openssl.h"
+#include "../log.h"
#include <openssl/aes.h>
+#include "../anytunError.h"
namespace crypto {
@@ -61,14 +63,61 @@ void Openssl::calcMasterKeySalt(std::string passphrase, uint16_t length, Buffer&
uint32_t Openssl::cipher(uint8_t* in, uint32_t ilen, uint8_t* out, uint32_t olen, const Buffer& masterkey, const Buffer& mastersalt, role_t role, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
{
+ Buffer key(masterkey.getLength(), false);
+ cipher_aesctr_ctr_t ctr;
+ calcCryptCtr(masterkey, mastersalt, KD_OUTBOUND, role, LABEL_ENC, seq_nr, sender_id, mux, &ctr);
+ deriveKey(KD_OUTBOUND, LABEL_ENC, role, seq_nr, sender_id, mux, masterkey, mastersalt, key);
+ calc(in, ilen, out, olen, key, &ctr);
return ilen>olen ? ilen : olen;
}
uint32_t Openssl::decipher(uint8_t* in, uint32_t ilen, uint8_t* out, uint32_t olen, const Buffer& masterkey, const Buffer& mastersalt, role_t role, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux)
{
+ Buffer key(masterkey.getLength(), false);
+ cipher_aesctr_ctr_t ctr;
+ calcCryptCtr(masterkey, mastersalt, KD_INBOUND, role, LABEL_ENC, seq_nr, sender_id, mux, &ctr);
+ deriveKey(KD_INBOUND, LABEL_ENC, role, seq_nr, sender_id, mux, masterkey, mastersalt, key);
+ calc(in, ilen, out, olen, key, &ctr);
return ilen>olen ? ilen : olen;
}
+
+void Openssl::calc(uint8_t* in, uint32_t ilen, uint8_t* out, uint32_t olen, const Buffer& key, cipher_aesctr_ctr_t * ctr)
+{
+ AES_KEY aes_key;
+ int ret = AES_set_encrypt_key(key.getConstBuf(), key.getLength()*8, &aes_key);
+ if(ret) {
+ cLog.msg(Log::PRIO_ERROR) << "AesIcmCipher: Failed to set cipher ssl key (code: " << ret << ")";
+ AnytunError::throwErr() << "AesIcmCipher: Failed to set cipher ssl key (code: " << ret << ")";
+ }
+
+ if(CTR_LENGTH != AES_BLOCK_SIZE) {
+ cLog.msg(Log::PRIO_ERROR) << "AesIcmCipher: Failed to set cipher CTR: size doesn't fit";
+ AnytunError::throwErr() << ("AesIcmCipher: Failed to set cipher CTR: size doesn't fit");
+ }
+ unsigned int num = 0;
+ uint8_t ecount_buf[AES_BLOCK_SIZE];
+ std::memset(ecount_buf, 0, AES_BLOCK_SIZE);
+ AES_ctr128_encrypt(in, out, (ilen < olen) ? ilen : olen, &aes_key, ctr->buf_, ecount_buf, &num);
+}
+
+void Openssl::deriveKey(kd_dir_t dir, satp_prf_label_t label, role_t role, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux, const Buffer& masterkey, const Buffer& mastersalt, Buffer& key)
+{
+ uint8_t ecount_buf[AES_BLOCK_SIZE];
+ AES_KEY aes_key;
+ key_derivation_aesctr_ctr_t ctr;
+ calcKeyCtr(mastersalt, dir, role, label, seq_nr, sender_id, mux, &ctr);
+ if(CTR_LENGTH != AES_BLOCK_SIZE) {
+ cLog.msg(Log::PRIO_ERROR) << "AesIcmCipher: Failed to set cipher CTR: size doesn't fit";
+ AnytunError::throwErr() << ("AesIcmCipher: Failed to set cipher CTR: size doesn't fit");
+ }
+ unsigned int 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);
+}
+
+
std::string Openssl::printType()
{
return "Openssl";
diff --git a/src/crypto/openssl.h b/src/crypto/openssl.h
index 2f3704e..956be99 100644
--- a/src/crypto/openssl.h
+++ b/src/crypto/openssl.h
@@ -57,12 +57,14 @@ namespace crypto {
virtual void calcMasterKeySalt(std::string passphrase, uint16_t length, Buffer& masterkey , Buffer& mastersalt);
virtual uint32_t cipher(uint8_t* in, uint32_t ilen, uint8_t* out, uint32_t olen, const Buffer& masterkey, const Buffer& mastersalt, role_t role, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
virtual uint32_t decipher(uint8_t* in, uint32_t ilen, uint8_t* out, uint32_t olen, const Buffer& masterkey, const Buffer& mastersalt, role_t role, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux);
-
+ virtual void deriveKey(kd_dir_t dir, satp_prf_label_t label, role_t role, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux, const Buffer& masterkey, const Buffer& mastersalt, Buffer& key);
// virtual
virtual ~Openssl();
virtual std::string printType();
//static
static bool init();
+ //implemented
+ void calc(uint8_t* in, uint32_t ilen, uint8_t* out, uint32_t olen, const Buffer& key, cipher_aesctr_ctr_t * ctr);
};
};