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 #include "Ciphersuite_C3.h"
00024 #include "bundling/Bundle.h"
00025 #include "bundling/BundleDaemon.h"
00026 #include "bundling/BundleProtocol.h"
00027 #include "bundling/SDNV.h"
00028 #include "contacts/Link.h"
00029 #include "openssl/rand.h"
00030 #include "gcm/gcm.h"
00031 #include "security/KeySteward.h"
00032
00033 namespace dtn {
00034
00035 static const char * log = "/dtn/bundle/ciphersuite";
00036
00037
00038 Ciphersuite_C3::Ciphersuite_C3()
00039 {
00040 }
00041
00042
00043 u_int16_t
00044 Ciphersuite_C3::cs_num(void)
00045 {
00046 return CSNUM_C3;
00047 }
00048
00049
00050 int
00051 Ciphersuite_C3::consume(Bundle* bundle, BlockInfo* block,
00052 u_char* buf, size_t len)
00053 {
00054 log_debug_p(log, "Ciphersuite_C3::consume()");
00055 int cc = block->owner()->consume(bundle, block, buf, len);
00056
00057 if (cc == -1) {
00058 return -1;
00059 }
00060
00061
00062
00063
00064 if (! block->complete()) {
00065 ASSERT(cc == (int)len);
00066 return cc;
00067 }
00068
00069 if ( block->locals() == NULL ) {
00070 parse(block);
00071 }
00072
00073 return cc;
00074 }
00075
00076
00077 bool
00078 Ciphersuite_C3::validate(const Bundle* bundle,
00079 BlockInfoVec* block_list,
00080 BlockInfo* block,
00081 status_report_reason_t* reception_reason,
00082 status_report_reason_t* deletion_reason)
00083 {
00084 (void)reception_reason;
00085
00086
00087
00088
00089
00090
00091
00092
00093 Bundle* deliberate_const_cast_bundle = const_cast<Bundle*>(bundle);
00094 u_int16_t cs_flags;
00095 BP_Local_CS* locals = dynamic_cast<BP_Local_CS*>(block->locals());
00096 EndpointID local_eid = BundleDaemon::instance()->local_eid();
00097 size_t offset;
00098 size_t len;
00099 gcm_ctx_ex ctx_ex;
00100 OpaqueContext* r = reinterpret_cast<OpaqueContext*>(&ctx_ex);
00101 bool changed = false;
00102 u_char key[key_len];
00103 u_char salt[salt_len];
00104 u_char iv[iv_len];
00105 u_char target_iv[iv_len];
00106 u_char nonce[nonce_len];
00107 u_char tag[tag_len];
00108 u_char tag_encap[tag_len];
00109 u_char* buf;
00110 u_char* ptr;
00111 u_char* data;
00112 BP_Local_CS* target_locals = NULL;
00113 int sdnv_len = 0;
00114 u_char item_type;
00115 int32_t rem;
00116 u_int64_t field_length = 0LL;
00117 u_int64_t frag_offset_;
00118 u_int64_t orig_length_;
00119 ret_type ret = 0;
00120 DataBuffer db;
00121
00122 log_debug_p(log, "Ciphersuite_C3::validate() %p", block);
00123 CS_FAIL_IF_NULL(locals);
00124 cs_flags = locals->cs_flags();
00125
00126 if ( Ciphersuite::destination_is_local_node(bundle, block) )
00127 {
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 buf = locals->security_params().buf();
00139 len = locals->security_params().len();
00140
00141 log_debug_p(log, "Ciphersuite_C3::validate() locals->correlator() 0x%llx", U64FMT(locals->correlator()));
00142 log_debug_p(log, "Ciphersuite_C3::validate() security params, len = %zu", len);
00143 while ( len > 0 ) {
00144 item_type = *buf++;
00145 --len;
00146 sdnv_len = SDNV::decode(buf, len, &field_length);
00147 buf += sdnv_len;
00148 len -= sdnv_len;
00149
00150 switch ( item_type ) {
00151 case CS_IV_field:
00152 {
00153 log_debug_p(log, "Ciphersuite_C3::validate() iv item, len = %llu", U64FMT(field_length));
00154 memcpy(iv, buf, iv_len);
00155 buf += field_length;
00156 len -= field_length;
00157 }
00158 break;
00159
00160 case CS_C_block_salt:
00161 {
00162 log_debug_p(log, "Ciphersuite_C3::validate() salt item, len = %llu", U64FMT(field_length));
00163 memcpy(salt, buf, nonce_len - iv_len);
00164 buf += field_length;
00165 len -= field_length;
00166 }
00167 break;
00168
00169 case CS_fragment_offset_and_length_field:
00170 {
00171 log_debug_p(log, "Ciphersuite_C3::validate() frag info item, len = %llu", U64FMT(field_length));
00172 sdnv_len = SDNV::decode(buf, len, &frag_offset_);
00173 buf += sdnv_len;
00174 len -= sdnv_len;
00175 sdnv_len = SDNV::decode(buf, len, &orig_length_);
00176 buf += sdnv_len;
00177 len -= sdnv_len;
00178 }
00179 break;
00180
00181 default:
00182 log_err_p(log, "Ciphersuite_C3::validate: unexpected item type %d in security_params",
00183 item_type);
00184 goto fail;
00185 }
00186 }
00187
00188
00189 buf = locals->security_result().buf();
00190 len = locals->security_result().len();
00191
00192 log_debug_p(log, "Ciphersuite_C3::validate() security result, len = %zu", len);
00193 while ( len > 0 ) {
00194 item_type = *buf++;
00195 --len;
00196 sdnv_len = SDNV::decode(buf, len, &field_length);
00197 buf += sdnv_len;
00198 len -= sdnv_len;
00199
00200 switch ( item_type ) {
00201 case CS_key_ID_field:
00202 {
00203 log_debug_p(log, "Ciphersuite_C3::validate() key ID item");
00204
00205 buf += field_length;
00206 len -= field_length;
00207 }
00208 break;
00209
00210 case CS_encoded_key_field:
00211 {
00212 log_debug_p(log, "Ciphersuite_C3::validate() encoded key item");
00213 KeySteward::decrypt(bundle, locals->security_src(), buf, field_length, db);
00214 memcpy(key, db.buf(), key_len);
00215 log_debug_p(log, "Ciphersuite_C3::validate() key 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",
00216 key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7],
00217 key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]);
00218 buf += field_length;
00219 len -= field_length;
00220 }
00221 break;
00222
00223 case CS_C_block_ICV_field:
00224 {
00225 log_debug_p(log, "Ciphersuite_C3::validate() icv item");
00226 memcpy(tag, buf, tag_len);
00227 buf += field_length;
00228 len -= field_length;
00229 }
00230 break;
00231
00232 case CS_encap_block_field:
00233 {
00234
00235
00236 log_err_p(log, "Ciphersuite_C3::validate: unexpected encap block in security_result");
00237 goto fail;
00238 }
00239 break;
00240
00241 default:
00242 log_err_p(log, "Ciphersuite_C3::validate: unexpected item type %d in security_result",
00243 item_type);
00244 goto fail;
00245 }
00246 }
00247
00248
00249 gcm_init_and_key(key, key_len, &(ctx_ex.c));
00250 ctx_ex.operation = op_decrypt;
00251
00252
00253
00254
00255
00256
00257 log_debug_p(log, "Ciphersuite_C3::validate() walk block list");
00258 for (BlockInfoVec::iterator iter = block_list->begin();
00259 iter != block_list->end();
00260 ++iter)
00261 {
00262
00263
00264 if ( (&*iter) <= block )
00265 continue;
00266
00267 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
00268
00269 switch ( iter->type() ) {
00270
00271 case BundleProtocol::CONFIDENTIALITY_BLOCK:
00272 {
00273 log_debug_p(log, "Ciphersuite_C3::validate() C block %p", &*iter);
00274 BlockInfo::DataBuffer encap_block;
00275 CS_FAIL_IF_NULL(target_locals);
00276
00277
00278
00279 log_debug_p(log, "Ciphersuite_C3::validate() C block owner_cs_num %d", target_locals->owner_cs_num());
00280 if ( target_locals->owner_cs_num() != CSNUM_C3 )
00281 continue;
00282
00283
00284
00285 if ( target_locals->correlator() != locals->correlator() )
00286 continue;
00287
00288
00289
00290 buf = target_locals->security_params().buf();
00291 len = target_locals->security_params().len();
00292
00293 log_debug_p(log, "Ciphersuite_C3::validate() target security params, len = %zu", len);
00294 while ( len > 0 ) {
00295 item_type = *buf++;
00296 --len;
00297 sdnv_len = SDNV::decode(buf, len, &field_length);
00298 buf += sdnv_len;
00299 len -= sdnv_len;
00300
00301 switch ( item_type ) {
00302 case CS_IV_field:
00303 {
00304 log_debug_p(log, "Ciphersuite_C3::validate() target iv item, len = %llu", U64FMT(field_length));
00305 memcpy(target_iv, buf, iv_len);
00306 buf += field_length;
00307 len -= field_length;
00308 }
00309 break;
00310
00311 default:
00312 log_err_p(log, "Ciphersuite_C3::validate: unexpected item type %d in target security_params",
00313 item_type);
00314 goto fail;
00315 }
00316 }
00317
00318 buf = target_locals->security_result().buf();
00319 len = target_locals->security_result().len();
00320
00321 log_debug_p(log, "Ciphersuite_C3::validate() target security result, len = %zu", len);
00322 while ( len > 0 ) {
00323 item_type = *buf++;
00324 --len;
00325 sdnv_len = SDNV::decode(buf, len, &field_length);
00326 buf += sdnv_len;
00327 len -= sdnv_len;
00328
00329
00330
00331 switch ( item_type ) {
00332 case CS_C_block_ICV_field:
00333 {
00334 log_debug_p(log, "Ciphersuite_C3::validate() target icv item, len = %llu", U64FMT(field_length));
00335 memcpy(tag_encap, buf, tag_len);
00336 buf += field_length;
00337 len -= field_length;
00338 }
00339 break;
00340
00341 case CS_encap_block_field:
00342 {
00343 log_debug_p(log, "Ciphersuite_C3::validate() encap block item, len = %llu", U64FMT(field_length));
00344 encap_block.reserve(field_length);
00345 encap_block.set_len(field_length);
00346 memcpy(encap_block.buf(), buf, field_length);
00347 buf += field_length;
00348 len -= field_length;
00349 }
00350 break;
00351
00352 default:
00353 log_err_p(log, "Ciphersuite_C3::validate: unexpected item type %d in target security_result",
00354 item_type);
00355 goto fail;
00356 }
00357 }
00358
00359
00360
00361
00362
00363 ptr = nonce;
00364
00365 memcpy(ptr, salt, nonce_len - iv_len);
00366 ptr += nonce_len - iv_len;
00367 memcpy(ptr, target_iv, iv_len);
00368
00369
00370 gcm_init_message(nonce, nonce_len, &(ctx_ex.c));
00371
00372
00373 ret = gcm_decrypt_message(nonce,
00374 nonce_len,
00375 NULL,
00376 0,
00377 encap_block.buf(),
00378 encap_block.len(),
00379 tag_encap,
00380 tag_len,
00381 &(ctx_ex.c));
00382
00383
00384 if ( ret != 0 ) {
00385 log_err_p(log, "Ciphersuite_C3::validate: gcm_decrypt_message failed, ret = %d", ret);
00386 goto fail;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 data = encap_block.buf();
00406 len = encap_block.len();
00407
00408 BlockInfo info(BundleProtocol::find_processor(*data));
00409 u_int64_t eid_ref_count = 0LLU;
00410 u_int64_t current_eid_count;
00411 u_int64_t flags;
00412 u_int64_t content_length = 0LLU;
00413
00414 BlockInfo::DataBuffer preamble;
00415 preamble.reserve(iter->full_length());
00416
00417
00418
00419 ptr = preamble.buf();
00420 rem = iter->full_length();
00421
00422 *ptr++ = *data++;
00423 rem--;
00424 len--;
00425 sdnv_len = SDNV::decode(data, len, &flags);
00426 data += sdnv_len;
00427 len -= sdnv_len;
00428 log_debug_p(log, "Ciphersuite_C3::validate() target block type %hhu flags 0x%llx", *(preamble.buf()), U64FMT(flags));
00429
00430
00431
00432
00433 if ( flags & BundleProtocol::BLOCK_FLAG_EID_REFS ) {
00434 sdnv_len = SDNV::decode(data, len, &eid_ref_count);
00435 data += sdnv_len;
00436 len -= sdnv_len;
00437
00438 current_eid_count = iter->eid_list().size();
00439
00440 if ( eid_ref_count != current_eid_count ) {
00441 log_err_p(log, "Ciphersuite_C3::validate: eid_ref_count %lld != current_eid_count %lld",
00442 U64FMT(eid_ref_count), U64FMT(current_eid_count));
00443 goto fail;
00444 }
00445 }
00446
00447
00448 if ( eid_ref_count > 0 ) {
00449 for ( u_int32_t i = 0; i < (2 * eid_ref_count); i++ ) {
00450 sdnv_len = SDNV::len(data);
00451 data += sdnv_len;
00452 len -= sdnv_len;
00453 }
00454 }
00455 sdnv_len = SDNV::decode(data, len, &content_length);
00456 data += sdnv_len;
00457 len -= sdnv_len;
00458 log_debug_p(log, "Ciphersuite_C3::validate() target data content size %llu", U64FMT(content_length));
00459
00460
00461
00462 if ( iter->flags() & BundleProtocol::BLOCK_FLAG_LAST_BLOCK )
00463 flags |= BundleProtocol::BLOCK_FLAG_LAST_BLOCK;
00464 else
00465 flags &= ~BundleProtocol::BLOCK_FLAG_LAST_BLOCK;
00466
00467
00468 sdnv_len = SDNV::encode(flags, ptr, rem);
00469 ptr += sdnv_len;
00470 rem -= sdnv_len;
00471
00472
00473 if ( eid_ref_count > 0 ) {
00474 u_char* cur_ptr = iter->contents().buf();
00475 size_t cur_len = iter->full_length();
00476
00477 cur_ptr++;
00478 cur_len--;
00479 sdnv_len = SDNV::len(cur_ptr);
00480 cur_ptr += sdnv_len;
00481 cur_len -= sdnv_len;
00482
00483 sdnv_len = SDNV::len(cur_ptr);
00484 cur_ptr += sdnv_len;
00485 cur_len -= sdnv_len;
00486
00487
00488 log_debug_p(log, "Ciphersuite_C3::validate() eid_ref_count %lld", U64FMT(eid_ref_count));
00489 sdnv_len = SDNV::encode(eid_ref_count, ptr, rem);
00490 ptr += sdnv_len;
00491 rem -= sdnv_len;
00492
00493
00494 for ( u_int32_t i = 0; i < (2 * eid_ref_count); i++ ) {
00495 sdnv_len = SDNV::len(cur_ptr);
00496 memcpy(ptr, cur_ptr, sdnv_len);
00497 cur_ptr += sdnv_len;
00498 cur_len -= sdnv_len;
00499 ptr += sdnv_len;
00500 rem -= sdnv_len;
00501 }
00502 }
00503
00504
00505 sdnv_len = SDNV::encode(content_length, ptr, rem);
00506 ptr += sdnv_len;
00507 rem -= sdnv_len;
00508
00509
00510 size_t preamble_size = ptr - preamble.buf();
00511 preamble.set_len(preamble_size);
00512 log_debug_p(log, "Ciphersuite_C3::validate() target preamble_size %zu", preamble_size);
00513
00514
00515 {
00516
00517 iter->~BlockInfo();
00518
00519
00520
00521
00522
00523
00524 log_debug_p(log, "Ciphersuite_C3::validate() re-init target");
00525 BlockInfo* bp = &*iter;
00526 bp = new (bp) BlockInfo(BundleProtocol::find_processor(*(preamble.buf())));
00527 CS_FAIL_IF_NULL(bp);
00528 }
00529
00530
00531 log_debug_p(log, "Ciphersuite_C3::validate() process target preamble");
00532 int cc = iter->owner()->consume(deliberate_const_cast_bundle, &*iter, preamble.buf(), preamble_size);
00533 if (cc < 0) {
00534 log_err_p(log, "Ciphersuite_C3::validate: consume failed handling encapsulated preamble 0x%x, cc = %d",
00535 info.type(), cc);
00536 goto fail;
00537 }
00538
00539
00540 log_debug_p(log, "Ciphersuite_C3::validate() process target content");
00541 cc = iter->owner()->consume(deliberate_const_cast_bundle, &*iter, data, len);
00542 if (cc < 0) {
00543 log_err_p(log, "Ciphersuite_C3::validate: consume failed handling encapsulated block 0x%x, cc = %d",
00544 info.type(), cc);
00545 goto fail;
00546 }
00547 log_debug_p(log, "Ciphersuite_C3::validate() decapsulation done");
00548 }
00549 break;
00550
00551 case BundleProtocol::PAYLOAD_BLOCK:
00552 {
00553 log_debug_p(log, "Ciphersuite_C3::validate() PAYLOAD_BLOCK");
00554 u_char tag_calc[tag_len];
00555
00556
00557
00558
00559 ptr = nonce;
00560
00561 memcpy(ptr, salt, salt_len);
00562 ptr += salt_len;
00563 memcpy(ptr, iv, iv_len);
00564 log_debug_p(log, "Ciphersuite_C3::validate() nonce 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",
00565 nonce[0], nonce[1], nonce[2], nonce[3], nonce[4], nonce[5], nonce[6], nonce[7], nonce[8], nonce[9], nonce[10], nonce[11]);
00566
00567
00568 gcm_init_message(nonce, nonce_len, &(ctx_ex.c));
00569
00570 offset = iter->data_offset();
00571 len = iter->data_length();
00572
00573 changed =
00574 iter->owner()->mutate( Ciphersuite_C3::do_crypt,
00575 deliberate_const_cast_bundle,
00576 block,
00577 &*iter,
00578 offset,
00579 len,
00580 r );
00581
00582
00583 gcm_compute_tag( tag_calc, tag_len, &(ctx_ex.c) );
00584 log_debug_p(log, "Ciphersuite_C3::validate() tag 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",
00585 tag[0], tag[1], tag[2], tag[3], tag[4], tag[5], tag[6], tag[7], tag[8], tag[9], tag[10], tag[11], tag[12], tag[13], tag[14], tag[15]);
00586 log_debug_p(log, "Ciphersuite_C3::validate() tag_calc 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",
00587 tag_calc[0], tag_calc[1], tag_calc[2], tag_calc[3], tag_calc[4], tag_calc[5], tag_calc[6], tag_calc[7],
00588 tag_calc[8], tag_calc[9], tag_calc[10], tag_calc[11], tag_calc[12], tag_calc[13], tag_calc[14], tag_calc[15]);
00589 if (memcmp(tag, tag_calc, tag_len) != 0) {
00590 log_err_p(log, "Ciphersuite_C3::validate: tag comparison failed");
00591 goto fail;
00592 }
00593
00594 }
00595 break;
00596
00597 default:
00598 continue;
00599
00600 }
00601 }
00602 log_debug_p(log, "Ciphersuite_C3::validate() walk block list done");
00603 locals->set_proc_flag(CS_BLOCK_PASSED_VALIDATION |
00604 CS_BLOCK_COMPLETED_DO_NOT_FORWARD);
00605 } else
00606 locals->set_proc_flag(CS_BLOCK_DID_NOT_FAIL);
00607
00608 log_debug_p(log, "Ciphersuite_C3::validate() %p done", block);
00609 return true;
00610
00611 fail:
00612 if ( locals != NULL )
00613 locals->set_proc_flag(CS_BLOCK_FAILED_VALIDATION |
00614 CS_BLOCK_COMPLETED_DO_NOT_FORWARD);
00615 *deletion_reason = BundleProtocol::REASON_SECURITY_FAILED;
00616 return false;
00617
00618 }
00619
00620
00621 int
00622 Ciphersuite_C3::prepare(const Bundle* bundle,
00623 BlockInfoVec* xmit_blocks,
00624 const BlockInfo* source,
00625 const LinkRef& link,
00626 list_owner_t list)
00627 {
00628 (void)bundle;
00629 (void)link;
00630
00631 int result = BP_FAIL;
00632 u_int16_t cs_flags = 0;
00633 BP_Local_CS* locals = NULL;
00634 BP_Local_CS* source_locals = NULL;
00635 EndpointID local_eid = BundleDaemon::instance()->local_eid();
00636 BundleDaemon* bd = BundleDaemon::instance();
00637
00638
00639 if ( (source != NULL) &&
00640 (dynamic_cast<BP_Local_CS*>(source->locals())->security_dest() == bd->local_eid().data()) ) {
00641 log_debug_p(log, "Ciphersuite_C3::prepare() - not being forwarded");
00642 return BP_SUCCESS;
00643 }
00644
00645 BlockInfo bi = BlockInfo(BundleProtocol::find_processor(BundleProtocol::CONFIDENTIALITY_BLOCK), source);
00646
00647
00648
00649
00650
00651 if ( list == BlockInfo::LIST_RECEIVED ) {
00652
00653 ASSERT(source != NULL);
00654 if ( Ciphersuite::destination_is_local_node(bundle, source) )
00655 return BP_SUCCESS;
00656
00657 xmit_blocks->push_back(bi);
00658 BlockInfo* bp = &(xmit_blocks->back());
00659 bp->set_eid_list(source->eid_list());
00660 log_debug_p(log, "Ciphersuite_C3::prepare() - forward received block len %u eid_list_count %zu new count %zu",
00661 source->full_length(), source->eid_list().size(), bp->eid_list().size());
00662
00663 CS_FAIL_IF_NULL( source->locals() )
00664
00665 source_locals = dynamic_cast<BP_Local_CS*>(source->locals());
00666 CS_FAIL_IF_NULL(source_locals);
00667 bp->set_locals(new BP_Local_CS);
00668 locals = dynamic_cast<BP_Local_CS*>(bp->locals());
00669 CS_FAIL_IF_NULL(locals);
00670 locals->set_owner_cs_num(CSNUM_C3);
00671 cs_flags = source_locals->cs_flags();
00672 locals->set_list_owner(BlockInfo::LIST_RECEIVED);
00673 locals->set_correlator(source_locals->correlator());
00674 bp->writable_contents()->reserve(source->full_length());
00675 bp->writable_contents()->set_len(0);
00676
00677
00678 if ( source_locals->cs_flags() & CS_BLOCK_HAS_SOURCE ) {
00679 CS_FAIL_IF(source_locals->security_src().length() == 0 );
00680 log_debug_p(log, "Ciphersuite_C3::prepare() add security_src EID");
00681 cs_flags |= CS_BLOCK_HAS_SOURCE;
00682 locals->set_security_src(source_locals->security_src());
00683 }
00684
00685 if ( source_locals->cs_flags() & CS_BLOCK_HAS_DEST ) {
00686 CS_FAIL_IF(source_locals->security_dest().length() == 0 );
00687 log_debug_p(log, "Ciphersuite_C3::prepare() add security_dest EID");
00688 cs_flags |= CS_BLOCK_HAS_DEST;
00689 locals->set_security_dest(source_locals->security_dest());
00690 }
00691 locals->set_cs_flags(cs_flags);
00692 log_debug_p(log, "Ciphersuite_C3::prepare() - inserted block eid_list_count %zu",
00693 bp->eid_list().size());
00694 result = BP_SUCCESS;
00695 return result;
00696 } else {
00697
00698
00699 log_debug_p(log, "Ciphersuite_C3::prepare() - add new block (or API block etc)");
00700 bi.set_locals(new BP_Local_CS);
00701 CS_FAIL_IF_NULL(bi.locals());
00702 locals = dynamic_cast<BP_Local_CS*>(bi.locals());
00703 CS_FAIL_IF_NULL(locals);
00704 locals->set_owner_cs_num(CSNUM_C3);
00705 locals->set_list_owner(list);
00706
00707
00708 if ( source != NULL && source->locals() != NULL) {
00709 locals->set_security_src(dynamic_cast<BP_Local_CS*>(source->locals())->security_src());
00710 locals->set_security_dest(dynamic_cast<BP_Local_CS*>(source->locals())->security_dest());
00711 }
00712
00713 log_debug_p(log, "Ciphersuite_C3::prepare() local_eid %s bundle->source_ %s", local_eid.c_str(), bundle->source().c_str());
00714
00715 if ( (locals->security_src().length() == 0) && (local_eid != bundle->source()))
00716 locals->set_security_src(local_eid.str());
00717
00718
00719 if ( locals->security_src().length() > 0 ) {
00720 log_debug_p(log, "Ciphersuite_C3::prepare() add security_src EID %s", locals->security_src().c_str());
00721 cs_flags |= CS_BLOCK_HAS_SOURCE;
00722 bi.add_eid(locals->security_src());
00723 }
00724
00725 if ( locals->security_dest().length() > 0 ) {
00726 log_debug_p(log, "Ciphersuite_C3::prepare() add security_dest EID %s", locals->security_dest().c_str());
00727 cs_flags |= CS_BLOCK_HAS_DEST;
00728 bi.add_eid(locals->security_dest());
00729 }
00730
00731 locals->set_cs_flags(cs_flags);
00732
00733
00734
00735
00736 if ( xmit_blocks->size() > 0 ) {
00737 BlockInfoVec::iterator iter = xmit_blocks->begin();
00738
00739 while ( iter != xmit_blocks->end()) {
00740 switch (iter->type()) {
00741 case BundleProtocol::PRIMARY_BLOCK:
00742 case BundleProtocol::BUNDLE_AUTHENTICATION_BLOCK:
00743 ++iter;
00744 continue;
00745
00746 default:
00747 break;
00748 }
00749 xmit_blocks->insert(iter, bi);
00750 break;
00751 }
00752 } else {
00753
00754 xmit_blocks->push_back(bi);
00755 }
00756 }
00757
00758
00759 result = BP_SUCCESS;
00760 return result;
00761
00762 fail:
00763 if ( locals != NULL )
00764 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
00765 return BP_FAIL;
00766 }
00767
00768
00769 int
00770 Ciphersuite_C3::generate(const Bundle* bundle,
00771 BlockInfoVec* xmit_blocks,
00772 BlockInfo* block,
00773 const LinkRef& link,
00774 bool last)
00775 {
00776 (void)bundle;
00777 (void)link;
00778 (void)xmit_blocks;
00779
00780 int result = BP_FAIL;
00781 u_char key[key_len];
00782 u_char iv[iv_len];
00783 u_char salt[nonce_len - iv_len];
00784 u_char fragment_item[24];
00785 u_int16_t cs_flags = 0;
00786 bool need_correlator = false;
00787 u_int64_t correlator = 0LLU;
00788 BP_Local_CS* locals = dynamic_cast<BP_Local_CS*>(block->locals());
00789 BP_Local_CS* target_locals = NULL;
00790 u_char* ptr;
00791 size_t temp;
00792 size_t rem;
00793 DataBuffer encrypted_key;
00794 size_t param_len = 0;
00795 size_t res_len = 0;
00796 size_t length = 0;
00797 u_char* buf = NULL;
00798 int len = 0;
00799 int sdnv_len = 0;
00800 u_int16_t n = 0;
00801 int err = 0;
00802 BlockInfo::DataBuffer* contents = NULL;
00803 LocalBuffer* digest_result = NULL;
00804 LocalBuffer* params = NULL;
00805
00806 log_debug_p(log, "Ciphersuite_C3::generate() %p", block);
00807
00808 CS_FAIL_IF_NULL(locals);
00809 cs_flags = locals->cs_flags();
00810
00811 if ( locals->list_owner() == BlockInfo::LIST_RECEIVED )
00812 {
00813
00814 size_t length = block->source()->data_length();
00815
00816 generate_preamble(xmit_blocks,
00817 block,
00818 BundleProtocol::CONFIDENTIALITY_BLOCK,
00819 BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR |
00820 BundleProtocol::BLOCK_FLAG_REPLICATE |
00821 (last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0),
00822 length);
00823
00824 BlockInfo::DataBuffer* contents = block->writable_contents();
00825 contents->reserve(block->data_offset() + length);
00826 contents->set_len(block->data_offset() + length);
00827 memcpy(contents->buf() + block->data_offset(),
00828 block->source()->data(), length);
00829 log_debug_p(log, "Ciphersuite_C3::generate() %p done", block);
00830 return BP_SUCCESS;
00831 }
00832
00833
00834
00835 for (BlockInfoVec::iterator iter = xmit_blocks->begin();
00836 iter != xmit_blocks->end();
00837 ++iter)
00838 {
00839 n++;
00840
00841
00842
00843
00844
00845
00846 if ( (&*iter) <= block )
00847 continue;
00848
00849 if ( iter->type() == BundleProtocol::PAYLOAD_SECURITY_BLOCK ) {
00850 need_correlator = true;
00851 break;
00852 }
00853
00854 if ( iter->type() == BundleProtocol::CONFIDENTIALITY_BLOCK ) {
00855 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
00856 CS_FAIL_IF_NULL(target_locals);
00857 if ( target_locals->owner_cs_num() == CSNUM_C3 ) {
00858 need_correlator = true;
00859 break;
00860 }
00861 }
00862
00863 }
00864
00865 if ( need_correlator ) {
00866 correlator = create_correlator(bundle, xmit_blocks);
00867 correlator |= (int)CSNUM_C3 << 16;
00868 locals->set_correlator( correlator );
00869 log_debug_p(log, "Ciphersuite_C3::generate() correlator %llu", U64FMT(correlator));
00870 }
00871
00872
00873
00874
00875
00876
00877
00878
00879 params = locals->writable_security_params();
00880
00881
00882 RAND_bytes(salt, sizeof(salt));
00883 RAND_bytes(iv, sizeof(iv));
00884
00885
00886 locals->set_salt(salt, sizeof(salt));
00887 locals->set_iv(iv, sizeof(iv));
00888
00889 param_len = 1 + 1 + sizeof(salt);
00890 param_len += 1 + 1 + sizeof(iv);
00891
00892 if ( bundle->is_fragment() ) {
00893 log_debug_p(log, "Ciphersuite_C3::generate() bundle is fragment");
00894 ptr = &fragment_item[2];
00895 rem = sizeof(fragment_item) - 2;
00896 temp = SDNV::encode(bundle->frag_offset(), ptr, rem);
00897 ptr += temp;
00898 rem -= temp;
00899 temp += SDNV::encode(bundle->payload().length(), ptr, rem);
00900 fragment_item[0] = CS_fragment_offset_and_length_field;
00901 fragment_item[1] = temp;
00902 param_len += 2 + temp;
00903
00904 }
00905
00906 params->reserve(param_len);
00907 params->set_len(param_len);
00908 log_debug_p(log, "Ciphersuite_C3::generate() security params, len = %zu", param_len);
00909
00910 ptr = params->buf();
00911 *ptr++ = CS_C_block_salt;
00912 *ptr++ = sizeof(salt);
00913 memcpy(ptr, salt, sizeof(salt));
00914 ptr += sizeof(salt);
00915 *ptr++ = CS_IV_field;
00916 *ptr++ = sizeof(iv);
00917 memcpy(ptr, iv, sizeof(iv));
00918 ptr += sizeof(iv);
00919
00920 if ( bundle->is_fragment() )
00921 memcpy(ptr, fragment_item, 2 + temp);
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 RAND_bytes(key, sizeof(key));
00938
00939
00940 locals->set_key(key, sizeof(key));
00941
00942 log_debug_p(log, "Ciphersuite_C3::generate() key 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",
00943 key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7],
00944 key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]);
00945 err = KeySteward::encrypt(bundle, NULL, link, locals->security_dest(), key, sizeof(key), encrypted_key);
00946 CS_FAIL_IF(err != 0);
00947 log_debug_p(log, "Ciphersuite_C3::generate() encrypted_key len = %zu", encrypted_key.len());
00948
00949 res_len = 1 + SDNV::encoding_len(encrypted_key.len()) + encrypted_key.len();
00950 res_len += 1 + 1 + tag_len;
00951
00952 digest_result = locals->writable_security_result();
00953 digest_result->reserve(res_len);
00954 digest_result->set_len(res_len);
00955 rem = res_len;
00956
00957 ptr = digest_result->buf();
00958 *ptr++ = Ciphersuite::CS_encoded_key_field;
00959 rem--;
00960 temp = SDNV::encode(encrypted_key.len(), ptr, rem);
00961 ptr += temp;
00962 rem -= temp;
00963 memcpy(ptr, encrypted_key.buf(), encrypted_key.len());
00964 ptr += encrypted_key.len();
00965 rem -= encrypted_key.len();
00966
00967
00968 length = 0;
00969 if ( need_correlator ) {
00970 log_debug_p(log, "Ciphersuite_C3::generate() correlator %llu", U64FMT(correlator));
00971 locals->set_correlator(correlator);
00972 length += SDNV::encoding_len(locals->correlator());
00973 cs_flags |= CS_BLOCK_HAS_CORRELATOR;
00974 }
00975
00976
00977 cs_flags |= CS_BLOCK_HAS_PARAMS;
00978 cs_flags |= CS_BLOCK_HAS_RESULT;
00979 locals->set_cs_flags(cs_flags);
00980 length += SDNV::encoding_len(CSNUM_C3);
00981 length += SDNV::encoding_len(locals->cs_flags());
00982
00983 param_len = locals->security_params().len();
00984 length += SDNV::encoding_len(param_len) + param_len;
00985 locals->set_security_result_offset(length);
00986 length += SDNV::encoding_len(res_len) + res_len;
00987
00988 contents = block->writable_contents();
00989
00990 generate_preamble(xmit_blocks,
00991 block,
00992 BundleProtocol::CONFIDENTIALITY_BLOCK,
00993 BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR |
00994 (last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0),
00995 length);
00996
00997
00998 log_debug_p(log, "Ciphersuite_C3::generate() preamble len %u block len %zu", block->data_offset(), length);
00999 contents->reserve(block->data_offset() + length);
01000 contents->set_len(block->data_offset() + length);
01001 buf = block->writable_contents()->buf() + block->data_offset();
01002 len = length;
01003
01004
01005
01006
01007
01008 sdnv_len = SDNV::encode(locals->owner_cs_num(), buf, len);
01009 CS_FAIL_IF(sdnv_len <= 0);
01010 buf += sdnv_len;
01011 len -= sdnv_len;
01012
01013 sdnv_len = SDNV::encode(locals->cs_flags(), buf, len);
01014 CS_FAIL_IF(sdnv_len <= 0);
01015 buf += sdnv_len;
01016 len -= sdnv_len;
01017
01018 if ( need_correlator ) {
01019
01020 sdnv_len = SDNV::encode(locals->correlator(), buf, len);
01021 CS_FAIL_IF(sdnv_len <= 0);
01022 buf += sdnv_len;
01023 len -= sdnv_len;
01024 }
01025
01026
01027
01028 sdnv_len = SDNV::encode(param_len, buf, len);
01029 CS_FAIL_IF(sdnv_len <= 0);
01030 buf += sdnv_len;
01031 len -= sdnv_len;
01032
01033
01034 memcpy(buf, locals->security_params().buf(), param_len );
01035 buf += param_len;
01036 len -= param_len;
01037
01038
01039 sdnv_len = SDNV::encode(res_len, buf, len);
01040
01041
01042
01043
01044 log_debug_p(log, "Ciphersuite_C3::generate() done");
01045
01046
01047 result = BP_SUCCESS;
01048 return result;
01049
01050 fail:
01051 if ( locals != NULL )
01052 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
01053 return BP_FAIL;
01054 }
01055
01056
01057 int
01058 Ciphersuite_C3::finalize(const Bundle* bundle,
01059 BlockInfoVec* xmit_blocks,
01060 BlockInfo* block,
01061 const LinkRef& link)
01062 {
01063 (void)link;
01064 int result = BP_FAIL;
01065 Bundle* deliberate_const_cast_bundle = const_cast<Bundle*>(bundle);
01066 size_t offset;
01067 size_t len;
01068 size_t length;
01069 size_t param_len;
01070 size_t res_len;
01071 gcm_ctx_ex ctx_ex;
01072 OpaqueContext* r = reinterpret_cast<OpaqueContext*>(&ctx_ex);
01073 bool changed = false;
01074 u_char key[key_len];
01075 u_char iv[iv_len];
01076 u_char nonce[nonce_len];
01077 u_char tag[tag_len];
01078 u_char* buf;
01079 u_char* ptr;
01080 BP_Local_CS* locals = NULL;
01081 BP_Local_CS* target_locals = NULL;
01082 u_int64_t correlator;
01083 std::vector<u_int64_t> correlator_list;
01084 std::vector<u_int64_t>::iterator cl_iter;
01085 size_t correlator_size = 0;
01086 int sdnv_len = 0;
01087 EndpointID local_eid = BundleDaemon::instance()->local_eid();
01088
01089 log_debug_p(log, "Ciphersuite_C3::finalize()");
01090 locals = dynamic_cast<BP_Local_CS*>(block->locals());
01091 CS_FAIL_IF_NULL(locals);
01092
01093
01094 if ( locals->list_owner() == BlockInfo::LIST_RECEIVED )
01095 return BP_SUCCESS;
01096
01097
01098 memcpy(key, locals->key().buf(), key_len);
01099 gcm_init_and_key(key, key_len, &(ctx_ex.c));
01100 ctx_ex.operation = op_encrypt;
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120 log_debug_p(log, "Ciphersuite_C3::finalize() walk block list");
01121 for (BlockInfoVec::iterator iter = xmit_blocks->begin();
01122 iter != xmit_blocks->end();
01123 ++iter)
01124 {
01125
01126
01127
01128
01129
01130
01131 if ( (&*iter) <= block ) {
01132 if ( iter->type() == BundleProtocol::PAYLOAD_SECURITY_BLOCK ) {
01133
01134 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
01135 CS_FAIL_IF_NULL(target_locals);
01136 correlator_list.push_back(target_locals->correlator());
01137 } else if (iter->type() == BundleProtocol::CONFIDENTIALITY_BLOCK ) {
01138 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
01139 CS_FAIL_IF_NULL(target_locals);
01140 if ( target_locals->owner_cs_num() == CSNUM_C3 ) {
01141 correlator_list.push_back(target_locals->correlator());
01142 }
01143 }
01144 continue;
01145 }
01146
01147
01148 switch ( iter->type() ) {
01149
01150 case BundleProtocol::PAYLOAD_SECURITY_BLOCK:
01151 case BundleProtocol::CONFIDENTIALITY_BLOCK:
01152 {
01153
01154 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
01155 CS_FAIL_IF_NULL(target_locals);
01156 log_debug_p(log, "Ciphersuite_C3::finalize() PS or C block type %d cs_num %d",
01157 iter->type(), target_locals->owner_cs_num());
01158 if ( iter->type() == BundleProtocol::CONFIDENTIALITY_BLOCK &&
01159 target_locals->owner_cs_num() != CSNUM_C3 )
01160 continue;
01161
01162
01163
01164
01165
01166 bool skip_psb = false;
01167 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
01168 log_debug_p(log, "Ciphersuite_C3::finalize() target_locals->cs_flags 0x%hx", target_locals->cs_flags());
01169 log_debug_p(log, "Ciphersuite_C3::finalize() target_locals->correlator() 0x%llx", U64FMT(target_locals->correlator()));
01170 if ( target_locals->cs_flags() & CS_BLOCK_HAS_CORRELATOR) {
01171 correlator = target_locals->correlator();
01172 for ( cl_iter = correlator_list.begin();
01173 cl_iter < correlator_list.end();
01174 ++cl_iter) {
01175 if ( correlator == *cl_iter) {
01176 skip_psb = true;
01177 break;
01178 }
01179 }
01180 if ( skip_psb )
01181 break;
01182
01183 }
01184
01185 log_debug_p(log, "Ciphersuite_C3::finalize() encapsulate this block, len %u eid_ref_count %zu",
01186 iter->full_length(), iter->eid_list().size());
01187
01188
01189
01190
01191
01192
01193
01194 bool last = iter->flags() & BundleProtocol::BLOCK_FLAG_LAST_BLOCK;
01195
01196
01197
01198
01199
01200 ptr = nonce;
01201
01202 memcpy(ptr, locals->salt().buf(), nonce_len - iv_len);
01203 ptr += nonce_len - iv_len;
01204 RAND_bytes(iv, sizeof(iv));
01205 memcpy(ptr, iv, iv_len);
01206
01207
01208 gcm_init_message(nonce, nonce_len, &(ctx_ex.c));
01209
01210
01211 gcm_encrypt_message(nonce,
01212 nonce_len,
01213 NULL,
01214 0,
01215 iter->writable_contents()->buf(),
01216 iter->full_length(),
01217 tag,
01218 tag_len,
01219 &(ctx_ex.c));
01220
01221
01222 BlockInfo::DataBuffer encap_block;
01223 size_t encap_len = 1 + SDNV::encoding_len(iter->full_length()) + iter->full_length();
01224 encap_block.reserve(encap_len);
01225 encap_block.set_len(encap_len);
01226 ptr = encap_block.buf();
01227 *ptr++ = CS_encap_block_field;
01228 sdnv_len = SDNV::encode(iter->full_length(), ptr, encap_len - 1);
01229 CS_FAIL_IF(sdnv_len <= 0);
01230 ptr += sdnv_len;
01231 memcpy(ptr, iter->contents().buf(), iter->full_length());
01232
01233
01234
01235 BP_Local_CS* new_target_locals = new BP_Local_CS(*locals);
01236 u_int16_t cs_flags = CS_BLOCK_HAS_PARAMS | CS_BLOCK_HAS_RESULT | CS_BLOCK_HAS_CORRELATOR;
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249 correlator_size = SDNV::encoding_len(locals->correlator());
01250
01251
01252
01253 length = 0;
01254 length += SDNV::encoding_len(CSNUM_C3);
01255 length += SDNV::encoding_len(locals->cs_flags());
01256 length += correlator_size;
01257 param_len = 1 + 1 + iv_len;
01258 length += SDNV::encoding_len(param_len) + param_len;
01259 res_len = 1 + 1 + tag_len + encap_len;
01260 length += SDNV::encoding_len(res_len) + res_len;
01261
01262 iter->writable_contents()->set_len(0);
01263 iter->set_owner(BundleProtocol::find_processor(BundleProtocol::CONFIDENTIALITY_BLOCK));
01264 generate_preamble(xmit_blocks,
01265 &*iter,
01266 BundleProtocol::CONFIDENTIALITY_BLOCK,
01267 BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR |
01268 (last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0),
01269 length);
01270
01271
01272 log_debug_p(log, "Ciphersuite_C3::finalize() preamble len %u block len %zu", iter->data_offset(), length);
01273 log_debug_p(log, "Ciphersuite_C3::finalize() owner()->block_type() %u buf()[0] %hhu",
01274 iter->owner()->block_type(), iter->contents().buf()[0]);
01275 iter->writable_contents()->reserve(iter->data_offset() + length);
01276 iter->writable_contents()->set_len(iter->data_offset() + length);
01277 buf = iter->writable_contents()->buf() + iter->data_offset();
01278 len = length;
01279
01280
01281
01282
01283 new_target_locals->set_cs_flags(cs_flags);
01284 sdnv_len = SDNV::encode(CSNUM_C3, buf, len);
01285 CS_FAIL_IF(sdnv_len <= 0);
01286 buf += sdnv_len;
01287 len -= sdnv_len;
01288
01289 sdnv_len = SDNV::encode(new_target_locals->cs_flags(), buf, len);
01290 CS_FAIL_IF(sdnv_len <= 0);
01291 buf += sdnv_len;
01292 len -= sdnv_len;
01293
01294
01295 sdnv_len = SDNV::encode(locals->correlator(), buf, len);
01296 CS_FAIL_IF(sdnv_len <= 0);
01297 buf += sdnv_len;
01298 len -= sdnv_len;
01299
01300
01301 sdnv_len = SDNV::encode(param_len, buf, len);
01302 CS_FAIL_IF(sdnv_len <= 0);
01303 buf += sdnv_len;
01304 len -= sdnv_len;
01305
01306
01307 *buf++ = CS_IV_field;
01308 --len;
01309 *buf++ = iv_len;
01310 --len;
01311 memcpy(buf, iv, iv_len);
01312 buf += iv_len;
01313 len -= iv_len;
01314
01315
01316 sdnv_len = SDNV::encode(res_len, buf, len);
01317 CS_FAIL_IF(sdnv_len <= 0);
01318 buf += sdnv_len;
01319 len -= sdnv_len;
01320
01321
01322 *buf++ = CS_C_block_ICV_field;
01323 --len;
01324 *buf++ = tag_len;
01325 --len;
01326 memcpy(buf, tag, tag_len);
01327 buf += tag_len;
01328 len -= tag_len;
01329
01330
01331 memcpy(buf, encap_block.buf(), encap_block.len());
01332 buf += encap_block.len();
01333 len -= encap_block.len();
01334 CS_FAIL_IF(len != 0);
01335
01336
01337
01338
01339
01340 iter->set_locals(new_target_locals);
01341 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals());
01342 log_debug_p(log, "Ciphersuite_C3::finalize() encapsulation done");
01343
01344 }
01345 break;
01346
01347 case BundleProtocol::PAYLOAD_BLOCK:
01348 {
01349
01350
01351
01352
01353
01354 u_char* ptr;
01355 size_t rem;
01356 u_char type;
01357 u_int64_t field_len;
01358 ptr = nonce;
01359
01360 log_debug_p(log, "Ciphersuite_C3::finalize() PAYLOAD_BLOCK");
01361 memcpy(ptr, locals->salt().buf(), salt_len);
01362 ptr += salt_len;
01363 memcpy(ptr, locals->iv().buf(), iv_len);
01364
01365
01366 log_debug_p(log, "Ciphersuite_C3::finalize() nonce 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",
01367 nonce[0], nonce[1], nonce[2], nonce[3], nonce[4], nonce[5], nonce[6], nonce[7], nonce[8], nonce[9], nonce[10], nonce[11]);
01368 gcm_init_message(nonce, nonce_len, &(ctx_ex.c));
01369
01370 offset = iter->data_offset();
01371 len = iter->data_length();
01372 changed =
01373 iter->owner()->mutate( Ciphersuite_C3::do_crypt,
01374 deliberate_const_cast_bundle,
01375 block,
01376 &*iter,
01377 offset,
01378 len,
01379 r);
01380
01381
01382 gcm_compute_tag( tag, tag_len, &(ctx_ex.c) );
01383 log_debug_p(log, "Ciphersuite_C3::finalize() tag 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",
01384 tag[0], tag[1], tag[2], tag[3], tag[4], tag[5], tag[6], tag[7], tag[8], tag[9], tag[10], tag[11], tag[12], tag[13], tag[14], tag[15]);
01385
01386
01387 LocalBuffer* result = locals->writable_security_result();
01388 ptr = result->buf();
01389 rem = result->len();
01390 type = *ptr++;
01391 CS_FAIL_IF(type != Ciphersuite::CS_encoded_key_field);
01392 rem--;
01393 sdnv_len = SDNV::decode( ptr, rem, &field_len);
01394 ptr += sdnv_len;
01395 rem -= sdnv_len;
01396 ptr += field_len;
01397 rem -= field_len;
01398 CS_FAIL_IF( rem != 1 + 1 + tag_len);
01399 *ptr++ = CS_C_block_ICV_field;
01400 rem--;
01401 *ptr++ = tag_len;
01402 rem--;
01403 memcpy(ptr, tag, tag_len);
01404
01405
01406 BlockInfo::DataBuffer* contents = block->writable_contents();
01407 u_char* buf = contents->buf();
01408 rem = contents->len();
01409 buf += block->data_offset();
01410 rem -= block->data_offset();
01411
01412 buf += locals->security_result_offset();
01413 rem -= locals->security_result_offset();
01414 sdnv_len = SDNV::len(buf);
01415 buf += sdnv_len;
01416 rem -= sdnv_len;
01417 memcpy(buf, result->buf(), result->len());
01418 log_debug_p(log, "Ciphersuite_C3::finalize() PAYLOAD_BLOCK done");
01419
01420
01421
01422 }
01423 break;
01424
01425 default:
01426 continue;
01427
01428 }
01429
01430
01431 }
01432 log_debug_p(log, "Ciphersuite_C3::finalize() done");
01433
01434 result = BP_SUCCESS;
01435 return result;
01436
01437 fail:
01438 if ( locals != NULL )
01439 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND);
01440 return BP_FAIL;
01441 }
01442
01443
01444 bool
01445 Ciphersuite_C3::do_crypt(const Bundle* bundle,
01446 const BlockInfo* caller_block,
01447 BlockInfo* target_block,
01448 void* buf,
01449 size_t len,
01450 OpaqueContext* r)
01451 {
01452 (void) bundle;
01453 (void) caller_block;
01454 (void) target_block;
01455 gcm_ctx_ex* pctx = reinterpret_cast<gcm_ctx_ex*>(r);
01456
01457 log_debug_p(log, "Ciphersuite_C3::do_crypt() operation %hhu len %zu", pctx->operation, len);
01458 if (pctx->operation == op_encrypt)
01459 gcm_encrypt( reinterpret_cast<u_char*>(buf), len, &(pctx->c) );
01460 else
01461 gcm_decrypt( reinterpret_cast<u_char*>(buf), len, &(pctx->c) );
01462
01463 return (len > 0) ? true : false;
01464 }
01465
01466 }
01467
01468 #endif