1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4
5 #include <stdio.h>
6
7 #include "linkkit/coap_api.h"
8 #include "iotx_coap_internal.h"
9 #include "Cloud_CoAPPlatform.h"
10 #include "Cloud_CoAPPlatform.h"
11 #include "Cloud_CoAPMessage.h"
12 #include "Cloud_CoAPExport.h"
13 #include "linkkit/infra/infra_aes.h"
14
15 #define IOTX_SIGN_LENGTH (40 + 1)
16 #define IOTX_SIGN_SOURCE_LEN (256)
17 #define IOTX_AUTH_TOKEN_LEN (192 + 1)
18 #define IOTX_COAP_INIT_TOKEN (0x01020304)
19 #define IOTX_LIST_MAX_ITEM (10)
20
21 #ifndef INFRA_LOG
22 #undef HEXDUMP_DEBUG
23 #undef HEXDUMP_INFO
24
25 #define HEXDUMP_DEBUG(...)
26 #define HEXDUMP_INFO(...)
27 #endif
28
29 #define IOTX_AUTH_STR "auth"
30 #define IOTX_SIGN_SRC_STR "clientId%sdeviceName%sproductKey%s"
31 #define IOTX_SIGN_SRC_STR_WITH_SEQ "clientId%sdeviceName%sproductKey%sseq%d"
32
33 #define IOTX_AUTH_DEVICENAME_STR \
34 "{\"productKey\":\"%s\",\"deviceName\":\"%s\",\"clientId\":\"%s\"," \
35 "\"sign\":\"%s\"}"
36 #define IOTX_AUTH_DEVICENAME_STR_WITH_SEQ \
37 "{\"productKey\":\"%s\",\"deviceName\":\"%s\",\"clientId\":\"%s\"," \
38 "\"sign\":\"%s\",\"seq\":\"%d\"}"
39
40 #define IOTX_COAP_ONLINE_DTLS_SERVER_URL \
41 "coaps://%s.coap.cn-shanghai.link.aliyuncs.com:5684"
42 #define IOTX_COAP_ONLINE_PSK_SERVER_URL \
43 "coap-psk://%s.coap.cn-shanghai.link.aliyuncs.com:5682"
44
45 iotx_coap_context_t *g_coap_context = NULL;
46
47 typedef struct {
48 char *p_auth_token;
49 int auth_token_len;
50 char is_authed;
51 iotx_coap_device_info_t *p_devinfo;
52 Cloud_CoAPContext *p_coap_ctx;
53 unsigned int coap_token;
54 unsigned int seq;
55 unsigned char key[32];
56 iotx_event_handle_t event_handle;
57 } iotx_coap_t;
58
iotx_calc_sign(const char * p_device_secret,const char * p_client_id,const char * p_device_name,const char * p_product_key,char sign[IOTX_SIGN_LENGTH])59 int iotx_calc_sign(const char *p_device_secret, const char *p_client_id,
60 const char *p_device_name, const char *p_product_key,
61 char sign[IOTX_SIGN_LENGTH])
62 {
63 char *p_msg = NULL;
64
65 p_msg = (char *)coap_malloc(IOTX_SIGN_SOURCE_LEN);
66 if (NULL == p_msg) {
67 return IOTX_ERR_NO_MEM;
68 }
69 memset(sign, 0x00, IOTX_SIGN_LENGTH);
70 memset(p_msg, 0x00, IOTX_SIGN_SOURCE_LEN);
71
72 HAL_Snprintf(p_msg, IOTX_SIGN_SOURCE_LEN, IOTX_SIGN_SRC_STR, p_client_id,
73 p_device_name, p_product_key);
74 utils_hmac_md5(p_msg, strlen(p_msg), sign, p_device_secret,
75 strlen(p_device_secret));
76
77 coap_free(p_msg);
78 COAP_DEBUG("The device name sign: %s", sign);
79 return IOTX_SUCCESS;
80 }
81
iotx_calc_sign_with_seq(const char * p_device_secret,const char * p_client_id,const char * p_device_name,const char * p_product_key,unsigned int seq,char sign[IOTX_SIGN_LENGTH])82 int iotx_calc_sign_with_seq(const char *p_device_secret,
83 const char *p_client_id, const char *p_device_name,
84 const char *p_product_key, unsigned int seq,
85 char sign[IOTX_SIGN_LENGTH])
86 {
87 char *p_msg = NULL;
88
89 p_msg = (char *)coap_malloc(IOTX_SIGN_SOURCE_LEN);
90 if (NULL == p_msg) {
91 return IOTX_ERR_NO_MEM;
92 }
93 memset(sign, 0x00, IOTX_SIGN_LENGTH);
94 memset(p_msg, 0x00, IOTX_SIGN_SOURCE_LEN);
95
96 HAL_Snprintf(p_msg, IOTX_SIGN_SOURCE_LEN, IOTX_SIGN_SRC_STR_WITH_SEQ,
97 p_client_id, p_device_name, p_product_key, seq);
98 COAP_DEBUG("The source string: %s", p_msg);
99 utils_hmac_md5(p_msg, strlen(p_msg), sign, p_device_secret,
100 strlen(p_device_secret));
101
102 coap_free(p_msg);
103 COAP_DEBUG("The device name sign with seq: %s", sign);
104 return IOTX_SUCCESS;
105 }
106
iotx_get_token_from_json(char * p_str,char * p_token,int len)107 static int iotx_get_token_from_json(char *p_str, char *p_token, int len)
108 {
109 char *p_value = NULL;
110 if (NULL == p_str || NULL == p_token) {
111 COAP_ERR("Invalid paramter p_str %p, p_token %p", p_str, p_token);
112 return IOTX_ERR_INVALID_PARAM;
113 }
114
115 p_value = LITE_json_value_of("token", p_str, 0x1234, "coap.cloud");
116 if (NULL != p_value) {
117 if (len - 1 < strlen(p_value)) {
118 return IOTX_ERR_BUFF_TOO_SHORT;
119 }
120 memset(p_token, 0x00, len);
121 strncpy(p_token, p_value, strlen(p_value));
122 #ifdef INFRA_MEM_STATS
123 LITE_free(p_value);
124 #else
125 HAL_Free((void *)p_value);
126 #endif
127 return IOTX_SUCCESS;
128 }
129
130 return IOTX_ERR_AUTH_FAILED;
131 }
132
iotx_parse_auth_from_json(char * p_str,iotx_coap_t * p_iotx_coap)133 static int iotx_parse_auth_from_json(char *p_str, iotx_coap_t *p_iotx_coap)
134 {
135 int ret = -1;
136 lite_cjson_t root;
137 lite_cjson_t node;
138 unsigned char key[32] = { 0 };
139 unsigned char buff[128] = { 0 };
140 unsigned char random[32 + 1] = { 0 };
141
142 if (NULL == p_str || NULL == p_iotx_coap) {
143 return IOTX_ERR_INVALID_PARAM;
144 }
145
146 memset(&root, 0x00, sizeof(lite_cjson_t));
147 memset(&node, 0x00, sizeof(lite_cjson_t));
148 ret = lite_cjson_parse(p_str, strlen(p_str), &root);
149 if (-1 == ret) {
150 return IOTX_ERR_AUTH_FAILED;
151 }
152
153 ret = lite_cjson_object_item(&root, "token", strlen("token"), &node);
154 if (-1 == ret) {
155 return IOTX_ERR_AUTH_FAILED;
156 }
157 if (p_iotx_coap->auth_token_len - 1 < node.value_length) {
158 return IOTX_ERR_BUFF_TOO_SHORT;
159 }
160 memset(p_iotx_coap->p_auth_token, 0x00, node.value_length);
161 strncpy(p_iotx_coap->p_auth_token, node.value, node.value_length);
162
163 memset(&node, 0x00, sizeof(lite_cjson_t));
164 ret =
165 lite_cjson_object_item(&root, "seqOffset", strlen("seqOffset"), &node);
166 if (-1 == ret) {
167 return IOTX_ERR_AUTH_FAILED;
168 }
169 p_iotx_coap->seq = node.value_int;
170
171 memset(&node, 0x00, sizeof(lite_cjson_t));
172 ret = lite_cjson_object_item(&root, "random", strlen("random"), &node);
173 if (-1 == ret) {
174 return IOTX_ERR_AUTH_FAILED;
175 }
176
177 if (node.value_length > 32) {
178 return IOTX_ERR_BUFF_TOO_SHORT;
179 }
180 memcpy(random, node.value, node.value_length);
181 HAL_Snprintf((char *)buff, sizeof(buff), "%s,%s",
182 p_iotx_coap->p_devinfo->device_secret, random);
183 COAP_DEBUG("The src:%s", buff);
184 utils_sha256(buff, strlen((char *)buff), key);
185 memcpy(p_iotx_coap->key, key + 8, 16);
186 COAP_DEBUG("The key is:");
187 HEXDUMP_DEBUG(key, 32);
188 COAP_DEBUG("The short key:");
189 HEXDUMP_DEBUG(p_iotx_coap->key, 16);
190
191 return IOTX_SUCCESS;
192 }
193
iotx_device_name_auth_callback(void * user,void * p_message)194 static void iotx_device_name_auth_callback(void *user, void *p_message)
195 {
196 int ret_code = IOTX_SUCCESS;
197 iotx_coap_t *p_iotx_coap = NULL;
198 Cloud_CoAPMessage *message = (Cloud_CoAPMessage *)p_message;
199
200 if (NULL == user) {
201 COAP_ERR("Invalid paramter, p_arg %p", user);
202 return;
203 }
204 p_iotx_coap = (iotx_coap_t *)user;
205
206 if (NULL == message) {
207 COAP_ERR("Invalid paramter, message %p", message);
208 return;
209 }
210 COAP_DEBUG("Receive response message:");
211 COAP_DEBUG("* Response Code : 0x%x", message->header.code);
212 COAP_DEBUG("* Payload: %s", message->payload);
213
214 switch (message->header.code) {
215 case COAP_MSG_CODE_205_CONTENT:
216 {
217 if (COAP_ENDPOINT_PSK == p_iotx_coap->p_coap_ctx->network.ep_type) {
218 ret_code = iotx_parse_auth_from_json((char *)message->payload,
219 p_iotx_coap);
220 } else {
221 ret_code = iotx_get_token_from_json(
222 (char *)message->payload, p_iotx_coap->p_auth_token,
223 p_iotx_coap->auth_token_len);
224 }
225
226 if (IOTX_SUCCESS == ret_code) {
227 p_iotx_coap->is_authed = IOT_TRUE;
228 COAP_INFO("CoAP authenticate success!!!");
229 }
230 break;
231 }
232 case COAP_MSG_CODE_500_INTERNAL_SERVER_ERROR:
233 {
234 COAP_INFO(
235 "CoAP internal server error, authenticate failed, will retry "
236 "it");
237 HAL_SleepMs(1000);
238 IOT_CoAP_DeviceNameAuth((iotx_coap_context_t *)p_iotx_coap);
239 break;
240 }
241 default:
242 break;
243 }
244 }
245
iotx_get_coap_token(iotx_coap_t * p_iotx_coap,unsigned char * p_encoded_data)246 static unsigned int iotx_get_coap_token(iotx_coap_t *p_iotx_coap,
247 unsigned char *p_encoded_data)
248 {
249 unsigned int value = p_iotx_coap->coap_token;
250 p_encoded_data[0] = (unsigned char)((value & 0x00FF) >> 0);
251 p_encoded_data[1] = (unsigned char)((value & 0xFF00) >> 8);
252 p_encoded_data[2] = (unsigned char)((value & 0xFF0000) >> 16);
253 p_encoded_data[3] = (unsigned char)((value & 0xFF000000) >> 24);
254 p_iotx_coap->coap_token++;
255 return sizeof(unsigned int);
256 }
257
iotx_event_notifyer(unsigned int code,Cloud_CoAPMessage * message)258 void iotx_event_notifyer(unsigned int code, Cloud_CoAPMessage *message)
259 {
260 if (NULL == message) {
261 COAP_ERR("Invalid paramter, message %p", message);
262 return;
263 }
264
265 COAP_DEBUG("Error code: 0x%x, payload: %s", code, message->payload);
266 switch (code) {
267 case COAP_MSG_CODE_402_BAD_OPTION:
268 case COAP_MSG_CODE_401_UNAUTHORIZED:
269 {
270 iotx_coap_t *p_context = NULL;
271 if (NULL != message->user) {
272 p_context = (iotx_coap_t *)message->user;
273 p_context->is_authed = IOT_FALSE;
274 IOT_CoAP_DeviceNameAuth(p_context);
275 COAP_INFO("IoTx token expired, will reauthenticate");
276 }
277 /* TODO: call event handle to notify application */
278 /* p_context->event_handle(); */
279 break;
280 }
281
282 default:
283 break;
284 }
285 }
286
iotx_get_well_known_handler(void * arg,void * p_response)287 static void iotx_get_well_known_handler(void *arg, void *p_response)
288 {
289 int len = 0;
290 unsigned char *p_payload = NULL;
291 iotx_coap_resp_code_t resp_code;
292 IOT_CoAP_GetMessageCode(p_response, &resp_code);
293 IOT_CoAP_GetMessagePayload(p_response, &p_payload, &len);
294 COAP_INFO("[APPL]: Message response code: %d", resp_code);
295 COAP_INFO("[APPL]: Len: %d, Payload: %s, ", len, p_payload);
296 }
297
iotx_get_well_known(iotx_coap_context_t * p_context)298 int iotx_get_well_known(iotx_coap_context_t *p_context)
299 {
300 int len = 0;
301 Cloud_CoAPContext *p_coap_ctx = NULL;
302 iotx_coap_t *p_iotx_coap = NULL;
303 Cloud_CoAPMessage message;
304 unsigned char token[8] = { 0 };
305
306 p_iotx_coap = (iotx_coap_t *)p_context;
307 p_coap_ctx = (Cloud_CoAPContext *)p_iotx_coap->p_coap_ctx;
308
309 CoAPMessage_init(&message);
310 CoAPMessageType_set(&message, COAP_MESSAGE_TYPE_CON);
311 CoAPMessageCode_set(&message, COAP_MSG_CODE_GET);
312 CoAPMessageId_set(&message, Cloud_CoAPMessageId_gen(p_coap_ctx));
313 len = iotx_get_coap_token(p_iotx_coap, token);
314 CoAPMessageToken_set(&message, token, len);
315 Cloud_CoAPMessageHandler_set(&message, iotx_get_well_known_handler);
316 CoAPStrOption_add(&message, COAP_OPTION_URI_PATH,
317 (unsigned char *)".well-known", strlen(".well-known"));
318 CoAPStrOption_add(&message, COAP_OPTION_URI_PATH, (unsigned char *)"core",
319 strlen("core"));
320 CoAPUintOption_add(&message, COAP_OPTION_ACCEPT, COAP_CT_APP_LINK_FORMAT);
321 CoAPMessageUserData_set(&message, (void *)p_iotx_coap);
322 Cloud_CoAPMessage_send(p_coap_ctx, &message);
323 CoAPMessage_destory(&message);
324 return IOTX_SUCCESS;
325 }
326
iotx_coap_report_rsphdl(void * arg,void * p_response)327 static void iotx_coap_report_rsphdl(void *arg, void *p_response)
328 {
329 int p_payload_len = 0;
330 unsigned char *p_payload = NULL;
331 iotx_coap_resp_code_t resp_code;
332
333 IOT_CoAP_GetMessageCode(p_response, &resp_code);
334 IOT_CoAP_GetMessagePayload(p_response, &p_payload, &p_payload_len);
335 COAP_DEBUG("Report response: CoAP response code = %d", resp_code);
336 COAP_DEBUG("Report response: CoAP msg_len = %d", p_payload_len);
337 if (p_payload_len > 0) {
338 COAP_DEBUG("Report response: CoAP msg = '%.*s'", p_payload_len,
339 p_payload);
340 } else {
341 COAP_WRN("Report response: CoAP response payload_len = 0");
342 }
343 }
344
coap_report_func(void * handle,const char * topic_name,int req_ack,void * data,int len)345 static int coap_report_func(void *handle, const char *topic_name, int req_ack,
346 void *data, int len)
347 {
348 iotx_message_t message;
349 char coap_topic[100] = { 0 };
350 (void)req_ack;
351
352 memset(&message, 0, sizeof(iotx_message_t));
353 message.p_payload = (unsigned char *)data;
354 message.payload_len = len;
355 message.resp_callback = iotx_coap_report_rsphdl;
356 message.msg_type = IOTX_MESSAGE_NON;
357 message.content_type = IOTX_CONTENT_TYPE_JSON;
358 HAL_Snprintf(coap_topic, 100, "/topic%s", topic_name);
359 return IOT_CoAP_SendMessage(handle, (char *)coap_topic, &message);
360 }
361
iotx_aes_cbc_encrypt(const unsigned char * src,int len,const unsigned char * key,void * out)362 int iotx_aes_cbc_encrypt(const unsigned char *src, int len,
363 const unsigned char *key, void *out)
364 {
365 char *iv = "543yhjy97ae7fyfg";
366
367 int len1 = len & 0xfffffff0;
368 int len2 = len1 + 16;
369 int pad = len2 - len;
370 int ret = 0;
371
372 p_Aes128_t aes_e_h = infra_aes128_init((unsigned char *)key,
373 (unsigned char *)iv, AES_ENCRYPTION);
374 if (len1) {
375 ret = infra_aes128_cbc_encrypt(aes_e_h, src, len1 >> 4, out);
376 }
377 if (!ret && pad) {
378 char buf[16] = { 0 };
379 memcpy(buf, src + len1, len - len1);
380 memset(buf + len - len1, pad, pad);
381 ret = infra_aes128_cbc_encrypt(aes_e_h, buf, 1,
382 (unsigned char *)out + len1);
383 }
384
385 infra_aes128_destroy(aes_e_h);
386
387 COAP_DEBUG("to encrypt src: %s, len: %d", src, len2);
388 return ret == 0 ? len2 : 0;
389 }
390
iotx_aes_cbc_decrypt(const unsigned char * src,int len,const unsigned char * key,void * out)391 int iotx_aes_cbc_decrypt(const unsigned char *src, int len,
392 const unsigned char *key, void *out)
393 {
394 char *iv = "543yhjy97ae7fyfg";
395
396 p_Aes128_t aes_d_h;
397 int ret = 0;
398 int n = len >> 4;
399
400 aes_d_h = infra_aes128_init((uint8_t *)key, (uint8_t *)iv, AES_DECRYPTION);
401 if (!aes_d_h) {
402 COAP_INFO("fail to decrypt");
403 return 0;
404 }
405 if (n > 1) {
406 ret = infra_aes128_cbc_decrypt(aes_d_h, src, n - 1, out);
407 }
408
409 if (ret == 0) {
410 char *out_c = (char *)out;
411 int offset = n > 0 ? ((n - 1) << 4) : 0;
412 out_c[offset] = 0;
413
414 if (aes_d_h) {
415 ret = infra_aes128_cbc_decrypt(aes_d_h, src + offset, 1,
416 out_c + offset);
417 } else {
418 COAP_ERR("fail to decrypt remain data");
419 }
420
421 if (ret == 0) {
422 char pad = out_c[len - 1];
423 out_c[len - pad] = 0;
424 /*
425 COAP_DEBUG("decrypt data:%s, len:%d", out_c, len - pad);
426 */
427 infra_aes128_destroy(aes_d_h);
428 return len - pad;
429 }
430 }
431 infra_aes128_destroy(aes_d_h);
432
433 return 0;
434 }
435
436 #if AES_CFB_NOPADDING
iotx_aes_cfb_encrypt(const unsigned char * src,int len,const unsigned char * key,void * out)437 static int iotx_aes_cfb_encrypt(const unsigned char *src, int len,
438 const unsigned char *key, void *out)
439 {
440 int ret = -1;
441 char *iv = "543yhjy97ae7fyfg";
442
443 p_Aes128_t aes_e_h = infra_aes128_init((unsigned char *)key,
444 (unsigned char *)iv, AES_ENCRYPTION);
445 ret = infra_aes128_cfb_encrypt(aes_e_h, src, len, out);
446 infra_aes128_destroy(aes_e_h);
447
448 COAP_DEBUG("to encrypt src:%s, len:%d", src, len);
449 return len;
450 }
451
iotx_aes_cfb_decrypt(const unsigned char * src,int len,const unsigned char * key,void * out)452 int iotx_aes_cfb_decrypt(const unsigned char *src, int len,
453 const unsigned char *key, void *out)
454 {
455 int ret = -1;
456 char *iv = "543yhjy97ae7fyfg";
457
458 p_Aes128_t aes_d_h = infra_aes128_init((unsigned char *)key,
459 (unsigned char *)iv, AES_ENCRYPTION);
460 ret = infra_aes128_cfb_decrypt(aes_d_h, src, len, out);
461 infra_aes128_destroy(aes_d_h);
462
463 return ret;
464 }
465 #endif
466
IOT_CoAP_DeviceNameAuth(iotx_coap_context_t * p_context)467 int IOT_CoAP_DeviceNameAuth(iotx_coap_context_t *p_context)
468 {
469 int len = 0;
470 int ret = COAP_SUCCESS;
471 Cloud_CoAPContext *p_coap_ctx = NULL;
472 iotx_coap_t *p_iotx_coap = NULL;
473 Cloud_CoAPMessage message;
474 unsigned char *p_payload = NULL;
475 unsigned char token[8] = { 0 };
476 char sign[IOTX_SIGN_LENGTH] = { 0 };
477
478 p_iotx_coap = (iotx_coap_t *)p_context;
479 if (NULL == p_iotx_coap ||
480 (NULL != p_iotx_coap && (NULL == p_iotx_coap->p_auth_token ||
481 NULL == p_iotx_coap->p_coap_ctx ||
482 0 == p_iotx_coap->auth_token_len))) {
483 COAP_DEBUG("Invalid paramter");
484 return IOTX_ERR_INVALID_PARAM;
485 }
486
487 p_coap_ctx = (Cloud_CoAPContext *)p_iotx_coap->p_coap_ctx;
488
489 CoAPMessage_init(&message);
490 CoAPMessageType_set(&message, COAP_MESSAGE_TYPE_CON);
491 CoAPMessageCode_set(&message, COAP_MSG_CODE_POST);
492 CoAPMessageId_set(&message, Cloud_CoAPMessageId_gen(p_coap_ctx));
493 len = iotx_get_coap_token(p_iotx_coap, token);
494 CoAPMessageToken_set(&message, token, len);
495 Cloud_CoAPMessageHandler_set(&message, iotx_device_name_auth_callback);
496
497 CoAPStrOption_add(&message, COAP_OPTION_URI_PATH,
498 (unsigned char *)IOTX_AUTH_STR, strlen(IOTX_AUTH_STR));
499 CoAPUintOption_add(&message, COAP_OPTION_CONTENT_FORMAT, COAP_CT_APP_JSON);
500 CoAPUintOption_add(&message, COAP_OPTION_ACCEPT, COAP_CT_APP_JSON);
501
502 CoAPMessageUserData_set(&message, (void *)p_iotx_coap);
503
504 p_payload = coap_malloc(COAP_MSG_MAX_PDU_LEN);
505 if (NULL == p_payload) {
506 CoAPMessage_destory(&message);
507 return IOTX_ERR_NO_MEM;
508 }
509 memset(p_payload, 0x00, COAP_MSG_MAX_PDU_LEN);
510
511 if (COAP_ENDPOINT_PSK == p_iotx_coap->p_coap_ctx->network.ep_type) {
512 iotx_calc_sign_with_seq(p_iotx_coap->p_devinfo->device_secret,
513 p_iotx_coap->p_devinfo->device_id,
514 p_iotx_coap->p_devinfo->device_name,
515 p_iotx_coap->p_devinfo->product_key,
516 p_iotx_coap->seq, sign);
517 HAL_Snprintf((char *)p_payload, COAP_MSG_MAX_PDU_LEN,
518 IOTX_AUTH_DEVICENAME_STR_WITH_SEQ,
519 p_iotx_coap->p_devinfo->product_key,
520 p_iotx_coap->p_devinfo->device_name,
521 p_iotx_coap->p_devinfo->device_id, sign, p_iotx_coap->seq);
522
523 } else {
524 iotx_calc_sign(p_iotx_coap->p_devinfo->device_secret,
525 p_iotx_coap->p_devinfo->device_id,
526 p_iotx_coap->p_devinfo->device_name,
527 p_iotx_coap->p_devinfo->product_key, sign);
528 HAL_Snprintf((char *)p_payload, COAP_MSG_MAX_PDU_LEN,
529 IOTX_AUTH_DEVICENAME_STR,
530 p_iotx_coap->p_devinfo->product_key,
531 p_iotx_coap->p_devinfo->device_name,
532 p_iotx_coap->p_devinfo->device_id, sign);
533 }
534 CoAPMessagePayload_set(&message, p_payload, strlen((char *)p_payload));
535 COAP_DEBUG("The payload is: %s", message.payload);
536 COAP_DEBUG("Send authentication message to server");
537 ret = Cloud_CoAPMessage_send(p_coap_ctx, &message);
538 coap_free(p_payload);
539 CoAPMessage_destory(&message);
540
541 if (COAP_SUCCESS != ret) {
542 COAP_DEBUG("Send authentication message to server failed, ret = %d",
543 ret);
544 return IOTX_ERR_SEND_MSG_FAILED;
545 }
546
547 ret = Cloud_CoAPMessage_recv(p_coap_ctx, CONFIG_COAP_AUTH_TIMEOUT, 2);
548 if (0 < ret && !p_iotx_coap->is_authed) {
549 COAP_INFO("CoAP authenticate failed");
550 return IOTX_ERR_AUTH_FAILED;
551 }
552
553 iotx_set_report_func(coap_report_func);
554 /* report module id */
555 ret = iotx_report_mid(p_context);
556 if (SUCCESS_RETURN != ret) {
557 COAP_WRN("Send ModuleId message to server(CoAP) failed, ret = %d", ret);
558 }
559 /* report device information */
560 ret = iotx_report_devinfo(p_context);
561 if (SUCCESS_RETURN != ret) {
562 COAP_WRN("Send devinfo message to server(CoAP) failed, ret = %d", ret);
563 }
564
565 return IOTX_SUCCESS;
566 }
567
iotx_split_path_2_option(char * uri,Cloud_CoAPMessage * message)568 static int iotx_split_path_2_option(char *uri, Cloud_CoAPMessage *message)
569 {
570 char *ptr = NULL;
571 char *pstr = NULL;
572 char path[COAP_MSG_MAX_PATH_LEN] = { 0 };
573
574 if (NULL == uri || NULL == message) {
575 COAP_ERR("Invalid paramter p_path %p, p_message %p", uri, message);
576 return IOTX_ERR_INVALID_PARAM;
577 }
578 if (IOTX_URI_MAX_LEN < strlen(uri)) {
579 COAP_ERR("The uri length is too loog,len = %d", (int)strlen(uri));
580 return IOTX_ERR_URI_TOO_LOOG;
581 }
582 COAP_DEBUG("The uri is %s", uri);
583 ptr = pstr = uri;
584 while ('\0' != *ptr) {
585 if ('/' == *ptr) {
586 if (ptr != pstr) {
587 memset(path, 0x00, sizeof(path));
588 strncpy(path, pstr, ptr - pstr);
589 COAP_DEBUG("path: %s,len=%d", path, (int)(ptr - pstr));
590 CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
591 (unsigned char *)path, (int)strlen(path));
592 }
593 pstr = ptr + 1;
594 }
595 if ('\0' == *(ptr + 1) && '\0' != *pstr) {
596 memset(path, 0x00, sizeof(path));
597 strncpy(path, pstr, sizeof(path) - 1);
598 COAP_DEBUG("path: %s,len=%d", path, (int)strlen(path));
599 CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
600 (unsigned char *)path, (int)strlen(path));
601 }
602 ptr++;
603 }
604 return IOTX_SUCCESS;
605 }
606
IOT_CoAP_GetCurToken(iotx_coap_context_t * p_context)607 uint32_t IOT_CoAP_GetCurToken(iotx_coap_context_t *p_context)
608 {
609 iotx_coap_t *p_iotx_coap = NULL;
610
611 if (p_context == NULL) {
612 return IOTX_ERR_INVALID_PARAM;
613 }
614 p_iotx_coap = (iotx_coap_t *)p_context;
615
616 return p_iotx_coap->coap_token;
617 }
618
IOT_CoAP_SendMessage(iotx_coap_context_t * p_context,char * p_path,iotx_message_t * p_message)619 int IOT_CoAP_SendMessage(iotx_coap_context_t *p_context, char *p_path,
620 iotx_message_t *p_message)
621 {
622 int len = 0;
623 int ret = IOTX_SUCCESS;
624 Cloud_CoAPContext *p_coap_ctx = NULL;
625 iotx_coap_t *p_iotx_coap = NULL;
626 Cloud_CoAPMessage message;
627 unsigned char token[8] = { 0 };
628 unsigned char *payload = NULL;
629
630 p_iotx_coap = (iotx_coap_t *)p_context;
631
632 if (NULL == p_context || NULL == p_path || NULL == p_message ||
633 (NULL != p_iotx_coap && NULL == p_iotx_coap->p_coap_ctx)) {
634 COAP_ERR("Invalid paramter p_context %p, p_uri %p, p_message %p",
635 p_context, p_path, p_message);
636 return IOTX_ERR_INVALID_PARAM;
637 }
638
639 #ifdef INFRA_LOG_NETWORK_PAYLOAD
640 COAP_INFO("Upstream Topic: '%s'", p_path);
641 COAP_INFO("Upstream Payload:");
642 iotx_facility_json_print((const char *)p_message->p_payload, LOG_INFO_LEVEL,
643 '>');
644 #endif
645
646 /* as this function only support POST request message, type ACK and RST
647 * shall be considered error parameters */
648 if (p_message->msg_type != IOTX_MESSAGE_CON &&
649 p_message->msg_type != IOTX_MESSAGE_NON) {
650 return IOTX_ERR_INVALID_PARAM;
651 }
652
653 if (p_message->payload_len >= COAP_MSG_MAX_PDU_LEN) {
654 COAP_ERR("The payload length %d is too loog", p_message->payload_len);
655 return IOTX_ERR_MSG_TOO_LOOG;
656 }
657
658 p_coap_ctx = (Cloud_CoAPContext *)p_iotx_coap->p_coap_ctx;
659 if (p_iotx_coap->is_authed) {
660 /* CoAPMessage_init(&message); */
661 CoAPMessage_init(&message);
662 CoAPMessageType_set(&message, p_message->msg_type);
663 CoAPMessageCode_set(&message, COAP_MSG_CODE_POST);
664 CoAPMessageId_set(&message, Cloud_CoAPMessageId_gen(p_coap_ctx));
665 len = iotx_get_coap_token(p_iotx_coap, token);
666 CoAPMessageToken_set(&message, token, len);
667 CoAPMessageUserData_set(&message, (void *)p_message->user_data);
668 Cloud_CoAPMessageHandler_set(&message, p_message->resp_callback);
669
670 ret = iotx_split_path_2_option(p_path, &message);
671 if (IOTX_SUCCESS != ret) {
672 return ret;
673 }
674
675 if (IOTX_CONTENT_TYPE_CBOR == p_message->content_type) {
676 CoAPUintOption_add(&message, COAP_OPTION_CONTENT_FORMAT,
677 COAP_CT_APP_CBOR);
678 CoAPUintOption_add(&message, COAP_OPTION_ACCEPT,
679 COAP_CT_APP_OCTET_STREAM);
680 } else {
681 CoAPUintOption_add(&message, COAP_OPTION_CONTENT_FORMAT,
682 COAP_CT_APP_JSON);
683 CoAPUintOption_add(&message, COAP_OPTION_ACCEPT,
684 COAP_CT_APP_OCTET_STREAM);
685 }
686 CoAPStrOption_add(&message, COAP_OPTION_AUTH_TOKEN,
687 (unsigned char *)p_iotx_coap->p_auth_token,
688 strlen(p_iotx_coap->p_auth_token));
689 if (COAP_ENDPOINT_PSK == p_iotx_coap->p_coap_ctx->network.ep_type) {
690 unsigned char buff[32] = { 0 };
691 unsigned char seq[33] = { 0 };
692 HAL_Snprintf((char *)buff, sizeof(buff) - 1, "%d",
693 p_iotx_coap->seq++);
694 len = iotx_aes_cbc_encrypt(buff, strlen((char *)buff),
695 p_iotx_coap->key, seq);
696 if (0 < len) {
697 CoAPStrOption_add(&message, COAP_OPTION_SEQ,
698 (unsigned char *)seq, len);
699 } else {
700 COAP_INFO("Encrypt seq failed");
701 }
702 HEXDUMP_DEBUG(seq, len);
703
704 payload = (unsigned char *)coap_malloc(COAP_MSG_MAX_PDU_LEN);
705 if (NULL == payload) {
706 return IOTX_ERR_NO_MEM;
707 }
708 memset(payload, 0x00, COAP_MSG_MAX_PDU_LEN);
709 len = iotx_aes_cbc_encrypt(p_message->p_payload,
710 p_message->payload_len, p_iotx_coap->key,
711 payload);
712 if (0 == len) {
713 coap_free(payload);
714 payload = NULL;
715 return IOTX_ERR_INVALID_PARAM;
716 }
717
718 HEXDUMP_DEBUG(payload, len);
719 CoAPMessagePayload_set(&message, payload, len);
720 } else {
721 CoAPMessagePayload_set(&message, p_message->p_payload,
722 p_message->payload_len);
723 }
724 ret = Cloud_CoAPMessage_send(p_coap_ctx, &message);
725 CoAPMessage_destory(&message);
726 if (NULL != payload) {
727 coap_free(payload);
728 payload = NULL;
729 }
730
731 if (COAP_ERROR_DATA_SIZE == ret) {
732 return IOTX_ERR_MSG_TOO_LOOG;
733 }
734
735 return IOTX_SUCCESS;
736 } else {
737 COAP_ERR("The client [%s/%s] still un-authorized yet, return %d",
738 p_iotx_coap->p_devinfo->product_key,
739 p_iotx_coap->p_devinfo->device_name, IOTX_ERR_NOT_AUTHED);
740 return IOTX_ERR_NOT_AUTHED;
741 }
742 }
743
IOT_CoAP_GetMessagePayload(void * p_message,unsigned char ** pp_payload,int * p_len)744 int IOT_CoAP_GetMessagePayload(void *p_message, unsigned char **pp_payload,
745 int *p_len)
746 {
747 Cloud_CoAPMessage *message = NULL;
748 iotx_coap_t *p_iotx_coap = NULL;
749
750 if (NULL == p_message || NULL == pp_payload || NULL == p_len ||
751 NULL == g_coap_context) {
752 COAP_ERR("Invalid parameter: p_message=%p, pp_payload=%p, p_len=%p",
753 p_message, pp_payload, p_len);
754 return IOTX_ERR_INVALID_PARAM;
755 }
756
757 p_iotx_coap = (iotx_coap_t *)g_coap_context;
758 message = (Cloud_CoAPMessage *)p_message;
759
760 COAP_DEBUG("message->payload: %p", message->payload);
761 COAP_DEBUG("message->payloadlen: %d", message->payloadlen);
762
763 if (message->payloadlen >= COAP_MSG_MAX_PDU_LEN) {
764 COAP_ERR("Invalid parameter: message->payloadlen(%d) out of [0, %d]",
765 message->payloadlen, COAP_MSG_MAX_PDU_LEN);
766 return IOTX_ERR_INVALID_PARAM;
767 }
768
769 if (COAP_ENDPOINT_PSK == p_iotx_coap->p_coap_ctx->network.ep_type) {
770 int len = 0;
771 unsigned char *payload = NULL;
772 payload = coap_malloc(COAP_MSG_MAX_PDU_LEN);
773 if (NULL == payload) {
774 return IOTX_ERR_NO_MEM;
775 }
776 memset(payload, 0x00, COAP_MSG_MAX_PDU_LEN);
777
778 HEXDUMP_DEBUG(message->payload, message->payloadlen);
779
780 len = iotx_aes_cbc_decrypt(message->payload, message->payloadlen,
781 p_iotx_coap->key, payload);
782 if (len > 0) {
783 COAP_DEBUG("payload: %.*s, len %d", len, payload, len);
784 }
785 if (len != 0) {
786 memcpy(message->payload, payload, len);
787 message->payloadlen = len;
788 HEXDUMP_DEBUG(payload, len);
789 }
790
791 coap_free(payload);
792 }
793
794 *pp_payload = message->payload;
795 *p_len = message->payloadlen;
796
797 return IOTX_SUCCESS;
798 }
799
IOT_CoAP_GetMessageToken(void * p_message,unsigned int * token)800 int IOT_CoAP_GetMessageToken(void *p_message, unsigned int *token)
801 {
802 Cloud_CoAPMessage *message = NULL;
803
804 if (NULL == p_message || NULL == token) {
805 COAP_ERR("Invalid paramter p_message %p, token= %p", p_message, token);
806 return -1;
807 }
808 message = (Cloud_CoAPMessage *)p_message;
809
810 *token = ((unsigned int)(message->token[3]) & 0xff) << 24;
811 *token += ((unsigned int)(message->token[2]) & 0xff) << 16;
812 *token += ((unsigned int)(message->token[1]) & 0xff) << 8;
813 *token += ((unsigned int)(message->token[0]) & 0xff);
814 return 0;
815 }
816
IOT_CoAP_GetMessageCode(void * p_message,iotx_coap_resp_code_t * p_resp_code)817 int IOT_CoAP_GetMessageCode(void *p_message, iotx_coap_resp_code_t *p_resp_code)
818 {
819 Cloud_CoAPMessage *message = NULL;
820
821 if (NULL == p_message || NULL == p_resp_code) {
822 COAP_ERR("Invalid paramter p_message %p, p_resp_code %p", p_message,
823 p_resp_code);
824 return IOTX_ERR_INVALID_PARAM;
825 }
826 message = (Cloud_CoAPMessage *)p_message;
827 *p_resp_code = (iotx_coap_resp_code_t)message->header.code;
828
829 return IOTX_SUCCESS;
830 }
831
iotx_get_seq(void)832 static unsigned int iotx_get_seq(void)
833 {
834 HAL_Srandom((unsigned int)HAL_UptimeMs());
835 return HAL_Random(0xffffffff) % 10000;
836 }
837
IOT_CoAP_Init(iotx_coap_config_t * p_config)838 iotx_coap_context_t *IOT_CoAP_Init(iotx_coap_config_t *p_config)
839 {
840 Cloud_CoAPInitParam param;
841 char url[128] = { 0 };
842 iotx_coap_t *p_iotx_coap = NULL;
843
844 if (NULL == p_config) {
845 COAP_ERR("Invalid paramter p_config %p", p_config);
846 return NULL;
847 }
848 if (NULL == p_config->p_devinfo) {
849 COAP_ERR("Invalid paramter p_devinfo %p", p_config->p_devinfo);
850 return NULL;
851 }
852
853 p_iotx_coap = coap_malloc(sizeof(iotx_coap_t));
854 if (NULL == p_iotx_coap) {
855 COAP_ERR(" Allocate memory for iotx_coap_context_t failed");
856 return NULL;
857 }
858 memset(p_iotx_coap, 0x00, sizeof(iotx_coap_t));
859
860 p_iotx_coap->p_auth_token = coap_malloc(IOTX_AUTH_TOKEN_LEN);
861 if (NULL == p_iotx_coap->p_auth_token) {
862 COAP_ERR(" Allocate memory for auth token failed");
863 goto err;
864 }
865 memset(p_iotx_coap->p_auth_token, 0x00, IOTX_AUTH_TOKEN_LEN);
866
867 /*Set the client isn't authed*/
868 p_iotx_coap->is_authed = IOT_FALSE;
869 p_iotx_coap->auth_token_len = IOTX_AUTH_TOKEN_LEN;
870
871 /*Get deivce information*/
872 p_iotx_coap->p_devinfo = coap_malloc(sizeof(iotx_coap_device_info_t));
873 if (NULL == p_iotx_coap->p_devinfo) {
874 COAP_ERR(" Allocate memory for iotx_coap_device_info_t failed");
875 goto err;
876 }
877 memset(p_iotx_coap->p_devinfo, 0x00, sizeof(iotx_coap_device_info_t));
878
879 /*It should be implement by the user*/
880 if (NULL != p_config->p_devinfo) {
881 memset(p_iotx_coap->p_devinfo, 0x00, sizeof(iotx_coap_device_info_t));
882 strncpy(p_iotx_coap->p_devinfo->device_id,
883 p_config->p_devinfo->device_id,
884 strlen(p_config->p_devinfo->device_id));
885 strncpy(p_iotx_coap->p_devinfo->product_key,
886 p_config->p_devinfo->product_key,
887 strlen(p_config->p_devinfo->product_key));
888 strncpy(p_iotx_coap->p_devinfo->device_secret,
889 p_config->p_devinfo->device_secret,
890 strlen(p_config->p_devinfo->device_secret));
891 strncpy(p_iotx_coap->p_devinfo->device_name,
892 p_config->p_devinfo->device_name,
893 strlen(p_config->p_devinfo->device_name));
894 }
895
896 /*Init coap token*/
897 p_iotx_coap->coap_token = IOTX_COAP_INIT_TOKEN;
898 p_iotx_coap->seq = iotx_get_seq();
899 memset(p_iotx_coap->key, 0x00, sizeof(p_iotx_coap->key));
900
901 /*Create coap context*/
902 memset(¶m, 0x00, sizeof(Cloud_CoAPInitParam));
903
904 if (NULL != p_config->p_url) {
905 param.url = p_config->p_url;
906 } else {
907 HAL_Snprintf(url, sizeof(url), IOTX_COAP_ONLINE_PSK_SERVER_URL,
908 p_iotx_coap->p_devinfo->product_key);
909 param.url = url;
910 COAP_INFO("Using default CoAP server: %s", url);
911 }
912 param.maxcount = IOTX_LIST_MAX_ITEM;
913 param.notifier = (Cloud_CoAPEventNotifier)iotx_event_notifyer;
914 param.waittime = p_config->wait_time_ms;
915 p_iotx_coap->p_coap_ctx = Cloud_CoAPContext_create(¶m);
916 if (NULL == p_iotx_coap->p_coap_ctx) {
917 COAP_ERR(" Create coap context failed");
918 goto err;
919 }
920
921 /*Register the event handle to notify the application */
922 p_iotx_coap->event_handle = p_config->event_handle;
923
924 g_coap_context = (iotx_coap_context_t *)p_iotx_coap;
925 return (iotx_coap_context_t *)p_iotx_coap;
926 err:
927 /* Error, release the memory */
928 if (NULL != p_iotx_coap) {
929 if (NULL != p_iotx_coap->p_devinfo) {
930 coap_free(p_iotx_coap->p_devinfo);
931 }
932 if (NULL != p_iotx_coap->p_auth_token) {
933 coap_free(p_iotx_coap->p_auth_token);
934 }
935 if (NULL != p_iotx_coap->p_coap_ctx) {
936 Cloud_CoAPContext_free(p_iotx_coap->p_coap_ctx);
937 }
938
939 p_iotx_coap->auth_token_len = 0;
940 p_iotx_coap->is_authed = IOT_FALSE;
941 coap_free(p_iotx_coap);
942 }
943 return NULL;
944 }
945
IOT_CoAP_Deinit(iotx_coap_context_t ** pp_context)946 void IOT_CoAP_Deinit(iotx_coap_context_t **pp_context)
947 {
948 iotx_coap_t *p_iotx_coap = NULL;
949
950 if (NULL != pp_context && NULL != *pp_context) {
951 p_iotx_coap = (iotx_coap_t *)*pp_context;
952 p_iotx_coap->is_authed = IOT_FALSE;
953 p_iotx_coap->auth_token_len = 0;
954 p_iotx_coap->coap_token = IOTX_COAP_INIT_TOKEN;
955
956 if (NULL != p_iotx_coap->p_auth_token) {
957 coap_free(p_iotx_coap->p_auth_token);
958 p_iotx_coap->p_auth_token = NULL;
959 }
960
961 if (NULL != p_iotx_coap->p_devinfo) {
962 coap_free(p_iotx_coap->p_devinfo);
963 p_iotx_coap->p_devinfo = NULL;
964 }
965
966 if (NULL != p_iotx_coap->p_coap_ctx) {
967 Cloud_CoAPContext_free(p_iotx_coap->p_coap_ctx);
968 p_iotx_coap->p_coap_ctx = NULL;
969 }
970 coap_free(p_iotx_coap);
971 *pp_context = NULL;
972 g_coap_context = NULL;
973 }
974 }
975
IOT_CoAP_Yield(iotx_coap_context_t * p_context)976 int IOT_CoAP_Yield(iotx_coap_context_t *p_context)
977 {
978 iotx_coap_t *p_iotx_coap = NULL;
979 p_iotx_coap = (iotx_coap_t *)p_context;
980 if (NULL == p_iotx_coap ||
981 (NULL != p_iotx_coap && NULL == p_iotx_coap->p_coap_ctx)) {
982 COAP_ERR("Invalid paramter");
983 return IOTX_ERR_INVALID_PARAM;
984 }
985
986 return Cloud_CoAPMessage_cycle(p_iotx_coap->p_coap_ctx);
987 }
988