Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pana.c Source File

pana.c

00001 /*
00002  * Copyright (c) 2013-2019, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #include "nsconfig.h"
00018 
00019 #include "ns_types.h"
00020 #include "eventOS_event.h"
00021 #include "ns_trace.h"
00022 #include "string.h"
00023 #include "randLIB.h"
00024 #include "nsdynmemLIB.h"
00025 #include "Core/include/ns_socket.h"
00026 #include "NWK_INTERFACE/Include/protocol.h"
00027 #include "ccmLIB.h"
00028 #include "shalib.h"
00029 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00030 #include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h"
00031 #ifdef ECC
00032 #include "libX509_V3.h"
00033 #include "ecc.h"
00034 #endif
00035 #include "Security/TLS/tls_lib.h"
00036 #include "Security/Common/sec_lib.h"
00037 #include "net_nvm_api.h"
00038 #include "Security/PANA/pana.h"
00039 #include "Security/PANA/pana_internal_api.h"
00040 #include "6LoWPAN/MAC/mac_helper.h"
00041 #include "6LoWPAN/MAC/mac_data_poll.h"
00042 #include "6LoWPAN/ND/nd_router_object.h"
00043 #include "Common_Protocols/udp.h"
00044 
00045 #ifdef ECC
00046 #include    "ecc.h"
00047 #endif
00048 #include "common_functions.h"
00049 #include "Security/PANA/pana_nvm.h"
00050 #include "Security/PANA/pana_avp.h"
00051 #include "Security/PANA/pana_eap_header.h"
00052 #include "Security/PANA/pana_header.h"
00053 #include "Security/PANA/eap_protocol.h"
00054 #include "net_pana_parameters_api.h"
00055 #include "Service_Libs/mle_service/mle_service_api.h"
00056 #include "socket_api.h"
00057 
00058 #ifdef PANA
00059 
00060 #define TRACE_GROUP "pana"
00061 
00062 typedef enum {
00063     ARM_PANA_INIT = 0,
00064     ARM_PANA_TLS_CB = 1,
00065 } arm_pana_event_id_e;
00066 
00067 //Pana Relay Constant
00068 const uint8_t PANA_AUTH_STRING[9] = {'I', 'E', 'T', 'F', ' ', 'P', 'A', 'N', 'A'};
00069 const uint8_t PANA_PAA_ENC_KEY_STRING[18] = {'I', 'E', 'T', 'F', ' ', 'P', 'A', 'N', 'A', ' ', 'P', 'A', 'A', ' ', 'E', 'n', 'c', 'r'};
00070 const uint8_t PANA_PAC_ENC_KEY_STRING[18] = {'I', 'E', 'T', 'F', ' ', 'P', 'A', 'N', 'A', ' ', 'P', 'a', 'C', ' ', 'E', 'n', 'c', 'r'};
00071 
00072 static void pana_key_calc(bool enc_key, sec_suite_t *suite);
00073 static void pana_handshake_copy(uint8_t *ptr, uint16_t len, bool request, sec_suite_t *suite);
00074 
00075 //TLS message parse support
00076 
00077 NS_LARGE int8_t pana_socket = -1;           /*socket variable*/
00078 static int8_t pana_tasklet_id = -1;
00079 static pana_socket_packet_handler_cb *pana_socket_packet_handler = NULL;
00080 static pana_state_machine_step *pana_state_machine_step_cb = NULL;
00081 static pana_eap_tls_up_cb *pana_tls_handler_cb = NULL;
00082 
00083 static NS_LARGE uint8_t pana_key_material[32];
00084 
00085 /** Pana Protocol Dynamic Parameters */
00086 static pana_lib_parameters_s pana_library_params = {
00087     .PCI_IRT = 10,
00088     .PCI_MRT = 60,
00089     .PCI_MRC = 5,
00090     .REQ_IRT = 20,
00091     .REQ_MRT = 60,
00092     .REQ_MRC = 4,
00093     .AUTHENTICATION_TIMEOUT = 120,
00094     .KEY_UPDATE_THRESHOLD = 10,
00095     .KEY_ID_MAX_VALUE = 0xff,
00096     .EAP_FRAGMENT_SIZE = EAP_MTU_FRAG_SIZE,
00097     .AUTH_COUNTER_MAX = 0xff
00098 };
00099 
00100 pana_lib_parameters_s *pana_parameters_get(void)
00101 {
00102     return &pana_library_params;
00103 }
00104 
00105 int8_t pana_socket_id_get(void)
00106 {
00107     return pana_socket;
00108 }
00109 
00110 void pana_common_state_machine(sec_suite_t *suite)
00111 {
00112     if (pana_state_machine_step_cb) {
00113         pana_state_machine_step_cb(suite);
00114     }
00115 }
00116 
00117 pana_session_t *pana_session_allocate(void)
00118 {
00119     pana_session_t *p_session =   ns_dyn_mem_alloc(sizeof(pana_session_t));
00120     if (p_session) {
00121         memset(p_session, 0, sizeof(pana_session_t));
00122         p_session->session_ready = false;
00123         p_session->key_warp = false;
00124         p_session->user_server = false;
00125         p_session->eap_id_seq = randLIB_get_8bit(); //Take Random EAP ID
00126     }
00127     return p_session;
00128 }
00129 
00130 void pana_session_base_init(pana_session_t *p_session)
00131 {
00132 
00133     memset(p_session, 0, sizeof(pana_session_t));
00134     p_session->session_ready = false;
00135     p_session->key_warp = false;
00136     p_session->user_server = false;
00137     p_session->eap_id_seq = randLIB_get_8bit(); //Take Random EAP ID
00138 
00139 }
00140 
00141 
00142 void pana_session_state_init(pana_session_t *p_session)
00143 {
00144     p_session->key_warp = false;
00145     p_session->address_status = 0;
00146 }
00147 
00148 pana_heap_t *pana_heap_structure_allocate(void)
00149 {
00150     pana_heap_t *heap = ns_dyn_mem_temporary_alloc(sizeof(pana_heap_t));
00151     if (heap) {
00152         heap->handshake_len = 0;
00153         heap->handshake_req_offset = 0;
00154         randLIB_get_n_bytes_random(heap->client_nonce, 16);
00155     }
00156     return heap;
00157 }
00158 
00159 static buffer_t *pana_eap_payload_to_avp(buffer_t *buf)
00160 {
00161     uint8_t *ptr;
00162 
00163     uint16_t eap_len, padding;
00164     eap_len = buffer_data_length(buf);
00165     padding = eap_len;
00166     if ((buf = buffer_headroom(buf, 8)) == 0) {
00167         return NULL;
00168     }
00169 
00170     buffer_data_reserve_header(buf, 8);
00171     //tr_debug("EAP AVP LEN: %02x", eap_len);
00172     ptr = buffer_data_pointer(buf);
00173     ptr = pana_avp_base_write(AVP_EAP_PAYLOAD_CODE, eap_len, ptr, 0, 0);
00174 
00175     //Check Padding
00176     padding %= 4;
00177     if (padding) {
00178         padding = 4 - padding;
00179         //tr_debug("Add Pad: %02x", padding);
00180         if ((buf = buffer_headroom(buf, padding)) != 0) {
00181             uint8_t *ptr2;
00182             buffer_data_reserve_header(buf, padding);
00183             ptr = buffer_data_pointer(buf);
00184             ptr2 = ptr;
00185             ptr += padding;
00186             memmove(ptr2, ptr, eap_len + 8);
00187         } else {
00188             return NULL;
00189         }
00190     }
00191 
00192     return buf;
00193 }
00194 
00195 int8_t pana_get_params(pana_lib_parameters_s *params)
00196 {
00197     if (params) {
00198         *params = pana_library_params;
00199         return 0;
00200     }
00201     return -1;
00202 }
00203 
00204 int8_t pana_set_params(const pana_lib_parameters_s *params)
00205 {
00206     int8_t ret_val = -1;
00207     if (!params) {
00208 
00209     } else if (params->PCI_IRT == 0 || params->PCI_MRT == 0 || params->PCI_MRC == 0) {
00210 
00211     } else if (params->REQ_IRT == 0 || params->REQ_MRT == 0 || params->REQ_MRC == 0) {
00212 
00213     } else if (params->KEY_UPDATE_THRESHOLD == 0 || params->KEY_ID_MAX_VALUE <  3) {
00214 
00215     } else if (params->EAP_FRAGMENT_SIZE < 64 || params->EAP_FRAGMENT_SIZE >= 920) {
00216 
00217     } else if ((params->PCI_IRT > params->PCI_MRT) || (params->REQ_IRT > params->REQ_MRT)) {
00218 
00219     } else {
00220         ret_val = 0;
00221         pana_library_params = *params;
00222     }
00223     return ret_val;
00224 
00225 }
00226 
00227 const pana_lib_parameters_s *pana_get_params_ptr(void)
00228 {
00229     return &pana_library_params;
00230 }
00231 
00232 void pana_timeout_timer_set(sec_suite_t *suite, sec_state_machine_t cur_state)
00233 {
00234     uint32_t timer;
00235     uint32_t timer_inc;
00236     uint32_t timer_max;
00237     uint8_t retry;
00238     retry = suite->retry_counter;
00239     if (cur_state == PANA_PCI_TX) {
00240         timer_inc = (pana_library_params.PCI_IRT * 10);
00241         timer_max = (pana_library_params.PCI_MRT * 10);
00242     } else {
00243         timer_inc = (pana_library_params.REQ_IRT * 10);
00244         timer_max = (pana_library_params.REQ_MRT * 10);
00245     }
00246     timer = timer_inc;
00247     while (retry > 1) {
00248         timer += timer_inc;
00249         if (timer > timer_max) {
00250             timer = timer_max;
00251             retry = 0;
00252         } else {
00253             retry--;
00254         }
00255     }
00256     //Set State
00257     suite->state = cur_state;
00258     suite->timer = timer;
00259 
00260 }
00261 uint8_t pana_retry_req_max_get(void)
00262 {
00263     return pana_library_params.REQ_MRC;
00264 }
00265 
00266 uint32_t pana_handshake_timeout(void)
00267 {
00268     uint32_t ret_val = (pana_library_params.AUTHENTICATION_TIMEOUT * 10);
00269     return ret_val;
00270 }
00271 
00272 int pana_retry_check(uint8_t counter, sec_state_machine_t cur_state)
00273 {
00274     int ret_val = -1;
00275     if (cur_state == PANA_PCI_TX) {
00276         if (counter < pana_library_params.PCI_MRC) {
00277             ret_val = 0;
00278         }
00279     } else {
00280         if (counter < pana_library_params.REQ_MRC) {
00281             ret_val = 0;
00282         }
00283     }
00284     return ret_val;
00285 }
00286 
00287 uint8_t *pana_key_get(const uint8_t *key)
00288 {
00289     static uint8_t key_seed[8] = {'Z', 'i', 'g', 'B', 'e', 'e', 'I', 'P'};
00290     SHALIB_init_HMAC(key, 16);
00291     SHALIB_push_data_HMAC(key_seed, 8);
00292     SHALIB_finish_HMAC(pana_key_material, 8);
00293     return pana_key_material;
00294 }
00295 
00296 //static void pana_key_pair_data_generate(sec_suite_t *suite)
00297 //{
00298 //    uint8_t *pac, *paa;
00299 //    if (suite->setups & TLS_SERVER_MODE) {
00300 //        //Server
00301 //        paa = suite->interface->iid_eui64;
00302 //        pac = &suite->session_address[8];
00303 //    } else {
00304 //        pac = suite->interface->iid_eui64;
00305 //        paa = &suite->session_address[8];
00306 //
00307 //    }
00308 //    SHALIB_push_data_HMAC(paa, 8);
00309 //    SHALIB_push_data_HMAC(pac, 8);
00310 //}
00311 ///* Define Pair wise Key*/
00312 //static uint8_t pana_hmac_temp_key[64];
00313 //static uint8_t *pana_generate_key_pair_key(sec_suite_t *suite, uint8_t *common_key, uint8_t *key_ptr)
00314 //{
00315 //    static uint8_t key_seed[8] = {'K', 'e', 'y', 'P', 'a', 'i', 'r', '?'};
00316 //    memcpy(pana_hmac_temp_key, suite->pana_session.pana_auth_key, 32);
00317 //    memcpy(&pana_hmac_temp_key[32], common_key, 16);
00318 //
00319 //    SHALIB_init_HMAC(pana_hmac_temp_key, 48);
00320 //
00321 //    SHALIB_push_data_HMAC(key_seed, 8);
00322 //    pana_key_pair_data_generate(suite);
00323 //    SHALIB_push_data_HMAC(&suite->pana_session.auth_cnt, 1);
00324 //    SHALIB_finish_HMAC(common_key, 4);
00325 //    return common_key;
00326 //}
00327 
00328 void pana_session_init_by_session_ptr(sec_suite_t *suite, auth_info_t *auth_ptr)
00329 {
00330     if (suite) {
00331         suite->setups = 0;
00332         pana_session_state_init(&suite->pana_session);
00333         suite->pana_session.auth_info = auth_ptr;
00334 
00335         eap_fragmentation_init(suite);
00336         if (suite->pana_session.session_ready) {
00337             tr_debug("Ping Notify");
00338             suite->state = PANA_PING_REQ;
00339             suite->timer = 1;
00340             suite->retry_counter = 0;
00341         } else {
00342             if (sec_pana_protocol_init(suite) == 0) {
00343                 sec_lib_state_machine_trig(suite, PANA_ERROR);
00344             }
00345         }
00346     }
00347 }
00348 
00349 void pana_authentication_ready(uint8_t status, protocol_interface_info_entry_t *cur_interface)
00350 {
00351     if (status) {
00352         nwk_6lowpan_bootsrap_pana_authentication_cb(true, cur_interface);
00353     } else {
00354         nwk_6lowpan_bootsrap_pana_authentication_cb(false, cur_interface);
00355     }
00356 }
00357 
00358 #ifdef ECC
00359 extern void sec_ecc_state_free(sec_suite_t *suite);
00360 #endif
00361 
00362 void pana_reset_values(uint16_t pana_id)
00363 {
00364     sec_suite_t *suite = 0;
00365 
00366     suite = sec_suite_selected_py_pan_id(pana_id);
00367     if (suite) {
00368         suite->timer = 0;
00369         sec_suite_tls_free(suite, true);
00370         pana_free_dynamic_ram(suite);
00371 #ifdef ECC
00372         sec_ecc_state_free(suite);
00373 #endif
00374     }
00375 
00376 }
00377 
00378 static void pana_socket_callback(void *cb)
00379 {
00380     socket_buffer_callback_t *cb_buf = cb;
00381     if (cb_buf->event_type == SOCKET_DATA) {
00382         buffer_t *buf = cb_buf->buf ;
00383         if (buf) {
00384 
00385             //Find or create session //Do CB HERE
00386             buf->socket  = socket_dereference(buf->socket );
00387             buf->session_ptr = NULL;
00388             pana_socket_packet_handler(buf);
00389         }
00390     } else {
00391 
00392         sec_suite_socket_event(cb_buf->event_type, cb_buf->session_ptr);
00393     }
00394 }
00395 
00396 void pana_event_handler(arm_event_s *event)
00397 {
00398     switch (event->event_type) {
00399         case ARM_PANA_INIT:
00400             tr_debug("Pana Tasklet Init");
00401             break;
00402 
00403         case ARM_PANA_TLS_CB:
00404             if (event->data_ptr) {
00405                 buffer_t *buf = event->data_ptr;
00406                 sec_suite_t *tls_suite = buf->session_ptr;
00407                 buf->session_ptr = NULL;
00408 
00409                 tls_suite = sec_suite_verify(tls_suite);
00410 
00411                 if (tls_suite && pana_tls_handler_cb) {
00412                     buf = pana_tls_handler_cb(buf, tls_suite);
00413                 } else {
00414                     tr_warn("Pana/TLS er");
00415                 }
00416 
00417                 if (buf) {
00418                     buffer_free(buf);
00419                 }
00420             }
00421             break;
00422         default:
00423             break;
00424     }
00425 }
00426 
00427 bool pana_socket_init(pana_socket_packet_handler_cb *socket_handler, pana_state_machine_step *state_machine_stepper, pana_eap_tls_up_cb *tls_handler_cb)
00428 {
00429     tr_debug("Pana sub-layer init");
00430     if (pana_socket == -1) {
00431         if (socket_create(SOCKET_FAMILY_IPV6, SOCKET_TYPE_DGRAM, 0, &pana_socket, UDP_PORT_PANA, pana_socket_callback, true) != eOK) {
00432             return false;
00433         }
00434         //GENERATE TASKLET if not created before
00435         if (pana_tasklet_id == -1) {
00436             pana_tasklet_id = eventOS_event_handler_create(&pana_event_handler, ARM_PANA_INIT);
00437             if (pana_tasklet_id < 0) {
00438                 socket_close(pana_socket);
00439                 pana_socket = -1;
00440                 return false;
00441             }
00442         }
00443     }
00444     tr_debug("Pana socket Id %i", pana_socket);
00445 
00446     pana_socket_packet_handler = socket_handler;
00447     pana_state_machine_step_cb = state_machine_stepper;
00448     pana_tls_handler_cb = tls_handler_cb;
00449     return true;
00450 }
00451 
00452 void pana_set_agend_address(buffer_t *buf, bool relay, sec_suite_t *suite)
00453 {
00454     uint8_t *ptr = 0;
00455     buf->interface  = suite->interface;
00456     protocol_interface_info_entry_t *cur = buf->interface ;
00457     if (cur) {
00458 
00459         if (suite->pana_session.user_server) {
00460             if (relay) {
00461                 ptr = protocol_6lowpan_nd_border_router_address_get(buf->interface ->nwk_id);
00462                 if (ptr) {
00463                     memcpy(buf->src_sa .address , ptr, 16);
00464                     ptr = suite->pana_session.session_relay_address;
00465                     memcpy(buf->dst_sa .address , ptr, 16);
00466                 }
00467                 //
00468                 buf->options .ll_security_bypass_tx  = false;
00469             } else {
00470                 //Default
00471                 addr_interface_get_ll_address(cur, buf->src_sa .address , 2);
00472                 ptr = suite->session_address;
00473                 memcpy(buf->dst_sa .address , ptr, 16);
00474                 buf->options .ll_security_bypass_tx  = true;
00475             }
00476         } else {
00477             if (relay) {
00478                 ptr = protocol_6lowpan_nd_border_router_address_get(buf->interface ->nwk_id);
00479                 if (ptr) {
00480                     memcpy(buf->dst_sa .address , ptr, 16);
00481                     memcpy(suite->pana_session.session_relay_address, ptr, 16);
00482                     //Select source by Dst address
00483                     (void) addr_interface_select_source(cur, buf->src_sa .address , buf->dst_sa .address , 0);
00484                 }
00485                 buf->options .ll_security_bypass_tx  = false;
00486             } else {
00487 
00488 
00489                 //tr_debug("LL Agent");
00490                 nd_router_t   *object = nd_get_pana_address();
00491                 if (object) {
00492                     icmp_nd_set_nd_def_router_address(buf->dst_sa .address , object);
00493                     tr_debug("MD Router adr: %s", trace_ipv6(buf->dst_sa .address ));
00494                 } else {
00495                     //tr_debug("Use Mac Coordinator");
00496                     protocol_6lowpan_interface_get_link_local_cordinator_address(cur, buf->dst_sa .address );
00497                 }
00498                 ptr = suite->session_address;
00499                 memcpy(ptr, buf->dst_sa .address , 16);
00500 
00501                 addr_interface_get_ll_address(cur, buf->src_sa .address , 1);
00502                 buf->options .ll_security_bypass_tx  = true;
00503             }
00504         }
00505     }
00506     tr_debug("DST %s src %s", trace_ipv6(buf->dst_sa .address ), trace_ipv6(buf->src_sa .address ));
00507     buf->src_sa .addr_type  = ADDR_IPV6 ;
00508     buf->dst_sa .addr_type  = ADDR_IPV6 ;
00509 
00510 }
00511 
00512 
00513 buffer_t *build_pana_base(buffer_t *buf, pana_header_t *header, sec_suite_t *suite)
00514 {
00515     uint8_t *ptr;
00516     buf->session_ptr = NULL;
00517     buf = buffer_headroom(buf, PANA_HEADER_LENGTH);
00518     if (!buf) {
00519         return NULL;
00520     }
00521 
00522     buf = buffer_turnaround(buf); // In case we're reusing a buffer
00523     ptr = buffer_data_reserve_header(buf, PANA_HEADER_LENGTH);
00524     header->payload_len = buffer_data_length(buf);
00525     pana_header_write(ptr, header);
00526 
00527     buf->src_sa .port  = UDP_PORT_PANA;
00528     buf->dst_sa .port  = suite->session_port;
00529     buf->info  = (buffer_info_t)(B_DIR_DOWN + B_FROM_APP + B_TO_UDP);
00530     if (header->type != PANA_MSG_RELAY || suite->pana_session.user_server) {
00531         buffer_socket_set(buf, socket_pointer_get(pana_socket));
00532         buf->session_ptr = suite;
00533     } else {
00534         buf->socket  = socket_dereference(buf->socket );
00535         buf->session_ptr = NULL;
00536     }
00537     //tr_debug("From Pana-> Core");
00538     buf->interface  = suite->interface;
00539     tr_debug("PANA len: %d", header->payload_len);
00540     return buf;
00541 }
00542 
00543 void pana_eap_tls_up(buffer_t *buf, sec_suite_t *suite)
00544 {
00545     buf = eap_up(buf, suite);
00546     if (!buf) {
00547         return;
00548     }
00549     pana_eap_down(buf, suite);
00550 }
00551 
00552 void pana_eap_down(buffer_t *buf, sec_suite_t *suite)
00553 {
00554     buf = eap_down(buf, suite);
00555     if (!buf) {
00556         return;
00557     }
00558     //Set EAP Payload
00559     pana_eap_payload_down(buf, NULL, suite);
00560 }
00561 
00562 void pana_eap_payload_down(buffer_t *buf, const uint8_t *nonce, sec_suite_t *suite)
00563 {
00564     buf = pana_eap_payload_to_avp(buf);
00565 
00566     if (!buf) {
00567         return;
00568     }
00569 
00570     if (nonce) {
00571         if ((buf = buffer_headroom(buf, 24)) == 0) {
00572             return;
00573         }
00574         buffer_data_reserve_header(buf, 24);
00575         uint8_t *ptr = buffer_data_pointer(buf);
00576         ptr = pana_avp_write_n_bytes(AVP_NONCE_CODE, 16, nonce, ptr);
00577     }
00578 
00579     pana_down(buf, suite);
00580 }
00581 
00582 
00583 void pana_handshake_copy(uint8_t *ptr, uint16_t len, bool request, sec_suite_t *suite)
00584 {
00585     if (suite->pana_session.pana_heap) {
00586         uint8_t *dptr = 0;
00587         pana_heap_t *pheap = suite->pana_session.pana_heap;
00588 
00589         dptr = pheap->pana_handshake;
00590         if (!request) {
00591             dptr += pheap->handshake_req_offset;
00592             pheap->handshake_len = len + pheap->handshake_req_offset;
00593         } else {
00594             pheap->handshake_req_offset = len;
00595             pheap->handshake_len = len;
00596         }
00597         memcpy(dptr, ptr, len);
00598     }
00599 }
00600 
00601 
00602 void pana_down(buffer_t *buf, sec_suite_t *suite)
00603 {
00604     //Check Request Or Response
00605     pana_header_t header;
00606     header.type = PANA_MSG_PA;
00607     if (suite->pana_session.user_server) {
00608         if (suite->state == PANA_REQUEST_TX) {
00609             header.flags = PANA_FLAGS_START | PANA_FLAGS_REQUEST;
00610         } else if (suite->state == EAP_PANA_FINISH || suite->state == PANA_FAILURE) {
00611             header.flags = (PANA_FLAGS_REQUEST | PANA_FLAGS_COMPLETE);
00612         } else if (suite->state == PANA_FAILURE_RESPONSE) {
00613             header.flags = (PANA_FLAGS_RESPONSE | PANA_FLAGS_COMPLETE);
00614         } else {
00615             header.flags = PANA_FLAGS_REQUEST;
00616         }
00617     } else {
00618 
00619         if (suite->state == PANA_FAILURE) {
00620             header.flags = PANA_FLAGS_COMPLETE;
00621         } else if (suite->state == PANA_START_RESPONSE) {
00622             header.flags = PANA_FLAGS_START;
00623         } else {
00624             header.flags = 0;
00625         }
00626     }
00627 
00628     if (header.flags & PANA_FLAGS_REQUEST) {
00629         header.seq = suite->pana_session.req_seq;
00630     } else {
00631         header.seq = suite->pana_session.res_seq;
00632     }
00633     header.session_id = suite->pana_session.session_id;
00634     pana_set_agend_address(buf, false, suite);
00635     buf = build_pana_base(buf, &header, suite);
00636     if (buf) {
00637         /**
00638          * Copy Authentication start message
00639          */
00640         if (header.flags & PANA_FLAGS_START) {
00641             uint16_t len = buffer_data_length(buf);
00642             uint8_t *ptr = buffer_data_pointer(buf);
00643 
00644             if (header.flags & PANA_FLAGS_REQUEST) {
00645                 pana_handshake_copy(ptr, len, true, suite);
00646             } else {
00647                 pana_handshake_copy(ptr, len, false, suite);
00648             }
00649         }
00650 
00651         if (suite->pana_session.address_status & 1) {
00652             tr_debug("Build Relay");
00653             buf = pana_relay_avp_build(buf, suite);
00654             if (buf) {
00655                 header.flags = 0;
00656                 header.type = PANA_MSG_RELAY;
00657                 header.session_id = 0;
00658                 header.seq = 0;
00659                 buf = build_pana_base(buf, &header, suite);
00660             }
00661         }
00662 
00663         protocol_push(buf);
00664     }
00665 
00666 
00667 }
00668 
00669 
00670 buffer_t *pana_relay_avp_build(buffer_t *buf, sec_suite_t *suite)
00671 {
00672     uint8_t *ptr, *adr_ptr;
00673     uint16_t relay_len, padding;
00674     relay_len = buffer_data_length(buf);
00675     padding = relay_len;
00676     buf->socket  = socket_dereference(buf->socket );
00677     buf->session_ptr = NULL;
00678     if ((buf = buffer_headroom(buf, 36)) == 0) {
00679         return buf;
00680     } else {
00681         buffer_data_reserve_header(buf, 36);
00682         ptr = buffer_data_pointer(buf);
00683         ptr = pana_avp_base_write(AVP_PAC_INFO_CODE, 18, ptr, 0, 0);
00684         //SET Relay IPV6 address
00685         if (suite->pana_session.user_server) {
00686             memcpy(ptr, suite->session_address, 16);
00687             ptr += 16;
00688             ptr = common_write_16_bit(suite->session_port, ptr);
00689 
00690             adr_ptr = protocol_6lowpan_nd_border_router_address_get(buf->interface ->nwk_id);
00691             if (adr_ptr) {
00692                 memcpy(buf->src_sa .address , adr_ptr, 16);
00693                 memcpy(buf->dst_sa .address , suite->pana_session.session_relay_address, 16);
00694                 buf->dst_sa .port  = suite->pana_session.relay_port;
00695             }
00696         } else {
00697             memcpy(ptr, buf->src_sa .address , 16);
00698             ptr += 16;
00699             ptr = common_write_16_bit(buf->src_sa .port , ptr);
00700         }
00701         //PADDING for PAC
00702         ptr = common_write_16_bit(0, ptr);
00703         //PANA Relay AVP header Write data is already there
00704         ptr = pana_avp_base_write(AVP_RELAY_MSG_CODE, relay_len, ptr, 0, 0);
00705     }
00706     //Enable security for relay allways by Default
00707     buf->options .ll_security_bypass_tx  = false;
00708     padding %= 4;
00709     if (padding) {
00710         padding = 4 - padding;
00711         //tr_debug("Add Pad: %02x", padding);
00712         if ((buf = buffer_headroom(buf, padding)) != 0) {
00713             uint8_t *ptr2;
00714             buffer_data_reserve_header(buf, padding);
00715             ptr = buffer_data_pointer(buf);
00716             ptr2 = ptr;
00717             ptr += padding;
00718             memmove(ptr2, ptr, relay_len + 36);
00719         }
00720     }
00721     return buf;
00722 }
00723 
00724 bool pana_auth_check(uint8_t *ptr, uint16_t length, uint8_t *authency, uint8_t *key)
00725 {
00726     if (!authency) {
00727         return false;
00728     }
00729     uint8_t hasn_buf_temp[16];
00730     uint8_t compare_hash_temp[16];
00731 
00732     //tr_debug("AV SUCCESS. Hash RX: %s", trace_array(ptr, 16));
00733     memcpy(compare_hash_temp, authency, 16);
00734     memset(authency, 0, 16);
00735     length += 16;
00736     ptr -= 16;//Shift Pana Headers back
00737     //tr_debug("Calc: %s", trace_array(key, 32) );
00738     SHALIB_init_HMAC(key, 32);
00739     SHALIB_push_data_HMAC(ptr, length);
00740     //tr_debug("%s", trace_array(ptr,length));
00741     SHALIB_finish_HMAC(hasn_buf_temp, 4);
00742 
00743     if (memcmp(hasn_buf_temp, compare_hash_temp, 16) != 0) {
00744         tr_debug("HASH AUTH Fail. RX: %s", trace_array(compare_hash_temp, 16));
00745         tr_debug("Cal: %s", trace_array(hasn_buf_temp, 16));
00746         return false;
00747     }
00748     return true;
00749 }
00750 
00751 int8_t pana_ccm_data_crypt(uint8_t *ptr, uint16_t len, uint8_t operation_type, uint32_t message_seq, sec_suite_t *suite)
00752 {
00753     uint8_t *explict_ptr;
00754     uint8_t *key_ptr = 0;
00755     ccm_globals_t ccm_ptr;
00756     key_ptr = suite->pana_session.pana_PAA_enc_key;
00757 
00758     //Here Comes AES Decrypt
00759     if (!ccm_sec_init(&ccm_ptr, AES_SECURITY_LEVEL_ENC, key_ptr, operation_type, 3)) {
00760         return -1;
00761     }
00762 
00763     explict_ptr = ccm_ptr.exp_nonce;
00764     //Set IV
00765     explict_ptr = common_write_32_bit(suite->pana_session.pana_key_id, explict_ptr);
00766     //SET EXP 4 octest Session ID, 4 Octet Pana SQN number
00767     explict_ptr = common_write_32_bit(suite->pana_session.session_id, explict_ptr);
00768     explict_ptr = common_write_32_bit(message_seq, explict_ptr);
00769     ccm_ptr.data_len = len;
00770     ccm_ptr.data_ptr  = ptr;
00771     return ccm_process_run(&ccm_ptr);
00772 }
00773 
00774 buffer_t *pana_relay_parse(buffer_t *buf)
00775 {
00776     uint8_t *ptr;
00777     buf->options .ll_security_bypass_tx  = true;
00778     //tr_debug("Relay RX");
00779     ptr = buffer_data_pointer(buf);
00780     uint16_t length = buffer_data_length(buf);
00781 
00782     pana_avp_t pac_info;
00783     pac_info.code = AVP_PAC_INFO_CODE;
00784 
00785     if (!pana_avp_discover(ptr, length, &pac_info)  || pac_info.len != 18) {
00786         tr_debug("No Pac info");
00787         return buffer_free(buf);
00788     }
00789 
00790     pana_avp_t relay_msg;
00791     relay_msg.code = AVP_RELAY_MSG_CODE;
00792 
00793     if (!pana_avp_discover(ptr, length, &relay_msg)) {
00794         tr_debug("No Relay MSG");
00795         return buffer_free(buf);
00796     }
00797     //Set Message data to relay msg
00798     buffer_data_pointer_set(buf, relay_msg.avp_ptr);
00799     buffer_data_length_set(buf, relay_msg.len);
00800     //Set Destination to Pac Info
00801     ptr = pac_info.avp_ptr;
00802     memcpy(buf->dst_sa .address , ptr, 16);
00803     //buf->dst_sa.addr_type = ADDR_IPV6;
00804     ptr += 16;
00805     buf->dst_sa .port  = common_read_16_bit(ptr);
00806     ptr += 2;
00807     //tr_debug("%s", trace_array(buf->dst_sa.address, 16) );
00808     return buf;
00809 }
00810 
00811 void pana_session_startms_parse(buffer_t *buf, pana_header_t *header, sec_suite_t *suite)
00812 {
00813     uint32_t prf_algorythm = 0;
00814     uint32_t integrity_algorythm = 12;
00815     uint32_t key_wrap = 0;
00816     bool key_wrap_parsed = false;
00817     uint16_t len = buffer_data_length(buf);
00818     uint8_t *ptr = buffer_data_pointer(buf);
00819 
00820     pana_avp_t avp_temp;
00821     //Read Resul and Key id if they are coming
00822     avp_temp.code = AVP_PRF_ALGORYTHM_CODE;
00823     avp_temp.len = 0;
00824     if (pana_avp_discover(ptr, len, &avp_temp) &&  avp_temp.len == 4) {
00825         prf_algorythm = common_read_32_bit(avp_temp.avp_ptr);
00826     }
00827 
00828     avp_temp.code = AVP_INTEGRIRTY_ALGORYTHM_CODE;
00829     avp_temp.len = 0;
00830     if (pana_avp_discover(ptr, len, &avp_temp) &&  avp_temp.len == 4) {
00831         integrity_algorythm = common_read_32_bit(avp_temp.avp_ptr);
00832     }
00833 
00834     avp_temp.code = AVP_KEY_WRAP_ALG_CODE;
00835     avp_temp.len = 0;
00836     if (pana_avp_discover(ptr, len, &avp_temp) &&  avp_temp.len == 4) {
00837         key_wrap = common_read_32_bit(avp_temp.avp_ptr);
00838         key_wrap_parsed = true;
00839     }
00840 
00841     bool drop_message = false;
00842     if ((header->flags & PANA_FLAGS_REQUEST)  == PANA_FLAGS_RESPONSE) {
00843         if (prf_algorythm != suite->pana_session.prf_algorythm) {
00844             tr_debug("PRF!!");
00845             drop_message = true;
00846         } else if (integrity_algorythm != suite->pana_session.integrity_algorythm) {
00847             tr_debug("int!!");
00848             drop_message = true;
00849         }
00850         if (key_wrap_parsed && key_wrap != suite->pana_session.key_wrap) {
00851             tr_debug("key!!");
00852             drop_message = true;
00853         }
00854 
00855     } else {
00856         if (prf_algorythm != 5) {
00857             drop_message = true;
00858         } else if (integrity_algorythm != 12) {
00859             drop_message = true;
00860         }
00861     }
00862 
00863     if (!drop_message) {
00864         if (key_wrap_parsed) {
00865             suite->pana_session.key_warp = true;
00866             suite->pana_session.key_wrap = key_wrap;
00867         }
00868         len += 16;
00869         ptr -= 16; //Shift Pana Headers back
00870         if ((header->flags & PANA_FLAGS_REQUEST)  == PANA_FLAGS_RESPONSE) {
00871             sec_lib_state_machine_trig(suite, EAP_IDENTITY_REQ);
00872             pana_handshake_copy(ptr, len, false, suite);
00873         } else {
00874             suite->pana_session.integrity_algorythm = integrity_algorythm;
00875             suite->pana_session.prf_algorythm = prf_algorythm;
00876             sec_lib_state_machine_trig(suite, PANA_START_RESPONSE);
00877             pana_handshake_copy(ptr, len, true, suite);
00878         }
00879         suite->retry_counter = 0;
00880 
00881     }
00882 
00883     buffer_free(buf);
00884 }
00885 
00886 buffer_t *pana_auth_message_handler(buffer_t *buf, pana_header_t *header, sec_suite_t *suite)
00887 {
00888     if (!buf) {
00889         return NULL;
00890     }
00891     protocol_interface_info_entry_t *cur = buf->interface ;
00892     if (!cur) {
00893         return buffer_free(buf);
00894     }
00895 
00896     uint16_t length = buffer_data_length(buf);
00897     uint8_t *ptr = buffer_data_pointer(buf);
00898     pana_avp_t avp_temp;
00899 
00900     if (suite->pana_session.session_ready) {
00901         return buffer_free(buf);
00902     }
00903 
00904     if (sec_check_suite_ptrs(suite) == 0) {
00905         tr_warn("SEC Lib Fail");
00906         return buffer_free(buf);
00907     }
00908 
00909     avp_temp.code = AVP_NONCE_CODE;
00910     if (pana_avp_discover(ptr, length, &avp_temp)) {
00911         if (avp_temp.len == 16) {
00912             if ((header->flags & PANA_FLAGS_REQUEST)  == PANA_FLAGS_RESPONSE) {
00913                 memcpy(suite->pana_session.pana_heap->client_nonce, avp_temp.avp_ptr, 16);
00914             } else {
00915                 memcpy(suite->pana_session.pana_heap->agent_nonce, avp_temp.avp_ptr, 16);
00916             }
00917             //tr_debug("Pana:A_NONCE OK");
00918 
00919         } else {
00920             tr_debug("A_NONCE length fail, Len: %x", avp_temp.len);
00921         }
00922     }
00923 
00924     avp_temp.code = AVP_EAP_PAYLOAD_CODE;
00925     if (pana_avp_discover(ptr, length, &avp_temp)) {
00926         ptr = avp_temp.avp_ptr;
00927         if (avp_temp.len > 4) {
00928             buf->buf_ptr  = 0;
00929             buf->buf_end  = avp_temp.len;
00930             memmove(buf->buf , ptr, avp_temp.len);
00931             return buf;
00932         }
00933     }
00934 
00935     return buffer_free(buf);
00936 }
00937 
00938 void pana_start_message_build(buffer_t *buf, sec_suite_t *suite)
00939 {
00940     uint8_t *ptr;
00941     //tr_debug("TX Pana Start Response");
00942     buf->buf_ptr  = PANA_HEADER_LENGTH;
00943     ptr = buffer_data_pointer(buf);
00944     ptr = pana_avp_32_bit_write(AVP_PRF_ALGORYTHM_CODE, suite->pana_session.prf_algorythm, ptr);
00945     ptr = pana_avp_32_bit_write(AVP_INTEGRIRTY_ALGORYTHM_CODE, suite->pana_session.integrity_algorythm, ptr);
00946     if (suite->pana_session.key_warp) {
00947         ptr = pana_avp_32_bit_write(AVP_KEY_WRAP_ALG_CODE, suite->pana_session.key_wrap, ptr);
00948     }
00949     buffer_data_end_set(buf, ptr);
00950     pana_down(buf, suite);
00951 }
00952 
00953 
00954 
00955 void eap_tls_payload_push(buffer_t *buf)
00956 {
00957     arm_event_s event = {
00958         .receiver = pana_tasklet_id,
00959         .sender = 0,
00960         .data_ptr = buf,
00961         .event_type = ARM_PANA_TLS_CB,
00962         .priority = ARM_LIB_HIGH_PRIORITY_EVENT,
00963     };
00964     if (eventOS_event_send(&event) != 0) {
00965         tr_warn("Free Buffer if fail");
00966         buf->session_ptr = NULL;
00967         buffer_free(buf);
00968     }
00969 }
00970 
00971 void pana_free_dynamic_ram(sec_suite_t *suite)
00972 {
00973     if (suite->pana_session.pana_heap) {
00974         tr_debug("Free Pana Heap");
00975         ns_dyn_mem_free(suite->pana_session.pana_heap);
00976         suite->pana_session.pana_heap = NULL;
00977     }
00978     eap_fragmentation_init(suite);
00979 }
00980 
00981 static void pana_key_calc(bool enc_key, sec_suite_t *suite)
00982 {
00983     pana_heap_t *pheap = suite->pana_session.pana_heap;
00984 
00985     //tr_debug("Pana Auth verify. MSK: %s", trace_array(suite->pana_session.MSK, 64) );
00986     SHALIB_init_HMAC(pheap->MSK, 64);
00987     if (enc_key) {
00988         //tr_debug("Cal Pana En Key start");
00989         SHALIB_push_data_HMAC(PANA_PAA_ENC_KEY_STRING, 18);
00990     } else {
00991         SHALIB_push_data_HMAC(PANA_AUTH_STRING, 9);
00992     }
00993 
00994     //tr_debug("Handshake data: %s", trace_array(pheap->pana_handshake, pheap->handshake_len));
00995     SHALIB_push_data_HMAC(pheap->pana_handshake, pheap->handshake_len);
00996 //  tr_debug("Handshake data");
00997 //  tr_debug("C Nonce: %s", trace_array(pheap->client_nonce, 16) );
00998     SHALIB_push_data_HMAC(pheap->client_nonce, 16);
00999 //  tr_debug("A Nonce: %s", trace_array(pheap->agent_nonce, 16) );
01000     SHALIB_push_data_HMAC(pheap->agent_nonce, 16);
01001     uint8_t temp32_buf[4];
01002 //  tr_debug("Key ID: %s", trace_array(temp32_buf, 4) );
01003     common_write_32_bit(suite->pana_session.pana_key_id, temp32_buf);
01004     SHALIB_push_data_HMAC(temp32_buf, 4);
01005     SHALIB_push_data_HMAC(&(const uint8_t) {
01006         1
01007     }, 1);
01008     if (enc_key) {
01009         uint8_t *key_ptr = suite->pana_session.pana_PAA_enc_key;
01010 
01011         SHALIB_finish_HMAC(key_ptr, 4);
01012     } else {
01013         SHALIB_finish_HMAC(suite->pana_session.pana_auth_key, 8);
01014     }
01015 }
01016 
01017 void pana_key_calculation(sec_suite_t *suite)
01018 {
01019     pana_key_calc(false, suite);
01020     pana_key_calc(true, suite);
01021 }
01022 
01023 void pana_auth_hash_calc(uint8_t *data_ptr, uint16_t data_length, uint8_t *key)
01024 {
01025     SHALIB_init_HMAC(key, 32);
01026     SHALIB_push_data_HMAC(data_ptr, data_length);
01027     data_ptr += (data_length - 16);
01028     SHALIB_finish_HMAC(data_ptr, 4);
01029 }
01030 
01031 #ifdef ECC
01032 static void certificate_copy_block(const arm_certificate_chain_entry_s *rx_chain_info, certificate_chain_internal_t *cert)
01033 {
01034     uint8_t i;
01035     cert->chain_length = rx_chain_info->chain_length;
01036     for (i = 0; i < cert->chain_length; i++) {
01037         //Copy Certi
01038         cert->certi_chain[i] = rx_chain_info->cert_chain[i];
01039         cert->certi_len[i] = rx_chain_info->cert_len[i];
01040         //Copy Cur Key
01041         cert->key_chain[i] = rx_chain_info->key_chain[i];
01042     }
01043 }
01044 #endif
01045 
01046 int8_t pana_interface_certificate_chain_set(const arm_certificate_chain_entry_s *chain_info)
01047 {
01048 #ifdef ECC
01049     if (!chain_info) {
01050         return -1;
01051     }
01052     certificate_chain_internal_t temp_certi;
01053     certificate_copy_block(chain_info, &temp_certi);
01054     return x509_cetificate_chain_push(SEC_NWK_AUTHENTICATION_CERTI_CHAIN, &temp_certi);
01055 #else
01056     (void) chain_info;
01057     return -1;
01058 #endif
01059 }
01060 
01061 #endif /*PANA*/
01062 //************************ECC Certificates end
01063 
01064 /* end of file */