1 /*
2  * Copyright (c) 2017 Linaro Limited
3  * Copyright (c) 2018-2019 Foundries.io
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define LOG_MODULE_NAME net_lwm2m_obj_security
9 #define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
10 
11 #include <logging/log.h>
12 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
13 
14 #include <stdint.h>
15 #include <init.h>
16 
17 #include "lwm2m_object.h"
18 #include "lwm2m_engine.h"
19 
20 #define SECURITY_VERSION_MAJOR 1
21 #define SECURITY_VERSION_MINOR 0
22 
23 /* Security resource IDs */
24 #define SECURITY_SERVER_URI_ID			0
25 #define SECURITY_BOOTSTRAP_FLAG_ID		1
26 #define SECURITY_MODE_ID			2
27 #define SECURITY_CLIENT_PK_ID			3
28 #define SECURITY_SERVER_PK_ID			4
29 #define SECURITY_SECRET_KEY_ID			5
30 #define SECURITY_SMS_MODE_ID			6
31 #define SECURITY_SMS_BINDING_KEY_PARAM_ID	7
32 #define SECURITY_SMS_BINDING_SECRET_KEY_ID	8
33 #define SECURITY_LWM2M_SERVER_SMS_NUM_ID	9
34 #define SECURITY_SHORT_SERVER_ID		10
35 #define SECURITY_CLIENT_HOLD_OFF_TIME_ID	11
36 #define SECURITY_BS_SERVER_ACCOUNT_TIMEOUT_ID	12
37 
38 #define SECURITY_MAX_ID				13
39 
40 #define MAX_INSTANCE_COUNT		CONFIG_LWM2M_SECURITY_INSTANCE_COUNT
41 
42 #define SECURITY_URI_LEN		255
43 #define IDENTITY_LEN			128
44 #define KEY_LEN				CONFIG_LWM2M_SECURITY_KEY_SIZE
45 
46 /*
47  * Calculate resource instances as follows:
48  * start with SECURITY_MAX_ID
49  */
50 #define RESOURCE_INSTANCE_COUNT	(SECURITY_MAX_ID)
51 
52 /* resource state variables */
53 static char  security_uri[MAX_INSTANCE_COUNT][SECURITY_URI_LEN];
54 static uint8_t  client_identity[MAX_INSTANCE_COUNT][IDENTITY_LEN];
55 static uint8_t  server_pk[MAX_INSTANCE_COUNT][KEY_LEN];
56 static uint8_t  secret_key[MAX_INSTANCE_COUNT][KEY_LEN];
57 static bool  bootstrap_flag[MAX_INSTANCE_COUNT];
58 static uint8_t  security_mode[MAX_INSTANCE_COUNT];
59 static uint16_t short_server_id[MAX_INSTANCE_COUNT];
60 
61 static struct lwm2m_engine_obj security;
62 static struct lwm2m_engine_obj_field fields[] = {
63 	OBJ_FIELD_DATA(SECURITY_SERVER_URI_ID, RW, STRING),
64 	OBJ_FIELD_DATA(SECURITY_BOOTSTRAP_FLAG_ID, W, BOOL),
65 	OBJ_FIELD_DATA(SECURITY_MODE_ID, W, U8),
66 	OBJ_FIELD_DATA(SECURITY_CLIENT_PK_ID, W, OPAQUE),
67 	OBJ_FIELD_DATA(SECURITY_SERVER_PK_ID, W, OPAQUE),
68 	OBJ_FIELD_DATA(SECURITY_SECRET_KEY_ID, W, OPAQUE),
69 	OBJ_FIELD_DATA(SECURITY_SMS_MODE_ID, W_OPT, U8),
70 	OBJ_FIELD_DATA(SECURITY_SMS_BINDING_KEY_PARAM_ID, W_OPT, OPAQUE),
71 	OBJ_FIELD_DATA(SECURITY_SMS_BINDING_SECRET_KEY_ID, W_OPT, OPAQUE),
72 	OBJ_FIELD_DATA(SECURITY_LWM2M_SERVER_SMS_NUM_ID, W_OPT, STRING),
73 	OBJ_FIELD_DATA(SECURITY_SHORT_SERVER_ID, W_OPT, U16),
74 	OBJ_FIELD_DATA(SECURITY_CLIENT_HOLD_OFF_TIME_ID, W_OPT, U32),
75 	OBJ_FIELD_DATA(SECURITY_BS_SERVER_ACCOUNT_TIMEOUT_ID, W_OPT, U32)
76 };
77 
78 static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
79 static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][SECURITY_MAX_ID];
80 static struct lwm2m_engine_res_inst
81 			res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
82 
security_create(uint16_t obj_inst_id)83 static struct lwm2m_engine_obj_inst *security_create(uint16_t obj_inst_id)
84 {
85 	int index, i = 0, j = 0;
86 
87 	/* Check that there is no other instance with this ID */
88 	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
89 		if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
90 			LOG_ERR("Can not create instance - "
91 				"already existing: %u", obj_inst_id);
92 			return NULL;
93 		}
94 	}
95 
96 	for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
97 		if (!inst[index].obj) {
98 			break;
99 		}
100 	}
101 
102 	if (index >= MAX_INSTANCE_COUNT) {
103 		LOG_ERR("Can not create instance - "
104 			"no more room: %u", obj_inst_id);
105 		return NULL;
106 	}
107 
108 	/* default values */
109 	security_uri[index][0] = '\0';
110 	client_identity[index][0] = '\0';
111 	bootstrap_flag[index] = 0;
112 	security_mode[index] = 0U;
113 	short_server_id[index] = 0U;
114 
115 	(void)memset(res[index], 0,
116 		     sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
117 	init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));
118 
119 	/* initialize instance resource data */
120 	INIT_OBJ_RES_DATA(SECURITY_SERVER_URI_ID, res[index], i,
121 			  res_inst[index], j,
122 			  security_uri[index], SECURITY_URI_LEN);
123 	INIT_OBJ_RES_DATA(SECURITY_BOOTSTRAP_FLAG_ID, res[index], i,
124 			  res_inst[index], j,
125 			  &bootstrap_flag[index], sizeof(*bootstrap_flag));
126 	INIT_OBJ_RES_DATA(SECURITY_MODE_ID, res[index], i,
127 			  res_inst[index], j,
128 			  &security_mode[index], sizeof(*security_mode));
129 	INIT_OBJ_RES_DATA(SECURITY_CLIENT_PK_ID, res[index], i,
130 			  res_inst[index], j,
131 			  &client_identity[index], IDENTITY_LEN);
132 	INIT_OBJ_RES_DATA(SECURITY_SERVER_PK_ID, res[index], i,
133 			  res_inst[index], j,
134 			  &server_pk[index], KEY_LEN);
135 	INIT_OBJ_RES_DATA(SECURITY_SECRET_KEY_ID, res[index], i,
136 			  res_inst[index], j,
137 			  &secret_key[index], KEY_LEN);
138 	INIT_OBJ_RES_DATA(SECURITY_SHORT_SERVER_ID, res[index], i,
139 			  res_inst[index], j,
140 			  &short_server_id[index], sizeof(*short_server_id));
141 
142 	inst[index].resources = res[index];
143 	inst[index].resource_count = i;
144 	LOG_DBG("Create LWM2M security instance: %d", obj_inst_id);
145 
146 	return &inst[index];
147 }
148 
lwm2m_security_inst_id_to_index(uint16_t obj_inst_id)149 int lwm2m_security_inst_id_to_index(uint16_t obj_inst_id)
150 {
151 	int i;
152 
153 	for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
154 		if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
155 			return i;
156 		}
157 	}
158 
159 	return -ENOENT;
160 }
161 
lwm2m_security_index_to_inst_id(int index)162 int lwm2m_security_index_to_inst_id(int index)
163 {
164 	if (index >= MAX_INSTANCE_COUNT) {
165 		return -EINVAL;
166 	}
167 
168 	/* not instanstiated */
169 	if (!inst[index].obj) {
170 		return -ENOENT;
171 	}
172 
173 	return inst[index].obj_inst_id;
174 }
175 
lwm2m_security_init(const struct device * dev)176 static int lwm2m_security_init(const struct device *dev)
177 {
178 	struct lwm2m_engine_obj_inst *obj_inst = NULL;
179 	int ret = 0;
180 
181 	security.obj_id = LWM2M_OBJECT_SECURITY_ID;
182 	security.version_major = SECURITY_VERSION_MAJOR;
183 	security.version_minor = SECURITY_VERSION_MINOR;
184 	security.is_core = true;
185 	security.fields = fields;
186 	security.field_count = ARRAY_SIZE(fields);
187 	security.max_instance_count = MAX_INSTANCE_COUNT;
188 	security.create_cb = security_create;
189 	lwm2m_register_obj(&security);
190 
191 	/* auto create the first instance */
192 	ret = lwm2m_create_obj_inst(LWM2M_OBJECT_SECURITY_ID, 0, &obj_inst);
193 	if (ret < 0) {
194 		LOG_ERR("Create LWM2M security instance 0 error: %d", ret);
195 	}
196 
197 	return ret;
198 }
199 
200 SYS_INIT(lwm2m_security_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
201