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