static void debugSaveCertificates(CSSM_DATA **outCerts) { #ifndef NDEBUG if (outCerts) { CSSM_DATA_PTR *certp; unsigned jx = 0; const char *certNameBase = "/tmp/tsa-resp-cert-"; char fname[PATH_MAX]; unsigned certCount = SecCmsArrayCount((void **)outCerts); dtprintf("Found %d certs\n",certCount); for (certp=outCerts;*certp;certp++, ++jx) { char numstr[32]; strncpy(fname, certNameBase, strlen(certNameBase)+1); sprintf(numstr,"%u", jx); strcat(fname,numstr); tsaWriteFileX(fname, (*certp)->Data, (*certp)->Length); if (jx > 5) break; //something wrong } } #endif }
static OSStatus validateTSAResponseAndAddTimeStamp(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR tsaResponse, uint64_t expectedNonce) { OSStatus status = SECFailure; SecAsn1CoderRef coder = NULL; SecAsn1TimeStampRespDER respDER = {{{0}},}; SecAsn1TSAPKIStatusInfo *tsastatus = NULL; int respstatus = -1; int failinfo = -1; require_action(tsaResponse && tsaResponse->Data && tsaResponse->Length, xit, status = errSecTimestampMissing); require_noerr(SecAsn1CoderCreate(&coder), xit); require_noerr(SecTSAResponseCopyDEREncoding(coder, tsaResponse, &respDER), xit); #ifndef NDEBUG tsaWriteFileX("/tmp/tsa-timeStampToken.der", respDER.timeStampTokenDER.Data, respDER.timeStampTokenDER.Length); #endif tsastatus = (SecAsn1TSAPKIStatusInfo *)&respDER.status; require_action(tsastatus->status.Data, xit, status = errSecTimestampBadDataFormat); respstatus = (int)tsaDER_ToInt(&tsastatus->status); #ifndef NDEBUG char buf[80]={0,}; if (tsastatus->failInfo.Data) // e.g. FI_BadRequest failinfo = (int)tsaDER_ToInt(&tsastatus->failInfo); if (tsastatus->statusString.Data && tsastatus->statusString.Length) { OSStatus strrx = decodeDERUTF8String(&tsastatus->statusString, buf, sizeof(buf)); dprintf("decodeDERUTF8String status: %d\n", (int)strrx); } dprintf("validateTSAResponse: status: %d, failinfo: %d, %s\n", respstatus, failinfo, buf); #endif switch (respstatus) { case PKIS_Granted: case PKIS_GrantedWithMods: // Success status = noErr; break; case PKIS_Rejection: status = errSecTimestampRejection; break; case PKIS_Waiting: status = errSecTimestampWaiting; break; case PKIS_RevocationWarning: status = errSecTimestampRevocationWarning; break; case PKIS_RevocationNotification: status = errSecTimestampRevocationNotification; break; default: status = errSecTimestampSystemFailure; break; } require_noerr(status, xit); // If we succeeded, then we must have a TimeStampToken require_action(respDER.timeStampTokenDER.Data && respDER.timeStampTokenDER.Length, xit, status = errSecTimestampBadDataFormat); dprintf("timestamp full expected nonce: %lld\n", expectedNonce); /* The bytes in respDER are a full CMS message, which we need to check now for validity. The code for this is essentially the same code taht is done during a timestamp verify, except that we also need to check the nonce. */ require_noerr(status = decodeTimeStampToken(signerinfo, &respDER.timeStampTokenDER, NULL, expectedNonce), xit); status = SecCmsSignerInfoAddTimeStamp(signerinfo, &respDER.timeStampTokenDER); xit: if (coder) SecAsn1CoderRelease(coder); return status; }