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