1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

pkg/wakaama: add own security object implementation

This commit is contained in:
Leandro Lanzieri 2021-03-11 15:12:27 +01:00
parent a5996e22b8
commit 4eb3ef4b4f
No known key found for this signature in database
GPG Key ID: F4E9A721761C7593
11 changed files with 1422 additions and 143 deletions

View File

@ -1,4 +1,4 @@
# Copyright (c) 2019 HAW Hamburg
# Copyright (c) 2021 HAW Hamburg
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
@ -10,96 +10,15 @@ menu "Wakaama LwM2M"
menu "Remote server"
config LWM2M_STANDARD_PORT
string "CoAP default port of the LwM2M server"
string "CoAP default port of a LwM2M server"
default "5683"
config LWM2M_DTLS_PORT
string "CoAPS default port of the LwM2M server"
string "CoAPS default port of a LwM2M server"
default "5684"
config LWM2M_SERVER_URI
string "LwM2M server URI to register/bootstrap with"
default "coap://[fd00:dead:beef::1]"
help
The host part of the URI MUST be a valid IPv6 address. Host names can
not be resolved at this time.
config LWM2M_SERVER_ID
int "Numeric ID of the Server URI"
default 10
help
This numeric ID corresponds to the server URI specified in the
previous option.
config LWM2M_BOOTSTRAP
bool "Is a bootstrap server"
help
The specified server is a LwM2M bootstrap server.
endmenu # Remote server
menu "Device"
choice
bool "Device binding and queue mode"
default LWM2M_DEVICE_BINDING_U
config LWM2M_DEVICE_BINDING_U
bool "UDP"
config LWM2M_DEVICE_BINDING_UQ
bool "UDP with Queue mode"
config LWM2M_DEVICE_BINDING_S
bool "SMS"
config LWM2M_DEVICE_BINDING_SQ
bool "SMS with Queue mode"
config LWM2M_DEVICE_BINDING_US
bool "UDP and SMS"
config LWM2M_DEVICE_BINDING_UQS
bool "UDP with Queue mode and SMS"
endchoice
config LWM2M_DEVICE_NAME
string "Device name"
default "testRIOTDevice"
help
This is the device name used to register at the LwM2M server.
config LWM2M_DEVICE_MANUFACTURER
string "Device manufacturer"
default "A RIOT maker"
config LWM2M_DEVICE_MODEL
string "Device model"
default "$(BOARD)"
config LWM2M_DEVICE_TYPE
string "Device type"
default "RIOT device"
config LWM2M_DEVICE_SERIAL
string "Device serial number"
default "undefined"
config LWM2M_DEVICE_FW_VERSION
string "Device firmware version"
default ""
config LWM2M_DEVICE_HW_VERSION
string "Device hardware version"
default "$(BOARD)"
config LWM2M_DEVICE_SW_VERSION
string "Device software version"
default ""
endmenu # Device
config LWM2M_DEVICE_TTL
int "Lifetime of the device"
default 300
@ -107,9 +26,13 @@ config LWM2M_DEVICE_TTL
Lifetime of the device on the LwM2M server, expressed in seconds.
config LWM2M_LOCAL_PORT
string "Default port for the local LwM2M instance"
string "Port for the local LwM2M CoAP"
default "5683"
config LWM2M_LOCAL_DTLS_PORT
string "Port for the local LwM2M CoAPs server"
default "5684"
config LWM2M_ALT_PATH
string "Alternate path to place LwM2M resources"
default "/"
@ -121,6 +44,22 @@ config LWM2M_TLSF_BUFFER
int "Allocation buffer size"
default 5120
config LWM2M_CREDMAN_TAG_BASE
int "Credential tag base"
default 10
help
Number to use as base for assigning tags to @ref net_credman
credentials.
config LWM2M_URI_MAX_SIZE
int "Maximum length of an URI allowed"
default 64
config LWM2M_BOOTSTRAP
bool "Bootsrap server support"
help
Say y to support using a bootstrap server to get server information.
rsource "contrib/objects/Kconfig"
endmenu # Wakaama LwM2M

View File

@ -8,8 +8,9 @@ USEMODULE += uri_parser
# folder, by adding 'wakaama_objects_<objectName>' modules
USEMODULE += wakaama_objects
# include the 'device' object implementation (mandatory)
# include mandatory objects
USEMODULE += wakaama_objects_device
USEMODULE += wakaama_objects_security
USEMODULE += ztimer
USEMODULE += ztimer_sec

View File

