X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/8a50f688fe9358387648fb83fbfecbefe8d32669..07691282a056c4efea71e1e505527601e8cc166b:/OSX/libsecurity_smime/lib/tsaSupport.c?ds=inline diff --git a/OSX/libsecurity_smime/lib/tsaSupport.c b/OSX/libsecurity_smime/lib/tsaSupport.c index f2faff0e..ac6c155f 100644 --- a/OSX/libsecurity_smime/lib/tsaSupport.c +++ b/OSX/libsecurity_smime/lib/tsaSupport.c @@ -48,11 +48,13 @@ #include #include #include +#include #include "tsaSupport.h" #include "tsaSupportPriv.h" #include "tsaTemplates.h" #include "cmslocal.h" +#include "cert.h" #include "secoid.h" #include "secitem.h" @@ -165,8 +167,7 @@ static void printDataAsHex(const char *title, const CSSM_DATA *d, unsigned maxTo int offset, sz = 0; const int wrapwid = 24; // large enough so SHA-1 hashes fit on one line... - if ((maxToPrint != 0) && (len > maxToPrint)) - { + if ((maxToPrint != 0) && (len > maxToPrint)) { len = maxToPrint; more = true; } @@ -178,22 +179,19 @@ static void printDataAsHex(const char *title, const CSSM_DATA *d, unsigned maxTo dtprintf("%s", buffer); offset = 0; - for (i=0; (i < len) && (offset+3 < bufferSize); i++, offset += sz) - { + for (i=0; (i < len) && (offset+3 < bufferSize); i++, offset += sz) { sz = sprintf(buffer + offset, " %02x", (unsigned int)cp[i] & 0xff); - if ((i % wrapwid) == (wrapwid-1)) - { - dtprintf("%s", buffer); + if ((i % wrapwid) == (wrapwid-1)) { + dtprintf("%s\n", buffer); offset = 0; sz = 0; } } sz=sprintf(buffer + offset, more?" ...\n":"\n"); - offset += sz; + offset += sz; buffer[offset+1]=0; -// fprintf(stderr, "%s", buffer); dtprintf("%s", buffer); free(buffer); @@ -900,7 +898,7 @@ xit: return result; } -static OSStatus verifyTSTInfo(const CSSM_DATA_PTR content, SecCertificateRef signerCert, SecAsn1TSATSTInfo *tstInfo, CFAbsoluteTime *timestampTime, uint64_t expectedNonce) +static OSStatus verifyTSTInfo(const CSSM_DATA_PTR content, SecCmsSignerInfoRef signerinfo, SecAsn1TSATSTInfo *tstInfo, CFAbsoluteTime *timestampTime, uint64_t expectedNonce, CSSM_DATA_PTR encDigest) { OSStatus status = paramErr; SecAsn1CoderRef coder = NULL; @@ -908,6 +906,9 @@ static OSStatus verifyTSTInfo(const CSSM_DATA_PTR content, SecCertificateRef sig if (!tstInfo) return SECFailure; + SecCertificateRef signerCert = SecCmsSignerInfoGetTimestampSigningCert(signerinfo); + SecAsn1TSAMessageImprint expectedMessageImprint; + require_noerr(SecAsn1CoderCreate(&coder), xit); require_noerr(SecAsn1Decode(coder, content->Data, content->Length, kSecAsn1TSATSTInfoTemplate, tstInfo), xit); @@ -922,9 +923,18 @@ static OSStatus verifyTSTInfo(const CSSM_DATA_PTR content, SecCertificateRef sig require_action(expectedNonce==nonce, xit, status = errSecTimestampRejection); } - status = SecTSAValidateTimestamp(tstInfo, signerCert, timestampTime); + // Check the times in the timestamp + require_noerr(status = SecTSAValidateTimestamp(tstInfo, signerCert, timestampTime), xit); dtprintf("SecTSAValidateTimestamp result: %ld\n", (long)status); + // Check the message imprint against the encDigest from the signerInfo containing this timestamp + SECOidTag hashAlg = SECOID_GetAlgorithmTag(&tstInfo->messageImprint.hashAlgorithm); + require_action(hashAlg == SEC_OID_SHA256 || hashAlg == SEC_OID_SHA1, xit, status = errSecInvalidDigestAlgorithm); + require_noerr(status = createTSAMessageImprint(signerinfo, &tstInfo->messageImprint.hashAlgorithm, + encDigest, &expectedMessageImprint), xit); + require_action(CERT_CompareCssmData(&expectedMessageImprint.hashedMessage, &tstInfo->messageImprint.hashedMessage), xit, + status = errSecTimestampInvalid; secerror("Timestamp MessageImprint did not match the signature's hash")); + xit: if (coder) SecAsn1CoderRelease(coder); @@ -1239,14 +1249,15 @@ OSStatus decodeTimeStampToken(SecCmsSignerInfoRef signerinfo, CSSM_DATA_PTR inDa OSStatus decodeTimeStampTokenWithPolicy(SecCmsSignerInfoRef signerinfo, CFTypeRef timeStampPolicy, CSSM_DATA_PTR inData, CSSM_DATA_PTR encDigest, uint64_t expectedNonce) { /* - We update signerinfo with timestamp and tsa certificate chain. - encDigest is the original signed blob, which we must hash and compare. - inData comes from the unAuthAttr section of the CMS message + We update signerinfo with timestamp and tsa certificate chain. + encDigest is the original signed blob, which we must hash and compare. + inData comes from the unAuthAttr section of the CMS message - These are set in signerinfo as side effects: - timestampTime - - timestampCertList - */ + These are set in signerinfo as side effects: + timestampTime + timestampCertList + timestampCert + */ SecCmsDecoderRef decoderContext = NULL; SecCmsMessageRef cmsMessage = NULL; @@ -1264,23 +1275,22 @@ OSStatus decodeTimeStampTokenWithPolicy(SecCmsSignerInfoRef signerinfo, CFTypeRe /* decode the message */ require_noerr(result = SecCmsDecoderCreate (NULL, NULL, NULL, NULL, NULL, NULL, NULL, &decoderContext), xit); result = SecCmsDecoderUpdate(decoderContext, inData->Data, inData->Length); - if (result) - { + if (result) { result = errSecTimestampInvalid; SecCmsDecoderDestroy(decoderContext); goto xit; - } + } require_noerr(result = SecCmsDecoderFinish(decoderContext, &cmsMessage), xit); // process the results contentLevelCount = SecCmsMessageContentLevelCount(cmsMessage); - if (encDigest) + if (encDigest) { printDataAsHex("encDigest",encDigest, 0); + } - for (ix = 0; ix < contentLevelCount; ++ix) - { + for (ix = 0; ix < contentLevelCount; ++ix) { dtprintf("\n----- Content Level %d -----\n", ix); // get content information contentInfo = SecCmsMessageContentLevel (cmsMessage, ix); @@ -1290,110 +1300,102 @@ OSStatus decodeTimeStampTokenWithPolicy(SecCmsSignerInfoRef signerinfo, CFTypeRe debugShowContentTypeOID(contentInfo); - switch (contentTypeTag) - { - case SEC_OID_PKCS7_SIGNED_DATA: - { - require((signedData = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(contentInfo)) != NULL, xit); - - debugShowSignerInfo(signedData); - - SECAlgorithmID **digestAlgorithms = SecCmsSignedDataGetDigestAlgs(signedData); - unsigned digestAlgCount = SecCmsArrayCount((void **)digestAlgorithms); - dtprintf("digestAlgCount: %d\n", digestAlgCount); - if (signedData->digests) - { - int jx; - char buffer[128]; - for (jx=0;jx < digestAlgCount;jx++) - { - sprintf(buffer, " digest[%u]", jx); - printDataAsHex(buffer,signedData->digests[jx], 0); - } - } - else - { - dtprintf("No digests\n"); - CSSM_DATA_PTR innerContent = SecCmsContentInfoGetInnerContent(contentInfo); - if (innerContent) - { - dtprintf("inner content length: %ld\n", innerContent->Length); - SecAsn1TSAMessageImprint fakeMessageImprint = {{{0}},}; - OSStatus status = createTSAMessageImprint(signedData, innerContent, &fakeMessageImprint); - require_noerr_action(status, xit, dtprintf("createTSAMessageImprint status: %d\n", (int)status); result = status); - printDataAsHex("inner content hash",&fakeMessageImprint.hashedMessage, 0); - CSSM_DATA_PTR digestdata = &fakeMessageImprint.hashedMessage; - CSSM_DATA_PTR digests[2] = {digestdata, NULL}; - status = SecCmsSignedDataSetDigests(signedData, digestAlgorithms, (CSSM_DATA_PTR *)&digests); - require_noerr_action(status, xit, dtprintf("createTSAMessageImprint status: %d\n", (int)status); result = status); + switch (contentTypeTag) { + case SEC_OID_PKCS7_SIGNED_DATA: { + require((signedData = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(contentInfo)) != NULL, xit); + + debugShowSignerInfo(signedData); + + SECAlgorithmID **digestAlgorithms = SecCmsSignedDataGetDigestAlgs(signedData); + unsigned digestAlgCount = SecCmsArrayCount((void **)digestAlgorithms); + dtprintf("digestAlgCount: %d\n", digestAlgCount); + if (signedData->digests) { + int jx; + char buffer[128]; + for (jx=0;jx < digestAlgCount;jx++) { + sprintf(buffer, " digest[%u]", jx); + printDataAsHex(buffer,signedData->digests[jx], 0); + } + } else { + dtprintf("digests not yet computed\n"); + CSSM_DATA_PTR innerContent = SecCmsContentInfoGetInnerContent(contentInfo); + if (innerContent) + { + dtprintf("inner content length: %ld\n", innerContent->Length); + SecAsn1TSAMessageImprint fakeMessageImprint = {{{0}},}; + SecCmsSignerInfoRef tsaSigner = SecCmsSignedDataGetSignerInfo(signedData, 0); + OSStatus status = createTSAMessageImprint(tsaSigner, &tsaSigner->digestAlg, innerContent, &fakeMessageImprint); + require_noerr_action(status, xit, dtprintf("createTSAMessageImprint status: %d\n", (int)status); result = status); + printDataAsHex("inner content hash",&fakeMessageImprint.hashedMessage, 0); + CSSM_DATA_PTR digestdata = &fakeMessageImprint.hashedMessage; + CSSM_DATA_PTR digests[2] = {digestdata, NULL}; + status = SecCmsSignedDataSetDigests(signedData, digestAlgorithms, (CSSM_DATA_PTR *)&digests); + require_noerr_action(status, xit, dtprintf("createTSAMessageImprint status: %d\n", (int)status); result = status); + } else { + dtprintf("no inner content\n"); + } } - else - dtprintf("no inner content\n"); - } - /* - Import the certificates. We leave this as a warning, since - there are configurations where the certificates are not returned. - */ - signingCerts = SecCmsSignedDataGetCertificateList(signedData); - if (signingCerts == NULL) - { dtprintf("SecCmsSignedDataGetCertificateList returned NULL\n"); } - else - { - if (!signerinfo->timestampCertList) - signerinfo->timestampCertList = CFArrayCreateMutable(kCFAllocatorDefault, 10, &kCFTypeArrayCallBacks); - saveTSACertificates(signingCerts, signerinfo->timestampCertList); - require_noerr(result = setTSALeafValidityDates(signerinfo), xit); - debugSaveCertificates(signingCerts); - } - - int numberOfSigners = SecCmsSignedDataSignerInfoCount (signedData); - - result = verifySigners(signedData, numberOfSigners, timeStampPolicy); - if (result) - dtprintf("verifySigners failed: %ld\n", (long)result); // warning + /* + Import the certificates. We leave this as a warning, since + there are configurations where the certificates are not returned. + */ + signingCerts = SecCmsSignedDataGetCertificateList(signedData); + if (signingCerts == NULL) { + dtprintf("SecCmsSignedDataGetCertificateList returned NULL\n"); + } else { + if (!signerinfo->timestampCertList) { + signerinfo->timestampCertList = CFArrayCreateMutable(kCFAllocatorDefault, 10, &kCFTypeArrayCallBacks); + } + saveTSACertificates(signingCerts, signerinfo->timestampCertList); + require_noerr(result = setTSALeafValidityDates(signerinfo), xit); + debugSaveCertificates(signingCerts); + } + int numberOfSigners = SecCmsSignedDataSignerInfoCount (signedData); - if (result) // remap to SecCmsVSTimestampNotTrusted ? - goto xit; + if (numberOfSigners > 0) { + /* @@@ assume there's only one signer since SecCms can't handle multiple signers anyway */ + signerinfo->timestampCert = CFRetainSafe(SecCmsSignerInfoGetSigningCertificate(signedData->signerInfos[0], NULL)); + } - break; - } - case SEC_OID_PKCS9_SIGNING_CERTIFICATE: - { - dtprintf("SEC_OID_PKCS9_SIGNING_CERTIFICATE seen\n"); - break; - } + result = verifySigners(signedData, numberOfSigners, timeStampPolicy); + if (result) { + dtprintf("verifySigners failed: %ld\n", (long)result); // warning + goto xit; // remap to SecCmsVSTimestampNotTrusted ? + } - case SEC_OID_PKCS9_ID_CT_TSTInfo: - { - SecAsn1TSATSTInfo tstInfo = {{0},}; - SecCertificateRef signerCert = SecCmsSignerInfoGetSigningCertificate(signerinfo, NULL); - result = verifyTSTInfo(contentInfo->rawContent, signerCert, &tstInfo, &signerinfo->timestampTime, expectedNonce); - if (signerinfo->timestampTime) - { - const char *tstamp = cfabsoluteTimeToString(signerinfo->timestampTime); - if (tstamp) - { - dtprintf("Timestamp Authority timestamp: %s\n", tstamp); - free((void *)tstamp); + break; + } + case SEC_OID_PKCS9_SIGNING_CERTIFICATE: { + dtprintf("SEC_OID_PKCS9_SIGNING_CERTIFICATE seen\n"); + break; + } + case SEC_OID_PKCS9_ID_CT_TSTInfo: { + SecAsn1TSATSTInfo tstInfo = {{0},}; + result = verifyTSTInfo(contentInfo->rawContent, signerinfo, &tstInfo, &signerinfo->timestampTime, expectedNonce, encDigest); + if (signerinfo->timestampTime) { + const char *tstamp = cfabsoluteTimeToString(signerinfo->timestampTime); + if (tstamp) { + dtprintf("Timestamp Authority timestamp: %s\n", tstamp); + free((void *)tstamp); + } } + break; } - break; - } - case SEC_OID_OTHER: - { - dtprintf("otherContent : %p\n", (char *)SecCmsContentInfoGetContent (contentInfo)); - break; - } - default: - dtprintf("ContentTypeTag : %x\n", contentTypeTag); - break; + case SEC_OID_OTHER: { + dtprintf("otherContent : %p\n", (char *)SecCmsContentInfoGetContent (contentInfo)); + break; + } + default: + dtprintf("ContentTypeTag : %x\n", contentTypeTag); + break; } } xit: - if (cmsMessage) - SecCmsMessageDestroy(cmsMessage); + if (cmsMessage) { + SecCmsMessageDestroy(cmsMessage); + } return result; }