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 }
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; }