Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers eap_tls_sec_prot_lib.c Source File

eap_tls_sec_prot_lib.c

00001 /*
00002  * Copyright (c) 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 
00018 #include "nsconfig.h"
00019 #include <string.h>
00020 #include "ns_types.h"
00021 #include "ns_list.h"
00022 #include "ns_trace.h"
00023 #include "nsdynmemLIB.h"
00024 #include "common_functions.h"
00025 #include "fhss_config.h "
00026 #include "NWK_INTERFACE/Include/protocol.h"
00027 #include "6LoWPAN/ws/ws_config.h"
00028 #include "Security/kmp/kmp_addr.h"
00029 #include "Security/kmp/kmp_api.h"
00030 #include "Security/PANA/pana_eap_header.h"
00031 #include "Security/eapol/eapol_helper.h"
00032 #include "Security/protocols/sec_prot_certs.h"
00033 #include "Security/protocols/sec_prot_keys.h"
00034 #include "Security/protocols/sec_prot.h"
00035 #include "Security/protocols/sec_prot_lib.h"
00036 #include "Security/protocols/eap_tls_sec_prot/eap_tls_sec_prot_lib.h"
00037 
00038 #ifdef HAVE_WS
00039 
00040 #define TRACE_GROUP "eapl"
00041 
00042 static int8_t eap_tls_sec_prot_lib_ack_update(tls_data_t *tls);
00043 static uint8_t *eap_tls_sec_prot_lib_fragment_write(uint8_t *data, uint16_t total_len, uint16_t handled_len, uint16_t *message_len, uint8_t *flags);
00044 static int8_t eap_tls_sec_prot_lib_fragment_read(tls_data_t *tls, uint8_t *data, uint16_t len);
00045 
00046 const uint8_t eap_msg_trace[4][10] = {"REQ", "RESPONSE", "SUCCESS", "FAILURE"};
00047 
00048 int8_t eap_tls_sec_prot_lib_message_allocate(tls_data_t *data, uint8_t head_len, uint16_t len)
00049 {
00050     ns_dyn_mem_free(data->data);
00051 
00052     data->data = ns_dyn_mem_temporary_alloc(head_len + len);
00053     if (!data->data) {
00054         return -1;
00055     }
00056     data->total_len = len;
00057     data->handled_len = 0;
00058 
00059     return 0;
00060 }
00061 
00062 int8_t eap_tls_sec_prot_lib_message_realloc(tls_data_t *data, uint8_t head_len, uint16_t new_len)
00063 {
00064     tls_data_t new_tls_send;
00065 
00066     eap_tls_sec_prot_lib_message_init(&new_tls_send);
00067     if (eap_tls_sec_prot_lib_message_allocate(&new_tls_send, head_len, new_len) < 0) {
00068         return -1;
00069     }
00070     memcpy(new_tls_send.data + head_len, data->data + head_len, data->handled_len);
00071     new_tls_send.handled_len = data->handled_len;
00072     eap_tls_sec_prot_lib_message_free(data);
00073 
00074     *data = new_tls_send;
00075 
00076     return 0;
00077 }
00078 
00079 void eap_tls_sec_prot_lib_message_free(tls_data_t *data)
00080 {
00081     ns_dyn_mem_free(data->data);
00082     data->handled_len = 0;
00083     data->data = 0;
00084     data->total_len = 0;
00085 }
00086 
00087 void eap_tls_sec_prot_lib_message_init(tls_data_t *data)
00088 {
00089     data->handled_len = 0;
00090     data->data = 0;
00091     data->total_len = 0;
00092 }
00093 
00094 int8_t eap_tls_sec_prot_lib_message_handle(uint8_t *data, uint16_t length, bool new_seq_id, tls_data_t *tls_send, tls_data_t *tls_recv)
00095 {
00096     int8_t result = EAP_TLS_MSG_CONTINUE;
00097 
00098     // EAP-TLS start
00099     if (data[0] & EAP_TLS_START) {
00100         result = EAP_TLS_MSG_START;
00101     } else if (data[0] & EAP_TLS_MORE_FRAGMENTS) {
00102         // More fragments
00103         eap_tls_sec_prot_lib_message_allocate(tls_send, TLS_HEAD_LEN, 0);
00104 
00105         // Handles the length field
00106         if (data[0] & EAP_TLS_FRAGMENT_LENGTH) {
00107             if (length < 5) {
00108                 tr_error("EAP-TLS: decode error");
00109                 return EAP_TLS_MSG_DECODE_ERROR;
00110             }
00111 
00112             uint32_t len = common_read_32_bit(&data[1]);
00113 
00114             //For first fragment allocates data for incoming TLS packet
00115             if (!tls_recv->data) {
00116                 eap_tls_sec_prot_lib_message_allocate(tls_recv, 0, len);
00117             }
00118             length -= 4;
00119             data += 4;
00120         }
00121         result = EAP_TLS_MSG_MORE_FRAG;
00122     } else if (data[0] == 0 || data[0] == EAP_TLS_FRAGMENT_LENGTH) {
00123         // Skip fragment length if present
00124         if (data[0] & EAP_TLS_FRAGMENT_LENGTH) {
00125             if (length < 5) {
00126                 tr_error("EAP-TLS: decode error");
00127                 return EAP_TLS_MSG_DECODE_ERROR;
00128             }
00129             length -= 4;
00130             data += 4;
00131         }
00132         // Last (or only) fragment or fragment acknowledge. If sending data
00133         // updates acknowledged fragments.
00134         if (new_seq_id && eap_tls_sec_prot_lib_ack_update(tls_send)) {
00135             // All send, free data
00136             eap_tls_sec_prot_lib_message_allocate(tls_send, TLS_HEAD_LEN, 0);
00137             result = EAP_TLS_MSG_SEND_DONE;
00138         }
00139     }
00140 
00141     length -= 1;  // EAP-TLS flags
00142     data += 1;
00143 
00144     // No further processing for EAP-TLS start
00145     if (result == EAP_TLS_MSG_START) {
00146         return EAP_TLS_MSG_START;
00147     }
00148 
00149     // TLS data not included
00150     if (length == 0) {
00151         if (new_seq_id && result == EAP_TLS_MSG_CONTINUE) {
00152             // If received only EAP-TLS header fails, and is not
00153             // fragment acknowledge or last frame
00154             result = EAP_TLS_MSG_FAIL;
00155         }
00156 
00157         return result;
00158     }
00159 
00160     // New (not seen) sequence identifier, update received data
00161     if (new_seq_id) {
00162         if (!tls_recv->data) {
00163             eap_tls_sec_prot_lib_message_allocate(tls_recv, 0, length);
00164         }
00165         if (eap_tls_sec_prot_lib_fragment_read(tls_recv, data, length)) {
00166             result = EAP_TLS_MSG_RECEIVE_DONE;
00167         }
00168     }
00169 
00170     return result;
00171 }
00172 
00173 uint8_t *eap_tls_sec_prot_lib_message_build(uint8_t eap_code, uint8_t eap_type, uint8_t *flags, uint8_t eap_id_seq, uint8_t header_size, tls_data_t *tls_send, uint16_t *length)
00174 {
00175     uint16_t eap_len = 4;
00176     uint8_t *data_ptr = NULL;
00177 
00178     // Write EAP-TLS data (from EAP-TLS flags field onward)
00179     if (tls_send->data) {
00180         data_ptr = eap_tls_sec_prot_lib_fragment_write(tls_send->data + TLS_HEAD_LEN, tls_send->total_len, tls_send->handled_len, &eap_len, flags);
00181     }
00182 
00183     eapol_pdu_t eapol_pdu;
00184 
00185     *length = eapol_pdu_eap_frame_init(&eapol_pdu, eap_code, eap_id_seq, eap_type, eap_len, data_ptr);
00186 
00187     uint8_t *eapol_decoded_data = ns_dyn_mem_temporary_alloc(*length + header_size);
00188     if (!eapol_decoded_data) {
00189         return NULL;
00190     }
00191 
00192     eapol_write_pdu_frame(eapol_decoded_data + header_size, &eapol_pdu);
00193 
00194     return eapol_decoded_data;
00195 }
00196 
00197 static int8_t eap_tls_sec_prot_lib_ack_update(tls_data_t *tls)
00198 {
00199     if (!tls->data || !tls->total_len) {
00200         return false;
00201     }
00202 
00203     if (tls->handled_len + TLS_FRAGMENT_LEN < tls->total_len) {
00204         tls->handled_len += TLS_FRAGMENT_LEN;
00205         return false;
00206     }
00207 
00208     tls->handled_len = tls->total_len;
00209     return true;
00210 }
00211 
00212 static int8_t eap_tls_sec_prot_lib_fragment_read(tls_data_t *tls, uint8_t *data, uint16_t len)
00213 {
00214     if (tls->handled_len + len > tls->total_len) {
00215         return true;
00216     }
00217 
00218     memcpy(tls->data + tls->handled_len, data, len);
00219     tls->handled_len += len;
00220 
00221     if (tls->handled_len == tls->total_len) {
00222         return true;
00223     }
00224 
00225     return false;
00226 }
00227 
00228 static uint8_t *eap_tls_sec_prot_lib_fragment_write(uint8_t *data, uint16_t total_len, uint16_t handled_len, uint16_t *message_len, uint8_t *flags)
00229 {
00230     uint8_t *data_begin = data + handled_len;
00231 
00232     if (*flags != 0xff) {
00233         data_begin -= 1;
00234         *message_len += 1;
00235         data_begin[0] = *flags;
00236     }
00237 
00238     if (total_len - handled_len > TLS_FRAGMENT_LEN) {
00239         *message_len += TLS_FRAGMENT_LEN;
00240 
00241         if (handled_len == 0) {
00242             data_begin -= 4; // length
00243             *message_len += 4;
00244             *flags |= EAP_TLS_MORE_FRAGMENTS | EAP_TLS_FRAGMENT_LENGTH;
00245             data_begin[0] = *flags;
00246             common_write_32_bit(total_len, &data_begin[1]);
00247         } else {
00248             *flags |= EAP_TLS_MORE_FRAGMENTS;
00249             data_begin[0] = *flags;
00250         }
00251     } else {
00252         *message_len += total_len - handled_len;
00253     }
00254 
00255     return data_begin;
00256 }
00257 
00258 #endif /* HAVE_WS */
00259