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