IBR-DTNSuite
0.8
|
00001 #include "ibrdtn/security/PayloadConfidentialBlock.h" 00002 #include "ibrdtn/security/PayloadIntegrityBlock.h" 00003 #include "ibrdtn/data/Bundle.h" 00004 #include "ibrdtn/data/SDNV.h" 00005 00006 #include <openssl/err.h> 00007 #include <openssl/rsa.h> 00008 #include <ibrcommon/thread/MutexLock.h> 00009 #include <ibrcommon/Logger.h> 00010 00011 #include <stdint.h> 00012 #include <typeinfo> 00013 00014 #ifdef __DEVELOPMENT_ASSERTIONS__ 00015 #include <cassert> 00016 #endif 00017 00018 namespace dtn 00019 { 00020 namespace security 00021 { 00022 dtn::data::Block* PayloadConfidentialBlock::Factory::create() 00023 { 00024 return new PayloadConfidentialBlock(); 00025 } 00026 00027 PayloadConfidentialBlock::PayloadConfidentialBlock() 00028 : SecurityBlock(PAYLOAD_CONFIDENTIAL_BLOCK, PCB_RSA_AES128_PAYLOAD_PIB_PCB) 00029 { 00030 } 00031 00032 PayloadConfidentialBlock::~PayloadConfidentialBlock() 00033 { 00034 } 00035 00036 void PayloadConfidentialBlock::encrypt(dtn::data::Bundle& bundle, const dtn::security::SecurityKey &long_key, const dtn::data::EID& source) 00037 { 00038 // contains the random salt 00039 u_int32_t salt; 00040 00041 // contains the random key 00042 unsigned char ephemeral_key[ibrcommon::AES128Stream::key_size_in_bytes]; 00043 00044 unsigned char iv[ibrcommon::AES128Stream::iv_len]; 00045 unsigned char tag[ibrcommon::AES128Stream::tag_len]; 00046 00047 // get all PCBs 00048 const std::list<const PayloadConfidentialBlock* > pcbs = bundle.getBlocks<PayloadConfidentialBlock>(); 00049 00050 // get all PIBs 00051 const std::list<const PayloadIntegrityBlock* > pibs = bundle.getBlocks<PayloadIntegrityBlock>(); 00052 00053 // create a new payload confidential block 00054 PayloadConfidentialBlock& pcb = bundle.push_front<PayloadConfidentialBlock>(); 00055 00056 // create a random salt and key 00057 createSaltAndKey(salt, ephemeral_key, ibrcommon::AES128Stream::key_size_in_bytes); 00058 00059 // encrypt payload - BEGIN 00060 dtn::data::PayloadBlock& plb = bundle.getBlock<dtn::data::PayloadBlock>(); 00061 ibrcommon::BLOB::Reference blobref = plb.getBLOB(); 00062 00063 { 00064 ibrcommon::BLOB::iostream stream = blobref.iostream(); 00065 ibrcommon::AES128Stream aes_stream(ibrcommon::CipherStream::CIPHER_ENCRYPT, *stream, ephemeral_key, salt); 00066 00067 // encrypt in place 00068 ((ibrcommon::CipherStream&)aes_stream).encrypt(*stream); 00069 00070 // check if this is a fragment 00071 if (bundle.get(dtn::data::PrimaryBlock::FRAGMENT)) 00072 { 00073 // ... and set the corresponding cipher suit params 00074 addFragmentRange(pcb._ciphersuite_params, bundle._fragmentoffset, stream.size()); 00075 } 00076 00077 // get the IV 00078 aes_stream.getIV(iv); 00079 00080 // get the tag 00081 aes_stream.getTag(tag); 00082 } 00083 // encrypt payload - END 00084 00085 // set the source and destination address of the new block 00086 if (source != bundle._source.getNode()) pcb.setSecuritySource( source ); 00087 if (long_key.reference != bundle._destination.getNode()) pcb.setSecurityDestination( long_key.reference ); 00088 00089 // set replicate in every fragment to true 00090 pcb.set(REPLICATE_IN_EVERY_FRAGMENT, true); 00091 00092 // store encypted key, tag, iv and salt 00093 addSalt(pcb._ciphersuite_params, salt); 00094 00095 // get the RSA key 00096 RSA *rsa_key = long_key.getRSA(); 00097 00098 // encrypt the random key and add it to the ciphersuite params 00099 addKey(pcb._ciphersuite_params, ephemeral_key, ibrcommon::AES128Stream::key_size_in_bytes, rsa_key); 00100 00101 // free the RSA key 00102 long_key.free(rsa_key); 00103 00104 pcb._ciphersuite_params.set(SecurityBlock::initialization_vector, iv, ibrcommon::AES128Stream::iv_len); 00105 pcb._ciphersuite_flags |= SecurityBlock::CONTAINS_CIPHERSUITE_PARAMS; 00106 00107 pcb._security_result.set(SecurityBlock::PCB_integrity_check_value, tag, ibrcommon::AES128Stream::tag_len); 00108 pcb._ciphersuite_flags |= SecurityBlock::CONTAINS_SECURITY_RESULT; 00109 00110 // create correlator 00111 u_int64_t correlator = createCorrelatorValue(bundle); 00112 00113 if (pcbs.size() > 0 || pibs.size() > 0) 00114 pcb.setCorrelator(correlator); 00115 00116 // encrypt PCBs and PIBs 00117 for (std::list<const PayloadConfidentialBlock*>::const_iterator it = pcbs.begin(); it != pcbs.end(); it++) 00118 SecurityBlock::encryptBlock<PayloadConfidentialBlock>(bundle, (dtn::data::Block&)**it, salt, ephemeral_key).setCorrelator(correlator); 00119 00120 for (std::list<const PayloadIntegrityBlock*>::const_iterator it = pibs.begin(); it != pibs.end(); it++) 00121 SecurityBlock::encryptBlock<PayloadConfidentialBlock>(bundle, (dtn::data::Block&)**it, salt, ephemeral_key).setCorrelator(correlator); 00122 } 00123 00124 void PayloadConfidentialBlock::decrypt(dtn::data::Bundle& bundle, const dtn::security::SecurityKey &long_key) 00125 { 00126 // list of block to delete if the process is successful 00127 std::list<const dtn::data::Block*> erasure_list; 00128 00129 // load the RSA key 00130 RSA *rsa_key = long_key.getRSA(); 00131 00132 try { 00133 // array for the current symmetric AES key 00134 unsigned char key[ibrcommon::AES128Stream::key_size_in_bytes]; 00135 00136 // correlator of the first PCB 00137 uint64_t correlator = 0; 00138 bool decrypt_related = false; 00139 00140 // get all blocks of this bundle 00141 const std::list<const dtn::data::Block*> blocks = bundle.getBlocks(); 00142 00143 // iterate through all blocks 00144 for (std::list<const dtn::data::Block* >::const_iterator it = blocks.begin(); it != blocks.end(); it++) 00145 { 00146 try { 00147 dynamic_cast<const PayloadIntegrityBlock&>(**it); 00148 00149 // add this block to the erasure list for later deletion 00150 erasure_list.push_back(*it); 00151 } catch (const std::bad_cast&) { }; 00152 00153 try { 00154 const PayloadConfidentialBlock &pcb = dynamic_cast<const PayloadConfidentialBlock&>(**it); 00155 00156 // get salt and key 00157 u_int32_t salt = getSalt(pcb._ciphersuite_params); 00158 00159 // decrypt related blocks 00160 if (decrypt_related) 00161 { 00162 // try to decrypt the block 00163 try { 00164 decryptBlock(bundle, (dtn::security::SecurityBlock&)**it, salt, key); 00165 00166 // success! add this block to the erasue list 00167 erasure_list.push_back(*it); 00168 } catch (const ibrcommon::Exception&) { 00169 IBRCOMMON_LOGGER(critical) << "tag verfication failed, reversing decryption..." << IBRCOMMON_LOGGER_ENDL; 00170 decryptBlock(bundle, (dtn::security::SecurityBlock&)**it, salt, key); 00171 00172 // abort the decryption and discard the bundle? 00173 throw ibrcommon::Exception("decrypt of correlated block reversed, tag verfication failed"); 00174 } 00175 } 00176 // if security destination does match the key, then try to decrypt the payload 00177 else if (pcb.isSecurityDestination(bundle, long_key.reference) && 00178 (pcb._ciphersuite_id == SecurityBlock::PCB_RSA_AES128_PAYLOAD_PIB_PCB)) 00179 { 00180 // try to decrypt the symmetric AES key 00181 if (!getKey(pcb._ciphersuite_params, key, ibrcommon::AES128Stream::key_size_in_bytes, rsa_key)) 00182 { 00183 IBRCOMMON_LOGGER(critical) << "could not get symmetric key decrypted" << IBRCOMMON_LOGGER_ENDL; 00184 throw ibrcommon::Exception("decrypt failed - could not get symmetric key decrypted"); 00185 } 00186 00187 // try to decrypt the payload 00188 if (!decryptPayload(bundle, key, salt)) 00189 { 00190 // reverse decryption 00191 IBRCOMMON_LOGGER(critical) << "tag verfication failed, reversing decryption..." << IBRCOMMON_LOGGER_ENDL; 00192 decryptPayload(bundle, key, salt); 00193 throw ibrcommon::Exception("decrypt reversed - tag verfication failed"); 00194 } 00195 00196 // success! add this block to the erasue list 00197 erasure_list.push_back(*it); 00198 00199 // check if first PCB has a correlator 00200 if (pcb._ciphersuite_flags & CONTAINS_CORRELATOR) 00201 { 00202 // ... and decrypt all correlated block with the same key 00203 decrypt_related = true; 00204 00205 // store the correlator 00206 correlator = pcb._correlator; 00207 } 00208 else 00209 { 00210 // no correlated blocks should exists 00211 // stop here with decryption 00212 break; 00213 } 00214 } 00215 else 00216 { 00217 // exit here, because we can not decrypt the first PCB. 00218 throw ibrcommon::Exception("unable to decrypt the first PCB"); 00219 } 00220 } catch (const std::bad_cast&) { }; 00221 } 00222 00223 // delete all block in the erasure list 00224 for (std::list<const dtn::data::Block* >::const_iterator it = erasure_list.begin(); it != erasure_list.end(); it++) 00225 { 00226 bundle.remove(**it); 00227 } 00228 } catch (const std::exception&) { 00229 long_key.free(rsa_key); 00230 throw; 00231 } 00232 00233 long_key.free(rsa_key); 00234 } 00235 00236 bool PayloadConfidentialBlock::decryptPayload(dtn::data::Bundle& bundle, const unsigned char ephemeral_key[ibrcommon::AES128Stream::key_size_in_bytes], const u_int32_t salt) 00237 { 00238 // TODO handle fragmentation 00239 PayloadConfidentialBlock& pcb = bundle.getBlock<PayloadConfidentialBlock>(); 00240 dtn::data::PayloadBlock& plb = bundle.getBlock<dtn::data::PayloadBlock>(); 00241 00242 // the array for the extracted iv 00243 unsigned char iv[ibrcommon::AES128Stream::iv_len]; 00244 pcb._ciphersuite_params.get(SecurityBlock::initialization_vector, iv, ibrcommon::AES128Stream::iv_len); 00245 00246 // the array for the extracted tag 00247 unsigned char tag[ibrcommon::AES128Stream::tag_len]; 00248 pcb._security_result.get(SecurityBlock::PCB_integrity_check_value, tag, ibrcommon::AES128Stream::tag_len); 00249 00250 // get the reference to the corresponding BLOB object 00251 ibrcommon::BLOB::Reference blobref = plb.getBLOB(); 00252 00253 // decrypt the payload and get the integrity signature (tag) 00254 { 00255 ibrcommon::BLOB::iostream stream = blobref.iostream(); 00256 ibrcommon::AES128Stream decrypt(ibrcommon::CipherStream::CIPHER_DECRYPT, *stream, ephemeral_key, salt, iv); 00257 ((ibrcommon::CipherStream&)decrypt).decrypt(*stream); 00258 00259 // get the decrypt tag 00260 if (!decrypt.verify(tag)) 00261 { 00262 IBRCOMMON_LOGGER(error) << "integrity signature of the decrypted payload is invalid" << IBRCOMMON_LOGGER_ENDL; 00263 return false; 00264 } 00265 } 00266 00267 return true; 00268 } 00269 } 00270 }