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
00039 u_int32_t salt;
00040
00041
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
00048 const std::list<const PayloadConfidentialBlock* > pcbs = bundle.getBlocks<PayloadConfidentialBlock>();
00049
00050
00051 const std::list<const PayloadIntegrityBlock* > pibs = bundle.getBlocks<PayloadIntegrityBlock>();
00052
00053
00054 PayloadConfidentialBlock& pcb = bundle.push_front<PayloadConfidentialBlock>();
00055
00056
00057 createSaltAndKey(salt, ephemeral_key, ibrcommon::AES128Stream::key_size_in_bytes);
00058
00059
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
00068 ((ibrcommon::CipherStream&)aes_stream).encrypt(*stream);
00069
00070
00071 if (bundle.get(dtn::data::PrimaryBlock::FRAGMENT))
00072 {
00073
00074 addFragmentRange(pcb._ciphersuite_params, bundle._fragmentoffset, stream.size());
00075 }
00076
00077
00078 aes_stream.getIV(iv);
00079
00080
00081 aes_stream.getTag(tag);
00082 }
00083
00084
00085
00086 if (source != bundle._source.getNodeEID()) pcb.setSecuritySource( source );
00087 if (long_key.reference != bundle._destination.getNodeEID()) pcb.setSecurityDestination( long_key.reference );
00088
00089
00090 pcb.set(REPLICATE_IN_EVERY_FRAGMENT, true);
00091
00092
00093 addSalt(pcb._ciphersuite_params, salt);
00094
00095
00096 RSA *rsa_key = long_key.getRSA();
00097
00098
00099 addKey(pcb._ciphersuite_params, ephemeral_key, ibrcommon::AES128Stream::key_size_in_bytes, rsa_key);
00100
00101
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::integrity_signature, tag, ibrcommon::AES128Stream::tag_len);
00108 pcb._ciphersuite_flags |= SecurityBlock::CONTAINS_SECURITY_RESULT;
00109
00110
00111 u_int64_t correlator = createCorrelatorValue(bundle);
00112
00113 if (pcbs.size() > 0 || pibs.size() > 0)
00114 pcb.setCorrelator(correlator);
00115
00116
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
00127 std::list<const dtn::data::Block*> erasure_list;
00128
00129
00130 RSA *rsa_key = long_key.getRSA();
00131
00132 try {
00133
00134 unsigned char key[ibrcommon::AES128Stream::key_size_in_bytes];
00135
00136
00137 uint64_t correlator = 0;
00138 bool decrypt_related = false;
00139
00140
00141 const std::list<const dtn::data::Block*> blocks = bundle.getBlocks();
00142
00143
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
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
00157 if (decrypt_related)
00158 {
00159
00160 try {
00161 decryptBlock(bundle, (dtn::security::SecurityBlock&)**it, salt, key);
00162
00163
00164 erasure_list.push_back(*it);
00165 } catch (const ibrcommon::Exception&) {
00166 IBRCOMMON_LOGGER(critical) << "tag verfication failed, reversing decryption..." << IBRCOMMON_LOGGER_ENDL;
00167 decryptBlock(bundle, (dtn::security::SecurityBlock&)**it, salt, key);
00168
00169
00170 throw ibrcommon::Exception("decrypt of correlated block reversed, tag verfication failed");
00171 }
00172 }
00173
00174 else if (pcb.isSecurityDestination(bundle, long_key.reference) &&
00175 (pcb._ciphersuite_id == SecurityBlock::PCB_RSA_AES128_PAYLOAD_PIB_PCB))
00176 {
00177
00178 u_int32_t salt = getSalt(pcb._ciphersuite_params);
00179
00180
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
00188 if (!decryptPayload(bundle, key, salt))
00189 {
00190
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
00197 erasure_list.push_back(*it);
00198
00199
00200 if (pcb._ciphersuite_flags & CONTAINS_CORRELATOR)
00201 {
00202
00203 decrypt_related = true;
00204
00205
00206 correlator = pcb._correlator;
00207 }
00208 else
00209 {
00210
00211
00212 break;
00213 }
00214 }
00215 else
00216 {
00217
00218 throw ibrcommon::Exception("unable to decrypt the first PCB");
00219 }
00220 } catch (const std::bad_cast&) { };
00221 }
00222
00223
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
00239 PayloadConfidentialBlock& pcb = bundle.getBlock<PayloadConfidentialBlock>();
00240 dtn::data::PayloadBlock& plb = bundle.getBlock<dtn::data::PayloadBlock>();
00241
00242
00243 unsigned char iv[ibrcommon::AES128Stream::iv_len];
00244 pcb._ciphersuite_params.get(SecurityBlock::initialization_vector, iv, ibrcommon::AES128Stream::iv_len);
00245
00246
00247 unsigned char tag[ibrcommon::AES128Stream::tag_len];
00248 pcb._security_result.get(SecurityBlock::integrity_signature, tag, ibrcommon::AES128Stream::tag_len);
00249
00250
00251 ibrcommon::BLOB::Reference blobref = plb.getBLOB();
00252
00253
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
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 }