@ -24,33 +24,13 @@
#include "lwm2m_client_config.h"
#include "lwm2m_client_objects.h"
/* These functions are defined by the objects (object_security.c and
* object_server.c are implemented by the Wakaama package. device.c can be
* found in 'contrib/objects') */
lwm2m_object_t *get_security_object(int server_id, const char *server_uri,
char *bs_psk_id, char *psk,
uint16_t psk_len, bool is_bootstrap);
/* These functions are defined by the objects (object_server.c is implemented by
* the Wakaama package. security.c and device.c can be found in
* 'contrib/objects') */
lwm2m_object_t *get_server_object(int server_id, const char *binding,
int lifetime, bool storing);
lwm2m_object_t *lwm2m_get_object_device(void);
lwm2m_object_t *lwm2m_client_get_security_object(
lwm2m_client_data_t *client_data)
{
(void)client_data;
lwm2m_object_t *ret;
char *server_uri = CONFIG_LWM2M_SERVER_URI;
int server_id = CONFIG_LWM2M_SERVER_ID;
uint16_t psk_len = -1;
char *psk_buffer = NULL;
char *psk_id = NULL;
ret = get_security_object(server_id, server_uri, psk_id, psk_buffer,
psk_len, IS_ACTIVE(CONFIG_LWM2M_BOOTSTRAP));
return ret;
}
lwm2m_object_t *lwm2m_client_get_server_object(
lwm2m_client_data_t *client_data)
{

View File

@ -6,3 +6,4 @@
#
rsource "Kconfig.light_control"
rsource "Kconfig.security"

View File

@ -0,0 +1,26 @@
# Copyright (c) 2021 HAW Hamburg
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
#
menu "Security object"
config LWM2M_OBJ_SECURITY_INSTANCES_MAX
int "Maximum number of instances of the Security object"
default 2
config LWM2M_OBJ_SECURITY_PUB_KEY_ID_BUFSIZE
int "Buffer size of the public key or ID resource"
default 128
config LWM2M_OBJ_SECURITY_SERVER_PUB_KEY_BUFSIZE
int "Buffer size of the server public key resource"
default 128
config LWM2M_OBJ_SECURITY_SEC_KEY_BUFSIZE
int "Buffer size of the secret key resource"
default 64
endmenu # Security object

View File

@ -0,0 +1,913 @@
/*
* Copyright (C) 2024 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
* @ingroup lwm2m_objects_security
*
* @file
* @brief Security object implementation for LwM2M client using Wakaama
*
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
* @}
*/
#include "liblwm2m.h"
#include "objects/security.h"
#include "lwm2m_client_config.h"
#include "lwm2m_client.h"
#include "kernel_defines.h"
#include "net/credman.h"
#include "mutex.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define ENABLE_DEBUG 0
#include "debug.h"
#define _USED_INSTANCES(_obj) (_obj.wakaama_object.instanceList)
#define _FREE_INSTANCES(_obj) (_obj.free_instances)
/**
* @brief Descriptor of a LwM2M Security object instance (Object ID = 0)
*/
typedef struct lwm2m_obj_security_inst {
/**
* @brief Linked list handle.
*/
lwm2m_list_t list;
/**
* @brief Server URI.
*/
char uri[CONFIG_LWM2M_URI_MAX_SIZE];
/**
* @brief Indicates if the server associated to the security instance is a Bootstrap-Server.
*/
bool is_bootstrap;
/**
* @brief Security mode to use with the server.
*/
uint8_t security_mode;
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
/**
* @brief Tag of the credential to use with the server.
*/
credman_tag_t cred_tag;
/**
* @brief Buffer for the public key or ID resource.
*/
uint8_t pub_key_or_id[CONFIG_LWM2M_OBJ_SECURITY_PUB_KEY_ID_BUFSIZE];
/**
* @brief Bytes used in @ref lwm2m_obj_security_inst_t::pub_key_or_id.
*/
size_t pub_key_or_id_len;
/**
* @brief Buffer for the server public key resource.
*/
uint8_t server_pub_key[CONFIG_LWM2M_OBJ_SECURITY_SERVER_PUB_KEY_BUFSIZE];
/**
* @brief Bytes used in @ref lwm2m_obj_security_inst_t::server_pub_key.
*/
size_t server_pub_key_len;
/**
* @brief Credman public key structure for the server.
*/
ecdsa_public_key_t server_credman_pub_key;
/**
* @brief Buffer for the secret or private key resource.
*/
uint8_t secret_key[CONFIG_LWM2M_OBJ_SECURITY_SEC_KEY_BUFSIZE];
/**
* @brief Bytes used in @ref lwm2m_obj_security_inst_t::secret_key.
*/
size_t secret_key_len;
#endif /* MODULE_WAKAAMA_CLIENT_DTLS */
/**
* @brief Short ID to reference the server.
*/
uint16_t short_id;
/**
* @brief Hold off time for registration.
*/
uint32_t client_hold_off_time;
/**
* @brief Timeout for Bootstrap-Server account deletion.
*/
uint32_t bs_account_timeout;
} lwm2m_obj_security_inst_t;
/**
* @brief 'Read' callback for the security object.
*
* @param[in] instance_id ID of the instance to read
* @param[in, out] num_data Number of resources requested. 0 means all.
* @param[in, out] data_array Initialized data array to output the values,
* when @p num_data != 0. Uninitialized otherwise.
* @param[in] object Security object pointer
*
* @retval COAP_205_CONTENT on success
* @retval COAP_404_NOT_FOUND when resource can't be found
* @retval COAP_500_INTERNAL_SERVER_ERROR otherwise
*/
static uint8_t _read_cb(uint16_t instance_id, int *num_data, lwm2m_data_t *data_array[],
lwm2m_object_t *object);
/**
* @brief 'Write' callback for the security object.
*
* @param[in] instance_id ID of the instance to write to
* @param[in] num_data Number of resources to write
* @param[in] data_array Array of data to write
* @param[in] object Security object pointer
*
* @retval COAP_204_CHANGED on success
* @retval COAP_400_BAD_REQUEST otherwise
*/
static uint8_t _write_cb(uint16_t instance_id, int num_data, lwm2m_data_t *data_array,
lwm2m_object_t *object);
/**
* @brief 'Delete' callback for the security object.
*
* @param[in] instance_id ID of the instance to delete
* @param[in] object Security object pointer
*
* @retval COAP_202_DELETED on success
* @retval COAP_404_NOT_FOUND when the instance can't be found
*/
static uint8_t _delete_cb(uint16_t instance_id, lwm2m_object_t *object);
/**
* @brief 'Create' callback for the security object.
*
* @param[in] instance_id ID of the instance to create
* @param[in] num_data Number of resources to write
* @param[in] data_array Array of data to write
* @param[in] object Security object pointer
*
* @retval COAP_201_CREATED on success
* @retval COAP_500_INTERNAL_SERVER_ERROR otherwise
*/
static uint8_t _create_cb(uint16_t instance_id, int num_data, lwm2m_data_t *data_array,
lwm2m_object_t *object);
/**
* @brief Get a value from a security object instance.
*
* @param data[in, out] Data structure indicating the id of the resource
* to get the value of. It will contain the value if
* successful.
* @param instance[in] Instance to get the data from.
* @retval 0 on success
* @retval <0 otherwise
*/
static int _get_value(lwm2m_data_t *data, lwm2m_obj_security_inst_t *instance);
/**
* @brief Initialize a new instance with the given arguments.
*
* @param instance[out] Instance to initialize.
* @param instance_id[in] ID of the instance.
* @param args[in] Arguments to initialize the instance with.
*
* @retval 0 on success
* @retval -ENOMEM if there is no memory available to copy credentials
* @retval -EINVAL if the arguments are invalid
*/
static int _initialize_new_instance(lwm2m_obj_security_inst_t *instance, uint16_t instance_id,
const lwm2m_obj_security_args_t *args);
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
/**
* @brief Update a credential in the credman registry with the current instance information.
*
* @param[in] instance Instance to update the credential to.
*
* @retval 0 on success
* @retval <0 otherwise
*/
static int _update_credential(lwm2m_obj_security_inst_t *instance);
#endif /* MODULE_WAKAAMA_CLIENT_DTLS */
struct lwm2m_security_object {
lwm2m_object_t wakaama_object; /**< Wakaama internal object */
mutex_t lock; /**< mutex for the instances access */
lwm2m_obj_security_inst_t *free_instances; /**< list of free instances */
lwm2m_obj_security_inst_t instances[CONFIG_LWM2M_OBJ_SECURITY_INSTANCES_MAX]; /**< instances */
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
credman_tag_t tag_count; /**< counter for the credential tags */
#endif
};
/**
* @brief Implementation of the object interface for the Security Object.
*/
static struct lwm2m_security_object _security_object = {
.lock = MUTEX_INIT,
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
.tag_count= CONFIG_LWM2M_CREDMAN_TAG_BASE,
#endif
.wakaama_object = {
.next = NULL,
.objID = LWM2M_SECURITY_OBJECT_ID,
.instanceList = NULL,
.readFunc = _read_cb,
.writeFunc = _write_cb,
.createFunc = _create_cb,
.deleteFunc = _delete_cb,
.executeFunc = NULL,
.discoverFunc = NULL,
.userData = NULL,
}
};
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
static int _update_credential(lwm2m_obj_security_inst_t *instance)
{
assert(instance);
credman_credential_t cred;
credman_type_t type;
if (instance->security_mode == LWM2M_SECURITY_MODE_PRE_SHARED_KEY) {
type = CREDMAN_TYPE_PSK;
}
else {
type = CREDMAN_TYPE_ECDSA;
}
credman_delete(instance->cred_tag, type);
if (instance->cred_tag == CREDMAN_TAG_EMPTY) {
instance->cred_tag = ++_security_object.tag_count;
}
cred.type = type;
cred.tag = instance->cred_tag;
DEBUG("[lwm2m:security]: updating credential with tag %d\n", cred.tag);
if (type == CREDMAN_TYPE_PSK) {
DEBUG("[lwm2m:security]: PSK ID: %.*s\n", (unsigned)instance->pub_key_or_id_len, instance->pub_key_or_id);
DEBUG("[lwm2m:security]: PSK Key: %.*s\n", (unsigned)instance->secret_key_len, instance->secret_key);
cred.params.psk.id.s = instance->pub_key_or_id;
cred.params.psk.id.len = instance->pub_key_or_id_len;
cred.params.psk.key.s = instance->secret_key;
cred.params.psk.key.len = instance->secret_key_len;
}
else {
DEBUG("[lwm2m:security]: Server pub. key: [");
for (size_t i = 0; i < instance->server_pub_key_len; i++) {
DEBUG("0x%02x ", instance->server_pub_key[i]);
}
DEBUG("]\n");
DEBUG("[lwm2m:security]: Pub. key: [");
for (size_t i = 0; i < instance->pub_key_or_id_len; i++) {
DEBUG("0x%02x ", instance->pub_key_or_id[i]);
}
DEBUG("]\n");
DEBUG("[lwm2m:security]: Priv. key: [");
for (size_t i = 0; i < instance->secret_key_len; i++) {
DEBUG("0x%02x ", instance->secret_key[i]);
}
DEBUG("]\n");
int res = credman_load_public_key(instance->server_pub_key, instance->server_pub_key_len,
&instance->server_credman_pub_key);
if (res != CREDMAN_OK) {
DEBUG("[lwm2m:security]: error loading server public key (%d)\n", res);
return -1;
}
cred.params.ecdsa.client_keys = &instance->server_credman_pub_key;
cred.params.ecdsa.client_keys_size = 1;
res = credman_load_private_ecc_key(instance->secret_key, instance->secret_key_len, &cred);
if (res != CREDMAN_OK) {
DEBUG("[lwm2m:security]: error loading private key (%d)\n", res);
return -1;
}
res = credman_load_public_key(instance->pub_key_or_id, instance->pub_key_or_id_len,
&(cred.params.ecdsa.public_key));
if (res != CREDMAN_OK) {
DEBUG("[lwm2m:security]: error loading own public key (%d)\n", res);
return -1;
}
}
lwm2m_client_add_credential(instance->cred_tag);
return credman_add(&cred) == CREDMAN_OK ? 0 : -1;
}
#endif /* MODULE_WAKAAMA_CLIENT_DTLS */
static int _get_value(lwm2m_data_t *data, lwm2m_obj_security_inst_t *instance)
{
assert(data);
assert(instance);
/* resource IDs are defined by Wakaama in liblwm2m.h */
switch (data->id) {
case LWM2M_SECURITY_URI_ID:
lwm2m_data_encode_string(instance->uri, data);
break;
case LWM2M_SECURITY_BOOTSTRAP_ID:
lwm2m_data_encode_bool(instance->is_bootstrap, data);
break;
case LWM2M_SECURITY_SHORT_SERVER_ID:
lwm2m_data_encode_int(instance->short_id, data);
break;
case LWM2M_SECURITY_HOLD_OFF_ID:
lwm2m_data_encode_int(instance->client_hold_off_time, data);
break;
case LWM2M_SECURITY_BOOTSTRAP_TIMEOUT_ID:
lwm2m_data_encode_int(instance->bs_account_timeout, data);
break;
case LWM2M_SECURITY_SECURITY_ID:
lwm2m_data_encode_int(instance->security_mode, data);
break;
case LWM2M_SECURITY_PUBLIC_KEY_ID:
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
lwm2m_data_encode_opaque(instance->pub_key_or_id, instance->pub_key_or_id_len, data);
#else
return COAP_404_NOT_FOUND;
#endif
break;
case LWM2M_SECURITY_SECRET_KEY_ID:
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
lwm2m_data_encode_opaque(instance->secret_key, instance->secret_key_len, data);
#else
return COAP_404_NOT_FOUND;
#endif
break;
case LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID:
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
lwm2m_data_encode_opaque(instance->server_pub_key, instance->server_pub_key_len, data);
#else
return COAP_404_NOT_FOUND;
#endif
break;
/* not implemented */
case LWM2M_SECURITY_SMS_SECURITY_ID:
case LWM2M_SECURITY_SMS_KEY_PARAM_ID:
case LWM2M_SECURITY_SMS_SECRET_KEY_ID:
case LWM2M_SECURITY_SMS_SERVER_NUMBER_ID:
return COAP_404_NOT_FOUND;
default:
return COAP_404_NOT_FOUND;
}
return COAP_205_CONTENT;
}
static uint8_t _read_cb(uint16_t instance_id, int *num_data, lwm2m_data_t *data_array[],
lwm2m_object_t *object)
{
lwm2m_obj_security_inst_t *instance;
uint8_t result;
int i = 0;
/* try to get the requested instance from the object list */
instance = (lwm2m_obj_security_inst_t *)lwm2m_list_find(object->instanceList, instance_id);
if (NULL == instance) {
result = COAP_404_NOT_FOUND;
goto out;
}
/* if the number of resources is not specified, we need to read all resources */
if (!*num_data) {
DEBUG("[security:read] all resources are read\n");
const uint16_t resList[] = {
LWM2M_SECURITY_URI_ID,
LWM2M_SECURITY_BOOTSTRAP_ID,
LWM2M_SECURITY_SECURITY_ID,
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
LWM2M_SECURITY_PUBLIC_KEY_ID,
LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID,
LWM2M_SECURITY_SECRET_KEY_ID,
#endif
/* LWM2M_SECURITY_SMS_SECURITY_ID, */
/* LWM2M_SECURITY_SMS_KEY_PARAM_ID, */
/* LWM2M_SECURITY_SMS_SECRET_KEY_ID, */
/* LWM2M_SECURITY_SMS_SERVER_NUMBER_ID, */
LWM2M_SECURITY_SHORT_SERVER_ID,
LWM2M_SECURITY_HOLD_OFF_ID,
LWM2M_SECURITY_BOOTSTRAP_TIMEOUT_ID
};
/* try to allocate data structures for all resources */
int resNum = ARRAY_SIZE(resList);
*data_array = lwm2m_data_new(resNum);
if (NULL == *data_array) {
result = COAP_500_INTERNAL_SERVER_ERROR;
goto out;
}
/* indicate the number of resources that are returned */
*num_data = resNum;
/* prepare the resource ID of all resources for the request */
for (i = 0 ; i < resNum ; i++) {
(*data_array)[i].id = resList[i];
}
}
/* the data structures in data_array contain the IDs of the resources to get the values of */
i = 0;
do {
DEBUG("[security:read] read: %d\n", (*data_array)[i].id);
result = _get_value(&(*data_array)[i], instance);
i++;
} while (i < *num_data && COAP_205_CONTENT == result);
out:
return result;
}
static uint8_t _write_cb(uint16_t instance_id, int num_data, lwm2m_data_t *data_array,
lwm2m_object_t *object)
{
lwm2m_obj_security_inst_t *instance;
int64_t value;
uint8_t result = COAP_404_NOT_FOUND;
int i = 0;
DEBUG("[lwm2m:security:write]: looking for instance %d\n", instance_id);
/* try to get the requested instance from the object list */
instance = (lwm2m_obj_security_inst_t *)lwm2m_list_find(object->instanceList, instance_id);
if (!instance) {
DEBUG("[lwm2m:security:write]: not found\n");
goto out;
}
/* iterate over the array of data to write */
do {
lwm2m_data_t *data = &data_array[i];
switch (data->id) {
case LWM2M_SECURITY_URI_ID:
DEBUG("[lwm2m:security:write]: writing URI\n");
if (data->value.asBuffer.length > CONFIG_LWM2M_URI_MAX_SIZE - 1) {
result = COAP_400_BAD_REQUEST;
}
strncpy(instance->uri, (char *)data->value.asBuffer.buffer,
data->value.asBuffer.length);
instance->uri[data->value.asBuffer.length] = '\0';
result = COAP_204_CHANGED;
break;
case LWM2M_SECURITY_BOOTSTRAP_ID:
DEBUG("[lwm2m:security:write]: writing bootstrap\n");
if (lwm2m_data_decode_bool(data, &(instance->is_bootstrap)) == 1) {
result = COAP_204_CHANGED;
}
else {
result = COAP_400_BAD_REQUEST;
}
break;
case LWM2M_SECURITY_SECURITY_ID:
DEBUG("[lwm2m:security:write]: writing sec. mode\n");
if (lwm2m_data_decode_int(data, &value) == 1) {
/* check if it is a valid security mode */
if (LWM2M_SECURITY_MODE_NONE == value ||
LWM2M_SECURITY_MODE_PRE_SHARED_KEY == value ||
LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY == value ||
LWM2M_SECURITY_MODE_CERTIFICATE == value) {
instance->security_mode = value;
result = COAP_204_CHANGED;
break;
}
}
result = COAP_400_BAD_REQUEST;
break;
case LWM2M_SECURITY_SHORT_SERVER_ID:
DEBUG("[lwm2m:security:write]: writing short ID\n");
if (lwm2m_data_decode_int(data, &value) == 1) {
/* check valid range of value */
if (value > 0 && value < UINT16_MAX) {
instance->short_id = value;
result = COAP_204_CHANGED;
break;
}
}
result = COAP_400_BAD_REQUEST;
break;
case LWM2M_SECURITY_HOLD_OFF_ID:
DEBUG("[lwm2m:security:write]: writing hold off time\n");
if (lwm2m_data_decode_int(data, &value) == 1) {
/* check valid range of value */
if (value >= 0 && value <= UINT32_MAX) {
instance->client_hold_off_time = value;
result = COAP_204_CHANGED;
break;
}
}
result = COAP_400_BAD_REQUEST;
break;
case LWM2M_SECURITY_BOOTSTRAP_TIMEOUT_ID:
DEBUG("[lwm2m:security:write]: writing bootstrap timeout\n");
if (lwm2m_data_decode_int(data, &value) == 1) {
/* check valid range of value */
if (value >= 0 && value <= UINT32_MAX) {
instance->bs_account_timeout = value;
result = COAP_204_CHANGED;
break;
}
}
result = COAP_400_BAD_REQUEST;
break;
case LWM2M_SECURITY_PUBLIC_KEY_ID:
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
DEBUG("[lwm2m:security:write]: writing pub. key or ID\n");
if (data->value.asBuffer.length >
CONFIG_LWM2M_OBJ_SECURITY_PUB_KEY_ID_BUFSIZE) {
result = COAP_500_INTERNAL_SERVER_ERROR;
}
/* copy the new value */
memcpy(instance->pub_key_or_id, data->value.asBuffer.buffer,
data->value.asBuffer.length);
/* if the size changed we need to modify the registered credential */
if (instance->pub_key_or_id_len != data->value.asBuffer.length) {
instance->pub_key_or_id_len = data->value.asBuffer.length;
_update_credential(instance);
}
#endif /* MODULE_WAKAAMA_CLIENT_DTLS */
result = COAP_204_CHANGED;
break;
case LWM2M_SECURITY_SECRET_KEY_ID:
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
DEBUG("[lwm2m:security:write]: writing sec. key\n");
if (data->value.asBuffer.length >
CONFIG_LWM2M_OBJ_SECURITY_SEC_KEY_BUFSIZE) {
result = COAP_500_INTERNAL_SERVER_ERROR;
}
/* copy the new value */
memcpy(instance->secret_key, data->value.asBuffer.buffer,
data->value.asBuffer.length);
/* if the size changed we need to modify the registered credential */
if (instance->secret_key_len != data->value.asBuffer.length) {
instance->secret_key_len = data->value.asBuffer.length;
_update_credential(instance);
}
#endif /* MODULE_WAKAAMA_CLIENT_DTLS */
result = COAP_204_CHANGED;
break;
case LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID:
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
DEBUG("[lwm2m:security:write]: writing server pub. key\n");
if (data->value.asBuffer.length >
CONFIG_LWM2M_OBJ_SECURITY_SERVER_PUB_KEY_BUFSIZE) {
result = COAP_500_INTERNAL_SERVER_ERROR;
}
/* copy the new value */
memcpy(instance->server_pub_key, data->value.asBuffer.buffer,
data->value.asBuffer.length);
/* if the size changed we need to modify the registered credential */
if (instance->server_pub_key_len != data->value.asBuffer.length) {
instance->server_pub_key_len = data->value.asBuffer.length;
_update_credential(instance);
}
#endif /* MODULE_WAKAAMA_CLIENT_DTLS */
result = COAP_204_CHANGED;
break;
/* not implemented, ignore for now */
case LWM2M_SECURITY_SMS_SECURITY_ID:
case LWM2M_SECURITY_SMS_KEY_PARAM_ID:
case LWM2M_SECURITY_SMS_SECRET_KEY_ID:
case LWM2M_SECURITY_SMS_SERVER_NUMBER_ID:
result = COAP_204_CHANGED;
break;
default:
DEBUG("[lwm2m:security:write]: unknown resource %d\n", data->id);
result = COAP_404_NOT_FOUND;
}
i++;
} while (i < num_data && result == COAP_204_CHANGED);
DEBUG("[lwm2m:security:write]: done\n");
out:
return result;
}
static uint8_t _delete_cb(uint16_t instance_id, lwm2m_object_t *object)
{
uint8_t result = COAP_404_NOT_FOUND;
lwm2m_obj_security_inst_t *instance;
mutex_lock(&_security_object.lock);
DEBUG("[lwm2m:security:write]: looking for instance %d\n", instance_id);
/* try to remove the requested instance from the list */
object->instanceList = LWM2M_LIST_RM(object->instanceList, instance_id, &instance);
/* check if the instance was found */
if (NULL == instance) {
result = COAP_404_NOT_FOUND;
goto free_out;
}
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
/* if there is an associated credential, de-register */
if (instance->cred_tag != CREDMAN_TAG_EMPTY) {
credman_type_t type = instance->security_mode == LWM2M_SECURITY_MODE_PRE_SHARED_KEY ?
CREDMAN_TYPE_PSK : CREDMAN_TYPE_ECDSA;
credman_delete(instance->cred_tag, type);
lwm2m_client_remove_credential(instance->cred_tag);
}
#endif /* MODULE_WAKAAMA_CLIENT_DTLS */
/* add instance to free instances list */
instance->list.id = UINT16_MAX;
_FREE_INSTANCES(_security_object) = (lwm2m_obj_security_inst_t *) LWM2M_LIST_ADD(
_FREE_INSTANCES(_security_object), instance);
result = COAP_202_DELETED;
free_out:
mutex_unlock(&_security_object.lock);
return result;
}
static uint8_t _create_cb(uint16_t instance_id, int num_data, lwm2m_data_t *data_array,
lwm2m_object_t *object)
{
lwm2m_obj_security_inst_t *instance;
uint8_t result;
mutex_lock(&_security_object.lock);
/* check that the ID is free to use */
if (LWM2M_LIST_FIND(_USED_INSTANCES(_security_object), instance_id ) != NULL) {
DEBUG("[lwm2m:security]: instance ID %" PRIu16 " already in use\n", instance_id);
result = COAP_400_BAD_REQUEST;
goto free_out;
}
/* try to allocate an instance, by popping a free node from the list */
_FREE_INSTANCES(_security_object) = (lwm2m_obj_security_inst_t *) lwm2m_list_remove(
(lwm2m_list_t *) _FREE_INSTANCES(_security_object),
UINT16_MAX,
(lwm2m_list_t **) &instance
);
if (!instance) {
DEBUG("[lwm2m:security:create] can't allocate free instance\n");
result = COAP_500_INTERNAL_SERVER_ERROR;
goto free_out;
}
memset(instance, 0, sizeof(lwm2m_obj_security_inst_t));
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
instance->cred_tag = CREDMAN_TAG_EMPTY;
#endif
/* add to the object instance list */
instance->list.id = instance_id;
object->instanceList = LWM2M_LIST_ADD(object->instanceList, instance);
/* write incoming data to the instance */
result = _write_cb(instance_id, num_data, data_array, object);
if (result != COAP_204_CHANGED) {
_delete_cb(instance_id, object);
}
else {
result = COAP_201_CREATED;
goto free_out;
}
free_out:
mutex_unlock(&_security_object.lock);
return result;
}
lwm2m_object_t *lwm2m_object_security_init(lwm2m_client_data_t *client_data)
{
/* initialize the instances */
for (unsigned i = 0; i < CONFIG_LWM2M_OBJ_SECURITY_INSTANCES_MAX; i++) {
_security_object.instances[i].list.next = NULL;
_security_object.instances[i].list.id = UINT16_MAX;
_FREE_INSTANCES(_security_object) = (lwm2m_obj_security_inst_t *) LWM2M_LIST_ADD(
_FREE_INSTANCES(_security_object), &(_security_object.instances[i]));
}
_security_object.wakaama_object.userData = client_data;
return &(_security_object.wakaama_object);
}
static int _initialize_new_instance(lwm2m_obj_security_inst_t *instance, uint16_t instance_id,
const lwm2m_obj_security_args_t *args)
{
memset(instance, 0, sizeof(lwm2m_obj_security_inst_t));
instance->list.id = instance_id;
instance->short_id = args->server_id;
instance->security_mode = args->security_mode;
instance->is_bootstrap = args->is_bootstrap;
instance->client_hold_off_time = args->client_hold_off_time;
instance->bs_account_timeout = args->bootstrap_account_timeout;
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
instance->cred_tag = CREDMAN_TAG_EMPTY;
#endif
/* copy the URI locally */
size_t uri_len = strlen(args->server_uri);
if (uri_len > CONFIG_LWM2M_URI_MAX_SIZE - 1) {
DEBUG("[lwm2m:security]: can't copy URI, not enough space\n");
return -ENOMEM;
}
strncpy(instance->uri, args->server_uri, uri_len);
instance->uri[uri_len] = '\0';
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
if (LWM2M_SECURITY_MODE_NONE != args->security_mode) {
if (LWM2M_SECURITY_MODE_CERTIFICATE == args->security_mode) {
DEBUG("[lwm2m:security]: certificate mode not supported\n");
return -EINVAL;
}
/* copy keys locally */
if (LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY == args->security_mode) {
if (!args->server_pub_key ||
args->server_pub_key_len > CONFIG_LWM2M_OBJ_SECURITY_SERVER_PUB_KEY_BUFSIZE) {
DEBUG("[lwm2m:security]: Invalid server public key\n");
return -EINVAL;
}
memcpy(instance->server_pub_key, args->server_pub_key, args->server_pub_key_len);
instance->server_pub_key_len = args->server_pub_key_len;
}
if (!args->pub_key_or_id ||
args->pub_key_or_id_len > CONFIG_LWM2M_OBJ_SECURITY_PUB_KEY_ID_BUFSIZE) {
DEBUG("[lwm2m:security]: Invalid public key or ID\n");
return -EINVAL;
}
memcpy(instance->pub_key_or_id, args->pub_key_or_id, args->pub_key_or_id_len);
instance->pub_key_or_id_len = args->pub_key_or_id_len;
if (!args->secret_key ||
args->secret_key_len > CONFIG_LWM2M_OBJ_SECURITY_SEC_KEY_BUFSIZE) {
DEBUG("[lwm2m:security]: Invalid secret key\n");
return -EINVAL;
}
memcpy(instance->secret_key, args->secret_key, args->secret_key_len);
instance->secret_key_len = args->secret_key_len;
/* assign a credential tag */
instance->cred_tag = ++_security_object.tag_count;
if (_update_credential(instance) < 0) {
DEBUG("[lwm2m:security]: could not register the credential\n");
return -ENOMEM;
}
}
#endif /* MODULE_WAKAAMA_CLIENT_DTLS */
return 0;
}
int lwm2m_object_security_instance_create(const lwm2m_obj_security_args_t *args,
int32_t instance_id)
{
assert(args);
int result = -ENOMEM;
uint16_t _instance_id;
lwm2m_obj_security_inst_t *instance = NULL;
/* lock object */
mutex_lock(&_security_object.lock);
/* some sanity checks */
if (!args || !args->server_id || !args->server_uri) {
DEBUG("[lwm2m:security]: invalid arguments\n");
result = -EINVAL;
goto free_out;
}
DEBUG("[lwm2m:security]: creating new instance\n");
/* determine ID for new instance */
if (instance_id < 0) {
_instance_id = lwm2m_list_newId((lwm2m_list_t *)_USED_INSTANCES(_security_object));
}
else {
/* sanity check */
if (instance_id >= (UINT16_MAX - 1)) {
DEBUG("[lwm2m:security]: instance ID %" PRIi32 " is too big\n", instance_id);
result = -EINVAL;
goto free_out;
}
_instance_id = (uint16_t)instance_id;
/* check that the ID is free to use */
if (LWM2M_LIST_FIND(_USED_INSTANCES(_security_object), _instance_id ) != NULL) {
DEBUG("[lwm2m:security]: instance ID %" PRIi32 " already in use\n", instance_id);
result = -EINVAL;
goto free_out;
}
}
/* try to allocate an instance, by popping a free node from the list */
_FREE_INSTANCES(_security_object) = (lwm2m_obj_security_inst_t *) lwm2m_list_remove(
(lwm2m_list_t *) _FREE_INSTANCES(_security_object),
UINT16_MAX,
(lwm2m_list_t **) &instance
);
if (!instance) {
DEBUG("[lwm2m:security]: can't allocate new instance\n");
goto free_out;
}
result = _initialize_new_instance(instance, _instance_id, args);
if (result < 0) {
DEBUG("[lwm2m:security]: could not initialize new instance\n");
goto free_out;
}
DEBUG("[lwm2m:security]: added instance with URI: %s\n", instance->uri);
/* add the new instance to the list */
_USED_INSTANCES(_security_object) = LWM2M_LIST_ADD(_USED_INSTANCES(_security_object), instance);
result = instance->list.id;
free_out:
mutex_unlock(&_security_object.lock);
return result;
}
credman_tag_t lwm2m_object_security_get_credential(uint16_t instance_id)
{
#if IS_USED(MODULE_WAKAAMA_CLIENT_DTLS)
lwm2m_obj_security_inst_t *instance;
/* try to get the requested instance from the object list */
instance = (lwm2m_obj_security_inst_t *)lwm2m_list_find(_USED_INSTANCES(_security_object),
instance_id);
if (NULL == instance) {
DEBUG("[lwm2m:security]: no instance %d\n", instance_id);
return CREDMAN_TAG_EMPTY;
}
return instance->cred_tag;
#else
(void) instance_id;
return CREDMAN_TAG_EMPTY;
#endif /* MODULE_WAKAAMA_CLIENT_DTLS */
}

View File

@ -1,7 +1,9 @@
/**
* @defgroup pkg_wakaama Wakaama LwM2M implementation
* @defgroup pkg_wakaama LwM2M - Lightweight Machine to Machine
* @ingroup pkg
* @ingroup net
* @brief Provides the Wakaama implementation of LwM2M
* @brief LwM2M implementation based on the Wakaama package
* @see https://github.com/eclipse/wakaama
*/
*
* For a list of the supported objects see @ref lwm2m_objects.
*/

View File

@ -72,23 +72,6 @@ extern "C" {
#define CONFIG_LWM2M_DEVICE_TTL 300
#endif
/**
* @brief LwM2M server URI to register/bootstrap with
*
* @note The host part of the URI MUST be a valid IPv6 address. Host names can
* not be resolved at this time.
*/
#ifndef CONFIG_LWM2M_SERVER_URI
#define CONFIG_LWM2M_SERVER_URI "coap://[fd00:dead:beef::1]"
#endif
/**
* @brief Numeric ID of CONFIG_LWM2M_SERVER_URI
*/
#ifndef CONFIG_LWM2M_SERVER_ID
#define CONFIG_LWM2M_SERVER_ID 10
#endif
/**
* @brief Alternate path to place LwM2M resources
*/
@ -97,7 +80,7 @@ extern "C" {
#endif
/**
* @brief Define to 1 to specify that @ref CONFIG_LWM2M_SERVER_URI is a bootstrap server
* @brief Define to 1 to add bootstrap server support
*
* To define just add it to your `CFLAGS` in your application's Makefile:
*
@ -234,6 +217,20 @@ extern "C" {
#define CONFIG_LWM2M_DEVICE_BINDINGS "U"
#endif
/**
* @brief Number to use as base for assigning tags to @ref net_credman credentials.
*/
#ifndef CONFIG_LWM2M_CREDMAN_TAG_BASE
#define CONFIG_LWM2M_CREDMAN_TAG_BASE (10U)
#endif
/**
* @brief Maximum length of an URI allowed.
*/
#ifndef CONFIG_LWM2M_URI_MAX_SIZE
#define CONFIG_LWM2M_URI_MAX_SIZE 64
#endif
#ifdef __cplusplus
}
#endif

View File

@ -40,18 +40,6 @@ extern "C" {
#define LWM2M_ACC_CTRL_CREATE (1 << 4) /**< Creation access */
/** @} */
/**
* @brief Creates a LwM2M security object with the default configuration from
* net/lwm2m.h
*
* @param[in, out] client_data Pointer to a LwM2M client data descriptor
*
* @return Pointer to the created object in success
* @return NULL otherwise
*/
lwm2m_object_t *lwm2m_client_get_security_object(
lwm2m_client_data_t *client_data);
/**
* @brief Creates a LwM2M server object with the default configuration from
* net/lwm2m.h

View File

@ -0,0 +1,433 @@
/*
* Copyright (C) 2021 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup lwm2m_objects
* @defgroup lwm2m_objects_security Security LwM2M object
* @brief Security object implementation for LwM2M client using Wakaama
*
* @experimental This API is considered experimental and may change in future releases without
* deprecation process.
*
* This implements the LwM2M Security object as specified in the Appendix E1 of
* the LwM2M specification.
*
* So far only NO_SEC, PSK (Pre-shared key) and RPK (Raw public key) modes are available.
*
* ## Resources
*
* For an XML description of the object see
* https://raw.githubusercontent.com/OpenMobileAlliance/lwm2m-registry/prod/version_history/0-1_0.xml.
*
* | Name | ID | Mandatory | Type | Range | Units | Implemented |
* | ----------------------- | -- | --------- | ------- | ------- | ----- | ---------- |
* | Server URI | 0 | Yes | String | | | Yes |
* | Bootstrap Server | 1 | Yes | Boolean | | | Yes |
* | Security Mode | 2 | Yes | Integer | 0-3 | | Yes |
* | Public Key or ID | 3 | Yes | Opaque | | | Yes |
* | Server Public Key | 4 | Yes | Opaque | | | Yes |
* | Secret Key | 5 | Yes | Opaque | | | Yes |
* | SMS Security Mode | 6 | No | Integer | 0-255 | | No |
* | SMS Binding Key Param. | 7 | No | Opaque | 6 B | | No |
* | SMS Binding Secret Keys | 8 | No | Opaque | 32-48 B | | No |
* | Server SMS Number | 9 | No | String | | | No |
* | Short Server ID | 10 | No | Integer | 1-65535 | | Yes |
* | Client Hold Off Time | 11 | No | Integer | | s | Yes |
* | BS Account Timeout | 12 | No | Integer | | s | Yes |
*
* ## Usage
*
* ### Pre-shared keys
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
* // assuming buffers psk_id and psk_key containing credential information
* // assuming client_data is a valid lwm2m_client_data_t instance
* // [...]
*
* // prepare instance arguments
* lwm2m_obj_security_args_t args = {
* .server_id = CONFIG_LWM2M_SERVER_SHORT_ID,
* .server_uri = CONFIG_LWM2M_SERVER_URI,
* .security_mode = LWM2M_SECURITY_MODE_PRE_SHARED_KEY,
* .pub_key_or_id = psk_id,
* .pub_key_or_id_len = sizeof(psk_id) - 1,
* .secret_key = psk_key,
* .secret_key_len = sizeof(psk_key) - 1,
* .is_bootstrap = false,
* .client_hold_off_time = 5,
* .bootstrap_account_timeout = 0
* };
*
* // initialize the security object and get handle
* lwm2m_object_t *sec_obj = lwm2m_object_security_init(&client_data);
*
* // instantiate a new security object with instance ID 1
* int res = lwm2m_object_security_instance_create(&args, 1);
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* ### Raw public keys
*
* To use this security mode the following keys are required:
* - server public key (`SubjectPublicKeyInfo` DER encoded, according to RFC5280)
* - own public (`SubjectPublicKeyInfo` DER encoded) and private (as a `ECPrivateKey` DER encoded
* sequence, according to RFC5915)keys. See bellow on how they can be generated.
*
* It is possible that you may need to increase @ref CONFIG_DTLS_HANDSHAKE_BUFSIZE_EXP when using
* RPK mode.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
* // assuming buffers rpk_pub, rpk_priv, and server_rpk_pub containing the elliptic curve keys
* // assuming client_data is a valid lwm2m_client_data_t instance
* // [...]
*
* // prepare instance arguments
* lwm2m_obj_security_args_t args = {
* .server_id = CONFIG_LWM2M_SERVER_SHORT_ID,
* .server_uri = CONFIG_LWM2M_SERVER_URI,
* .security_mode = LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY,
* .pub_key_or_id = rpk_pub,
* .pub_key_or_id_len = sizeof(rpk_pub),
* .secret_key = rpk_priv,
* .secret_key_len = sizeof(rpk_priv),
* .server_pub_key = server_rpk_pub,
* .server_pub_key_len = sizeof(server_rpk_pub),
* .is_bootstrap = false,
* .client_hold_off_time = 5,
* .bootstrap_account_timeout = 0
* };
*
* // initialize the security object and get handle
* lwm2m_object_t *sec_obj = lwm2m_object_security_init(&client_data);
*
* // instantiate a new security object with next available instance ID
* int id = lwm2m_object_security_instance_create(&args, -1);
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* #### Generating the keys
*
* The local key pair can be generated using [OpenSSL](https://www.openssl.org/).
* 1. Generate the key pair using the secp256r1 parameters:
* ~~~~~~~~~~~~~~~~~~~~
* $ openssl ecparam -name secp256r1 -genkey -outform der -out keys.der
* ~~~~~~~~~~~~~~~~~~~~
*
* 2. Get the public part of the key:
* ~~~~~~~~~~~~~~~~~~~~
* $ openssl ec -in keys.der -inform DER -outform DER -pubout | xxd -i
* ~~~~~~~~~~~~~~~~~~~~
*
* 3. Get the private part of the key:
* ~~~~~~~~~~~~~~~~~~~~
* $ openssl ec -in keys.der -inform DER -no_public -outform DER | xxd -i
* ~~~~~~~~~~~~~~~~~~~~
*
* 4. If your server requires your public key as X-Y coordinates you can dump it as text, remove the
* first byte and split the rest in two equally-sized parts. The first part will be X, the
* second Y.
* ~~~~~~~~~~~~~~~~~~~~
* $ openssl ec -in keys.der -inform DER -text
*
* [...]
* pub:
* 04:a0:c3:8e:cb:a1:02:eb:5d:25:96:98:bb:60:8e:
* 28:19:56:06:96:70:15:9b:54:ff:d9:60:32:c3:3e:
* 89:08:ae:3a:33:2f:54:5f:68:a2:ac:d1:b9:df:2b:
* 79:65:49:3f:1c:ae:64:7a:32:02:e4:32:8d:6b:22:
* 67:83:0d:7c:b2
* ASN1 OID: prime256v1
* NIST CURVE: P-256
* [...]
* ~~~~~~~~~~~~~~~~~~~~
*
* Following the example above we have:
* ~~~~~~~~~~~~~~~~~~~~
* X : a0c38ecba102eb5d259698bb608e281956069670159b54ffd96032c33e8908ae
* Y : 3a332f545f68a2acd1b9df2b7965493f1cae647a3202e4328d6b2267830d7cb2
* ~~~~~~~~~~~~~~~~~~~~
* @{
*
* @file
*
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
*/
#ifndef OBJECTS_SECURITY_H
#define OBJECTS_SECURITY_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "liblwm2m.h"
#include "net/credman.h"
#include "lwm2m_client.h"
#include "lwm2m_client_config.h"
/* these are defined in liblwm2m.h, and are reproduced here for documentation purposes */
#ifdef DOXYGEN
/**
* @name LwM2M Security object security modes
* @{
*/
/**
* @brief Pre-Shared keys mode
*/
#define LWM2M_SECURITY_MODE_PRE_SHARED_KEY 0
/**
* @brief Raw public keys mode
*/
#define LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY 1
/**
* @brief Certificate mode
*/
#define LWM2M_SECURITY_MODE_CERTIFICATE 2
/**
* @brief No security mode
*/
#define LWM2M_SECURITY_MODE_NONE 3
/** @} */
/**
* @name Resource IDs for the LWM2M Security Object
* @{
*/
/**
* @brief Server URI
*/
#define LWM2M_SECURITY_URI_ID 0
/**
* @brief Bootstrap server
*/
#define LWM2M_SECURITY_BOOTSTRAP_ID 1
/**
* @brief Security mode
*/
#define LWM2M_SECURITY_SECURITY_ID 2
/**
* @brief Public key or ID
*/
#define LWM2M_SECURITY_PUBLIC_KEY_ID 3
/**
* @brief Server public key
*/
#define LWM2M_SECURITY_SERVER_PUBLIC_KEY_ID 4
/**
* @brief Secret key
*/
#define LWM2M_SECURITY_SECRET_KEY_ID 5
/**
* @brief SMS security mode
*/
#define LWM2M_SECURITY_SMS_SECURITY_ID 6
/**
* @brief SMS binding key parameters
*/
#define LWM2M_SECURITY_SMS_KEY_PARAM_ID 7
/**
* @brief SMS binding secret keys
*/
#define LWM2M_SECURITY_SMS_SECRET_KEY_ID 8
/**
* @brief Server SMS number
*/
#define LWM2M_SECURITY_SMS_SERVER_NUMBER_ID 9
/**
* @brief Short server ID
*/
#define LWM2M_SECURITY_SHORT_SERVER_ID 10
/**
* @brief Client hold-off time
*/
#define LWM2M_SECURITY_HOLD_OFF_ID 11
/**
* @brief Boostrap server account timeout
*/
#define LWM2M_SECURITY_BOOTSTRAP_TIMEOUT_ID 12
/** @} */
#endif /* DOXYGEN */
/**
* @defgroup lwm2m_objects_security_config LwM2M Security object compile configurations
* @ingroup lwm2m_client_config
* @{
*/
/**
* @brief Maximum number of instances of the Security object
*/
#ifndef CONFIG_LWM2M_OBJ_SECURITY_INSTANCES_MAX
#define CONFIG_LWM2M_OBJ_SECURITY_INSTANCES_MAX (2)
#endif
/**
* @brief Buffer size of the public key or ID resource
*/
#ifndef CONFIG_LWM2M_OBJ_SECURITY_PUB_KEY_ID_BUFSIZE
#define CONFIG_LWM2M_OBJ_SECURITY_PUB_KEY_ID_BUFSIZE (128)
#endif
/**
* @brief Buffer size of the server public key resource
*/
#ifndef CONFIG_LWM2M_OBJ_SECURITY_SERVER_PUB_KEY_BUFSIZE
#define CONFIG_LWM2M_OBJ_SECURITY_SERVER_PUB_KEY_BUFSIZE (128)
#endif
/**
* @brief Buffer size of the secret key resource
*/
#ifndef CONFIG_LWM2M_OBJ_SECURITY_SEC_KEY_BUFSIZE
#define CONFIG_LWM2M_OBJ_SECURITY_SEC_KEY_BUFSIZE (64)
#endif
/** @} */
/**
* @brief Arguments for a new Security object instance creation
* (@ref lwm2m_object_security_instance_create).
*/
typedef struct lwm2m_obj_security_args {
/**
* @brief Server's short ID the instance is associated to.
*/
uint16_t server_id;
/**
* @brief Server's URI the instance is associated to.
*
* @note This buffer will be copied internally.
*/
const char *server_uri;
/**
* @brief Security mode to use. For now only @ref LWM2M_SECURITY_MODE_NONE and
* @ref LWM2M_SECURITY_MODE_PRE_SHARED_KEY and
* @ref LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY are supported.
*/
uint8_t security_mode;
/**
* @brief Pointer to the Key ID when using @ref LWM2M_SECURITY_MODE_PRE_SHARED_KEY.
* Pointer to the public key encoded as a `SubjectPublicKeyInfo` sequence when using
* @ref LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY (see @ref credman_load_public_key).
* May be `NULL` when @ref LWM2M_SECURITY_MODE_NONE is used.
*
* @note This buffer will be copied internally.
*/
const uint8_t *pub_key_or_id;
/**
* @brief Length of @ref lwm2m_obj_security_args_t::pub_key_or_id.
*/
size_t pub_key_or_id_len;
/**
* @brief Pointer to the Key when using @ref LWM2M_SECURITY_MODE_PRE_SHARED_KEY.
* Pointer to the private key PKCS8 DER encoded when using
* @ref LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY (see @ref credman_load_private_key).
* May be `NULL` when @ref LWM2M_SECURITY_MODE_NONE is used.
*
* @note This buffer will be copied internally.
*/
const uint8_t *secret_key;
/**
* @brief Length of @ref lwm2m_obj_security_args_t::secret_key.
*/
size_t secret_key_len;
/**
* @brief Pointer to the server public key encoded as a `SubjectPublicKeyInfo` sequence when
* using @ref LWM2M_SECURITY_MODE_RAW_PUBLIC_KEY (see @ref credman_load_public_key).
* May be `NULL` when @ref LWM2M_SECURITY_MODE_NONE or
* @ref LWM2M_SECURITY_MODE_PRE_SHARED_KEY are used.
*
* @note This buffer will be copied internally.
*/
const uint8_t *server_pub_key;
/**
* @brief Length of @ref lwm2m_obj_security_args_t::server_pub_key.
*/
size_t server_pub_key_len;
/**
* @brief When `true` the security instance is associated to the Bootstrap-Server.
*/
bool is_bootstrap;
/**
* @brief Time, in seconds, to wait before initiating a 'Client Initiated Bootstrap', after it
* has been determined that it should be initiated.
*/
uint32_t client_hold_off_time;
/**
* @brief Time, in seconds, that the client waits before it purges the Bootstrap-Server's
* account. 0 means never.
*/
uint32_t bootstrap_account_timeout;
} lwm2m_obj_security_args_t;
/**
* @brief Initialize the Security object.
*
* @param[in] client_data LwM2M client data.
*
* @return Pointer to the Security object on success
*/
lwm2m_object_t *lwm2m_object_security_init(lwm2m_client_data_t *client_data);
/**
* @brief Create a new Security instance and add it to the @p object list.
*
* @param[in] args Initialize structure with the parameter for the instance. May
* not be NULL.
* @param[in] instance_id ID for the new instance. It must be between 0 and
* (UINT16_MAX - 1), if -1 the next available ID will be used.
*
* @return Instance ID (> 0) on success
* @return -EINVAL if an invalid @p instance_id is given
* @return -ENOMEM if no memory is available to create a new instance
*/
int lwm2m_object_security_instance_create(const lwm2m_obj_security_args_t *args,
int32_t instance_id);
/**
* @brief Get the credential of a given instance of the security object.
*
* @param[in] instance_id ID of the instance.
*
* @return Credential tag.
* @retval CREDMAN_TAG_EMPTY when no credential is assigned.
*/
credman_tag_t lwm2m_object_security_get_credential(uint16_t instance_id);
#ifdef __cplusplus
}
#endif
#endif /* OBJECTS_SECURITY_H */
/** @} */

View File

@ -2,7 +2,6 @@ MODULE = wakaama_client
SRC = \
object_server.c \
object_security.c \
object_access_control.c \
#