Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sec_prot_certs.c Source File

sec_prot_certs.c

00001 /*
00002  * Copyright (c) 2016-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 "NWK_INTERFACE/Include/protocol.h"
00025 #include "Common_Protocols/ipv6_constants.h"
00026 #include "socket_api.h"
00027 #include "6LoWPAN/ws/ws_config.h"
00028 #include "Security/protocols/sec_prot_certs.h"
00029 #include "Security/protocols/sec_prot_keys.h"
00030 
00031 #ifdef HAVE_WS
00032 
00033 #define TRACE_GROUP "spce"
00034 
00035 // Length for PEM coded certificate's begin and end certificate text strings
00036 #define SEC_PROT_CERT_PEM_HEADER_FOOTER_LEN                52
00037 #define SEC_PROT_CERT_PEM_HEADER_STR                       "-----BEGIN CERTIFICATE-----"
00038 
00039 int8_t sec_prot_certs_init(sec_prot_certs_t *certs)
00040 {
00041     if (!certs) {
00042         return -1;
00043     }
00044 
00045     sec_prot_certs_chain_entry_init(&certs->own_cert_chain);
00046     ns_list_init(&certs->trusted_cert_chain_list);
00047     ns_list_init(&certs->cert_revocat_lists);
00048     certs->own_cert_chain_len = 0;
00049     certs->ext_cert_valid_enabled = false;
00050 
00051     return 0;
00052 }
00053 
00054 void sec_prot_certs_delete(sec_prot_certs_t *certs)
00055 {
00056     if (!certs) {
00057         return;
00058     }
00059 
00060     sec_prot_certs_chain_entry_init(&certs->own_cert_chain);
00061     sec_prot_certs_chain_list_delete(&certs->trusted_cert_chain_list);
00062     sec_prot_certs_revocat_lists_delete(&certs->cert_revocat_lists);
00063 }
00064 
00065 int8_t sec_prot_certs_ext_certificate_validation_set(sec_prot_certs_t *certs, bool enabled)
00066 {
00067     if (!certs) {
00068         return -1;
00069     }
00070 
00071     certs->ext_cert_valid_enabled = enabled;
00072 
00073     return 0;
00074 }
00075 
00076 bool sec_prot_certs_ext_certificate_validation_get(const sec_prot_certs_t *certs)
00077 {
00078     return certs->ext_cert_valid_enabled;
00079 }
00080 
00081 uint16_t sec_prot_certs_own_cert_chain_len_get(const sec_prot_certs_t *certs)
00082 {
00083     return certs->own_cert_chain_len;
00084 }
00085 
00086 cert_chain_entry_t *sec_prot_certs_chain_entry_create(void)
00087 {
00088     cert_chain_entry_t *entry = ns_dyn_mem_alloc(sizeof(cert_chain_entry_t));
00089     if (!entry) {
00090         return NULL;
00091     }
00092     sec_prot_certs_chain_entry_init(entry);
00093     return entry;
00094 }
00095 
00096 void sec_prot_certs_chain_entry_init(cert_chain_entry_t *entry)
00097 {
00098     memset(entry, 0, sizeof(cert_chain_entry_t));
00099 }
00100 
00101 void sec_prot_certs_chain_entry_delete(cert_chain_entry_t *entry)
00102 {
00103     ns_dyn_mem_free(entry);
00104 }
00105 
00106 int8_t sec_prot_certs_cert_set(cert_chain_entry_t *entry, uint8_t index, uint8_t *cert, uint16_t cert_len)
00107 {
00108     if (!entry || index >= SEC_PROT_CERT_CHAIN_DEPTH) {
00109         return -1;
00110     }
00111 
00112     entry->cert[index] = cert;
00113     entry->cert_len[index] = cert_len;
00114 
00115     return 0;
00116 }
00117 
00118 uint8_t *sec_prot_certs_cert_get(const cert_chain_entry_t *entry, uint8_t index, uint16_t *cert_len)
00119 {
00120     if (!entry || index >= SEC_PROT_CERT_CHAIN_DEPTH || !entry->cert[index]) {
00121         return NULL;
00122     }
00123 
00124     *cert_len = entry->cert_len[index];
00125     return entry->cert[index];
00126 }
00127 
00128 uint16_t sec_prot_certs_cert_chain_entry_len_get(const cert_chain_entry_t *entry)
00129 {
00130     uint16_t chain_length = 0;
00131     for (uint8_t index = 0; index < SEC_PROT_CERT_CHAIN_DEPTH; index++) {
00132         if (entry->cert[index]) {
00133             uint16_t cert_length  = entry->cert_len[index];
00134             // Checks if certificate is in PEM base64 format
00135             if (cert_length > SEC_PROT_CERT_PEM_HEADER_FOOTER_LEN &&
00136                     entry->cert[index][cert_length - 1] == '\0' &&
00137                     strstr((const char *)entry->cert[index], SEC_PROT_CERT_PEM_HEADER_STR) != NULL) {
00138                 cert_length -= SEC_PROT_CERT_PEM_HEADER_FOOTER_LEN;
00139                 /* 4 base64 chars encode 3 bytes (ignores line endings and possible paddings in the
00140                    calculation i.e they are counted to length) */
00141                 chain_length += (cert_length / 4) * 3;
00142             } else {
00143                 chain_length += cert_length;
00144             }
00145         }
00146     }
00147     return chain_length;
00148 }
00149 
00150 int8_t sec_prot_certs_priv_key_set(cert_chain_entry_t *entry, uint8_t *key, uint8_t key_len)
00151 {
00152     if (!entry) {
00153         return -1;
00154     }
00155 
00156     entry->key = key;
00157     entry->key_len = key_len;
00158 
00159     return 0;
00160 }
00161 
00162 uint8_t *sec_prot_certs_priv_key_get(const cert_chain_entry_t *entry, uint8_t *key_len)
00163 {
00164     if (!entry) {
00165         return NULL;
00166     }
00167     *key_len = entry->key_len;
00168     return entry->key;
00169 }
00170 
00171 void sec_prot_certs_chain_list_add(cert_chain_list_t *cert_chain_list, cert_chain_entry_t *entry)
00172 {
00173     ns_list_add_to_end(cert_chain_list, entry);
00174 }
00175 
00176 void sec_prot_certs_chain_list_delete(cert_chain_list_t *chain_list)
00177 {
00178     ns_list_foreach_safe(cert_chain_entry_t, entry, chain_list) {
00179         ns_list_remove(chain_list, entry);
00180         ns_dyn_mem_free(entry);
00181     }
00182 }
00183 
00184 void sec_prot_certs_chain_list_entry_delete(cert_chain_list_t *chain_list, cert_chain_entry_t *entry)
00185 {
00186     ns_list_remove(chain_list, entry);
00187     sec_prot_certs_chain_entry_delete(entry);
00188 }
00189 
00190 cert_chain_entry_t *sec_prot_certs_chain_list_entry_find(cert_chain_list_t *chain_list, cert_chain_entry_t *entry)
00191 {
00192     ns_list_foreach(cert_chain_entry_t, list_entry, chain_list) {
00193         bool match = true;
00194         for (uint8_t i = 0; i < SEC_PROT_CERT_CHAIN_DEPTH; i++) {
00195             if (list_entry->cert_len[i] != entry->cert_len[i]) {
00196                 match = false;
00197                 break;
00198             }
00199             if (memcmp(list_entry->cert[i], entry->cert[i], list_entry->cert_len[i]) != 0) {
00200                 match = false;
00201                 break;
00202             }
00203         }
00204         if (match) {
00205             return list_entry;
00206         }
00207     }
00208     return NULL;
00209 }
00210 
00211 cert_revocat_list_entry_t *sec_prot_certs_revocat_list_entry_create(void)
00212 {
00213     cert_revocat_list_entry_t *entry = ns_dyn_mem_alloc(sizeof(cert_revocat_list_entry_t));
00214     if (!entry) {
00215         return NULL;
00216     }
00217     sec_prot_certs_revocat_list_entry_init(entry);
00218     return entry;
00219 }
00220 
00221 void sec_prot_certs_revocat_list_entry_init(cert_revocat_list_entry_t *entry)
00222 {
00223     memset(entry, 0, sizeof(cert_revocat_list_entry_t));
00224 }
00225 
00226 void sec_prot_certs_revocat_list_entry_delete(cert_revocat_list_entry_t *entry)
00227 {
00228     ns_dyn_mem_free(entry);
00229 }
00230 
00231 int8_t sec_prot_certs_revocat_list_set(cert_revocat_list_entry_t *entry, const uint8_t *crl, uint16_t crl_len)
00232 {
00233     if (!entry) {
00234         return -1;
00235     }
00236 
00237     entry->crl = crl;
00238     entry->crl_len = crl_len;
00239 
00240     return 0;
00241 }
00242 
00243 const uint8_t *sec_prot_certs_revocat_list_get(const cert_revocat_list_entry_t *entry, uint16_t *crl_len)
00244 {
00245     if (!entry) {
00246         return NULL;
00247     }
00248     *crl_len = entry->crl_len;
00249     return entry->crl;
00250 }
00251 
00252 void sec_prot_certs_revocat_lists_add(cert_revocat_lists_t *cert_revocat_lists, cert_revocat_list_entry_t *entry)
00253 {
00254     ns_list_add_to_end(cert_revocat_lists, entry);
00255 }
00256 
00257 void sec_prot_certs_revocat_lists_entry_delete(cert_revocat_lists_t *cert_revocat_lists, cert_revocat_list_entry_t *entry)
00258 {
00259     ns_list_remove(cert_revocat_lists, entry);
00260     sec_prot_certs_revocat_list_entry_delete(entry);
00261 }
00262 
00263 cert_revocat_list_entry_t *sec_prot_certs_revocat_lists_entry_find(cert_revocat_lists_t *cert_revocat_lists, cert_revocat_list_entry_t *entry)
00264 {
00265     ns_list_foreach_safe(cert_revocat_list_entry_t, list_entry, cert_revocat_lists) {
00266         if (list_entry->crl_len == entry->crl_len) {
00267             if (memcmp(list_entry->crl, entry->crl, list_entry->crl_len) == 0) {
00268                 return list_entry;
00269             }
00270         }
00271     }
00272 
00273     return NULL;
00274 }
00275 
00276 void sec_prot_certs_revocat_lists_delete(cert_revocat_lists_t *cert_revocat_lists)
00277 {
00278     ns_list_foreach_safe(cert_revocat_list_entry_t, entry, cert_revocat_lists) {
00279         ns_list_remove(cert_revocat_lists, entry);
00280         ns_dyn_mem_free(entry);
00281     }
00282 }
00283 
00284 #endif /* HAVE_WS */