Skip to content

Commit

Permalink
Added dynamic setting to enable certificate validation
Browse files Browse the repository at this point in the history
Added dynamic setting to border router interface to set validation of
Wi-SUN specific fields on Wi-SUN certificates.
  • Loading branch information
Mika Leppänen committed Sep 24, 2019
1 parent ff531d3 commit 0675a89
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 36 deletions.
22 changes: 22 additions & 0 deletions nanostack/ws_bbr_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,26 @@ int ws_bbr_node_access_revoke_start(int8_t interface_id);
*/
int ws_bbr_eapol_node_limit_set(int8_t interface_id, uint16_t limit);

/**
* Extended certificate validation
*/
#define BBR_CRT_EXT_VALID_NONE 0x00 /**< Do not make extended validations */
#define BBR_CRT_EXT_VALID_WISUN 0x01 /**< Validate Wi-SUN specific fields */

/**
* Sets extended certificate validation setting
*
* Sets extended certificate validation setting on border router. Function can be used
* to set which fields on client certificate are validated.
*
* \param interface_id Network interface ID
* \param validation Extended Certificate validation setting
* BBR_CRT_EXT_VALID_NONE Do not make extended validations
* BBR_CRT_EXT_VALID_WISUN Validate Wi-SUN specific fields
*
* \return 0 Validation setting was set
* \return <0 Setting set failed
*/
int ws_bbr_ext_certificate_validation_set(int8_t interface_id, uint8_t validation);

#endif /* WS_BBR_API_H_ */
15 changes: 15 additions & 0 deletions source/6LoWPAN/ws/ws_bbr_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,3 +636,18 @@ int ws_bbr_eapol_node_limit_set(int8_t interface_id, uint16_t limit)
return -1;
#endif
}

int ws_bbr_ext_certificate_validation_set(int8_t interface_id, uint8_t validation)
{
(void) interface_id;
#ifdef HAVE_WS_BORDER_ROUTER
bool enabled = false;
if (validation & BBR_CRT_EXT_VALID_WISUN) {
enabled = true;
}
return ws_pae_controller_ext_certificate_validation_set(interface_id, enabled);
#else
(void) validation;
return -1;
#endif
}
25 changes: 24 additions & 1 deletion source/6LoWPAN/ws/ws_pae_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ typedef struct {
typedef struct {
uint16_t node_limit; /**< Max number of stored supplicants */
bool node_limit_set : 1; /**< Node limit set */
bool ext_cert_valid_enabled : 1; /**< Extended certificate validation enabled */
} pae_controller_config_t;

static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr);
Expand All @@ -126,7 +127,8 @@ static NS_LIST_DEFINE(pae_controller_list, pae_controller_t, link);

pae_controller_config_t pae_controller_config = {
.node_limit = 0,
.node_limit_set = false
.node_limit_set = false,
.ext_cert_valid_enabled = false
};

#if !defined(HAVE_PAE_SUPP) && !defined(HAVE_PAE_AUTH)
Expand Down Expand Up @@ -592,6 +594,7 @@ static void ws_pae_controller_data_init(pae_controller_t *controller)
sec_prot_keys_gtks_init(&controller->gtks);
sec_prot_keys_gtks_init(&controller->next_gtks);
sec_prot_certs_init(&controller->certs);
sec_prot_certs_ext_certificate_validation_set(&controller->certs, pae_controller_config.ext_cert_valid_enabled);
ws_pae_timers_settings_init(&controller->timer_settings);
}

Expand Down Expand Up @@ -1100,6 +1103,26 @@ int8_t ws_pae_controller_node_limit_set(int8_t interface_id, uint16_t limit)
#endif
}

int8_t ws_pae_controller_ext_certificate_validation_set(int8_t interface_id, bool enabled)
{
#ifdef HAVE_PAE_AUTH
pae_controller_config.ext_cert_valid_enabled = enabled;

pae_controller_t *controller = ws_pae_controller_get_or_create(interface_id);
if (!controller) {
return -1;
}

sec_prot_certs_ext_certificate_validation_set(&controller->certs, enabled);

return 0;
#else
(void) interface_id;
(void) enabled;
return -1;
#endif
}

