]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_cms/lib/CMSDecoder.cpp
Security-59306.61.1.tar.gz
[apple/security.git] / OSX / libsecurity_cms / lib / CMSDecoder.cpp
index b8944d0af52a2154d51c1b131f245f580ca26308..9fe2ecb96ab264ba535dfc11a8f914ee98dbdc6f 100644 (file)
@@ -25,8 +25,8 @@
  * CMSDecoder.cpp - Interface for decoding CMS messages.
  */
 
  * CMSDecoder.cpp - Interface for decoding CMS messages.
  */
 
-#include "CMSDecoder.h"
-#include "CMSPrivate.h"
+#include <Security/CMSDecoder.h>
+#include <Security/CMSPrivate.h>
 #include "CMSUtils.h"
 #include <../libsecurity_codesigning/lib/csutilities.h>
 
 #include "CMSUtils.h"
 #include <../libsecurity_codesigning/lib/csutilities.h>
 
@@ -42,6 +42,7 @@
 #include <Security/oidsattr.h>
 #include <Security/SecTrustPriv.h>
 #include <CoreFoundation/CFRuntime.h>
 #include <Security/oidsattr.h>
 #include <Security/SecTrustPriv.h>
 #include <CoreFoundation/CFRuntime.h>
+#include <utilities/SecCFWrappers.h>
 #include <pthread.h>
 #include <syslog.h>
 #include <AssertMacros.h>
 #include <pthread.h>
 #include <syslog.h>
 #include <AssertMacros.h>
@@ -66,7 +67,7 @@ struct _CMSDecoder {
        SecArenaPoolRef         arena;                          /* the decoder's arena */
        SecCmsDecoderRef        decoder;
        CFDataRef                       detachedContent;
        SecArenaPoolRef         arena;                          /* the decoder's arena */
        SecCmsDecoderRef        decoder;
        CFDataRef                       detachedContent;
-       CFTypeRef                       keychainOrArray;        /* from CMSDecoderSetSearchKeychain() */
+       CFTypeRef                       keychainOrArray;        /* unused */
        
        /*
         * The following are valid (and quiescent) after CMSDecoderFinalizeMessage().
        
        /*
         * The following are valid (and quiescent) after CMSDecoderFinalizeMessage().
@@ -127,19 +128,20 @@ static void cmsDecoderFinalize(
        if(cmsDecoder->decoder != NULL) {
                /*
                 * Normally this gets freed in SecCmsDecoderFinish - this is
        if(cmsDecoder->decoder != NULL) {
                /*
                 * Normally this gets freed in SecCmsDecoderFinish - this is
-                * an error case.
-                * FIXME: SecCmsDecoderDestroy() appears to destroy the
-                * cmsMsg too! Plus there's a comment there re: a leak...
+                * an error case. Unlike Finish, this calls SecCmsMessageDestroy.
                 */
                SecCmsDecoderDestroy(cmsDecoder->decoder);
                 */
                SecCmsDecoderDestroy(cmsDecoder->decoder);
+               cmsDecoder->cmsMsg = NULL;
        }
        CFRELEASE(cmsDecoder->detachedContent);
        CFRELEASE(cmsDecoder->keychainOrArray);
        if(cmsDecoder->cmsMsg != NULL) {
                SecCmsMessageDestroy(cmsDecoder->cmsMsg);
        }
        CFRELEASE(cmsDecoder->detachedContent);
        CFRELEASE(cmsDecoder->keychainOrArray);
        if(cmsDecoder->cmsMsg != NULL) {
                SecCmsMessageDestroy(cmsDecoder->cmsMsg);
+               cmsDecoder->cmsMsg = NULL;
        }
        if(cmsDecoder->arena != NULL) {
                SecArenaPoolFree(cmsDecoder->arena, false);
        }
        if(cmsDecoder->arena != NULL) {
                SecArenaPoolFree(cmsDecoder->arena, false);
+               cmsDecoder->arena = NULL;
        }
 }
 
        }
 }
 
