Esempio n. 1
0
//
// Check to see if a certificate contains a particular field, by OID. This works for extensions,
// even ones not recognized by the local CL. It does not return any value, only presence.
//
bool certificateHasField(SecCertificateRef cert, const CSSM_OID &oid)
{
	assert(cert);
	CSSM_DATA *value;
	switch (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &oid, &value)) {
	case errSecSuccess:
		MacOSError::check(SecCertificateReleaseFirstFieldValue(cert, &oid, value));
		return true;					// extension found by oid
	case errSecUnknownTag:
		break;							// oid not recognized by CL - continue below
	default:
		MacOSError::throwMe(rc);		// error: fail
	}
	
	// check the CL's bag of unrecognized extensions
	CSSM_DATA **values;
	bool found = false;
	if (SecCertificateCopyFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, &values))
		return false;	// no unrecognized extensions - no match
	if (values)
		for (CSSM_DATA **p = values; *p; p++) {
			const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)(*p)->Data;
			if (oid == ext->extnId) {
				found = true;
				break;
			}
		}
	MacOSError::check(SecCertificateReleaseFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, values));
	return found;
}
Esempio n. 2
0
// Return the decoded value of the subjectKeyID extension. The caller should 
// free up the storage allocated in retItem->data.
SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert, SECItem *retItem)
{
    CSSM_DATA_PTR fieldValue = NULL;
    OSStatus ortn;
    CSSM_X509_EXTENSION *extp;
    CE_SubjectKeyID *skid;
    
    ortn = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_SubjectKeyIdentifier,
	&fieldValue);
    if(ortn || (fieldValue == NULL)) {
	/* this cert doesn't have that extension */
	return SECFailure;
    }
    extp = (CSSM_X509_EXTENSION *)fieldValue->Data;
    skid = (CE_SubjectKeyID *)extp->value.parsedValue;
    retItem->Data = (uint8 *)PORT_Alloc(skid->Length);
    retItem->Length = skid->Length;
    memmove(retItem->Data, skid->Data, retItem->Length);
    SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_SubjectKeyIdentifier,
	fieldValue);
    return SECSuccess;
}
Esempio n. 3
0
//
// Retrieve X.509 policy extension OIDs, if any.
// This currently ignores policy qualifiers.
//
bool certificateHasPolicy(SecCertificateRef cert, const CSSM_OID &policyOid)
{
	bool matched = false;
	assert(cert);
	CSSM_DATA *data;
	if (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_CertificatePolicies, &data))
		MacOSError::throwMe(rc);
	if (data && data->Data && data->Length == sizeof(CSSM_X509_EXTENSION)) {
		const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)data->Data;
		assert(ext->format == CSSM_X509_DATAFORMAT_PARSED);
		const CE_CertPolicies *policies = (const CE_CertPolicies *)ext->value.parsedValue;
		if (policies)
			for (unsigned int n = 0; n < policies->numPolicies; n++) {
				const CE_PolicyInformation &cp = policies->policies[n];
				if (cp.certPolicyId == policyOid) {
					matched = true;
					break;
				}
			}
	}
	SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_PolicyConstraints, data);
	return matched;
}
Esempio n. 4
0
/*
 * Determine the basic signing algorithm, without the digest, component, of
 * a cert. The returned algorithm will be RSA, DSA, or ECDSA.
 */
