EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers eap_protocol.c Source File

eap_protocol.c

00001 /*
00002  * Copyright (c) 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 
00018 
00019 #include "nsconfig.h"
00020 
00021 #include "ns_types.h"
00022 #include "eventOS_event.h"
00023 #include "ns_trace.h"
00024 #include "string.h"
00025 #include "Core/include/socket.h"
00026 #include "NWK_INTERFACE/Include/protocol.h"
00027 #include "6LoWPAN/Bootstraps/protocol_6lowpan.h"
00028 #include "6LoWPAN/Bootstraps/protocol_6lowpan_bootstrap.h"
00029 #ifdef ECC
00030 #include "libX509_V3.h"
00031 #include "ecc.h"
00032 #endif
00033 #include "Security/Common/sec_lib.h"
00034 #include "net_nvm_api.h"
00035 #include "Security/PANA/pana.h"
00036 
00037 #include "common_functions.h"
00038 #include "Security/PANA/pana_eap_header.h"
00039 #ifdef PANA
00040 
00041 #define TRACE_GROUP "eap"
00042 
00043 const uint8_t EAP_ANYMOUS[9] = {'a', 'n', 'o', 'n', 'y', 'm', 'o', 'u', 's'};
00044 
00045 static buffer_t *eap_common_headroom_get_to_buffer(buffer_t *buf, uint16_t header_size)
00046 {
00047     if ((buf = buffer_headroom(buf, header_size)) == 0) {
00048         return NULL;
00049     }
00050     buffer_data_reserve_header(buf, header_size);
00051     return buf;
00052 }
00053 
00054 void pana_eap_identity_build(buffer_t *buf, sec_suite_t *suite)
00055 {
00056     uint8_t *ptr;
00057     uint8_t eap_code;
00058     buf->buf_ptr  = 0;
00059     const uint8_t *nonce_ptr;
00060     if (suite->pana_session.user_server) {
00061         buf->buf_end  = 0;
00062         eap_code = EAP_REQ;
00063         nonce_ptr = suite->pana_session.pana_heap->agent_nonce;
00064     } else {
00065 
00066         buf->buf_end  = 9;
00067         ptr = buf->buf ;
00068         memcpy(ptr, EAP_ANYMOUS, 9);
00069         eap_code = EAP_RESPONSE;
00070         nonce_ptr = suite->pana_session.pana_heap->client_nonce;
00071     }
00072 
00073     buf = eap_common_headroom_get_to_buffer(buf, eap_header_size(eap_code));
00074     if (!buf) {
00075         return;
00076     }
00077 
00078     eap_header_build(buffer_data_pointer(buf), buffer_data_length(buf), eap_code, suite->pana_session.eap_id_seq, EAP_IDENTITY);
00079 
00080     pana_eap_payload_down(buf, nonce_ptr, suite);
00081     tr_warn("TX EAP Identity!");
00082 }
00083 
00084 void pana_eap_tls_start_build(buffer_t *buf, sec_suite_t *suite)
00085 {
00086     buf->buf_ptr  = 0;
00087     buf->buf_end  = 0;
00088     if (suite->tls_session->tls_heap) {
00089         tls_heap_t *tls_heap = suite->tls_session->tls_heap;
00090         tls_heap->tls_handshake_h_len = 0;
00091     }
00092 
00093     uint8_t header_size = eap_header_size(EAP_REQ);
00094     header_size += eap_tls_header_size(EAP_TLS_START);
00095 
00096     buf = eap_common_headroom_get_to_buffer(buf, header_size);
00097     if (!buf) {
00098         return;
00099     }
00100 
00101     uint8_t *ptr = eap_header_build(buffer_data_pointer(buf), buffer_data_length(buf),EAP_REQ, suite->pana_session.eap_id_seq, EAP_TLS);
00102 
00103     eap_tls_header_build(ptr, EAP_TLS_START, 0);
00104 
00105     pana_eap_payload_down(buf, NULL, suite);
00106 
00107 }
00108 
00109 
00110 void pana_eap_tls_finnish_build(buffer_t *buf, sec_suite_t *suite)
00111 {
00112     buffer_data_clear(buf);
00113     uint8_t eap_code;
00114     if (suite->state == TLS_ALERT) {
00115         eap_code = EAP_FAILURE;
00116     } else {
00117         eap_code = EAP_RESPONSE;
00118     }
00119 
00120 
00121     uint8_t header_size = eap_header_size(eap_code);
00122     header_size += eap_tls_header_size(0);
00123 
00124     buf = eap_common_headroom_get_to_buffer(buf, header_size);
00125     if (!buf) {
00126         return;
00127     }
00128 
00129     uint8_t *ptr = eap_header_build(buffer_data_pointer(buf), buffer_data_length(buf),eap_code, suite->pana_session.eap_id_seq, EAP_TLS);
00130 
00131     eap_tls_header_build(ptr, 0, 0);
00132 
00133     pana_eap_payload_down(buf, NULL, suite);
00134 }
00135 
00136 bool pana_eap_frag_re_tx(sec_suite_t *suite)
00137 {
00138     buffer_t *f_buf;
00139     if (suite->pana_session.eap_assy_buf) {
00140         buffer_t *buf = 0;
00141         f_buf = buffer_get(suite->pana_session.last_assy_size + 50);
00142         buf = suite->pana_session.eap_assy_buf;
00143         if (f_buf) {
00144             memcpy(buffer_data_pointer(f_buf), buffer_data_pointer(buf) + suite->pana_session.assy_off_set, suite->pana_session.last_assy_size);
00145             buffer_data_length_set(f_buf, suite->pana_session.last_assy_size);
00146             goto success_push;
00147         }
00148     } else if (suite->pana_session.eap_frag_buf) {
00149         f_buf = buffer_get(127);
00150         if (f_buf) {
00151 
00152             //tr_debug("EAP assembly re REQ timer");
00153             f_buf->buf_ptr  = f_buf->buf_end ;
00154             goto success_push;
00155         }
00156     }
00157     return false;
00158     success_push:
00159     f_buf->interface  = suite->interface;
00160     memcpy(f_buf->dst_sa .address , suite->session_address, 16);
00161     f_buf->src_sa .addr_type  = ADDR_NONE ;
00162     pana_eap_down(f_buf, suite);
00163     return true;
00164 }
00165 
00166 buffer_t *eap_down(buffer_t *buf, sec_suite_t *suite)
00167 {
00168     //tr_debug("EAP Down");
00169     uint16_t tls_payload_len = 0;
00170     uint8_t eap_code;
00171     uint8_t eap_tls_flags = 0;
00172     tls_payload_len = buffer_data_length(buf);
00173     if (tls_payload_len >  EAP_MTU_SIZE) {
00174         //Check Fragmentation
00175         if (suite->pana_session.assy_length) {
00176             tr_debug("Already Fragmentation");
00177             buffer_free(buf);
00178             buf = (buffer_t *)0;
00179             return buf;
00180         } else {
00181             pana_lib_parameters_s *parameters = pana_parameters_get();
00182 
00183             buffer_t *f_buf = buffer_get(parameters->EAP_FRAGMENT_SIZE + 50);
00184             buf->seq  = suite->pana_session.eap_id_seq;
00185             suite->pana_session.eap_assy_buf  = buf;
00186             suite->pana_session.assy_length = tls_payload_len;
00187             suite->pana_session.assy_off_set = 0;
00188             suite->pana_session.last_assy_size = parameters->EAP_FRAGMENT_SIZE;
00189             if (suite->pana_session.user_server) {
00190                 //tr_debug("Set Re Tx Timer");
00191                 pana_timeout_timer_set(suite, suite->state);
00192             } else {
00193                 sec_set_auth_timeout(suite,TLS_KEY_CHANGE);
00194             }
00195             if (f_buf) {
00196                 f_buf->interface  = suite->interface;
00197                 eap_tls_flags = EAP_TLS_FRAGMENT_LENGTH | EAP_TLS_MORE_FRAGMENTS;
00198                 memcpy(buffer_data_pointer(f_buf), buffer_data_pointer(buf), parameters->EAP_FRAGMENT_SIZE);
00199                 memcpy(f_buf->dst_sa .address , buf->src_sa .address , 16);
00200                 buf->src_sa .addr_type  = ADDR_NONE ;
00201                 f_buf->src_sa .addr_type  = ADDR_NONE ;
00202                 buffer_data_length_set(f_buf, parameters->EAP_FRAGMENT_SIZE);
00203                 buf = f_buf;
00204 
00205             } else {
00206                 return NULL;
00207             }
00208         }
00209     } else {
00210         if (suite->pana_session.assy_length) {
00211             if (suite->pana_session.assy_length > (suite->pana_session.assy_off_set + suite->pana_session.last_assy_size)) {
00212                 eap_tls_flags = EAP_TLS_MORE_FRAGMENTS;
00213                 if (suite->pana_session.assy_off_set == 0) {
00214                     eap_tls_flags |= EAP_TLS_FRAGMENT_LENGTH;
00215                     //tr_debug("Retry First");
00216                 }
00217             }
00218         }
00219     }
00220 
00221     if (suite->pana_session.user_server) {
00222         eap_code = EAP_REQ;
00223     } else {
00224         eap_code = EAP_RESPONSE;
00225     }
00226 
00227     uint8_t header_size = eap_header_size(eap_code);
00228     header_size += eap_tls_header_size(eap_tls_flags);
00229 
00230     buf = eap_common_headroom_get_to_buffer(buf, header_size);
00231     if (!buf) {
00232         return NULL;
00233     }
00234 
00235     uint8_t *ptr = eap_header_build(buffer_data_pointer(buf), buffer_data_length(buf),eap_code, suite->pana_session.eap_id_seq, EAP_TLS);
00236 
00237     eap_tls_header_build(ptr, eap_tls_flags, suite->pana_session.assy_length);
00238 
00239     return (buf);
00240 }
00241 
00242 buffer_t *eap_up(buffer_t *buf, sec_suite_t *suite)
00243 {
00244     uint8_t *ptr = buffer_data_pointer(buf);
00245     uint16_t payload_length = buffer_data_length(buf);
00246     eap_header_t header;
00247     if (!eap_header_parse(ptr, payload_length, &header)) {
00248         return buffer_free(buf);
00249     }
00250 
00251     if (header.eap_code == EAP_RESPONSE) {
00252         if (header.id_seq != suite->pana_session.eap_id_seq) {
00253             tr_warn("EAP:Drop Packet by ID");
00254             suite->timer = 65;
00255             return buffer_free(buf);
00256         }
00257         //tr_debug("EAP RES");
00258         suite->pana_session.eap_id_seq++;
00259         suite->retry_counter = 0;
00260     } else if (header.eap_code == EAP_REQ) {
00261 
00262         if (header.type == EAP_IDENTITY) {
00263             suite->pana_session.eap_id_seq = header.id_seq;
00264         } else {
00265 
00266             uint8_t eap_seq = suite->pana_session.eap_id_seq;
00267             if (eap_seq == 0xff) {
00268                 eap_seq = 0;
00269             } else {
00270                 eap_seq++;
00271             }
00272 
00273             if (eap_seq != header.id_seq) {
00274                 if (suite->pana_session.eap_id_seq == header.id_seq) {
00275                     //tr_debug("EAP:Same SEQ");
00276                     if (suite->pana_session.assy_length) {
00277                         tr_debug("SEND ACK. Should send same packet again");
00278                     } else if (suite->pana_session.frag_length) {
00279                         tr_debug("SEND ACK. Should send same packet again");
00280                         buf->buf_ptr  = buf->buf_end ;
00281                         buf = buffer_turnaround(buf);
00282                         memcpy(buf->dst_sa .address , buf->src_sa .address , 16);
00283                         buf->src_sa .addr_type  = ADDR_NONE ;
00284                         return buf;
00285                     } else {
00286                         tr_debug("REQ but Frag ready");
00287                         return buffer_free(buf);
00288                     }
00289                 } else {
00290                     tr_debug("EAP:Drop unknown Req ID. MSG: %x, ses: %x", header.id_seq, suite->pana_session.eap_id_seq);
00291                     return buffer_free(buf);
00292                 }
00293             } else {
00294                suite->pana_session.eap_id_seq = header.id_seq;
00295             }
00296         }
00297     }
00298 
00299     switch (header.type) {
00300         case EAP_IDENTITY:
00301             if (header.eap_code == EAP_REQ) {
00302                 sec_lib_state_machine_trig(suite, EAP_IDENTITY_RES);
00303             } else {
00304 #ifdef PANA_SERVER_API
00305                 if (suite->pana_session.user_server) {
00306                     sec_lib_state_machine_trig(suite, TLS_START);
00307                 }
00308 #endif
00309             }
00310             return buffer_free(buf);
00311 
00312         case EAP_TLS:
00313         case EAP_TTLS: {
00314             eap_tls_header_t eap_tls_header;
00315             if (!eap_tls_header_parse(header.data_ptr, header.length -5, &eap_tls_header) ) {
00316                 return buffer_free(buf);
00317             }
00318 
00319             if (eap_tls_header.eap_tls_flags & EAP_TLS_START) {
00320                 suite->pana_session.eap_id_seq = header.id_seq;
00321                 sec_lib_state_machine_trig(suite, TLS_INIT);
00322                 return buffer_free(buf);
00323             }
00324             buffer_data_pointer_set(buf, eap_tls_header.data_ptr);
00325 
00326             if (header.eap_code == EAP_RESPONSE) {
00327                 if (eap_tls_header.eap_tls_flags) {
00328                     if (suite->pana_session.assy_length) {
00329                         suite->pana_session.assy_off_set += suite->pana_session.last_assy_size;
00330                         if (suite->pana_session.assy_off_set < suite->pana_session.assy_length) {
00331                             tr_warn("Packet TX process fail");
00332                         } else {
00333                             tr_debug("EAP Frag TX Done & Start RX frag");
00334 
00335                         }
00336                         //tr_debug("Free Frag Buf");
00337                         if (suite->pana_session.eap_assy_buf) {
00338                             tr_debug("Free Frag Buf");
00339                             buffer_free(suite->pana_session.eap_assy_buf);
00340                             suite->pana_session.eap_assy_buf  = 0;
00341                         }
00342                         suite->pana_session.assy_length = 0;
00343                         suite->pana_session.assy_off_set = 0;
00344                         suite->pana_session.last_assy_size = 0;
00345                     }
00346                 }
00347             }
00348 
00349             if ((eap_tls_header.eap_tls_flags & EAP_TLS_MORE_FRAGMENTS) == 0) {
00350                 if (suite->pana_session.frag_length) {
00351                     buffer_t *t_buf = suite->pana_session.eap_frag_buf;
00352 
00353                     uint16_t check_len = suite->pana_session.frag_off_set;
00354                     check_len += eap_tls_header.tls_frame_length;
00355                     suite->pana_session.eap_frag_buf = NULL;
00356                     suite->pana_session.frag_length = 0;
00357                     if (check_len == buffer_data_length(t_buf)) {
00358                         memcpy(buffer_data_pointer(t_buf) + suite->pana_session.frag_off_set, eap_tls_header.data_ptr, eap_tls_header.tls_frame_length);
00359                         t_buf->seq  = header.id_seq;
00360                         tr_debug("Full packet RX");
00361                         buffer_free(buf);
00362                         buf = t_buf;
00363                         suite->pana_session.frag_off_set = 0;
00364                     } else {
00365 
00366                         buffer_free(t_buf);
00367                         suite->pana_session.frag_off_set = 0;
00368                         sec_lib_state_machine_trig(suite, TLS_ALERT_INTERNAL);
00369                         return buffer_free(buf);
00370                     }
00371                 } else if (suite->pana_session.assy_length) {
00372                     buffer_t *t_buf = suite->pana_session.eap_assy_buf;
00373                     if (header.eap_code == EAP_RESPONSE) {
00374                         suite->pana_session.assy_off_set += suite->pana_session.last_assy_size;
00375                         if (eap_tls_header.tls_frame_length == 0) {
00376                             t_buf->seq  = header.id_seq;
00377                         }
00378                     } else {
00379                         uint8_t cmp_seq = t_buf->seq ;
00380                         if (cmp_seq == 0xff) {
00381                             cmp_seq = 0;
00382                         } else {
00383                             cmp_seq++;
00384                         }
00385                         if (cmp_seq == header.id_seq) {
00386                             suite->pana_session.assy_off_set += suite->pana_session.last_assy_size;
00387                             if (eap_tls_header.tls_frame_length == 0) {
00388                                 t_buf->seq  = header.id_seq;
00389                             }
00390                         } else {
00391                             tr_debug("RETX");
00392                         }
00393                     }
00394                     if (suite->pana_session.assy_off_set < suite->pana_session.assy_length) {
00395                         if (eap_tls_header.tls_frame_length == 0) {
00396                             uint16_t len = 0;
00397                             buffer_t *f_buf = 0;
00398                             buffer_free(buf);
00399                             suite->retry_counter = 0;
00400                             pana_lib_parameters_s *parameters = pana_parameters_get();
00401                             if (suite->pana_session.assy_off_set + parameters->EAP_FRAGMENT_SIZE < suite->pana_session.assy_length) {
00402                                 len = parameters->EAP_FRAGMENT_SIZE;
00403                             } else {
00404                                 len = suite->pana_session.assy_length - suite->pana_session.assy_off_set;
00405                             }
00406 
00407                             f_buf = buffer_get(len + 50);
00408                             if (f_buf) {
00409                                 //memcpy(f_buf->dst_sa.address, t_buf->src_sa.address, 16);
00410                                 f_buf->interface  = suite->interface;
00411                                 f_buf->src_sa .addr_type  = ADDR_NONE ;
00412                                 f_buf->dst_sa .addr_type  = ADDR_NONE ;
00413                                 memcpy(buffer_data_pointer(f_buf), buffer_data_pointer(t_buf) + suite->pana_session.assy_off_set, len);
00414                                 buffer_data_length_set(f_buf, len);
00415                                 suite->pana_session.last_assy_size = len;
00416                                 tr_debug("Push frag");
00417                                 return (f_buf);
00418                             } else {
00419                                 tr_warn("No Mem");
00420                                 return NULL;
00421                             }
00422                         } else {
00423                             //IT cuold be alert
00424                             buf->session_ptr = suite;
00425                             eap_tls_payload_push(buf);
00426                             return NULL;
00427                         }
00428                     } else {
00429                         tr_debug("EAP Frag TX Done");
00430                         suite->pana_session.eap_assy_buf  = buffer_free(t_buf);
00431                         suite->pana_session.assy_length = 0;
00432                         suite->pana_session.assy_off_set = 0;
00433                         suite->pana_session.last_assy_size = 0;
00434                     }
00435                 } else if (!eap_tls_header.tls_frame_length) {
00436                     if (header.eap_code == EAP_RESPONSE) {
00437 #ifdef PANA_SERVER_API
00438                         if (suite->state == TLS_KEY_CHANGE && suite->pana_session.user_server) {
00439                             //tr_debug("TLS Auth Ready");
00440                             pana_key_calculation(suite);
00441                             sec_lib_state_machine_trig(suite, TLS_EAP_END_PANA_VERIFY);
00442                         }
00443 #endif
00444                     }
00445 
00446                     return buffer_free(buf);
00447                 }
00448                 buf->session_ptr = suite;
00449                 eap_tls_payload_push(buf);
00450                 return NULL;
00451 
00452             }
00453 
00454             //More flag is active
00455             if (!eap_tls_header.tls_frame_length) {
00456                 tr_debug("More without Data");
00457                 return buffer_free(buf);
00458             }
00459             bool skip_packet = false;
00460 
00461             if (eap_tls_header.tls_length) {
00462                 //Check did we have a already action
00463                 if (suite->pana_session.frag_length == 0) {
00464 
00465                     buffer_t *f_buf = buffer_get(eap_tls_header.tls_length);
00466                     tr_debug("First Fragment");
00467                     if (f_buf) {
00468                         buffer_data_length_set(f_buf, eap_tls_header.tls_length);
00469                         memcpy(buffer_data_pointer(f_buf), eap_tls_header.data_ptr, eap_tls_header.tls_frame_length);
00470                         suite->pana_session.frag_off_set = eap_tls_header.tls_frame_length;
00471                         f_buf->seq  = header.id_seq;
00472                         suite->pana_session.eap_frag_buf = f_buf;
00473                         suite->pana_session.frag_length = eap_tls_header.tls_length;
00474                         skip_packet = true;
00475                     } else {
00476                         tr_debug("No free men for Fragment: %i", eap_tls_header.tls_length);
00477                         sec_lib_state_machine_trig(suite, TLS_ALERT_INTERNAL);
00478                         return buffer_free(buf);
00479                     }
00480                 } else if (suite->pana_session.frag_length != eap_tls_header.tls_length) {
00481                     tr_debug("Fragment started already");
00482                     skip_packet = true;
00483                 } else {
00484 
00485                 }
00486             }
00487 
00488             if (!skip_packet && suite->pana_session.frag_length) {
00489                 uint16_t check_len = 0;
00490                 buffer_t *t_buf = suite->pana_session.eap_frag_buf;
00491                 check_len = suite->pana_session.frag_off_set;
00492                 check_len += eap_tls_header.tls_frame_length;
00493 
00494                 //new sequency
00495                 if (check_len < buffer_data_length(t_buf)) {
00496                     tr_debug("Copy Data to Fragment");
00497                     memcpy(buffer_data_pointer(t_buf) + suite->pana_session.frag_off_set, eap_tls_header.data_ptr, eap_tls_header.tls_frame_length);
00498                     suite->pana_session.frag_off_set += eap_tls_header.tls_frame_length;
00499                     t_buf->seq  = suite->pana_session.eap_id_seq;
00500                 } else {
00501                     tr_debug("Overflow possible Free Current entry and set Alert");
00502                     buffer_free(t_buf);
00503                     suite->pana_session.eap_frag_buf = NULL;
00504                     suite->pana_session.frag_length = 0;
00505                     suite->pana_session.frag_off_set = 0;
00506                     sec_lib_state_machine_trig(suite, TLS_ALERT_INTERNAL);
00507                     return buffer_free(buf);
00508                 }
00509             }
00510 
00511             if (header.eap_code == EAP_RESPONSE) {
00512 #ifdef PANA_SERVER_API
00513                 if (suite->state == TLS_TX_SERVER_KEY_EXCHANGE) {
00514                     if (suite->pana_session.assy_length) {
00515                         suite->retry_counter = 0;
00516                     }
00517                 }
00518 #endif
00519                 pana_timeout_timer_set(suite, suite->state);
00520             }
00521             /* TX ACK or new request to sender*/
00522             buf = buffer_turnaround(buf);
00523             buf->buf_ptr  = buf->buf_end ;
00524             memcpy(buf->dst_sa .address , buf->src_sa .address , 16);
00525             buf->src_sa .addr_type  = ADDR_NONE ;
00526             return (buf);
00527         }
00528 
00529 
00530         default:
00531             tr_debug("%x", header.type);
00532             return buffer_free(buf);
00533     }
00534 }
00535 #endif