lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | /***************************************************************/
|
| 2 | //
|
| 3 | //²Î¼û ÖйúÁªÍ¨esimÄ£×éÀ©Õ¹Ö¸Áî¼¼Êõ¹æ·¶
|
| 4 | //
|
| 5 | /***************************************************************/
|
| 6 |
|
| 7 | #include <stdio.h>
|
| 8 | #include <stdlib.h>
|
| 9 | #include <string.h>
|
| 10 | #include <ctype.h>
|
| 11 | #include <sys/time.h>
|
| 12 | #include <termios.h>
|
| 13 | #include <errno.h>
|
| 14 |
|
| 15 | #include "lpa_inner.h"
|
| 16 |
|
| 17 |
|
| 18 | #define SMDP_PORT 443
|
| 19 | #define SMDP_DL_INTERVAL 95//ÏÂÔØ¼ä¸ô>90s
|
| 20 |
|
| 21 |
|
| 22 | //´¥·¢·þÎñÆ÷httpÇëÇó
|
| 23 | static char smdp_https_req[] =
|
| 24 | "POST /gsma/rsp2/es9plus/%s HTTP/1.1\r\n"
|
| 25 | "Host: %s\r\n"
|
| 26 | "User-Agent: gsma-rsp-lpad\r\n"
|
| 27 | "X-Admin-Protocol: gsma/rsp/v2.2.0\r\n"
|
| 28 | "Content-Type: application/json\r\n"
|
| 29 | "Content-Length: %d\r\n"
|
| 30 | "\r\n%s\r\n";
|
| 31 |
|
| 32 | static https_context_t g_https_ct = {0};
|
| 33 | static char g_transid[MAX_TRANSID_LEN] = {0};
|
| 34 | char curent_iccid[ICCID_LEN+1] = {0};
|
| 35 |
|
| 36 | extern char g_imei[MAX_IMEI_LEN];
|
| 37 |
|
| 38 | //iccid from bpp install result, if null, failed
|
| 39 | //ISD-P AID, tag '4F';ICCID, tag '5A'. if succ, has AID
|
| 40 | static int lpa_parse_iccid_apdu(char *apdu, char *iccid, int size)
|
| 41 | {
|
| 42 | int apdu_len = strlen(apdu);
|
| 43 | unsigned char *apdu_byte = malloc(apdu_len/2 + 1);
|
| 44 | int apdu_byte_len = 0;
|
| 45 | char *tag_hex = NULL;
|
| 46 | char has_iccid[ICCID_LEN+1] = {0};
|
| 47 |
|
| 48 | if (apdu_byte == NULL) {
|
| 49 | printf("lpa_parse_iccid_apdu no memory\n");
|
| 50 | return -1;
|
| 51 | }
|
| 52 | memset(apdu_byte, 0, apdu_len/2 + 1);
|
| 53 |
|
| 54 | apdu_byte_len = string2bytes(apdu, apdu_byte, apdu_len);
|
| 55 |
|
| 56 | tag_hex = lpa_tlv_get_val_by_tag(apdu_byte, apdu_byte_len, 0x4F);
|
| 57 | if (tag_hex == NULL) {
|
| 58 | printf("lpa_parse_iccid_apdu not find AID\n");
|
| 59 | free(apdu_byte);
|
| 60 | return -1;
|
| 61 | }
|
| 62 | printf("lpa aid:%s\n", tag_hex);
|
| 63 | free(tag_hex);
|
| 64 | tag_hex = NULL;
|
| 65 |
|
| 66 | tag_hex = lpa_tlv_get_val_by_tag(apdu_byte, apdu_byte_len, 0x5A);
|
| 67 | if (tag_hex == NULL) {
|
| 68 | printf("lpa_parse_iccid_apdu not find iccid\n");
|
| 69 | free(apdu_byte);
|
| 70 | return -1;
|
| 71 |
|
| 72 | }
|
| 73 |
|
| 74 | snprintf(iccid, size, "%s", tag_hex);
|
| 75 |
|
| 76 | sc_cfg_get("lpa_bpp_iccid", has_iccid, sizeof(has_iccid));
|
| 77 | if (strcmp(iccid, has_iccid) != 0) {
|
| 78 | sc_cfg_set("lpa_bpp_iccid", iccid);
|
| 79 | sc_cfg_save();
|
| 80 | printf("lpa iccid not same?\n");
|
| 81 | }
|
| 82 |
|
| 83 | printf("lpa iccid:%s\n", iccid);
|
| 84 |
|
| 85 | free(apdu_byte);
|
| 86 | free(tag_hex);
|
| 87 | return 0;
|
| 88 | }
|
| 89 |
|
| 90 | static int lpa_connect_smdp(char *host)
|
| 91 | {
|
| 92 | SSL_library_init();
|
| 93 |
|
| 94 | g_https_ct.port=SMDP_PORT;
|
| 95 | g_https_ct.host=host;
|
| 96 | g_https_ct.path=NULL;
|
| 97 | return https_init(&g_https_ct);
|
| 98 | }
|
| 99 |
|
| 100 | static void lpa_disconn_smdp(char *host)
|
| 101 | {
|
| 102 | https_uninit(&g_https_ct);
|
| 103 | }
|
| 104 |
|
| 105 | static char *lpa_smdp_session(char *path, char *req_data, int *res_len)
|
| 106 | {
|
| 107 | int ret = -1;
|
| 108 | int cont_len = 0;
|
| 109 | char *https_req = NULL;
|
| 110 | char *https_resp = NULL;
|
| 111 | int https_req_len = strlen(smdp_https_req)+strlen(path)+strlen(g_https_ct.host)+strlen(req_data)+32;
|
| 112 |
|
| 113 | *res_len = -1;
|
| 114 |
|
| 115 | if (https_req_len > SMDP_HTTP_MAX_LEN)
|
| 116 | return NULL;
|
| 117 |
|
| 118 | https_req = malloc(https_req_len);
|
| 119 | if (https_req == NULL)
|
| 120 | return NULL;
|
| 121 |
|
| 122 | memset(https_req, 0, https_req_len);
|
| 123 | g_https_ct.path = path;
|
| 124 | ret = snprintf(https_req, https_req_len, smdp_https_req,
|
| 125 | g_https_ct.path, g_https_ct.host, strlen(req_data), req_data);
|
| 126 |
|
| 127 | printf("[https_smdp]req[%d]:##%s##\n", strlen(https_req), https_req);
|
| 128 | ret = https_write(&g_https_ct, https_req, ret);
|
| 129 | if (ret == -1) {
|
| 130 | //EAGAIN?
|
| 131 | free(https_req);
|
| 132 | printf("[https_smdp] https_write err:%d.\n", errno);
|
| 133 | return NULL;
|
| 134 | }
|
| 135 |
|
| 136 | ret = https_get_status_code(&g_https_ct, &cont_len);
|
| 137 | if(ret == 200) {
|
| 138 | printf("[https_smdp] https_recv len:%d.\n", cont_len);
|
| 139 | if (cont_len == HTTP_CHUNKED_FLAG) {
|
| 140 | ret = https_read_chunked_content(&g_https_ct, &https_resp, SMDP_HTTP_MAX_LEN);
|
| 141 | if(ret > 0) {
|
| 142 | *res_len = ret;
|
| 143 | https_resp[ret] = '\0'; //×Ö·û´®½áÊø±êʶ
|
| 144 | printf("[https_smdp] https_write https_resp_content##%s##\n",https_resp);
|
| 145 | }
|
| 146 | printf("[https_smdp] https_resp chunk %d!!!\n", ret);
|
| 147 | }
|
| 148 | else {
|
| 149 | if (cont_len >= SMDP_HTTP_MAX_LEN) {
|
| 150 | free(https_req);
|
| 151 | printf("[https_smdp] https_recv too long = %d.\n", cont_len);
|
| 152 | return NULL;
|
| 153 | }
|
| 154 | https_resp = malloc(cont_len + 1);
|
| 155 | if (https_resp == NULL) {
|
| 156 | free(https_req);
|
| 157 | return NULL;
|
| 158 | }
|
| 159 |
|
| 160 | memset(https_resp, 0, cont_len + 1);
|
| 161 | ret = https_read_content(&g_https_ct, https_resp, cont_len);
|
| 162 | if(ret > 0) {
|
| 163 | *res_len = ret;
|
| 164 | https_resp[ret] = '\0'; //×Ö·û´®½áÊø±êʶ
|
| 165 | printf("[https_smdp] https_read_content##%s##\n",https_resp);
|
| 166 | }
|
| 167 | else {
|
| 168 | *res_len = -1;
|
| 169 | free(https_req);
|
| 170 | free(https_resp);
|
| 171 | return NULL;
|
| 172 | }
|
| 173 | }
|
| 174 | }
|
| 175 | else if(ret == 204) {
|
| 176 | *res_len = 0;
|
| 177 | }
|
| 178 | else {
|
| 179 | printf("[https_smdp] https_resp code = %d.\n", ret);
|
| 180 | }
|
| 181 |
|
| 182 | free(https_req);
|
| 183 | return https_resp;
|
| 184 | }
|
| 185 | /***************************************************************/
|
| 186 | //
|
| 187 | //ÌáÈ¡stringÀàÐÍÊý¾Ý
|
| 188 | //
|
| 189 | /***************************************************************/
|
| 190 | static char *lpa_parse_json_str(char *srcStr, char *key)
|
| 191 | {
|
| 192 | cJSON *root = NULL;
|
| 193 | cJSON *object = NULL;
|
| 194 | char *value_str = NULL;
|
| 195 | int value_len = 0;
|
| 196 |
|
| 197 | root = cJSON_Parse(srcStr);
|
| 198 | if (root == NULL) {
|
| 199 | printf("root == NULL\n");
|
| 200 | return NULL;
|
| 201 | }
|
| 202 |
|
| 203 | object = cJSON_GetObjectItem(root, key);
|
| 204 | if (object == NULL) {
|
| 205 | printf("key: %s not find\n", key);
|
| 206 | cJSON_Delete(root);
|
| 207 | return NULL;
|
| 208 | }
|
| 209 | //printf("key:%s-value:%s\n", key, object->valuestring);
|
| 210 | value_len = strlen(object->valuestring);
|
| 211 |
|
| 212 | value_str = malloc(value_len + 1);
|
| 213 | if (value_str == NULL) {
|
| 214 | cJSON_Delete(root);
|
| 215 | return NULL;
|
| 216 |
|
| 217 | }
|
| 218 | memset(value_str, 0, value_len + 1);
|
| 219 | strncpy(value_str, object->valuestring, value_len);
|
| 220 |
|
| 221 | cJSON_Delete(root);
|
| 222 | return value_str;
|
| 223 | }
|
| 224 |
|
| 225 | /***************************************************************/
|
| 226 | //
|
| 227 | //ÌáÈ¡stringÀàÐ͵Äbase64Êý¾Ý->decode->hex string
|
| 228 | //
|
| 229 | /***************************************************************/
|
| 230 | static char *lpa_parse_json_decode(char *srcStr, char *key)
|
| 231 | {
|
| 232 | cJSON *root = NULL;
|
| 233 | cJSON *object = NULL;
|
| 234 | char *value_byte = NULL;
|
| 235 | char *value_str = NULL;
|
| 236 | int value_len = 0;
|
| 237 |
|
| 238 | root = cJSON_Parse(srcStr);
|
| 239 | if (root == NULL) {
|
| 240 | printf("root == NULL\n");
|
| 241 | return NULL;
|
| 242 | }
|
| 243 |
|
| 244 | object = cJSON_GetObjectItem(root, key);
|
| 245 | if (object == NULL) {
|
| 246 | printf("key: %s not find\n", key);
|
| 247 | cJSON_Delete(root);
|
| 248 | return NULL;
|
| 249 | }
|
| 250 |
|
| 251 | //printf("key:%s-value:%s\n", key, object->valuestring);
|
| 252 | value_byte = lpa_base64_decode(object->valuestring, strlen(object->valuestring), &value_len);
|
| 253 | if (value_byte == NULL) {
|
| 254 | printf("lpa_base64_decode fail\n");
|
| 255 | cJSON_Delete(root);
|
| 256 | return NULL;
|
| 257 | }
|
| 258 |
|
| 259 | value_str = malloc(value_len*2 + 1);
|
| 260 | if (value_str == NULL) {
|
| 261 | free(value_byte);
|
| 262 | cJSON_Delete(root);
|
| 263 | return NULL;
|
| 264 |
|
| 265 | }
|
| 266 |
|
| 267 | memset(value_str, 0, value_len*2 + 1);
|
| 268 | bytes2string(value_byte, value_str, value_len);
|
| 269 | *(value_str + value_len*2) = '\0';
|
| 270 | //printf("key:%s(%d)-hex:%s\n", key, value_len*2, value_str);
|
| 271 | free(value_byte);
|
| 272 | cJSON_Delete(root);
|
| 273 | return value_str;
|
| 274 | }
|
| 275 |
|
| 276 | /***************************************************************/
|
| 277 | //
|
| 278 | //char srcStr[] =
|
| 279 | //"{"
|
| 280 | // "\"header\" : {"
|
| 281 | // "\"functionExecutionStatus\" : {"
|
| 282 | // "\"status\" : \"Executed-Success\""
|
| 283 | // "}"
|
| 284 | // "},"
|
| 285 | // "\"serverSigned1\": \"MEKAEAK3+mF5GUrrl+BlIUcujtSBEFK4u91WT/9GbQX+6pX/aoCDCmVzaW0ud28uY26EEEYRuTYzeka9iSyW+gSFF44=\","
|
| 286 | // "\"transactionId\": \"02B7FA6179194AEB97E06521472E8ED4\","
|
| 287 | // "\"serverSignature1\": \"XzdA9J6G6txPTOeOjQThaH/u/Wy/LOcZYec9reC65gjva7waj0XFBs0k551ynos1izFUpXbF8vctFw+/Enqu5aDQTA==\","
|
| 288 | // "\"serverCertificate\": \"MIIC1jCCAn2gAwIBAgIDAYb6MAoGCCqGSM49BAMCMH4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQIDAVKSUxJTjESMBAGA1UEBwwJQ0hBTkdDSFVOMQ0wCwYDVQQLDARDVUNBMQswCQYDVQQKDAJDVTEvMC0GA1UEAwwmQ2hpbmEgVW5pY29tIGVTSU0gUm9vdCBDQSBOSVNUUCBCWlRFU1QwHhcNMTkxMjI1MTUyNzEyWhcNMjAxMjI0MTUyNzEyWjB5MQswCQYDVQQGEwJDTjEnMCUGA1UECwweSW5ub3ZhdGl2ZSBCdXNpbmVzcyBEZXBhcnRtZW50MQ4wDAYDVQQKDAVWc2VuczExMC8GA1UEAwwoVW5pY29tIFZzZW5zIENvbW11bmljYXRpb24gQ28uIEx0ZChUZXN0KTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABC0BAmyq7voWvhezfZnAoQyRb5CgvPjFuGr7c4arFsbBFNYcv7w5C3Tp3wHD03HkIIhPuZrkx9kWNYeBrekfBw6jge4wgeswHwYDVR0jBBgwFoAUfA5UcBQ+qJmO2d8wBXTJLlqayx8wHQYDVR0OBBYEFC2+UJhg5G9/+zlI3mqf7YMrZHPMMA4GA1UdDwEB/wQEAwIHgDAXBgNVHSABAf8EDTALMAkGB2eBEgECAQQwFQYDVR0RBA4wDIgKKwYBBAGC9UYCBDBpBgNVHR8EYjBgMC6gLKAqhihodHRwOi8vY3JsLnVuaS1jYS5jb20uY24vZG93bmxvYWQvbjEuY3JsMC6gLKAqhihodHRwOi8vY3JsLnVuaS1jYS5jb20uY24vZG93bmxvYWQvbjIuY3JsMAoGCCqGSM49BAMCA0cAMEQCIBEAZfg9hJIax/xRpVIAjjmENrPr7q97E0Hv2s+8aOPDAiBaURKuxxzZ8/P0DKE7SmW+AhbxBl1TQd09sM6+Plzu9A==\","
|
| 289 | // "\"euiccCiPKIdToBeUsed\": \"BBR8DlRwFD6omY7Z3zAFdMkuWprLHw==\""
|
| 290 | //"}";
|
| 291 | //
|
| 292 | /***************************************************************/
|
| 293 | static char *lpa_parse_initauth_resp(char *srcStr)
|
| 294 | {
|
| 295 | char *transid = NULL;
|
| 296 | char *signed_hex = NULL;
|
| 297 | char *signature_hex = NULL;
|
| 298 | char *ciPKId_hex = NULL;
|
| 299 | char *certificate_hex = NULL;
|
| 300 |
|
| 301 | char *authser_apdu = NULL;
|
| 302 | //1 transid
|
| 303 | //2 get sig...
|
| 304 | //3 genaner at and send
|
| 305 |
|
| 306 | transid = lpa_parse_json_str(srcStr, "transactionId");
|
| 307 | if (transid == NULL)
|
| 308 | goto parse_END;
|
| 309 | snprintf(g_transid, sizeof(g_transid), "%s", transid);
|
| 310 |
|
| 311 |
|
| 312 | signed_hex = lpa_parse_json_decode(srcStr, "serverSigned1");
|
| 313 | if (signed_hex == NULL)
|
| 314 | goto parse_END;
|
| 315 |
|
| 316 | signature_hex = lpa_parse_json_decode(srcStr, "serverSignature1");
|
| 317 | if (signature_hex == NULL)
|
| 318 | goto parse_END;
|
| 319 |
|
| 320 | ciPKId_hex = lpa_parse_json_decode(srcStr, "euiccCiPKIdToBeUsed");
|
| 321 | if (ciPKId_hex == NULL)
|
| 322 | goto parse_END;
|
| 323 |
|
| 324 | certificate_hex = lpa_parse_json_decode(srcStr, "serverCertificate");
|
| 325 | if (certificate_hex == NULL)
|
| 326 | goto parse_END;
|
| 327 |
|
| 328 | //×îºóÒ»¶ÎÊÇɶ£¿ctxparams
|
| 329 | //80E29103£¿91±íʾ½öÒ»¶Î»òÕß×îºóÒ»¶Î
|
| 330 | //×î×îºóµÄ00²»ËãÔÚ³¤¶ÈÄÚ
|
| 331 | // 80E21100FFBF38(00 = i, ff =len)
|
| 332 | // ffÖ®ºó×¶àÉÙÏß²»¹Ü
|
| 333 | // ÏÈËãbf38ºó×¶àÉÙ£¬½«bf38ºóÊý¾ÝÏÈ×éºÃ£¬ÔÙ¼Ó
|
| 334 | // 80E2110iLLÀ´·Ö¸îat
|
| 335 | // ²¢ÔÚ×îºóÒ»¶ÎÏ·¢ºó¶ÁÈÏÖ¤·þÎñÆ÷µÄ²ÎÊýat
|
| 336 |
|
| 337 | //matchingId´Ó¼¤»îÂëÖÐÈ¡£¬Ä¿Ç°Ã»ÓÃ
|
| 338 | authser_apdu = AuthenticateServer(signed_hex, signature_hex, ciPKId_hex, certificate_hex, "", g_imei);
|
| 339 |
|
| 340 |
|
| 341 | parse_END:
|
| 342 | if (transid != NULL)
|
| 343 | free(transid);
|
| 344 | if (signed_hex != NULL)
|
| 345 | free(signed_hex);
|
| 346 | if (signature_hex != NULL)
|
| 347 | free(signature_hex);
|
| 348 | if (ciPKId_hex != NULL)
|
| 349 | free(ciPKId_hex);
|
| 350 | if (certificate_hex != NULL)
|
| 351 | free(certificate_hex);
|
| 352 |
|
| 353 | return authser_apdu;
|
| 354 | }
|
| 355 |
|
| 356 | static char *lpa_parse_authcli_resp(char *srcStr)
|
| 357 | {
|
| 358 | char *transid = NULL;
|
| 359 | char *signed2_hex = NULL;
|
| 360 | char *signature2_hex = NULL;
|
| 361 | char *certi_hex = NULL;
|
| 362 | //char *meta_hex = NULL;
|
| 363 |
|
| 364 | char *predl_apdu = NULL;
|
| 365 |
|
| 366 | transid = lpa_parse_json_str(srcStr, "transactionId");
|
| 367 | if (transid == NULL)
|
| 368 | goto parse_END;
|
| 369 | snprintf(g_transid, sizeof(g_transid), "%s", transid);
|
| 370 |
|
| 371 |
|
| 372 | signed2_hex = lpa_parse_json_decode(srcStr, "smdpSigned2");
|
| 373 | if (signed2_hex == NULL)
|
| 374 | goto parse_END;
|
| 375 |
|
| 376 | signature2_hex = lpa_parse_json_decode(srcStr, "smdpSignature2");
|
| 377 | if (signature2_hex == NULL)
|
| 378 | goto parse_END;
|
| 379 |
|
| 380 | certi_hex = lpa_parse_json_decode(srcStr, "smdpCertificate");
|
| 381 | if (certi_hex == NULL)
|
| 382 | goto parse_END;
|
| 383 |
|
| 384 | //meta_hex = lpa_parse_json_decode(srcStr, "profileMetadata");
|
| 385 | //if (meta_hex == NULL)
|
| 386 | // goto parse_END;
|
| 387 |
|
| 388 | predl_apdu = PrepareDownload(transid, signed2_hex, signature2_hex, certi_hex, "");
|
| 389 |
|
| 390 | parse_END:
|
| 391 | if (transid != NULL)
|
| 392 | free(transid);
|
| 393 | if (signed2_hex != NULL)
|
| 394 | free(signed2_hex);
|
| 395 | if (signature2_hex != NULL)
|
| 396 | free(signature2_hex);
|
| 397 | if (certi_hex != NULL)
|
| 398 | free(certi_hex);
|
| 399 | //if (meta_hex != NULL)
|
| 400 | // free(meta_hex);
|
| 401 |
|
| 402 | return predl_apdu;
|
| 403 | }
|
| 404 |
|
| 405 | static char *lpa_parse_getbpp_resp(char *srcStr)
|
| 406 | {
|
| 407 | char *transid = NULL;
|
| 408 | char *bpp_b64 = NULL;
|
| 409 |
|
| 410 | char *notify_apdu = NULL;
|
| 411 |
|
| 412 | transid = lpa_parse_json_str(srcStr, "transactionId");
|
| 413 | if (transid == NULL)
|
| 414 | goto parse_END;
|
| 415 | snprintf(g_transid, sizeof(g_transid), "%s", transid);
|
| 416 |
|
| 417 |
|
| 418 | bpp_b64 = lpa_parse_json_str(srcStr, "boundProfilePackage");
|
| 419 | if (bpp_b64 == NULL)
|
| 420 | goto parse_END;
|
| 421 |
|
| 422 | notify_apdu = LoadBoundProfilePackage(bpp_b64);
|
| 423 |
|
| 424 | parse_END:
|
| 425 | if (transid != NULL)
|
| 426 | free(transid);
|
| 427 | if (bpp_b64 != NULL)
|
| 428 | free(bpp_b64);
|
| 429 |
|
| 430 | return notify_apdu;
|
| 431 | }
|
| 432 |
|
| 433 |
|
| 434 | //·µ»ØjsonÊý¾Ý¸øÏÂÒ»²½µ÷ÓÃ
|
| 435 | static char *lpa_initauth(void)
|
| 436 | {
|
| 437 | int ret = -1;
|
| 438 | char *euiccChallenge = NULL;
|
| 439 | char *euiccInfo1 = NULL;
|
| 440 | char *ia_json = NULL;
|
| 441 | char *https_resp = NULL;
|
| 442 | char *resp_apdu = NULL;
|
| 443 |
|
| 444 | euiccChallenge = GetEUICCChallenge();
|
| 445 | if (euiccChallenge == NULL) {
|
| 446 | return NULL;
|
| 447 | }
|
| 448 |
|
| 449 | euiccInfo1 = GetEUICCInfo(TRUE);
|
| 450 | if (euiccInfo1 == NULL) {
|
| 451 | free(euiccChallenge);
|
| 452 | return NULL;
|
| 453 | }
|
| 454 |
|
| 455 | ia_json = InitiateAuthentication(euiccChallenge, euiccInfo1, g_https_ct.host);
|
| 456 | if (ia_json == NULL) {
|
| 457 | free(euiccChallenge);
|
| 458 | free(euiccInfo1);
|
| 459 | return NULL;
|
| 460 | }
|
| 461 |
|
| 462 | https_resp = lpa_smdp_session("initiateAuthentication", ia_json, &ret);
|
| 463 | if (https_resp != NULL) {
|
| 464 | resp_apdu = lpa_parse_initauth_resp(https_resp);
|
| 465 | free(https_resp);
|
| 466 | }
|
| 467 |
|
| 468 | free(euiccChallenge);
|
| 469 | free(euiccInfo1);
|
| 470 | free(ia_json);
|
| 471 | return resp_apdu;
|
| 472 | }
|
| 473 |
|
| 474 | static char *lpa_authclient(char *as_apdu)
|
| 475 | {
|
| 476 | int ret = -1;
|
| 477 |
|
| 478 | char *ac_json = NULL;
|
| 479 | char *https_resp = NULL;
|
| 480 | char *resp_apdu = NULL;
|
| 481 |
|
| 482 | ac_json = AuthenticateClient(g_transid, as_apdu);
|
| 483 | if (ac_json == NULL) {
|
| 484 | return NULL;
|
| 485 | }
|
| 486 |
|
| 487 | https_resp = lpa_smdp_session("authenticateClient", ac_json, &ret);
|
| 488 | if (https_resp != NULL) {
|
| 489 | resp_apdu = lpa_parse_authcli_resp(https_resp);
|
| 490 | free(https_resp);
|
| 491 | }
|
| 492 |
|
| 493 | free(ac_json);
|
| 494 | return resp_apdu;
|
| 495 | }
|
| 496 |
|
| 497 | static char *lpa_getbpp(char *pdl_apdu)
|
| 498 | {
|
| 499 | int ret = -1;
|
| 500 |
|
| 501 | char *bpp_json = NULL;
|
| 502 | char *https_resp = NULL;
|
| 503 | char *resp_apdu = NULL;
|
| 504 |
|
| 505 | bpp_json = GetBoundProfilePackage(g_transid, pdl_apdu);
|
| 506 | if (bpp_json == NULL) {
|
| 507 | return NULL;
|
| 508 | }
|
| 509 |
|
| 510 | https_resp = lpa_smdp_session("getBoundProfilePackage", bpp_json, &ret);
|
| 511 | if (ret > 0) {
|
| 512 | resp_apdu = lpa_parse_getbpp_resp(https_resp);
|
| 513 | free(https_resp);
|
| 514 | }
|
| 515 |
|
| 516 | free(bpp_json);
|
| 517 | return resp_apdu;
|
| 518 | }
|
| 519 |
|
| 520 | static int lpa_notification(char *notify_apdu)
|
| 521 | {
|
| 522 | int ret = -1;
|
| 523 |
|
| 524 | char *notify_json = NULL;
|
| 525 | char *https_resp = NULL;
|
| 526 |
|
| 527 | notify_json = HandleNotification(notify_apdu);
|
| 528 | if (notify_json == NULL) {
|
| 529 | return ret;
|
| 530 | }
|
| 531 | https_resp = lpa_smdp_session("handleNotification", notify_json, &ret);
|
| 532 | if (https_resp != NULL)
|
| 533 | free(https_resp);
|
| 534 | //no resp?
|
| 535 |
|
| 536 | free(notify_json);
|
| 537 | return ret;
|
| 538 | }
|
| 539 |
|
| 540 | /***************************************************************/
|
| 541 | //
|
| 542 | //"1$esim.wo.cn$$1.3.6.1.4.1.47814.2.4"
|
| 543 | //
|
| 544 | /***************************************************************/
|
| 545 | static char *parse_accode(char *activecode)
|
| 546 | {
|
| 547 | char *save = NULL;
|
| 548 | char *host = NULL;
|
| 549 | char *tmp = NULL;
|
| 550 | tmp = strtok_r(activecode, "$", &save);
|
| 551 | if (tmp == NULL)
|
| 552 | return NULL;
|
| 553 | tmp = strtok_r(NULL, "$", &save);
|
| 554 | if (tmp == NULL)
|
| 555 | return NULL;
|
| 556 |
|
| 557 | host = malloc(APDU_RESP_LEN);
|
| 558 | if (host == NULL)
|
| 559 | return NULL;
|
| 560 | memset(host, 0, APDU_RESP_LEN);
|
| 561 | strncpy(host, tmp, APDU_RESP_LEN-1);
|
| 562 |
|
| 563 | printf("server:%s\n", host);
|
| 564 | return host;
|
| 565 | }
|
| 566 |
|
| 567 | static int downloadProfile(char *smdpAddress)
|
| 568 | {
|
| 569 | int res = -1;
|
| 570 | char *authser_apdu = NULL;//auth server apdu
|
| 571 | char *predl_apdu = NULL;//prepare download apdu
|
| 572 | char *notify_apdu = NULL;//Notification apdu
|
| 573 | int notify_res = -1;
|
| 574 | int notify_check = -1;
|
| 575 | //1 creat https
|
| 576 | //2 get auth, send
|
| 577 |
|
| 578 | res = lpa_connect_smdp(smdpAddress);
|
| 579 | if (res != 0) {
|
| 580 | res = -2;
|
| 581 | goto download_END;
|
| 582 | }
|
| 583 |
|
| 584 | authser_apdu = lpa_initauth();
|
| 585 | if (authser_apdu == NULL || strlen(authser_apdu) == 0) {
|
| 586 | res = -2;
|
| 587 | goto download_END;
|
| 588 | }
|
| 589 |
|
| 590 | predl_apdu = lpa_authclient(authser_apdu);
|
| 591 | if (predl_apdu == NULL || strlen(predl_apdu) == 0) {
|
| 592 | res = -2;
|
| 593 | goto download_END;
|
| 594 | }
|
| 595 |
|
| 596 | notify_apdu = lpa_getbpp(predl_apdu);
|
| 597 | if (notify_apdu == NULL || strlen(notify_apdu) == 0) {
|
| 598 | res = -2;
|
| 599 | goto download_END;
|
| 600 | }
|
| 601 | //dtest
|
| 602 | #if 1
|
| 603 | notify_res = lpa_notification(notify_apdu);
|
| 604 | if (notify_res == -1) {
|
| 605 | printf("lpa_notification fail\n");
|
| 606 | //goto download_END;//skip, use updata result
|
| 607 | }
|
| 608 | #endif
|
| 609 |
|
| 610 | notify_check = lpa_parse_iccid_apdu(notify_apdu, curent_iccid, sizeof(curent_iccid));
|
| 611 | if (notify_check == -1)
|
| 612 | goto download_END;
|
| 613 |
|
| 614 |
|
| 615 | res = 0;
|
| 616 | download_END:
|
| 617 | if (authser_apdu != NULL)
|
| 618 | free(authser_apdu);
|
| 619 | if (predl_apdu != NULL)
|
| 620 | free(predl_apdu);
|
| 621 | if (notify_apdu != NULL)
|
| 622 | free(notify_apdu);
|
| 623 |
|
| 624 | lpa_disconn_smdp(smdpAddress);
|
| 625 | return res;
|
| 626 | }
|
| 627 |
|
| 628 | /***************************************************************/
|
| 629 | //
|
| 630 | //ÊäÈ뼤»îÂ뷽ʽÏÂÔØprofile
|
| 631 | //È·ÈÏÂëδÓà confirmcode = NULL
|
| 632 | //
|
| 633 | /***************************************************************/
|
| 634 | int downloadProfileByAc(char *activecode, char *confirmcode)
|
| 635 | {
|
| 636 | int res = -1;
|
| 637 | char *smdpAddress = NULL;
|
| 638 |
|
| 639 | char dl_retry[6] = {0};
|
| 640 | int count = 0;
|
| 641 | int i = 0;
|
| 642 |
|
| 643 | sc_cfg_get("lpa_dl_retry", dl_retry, sizeof(dl_retry));
|
| 644 | count = atoi(dl_retry);
|
| 645 | printf("lpa_updata_retry:%s,%d\n", dl_retry, count);
|
| 646 | if (count <= 0 || count > 10) { //kw 3
|
| 647 | count = 1;
|
| 648 | }
|
| 649 |
|
| 650 | smdpAddress = parse_accode(activecode);
|
| 651 | if (smdpAddress == NULL)
|
| 652 | return -1;
|
| 653 |
|
| 654 | for (i = 0; i < count; i++) {
|
| 655 | res = downloadProfile(smdpAddress);
|
| 656 | if (res == -2 && i < count-1) {
|
| 657 | //retry
|
| 658 | sleep(SMDP_DL_INTERVAL);
|
| 659 | continue;
|
| 660 | }
|
| 661 | break;
|
| 662 | }
|
| 663 |
|
| 664 | free(smdpAddress);
|
| 665 | return res;
|
| 666 | }
|
| 667 |
|
| 668 | #if 0
|
| 669 | int downloadProfileByEid(void)
|
| 670 | {
|
| 671 | int res = -1;
|
| 672 | char *smdpAddress = "esim.wo.cn";//get from default
|
| 673 |
|
| 674 | res = downloadProfile(smdpAddress);
|
| 675 |
|
| 676 | return res;
|
| 677 | }
|
| 678 | #endif
|
| 679 |
|
| 680 | /***************************************************************/
|
| 681 | //
|
| 682 | //ÆôÓÃprofile
|
| 683 | //in: iccid 20
|
| 684 | //
|
| 685 | //parse 8001xx return xx:
|
| 686 | //0£ºOK
|
| 687 | //1£ºiccidOrAidNotFound£»
|
| 688 | //2£ºprofileNotInDisabledState£»
|
| 689 | //3£ºdisallowedByPolicy£»
|
| 690 | //4£ºwrongProfileReenabling£»
|
| 691 | //5£ºcatBusy£»
|
| 692 | //127£ºundefinedError
|
| 693 | //ÆäÓà·µ»ØÖµ²Î¿¼6.10½Ú
|
| 694 | //
|
| 695 | /***************************************************************/
|
| 696 | int enableProfile(char *iccid)
|
| 697 | {
|
| 698 | char *apdu = NULL;
|
| 699 | int res = 127;
|
| 700 | apdu = EnableProfile(iccid);
|
| 701 | if (apdu == NULL)
|
| 702 | return 127;
|
| 703 | errno = 0;
|
| 704 | res = strtol(apdu, NULL, 16);
|
| 705 | if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
|
| 706 | {
|
| 707 | printf("strtol errno %d: %s\n", errno, strerror(errno));
|
| 708 | }
|
| 709 | free(apdu);
|
| 710 | return res;
|
| 711 | }
|
| 712 |
|
| 713 | /***************************************************************/
|
| 714 | //
|
| 715 | //½ûÓÃprofile
|
| 716 | //
|
| 717 | /***************************************************************/
|
| 718 | int disableProfile(char * iccid)
|
| 719 | {
|
| 720 | char *apdu = NULL;
|
| 721 | int res = 127;
|
| 722 | apdu = DisableProfile(iccid);
|
| 723 | if (apdu == NULL)
|
| 724 | return 127;
|
| 725 | errno = 0;
|
| 726 | res = strtol(apdu, NULL, 16);
|
| 727 | if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
|
| 728 | {
|
| 729 | printf("strtol errno %d: %s\n", errno, strerror(errno));
|
| 730 | }
|
| 731 | free(apdu);
|
| 732 | return res;
|
| 733 | }
|
| 734 |
|
| 735 |
|
| 736 | /***************************************************************/
|
| 737 | //
|
| 738 | //ɾ³ýprofile
|
| 739 | //
|
| 740 | /***************************************************************/
|
| 741 | int deleteProfile(char * iccid)
|
| 742 | {
|
| 743 | char *apdu = NULL;
|
| 744 | int res = 127;
|
| 745 | apdu = DeleteProfile(iccid);
|
| 746 | if (apdu == NULL)
|
| 747 | return 127;
|
| 748 | errno = 0;
|
| 749 | res = strtol(apdu, NULL, 16);
|
| 750 | if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
|
| 751 | {
|
| 752 | printf("strtol errno %d: %s\n", errno, strerror(errno));
|
| 753 | }
|
| 754 | free(apdu);
|
| 755 | return res;
|
| 756 | }
|
| 757 |
|
| 758 |
|
| 759 | int memoryReset(void)
|
| 760 | {
|
| 761 | char *apdu = NULL;
|
| 762 | int res = 127;
|
| 763 | apdu = EUICCMemoryReset();
|
| 764 | if (apdu == NULL)
|
| 765 | return 127;
|
| 766 | errno = 0;
|
| 767 | res = strtol(apdu, NULL, 16);
|
| 768 | if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
|
| 769 | {
|
| 770 | printf("strtol errno %d: %s\n", errno, strerror(errno));
|
| 771 | }
|
| 772 | free(apdu);
|
| 773 | return res;
|
| 774 | }
|
| 775 |
|
| 776 | //limit 10
|
| 777 | static char *lap_parse_profile_list(char *pdu, int *list_n)
|
| 778 | {
|
| 779 | char *js_list = NULL;
|
| 780 |
|
| 781 | char *profile = NULL;
|
| 782 | char *iccid = NULL;
|
| 783 | char *state = NULL;
|
| 784 | int status = 0;
|
| 785 | int i = 0;
|
| 786 | char *tmp_pdu = pdu;
|
| 787 | char *offset = NULL;
|
| 788 |
|
| 789 | js_list = malloc(APDU_RESP_LEN);
|
| 790 | if (js_list == NULL)
|
| 791 | return NULL;
|
| 792 | memset(js_list, 0, APDU_RESP_LEN);
|
| 793 |
|
| 794 | while(i < 10 && strlen(tmp_pdu) > 0) {
|
| 795 | profile = lpa_tag_apdu_from_atresp(tmp_pdu, 0xE3);
|
| 796 | if (profile == NULL)
|
| 797 | break;
|
| 798 |
|
| 799 | iccid = lpa_tag_apdu_from_atresp(tmp_pdu, 0x5A);
|
| 800 | if (iccid == NULL) {
|
| 801 | free(profile);
|
| 802 | break;
|
| 803 | }
|
| 804 | lpa_trans_iccid(iccid, strlen(iccid));
|
| 805 |
|
| 806 | state = lpa_tag_apdu_from_atresp(tmp_pdu, 0x9F70);
|
| 807 | if (state == NULL) {
|
| 808 | free(profile);
|
| 809 | free(iccid);
|
| 810 | break;
|
| 811 | }
|
| 812 | errno = 0;
|
| 813 | status = strtol(state, NULL, 16);
|
| 814 | if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
|
| 815 | {
|
| 816 | printf("strtol errno %d: %s\n", errno, strerror(errno));
|
| 817 | }
|
| 818 | if (i == 0) {
|
| 819 | snprintf(js_list, APDU_RESP_LEN,
|
| 820 | "{\"ICCID\":\"%s\",\"STATUS\":%d}", iccid, status);
|
| 821 | }
|
| 822 | else {
|
| 823 | snprintf(js_list + strlen(js_list), APDU_RESP_LEN - strlen(js_list),
|
| 824 | ",{\"ICCID\":\"%s\",\"STATUS\":%d}", iccid, status);
|
| 825 | }
|
| 826 |
|
| 827 | offset = strstr(tmp_pdu, profile);
|
| 828 | if (offset == NULL) {
|
| 829 | free(profile);
|
| 830 | free(iccid);
|
| 831 | free(state);
|
| 832 | break;
|
| 833 | }
|
| 834 | tmp_pdu = offset + strlen(profile);
|
| 835 | free(profile);
|
| 836 | free(iccid);
|
| 837 | free(state);
|
| 838 | i++;
|
| 839 |
|
| 840 | }
|
| 841 | *list_n = i;
|
| 842 | return js_list;
|
| 843 | }
|
| 844 |
|
| 845 | /***************************************************************/
|
| 846 | //
|
| 847 | //·µ»Ø¸öÊý£¬ºÍjson array[iccid, state]
|
| 848 | //
|
| 849 | /***************************************************************/
|
| 850 | int getProfileList(char **info)
|
| 851 | {
|
| 852 | char *apdu = NULL;
|
| 853 | int prof_num = 0;
|
| 854 |
|
| 855 | apdu = GetProfilesInfo(NULL);
|
| 856 | if (apdu == NULL)
|
| 857 | return prof_num;
|
| 858 |
|
| 859 |
|
| 860 | *info = lap_parse_profile_list(apdu, &prof_num);
|
| 861 |
|
| 862 |
|
| 863 | free(apdu);
|
| 864 | return prof_num;
|
| 865 | }
|
| 866 |
|