/* throws Exception */ void BlobTest::doRetrieval() { bool passed=false; TIMER_START("Blob Retrieval"); rs.reset(stmt->executeQuery("SELECT blobdata from BLOBTEST LIMIT 1")); rs->next(); TIMER_STOP("Blob Retrieval"); TIMER_START("getString"); String s(rs->getString(1)); TIMER_STOP("getString"); TIMER_START("Blob Check 1"); passed=checkBlob(s); TIMER_STOP("Blob Check 1"); ASSERT_MESSAGE(passed, "Inserted BLOB data did not match retrieved BLOB data for getString()."); s.clear(); TIMER_START("getBlob"); boost::scoped_ptr<std::istream> inStr(rs->getBlob(1)); TIMER_STOP("getBlob"); TIMER_START("Stream Reading"); char buff[1048]; while (!inStr->eof()) { inStr->read(buff, sizeof (buff)); s.append(buff, inStr->gcount()); } TIMER_STOP("Stream Reading"); TIMER_START("Blob Check 2"); passed=checkBlob(s); TIMER_STOP("Blob Check 2"); ASSERT_MESSAGE(passed, "Inserted BLOB data did not match retrieved BLOB data for getBlob()."); /* inStr = rs->getAsciiStream(1); bOut = new ByteArrayOutputStream(); while ((b = inStr.read()) != -1) { bOut.write((byte) b); } retrBytes = bOut.toByteArray(); passed = checkBlob(retrBytes); assertTrue( "Inserted BLOB data did not match retrieved BLOB data for getAsciiStream().", passed); inStr = rs->getUnicodeStream(1); bOut = new ByteArrayOutputStream(); while ((b = inStr.read()) != -1) { bOut.write((byte) b); } retrBytes = bOut.toByteArray(); passed = checkBlob(retrBytes); assertTrue( "Inserted BLOB data did not match retrieved BLOB data for getUnicodeStream().", passed);*/ }
int main(int argc, char* argv[]) { init_libxpwn(&argc, argv); OutputState *outputState; size_t fileLength; AbstractFile *signFile; Dictionary *signDict = NULL; DataValue *ticket; Dictionary *dict; AbstractFile *manifestFile; Dictionary* manifest; struct component_t *array; char *plist; int i, j, n; int rv, error = 0; X509 *x0, *y1, *y2; uint64_t savecid = 0; const unsigned char *p; int verbose = FALSE; int fromzip = FALSE; if (argc < 3) { XLOG(0, "usage %s file.shsh BuildManifest.plist [-v] [-z]\n", argv[0]); return 0; } for (i = 3; i < argc; i++) { if (!strcmp(argv[i], "-v")) { verbose = TRUE; continue; } if (!strcmp(argv[i], "-z")) { fromzip = TRUE; continue; } } // XXX handle gzip/bplist files signFile = createAbstractFileFromFile(fopen(argv[1], "rb")); if (!signFile) { XLOG(0, "FATAL: cannot open %s\n", argv[1]); exit(1); } fileLength = signFile->getLength(signFile); plist = malloc(fileLength); signFile->read(signFile, plist, fileLength); signFile->close(signFile); signDict = createRoot(plist); free(plist); if (!signDict) { XLOG(0, "FATAL: cannot parse %s\n", argv[1]); exit(1); } MaxLoadZipSize = 128 * 1024; if (fromzip) { outputState = loadZip2(argv[2], TRUE); // XXX ASSERT manifestFile = getFileFromOutputState(&outputState, "BuildManifest.plist"); } else { outputState = NULL; manifestFile = createAbstractFileFromFile(fopen(argv[2], "rb")); } if (!manifestFile) { XLOG(0, "FATAL: cannot open %s\n", argv[2]); exit(1); } fileLength = manifestFile->getLength(manifestFile); plist = malloc(fileLength); manifestFile->read(manifestFile, plist, fileLength); manifestFile->close(manifestFile); manifest = createRoot(plist); free(plist); if (!manifest) { XLOG(0, "FATAL: cannot parse %s\n", argv[2]); exit(1); } releaseOutput(&outputState); array = parseManifest(manifest, &n); if (!array) { XLOG(0, "FATAL: cannot parse manifest\n"); exit(1); } OPENSSL_add_all_algorithms_noconf(); p = cerb; x0 = d2i_X509(NULL, &p, cerb_len); if (!x0) { XLOG(0, "FATAL: cannot load root CA\n"); exit(1); } ticket = (DataValue *)getValueByKey(signDict, "APTicket"); if (ticket) { p = ticket->value; rv = asn1_parse2(&p, ticket->len, 0, 0); if (!rv || !apcert.value || !rsasig.value || !theset.value) { XLOG(0, "FATAL: cannot parse ticket\n"); exit(1); } if (clen > 0 && contarray->len == 8) { savecid = getECID(contarray->value); } if (!savecid) { printf("ERROR: bad, bad ECID\n"); error = 1; } rv = extract2Certs(apcert.value, apcert.len, &y1, &y2); if (rv == 0) { rv = cryptoMagic(x0, y1, y2, theset.value, theset.len, (unsigned char *)rsasig.value, rsasig.len, NULL); X509_free(y1); X509_free(y2); } if (rv) { printf("ERROR: APTicket failed crypto\n"); error = 1; } } else { VERBOSE("WARNING: cannot find ticket in %s\n", argv[1]); } dict = (Dictionary *)signDict->values; while (dict) { DataValue *blob = NULL; DataValue *partialDigest = NULL; if (dict->dValue.type == DictionaryType) { blob = (DataValue *)getValueByKey(dict, "Blob"); partialDigest = (DataValue *)getValueByKey(dict, "PartialDigest"); } if (blob && partialDigest) { const char *diag = checkBlob(x0, blob, partialDigest, &savecid); if (diag) { printf("ERROR: Blob for %s is invalid (%s)\n", dict->dValue.key, diag); error = 1; } else { for (i = 0; i < n; i++) { struct component_t *centry = array + i; if (centry->partial && partialDigest->len == centry->partial->len && !memcmp(partialDigest->value, centry->partial->value, partialDigest->len)) { array[i].blob = blob; } } } } dict = (Dictionary *)dict->dValue.next; } if (!ticket && !savecid) { printf("ERROR: bad, bad ECID\n"); error = 1; } for (i = 0; i < n; i++) { struct component_t *centry = array + i; int found = FALSE; for (j = 0; j < clen; j++) { struct tuple_t *tentry = contarray + j; if (tentry->len == centry->digest->len && !memcmp(tentry->value, centry->digest->value, tentry->len)) { found = TRUE; } } if (!found) { if (centry->blob) { VERBOSE("WARNING: no digest for %s (%s), but it has blob\n", centry->key, centry->path); } else if (!centry->required) { VERBOSE("WARNING: no digest for %s (%s), but it is not critical\n", centry->key, centry->path); } else { printf("ERROR: no digest for %s (%s) and no blob found\n", centry->key, centry->path); error = 1; } } else { VERBOSE("INFO: %s (%s) is signed by APTicket%s\n", centry->key, centry->path, centry->blob ? " and blob" : ""); } } free(array); free(contarray); releaseDictionary(manifest); releaseDictionary(signDict); if (error) { printf("%s is BROKEN\n", argv[1]); } else { printf("%s seems usable for ECID 0x%016llX\n", argv[1], savecid); } X509_free(x0); EVP_cleanup(); ERR_remove_state(0); CRYPTO_cleanup_all_ex_data(); return error; }