Beispiel #1
0
		bool DefaultSerializer::isCompressable(const dtn::data::Bundle &obj) const
		{
			// check if all EID are compressable
			bool compressable = ( obj.source.isCompressable() &&
					obj.destination.isCompressable() &&
					obj.reportto.isCompressable() &&
					obj.custodian.isCompressable() );

			if (compressable)
			{
				// add EID of all secondary blocks
				for (Bundle::const_iterator iter = obj.begin(); iter != obj.end(); ++iter)
				{
					const Block &b = (**iter);
					const std::list<dtn::data::EID> eids = b.getEIDList();

					for (std::list<dtn::data::EID>::const_iterator eit = eids.begin(); eit != eids.end(); ++eit)
					{
						const dtn::data::EID &eid = (*eit);
						if (!eid.isCompressable())
						{
							return false;
						}
					}
				}
			}

			return compressable;
		}
		void SecurityManager::verifyBAB(dtn::data::Bundle &bundle) const throw (VerificationFailedException)
		{
			IBRCOMMON_LOGGER_DEBUG_TAG("SecurityManager", 10) << "verify authenticated bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;

			// iterate over all BABs of this bundle
			dtn::data::Bundle::find_iterator it(bundle.begin(), dtn::security::BundleAuthenticationBlock::BLOCK_TYPE);
			while (it.next(bundle.end()))
			{
				const dtn::security::BundleAuthenticationBlock& bab = dynamic_cast<const dtn::security::BundleAuthenticationBlock&>(**it);

				// look for the right BAB-factory
				const dtn::data::EID node = bab.getSecuritySource(bundle);

				try {
					// try to load the key of the BAB
					const SecurityKey key = SecurityKeyManager::getInstance().get(node, SecurityKey::KEY_SHARED);

					// verify the bundle
					dtn::security::BundleAuthenticationBlock::verify(bundle, key);

					// strip all BAB of this bundle
					dtn::security::BundleAuthenticationBlock::strip(bundle);

					// set the verify bit, after verification
					bundle.set(dtn::data::Bundle::DTNSEC_STATUS_AUTHENTICATED, true);

					// at least one BAB has been authenticated, we're done!
					break;
				} catch (const SecurityKey::KeyNotFoundException&) {
					// no key for this node found
				}
			}
		}
