blob: b6efdad307a49de5e632fadf6d19b694a1f765ec [file] [log] [blame]
/*
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2018-2019 Foundries.io
*
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_MODULE_NAME net_lwm2m_obj_security
#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#include <stdint.h>
#include <zephyr/init.h>
#include "lwm2m_object.h"
#include "lwm2m_engine.h"
#define SECURITY_VERSION_MAJOR 1
#if defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1)
#define SECURITY_VERSION_MINOR 1
#define SECURITY_MAX_ID 18
#ifdef CONFIG_LWM2M_SECURITY_DTLS_TLS_CIPHERSUITE_MAX
#define DTLS_TLS_CIPHERSUITE_MAX CONFIG_LWM2M_SECURITY_DTLS_TLS_CIPHERSUITE_MAX
#else
#define DTLS_TLS_CIPHERSUITE_MAX 0
#endif /* CONFIG_LWM2M_SECURITY_DTLS_TLS_CIPHERSUITE_MAX */
#else
#define SECURITY_VERSION_MINOR 0
#define SECURITY_MAX_ID 13
#endif /* defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1) */
/* Security resource IDs */
#define SECURITY_SERVER_URI_ID 0
#define SECURITY_BOOTSTRAP_FLAG_ID 1
#define SECURITY_MODE_ID 2
#define SECURITY_CLIENT_PK_ID 3
#define SECURITY_SERVER_PK_ID 4
#define SECURITY_SECRET_KEY_ID 5
#define SECURITY_SMS_MODE_ID 6
#define SECURITY_SMS_BINDING_KEY_PARAM_ID 7
#define SECURITY_SMS_BINDING_SECRET_KEY_ID 8
#define SECURITY_LWM2M_SERVER_SMS_NUM_ID 9
#define SECURITY_SHORT_SERVER_ID 10
#define SECURITY_CLIENT_HOLD_OFF_TIME_ID 11
#define SECURITY_BS_SERVER_ACCOUNT_TIMEOUT_ID 12
#if defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1)
#define SECURITY_MATCHING_TYPE_ID 13
#define SECURITY_SNI_ID 14
#define SECURITY_CERTIFICATE_USAGE_ID 15
#define SECURITY_DTLS_TLS_CIPHERSUITE_ID 16
#define SECURITY_OSCORE_SEC_MODE_ID 17
#endif
#define MAX_INSTANCE_COUNT CONFIG_LWM2M_SECURITY_INSTANCE_COUNT
#define SECURITY_URI_LEN 255
#define IDENTITY_LEN 128
#define KEY_LEN CONFIG_LWM2M_SECURITY_KEY_SIZE
/*
* Calculate resource instances as follows:
* start with SECURITY_MAX_ID
*
* If using object version 1.1
* subtract MULTI resources because their counts include 0 resource (1)
* add DTLS_TLS_CIPHERSUITE_MAX for DTLS_TLS_CIPHERSUITE resource instances
*/
#if defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1)
#define RESOURCE_INSTANCE_COUNT (SECURITY_MAX_ID - 1 + DTLS_TLS_CIPHERSUITE_MAX)
#else
#define RESOURCE_INSTANCE_COUNT (SECURITY_MAX_ID)
#endif
/* resource state variables */
static char security_uri[MAX_INSTANCE_COUNT][SECURITY_URI_LEN];
static uint8_t client_identity[MAX_INSTANCE_COUNT][IDENTITY_LEN];
static uint8_t server_pk[MAX_INSTANCE_COUNT][KEY_LEN];
static uint8_t secret_key[MAX_INSTANCE_COUNT][KEY_LEN];
static bool bootstrap_flag[MAX_INSTANCE_COUNT];
static uint8_t security_mode[MAX_INSTANCE_COUNT];
static uint16_t short_server_id[MAX_INSTANCE_COUNT];
static struct lwm2m_engine_obj security;
static struct lwm2m_engine_obj_field fields[] = {
OBJ_FIELD_DATA(SECURITY_SERVER_URI_ID, RW, STRING),
OBJ_FIELD_DATA(SECURITY_BOOTSTRAP_FLAG_ID, W, BOOL),
OBJ_FIELD_DATA(SECURITY_MODE_ID, W, U8),
OBJ_FIELD_DATA(SECURITY_CLIENT_PK_ID, W, OPAQUE),
OBJ_FIELD_DATA(SECURITY_SERVER_PK_ID, W, OPAQUE),
OBJ_FIELD_DATA(SECURITY_SECRET_KEY_ID, W, OPAQUE),
OBJ_FIELD_DATA(SECURITY_SMS_MODE_ID, W_OPT, U8),
OBJ_FIELD_DATA(SECURITY_SMS_BINDING_KEY_PARAM_ID, W_OPT, OPAQUE),
OBJ_FIELD_DATA(SECURITY_SMS_BINDING_SECRET_KEY_ID, W_OPT, OPAQUE),
OBJ_FIELD_DATA(SECURITY_LWM2M_SERVER_SMS_NUM_ID, W_OPT, STRING),
OBJ_FIELD_DATA(SECURITY_SHORT_SERVER_ID, W_OPT, U16),
OBJ_FIELD_DATA(SECURITY_CLIENT_HOLD_OFF_TIME_ID, W_OPT, S32),
OBJ_FIELD_DATA(SECURITY_BS_SERVER_ACCOUNT_TIMEOUT_ID, W_OPT, S32),
#if defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1)
OBJ_FIELD_DATA(SECURITY_MATCHING_TYPE_ID, W_OPT, S32),
OBJ_FIELD_DATA(SECURITY_SNI_ID, W_OPT, STRING),
OBJ_FIELD_DATA(SECURITY_CERTIFICATE_USAGE_ID, W_OPT, U32),
OBJ_FIELD_DATA(SECURITY_DTLS_TLS_CIPHERSUITE_ID, W_OPT, U32),
OBJ_FIELD_DATA(SECURITY_OSCORE_SEC_MODE_ID, W_OPT, OBJLNK)
#endif
};
static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][SECURITY_MAX_ID];
static struct lwm2m_engine_res_inst
res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
static struct lwm2m_engine_obj_inst *security_create(uint16_t obj_inst_id)
{
int index, i = 0, j = 0;
/* Check that there is no other instance with this ID */
for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
LOG_ERR("Can not create instance - "
"already existing: %u", obj_inst_id);
return NULL;
}
}
for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
if (!inst[index].obj) {
break;
}
}
if (index >= MAX_INSTANCE_COUNT) {
LOG_ERR("Can not create instance - "
"no more room: %u", obj_inst_id);
return NULL;
}
/* default values */
security_uri[index][0] = '\0';
client_identity[index][0] = '\0';
bootstrap_flag[index] = 0;
security_mode[index] = 0U;
short_server_id[index] = 0U;
(void)memset(res[index], 0,
sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));
/* initialize instance resource data */
INIT_OBJ_RES_DATA_LEN(SECURITY_SERVER_URI_ID, res[index], i,
res_inst[index], j,
security_uri[index], SECURITY_URI_LEN, 0);
INIT_OBJ_RES_DATA(SECURITY_BOOTSTRAP_FLAG_ID, res[index], i,
res_inst[index], j,
&bootstrap_flag[index], sizeof(*bootstrap_flag));
INIT_OBJ_RES_DATA(SECURITY_MODE_ID, res[index], i,
res_inst[index], j,
&security_mode[index], sizeof(*security_mode));
INIT_OBJ_RES_DATA_LEN(SECURITY_CLIENT_PK_ID, res[index], i,
res_inst[index], j,
&client_identity[index], IDENTITY_LEN, 0);
INIT_OBJ_RES_DATA_LEN(SECURITY_SERVER_PK_ID, res[index], i,
res_inst[index], j,
&server_pk[index], KEY_LEN, 0);
INIT_OBJ_RES_DATA_LEN(SECURITY_SECRET_KEY_ID, res[index], i,
res_inst[index], j,
&secret_key[index], KEY_LEN, 0);
INIT_OBJ_RES_DATA(SECURITY_SHORT_SERVER_ID, res[index], i,
res_inst[index], j,
&short_server_id[index], sizeof(*short_server_id));
#if defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1)
INIT_OBJ_RES_OPTDATA(SECURITY_MATCHING_TYPE_ID, res[index], i, res_inst[index], j);
INIT_OBJ_RES_OPTDATA(SECURITY_SNI_ID, res[index], i, res_inst[index], j);
INIT_OBJ_RES_OPTDATA(SECURITY_CERTIFICATE_USAGE_ID, res[index], i, res_inst[index], j);
INIT_OBJ_RES_MULTI_OPTDATA(SECURITY_DTLS_TLS_CIPHERSUITE_ID, res[index], i,
res_inst[index], j, DTLS_TLS_CIPHERSUITE_MAX, false);
INIT_OBJ_RES_OPTDATA(SECURITY_OSCORE_SEC_MODE_ID, res[index], i, res_inst[index], j);
#endif
inst[index].resources = res[index];
inst[index].resource_count = i;
LOG_DBG("Create LWM2M security instance: %d", obj_inst_id);
return &inst[index];
}
int lwm2m_security_inst_id_to_index(uint16_t obj_inst_id)
{
int i;
for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
return i;
}
}
return -ENOENT;
}
int lwm2m_security_index_to_inst_id(int index)
{
if (index >= MAX_INSTANCE_COUNT) {
return -EINVAL;
}
/* not instantiated */
if (!inst[index].obj) {
return -ENOENT;
}
return inst[index].obj_inst_id;
}
static int lwm2m_security_init(const struct device *dev)
{
struct lwm2m_engine_obj_inst *obj_inst = NULL;
int ret = 0;
security.obj_id = LWM2M_OBJECT_SECURITY_ID;
security.version_major = SECURITY_VERSION_MAJOR;
security.version_minor = SECURITY_VERSION_MINOR;
security.is_core = true;
security.fields = fields;
security.field_count = ARRAY_SIZE(fields);
security.max_instance_count = MAX_INSTANCE_COUNT;
security.create_cb = security_create;
lwm2m_register_obj(&security);
/* auto create the first instance */
ret = lwm2m_create_obj_inst(LWM2M_OBJECT_SECURITY_ID, 0, &obj_inst);
if (ret < 0) {
LOG_ERR("Create LWM2M security instance 0 error: %d", ret);
}
return ret;
}
SYS_INIT(lwm2m_security_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);