1 #include <stdio.h>
2 #include <string.h>
3 #include "linkkit/infra/infra_defs.h"
4 #include "linkkit/infra/infra_config.h"
5 #include "linkkit/infra/infra_sha256.h"
6
7 #include "linkkit/dev_sign_api.h"
8 #include "linkkit/wrappers/wrappers.h"
9
10 /* all secure mode define */
11 #define MODE_TLS_GUIDER "-1"
12 #define MODE_TLS_DIRECT "2"
13 #define MODE_TCP_DIRECT_PLAIN "3"
14 #define MODE_ITLS_DNS_ID2 "8"
15
16 #if defined(MQTT_PRE_AUTH)
17 #define SECURE_MODE MODE_TLS_GUIDER
18 #elif defined(SUPPORT_TLS)
19 #define SECURE_MODE MODE_TLS_DIRECT
20 #else
21 #define SECURE_MODE MODE_TCP_DIRECT_PLAIN
22 #endif
23
24 /* use fixed timestamp */
25 #define TIMESTAMP_VALUE "2524608000000"
26
27 /* clientid key value pair define */
28 const char *clientid_kv[][2] = {
29 { "timestamp", TIMESTAMP_VALUE },
30 { "_v", "sdk-c-" IOTX_SDK_VERSION },
31 { "securemode", SECURE_MODE },
32 #ifdef SIGN_CIPHER_HMAC_SHA256
33 { "signmethod", "hmacsha256" },
34 #elif defined(SIGN_CIPHER_HMAC_SHA1)
35 { "signmethod", "hmacsha1" },
36 #else
37 #error "SIGN CIPHER is not defined"
38 #endif
39 { "lan", "C" },
40 #ifdef MQTT_AUTO_SUBSCRIBE
41 { "_ss", "1" },
42 #endif
43 { "gw", "0" },
44 { "ext", "0" },
45 };
46
_hex2str(uint8_t * input,uint16_t input_len,char * output)47 static void _hex2str(uint8_t *input, uint16_t input_len, char *output)
48 {
49 char *zEncode = "0123456789abcdef";
50 int i = 0, j = 0;
51
52 for (i = 0; i < input_len; i++) {
53 output[j++] = zEncode[(input[i] >> 4) & 0xf];
54 output[j++] = zEncode[(input[i]) & 0xf];
55 }
56 }
57
_sign_get_clientid(char * clientid_string,const char * device_id,const char * custom_kv,uint8_t enable_itls)58 int _sign_get_clientid(char *clientid_string, const char *device_id,
59 const char *custom_kv, uint8_t enable_itls)
60 {
61 uint8_t i;
62
63 if (clientid_string == NULL || device_id == NULL) {
64 return FAIL_RETURN;
65 }
66 if (strlen(device_id) + 1 >= DEV_SIGN_CLIENT_ID_MAXLEN) {
67 return FAIL_RETURN;
68 }
69 memset(clientid_string, 0, DEV_SIGN_CLIENT_ID_MAXLEN);
70 memcpy(clientid_string, device_id, strlen(device_id));
71 memcpy(clientid_string + strlen(clientid_string), "|", 1);
72
73 if (enable_itls > 0) {
74 clientid_kv[2][1] = MODE_ITLS_DNS_ID2;
75 } else {
76 clientid_kv[2][1] = SECURE_MODE;
77 }
78
79 for (i = 0; i < (sizeof(clientid_kv) / (sizeof(clientid_kv[0]))); i++) {
80 if ((strlen(clientid_string) + strlen(clientid_kv[i][0]) +
81 strlen(clientid_kv[i][1]) + 2) >= DEV_SIGN_CLIENT_ID_MAXLEN) {
82 return FAIL_RETURN;
83 }
84
85 memcpy(clientid_string + strlen(clientid_string), clientid_kv[i][0],
86 strlen(clientid_kv[i][0]));
87 memcpy(clientid_string + strlen(clientid_string), "=", 1);
88 memcpy(clientid_string + strlen(clientid_string), clientid_kv[i][1],
89 strlen(clientid_kv[i][1]));
90 memcpy(clientid_string + strlen(clientid_string), ",", 1);
91 }
92
93 if (custom_kv != NULL) {
94 if ((strlen(clientid_string) + strlen(custom_kv) + 1) >=
95 DEV_SIGN_CLIENT_ID_MAXLEN) {
96 return FAIL_RETURN;
97 }
98 memcpy(clientid_string + strlen(clientid_string), custom_kv,
99 strlen(custom_kv));
100 memcpy(clientid_string + strlen(clientid_string), ",", 1);
101 }
102
103 memcpy(clientid_string + strlen(clientid_string) - 1, "|", 1);
104
105 return SUCCESS_RETURN;
106 }
107
108 #define SIGN_FMT_LEN 50 /* "clientId%sdeviceName%sproductKey%stimestamp%s";*/
109
110 #ifdef SIGN_CIPHER_HMAC_SHA256
_iotx_generate_sign_string(const char * device_id,const char * device_name,const char * product_key,const char * device_secret,char * sign_string)111 int _iotx_generate_sign_string(const char *device_id, const char *device_name,
112 const char *product_key,
113 const char *device_secret, char *sign_string)
114 {
115 char signsource[DEV_SIGN_SOURCE_MAXLEN] = { 0 };
116 uint16_t signsource_len = 0;
117 uint8_t sign_hex[32] = { 0 };
118
119 signsource_len = SIGN_FMT_LEN + strlen(device_id) + strlen(device_name) +
120 strlen(product_key) + strlen(TIMESTAMP_VALUE);
121 if (signsource_len >= DEV_SIGN_SOURCE_MAXLEN) {
122 return ERROR_DEV_SIGN_SOURCE_TOO_SHORT;
123 }
124
125 memset(signsource, 0, DEV_SIGN_SOURCE_MAXLEN);
126 memcpy(signsource, "clientId", strlen("clientId"));
127 memcpy(signsource + strlen(signsource), device_id, strlen(device_id));
128 memcpy(signsource + strlen(signsource), "deviceName", strlen("deviceName"));
129 memcpy(signsource + strlen(signsource), device_name, strlen(device_name));
130 memcpy(signsource + strlen(signsource), "productKey", strlen("productKey"));
131 memcpy(signsource + strlen(signsource), product_key, strlen(product_key));
132 memcpy(signsource + strlen(signsource), "timestamp", strlen("timestamp"));
133 memcpy(signsource + strlen(signsource), TIMESTAMP_VALUE,
134 strlen(TIMESTAMP_VALUE));
135
136 utils_hmac_sha256((uint8_t *)signsource, strlen(signsource),
137 (uint8_t *)device_secret, strlen(device_secret),
138 sign_hex);
139
140 _hex2str(sign_hex, 32, sign_string);
141
142 return SUCCESS_RETURN;
143 }
144 #elif defined(SIGN_CIPHER_HMAC_SHA1)
_iotx_generate_sign_string(const char * device_id,const char * device_name,const char * product_key,const char * device_secret,char * sign_string)145 int _iotx_generate_sign_string(const char *device_id, const char *device_name,
146 const char *product_key,
147 const char *device_secret, char *sign_string)
148 {
149 char signsource[DEV_SIGN_SOURCE_MAXLEN] = { 0 };
150 uint16_t signsource_len = 0;
151 uint8_t sign_hex[32] = { 0 };
152
153 signsource_len = SIGN_FMT_LEN + strlen(device_id) + strlen(device_name) +
154 strlen(product_key) + strlen(TIMESTAMP_VALUE);
155 if (signsource_len >= DEV_SIGN_SOURCE_MAXLEN) {
156 return ERROR_DEV_SIGN_SOURCE_TOO_SHORT;
157 }
158 memset(signsource, 0, DEV_SIGN_SOURCE_MAXLEN);
159 memcpy(signsource, "clientId", strlen("clientId"));
160 memcpy(signsource + strlen(signsource), device_id, strlen(device_id));
161 memcpy(signsource + strlen(signsource), "deviceName", strlen("deviceName"));
162 memcpy(signsource + strlen(signsource), device_name, strlen(device_name));
163 memcpy(signsource + strlen(signsource), "productKey", strlen("productKey"));
164 memcpy(signsource + strlen(signsource), product_key, strlen(product_key));
165 memcpy(signsource + strlen(signsource), "timestamp", strlen("timestamp"));
166 memcpy(signsource + strlen(signsource), TIMESTAMP_VALUE,
167 strlen(TIMESTAMP_VALUE));
168 utils_hmac_sha1((uint8_t *)signsource, strlen(signsource), sign_hex,
169 (uint8_t *)device_secret, strlen(device_secret));
170 snprintf(sign_string, 41, "%s", sign_hex);
171
172 return SUCCESS_RETURN;
173 }
174 #else
175 #error "SIGN CIPHER is not defined"
176 #endif
177
IOT_Sign_MQTT(iotx_mqtt_region_types_t region,iotx_dev_meta_info_t * meta,iotx_sign_mqtt_t * signout)178 int32_t IOT_Sign_MQTT(iotx_mqtt_region_types_t region,
179 iotx_dev_meta_info_t *meta, iotx_sign_mqtt_t *signout)
180 {
181 uint16_t length = 0;
182 char device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 1] = { 0 };
183 int res;
184
185 if (region >= IOTX_MQTT_DOMAIN_NUMBER || meta == NULL) {
186 return -1;
187 }
188
189 memset(signout, 0, sizeof(iotx_sign_mqtt_t));
190
191 memcpy(device_id, meta->product_key, strlen(meta->product_key));
192 memcpy(device_id + strlen(device_id), ".", strlen("."));
193 memcpy(device_id + strlen(device_id), meta->device_name,
194 strlen(meta->device_name));
195
196 /* setup clientid */
197 if (_sign_get_clientid(signout->clientid, device_id, NULL, 0) !=
198 SUCCESS_RETURN) {
199 return ERROR_DEV_SIGN_CLIENT_ID_TOO_SHORT;
200 }
201
202 /* setup password */
203 memset(signout->password, 0, DEV_SIGN_PASSWORD_MAXLEN);
204 res = _iotx_generate_sign_string(device_id, meta->device_name,
205 meta->product_key, meta->device_secret,
206 signout->password);
207 if (res < SUCCESS_RETURN) {
208 return res;
209 }
210
211 /* setup hostname */
212 if (IOTX_CLOUD_REGION_CUSTOM == region) {
213 if (g_infra_mqtt_domain[region] == NULL) {
214 return ERROR_DEV_SIGN_CUSTOM_DOMAIN_IS_NULL;
215 }
216
217 length = strlen(g_infra_mqtt_domain[region]) + 1;
218 if (length >= DEV_SIGN_HOSTNAME_MAXLEN) {
219 return ERROR_DEV_SIGN_HOST_NAME_TOO_SHORT;
220 }
221
222 memset(signout->hostname, 0, DEV_SIGN_HOSTNAME_MAXLEN);
223 memcpy(signout->hostname, g_infra_mqtt_domain[region],
224 strlen(g_infra_mqtt_domain[region]));
225 } else {
226 length =
227 strlen(meta->product_key) + strlen(g_infra_mqtt_domain[region]) + 2;
228 if (length >= DEV_SIGN_HOSTNAME_MAXLEN) {
229 return ERROR_DEV_SIGN_HOST_NAME_TOO_SHORT;
230 }
231 memset(signout->hostname, 0, DEV_SIGN_HOSTNAME_MAXLEN);
232 memcpy(signout->hostname, meta->product_key, strlen(meta->product_key));
233 memcpy(signout->hostname + strlen(signout->hostname), ".", strlen("."));
234 memcpy(signout->hostname + strlen(signout->hostname),
235 g_infra_mqtt_domain[region],
236 strlen(g_infra_mqtt_domain[region]));
237 }
238
239 /* setup username */
240 length = strlen(meta->device_name) + strlen(meta->product_key) + 2;
241 if (length >= DEV_SIGN_USERNAME_MAXLEN) {
242 return ERROR_DEV_SIGN_USERNAME_TOO_SHORT;
243 }
244 memset(signout->username, 0, DEV_SIGN_USERNAME_MAXLEN);
245 memcpy(signout->username, meta->device_name, strlen(meta->device_name));
246 memcpy(signout->username + strlen(signout->username), "&", strlen("&"));
247 memcpy(signout->username + strlen(signout->username), meta->product_key,
248 strlen(meta->product_key));
249
250 /* setup port */
251
252 signout->port = 1883;
253
254 return SUCCESS_RETURN;
255 }
256