luat_iotauth.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. #include "luat_base.h"
  2. #include "luat_crypto.h"
  3. #include "luat_mem.h"
  4. #include "time.h"
  5. #include "luat_str.h"
  6. #include "luat_mcu.h"
  7. #include "printf.h"
  8. #include "luat_iotauth.h"
  9. #define LUAT_LOG_TAG "iotauth"
  10. #include "luat_log.h"
  11. static const unsigned char hexchars_s[] = "0123456789abcdef";
  12. static const unsigned char hexchars_u[] = "0123456789ABCDEF";
  13. static void str_tohex(const char* str, size_t str_len, char* hex,uint8_t uppercase) {
  14. const unsigned char* hexchars = NULL;
  15. if (uppercase)
  16. hexchars = hexchars_u;
  17. else
  18. hexchars = hexchars_s;
  19. for (size_t i = 0; i < str_len; i++)
  20. {
  21. char ch = *(str+i);
  22. hex[i*2] = hexchars[(unsigned char)ch >> 4];
  23. hex[i*2+1] = hexchars[(unsigned char)ch & 0xF];
  24. }
  25. }
  26. static const unsigned char base64_dec_map[128] =
  27. {
  28. 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
  29. 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
  30. 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
  31. 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
  32. 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
  33. 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
  34. 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
  35. 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
  36. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  37. 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
  38. 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
  39. 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
  40. 49, 50, 51, 127, 127, 127, 127, 127
  41. };
  42. static int str_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
  43. const unsigned char *src, size_t slen )
  44. {
  45. size_t i, n;
  46. uint32_t j, x;
  47. unsigned char *p;
  48. /* First pass: check for validity and get output length */
  49. for( i = n = j = 0; i < slen; i++ )
  50. {
  51. /* Skip spaces before checking for EOL */
  52. x = 0;
  53. while( i < slen && src[i] == ' ' )
  54. {
  55. ++i;
  56. ++x;
  57. }
  58. /* Spaces at end of buffer are OK */
  59. if( i == slen )
  60. break;
  61. if( ( slen - i ) >= 2 &&
  62. src[i] == '\r' && src[i + 1] == '\n' )
  63. continue;
  64. if( src[i] == '\n' )
  65. continue;
  66. /* Space inside a line is an error */
  67. if( x != 0 )
  68. return( -2 );
  69. if( src[i] == '=' && ++j > 2 )
  70. return( -2 );
  71. if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
  72. return( -2 );
  73. if( base64_dec_map[src[i]] < 64 && j != 0 )
  74. return( -2 );
  75. n++;
  76. }
  77. if( n == 0 )
  78. {
  79. *olen = 0;
  80. return( 0 );
  81. }
  82. /* The following expression is to calculate the following formula without
  83. * risk of integer overflow in n:
  84. * n = ( ( n * 6 ) + 7 ) >> 3;
  85. */
  86. n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
  87. n -= j;
  88. if( dst == NULL || dlen < n )
  89. {
  90. *olen = n;
  91. return( -1 );
  92. }
  93. for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
  94. {
  95. if( *src == '\r' || *src == '\n' || *src == ' ' )
  96. continue;
  97. j -= ( base64_dec_map[*src] == 64 );
  98. x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
  99. if( ++n == 4 )
  100. {
  101. n = 0;
  102. if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
  103. if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
  104. if( j > 2 ) *p++ = (unsigned char)( x );
  105. }
  106. }
  107. *olen = p - dst;
  108. return( 0 );
  109. }
  110. int luat_aliyun_token(iotauth_ctx_t* ctx,const char* product_key,const char* device_name,const char* device_secret,long long cur_timestamp,const char* method,uint8_t is_tls){
  111. char deviceId[64] = {0};
  112. char macSrc[200] = {0};
  113. char macRes[32] = {0};
  114. char timestamp_value[20] = {0};
  115. uint8_t securemode = 3;
  116. if (is_tls){
  117. securemode = 2;
  118. }
  119. sprintf_(timestamp_value,"%lld",cur_timestamp);
  120. sprintf_(deviceId,"%s.%s",product_key,device_name);
  121. /* setup clientid */
  122. if (!strcmp("hmacmd5", method)||!strcmp("HMACMD5", method)) {
  123. sprintf_(ctx->client_id,"%s|securemode=%d,signmethod=hmacmd5,timestamp=%s|",deviceId,securemode,timestamp_value);
  124. }else if (!strcmp("hmacsha1", method)||!strcmp("HMACSHA1", method)) {
  125. sprintf_(ctx->client_id,"%s|securemode=%d,signmethod=hmacsha1,timestamp=%s|",deviceId,securemode,timestamp_value);
  126. }else if (!strcmp("hmacsha256", method)||!strcmp("HMACSHA256", method)) {
  127. sprintf_(ctx->client_id,"%s|securemode=%d,signmethod=hmacsha256,timestamp=%s|",deviceId,securemode,timestamp_value);
  128. }else{
  129. LLOGE("not support: %s",method);
  130. return -1;
  131. }
  132. /* setup username */
  133. sprintf_(ctx->user_name,"%s&%s",device_name,product_key);
  134. /* setup password */
  135. memcpy(macSrc, "clientId", strlen("clientId"));
  136. memcpy(macSrc + strlen(macSrc), deviceId, strlen(deviceId));
  137. memcpy(macSrc + strlen(macSrc), "deviceName", strlen("deviceName"));
  138. memcpy(macSrc + strlen(macSrc), device_name, strlen(device_name));
  139. memcpy(macSrc + strlen(macSrc), "productKey", strlen("productKey"));
  140. memcpy(macSrc + strlen(macSrc), product_key, strlen(product_key));
  141. memcpy(macSrc + strlen(macSrc), "timestamp", strlen("timestamp"));
  142. memcpy(macSrc + strlen(macSrc), timestamp_value, strlen(timestamp_value));
  143. if (!strcmp("hmacmd5", method)||!strcmp("HMACMD5", method)) {
  144. luat_crypto_hmac_md5_simple(macSrc, strlen(macSrc),device_secret, strlen(device_secret), macRes);
  145. str_tohex(macRes, 16, ctx->password,1);
  146. }else if (!strcmp("hmacsha1", method)||!strcmp("HMACSHA1", method)) {
  147. luat_crypto_hmac_sha1_simple(macSrc, strlen(macSrc),device_secret, strlen(device_secret), macRes);
  148. str_tohex(macRes, 20, ctx->password,1);
  149. }else if (!strcmp("hmacsha256", method)||!strcmp("HMACSHA256", method)) {
  150. luat_crypto_hmac_sha256_simple(macSrc, strlen(macSrc),device_secret, strlen(device_secret), macRes);
  151. str_tohex(macRes, 32, ctx->password,1);
  152. }else{
  153. LLOGE("not support: %s",method);
  154. return -1;
  155. }
  156. return 0;
  157. }
  158. typedef struct {
  159. char et[32];
  160. char version[12];
  161. char method[12];
  162. char res[64];
  163. char sign[64];
  164. } sign_msg;
  165. typedef struct {
  166. char* old_str;
  167. char* str;
  168. }URL_PARAMETES;
  169. static int url_encoding_for_token(sign_msg* msg,char *token){
  170. int i,j,k,slen;
  171. sign_msg* temp_msg = msg;
  172. URL_PARAMETES url_patametes[] = {
  173. {"+","%2B"},
  174. {" ","%20"},
  175. {"/","%2F"},
  176. {"?","%3F"},
  177. {"%","%25"},
  178. {"#","%23"},
  179. {"&","%26"},
  180. {"=","%3D"},
  181. };
  182. char temp[64] = {0};
  183. slen = strlen(temp_msg->res);
  184. for (i = 0,j = 0; i < slen; i++) {
  185. for(k = 0; k < 8; k++){
  186. if(temp_msg->res[i] == url_patametes[k].old_str[0]) {
  187. memcpy(&temp[j],url_patametes[k].str,strlen(url_patametes[k].str));
  188. j+=3;
  189. break;
  190. }
  191. }
  192. if (k == 8) {
  193. temp[j++] = temp_msg->res[i];
  194. }
  195. }
  196. memcpy(temp_msg->res,temp,strlen(temp));
  197. temp_msg->res[strlen(temp)] = 0;
  198. memset(temp,0x00,sizeof(temp));
  199. slen = strlen(temp_msg->sign);
  200. for (i = 0,j = 0; i < slen; i++) {
  201. for(k = 0; k < 8; k++){
  202. if(temp_msg->sign[i] == url_patametes[k].old_str[0]) {
  203. memcpy(&temp[j],url_patametes[k].str,strlen(url_patametes[k].str));
  204. j+=3;
  205. break;
  206. }
  207. }
  208. if(k == 8){
  209. temp[j++] = temp_msg->sign[i];
  210. }
  211. }
  212. memcpy(temp_msg->sign,temp,strlen(temp));
  213. temp_msg->sign[strlen(temp)] = 0;
  214. if(snprintf_(token,PASSWORD_LEN, "version=%s&res=%s&et=%s&method=%s&sign=%s", temp_msg->version, temp_msg->res, temp_msg->et, temp_msg->method, temp_msg->sign)<0){
  215. return -1;
  216. }
  217. return strlen(token);
  218. }
  219. int luat_onenet_token(iotauth_ctx_t* ctx,const iotauth_onenet_t* onenet) {
  220. size_t declen = 0, enclen = 0,hmac_len = 0;
  221. char plaintext[64] = { 0 };
  222. char hmac[64] = { 0 };
  223. char StringForSignature[256] = { 0 };
  224. sign_msg sign = {0};
  225. memcpy(sign.method, onenet->method, strlen(onenet->method));
  226. memcpy(sign.version, onenet->version, strlen(onenet->version));
  227. sprintf_(sign.et,"%lld", onenet->cur_timestamp);
  228. if (onenet->res) {
  229. sprintf_(sign.res, "%s", onenet->res);
  230. }
  231. else {
  232. sprintf_(sign.res,"products/%s/devices/%s", onenet->product_id, onenet->device_name);
  233. }
  234. str_base64_decode((unsigned char *)plaintext, sizeof(plaintext), &declen, (const unsigned char * )onenet->device_secret, strlen((char*)onenet->device_secret));
  235. sprintf_(StringForSignature, "%s\n%s\n%s\n%s", sign.et, sign.method, sign.res, sign.version);
  236. if (!strcmp("md5", onenet->method)||!strcmp("MD5", onenet->method)) {
  237. luat_crypto_hmac_md5_simple(StringForSignature, strlen(StringForSignature), plaintext, declen, hmac);
  238. hmac_len = 16;
  239. }else if (!strcmp("sha1", onenet->method)||!strcmp("SHA1", onenet->method)) {
  240. luat_crypto_hmac_sha1_simple(StringForSignature, strlen(StringForSignature),plaintext, declen, hmac);
  241. hmac_len = 20;
  242. }else if (!strcmp("sha256", onenet->method)||!strcmp("SHA256", onenet->method)) {
  243. luat_crypto_hmac_sha256_simple(StringForSignature, strlen(StringForSignature),plaintext, declen, hmac);
  244. hmac_len = 32;
  245. }else{
  246. LLOGE("not support: %s", onenet->method);
  247. return -1;
  248. }
  249. luat_str_base64_encode((unsigned char *)sign.sign, sizeof(sign.sign), &enclen, (const unsigned char * )hmac, hmac_len);
  250. snprintf_(ctx->client_id, CLIENT_ID_LEN,"%s", onenet->device_name);
  251. snprintf_(ctx->user_name, USER_NAME_LEN,"%s", onenet->product_id);
  252. url_encoding_for_token(&sign, ctx->password);
  253. return 0;
  254. }
  255. int luat_iotda_token(iotauth_ctx_t* ctx,const char* device_id,const char* device_secret,long long cur_timestamp,int ins_timestamp){
  256. char hmac[65] = {0};
  257. char timestamp[11] = {0};
  258. struct tm *timeinfo = localtime( &cur_timestamp );
  259. if(snprintf_(timestamp, 11, "%04d%02d%02d%02d", (timeinfo->tm_year)+1900,timeinfo->tm_mon+1,timeinfo->tm_mday,timeinfo->tm_hour)<0){
  260. return -1;
  261. }
  262. snprintf_(ctx->client_id, CLIENT_ID_LEN, "%s_0_%d_%s", device_id,ins_timestamp,timestamp);
  263. snprintf_(ctx->user_name, USER_NAME_LEN,"%s", device_id);
  264. luat_crypto_hmac_sha256_simple(device_secret, strlen(device_secret),timestamp, strlen(timestamp), hmac);
  265. str_tohex(hmac, 32, ctx->password,0);
  266. return 0;
  267. }
  268. /* Max size of base64 encoded PSK = 64, after decode: 64/4*3 = 48*/
  269. #define DECODE_PSK_LENGTH 48
  270. /* Max size of conn Id */
  271. #define MAX_CONN_ID_LEN (6)
  272. static void get_next_conn_id(char *conn_id){
  273. size_t i;
  274. luat_crypto_trng(conn_id, 5);
  275. for (i = 0; i < MAX_CONN_ID_LEN - 1; i++) {
  276. conn_id[i] = (conn_id[i] % 26) + 'a';
  277. }
  278. conn_id[MAX_CONN_ID_LEN - 1] = '\0';
  279. }
  280. int luat_qcloud_token(iotauth_ctx_t* ctx,const char* product_id,const char* device_name,const char* device_secret,long long cur_timestamp,const char* method,const char* sdk_appid){
  281. char conn_id[MAX_CONN_ID_LEN] = {0};
  282. char username_sign[41] = {0};
  283. char psk_base64decode[DECODE_PSK_LENGTH] = {0};
  284. size_t psk_base64decode_len = 0;
  285. str_base64_decode((unsigned char *)psk_base64decode, DECODE_PSK_LENGTH, &psk_base64decode_len,(unsigned char *)device_secret, strlen(device_secret));
  286. get_next_conn_id(conn_id);
  287. snprintf_(ctx->client_id, CLIENT_ID_LEN,"%s%s", product_id,device_name);
  288. snprintf_(ctx->user_name, USER_NAME_LEN,"%s%s;%s;%s;%lld", product_id, device_name, sdk_appid,conn_id, cur_timestamp);
  289. if (!strcmp("sha1", method)||!strcmp("SHA1", method)) {
  290. luat_crypto_hmac_sha1_simple(ctx->user_name, strlen(ctx->user_name),psk_base64decode, psk_base64decode_len, username_sign);
  291. }else if (!strcmp("sha256", method)||!strcmp("SHA256", method)) {
  292. luat_crypto_hmac_sha256_simple(ctx->user_name, strlen(ctx->user_name),psk_base64decode, psk_base64decode_len, username_sign);
  293. }else{
  294. LLOGE("not support: %s",method);
  295. return -1;
  296. }
  297. char username_sign_hex[100] = {0};
  298. if (!strcmp("sha1", method)||!strcmp("SHA1", method)) {
  299. str_tohex(username_sign, 20, username_sign_hex,0);
  300. snprintf_(ctx->password, PASSWORD_LEN,"%s;hmacsha1", username_sign_hex);
  301. }else if (!strcmp("sha256", method)||!strcmp("SHA256", method)) {
  302. str_tohex(username_sign, 32, username_sign_hex,0);
  303. snprintf_(ctx->password, PASSWORD_LEN,"%s;hmacsha256", username_sign_hex);
  304. }
  305. return 0;
  306. }
  307. int luat_tuya_token(iotauth_ctx_t* ctx,const char* device_id,const char* device_secret,long long cur_timestamp){
  308. char hmac[65] = {0};
  309. char token_temp[100] = {0};
  310. snprintf_(token_temp, 100, "deviceId=%s,timestamp=%lld,secureMode=1,accessType=1", device_id, cur_timestamp);
  311. luat_crypto_hmac_sha256_simple(token_temp, strlen(token_temp),device_secret, strlen(device_secret), hmac);
  312. snprintf_(ctx->client_id, CLIENT_ID_LEN, "tuyalink_%s", device_id);
  313. snprintf_(ctx->user_name, USER_NAME_LEN, "%s|signMethod=hmacSha256,timestamp=%lld,secureMode=1,accessType=1", device_id,cur_timestamp);
  314. str_tohex(hmac, 32, ctx->password,0);
  315. return 0;
  316. }
  317. int luat_baidu_token(iotauth_ctx_t* ctx,const char* iot_core_id,const char* device_key,const char* device_secret,const char* method,long long cur_timestamp){
  318. char crypto[64] = {0};
  319. char token_temp[100] = {0};
  320. snprintf_(ctx->client_id, CLIENT_ID_LEN, "%s", iot_core_id);
  321. if (!strcmp("MD5", method)||!strcmp("md5", method)) {
  322. if (cur_timestamp){
  323. snprintf_(ctx->user_name,USER_NAME_LEN, "thingidp@%s|%s|%lld|%s",iot_core_id,device_key,cur_timestamp,"MD5");
  324. }else{
  325. snprintf_(ctx->user_name,USER_NAME_LEN, "thingidp@%s|%s|%s",iot_core_id,device_key,"MD5");
  326. }
  327. snprintf_(token_temp, 100, "%s&%lld&%s%s",device_key,cur_timestamp,"MD5",device_secret);
  328. luat_crypto_md5_simple(token_temp, strlen(token_temp),crypto);
  329. str_tohex(crypto, 16, ctx->password,0);
  330. }else if (!strcmp("SHA256", method)||!strcmp("sha256", method)) {
  331. if (cur_timestamp){
  332. snprintf_(ctx->user_name,USER_NAME_LEN, "thingidp@%s|%s|%lld|%s",iot_core_id,device_key,cur_timestamp,"SHA256");
  333. }else{
  334. snprintf_(ctx->user_name,USER_NAME_LEN, "thingidp@%s|%s|%s",iot_core_id,device_key,"SHA256");
  335. }
  336. snprintf_(token_temp, 100, "%s&%lld&%s%s",device_key,cur_timestamp,"SHA256",device_secret);
  337. luat_crypto_sha256_simple(token_temp, strlen(token_temp),crypto);
  338. str_tohex(crypto, 32, ctx->password,0);
  339. }else{
  340. LLOGE("not support: %s",method);
  341. return -1;
  342. }
  343. return 0;
  344. }