]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_smime/lib/cmssiginfo.c
Security-57740.31.2.tar.gz
[apple/security.git] / libsecurity_smime / lib / cmssiginfo.c
index cce6955355bbdae6ae60987e5d3719d0af0505f2..296c17ea45319b640cb2001fd3340d684ae460c2 100644 (file)
@@ -59,6 +59,7 @@
 #include <Security/SecKeyPriv.h>
 #include <utilities/SecCFWrappers.h>
 #include <CoreFoundation/CFTimeZone.h>
+#include <Security/SecBasePriv.h>
 
 
 #define HIDIGIT(v) (((v) / 10) + '0')    
@@ -320,7 +321,7 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, SecAsn1Item * digest, SecAs
     SECOidTag pubkAlgTag;
     SecAsn1Item signature = { 0 };
     OSStatus rv;
-    PLArenaPool *poolp, *tmppoolp;
+    PLArenaPool *poolp, *tmppoolp = NULL;
     const SECAlgorithmID *algID = NULL;
     //CERTSubjectPublicKeyInfo *spki;
 
@@ -328,6 +329,8 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, SecAsn1Item * digest, SecAs
 
     poolp = signerinfo->signedData->contentInfo.cmsg->poolp;
 
+    SecAsn1AlgId _algID;
+
     switch (signerinfo->signerIdentifier.identifierType) {
     case SecCmsSignerIDIssuerSN:
         privkey = signerinfo->signingKey;
@@ -339,7 +342,7 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, SecAsn1Item * digest, SecAs
            goto loser;
         }
 #else
-        SecAsn1AlgId _algID = SecCertificateGetPublicKeyAlgorithmID(cert);
+        _algID = SecCertificateGetPublicKeyAlgorithmID(cert);
         algID = &_algID;
 #endif
         break;
@@ -370,6 +373,13 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, SecAsn1Item * digest, SecAs
     }
     digestalgtag = SecCmsSignerInfoGetDigestAlgTag(signerinfo);
     pubkAlgTag = SECOID_GetAlgorithmTag(algID);
