00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifdef HAVE_CONFIG_H
00018 # include <dtn-config.h>
00019 #endif
00020
00021 #ifdef BSP_ENABLED
00022
00023 #define OPENSSL_FIPS 1
00024
00025 #include "Ciphersuite_PS2.h"
00026 #include "Ciphersuite_C3.h"
00027 #include "bundling/Bundle.h"
00028 #include "bundling/BundleDaemon.h"
00029 #include "bundling/BundleProtocol.h"
00030 #include "bundling/SDNV.h"
00031 #include "contacts/Link.h"
00032 #include "security/KeySteward.h"
00033 #include "openssl/evp.h"
00034
00035 namespace dtn {
00036
00037 static const char * log = "/dtn/bundle/ciphersuite";
00038
00043 struct PrimaryBlock_ex {
00044 u_int8_t version;
00045 u_int64_t processing_flags;
00046 u_int64_t block_length;
00047 u_int64_t dest_scheme_offset;
00048 u_int64_t dest_ssp_offset;
00049 u_int64_t source_scheme_offset;
00050 u_int64_t source_ssp_offset;
00051 u_int64_t replyto_scheme_offset;
00052 u_int64_t replyto_ssp_offset;
00053 u_int64_t custodian_scheme_offset;
00054 u_int64_t custodian_ssp_offset;
00055 u_int64_t creation_time;
00056 u_int64_t creation_sequence;
00057 u_int64_t lifetime;
00058 u_int64_t dictionary_length;
00059 u_int64_t fragment_offset;
00060 u_int64_t original_length;
00061 };
00062
00063
00064
00065 #if defined(WORDS_BIGENDIAN) && (WORDS_BIGENDIAN == 1)
00066 #define htonq( x ) (x)
00067 #define ntohq( x ) (x)
00068 #else
00069
00070 inline u_int64_t htonq( u_int64_t x )
00071 {
00072 u_int64_t res;
00073 u_int32_t hi = x >> 32;
00074 u_int32_t lo = x & 0xffffffff;
00075 hi = htonl( hi );
00076 res = htonl( lo );
00077 res = res << 32 | hi;
00078
00079 return res;
00080 }
00081
00082 inline u_int64_t ntohq( u_int64_t x )
00083 {
00084 u_int64_t res;
00085 u_int32_t hi = x >> 32;
00086 u_int32_t lo = x & 0xffffffff;
00087 hi = ntohl( hi );
00088 res = ntohl( lo );
00089 res = res << 32 | hi;
00090
00091 return res;
00092 }
00093 #endif
00094
00095
00096
00097 Ciphersuite_PS2::Ciphersuite_PS2()
00098 {
00099 }
00100
00101
00102 u_int16_t
00103 Ciphersuite_PS2::cs_num(void)
00104 {
00105 return CSNUM_PS2;
00106 }
00107
00108
00109 int
00110 Ciphersuite_PS2::consume(Bundle* bundle,
00111 BlockInfo* block,
00112 u_char* buf,
00113 size_t len)
00114 {
00115 int cc = block->owner()->consume(bundle, block, buf, len);
00116
00117 if (cc == -1) {
00118 return -1;
00119 }
00120
00121
00122
00123
00124 if (! block->complete()) {
00125 ASSERT(cc == (int)len);
00126 return cc;
00127 }
00128
00129 if ( block->locals() == NULL ) {
00130 parse(block);
00131 }
00132
00133 return cc;
00134 }
00135
00136
00137 bool
00138 Ciphersuite_PS2::validate(const Bundle* bundle,
00139 BlockInfoVec* block_list,
00140 BlockInfo* block,
00141 status_report_reason_t* reception_reason,
00142 status_report_reason_t* deletion_reason)
00143 {
00144 (void)reception_reason;
00145
00146 size_t sdnv_len;
00147 u_char* buf;
00148 size_t len;
00149 size_t digest_len;
00150 u_char ps_digest[EVP_MAX_MD_SIZE];
00151 u_int32_t rlen = 0;
00152 BP_Local_CS* locals = NULL;
00153 u_int64_t field_length;
00154 std::vector<u_int64_t> correlator_list;
00155 std::vector<u_int64_t>::iterator cl_iter;
00156 EndpointID local_eid = BundleDaemon::instance()->local_eid();
00157 BlockInfoVec::iterator iter;
00158 u_int16_t cs_flags;
00159 int err = 0;
00160 DataBuffer db;
00161
00162 log_debug_p(log, "Ciphersuite_PS2::validate()");
00163 locals = dynamic_cast<BP_Local_CS*>(block->locals());
00164 CS_FAIL_IF_NULL(locals);
00165 cs_flags = locals->cs_flags();
00166
00167 if ( destination_is_local_node(bundle, block) )
00168 {
00169
00170 if ( !(cs_flags & CS_BLOCK_HAS_RESULT) ) {
00171 log_err_p(log, "Ciphersuite_PS2::validate: block has no security_result");
00172 goto fail;
00173 }
00174
00175 create_digest(bundle, block_list, block, db);
00176 digest_len = db.len();
00177 memcpy(ps_digest, db.buf(), digest_len);
00178
00179 log_debug_p(log, "Ciphersuite_PS2::validate() digest 0x%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx",
00180 ps_digest[0], ps_digest[1], ps_digest[2], ps_digest[3], ps_digest[4], ps_digest[5], ps_digest[6], ps_digest[7], ps_digest[8], ps_digest[9], ps_digest[10],
00181 ps_digest[11], ps_digest[12], ps_digest[13], ps_digest[14], ps_digest[15], ps_digest[16], ps_digest[17], ps_digest[18], ps_digest[19]);
00182
00183
00184 buf = locals->security_result().buf();
00185 len = locals->security_result().len();
00186
00187 log_debug_p(log, "Ciphersuite_PS2::validate() security result, len = %zu", len);
00188 while ( len > 0 ) {
00189 u_char item_type = *buf++;
00190 --len;
00191 sdnv_len = SDNV::decode(buf, len, &field_length);
00192 buf += sdnv_len;
00193 len -= sdnv_len;
00194
00195 switch ( item_type ) {
00196 case CS_signature_field:
00197 {
00198 log_debug_p(log, "Ciphersuite_PS2::validate() CS_signature_field item, len %llu", U64FMT(field_length));
00199
00200 err = KeySteward::verify(bundle, buf, field_length, ps_digest, rlen);
00201 if ( err == 0 ) {
00202 locals->set_proc_flag(CS_BLOCK_PASSED_VALIDATION | CS_BLOCK_COMPLETED_DO_NOT_FORWARD);
00203 } else {
00204 log_err_p(log, "Ciphersuite_PS2::validate: CS_signature_field validation failed");
00205 goto fail;
00206 }
00207
00208 }
00209 break;
00210
00211 default:
00212 log_err_p(log, "Ciphersuite_PS2::validate: unexpected item type %d in security_result", item_type);
00213 goto fail;
00214 }
00215 buf += field_length;
00216 len -= field_length;
00217 }
00218 } else
00219 locals->set_proc_flag(CS_BLOCK_DID_NOT_FAIL);
00220
00221 log_debug_p(log, "Ciphersuite_PS2::validate() done");
00222
00223 return true;
00224
00225
00226
00227 fail:
00228 locals->set_proc_flag(CS_BLOCK_FAILED_VALIDATION | CS_BLOCK_COMPLETED_DO_NOT_FORWARD);
00229 *deletion_reason = BundleProtocol::REASON_SECURITY_FAILED;
00230 return false;
00231 }
00232
00233
00234 int
00235 Ciphersuite_PS2::prepare(const Bundle* bundle,
00236 BlockInfoVec* xmit_blocks,
00237 const BlockInfo* source,
00238 const LinkRef& link,
00239 list_owner_t list)
00240 {
00241 (void)bundle;
00242 (void)link;
00243
00244 int result = BP_FAIL;
00245 u_int16_t cs_flags = 0;
00246 BP_Local_CS* locals = NULL;
00247 BP_Local_CS* source_locals = NULL;
00248 EndpointID local_eid = BundleDaemon::instance()->local_eid();
00249 BundleDaemon* bd = BundleDaemon::instance();
00250
00251
00252 if ( (source != NULL) &&
00253 (dynamic_cast<BP_Local_CS*>(source->locals())->security_dest() == bd->local_eid().data()) ) {
00254 log_debug_p(log, "Ciphersuite_PS2::prepare() - not being forwarded");
00255 return BP_SUCCESS;
00256 }
00257
00258 BlockInfo bi = BlockInfo(BundleProtocol::find_processor(BundleProtocol::PAYLOAD_SECURITY_BLOCK), source);
00259
00260
00261
00262
00263
00264 if ( list == BlockInfo::LIST_RECEIVED ) {
00265
00266 if ( Ciphersuite::destination_is_local_node(bundle, source) )
00267 return BP_SUCCESS;
00268
00269 CS_FAIL_IF_NULL(source);
00270 xmit_blocks->push_back(bi);
00271 BlockInfo* bp = &(xmit_blocks->back());
00272 CS_FAIL_IF_NULL(bp);
00273 bp->set_eid_list(source->eid_list());
00274 log_debug_p(log, "Ciphersuite_PS2::prepare() - forward received block len %u eid_list_count %zu new count %zu",
00275 source->full_length(), source->eid_list().size(), bp->eid_list().size());
00276
00277 CS_FAIL_IF_NULL( source->locals() );
00278
00279 source_locals = dynamic_cast<BP_Local_CS*>(source->locals());
00280 CS_FAIL_IF_NULL(source_locals);
00281 bp->set_locals(new BP_Local_CS);
00282 locals = dynamic_cast<BP_Local_CS*>(bp->locals());
00283 CS_FAIL_IF_NULL(locals);
00284 locals->set_owner_cs_num(CSNUM_PS2);
00285 cs_flags = source_locals->cs_flags();
00286 locals->set_list_owner(BlockInfo::LIST_RECEIVED);
00287 locals->set_correlator(source_locals->correlator());
00288 bp->writable_contents()->reserve(source->full_length());
00289 bp->writable_contents()->set_len(0);
00290
00291
00292 if ( source_locals->cs_flags() & CS_BLOCK_HAS_SOURCE ) {
00293 CS_FAIL_IF(source_locals->security_src().length() == 0 );
00294 log_debug_p(log, "Ciphersuite_PS2::prepare() add security_src EID");
00295 cs_flags |= CS_BLOCK_HAS_SOURCE;
00296 locals->set_security_src(source_locals->security_src());
00297 }
00298
00299 if ( source_locals->cs_flags() & CS_BLOCK_HAS_DEST ) {
00300 CS_FAIL_IF(source_locals->security_dest().length() == 0 );
00301 log_debug_p(log, "Ciphersuite_PS2::prepare() add security_dest EID");
00302 cs_flags |= CS_BLOCK_HAS_DEST;
00303 locals->set_security_dest(source_locals->security_dest());
00304 }
00305 locals->set_cs_flags(cs_flags);
00306 log_debug_p(log, "Ciphersuite_PS2::prepare() - inserted block eid_list_count %zu",
00307 bp->eid_list().size());
00308 result = BP_SUCCESS;
00309 return result;
00310 } else {
00311
00312
00313 log_debug_p(log, "Ciphersuite_PS2::prepare() - add new block (or API block etc)");
00314 bi.set_locals(new BP_Local_CS);
00315 CS_FAIL_IF_NULL(bi.locals());
00316 locals = dynamic_cast<BP_Local_CS*>(bi.locals());
00317 CS_FAIL_IF_NULL(locals);
00318 locals->set_owner_cs_num(CSNUM_PS2);
00319 locals->set_list_owner(list);
00320
00321
00322 if ( source != NULL && source->locals() != NULL) {
00323 locals->set_security_src(dynamic_cast<BP_Local_CS*>(source->locals())->security_src());
00324 locals->set_security_dest(dynamic_cast<BP_Local_CS*>(source->locals())->security_dest());
00325 }
00326
00327 log_debug_p(log, "Ciphersuite_PS2::prepare() local_eid %s bundle->source_ %s", local_eid.c_str(), bundle->source().c_str());
00328
00329 if ( (locals->security_src().length() == 0) && (local_eid != bundle->source()))
00330 locals->set_security_src(local_eid.str());
00331
00332
00333 if ( locals->security_src().length() > 0 ) {
00334 log_debug_p(log, "Ciphersuite_PS2::prepare() add security_src EID %s", locals->security_src().c_str());
00335 cs_flags |= CS_BLOCK_HAS_SOURCE;
00336 bi.add_eid(locals->security_src());
00337 }
00338
00339 if ( locals->security_dest().length() > 0 ) {
00340 log_debug_p(log, "Ciphersuite_PS2::prepare() add security_dest EID %s", locals->security_dest().c_str());
00341 cs_flags |= CS_BLOCK_HAS_DEST;
00342 bi.add_eid(locals->security_dest());
00343 }
00344
00345 locals->set_cs_flags(cs_flags);
00346
00347
00348
00349
00350 if ( xmit_blocks->size() > 0 ) {
00351 BlockInfoVec::iterator iter = xmit_blocks->begin();
00352
00353 while ( iter != xmit_blocks->end()) {
00354 switch (iter->type()) {
00355 case BundleProtocol::PRIMARY_BLOCK:
00356 case BundleProtocol::BUNDLE_AUTHENTICATION_BLOCK:
00357 ++iter;
00358 continue;
00359
00360 default:
00361 break;
00362 }
00363 xmit_blocks->insert(iter, bi);
00364 break;
00365 }
00366 } else {
00367
00368 xmit_blocks->push_back(bi);
00369 }
00370 }
00371
00372 result = BP_SUCCESS;
00373 return result;
00374
00375 fail:
00376 if ( locals != NULL )
00377 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
00378 return BP_FAIL;
00379 }
00380
00381
00382 int
00383 Ciphersuite_PS2::generate(const Bundle* bundle,
00384 BlockInfoVec* xmit_blocks,
00385 BlockInfo* block,
00386 const LinkRef& link,
00387 bool last)
00388 {
00389 (void)bundle;
00390 (void)link;
00391 (void)xmit_blocks;
00392
00393 int result = BP_FAIL;
00394 size_t sig_len = 0;
00395 size_t res_len = 0;
00396 size_t length = 0;
00397 size_t param_len = 0;
00398 u_char fragment_item[24];
00399 u_int16_t cs_flags = 0;
00400 BP_Local_CS* locals = dynamic_cast<BP_Local_CS*>(block->locals());
00401 u_char* ptr;
00402 size_t temp;
00403 size_t rem;
00404 DataBuffer encrypted_key;
00405 EVP_MD_CTX ctx;
00406 size_t digest_len;
00407 u_char* buf = NULL;
00408
00409 int sdnv_len = 0;
00410 int err = 0;
00411 int len = 0;
00412 BlockInfo::DataBuffer* contents = NULL;
00413 LocalBuffer* params = NULL;
00414
00415 log_debug_p(log, "Ciphersuite_PS2::generate() %p", block);
00416 CS_FAIL_IF_NULL(locals);
00417 cs_flags = locals->cs_flags();
00418
00419 if ( locals->list_owner() == BlockInfo::LIST_RECEIVED )
00420 {
00421
00422 size_t length = block->source()->data_length();
00423
00424 generate_preamble(xmit_blocks,
00425 block,
00426 BundleProtocol::PAYLOAD_SECURITY_BLOCK,
00427 BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR |
00428 (last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0),
00429 length);
00430
00431 BlockInfo::DataBuffer* contents = block->writable_contents();
00432 contents->reserve(block->data_offset() + length);
00433 contents->set_len(block->data_offset() + length);
00434 memcpy(contents->buf() + block->data_offset(),
00435 block->source()->data(), length);
00436 log_debug_p(log, "Ciphersuite_PS2::generate() %p done", block);
00437 return BP_SUCCESS;
00438 }
00439
00440
00441
00442
00443
00444
00445 params = locals->writable_security_params();
00446
00447 param_len = 0;
00448
00449 if ( bundle->is_fragment() ) {
00450 log_debug_p(log, "Ciphersuite_PS2::generate() bundle is fragment");
00451 ptr = &fragment_item[2];
00452 rem = sizeof(fragment_item) - 2;
00453 temp = SDNV::encode(bundle->frag_offset(), ptr, rem);
00454 ptr += temp;
00455 rem -= temp;
00456 temp += SDNV::encode(bundle->payload().length(), ptr, rem);
00457 fragment_item[0] = CS_fragment_offset_and_length_field;
00458 fragment_item[1] = temp;
00459 param_len += 2 + temp;
00460
00461 }
00462
00463 if ( param_len > 0 ) {
00464 cs_flags |= CS_BLOCK_HAS_PARAMS;
00465 params->reserve(param_len);
00466 params->set_len(param_len);
00467 log_debug_p(log, "Ciphersuite_PS2::generate() security params, len = %zu", param_len);
00468
00469 ptr = params->buf();
00470
00471 if ( bundle->is_fragment() )
00472 memcpy(ptr, fragment_item, 2 + temp);
00473 }
00474
00475
00476
00477
00478
00479
00480
00481 EVP_MD_CTX_init(&ctx);
00482 err = EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
00483 CS_FAIL_IF(err == 0);
00484 digest_len = EVP_MD_CTX_size(&ctx);
00485 EVP_MD_CTX_cleanup(&ctx);
00486
00487 KeySteward::signature_length(bundle, NULL, link, digest_len, sig_len);
00488
00489 res_len = 1 + SDNV::encoding_len(sig_len) + sig_len;
00490
00491
00492 cs_flags |= CS_BLOCK_HAS_RESULT;
00493 locals->set_cs_flags(cs_flags);
00494 length = 0;
00495 length += SDNV::encoding_len(CSNUM_PS2);
00496 length += SDNV::encoding_len(locals->cs_flags());
00497
00498 param_len = locals->security_params().len();
00499 length += SDNV::encoding_len(param_len) + param_len;
00500 locals->set_security_result_offset(length);
00501 length += SDNV::encoding_len(res_len) + res_len;
00502
00503 contents = block->writable_contents();
00504
00505 generate_preamble(xmit_blocks,
00506 block,
00507 BundleProtocol::PAYLOAD_SECURITY_BLOCK,
00508 BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR |
00509 (last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0),
00510 length);
00511
00512
00513 log_debug_p(log, "Ciphersuite_PS2::generate() preamble len %u block len %zu", block->data_offset(), length);
00514 contents->reserve(block->data_offset() + length);
00515 contents->set_len(block->data_offset() + length);
00516 buf = block->writable_contents()->buf() + block->data_offset();
00517 len = length;
00518
00519
00520
00521
00522 sdnv_len = SDNV::encode(locals->owner_cs_num(), buf, len);
00523 CS_FAIL_IF(sdnv_len <= 0);
00524 buf += sdnv_len;
00525 len -= sdnv_len;
00526
00527 sdnv_len = SDNV::encode(locals->cs_flags(), buf, len);
00528 CS_FAIL_IF(sdnv_len <= 0);
00529 buf += sdnv_len;
00530 len -= sdnv_len;
00531
00532 if ( param_len > 0 ) {
00533
00534 sdnv_len = SDNV::encode(param_len, buf, len);
00535 CS_FAIL_IF(sdnv_len <= 0);
00536 buf += sdnv_len;
00537 len -= sdnv_len;
00538
00539
00540 memcpy(buf, locals->security_params().buf(), param_len );
00541 buf += param_len;
00542 len -= param_len;
00543 }
00544
00545
00546 sdnv_len = SDNV::encode(res_len, buf, len);
00547
00548
00549
00550
00551 log_debug_p(log, "Ciphersuite_PS2::generate() done");
00552
00553
00554 result = BP_SUCCESS;
00555 return result;
00556
00557 fail:
00558 if ( locals != NULL )
00559 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
00560 return BP_FAIL;
00561 }
00562
00563
00564 int
00565 Ciphersuite_PS2::finalize(const Bundle* bundle,
00566 BlockInfoVec* xmit_blocks,
00567 BlockInfo* block,
00568 const LinkRef& link)
00569 {
00570 (void)link;
00571 int result = BP_FAIL;
00572 size_t len;
00573 size_t sdnv_len;
00574 size_t res_len;
00575 u_char* buf;
00576 u_char ps_digest[EVP_MAX_MD_SIZE];
00577 u_int32_t rlen = 0;
00578 BP_Local_CS* locals = NULL;
00579 std::vector<u_int64_t> correlator_list;
00580 std::vector<u_int64_t>::iterator cl_iter;
00581 EndpointID local_eid = BundleDaemon::instance()->local_eid();
00582 BlockInfoVec::iterator iter;
00583 DataBuffer db;
00584 int err = 0;
00585 BlockInfo::DataBuffer* contents = NULL;
00586 LocalBuffer* digest_result = NULL;
00587 size_t sig_len = 0;
00588
00589 log_debug_p(log, "Ciphersuite_PS2::finalize()");
00590 locals = dynamic_cast<BP_Local_CS*>(block->locals());
00591 CS_FAIL_IF_NULL(locals);
00592
00593
00594 if ( locals->list_owner() == BlockInfo::LIST_RECEIVED )
00595 return BP_SUCCESS;
00596
00597 create_digest(bundle, xmit_blocks, block, db);
00598
00599 err = KeySteward::sign(bundle, NULL, link, ps_digest, rlen, db);
00600 CS_FAIL_IF(err != 0);
00601 sig_len = db.len();
00602 res_len = 1 + SDNV::encoding_len(sig_len) + sig_len;
00603
00604
00605 digest_result = locals->writable_security_result();
00606 digest_result->reserve(res_len);
00607 digest_result->set_len(res_len);
00608
00609 buf = digest_result->buf();
00610 len = digest_result->len();
00611
00612 *buf++ = Ciphersuite::CS_signature_field;
00613 len--;
00614
00615 sdnv_len = SDNV::encode(sig_len, buf, len);
00616 buf += sdnv_len;
00617 len -= sdnv_len;
00618
00619 memcpy(buf, db.buf(), sig_len);
00620
00621
00622
00623 contents = block->writable_contents();
00624 buf = contents->buf();
00625 len = contents->len();
00626 buf += block->data_offset();
00627 len -= block->data_offset();
00628
00629 buf += locals->security_result_offset();
00630 len -= locals->security_result_offset();
00631 sdnv_len = SDNV::len(buf);
00632 buf += sdnv_len;
00633 len -= sdnv_len;
00634 memcpy(buf, digest_result->buf(), digest_result->len());
00635 log_debug_p(log, "Ciphersuite_PS2::finalize() done");
00636
00637 result = BP_SUCCESS;
00638 return result;
00639
00640 fail:
00641 if ( locals != NULL )
00642 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
00643 return BP_FAIL;
00644 }
00645
00646
00647 void
00648 Ciphersuite_PS2::digest(const Bundle* bundle,
00649 const BlockInfo* caller_block,
00650 const BlockInfo* target_block,
00651 const void* buf,
00652 size_t len,
00653 OpaqueContext* r)
00654 {
00655 (void)bundle;
00656 (void)caller_block;
00657 (void)target_block;
00658 log_debug_p(log, "Ciphersuite_PS2::digest() %zu bytes", len);
00659
00660 EVP_MD_CTX* pctx = reinterpret_cast<EVP_MD_CTX*>(r);
00661
00662 EVP_DigestUpdate( pctx, buf, len );
00663 }
00664
00665
00666 void
00667 Ciphersuite_PS2::create_digest(const Bundle* bundle,
00668 BlockInfoVec* block_list,
00669 BlockInfo* block,
00670 DataBuffer& db)
00671 {
00672 size_t len;
00673 size_t sdnv_len;
00674 EVP_MD_CTX ctx;
00675 OpaqueContext* r = reinterpret_cast<OpaqueContext*>(&ctx);
00676 char* dict;
00677 u_int32_t offset;
00678 u_char* buf;
00679 const char* ptr;
00680 size_t plen;
00681 size_t digest_len;
00682 u_char ps_digest[EVP_MAX_MD_SIZE];
00683 u_int32_t rlen = 0;
00684 u_int32_t header_len;
00685 u_char c;
00686 u_int64_t eid_ref_count = 0LLU;
00687 BP_Local_CS* locals = NULL;
00688 BP_Local_CS* target_locals = NULL;
00689 u_int64_t target_flags;
00690 u_int64_t flags_save;
00691 u_int64_t mask = 0LLU;
00692 u_int64_t mask_primary = 0LLU;
00693 u_int64_t target_content_length;
00694 u_int64_t correlator;
00695 u_int64_t cs_flags;
00696 u_int64_t suite_num;
00697 std::vector<u_int64_t> correlator_list;
00698 std::vector<u_int64_t>::iterator cl_iter;
00699 EndpointID local_eid = BundleDaemon::instance()->local_eid();
00700 BlockInfoVec::iterator iter;
00701 int err = 0;
00702 PrimaryBlock_ex primary;
00703
00704 log_debug_p(log, "Ciphersuite_PS2::create_digest()");
00705 locals = dynamic_cast<BP_Local_CS*>(block->locals());
00706
00707
00708 EVP_MD_CTX_init(&ctx);
00709 err = EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL);
00710 digest_len = EVP_MD_CTX_size(&ctx);
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726 header_len = 1
00727 + 8
00728 + 4
00729 + 4
00730 + 4
00731 + 4
00732 + 8
00733 + 8
00734 + 8;
00735
00736 if ( bundle->is_fragment() )
00737 header_len += 8
00738 + 8;
00739
00740
00741
00742 iter = block_list->begin();
00743
00744 err = read_primary(bundle, &*iter, primary, &dict);
00745
00746 header_len += strlen(dict + primary.dest_scheme_offset);
00747 header_len += strlen(dict + primary.dest_ssp_offset);
00748 header_len += strlen(dict + primary.source_scheme_offset);
00749 header_len += strlen(dict + primary.source_ssp_offset);
00750 header_len += strlen(dict + primary.replyto_scheme_offset);
00751 header_len += strlen(dict + primary.replyto_ssp_offset);
00752 log_debug_p(log, "Ciphersuite_PS2::create_digest() header_len %u", header_len);
00753
00754
00755
00756 digest( bundle, block, &*iter, &primary.version, 1, r);
00757
00758 primary.processing_flags &= mask_primary;
00759 target_flags = htonq(primary.processing_flags);
00760 digest( bundle, block, &*iter, &primary.processing_flags, sizeof(primary.processing_flags), r);
00761
00762 header_len = htonl(header_len);
00763 digest( bundle, block, &*iter, &header_len, sizeof(header_len), r);
00764
00765
00766 offset = strlen(dict + primary.dest_scheme_offset) + strlen(dict + primary.dest_ssp_offset);
00767 offset = htonl(offset);
00768 digest( bundle, block, &*iter, &offset, sizeof(offset), r);
00769 digest( bundle, block, &*iter, dict + primary.dest_scheme_offset, strlen(dict + primary.dest_scheme_offset), r);
00770 digest( bundle, block, &*iter, dict + primary.dest_ssp_offset, strlen(dict + primary.dest_ssp_offset), r);
00771
00772 offset = strlen(dict + primary.source_scheme_offset) + strlen(dict + primary.source_ssp_offset);
00773 offset = htonl(offset);
00774 digest( bundle, block, &*iter, &offset, sizeof(offset), r);
00775 digest( bundle, block, &*iter, dict + primary.source_scheme_offset, strlen(dict + primary.source_scheme_offset), r);
00776 digest( bundle, block, &*iter, dict + primary.source_ssp_offset, strlen(dict + primary.source_ssp_offset), r);
00777
00778 offset = strlen(dict + primary.replyto_scheme_offset) + strlen(dict + primary.replyto_ssp_offset);
00779 offset = htonl(offset);
00780 digest( bundle, block, &*iter, &offset, sizeof(offset), r);
00781 digest( bundle, block, &*iter, dict + primary.replyto_scheme_offset, strlen(dict + primary.replyto_scheme_offset), r);
00782 digest( bundle, block, &*iter, dict + primary.replyto_ssp_offset, strlen(dict + primary.replyto_ssp_offset), r);
00783
00784
00785 primary.creation_time = htonq(primary.creation_time);
00786 digest( bundle, block, &*iter, &primary.creation_time, sizeof(primary.creation_time), r);
00787 primary.creation_sequence = htonq(primary.creation_sequence);
00788 digest( bundle, block, &*iter, &primary.creation_sequence, sizeof(primary.creation_sequence), r);
00789 primary.lifetime = htonq(primary.lifetime);
00790 digest( bundle, block, &*iter, &primary.lifetime, sizeof(primary.lifetime), r);
00791
00792 if ( bundle->is_fragment() ) {
00793 primary.fragment_offset = htonq(primary.fragment_offset);
00794 digest( bundle, block, &*iter, &primary.fragment_offset, sizeof(primary.fragment_offset), r);
00795 primary.original_length = htonq(primary.original_length);
00796 digest( bundle, block, &*iter, &primary.original_length, sizeof(primary.original_length), r);
00797 }
00798
00799 ++iter;
00800
00801 log_debug_p(log, "Ciphersuite_PS2::create_digest() walk block list");
00802 for ( ;
00803 iter != block_list->end();
00804 ++iter)
00805 {
00806
00807
00808
00809
00810
00811
00812 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
00813 if ( (&*iter) <= block ) {
00814 if ( iter->type() == BundleProtocol::PAYLOAD_SECURITY_BLOCK ||
00815 (iter->type() == BundleProtocol::CONFIDENTIALITY_BLOCK &&
00816 target_locals->owner_cs_num() == Ciphersuite_C3::CSNUM_C3 ) ) {
00817 if ( target_locals->cs_flags() & CS_BLOCK_HAS_CORRELATOR) {
00818
00819 correlator_list.push_back(target_locals->correlator());
00820 }
00821 }
00822 continue;
00823 }
00824
00825
00826 switch ( iter->type() ) {
00827 case BundleProtocol::PAYLOAD_SECURITY_BLOCK:
00828 case BundleProtocol::CONFIDENTIALITY_BLOCK:
00829 {
00830
00831 log_debug_p(log, "Ciphersuite_PS2::create_digest() PS or C block type %d cs_num %d",
00832 iter->type(), target_locals->owner_cs_num());
00833 if ( iter->type() == BundleProtocol::PAYLOAD_SECURITY_BLOCK &&
00834 target_locals->owner_cs_num() != Ciphersuite_C3::CSNUM_C3 )
00835 continue;
00836
00837
00838
00839
00840
00841 bool skip_target = false;
00842 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
00843 log_debug_p(log, "Ciphersuite_PS2::create_digest() target_locals->cs_flags 0x%hx", target_locals->cs_flags());
00844 log_debug_p(log, "Ciphersuite_PS2::create_digest() target_locals->correlator() 0x%llx", U64FMT(target_locals->correlator()));
00845 if ( target_locals->cs_flags() & CS_BLOCK_HAS_CORRELATOR) {
00846 correlator = target_locals->correlator();
00847 for ( cl_iter = correlator_list.begin();
00848 cl_iter < correlator_list.end();
00849 ++cl_iter) {
00850 if ( correlator == *cl_iter) {
00851 skip_target = true;
00852 break;
00853 }
00854 }
00855 if ( skip_target )
00856 break;
00857
00858 }
00859
00860 log_debug_p(log, "Ciphersuite_PS2::create_digest() digest this block, len %u eid_list().size() %zu",
00861 iter->full_length(), iter->eid_list().size());
00862
00863
00864
00865
00866 buf = iter->contents().buf();
00867 len = iter->full_length();
00868
00869
00870
00871 c = *buf++;
00872 len--;
00873 digest( bundle, block, &*iter, &c, 1, r);
00874
00875
00876 sdnv_len = SDNV::decode( buf, len, &target_flags);
00877 buf += sdnv_len;
00878 len -= sdnv_len;
00879
00880 flags_save = target_flags;
00881 target_flags &= mask;
00882 target_flags = htonq(target_flags);
00883 digest( bundle, block, &*iter, &target_flags, sizeof(target_flags), r);
00884
00885
00886 if ( flags_save & BundleProtocol::BLOCK_FLAG_EID_REFS ) {
00887 sdnv_len = SDNV::decode(buf, len, &eid_ref_count);
00888 buf += sdnv_len;
00889 len -= sdnv_len;
00890 log_debug_p(log, "Ciphersuite_PS2::create_digest() eid_ref_count %llu", U64FMT(eid_ref_count));
00891
00892
00893 if ( eid_ref_count > 0 ) {
00894 for ( u_int32_t i = 0; i < (2 * eid_ref_count); i++ ) {
00895 sdnv_len = SDNV::decode(buf, len, &offset);
00896 buf += sdnv_len;
00897 len -= sdnv_len;
00898
00899 ptr = dict + offset;
00900 plen = strlen(ptr);
00901 digest( bundle, block, &*iter, ptr, plen, r);
00902 }
00903 }
00904 }
00905
00906
00907 sdnv_len = SDNV::decode(buf, len, &target_content_length);
00908 buf += sdnv_len;
00909 len -= sdnv_len;
00910
00911 target_content_length = htonq(target_content_length);
00912 digest( bundle, block, &*iter, &target_content_length, sizeof(target_content_length), r);
00913
00914
00915 offset = buf - iter->contents().buf();
00916 ASSERT(offset == iter->data_offset());
00917
00918
00919
00920
00921
00922
00923
00924 if ( (&*iter) == block ) {
00925
00926
00927 sdnv_len = SDNV::decode(buf,
00928 len,
00929 &suite_num);
00930 buf += sdnv_len;
00931 len -= sdnv_len;
00932
00933 sdnv_len = SDNV::decode(buf,
00934 len,
00935 &cs_flags);
00936 buf += sdnv_len;
00937 len -= sdnv_len;
00938
00939 if ( cs_flags & CS_BLOCK_HAS_RESULT ) {
00940
00941 if ( cs_flags & CS_BLOCK_HAS_CORRELATOR )
00942 buf += SDNV::len(buf);
00943
00944 if ( cs_flags & CS_BLOCK_HAS_PARAMS )
00945 buf += SDNV::len(buf);
00946
00947 if ( cs_flags & CS_BLOCK_HAS_RESULT ) {
00948 sdnv_len = SDNV::decode(buf, len, &target_content_length);
00949 buf += sdnv_len;
00950 len -= sdnv_len;
00951 buf += SDNV::len(buf);
00952 }
00953
00954 len = buf - iter->contents().buf();
00955 }
00956
00957 buf = iter->contents().buf();
00958 }
00959
00960 iter->owner()->process( Ciphersuite_PS2::digest,
00961 bundle,
00962 block,
00963 &*iter,
00964 offset,
00965 len,
00966 r);
00967
00968 log_debug_p(log, "Ciphersuite_PS2::create_digest() digest done %p", &*iter);
00969
00970 }
00971 break;
00972
00973 case BundleProtocol::PAYLOAD_BLOCK:
00974 {
00975
00976
00977 buf = iter->contents().buf();
00978 len = iter->full_length();
00979
00980
00981
00982 c = *buf++;
00983 len--;
00984 digest( bundle, block, &*iter, &c, 1, r);
00985
00986
00987 sdnv_len = SDNV::decode( buf, len, &target_flags);
00988 buf += sdnv_len;
00989 len -= sdnv_len;
00990
00991 flags_save = target_flags;
00992 target_flags &= mask;
00993 target_flags = htonq(target_flags);
00994 digest( bundle, block, &*iter, &target_flags, sizeof(target_flags), r);
00995
00996
00997 if ( flags_save & BundleProtocol::BLOCK_FLAG_EID_REFS ) {
00998 sdnv_len = SDNV::decode(buf, len, &eid_ref_count);
00999 buf += sdnv_len;
01000 len -= sdnv_len;
01001
01002
01003 if ( eid_ref_count > 0 ) {
01004 for ( u_int32_t i = 0; i < (2 * eid_ref_count); i++ ) {
01005 sdnv_len = SDNV::decode(buf, len, &offset);
01006 buf += sdnv_len;
01007 len -= sdnv_len;
01008
01009 ptr = dict + offset;
01010 plen = strlen(ptr);
01011 digest( bundle, block, &*iter, ptr, plen, r);
01012 }
01013 }
01014 }
01015
01016
01017 sdnv_len = SDNV::decode(buf, len, &target_content_length);
01018 buf += sdnv_len;
01019 len -= sdnv_len;
01020
01021 target_content_length = htonq(target_content_length);
01022 digest( bundle, block, &*iter, &target_content_length, sizeof(target_content_length), r);
01023
01024
01025 offset = buf - iter->contents().buf();
01026 ASSERT(offset == iter->data_offset());
01027
01028
01029
01030
01031 iter->owner()->process( Ciphersuite_PS2::digest,
01032 bundle,
01033 block,
01034 &*iter,
01035 offset,
01036 len,
01037 r);
01038
01039 log_debug_p(log, "Ciphersuite_PS2::create_digest() PAYLOAD_BLOCK done");
01040 }
01041 break;
01042
01043 default:
01044 continue;
01045
01046 }
01047 }
01048
01049
01050 err = EVP_DigestFinal_ex(&ctx, ps_digest, &rlen);
01051
01052
01053 log_debug_p(log, "Ciphersuite_PS2::create_digest() digest 0x%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx%2.2hhx",
01054 ps_digest[0], ps_digest[1], ps_digest[2], ps_digest[3], ps_digest[4], ps_digest[5], ps_digest[6], ps_digest[7], ps_digest[8], ps_digest[9], ps_digest[10],
01055 ps_digest[11], ps_digest[12], ps_digest[13], ps_digest[14], ps_digest[15], ps_digest[16], ps_digest[17], ps_digest[18], ps_digest[19]);
01056
01057 EVP_MD_CTX_cleanup(&ctx);
01058
01059 db.reserve(digest_len);
01060 db.set_len(digest_len);
01061 memcpy(db.buf(), ps_digest, digest_len);
01062
01063 log_debug_p(log, "Ciphersuite_PS2::create_digest() done");
01064
01065 }
01066
01067
01068
01069 int
01070 Ciphersuite_PS2::read_primary(const Bundle* bundle,
01071 BlockInfo* block,
01072 PrimaryBlock_ex& primary,
01073 char** dict)
01074 {
01075 u_char* buf;
01076 size_t len;
01077
01078 size_t primary_len = block->full_length();
01079
01080 buf = block->writable_contents()->buf();
01081 len = block->writable_contents()->len();
01082
01083 ASSERT(primary_len == len);
01084
01085 primary.version = *(u_int8_t*)buf;
01086 buf += 1;
01087 len -= 1;
01088
01089 if (primary.version != BundleProtocol::CURRENT_VERSION) {
01090 log_warn_p(log, "protocol version mismatch %d != %d",
01091 primary.version, BundleProtocol::CURRENT_VERSION);
01092 return -1;
01093 }
01094
01095 #define PBP_READ_SDNV(location) { \
01096 int sdnv_len = SDNV::decode(buf, len, location); \
01097 if (sdnv_len < 0) \
01098 goto tooshort; \
01099 buf += sdnv_len; \
01100 len -= sdnv_len; }
01101
01102
01103 PBP_READ_SDNV(&primary.processing_flags);
01104 PBP_READ_SDNV(&primary.block_length);
01105
01106 log_debug_p(log, "parsed primary block: version %d length %u",
01107 primary.version, block->data_length());
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119 ASSERT(len == primary.block_length);
01120
01121
01122 PBP_READ_SDNV(&primary.dest_scheme_offset);
01123 PBP_READ_SDNV(&primary.dest_ssp_offset);
01124 PBP_READ_SDNV(&primary.source_scheme_offset);
01125 PBP_READ_SDNV(&primary.source_ssp_offset);
01126 PBP_READ_SDNV(&primary.replyto_scheme_offset);
01127 PBP_READ_SDNV(&primary.replyto_ssp_offset);
01128 PBP_READ_SDNV(&primary.custodian_scheme_offset);
01129 PBP_READ_SDNV(&primary.custodian_ssp_offset);
01130 PBP_READ_SDNV(&primary.creation_time);
01131 PBP_READ_SDNV(&primary.creation_sequence);
01132 PBP_READ_SDNV(&primary.lifetime);
01133 PBP_READ_SDNV(&primary.dictionary_length);
01134 *dict = reinterpret_cast<char*>(buf);
01135 if (bundle->is_fragment()) {
01136 PBP_READ_SDNV(&primary.fragment_offset);
01137 PBP_READ_SDNV(&primary.original_length);
01138 }
01139 #undef PBP_READ_SDNV
01140 return 0;
01141
01142 tooshort:
01143 return -1;
01144 }
01145
01146
01147 }
01148
01149 #endif