Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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 */
Generated on Tue Jul 12 2022 13:54:49 by