@@ -310,7 +312,9 @@ OSStatus CMSDecoderFinalizeMessage(
                 (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci);
                                /* dig down one more layer for eContentType */
                                ci = SecCmsSignedDataGetContentInfo(cmsDecoder->signedData);
                 (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci);
                                /* dig down one more layer for eContentType */
                                ci = SecCmsSignedDataGetContentInfo(cmsDecoder->signedData);
-                               cmsDecoder->eContentType = SecCmsContentInfoGetContentTypeOID(ci);
+                               if (ci) {
+                                       cmsDecoder->eContentType = SecCmsContentInfoGetContentTypeOID(ci);
+                               }
                                break;
                        default:
                                break;
                                break;
                        default:
                                break;
@@ -382,24 +386,14 @@ OSStatus CMSDecoderCopyDetachedContent(
 }
 
 /*
 }
 
 /*
- * Optionally specify a SecKeychainRef, or an array of them, containing
- * intermediate certs to be used in verifying a signed message's signer
- * certs. By default, the default keychain search list is used for this.
- * Specify an empty CFArrayRef to search *no* keychains for intermediate
- * certs.
- * IF this is called, it must be called before CMSDecoderCopySignerStatus().
+ * Beginning in 10.12, this function stopped affecting the behavior of the
+ * CMS Decoder. Its only use was in SecTrustSetKeychains which is a no-op.
+ * Please discontinue use.
  */
 OSStatus CMSDecoderSetSearchKeychain(
                                      CMSDecoderRef             cmsDecoder,
                                      CFTypeRef                 keychainOrArray)
 {
  */
 OSStatus CMSDecoderSetSearchKeychain(
                                      CMSDecoderRef             cmsDecoder,
                                      CFTypeRef                 keychainOrArray)
 {
-       if(cmsDecoder == NULL) {
-               return errSecParam;
-       }
-       cmsDecoder->keychainOrArray = keychainOrArray;
-       if(keychainOrArray) {
-               CFRetain(keychainOrArray);
-       }
        return errSecSuccess;
 }
 
        return errSecSuccess;
 }
 
@@ -435,7 +429,7 @@ OSStatus CMSDecoderCopySignerStatus(
                                     SecTrustRef                        *secTrust,                              /* optional; RETURNED */
                                     OSStatus                   *certVerifyResultCode)  /* optional; RETURNED */
 {
                                     SecTrustRef                        *secTrust,                              /* optional; RETURNED */
                                     OSStatus                   *certVerifyResultCode)  /* optional; RETURNED */
 {
-       if((cmsDecoder == NULL) || (cmsDecoder->decState != DS_Final)) {
+       if((cmsDecoder == NULL) || (cmsDecoder->decState != DS_Final) || (!policyOrArray) || !signerStatus) {
                return errSecParam;
        }
        
                return errSecParam;
        }
        
@@ -473,11 +467,7 @@ OSStatus CMSDecoderCopySignerStatus(
        SecTrustRef theTrust = NULL;
        OSStatus vfyRtn = SecCmsSignedDataVerifySignerInfo(cmsDecoder->signedData,
                                                        (int)signerIndex,
        SecTrustRef theTrust = NULL;
        OSStatus vfyRtn = SecCmsSignedDataVerifySignerInfo(cmsDecoder->signedData,
                                                        (int)signerIndex,
-                                                       /*
-                                                        * FIXME this cast should not be necessary, but libsecurity_smime
-                                                        * declares this argument as a SecKeychainRef
-                                                        */
-                                                       (SecKeychainRef)cmsDecoder->keychainOrArray,
+                                                       NULL,
                                                        policyOrArray,
                                                        &theTrust);
 
                                                        policyOrArray,
                                                        &theTrust);
 
@@ -505,8 +495,7 @@ OSStatus CMSDecoderCopySignerStatus(
        if(secTrust != NULL) {
                *secTrust = theTrust;
                /* we'll release our reference at the end */
        if(secTrust != NULL) {
                *secTrust = theTrust;
                /* we'll release our reference at the end */
-               if (theTrust)
-                       CFRetain(theTrust);
+               CFRetainSafe(theTrust);
        }
        SecCmsSignerInfoRef signerInfo =
     SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex);
        }
        SecCmsSignerInfoRef signerInfo =
     SecCmsSignedDataGetSignerInfo(cmsDecoder->signedData, (int)signerIndex);
@@ -537,10 +526,6 @@ OSStatus CMSDecoderCopySignerStatus(
                        case kSecTrustResultDeny:
                                tpVfyStatus = CSSMERR_APPLETP_TRUST_SETTING_DENY;
                                break;
                        case kSecTrustResultDeny:
                                tpVfyStatus = CSSMERR_APPLETP_TRUST_SETTING_DENY;
                                break;
-                       case kSecTrustResultConfirm:
-                               dprintf("SecTrustEvaluate reported confirm\n");
-                               tpVfyStatus = CSSMERR_TP_NOT_TRUSTED;
-                               break;
                        default:
                        {
                                /* get low-level TP error */
                        default:
                        {
                                /* get low-level TP error */
@@ -999,3 +984,132 @@ OSStatus CMSDecoderCopySignerTimestampCertificates(
     xit:
         return status;
     }
     xit:
         return status;
     }
+
+/*
+ * Obtain the Hash Agility attribute value of signer 'signerIndex'
+ * of a CMS message, if present.
+ *
+ * Returns errSecParam if the CMS message was not signed or if signerIndex
+ * is greater than the number of signers of the message minus one.
+ *
+ * This cannot be called until after CMSDecoderFinalizeMessage() is called.
+ */
+OSStatus CMSDecoderCopySignerAppleCodesigningHashAgility(
+    CMSDecoderRef              cmsDecoder,
+    size_t                             signerIndex,            /* usually 0 */
+    CFDataRef  CF_RETURNS_RETAINED *hashAgilityAttrValue)                      /* RETURNED */
+{
+    OSStatus status = errSecParam;
+    SecCmsMessageRef cmsg;
+    SecCmsSignedDataRef signedData = NULL;
+    int numContentInfos = 0;
+    CFDataRef returnedValue = NULL;
+
+    require(cmsDecoder && hashAgilityAttrValue, exit);
+    require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), exit);
+    numContentInfos = SecCmsMessageContentLevelCount(cmsg);
+    for (int dex = 0; !signedData && dex < numContentInfos; dex++)
+    {
+        SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex);
+        SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
+        if (tag == SEC_OID_PKCS7_SIGNED_DATA)
+            if ((signedData = SecCmsSignedDataRef(SecCmsContentInfoGetContent(ci))))
+                if (SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex))
+                {
+                    status = SecCmsSignerInfoGetAppleCodesigningHashAgility(signerInfo, &returnedValue);
+                    break;
+                }
+    }
+exit:
+    if (status == errSecSuccess && returnedValue) {
+        *hashAgilityAttrValue = (CFDataRef) CFRetain(returnedValue);
+    } else {
+        *hashAgilityAttrValue = NULL;
+    }
+    return status;
+}
+
+/*
+ * Obtain the Hash Agility V2 attribute value of signer 'signerIndex'
+ * of a CMS message, if present.
+ *
+ * Returns errSecParam if the CMS message was not signed or if signerIndex
+ * is greater than the number of signers of the message minus one.
+ *
+ * This cannot be called until after CMSDecoderFinalizeMessage() is called.
+ */
+OSStatus CMSDecoderCopySignerAppleCodesigningHashAgilityV2(
+    CMSDecoderRef        cmsDecoder,
+    size_t                signerIndex,            /* usually 0 */
+    CFDictionaryRef  CF_RETURNS_RETAINED *hashAgilityV2AttrValues)            /* RETURNED */
+{
+    OSStatus status = errSecParam;
+    SecCmsMessageRef cmsg;
+    SecCmsSignedDataRef signedData = NULL;
+    int numContentInfos = 0;
+    CFDictionaryRef returnedValue = NULL;
+
+    require(cmsDecoder && hashAgilityV2AttrValues, exit);
+    require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), exit);
+    numContentInfos = SecCmsMessageContentLevelCount(cmsg);
+    for (int dex = 0; !signedData && dex < numContentInfos; dex++)
+    {
+        SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex);
+        SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
+        if (tag == SEC_OID_PKCS7_SIGNED_DATA)
+            if ((signedData = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci))) {
+                SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex);
+                if (signerInfo)
+                {
+                    status = SecCmsSignerInfoGetAppleCodesigningHashAgilityV2(signerInfo, &returnedValue);
+                    break;
+                }
+            }
+    }
+exit:
+    if (status == errSecSuccess && returnedValue) {
+        *hashAgilityV2AttrValues = (CFDictionaryRef) CFRetain(returnedValue);
+    } else {
+        *hashAgilityV2AttrValues = NULL;
+    }
+    return status;
+}
+
+/*
+ * Obtain the expiration time of signer 'signerIndex' of a CMS message, if
+ * present. This is part of the signed attributes of the message.
+ *
+ * Returns errSecParam if the CMS message was not signed or if signerIndex
+ * is greater than the number of signers of the message minus one.
+ *
+ * This cannot be called until after CMSDecoderFinalizeMessage() is called.
+ */
+OSStatus CMSDecoderCopySignerAppleExpirationTime(
+    CMSDecoderRef      cmsDecoder,
+    size_t             signerIndex,
+    CFAbsoluteTime     *expirationTime)            /* RETURNED */
+{
+    OSStatus status = errSecParam;
+    SecCmsMessageRef cmsg = NULL;
+    int numContentInfos  = 0;
+    SecCmsSignedDataRef signedData = NULL;
+
+    require(cmsDecoder && expirationTime, xit);
+    require_noerr(CMSDecoderGetCmsMessage(cmsDecoder, &cmsg), xit);
+    numContentInfos = SecCmsMessageContentLevelCount(cmsg);
+    for (int dex = 0; !signedData && dex < numContentInfos; dex++) {
+        SecCmsContentInfoRef ci = SecCmsMessageContentLevel(cmsg, dex);
+        SECOidTag tag = SecCmsContentInfoGetContentTypeTag(ci);
+        if (tag == SEC_OID_PKCS7_SIGNED_DATA) {
+            if ((signedData = (SecCmsSignedDataRef)SecCmsContentInfoGetContent(ci))) {
+                SecCmsSignerInfoRef signerInfo = SecCmsSignedDataGetSignerInfo(signedData, (int)signerIndex);
+                if (signerInfo) {
+                    status = SecCmsSignerInfoGetAppleExpirationTime(signerInfo, expirationTime);
+                    break;
+                }
+            }
+        }
+    }
+xit:
+    return status;
+}