IBR-DTNSuite
0.8
|
00001 #include "ibrdtn/security/PayloadIntegrityBlock.h" 00002 #include "ibrdtn/security/MutualSerializer.h" 00003 #include "ibrdtn/data/Bundle.h" 00004 00005 #include <ibrcommon/ssl/RSASHA256Stream.h> 00006 #include <ibrcommon/Logger.h> 00007 #include <openssl/err.h> 00008 #include <openssl/rsa.h> 00009 00010 #ifdef __DEVELOPMENT_ASSERTIONS__ 00011 #include <cassert> 00012 #endif 00013 00014 namespace dtn 00015 { 00016 namespace security 00017 { 00018 dtn::data::Block* PayloadIntegrityBlock::Factory::create() 00019 { 00020 return new PayloadIntegrityBlock(); 00021 } 00022 00023 PayloadIntegrityBlock::PayloadIntegrityBlock() 00024 : SecurityBlock(PAYLOAD_INTEGRITY_BLOCK, PIB_RSA_SHA256), result_size(0) 00025 { 00026 } 00027 00028 PayloadIntegrityBlock::~PayloadIntegrityBlock() 00029 { 00030 } 00031 00032 size_t PayloadIntegrityBlock::getSecurityResultSize() const 00033 { 00034 if (result_size > 0) 00035 { 00036 return result_size; 00037 } 00038 00039 return SecurityBlock::getSecurityResultSize(); 00040 } 00041 00042 void PayloadIntegrityBlock::sign(dtn::data::Bundle &bundle, const SecurityKey &key, const dtn::data::EID& destination) 00043 { 00044 PayloadIntegrityBlock& pib = bundle.push_front<PayloadIntegrityBlock>(); 00045 pib.set(REPLICATE_IN_EVERY_FRAGMENT, true); 00046 00047 // check if this is a fragment 00048 if (bundle.get(dtn::data::PrimaryBlock::FRAGMENT)) 00049 { 00050 dtn::data::PayloadBlock& plb = bundle.getBlock<dtn::data::PayloadBlock>(); 00051 ibrcommon::BLOB::Reference blobref = plb.getBLOB(); 00052 ibrcommon::BLOB::iostream stream = blobref.iostream(); 00053 addFragmentRange(pib._ciphersuite_params, bundle._fragmentoffset, stream.size()); 00054 } 00055 00056 // set the source and destination address of the new block 00057 if (key.reference != bundle._source.getNode()) pib.setSecuritySource( key.reference ); 00058 if (destination != bundle._destination.getNode()) pib.setSecurityDestination( destination ); 00059 00060 pib.setResultSize(key); 00061 pib.setCiphersuiteId(SecurityBlock::PIB_RSA_SHA256); 00062 pib._ciphersuite_flags |= CONTAINS_SECURITY_RESULT; 00063 std::string sign = calcHash(bundle, key, pib); 00064 pib._security_result.set(SecurityBlock::integrity_signature, sign); 00065 } 00066 00067 const std::string PayloadIntegrityBlock::calcHash(const dtn::data::Bundle &bundle, const SecurityKey &key, PayloadIntegrityBlock& ignore) 00068 { 00069 EVP_PKEY *pkey = key.getEVP(); 00070 ibrcommon::RSASHA256Stream rs2s(pkey); 00071 00072 // serialize the bundle in the mutable form 00073 dtn::security::MutualSerializer ms(rs2s, &ignore); 00074 (dtn::data::DefaultSerializer&)ms << bundle; rs2s << std::flush; 00075 00076 int return_code = rs2s.getSign().first; 00077 std::string sign_string = rs2s.getSign().second; 00078 SecurityKey::free(pkey); 00079 00080 if (return_code) 00081 return sign_string; 00082 else 00083 { 00084 IBRCOMMON_LOGGER_ex(critical) << "an error occured at the creation of the hash and it is invalid" << IBRCOMMON_LOGGER_ENDL; 00085 ERR_print_errors_fp(stderr); 00086 return std::string(""); 00087 } 00088 } 00089 00090 void PayloadIntegrityBlock::verify(const dtn::data::Bundle& bundle, const SecurityKey &key, const PayloadIntegrityBlock &sb, const bool use_eid) 00091 { 00092 // check if we have the public key of the security source 00093 if (use_eid) 00094 { 00095 if (!sb.isSecuritySource(bundle, key.reference)) 00096 { 00097 throw ibrcommon::Exception("key not match the security source"); 00098 } 00099 } 00100 00101 // check the correct algorithm 00102 if (sb._ciphersuite_id != SecurityBlock::PIB_RSA_SHA256) 00103 { 00104 throw ibrcommon::Exception("can not verify the PIB because of an invalid algorithm"); 00105 } 00106 00107 EVP_PKEY *pkey = key.getEVP(); 00108 if (pkey == NULL) throw ibrcommon::Exception("verification error"); 00109 00110 ibrcommon::RSASHA256Stream rs2s(pkey, true); 00111 00112 // serialize the bundle in the mutable form 00113 dtn::security::MutualSerializer ms(rs2s, &sb); 00114 (dtn::data::DefaultSerializer&)ms << bundle; rs2s << std::flush; 00115 00116 int ret = rs2s.getVerification(sb._security_result.get(SecurityBlock::integrity_signature)); 00117 SecurityKey::free(pkey); 00118 00119 if (ret == 0) 00120 { 00121 throw ibrcommon::Exception("verification failed"); 00122 } 00123 else if (ret < 0) 00124 { 00125 throw ibrcommon::Exception("verification error"); 00126 } 00127 } 00128 00129 void PayloadIntegrityBlock::verify(const dtn::data::Bundle &bundle, const SecurityKey &key) 00130 { 00131 // iterate over all PIBs to find the right one 00132 std::list<const PayloadIntegrityBlock *> pibs = bundle.getBlocks<PayloadIntegrityBlock>(); 00133 00134 for (std::list<const PayloadIntegrityBlock *>::const_iterator it = pibs.begin(); it!=pibs.end(); it++) 00135 { 00136 verify(bundle, key, **it); 00137 } 00138 } 00139 00140 void PayloadIntegrityBlock::setResultSize(const SecurityKey &key) 00141 { 00142 EVP_PKEY *pkey = key.getEVP(); 00143 00144 // size of integrity_signature 00145 if ((result_size = EVP_PKEY_size(pkey)) > 0) 00146 { 00147 // sdnv length 00148 result_size += dtn::data::SDNV(result_size).getLength(); 00149 00150 // type 00151 result_size++; 00152 } 00153 else 00154 { 00155 result_size = _security_result.getLength(); 00156 } 00157 00158 SecurityKey::free(pkey); 00159 } 00160 00161 void PayloadIntegrityBlock::strip(dtn::data::Bundle& bundle, const SecurityKey &key, const bool all) 00162 { 00163 std::list<const PayloadIntegrityBlock *> pibs = bundle.getBlocks<PayloadIntegrityBlock>(); 00164 const PayloadIntegrityBlock * valid = NULL; 00165 00166 // search for valid PIB 00167 for (std::list<const PayloadIntegrityBlock *>::const_iterator it = pibs.begin(); it != pibs.end() && !valid; it++) 00168 { 00169 const PayloadIntegrityBlock &pib = (**it); 00170 00171 // check if the PIB is valid 00172 try { 00173 verify(bundle, key, pib); 00174 00175 // found an valid PIB, remove it 00176 bundle.remove(pib); 00177 00178 // remove all previous pibs if all = true 00179 if (all && (it != pibs.begin())) 00180 { 00181 // move the iterator one backward 00182 for (it--; it != pibs.begin(); it--) 00183 { 00184 bundle.remove(**it); 00185 } 00186 00187 // remove the first PIB too 00188 bundle.remove(**it); 00189 } 00190 00191 return; 00192 } catch (const ibrcommon::Exception&) { }; 00193 } 00194 } 00195 00196 void PayloadIntegrityBlock::strip(dtn::data::Bundle& bundle) 00197 { 00198 std::list<const PayloadIntegrityBlock *> pibs = bundle.getBlocks<PayloadIntegrityBlock>(); 00199 for (std::list<const PayloadIntegrityBlock *>::const_iterator it = pibs.begin(); it != pibs.end(); it++) 00200 { 00201 bundle.remove(*(*it)); 00202 } 00203 } 00204 00205 std::istream& PayloadIntegrityBlock::deserialize(std::istream &stream, const size_t length) 00206 { 00207 // deserialize the SecurityBlock 00208 SecurityBlock::deserialize(stream, length); 00209 00210 // set the key size locally 00211 result_size = _security_result.getLength(); 00212 00213 return stream; 00214 } 00215 } 00216 }