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