static int p12MacParse( const NSS_P12_MacData &macData, P12ParseInfo &pinfo, unsigned depth) // print indent depth { if(p12AlgIdParse(macData.mac.digestAlgorithm, NULL, pinfo, depth)) { return 1; } doIndent(depth); printf("Digest : "); printDataAsHex(&macData.mac.digest, 20); doIndent(depth); printf("Salt : "); printDataAsHex(&macData.macSalt, 16); const CSSM_DATA &iter = macData.iterations; if(iter.Length > 4) { doIndent(depth); printf("***Warning: malformed iteraton length (%u)\n", (unsigned)iter.Length); } unsigned i = dataToInt(iter); doIndent(depth); printf("Iterations = %u\n", i); return 0; }
void displayTSTInfo(SecAsn1TSATSTInfo *tstInfo) { #ifndef NDEBUG dtprintf("--- TSTInfo ---\n"); if (!tstInfo) return; if (tstInfo->version.Data) { uint64_t vers = tsaDER_ToInt(&tstInfo->version); dtprintf("Version:\t\t%u\n", (int)vers); } if (tstInfo->serialNumber.Data) { uint64_t sn = tsaDER_ToInt(&tstInfo->serialNumber); dtprintf("SerialNumber:\t%llu\n", sn); } if (tstInfo->ordering.Data) { uint64_t ord = tsaDER_ToInt(&tstInfo->ordering); dtprintf("Ordering:\t\t%s\n", ord?"yes":"no"); } if (tstInfo->nonce.Data) { uint64_t nonce = tsaDER_ToInt(&tstInfo->nonce); dtprintf("Nonce:\t\t%llu\n", nonce); } else dtprintf("Nonce:\t\tnot specified\n"); if (tstInfo->genTime.Data) { char buf[tstInfo->genTime.Length+1]; memcpy(buf, (const char *)tstInfo->genTime.Data, tstInfo->genTime.Length); buf[tstInfo->genTime.Length]=0; dtprintf("GenTime:\t\t%s\n", buf); } dtprintf("-- MessageImprint --\n"); if (true) // SecAsn1TSAMessageImprint { printDataAsHex(" Algorithm:",&tstInfo->messageImprint.hashAlgorithm.algorithm, 0); printDataAsHex(" Message :", &tstInfo->messageImprint.hashedMessage, 0);//tstInfo->messageImprint.hashedMessage.Length); } #endif }
/* * Parse a NSS_P7_EncryptedData - specifically in the context * of a P12 in password privacy mode. (The latter assumption is * to enable us to infer CSSM_X509_ALGORITHM_IDENTIFIER.parameters * format). */ static int encryptedDataParse( const NSS_P7_EncryptedData &edata, P12ParseInfo &pinfo, NSS_P12_PBE_Params *pbep, // optional, RETURNED unsigned depth) // print indent depth { doIndent(depth); printf("version = %u\n", (unsigned)dataToInt(edata.version)); const NSS_P7_EncrContentInfo &ci = edata.contentInfo; doIndent(depth); printf("contentType = %s\n", oidStr(ci.contentType, pinfo.mParser)); /* * Parse the alg ID, safe PBE params for when we do the * key unwrap */ const CSSM_X509_ALGORITHM_IDENTIFIER &algId = ci.encrAlg; if(p12AlgIdParse(algId, pbep, pinfo, depth)) { return 1; } doIndent(depth); printf("encrContent : "); printDataAsHex(&ci.encrContent, 12); return 0; }
static int attrParse( const NSS_Attribute *attr, P12ParseInfo &pinfo, unsigned depth) { doIndent(depth); printf("attrType : %s\n", oidStr(attr->attrType, pinfo.mParser)); unsigned numVals = nssArraySize((const void **)attr->attrValue); doIndent(depth); printf("numValues = %u\n", numVals); for(unsigned dex=0; dex<numVals; dex++) { doIndent(depth); printf("val[%u] : ", dex); /* * Note: these two enumerated types should only have one att value * per PKCS9. Leave that to real apps, we want to see what's there * in any case. */ if(nssCompareCssmData(&attr->attrType, &CSSMOID_PKCS9_FriendlyName)) { /* BMP string (UniCode) */ CSSM_DATA ustr; if(pinfo.mCoder.decodeItem(*attr->attrValue[dex], kSecAsn1BMPStringTemplate, &ustr)) { printf("***Error decoding BMP string\n"); continue; } printDataAsUnichars(ustr); } else if(nssCompareCssmData(&attr->attrType, &CSSMOID_PKCS9_LocalKeyId)) { /* Octet string */ CSSM_DATA ostr; if(pinfo.mCoder.decodeItem(*attr->attrValue[dex], kSecAsn1ObjectIDTemplate, &ostr)) { printf("***Error decoding LocalKeyId string\n"); continue; } printDataAsHex(&ostr, 16); } else { printDataAsHex(attr->attrValue[dex], 8); } } return 0; }
/* * Parse an CSSM_X509_ALGORITHM_IDENTIFIER specific to P12. * Decode the alg params as a NSS_P12_PBE_Params and parse and * return the result if the pbeParams is non-NULL. */ static int p12AlgIdParse( const CSSM_X509_ALGORITHM_IDENTIFIER &algId, NSS_P12_PBE_Params *pbeParams, // optional P12ParseInfo &pinfo, unsigned depth) // print indent depth { doIndent(depth); printf("encrAlg = %s\n", oidStr(algId.algorithm, pinfo.mParser)); const CSSM_DATA ¶m = algId.parameters; if(pbeParams == NULL) { /* alg params are uninterpreted */ doIndent(depth); printf("Alg Params : "); printDataAsHex(¶m); return 0; } if(param.Length == 0) { printf("===warning: no alg parameters, this is not optional\n"); return 0; } memset(pbeParams, 0, sizeof(*pbeParams)); if(pinfo.mCoder.decodeItem(param, NSS_P12_PBE_ParamsTemplate, pbeParams)) { printf("***Error decoding NSS_P12_PBE_Params\n"); return 1; } doIndent(depth); printf("Salt : "); printDataAsHex(&pbeParams->salt); doIndent(depth); if(pbeParams->iterations.Length > 4) { printf("warning: iterations greater than max int\n"); doIndent(depth); printf("Iterations : "); printDataAsHex(&pbeParams->iterations); } else { printf("Iterations : %u\n", (unsigned)dataToInt(pbeParams->iterations)); } return 0; }
static void dumpCertID( SecAsn1OCSPCertID *certID, int indent) { doIndent(indent); printf("algId : "); printDataAsHex(&certID->algId.algorithm); doIndent(indent); printf("issuerNameHash : "); printDataAsHex(&certID->issuerNameHash); doIndent(indent); printf("issuerPubKeyHash : "); printDataAsHex(&certID->issuerPubKeyHash); doIndent(indent); printf("serialNumber : "); printDataAsHex(&certID->serialNumber); }
static void printTaggedItem( const NSS_TaggedItem &ti) { switch(ti.tag) { case BER_TAG_PRINTABLE_STRING: case BER_TAG_T61_STRING: case BER_TAG_IA5_STRING: case BER_TAG_UTC_TIME: case BER_TAG_GENERALIZED_TIME: printString(&ti.item); break; default: printDataAsHex(&ti.item, 0); } }
static void debugShowContentTypeOID(SecCmsContentInfoRef contentInfo) { #ifndef NDEBUG CSSM_OID *typeOID = SecCmsContentInfoGetContentTypeOID(contentInfo); if (typeOID) { CFStringRef oidCFStr = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, typeOID); char *oidstr = cfStringToChar(oidCFStr); printDataAsHex("oid:", typeOID, (unsigned int)typeOID->Length); dtprintf("\toid: %s\n", oidstr); if (oidCFStr) CFRelease(oidCFStr); if (oidstr) free(oidstr); } #endif }
/* * ShroudedKeyBag parser w/decrypt */ static int shroudedKeyBagParse( const NSS_P12_ShroudedKeyBag *keyBag, P12ParseInfo &pinfo, unsigned depth) { const CSSM_X509_ALGORITHM_IDENTIFIER &algId = keyBag->algorithm; NSS_P12_PBE_Params pbep; if(p12AlgIdParse(algId, &pbep, pinfo, depth)) { return 1; } if(pinfo.mPwd.Data == NULL) { doIndent(depth); printf("=== Key not decrypted (no passphrase)===\n"); return 0; } /* * Prepare for decryption */ CSSM_ALGORITHMS keyAlg; // e.g., CSSM_ALGID_DES CSSM_ALGORITHMS encrAlg; // e.g., CSSM_ALGID_3DES_3KEY_EDE CSSM_ALGORITHMS pbeHashAlg; // SHA1 or MD5 uint32 keySizeInBits; uint32 blockSizeInBytes; // for IV, optional CSSM_PADDING padding; // CSSM_PADDING_PKCS7, etc. CSSM_ENCRYPT_MODE mode; // CSSM_ALGMODE_CBCPadIV8, etc. #if IMPORT_EXPORT_COMPLETE PKCS_Which pkcs; bool found = pkcsOidToParams(&algId.algorithm, keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, padding, mode, pkcs); #else bool found = pkcsOidToParams(&algId.algorithm, keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, padding, mode); #endif if(!found) { printf("***ShroudedKeyBag encrAlg not understood\n"); return 1; } unsigned iterCount = dataToInt(pbep.iterations); CSSM_DATA berPrivKey; /* decrypt, result is BER encoded private key */ CSSM_RETURN crtn = p12Decrypt_app(pinfo.mCspHand, keyBag->encryptedData, keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes, padding, mode, iterCount, pbep.salt, pinfo.mPwd, pinfo.mCoder, berPrivKey); if(crtn) { doIndent(depth); printf("***Error decrypting private key\n"); return 1; } /* decode */ NSS_PrivateKeyInfo privKey; memset(&privKey, 0, sizeof(privKey)); if(pinfo.mCoder.decodeItem(berPrivKey, kSecAsn1PrivateKeyInfoTemplate, &privKey)) { doIndent(depth); printf("***Error decoding decrypted private key\n"); return 1; } /* * in P12 library, we'd convert the result into a CSSM_KEY * or a SecItem... */ CSSM_X509_ALGORITHM_IDENTIFIER &privAlg = privKey.algorithm; doIndent(depth); printf("Priv Key Alg : %s\n", oidStr(privAlg.algorithm, pinfo.mParser)); doIndent(depth); printf("Priv Key Blob : "); printDataAsHex(&privKey.privateKey, 16); unsigned numAttrs = nssArraySize((const void**)privKey.attributes); if(numAttrs) { doIndent(depth+3); printf("numAttrs = %u\n", numAttrs); for(unsigned i=0; i<numAttrs; i++) { doIndent(depth+3); printf("attr[%u]:\n", i); attrParse(privKey.attributes[i], pinfo, depth+6); } } return 0; }
static int parseOcspResp( CSSM_CL_HANDLE clHand, unsigned char *inFile, unsigned inFileLen, bool verbose) { SecAsn1OCSPResponse topResp; SecAsn1CoderRef coder; OSStatus ortn; int indent = 0; const char *str; SecAsn1OCSPBasicResponse basicResp; unsigned numCerts = 0; SecAsn1CoderCreate(&coder); memset(&topResp, 0, sizeof(topResp)); ortn = SecAsn1Decode(coder, inFile, inFileLen, kSecAsn1OCSPResponseTemplate, &topResp); if(ortn) { printf("***Error decoding SecAsn1OCSPResponse\n"); goto errOut; } printf("OCSPResponse:\n"); indent += 2; doIndent(indent); printf("responseStatus: "); if(topResp.responseStatus.Length == 0) { printf("**MALFORMED**\n"); } else { switch(topResp.responseStatus.Data[0]) { case RS_Success: str = "RS_Success"; break; case RS_MalformedRequest: str = "RS_MalformedRequest"; break; case RS_InternalError: str = "RS_InternalError"; break; case RS_TryLater: str = "RS_TryLater"; break; case RS_Unused: str = "RS_Unused"; break; case RS_SigRequired: str = "RS_SigRequired"; break; case RS_Unauthorized: str = "RS_Unauthorized"; break; default: str = "MALFORMED (unknown enum)\n"; break; } printf("%s (%u(d))\n", str, topResp.responseStatus.Data[0]); } doIndent(indent); printf("ResponseBytes: "); if(topResp.responseBytes == NULL) { printf("empty\n"); goto errOut; } printf("\n"); indent += 2; doIndent(indent); printf("responseType: "); if(appCompareCssmData(&topResp.responseBytes->responseType, &CSSMOID_PKIX_OCSP_BASIC)) { str = "ocsp-basic"; } else { str = "Unknown type\n"; } printf("%s\n", str); /* decode the BasicOCSPResponse */ memset(&basicResp, 0, sizeof(basicResp)); ortn = SecAsn1DecodeData(coder, &topResp.responseBytes->response, kSecAsn1OCSPBasicResponseTemplate, &basicResp); if(ortn) { printf("***Error decoding BasicOCSPResponse\n"); goto errOut; } doIndent(indent); printf("BasicOCSPResponse:\n"); indent += 2; doIndent(indent); printf("ResponseData:\n"); parseResponseData(coder, indent + 2, basicResp.tbsResponseData); doIndent(indent); printf("sig: "); printDataAsHex(&basicResp.sig, 8); numCerts = ocspdArraySize((const void **)basicResp.certs); doIndent(indent); printf("Num Certs: %u\n", numCerts); if(verbose) { for(unsigned dex=0; dex<numCerts; dex++) { printf("+++++++++++++++++++++++++ Cert %u +++++++++++++++++++++++++\n", dex); printCert(basicResp.certs[dex]->Data, basicResp.certs[dex]->Length, CSSM_FALSE); printf("+++++++++++++++++++++++ End Cert %u +++++++++++++++++++++++\n", dex); } } indent -= 2; // end of BasicOCSPResponse indent -= 2; // end of ResponseBytes indent -= 2; // end of OCSPResponse errOut: SecAsn1CoderRelease(coder); return ortn; }
/* decode and parse tbsResponseData, sitting in SecAsn1OCSPBasicResponse as an * ASN_ANY */ static int parseResponseData( SecAsn1CoderRef coder, int indent, const CSSM_DATA &tbsResponseData) { SecAsn1OCSPResponseData respData; SecAsn1OCSPResponderID responderID; uint8 tag; const SecAsn1Template *templ; unsigned numExts; memset(&respData, 0, sizeof(respData)); OSStatus ortn = SecAsn1DecodeData(coder, &tbsResponseData, kSecAsn1OCSPResponseDataTemplate, &respData); if(ortn) { printf("***Error decoding ResponseData\n"); return 1; } if(respData.version && respData.version->Data) { doIndent(indent); printf("version: %u\n", respData.version->Data[0]); } doIndent(indent); printf("ResponderID:\n"); indent += 2; memset(&responderID, 0, sizeof(responderID)); if(respData.responderID.Data == NULL) { doIndent(indent); printf("***Malformed(empty)***\n"); return 1; } /* lame-o choice processing */ tag = respData.responderID.Data[0] & SEC_ASN1_TAGNUM_MASK; switch(tag) { case RIT_Name: templ = kSecAsn1OCSPResponderIDAsNameTemplate; break; case RIT_Key: templ = kSecAsn1OCSPResponderIDAsKeyTemplate; break; default: doIndent(indent); printf("**Unknown tag for ResponderID (%u)\n", tag); return 1; } ortn = SecAsn1DecodeData(coder, &respData.responderID, templ, &responderID); if(ortn) { doIndent(indent); printf("***Error decoding ResponderID\n"); return 1; } doIndent(indent); switch(tag) { case RIT_Name: printf("byName:\n"); printName((NSS_Name &)responderID.byName, indent + 2); break; case RIT_Key: printf("byKey : "); printDataAsHex(&responderID.byKey); break; } indent -= 2; // end of ResponderID doIndent(indent); printf("producedAt: "); printString(&respData.producedAt); unsigned numResps = ocspdArraySize((const void **)respData.responses); doIndent(indent); printf("Num responses: %u\n", numResps); for(unsigned dex=0; dex<numResps; dex++) { SecAsn1OCSPSingleResponse *resp = respData.responses[dex]; doIndent(indent); printf("Response %u:\n", dex); indent += 2; doIndent(indent); printf("CertID:\n"); dumpCertID(&resp->certID, indent + 2); doIndent(indent); printf("certStatus: "); /* lame-o choice processing */ tag = resp->certStatus.Data[0] & SEC_ASN1_TAGNUM_MASK; switch(tag) { case CS_Good: printf("Good\n"); break; case CS_Unknown: printf("Unknown\n"); break; default: printf("**MALFORMED cert status tag (%u)\n", tag); break; case CS_Revoked: { printf("Revoked\n"); doIndent(indent); SecAsn1OCSPCertStatus certStatus; memset(&certStatus, 0, sizeof(certStatus)); ortn = SecAsn1DecodeData(coder, &resp->certStatus, kSecAsn1OCSPCertStatusRevokedTemplate, &certStatus); if(ortn) { doIndent(indent); printf("***error parsing RevokedInfo\n"); break; } if(certStatus.revokedInfo == NULL) { doIndent(indent); printf("***GAK! Malformed (empty) revokedInfo\n");break; } printf("RevokedIndfo:\n"); indent += 2; doIndent(indent); printf("revocationTime: "); printString(&certStatus.revokedInfo->revocationTime); if(certStatus.revokedInfo->revocationReason) { doIndent(indent); printf("reason: %u\n", certStatus.revokedInfo->revocationReason->Data[0]); } indent -= 2; // end of RevokedInfo break; } } /* switch cert status tag */ doIndent(indent); printf("thisUpdate: "); printString(&resp->thisUpdate); if(resp->nextUpdate) { doIndent(indent); printf("nextUpdate: "); printString(resp->nextUpdate); } numExts = ocspdArraySize((const void **)resp->singleExtensions); for(unsigned extDex=0; extDex<numExts; extDex++) { doIndent(indent); printf("singleExtensions[%u]\n", extDex); printOcspExt(coder, resp->singleExtensions[extDex], indent + 2); } indent -= 2; // end of resp[dex] } numExts = ocspdArraySize((const void **)respData.responseExtensions); for(unsigned extDex=0; extDex<numExts; extDex++) { doIndent(indent); printf("responseExtensions[%u]\n", extDex); printOcspExt(coder, respData.responseExtensions[extDex], indent + 2); } return 0; }
static int parseOcspReq( CSSM_CL_HANDLE clHand, unsigned char *inFile, unsigned inFileLen, bool verbose) { SecAsn1CoderRef coder; SecAsn1OCSPSignedRequest signedReq; SecAsn1OCSPTbsRequest &tbs = signedReq.tbsRequest; OSStatus ortn; int indent; unsigned numExts; unsigned numReqs; SecAsn1CoderCreate(&coder); memset(&signedReq, 0, sizeof(signedReq)); ortn = SecAsn1Decode(coder, inFile, inFileLen, kSecAsn1OCSPSignedRequestTemplate, &signedReq); if(ortn) { printf("***Error decoding SecAsn1OCSPSignedRequest\n"); goto errOut; } printf("SecAsn1OCSPSignedRequest:\n"); printf("SecAsn1OCSPTbsRequest:\n"); indent = 2; if(tbs.version) { doIndent(indent); printf("Version : "); printDataAsHex(tbs.version); } if(tbs.requestorName) { doIndent(indent); printf("NSS_GeneralName found; print it later maybe\n"); } numReqs = ocspdArraySize((const void **)tbs.requestList); for(unsigned dex=0; dex<numReqs; dex++) { SecAsn1OCSPRequest *req = tbs.requestList[dex]; doIndent(indent); printf("Request List Entry %u\n", dex); indent += 2; doIndent(indent); printf("CertID:\n"); indent += 2; SecAsn1OCSPCertID *certID = &req->reqCert; dumpCertID(certID, indent); indent -= 2; numExts = ocspdArraySize((const void **)req->extensions); for(unsigned extDex=0; extDex<numExts; extDex++) { doIndent(indent); printf("singleExtension[%u]\n", extDex); printOcspExt(coder, req->extensions[dex], indent + 2); } indent -= 2; } numExts = ocspdArraySize((const void **)tbs.requestExtensions); for(unsigned extDex=0; extDex<numExts; extDex++) { doIndent(indent); printf("requestExtension[%u]\n", extDex); printOcspExt(coder, tbs.requestExtensions[extDex], indent + 2); } indent -= 2; if(signedReq.signature) { printf("SecAsn1OCSPSignature:\n"); indent += 2; doIndent(indent); printf("==unparsed for now ==\n"); /* ... */ indent -= 2; } errOut: SecAsn1CoderRelease(coder); return ortn; }
static void printOcspExt( SecAsn1CoderRef coder, NSS_CertExtension *nssExt, int indent) { OCSPExtension *ocspExt = NULL; try { ocspExt = OCSPExtension::createFromNSS(coder, *nssExt); } catch(...) { doIndent(indent); printf("***Error thrown parsing extension\n"); return; } switch(ocspExt->tag()) { case OET_Unknown: doIndent(indent); printf("Extension type: Unknown\n"); printCritical(indent, ocspExt); return; case OET_Nonce: { doIndent(indent); printf("Extension type : Nonce\n"); printCritical(indent, ocspExt); doIndent(indent); OCSPNonce *nonce = dynamic_cast<OCSPNonce *>(ocspExt); if(nonce == NULL) { printf("***dynamic_cast failure in OCSPNonce!\n"); return; } printf("nonce value : "); printDataAsHex(&nonce->nonce()); break; } case OET_CrlReference: doIndent(indent); printf("Extension type : CrlReference"); printCritical(indent, ocspExt); /* TBD */ return; case OET_AcceptResponse: doIndent(indent); printf("Extension type : AcceptResponse"); printCritical(indent, ocspExt); /* TBD */ return; case OET_ArchiveCutoff: doIndent(indent); printf("Extension type : ArchiveCutoff"); printCritical(indent, ocspExt); /* TBD */ return; case OET_ServiceLocator: doIndent(indent); printf("Extension type : ServiceLocator"); printCritical(indent, ocspExt); /* TBD */ return; default: /* this code is out of sync with ocspExtensions.{h,cpp} */ doIndent(indent); printf("Extension type : unrecognized - code sync error"); printCritical(indent, ocspExt); return; } }