/** * Notifies the hipd about an anchor change in the hipfw * * @param entry the sadb entry for the outbound direction * @return 0 on success, -1 on error, 1 for inbound sadb entry */ int send_anchor_change_to_hipd(const struct hip_sa_entry *entry) { int err = 0; int hash_length = 0; long i = 0; unsigned char *anchor = NULL; struct hip_common *msg = NULL; struct hash_chain *hchain = NULL; struct hash_tree *htree = NULL; HIP_ASSERT(entry != NULL); HIP_ASSERT(entry->direction == HIP_SPI_DIRECTION_OUT); HIP_IFEL((hash_length = esp_prot_get_hash_length(entry->esp_prot_transform)) <= 0, -1, "error or tried to resolve UNUSED transform\n"); HIP_IFEL(!(msg = malloc(HIP_MAX_PACKET)), -1, "failed to allocate memory\n"); hip_msg_init(msg); HIP_IFEL(hip_build_user_hdr(msg, HIP_MSG_ANCHOR_CHANGE, 0), -1, "build hdr failed\n"); HIP_DEBUG_HIT("src_hit", &entry->inner_src_addr); HIP_IFEL(hip_build_param_contents(msg, &entry->inner_src_addr, HIP_PARAM_HIT, sizeof(struct in6_addr)), -1, "build param contents failed\n"); HIP_DEBUG_HIT("dst_hit", &entry->inner_dst_addr); HIP_IFEL(hip_build_param_contents(msg, &entry->inner_dst_addr, HIP_PARAM_HIT, sizeof(struct in6_addr)), -1, "build param contents failed\n"); HIP_DEBUG("direction: %i\n", entry->direction); HIP_IFEL(hip_build_param_contents(msg, &entry->direction, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); HIP_DEBUG("esp_prot_transform: %u\n", entry->esp_prot_transform); HIP_IFEL(hip_build_param_contents(msg, &entry->esp_prot_transform, HIP_PARAM_ESP_PROT_TFM, sizeof(uint8_t)), -1, "build param contents failed\n"); HIP_DEBUG("esp_prot_num_parallel_hchains: %i\n", num_parallel_hchains); HIP_IFEL(hip_build_param_contents(msg, &num_parallel_hchains, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); for (i = 0; i < num_parallel_hchains; i++) { // the anchor change has already occurred on fw-side if (entry->esp_prot_transform == ESP_PROT_TFM_TREE) { htree = entry->active_hash_items[i]; anchor = htree->root; } else { hchain = entry->active_hash_items[i]; anchor = hchain_get_anchor(hchain); } HIP_HEXDUMP("anchor: ", anchor, hash_length); HIP_IFEL(hip_build_param_contents(msg, anchor, HIP_PARAM_HCHAIN_ANCHOR, hash_length), -1, "build param contents failed\n"); } HIP_DUMP_MSG(msg); /* send msg to hipd and receive corresponding reply */ HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_sock), -1, "send_recv msg failed\n"); /* check error value */ HIP_IFEL(hip_get_msg_err(msg), -1, "hipd returned error message!\n"); HIP_DEBUG("send_recv msg succeeded\n"); out_err: free(msg); return err; }
/** creates the anchor element message * * @param hcstore the BEX store * @param use_hash_trees indicates whether hash chains or hash trees are stored * @return the message on success, NULL on error * * @note this will only consider the first hchain item in each shelf, as only * this should be set up for the store containing the hchains for the BEX * @note the created message contains hash_length and anchors for each transform */ static struct hip_common *create_bex_store_update_msg(struct hchain_store *hcstore, const int use_hash_trees) { struct hip_common *msg = NULL; struct esp_prot_tfm *transform = NULL; struct hash_chain *hchain = NULL; struct hash_tree *htree = NULL; unsigned char *anchor = NULL; unsigned j = 0; uint8_t i = 0; int hash_length = 0, num_hchains = 0, err = 0, hash_item_length = 0; HIP_ASSERT(hcstore != NULL); HIP_IFEL(!(msg = malloc(HIP_MAX_PACKET)), -1, "failed to allocate memory\n"); hip_msg_init(msg); HIP_IFEL(hip_build_user_hdr(msg, HIP_MSG_BEX_STORE_UPDATE, 0), -1, "build hdr failed\n"); // first add hash_length and num_hchain for each transform for (i = 1; i <= NUM_TRANSFORMS; i++) { HIP_IFEL(!(transform = esp_prot_resolve_transform(token_transform)), -1, "failed to resolve transform\n"); HIP_IFEL((hash_length = esp_prot_get_hash_length(token_transform)) <= 0, -1, "hash_length <= 0, expecting something bigger\n"); HIP_IFEL((num_hchains = hip_ll_get_size(&hcstore->hchain_shelves[transform->hash_func_id] [transform->hash_length_id]. hchains[DEFAULT_HCHAIN_LENGTH_ID][NUM_BEX_HIERARCHIES - 1])) <= 0, -1, "num_hchains <= 0, expecting something higher\n"); // tell hipd about transform HIP_IFEL(hip_build_param_contents(msg, &token_transform, HIP_PARAM_UINT, sizeof(uint8_t)), -1, "build param contents failed\n"); HIP_DEBUG("added esp_transform: %u\n", token_transform); // add num_hchains for this transform, needed on receiver side HIP_IFEL(hip_build_param_contents(msg, &num_hchains, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); HIP_DEBUG("added num_hchains: %i\n", num_hchains); // add the hash_length for this transform, needed on receiver side HIP_IFEL(hip_build_param_contents(msg, &hash_length, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); HIP_DEBUG("added hash_length: %i\n", hash_length); } // now add the hchain anchors for (i = 1; i <= NUM_TRANSFORMS; i++) { HIP_IFEL(!(transform = esp_prot_resolve_transform(token_transform)), -1, "failed to resolve transform\n"); HIP_IFEL((hash_length = esp_prot_get_hash_length(token_transform)) <= 0, -1, "hash_length <= 0, expecting something bigger\n"); // ensure correct boundaries HIP_ASSERT(transform->hash_func_id >= 0 && transform->hash_func_id < NUM_HASH_FUNCTIONS); HIP_ASSERT(transform->hash_length_id >= 0 && transform->hash_length_id < NUM_HASH_LENGTHS); // add anchor with this transform for (j = 0; j < hip_ll_get_size(&hcstore->hchain_shelves[transform->hash_func_id] [transform->hash_length_id]. hchains[DEFAULT_HCHAIN_LENGTH_ID][NUM_BEX_HIERARCHIES - 1]); j++) { if (use_hash_trees) { HIP_IFEL(!(htree = hip_ll_get(&hcstore->hchain_shelves[transform->hash_func_id] [transform->hash_length_id].hchains[DEFAULT_HCHAIN_LENGTH_ID][NUM_BEX_HIERARCHIES - 1], j)), -1, "failed to retrieve htree\n"); anchor = htree->root; hash_item_length = htree->num_data_blocks; } else { HIP_IFEL(!(hchain = hip_ll_get(&hcstore->hchain_shelves[transform->hash_func_id] [transform->hash_length_id].hchains[DEFAULT_HCHAIN_LENGTH_ID][NUM_BEX_HIERARCHIES - 1], j)), -1, "failed to retrieve hchain\n"); anchor = hchain_get_anchor(hchain); hash_item_length = hchain->hchain_length; } HIP_IFEL(hip_build_param_contents(msg, anchor, HIP_PARAM_HCHAIN_ANCHOR, hash_length), -1, "build param contents failed\n"); HIP_HEXDUMP("added anchor: ", anchor, hash_length); // also send the hchain/htree length for each item HIP_IFEL(hip_build_param_contents(msg, &hash_item_length, HIP_PARAM_INT, sizeof(int)), -1, "build param contents failed\n"); HIP_DEBUG("added hash_item_length: %i\n", hash_item_length); } } out_err: if (err) { free(msg); msg = NULL; } return msg; }
int main(int argc, char ** argv) { int i; char c; int err = 0; struct timeval start_time; struct timeval stop_time; hash_chain_t *hchain = NULL; hash_tree_t *htree = NULL; statistics_data_t creation_stats; statistics_data_t verify_stats; uint64_t timediff = 0; uint32_t num_items = 0; double min = 0.0, max = 0.0, avg = 0.0; double std_dev = 0.0; unsigned char *branch_nodes = NULL; int branch_length = 0; unsigned char *secret = NULL; int secret_length = 0; hash_chain_t *hchains[8]; unsigned char *data = NULL; int data_length = 0; unsigned char *root = NULL; int root_length = 0; hash_function = NULL; while ((c=getopt(argc, argv, "ctsml:h:v:n:")) != -1) { switch (c) { case 'c': test_hc = 1; break; case 't': test_ht = 1; break; case 's': hash_function = hash_functions[0]; break; case 'm': hash_function = hash_functions[1]; break; case 'l': hchain_length = atoi(optarg); break; case 'h': hash_length = atoi(optarg); break; case 'v': verify_length = atoi(optarg); break; case 'n': count = atoi(optarg); break; case ':': printf("Missing argument %c\n", optopt); print_usage(); exit(1); case '?': printf("Unknown option %c\n", optopt); print_usage(); exit(1); } } if (hash_function == NULL) { printf("no hash function selected!\n"); print_usage(); exit(1); } hip_set_logdebug(LOGDEBUG_NONE); memset(&creation_stats, 0, sizeof(statistics_data_t)); memset(&verify_stats, 0, sizeof(statistics_data_t)); print_timeres(); if (test_hc) { printf( "-------------------------------\n" "Hash chain performance test\n" "-------------------------------\n\n"); printf("Creating %d hash chains of length %d with element length %d\n", count, hchain_length, hash_length); for(i = 0; i < count; i++) { gettimeofday(&start_time, NULL); if (hchain = hchain_create(hash_function, hash_length, hchain_length, 0, NULL)) { gettimeofday(&stop_time, NULL); timediff = calc_timeval_diff(&start_time, &stop_time); add_statistics_item(&creation_stats, timediff); hchain_free(hchain); } else { printf("ERROR creating hchain!\n"); exit(1); } } calc_statistics(&creation_stats, &num_items, &min, &max, &avg, &std_dev, STATS_IN_MSECS); printf("creation statistics - num_data_items: %u, min: %.3fms, max: %.3fms, avg: %.3fms, std_dev: %.3fms\n", num_items, min, max, avg, std_dev); printf("\n"); printf("Verifying %d hash chains of length %d with element length %d\n", count, verify_length, hash_length); for(i = 0; i < count; i++) { if (!(hchain = hchain_create(hash_function, hash_length, verify_length, 0, NULL))) { printf("ERROR creating hchain!"); exit(1); } gettimeofday(&start_time, NULL); if(hchain_verify(hchain_get_seed(hchain), hchain_get_anchor(hchain), hash_function, hash_length, verify_length, NULL, 0)) { gettimeofday(&stop_time, NULL); timediff = calc_timeval_diff(&start_time, &stop_time); add_statistics_item(&verify_stats, timediff); hchain_free(hchain); } else { printf("ERROR verifying hchain!\n"); exit(1); } } calc_statistics(&verify_stats, &num_items, &min, &max, &avg, &std_dev, STATS_IN_MSECS); printf("verification statistics - num_data_items: %u, min: %.3fms, max: %.3fms, avg: %.3fms, std_dev: %.3fms\n", num_items, min, max, avg, std_dev); } if (test_ht) { printf( "\n-------------------------------\n" "Hash tree performance test\n" "-------------------------------\n\n"); memset(&creation_stats, 0, sizeof(statistics_data_t)); memset(&verify_stats, 0, sizeof(statistics_data_t)); printf("Creating %d hash trees of length %d with element length %d\n", count, hchain_length, hash_length); for(i = 0; i < count; i++) { HIP_DEBUG("number of leaves: %i\n", hchain_length); HIP_DEBUG("hash_length: %i\n", hash_length); HIP_DEBUG("data_length: %i\n", hash_length); gettimeofday(&start_time, NULL); htree = htree_init(hchain_length, hash_length, hash_length, 0, NULL, 0); htree_add_random_data(htree, hchain_length); htree_calc_nodes(htree, htree_leaf_generator, htree_node_generator, NULL); gettimeofday(&stop_time, NULL); timediff = calc_timeval_diff(&start_time, &stop_time); add_statistics_item(&creation_stats, timediff); htree_free(htree); } calc_statistics(&creation_stats, &num_items, &min, &max, &avg, &std_dev, STATS_IN_MSECS); printf("creation statistics - num_data_items: %u, min: %.3fms, max: %.3fms, avg: %.3fms, std_dev: %.3fms\n", num_items, min, max, avg, std_dev); for(i = 0; i < count; i++) { htree = htree_init(hchain_length, hash_length, hash_length, hash_length, NULL, 0); htree_add_random_data(htree, hchain_length); htree_add_random_secrets(htree); htree_calc_nodes(htree, htree_leaf_generator, htree_node_generator, NULL); root = htree_get_root(htree, &root_length); branch_nodes = htree_get_branch(htree, i, NULL, &branch_length); data = htree_get_data(htree, i, &data_length); secret = htree_get_secret(htree, i, &secret_length); gettimeofday(&start_time, NULL); if (!htree_verify_branch(root, root_length, branch_nodes, branch_length, data, data_length, i, secret, secret_length, htree_leaf_generator, htree_node_generator, NULL)) { gettimeofday(&stop_time, NULL); timediff = calc_timeval_diff(&start_time, &stop_time); add_statistics_item(&verify_stats, timediff); HIP_DEBUG("branch verified\n"); } else { printf("ERROR verifying htree!\n"); exit(1); } htree_free(htree); } calc_statistics(&verify_stats, &num_items, &min, &max, &avg, &std_dev, STATS_IN_MSECS); printf("verification statistics - num_data_items: %u, min: %.3fms, max: %.3fms, avg: %.3fms, std_dev: %.3fms\n", num_items, min, max, avg, std_dev); printf("\n\ntrying out hchain linking...\n"); // simulate level 0 creation htree = htree_init(8, hash_length, hash_length, hash_length, NULL, 0); htree_add_random_secrets(htree); for (i = 0; i < 8; i++) { hchains[i] = hchain_create(hash_function, hash_length, hchain_length, 0, NULL); htree_add_data(htree, hchain_get_anchor(hchains[i]), hash_length); } htree_calc_nodes(htree, htree_leaf_generator, htree_node_generator, NULL); // simulate level 1 creation hchain = hchain_create(hash_function, hash_length, hchain_length, 1, htree); // simulate BEX // get hchain anchor root = htree_get_root(htree, &root_length); // simulate level 1 hchain verification if(!hchain_verify(hchain_get_seed(hchain), hchain_get_anchor(hchain), hash_function, hash_length, verify_length, root, root_length)) { printf("hchain level 1 verfied\n"); } else { printf("ERROR verifying hchain level 1!\n"); exit(1); } // simulate update branch_nodes = htree_get_branch(htree, 0, NULL, &branch_length); secret = htree_get_secret(htree, 0, &secret_length); data = htree_get_data(htree, 0, &data_length); if (!htree_verify_branch(root, root_length, branch_nodes, branch_length, data, data_length, i, secret, secret_length, htree_leaf_generator, htree_node_generator, NULL)) { printf("anchor verified\n"); } else { printf("ERROR verifying anchor!\n"); exit(1); } if (!memcmp(data, hchain_get_anchor(hchains[0]), hash_length)) { printf("yes, this is the anchor we verified!\n"); } else { printf("ERROR no this is not the anchor we verified!\n"); exit(1); } hchain_free(hchain); // simulate level 0 hchain verification if(!hchain_verify(hchain_get_seed(hchains[0]), data, hash_function, hash_length, verify_length, NULL, 0)) { printf("hchain level 0 verfied\n"); } else { printf("ERROR verifying hchain level 0!\n"); exit(1); } } }