void BundleStorageTest::testFragment(dtn::storage::BundleStorage &storage)
{
	// Add fragment of a bundle to the storage
	dtn::data::Bundle b;

	// set standard variables
	b.source = dtn::data::EID("dtn://node-one/test");
	b.lifetime = 1;
	b.destination = dtn::data::EID("dtn://node-two/test");

	// add some payload
	ibrcommon::BLOB::Reference ref = ibrcommon::BLOB::create();
	b.push_back(ref);

	(*ref.iostream()) << "Hallo Welt" << std::endl;

	// transform bundle into a fragment
	b.procflags.setBit(dtn::data::PrimaryBlock::FRAGMENT, true);
	b.fragmentoffset = 4;
	b.appdatalength = 50;

	// store the bundle
	storage.store(b);

	CPPUNIT_ASSERT_EQUAL((size_t)1, storage.count());

	// create a non-fragment meta bundle
	const dtn::data::BundleID id(b);

	const dtn::data::Bundle retrieved = storage.get(id);

	CPPUNIT_ASSERT_EQUAL(id.getPayloadLength(), retrieved.getPayloadLength());

	CPPUNIT_ASSERT_EQUAL(id, (const dtn::data::BundleID&)retrieved);
}
void BundleStorageTest::testStore(dtn::storage::BundleStorage &storage)
{
	dtn::data::Bundle b;
	b.source = dtn::data::EID("dtn://node-one/test");

	// set standard variable.sourceurce = dtn::data::EID("dtn://node-one/test");
	b.lifetime = 120;
	b.destination = dtn::data::EID("dtn://node-two/test");

	// add some payload
	ibrcommon::BLOB::Reference ref = ibrcommon::BLOB::create();
	b.push_back(ref);

	(*ref.iostream()) << "Hallo Welt" << std::endl;

	CPPUNIT_ASSERT_EQUAL((dtn::data::Size)0, storage.count());

	storage.store(b);

	CPPUNIT_ASSERT_EQUAL((dtn::data::Size)1, storage.count());

	// create a bundle id
	const dtn::data::BundleID id(b);

	CPPUNIT_ASSERT_EQUAL(id, (const dtn::data::BundleID&)b);

	const dtn::data::Bundle retrieved = storage.get(id);

	CPPUNIT_ASSERT_EQUAL(id.getPayloadLength(), retrieved.getPayloadLength());

	CPPUNIT_ASSERT_EQUAL(id, (const dtn::data::BundleID&)retrieved);
}
		void ExtensionSecurityBlock::decrypt(dtn::data::Bundle& bundle, const SecurityKey &key, const dtn::data::Number &correlator)
		{
			// iterate through all extension security blocks
			dtn::data::Bundle::find_iterator find_it(bundle.begin(), ExtensionSecurityBlock::BLOCK_TYPE);
			while (find_it.next(bundle.end()))
			{
				const dtn::security::ExtensionSecurityBlock &esb = dynamic_cast<const dtn::security::ExtensionSecurityBlock&>(**find_it);

				if ((correlator == 0) || (correlator == esb._correlator))
				{
					decrypt(bundle, key, find_it);
				}
			}
		}
		void PayloadIntegrityBlock::verify(const dtn::data::Bundle &bundle, const SecurityKey &key)
		{
			// iterate over all PIBs to find the right one
			dtn::data::Bundle::const_find_iterator it(bundle.begin(), PayloadIntegrityBlock::BLOCK_TYPE);

			while (it.next(bundle.end()))
			{
				const PayloadIntegrityBlock &sb = dynamic_cast<const PayloadIntegrityBlock&>(**it);

				// check if we have the public key of the security source
				// skip this block if the given key isn't the right one
				if (!sb.isSecuritySource(bundle, key.reference)) continue;

				// check the correct algorithm
				if (sb._ciphersuite_id != SecurityBlock::PIB_RSA_SHA256)
				{
					throw VerificationFailedException("can not verify the PIB because of an invalid algorithm");
				}

				EVP_PKEY *pkey = key.getEVP();
				if (pkey == NULL) throw VerificationFailedException("verification error");

				ibrcommon::RSASHA256Stream rs2s(pkey, true);

				// serialize the bundle in the mutable form
				dtn::security::MutableSerializer ms(rs2s, &sb);
				(dtn::data::DefaultSerializer&)ms << bundle; rs2s << std::flush;

				try {
					int ret = rs2s.getVerification(sb._security_result.get(SecurityBlock::integrity_signature));
					SecurityKey::free(pkey);

					if (ret > 0)
					{
						// success!
						return;
					}
					else if (ret < 0)
					{
						throw VerificationFailedException("verification error");
					}
				} catch (const ElementMissingException&) {
					// This PIB can not verified due to a missing integrity signature
					throw VerificationFailedException("Integrity signature is missing!");
				}
			}

			throw VerificationFailedException("verification failed");
		}
Beispiel #7
0
		void Registration::processIncomingBundle(const dtn::data::EID &source, dtn::data::Bundle &bundle)
		{
			// check address fields for "api:me", this has to be replaced
			static const dtn::data::EID clienteid("api:me");

			// create a new sequence number
			bundle.relabel();

			// if the relabeling results in a zero timestamp, add an ageblock
			if (bundle.timestamp == 0)
			{
				// check for ageblock
				try {
					bundle.find<dtn::data::AgeBlock>();
				} catch (const dtn::data::Bundle::NoSuchBlockFoundException&) {
					// add a new ageblock
					bundle.push_front<dtn::data::AgeBlock>();
				}
			}

			// set the source address to the sending EID
			bundle.source = source;

			if (bundle.destination == clienteid) bundle.destination = source;
			if (bundle.reportto == clienteid) bundle.reportto = source;
			if (bundle.custodian == clienteid) bundle.custodian = source;

			// inject the bundle
			dtn::core::BundleCore::inject(source, bundle);
		}
