X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5c19dc3ae3bd8e40a9c028b0deddd50ff337692c..07691282a056c4efea71e1e505527601e8cc166b:/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp diff --git a/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp b/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp index 761dc806..786c21f1 100644 --- a/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp +++ b/OSX/libsecurity_apple_x509_tp/lib/tpPolicies.cpp @@ -75,14 +75,18 @@ typedef struct { iSignExtenInfo inhibitAnyPolicy; iSignExtenInfo certificatePolicies; + /* flag indicating presence of CSSMOID_APPLE_EXTENSION_PROVISIONING_PROFILE_SIGNING */ + CSSM_BOOL foundProvisioningProfileSigningMarker; /* flag indicating presence of CSSMOID_APPLE_EXTENSION_PASSBOOK_SIGNING */ - CSSM_BOOL foundPassbookSigning; + CSSM_BOOL foundPassbookSigningMarker; /* flag indicating presence of CSSMOID_APPLE_EXTENSION_SYSINT2_INTERMEDIATE */ CSSM_BOOL foundAppleSysInt2Marker; /* flag indicating presence of CSSMOID_APPLE_EXTENSION_SERVER_AUTHENTICATION */ CSSM_BOOL foundAppleServerAuthMarker; /* flag indicating presence of CSSMOID_APPLE_EXTENSION_ESCROW_SERVICE */ CSSM_BOOL foundEscrowServiceMarker; + /* flag indicating presence of CSSMOID_APPLE_EXTENSION_WWDR_INTERMEDIATE */ + CSSM_BOOL foundAppleWWDRIntMarker; /* flag indicating presence of a critical extension we don't understand */ CSSM_BOOL foundUnknownCritical; /* flag indicating that this certificate was signed with a known-broken algorithm */ @@ -163,9 +167,6 @@ const CSSM_OID CSSMOID_PIV_AUTH = {PIV_AUTH_OID_LEN, (uint8 *)OID_PIV_AUTH}; static const uint8 OID_PIV_AUTH_2048[] = {PIV_AUTH_2048_OID}; const CSSM_OID CSSMOID_PIV_AUTH_2048 = {PIV_AUTH_2048_OID_LEN, (uint8 *)OID_PIV_AUTH_2048}; -static CSSM_RETURN tp_verifyAppleIDSharingOpts(TPCertGroup &certGroup, - const CSSM_DATA *fieldOpts, // optional Common Name - const iSignCertInfo *certInfo); /* * Setup a single iSignExtenInfo. Called once per known extension * per cert. @@ -254,8 +255,10 @@ static CSSM_RETURN iSignSearchUnknownExtensions( CSSM_HANDLE searchHand = CSSM_INVALID_HANDLE; uint32 numFields = 0; - certInfo->foundPassbookSigning = CSSM_FALSE; + certInfo->foundProvisioningProfileSigningMarker = CSSM_FALSE; + certInfo->foundPassbookSigningMarker = CSSM_FALSE; certInfo->foundAppleSysInt2Marker = CSSM_FALSE; + certInfo->foundAppleWWDRIntMarker = CSSM_FALSE; certInfo->foundEscrowServiceMarker = CSSM_FALSE; crtn = CSSM_CL_CertGetFirstCachedFieldValue(tpCert->clHand(), @@ -285,7 +288,7 @@ static CSSM_RETURN iSignSearchUnknownExtensions( !memcmp(cssmExt->extnId.Data, CSSMOID_APPLE_EXTENSION_PASSBOOK_SIGNING.Data, APPLE_EXTENSION_CODE_SIGNING_LENGTH+1)) { /* this is the Passbook Signing extension */ - certInfo->foundPassbookSigning = CSSM_TRUE; + certInfo->foundPassbookSigningMarker = CSSM_TRUE; } if (cssmExt->extnId.Length == APPLE_EXTENSION_SYSINT2_INTERMEDIATE_LENGTH && !memcmp(cssmExt->extnId.Data, CSSMOID_APPLE_EXTENSION_SYSINT2_INTERMEDIATE.Data, @@ -299,6 +302,18 @@ static CSSM_RETURN iSignSearchUnknownExtensions( /* this is the Escrow Service Signing extension */ certInfo->foundEscrowServiceMarker = CSSM_TRUE; } + if (cssmExt->extnId.Length == APPLE_EXTENSION_PROVISIONING_PROFILE_SIGNING_LENGTH && + !memcmp(cssmExt->extnId.Data, CSSMOID_APPLE_EXTENSION_PROVISIONING_PROFILE_SIGNING.Data, + APPLE_EXTENSION_PROVISIONING_PROFILE_SIGNING_LENGTH)) { + /* this is the Provisioning Profile Signing extension */ + certInfo->foundProvisioningProfileSigningMarker = CSSM_TRUE; + } + if (cssmExt->extnId.Length == APPLE_EXTENSION_WWDR_INTERMEDIATE_LENGTH && + !memcmp(cssmExt->extnId.Data, CSSMOID_APPLE_EXTENSION_WWDR_INTERMEDIATE.Data, + APPLE_EXTENSION_WWDR_INTERMEDIATE_LENGTH)) { + /* this is the Apple WWDR extension */ + certInfo->foundAppleWWDRIntMarker = CSSM_TRUE; + } if(iSignVerifyCriticalExtension(cssmExt) != CSSM_OK) { /* BRRZAPP! Found an unknown extension marked critical */ @@ -333,7 +348,7 @@ static CSSM_RETURN iSignSearchUnknownExtensions( !memcmp(cssmExt->extnId.Data, CSSMOID_APPLE_EXTENSION_PASSBOOK_SIGNING.Data, APPLE_EXTENSION_CODE_SIGNING_LENGTH+1)) { /* this is the Passbook Signing extension */ - certInfo->foundPassbookSigning = CSSM_TRUE; + certInfo->foundPassbookSigningMarker = CSSM_TRUE; } if (cssmExt->extnId.Length == APPLE_EXTENSION_SYSINT2_INTERMEDIATE_LENGTH && !memcmp(cssmExt->extnId.Data, CSSMOID_APPLE_EXTENSION_SYSINT2_INTERMEDIATE.Data, @@ -353,6 +368,18 @@ static CSSM_RETURN iSignSearchUnknownExtensions( /* this is the Escrow Service Signing extension */ certInfo->foundEscrowServiceMarker = CSSM_TRUE; } + if (cssmExt->extnId.Length == APPLE_EXTENSION_PROVISIONING_PROFILE_SIGNING_LENGTH && + !memcmp(cssmExt->extnId.Data, CSSMOID_APPLE_EXTENSION_PROVISIONING_PROFILE_SIGNING.Data, + APPLE_EXTENSION_PROVISIONING_PROFILE_SIGNING_LENGTH)) { + /* this is the Provisioning Profile Signing extension */ + certInfo->foundProvisioningProfileSigningMarker = CSSM_TRUE; + } + if (cssmExt->extnId.Length == APPLE_EXTENSION_WWDR_INTERMEDIATE_LENGTH && + !memcmp(cssmExt->extnId.Data, CSSMOID_APPLE_EXTENSION_WWDR_INTERMEDIATE.Data, + APPLE_EXTENSION_WWDR_INTERMEDIATE_LENGTH)) { + /* this is the Apple WWDR extension */ + certInfo->foundAppleWWDRIntMarker = CSSM_TRUE; + } if(iSignVerifyCriticalExtension(cssmExt) != CSSM_OK) { /* BRRZAPP! Found an unknown extension marked critical */ @@ -606,7 +633,7 @@ static CSSM_BOOL tpCompareSubjectName( CSSM_BOOL ourRtn = CSSM_FALSE; const CSSM_OID *oidSrch; - const char x500_userid_oid[] = { 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x01 }; + const unsigned char x500_userid_oid[] = { 0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x01 }; CSSM_OID X500_UserID_OID = { sizeof(x500_userid_oid), (uint8*)x500_userid_oid }; fieldFound = false; @@ -658,7 +685,7 @@ static CSSM_BOOL tpCompareSubjectName( case SN_CommonName: { /* handle odd encodings that we need to convert to 8-bit */ - CFStringBuiltInEncodings encoding; + CFStringBuiltInEncodings encoding = kCFStringEncodingUnicode; CFDataRef cfd = NULL; bool doConvert = false; switch(ptvp->valueType) { @@ -935,7 +962,7 @@ static CSSM_BOOL tpIsNumeric( * CFStringRef. Caller owns and must release the result. NULL return means * unconvertible input "string". */ -static CFStringRef tpTvpToCfString( +static CFStringRef CF_RETURNS_RETAINED tpTvpToCfString( const CSSM_X509_TYPE_VALUE_PAIR *tvp) { CFStringBuiltInEncodings encoding; @@ -1960,7 +1987,7 @@ static CSSM_RETURN tp_verifyMacAppStoreReceiptOpts( if (!isCertInfo->basicConstraints.present) { - tpPolicyError("tp_verifyAppleIDSharingOpts: no basicConstraints in intermediate"); + tpPolicyError("tp_verifyMacAppStoreReceiptOpts: no basicConstraints in intermediate"); if (tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS)) return CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS; } @@ -2007,177 +2034,6 @@ bool certificatePoliciesContainsOID(const CE_CertPolicies *certPolicies, const C return false; } - -/* - * Verify Apple ID Sharing options. - * - * -- Do basic cert validation (OCSP-based certs) - * -- Validate that the cert is an Apple ID sharing cert: - * has a custom extension: OID: Apple ID Sharing Certificate ( 1 2 840 113635 100 4 7 ) - * (CSSMOID_APPLE_EXTENSION_APPLEID_SHARING) - * EKU should have both client and server authentication - * chains to the "Apple Application Integration Certification Authority" intermediate - * -- optionally has a client-specified common name, which is the Apple ID account's UUID. - - * -- Must have one intermediate cert ("Apple Application Integration Certification Authority") - * -- intermediate must have basic constraints with path length 0 - * -- intermediate has CSSMOID_APPLE_EXTENSION_AAI_INTERMEDIATE extension (OID 1 2 840 113635 100 6 2 3) - OR APPLE_EXTENSION_AAI_INTERMEDIATE_2 - */ - -static CSSM_RETURN tp_verifyAppleIDSharingOpts(TPCertGroup &certGroup, - const CSSM_DATA *fieldOpts, // optional Common Name - const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() -{ - unsigned numCerts = certGroup.numCerts(); - const iSignCertInfo *isCertInfo; - TPCertInfo *tpCert; - // const CE_BasicConstraints *bc; // currently unused - CE_ExtendedKeyUsage *eku; - CSSM_RETURN crtn = CSSM_OK; - unsigned int serverNameLen = 0; - const char *serverName = NULL; - - // The CSSM_APPLE_TP_SMIME_OPTIONS pointer is optional as is everything in it. - if (fieldOpts && fieldOpts->Data) - { - CSSM_APPLE_TP_SSL_OPTIONS *sslOpts = (CSSM_APPLE_TP_SSL_OPTIONS *)fieldOpts->Data; - switch (sslOpts->Version) - { - case CSSM_APPLE_TP_SSL_OPTS_VERSION: - if (fieldOpts->Length != sizeof(CSSM_APPLE_TP_SSL_OPTIONS)) - return CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; - break; - /* handle backwards compatibility here if necessary */ - default: - return CSSMERR_TP_INVALID_POLICY_IDENTIFIERS; - } - serverNameLen = sslOpts->ServerNameLen; - serverName = sslOpts->ServerName; - } - - //------------------------------------------------------------------------ - - if (numCerts != 3) - { - if (!certGroup.isAllowedError(CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH)) - { - tpPolicyError("tp_verifyAppleIDSharingOpts: numCerts %u", numCerts); - return CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH; - } - else - if (numCerts < 3) - { - /* this error allowed, but no intermediate...check leaf */ - goto checkLeaf; - } - } - - /* verify intermediate cert */ - isCertInfo = &certInfo[1]; - tpCert = certGroup.certAtIndex(1); - - if (!isCertInfo->basicConstraints.present) - { - tpPolicyError("tp_verifyAppleIDSharingOpts: no basicConstraints in intermediate"); - if (tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS)) - return CSSMERR_APPLETP_CS_NO_BASIC_CONSTRAINTS; - } - -checkLeaf: - - /* verify leaf cert */ - isCertInfo = &certInfo[0]; - tpCert = certGroup.certAtIndex(0); - - /* host name check is optional */ - if (serverNameLen != 0) - { - if (serverName == NULL) - return CSSMERR_TP_INVALID_POINTER; - - /* convert caller's hostname string to lower case */ - char *hostName = (char *)certGroup.alloc().malloc(serverNameLen); - memmove(hostName, serverName, serverNameLen); - tpToLower(hostName, serverNameLen); - - /* Check common name... */ - - bool fieldFound; - CSSM_BOOL match = tpCompareSubjectName(*tpCert, SN_CommonName, false, hostName, - serverNameLen, fieldFound); - - certGroup.alloc().free(hostName); - if (!match && tpCert->addStatusCode(CSSMERR_APPLETP_HOSTNAME_MISMATCH)) - return CSSMERR_APPLETP_HOSTNAME_MISMATCH; - } - - if (certInfo->certificatePolicies.present) - { - const CE_CertPolicies *certPolicies = - &isCertInfo->certificatePolicies.extnData->certPolicies; - if (!certificatePoliciesContainsOID(certPolicies, &CSSMOID_APPLEID_SHARING_CERT_POLICY)) - if (tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION)) - return CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; - } - else - if (tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION)) - return CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; - - if (!isCertInfo->extendKeyUsage.present) - { - tpPolicyError("tp_verifyAppleIDSharingOpts: no extendedKeyUse in leaf"); - if (tpCert->addStatusCode(CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE)) - return crtn ? crtn : CSSMERR_APPLETP_CS_NO_EXTENDED_KEY_USAGE; - - /* have to skip remainder */ - return CSSM_OK; - } - - // Check that certificate can do Client and Server Authentication (EKU) - eku = &isCertInfo->extendKeyUsage.extnData->extendedKeyUsage; - assert(eku != NULL); - if(eku->numPurposes != 2) - { - tpPolicyError("tp_verifyAppleIDSharingOpts: bad eku->numPurposes (%lu)", - (unsigned long)eku->numPurposes); - if (tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) - { - if (crtn == CSSM_OK) - crtn = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; - } - return crtn; - } - bool canDoClientAuth = false, canDoServerAuth = false, ekuError = false; - for (int ix=0;ix<2;ix++) - { - if (tpCompareOids(&eku->purposes[ix], &CSSMOID_ClientAuth)) - canDoClientAuth = true; - else - if (tpCompareOids(&eku->purposes[ix], &CSSMOID_ServerAuth)) - canDoServerAuth = true; - else - { - ekuError = true; - break; - } - } - - if (!(canDoClientAuth && canDoServerAuth)) - ekuError = true; - if (ekuError) - { - tpPolicyError("tp_verifyAppleIDSharingOpts: bad EKU in leaf"); - if (tpCert->addStatusCode(CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE)) - { - if (crtn == CSSM_OK) - crtn = CSSMERR_APPLETP_INVALID_EXTENDED_KEY_USAGE; - } - } - - return crtn; -} - /* * Verify Time Stamping (RFC3161) policy options. * @@ -2336,7 +2192,7 @@ static CSSM_RETURN tp_verifyPassbookSigningOpts(TPCertGroup &certGroup, } /* Check that Passbook Signing marker extension is present */ - if (!(isCertInfo->foundPassbookSigning == CSSM_TRUE)) { + if (!(isCertInfo->foundPassbookSigningMarker == CSSM_TRUE)) { tpPolicyError("tp_verifyPassbookSigningOpts: no Passbook Signing extension in leaf"); tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION); crtn = CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; @@ -2573,6 +2429,68 @@ static CSSM_RETURN tp_verifyPCSEscrowServiceSigningOpts(TPCertGroup &certGroup, return tp_verifyEscrowServiceCommon(certGroup, fieldOpts, certInfo, kSecCertificateProductionPCSEscrowRoot); } +/* + * Verify Provisioning Profile Signing policy options. + * + * -- Do basic cert validation (OCSP-based certs) + * -- Chains to the Apple root CA + * -- Leaf has Provisioning Profile marker OID (1.2.840.113635.100.4.11) + * -- Intermediate has WWDR marker OID (1.2.840.113635.100.6.2.1) + */ +static CSSM_RETURN tp_verifyProvisioningProfileSigningOpts(TPCertGroup &certGroup, + const CSSM_DATA *fieldOpts, + const iSignCertInfo *certInfo) // all certs, size certGroup.numCerts() +{ + unsigned numCerts = certGroup.numCerts(); + const iSignCertInfo *isCertInfo; + TPCertInfo *tpCert; + CSSM_RETURN crtn = CSSM_OK; + + isCertInfo = &certInfo[0]; + tpCert = certGroup.certAtIndex(0); + + /* Check that cert chain is anchored by the Apple Root CA */ + if (numCerts < 3) { + tpPolicyError("tp_verifyProvisioningProfileSigningOpts: numCerts %u", numCerts); + crtn = CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH; + goto cleanup; + } + else { + tpCert = certGroup.certAtIndex(numCerts-1); + const CSSM_DATA *certData = tpCert->itemData(); + unsigned char digest[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1(certData->Data, (CC_LONG)certData->Length, digest); + if (memcmp(digest, kAppleCASHA1, sizeof(digest))) { + tpPolicyError("tp_verifyProvisioningProfileSigningOpts: invalid anchor for policy"); + tpCert->addStatusCode(CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH); + crtn = CSSMERR_APPLETP_CS_BAD_CERT_CHAIN_LENGTH; + goto cleanup; + } + } + + /* Check that Provisioning Profile Signing marker extension is present */ + if (!(isCertInfo->foundProvisioningProfileSigningMarker == CSSM_TRUE)) { + tpPolicyError("tp_verifyProvisioningProfileSigningOpts: no Provisioning Profile Signing extension in leaf"); + tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION); + crtn = CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; + goto cleanup; + } + + /* Check that Apple WWDR marker extension is present in intermediate */ + isCertInfo = &certInfo[1]; + tpCert = certGroup.certAtIndex(1); + if (!(isCertInfo->foundAppleWWDRIntMarker == CSSM_TRUE)) { + tpPolicyError("tp_verifyProvisioningProfileSigningOpts: intermediate marker extension not found"); + tpCert->addStatusCode(CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION); + crtn = CSSMERR_APPLETP_MISSING_REQUIRED_EXTENSION; + goto cleanup; + } + +cleanup: + return crtn; + +} + /* * Verify Configuration Profile Signing policy options. * @@ -3233,8 +3151,11 @@ CSSM_RETURN tp_policyVerify( policyError = tp_verifyMacAppStoreReceiptOpts(*certGroup, policyFieldData, certInfo); break; case kTP_AppleIDSharing: - policyError = tp_verifyAppleIDSharingOpts(*certGroup, policyFieldData, certInfo); - break; + /* As of macOS 10.12, this code path should be unused. Until we can remove this + * module entirely, ensure that no Apple ID evaluations take this path. [10119995] */ + tpPolicyError("tp_policyVerify: unexpected attempt to use legacy kTP_AppleIDSharing"); + policyFail = CSSM_TRUE; + abort(); case kTP_TimeStamping: policyError = tp_verifyTimeStampingOpts(*certGroup, policyFieldData, certInfo); break; @@ -3259,6 +3180,9 @@ CSSM_RETURN tp_policyVerify( case kTP_PCSEscrowService: policyError = tp_verifyPCSEscrowServiceSigningOpts(*certGroup, policyFieldData, certInfo); break; + case kTP_ProvisioningProfileSigning: + policyError = tp_verifyProvisioningProfileSigningOpts(*certGroup, policyFieldData, certInfo); + break; case kTPx509Basic: case kTPiSign: case kCrlPolicy: