/* Cesar project {{{ * * Copyright (C) 2007 Spidcom * * <<>> * * }}} */ /** * \file cp/msg/msg_cm.c * \brief * \ingroup cp_msg */ #include "common/std.h" #include "cp/beacon/inc/bentry.h" #include "cp/beacon/inc/beacons_ctx.h" #include "cp/beacon/forward.h" #include "cp/beacon/inc/beacons_work.h" #include "cp/msg/inc/msg_cm.h" #include "lib/crc.h" static crc_t crc_m; static u32 *crc_table[256]; void msg_cm_init(void) { // init the CRC context (CRC used in cm_encrypted_payload) crc_m.width = 32; crc_m.generator = 0x4C11DB7; //4.2.1 crc_m.init = 0xFFFFFFFF; crc_m.refin = true; crc_m.refout = true; crc_m.xorout = 0xFFFFFFFF; crc_m.table.t32 = (u32 *) crc_table; crc_m.reg_init = 0; crc_init(&crc_m); } void msg_cm_unassociated_sta_ind_send(const mac_address_t oda) { // 11.5.1 msg_mme_t *msg_p, *msg_to_send; cm_unassociated_sta_t *unassociated_sta_p; msg_param_t msg_param; u8 buffer[1518]; msg_p = msg_sending_common_part((msg_mme_t *)buffer, oda, &msg_param); msg_p->mm_type = CM_UNASSOCIATED_STA_IND; // set the message values unassociated_sta_p = (cm_unassociated_sta_t *) & msg_p->mm_entry; unassociated_sta_p->nid = cp_station_get_nid(NULL); //TODO : pass CP ctx as first argument instead of NULL pointer... unassociated_sta_p->cco_capability = cp_station_get_cco_capa(); // set the mnbf flag msg_param.mnbf = 1; msg_param.encryption = NOT_ENCRYPTED; // and finaly, send the message printf(" send cm_unassociated_sta\n"); msg_to_send = interf_give_buf (); dbg_assert ( !msg_check_wrong_mme_const_values (msg_to_send)); //msg_cm_unassociated_sta_ind_convert((u8 *)msg_to_send, msg_p, BITSTREAM_WRITE); msg_send(msg_p, sizeof(cm_unassociated_sta_t) + MSG_MME_HEADER_SIZE, msg_param); } // set the following flag to 1 if you want to // test the message as on page 681 #define TEST_681 0 void msg_cm_encrypted_payload_ind_send( const msg_mme_t *encapsulated_msg_p, const msg_param_t encapsulated_msg_param, const tei_t tei, const bool last_msg_of_p_run, const cp_pid_t pid, const u16 msg_size ) { // 11.5.2 msg_mme_t *msg_p; cm_encrypted_payload_t *cm_encrypted_payload_p; cm_encrypted_payload_sub_t *cm_encrypted_payload_sub_p; msg_param_t msg_param; cp_station_status_t station_status; protocol_run_t pr_run; u8 rf, i, pad_size; aes_key_t *aes_key_p; aes_context ctx; u16 total_msg_size = msg_size + sizeof(cm_encrypted_payload_t) - COUNT(cm_encrypted_payload_p->rf) + 9; u8 buffer[1518], data_to_encrypt[1518]; int *int_p; u8 iv[16]; dbg_assert ( !msg_check_wrong_mme_const_values (encapsulated_msg_p)); dbg_assert(tei != 0 && tei != 0xFF); dbg_assert(pid <= HLE_PRO); dbg_assert(msg_size < (sizeof(msg_mme_t) - sizeof(cm_encrypted_payload_t) - sizeof(cm_encrypted_payload_sub_t))); msg_p = msg_sending_common_part((msg_mme_t *)buffer, encapsulated_msg_p->oda, &msg_param); msg_p->mm_type = CM_ENCRYPTED_PAYLOAD_IND; // set the message values cm_encrypted_payload_p = (cm_encrypted_payload_t *) & msg_p->mm_entry; // set the message values... cm_encrypted_payload_p->peks = encapsulated_msg_param.peks; // set the avln status of the station station_status = cp_station_get_status(); #if TEST_681 station_status = 5; #endif if(station_status == STATION_UNASSOCIATED) { cm_encrypted_payload_p->avln_status = cp_station_get_cco_capa(); } else { if(cp_station_get_is_cco()) { cm_encrypted_payload_p->avln_status = 0x08; } else { // the station is assosciated cm_encrypted_payload_p->avln_status = 0x04; if(cp_station_get_pcco_capa()) cm_encrypted_payload_p->avln_status = 0x05; } } // set the protocol run parameters if(secu_gen_protocol_run_param(tei, last_msg_of_p_run, &pr_run) == PRN_NotInitialised) { secu_start_new_protocol_run(tei, pid, &pr_run); secu_gen_protocol_run_param(tei, last_msg_of_p_run, &pr_run); #if TEST_681 pr_run.pmn = 3; pr_run.prn = 0x372D; #endif } cm_encrypted_payload_p->pid = pr_run.pid; cm_encrypted_payload_p->prn = pr_run.prn; cm_encrypted_payload_p->pmn = pr_run.pmn; cm_encrypted_payload_p->len = msg_size; if(pid == HLE_PRO) // case PID == 0x4 { // calculate the UUID field as specified in rfc4122 chap 4.4 int_p = (int *)cm_encrypted_payload_p->iv; for(i=0 ; i<4 ; i++) { *int_p = rand_in(0, 0); int_p++; } cm_encrypted_payload_p->iv[8] &= 0xBF; cm_encrypted_payload_p->iv[8] |= 0x80; cm_encrypted_payload_p->iv[6] = 0x4; cm_encrypted_payload_p->iv[7] = 0x0; // case PID == 0x4 implies no random filer rf = 0; memcpy(cm_encrypted_payload_p->rf, encapsulated_msg_p, msg_size); } else { // set the IV field (16 random bytes) int_p = (int *) iv; for(i=0 ; i<4 ; i++) { *int_p = rand_in(0, 0); int_p++; } #if TEST_681 memcpy(iv, "\xFE\xDC\xBA\x98\x76\x54\x32\x10\xFE\xDC\xBA\x98\x76\x54\x32\x10", 16); #endif memcpy(cm_encrypted_payload_p->iv, iv, 16); // calculate the rf filler size rf = rand_in(0, COUNT(cm_encrypted_payload_p->rf)); // fill the rf field with random data for(i=0 ; icrc = crc_compute_block(&crc_m, (u8 *)encapsulated_msg_p, msg_size); cm_encrypted_payload_sub_p->pid = pid; cm_encrypted_payload_sub_p->prn = pr_run.prn; cm_encrypted_payload_sub_p->pmn = pr_run.pmn; pad_size = 16 - (msg_size + rf + 9) % 16; for(i=0 ; i < pad_size ; i++) cm_encrypted_payload_sub_p->padding[i] = (u8) rand_in(0, 0xFF); #if TEST_681 cm_encrypted_payload_sub_p->padding[0] = 0xac ; cm_encrypted_payload_sub_p->padding[1] = 0xbc ; cm_encrypted_payload_sub_p->padding[2] = 0xd2 ; cm_encrypted_payload_sub_p->padding[3] = 0x11 ; cm_encrypted_payload_sub_p->padding[4] = 0x4d ; cm_encrypted_payload_sub_p->padding[5] = 0xae ; cm_encrypted_payload_sub_p->padding[6] = 0x15 ; cm_encrypted_payload_sub_p->padding[7] = 0x77 ; cm_encrypted_payload_sub_p->padding[8] = 0xc6 ; #endif cm_encrypted_payload_sub_p->padding[i] = rf; aes_key_p = secu_get_ek_from_peks(encapsulated_msg_param.peks, tei); aes_set_key(&ctx, (u8 *) aes_key_p, sizeof(aes_key_t)*8); aes_cbc_encrypt (&ctx, iv, data_to_encrypt, cm_encrypted_payload_p->rf+rf, rf+msg_size+pad_size+9); total_msg_size += rf + pad_size; } // set the mnbf flag msg_param.encryption = NOT_ENCRYPTED; // and finaly, send the message msg_send(msg_p, total_msg_size, msg_param); } /* void msg_cm_conn_new_req_send(msg_cm_conn_new_req_t msg) { // msg_mme_t *msg; // cm_conn_new_req_t } void msg_cm_conn_new_cnf_send() { } void msg_cm_conn_rel_ind_send() { } void msg_cm_conn_rel_rsp_send() { } void msg_cm_conn_mod_req_send() { } void msg_cm_conn_mod_cnf_send() { } void msg_cm_conn_info_req_send() { } void msg_cm_conn_info_cnf_send() { } */