diff options
| author | 2013-11-19 20:01:55 +0100 | |
|---|---|---|
| committer | 2013-11-19 20:01:55 +0100 | |
| commit | 054a79d64e55ce7d9874e65814c5a17caa1ca1f0 (patch) | |
| tree | c65e45aa558c79533d29eb193362e8263ce8fc41 | |
| parent | f6ee4a8efc3bfad2c2d451e3ad86edaca765ff9f (diff) | |
| download | libirecovery-054a79d64e55ce7d9874e65814c5a17caa1ca1f0.tar.gz libirecovery-054a79d64e55ce7d9874e65814c5a17caa1ca1f0.tar.bz2 | |
remove irecv_get_* functions and provide general irecv_get_device_info()
| -rw-r--r-- | include/libirecovery.h | 23 | ||||
| -rw-r--r-- | src/libirecovery.c | 485 | ||||
| -rw-r--r-- | tools/irecovery.c | 41 |
3 files changed, 264 insertions, 285 deletions
diff --git a/include/libirecovery.h b/include/libirecovery.h index d34e0f2..b575fed 100644 --- a/include/libirecovery.h +++ b/include/libirecovery.h | |||
| @@ -75,6 +75,22 @@ struct irecv_device { | |||
| 75 | }; | 75 | }; |
| 76 | typedef struct irecv_device* irecv_device_t; | 76 | typedef struct irecv_device* irecv_device_t; |
| 77 | 77 | ||
| 78 | struct irecv_device_info { | ||
| 79 | unsigned int cpid; | ||
| 80 | unsigned int cprv; | ||
| 81 | unsigned int cpfm; | ||
| 82 | unsigned int scep; | ||
| 83 | unsigned int bdid; | ||
| 84 | unsigned long long ecid; | ||
| 85 | unsigned int ibfl; | ||
| 86 | char* srnm; | ||
| 87 | char* imei; | ||
| 88 | unsigned char* ap_nonce; | ||
| 89 | unsigned int ap_nonce_size; | ||
| 90 | unsigned char* sep_nonce; | ||
| 91 | unsigned int sep_nonce_size; | ||
| 92 | }; | ||
| 93 | |||
| 78 | typedef struct irecv_client_private irecv_client_private; | 94 | typedef struct irecv_client_private irecv_client_private; |
| 79 | typedef irecv_client_private* irecv_client_t; | 95 | typedef irecv_client_private* irecv_client_t; |
| 80 | 96 | ||
| @@ -124,12 +140,7 @@ irecv_error_t irecv_getret(irecv_client_t client, unsigned int* value); | |||
| 124 | 140 | ||
| 125 | /* device information */ | 141 | /* device information */ |
| 126 | irecv_error_t irecv_get_mode(irecv_client_t client, int* mode); | 142 | irecv_error_t irecv_get_mode(irecv_client_t client, int* mode); |
| 127 | irecv_error_t irecv_get_cpid(irecv_client_t client, unsigned int* cpid); | 143 | const struct irecv_device_info* irecv_get_device_info(irecv_client_t client); |
| 128 | irecv_error_t irecv_get_bdid(irecv_client_t client, unsigned int* bdid); | ||
| 129 | irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid); | ||
| 130 | irecv_error_t irecv_get_nonce_with_tag(irecv_client_t client, const char* tag, unsigned char** nonce, int* nonce_size); | ||
| 131 | irecv_error_t irecv_get_srnm(irecv_client_t client, char* srnm); | ||
| 132 | irecv_error_t irecv_get_imei(irecv_client_t client, char* imei); | ||
| 133 | 144 | ||
| 134 | /* device database queries */ | 145 | /* device database queries */ |
| 135 | irecv_device_t irecv_devices_get_all(); | 146 | irecv_device_t irecv_devices_get_all(); |
diff --git a/src/libirecovery.c b/src/libirecovery.c index f189838..604a9c4 100644 --- a/src/libirecovery.c +++ b/src/libirecovery.c | |||
| @@ -49,7 +49,7 @@ struct irecv_client_private { | |||
| 49 | int interface; | 49 | int interface; |
| 50 | int alt_interface; | 50 | int alt_interface; |
| 51 | unsigned int mode; | 51 | unsigned int mode; |
| 52 | char serial[256]; | 52 | struct irecv_device_info device_info; |
| 53 | #ifndef WIN32 | 53 | #ifndef WIN32 |
| 54 | libusb_device_handle* handle; | 54 | libusb_device_handle* handle; |
| 55 | #else | 55 | #else |
| @@ -191,6 +191,191 @@ static unsigned int dfu_hash_t1[256] = { | |||
| 191 | #define dfu_hash_step(a,b) \ | 191 | #define dfu_hash_step(a,b) \ |
| 192 | a = (dfu_hash_t1[(a & 0xFF) ^ ((unsigned char)b)] ^ (a >> 8)) | 192 | a = (dfu_hash_t1[(a & 0xFF) ^ ((unsigned char)b)] ^ (a >> 8)) |
| 193 | 193 | ||
| 194 | static int irecv_get_string_descriptor_ascii(irecv_client_t client, uint8_t desc_index, unsigned char * buffer, int size) { | ||
| 195 | #ifndef WIN32 | ||
| 196 | return libusb_get_string_descriptor_ascii(client->handle, desc_index, buffer, size); | ||
| 197 | #else | ||
| 198 | irecv_error_t ret; | ||
| 199 | unsigned short langid = 0; | ||
| 200 | unsigned char data[255]; | ||
| 201 | int di, si; | ||
| 202 | memset(data, 0, sizeof(data)); | ||
| 203 | memset(buffer, 0, size); | ||
| 204 | |||
| 205 | ret = irecv_usb_control_transfer(client, 0x80, 0x06, (0x03 << 8) | desc_index, langid, data, sizeof(data), USB_TIMEOUT); | ||
| 206 | |||
| 207 | if (ret < 0) return ret; | ||
| 208 | if (data[1] != 0x03) return IRECV_E_UNKNOWN_ERROR; | ||
| 209 | if (data[0] > ret) return IRECV_E_UNKNOWN_ERROR; | ||
| 210 | |||
| 211 | for (di = 0, si = 2; si < data[0]; si += 2) { | ||
| 212 | if (di >= (size - 1)) break; | ||
| 213 | if (data[si + 1]) { | ||
| 214 | /* high byte */ | ||
| 215 | buffer[di++] = '?'; | ||
| 216 | } else { | ||
| 217 | buffer[di++] = data[si]; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | buffer[di] = 0; | ||
| 221 | |||
| 222 | return di; | ||
| 223 | #endif | ||
| 224 | } | ||
| 225 | |||
| 226 | static void irecv_load_device_info_from_iboot_string(irecv_client_t client, const char* iboot_string) | ||
| 227 | { | ||
| 228 | if (!client || !iboot_string) { | ||
| 229 | return; | ||
| 230 | } | ||
| 231 | |||
| 232 | memset(&client->device_info, '\0', sizeof(struct irecv_device_info)); | ||
| 233 | |||
| 234 | char* ptr; | ||
| 235 | |||
| 236 | ptr = strstr(iboot_string, "CPID:"); | ||
| 237 | if (ptr != NULL) { | ||
| 238 | sscanf(ptr, "CPID:%x", &client->device_info.cpid); | ||
| 239 | } | ||
| 240 | |||
| 241 | ptr = strstr(iboot_string, "CPRV:"); | ||
| 242 | if (ptr != NULL) { | ||
| 243 | sscanf(ptr, "CPRV:%x", &client->device_info.cprv); | ||
| 244 | } | ||
| 245 | |||
| 246 | ptr = strstr(iboot_string, "CPFM:"); | ||
| 247 | if (ptr != NULL) { | ||
| 248 | sscanf(ptr, "CPFM:%x", &client->device_info.cpfm); | ||
| 249 | } | ||
| 250 | |||
| 251 | ptr = strstr(iboot_string, "SCEP:"); | ||
| 252 | if (ptr != NULL) { | ||
| 253 | sscanf(ptr, "SCEP:%x", &client->device_info.scep); | ||
| 254 | } | ||
| 255 | |||
| 256 | ptr = strstr(iboot_string, "BDID:"); | ||
| 257 | if (ptr != NULL) { | ||
| 258 | sscanf(ptr, "BDID:%x", &client->device_info.bdid); | ||
| 259 | } | ||
| 260 | |||
| 261 | ptr = strstr(iboot_string, "ECID:"); | ||
| 262 | if (ptr != NULL) { | ||
| 263 | sscanf(ptr, "ECID:" _FMT_qX, &client->device_info.ecid); | ||
| 264 | } | ||
| 265 | |||
| 266 | ptr = strstr(iboot_string, "IBFL:"); | ||
| 267 | if (ptr != NULL) { | ||
| 268 | sscanf(ptr, "IBFL:%x", &client->device_info.ibfl); | ||
| 269 | } | ||
| 270 | |||
| 271 | char tmp[256]; | ||
| 272 | tmp[0] = '\0'; | ||
| 273 | ptr = strstr(iboot_string, "SRNM:["); | ||
| 274 | if(ptr != NULL) { | ||
| 275 | sscanf(ptr, "SRNM:[%s]", tmp); | ||
| 276 | ptr = strrchr(tmp, ']'); | ||
| 277 | if(ptr != NULL) { | ||
| 278 | *ptr = '\0'; | ||
| 279 | } | ||
| 280 | client->device_info.srnm = strdup(tmp); | ||
| 281 | } | ||
| 282 | |||
| 283 | tmp[0] = '\0'; | ||
| 284 | ptr = strstr(iboot_string, "IMEI:["); | ||
| 285 | if(ptr != NULL) { | ||
| 286 | sscanf(ptr, "IMEI:[%s]", tmp); | ||
| 287 | ptr = strrchr(tmp, ']'); | ||
| 288 | if(ptr != NULL) { | ||
| 289 | *ptr = '\0'; | ||
| 290 | } | ||
| 291 | client->device_info.imei = strdup(tmp); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | static void irecv_copy_nonce_with_tag(irecv_client_t client, const char* tag, unsigned char** nonce, unsigned int* nonce_size) | ||
| 296 | { | ||
| 297 | if (!client || !tag) { | ||
| 298 | return; | ||
| 299 | } | ||
| 300 | |||
| 301 | char buf[255]; | ||
| 302 | int len; | ||
| 303 | |||
| 304 | *nonce = NULL; | ||
| 305 | *nonce_size = 0; | ||
| 306 | |||
| 307 | len = irecv_get_string_descriptor_ascii(client, 1, (unsigned char*) buf, 255); | ||
| 308 | debug("%s: got length: %d\n", __func__, len); | ||
| 309 | if (len < 0) { | ||
| 310 | return; | ||
| 311 | } | ||
| 312 | |||
| 313 | buf[len] = 0; | ||
| 314 | debug("%s: buf='%s' tag='%s'\n", __func__, buf, tag); | ||
| 315 | |||
| 316 | int taglen = strlen(tag); | ||
| 317 | int nlen = 0; | ||
| 318 | char* nonce_string = NULL; | ||
| 319 | char* p = buf; | ||
| 320 | char* colon = NULL; | ||
| 321 | do { | ||
| 322 | colon = strchr(p, ':'); | ||
| 323 | if (!colon) | ||
| 324 | break; | ||
| 325 | if (colon-taglen < p) { | ||
| 326 | break; | ||
| 327 | } | ||
| 328 | char *space = strchr(colon, ' '); | ||
| 329 | if (strncmp(colon-taglen, tag, taglen) == 0) { | ||
| 330 | p = colon+1; | ||
| 331 | if (!space) { | ||
| 332 | nlen = strlen(p); | ||
| 333 | } else { | ||
| 334 | nlen = space-p; | ||
| 335 | } | ||
| 336 | nonce_string = p; | ||
| 337 | nlen/=2; | ||
| 338 | break; | ||
| 339 | } else { | ||
| 340 | if (!space) { | ||
| 341 | break; | ||
| 342 | } else { | ||
| 343 | p = space+1; | ||
| 344 | } | ||
| 345 | } | ||
| 346 | } while (colon); | ||
| 347 | |||
| 348 | if (nlen == 0) { | ||
| 349 | debug("%s: ERROR: couldn't find tag %s in string %s\n", __func__, tag, buf); | ||
| 350 | return; | ||
| 351 | } | ||
| 352 | |||
| 353 | unsigned char *nn = malloc(nlen); | ||
| 354 | if (!nn) { | ||
| 355 | return; | ||
| 356 | } | ||
| 357 | |||
| 358 | int i = 0; | ||
| 359 | for (i = 0; i < nlen; i++) { | ||
| 360 | int val = 0; | ||
| 361 | if (sscanf(nonce_string+(i*2), "%02X", &val) == 1) { | ||
| 362 | nn[i] = (unsigned char)val; | ||
| 363 | } else { | ||
| 364 | debug("%s: ERROR: unexpected data in nonce result (%2s)\n", __func__, nonce_string+(i*2)); | ||
| 365 | break; | ||
| 366 | } | ||
| 367 | } | ||
| 368 | |||
| 369 | if (i != nlen) { | ||
| 370 | debug("%s: ERROR: unable to parse nonce\n", __func__); | ||
| 371 | free(nn); | ||
| 372 | return; | ||
| 373 | } | ||
| 374 | |||
| 375 | *nonce = nn; | ||
| 376 | *nonce_size = nlen; | ||
| 377 | } | ||
| 378 | |||
| 194 | #ifdef WIN32 | 379 | #ifdef WIN32 |
| 195 | static const GUID GUID_DEVINTERFACE_IBOOT = {0xED82A167L, 0xD61A, 0x4AF6, {0x9A, 0xB6, 0x11, 0xE5, 0x22, 0x36, 0xC5, 0x76}}; | 380 | static const GUID GUID_DEVINTERFACE_IBOOT = {0xED82A167L, 0xD61A, 0x4AF6, {0x9A, 0xB6, 0x11, 0xE5, 0x22, 0x36, 0xC5, 0x76}}; |
| 196 | static const GUID GUID_DEVINTERFACE_DFU = {0xB8085869L, 0xFEB9, 0x404B, {0x8C, 0xB1, 0x1E, 0x5C, 0x14, 0xFA, 0x8C, 0x54}}; | 381 | static const GUID GUID_DEVINTERFACE_DFU = {0xB8085869L, 0xFEB9, 0x404B, {0x8C, 0xB1, 0x1E, 0x5C, 0x14, 0xFA, 0x8C, 0x54}}; |
| @@ -262,37 +447,31 @@ irecv_error_t mobiledevice_connect(irecv_client_t* client, unsigned long long ec | |||
| 262 | continue; | 447 | continue; |
| 263 | } | 448 | } |
| 264 | 449 | ||
| 265 | _client->serial[0] = '\0'; | 450 | char* serial_str[256]; |
| 266 | if ((sscanf(result, "\\\\?\\usb#vid_%*04x&pid_%*04x#%s#", _client->serial) != 1) || (_client->serial[0] == '\0')) { | 451 | serial_str[0] = '\0'; |
| 452 | if ((sscanf(result, "\\\\?\\usb#vid_%*04x&pid_%*04x#%s#", serial_str) != 1) || (serial_str[0] == '\0')) { | ||
| 267 | mobiledevice_closepipes(_client); | 453 | mobiledevice_closepipes(_client); |
| 268 | continue; | 454 | continue; |
| 269 | } | 455 | } |
| 270 | 456 | ||
| 271 | char* p = strchr(_client->serial, '#'); | 457 | char* p = strchr(serial_str, '#'); |
| 272 | if (p) { | 458 | if (p) { |
| 273 | *p = '\0'; | 459 | *p = '\0'; |
| 274 | } | 460 | } |
| 275 | 461 | ||
| 276 | int j; | 462 | int j; |
| 277 | for (j = 0; j < strlen(_client->serial); j++) { | 463 | for (j = 0; j < strlen(serial_str); j++) { |
| 278 | if (_client->serial[j] == '_') { | 464 | if (serial_str[j] == '_') { |
| 279 | _client->serial[j] = ' '; | 465 | serial_str[j] = ' '; |
| 280 | } else { | 466 | } else { |
| 281 | _client->serial[j] = toupper(_client->serial[j]); | 467 | serial_str[j] = toupper(serial_str[j]); |
| 282 | } | 468 | } |
| 283 | } | 469 | } |
| 284 | 470 | ||
| 285 | if (ecid != 0) { | 471 | irecv_load_device_info_from_iboot_string(_client, serial_str); |
| 286 | char* ecid_string = strstr(_client->serial, "ECID:"); | ||
| 287 | if (ecid_string == NULL) { | ||
| 288 | debug("%s: could not get ECID for device\n", __func__); | ||
| 289 | mobiledevice_closepipes(_client); | ||
| 290 | continue; | ||
| 291 | } | ||
| 292 | 472 | ||
| 293 | unsigned long long this_ecid = 0; | 473 | if (ecid != 0) { |
| 294 | sscanf(ecid_string, "ECID:" _FMT_qX, (unsigned long long*)&this_ecid); | 474 | if (_client->device_info.ecid != ecid) { |
| 295 | if (this_ecid != ecid) { | ||
| 296 | mobiledevice_closepipes(_client); | 475 | mobiledevice_closepipes(_client); |
| 297 | continue; | 476 | continue; |
| 298 | } | 477 | } |
| @@ -344,37 +523,29 @@ irecv_error_t mobiledevice_connect(irecv_client_t* client, unsigned long long ec | |||
| 344 | continue; | 523 | continue; |
| 345 | } | 524 | } |
| 346 | 525 | ||
| 347 | _client->serial[0] = '\0'; | 526 | char serial_str[256]; |
| 348 | if ((sscanf(result, "\\\\?\\usb#vid_%*04x&pid_%*04x#%s#", _client->serial) != 1) || (_client->serial[0] == '\0')) { | 527 | serial_str[0] = '\0'; |
| 528 | if ((sscanf(result, "\\\\?\\usb#vid_%*04x&pid_%*04x#%s#", serial_str) != 1) || (serial_str[0] == '\0')) { | ||
| 349 | mobiledevice_closepipes(_client); | 529 | mobiledevice_closepipes(_client); |
| 350 | continue; | 530 | continue; |
| 351 | } | 531 | } |
| 352 | 532 | ||
| 353 | char* p = strchr(_client->serial, '#'); | 533 | char* p = strchr(serial_str, '#'); |
| 354 | if (p) { | 534 | if (p) { |
| 355 | *p = '\0'; | 535 | *p = '\0'; |
| 356 | } | 536 | } |
| 357 | 537 | ||
| 358 | int j; | 538 | int j; |
| 359 | for (j = 0; j < strlen(_client->serial); j++) { | 539 | for (j = 0; j < strlen(serial_str); j++) { |
| 360 | if (_client->serial[j] == '_') { | 540 | if (serial_str[j] == '_') { |
| 361 | _client->serial[j] = ' '; | 541 | serial_str[j] = ' '; |
| 362 | } else { | 542 | } else { |
| 363 | _client->serial[j] = toupper(_client->serial[j]); | 543 | serial_str[j] = toupper(serial_str[j]); |
| 364 | } | 544 | } |
| 365 | } | 545 | } |
| 366 | 546 | ||
| 367 | if (ecid != 0) { | 547 | if (ecid != 0) { |
| 368 | char* ecid_string = strstr(_client->serial, "ECID:"); | 548 | if (_client->device_info.ecid != ecid) { |
| 369 | if (ecid_string == NULL) { | ||
| 370 | debug("%s: could not get ECID for device\n", __func__); | ||
| 371 | mobiledevice_closepipes(_client); | ||
| 372 | continue; | ||
| 373 | } | ||
| 374 | |||
| 375 | unsigned long long this_ecid = 0; | ||
| 376 | sscanf(ecid_string, "ECID:" _FMT_qX, (unsigned long long*)&this_ecid); | ||
| 377 | if (this_ecid != ecid) { | ||
| 378 | mobiledevice_closepipes(_client); | 549 | mobiledevice_closepipes(_client); |
| 379 | continue; | 550 | continue; |
| 380 | } | 551 | } |
| @@ -538,38 +709,6 @@ int irecv_usb_bulk_transfer(irecv_client_t client, | |||
| 538 | return ret; | 709 | return ret; |
| 539 | } | 710 | } |
| 540 | 711 | ||
| 541 | static int irecv_get_string_descriptor_ascii(irecv_client_t client, uint8_t desc_index, unsigned char * buffer, int size) { | ||
| 542 | #ifndef WIN32 | ||
| 543 | return libusb_get_string_descriptor_ascii(client->handle, desc_index, buffer, size); | ||
| 544 | #else | ||
| 545 | irecv_error_t ret; | ||
| 546 | unsigned short langid = 0; | ||
| 547 | unsigned char data[255]; | ||
| 548 | int di, si; | ||
| 549 | memset(data, 0, sizeof(data)); | ||
| 550 | memset(buffer, 0, size); | ||
| 551 | |||
| 552 | ret = irecv_usb_control_transfer(client, 0x80, 0x06, (0x03 << 8) | desc_index, langid, data, sizeof(data), USB_TIMEOUT); | ||
| 553 | |||
| 554 | if (ret < 0) return ret; | ||
| 555 | if (data[1] != 0x03) return IRECV_E_UNKNOWN_ERROR; | ||
| 556 | if (data[0] > ret) return IRECV_E_UNKNOWN_ERROR; | ||
| 557 | |||
| 558 | for (di = 0, si = 2; si < data[0]; si += 2) { | ||
| 559 | if (di >= (size - 1)) break; | ||
| 560 | if (data[si + 1]) { | ||
| 561 | /* high byte */ | ||
| 562 | buffer[di++] = '?'; | ||
| 563 | } else { | ||
| 564 | buffer[di++] = data[si]; | ||
| 565 | } | ||
| 566 | } | ||
| 567 | buffer[di] = 0; | ||
| 568 | |||
| 569 | return di; | ||
| 570 | #endif | ||
| 571 | } | ||
| 572 | |||
| 573 | irecv_error_t irecv_open_with_ecid(irecv_client_t* pclient, unsigned long long ecid) { | 712 | irecv_error_t irecv_open_with_ecid(irecv_client_t* pclient, unsigned long long ecid) { |
| 574 | if(libirecovery_debug) { | 713 | if(libirecovery_debug) { |
| 575 | irecv_set_debug_level(libirecovery_debug); | 714 | irecv_set_debug_level(libirecovery_debug); |
| @@ -637,11 +776,16 @@ irecv_error_t irecv_open_with_ecid(irecv_client_t* pclient, unsigned long long e | |||
| 637 | client->handle = usb_handle; | 776 | client->handle = usb_handle; |
| 638 | client->mode = usb_descriptor.idProduct; | 777 | client->mode = usb_descriptor.idProduct; |
| 639 | 778 | ||
| 640 | /* cache usb serial */ | 779 | char serial_str[256]; |
| 641 | irecv_get_string_descriptor_ascii(client, usb_descriptor.iSerialNumber, (unsigned char*) client->serial, 255); | 780 | irecv_get_string_descriptor_ascii(client, usb_descriptor.iSerialNumber, (unsigned char*)serial_str, 255); |
| 781 | |||
| 782 | irecv_load_device_info_from_iboot_string(client, serial_str); | ||
| 783 | |||
| 784 | irecv_copy_nonce_with_tag(client, "NONC", &client->device_info.ap_nonce, &client->device_info.ap_nonce_size); | ||
| 785 | irecv_copy_nonce_with_tag(client, "SNON", &client->device_info.sep_nonce, &client->device_info.sep_nonce_size); | ||
| 642 | 786 | ||
| 643 | if (ecid != 0) { | 787 | if (ecid != 0) { |
| 644 | char* ecid_string = strstr(client->serial, "ECID:"); | 788 | char* ecid_string = strstr(serial_str, "ECID:"); |
| 645 | if (ecid_string == NULL) { | 789 | if (ecid_string == NULL) { |
| 646 | debug("%s: could not get ECID for device\n", __func__); | 790 | debug("%s: could not get ECID for device\n", __func__); |
| 647 | irecv_close(client); | 791 | irecv_close(client); |
| @@ -870,6 +1014,18 @@ irecv_error_t irecv_close(irecv_client_t client) { | |||
| 870 | } | 1014 | } |
| 871 | mobiledevice_closepipes(client); | 1015 | mobiledevice_closepipes(client); |
| 872 | #endif | 1016 | #endif |
| 1017 | if (client->device_info.srnm) { | ||
| 1018 | free(client->device_info.srnm); | ||
| 1019 | } | ||
| 1020 | if (client->device_info.imei) { | ||
| 1021 | free(client->device_info.imei); | ||
| 1022 | } | ||
| 1023 | if (client->device_info.ap_nonce) { | ||
| 1024 | free(client->device_info.ap_nonce); | ||
| 1025 | } | ||
| 1026 | if (client->device_info.sep_nonce) { | ||
| 1027 | free(client->device_info.sep_nonce); | ||
| 1028 | } | ||
| 873 | free(client); | 1029 | free(client); |
| 874 | client = NULL; | 1030 | client = NULL; |
| 875 | } | 1031 | } |
| @@ -1216,186 +1372,12 @@ irecv_error_t irecv_get_mode(irecv_client_t client, int* mode) { | |||
| 1216 | return IRECV_E_SUCCESS; | 1372 | return IRECV_E_SUCCESS; |
| 1217 | } | 1373 | } |
| 1218 | 1374 | ||
| 1219 | irecv_error_t irecv_get_cpid(irecv_client_t client, unsigned int* cpid) { | 1375 | const struct irecv_device_info* irecv_get_device_info(irecv_client_t client) |
| 1376 | { | ||
| 1220 | if (check_context(client) != IRECV_E_SUCCESS) | 1377 | if (check_context(client) != IRECV_E_SUCCESS) |
| 1221 | return IRECV_E_NO_DEVICE; | 1378 | return NULL; |
| 1222 | |||
| 1223 | if (client->mode == IRECV_K_WTF_MODE) { | ||
| 1224 | char s_cpid[8] = {0,}; | ||
| 1225 | strncpy(s_cpid, client->serial, 4); | ||
| 1226 | if (sscanf(s_cpid, "%x", cpid) != 1) { | ||
| 1227 | *cpid = 0; | ||
| 1228 | return IRECV_E_UNKNOWN_ERROR; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | return IRECV_E_SUCCESS; | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | char* cpid_string = strstr(client->serial, "CPID:"); | ||
| 1235 | if (cpid_string == NULL) { | ||
| 1236 | *cpid = 0; | ||
| 1237 | return IRECV_E_UNKNOWN_ERROR; | ||
| 1238 | } | ||
| 1239 | sscanf(cpid_string, "CPID:%x", cpid); | ||
| 1240 | |||
| 1241 | return IRECV_E_SUCCESS; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | irecv_error_t irecv_get_bdid(irecv_client_t client, unsigned int* bdid) { | ||
| 1245 | if (check_context(client) != IRECV_E_SUCCESS) | ||
| 1246 | return IRECV_E_NO_DEVICE; | ||
| 1247 | |||
| 1248 | char* bdid_string = strstr(client->serial, "BDID:"); | ||
| 1249 | if (bdid_string == NULL) { | ||
| 1250 | *bdid = 0; | ||
| 1251 | return IRECV_E_UNKNOWN_ERROR; | ||
| 1252 | } | ||
| 1253 | sscanf(bdid_string, "BDID:%x", bdid); | ||
| 1254 | |||
| 1255 | return IRECV_E_SUCCESS; | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | irecv_error_t irecv_get_ecid(irecv_client_t client, unsigned long long* ecid) { | ||
| 1259 | if (check_context(client) != IRECV_E_SUCCESS) | ||
| 1260 | return IRECV_E_NO_DEVICE; | ||
| 1261 | |||
| 1262 | char* ecid_string = strstr(client->serial, "ECID:"); | ||
| 1263 | if (ecid_string == NULL) { | ||
| 1264 | *ecid = 0; | ||
| 1265 | return IRECV_E_UNKNOWN_ERROR; | ||
| 1266 | } | ||
| 1267 | sscanf(ecid_string, "ECID:" _FMT_qX, ecid); | ||
| 1268 | |||
| 1269 | return IRECV_E_SUCCESS; | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | irecv_error_t irecv_get_srnm(irecv_client_t client, char* srnm) { | ||
| 1273 | if (check_context(client) != IRECV_E_SUCCESS) | ||
| 1274 | return IRECV_E_NO_DEVICE; | ||
| 1275 | |||
| 1276 | char* srnmp; | ||
| 1277 | char* srnm_string = strstr(client->serial, "SRNM:["); | ||
| 1278 | if(srnm_string == NULL) { | ||
| 1279 | *srnm = 0; | ||
| 1280 | return IRECV_E_UNKNOWN_ERROR; | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | sscanf(srnm_string, "SRNM:[%s]", srnm); | ||
| 1284 | srnmp = strrchr(srnm, ']'); | ||
| 1285 | if(srnmp != NULL) { | ||
| 1286 | *srnmp = '\0'; | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | return IRECV_E_SUCCESS; | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | irecv_error_t irecv_get_imei(irecv_client_t client, char* imei) { | ||
| 1293 | if (check_context(client) != IRECV_E_SUCCESS) | ||
| 1294 | return IRECV_E_NO_DEVICE; | ||
| 1295 | |||
| 1296 | char* imeip; | ||
| 1297 | char* imei_string = strstr(client->serial, "IMEI:["); | ||
| 1298 | if (imei_string == NULL) { | ||
| 1299 | *imei = 0; | ||
| 1300 | return IRECV_E_UNKNOWN_ERROR; | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | |||
| 1304 | sscanf(imei_string, "IMEI:[%s]", imei); | ||
| 1305 | imeip = strrchr(imei, ']'); | ||
| 1306 | if(imeip != NULL) { | ||
| 1307 | *imeip = '\0'; | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | return IRECV_E_SUCCESS; | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | irecv_error_t irecv_get_nonce_with_tag(irecv_client_t client, const char* tag, unsigned char** nonce, int* nonce_size) { | ||
| 1314 | if (check_context(client) != IRECV_E_SUCCESS) | ||
| 1315 | return IRECV_E_NO_DEVICE; | ||
| 1316 | |||
| 1317 | if (tag == NULL) { | ||
| 1318 | return IRECV_E_INVALID_INPUT; | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | char buf[255]; | ||
| 1322 | int len; | ||
| 1323 | |||
| 1324 | *nonce = NULL; | ||
| 1325 | *nonce_size = 0; | ||
| 1326 | |||
| 1327 | len = irecv_get_string_descriptor_ascii(client, 1, (unsigned char*) buf, 255); | ||
| 1328 | debug("%s: got length: %d\n", __func__, len); | ||
| 1329 | if (len < 0) { | ||
| 1330 | return len; | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | buf[len] = 0; | ||
| 1334 | debug("%s: buf='%s' tag='%s'\n", __func__, buf, tag); | ||
| 1335 | |||
| 1336 | int taglen = strlen(tag); | ||
| 1337 | int nlen = 0; | ||
| 1338 | char* nonce_string = NULL; | ||
| 1339 | char* p = buf; | ||
| 1340 | char* colon = NULL; | ||
| 1341 | do { | ||
| 1342 | colon = strchr(p, ':'); | ||
| 1343 | if (!colon) | ||
| 1344 | break; | ||
| 1345 | if (colon-taglen < p) { | ||
| 1346 | break; | ||
| 1347 | } | ||
| 1348 | char *space = strchr(colon, ' '); | ||
| 1349 | if (strncmp(colon-taglen, tag, taglen) == 0) { | ||
| 1350 | p = colon+1; | ||
| 1351 | if (!space) { | ||
| 1352 | nlen = strlen(p); | ||
| 1353 | } else { | ||
| 1354 | nlen = space-p; | ||
| 1355 | } | ||
| 1356 | nonce_string = p; | ||
| 1357 | nlen/=2; | ||
| 1358 | break; | ||
| 1359 | } else { | ||
| 1360 | if (!space) { | ||
| 1361 | break; | ||
| 1362 | } else { | ||
| 1363 | p = space+1; | ||
| 1364 | } | ||
| 1365 | } | ||
| 1366 | } while (colon); | ||
| 1367 | |||
| 1368 | if (nlen == 0) { | ||
| 1369 | debug("%s: ERROR: couldn't find tag %s in string %s\n", __func__, tag, buf); | ||
| 1370 | return IRECV_E_UNKNOWN_ERROR; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | unsigned char *nn = malloc(nlen); | ||
| 1374 | if (!nn) { | ||
| 1375 | return IRECV_E_OUT_OF_MEMORY; | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | int i = 0; | ||
| 1379 | for (i = 0; i < nlen; i++) { | ||
| 1380 | int val = 0; | ||
| 1381 | if (sscanf(nonce_string+(i*2), "%02X", &val) == 1) { | ||
| 1382 | nn[i] = (unsigned char)val; | ||
| 1383 | } else { | ||
| 1384 | debug("%s: ERROR: unexpected data in nonce result (%2s)\n", __func__, nonce_string+(i*2)); | ||
| 1385 | break; | ||
| 1386 | } | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | if (i != nlen) { | ||
| 1390 | debug("%s: ERROR: unable to parse nonce\n", __func__); | ||
| 1391 | free(nn); | ||
| 1392 | return IRECV_E_UNKNOWN_ERROR; | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | *nonce = nn; | ||
| 1396 | *nonce_size = nlen; | ||
| 1397 | 1379 | ||
| 1398 | return IRECV_E_SUCCESS; | 1380 | return &client->device_info; |
| 1399 | } | 1381 | } |
| 1400 | 1382 | ||
| 1401 | irecv_error_t irecv_trigger_limera1n_exploit(irecv_client_t client) { | 1383 | irecv_error_t irecv_trigger_limera1n_exploit(irecv_client_t client) { |
| @@ -1601,11 +1583,11 @@ irecv_error_t irecv_devices_get_device_by_client(irecv_client_t client, irecv_de | |||
| 1601 | 1583 | ||
| 1602 | *device = NULL; | 1584 | *device = NULL; |
| 1603 | 1585 | ||
| 1604 | if (irecv_get_cpid(client, &cpid) < 0) { | 1586 | if (client->device_info.cpid == 0) { |
| 1605 | return IRECV_E_UNKNOWN_ERROR; | 1587 | return IRECV_E_UNKNOWN_ERROR; |
| 1606 | } | 1588 | } |
| 1607 | 1589 | ||
| 1608 | if (irecv_get_bdid(client, &bdid) < 0) { | 1590 | if (client->device_info.bdid == 0) { |
| 1609 | return IRECV_E_UNKNOWN_ERROR; | 1591 | return IRECV_E_UNKNOWN_ERROR; |
| 1610 | } | 1592 | } |
| 1611 | 1593 | ||
| @@ -1660,8 +1642,7 @@ irecv_client_t irecv_reconnect(irecv_client_t client, int initial_pause) { | |||
| 1660 | irecv_client_t new_client = NULL; | 1642 | irecv_client_t new_client = NULL; |
| 1661 | irecv_event_cb_t progress_callback = client->progress_callback; | 1643 | irecv_event_cb_t progress_callback = client->progress_callback; |
| 1662 | 1644 | ||
| 1663 | unsigned long long ecid = 0; | 1645 | unsigned long long ecid = client->device_info.ecid; |
| 1664 | irecv_get_ecid(client, &ecid); | ||
| 1665 | 1646 | ||
| 1666 | if (check_context(client) == IRECV_E_SUCCESS) { | 1647 | if (check_context(client) == IRECV_E_SUCCESS) { |
| 1667 | irecv_close(client); | 1648 | irecv_close(client); |
diff --git a/tools/irecovery.c b/tools/irecovery.c index a8c85eb..a14e2b6 100644 --- a/tools/irecovery.c +++ b/tools/irecovery.c | |||
| @@ -131,33 +131,20 @@ static void parse_command(irecv_client_t client, unsigned char* command, unsigne | |||
| 131 | } | 131 | } |
| 132 | } else if (!strcmp(cmd, "/deviceinfo")) { | 132 | } else if (!strcmp(cmd, "/deviceinfo")) { |
| 133 | int ret, mode; | 133 | int ret, mode; |
| 134 | unsigned int cpid, bdid; | 134 | const struct irecv_device_info *devinfo = irecv_get_device_info(client); |
| 135 | unsigned long long ecid; | 135 | |
| 136 | char srnm[12], imei[15]; | 136 | if (devinfo) { |
| 137 | 137 | printf("CPID: %x\n", devinfo->cpid); | |
| 138 | ret = irecv_get_cpid(client, &cpid); | 138 | printf("CPRV: %x\n", devinfo->cprv); |
| 139 | if(ret == IRECV_E_SUCCESS) { | 139 | printf("BDID: %x\n", devinfo->bdid); |
| 140 | printf("CPID: %d\n", cpid); | 140 | printf("ECID: " _FMT_lld "\n", devinfo->ecid); |
| 141 | } | 141 | printf("CPFM: %x\n", devinfo->cpfm); |
| 142 | 142 | printf("SCEP: %x\n", devinfo->scep); | |
| 143 | ret = irecv_get_bdid(client, &bdid); | 143 | printf("IBFL: %x\n", devinfo->ibfl); |
| 144 | if(ret == IRECV_E_SUCCESS) { | 144 | printf("SRNM: %s\n", (devinfo->srnm) ? devinfo->srnm : "N/A"); |
| 145 | printf("BDID: %d\n", bdid); | 145 | printf("IMEI: %s\n", (devinfo->imei) ? devinfo->imei : "N/A"); |
| 146 | } | 146 | } else { |
| 147 | 147 | printf("Could not get device info?!\n"); | |
| 148 | ret = irecv_get_ecid(client, &ecid); | ||
| 149 | if(ret == IRECV_E_SUCCESS) { | ||
| 150 | printf("ECID: " _FMT_lld "\n", ecid); | ||
| 151 | } | ||
| 152 | |||
| 153 | ret = irecv_get_srnm(client, srnm); | ||
| 154 | if(ret == IRECV_E_SUCCESS) { | ||
| 155 | printf("SRNM: %s\n", srnm); | ||
| 156 | } | ||
| 157 | |||
| 158 | ret = irecv_get_imei(client, imei); | ||
| 159 | if(ret == IRECV_E_SUCCESS) { | ||
| 160 | printf("IMEI: %s\n", imei); | ||
| 161 | } | 148 | } |
| 162 | 149 | ||
| 163 | ret = irecv_get_mode(client, &mode); | 150 | ret = irecv_get_mode(client, &mode); |