void ws_pae_controller_forced_gc(bool full_gc)
{
/* Purge only when on critical limit since node limit should handle limiting
Expand Down
12 changes: 12 additions & 0 deletions source/6LoWPAN/ws/ws_pae_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,18 @@ int8_t ws_pae_controller_node_access_revoke_start(int8_t interface_id);
*/
int8_t ws_pae_controller_node_limit_set(int8_t interface_id, uint16_t limit);

/**
* ws_pae_controller_ext_certificate_validation_set enable or disable extended certificate validation
*
* \param interface_ptr interface
* \param enabled true to enable extended validation, false to disable
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_controller_ext_certificate_validation_set(int8_t interface_id, bool enabled);

/**
* ws_pae_controller_active_key_update update active key (test interface)
*
Expand Down
17 changes: 17 additions & 0 deletions source/Security/protocols/sec_prot_certs.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ int8_t sec_prot_certs_init(sec_prot_certs_t *certs)
sec_prot_certs_chain_entry_init(&certs->own_cert_chain);
ns_list_init(&certs->trusted_cert_chain_list);
ns_list_init(&certs->cert_revocat_lists);
certs->ext_cert_valid_enabled = false;

return 0;
}
Expand All @@ -56,6 +57,22 @@ void sec_prot_certs_delete(sec_prot_certs_t *certs)
sec_prot_certs_revocat_lists_delete(&certs->cert_revocat_lists);
}

int8_t sec_prot_certs_ext_certificate_validation_set(sec_prot_certs_t *certs, bool enabled)
{
if (!certs) {
return -1;
}

certs->ext_cert_valid_enabled = enabled;

return 0;
}

bool sec_prot_certs_ext_certificate_validation_get(const sec_prot_certs_t *certs)
{
return certs->ext_cert_valid_enabled;
}

cert_chain_entry_t *sec_prot_certs_chain_entry_create(void)
{
cert_chain_entry_t *entry = ns_dyn_mem_alloc(sizeof(cert_chain_entry_t));
Expand Down
23 changes: 23 additions & 0 deletions source/Security/protocols/sec_prot_certs.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ typedef struct {
cert_chain_entry_t own_cert_chain; /**< Own certificate chain */
cert_chain_list_t trusted_cert_chain_list; /**< Trusted certificate chain lists */
cert_revocat_lists_t cert_revocat_lists; /**< Certificate Revocation Lists */
bool ext_cert_valid_enabled : 1; /**< Extended certificate validation enabled */
} sec_prot_certs_t;

/**
Expand All @@ -78,6 +79,28 @@ int8_t sec_prot_certs_init(sec_prot_certs_t *certs);
*/
void sec_prot_certs_delete(sec_prot_certs_t *certs);

/**
* sec_prot_certs_ext_certificate_validation_set enable or disable extended certificate validation
*
* \param certs certificate information
* \param enabled true to enable extended validation, false to disable
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t sec_prot_certs_ext_certificate_validation_set(sec_prot_certs_t *certs, bool enabled);

/**
* sec_prot_certs_ext_certificate_validation_get get extended certificate validation setting
*
* \param certs certificate information
*
* \return true/false enabled or not
*
*/
bool sec_prot_certs_ext_certificate_validation_get(const sec_prot_certs_t *certs);