static OSStatus sslCertSignerAlg(
	SecCertificateRef certRef,
	CSSM_ALGORITHMS *signerAlg)
{
	OSStatus ortn;
	CSSM_DATA_PTR fieldPtr;
	CSSM_X509_ALGORITHM_IDENTIFIER *algId;
	CSSM_ALGORITHMS sigAlg;

	/*
	 * Extract the full signature algorithm OID
	 */
	*signerAlg = CSSM_ALGID_NONE;
	ortn = SecCertificateCopyFirstFieldValue(certRef,
		&CSSMOID_X509V1SignatureAlgorithm,
		&fieldPtr);
	if(ortn) {
		return ortn;
	}
	if(fieldPtr->Length != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)) {
		sslErrorLog("sslCertSignerAlg() length error\n");
		ortn = errSSLCrypto;
		goto errOut;
	}
	algId = (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldPtr->Data;
	if(!cssmOidToAlg(&algId->algorithm, &sigAlg)) {
		/* Only way this could happen is if we're given a bad cert */
		sslErrorLog("sslCertSignerAlg() bad sigAlg OID\n");
		ortn = paramErr;
		goto errOut;
	}

	/*
	 * OK we have the full signature algorithm as a CSSM_ALGORITHMS.
	 * Extract the core signature alg.
	 */
	switch(sigAlg) {
		case CSSM_ALGID_RSA:
		case CSSM_ALGID_MD2WithRSA:
		case CSSM_ALGID_MD5WithRSA:
		case CSSM_ALGID_SHA1WithRSA:
		case CSSM_ALGID_SHA224WithRSA:
		case CSSM_ALGID_SHA256WithRSA:
		case CSSM_ALGID_SHA384WithRSA:
		case CSSM_ALGID_SHA512WithRSA:
			*signerAlg = CSSM_ALGID_RSA;
			break;
		case CSSM_ALGID_SHA1WithECDSA:
		case CSSM_ALGID_SHA224WithECDSA:
		case CSSM_ALGID_SHA256WithECDSA:
		case CSSM_ALGID_SHA384WithECDSA:
		case CSSM_ALGID_SHA512WithECDSA:
		case CSSM_ALGID_ECDSA:
		case CSSM_ALGID_ECDSA_SPECIFIED:
			*signerAlg = CSSM_ALGID_ECDSA;
			break;
		case CSSM_ALGID_DSA:
		case CSSM_ALGID_SHA1WithDSA:
			*signerAlg = CSSM_ALGID_DSA;
			break;
		default:
			sslErrorLog("sslCertSignerAlg() unknown sigAlg\n");
			ortn = paramErr;
			break;
	}
errOut:
	SecCertificateReleaseFirstFieldValue(certRef,
		&CSSMOID_X509V1SignatureAlgorithm, fieldPtr);
	return ortn;
}
Esempio n. 5
0
static bool isSoftwareUpdateDevelopment(SecTrustRef trust) {
    bool isPolicy = false, isEKU = false;
    CFArrayRef policies = NULL;

    /* Policy used to evaluate was SWUpdateSigning */
    SecTrustCopyPolicies(trust, &policies);
    if (policies) {
        SecPolicyRef swUpdatePolicy = SecPolicyCreateAppleSWUpdateSigning();
        if (swUpdatePolicy && CFArrayContainsValue(policies, CFRangeMake(0, CFArrayGetCount(policies)),
                                                   swUpdatePolicy)) {
            isPolicy = true;
        }
        if (swUpdatePolicy) { CFRelease(swUpdatePolicy); }
        CFRelease(policies);
    }
    if (!isPolicy) {
        return false;
    }

    /* Only error was EKU on the leaf */
    CFArrayRef details = SecTrustCopyFilteredDetails(trust);
    CFIndex ix, count = CFArrayGetCount(details);
    bool hasDisqualifyingError = false;
    for (ix = 0; ix < count; ix++) {
        CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, ix);
        if (ix == 0) { // Leaf
            if (CFDictionaryGetCount(detail) != 1 || // One error
                CFDictionaryGetValue(detail, CFSTR("ExtendedKeyUsage")) != kCFBooleanFalse) { // kSecPolicyCheckExtendedKeyUsage
                hasDisqualifyingError = true;
                break;
            }
        } else {
            if (CFDictionaryGetCount(detail) > 0) { // No errors on other certs
                hasDisqualifyingError = true;
                break;
            }
        }
    }
    CFReleaseSafe(details);
    if (hasDisqualifyingError) {
        return false;
    }

    /* EKU on the leaf is the Apple Development Code Signing OID */
    SecCertificateRef leaf = SecTrustGetCertificateAtIndex(trust, 0);
    CSSM_DATA *fieldValue = NULL;
    if (errSecSuccess != SecCertificateCopyFirstFieldValue(leaf, &CSSMOID_ExtendedKeyUsage, &fieldValue)) {
        return false;
    }
    if (fieldValue && fieldValue->Data && fieldValue->Length == sizeof(CSSM_X509_EXTENSION)) {
        const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)fieldValue->Data;
        if (ext->format == CSSM_X509_DATAFORMAT_PARSED) {
            const CE_ExtendedKeyUsage *ekus = (const CE_ExtendedKeyUsage *)ext->value.parsedValue;
            if (ekus && (ekus->numPurposes == 1) && ekus->purposes[0].Data &&
                (ekus->purposes[0].Length == CSSMOID_APPLE_EKU_CODE_SIGNING_DEV.Length) &&
                (memcmp(ekus->purposes[0].Data, CSSMOID_APPLE_EKU_CODE_SIGNING_DEV.Data,
                        ekus->purposes[0].Length) == 0)) {
                isEKU = true;
            }
        }
    }
    SecCertificateReleaseFirstFieldValue(leaf, &CSSMOID_ExtendedKeyUsage, fieldValue);
    return isEKU;
}