Beispiel #8
0
		Length DefaultSerializer::getLength(const dtn::data::Bundle &obj)
		{
			// rebuild the dictionary
			rebuildDictionary(obj);

			Length len = 0;
			len += getLength( (PrimaryBlock&)obj );
			
			// add size of all blocks
			for (Bundle::const_iterator iter = obj.begin(); iter != obj.end(); ++iter)
			{
				const Block &b = (**iter);
				len += getLength( b );
			}

			return len;
		}
		void BundleAuthenticationBlock::verify(const dtn::data::Bundle& bundle, const dtn::security::SecurityKey &key, dtn::data::Number &correlator) throw (ibrcommon::Exception)
		{
			// get the blocks, with which the key should match
			std::set<dtn::data::Number> correlators;

			// calculate the MAC of this bundle
			std::string our_hash_string = calcMAC(bundle, key);

			dtn::data::Bundle::const_find_iterator it(bundle.begin(), BundleAuthenticationBlock::BLOCK_TYPE);
			while (it.next(bundle.end()))
			{
				const BundleAuthenticationBlock &bab = dynamic_cast<const BundleAuthenticationBlock&>(**it);

				// the bab contains a security result
				if (bab._ciphersuite_flags & CONTAINS_SECURITY_RESULT)
				{
					// is this correlator known?
					if (correlators.find(bab._correlator) == correlators.end()) continue;

					std::string bab_result = bab._security_result.get(SecurityBlock::integrity_signature);
					if (our_hash_string == bab_result)
					{
						// hash matched
						correlator = bab._correlator;
						return;
					}

					IBRCOMMON_LOGGER_DEBUG_TAG("BundleAuthenticationBlock", 15) << "security mac does not match" << IBRCOMMON_LOGGER_ENDL;
				}
				// bab contains no security result but a correlator
				else if (bab._ciphersuite_flags &  CONTAINS_CORRELATOR)
				{
					// currently we only support BAB_HMAC mechanism
					if (bab._ciphersuite_id != SecurityBlock::BAB_HMAC) continue;

					// skip this BAB if the security source do not match the key
					if (!bab.isSecuritySource(bundle, key.reference)) continue;

					// remember it for later check
					correlators.insert(bab._correlator);
				}
			}

			throw ibrcommon::Exception("verification failed");
		}
		void SecurityManager::decrypt(dtn::data::Bundle &bundle) const throw (DecryptException, KeyMissingException)
		{
			// check if the bundle has to be decrypted, return when not
			if (std::count(bundle.begin(), bundle.end(), dtn::security::PayloadConfidentialBlock::BLOCK_TYPE) <= 0) return;

			// decrypt
			try {
				IBRCOMMON_LOGGER_DEBUG_TAG("SecurityManager", 10) << "decrypt bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;

				// get the encryption key
				dtn::security::SecurityKey key = SecurityKeyManager::getInstance().get(dtn::core::BundleCore::local, dtn::security::SecurityKey::KEY_PRIVATE);

				// encrypt the payload of the bundle
				dtn::security::PayloadConfidentialBlock::decrypt(bundle, key);

				bundle.set(dtn::data::Bundle::DTNSEC_STATUS_CONFIDENTIAL, true);
			} catch (const ibrcommon::Exception &ex) {
				throw DecryptException(ex.what());
			}
		}
		void BundleAuthenticationBlock::strip(dtn::data::Bundle &bundle, const dtn::security::SecurityKey &key)
		{
			// store the correlator of the verified BABs
			dtn::data::Number correlator;

			// verify the babs of the bundle
			verify(bundle, key, correlator);

			// iterate over all BABs
			dtn::data::Bundle::find_iterator it(bundle.begin(), BundleAuthenticationBlock::BLOCK_TYPE);
			while (it.next(bundle.end()))
			{
				const BundleAuthenticationBlock &bab = dynamic_cast<const BundleAuthenticationBlock&>(**it);

				// if the correlator is already authenticated, then remove the BAB
				if ((bab._ciphersuite_flags & SecurityBlock::CONTAINS_CORRELATOR) && (bab._correlator == correlator))
				{
					bundle.erase(it);
				}
			}
		}
		void SecurityManager::fastverify(const dtn::data::Bundle &bundle) const throw (VerificationFailedException)
		{
			// do a fast verify without manipulating the bundle
			const dtn::daemon::Configuration::Security &secconf = dtn::daemon::Configuration::getInstance().getSecurity();

			if (secconf.getLevel() & dtn::daemon::Configuration::Security::SECURITY_LEVEL_ENCRYPTED)
			{
				// check if the bundle is encrypted and throw an exception if not
				//throw VerificationFailedException("Bundle is not encrypted");
				IBRCOMMON_LOGGER_DEBUG_TAG("SecurityManager", 10) << "encryption required, verify bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;

				if (std::count(bundle.begin(), bundle.end(), dtn::security::PayloadConfidentialBlock::BLOCK_TYPE) == 0)
					throw VerificationFailedException("No PCB available!");
			}

			if (secconf.getLevel() & dtn::daemon::Configuration::Security::SECURITY_LEVEL_SIGNED)
			{
				// check if the bundle is signed and throw an exception if not
				//throw VerificationFailedException("Bundle is not signed");
				IBRCOMMON_LOGGER_DEBUG_TAG("SecurityManager", 10) << "signature required, verify bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;

				if (std::count(bundle.begin(), bundle.end(), dtn::security::PayloadIntegrityBlock::BLOCK_TYPE) == 0)
					throw VerificationFailedException("No PIB available!");
			}

			if (secconf.getLevel() & dtn::daemon::Configuration::Security::SECURITY_LEVEL_AUTHENTICATED)
			{
				// check if the bundle is signed and throw an exception if not
				//throw VerificationFailedException("Bundle is not signed");
				IBRCOMMON_LOGGER_DEBUG_TAG("SecurityManager", 10) << "authentication required, verify bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;

				if (std::count(bundle.begin(), bundle.end(), dtn::security::BundleAuthenticationBlock::BLOCK_TYPE) == 0)
					throw VerificationFailedException("No BAB available!");
			}
		}
		void SecurityManager::verifyPIB(dtn::data::Bundle &bundle) const throw (VerificationFailedException)
		{
			IBRCOMMON_LOGGER_DEBUG_TAG("SecurityManager", 10) << "verify signed bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;

			// iterate through all blocks
			for (dtn::data::Bundle::iterator it = bundle.begin(); it != bundle.end();)
			{
				const dtn::data::Block &block = (**it);

				if (block.getType() == dtn::security::PayloadConfidentialBlock::BLOCK_TYPE) {
					// payload after a PCB can not verified until the payload is decrypted
					break;
				}

				try {
					const dtn::security::PayloadIntegrityBlock& pib = dynamic_cast<const dtn::security::PayloadIntegrityBlock&>(block);

					const SecurityKey key = SecurityKeyManager::getInstance().get(pib.getSecuritySource(bundle), SecurityKey::KEY_PUBLIC);

					// try to verify the bundle with the key for the current PIB
					dtn::security::PayloadIntegrityBlock::verify(bundle, key);

					// if we are the security destination
					if (pib.isSecurityDestination(bundle, dtn::core::BundleCore::local)) {
						// remove the valid PIB
						bundle.erase(it++);
					} else {
						++it;
					}

					// set the verify bit, after verification
					bundle.set(dtn::data::PrimaryBlock::DTNSEC_STATUS_VERIFIED, true);

					IBRCOMMON_LOGGER_DEBUG_TAG("SecurityManager", 5) << "Bundle " << bundle.toString() << " successfully verified" << IBRCOMMON_LOGGER_ENDL;
					continue;
				} catch (const dtn::security::VerificationSkippedException&) {
					// un-set the verify bit
					bundle.set(dtn::data::PrimaryBlock::DTNSEC_STATUS_VERIFIED, false);
				} catch (const SecurityKey::KeyNotFoundException&) {
					// un-set the verify bit
					bundle.set(dtn::data::PrimaryBlock::DTNSEC_STATUS_VERIFIED, false);
				} catch (const std::bad_cast&) {
					// current block is not a PIB
				}

				++it;
			}
		}
		void SecurityManager::auth(dtn::data::Bundle &bundle) const throw (KeyMissingException)
		{
			IBRCOMMON_LOGGER_DEBUG_TAG("SecurityManager", 10) << "auth bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;

			try {
				// try to load the local key
				const SecurityKey key = SecurityKeyManager::getInstance().get(dtn::core::BundleCore::local, SecurityKey::KEY_SHARED);

				// sign the bundle with BABs
				dtn::security::BundleAuthenticationBlock::auth(bundle, key);
			} catch (const SecurityKey::KeyNotFoundException &ex) {
				throw KeyMissingException(ex.what());
			}
		}
		void SecurityManager::encrypt(dtn::data::Bundle &bundle) const throw (EncryptException, KeyMissingException)
		{
			try {
				IBRCOMMON_LOGGER_DEBUG_TAG("SecurityManager", 10) << "encrypt bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;

				// get the encryption key
				dtn::security::SecurityKey key = SecurityKeyManager::getInstance().get(bundle.destination, dtn::security::SecurityKey::KEY_PUBLIC);

				// encrypt the payload of the bundle
				dtn::security::PayloadConfidentialBlock::encrypt(bundle, key, dtn::core::BundleCore::local);
			} catch (const ibrcommon::Exception &ex) {
				throw EncryptException(ex.what());
			}
		}
		void SecurityManager::sign(dtn::data::Bundle &bundle) const throw (KeyMissingException)
		{
			IBRCOMMON_LOGGER_DEBUG_TAG("SecurityManager", 10) << "sign bundle: " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;

			try {
				// try to load the local key
				const SecurityKey key = SecurityKeyManager::getInstance().get(dtn::core::BundleCore::local, SecurityKey::KEY_PRIVATE);

				// sign the bundle with PIB
				dtn::security::PayloadIntegrityBlock::sign(bundle, key, bundle.destination.getNode());
			} catch (const SecurityKey::KeyNotFoundException &ex) {
				throw KeyMissingException(ex.what());
			}
		}
		void PayloadIntegrityBlock::sign(dtn::data::Bundle &bundle, const SecurityKey &key, const dtn::data::EID& destination)
		{
			PayloadIntegrityBlock& pib = bundle.push_front<PayloadIntegrityBlock>();
			pib.set(REPLICATE_IN_EVERY_FRAGMENT, true);

			// check if this is a fragment
			if (bundle.get(dtn::data::PrimaryBlock::FRAGMENT))
			{
				dtn::data::PayloadBlock& plb = bundle.find<dtn::data::PayloadBlock>();
				ibrcommon::BLOB::Reference blobref = plb.getBLOB();
				ibrcommon::BLOB::iostream stream = blobref.iostream();
				addFragmentRange(pib._ciphersuite_params, bundle.fragmentoffset, stream.size());
			}

			// set the source and destination address of the new block
			if (!key.reference.sameHost(bundle.source)) pib.setSecuritySource( key.reference );
			if (!destination.sameHost(bundle.destination)) pib.setSecurityDestination( destination );

			pib.setResultSize(key);
			pib.setCiphersuiteId(SecurityBlock::PIB_RSA_SHA256);
			pib._ciphersuite_flags |= CONTAINS_SECURITY_RESULT;
			std::string sign = calcHash(bundle, key, pib);
			pib._security_result.set(SecurityBlock::integrity_signature, sign);
		}
