IBR-DTNSuite 0.6

ibrdtn/ibrdtn/security/BundleAuthenticationBlock.cpp

Go to the documentation of this file.
00001 #include "ibrdtn/data/Bundle.h"
00002 #include "ibrdtn/security/BundleAuthenticationBlock.h"
00003 #include "ibrdtn/security/StrictSerializer.h"
00004 #include "ibrcommon/ssl/HMacStream.h"
00005 #include <ibrcommon/Logger.h>
00006 #include <cstring>
00007 #include <set>
00008 
00009 #ifdef __DEVELOPMENT_ASSERTIONS__
00010 #include <cassert>
00011 #endif
00012 
00013 namespace dtn
00014 {
00015         namespace security
00016         {
00017                 dtn::data::Block* BundleAuthenticationBlock::Factory::create()
00018                 {
00019                         return new BundleAuthenticationBlock();
00020                 }
00021 
00022                 BundleAuthenticationBlock::BundleAuthenticationBlock()
00023                  : SecurityBlock(BUNDLE_AUTHENTICATION_BLOCK, BAB_HMAC)
00024                 {
00025                 }
00026 
00027                 BundleAuthenticationBlock::~BundleAuthenticationBlock()
00028                 {
00029                 }
00030 
00031                 void BundleAuthenticationBlock::auth(dtn::data::Bundle &bundle, const dtn::security::SecurityKey &key)
00032                 {
00033                         BundleAuthenticationBlock& bab_begin = bundle.push_front<BundleAuthenticationBlock>();
00034 
00035                         // set security source
00036                         if (key.reference != bundle._source.getNode()) bab_begin.setSecuritySource( key.reference );
00037 
00038                         u_int64_t correlator = createCorrelatorValue(bundle);
00039                         bab_begin.setCorrelator(correlator);
00040                         bab_begin.setCiphersuiteId(BAB_HMAC);
00041 
00042                         BundleAuthenticationBlock& bab_end = bundle.push_back<BundleAuthenticationBlock>();
00043                         bab_end.setCorrelator(correlator);
00044                         bab_end._ciphersuite_flags |= CONTAINS_SECURITY_RESULT;
00045 
00046                         std::string sizehash_hash = calcMAC(bundle, key);
00047                         bab_end._security_result.set(SecurityBlock::integrity_signature, sizehash_hash);
00048                 }
00049 
00050                 void BundleAuthenticationBlock::verify(const dtn::data::Bundle &bundle, const dtn::security::SecurityKey &key) throw (ibrcommon::Exception)
00051                 {
00052                         // store the correlator of the verified BABs
00053                         u_int64_t correlator;
00054 
00055                         // verify the babs of the bundle
00056                         verify(bundle, key, correlator);
00057                 }
00058 
00059                 void BundleAuthenticationBlock::strip(dtn::data::Bundle &bundle, const dtn::security::SecurityKey &key)
00060                 {
00061                         // store the correlator of the verified BABs
00062                         u_int64_t correlator;
00063 
00064                         // verify the babs of the bundle
00065                         verify(bundle, key, correlator);
00066 
00067                         // get the list of BABs
00068                         const std::list<const BundleAuthenticationBlock *> babs = bundle.getBlocks<BundleAuthenticationBlock>();
00069 
00070                         for (std::list<const BundleAuthenticationBlock *>::const_iterator it = babs.begin(); it != babs.end(); it++)
00071                         {
00072                                 const BundleAuthenticationBlock &bab = (**it);
00073 
00074                                 // if the correlator is already authenticated, then remove the BAB
00075                                 if ((bab._ciphersuite_flags & SecurityBlock::CONTAINS_CORRELATOR) && (bab._correlator == correlator))
00076                                 {
00077                                         bundle.remove(bab);
00078                                 }
00079                         }
00080                 }
00081 
00082                 void BundleAuthenticationBlock::strip(dtn::data::Bundle& bundle)
00083                 {
00084                         // blocks of a certain type
00085                         const std::list<const BundleAuthenticationBlock *> babs = bundle.getBlocks<BundleAuthenticationBlock>();
00086 
00087                         for (std::list<const BundleAuthenticationBlock *>::const_iterator it = babs.begin(); it != babs.end(); it++)
00088                         {
00089                                 bundle.remove(*(*it));
00090                         }
00091                 }
00092 
00093                 void BundleAuthenticationBlock::verify(const dtn::data::Bundle& bundle, const dtn::security::SecurityKey &key, u_int64_t &correlator) throw (ibrcommon::Exception)
00094                 {
00095                         std::list<const BundleAuthenticationBlock *> babs = bundle.getBlocks<BundleAuthenticationBlock>();
00096 
00097                         // get the blocks, with which the key should match
00098                         std::set<u_int64_t> correlators;
00099 
00100                         // calculate the MAC of this bundle
00101                         std::string our_hash_string = calcMAC(bundle, key);
00102 
00103                         for (std::list<const BundleAuthenticationBlock *>::const_iterator it = babs.begin(); it != babs.end(); it++)
00104                         {
00105                                 const BundleAuthenticationBlock &bab = (**it);
00106 
00107                                 // the bab contains a security result
00108                                 if (bab._ciphersuite_flags & CONTAINS_SECURITY_RESULT)
00109                                 {
00110                                         // is this correlator known?
00111                                         if (correlators.find(bab._correlator) == correlators.end()) continue;
00112 
00113                                         std::string bab_result = bab._security_result.get(SecurityBlock::integrity_signature);
00114                                         if (our_hash_string == bab_result)
00115                                         {
00116                                                 // hash matched
00117                                                 correlator = bab._correlator;
00118                                                 return;
00119                                         }
00120 
00121                                         IBRCOMMON_LOGGER_DEBUG(15) << "security mac does not match" << IBRCOMMON_LOGGER_ENDL;
00122                                 }
00123                                 // bab contains no security result but a correlator
00124                                 else if (bab._ciphersuite_flags &  CONTAINS_CORRELATOR)
00125                                 {
00126                                         // currently we only support BAB_HMAC mechanism
00127                                         if (bab._ciphersuite_id != SecurityBlock::BAB_HMAC) continue;
00128 
00129                                         // skip this BAB if the security source do not match the key
00130                                         if (!bab.isSecuritySource(bundle, key.reference)) continue;
00131 
00132                                         // remember it for later check
00133                                         correlators.insert(bab._correlator);
00134                                 }
00135                         }
00136 
00137                         throw ibrcommon::Exception("verification failed");
00138                 }
00139 
00140                 std::string BundleAuthenticationBlock::calcMAC(const dtn::data::Bundle& bundle, const dtn::security::SecurityKey &key, const bool with_correlator, const u_int64_t correlator)
00141                 {
00142                         std::string hmac_key = key.getData();
00143                         ibrcommon::HMacStream hms((const unsigned char*)hmac_key.c_str(), hmac_key.length());
00144                         dtn::security::StrictSerializer ss(hms, BUNDLE_AUTHENTICATION_BLOCK, with_correlator, correlator);
00145                         ss << bundle;
00146                         hms << std::flush;
00147 
00148                         return ibrcommon::HashStream::extract(hms);
00149                 }
00150 
00151                 size_t BundleAuthenticationBlock::getSecurityResultSize() const
00152                 {
00153                         // TLV type
00154                         size_t size = 1;
00155                         // length of value length
00156                         size += dtn::data::SDNV::getLength(EVP_MD_size(EVP_sha1()));
00157                         // length of value
00158                         size += EVP_MD_size(EVP_sha1());
00159                         return size;
00160                 }
00161 
00162         }
00163 }