Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers kde_helper.c Source File

kde_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 #include "nsconfig.h"
00019 #include "ns_types.h"
00020 #include "eventOS_event.h"
00021 #include "ns_trace.h"
00022 #include "string.h"
00023 #include "common_functions.h"
00024 #include "Security/eapol/kde_helper.h"
00025 
00026 #ifdef HAVE_WS
00027 
00028 #define TRACE_GROUP "kdeh"
00029 
00030 #define IEEE_802_11_OUI          ieee_802_11_oui
00031 #define WISUN_OUI                wisun_oui
00032 
00033 const uint8_t ieee_802_11_oui[3] = {0x00, 0x0F, 0xAC};
00034 const uint8_t wisun_oui[3] = {0x0C, 0x5A, 0x9E};
00035 
00036 #define KDE_TYPE    0xdd
00037 
00038 // IEEE 802.11
00039 #define KDE_GTK                  0x01
00040 #define KDE_PMKID                0x04
00041 #define KDE_LIFETIME             0x07
00042 // Wi-Sun
00043 #define KDE_PTKID                0x01
00044 #define KDE_GTKL                 0x02
00045 
00046 #define GTK_LEN                  16
00047 #define PMKID_LEN                16
00048 #define PTKID_LEN                16
00049 
00050 #define KDE_MIN_LEN              6
00051 #define KDE_FIXED_LEN            2
00052 
00053 #define KDE_PADDED_MIN_LEN       16
00054 
00055 #define KDE_TYPE_INDEX           0
00056 #define KDE_LENGTH_INDEX         1
00057 #define KDE_OUI1_INDEX           2
00058 #define KDE_OUI2_INDEX           3
00059 #define KDE_OUI3_INDEX           4
00060 #define KDE_DATA_TYPE_INDEX      5
00061 #define KDE_DATA_INDEX           6
00062 
00063 /*
00064     From IEEE 802.11 chapter 11.6.2 EAPOL-Key frames
00065 
00066     If the Encrypted Key Data subfield (of the Key Information field) is 1,
00067     the entire Key Data field shall be encrypted. If the Key Data field
00068     uses the NIST AES key wrap, then the Key Data field shall be padded before
00069     encrypting if the key data length is less than 16 octets or if it is not
00070     a multiple of 8.
00071     The padding consists of appending a single octet 0xdd followed by zero
00072     or more 0x00 octets. When processing a received EAPOL-Key message, the
00073     receiver shall ignore this trailing padding.
00074 */
00075 uint16_t kde_padded_length_calc(uint16_t kde_length)
00076 {
00077     if (kde_length < KDE_PADDED_MIN_LEN) {
00078         return KDE_PADDED_MIN_LEN;
00079     }
00080 
00081     return ((kde_length + 7) / 8) * 8;
00082 }
00083 
00084 void kde_padding_write(uint8_t *start_ptr, uint8_t *end_ptr)
00085 {
00086     uint8_t padding = 0xdd;
00087 
00088     while (start_ptr < end_ptr) {
00089         *start_ptr++ = padding;
00090         padding = 0x00;
00091     }
00092 }
00093 
00094 static uint8_t *kde_header_write(uint8_t *ptr, const uint8_t *oui, uint8_t data_type, uint8_t data_length)
00095 {
00096     *ptr++ = KDE_TYPE;
00097     *ptr++ = data_length - KDE_FIXED_LEN;
00098     *ptr++ = oui[0];
00099     *ptr++ = oui[1];
00100     *ptr++ = oui[2];
00101     *ptr++ = data_type;
00102 
00103     return ptr;
00104 }
00105 
00106 static const uint8_t *kde_search(const uint8_t *ptr, uint16_t len, const uint8_t *oui, uint8_t data_type, uint16_t kde_min_len)
00107 {
00108     while (len >= KDE_MIN_LEN) {
00109         uint16_t kde_len = ptr[1] + KDE_FIXED_LEN;
00110 
00111         // For the type 0xdd the length shall be at least 6 */
00112         if ((ptr[KDE_TYPE_INDEX] == 0xdd && kde_len < KDE_MIN_LEN) || kde_len > len) {
00113             return NULL;
00114         }
00115 
00116         if (kde_len >= kde_min_len && ptr[KDE_OUI1_INDEX] == oui[0] && ptr[KDE_OUI2_INDEX] == oui[1]
00117                 && ptr[KDE_OUI3_INDEX] == oui[2] && ptr[KDE_DATA_TYPE_INDEX] == data_type) {
00118             return &ptr[KDE_DATA_INDEX];
00119         }
00120 
00121         if (len > kde_len) {
00122             len -= kde_len;
00123             ptr += kde_len;
00124         } else {
00125             return NULL;
00126         }
00127     }
00128 
00129     return NULL;
00130 }
00131 
00132 uint8_t *kde_gtk_write(uint8_t *ptr, uint8_t key_id, const uint8_t *gtk)
00133 {
00134     ptr = kde_header_write(ptr, IEEE_802_11_OUI, KDE_GTK, KDE_GTK_LEN);
00135 
00136     // bits 0-1: keyid (0,1,2, or 3), bit 2: Tx, other: reserved (0)
00137     *ptr++ = key_id;
00138     *ptr++ = 0x00; // reserved
00139     memcpy(ptr, gtk, GTK_LEN);
00140     ptr += GTK_LEN;
00141 
00142     return ptr;
00143 }
00144 
00145 uint8_t *kde_pmkid_write(uint8_t *ptr, const uint8_t *pmkid)
00146 {
00147     ptr = kde_header_write(ptr, IEEE_802_11_OUI, KDE_PMKID, KDE_PMKID_LEN);
00148 
00149     memcpy(ptr, pmkid, PMKID_LEN);
00150     ptr += PMKID_LEN;
00151 
00152     return ptr;
00153 }
00154 
00155 uint8_t *kde_ptkid_write(uint8_t *ptr, const uint8_t *ptkid)
00156 {
00157     ptr = kde_header_write(ptr, WISUN_OUI, KDE_PTKID, KDE_PTKID_LEN);
00158 
00159     memcpy(ptr, ptkid, PTKID_LEN);
00160     ptr += PTKID_LEN;
00161 
00162     return ptr;
00163 }
00164 
00165 uint8_t *kde_lifetime_write(uint8_t *ptr, uint32_t lifetime)
00166 {
00167     ptr = kde_header_write(ptr, IEEE_802_11_OUI, KDE_LIFETIME, KDE_LIFETIME_LEN);
00168     ptr = common_write_32_bit(lifetime, ptr);
00169 
00170     return ptr;
00171 }
00172 
00173 uint8_t *kde_gtkl_write(uint8_t *ptr, uint8_t gtkl)
00174 {
00175     ptr = kde_header_write(ptr, WISUN_OUI, KDE_GTKL, KDE_GTKL_LEN);
00176     *ptr++ = gtkl;
00177 
00178     return ptr;
00179 }
00180 
00181 int8_t kde_gtk_read(const uint8_t *ptr, uint16_t len, uint8_t *key_id, uint8_t *gtk)
00182 {
00183     ptr = kde_search(ptr, len, IEEE_802_11_OUI, KDE_GTK, KDE_GTK_LEN);
00184     if (ptr == NULL) {
00185         return -1;
00186     }
00187 
00188     *key_id = *ptr++ & 0x03;
00189     ptr++;
00190     memcpy(gtk, ptr, GTK_LEN);
00191 
00192     return 0;
00193 }
00194 
00195 int8_t kde_pmkid_read(const uint8_t *ptr, uint16_t len, uint8_t *pmkid)
00196 {
00197     ptr = kde_search(ptr, len, IEEE_802_11_OUI, KDE_PMKID, KDE_PMKID_LEN);
00198     if (ptr == NULL) {
00199         return -1;
00200     }
00201 
00202     memcpy(pmkid, ptr, PMKID_LEN);
00203 
00204     return 0;
00205 }
00206 
00207 int8_t kde_ptkid_read(const uint8_t *ptr, uint16_t len, uint8_t *ptkid)
00208 {
00209     ptr = kde_search(ptr, len, WISUN_OUI, KDE_PTKID, KDE_PTKID_LEN);
00210     if (ptr == NULL) {
00211         return -1;
00212     }
00213 
00214     memcpy(ptkid, ptr, PTKID_LEN);
00215 
00216     return 0;
00217 }
00218 
00219 int8_t kde_lifetime_read(const uint8_t *ptr, uint16_t len, uint32_t *lifetime)
00220 {
00221     ptr = kde_search(ptr, len, IEEE_802_11_OUI, KDE_LIFETIME, KDE_LIFETIME_LEN);
00222     if (ptr == NULL) {
00223         return -1;
00224     }
00225 
00226     *lifetime = common_read_32_bit(ptr);
00227 
00228     return 0;
00229 }
00230 
00231 int8_t kde_gtkl_read(const uint8_t *ptr, uint16_t len, uint8_t *gtkl)
00232 {
00233     ptr = kde_search(ptr, len, WISUN_OUI, KDE_GTKL, KDE_GTKL_LEN);
00234     if (ptr == NULL) {
00235         return -1;
00236     }
00237 
00238     *gtkl = *ptr;
00239 
00240     return 0;
00241 }
00242 
00243 #endif
00244