void writeImg3Element(AbstractFile* file, Img3Element* element, Img3Info* info) { off_t curPos; if(info->exploit24k && element->header->magic == IMG3_TYPE_MAGIC) { // Drop TYPE tag for exploited LLB, because it throws off our payload calculations // Bootrom shouldn't care anyway, and kernel currently doesn't care return; } curPos = file->tell(file); if(element->header->magic == IMG3_CERT_MAGIC) { if(info->exploit24k) { do24kpwn(info, element, curPos, x24kpwn_overflow_data, sizeof(x24kpwn_overflow_data), x24kpwn_payload_data, sizeof(x24kpwn_payload_data)); } else if(info->exploitN8824k) { do24kpwn(info, element, curPos, n8824kpwn_overflow_data, sizeof(n8824kpwn_overflow_data), n8824kpwn_payload_data, sizeof(n8824kpwn_payload_data)); } } flipAppleImg3Header(element->header); file->write(file, element->header, sizeof(AppleImg3Header)); flipAppleImg3Header(element->header); element->write(file, element, info); file->seek(file, curPos + element->header->size); }
void writeImg3Element(AbstractFile* file, Img3Element* element, Img3Info* info) { off_t curPos; curPos = file->tell(file); flipAppleImg3Header(element->header); file->write(file, element->header, sizeof(AppleImg3Header)); flipAppleImg3Header(element->header); element->write(file, element, info); file->seek(file, curPos + element->header->size); }
void writeImg3Root(AbstractFile * file, Img3Element * element, Img3Info * info) { AppleImg3RootHeader *header; Img3Element *current; off_t curPos; curPos = file->tell(file); curPos -= sizeof(AppleImg3Header); file->seek(file, curPos + sizeof(AppleImg3RootHeader)); header = (AppleImg3RootHeader *) element->header; current = (Img3Element *) element->data; while (current != NULL) { if (current->header->magic == IMG3_SHSH_MAGIC) { header->extra.shshOffset = (uint32_t) (file->tell(file) - sizeof(AppleImg3RootHeader)); } if (current->header->magic != IMG3_KBAG_MAGIC || info->encrypted) { writeImg3Element(file, current, info); } current = current->next; } header->base.dataSize = file->tell(file) - (curPos + sizeof(AppleImg3RootHeader)); header->base.size = sizeof(AppleImg3RootHeader) + header->base.dataSize; file->seek(file, curPos); flipAppleImg3Header(&(header->base)); flipAppleImg3RootExtra(&(header->extra)); file->write(file, header, sizeof(AppleImg3RootHeader)); flipAppleImg3RootExtra(&(header->extra)); flipAppleImg3Header(&(header->base)); file->seek(file, header->base.size); }
Img3Element *readImg3Element(AbstractFile * file) { Img3Element *toReturn; AppleImg3Header *header; off_t curPos; curPos = file->tell(file); header = (AppleImg3Header *) malloc(sizeof(AppleImg3Header)); file->read(file, header, sizeof(AppleImg3Header)); flipAppleImg3Header(header); toReturn = (Img3Element *) malloc(sizeof(Img3Element)); toReturn->header = header; toReturn->next = NULL; switch (header->magic) { case IMG3_MAGIC: readImg3Root(file, toReturn); break; case IMG3_KBAG_MAGIC: toReturn->data = (unsigned char *)malloc(header->dataSize); toReturn->write = writeImg3KBAG; toReturn->free = freeImg3Default; file->read(file, toReturn->data, header->dataSize); flipAppleImg3KBAGHeader((AppleImg3KBAGHeader *) toReturn->data); break; default: { uint32_t sz = header->size - sizeof(AppleImg3Header); /* header->dataSize */ toReturn->data = (unsigned char *)malloc(sz); toReturn->write = writeImg3Default; toReturn->free = freeImg3Default; file->read(file, toReturn->data, sz); } } file->seek(file, curPos + toReturn->header->size); return toReturn; }
static int cryptoMagic(X509 *x0, X509 *x1, X509 *x2, const unsigned char *toHashData, int toHashLength, /*XXX const*/ unsigned char *rsaSigData, int rsaSigLen, DataValue *partialDigest) { int rv = 0; EVP_PKEY *pk = X509_get_pubkey(x2); if (pk) { if (pk->type == EVP_PKEY_RSA) { RSA *rsa = EVP_PKEY_get1_RSA(pk); if (rsa) { X509_STORE *store = X509_STORE_new(); if (store) { X509_STORE_CTX ctx; X509_STORE_add_cert(store, x0); X509_STORE_add_cert(store, x1); if (X509_STORE_CTX_init(&ctx, store, x2, 0) == 1) { X509_STORE_CTX_set_flags(&ctx, X509_V_FLAG_IGNORE_CRITICAL); if (X509_verify_cert(&ctx) == 1) { unsigned char md[SHA_DIGEST_LENGTH]; if (partialDigest) { // XXX we need to flip ECID back before hashing flipAppleImg3Header((AppleImg3Header *)toHashData); doPartialSHA1(md, toHashData, toHashLength, partialDigest); } else { SHA1(toHashData, toHashLength, md); } rv = RSA_verify(NID_sha1, md, SHA_DIGEST_LENGTH, rsaSigData, rsaSigLen, rsa); } X509_STORE_CTX_cleanup(&ctx); } X509_STORE_free(store); } RSA_free(rsa); } } EVP_PKEY_free(pk); } return rv ? 0 : -1; }
static const char * checkBlob(X509 *x0, DataValue *blob, DataValue *partialDigest, uint64_t *savecid) { int rv; X509 *x1, *x2; uint64_t thisecid; unsigned partial0; int len = blob->len; const unsigned char *ptr = blob->value; AppleImg3Header *cert = NULL; AppleImg3Header *ecid = NULL; AppleImg3Header *shsh = NULL; while (len > 0) { AppleImg3Header *hdr; if (len < sizeof(AppleImg3Header)) { return "truncated"; } hdr = (AppleImg3Header *)ptr; flipAppleImg3Header(hdr); // XXX we need to flip ECID back before hashing switch (hdr->magic) { case IMG3_ECID_MAGIC: ecid = (AppleImg3Header *)ptr; break; case IMG3_SHSH_MAGIC: shsh = (AppleImg3Header *)ptr; break; case IMG3_CERT_MAGIC: cert = (AppleImg3Header *)ptr; break; default: return "unknown"; } len -= hdr->size; ptr += hdr->size; } if (!ecid || !shsh || !cert) { return "incomplete"; } partial0 = *(unsigned *)partialDigest->value; FLIPENDIANLE(partial0); if (partial0 != 0x40 || partial0 != ecid->size) { return "internal"; // XXX see doPartialSHA1() } thisecid = getECID(ecid + 1); if (*savecid == 0) { *savecid = thisecid; } if (*savecid != thisecid) { return "mismatch"; } rv = extract2Certs((unsigned char *)(cert + 1), cert->dataSize, &x1, &x2); if (rv) { return "asn1"; } rv = cryptoMagic(x0, x1, x2, (unsigned char *)ecid, ecid->size, (unsigned char *)(shsh + 1), shsh->dataSize, partialDigest); X509_free(x2); X509_free(x1); return rv ? "crypto" : NULL; }