IBR-DTNSuite 0.6

ibrdtn/ibrdtn/security/SecurityBlock.cpp

Go to the documentation of this file.
00001 /*
00002  * SecurityBlock.cpp
00003  *
00004  *  Created on: 08.03.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "ibrdtn/security/SecurityBlock.h"
00009 #include "ibrdtn/security/MutualSerializer.h"
00010 #include "ibrdtn/data/Bundle.h"
00011 #include "ibrdtn/data/PayloadBlock.h"
00012 #include "ibrdtn/data/ExtensionBlock.h"
00013 
00014 #include <ibrcommon/Logger.h>
00015 #include <cstdlib>
00016 #include <openssl/rand.h>
00017 #include <openssl/err.h>
00018 #include <openssl/rsa.h>
00019 
00020 #ifdef __DEVELOPMENT_ASSERTIONS__
00021 #include <cassert>
00022 #endif
00023 
00024 namespace dtn
00025 {
00026         namespace security
00027         {
00028                 const std::string SecurityBlock::TLVList::toString() const
00029                 {
00030                         std::stringstream ss;
00031 
00032                         for (std::set<TLV>::const_iterator iter = begin(); iter != end(); iter++)
00033                         {
00034                                 ss << (*iter);
00035                         }
00036 
00037                         return ss.str();
00038                 }
00039 
00040                 size_t SecurityBlock::TLVList::getLength() const
00041                 {
00042                         size_t len = getPayloadLength();
00043                         return len;
00044                 }
00045 
00046                 size_t SecurityBlock::TLVList::getPayloadLength() const
00047                 {
00048                         size_t len = 0;
00049 
00050                         for (std::set<SecurityBlock::TLV>::const_iterator iter = begin(); iter != end(); iter++)
00051                         {
00052                                 len += (*iter).getLength();
00053                         }
00054 
00055                         return len;
00056                 }
00057 
00058                 const std::string SecurityBlock::TLVList::get(SecurityBlock::TLV_TYPES type) const
00059                 {
00060                         for (std::set<SecurityBlock::TLV>::const_iterator iter = begin(); iter != end(); iter++)
00061                         {
00062                                 if ((*iter).getType() == type)
00063                                 {
00064                                         return (*iter).getValue();
00065                                 }
00066                         }
00067 
00068                         throw ibrcommon::Exception("element not found");
00069                 }
00070 
00071                 void SecurityBlock::TLVList::get(TLV_TYPES type, unsigned char *value, size_t length) const
00072                 {
00073                         const std::string data = get(type);
00074 
00075                         if (length < data.size())
00076                         {
00077                                 ::memcpy(value, data.c_str(), length);
00078                         }
00079                         else
00080                         {
00081                                 ::memcpy(value, data.c_str(), data.size());
00082                         }
00083                 }
00084 
00085                 void SecurityBlock::TLVList::set(SecurityBlock::TLV_TYPES type, std::string value)
00086                 {
00087                         SecurityBlock::TLV tlv(type, value);
00088 
00089                         erase(tlv);
00090                         insert(tlv);
00091                 }
00092 
00093                 void SecurityBlock::TLVList::set(TLV_TYPES type, const unsigned char *value, size_t length)
00094                 {
00095                         const std::string data(reinterpret_cast<const char *>(value), length);
00096                         set(type, data);
00097                 }
00098 
00099                 void SecurityBlock::TLVList::remove(SecurityBlock::TLV_TYPES type)
00100                 {
00101                         erase(SecurityBlock::TLV(type, ""));
00102                 }
00103 
00104                 const std::string SecurityBlock::TLV::getValue() const
00105                 {
00106                         return _value;
00107                 }
00108 
00109                 SecurityBlock::TLV_TYPES SecurityBlock::TLV::getType() const
00110                 {
00111                         return _type;
00112                 }
00113 
00114                 size_t SecurityBlock::TLV::getLength() const
00115                 {
00116                         return _value.getLength() + sizeof(char);
00117                 }
00118 
00119                 std::ostream& operator<<(std::ostream &stream, const SecurityBlock::TLVList &tlvlist)
00120                 {
00121                         dtn::data::SDNV length(tlvlist.getPayloadLength());
00122                         stream << length;
00123 
00124                         for (std::set<SecurityBlock::TLV>::const_iterator iter = tlvlist.begin(); iter != tlvlist.end(); iter++)
00125                         {
00126                                 stream << (*iter);
00127                         }
00128                         return stream;
00129                 }
00130 
00131                 std::istream& operator>>(std::istream &stream, SecurityBlock::TLVList &tlvlist)
00132                 {
00133                         dtn::data::SDNV length;
00134                         stream >> length;
00135                         size_t read_length = 0;
00136 
00137                         while (read_length < length.getValue())
00138                         {
00139                                 SecurityBlock::TLV tlv;
00140                                 stream >> tlv;
00141                                 tlvlist.insert(tlv);
00142                                 read_length += tlv.getLength();
00143                         }
00144 
00145                         return stream;
00146                 }
00147 
00148                 bool SecurityBlock::TLV::operator<(const SecurityBlock::TLV &tlv) const
00149                 {
00150                         return (_type < tlv._type);
00151                 }
00152 
00153                 bool SecurityBlock::TLV::operator==(const SecurityBlock::TLV &tlv) const
00154                 {
00155                         return (_type == tlv._type);
00156                 }
00157 
00158                 std::ostream& operator<<(std::ostream &stream, const SecurityBlock::TLV &tlv)
00159                 {
00160                         stream.put((char)tlv._type);
00161                         stream << tlv._value;
00162                         return stream;
00163                 }
00164 
00165                 std::istream& operator>>(std::istream &stream, SecurityBlock::TLV &tlv)
00166                 {
00167                         char tlv_type;
00168                         stream.get(tlv_type); tlv._type = SecurityBlock::TLV_TYPES(tlv_type);
00169                         stream >> tlv._value;
00170                         return stream;
00171                 }
00172 
00173                 SecurityBlock::SecurityBlock(const dtn::security::SecurityBlock::BLOCK_TYPES type, const dtn::security::SecurityBlock::CIPHERSUITE_IDS id)
00174                 : Block(type), _ciphersuite_id(id), _ciphersuite_flags(0), _correlator(0)
00175                 {
00176 
00177                 }
00178 
00179                 SecurityBlock::SecurityBlock(const dtn::security::SecurityBlock::BLOCK_TYPES type)
00180                 : Block(type), _ciphersuite_flags(0), _correlator(0)
00181                 {
00182 
00183                 }
00184 
00185                 SecurityBlock::~SecurityBlock()
00186                 {
00187                 }
00188 
00189                 void SecurityBlock::store_security_references()
00190                 {
00191                         // clear the EID list
00192                         _eids.clear();
00193 
00194                         // first the security source
00195                         if (_security_source == dtn::data::EID())
00196                         {
00197                                 _ciphersuite_flags &= ~(SecurityBlock::CONTAINS_SECURITY_SOURCE);
00198                         }
00199                         else
00200                         {
00201                                 _ciphersuite_flags |= SecurityBlock::CONTAINS_SECURITY_SOURCE;
00202                                 _eids.push_back(_security_source);
00203                         }
00204 
00205                         // then the destination
00206                         if (_security_destination == dtn::data::EID())
00207                         {
00208                                 _ciphersuite_flags &= ~(SecurityBlock::CONTAINS_SECURITY_DESTINATION);
00209                         }
00210                         else
00211                         {
00212                                 _ciphersuite_flags |= SecurityBlock::CONTAINS_SECURITY_DESTINATION;
00213                                 _eids.push_back(_security_destination);
00214                         }
00215 
00216                         if (_eids.size() > 0)
00217                         {
00218                                 set(Block::BLOCK_CONTAINS_EIDS, true);
00219                         }
00220                         else
00221                         {
00222                                 set(Block::BLOCK_CONTAINS_EIDS, false);
00223                         }
00224                 }
00225 
00226                 const dtn::data::EID SecurityBlock::getSecuritySource() const
00227                 {
00228                         return _security_source;
00229                 }
00230 
00231                 const dtn::data::EID SecurityBlock::getSecurityDestination() const
00232                 {
00233                         return _security_destination;
00234                 }
00235 
00236                 void SecurityBlock::setSecuritySource(const dtn::data::EID &source)
00237                 {
00238                         _security_source = source;
00239                         store_security_references();
00240                 }
00241 
00242                 void SecurityBlock::setSecurityDestination(const dtn::data::EID &destination)
00243                 {
00244                         _security_destination = destination;
00245                         store_security_references();
00246                 }
00247 
00248                 void SecurityBlock::setCiphersuiteId(const CIPHERSUITE_IDS id)
00249                 {
00250                         _ciphersuite_id = static_cast<u_int64_t>(id);
00251                 }
00252 
00253                 void SecurityBlock::setCorrelator(const u_int64_t corr)
00254                 {
00255                         _correlator = corr;
00256                         _ciphersuite_flags |= SecurityBlock::CONTAINS_CORRELATOR;
00257                 }
00258 
00259                 bool SecurityBlock::isCorrelatorPresent(const dtn::data::Bundle& bundle, const u_int64_t correlator)
00260                 {
00261                         std::list<const dtn::data::Block *> blocks = bundle.getBlocks();
00262                         bool return_val = false;
00263                         for (std::list<const dtn::data::Block *>::const_iterator it = blocks.begin(); it != blocks.end() && !return_val; it++)
00264                         {
00265                                 char type = (*it)->getType();
00266                                 if (type == BUNDLE_AUTHENTICATION_BLOCK
00267                                         || type == PAYLOAD_INTEGRITY_BLOCK
00268                                         || type == PAYLOAD_CONFIDENTIAL_BLOCK
00269                                         || type == EXTENSION_SECURITY_BLOCK)
00270                                 return_val = static_cast<const SecurityBlock*>(*it)->_correlator == correlator;
00271                         }
00272                         return return_val;
00273                 }
00274 
00275                 u_int64_t SecurityBlock::createCorrelatorValue(const dtn::data::Bundle& bundle)
00276                 {
00277                         u_int64_t corr = random();
00278                         while (isCorrelatorPresent(bundle, corr))
00279                                 corr = random();
00280                         return corr;
00281                 }
00282 
00283                 size_t SecurityBlock::getLength() const
00284                 {
00285                         size_t length = dtn::data::SDNV::getLength(_ciphersuite_id)
00286                                 + dtn::data::SDNV::getLength(_ciphersuite_flags);
00287 
00288                         if (_ciphersuite_flags & CONTAINS_CORRELATOR)
00289                         {
00290                                 length += dtn::data::SDNV::getLength(_correlator);
00291                         }
00292 
00293                         if (_ciphersuite_flags & CONTAINS_CIPHERSUITE_PARAMS)
00294                         {
00295                                 const dtn::data::SDNV size(_ciphersuite_params.getLength());
00296                                 length += size.getLength() + size.getValue();
00297                         }
00298 
00299                         if (_ciphersuite_flags & CONTAINS_SECURITY_RESULT)
00300                         {
00301                                 const dtn::data::SDNV size(getSecurityResultSize());
00302                                 length += size.getLength() + size.getValue();
00303                         }
00304 
00305                         return length;
00306                 }
00307 
00308                 size_t SecurityBlock::getLength_mutable() const
00309                 {
00310                         // ciphersuite_id
00311                         size_t length = MutualSerializer::sdnv_size;
00312 
00313                         // ciphersuite_flags
00314                         length += MutualSerializer::sdnv_size;
00315 
00316                         // correlator
00317                         if (_ciphersuite_flags & CONTAINS_CORRELATOR)
00318                         {
00319                                 length += MutualSerializer::sdnv_size;
00320                         }
00321 
00322                         // ciphersuite parameters
00323                         if (_ciphersuite_flags & CONTAINS_CIPHERSUITE_PARAMS)
00324                         {
00325                                 length += MutualSerializer::sdnv_size;
00326                                 length += _ciphersuite_params.getLength();
00327                         }
00328                         // security result
00329                         if (_ciphersuite_flags & CONTAINS_SECURITY_RESULT)
00330                         {
00331                                 length += MutualSerializer::sdnv_size + getSecurityResultSize();
00332                         }
00333 
00334                         return length;
00335                 }
00336 
00337                 std::ostream& SecurityBlock::serialize(std::ostream &stream, size_t &length) const
00338                 {
00339                         stream << dtn::data::SDNV(_ciphersuite_id) << dtn::data::SDNV(_ciphersuite_flags);
00340 
00341                         if (_ciphersuite_flags & CONTAINS_CORRELATOR)
00342                         {
00343                                 stream << dtn::data::SDNV(_correlator);
00344                         }
00345 
00346                         if (_ciphersuite_flags & CONTAINS_CIPHERSUITE_PARAMS)
00347                         {
00348                                 stream << _ciphersuite_params;
00349                         }
00350 
00351                         if (_ciphersuite_flags & CONTAINS_SECURITY_RESULT)
00352                         {
00353                                 stream << _security_result;
00354                         }
00355 
00356                         return stream;
00357                 }
00358 
00359                 std::ostream& SecurityBlock::serialize_strict(std::ostream &stream, size_t &length) const
00360                 {
00361                         stream << dtn::data::SDNV(_ciphersuite_id) << dtn::data::SDNV(_ciphersuite_flags);
00362 
00363                         if (_ciphersuite_flags & CONTAINS_CORRELATOR)
00364                         {
00365                                 stream << dtn::data::SDNV(_correlator);
00366                         }
00367 
00368                         if (_ciphersuite_flags & CONTAINS_CIPHERSUITE_PARAMS)
00369                         {
00370                                 stream << _ciphersuite_params;
00371                         }
00372 
00373                         if (_ciphersuite_flags & CONTAINS_SECURITY_RESULT)
00374                         {
00375                                 stream << dtn::data::SDNV(getSecurityResultSize());
00376                         }
00377 
00378                         return stream;
00379                 }
00380 
00381                 std::istream& SecurityBlock::deserialize(std::istream &stream, const size_t length)
00382                 {
00383 #ifdef __DEVELOPMENT_ASSERTIONS__
00384                         // recheck blocktype. if blocktype is set wrong, this will be a huge fail
00385                         assert(_blocktype == BUNDLE_AUTHENTICATION_BLOCK || _blocktype == PAYLOAD_INTEGRITY_BLOCK || _blocktype == PAYLOAD_CONFIDENTIAL_BLOCK || _blocktype == EXTENSION_SECURITY_BLOCK);
00386 #endif
00387 
00388                         dtn::data::SDNV ciphersuite_id, ciphersuite_flags;
00389                         stream >> ciphersuite_id >> ciphersuite_flags;
00390                         _ciphersuite_id = ciphersuite_id.getValue();
00391                         _ciphersuite_flags = ciphersuite_flags.getValue();
00392 
00393 #ifdef __DEVELOPMENT_ASSERTIONS__
00394                         // recheck ciphersuite_id
00395                         assert(_ciphersuite_id == BAB_HMAC || _ciphersuite_id == PIB_RSA_SHA256 || _ciphersuite_id == PCB_RSA_AES128_PAYLOAD_PIB_PCB || _ciphersuite_id == ESB_RSA_AES128_EXT);
00396                         // recheck ciphersuite_flags, could be more exhaustive
00397                         assert(_ciphersuite_flags < 32);
00398 #endif
00399 
00400                         // copy security source and destination
00401                         if (_ciphersuite_flags & SecurityBlock::CONTAINS_SECURITY_SOURCE)
00402                         {
00403                                 if (_eids.size() == 0)
00404                                         throw dtn::SerializationFailedException("ciphersuite flags indicate a security source, but it is not present");
00405 
00406                                 _security_source = _eids.front();
00407                         }
00408 
00409                         if (_ciphersuite_flags & SecurityBlock::CONTAINS_SECURITY_DESTINATION)
00410                         {
00411                                 if (_ciphersuite_flags & SecurityBlock::CONTAINS_SECURITY_SOURCE)
00412                                 {
00413                                         if (_eids.size() < 2)
00414                                                 throw dtn::SerializationFailedException("ciphersuite flags indicate a security destination, but it is not present");
00415 
00416                                         _security_destination = (*(_eids.begin())++);
00417                                 }
00418                                 else
00419                                 {
00420                                         if (_eids.size() == 0)
00421                                                 throw dtn::SerializationFailedException("ciphersuite flags indicate a security destination, but it is not present");
00422 
00423                                         _security_destination = _eids.front();
00424                                 }
00425                         }
00426 
00427                         if (_ciphersuite_flags & CONTAINS_CORRELATOR)
00428                         {
00429                                 dtn::data::SDNV correlator;
00430                                 stream >> correlator;
00431                                 _correlator = correlator.getValue();
00432                         }
00433                         if (_ciphersuite_flags & CONTAINS_CIPHERSUITE_PARAMS)
00434                         {
00435                                 stream >> _ciphersuite_params;
00436 #ifdef __DEVELOPMENT_ASSERTIONS__
00437                                 assert(_ciphersuite_params.getLength() > 0);
00438 #endif
00439                         }
00440 
00441                         if (_ciphersuite_flags & CONTAINS_SECURITY_RESULT)
00442                         {
00443                                 stream >> _security_result;
00444 #ifdef __DEVELOPMENT_ASSERTIONS__
00445                                 assert(_security_result.getLength() > 0);
00446 #endif
00447                         }
00448 
00449                         return stream;
00450                 }
00451 
00452                 dtn::security::MutualSerializer& SecurityBlock::serialize_mutable(dtn::security::MutualSerializer &serializer) const
00453                 {
00454                         serializer << dtn::data::SDNV(_ciphersuite_id);
00455                         serializer << dtn::data::SDNV(_ciphersuite_flags);
00456 
00457                         if (_ciphersuite_flags & CONTAINS_CORRELATOR)
00458                                 serializer << dtn::data::SDNV(_ciphersuite_flags);
00459 
00460                         if (_ciphersuite_flags & CONTAINS_CIPHERSUITE_PARAMS)
00461                         {
00462                                 serializer << _ciphersuite_params;
00463                         }
00464 
00465                         if (_ciphersuite_flags & CONTAINS_SECURITY_RESULT)
00466                         {
00467                                 serializer << _security_result;
00468                         }
00469 
00470                         return serializer;
00471                 }
00472 
00473                 dtn::security::MutualSerializer& SecurityBlock::serialize_mutable_without_security_result(dtn::security::MutualSerializer &serializer) const
00474                 {
00475                         serializer << dtn::data::SDNV(_ciphersuite_id);
00476                         serializer << dtn::data::SDNV(_ciphersuite_flags);
00477 
00478                         if (_ciphersuite_flags & CONTAINS_CORRELATOR)
00479                                 serializer << dtn::data::SDNV(_ciphersuite_flags);
00480 
00481                         if (_ciphersuite_flags & CONTAINS_CIPHERSUITE_PARAMS)
00482                         {
00483                                 serializer << _ciphersuite_params;
00484                         }
00485 
00486                         if (_ciphersuite_flags & CONTAINS_SECURITY_RESULT)
00487                         {
00488                                 serializer << dtn::data::SDNV(getSecurityResultSize());
00489                         }
00490 
00491                         return serializer;
00492                 }
00493 
00494                 size_t SecurityBlock::getSecurityResultSize() const
00495                 {
00496 #ifdef __DEVELOPMENT_ASSERTIONS__
00497                         assert(_security_result.getLength() != 0);
00498 #endif
00499                         return _security_result.getLength();
00500                 }
00501 
00502                 void SecurityBlock::createSaltAndKey(u_int32_t& salt, unsigned char* key, size_t key_size)
00503                 {
00504 
00505                         if (!RAND_bytes(reinterpret_cast<unsigned char *>(&salt), sizeof(u_int32_t)))
00506                         {
00507                                 IBRCOMMON_LOGGER_ex(critical) << "failed to generate salt. maybe /dev/urandom is missing for seeding the PRNG" << IBRCOMMON_LOGGER_ENDL;
00508                                 ERR_print_errors_fp(stderr);
00509                         }
00510                         if (!RAND_bytes(key, key_size))
00511                         {
00512                                 IBRCOMMON_LOGGER_ex(critical) << "failed to generate key. maybe /dev/urandom is missing for seeding the PRNG" << IBRCOMMON_LOGGER_ENDL;
00513                                 ERR_print_errors_fp(stderr);
00514                         }
00515                 }
00516 
00517                 void SecurityBlock::addKey(TLVList& security_parameter, unsigned char const * const key, size_t key_size, RSA * rsa)
00518                 {
00519                         // encrypt the ephemeral key and place it in _ciphersuite_params
00520 #ifdef __DEVELOPMENT_ASSERTIONS__
00521                         assert(key_size < RSA_size(rsa)-41);
00522 #endif
00523                         unsigned char encrypted_key[RSA_size(rsa)];
00524                         int encrypted_key_len = RSA_public_encrypt(key_size, key, encrypted_key, rsa, RSA_PKCS1_OAEP_PADDING);
00525                         if (encrypted_key_len == -1)
00526                         {
00527                                 IBRCOMMON_LOGGER_ex(critical) << "failed to encrypt the symmetric AES key" << IBRCOMMON_LOGGER_ENDL;
00528                                 ERR_print_errors_fp(stderr);
00529                         }
00530                         security_parameter.set(SecurityBlock::key_information, std::string(reinterpret_cast<char *>(encrypted_key), encrypted_key_len));
00531                 }
00532 
00533                 bool SecurityBlock::getKey(const TLVList& security_parameter, unsigned char * key, size_t key_size, RSA * rsa)
00534                 {
00535                         std::string key_string = security_parameter.get(SecurityBlock::key_information);
00536                         // get key, convert with reinterpret_cast
00537                         unsigned char const * encrypted_key = reinterpret_cast<const unsigned char*>(key_string.c_str());
00538                         unsigned char the_key[RSA_size(rsa)];
00539                         RSA_blinding_on(rsa, NULL);
00540                         int plaintext_key_len = RSA_private_decrypt(key_string.size(), encrypted_key, the_key, rsa, RSA_PKCS1_OAEP_PADDING);
00541                         RSA_blinding_off(rsa);
00542                         if (plaintext_key_len == -1)
00543                         {
00544                                 IBRCOMMON_LOGGER_ex(critical) << "failed to decrypt the symmetric AES key" << IBRCOMMON_LOGGER_ENDL;
00545                                 ERR_print_errors_fp(stderr);
00546                                 return false;
00547                         }
00548 #ifdef __DEVELOPMENT_ASSERTIONS__
00549                         assert(plaintext_key_len == key_size);
00550 #endif
00551                         std::copy(the_key, the_key+key_size, key);
00552                         return true;
00553                 }
00554 
00555                 void SecurityBlock::copyEID(const Block& from, Block& to, size_t skip)
00556                 {
00557                         // take eid list, getEIDList() is broken
00558                         std::list<dtn::data::EID> their_eids = from.getEIDList();
00559                         std::list<dtn::data::EID>::iterator it = their_eids.begin();
00560 
00561                         while (it != their_eids.end() && skip > 0)
00562                         {
00563                                 skip--;
00564                                 it++;
00565                         }
00566 
00567                         for (; it != their_eids.end(); it++)
00568                                 to.addEID(*it);
00569                 }
00570 
00571                 void SecurityBlock::addSalt(TLVList& security_parameters, u_int32_t salt)
00572                 {
00573                         std::stringstream salt_stream;
00574                         salt_stream << salt;
00575                         security_parameters.set(SecurityBlock::salt, salt_stream.str());
00576                 }
00577 
00578                 u_int32_t SecurityBlock::getSalt(const TLVList& security_parameters)
00579                 {
00580                         // get salt, convert with stringstream
00581                         std::string salt_string = security_parameters.get(SecurityBlock::salt);
00582                         std::stringstream salt_stream;
00583                         salt_stream << salt_string;
00584                         u_int32_t salt;
00585                         salt_stream >> salt;
00586                         return salt;
00587                 }
00588 
00589                 void SecurityBlock::decryptBlock(dtn::data::Bundle& bundle, const dtn::security::SecurityBlock &block, u_int32_t salt, const unsigned char key[ibrcommon::AES128Stream::key_size_in_bytes])
00590                 {
00591                         // the array for the extracted tag
00592                         unsigned char tag[ibrcommon::AES128Stream::tag_len];
00593 
00594                         // the array for the extracted iv
00595                         unsigned char iv[ibrcommon::AES128Stream::iv_len];
00596 
00597                         // get iv, convert with reinterpret_cast
00598                         block._ciphersuite_params.get(SecurityBlock::initialization_vector, iv, ibrcommon::AES128Stream::iv_len);
00599 
00600                         // get data and tag, the last tag_len bytes are the tag. cut them of and reinterpret_cast
00601                         std::string block_data = block._security_result.get(SecurityBlock::encapsulated_block);
00602 
00603                         // create a pointer to the tag begin
00604                         const char *tag_p = block_data.c_str() + (block_data.size() - ibrcommon::AES128Stream::tag_len);
00605 
00606                         // copy the tag
00607                         ::memcpy(tag, tag_p, ibrcommon::AES128Stream::tag_len);
00608 
00609                         // strip off the tag from block data
00610                         block_data.resize(block_data.size() - ibrcommon::AES128Stream::tag_len);
00611 
00612                         // decrypt block
00613                         std::stringstream plaintext;
00614                         ibrcommon::AES128Stream decrypt(ibrcommon::CipherStream::CIPHER_DECRYPT, plaintext, key, salt, iv);
00615                         decrypt << block_data << std::flush;
00616 
00617                         // verify the decrypt tag
00618                         if (!decrypt.verify(tag))
00619                         {
00620                                 throw ibrcommon::Exception("decryption of block failed - tag is bad");
00621                         }
00622 
00623                         // deserialize block
00624                         dtn::data::DefaultDeserializer ddser(plaintext);
00625 
00626                         // peek the block type
00627                         char block_type = plaintext.peek();
00628 
00629                         if (block_type == dtn::data::PayloadBlock::BLOCK_TYPE)
00630                         {
00631                                 dtn::data::PayloadBlock &plaintext_block = bundle.insert<dtn::data::PayloadBlock>(block);
00632                                 ddser >> plaintext_block;
00633                         }
00634                         else
00635                         {
00636                                 try {
00637                                         dtn::data::ExtensionBlock::Factory &f = dtn::data::ExtensionBlock::Factory::get(block_type);
00638                                         dtn::data::Block &plaintext_block = bundle.insert(f, block);
00639                                         ddser >> plaintext_block;
00640 
00641                                         plaintext_block.getEIDList().clear();
00642 
00643                                         // copy eids
00644                                         // remove security_source and destination
00645                                         size_t skip = 0;
00646                                         if (block._ciphersuite_flags & SecurityBlock::CONTAINS_SECURITY_DESTINATION)
00647                                                 skip++;
00648                                         if (block._ciphersuite_flags & SecurityBlock::CONTAINS_SECURITY_SOURCE)
00649                                                 skip++;
00650                                         copyEID(plaintext_block, plaintext_block, skip);
00651 
00652                                 } catch (const ibrcommon::Exception &ex) {
00653                                         dtn::data::ExtensionBlock &plaintext_block = bundle.insert<dtn::data::ExtensionBlock>(block);
00654                                         ddser >> plaintext_block;
00655 
00656                                         plaintext_block.getEIDList().clear();
00657 
00658                                         // copy eids
00659                                         // remove security_source and destination
00660                                         size_t skip = 0;
00661                                         if (block._ciphersuite_flags & SecurityBlock::CONTAINS_SECURITY_DESTINATION)
00662                                                 skip++;
00663                                         if (block._ciphersuite_flags & SecurityBlock::CONTAINS_SECURITY_SOURCE)
00664                                                 skip++;
00665                                         copyEID(plaintext_block, plaintext_block, skip);
00666                                 }
00667                         }
00668 
00669                         bundle.remove(block);
00670                 }
00671 
00672                 void SecurityBlock::addFragmentRange(TLVList& ciphersuite_params, size_t fragmentoffset, size_t payload_length)
00673                 {
00674                         dtn::data::SDNV offset(fragmentoffset);
00675                         dtn::data::SDNV range_sdnv(payload_length);
00676 
00677                         std::stringstream ss;
00678                         ss << offset << range_sdnv;
00679 
00680                         ciphersuite_params.set(SecurityBlock::fragment_range, ss.str());
00681                 }
00682 
00683                 bool SecurityBlock::isSecuritySource(const dtn::data::Bundle& bundle, const dtn::data::EID& eid) const
00684                 {
00685                         IBRCOMMON_LOGGER_DEBUG(30) << "check security source: " << getSecuritySource(bundle).getString() << " == " << eid.getNode().getString() << IBRCOMMON_LOGGER_ENDL;
00686                         return getSecuritySource(bundle) == eid.getNode();
00687                 }
00688 
00689                 bool SecurityBlock::isSecurityDestination(const dtn::data::Bundle& bundle, const dtn::data::EID& eid) const
00690                 {
00691                         IBRCOMMON_LOGGER_DEBUG(30) << "check security destination: " << getSecurityDestination(bundle).getString() << " == " << eid.getNode().getString() << IBRCOMMON_LOGGER_ENDL;
00692                         return getSecurityDestination(bundle) == eid.getNode();
00693                 }
00694                 
00695                 const dtn::data::EID SecurityBlock::getSecuritySource(const dtn::data::Bundle& bundle) const
00696                 {
00697                         dtn::data::EID source = getSecuritySource();
00698                         if (source == dtn::data::EID())
00699                                 source = bundle._source.getNode();
00700                         return source;
00701                 }
00702 
00703                 const dtn::data::EID SecurityBlock::getSecurityDestination(const dtn::data::Bundle& bundle) const
00704                 {
00705                         dtn::data::EID destination = getSecurityDestination();
00706                         if (destination == dtn::data::EID())
00707                                 destination = bundle._destination.getNode();
00708                         return destination;
00709                 }
00710         }
00711 }