Nicolas Borla / Mbed OS BBR_1Ebene
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pana.c Source File

pana.c

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