Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers eapol_helper.c Source File

eapol_helper.c

00001 /*
00002  * Copyright (c) 2018-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 
00019 
00020 #include "nsconfig.h"
00021 
00022 #include "ns_types.h"
00023 #include "eventOS_event.h"
00024 #include "ns_trace.h"
00025 #include "string.h"
00026 #include "common_functions.h"
00027 #include "Security/PANA/pana_eap_header.h"
00028 #include "Security/eapol/eapol_helper.h"
00029 
00030 #ifdef HAVE_WS
00031 
00032 #define KEY_INFO_VERSION_BIT_MASK   0x0007
00033 #define KEY_INFO_VERSION_BIT_SHIFT  0
00034 #define KEY_INFO_KEY_TYPE_BIT_MASK  0x0008
00035 #define KEY_INFO_KEY_TYPE_BIT_SHIFT 3
00036 #define KEY_INFO_INSTALL_BIT_MASK   0x0040
00037 #define KEY_INFO_INSTALL_BIT_SHIFT  6
00038 #define KEY_INFO_ACK_BIT_MASK       0x0080
00039 #define KEY_INFO_ACK_BIT_SHIFT      7
00040 #define KEY_INFO_MIC_MASK           0x0100
00041 #define KEY_INFO_MIC_SHIFT          8
00042 #define KEY_INFO_SECURE_MASK        0x0200
00043 #define KEY_INFO_SECURE_SHIFT       9
00044 #define KEY_INFO_ERROR_MASK         0x0400
00045 #define KEY_INFO_ERROR_SHIFT        10
00046 #define KEY_INFO_REQUEST_MASK       0x0800
00047 #define KEY_INFO_REQUEST_SHIFT      11
00048 #define KEY_INFO_ENC_KEY_DATA_MASK  0x1000
00049 #define KEY_INFO_ENC_KEY_DATA_SHIFT 12
00050 #define KEY_INFO_SMK_MASK           0x2000
00051 #define KEY_INFO_SMK_SHIFT          13
00052 
00053 static uint8_t *eapol_key_information_write(eapol_key_information_t *key_information, uint8_t *ptr)
00054 {
00055     uint16_t key_info = 0;
00056     key_info |= (key_information->description_version << KEY_INFO_VERSION_BIT_SHIFT);
00057     key_info |= (key_information->pairwise_key << KEY_INFO_KEY_TYPE_BIT_SHIFT);
00058     key_info |= (key_information->install << KEY_INFO_INSTALL_BIT_SHIFT);
00059     key_info |= (key_information->key_ack << KEY_INFO_ACK_BIT_SHIFT);
00060     key_info |= (key_information->key_mic << KEY_INFO_MIC_SHIFT);
00061     key_info |= (key_information->secured_key_frame << KEY_INFO_SECURE_SHIFT);
00062     key_info |= (key_information->error << KEY_INFO_ERROR_SHIFT);
00063     key_info |= (key_information->request << KEY_INFO_REQUEST_SHIFT);
00064     key_info |= (key_information->encrypted_key_data << KEY_INFO_ENC_KEY_DATA_SHIFT);
00065     key_info |= (key_information->smk_handshake << KEY_INFO_SMK_SHIFT);
00066     return common_write_16_bit(key_info, ptr);
00067 }
00068 
00069 static uint8_t *eapol_key_information_read(eapol_key_information_t *key_information, uint8_t *ptr)
00070 {
00071     uint16_t key_info = common_read_16_bit(ptr);
00072     key_information->description_version = ((key_info & KEY_INFO_VERSION_BIT_MASK) >> KEY_INFO_VERSION_BIT_SHIFT);
00073     key_information->pairwise_key = ((key_info & KEY_INFO_KEY_TYPE_BIT_MASK) >> KEY_INFO_KEY_TYPE_BIT_SHIFT);
00074     key_information->install = ((key_info & KEY_INFO_INSTALL_BIT_MASK) >> KEY_INFO_INSTALL_BIT_SHIFT);
00075     key_information->key_ack = ((key_info & KEY_INFO_ACK_BIT_MASK) >> KEY_INFO_ACK_BIT_SHIFT);
00076     key_information->key_mic = ((key_info & KEY_INFO_MIC_MASK) >> KEY_INFO_MIC_SHIFT);
00077     key_information->secured_key_frame = ((key_info & KEY_INFO_SECURE_MASK) >> KEY_INFO_SECURE_SHIFT);
00078     key_information->error = ((key_info & KEY_INFO_ERROR_MASK) >> KEY_INFO_ERROR_SHIFT);
00079     key_information->request = ((key_info & KEY_INFO_REQUEST_MASK) >> KEY_INFO_REQUEST_SHIFT);
00080     key_information->encrypted_key_data = ((key_info & KEY_INFO_ENC_KEY_DATA_MASK) >> KEY_INFO_ENC_KEY_DATA_SHIFT);
00081     key_information->smk_handshake = ((key_info & KEY_INFO_SMK_MASK) >> KEY_INFO_SMK_SHIFT);
00082     return ptr + 2;
00083 }
00084 
00085 
00086 static bool eapol_parse_eap_packet(eapol_pdu_t *eapol_pdu)
00087 {
00088     return eap_header_parse(eapol_pdu->packet_body, eapol_pdu->packet_length, &eapol_pdu->msg.eap);
00089 }
00090 
00091 
00092 static bool eapol_parse_key_packet(eapol_pdu_t *eapol_pdu)
00093 {
00094     if (eapol_pdu->packet_length < EAPOL_KEY_FRAME_BASE_SIZE) {
00095         return false;
00096     }
00097     uint8_t *ptr = eapol_pdu->packet_body;
00098     eapol_key_frame_t *key_frame = &eapol_pdu->msg.key;
00099     key_frame->key_description = *ptr++;
00100     if (key_frame->key_description != EAPOL_RSN_KEY_DESCRIPTION) {
00101         return false;
00102     }
00103     ptr = eapol_key_information_read(&key_frame->key_information, ptr);
00104     if (key_frame->key_information.description_version != KEY_DESCRIPTION_HMAC_SHA1_MIC_AES_ENC) {
00105         return false;
00106     }
00107     key_frame->key_length = common_read_16_bit(ptr);
00108     ptr += 2;
00109 
00110     key_frame->replay_counter = common_read_64_bit(ptr);
00111     ptr += 8;
00112 
00113     key_frame->key_nonce = ptr;
00114     ptr += 32;
00115 
00116     key_frame->key_iv = ptr;
00117     ptr += 16;
00118 
00119     key_frame->key_rsc = ptr;
00120     ptr += 16; //Skip 8 byte RSC + RESERVED 8
00121 
00122     key_frame->key_mic = ptr;
00123     ptr += 16;
00124 
00125     key_frame->key_data_length = common_read_16_bit(ptr);
00126     ptr += 2;
00127     key_frame->key_data = ptr;
00128     if (key_frame->key_data_length > (eapol_pdu->packet_length - EAPOL_KEY_FRAME_BASE_SIZE)) {
00129         return false;
00130     }
00131 
00132     return true;
00133 
00134 }
00135 
00136 void eapol_write_key_packet_mic(uint8_t *eapol_pdu, uint8_t *mic)
00137 {
00138     if (mic) {
00139         memcpy(&eapol_pdu[81], mic, 16);
00140     } else {
00141         memset(&eapol_pdu[81], 0, 16);
00142     }
00143 }
00144 
00145 bool eapol_parse_pdu_header(uint8_t *ptr, uint16_t data_length, eapol_pdu_t *eapol_pdu)
00146 {
00147     //Validate MIN length
00148     if (data_length < EAPOL_BASE_LENGTH) {
00149         return false;
00150     }
00151     //Validate Protocol version
00152     uint8_t protocol = *ptr++;
00153     if (protocol != EAPOL_PROTOCOL_VERSION) {
00154         return false;
00155     }
00156     eapol_pdu->packet_type = *ptr++;
00157     eapol_pdu->packet_length = common_read_16_bit(ptr);
00158     ptr += 2;
00159     //Validate Body Length
00160     if (eapol_pdu->packet_length > data_length - EAPOL_BASE_LENGTH) {
00161         return false;
00162     }
00163     eapol_pdu->packet_body = ptr;
00164 
00165     if (eapol_pdu->packet_type == EAPOL_EAP_TYPE) {
00166         return eapol_parse_eap_packet(eapol_pdu);
00167     } else if (eapol_pdu->packet_type == EAPOL_KEY_TYPE) {
00168         return eapol_parse_key_packet(eapol_pdu);
00169     } else {
00170         return false;
00171     }
00172 
00173 }
00174 
00175 uint8_t *eapol_write_pdu_frame(uint8_t *ptr, eapol_pdu_t *eapol_pdu)
00176 {
00177     *ptr++ = EAPOL_PROTOCOL_VERSION;
00178     *ptr++ = eapol_pdu->packet_type;
00179     ptr = common_write_16_bit(eapol_pdu->packet_length, ptr);
00180     eapol_pdu->packet_body = ptr;
00181 
00182     if (eapol_pdu->packet_type == EAPOL_EAP_TYPE) {
00183         eap_header_t *eap_header = &eapol_pdu->msg.eap;
00184         ptr = eap_header_build(ptr, eap_header->length, eap_header->eap_code, eap_header->id_seq, eap_header->type);
00185         memcpy(ptr, eap_header->data_ptr, eap_header->length - (ptr - eapol_pdu->packet_body));
00186         ptr += eap_header->length - (ptr - eapol_pdu->packet_body);
00187 
00188     } else if (eapol_pdu->packet_type == EAPOL_KEY_TYPE) {
00189         eapol_key_frame_t *key_frame = &eapol_pdu->msg.key;
00190         *ptr++ = key_frame->key_description;
00191         ptr = eapol_key_information_write(&key_frame->key_information, ptr);
00192         ptr = common_write_16_bit(key_frame->key_length, ptr);
00193         ptr = common_write_64_bit(key_frame->replay_counter, ptr);
00194 
00195         if (key_frame->key_nonce) {
00196             memcpy(ptr, key_frame->key_nonce, 32);
00197         } else {
00198             memset(ptr, 0, 32);
00199         }
00200         ptr += 32;
00201 
00202         if (key_frame->key_iv) {
00203             memcpy(ptr, key_frame->key_iv, 16);
00204         } else {
00205             memset(ptr, 0, 16);
00206         }
00207         ptr += 16;
00208 
00209         if (key_frame->key_rsc) {
00210             memcpy(ptr, key_frame->key_rsc, 8);
00211         } else {
00212             memset(ptr, 0, 8);
00213         }
00214         ptr += 8;
00215 
00216         //Reserved 8bytes
00217         memset(ptr, 0, 8);
00218         ptr += 8;
00219 
00220         if (key_frame->key_mic && key_frame->key_information.key_mic) {
00221             memcpy(ptr, key_frame->key_mic, 16);
00222         } else {
00223             memset(ptr, 0, 16);
00224         }
00225         ptr += 16;
00226         ptr = common_write_16_bit(key_frame->key_data_length, ptr);
00227         if (key_frame->key_data_length && key_frame->key_data) {
00228             memcpy(ptr, key_frame->key_data, key_frame->key_data_length);
00229             ptr += key_frame->key_data_length;
00230         }
00231     }
00232 
00233     return ptr;
00234 }
00235 
00236 
00237 
00238 uint16_t eapol_pdu_eap_frame_init(eapol_pdu_t *eapol_pdu, uint8_t eap_code, uint8_t id_seq, uint8_t type, uint16_t data_length, uint8_t *data_ptr)
00239 {
00240     memset(eapol_pdu, 0, sizeof(eapol_pdu_t));
00241 
00242     eapol_pdu->packet_type = EAPOL_EAP_TYPE;
00243     eapol_pdu->packet_length = data_length;
00244     eapol_pdu->msg.eap.eap_code = eap_code;
00245     eapol_pdu->msg.eap.data_ptr = data_ptr;
00246     eapol_pdu->msg.eap.length = data_length;
00247     eapol_pdu->msg.eap.id_seq = id_seq;
00248     eapol_pdu->msg.eap.type = type;
00249 
00250     if (eap_code == EAP_REQ || eap_code == EAP_RESPONSE) {
00251         eapol_pdu->packet_body += 5;
00252         eapol_pdu->msg.eap.length++; // Add space for type
00253         eapol_pdu->packet_length++;
00254     } else {
00255         eapol_pdu->packet_body += 4;
00256     }
00257 
00258     return eapol_pdu_total_length(eapol_pdu);
00259 
00260 }
00261 
00262 uint16_t eapol_pdu_key_frame_init(eapol_pdu_t *eapol_pdu, uint16_t data_length, uint8_t *data_ptr)
00263 {
00264     memset(eapol_pdu, 0, sizeof(eapol_pdu_t));
00265 
00266     eapol_pdu->packet_type = EAPOL_KEY_TYPE;
00267     eapol_pdu->packet_length = data_length + EAPOL_KEY_FRAME_BASE_SIZE;
00268     eapol_pdu->msg.key.key_data = data_ptr;
00269     eapol_pdu->msg.key.key_description = EAPOL_RSN_KEY_DESCRIPTION;
00270     eapol_pdu->msg.key.key_data_length = data_length;
00271     eapol_pdu->msg.key.key_information.description_version = KEY_DESCRIPTION_HMAC_SHA1_MIC_AES_ENC;
00272 
00273     return eapol_pdu_total_length(eapol_pdu);
00274 
00275 }
00276 
00277 uint8_t eapol_pdu_key_mask_get(eapol_pdu_t *eapol_pdu)
00278 {
00279     uint8_t key_mask = 0;
00280 
00281     if (eapol_pdu->msg.key.key_information.install) {
00282         key_mask |= KEY_INFO_INSTALL;
00283     }
00284     if (eapol_pdu->msg.key.key_information.key_ack) {
00285         key_mask |= KEY_INFO_KEY_ACK;
00286     }
00287     if (eapol_pdu->msg.key.key_information.key_mic) {
00288         key_mask |= KEY_INFO_KEY_MIC;
00289     }
00290     if (eapol_pdu->msg.key.key_information.secured_key_frame) {
00291         key_mask |= KEY_INFO_SECURED_KEY_FRAME;
00292     }
00293 
00294     return key_mask;
00295 }
00296 
00297 #endif
00298