Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ws_pae_nvm_data.c Source File

ws_pae_nvm_data.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 "6LoWPAN/ws/ws_config.h"
00026 #include "ns_file_system.h"
00027 #include "Security/protocols/sec_prot_certs.h"
00028 #include "Security/protocols/sec_prot_keys.h"
00029 #include "6LoWPAN/ws/ws_pae_nvm_store.h"
00030 #include "6LoWPAN/ws/ws_pae_nvm_data.h"
00031 
00032 #ifdef HAVE_WS
00033 
00034 #define TRACE_GROUP "wsnv"
00035 
00036 #define PAE_NVM_NW_INFO_TAG              1
00037 #define PAE_NVM_KEYS_TAG                 2
00038 #define PAE_NVM_FRAME_COUNTER_TAG        3
00039 
00040 // pan_id (2) + network name (33) + (GTK set (1) + GTK lifetime (4) + GTK (16)) * 4
00041 #define PAE_NVM_NW_INFO_LEN              2 + 33 + (1 + 4 + GTK_LEN) * GTK_NUM
00042 
00043 // PTK EUI-64 set (1) + PTK EUI-64 (8) + PMK set (1) + PMK (32) + PMK replay counter (8) + PTK set (1) + PTK (48)
00044 #define PAE_NVM_KEYS_LEN                 1 + 8 + 1 + PMK_LEN + 8 + 1 + PTK_LEN
00045 
00046 // (frame counter set (1) + GTK (16) + frame counter (4)) * 4
00047 #define PAE_NVM_FRAME_COUNTER_LEN        (1 + GTK_LEN + 4) * GTK_NUM
00048 
00049 #define PAE_NVM_FIELD_NOT_SET            0   // Field is not present
00050 #define PAE_NVM_FIELD_SET                1   // Field is present
00051 
00052 nvm_tlv_entry_t *ws_pae_buffer_allocate(void)
00053 {
00054     //Allocate worts case buffer
00055     return ns_dyn_mem_temporary_alloc(sizeof(nvm_tlv_entry_t) + PAE_NVM_NW_INFO_LEN);
00056 }
00057 
00058 void ws_pae_nvm_store_nw_info_tlv_create(nvm_tlv_entry_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks)
00059 {
00060 
00061     tlv_entry->tag = PAE_NVM_NW_INFO_TAG;
00062     tlv_entry->len = PAE_NVM_NW_INFO_LEN;
00063 
00064     uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
00065 
00066     tlv = common_write_16_bit(pan_id, tlv);
00067 
00068     memset(tlv, 0, 33);
00069     strncpy((char *)tlv, nw_name, 32);
00070     tlv += 33;
00071 
00072     for (uint8_t i = 0; i < GTK_NUM; i++) {
00073         if (sec_prot_keys_gtk_is_set(gtks, i)) {
00074             *tlv++ = PAE_NVM_FIELD_SET; // GTK is set
00075             uint32_t lifetime = sec_prot_keys_gtk_lifetime_get(gtks, i);
00076             tlv = common_write_32_bit(lifetime, tlv);
00077 
00078             uint8_t *gtk = sec_prot_keys_gtk_get(gtks, i);
00079             memcpy(tlv, gtk, GTK_LEN);
00080             tlv += GTK_LEN;
00081         } else {
00082             *tlv++ = PAE_NVM_FIELD_NOT_SET; // GTK is not set
00083             memset(tlv, 0, 4 + GTK_LEN);
00084             tlv += 4 + GTK_LEN;
00085         }
00086     }
00087 
00088     tr_debug("NVM NW_INFO write PAN ID %i name: %s", pan_id, nw_name);
00089 
00090 }
00091 
00092 int8_t ws_pae_nvm_store_nw_info_tlv_read(nvm_tlv_entry_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks)
00093 {
00094     if (!tlv_entry || !pan_id || !nw_name || !gtks) {
00095         return -1;
00096     }
00097 
00098     if (tlv_entry->tag != PAE_NVM_NW_INFO_TAG || tlv_entry->len != PAE_NVM_NW_INFO_LEN) {
00099         return -1;
00100     }
00101 
00102     uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
00103 
00104     *pan_id = common_read_16_bit(tlv);
00105     tlv += 2;
00106 
00107     memset(nw_name, 0, 33);
00108     strncpy(nw_name, (char *) tlv, 32);
00109     tlv += 33;
00110 
00111     for (uint8_t i = 0; i < GTK_NUM; i++) {
00112         if (*tlv++ == PAE_NVM_FIELD_SET) { /* GTK is set */
00113             uint32_t lifetime = common_read_32_bit(tlv);
00114             tlv += 4;
00115             sec_prot_keys_gtk_set(gtks, i, tlv, lifetime);
00116             tlv += GTK_LEN;
00117         } else {
00118             tlv += 4 + GTK_LEN;
00119         }
00120     }
00121     sec_prot_keys_gtks_updated_reset(gtks);
00122 
00123     tr_debug("NVM NW_INFO read PAN ID %i name: %s", *pan_id, nw_name);
00124 
00125     return 0;
00126 }
00127 
00128 void ws_pae_nvm_store_keys_tlv_create(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_t *sec_keys)
00129 {
00130     tlv_entry->tag = PAE_NVM_KEYS_TAG;
00131     tlv_entry->len = PAE_NVM_KEYS_LEN;
00132 
00133     uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
00134 
00135     uint8_t *eui_64 = sec_prot_keys_ptk_eui_64_get(sec_keys);
00136     if (eui_64) {
00137         *tlv++ = PAE_NVM_FIELD_SET;
00138         memcpy(tlv, eui_64, 8);
00139     } else {
00140         *tlv++ = PAE_NVM_FIELD_NOT_SET;
00141         memset(tlv, 0, 8);
00142     }
00143     tlv += 8;
00144 
00145     uint8_t *pmk = sec_prot_keys_pmk_get(sec_keys);
00146     if (pmk) {
00147         *tlv++ = PAE_NVM_FIELD_SET;
00148         memcpy(tlv, pmk, PMK_LEN);
00149     } else {
00150         *tlv++ = PAE_NVM_FIELD_NOT_SET;
00151         memset(tlv, 0, PMK_LEN);
00152     }
00153     tlv += PMK_LEN;
00154 
00155     uint64_t counter = sec_prot_keys_pmk_replay_cnt_get(sec_keys);
00156     tlv = common_write_64_bit(counter, tlv);
00157 
00158     uint8_t *ptk = sec_prot_keys_ptk_get(sec_keys);
00159     if (ptk) {
00160         *tlv++ = PAE_NVM_FIELD_SET;
00161         memcpy(tlv, ptk, PTK_LEN);
00162     } else {
00163         *tlv++ = PAE_NVM_FIELD_NOT_SET;
00164         memset(tlv, 0, PTK_LEN);
00165     }
00166     tlv += PTK_LEN;
00167 
00168     tr_debug("NVM KEYS write");
00169 
00170 }
00171 
00172 int8_t ws_pae_nvm_store_keys_tlv_read(nvm_tlv_entry_t *tlv_entry, sec_prot_keys_t *sec_keys)
00173 {
00174     if (!tlv_entry || !sec_keys) {
00175         return -1;
00176     }
00177 
00178     if (tlv_entry->tag != PAE_NVM_KEYS_TAG || tlv_entry->len != PAE_NVM_KEYS_LEN) {
00179         return -1;
00180     }
00181 
00182     uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
00183 
00184     // EUI-64 set */
00185     if (*tlv++ == PAE_NVM_FIELD_SET) {
00186         sec_prot_keys_ptk_eui_64_write(sec_keys, tlv);
00187     }
00188     tlv += 8;
00189 
00190     // PMK set
00191     if (*tlv++ == PAE_NVM_FIELD_SET) {
00192         sec_prot_keys_pmk_write(sec_keys, tlv);
00193     }
00194     tlv += PMK_LEN;
00195 
00196     uint64_t counter = common_read_64_bit(tlv);
00197     tlv += 8;
00198     sec_prot_keys_pmk_replay_cnt_set(sec_keys, counter);
00199 
00200     // PTK set
00201     if (*tlv++ == PAE_NVM_FIELD_SET) {
00202         sec_prot_keys_ptk_write(sec_keys, tlv);
00203     }
00204 
00205     tlv += PTK_LEN;
00206 
00207     sec_prot_keys_updated_reset(sec_keys);
00208 
00209     tr_debug("NVM KEYS read");
00210 
00211     return 0;
00212 }
00213 
00214 void ws_pae_nvm_store_frame_counter_tlv_create(nvm_tlv_entry_t *tlv_entry, frame_counters_t *counters)
00215 {
00216     tlv_entry->tag = PAE_NVM_FRAME_COUNTER_TAG;
00217     tlv_entry->len = PAE_NVM_FRAME_COUNTER_LEN;
00218 
00219     uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
00220 
00221     for (uint8_t index = 0; index < GTK_NUM; index++) {
00222         if (!counters->counter[index].set) {
00223             *tlv++ = PAE_NVM_FIELD_NOT_SET;
00224             memset(tlv, 0, GTK_LEN + 4);
00225             tlv += GTK_LEN + 4;
00226             continue;
00227         }
00228         *tlv++ = PAE_NVM_FIELD_SET;
00229         memcpy(tlv, counters->counter[index].gtk, GTK_LEN);
00230         tlv += GTK_LEN;
00231         tlv = common_write_32_bit(counters->counter[index].frame_counter, tlv);
00232     }
00233 
00234     tr_debug("NVM FRAME COUNTER write");
00235 }
00236 
00237 int8_t ws_pae_nvm_store_frame_counter_tlv_read(nvm_tlv_entry_t *tlv_entry, frame_counters_t *counters)
00238 {
00239     if (!tlv_entry || !counters) {
00240         return -1;
00241     }
00242 
00243     if (tlv_entry->tag != PAE_NVM_FRAME_COUNTER_TAG || tlv_entry->len != PAE_NVM_FRAME_COUNTER_LEN) {
00244         return -1;
00245     }
00246 
00247     uint8_t *tlv = ((uint8_t *) &tlv_entry->tag) + NVM_TLV_FIXED_LEN;
00248 
00249     for (uint8_t index = 0; index < GTK_NUM; index++) {
00250         // Frame counter not set
00251         if (*tlv++ == PAE_NVM_FIELD_NOT_SET) {
00252             counters->counter[index].set = false;
00253             tlv += GTK_LEN + 4;
00254             continue;
00255         }
00256         // Frame counter is set, read GTK key and counter values
00257         counters->counter[index].set = true;
00258         memcpy(counters->counter[index].gtk, tlv, GTK_LEN);
00259         tlv += GTK_LEN;
00260         counters->counter[index].frame_counter = common_read_32_bit(tlv);
00261         tlv += 4;
00262     }
00263 
00264     tr_debug("NVM FRAME COUNTER read");
00265 
00266     return 0;
00267 }
00268 
00269 #endif /* HAVE_WS */
00270