int DERImg4Decode(const DERItem *a1, DERItem *a2) { int rv; DERDecodedInfo var_38; if (a1 == NULL || a2 == NULL) { return DR_ParamErr; } rv = DERDecodeItem(a1, &var_38); if (rv) { return rv; } if (var_38.tag != ASN1_CONSTR_SEQUENCE) { return DR_UnexpectedTag; } if (a1->data + a1->length != var_38.content.data + var_38.content.length) { return DR_BufOverflow; } rv = DERParseSequenceContent(&var_38.content, 4, DERImg4ItemSpecs, a2, 0); if (rv) { return rv; } if (DERImg4DecodeTagCompare(a2, 'IMG4')) { return DR_UnexpectedTag; } return 0; }
int DERDecodeTimeStampResponse( const CSSM_DATA *contents, CSSM_DATA *derStatus, CSSM_DATA *derTimeStampToken, size_t *numUsedBytes) /* RETURNED */ { DERReturn drtn = DR_ParamErr; DERDecodedInfo decodedPackage; if (contents) { DERItem derContents = {.data = contents->Data, .length = contents->Length }; DERTimeStampResp derResponse = {{0,},{0,}}; DERReturn rx; require_noerr(DERDecodeItem(&derContents, &decodedPackage), badResponse); rx = DERParseSequenceContent(&decodedPackage.content, DERNumTimeStampRespItemSpecs, DERTimeStampRespItemSpecs, &derResponse, 0); if (rx != DR_Success) goto badResponse; /* require_noerr(DERParseSequenceContent(&decodedPackage.content, DERNumTimeStampRespItemSpecs, DERTimeStampRespItemSpecs, &derResponse, 0), badResponse); */ if (derStatus && derResponse.status.data) { derStatus->Data = malloc(derResponse.status.length); derStatus->Length = derResponse.status.length; memcpy(derStatus->Data, derResponse.status.data, derStatus->Length); } if (derTimeStampToken && derResponse.timeStampToken.data) { derTimeStampToken->Data = malloc(derResponse.timeStampToken.length); derTimeStampToken->Length = derResponse.timeStampToken.length; memcpy(derTimeStampToken->Data, derResponse.timeStampToken.data, derTimeStampToken->Length); } } drtn = DR_Success; badResponse: if (numUsedBytes) *numUsedBytes = decodedPackage.content.length + decodedPackage.content.data - contents->Data; return drtn; }
static void printValidity( DERItem *validity, int verbose) { DERReturn drtn; DERValidity derv; drtn = DERParseSequenceContent(validity, DERNumValidityItemSpecs, DERValidityItemSpecs, &derv, sizeof(derv)); if(drtn) { DERPerror("DERParseSequenceContent(validity)", drtn); return; } decodePrintItem("notBefore", IT_Leaf, verbose, &derv.notBefore); decodePrintItem("notAfter", IT_Leaf, verbose, &derv.notAfter); }
/* * This is a SEQUENCE OF so we use the low-level DERDecodeSeq* routines to snag one entry * at a time. */ static void printRevokedCerts( DERItem *revokedCerts, int verbose) { DERReturn drtn; DERDecodedInfo currItem; DERSequence seq; unsigned certNum; DERRevokedCert revoked; drtn = DERDecodeSeqContentInit(revokedCerts, &seq); if(drtn) { DERPerror("DERDecodeSeqContentInit(revokedCerts)", drtn); return; } for(certNum=0; ; certNum++) { drtn = DERDecodeSeqNext(&seq, &currItem); switch(drtn) { case DR_EndOfSequence: /* normal termination */ return; default: DERPerror("DERDecodeSeqNext", drtn); return; case DR_Success: doIndent(); printf("revoked cert %u\n", certNum); incrIndent(); drtn = DERParseSequenceContent(&currItem.content, DERNumRevokedCertItemSpecs, DERRevokedCertItemSpecs, &revoked, sizeof(revoked)); if(drtn) { DERPerror("DERParseSequenceContent(RevokedCert)", drtn); decrIndent(); return; } printItem("serialNum", IT_Leaf, verbose, ASN1_INTEGER, &revoked.serialNum); decodePrintItem("revocationDate", IT_Leaf, verbose, &revoked.revocationDate); printItem("extensions", IT_Branch, verbose, ASN1_CONSTR_SEQUENCE, &revoked.extensions); decrIndent(); } } }
void printAlgId( const DERItem *content, int verbose) { DERReturn drtn; DERAlgorithmId algId; drtn = DERParseSequenceContent(content, DERNumAlgorithmIdItemSpecs, DERAlgorithmIdItemSpecs, &algId, sizeof(algId)); if(drtn) { DERPerror("DERParseSequenceContent(algId)", drtn); return; } printItem("alg", IT_Leaf, verbose, ASN1_OBJECT_ID, &algId.oid); if(algId.params.data) { printItem("params", IT_Leaf, verbose, algId.params.data[0], &algId.params); } }
/* * High level sequence parse, starting with top-level tag and content. * Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's * OK, use DERParseSequenceContent(). */ DERReturn DERParseSequenceOf( const DERItem *der, DERShort numItems, /* size of itemSpecs[] */ const DERItemSpec *itemSpecs, void *dest, /* DERDecodedInfo(s) here RETURNED */ DERSize *numDestItems) /* output */ { DERReturn drtn; DERDecodedInfo topDecode; drtn = DERDecodeItem(der, &topDecode); if(drtn) { return drtn; } if(topDecode.tag != ASN1_CONSTR_SEQUENCE) { return DR_UnexpectedTag; } return DERParseSequenceContent(&topDecode.content, numItems, itemSpecs, dest, sizeToZero); }
int main(int argc, char **argv) { int rv; const char *what; const char *filename; const char *outname; TheImg4 *img4; unsigned type; unsigned written; unsigned char ivkey[16 + 32]; unsigned char *iv = NULL, *key = NULL; unsigned char *output = NULL; unsigned outlen = 0; int outdup = 0; DERItem item; unsigned char *data; size_t size; if (argc < 4) { fprintf(stderr, "usage: %s {-image|-extra|-keybag|-ticket} input output [ivkey]\n", argv[0]); return 1; } what = argv[1]; filename = argv[2]; outname = argv[3]; if (argc > 4) { rv = str2hex(sizeof(ivkey), ivkey, argv[4]); if (rv == sizeof(ivkey)) { iv = ivkey; key = ivkey + 16; } } data = read_file(filename, 0, &size); if (data == NULL) { fprintf(stderr, "[e] cannot read '%s'\n", filename); return -1; } img4 = parse(data, size); if (!img4) { fprintf(stderr, "[e] cannot parse '%s'\n", filename); free(data); return -1; } rv = Img4DecodeGetPayloadType(img4, &type); if (rv) { fprintf(stderr, "[e] cannot identify '%s'\n", filename); goto err; } printf("%c%c%c%c\n", FOURCC(type)); if (!strncmp(what, "-i", 2) || !strncmp(what, "-e", 2)) { int decompress; rv = Img4DecodeGetPayload(img4, &item); if (rv) { fprintf(stderr, "[e] cannot extract payload from '%s'\n", filename); goto err; } output = item.data; outlen = item.length; if (iv && key) { if (outlen & 15) { unsigned usize = (outlen + 15) & ~15; unsigned char *tmp = calloc(1, usize); if (!tmp) { fprintf(stderr, "[e] out of memory %u\n", usize); goto err; } memcpy(tmp, output, outlen); OUTSET(tmp); } rv = Img4DecodeGetPayloadKeybag(img4, &item); if (rv || item.length == 0) { fprintf(stderr, "[w] image '%s' has no keybag\n", filename); } #ifdef USE_CORECRYPTO cccbc_one_shot(ccaes_cbc_decrypt_mode(), 32, key, iv, (outlen + 15) / 16, output, output); #else AES_KEY decryptKey; AES_set_decrypt_key(key, 256, &decryptKey); AES_cbc_encrypt(output, output, (outlen + 15) & ~15, &decryptKey, iv, AES_DECRYPT); #endif } #ifdef iOS10 if (img4->payload.compression.data && img4->payload.compression.length) { DERItem tmp[2]; uint32_t deco = 0; uint64_t usize = 0; if (DERParseSequenceContent(&img4->payload.compression, 2, DERImg4PayloadItemSpecs10c, tmp, 0) || DERParseInteger(&tmp[0], &deco) || DERParseInteger64(&tmp[1], &usize)) { fprintf(stderr, "[e] cannot get decompression info\n"); goto err; } if (deco == 1 && what[1] == 'i') { size_t asize = lzfse_decode_scratch_size(); unsigned char *dec, *aux = malloc(asize); if (!aux) { fprintf(stderr, "[e] out of memory %zu\n", asize); goto err; } dec = malloc(usize + 1); if (!dec) { fprintf(stderr, "[e] out of memory %llu\n", usize + 1); free(aux); goto err; } outlen = lzfse_decode_buffer(dec, usize + 1, output, outlen, aux); free(aux); if (outlen != usize) { fprintf(stderr, "[e] decompression error\n"); free(dec); goto err; } OUTSET(dec); } } #endif decompress = (DWORD_BE(output, 0) == 'comp' && DWORD_BE(output, 4) == 'lzss'); if (decompress && what[1] == 'i') { uint32_t csize = DWORD_BE(output, 16); uint32_t usize = DWORD_BE(output, 12); uint32_t adler = DWORD_BE(output, 8); unsigned char *dec = malloc(usize); if (outlen > 0x180 + csize) { fprintf(stderr, "[i] extra 0x%x bytes after compressed chunk\n", outlen - 0x180 - csize); } if (!dec) { fprintf(stderr, "[e] out of memory %u\n", usize); goto err; } outlen = decompress_lzss(dec, output + 0x180, csize); if (adler != lzadler32(dec, outlen)) { fprintf(stderr, "[w] adler32 mismatch\n"); } OUTSET(dec); } else if (decompress) { uint32_t csize = DWORD_BE(output, 16); uint32_t usize = outlen - 0x180 - csize; if (outlen > 0x180 + csize) { unsigned char *dec = malloc(usize); if (!dec) { fprintf(stderr, "[e] out of memory %u\n", usize); goto err; } memcpy(dec, output + 0x180 + csize, usize); outlen = usize; OUTSET(dec); } else { OUTSET(NULL); } } else if (what[1] == 'e') { OUTSET(NULL); } if (!output) { fprintf(stderr, "[e] nothing to do\n"); goto err; } } if (!strncmp(what, "-k", 2)) { rv = Img4DecodeGetPayloadKeybag(img4, &item); if (rv == 0 && item.length) { output = item.data; outlen = item.length; } else { fprintf(stderr, "[e] image '%s' has no keybag\n", filename); goto err; } } if (!strncmp(what, "-t", 2)) { bool exists = false; rv = Img4DecodeManifestExists(img4, &exists); if (rv == 0 && exists) { output = img4->manifestRaw.data; outlen = img4->manifestRaw.length; } else { fprintf(stderr, "[e] image '%s' has no ticket\n", filename); goto err; } } written = write_file(outname, output, outlen); if (written != outlen) { fprintf(stderr, "[e] cannot write '%s'\n", outname); goto err; } rv = 0; out: if (outdup) { free(output); } free(img4); free(data); return rv; err: rv = -1; goto out; }
/* * Given a SSLCertificate cert, obtain its public key as a SSLPubKey. * Caller must sslFreePubKey and free the SSLPubKey itself. */ OSStatus sslPubKeyFromCert( SSLContext *ctx, const SSLCertificate *cert, SSLPubKey **pubKey) // RETURNED { DERItem der; DERSignedCertCrl signedCert; DERTBSCert tbsCert; DERSubjPubKeyInfo pubKeyInfo; DERByte numUnused; DERItem pubKeyPkcs1; SSLPubKey *key; DERReturn drtn; RSAStatus rsaStatus; assert(cert); assert(pubKey != NULL); der.data = cert->derCert.data; der.length = cert->derCert.length; /* top level decode */ drtn = DERParseSequence(&der, DERNumSignedCertCrlItemSpecs, DERSignedCertCrlItemSpecs, &signedCert, sizeof(signedCert)); if(drtn) return errSSLBadCert; /* decode the TBSCert - it was saved in full DER form */ drtn = DERParseSequence(&signedCert.tbs, DERNumTBSCertItemSpecs, DERTBSCertItemSpecs, &tbsCert, sizeof(tbsCert)); if(drtn) return errSSLBadCert; /* sequence we're given: encoded DERSubjPubKeyInfo */ drtn = DERParseSequenceContent(&tbsCert.subjectPubKey, DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs, &pubKeyInfo, sizeof(pubKeyInfo)); if(drtn) return errSSLBadCert; /* @@@ verify that this is an RSA key by decoding the AlgId */ /* * The contents of pubKeyInfo.pubKey is a bit string whose contents * are a PKCS1 format RSA key. */ drtn = DERParseBitString(&pubKeyInfo.pubKey, &pubKeyPkcs1, &numUnused); if(drtn) return errSSLBadCert; #if TARGET_OS_IOS /* Now we have the public key in pkcs1 format. Let's make a public key object out of it. */ key = sslMalloc(sizeof(*key)); rsaStatus = RSA_DecodePubKey(pubKeyPkcs1.data, pubKeyPkcs1.length, &key->rsaKey); if (rsaStatus) { sslFree(key); } #else SecKeyRef rsaPubKeyRef = SecKeyCreateRSAPublicKey(NULL, pubKeyPkcs1.data, pubKeyPkcs1.length, kSecKeyEncodingRSAPublicParams); rsaStatus = (rsaPubKeyRef) ? 0 : 1; key = (SSLPubKey*)rsaPubKeyRef; #endif if (rsaStatus) { return rsaStatusToSSL(rsaStatus); } *pubKey = key; return noErr; }