+
+    /* we no longer support signing with MD5 */
+    if (digestalgtag == SEC_OID_MD5) {
+        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
+        goto loser;
+    }
+
 #if USE_CDSA_CRYPTO
     if (signerinfo->signerIdentifier.identifierType == SecCmsSignerIDSubjectKeyID) {
       SECOID_DestroyAlgorithmID(&freeAlgID, PR_FALSE);
@@ -444,6 +454,7 @@ SecCmsSignerInfoSign(SecCmsSignerInfoRef signerinfo, SecAsn1Item * digest, SecAs
 #endif
 
        PORT_FreeArena(tmppoolp, PR_FALSE); /* awkward memory management :-( */
+       tmppoolp = 0;
     } else {
         signature.Length = SecKeyGetSize(privkey, kSecKeySignatureSize);
         signature.Data = PORT_ZAlloc(signature.Length);
@@ -481,6 +492,8 @@ loser:
        SECITEM_FreeItem (&signature, PR_FALSE);
     if (privkey)
        SECKEY_DestroyPrivateKey(privkey);
+    if (tmppoolp)
+       PORT_FreeArena(tmppoolp, PR_FALSE);
     return SECFailure;
 }
 
@@ -570,9 +583,17 @@ SecCmsSignerInfoVerifyCertificate(SecCmsSignerInfoRef signerinfo, SecKeychainRef
     {
        if (PORT_GetError() == SEC_ERROR_UNTRUSTED_CERT)
        {
-           /* Signature or digest level verificationStatus errors should supercede certificate level errors, so only change the verificationStatus if the status was GoodSignature. */
-           if (signerinfo->verificationStatus == SecCmsVSGoodSignature)
-               signerinfo->verificationStatus = SecCmsVSSigningCertNotTrusted;
+               /* Signature or digest level verificationStatus errors should supercede certificate level errors, so only change the verificationStatus if the status was GoodSignature. */
+#if 0
+#warning DEBUG - SecCmsSignerInfoVerifyCertificate trusts everything!
+               if (signerinfo->verificationStatus == SecCmsVSGoodSignature) {
+                        syslog(LOG_ERR, "SecCmsSignerInfoVerifyCertificate ignoring SEC_ERROR_UNTRUSTED_CERT");
+                        rv = SECSuccess;
+               }
+#else
+               if (signerinfo->verificationStatus == SecCmsVSGoodSignature)
+                       signerinfo->verificationStatus = SecCmsVSSigningCertNotTrusted;
+#endif
        }
     }
 
@@ -811,6 +832,44 @@ SecCmsSignerInfoGetSigningTime(SecCmsSignerInfoRef sinfo, CFAbsoluteTime *stime)
     return SECSuccess;
 }
 
+/*!
+     @function
+     @abstract Return the data in the signed Codesigning Hash Agility attribute.
+     @param sinfo SignerInfo data for this signer, pointer to a CFDataRef for attribute value
+     @discussion Returns a CFDataRef containing the value of the attribute
+     @result A return value of errSecInternal is an error trying to look up the oid.
+             A status value of success with null result data indicates the attribute was not present.
+ */
+OSStatus
+SecCmsSignerInfoGetAppleCodesigningHashAgility(SecCmsSignerInfoRef sinfo, CFDataRef *sdata)
+{
+    SecCmsAttribute *attr;
+    SecAsn1Item *value;
+
+    if (sinfo == NULL || sdata == NULL)
+        return errSecParam;
+
+    *sdata = NULL;
+
+    if (sinfo->hashAgilityAttrValue != NULL) {
+        *sdata = sinfo->hashAgilityAttrValue;  /* cached copy */
+        return SECSuccess;
+    }
+
+    attr = SecCmsAttributeArrayFindAttrByOidTag(sinfo->authAttr, SEC_OID_APPLE_HASH_AGILITY, PR_TRUE);
+
+    /* attribute not found */
+    if (attr == NULL || (value = SecCmsAttributeGetValue(attr)) == NULL)
+        return SECSuccess;
+
+    sinfo->hashAgilityAttrValue = CFDataCreate(NULL, value->Data, value->Length);      /* make cached copy */
+    if (sinfo->hashAgilityAttrValue) {
+        *sdata = sinfo->hashAgilityAttrValue;
+        return SECSuccess;
+    }
+    return errSecAllocate;
+}
+
 /*
  * Return the signing cert of a CMS signerInfo.
  *
@@ -1194,6 +1253,54 @@ SecCmsSignerInfoAddCounterSignature(SecCmsSignerInfoRef signerinfo,
     return SECFailure;
 }
 
+/*!
+     @function
+     @abstract Add the Apple Codesigning Hash Agility attribute to the authenticated (i.e. signed) attributes of "signerinfo".
+     @discussion This is expected to be included in outgoing signed Apple code signatures.
+ */
+OSStatus
+SecCmsSignerInfoAddAppleCodesigningHashAgility(SecCmsSignerInfoRef signerinfo, CFDataRef attrValue)
+{
+    SecCmsAttribute *attr;
+    PLArenaPool *poolp = signerinfo->signedData->contentInfo.cmsg->poolp;
+    void *mark = PORT_ArenaMark(poolp);
+    OSStatus status = SECFailure;
+
+    /* The value is required for this attribute. */
+    if (!attrValue) {
+        status = errSecParam;
+        goto loser;
+    }
+
+    /*
+     * SecCmsAttributeCreate makes a copy of the data in value, so
+     * we don't need to copy into the CSSM_DATA struct.
+     */
+    SecAsn1Item value;
+    value.Length = CFDataGetLength(attrValue);
+    value.Data = (uint8_t *)CFDataGetBytePtr(attrValue);
+
+    if ((attr = SecCmsAttributeCreate(poolp,
+                                      SEC_OID_APPLE_HASH_AGILITY,
+                                      &value,
+                                      PR_FALSE)) == NULL) {
+        status = errSecAllocate;
+        goto loser;
+    }
+
+    if (SecCmsSignerInfoAddAuthAttr(signerinfo, attr) != SECSuccess) {
+        status = errSecInternal;
+        goto loser;
+    }
+
+    PORT_ArenaUnmark(poolp, mark);
+    return SECSuccess;
+
+loser:
+    PORT_ArenaRelease(poolp, mark);
+    return status;
+}
+
 /*
  * XXXX the following needs to be done in the S/MIME layer code
  * after signature of a signerinfo is verified