|
IBR-DTNSuite 0.6
|
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 }