|
1 /* |
|
2 * Copyright 2006 SPARTA Inc |
|
3 * |
|
4 * Licensed under the Apache License, Version 2.0 (the "License"); |
|
5 * you may not use this file except in compliance with the License. |
|
6 * You may obtain a copy of the License at |
|
7 * |
|
8 * http://www.apache.org/licenses/LICENSE-2.0 |
|
9 * |
|
10 * Unless required by applicable law or agreed to in writing, software |
|
11 * distributed under the License is distributed on an "AS IS" BASIS, |
|
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
13 * See the License for the specific language governing permissions and |
|
14 * limitations under the License. |
|
15 */ |
|
16 |
|
17 #ifdef HAVE_CONFIG_H |
|
18 # include <dtn-config.h> |
|
19 #endif |
|
20 |
|
21 #ifdef BSP_ENABLED |
|
22 |
|
23 #define OPENSSL_FIPS 1 /* required for sha256 */ |
|
24 |
|
25 #include "Ciphersuite_PI2.h" |
|
26 #include "Ciphersuite_PC3.h" |
|
27 #include "bundling/Bundle.h" |
|
28 #include "bundling/BundleDaemon.h" |
|
29 #include "bundling/BundleProtocol.h" |
|
30 #include "bundling/SDNV.h" |
|
31 #include "contacts/Link.h" |
|
32 #include "security/KeySteward.h" |
|
33 #include "openssl/evp.h" |
|
34 |
|
35 namespace dtn { |
|
36 |
|
37 static const char * log = "/dtn/bundle/ciphersuite"; |
|
38 |
|
39 /** |
|
40 * Local definition borrowed from PrimaryBlockProcessor.h |
|
41 * and with frag_offest and orig_length added |
|
42 */ |
|
43 struct PrimaryBlock_ex { |
|
44 u_int8_t version; |
|
45 u_int64_t processing_flags; |
|
46 u_int64_t block_length; |
|
47 u_int64_t dest_scheme_offset; |
|
48 u_int64_t dest_ssp_offset; |
|
49 u_int64_t source_scheme_offset; |
|
50 u_int64_t source_ssp_offset; |
|
51 u_int64_t replyto_scheme_offset; |
|
52 u_int64_t replyto_ssp_offset; |
|
53 u_int64_t custodian_scheme_offset; |
|
54 u_int64_t custodian_ssp_offset; |
|
55 u_int64_t creation_time; |
|
56 u_int64_t creation_sequence; |
|
57 u_int64_t lifetime; |
|
58 u_int64_t dictionary_length; |
|
59 u_int64_t fragment_offset; |
|
60 u_int64_t original_length; |
|
61 }; |
|
62 |
|
63 // Need quad versions of hton for manipulating full-length (unpacked) SDNV values |
|
64 |
|
65 #if defined(WORDS_BIGENDIAN) && (WORDS_BIGENDIAN == 1) |
|
66 #define htonq( x ) (x) |
|
67 #define ntohq( x ) (x) |
|
68 #else |
|
69 |
|
70 inline u_int64_t htonq( u_int64_t x ) |
|
71 { |
|
72 u_int64_t res; |
|
73 u_int32_t hi = x >> 32; |
|
74 u_int32_t lo = x & 0xffffffff; |
|
75 hi = htonl( hi ); |
|
76 res = htonl( lo ); |
|
77 res = res << 32 | hi; |
|
78 |
|
79 return res; |
|
80 } |
|
81 |
|
82 inline u_int64_t ntohq( u_int64_t x ) |
|
83 { |
|
84 u_int64_t res; |
|
85 u_int32_t hi = x >> 32; |
|
86 u_int32_t lo = x & 0xffffffff; |
|
87 hi = ntohl( hi ); |
|
88 res = ntohl( lo ); |
|
89 res = res << 32 | hi; |
|
90 |
|
91 return res; |
|
92 } |
|
93 #endif |
|
94 |
|
95 |
|
96 //---------------------------------------------------------------------- |
|
97 Ciphersuite_PI2::Ciphersuite_PI2() |
|
98 { |
|
99 } |
|
100 |
|
101 //---------------------------------------------------------------------- |
|
102 u_int16_t |
|
103 Ciphersuite_PI2::cs_num(void) |
|
104 { |
|
105 return CSNUM_PI2; |
|
106 } |
|
107 |
|
108 //---------------------------------------------------------------------- |
|
109 int |
|
110 Ciphersuite_PI2::consume(Bundle* bundle, |
|
111 BlockInfo* block, |
|
112 u_char* buf, |
|
113 size_t len) |
|
114 { |
|
115 int cc = block->owner()->consume(bundle, block, buf, len); |
|
116 |
|
117 if (cc == -1) { |
|
118 return -1; // protocol error |
|
119 } |
|
120 |
|
121 |
|
122 // in on-the-fly scenario, process this data for those interested |
|
123 |
|
124 if (! block->complete()) { |
|
125 ASSERT(cc == (int)len); |
|
126 return cc; |
|
127 } |
|
128 |
|
129 if ( block->locals() == NULL ) { // then we need to parse it |
|
130 parse(block); |
|
131 } |
|
132 |
|
133 return cc; |
|
134 } |
|
135 |
|
136 //---------------------------------------------------------------------- |
|
137 bool |
|
138 Ciphersuite_PI2::validate(const Bundle* bundle, |
|
139 BlockInfoVec* block_list, |
|
140 BlockInfo* block, |
|
141 status_report_reason_t* reception_reason, |
|
142 status_report_reason_t* deletion_reason) |
|
143 { |
|
144 (void)reception_reason; |
|
145 |
|
146 size_t sdnv_len; |
|
147 u_char* buf; |
|
148 size_t len; |
|
149 size_t digest_len; |
|
150 u_char ps_digest[EVP_MAX_MD_SIZE]; |
|
151 BP_Local_CS* locals = NULL; |
|
152 u_int64_t field_length; |
|
153 std::vector<u_int64_t> correlator_list; |
|
154 std::vector<u_int64_t>::iterator cl_iter; |
|
155 EndpointID local_eid = BundleDaemon::instance()->local_eid(); |
|
156 BlockInfoVec::iterator iter; |
|
157 u_int16_t cs_flags; |
|
158 int err = 0; |
|
159 DataBuffer db; |
|
160 |
|
161 log_debug_p(log, "Ciphersuite_PI2::validate()"); |
|
162 locals = dynamic_cast<BP_Local_CS*>(block->locals()); |
|
163 CS_FAIL_IF_NULL(locals); |
|
164 cs_flags = locals->cs_flags(); |
|
165 |
|
166 if ( destination_is_local_node(bundle, block) ) |
|
167 { //yes - this is ours so go to work |
|
168 |
|
169 if ( !(cs_flags & CS_BLOCK_HAS_RESULT) ) { |
|
170 log_err_p(log, "Ciphersuite_PI2::validate: block has no security_result"); |
|
171 goto fail; |
|
172 } |
|
173 |
|
174 create_digest(bundle, block_list, block, db); |
|
175 digest_len = db.len(); |
|
176 memcpy(ps_digest, db.buf(), digest_len); |
|
177 |
|
178 log_debug_p(log, "Ciphersuite_PI2::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", |
|
179 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], |
|
180 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]); |
|
181 |
|
182 // get pieces from results -- should be just the signature |
|
183 buf = locals->security_result().buf(); |
|
184 len = locals->security_result().len(); |
|
185 |
|
186 log_debug_p(log, "Ciphersuite_PI2::validate() security result, len = %zu", len); |
|
187 while ( len > 0 ) { |
|
188 u_char item_type = *buf++; |
|
189 --len; |
|
190 sdnv_len = SDNV::decode(buf, len, &field_length); |
|
191 buf += sdnv_len; |
|
192 len -= sdnv_len; |
|
193 |
|
194 switch ( item_type ) { |
|
195 case CS_signature_field: |
|
196 { |
|
197 log_debug_p(log, "Ciphersuite_PI2::validate() CS_signature_field item, len %llu", U64FMT(field_length)); |
|
198 |
|
199 err = KeySteward::verify(bundle, buf, field_length, ps_digest, digest_len); |
|
200 if ( err == 0 ) { |
|
201 log_debug_p(log, "Ciphersuite_PI2::validate() -- KeySteward::verify() returned %d", err); |
|
202 locals->set_proc_flag(CS_BLOCK_PASSED_VALIDATION | CS_BLOCK_COMPLETED_DO_NOT_FORWARD); |
|
203 } else { |
|
204 log_err_p(log, "Ciphersuite_PI2::validate: CS_signature_field validation failed"); |
|
205 goto fail; |
|
206 } |
|
207 |
|
208 } |
|
209 break; |
|
210 |
|
211 default: // deal with improper items |
|
212 log_err_p(log, "Ciphersuite_PI2::validate: unexpected item type %d in security_result", item_type); |
|
213 goto fail; |
|
214 } |
|
215 buf += field_length; |
|
216 len -= field_length; |
|
217 } |
|
218 } else |
|
219 locals->set_proc_flag(CS_BLOCK_DID_NOT_FAIL); // not for here so we didn't check this block |
|
220 |
|
221 log_debug_p(log, "Ciphersuite_PI2::validate() done"); |
|
222 |
|
223 return true; |
|
224 |
|
225 |
|
226 |
|
227 fail: |
|
228 locals->set_proc_flag(CS_BLOCK_FAILED_VALIDATION | CS_BLOCK_COMPLETED_DO_NOT_FORWARD); |
|
229 *deletion_reason = BundleProtocol::REASON_SECURITY_FAILED; |
|
230 return false; |
|
231 } |
|
232 |
|
233 //---------------------------------------------------------------------- |
|
234 int |
|
235 Ciphersuite_PI2::prepare(const Bundle* bundle, |
|
236 BlockInfoVec* xmit_blocks, |
|
237 const BlockInfo* source, |
|
238 const LinkRef& link, |
|
239 list_owner_t list) |
|
240 { |
|
241 (void)bundle; |
|
242 (void)link; |
|
243 |
|
244 int result = BP_FAIL; |
|
245 u_int16_t cs_flags = 0; |
|
246 BP_Local_CS* locals = NULL; |
|
247 BP_Local_CS* source_locals = NULL; |
|
248 EndpointID local_eid = BundleDaemon::instance()->local_eid(); |
|
249 BundleDaemon* bd = BundleDaemon::instance(); |
|
250 |
|
251 //XXXpl - fix this test |
|
252 if ( (source != NULL) && |
|
253 (dynamic_cast<BP_Local_CS*>(source->locals())->security_dest() == bd->local_eid().data()) ) { |
|
254 log_debug_p(log, "Ciphersuite_PI2::prepare() - not being forwarded"); |
|
255 return BP_SUCCESS; //it was for us so don't forward |
|
256 } |
|
257 |
|
258 BlockInfo bi = BlockInfo(BundleProtocol::find_processor(BundleProtocol::PAYLOAD_SECURITY_BLOCK), source); // NULL source is OK here |
|
259 |
|
260 // If this is a received block then there's not a lot to do yet. |
|
261 // We copy some parameters - the main work is done in generate(). |
|
262 // Insertion is at the end of the list, which means that |
|
263 // it will be in the same position as received |
|
264 if ( list == BlockInfo::LIST_RECEIVED ) { |
|
265 |
|
266 if ( Ciphersuite::destination_is_local_node(bundle, source) ) |
|
267 return BP_SUCCESS; //don't forward if it's for here |
|
268 |
|
269 CS_FAIL_IF_NULL(source); |
|
270 xmit_blocks->push_back(bi); |
|
271 BlockInfo* bp = &(xmit_blocks->back()); |
|
272 CS_FAIL_IF_NULL(bp); |
|
273 bp->set_eid_list(source->eid_list()); |
|
274 log_debug_p(log, "Ciphersuite_PI2::prepare() - forward received block len %u eid_list_count %zu new count %zu", |
|
275 source->full_length(), source->eid_list().size(), bp->eid_list().size()); |
|
276 |
|
277 CS_FAIL_IF_NULL( source->locals() ); // broken |
|
278 |
|
279 source_locals = dynamic_cast<BP_Local_CS*>(source->locals()); |
|
280 CS_FAIL_IF_NULL(source_locals); // also broken |
|
281 bp->set_locals(new BP_Local_CS); |
|
282 locals = dynamic_cast<BP_Local_CS*>(bp->locals()); |
|
283 CS_FAIL_IF_NULL(locals); |
|
284 locals->set_owner_cs_num(CSNUM_PI2); |
|
285 cs_flags = source_locals->cs_flags(); |
|
286 locals->set_list_owner(BlockInfo::LIST_RECEIVED); |
|
287 locals->set_correlator(source_locals->correlator()); |
|
288 bp->writable_contents()->reserve(source->full_length()); |
|
289 bp->writable_contents()->set_len(0); |
|
290 |
|
291 // copy security-src and -dest if they exist |
|
292 if ( source_locals->cs_flags() & CS_BLOCK_HAS_SOURCE ) { |
|
293 CS_FAIL_IF(source_locals->security_src().length() == 0 ); |
|
294 log_debug_p(log, "Ciphersuite_PI2::prepare() add security_src EID"); |
|
295 cs_flags |= CS_BLOCK_HAS_SOURCE; |
|
296 locals->set_security_src(source_locals->security_src()); |
|
297 } |
|
298 |
|
299 if ( source_locals->cs_flags() & CS_BLOCK_HAS_DEST ) { |
|
300 CS_FAIL_IF(source_locals->security_dest().length() == 0 ); |
|
301 log_debug_p(log, "Ciphersuite_PI2::prepare() add security_dest EID"); |
|
302 cs_flags |= CS_BLOCK_HAS_DEST; |
|
303 locals->set_security_dest(source_locals->security_dest()); |
|
304 } |
|
305 locals->set_cs_flags(cs_flags); |
|
306 log_debug_p(log, "Ciphersuite_PI2::prepare() - inserted block eid_list_count %zu", |
|
307 bp->eid_list().size()); |
|
308 result = BP_SUCCESS; |
|
309 return result; |
|
310 } else { |
|
311 |
|
312 // initialize the block |
|
313 log_debug_p(log, "Ciphersuite_PI2::prepare() - add new block (or API block etc)"); |
|
314 bi.set_locals(new BP_Local_CS); |
|
315 CS_FAIL_IF_NULL(bi.locals()); |
|
316 locals = dynamic_cast<BP_Local_CS*>(bi.locals()); |
|
317 CS_FAIL_IF_NULL(locals); |
|
318 locals->set_owner_cs_num(CSNUM_PI2); |
|
319 locals->set_list_owner(list); |
|
320 |
|
321 // if there is a security-src and/or -dest, use it -- might be specified by API |
|
322 if ( source != NULL && source->locals() != NULL) { |
|
323 locals->set_security_src(dynamic_cast<BP_Local_CS*>(source->locals())->security_src()); |
|
324 locals->set_security_dest(dynamic_cast<BP_Local_CS*>(source->locals())->security_dest()); |
|
325 } |
|
326 |
|
327 log_debug_p(log, "Ciphersuite_PI2::prepare() local_eid %s bundle->source_ %s", local_eid.c_str(), bundle->source().c_str()); |
|
328 // if not, and we didn't create the bundle, specify ourselves as sec-src |
|
329 if ( (locals->security_src().length() == 0) && (local_eid != bundle->source())) |
|
330 locals->set_security_src(local_eid.str()); |
|
331 |
|
332 // if we now have one, add it to list, etc |
|
333 if ( locals->security_src().length() > 0 ) { |
|
334 log_debug_p(log, "Ciphersuite_PI2::prepare() add security_src EID %s", locals->security_src().c_str()); |
|
335 cs_flags |= CS_BLOCK_HAS_SOURCE; |
|
336 bi.add_eid(locals->security_src()); |
|
337 } |
|
338 |
|
339 if ( locals->security_dest().length() > 0 ) { |
|
340 log_debug_p(log, "Ciphersuite_PI2::prepare() add security_dest EID %s", locals->security_dest().c_str()); |
|
341 cs_flags |= CS_BLOCK_HAS_DEST; |
|
342 bi.add_eid(locals->security_dest()); |
|
343 } |
|
344 |
|
345 locals->set_cs_flags(cs_flags); |
|
346 |
|
347 // We should already have the primary block in the list. |
|
348 // We'll insert this after the primary and any BA blocks |
|
349 // and before everything else |
|
350 if ( xmit_blocks->size() > 0 ) { |
|
351 BlockInfoVec::iterator iter = xmit_blocks->begin(); |
|
352 |
|
353 while ( iter != xmit_blocks->end()) { |
|
354 switch (iter->type()) { |
|
355 case BundleProtocol::PRIMARY_BLOCK: |
|
356 case BundleProtocol::BUNDLE_AUTHENTICATION_BLOCK: |
|
357 ++iter; |
|
358 continue; |
|
359 |
|
360 default: |
|
361 break; |
|
362 } |
|
363 xmit_blocks->insert(iter, bi); |
|
364 break; |
|
365 } |
|
366 } else { |
|
367 // it's weird if there are no other blocks but, oh well ... |
|
368 xmit_blocks->push_back(bi); |
|
369 } |
|
370 } |
|
371 |
|
372 result = BP_SUCCESS; |
|
373 return result; |
|
374 |
|
375 fail: |
|
376 if ( locals != NULL ) |
|
377 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND); |
|
378 return BP_FAIL; |
|
379 } |
|
380 |
|
381 //---------------------------------------------------------------------- |
|
382 int |
|
383 Ciphersuite_PI2::generate(const Bundle* bundle, |
|
384 BlockInfoVec* xmit_blocks, |
|
385 BlockInfo* block, |
|
386 const LinkRef& link, |
|
387 bool last) |
|
388 { |
|
389 (void)bundle; |
|
390 (void)link; |
|
391 (void)xmit_blocks; |
|
392 |
|
393 int result = BP_FAIL; |
|
394 size_t sig_len = 0; |
|
395 size_t res_len = 0; |
|
396 size_t length = 0; |
|
397 size_t param_len = 0; |
|
398 u_char fragment_item[24]; // 24 is enough for 2 max-sized SDNVs and type and length |
|
399 u_int16_t cs_flags = 0; |
|
400 BP_Local_CS* locals = dynamic_cast<BP_Local_CS*>(block->locals()); |
|
401 u_char* ptr; |
|
402 size_t temp; |
|
403 size_t rem; |
|
404 DataBuffer encrypted_key; |
|
405 EVP_MD_CTX ctx; |
|
406 size_t digest_len; |
|
407 u_char* buf = NULL; |
|
408 |
|
409 int sdnv_len = 0; // use an int to handle -1 return values |
|
410 int err = 0; |
|
411 int len = 0; |
|
412 BlockInfo::DataBuffer* contents = NULL; |
|
413 LocalBuffer* params = NULL; |
|
414 |
|
415 log_debug_p(log, "Ciphersuite_PI2::generate() %p", block); |
|
416 CS_FAIL_IF_NULL(locals); |
|
417 cs_flags = locals->cs_flags(); // get flags from prepare() |
|
418 // if this is a received block then it's easy |
|
419 if ( locals->list_owner() == BlockInfo::LIST_RECEIVED ) |
|
420 { |
|
421 // generate the preamble and copy the data. |
|
422 size_t length = block->source()->data_length(); |
|
423 |
|
424 generate_preamble(xmit_blocks, |
|
425 block, |
|
426 BundleProtocol::PAYLOAD_SECURITY_BLOCK, |
|
427 BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR | |
|
428 (last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0), |
|
429 length); |
|
430 |
|
431 BlockInfo::DataBuffer* contents = block->writable_contents(); |
|
432 contents->reserve(block->data_offset() + length); |
|
433 contents->set_len(block->data_offset() + length); |
|
434 memcpy(contents->buf() + block->data_offset(), |
|
435 block->source()->data(), length); |
|
436 log_debug_p(log, "Ciphersuite_PI2::generate() %p done", block); |
|
437 return BP_SUCCESS; |
|
438 } /************** forwarding done **************/ |
|
439 |
|
440 |
|
441 /* params field will contain |
|
442 - fragment offset and length, if a fragment-bundle, plus type and length |
|
443 */ |
|
444 |
|
445 params = locals->writable_security_params(); |
|
446 |
|
447 param_len = 0; |
|
448 |
|
449 if ( bundle->is_fragment() ) { |
|
450 log_debug_p(log, "Ciphersuite_PI2::generate() bundle is fragment"); |
|
451 ptr = &fragment_item[2]; |
|
452 rem = sizeof(fragment_item) - 2; |
|
453 temp = SDNV::encode(bundle->frag_offset(), ptr, rem); |
|
454 ptr += temp; |
|
455 rem -= temp; |
|
456 temp += SDNV::encode(bundle->payload().length(), ptr, rem); |
|
457 fragment_item[0] = CS_fragment_offset_and_length_field; |
|
458 fragment_item[1] = temp; //guaranteed to fit as a "one-byte SDNV" |
|
459 param_len += 2 + temp; |
|
460 |
|
461 } |
|
462 |
|
463 if ( param_len > 0 ) { |
|
464 cs_flags |= CS_BLOCK_HAS_PARAMS; |
|
465 params->reserve(param_len); |
|
466 params->set_len(param_len); |
|
467 log_debug_p(log, "Ciphersuite_PI2::generate() security params, len = %zu", param_len); |
|
468 |
|
469 ptr = params->buf(); |
|
470 |
|
471 if ( bundle->is_fragment() ) |
|
472 memcpy(ptr, fragment_item, 2 + temp); |
|
473 } |
|
474 |
|
475 // need to calculate the size of the security-result items, |
|
476 // and the total length of the combined field |
|
477 |
|
478 /* result field will contain |
|
479 - signed hash, plus type and length |
|
480 */ |
|
481 EVP_MD_CTX_init(&ctx); |
|
482 err = EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL); |
|
483 CS_FAIL_IF(err == 0); |
|
484 digest_len = EVP_MD_CTX_size(&ctx); |
|
485 EVP_MD_CTX_cleanup(&ctx); |
|
486 |
|
487 KeySteward::signature_length(bundle, NULL, link, digest_len, sig_len); |
|
488 |
|
489 res_len = 1 + SDNV::encoding_len(sig_len) + sig_len; |
|
490 |
|
491 // First we need to work out the lengths and create the preamble |
|
492 cs_flags |= CS_BLOCK_HAS_RESULT; |
|
493 locals->set_cs_flags(cs_flags); |
|
494 length = 0; |
|
495 length += SDNV::encoding_len(CSNUM_PI2); |
|
496 length += SDNV::encoding_len(locals->cs_flags()); |
|
497 |
|
498 param_len = locals->security_params().len(); |
|
499 length += SDNV::encoding_len(param_len) + param_len; |
|
500 locals->set_security_result_offset(length); //remember this for finalize() |
|
501 length += SDNV::encoding_len(res_len) + res_len; |
|
502 |
|
503 contents = block->writable_contents(); |
|
504 |
|
505 generate_preamble(xmit_blocks, |
|
506 block, |
|
507 BundleProtocol::PAYLOAD_SECURITY_BLOCK, |
|
508 BundleProtocol::BLOCK_FLAG_DISCARD_BUNDLE_ONERROR | |
|
509 (last ? BundleProtocol::BLOCK_FLAG_LAST_BLOCK : 0), |
|
510 length); |
|
511 |
|
512 |
|
513 log_debug_p(log, "Ciphersuite_PI2::generate() preamble len %u block len %zu", block->data_offset(), length); |
|
514 contents->reserve(block->data_offset() + length); |
|
515 contents->set_len(block->data_offset() + length); |
|
516 buf = block->writable_contents()->buf() + block->data_offset(); |
|
517 len = length; |
|
518 |
|
519 // Assemble data into block contents. |
|
520 |
|
521 // ciphersuite number and flags |
|
522 sdnv_len = SDNV::encode(locals->owner_cs_num(), buf, len); |
|
523 CS_FAIL_IF(sdnv_len <= 0); |
|
524 buf += sdnv_len; |
|
525 len -= sdnv_len; |
|
526 |
|
527 sdnv_len = SDNV::encode(locals->cs_flags(), buf, len); |
|
528 CS_FAIL_IF(sdnv_len <= 0); |
|
529 buf += sdnv_len; |
|
530 len -= sdnv_len; |
|
531 |
|
532 if ( param_len > 0 ) { |
|
533 // length of params |
|
534 sdnv_len = SDNV::encode(param_len, buf, len); |
|
535 CS_FAIL_IF(sdnv_len <= 0); |
|
536 buf += sdnv_len; |
|
537 len -= sdnv_len; |
|
538 |
|
539 // params data |
|
540 memcpy(buf, locals->security_params().buf(), param_len ); |
|
541 buf += param_len; |
|
542 len -= param_len; |
|
543 } |
|
544 |
|
545 // length of result -- we have to put this in now |
|
546 sdnv_len = SDNV::encode(res_len, buf, len); |
|
547 |
|
548 |
|
549 // no, no ! Not yet !! |
|
550 // ASSERT( len == 0 ); |
|
551 log_debug_p(log, "Ciphersuite_PI2::generate() done"); |
|
552 |
|
553 |
|
554 result = BP_SUCCESS; |
|
555 return result; |
|
556 |
|
557 fail: |
|
558 if ( locals != NULL ) |
|
559 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND); |
|
560 return BP_FAIL; |
|
561 } |
|
562 |
|
563 //---------------------------------------------------------------------- |
|
564 int |
|
565 Ciphersuite_PI2::finalize(const Bundle* bundle, |
|
566 BlockInfoVec* xmit_blocks, |
|
567 BlockInfo* block, |
|
568 const LinkRef& link) |
|
569 { |
|
570 (void)link; |
|
571 int result = BP_FAIL; |
|
572 size_t len; |
|
573 size_t sdnv_len; |
|
574 size_t res_len; |
|
575 u_char* buf; |
|
576 BP_Local_CS* locals = NULL; |
|
577 std::vector<u_int64_t> correlator_list; |
|
578 std::vector<u_int64_t>::iterator cl_iter; |
|
579 EndpointID local_eid = BundleDaemon::instance()->local_eid(); |
|
580 BlockInfoVec::iterator iter; |
|
581 DataBuffer db_digest; |
|
582 DataBuffer db_signed; |
|
583 int err = 0; |
|
584 BlockInfo::DataBuffer* contents = NULL; |
|
585 LocalBuffer* digest_result = NULL; |
|
586 size_t sig_len = 0; |
|
587 |
|
588 log_debug_p(log, "Ciphersuite_PI2::finalize()"); |
|
589 locals = dynamic_cast<BP_Local_CS*>(block->locals()); |
|
590 CS_FAIL_IF_NULL(locals); |
|
591 |
|
592 // if this is a received block then we're done |
|
593 if ( locals->list_owner() == BlockInfo::LIST_RECEIVED ) |
|
594 return BP_SUCCESS; |
|
595 |
|
596 create_digest(bundle, xmit_blocks, block, db_digest); |
|
597 |
|
598 err = KeySteward::sign(bundle, NULL, link, db_digest, db_signed); |
|
599 CS_FAIL_IF(err != 0); |
|
600 sig_len = db_signed.len(); |
|
601 res_len = 1 + SDNV::encoding_len(sig_len) + sig_len; |
|
602 |
|
603 // build the result item |
|
604 digest_result = locals->writable_security_result(); |
|
605 digest_result->reserve(res_len); |
|
606 digest_result->set_len(res_len); |
|
607 |
|
608 buf = digest_result->buf(); |
|
609 len = digest_result->len(); |
|
610 |
|
611 *buf++ = Ciphersuite::CS_signature_field; // item type |
|
612 len--; |
|
613 |
|
614 sdnv_len = SDNV::encode(sig_len, buf, len); |
|
615 buf += sdnv_len; |
|
616 len -= sdnv_len; |
|
617 |
|
618 memcpy(buf, db_signed.buf(), sig_len); |
|
619 |
|
620 |
|
621 // now put the result item into the block contents |
|
622 contents = block->writable_contents(); |
|
623 buf = contents->buf(); |
|
624 len = contents->len(); |
|
625 buf += block->data_offset(); // we need to add data_offset as well, |
|
626 len -= block->data_offset(); // since we're pointing at the whole buffer |
|
627 |
|
628 buf += locals->security_result_offset(); //and this offset is just within |
|
629 len -= locals->security_result_offset(); //the data portion of the buffer |
|
630 sdnv_len = SDNV::len(buf); // size of result-length field |
|
631 buf += sdnv_len; // step over that length field |
|
632 len -= sdnv_len; |
|
633 memcpy(buf, digest_result->buf(), digest_result->len()); |
|
634 log_debug_p(log, "Ciphersuite_PI2::finalize() done"); |
|
635 |
|
636 result = BP_SUCCESS; |
|
637 return result; |
|
638 |
|
639 fail: |
|
640 if ( locals != NULL ) |
|
641 locals->set_proc_flag(CS_BLOCK_PROCESSING_FAILED_DO_NOT_SEND); |
|
642 return BP_FAIL; |
|
643 } |
|
644 |
|
645 //---------------------------------------------------------------------- |
|
646 void |
|
647 Ciphersuite_PI2::digest(const Bundle* bundle, |
|
648 const BlockInfo* caller_block, |
|
649 const BlockInfo* target_block, |
|
650 const void* buf, |
|
651 size_t len, |
|
652 OpaqueContext* r) |
|
653 { |
|
654 (void)bundle; |
|
655 (void)caller_block; |
|
656 (void)target_block; |
|
657 log_debug_p(log, "Ciphersuite_PI2::digest() %zu bytes", len); |
|
658 |
|
659 EVP_MD_CTX* pctx = reinterpret_cast<EVP_MD_CTX*>(r); |
|
660 |
|
661 EVP_DigestUpdate( pctx, buf, len ); |
|
662 } |
|
663 |
|
664 //---------------------------------------------------------------------- |
|
665 void |
|
666 Ciphersuite_PI2::create_digest(const Bundle* bundle, |
|
667 BlockInfoVec* block_list, |
|
668 BlockInfo* block, |
|
669 DataBuffer& db) |
|
670 { |
|
671 size_t len; |
|
672 size_t sdnv_len; |
|
673 EVP_MD_CTX ctx; |
|
674 OpaqueContext* r = reinterpret_cast<OpaqueContext*>(&ctx); |
|
675 char* dict; |
|
676 u_int32_t offset; |
|
677 u_char* buf; |
|
678 const char* ptr; |
|
679 size_t plen; |
|
680 size_t digest_len; |
|
681 u_char ps_digest[EVP_MAX_MD_SIZE]; |
|
682 u_int32_t rlen = 0; |
|
683 u_int32_t header_len; |
|
684 u_char c; |
|
685 u_int64_t eid_ref_count = 0LLU; |
|
686 BP_Local_CS* locals = NULL; |
|
687 BP_Local_CS* target_locals = NULL; |
|
688 u_int64_t target_flags; |
|
689 u_int64_t flags_save; |
|
690 u_int64_t mask = 0LLU; /// specify mask for flags |
|
691 u_int64_t mask_primary = 0LLU; /// mask for primary-block flags |
|
692 u_int64_t target_content_length; |
|
693 u_int64_t correlator; |
|
694 u_int64_t cs_flags; |
|
695 u_int64_t suite_num; |
|
696 std::vector<u_int64_t> correlator_list; |
|
697 std::vector<u_int64_t>::iterator cl_iter; |
|
698 EndpointID local_eid = BundleDaemon::instance()->local_eid(); |
|
699 BlockInfoVec::iterator iter; |
|
700 int err = 0; |
|
701 PrimaryBlock_ex primary; |
|
702 |
|
703 log_debug_p(log, "Ciphersuite_PI2::create_digest()"); |
|
704 locals = dynamic_cast<BP_Local_CS*>(block->locals()); |
|
705 |
|
706 // prepare context |
|
707 EVP_MD_CTX_init(&ctx); |
|
708 err = EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL); |
|
709 digest_len = EVP_MD_CTX_size(&ctx); |
|
710 // XXX-pl check error -- zero is failure |
|
711 |
|
712 // Walk the list and process each of the blocks. |
|
713 // We only digest PS, C3 and the payload data, |
|
714 // all others are ignored |
|
715 |
|
716 // Note that we can only process PSBs and C3s that follow this block |
|
717 // as doing otherwise would mean that there would be a |
|
718 // correlator block preceding its parent |
|
719 |
|
720 // There can also be tunnelling issues, depending upon the |
|
721 // exact sequencing of blocks. It seems best to add C blocks |
|
722 // as early as possible in order to mitigate this problem. |
|
723 // That has its own drawbacks unfortunately |
|
724 |
|
725 header_len = 1 //version |
|
726 + 8 //flags SDNV |
|
727 + 4 //header length itself |
|
728 + 4 //destination eid length |
|
729 + 4 //source eid length |
|
730 + 4 //report-to eid length |
|
731 + 8 //creation SDNV #1 |
|
732 + 8 //creation SDNV #2 |
|
733 + 8; //lifetime SDNV |
|
734 |
|
735 if ( bundle->is_fragment() ) |
|
736 header_len += 8 //fragment offset SDNV |
|
737 + 8; //total-length SDNV |
|
738 |
|
739 // do stuff for primary, and ignore it during the walk |
|
740 |
|
741 iter = block_list->begin(); //primary |
|
742 |
|
743 err = read_primary(bundle, &*iter, primary, &dict); |
|
744 |
|
745 header_len += strlen(dict + primary.dest_scheme_offset); |
|
746 header_len += strlen(dict + primary.dest_ssp_offset); |
|
747 header_len += strlen(dict + primary.source_scheme_offset); |
|
748 header_len += strlen(dict + primary.source_ssp_offset); |
|
749 header_len += strlen(dict + primary.replyto_scheme_offset); |
|
750 header_len += strlen(dict + primary.replyto_ssp_offset); |
|
751 log_debug_p(log, "Ciphersuite_PI2::create_digest() header_len %u", header_len); |
|
752 |
|
753 |
|
754 // Now start the actual digest process |
|
755 digest( bundle, block, &*iter, &primary.version, 1, r); //version |
|
756 |
|
757 primary.processing_flags &= mask_primary; |
|
758 target_flags = htonq(primary.processing_flags); |
|
759 digest( bundle, block, &*iter, &primary.processing_flags, sizeof(primary.processing_flags), r); |
|
760 |
|
761 header_len = htonl(header_len); |
|
762 digest( bundle, block, &*iter, &header_len, sizeof(header_len), r); |
|
763 |
|
764 |
|
765 offset = strlen(dict + primary.dest_scheme_offset) + strlen(dict + primary.dest_ssp_offset); // Note:- "offset" is 4 bytes, not 8 |
|
766 offset = htonl(offset); |
|
767 digest( bundle, block, &*iter, &offset, sizeof(offset), r); |
|
768 digest( bundle, block, &*iter, dict + primary.dest_scheme_offset, strlen(dict + primary.dest_scheme_offset), r); |
|
769 digest( bundle, block, &*iter, dict + primary.dest_ssp_offset, strlen(dict + primary.dest_ssp_offset), r); |
|
770 |
|
771 offset = strlen(dict + primary.source_scheme_offset) + strlen(dict + primary.source_ssp_offset); |
|
772 offset = htonl(offset); |
|
773 digest( bundle, block, &*iter, &offset, sizeof(offset), r); |
|
774 digest( bundle, block, &*iter, dict + primary.source_scheme_offset, strlen(dict + primary.source_scheme_offset), r); |
|
775 digest( bundle, block, &*iter, dict + primary.source_ssp_offset, strlen(dict + primary.source_ssp_offset), r); |
|
776 |
|
777 offset = strlen(dict + primary.replyto_scheme_offset) + strlen(dict + primary.replyto_ssp_offset); |
|
778 offset = htonl(offset); |
|
779 digest( bundle, block, &*iter, &offset, sizeof(offset), r); |
|
780 digest( bundle, block, &*iter, dict + primary.replyto_scheme_offset, strlen(dict + primary.replyto_scheme_offset), r); |
|
781 digest( bundle, block, &*iter, dict + primary.replyto_ssp_offset, strlen(dict + primary.replyto_ssp_offset), r); |
|
782 |
|
783 // two SDNVs for creation timestamp, one for lifetime |
|
784 primary.creation_time = htonq(primary.creation_time); |
|
785 digest( bundle, block, &*iter, &primary.creation_time, sizeof(primary.creation_time), r); |
|
786 primary.creation_sequence = htonq(primary.creation_sequence); |
|
787 digest( bundle, block, &*iter, &primary.creation_sequence, sizeof(primary.creation_sequence), r); |
|
788 primary.lifetime = htonq(primary.lifetime); |
|
789 digest( bundle, block, &*iter, &primary.lifetime, sizeof(primary.lifetime), r); |
|
790 |
|
791 if ( bundle->is_fragment() ) { |
|
792 primary.fragment_offset = htonq(primary.fragment_offset); |
|
793 digest( bundle, block, &*iter, &primary.fragment_offset, sizeof(primary.fragment_offset), r); |
|
794 primary.original_length = htonq(primary.original_length); |
|
795 digest( bundle, block, &*iter, &primary.original_length, sizeof(primary.original_length), r); |
|
796 } |
|
797 |
|
798 ++iter; //primary is done now |
|
799 |
|
800 log_debug_p(log, "Ciphersuite_PI2::create_digest() walk block list"); |
|
801 for ( ; |
|
802 iter != block_list->end(); |
|
803 ++iter) |
|
804 { |
|
805 // Advance the iterator to our current position. |
|
806 // While we do it, we also remember the correlator values |
|
807 // of any PSBs or C3 blocks we encounter. |
|
808 // We do this to avoid processing any related correlated blocks |
|
809 // Note that we include the current block in the test below |
|
810 // in order to prevent encapsulating it !! |
|
811 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals()); |
|
812 if ( (&*iter) <= block ) { |
|
813 if ( iter->type() == BundleProtocol::PAYLOAD_SECURITY_BLOCK || |
|
814 (iter->type() == BundleProtocol::CONFIDENTIALITY_BLOCK && |
|
815 target_locals->owner_cs_num() == Ciphersuite_PC3::CSNUM_PC3 ) ) { |
|
816 if ( target_locals->cs_flags() & CS_BLOCK_HAS_CORRELATOR) { |
|
817 //add correlator to exclude-list |
|
818 correlator_list.push_back(target_locals->correlator()); |
|
819 } |
|
820 } |
|
821 continue; |
|
822 } |
|
823 |
|
824 |
|
825 switch ( iter->type() ) { |
|
826 case BundleProtocol::PAYLOAD_SECURITY_BLOCK: |
|
827 case BundleProtocol::CONFIDENTIALITY_BLOCK: |
|
828 { |
|
829 |
|
830 log_debug_p(log, "Ciphersuite_PI2::create_digest() PS or C block type %d cs_num %d", |
|
831 iter->type(), target_locals->owner_cs_num()); |
|
832 if ( iter->type() == BundleProtocol::PAYLOAD_SECURITY_BLOCK && |
|
833 target_locals->owner_cs_num() != Ciphersuite_PC3::CSNUM_PC3 ) |
|
834 continue; // only digest C3 |
|
835 |
|
836 |
|
837 // see if there's a correlator and, if there is, |
|
838 // if this is a secondary block. Only process a secondary |
|
839 // if we also did its primary |
|
840 bool skip_target = false; |
|
841 target_locals = dynamic_cast<BP_Local_CS*>(iter->locals()); |
|
842 log_debug_p(log, "Ciphersuite_PI2::create_digest() target_locals->cs_flags 0x%hx", target_locals->cs_flags()); |
|
843 log_debug_p(log, "Ciphersuite_PI2::create_digest() target_locals->correlator() 0x%llx", U64FMT(target_locals->correlator())); |
|
844 if ( target_locals->cs_flags() & CS_BLOCK_HAS_CORRELATOR) { |
|
845 correlator = target_locals->correlator(); |
|
846 for ( cl_iter = correlator_list.begin(); |
|
847 cl_iter < correlator_list.end(); |
|
848 ++cl_iter) { |
|
849 if ( correlator == *cl_iter) { |
|
850 skip_target = true; |
|
851 break; //break from for-loop |
|
852 } |
|
853 } |
|
854 if ( skip_target ) |
|
855 break; //break from switch, continue for "for" loop |
|
856 |
|
857 } |
|
858 |
|
859 log_debug_p(log, "Ciphersuite_PI2::create_digest() digest this block, len %u eid_list().size() %zu", |
|
860 iter->full_length(), iter->eid_list().size()); |
|
861 // Either it has no correlator, or it wasn't in the list. |
|
862 // So we will process it in the digest |
|
863 |
|
864 /********** start preamble processing **********/ |
|
865 buf = iter->contents().buf(); |
|
866 len = iter->full_length(); |
|
867 |
|
868 |
|
869 // Process block type |
|
870 c = *buf++; |
|
871 len--; |
|
872 digest( bundle, block, &*iter, &c, 1, r); |
|
873 |
|
874 // Process flags |
|
875 sdnv_len = SDNV::decode( buf, len, &target_flags); |
|
876 buf += sdnv_len; |
|
877 len -= sdnv_len; |
|
878 |
|
879 flags_save = target_flags; |
|
880 target_flags &= mask; |
|
881 target_flags = htonq(target_flags); |
|
882 digest( bundle, block, &*iter, &target_flags, sizeof(target_flags), r); |
|
883 |
|
884 // EID list is next, starting with the count although we don't digest it |
|
885 if ( flags_save & BundleProtocol::BLOCK_FLAG_EID_REFS ) { |
|
886 sdnv_len = SDNV::decode(buf, len, &eid_ref_count); |
|
887 buf += sdnv_len; |
|
888 len -= sdnv_len; |
|
889 log_debug_p(log, "Ciphersuite_PI2::create_digest() eid_ref_count %llu", U64FMT(eid_ref_count)); |
|
890 |
|
891 // each ref is a pair of SDNVs, so process 2 * eid_ref_count text pieces |
|
892 if ( eid_ref_count > 0 ) { |
|
893 for ( u_int32_t i = 0; i < (2 * eid_ref_count); i++ ) { |
|
894 sdnv_len = SDNV::decode(buf, len, &offset); |
|
895 buf += sdnv_len; |
|
896 len -= sdnv_len; |
|
897 |
|
898 ptr = dict + offset; //point at item in dictionary |
|
899 plen = strlen(ptr); // length *without* NULL-terminator |
|
900 digest( bundle, block, &*iter, ptr, plen, r); |
|
901 } |
|
902 } |
|
903 } |
|
904 |
|
905 // Process data length |
|
906 sdnv_len = SDNV::decode(buf, len, &target_content_length); |
|
907 buf += sdnv_len; |
|
908 len -= sdnv_len; |
|
909 |
|
910 target_content_length = htonq(target_content_length); |
|
911 digest( bundle, block, &*iter, &target_content_length, sizeof(target_content_length), r); |
|
912 |
|
913 // start of data is where to start main digest |
|
914 offset = buf - iter->contents().buf(); |
|
915 ASSERT(offset == iter->data_offset()); |
|
916 /********** end of preamble processing **********/ |
|
917 |
|
918 |
|
919 /********** start content processing **********/ |
|
920 |
|
921 // if it's the current block, we have to exclude security-result data. |
|
922 // Note that security-result-length *is* included |
|
923 if ( (&*iter) == block ) { |
|
924 |
|
925 // ciphersuite number and flags |
|
926 sdnv_len = SDNV::decode(buf, |
|
927 len, |
|
928 &suite_num); |
|
929 buf += sdnv_len; |
|
930 len -= sdnv_len; |
|
931 |
|
932 sdnv_len = SDNV::decode(buf, |
|
933 len, |
|
934 &cs_flags); |
|
935 buf += sdnv_len; |
|
936 len -= sdnv_len; |
|
937 |
|
938 if ( cs_flags & CS_BLOCK_HAS_RESULT ) { |
|
939 // if there's a security-result we have to ease up to it |
|
940 if ( cs_flags & CS_BLOCK_HAS_CORRELATOR ) |
|
941 buf += SDNV::len(buf); //step over correlator |
|
942 |
|
943 if ( cs_flags & CS_BLOCK_HAS_PARAMS ) |
|
944 buf += SDNV::len(buf); //step over params |
|
945 |
|
946 if ( cs_flags & CS_BLOCK_HAS_RESULT ) { |
|
947 sdnv_len = SDNV::decode(buf, len, &target_content_length); |
|
948 buf += sdnv_len; |
|
949 len -= sdnv_len; |
|
950 buf += SDNV::len(buf); //step over security-result-length field |
|
951 } |
|
952 |
|
953 len = buf - iter->contents().buf(); //this is the length to use |
|
954 } |
|
955 // now set buf back to the start of the content |
|
956 buf = iter->contents().buf(); |
|
957 } |
|
958 |
|
959 iter->owner()->process( Ciphersuite_PI2::digest, |
|
960 bundle, |
|
961 block, |
|
962 &*iter, |
|
963 offset, |
|
964 len, |
|
965 r); |
|
966 /********** end of content processing **********/ |
|
967 log_debug_p(log, "Ciphersuite_PI2::create_digest() digest done %p", &*iter); |
|
968 |
|
969 } |
|
970 break; //break from switch, continue for "for" loop |
|
971 |
|
972 case BundleProtocol::PAYLOAD_BLOCK: |
|
973 { |
|
974 |
|
975 /********** start preamble processing **********/ |
|
976 buf = iter->contents().buf(); |
|
977 len = iter->full_length(); |
|
978 |
|
979 |
|
980 // Process block type |
|
981 c = *buf++; |
|
982 len--; |
|
983 digest( bundle, block, &*iter, &c, 1, r); |
|
984 |
|
985 // Process flags |
|
986 sdnv_len = SDNV::decode( buf, len, &target_flags); |
|
987 buf += sdnv_len; |
|
988 len -= sdnv_len; |
|
989 |
|
990 flags_save = target_flags; |
|
991 target_flags &= mask; |
|
992 target_flags = htonq(target_flags); |
|
993 digest( bundle, block, &*iter, &target_flags, sizeof(target_flags), r); |
|
994 |
|
995 // EID list is next, starting with the count although we don't digest it |
|
996 if ( flags_save & BundleProtocol::BLOCK_FLAG_EID_REFS ) { |
|
997 sdnv_len = SDNV::decode(buf, len, &eid_ref_count); |
|
998 buf += sdnv_len; |
|
999 len -= sdnv_len; |
|
1000 |
|
1001 // each ref is a pair of SDNVs, so process 2 * eid_ref_count text pieces |
|
1002 if ( eid_ref_count > 0 ) { |
|
1003 for ( u_int32_t i = 0; i < (2 * eid_ref_count); i++ ) { |
|
1004 sdnv_len = SDNV::decode(buf, len, &offset); |
|
1005 buf += sdnv_len; |
|
1006 len -= sdnv_len; |
|
1007 |
|
1008 ptr = dict + offset; //point at item in dictionary |
|
1009 plen = strlen(ptr); // length *without* NULL-terminator |
|
1010 digest( bundle, block, &*iter, ptr, plen, r); |
|
1011 } |
|
1012 } |
|
1013 } |
|
1014 |
|
1015 // Process data length |
|
1016 sdnv_len = SDNV::decode(buf, len, &target_content_length); |
|
1017 buf += sdnv_len; |
|
1018 len -= sdnv_len; |
|
1019 |
|
1020 target_content_length = htonq(target_content_length); |
|
1021 digest( bundle, block, &*iter, &target_content_length, sizeof(target_content_length), r); |
|
1022 |
|
1023 // start of data is where to start main digest |
|
1024 offset = buf - iter->contents().buf(); |
|
1025 ASSERT(offset == iter->data_offset()); |
|
1026 /********** end of preamble processing **********/ |
|
1027 |
|
1028 /********** start content processing **********/ |
|
1029 |
|
1030 iter->owner()->process( Ciphersuite_PI2::digest, |
|
1031 bundle, |
|
1032 block, |
|
1033 &*iter, |
|
1034 offset, |
|
1035 len, |
|
1036 r); |
|
1037 /********** end of content processing **********/ |
|
1038 log_debug_p(log, "Ciphersuite_PI2::create_digest() PAYLOAD_BLOCK done"); |
|
1039 } |
|
1040 break; //break from switch, continue for "for" loop |
|
1041 |
|
1042 default: |
|
1043 continue; |
|
1044 |
|
1045 } // end of switch |
|
1046 } // end of loop-through-all-the-blocks |
|
1047 |
|
1048 |
|
1049 err = EVP_DigestFinal_ex(&ctx, ps_digest, &rlen); |
|
1050 // XXX-pl check error -- zero is failure |
|
1051 |
|
1052 log_debug_p(log, "Ciphersuite_PI2::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", |
|
1053 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], |
|
1054 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]); |
|
1055 |
|
1056 EVP_MD_CTX_cleanup(&ctx); |
|
1057 |
|
1058 db.reserve(digest_len); |
|
1059 db.set_len(digest_len); |
|
1060 memcpy(db.buf(), ps_digest, digest_len); |
|
1061 |
|
1062 log_debug_p(log, "Ciphersuite_PI2::create_digest() done"); |
|
1063 |
|
1064 } |
|
1065 |
|
1066 |
|
1067 //---------------------------------------------------------------------- |
|
1068 int |
|
1069 Ciphersuite_PI2::read_primary(const Bundle* bundle, |
|
1070 BlockInfo* block, |
|
1071 PrimaryBlock_ex& primary, |
|
1072 char** dict) |
|
1073 { |
|
1074 u_char* buf; |
|
1075 size_t len; |
|
1076 |
|
1077 size_t primary_len = block->full_length(); |
|
1078 |
|
1079 buf = block->writable_contents()->buf(); |
|
1080 len = block->writable_contents()->len(); |
|
1081 |
|
1082 ASSERT(primary_len == len); |
|
1083 |
|
1084 primary.version = *(u_int8_t*)buf; |
|
1085 buf += 1; |
|
1086 len -= 1; |
|
1087 |
|
1088 if (primary.version != BundleProtocol::CURRENT_VERSION) { |
|
1089 log_warn_p(log, "protocol version mismatch %d != %d", |
|
1090 primary.version, BundleProtocol::CURRENT_VERSION); |
|
1091 return -1; |
|
1092 } |
|
1093 |
|
1094 #define PBP_READ_SDNV(location) { \ |
|
1095 int sdnv_len = SDNV::decode(buf, len, location); \ |
|
1096 if (sdnv_len < 0) \ |
|
1097 goto tooshort; \ |
|
1098 buf += sdnv_len; \ |
|
1099 len -= sdnv_len; } |
|
1100 |
|
1101 // Grab the SDNVs representing the flags and the block length. |
|
1102 PBP_READ_SDNV(&primary.processing_flags); |
|
1103 PBP_READ_SDNV(&primary.block_length); |
|
1104 |
|
1105 log_debug_p(log, "parsed primary block: version %d length %u", |
|
1106 primary.version, block->data_length()); |
|
1107 |
|
1108 /* |
|
1109 * it may be that the ASSERT which follows is not appropriate because we're doing this |
|
1110 * on the outbound side and it seems that data_length() is the same as full_length(). |
|
1111 * But what's remaining should be the same as what is promised. |
|
1112 log_debug_p(log, "parsed primary block: version %d length %u full_length %u len remaining %zu", |
|
1113 primary.version, block->data_length(), block->full_length(), len); |
|
1114 // What remains in the buffer should now be equal to what the block-length |
|
1115 // field advertised. |
|
1116 ASSERT(len == block->data_length()); |
|
1117 */ |
|
1118 ASSERT(len == primary.block_length); |
|
1119 |
|
1120 // Read the various SDNVs up to the start of the dictionary. |
|
1121 PBP_READ_SDNV(&primary.dest_scheme_offset); |
|
1122 PBP_READ_SDNV(&primary.dest_ssp_offset); |
|
1123 PBP_READ_SDNV(&primary.source_scheme_offset); |
|
1124 PBP_READ_SDNV(&primary.source_ssp_offset); |
|
1125 PBP_READ_SDNV(&primary.replyto_scheme_offset); |
|
1126 PBP_READ_SDNV(&primary.replyto_ssp_offset); |
|
1127 PBP_READ_SDNV(&primary.custodian_scheme_offset); |
|
1128 PBP_READ_SDNV(&primary.custodian_ssp_offset); |
|
1129 PBP_READ_SDNV(&primary.creation_time); |
|
1130 PBP_READ_SDNV(&primary.creation_sequence); |
|
1131 PBP_READ_SDNV(&primary.lifetime); |
|
1132 PBP_READ_SDNV(&primary.dictionary_length); |
|
1133 *dict = reinterpret_cast<char*>(buf); |
|
1134 if (bundle->is_fragment()) { |
|
1135 PBP_READ_SDNV(&primary.fragment_offset); |
|
1136 PBP_READ_SDNV(&primary.original_length); |
|
1137 } |
|
1138 #undef PBP_READ_SDNV |
|
1139 return 0; |
|
1140 |
|
1141 tooshort: |
|
1142 return -1; |
|
1143 } |
|
1144 |
|
1145 |
|
1146 } // namespace dtn |
|
1147 |
|
1148 #endif /* BSP_ENABLED */ |