Beispiel #18
0
		void Registration::processIncomingBundle(const dtn::data::EID &source, dtn::data::Bundle &bundle)
		{
			// check address fields for "api:me", this has to be replaced
			static const dtn::data::EID clienteid("api:me");

			// set the source address to the sending EID
			bundle.source = source;

			if (bundle.destination == clienteid) bundle.destination = source;
			if (bundle.reportto == clienteid) bundle.reportto = source;
			if (bundle.custodian == clienteid) bundle.custodian = source;

			// if the timestamp is not set, add a ageblock
			if (bundle.timestamp == 0)
			{
				// check for ageblock
				try {
					bundle.find<dtn::data::AgeBlock>();
				} catch (const dtn::data::Bundle::NoSuchBlockFoundException&) {
					// add a new ageblock
					bundle.push_front<dtn::data::AgeBlock>();
				}
			}

			// modify TrackingBlock
			try {
				dtn::data::TrackingBlock &track = bundle.find<dtn::data::TrackingBlock>();
				track.append(dtn::core::BundleCore::local);
			} catch (const dtn::data::Bundle::NoSuchBlockFoundException&) { };

#ifdef WITH_COMPRESSION
			// if the compression bit is set, then compress the bundle
			if (bundle.get(dtn::data::PrimaryBlock::IBRDTN_REQUEST_COMPRESSION))
			{
				try {
					dtn::data::CompressedPayloadBlock::compress(bundle, dtn::data::CompressedPayloadBlock::COMPRESSION_ZLIB);
				} catch (const ibrcommon::Exception &ex) {
					IBRCOMMON_LOGGER_TAG(Registration::TAG, warning) << "compression of bundle failed: " << ex.what() << IBRCOMMON_LOGGER_ENDL;
				};
			}
#endif

#ifdef WITH_BUNDLE_SECURITY
			// if the encrypt bit is set, then try to encrypt the bundle
			if (bundle.get(dtn::data::PrimaryBlock::DTNSEC_REQUEST_ENCRYPT))
			{
				try {
					dtn::security::SecurityManager::getInstance().encrypt(bundle);

					bundle.set(dtn::data::PrimaryBlock::DTNSEC_REQUEST_ENCRYPT, false);
				} catch (const dtn::security::SecurityManager::KeyMissingException&) {
					// sign requested, but no key is available
					IBRCOMMON_LOGGER_TAG(Registration::TAG, warning) << "No key available for encrypt process." << IBRCOMMON_LOGGER_ENDL;
				} catch (const dtn::security::SecurityManager::EncryptException&) {
					IBRCOMMON_LOGGER_TAG(Registration::TAG, warning) << "Encryption of bundle failed." << IBRCOMMON_LOGGER_ENDL;
				}
			}

			// if the sign bit is set, then try to sign the bundle
			if (bundle.get(dtn::data::PrimaryBlock::DTNSEC_REQUEST_SIGN))
			{
				try {
					dtn::security::SecurityManager::getInstance().sign(bundle);

					bundle.set(dtn::data::PrimaryBlock::DTNSEC_REQUEST_SIGN, false);
				} catch (const dtn::security::SecurityManager::KeyMissingException&) {
					// sign requested, but no key is available
					IBRCOMMON_LOGGER_TAG(Registration::TAG, warning) << "No key available for sign process." << IBRCOMMON_LOGGER_ENDL;
				}
			}
#endif

			// get the payload size maximum
			size_t maxPayloadLength = dtn::daemon::Configuration::getInstance().getLimit("payload");

			// check if fragmentation is enabled
			// do not try pro-active fragmentation if the payload length is not limited
			if (dtn::daemon::Configuration::getInstance().getNetwork().doFragmentation() && (maxPayloadLength > 0))
			{
				try {
					std::list<dtn::data::Bundle> fragments;

					dtn::core::FragmentManager::split(bundle, maxPayloadLength, fragments);

					//for each fragment raise bundle received event
					for(std::list<dtn::data::Bundle>::iterator it = fragments.begin(); it != fragments.end(); ++it)
					{
						// raise default bundle received event
						dtn::net::BundleReceivedEvent::raise(source, *it, true);
					}

					return;
				} catch (const FragmentationProhibitedException&) {
				} catch (const FragmentationNotNecessaryException&) {
				} catch (const FragmentationAbortedException&) {
					// drop the bundle
					return;
				}
			}

			// raise default bundle received event
			dtn::net::BundleReceivedEvent::raise(source, bundle, true);
		}
		void PayloadConfidentialBlock::encrypt(dtn::data::Bundle& bundle, const dtn::security::SecurityKey &long_key, const dtn::data::EID& source)
		{
			// contains the random salt
			uint32_t salt;

			// contains the random key
			unsigned char ephemeral_key[ibrcommon::AES128Stream::key_size_in_bytes];

			unsigned char iv[ibrcommon::AES128Stream::iv_len];
			unsigned char tag[ibrcommon::AES128Stream::tag_len];

			// create a new correlator value
			dtn::data::Number correlator = createCorrelatorValue(bundle);

			// create a random salt and key
			createSaltAndKey(salt, ephemeral_key, ibrcommon::AES128Stream::key_size_in_bytes);

			// count all PCBs
			dtn::data::Size pcbs_size = std::count(bundle.begin(), bundle.end(), PayloadConfidentialBlock::BLOCK_TYPE);

			// count all PIBs
			dtn::data::Size pibs_size = std::count(bundle.begin(), bundle.end(), PayloadIntegrityBlock::BLOCK_TYPE);

			// encrypt PCBs and PIBs
			dtn::data::Bundle::find_iterator find_pcb(bundle.begin(), PayloadConfidentialBlock::BLOCK_TYPE);
			while (find_pcb.next(bundle.end()))
			{
				SecurityBlock::encryptBlock<PayloadConfidentialBlock>(bundle, find_pcb, salt, ephemeral_key).setCorrelator(correlator);
			}

			dtn::data::Bundle::find_iterator find_pib(bundle.begin(), PayloadIntegrityBlock::BLOCK_TYPE);
			while (find_pib.next(bundle.end()))
			{
				SecurityBlock::encryptBlock<PayloadConfidentialBlock>(bundle, find_pib, salt, ephemeral_key).setCorrelator(correlator);
			}

			// create a new payload confidential block
			PayloadConfidentialBlock& pcb = bundle.push_front<PayloadConfidentialBlock>();

			// set the correlator
			if (pcbs_size > 0 || pibs_size > 0)
				pcb.setCorrelator(correlator);

			// get reference to the payload block
			dtn::data::PayloadBlock& plb = bundle.find<dtn::data::PayloadBlock>();
			ibrcommon::BLOB::Reference blobref = plb.getBLOB();

			// encrypt payload - BEGIN
			{
				ibrcommon::BLOB::iostream stream = blobref.iostream();
				ibrcommon::AES128Stream aes_stream(ibrcommon::CipherStream::CIPHER_ENCRYPT, *stream, ephemeral_key, salt);

				// encrypt in place
				((ibrcommon::CipherStream&)aes_stream).encrypt(*stream);

				// check if this is a fragment
				if (bundle.get(dtn::data::PrimaryBlock::FRAGMENT))
				{
					// ... and set the corresponding cipher suit params
					addFragmentRange(pcb._ciphersuite_params, bundle.fragmentoffset, stream.size());
				}

				// get the IV
				aes_stream.getIV(iv);

				// get the tag
				aes_stream.getTag(tag);
			}
			// encrypt payload - END

			// set the source and destination address of the new block
			if (source != bundle.source.getNode()) pcb.setSecuritySource( source );
			if (long_key.reference != bundle.destination.getNode()) pcb.setSecurityDestination( long_key.reference );

			// set replicate in every fragment to true
			pcb.set(REPLICATE_IN_EVERY_FRAGMENT, true);

			// store encypted key, tag, iv and salt
			addSalt(pcb._ciphersuite_params, salt);

			// get the RSA key
			RSA *rsa_key = long_key.getRSA();

			// encrypt the random key and add it to the ciphersuite params
			addKey(pcb._ciphersuite_params, ephemeral_key, ibrcommon::AES128Stream::key_size_in_bytes, rsa_key);

			// free the RSA key
			long_key.free(rsa_key);

			pcb._ciphersuite_params.set(SecurityBlock::initialization_vector, iv, ibrcommon::AES128Stream::iv_len);
			pcb._ciphersuite_flags |= SecurityBlock::CONTAINS_CIPHERSUITE_PARAMS;

			pcb._security_result.set(SecurityBlock::PCB_integrity_check_value, tag, ibrcommon::AES128Stream::tag_len);
			pcb._ciphersuite_flags |= SecurityBlock::CONTAINS_SECURITY_RESULT;
		}
		void PayloadIntegrityBlock::strip(dtn::data::Bundle& bundle)
		{
			bundle.erase(std::remove(bundle.begin(), bundle.end(), PayloadIntegrityBlock::BLOCK_TYPE), bundle.end());
		}
		void BundleAuthenticationBlock::strip(dtn::data::Bundle& bundle)
		{
			bundle.erase(std::remove(bundle.begin(), bundle.end(), BundleAuthenticationBlock::BLOCK_TYPE), bundle.end());
		}
		void MemoryBundleStorage::store(const dtn::data::Bundle &bundle)
		{
			ibrcommon::MutexLock l(_bundleslock);

			if (_faulty) return;

			// get size of the bundle
			dtn::data::DefaultSerializer s(std::cout);
			dtn::data::Length size = s.getLength(bundle);

			// increment the storage size
			allocSpace(size);

			// insert Container
			pair<set<dtn::data::Bundle>::iterator,bool> ret = _bundles.insert( bundle );

			if (ret.second)
			{
				const dtn::data::MetaBundle m = dtn::data::MetaBundle::create(bundle);
				_list.add(m);
				_priority_index.insert(m);

				_bundle_lengths[m] = size;

				// raise bundle added event
				eventBundleAdded(m);
			}
			else
			{
				// free the previously allocated space
				freeSpace(size);

				IBRCOMMON_LOGGER_DEBUG_TAG(MemoryBundleStorage::TAG, 5) << "got bundle duplicate " << bundle.toString() << IBRCOMMON_LOGGER_ENDL;
			}
		}
		void PayloadConfidentialBlock::decrypt(dtn::data::Bundle& bundle, const dtn::security::SecurityKey &long_key)
		{
			// list of block to delete if the process is successful
			std::list<const dtn::data::Block*> erasure_list;
			
			// load the RSA key
			RSA *rsa_key = long_key.getRSA();

			try {
				// array for the current symmetric AES key
				unsigned char key[ibrcommon::AES128Stream::key_size_in_bytes];

				// correlator of the first PCB
				dtn::data::Number correlator = 0;
				bool decrypt_related = false;

				// iterate through all blocks
				for (dtn::data::Bundle::iterator it = bundle.begin(); it != bundle.end(); ++it)
				{
					try {
						dynamic_cast<const PayloadIntegrityBlock&>(**it);

						// add this block to the erasure list for later deletion
						erasure_list.push_back(&**it);
					} catch (const std::bad_cast&) { };

					try {
						const PayloadConfidentialBlock &pcb = dynamic_cast<const PayloadConfidentialBlock&>(**it);

						// get salt and key
						uint32_t salt = getSalt(pcb._ciphersuite_params);

						// decrypt related blocks
						if (decrypt_related)
						{
							// try to decrypt the block
							try {
								decryptBlock(bundle, it, salt, key);

								// success! add this block to the erasue list
								erasure_list.push_back(&**it);
							} catch (const ibrcommon::Exception&) {
								IBRCOMMON_LOGGER_TAG("PayloadConfidentialBlock", critical) << "tag verfication failed, reversing decryption..." << IBRCOMMON_LOGGER_ENDL;
								decryptBlock(bundle, it, salt, key);

								// abort the decryption and discard the bundle?
								throw ibrcommon::Exception("decrypt of correlated block reversed, tag verfication failed");
							}
						}
						// if security destination does match the key, then try to decrypt the payload
						else if (pcb.isSecurityDestination(bundle, long_key.reference) &&
							(pcb._ciphersuite_id == SecurityBlock::PCB_RSA_AES128_PAYLOAD_PIB_PCB))
						{
							// try to decrypt the symmetric AES key
							if (!getKey(pcb._ciphersuite_params, key, ibrcommon::AES128Stream::key_size_in_bytes, rsa_key))
							{
								IBRCOMMON_LOGGER_TAG("PayloadConfidentialBlock", critical) << "could not get symmetric key decrypted" << IBRCOMMON_LOGGER_ENDL;
								throw ibrcommon::Exception("decrypt failed - could not get symmetric key decrypted");
							}

							// try to decrypt the payload
							if (!decryptPayload(bundle, key, salt))
							{
								// reverse decryption
								IBRCOMMON_LOGGER_TAG("PayloadConfidentialBlock", critical) << "tag verfication failed, reversing decryption..." << IBRCOMMON_LOGGER_ENDL;
								decryptPayload(bundle, key, salt);
								throw ibrcommon::Exception("decrypt reversed - tag verfication failed");
							}

							// success! add this block to the erasue list
							erasure_list.push_back(&**it);

							// check if first PCB has a correlator
							if (pcb._ciphersuite_flags & CONTAINS_CORRELATOR)
							{
								// ... and decrypt all correlated block with the same key
								decrypt_related = true;

								// store the correlator
								correlator = pcb._correlator;
							}
							else
							{
								// no correlated blocks should exists
								// stop here with decryption
								break;
							}
						}
						else
						{
							// exit here, because we can not decrypt the first PCB.
							throw ibrcommon::Exception("unable to decrypt the first PCB");
						}
					} catch (const std::bad_cast&) { };
				}

				// delete all block in the erasure list
				for (std::list<const dtn::data::Block* >::const_iterator it = erasure_list.begin(); it != erasure_list.end(); ++it)
				{
					bundle.remove(**it);
				}
			} catch (const std::exception&) {
				long_key.free(rsa_key);
				throw;
			}

			long_key.free(rsa_key);
		}