| | 113 | |
| | 114 | struct linkedit_data_command { |
| | 115 | uint32_t cmd; |
| | 116 | uint32_t cmdsize; |
| | 117 | uint32_t dataoff; |
| | 118 | uint32_t datasize; |
| | 119 | }; |
| | 120 | |
| | 121 | uint16_t Swap_(uint16_t value) { |
| | 122 | return |
| | 123 | ((value >> 8) & 0x00ff) | |
| | 124 | ((value << 8) & 0xff00); |
| | 125 | } |
| | 126 | |
| | 127 | uint32_t Swap_(uint32_t value) { |
| | 128 | value = ((value >> 8) & 0x00ff00ff) | |
| | 129 | ((value << 8) & 0xff00ff00); |
| | 130 | value = ((value >> 16) & 0x0000ffff) | |
| | 131 | ((value << 16) & 0xffff0000); |
| | 132 | return value; |
| | 133 | } |
| | 134 | |
| | 135 | int16_t Swap_(int16_t value) { |
| | 136 | return Swap_(static_cast<uint16_t>(value)); |
| | 137 | } |
| | 138 | |
| | 139 | int32_t Swap_(int32_t value) { |
| | 140 | return Swap_(static_cast<uint32_t>(value)); |
| | 141 | } |
| | 142 | |
| | 143 | uint16_t Swap(uint16_t value) { |
| | 144 | return true ? Swap_(value) : value; |
| | 145 | } |
| | 146 | |
| | 147 | uint32_t Swap(uint32_t value) { |
| | 148 | return true ? Swap_(value) : value; |
| | 149 | } |
| | 150 | |
| | 151 | int16_t Swap(int16_t value) { |
| | 152 | return Swap(static_cast<uint16_t>(value)); |
| | 153 | } |
| | 154 | |
| | 155 | int32_t Swap(int32_t value) { |
| | 156 | return Swap(static_cast<uint32_t>(value)); |
| | 157 | } |
| 248 | | Framework framework(file->c_str()); |
| | 332 | const char *path(file->c_str()); |
| | 333 | const char *base = strrchr(path, '/'); |
| | 334 | char *temp(NULL), *dir; |
| | 335 | |
| | 336 | if (base != NULL) |
| | 337 | dir = strndup(path, base++ - path + 1); |
| | 338 | else { |
| | 339 | dir = strdup(""); |
| | 340 | base = path; |
| | 341 | } |
| | 342 | |
| | 343 | if (flag_S) { |
| | 344 | asprintf(&temp, "%s.%s.cs", dir, base); |
| | 345 | const char *allocate = getenv("CODESIGN_ALLOCATE"); |
| | 346 | if (allocate == NULL) |
| | 347 | allocate = "codesign_allocate"; |
| | 348 | |
| | 349 | size_t size; { |
| | 350 | Framework framework(path); |
| | 351 | size = framework.GetSize(); |
| | 352 | } |
| | 353 | |
| | 354 | pid_t pid = fork(); |
| | 355 | _syscall(pid); |
| | 356 | if (pid == 0) { |
| | 357 | char *ssize; |
| | 358 | asprintf(&ssize, "%u", (sizeof(struct SuperBlob) + sizeof(struct BlobIndex) + sizeof(struct CodeDirectory) + strlen(base) + 1 + (size + 0x1000 - 1) / 0x1000 * 0x14 + 15) / 16 * 16); |
| | 359 | printf("%s\n", ssize); |
| | 360 | execlp(allocate, allocate, "-i", path, "-a", "arm", ssize, "-o", temp, NULL); |
| | 361 | _assert(false); |
| | 362 | } |
| | 363 | |
| | 364 | int status; |
| | 365 | _syscall(waitpid(pid, &status, 0)); |
| | 366 | _assert(WIFEXITED(status)); |
| | 367 | _assert(WEXITSTATUS(status) == 0); |
| | 368 | } |
| | 369 | |
| | 370 | Framework framework(temp == NULL ? path : temp); |
| | 371 | struct linkedit_data_command *signature(NULL); |
| | 415 | if (flag_S) { |
| | 416 | _assert(signature != NULL); |
| | 417 | |
| | 418 | uint32_t data = framework.Swap(signature->dataoff); |
| | 419 | uint32_t size = framework.Swap(signature->datasize); |
| | 420 | |
| | 421 | uint8_t *top = reinterpret_cast<uint8_t *>(framework.GetBase()); |
| | 422 | uint8_t *blob = top + data; |
| | 423 | struct SuperBlob *super = reinterpret_cast<struct SuperBlob *>(blob); |
| | 424 | super->magic = Swap(CSMAGIC_EMBEDDED_SIGNATURE); |
| | 425 | |
| | 426 | uint32_t count = 1; |
| | 427 | uint32_t offset = sizeof(struct SuperBlob) + count * sizeof(struct BlobIndex); |
| | 428 | |
| | 429 | super->index[0].type = Swap(CSSLOT_CODEDIRECTORY); |
| | 430 | super->index[0].offset = Swap(offset); |
| | 431 | |
| | 432 | uint32_t begin = offset; |
| | 433 | struct CodeDirectory *directory = reinterpret_cast<struct CodeDirectory *>(blob + begin); |
| | 434 | offset += sizeof(struct CodeDirectory); |
| | 435 | |
| | 436 | directory->magic = Swap(CSMAGIC_CODEDIRECTORY); |
| | 437 | directory->version = Swap(0x00020001); |
| | 438 | directory->flags = Swap(0); |
| | 439 | directory->codeLimit = Swap(data); |
| | 440 | directory->hashSize = 0x14; |
| | 441 | directory->hashType = 0x01; |
| | 442 | directory->spare1 = 0x00; |
| | 443 | directory->pageSize = 0x0c; |
| | 444 | directory->spare2 = Swap(0); |
| | 445 | |
| | 446 | directory->identOffset = Swap(offset - begin); |
| | 447 | strcpy(reinterpret_cast<char *>(blob + offset), base); |
| | 448 | offset += strlen(base) + 1; |
| | 449 | |
| | 450 | uint8_t (*hashes)[20] = reinterpret_cast<uint8_t (*)[20]>(blob + offset); |
| | 451 | uint32_t special = 0; |
| | 452 | |
| | 453 | uint32_t pages = (data + 0x1000 - 1) / 0x1000; |
| | 454 | directory->nSpecialSlots = Swap(special); |
| | 455 | directory->nCodeSlots = Swap(pages); |
| | 456 | |
| | 457 | if (pages != 1) |
| | 458 | for (size_t i = 0; i != pages - 1; ++i) |
| | 459 | sha1(hashes[special + i], top + 0x1000 * i, 0x1000); |
| | 460 | if (pages != 0) |
| | 461 | sha1(hashes[special + pages - 1], top + 0x1000 * (pages - 1), data % 0x1000); |
| | 462 | |
| | 463 | directory->hashOffset = Swap(offset - begin); |
| | 464 | offset += sizeof(*hashes) * (special + pages); |
| | 465 | directory->length = Swap(offset - begin); |
| | 466 | |
| | 467 | super->count = Swap(count); |
| | 468 | super->length = Swap(offset); |
| | 469 | |
| | 470 | _assert(offset < size); |
| | 471 | memset(blob + offset, 0, size - offset); |
| | 472 | } |
| | 473 | |
| | 474 | if (temp) { |
| | 475 | _syscall(unlink(path)); |
| | 476 | _syscall(rename(temp, path)); |
| | 477 | free(temp); |
| | 478 | } |
| | 479 | |
| | 480 | free(dir); |