From 2d712656364cf982a56fa4e7a8f1eab714240266 Mon Sep 17 00:00:00 2001 From: Othmar Gsenger Date: Wed, 19 Nov 2014 19:56:32 +0000 Subject: openssl crypt new implementation added --- src/buffer.cpp | 5 +++++ src/buffer.h | 1 + src/crypto/interface.cpp | 28 +++++++++++++++++++++++++++ src/crypto/interface.h | 47 ++++++++++++++++++++++++++++++++++++++++++++++ src/crypto/openssl.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ src/crypto/openssl.h | 4 +++- 6 files changed, 133 insertions(+), 1 deletion(-) 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 +#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); }; }; -- cgit v1.2.3