50 #include "lwm2m-server.h" 51 #include "lwm2m-security.h" 57 #define LOG_MODULE "lwm2m-sec" 58 #define LOG_LEVEL LOG_LEVEL_LWM2M 60 #define MAX_COUNT LWM2M_SERVER_MAX_COUNT 62 static lwm2m_status_t lwm2m_callback(lwm2m_object_instance_t *
object,
63 lwm2m_context_t *ctx);
65 static lwm2m_object_instance_t *get_by_id(uint16_t instance_id,
66 lwm2m_status_t *status);
68 static const lwm2m_resource_id_t resources[] = {
69 LWM2M_SECURITY_SERVER_URI_ID, LWM2M_SECURITY_BOOTSTRAP_SERVER_ID,
70 LWM2M_SECURITY_MODE_ID, LWM2M_SECURITY_CLIENT_PKI_ID,
71 LWM2M_SECURITY_SERVER_PKI_ID, LWM2M_SECURITY_KEY_ID,
72 LWM2M_SECURITY_SHORT_SERVER_ID
76 static lwm2m_security_server_t instances[MAX_COUNT];
78 static lwm2m_object_instance_t *
79 create_instance(uint16_t instance_id, lwm2m_status_t *status)
81 lwm2m_object_instance_t *instance;
84 instance = get_by_id(instance_id, NULL);
85 if(instance != NULL) {
88 *status = LWM2M_STATUS_OPERATION_NOT_ALLOWED;
93 for(i = 0; i < MAX_COUNT; i++) {
94 if(instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) {
95 memset(&instances[i], 0,
sizeof(instances[i]));
96 instances[i].instance.callback = lwm2m_callback;
97 instances[i].instance.object_id = LWM2M_OBJECT_SECURITY_ID;
98 instances[i].instance.instance_id = instance_id;
99 instances[i].instance.resource_ids = resources;
100 instances[i].instance.resource_count =
101 sizeof(resources) /
sizeof(lwm2m_resource_id_t);
102 list_add(instances_list, &instances[i].instance);
104 LOG_DBG(
"Create new security instance %u\n", instance_id);
105 return &instances[i].instance;
110 *status = LWM2M_STATUS_SERVICE_UNAVAILABLE;
117 delete_instance(uint16_t instance_id, lwm2m_status_t *status)
119 lwm2m_object_instance_t *instance;
121 if(instance_id == LWM2M_OBJECT_INSTANCE_NONE) {
123 while((instance =
list_pop(instances_list)) != NULL) {
124 instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE;
129 instance = get_by_id(instance_id, NULL);
130 if(instance != NULL) {
131 instance->instance_id = LWM2M_OBJECT_INSTANCE_NONE;
139 static lwm2m_object_instance_t *
140 get_first(lwm2m_status_t *status)
145 static lwm2m_object_instance_t *
146 get_next(lwm2m_object_instance_t *instance, lwm2m_status_t *status)
148 return instance == NULL ? NULL : instance->next;
151 static lwm2m_object_instance_t *
152 get_by_id(uint16_t instance_id, lwm2m_status_t *status)
154 lwm2m_object_instance_t *instance;
155 for(instance =
list_head(instances_list);
157 instance = instance->next) {
158 if(instance->instance_id == instance_id) {
165 static lwm2m_status_t
166 lwm2m_callback(lwm2m_object_instance_t *
object,
167 lwm2m_context_t *ctx)
173 lwm2m_security_server_t *security;
174 security = (lwm2m_security_server_t *)
object;
176 if(ctx->operation == LWM2M_OP_WRITE) {
178 switch(ctx->resource_id) {
179 case LWM2M_SECURITY_SERVER_URI_ID:
180 LOG_DBG(
"Writing security URI value: len: %"PRId16
"\n", ctx->inbuf->size);
181 value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->server_uri, LWM2M_SECURITY_URI_SIZE);
183 security->server_uri_len = ctx->last_value_len;
185 case LWM2M_SECURITY_BOOTSTRAP_SERVER_ID:
186 value = lwm2m_object_read_boolean(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &iv);
188 LOG_DBG(
"Set Bootstrap: %d\n", iv);
189 security->bootstrap = (uint8_t) iv;
191 LOG_WARN(
"Failed to set bootstrap\n");
194 case LWM2M_SECURITY_MODE_ID:
197 value = lwm2m_object_read_int(ctx, ctx->inbuf->buffer, ctx->inbuf->size, &v2);
198 LOG_DBG(
"Writing security MODE value: %"PRId32
" len: %d\n", v2,
199 (
int)ctx->inbuf->size);
200 security->security_mode = v2;
203 case LWM2M_SECURITY_CLIENT_PKI_ID:
204 value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->public_key, LWM2M_SECURITY_KEY_SIZE);
205 security->public_key_len = ctx->last_value_len;
207 LOG_DBG(
"Writing client PKI: len: %"PRIu16
" '", ctx->last_value_len);
208 LOG_DBG_COAP_STRING((
const char *)security->public_key,
209 ctx->last_value_len);
212 case LWM2M_SECURITY_KEY_ID:
213 value = lwm2m_object_read_string(ctx, ctx->inbuf->buffer, ctx->inbuf->size, security->secret_key, LWM2M_SECURITY_KEY_SIZE);
214 security->secret_key_len = ctx->last_value_len;
216 LOG_DBG(
"Writing secret key: len: %"PRIu16
" '", ctx->last_value_len);
217 LOG_DBG_COAP_STRING((
const char *)security->secret_key,
218 ctx->last_value_len);
223 }
else if(ctx->operation == LWM2M_OP_READ) {
224 switch(ctx->resource_id) {
225 case LWM2M_SECURITY_SERVER_URI_ID:
226 lwm2m_object_write_string(ctx, (
const char *) security->server_uri,
227 security->server_uri_len);
230 return LWM2M_STATUS_ERROR;
233 return LWM2M_STATUS_OK;
237 lwm2m_security_server_t *
238 lwm2m_security_get_first(
void)
243 lwm2m_security_server_t *
244 lwm2m_security_get_next(lwm2m_security_server_t *last)
246 return last == NULL ? NULL : (lwm2m_security_server_t *)last->instance.next;
249 lwm2m_security_server_t *
250 lwm2m_security_add_server(uint16_t instance_id,
252 const uint8_t *server_uri,
253 uint8_t server_uri_len)
255 lwm2m_security_server_t *server;
258 if(server_uri_len > LWM2M_SECURITY_URI_SIZE) {
259 LOG_WARN(
"too long server URI: %u\n", server_uri_len);
263 for(server = lwm2m_security_get_first();
265 server = lwm2m_security_get_next(server)) {
266 if(server->server_id == server_id) {
267 if(server->instance.instance_id != instance_id) {
268 LOG_WARN(
"wrong instance id\n");
273 }
else if(server->instance.instance_id == instance_id) {
274 LOG_WARN(
"wrong server id\n");
280 for(i = 0; i < MAX_COUNT; i++) {
281 if(instances[i].instance.instance_id == LWM2M_OBJECT_INSTANCE_NONE) {
282 memset(&instances[i], 0,
sizeof(instances[i]));
283 instances[i].instance.callback = lwm2m_callback;
284 instances[i].instance.object_id = LWM2M_OBJECT_SECURITY_ID;
285 instances[i].instance.instance_id = instance_id;
286 instances[i].instance.resource_ids = resources;
287 instances[i].instance.resource_count =
288 sizeof(resources) /
sizeof(lwm2m_resource_id_t);
289 list_add(instances_list, &instances[i].instance);
290 server = &instances[i];
294 LOG_WARN(
"no space for more servers\n");
299 memcpy(server->server_uri, server_uri, server_uri_len);
300 server->server_uri_len = server_uri_len;
306 lwm2m_security_set_server_psk(lwm2m_security_server_t *server,
307 const uint8_t *identity,
308 uint8_t identity_len,
312 if(server == NULL || identity == NULL || key == NULL) {
315 if(identity_len > LWM2M_SECURITY_KEY_SIZE) {
316 LOG_WARN(
"too large identity: %u\n", identity_len);
319 if(key_len > LWM2M_SECURITY_KEY_SIZE) {
320 LOG_WARN(
"too large identity: %u\n", key_len);
323 memcpy(server->public_key, identity, identity_len);
324 server->public_key_len = identity_len;
325 memcpy(server->secret_key, key, key_len);
326 server->secret_key_len = key_len;
328 server->security_mode = LWM2M_SECURITY_MODE_PSK;
333 static const lwm2m_object_impl_t impl = {
334 .object_id = LWM2M_OBJECT_SECURITY_ID,
335 .get_first = get_first,
336 .get_next = get_next,
337 .get_by_id = get_by_id,
338 .create_instance = create_instance,
339 .delete_instance = delete_instance,
341 static lwm2m_object_t reg_object = {
346 #if COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M 348 get_psk_info(
const coap_endpoint_t *address_info,
352 lwm2m_security_server_t *e;
355 if(info == NULL || address_info == NULL) {
359 for(e = lwm2m_security_get_first();
361 e = lwm2m_security_get_next(e)) {
362 if(e->server_uri_len == 0) {
365 if(e->security_mode != LWM2M_SECURITY_MODE_PSK) {
371 LOG_DBG(
"failed to parse server URI ");
372 LOG_DBG_COAP_STRING((
char *)e->server_uri, e->server_uri_len);
378 LOG_DBG(
"wrong server ");
379 LOG_DBG_COAP_EP(address_info);
381 LOG_DBG_COAP_EP(&ep);
385 if(info->identity_len > 0 && info->identity != NULL) {
387 if(info->identity_len != e->public_key_len ||
388 memcmp(info->identity, e->public_key, info->identity_len)) {
390 LOG_DBG(
"identity not matching\n");
395 LOG_DBG(
"found security match!\n");
404 if(info->identity == NULL || info->identity_len == 0) {
406 info->identity = e->public_key;
407 info->identity_len = e->public_key_len;
411 if(e->secret_key_len == 0) {
416 info->key = e->secret_key;
417 info->key_len = e->secret_key_len;
421 .coap_get_psk_info = get_psk_info
427 lwm2m_security_init(
void)
435 for(i = 0; i < MAX_COUNT; i++) {
436 instances[i].instance.instance_id = LWM2M_OBJECT_INSTANCE_NONE;
438 if(lwm2m_engine_add_generic_object(®_object)) {
441 #if COAP_DTLS_KEYSTORE_CONF_WITH_LWM2M 444 LOG_DBG(
"registered keystore\n");
449 LOG_WARN(
"failed to register\n");
Header file for the LWM2M object API
int coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep)
Parse a CoAP endpoint.
Linked list manipulation routines.
The structure of a CoAP keystore.
void coap_set_keystore(const coap_keystore_t *keystore)
Set the CoAP keystore to use by CoAP.
void * list_head(list_t list)
Get a pointer to the first element of a list.
The structure of a CoAP pre-shared key info.
void list_add(list_t list, void *item)
Add an item at the end of a list.
void list_init(list_t list)
Initialize a list.
#define LIST(name)
Declare a linked list.
Header file for the Contiki OMA LWM2M engine
void * list_pop(list_t list)
Remove the first object on a list.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
int coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2)
Compare two CoAP endpoints.