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 <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
13
14 #include <stdint.h>
15 #include <zephyr/init.h>
16
17 #include "lwm2m_object.h"
18 #include "lwm2m_engine.h"
19
20 #define SECURITY_VERSION_MAJOR 1
21 #if defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1)
22 #define SECURITY_VERSION_MINOR 1
23 #define SECURITY_MAX_ID 18
24 #ifdef CONFIG_LWM2M_SECURITY_DTLS_TLS_CIPHERSUITE_MAX
25 #define DTLS_TLS_CIPHERSUITE_MAX CONFIG_LWM2M_SECURITY_DTLS_TLS_CIPHERSUITE_MAX
26 #else
27 #define DTLS_TLS_CIPHERSUITE_MAX 0
28 #endif /* CONFIG_LWM2M_SECURITY_DTLS_TLS_CIPHERSUITE_MAX */
29 #else
30 #define SECURITY_VERSION_MINOR 0
31 #define SECURITY_MAX_ID 13
32 #endif /* defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1) */
33
34 /* Security resource IDs */
35 #define SECURITY_SERVER_URI_ID 0
36 #define SECURITY_BOOTSTRAP_FLAG_ID 1
37 #define SECURITY_MODE_ID 2
38 #define SECURITY_CLIENT_PK_ID 3
39 #define SECURITY_SERVER_PK_ID 4
40 #define SECURITY_SECRET_KEY_ID 5
41 #define SECURITY_SMS_MODE_ID 6
42 #define SECURITY_SMS_BINDING_KEY_PARAM_ID 7
43 #define SECURITY_SMS_BINDING_SECRET_KEY_ID 8
44 #define SECURITY_LWM2M_SERVER_SMS_NUM_ID 9
45 #define SECURITY_SHORT_SERVER_ID 10
46 #define SECURITY_CLIENT_HOLD_OFF_TIME_ID 11
47 #define SECURITY_BS_SERVER_ACCOUNT_TIMEOUT_ID 12
48 #if defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1)
49 #define SECURITY_MATCHING_TYPE_ID 13
50 #define SECURITY_SNI_ID 14
51 #define SECURITY_CERTIFICATE_USAGE_ID 15
52 #define SECURITY_DTLS_TLS_CIPHERSUITE_ID 16
53 #define SECURITY_OSCORE_SEC_MODE_ID 17
54 #endif
55
56 #define MAX_INSTANCE_COUNT CONFIG_LWM2M_SECURITY_INSTANCE_COUNT
57
58 #define SECURITY_URI_LEN 255
59 #define IDENTITY_LEN CONFIG_LWM2M_SECURITY_KEY_SIZE
60 #define KEY_LEN CONFIG_LWM2M_SECURITY_KEY_SIZE
61
62 /*
63 * Calculate resource instances as follows:
64 * start with SECURITY_MAX_ID
65 *
66 * If using object version 1.1
67 * subtract MULTI resources because their counts include 0 resource (1)
68 * add DTLS_TLS_CIPHERSUITE_MAX for DTLS_TLS_CIPHERSUITE resource instances
69 */
70 #if defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1)
71 #define RESOURCE_INSTANCE_COUNT (SECURITY_MAX_ID - 1 + DTLS_TLS_CIPHERSUITE_MAX)
72 #else
73 #define RESOURCE_INSTANCE_COUNT (SECURITY_MAX_ID)
74 #endif
75
76 /* resource state variables */
77 static char security_uri[MAX_INSTANCE_COUNT][SECURITY_URI_LEN];
78 static uint8_t client_identity[MAX_INSTANCE_COUNT][IDENTITY_LEN];
79 static uint8_t server_pk[MAX_INSTANCE_COUNT][KEY_LEN];
80 static uint8_t secret_key[MAX_INSTANCE_COUNT][KEY_LEN];
81 static bool bootstrap_flag[MAX_INSTANCE_COUNT];
82 static uint8_t security_mode[MAX_INSTANCE_COUNT];
83 static uint16_t short_server_id[MAX_INSTANCE_COUNT];
84
85 static struct lwm2m_engine_obj security;
86 static struct lwm2m_engine_obj_field fields[] = {
87 OBJ_FIELD_DATA(SECURITY_SERVER_URI_ID, RW, STRING),
88 OBJ_FIELD_DATA(SECURITY_BOOTSTRAP_FLAG_ID, W, BOOL),
89 OBJ_FIELD_DATA(SECURITY_MODE_ID, W, U8),
90 OBJ_FIELD_DATA(SECURITY_CLIENT_PK_ID, W, OPAQUE),
91 OBJ_FIELD_DATA(SECURITY_SERVER_PK_ID, W, OPAQUE),
92 OBJ_FIELD_DATA(SECURITY_SECRET_KEY_ID, W, OPAQUE),
93 OBJ_FIELD_DATA(SECURITY_SMS_MODE_ID, W_OPT, U8),
94 OBJ_FIELD_DATA(SECURITY_SMS_BINDING_KEY_PARAM_ID, W_OPT, OPAQUE),
95 OBJ_FIELD_DATA(SECURITY_SMS_BINDING_SECRET_KEY_ID, W_OPT, OPAQUE),
96 OBJ_FIELD_DATA(SECURITY_LWM2M_SERVER_SMS_NUM_ID, W_OPT, STRING),
97 OBJ_FIELD_DATA(SECURITY_SHORT_SERVER_ID, W_OPT, U16),
98 OBJ_FIELD_DATA(SECURITY_CLIENT_HOLD_OFF_TIME_ID, W_OPT, S32),
99 OBJ_FIELD_DATA(SECURITY_BS_SERVER_ACCOUNT_TIMEOUT_ID, W_OPT, S32),
100 #if defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1)
101 OBJ_FIELD_DATA(SECURITY_MATCHING_TYPE_ID, W_OPT, S32),
102 OBJ_FIELD_DATA(SECURITY_SNI_ID, W_OPT, STRING),
103 OBJ_FIELD_DATA(SECURITY_CERTIFICATE_USAGE_ID, W_OPT, U32),
104 OBJ_FIELD_DATA(SECURITY_DTLS_TLS_CIPHERSUITE_ID, W_OPT, U32),
105 OBJ_FIELD_DATA(SECURITY_OSCORE_SEC_MODE_ID, W_OPT, OBJLNK)
106 #endif
107 };
108
109 static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
110 static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][SECURITY_MAX_ID];
111 static struct lwm2m_engine_res_inst
112 res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
113
security_create(uint16_t obj_inst_id)114 static struct lwm2m_engine_obj_inst *security_create(uint16_t obj_inst_id)
115 {
116 int index, i = 0, j = 0;
117
118 /* Check that there is no other instance with this ID */
119 for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
120 if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
121 LOG_ERR("Can not create instance - "
122 "already existing: %u", obj_inst_id);
123 return NULL;
124 }
125 }
126
127 for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
128 if (!inst[index].obj) {
129 break;
130 }
131 }
132
133 if (index >= MAX_INSTANCE_COUNT) {
134 LOG_ERR("Can not create instance - "
135 "no more room: %u", obj_inst_id);
136 return NULL;
137 }
138
139 /* default values */
140 security_uri[index][0] = '\0';
141 client_identity[index][0] = '\0';
142 bootstrap_flag[index] = 0;
143 security_mode[index] = 0U;
144 short_server_id[index] = 0U;
145
146 (void)memset(res[index], 0,
147 sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
148 init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));
149
150 /* initialize instance resource data */
151 INIT_OBJ_RES_DATA_LEN(SECURITY_SERVER_URI_ID, res[index], i,
152 res_inst[index], j,
153 security_uri[index], SECURITY_URI_LEN, 0);
154 INIT_OBJ_RES_DATA(SECURITY_BOOTSTRAP_FLAG_ID, res[index], i,
155 res_inst[index], j,
156 &bootstrap_flag[index], sizeof(*bootstrap_flag));
157 INIT_OBJ_RES_DATA(SECURITY_MODE_ID, res[index], i,
158 res_inst[index], j,
159 &security_mode[index], sizeof(*security_mode));
160 INIT_OBJ_RES_DATA_LEN(SECURITY_CLIENT_PK_ID, res[index], i,
161 res_inst[index], j,
162 &client_identity[index], IDENTITY_LEN, 0);
163 INIT_OBJ_RES_DATA_LEN(SECURITY_SERVER_PK_ID, res[index], i,
164 res_inst[index], j,
165 &server_pk[index], KEY_LEN, 0);
166 INIT_OBJ_RES_DATA_LEN(SECURITY_SECRET_KEY_ID, res[index], i,
167 res_inst[index], j,
168 &secret_key[index], KEY_LEN, 0);
169 INIT_OBJ_RES_DATA(SECURITY_SHORT_SERVER_ID, res[index], i,
170 res_inst[index], j,
171 &short_server_id[index], sizeof(*short_server_id));
172 #if defined(CONFIG_LWM2M_SECURITY_OBJECT_VERSION_1_1)
173 INIT_OBJ_RES_OPTDATA(SECURITY_MATCHING_TYPE_ID, res[index], i, res_inst[index], j);
174 INIT_OBJ_RES_OPTDATA(SECURITY_SNI_ID, res[index], i, res_inst[index], j);
175 INIT_OBJ_RES_OPTDATA(SECURITY_CERTIFICATE_USAGE_ID, res[index], i, res_inst[index], j);
176 INIT_OBJ_RES_MULTI_OPTDATA(SECURITY_DTLS_TLS_CIPHERSUITE_ID, res[index], i,
177 res_inst[index], j, DTLS_TLS_CIPHERSUITE_MAX, false);
178 INIT_OBJ_RES_OPTDATA(SECURITY_OSCORE_SEC_MODE_ID, res[index], i, res_inst[index], j);
179 #endif
180
181 inst[index].resources = res[index];
182 inst[index].resource_count = i;
183 LOG_DBG("Create LWM2M security instance: %d", obj_inst_id);
184
185 return &inst[index];
186 }
187
lwm2m_security_inst_id_to_index(uint16_t obj_inst_id)188 int lwm2m_security_inst_id_to_index(uint16_t obj_inst_id)
189 {
190 int i;
191
192 for (i = 0; i < MAX_INSTANCE_COUNT; i++) {
193 if (inst[i].obj && inst[i].obj_inst_id == obj_inst_id) {
194 return i;
195 }
196 }
197
198 return -ENOENT;
199 }
200
lwm2m_security_index_to_inst_id(int index)201 int lwm2m_security_index_to_inst_id(int index)
202 {
203 if (index >= MAX_INSTANCE_COUNT) {
204 return -EINVAL;
205 }
206
207 /* not instantiated */
208 if (!inst[index].obj) {
209 return -ENOENT;
210 }
211
212 return inst[index].obj_inst_id;
213 }
214
lwm2m_security_short_id_to_inst(uint16_t short_id)215 int lwm2m_security_short_id_to_inst(uint16_t short_id)
216 {
217 for (int i = 0; i < MAX_INSTANCE_COUNT; i++) {
218 if (short_server_id[i] == short_id) {
219 return inst[i].obj_inst_id;
220 }
221 }
222 return -ENOENT;
223 }
224
lwm2m_security_mode(struct lwm2m_ctx * ctx)225 int lwm2m_security_mode(struct lwm2m_ctx *ctx)
226 {
227 int ret;
228 uint8_t mode;
229 struct lwm2m_obj_path path =
230 LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, ctx->sec_obj_inst, SECURITY_MODE_ID);
231
232 ret = lwm2m_get_u8(&path, &mode);
233 if (ret) {
234 return ret;
235 }
236 return (int)mode;
237 }
238
239
lwm2m_security_init(void)240 static int lwm2m_security_init(void)
241 {
242 struct lwm2m_engine_obj_inst *obj_inst = NULL;
243 int ret = 0;
244
245 security.obj_id = LWM2M_OBJECT_SECURITY_ID;
246 security.version_major = SECURITY_VERSION_MAJOR;
247 security.version_minor = SECURITY_VERSION_MINOR;
248 security.is_core = true;
249 security.fields = fields;
250 security.field_count = ARRAY_SIZE(fields);
251 security.max_instance_count = MAX_INSTANCE_COUNT;
252 security.create_cb = security_create;
253 lwm2m_register_obj(&security);
254
255 /* auto create the first instance */
256 ret = lwm2m_create_obj_inst(LWM2M_OBJECT_SECURITY_ID, 0, &obj_inst);
257 if (ret < 0) {
258 LOG_ERR("Create LWM2M security instance 0 error: %d", ret);
259 }
260
261 return ret;
262 }
263
264 LWM2M_CORE_INIT(lwm2m_security_init);
265