/**
* sec_prot_certs_chain_entry_create allocate memory for certificate chain entry
*
Expand Down
74 changes: 39 additions & 35 deletions source/Security/protocols/tls_sec_prot/tls_sec_prot_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,8 @@
#define TLS_HANDSHAKE_TIMEOUT_MAX 201000

//#define TLS_SEC_PROT_LIB_TLS_DEBUG // Enable mbed TLS debug traces
#define TLS_SEC_PROT_LIB_CERT_VALID_SKIP // Skip certificate validation

typedef int tls_sec_prot_lib_crt_verify_cb(mbedtls_x509_crt *crt, uint32_t *flags);
typedef int tls_sec_prot_lib_crt_verify_cb(tls_security_t *sec, mbedtls_x509_crt *crt, uint32_t *flags);

struct tls_security_s {
mbedtls_ssl_config conf; /**< mbed TLS SSL configuration */
Expand All @@ -75,6 +74,7 @@ struct tls_security_s {
mbedtls_x509_crt owncert; /**< Own certificate(s) */
mbedtls_pk_context pkey; /**< Private key for own certificate */
void *handle; /**< Handle provided in callbacks (defined by library user) */
bool ext_cert_valid : 1; /**< Extended certificate validation enabled */
tls_sec_prot_lib_crt_verify_cb *crt_verify; /**< Verify function for top certificate */
tls_sec_prot_lib_send *send; /**< Send callback */
tls_sec_prot_lib_receive *receive; /**< Receive callback */
Expand All @@ -98,10 +98,10 @@ static int tls_sec_prot_lib_x509_crt_verify(void *ctx, mbedtls_x509_crt *crt, in
static int8_t tls_sec_prot_lib_subject_alternative_name_validate(mbedtls_x509_crt *crt);
static int8_t tls_sec_prot_lib_extended_key_usage_validate(mbedtls_x509_crt *crt);
#ifdef HAVE_PAE_AUTH
static int tls_sec_prot_lib_x509_crt_idevid_ldevid_verify(mbedtls_x509_crt *crt, uint32_t *flags);
static int tls_sec_prot_lib_x509_crt_idevid_ldevid_verify(tls_security_t *sec, mbedtls_x509_crt *crt, uint32_t *flags);
#endif
#ifdef HAVE_PAE_SUPP
static int tls_sec_prot_lib_x509_crt_server_verify(mbedtls_x509_crt *crt, uint32_t *flags);
static int tls_sec_prot_lib_x509_crt_server_verify(tls_security_t *sec, mbedtls_x509_crt *crt, uint32_t *flags);
#endif
#ifdef TLS_SEC_PROT_LIB_TLS_DEBUG
static void tls_sec_prot_lib_debug(void *ctx, int level, const char *file, int line, const char *string);
Expand All @@ -115,6 +115,17 @@ static void *tls_sec_prot_lib_mem_calloc(size_t count, size_t size);
static void tls_sec_prot_lib_mem_free(void *ptr);
#endif

#if defined(HAVE_PAE_AUTH) && defined(HAVE_PAE_SUPP)
#define is_server_is_set (is_server == true)
#define is_server_is_not_set (is_server == false)
#elif defined(HAVE_PAE_AUTH)
#define is_server_is_set true
#define is_server_is_not_set false
#elif defined(HAVE_PAE_SUPP)
#define is_server_is_set false
#define is_server_is_not_set true
#endif

int8_t tls_sec_prot_lib_init(tls_security_t *sec)
{
const char *pers = "ws_tls";
Expand All @@ -123,7 +134,6 @@ int8_t tls_sec_prot_lib_init(tls_security_t *sec)
mbedtls_platform_set_calloc_free(tls_sec_prot_lib_mem_calloc, tls_sec_prot_lib_mem_free);
#endif


mbedtls_ssl_init(&sec->ssl);
mbedtls_ssl_config_init(&sec->conf);
mbedtls_ctr_drbg_init(&sec->ctr_drbg);
Expand Down Expand Up @@ -282,22 +292,18 @@ static int tls_sec_prot_lib_configure_certificates(tls_security_t *sec, const se
// Certificate verify required on both client and server
mbedtls_ssl_conf_authmode(&sec->conf, MBEDTLS_SSL_VERIFY_REQUIRED);

// Get extended certificate validation setting
sec->ext_cert_valid = sec_prot_certs_ext_certificate_validation_get(certs);

return 0;
}

#if defined(HAVE_PAE_AUTH) && defined(HAVE_PAE_SUPP)
#define is_server_is_set (is_server == true)
#define is_server_is_not_set (is_server == false)
#elif defined(HAVE_PAE_AUTH)
#define is_server_is_set true
#define is_server_is_not_set false
#elif defined(HAVE_PAE_SUPP)
#define is_server_is_set false
#define is_server_is_not_set true
#endif

int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_prot_certs_t *certs)
{
#if !defined(HAVE_PAE_SUPP) || !defined(HAVE_PAE_AUTH)
(void) is_server;
#endif

if (!sec) {
return -1;
}
Expand All @@ -313,6 +319,7 @@ int8_t tls_sec_prot_lib_connect(tls_security_t *sec, bool is_server, const sec_p
}
#endif


if ((mbedtls_ssl_config_defaults(&sec->conf,
is_server_is_set ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM, 0)) != 0) {
Expand Down Expand Up @@ -470,23 +477,20 @@ static int tls_sec_prot_lib_ssl_export_keys(void *p_expkey, const unsigned char

static int tls_sec_prot_lib_x509_crt_verify(void *ctx, mbedtls_x509_crt *crt, int certificate_depth, uint32_t *flags)
{
/* MD/PK forced also by configuration flags and dynamic settings but still verified
here to prevent invalid configurations/certificates */
tls_security_t *sec = (tls_security_t *) ctx;

/* MD/PK forced by configuration flags and dynamic settings but traced also here
to prevent invalid configurations/certificates */
if (crt->sig_md != MBEDTLS_MD_SHA256) {
tr_error("Invalid signature md algorithm");
*flags |= MBEDTLS_X509_BADCRL_BAD_MD;
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
}
if (crt->sig_pk != MBEDTLS_PK_ECDSA) {
tr_error("Invalid signature pk algorithm");
*flags |= MBEDTLS_X509_BADCRL_BAD_PK;
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
}

// Verify top certificate of the chain
if (certificate_depth == 0) {
tls_security_t *sec = (tls_security_t *)ctx;
return sec->crt_verify(crt, flags);
return sec->crt_verify(sec, crt, flags);
}

// No further checks for intermediate and root certificates at the moment
Expand Down Expand Up @@ -528,29 +532,30 @@ static int8_t tls_sec_prot_lib_extended_key_usage_validate(mbedtls_x509_crt *crt
{
// Extended key usage must be present
if (mbedtls_x509_crt_check_extended_key_usage(crt, MBEDTLS_OID_WISUN_FAN, sizeof(MBEDTLS_OID_WISUN_FAN) - 1) != 0) {
tr_error("invalid extended key usage");
return -1; // FAIL
}
return 0;
}

#ifdef HAVE_PAE_AUTH
static int tls_sec_prot_lib_x509_crt_idevid_ldevid_verify(mbedtls_x509_crt *crt, uint32_t *flags)
static int tls_sec_prot_lib_x509_crt_idevid_ldevid_verify(tls_security_t *sec, mbedtls_x509_crt *crt, uint32_t *flags)
{
// For both IDevID and LDevId both subject alternative name or extended key usage must be valid
if (tls_sec_prot_lib_subject_alternative_name_validate(crt) < 0 ||
tls_sec_prot_lib_extended_key_usage_validate(crt) < 0) {
tr_error("invalid cert");
#ifndef TLS_SEC_PROT_LIB_CERT_VALID_SKIP
*flags |= MBEDTLS_X509_BADCERT_OTHER;
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
#endif
if (sec->ext_cert_valid) {
*flags |= MBEDTLS_X509_BADCERT_OTHER;
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
}
}
return 0;
}
#endif

#ifdef HAVE_PAE_SUPP
static int tls_sec_prot_lib_x509_crt_server_verify(mbedtls_x509_crt *crt, uint32_t *flags)
static int tls_sec_prot_lib_x509_crt_server_verify(tls_security_t *sec, mbedtls_x509_crt *crt, uint32_t *flags)
{
int8_t sane_res = tls_sec_prot_lib_subject_alternative_name_validate(crt);
int8_t ext_key_res = tls_sec_prot_lib_extended_key_usage_validate(crt);
Expand All @@ -560,10 +565,10 @@ static int tls_sec_prot_lib_x509_crt_server_verify(mbedtls_x509_crt *crt, uint32
// Then both subject alternative name and extended key usage must be valid
if (sane_res < 0 || ext_key_res < 0) {
tr_error("invalid cert");
#ifndef TLS_SEC_PROT_LIB_CERT_VALID_SKIP
*flags |= MBEDTLS_X509_BADCERT_OTHER;
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
#endif
if (sec->ext_cert_valid) {
*flags |= MBEDTLS_X509_BADCERT_OTHER;
return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED;
}
}
}

Expand Down Expand Up @@ -656,4 +661,3 @@ uint16_t tls_sec_prot_lib_size(void)
}
#endif /* WS_MBEDTLS_SECURITY_ENABLED */
#endif /* HAVE_WS */

0 comments on commit 0675a89

Please sign in to comment.