Ejemplo n.º 1
1
extern "C" PAL_X509ContentType AppleCryptoNative_X509GetContentType(uint8_t* pbData, int32_t cbData)
{
    if (pbData == nullptr || cbData < 0)
        return PAL_X509Unknown;

    CFDataRef cfData = CFDataCreateWithBytesNoCopy(nullptr, pbData, cbData, kCFAllocatorNull);

    if (cfData == nullptr)
        return PAL_X509Unknown;

    // The sniffing order is:
    // * X509 DER
    // * PKCS7 PEM/DER
    // * PKCS12 DER (or PEM if Apple has non-standard support for that)
    // * X509 PEM (or DER, but that already matched)
    //
    // If the X509 PEM check is done first SecItemImport will erroneously match
    // some PKCS#7 blobs and say they were certificates.
    //
    // Likewise, if the X509 DER check isn't done first, Apple will report it as
    // being a PKCS#7.
    SecCertificateRef certref = SecCertificateCreateWithData(nullptr, cfData);

    if (certref != nullptr)
    {
        CFRelease(certref);
        return PAL_Certificate;
    }

    SecExternalFormat dataFormat = kSecFormatPKCS7;
    SecExternalFormat actualFormat = dataFormat;
    SecExternalItemType itemType = kSecItemTypeAggregate;
    SecExternalItemType actualType = itemType;

    OSStatus osStatus = SecItemImport(cfData, nullptr, &actualFormat, &actualType, 0, nullptr, nullptr, nullptr);

    if (osStatus == noErr)
    {
        if (actualType == itemType && actualFormat == dataFormat)
        {
            return PAL_Pkcs7;
        }
    }

    dataFormat = kSecFormatPKCS12;
    actualFormat = dataFormat;
    itemType = kSecItemTypeAggregate;
    actualType = itemType;

    osStatus = SecItemImport(cfData, nullptr, &actualFormat, &actualType, 0, nullptr, nullptr, nullptr);

    if (osStatus == errSecPassphraseRequired)
    {
        dataFormat = kSecFormatPKCS12;
        actualFormat = dataFormat;
        itemType = kSecItemTypeAggregate;
        actualType = itemType;

        SecItemImportExportKeyParameters importParams = {};
        importParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
        importParams.passphrase = CFSTR("");

        osStatus = SecItemImport(cfData, nullptr, &actualFormat, &actualType, 0, &importParams, nullptr, nullptr);

        CFRelease(importParams.passphrase);
        importParams.passphrase = nullptr;
    }

    if (osStatus == noErr || osStatus == errSecPkcs12VerifyFailure)
    {
        if (actualType == itemType && actualFormat == dataFormat)
        {
            return PAL_Pkcs12;
        }
    }

    dataFormat = kSecFormatX509Cert;
    actualFormat = dataFormat;
    itemType = kSecItemTypeCertificate;
    actualType = itemType;

    osStatus = SecItemImport(cfData, nullptr, &actualFormat, &actualType, 0, nullptr, nullptr, nullptr);

    if (osStatus == noErr)
    {
        if (actualType == itemType && actualFormat == dataFormat)
        {
            return PAL_Certificate;
        }
    }

    return PAL_X509Unknown;
}
Ejemplo n.º 2
0
static int tls_create_trust_from_certs(const SSLCertificate *cert, SecTrustRef *trustRef)
{
    int err;
    CFMutableArrayRef certArray = NULL;
    CFDataRef certData = NULL;
    SecCertificateRef cfCert = NULL;

    if(cert==NULL) {
        test_printf("No certs, do not create SecTrustRef\n");
        *trustRef = NULL;
        return 0;
    }

    certArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
    while(cert) {
        base64_dump(cert->derCert, "CERTIFICATE");
        require_action((certData = CFDataCreate(kCFAllocatorDefault, cert->derCert.data, cert->derCert.length)), out, err = errSecAllocate);
        require_action((cfCert = SecCertificateCreateWithData(kCFAllocatorDefault, certData)), out, err = errSecAllocate);
        CFArrayAppendValue(certArray, cfCert);
        CFReleaseNull(cfCert);
        CFReleaseNull(certData);
        cert=cert->next;
    }

    require_noerr((err=SecTrustCreateWithCertificates(certArray, NULL, trustRef)), out);

out:
    CFReleaseSafe(certData);
    CFReleaseSafe(cfCert);
    CFReleaseSafe(certArray);

    return err;
}
Ejemplo n.º 3
0
/* Convert cert in DER format into an CFArray of SecCertificateRef */
CFArrayRef
tls_get_peer_certs(const SSLCertificate *certs)
{
    const SSLCertificate *cert;

    CFMutableArrayRef certArray = NULL;
    CFDataRef certData = NULL;
    SecCertificateRef cfCert = NULL;

    certArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
    require(certArray, out);
    cert = certs;
    while(cert) {
        require((certData = CFDataCreate(kCFAllocatorDefault, cert->derCert.data, cert->derCert.length)), out);
        require((cfCert = SecCertificateCreateWithData(kCFAllocatorDefault, certData)), out);
        CFArrayAppendValue(certArray, cfCert);
        CFReleaseNull(cfCert);
        CFReleaseNull(certData);
        cert=cert->next;
    }

    return certArray;

out:
    CFReleaseNull(cfCert);
    CFReleaseNull(certData);
    CFReleaseNull(certArray);
    return NULL;
}
Ejemplo n.º 4
0
static void SecCAIssuerRequestCompleted(asynchttp_t *http,
    CFTimeInterval maxAge) {
    /* Cast depends on http being first field in struct SecCAIssuerRequest. */
    SecCAIssuerRequestRef request = (SecCAIssuerRequestRef)http;
    CFDataRef data = (request->http.response ?
        CFHTTPMessageCopyBody(request->http.response) : NULL);
    if (data) {
        SecCertificateRef parent = SecCertificateCreateWithData(NULL, data);
        CFRelease(data);
        if (parent) {
            /* We keep responses in the cache for at least 7 days, or longer
             if the http response tells us to keep it around for more. */
            if (maxAge < SECONDS_PER_DAY * 7)
                maxAge = SECONDS_PER_DAY * 7;
            CFAbsoluteTime expires = CFAbsoluteTimeGetCurrent() + maxAge;
            CFURLRef issuer = CFArrayGetValueAtIndex(request->issuers,
                                                     request->issuerIX - 1);
            SecCAIssuerCacheAddCertificate(parent, issuer, expires);
            CFArrayRef parents = SecCAIssuerConvertToParents(
                request->certificate, parent);
            if (parents) {
                secdebug("caissuer", "response: %@ good", http->response);
                request->callback(request->context, parents);
                CFRelease(parents);
                SecCAIssuerRequestRelease(request);
                return;
            }
        }
    }

    secdebug("caissuer", "response: %@ not parent, trying next caissuer",
        http->response);
    SecCAIssuerRequestIssue(request);
}
static void tests(void)
{
    SecTrustResultType trustResult = kSecTrustResultProceed;
	SecPolicyRef policy = NULL;
	SecTrustRef trust = NULL;
	CFArrayRef certs = NULL;
	
	CFDataRef appleid_record_signing_cert_data = NULL;
	isnt(appleid_record_signing_cert_data = CFDataCreate(kCFAllocatorDefault, kLeafCert, sizeof(kLeafCert)), 
		NULL, "Get the AppleID Record Signing Leaf Certificate Data");
		
	SecCertificateRef appleid_record_signing_cert = NULL;
	isnt(appleid_record_signing_cert = SecCertificateCreateWithData(kCFAllocatorDefault, appleid_record_signing_cert_data),
		NULL, "Get the AppleID Record Signing Leaf Certificate Data");
		
	CFDataRef appleid_intermediate_cert_data = NULL;
	isnt(appleid_intermediate_cert_data = CFDataCreate(kCFAllocatorDefault, kIntermediateCert, sizeof(kIntermediateCert)), 
		NULL, "Get the AppleID Intermediate Certificate Data");
		
	SecCertificateRef appleid_intermediate_cert = NULL;
	isnt(appleid_intermediate_cert = SecCertificateCreateWithData(kCFAllocatorDefault, appleid_intermediate_cert_data),
		NULL, "Get the AppleID Intermediate Certificate");
		
	SecCertificateRef certs_to_use[] = {appleid_record_signing_cert, appleid_intermediate_cert};
		
	certs = CFArrayCreate(NULL, (const void **)certs_to_use, 2, NULL);
		
	isnt(policy = SecPolicyCreateAppleIDValidationRecordSigningPolicy(),
		NULL, "Create AppleID Record signing policy SecPolicyRef");
				
	ok_status(SecTrustCreateWithCertificates(certs, policy, &trust),
        "Create AppleID record signing leaf");

	ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate escrow service trust for club 1");
		
	is_status(trustResult, kSecTrustResultUnspecified,
		"Trust is kSecTrustResultUnspecified AppleID record signing leaf");
		
	CFReleaseSafe(trust);
	CFReleaseSafe(policy);
	CFReleaseSafe(certs);
	CFReleaseSafe(appleid_record_signing_cert);
    CFReleaseSafe(appleid_intermediate_cert_data);
    CFReleaseSafe(appleid_record_signing_cert_data);
}
bool decode(ArgumentDecoder* decoder, RetainPtr<SecCertificateRef>& result)
{
    RetainPtr<CFDataRef> data;
    if (!decode(decoder, data))
        return false;

    result.adoptCF(SecCertificateCreateWithData(0, data.get()));
    return true;
}
Ejemplo n.º 7
0
  virtual void SetUp() {
    std::string raw;
    CFDataRef data;

    raw = base64Decode(getCACertificateContent());
    data = CFDataCreate(NULL, (const UInt8*)raw.c_str(), (CFIndex)raw.size());
    cert = SecCertificateCreateWithData(NULL, data);
    CFRelease(data);
  }
bool verify_X509_cert_chain(const std::vector<std::string> &certChain, const std::string &hostName)
{
    // Build up CFArrayRef with all the certificates.
    // All this code is basically just to get into the correct structures for the Apple APIs.
    // Copies are avoided whenever possible.
    std::vector<cf_ref<SecCertificateRef>> certs;
    for(const auto & certBuf : certChain)
    {
        cf_ref<CFDataRef> certDataRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
                                                                   reinterpret_cast<const unsigned char*>(certBuf.c_str()),
                                                                   certBuf.size(),
                                                                   kCFAllocatorNull);
        if(certDataRef.get() == nullptr)
        {
            return false;
        }

        cf_ref<SecCertificateRef> certObj = SecCertificateCreateWithData(nullptr, certDataRef.get());
        if(certObj.get() == nullptr)
        {
            return false;
        }
        certs.push_back(std::move(certObj));
    }
    cf_ref<CFArrayRef> certsArray = CFArrayCreate(kCFAllocatorDefault, const_cast<const void **>(reinterpret_cast<void **>(&certs[0])), certs.size(), nullptr);
    if(certsArray.get() == nullptr)
    {
        return false;
    }

    // Create trust management object with certificates and SSL policy.
    // Note: SecTrustCreateWithCertificates expects the certificate to be
    // verified is the first element.
    cf_ref<CFStringRef> cfHostName = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault,
                                                                    hostName.c_str(),
                                                                    kCFStringEncodingASCII,
                                                                    kCFAllocatorNull);
    if(cfHostName.get() == nullptr)
    {
        return false;
    }
    cf_ref<SecPolicyRef> policy = SecPolicyCreateSSL(true /* client side */, cfHostName.get());
    cf_ref<SecTrustRef> trust;
    OSStatus status = SecTrustCreateWithCertificates(certsArray.get(), policy.get(), &trust.get());
    if(status == noErr)
    {
        // Perform actual certificate verification.
        SecTrustResultType trustResult;
        status = SecTrustEvaluate(trust.get(), &trustResult);
        if(status == noErr && (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed))
        {
            return true;
        }
    }

    return false;
}
Ejemplo n.º 9
0
static void build_trust_chains(const void *key, const void *value, 
    void *context)
{
    CFMutableDictionaryRef identity_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 
        0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    SecKeyRef private_key = NULL;
    SecCertificateRef cert = NULL;
    SecIdentityRef identity = NULL;
    SecPolicyRef policy = NULL;
    CFMutableArrayRef cert_chain = NULL, eval_chain = NULL;
    SecTrustRef trust = NULL;
    build_trust_chains_context * a_build_trust_chains_context = (build_trust_chains_context*)context;

    CFDataRef key_bytes = CFDictionaryGetValue(value, CFSTR("key"));
    require(key_bytes, out);
    CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert"));
    require(cert_bytes, out);

    /* p12import only passes up rsa keys */
    require (private_key = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault, 
        CFDataGetBytePtr(key_bytes), CFDataGetLength(key_bytes),
        kSecKeyEncodingPkcs1), out);
    require(cert = SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes), out);
    require(identity = SecIdentityCreate(kCFAllocatorDefault, cert, private_key), out);
    CFDictionarySetValue(identity_dict, kSecImportItemIdentity, identity);
    
    eval_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
    require(eval_chain, out);
    CFArrayAppendValue(eval_chain, cert);
    CFRange all_certs = { 0, CFArrayGetCount(a_build_trust_chains_context->certs) };
    CFArrayAppendArray(eval_chain, a_build_trust_chains_context->certs, all_certs);
    require(policy = SecPolicyCreateBasicX509(), out);
    SecTrustResultType result;
    SecTrustCreateWithCertificates(eval_chain, policy, &trust);
    require(trust, out);
    SecTrustEvaluate(trust, &result);
    CFDictionarySetValue(identity_dict, kSecImportItemTrust, trust);
    
    require(cert_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks), out);
    CFIndex cert_chain_length = SecTrustGetCertificateCount(trust);
    int i;
    for (i = 0; i < cert_chain_length; i++)
        CFArrayAppendValue(cert_chain, SecTrustGetCertificateAtIndex(trust, i));
    CFDictionarySetValue(identity_dict, kSecImportItemCertChain, cert_chain);
    
    CFArrayAppendValue(a_build_trust_chains_context->identities, identity_dict);
out:
    CFReleaseSafe(identity_dict);
    CFReleaseSafe(identity);
    CFReleaseSafe(private_key);
    CFReleaseSafe(cert);
    CFReleaseSafe(policy);
    CFReleaseSafe(cert_chain);
    CFReleaseSafe(eval_chain);
    CFReleaseSafe(trust);
}
Ejemplo n.º 10
0
  virtual void SetUp() {
    std::string raw;
    CFDataRef data;

    raw = base64Decode(getCACertificateContent());
    data =
        CFDataCreate(nullptr, (const UInt8 *)raw.c_str(), (CFIndex)raw.size());
    cert = SecCertificateCreateWithData(nullptr, data);
    cert_der_data = SecCertificateCopyData(cert);
    auto bytes = CFDataGetBytePtr(cert_der_data);
    x_cert = d2i_X509(nullptr, &bytes, CFDataGetLength(cert_der_data));

    CFRelease(data);
  }
Ejemplo n.º 11
0
static void collect_certs(const void *key, const void *value, void *context)
{
    if (!CFDictionaryContainsKey(value, CFSTR("key"))) {
        CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert"));
        if (!cert_bytes)
            return;
        SecCertificateRef cert = 
            SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes);
        if (!cert)
            return;
        CFMutableArrayRef cert_array = (CFMutableArrayRef)context;
        CFArrayAppendValue(cert_array, cert);
        CFRelease(cert);
    }
}
Ejemplo n.º 12
0
static CFArrayRef copyCertChainFromSignature(xar_signature_t sig)
{
	unsigned count = xar_signature_get_x509certificate_count(sig);
	CFRef<CFMutableArrayRef> certs = makeCFMutableArray(0);
	for (unsigned ix = 0; ix < count; ix++) {
		const uint8_t *data;
		uint32_t length;
		if (xar_signature_get_x509certificate_data(sig, ix, &data, &length) == 0) {
			CFTempData cdata(data, length);
			CFRef<SecCertificateRef> cert = SecCertificateCreateWithData(NULL, cdata);
			CFArrayAppendValue(certs, cert.get());
		}
	}
	return certs.yield();
}
Ejemplo n.º 13
0
/********************************************************
 *********** SecSystemAnchorSource object ************
 ********************************************************/
static bool SecSystemAnchorSourceCopyParents(
	SecCertificateSourceRef source, SecCertificateRef certificate,
        void *context, SecCertificateSourceParents callback) {
#ifndef SECITEM_SHIM_OSX
    CFMutableArrayRef parents = NULL;
    CFDataRef nic = SecCertificateGetNormalizedIssuerContent(certificate);
    /* 64 bits cast: the worst that can happen here is we truncate the length and match an actual anchor.
       It does not matter since we would be returning the wrong anchors */
    assert((unsigned long)CFDataGetLength(nic)<UINT_MAX); /* Debug check. correct as long as CFIndex is signed long */
    const struct subject_to_ix_t *i2x =
        subject_to_anchor_ix((const char *)CFDataGetBytePtr(nic),
            (unsigned int)CFDataGetLength(nic));
    require_quiet(i2x, errOut);
    int anchor_ix = i2x->anchor_ix;
    CFIndex capacity = 0;
    do {
        ++capacity;
    } while ((anchor_ix = anchorslist[anchor_ix].next_same_subject));

    parents = CFArrayCreateMutable(kCFAllocatorDefault, capacity,
        &kCFTypeArrayCallBacks);
    anchor_ix = i2x->anchor_ix;
    do {
        const void *anchor = NULL;
        CFDataRef anchor_data = NULL;

        require_quiet(anchor_data = CFDataCreateWithBytesNoCopy(
            kCFAllocatorDefault, (const UInt8 *)anchorslist[anchor_ix].data,
            anchorslist[anchor_ix].length, kCFAllocatorNull), errOut);
        anchor = SecCertificateCreateWithData(kCFAllocatorDefault,
            anchor_data);
        CFRelease(anchor_data);
        if (anchor) {
            CFArrayAppendValue(parents, anchor);
            CFRelease(anchor);
        }
    } while ((anchor_ix = anchorslist[anchor_ix].next_same_subject));

errOut:
    callback(context, parents);
    CFReleaseSafe(parents);
#endif
    return true;
}
static bool decodeCertificateChain(Decoder& decoder, RetainPtr<CFArrayRef>& certificateChain)
{
    uint64_t size;
    if (!decoder.decode(size))
        return false;

    auto array = adoptCF(CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));

    for (size_t i = 0; i < size; ++i) {
        RetainPtr<CFDataRef> data;
        if (!decodeCFData(decoder, data))
            return false;

        auto certificate = adoptCF(SecCertificateCreateWithData(0, data.get()));
        CFArrayAppendValue(array.get(), certificate.get());
    }

    certificateChain = WTFMove(array);
    return true;
}
Ejemplo n.º 15
0
/* Extract public SecKeyRef from Certificate Chain */
static
int sslCopyPeerPubKey(const SSLCertificate *certchain,
                      SecKeyRef            *pubKey)
{
    int err;
    check(pubKey);
    SecTrustRef trust = NULL;
    const SSLCertificate *cert;
    CFMutableArrayRef certArray = NULL;
    CFDataRef certData = NULL;
    SecCertificateRef cfCert = NULL;

    err = errSSLInternal;

    certArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
    cert = certchain;
    while(cert) {
        require((certData = CFDataCreate(kCFAllocatorDefault, cert->derCert.data, cert->derCert.length)), out);
        require((cfCert = SecCertificateCreateWithData(kCFAllocatorDefault, certData)), out);
        CFArrayAppendValue(certArray, cfCert);
        CFReleaseNull(cfCert);
        CFReleaseNull(certData);
        cert=cert->next;
    }

    require_noerr((err=SecTrustCreateWithCertificates(certArray, NULL, &trust)), out);
    SecKeyRef key = SecTrustCopyPublicKey(trust);
    require_action(key, out, err=-9808); // errSSLBadCert

    *pubKey = key;

    err = errSecSuccess;

out:
    CFReleaseSafe(certData);
    CFReleaseSafe(cfCert);
    CFReleaseSafe(trust);
    CFReleaseSafe(certArray);

    return err;
}
/* Test basic add delete update copy matching stuff. */
static void tests(void)
{
	SecCertificateRef cert0, cert1, cert2, cert3, cert4, cert5, cert6;
	isnt(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)),
		NULL, "create cert0");
	isnt(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)),
		NULL, "create cert1");

    CFDataRef cert2Data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
        _c2, sizeof(_c2), kCFAllocatorNull);
	isnt(cert2 = SecCertificateCreateWithData(kCFAllocatorDefault, cert2Data),
		NULL, "create cert2");
    CFReleaseNull(cert2Data);

	isnt(cert3 = SecCertificateCreateWithBytes(NULL, _phased_c3, sizeof(_phased_c3)),
		NULL, "create cert3");

    CFDataRef cert4data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
        pem, sizeof(pem), kCFAllocatorNull);
    ok(cert4 = SecCertificateCreateWithPEM(NULL, cert4data), "create cert from pem");
    CFReleaseNull(cert4data);

	isnt(cert5 = SecCertificateCreateWithBytes(NULL, _elektron_v1_cert_der,
        sizeof(_elektron_v1_cert_der)), NULL, "create cert5");

	isnt(cert6 = SecCertificateCreateWithBytes(NULL, _wapi_as_der,
        sizeof(_wapi_as_der)), NULL, "create cert6");

    ok(SecCertificateIsSelfSignedCA(cert0), "cert0 is CA");
    ok(!SecCertificateIsSelfSignedCA(cert1), "cert1 is not CA");
    ok(SecCertificateIsSelfSignedCA(cert5), "cert5 is v1 CA");

    CFStringRef subjectSummary, issuerSummary;
    isnt(subjectSummary = SecCertificateCopySubjectSummary(cert1), NULL,
        "cert1 has a subject summary");
    isnt(issuerSummary = SecCertificateCopyIssuerSummary(cert1), NULL,
        "cert1 has an issuer summary");

    ok(subjectSummary && CFEqual(subjectSummary, CFSTR("www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign, VeriSign International Server CA - Class 3, VeriSign, Inc.")),
        "subject summary is \"www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign, VeriSign International Server CA - Class 3, VeriSign, Inc.\"");
    ok(issuerSummary && CFEqual(issuerSummary,
        CFSTR("Class 3 Public Primary Certification Authority")),
        "issuer summary is \"Class 3 Public Primary Certification Authority\"");

    CFArrayRef ntPrincipalNames;
    ok(ntPrincipalNames = SecCertificateCopyNTPrincipalNames(cert2),
        "SecCertificateCopyNTPrincipalNames");
    is(CFArrayGetCount(ntPrincipalNames), 1, "we got 1 princialname back");
    CFStringRef principal = (CFStringRef)CFArrayGetValueAtIndex(ntPrincipalNames, 0);
    ok(CFEqual(principal, CFSTR("*****@*****.**")),
        "first principal is [email protected]");
    CFReleaseSafe(ntPrincipalNames);

	CFReleaseSafe(subjectSummary);
	CFReleaseSafe(issuerSummary);

    isnt(subjectSummary = SecCertificateCopySubjectSummary(cert3), NULL,
        "cert3 has a subject summary");
	/* @@@ this causes a double free without an extra retain in obtainSummaryFromX501Name():
	       summary->description = string = copyDERThingDescription(kCFAllocatorDefault, value, true); */
	CFReleaseSafe(subjectSummary);

    isnt(subjectSummary = SecCertificateCopySubjectSummary(cert4), NULL,
        "cert4 has a subject summary");
    ok(subjectSummary && CFEqual(subjectSummary, CFSTR("S5L8900 Secure Boot")),
        "cert4 is S5L8900 Secure Boot");
	CFReleaseSafe(subjectSummary);

    CFStringRef desc = NULL;
    ok(desc = CFCopyDescription(cert4), "cert4 CFCopyDescription works");

	CFReleaseSafe(cert0);
	CFReleaseSafe(cert1);
	CFReleaseSafe(cert2);
	CFReleaseSafe(cert3);
	CFReleaseSafe(cert4);
	CFReleaseSafe(cert5);
	CFReleaseSafe(cert6);
	CFReleaseNull(desc);
}
Ejemplo n.º 17
0
bool mailcore::checkCertificate(mailstream * stream, String * hostname)
{
#if __APPLE__
    bool result = false;
    CFStringRef hostnameCFString;
    SecPolicyRef policy;
    CFMutableArrayRef certificates;
    SecTrustRef trust = NULL;
    SecTrustResultType trustResult;
    OSStatus status;
    
    carray * cCerts = mailstream_get_certificate_chain(stream);
    if (cCerts == NULL) {
        fprintf(stderr, "warning: No certificate chain retrieved");
        goto err;
    }
    
    hostnameCFString = CFStringCreateWithCharacters(NULL, (const UniChar *) hostname->unicodeCharacters(),
                                                                hostname->length());
    policy = SecPolicyCreateSSL(true, hostnameCFString);
    certificates = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
    
    for(unsigned int i = 0 ; i < carray_count(cCerts) ; i ++) {
        MMAPString * str;
        str = (MMAPString *) carray_get(cCerts, i);
        CFDataRef data = CFDataCreate(NULL, (const UInt8 *) str->str, (CFIndex) str->len);
        SecCertificateRef cert = SecCertificateCreateWithData(NULL, data);
        CFArrayAppendValue(certificates, cert);
        CFRelease(data);
        CFRelease(cert);
    }
    
    static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
    
    // The below API calls are not thread safe. We're making sure not to call the concurrently.
    pthread_mutex_lock(&lock);
    
    status = SecTrustCreateWithCertificates(certificates, policy, &trust);
    if (status != noErr) {
        pthread_mutex_unlock(&lock);
        goto free_certs;
    }
    
    status = SecTrustEvaluate(trust, &trustResult);
    if (status != noErr) {
        pthread_mutex_unlock(&lock);
        goto free_certs;
    }
    
    pthread_mutex_unlock(&lock);
    
    switch (trustResult) {
        case kSecTrustResultUnspecified:
        case kSecTrustResultProceed:
            // certificate chain is ok
            result = true;
            break;
            
        default:
            // certificate chain is invalid
            break;
    }
    
    CFRelease(trust);
free_certs:
    CFRelease(certificates);
    mailstream_certificate_chain_free(cCerts);
    CFRelease(policy);
    CFRelease(hostnameCFString);
err:
    return result;
#else
    bool result = false;
    X509_STORE * store = NULL;
    X509_STORE_CTX * storectx = NULL;
    STACK_OF(X509) * certificates = NULL;
#if defined(ANDROID) || defined(__ANDROID__)
    DIR * dir = NULL;
    struct dirent * ent = NULL;
    FILE * f = NULL;
#endif
    int status;
    
    carray * cCerts = mailstream_get_certificate_chain(stream);
    if (cCerts == NULL) {
        fprintf(stderr, "warning: No certificate chain retrieved");
        goto err;
    }
    
    store = X509_STORE_new();
    if (store == NULL) {
        goto free_certs;
    }
    
#ifdef _MSC_VER
	HCERTSTORE systemStore = CertOpenSystemStore(NULL, L"ROOT");

	PCCERT_CONTEXT previousCert = NULL;
	while (1) {
		PCCERT_CONTEXT nextCert = CertEnumCertificatesInStore(systemStore, previousCert);
		if (nextCert == NULL) {
			break;
		}
		X509 * openSSLCert = d2i_X509(NULL, (const unsigned char **)&nextCert->pbCertEncoded, nextCert->cbCertEncoded);
		if (openSSLCert != NULL) {
			X509_STORE_add_cert(store, openSSLCert);
			X509_free(openSSLCert);
		}
		previousCert = nextCert;
	}
	CertCloseStore(systemStore, 0);
#elif defined(ANDROID) || defined(__ANDROID__)
    dir = opendir("/system/etc/security/cacerts");
    while (ent = readdir(dir)) {
        if (ent->d_name[0] == '.') {
            continue;
        }
        char filename[1024];
        snprintf(filename, sizeof(filename), "/system/etc/security/cacerts/%s", ent->d_name);
        f = fopen(filename, "rb");
        if (f != NULL) {
            X509 * cert = PEM_read_X509(f, NULL, NULL, NULL);
            if (cert != NULL) {
                X509_STORE_add_cert(store, cert);
                X509_free(cert);
            }
            fclose(f);
        }
    }
    closedir(dir);
#endif

	status = X509_STORE_set_default_paths(store);
    if (status != 1) {
        printf("Error loading the system-wide CA certificates");
    }
    
    certificates = sk_X509_new_null();
    for(unsigned int i = 0 ; i < carray_count(cCerts) ; i ++) {
        MMAPString * str;
        str = (MMAPString *) carray_get(cCerts, i);
        if (str == NULL) {
            goto free_certs;
        }
        BIO *bio = BIO_new_mem_buf((void *) str->str, str->len);
        X509 *certificate = d2i_X509_bio(bio, NULL);
        BIO_free(bio);
        if (!sk_X509_push(certificates, certificate)) {
            goto free_certs;
        }
    }
    
    storectx = X509_STORE_CTX_new();
    if (storectx == NULL) {
        goto free_certs;
    }
    
    status = X509_STORE_CTX_init(storectx, store, sk_X509_value(certificates, 0), certificates);
    if (status != 1) {
        goto free_certs;
    }
    
    status = X509_verify_cert(storectx);
    if (status == 1) {
        result = true;
    }
    
free_certs:
    mailstream_certificate_chain_free(cCerts);
    if (certificates != NULL) {
        sk_X509_pop_free((STACK_OF(X509) *) certificates, X509_free);
    }
Ejemplo n.º 18
0
CryptoX_Result
CryptoMac_LoadPublicKey(const unsigned char* aCertData,
                        CryptoX_PublicKey* aPublicKey)
{
  if (!aCertData || !aPublicKey) {
    return CryptoX_Error;
  }
  *aPublicKey = NULL;

  if (!OnLionOrLater()) {
    if (!sCspHandle) {
      CSSM_RETURN rv;
      if (!sCssmInitialized) {
        CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
        rv = CSSM_Init(&sCssmVersion,
                       CSSM_PRIVILEGE_SCOPE_PROCESS,
                       &sMozCssmGuid,
                       CSSM_KEY_HIERARCHY_NONE,
                       &pvcPolicy,
                       NULL);
        if (rv != CSSM_OK) {
          return CryptoX_Error;
        }
        sCssmInitialized = true;
      }

      rv = CSSM_ModuleLoad(&gGuidAppleCSP,
                           CSSM_KEY_HIERARCHY_NONE,
                           NULL,
                           NULL);
      if (rv != CSSM_OK) {
        return CryptoX_Error;
      }

      CSSM_CSP_HANDLE cspHandle;
      rv = CSSM_ModuleAttach(&gGuidAppleCSP,
                             &sCssmVersion,
                             &cssmMemFuncs,
                             0,
                             CSSM_SERVICE_CSP,
                             0,
                             CSSM_KEY_HIERARCHY_NONE,
                             NULL,
                             0,
                             NULL,
                             &cspHandle);
      if (rv != CSSM_OK) {
        return CryptoX_Error;
      }
      sCspHandle = cspHandle;
    }

    FILE* certFile = NULL;
    long certFileSize = 0;
    uint8* certBuffer = NULL;

    certFile = fopen((char*)aCertData, "rb");
    if (!certFile) {
      return CryptoX_Error;
    }
    if (fseek(certFile, 0, SEEK_END)) {
      fclose(certFile);
      return CryptoX_Error;
    }
    certFileSize = ftell(certFile);
    if (certFileSize < 0) {
      fclose(certFile);
      return CryptoX_Error;
    }
    certBuffer = (uint8*)malloc(certFileSize);
    if (fseek(certFile, 0, SEEK_SET)) {
      free(certBuffer);
      fclose(certFile);
      return CryptoX_Error;
    }
    uint readResult = fread(certBuffer, sizeof(uint8), certFileSize, certFile);
    if (readResult != certFileSize) {
      free(certBuffer);
      fclose(certFile);
      return CryptoX_Error;
    }
    fclose(certFile);

    CFDataRef certData = CFDataCreate(kCFAllocatorDefault,
                                      certBuffer,
                                      certFileSize);
    free(certBuffer);
    if (!certData) {
      return CryptoX_Error;
    }

    SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault,
                                                          certData);
    CFRelease(certData);
    if (!cert) {
      return CryptoX_Error;
    }

    SecKeyRef publicKey;
    OSStatus status = SecCertificateCopyPublicKey(cert, (SecKeyRef*)&publicKey);
    CFRelease(cert);
    if (status) {
      return CryptoX_Error;
    }

    *aPublicKey = (void*)publicKey;
    return CryptoX_Success;
  }

  CFURLRef url =
    CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
                                            aCertData,
                                            strlen((char*)aCertData),
                                            false);
  if (!url) {
    return CryptoX_Error;
  }

  CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
  if (!stream) {
    CFRelease(url);
    return CryptoX_Error;
  }

  SecTransformRef readTransform =
    SecTransformCreateReadTransformWithReadStreamPtr(stream);
  if (!readTransform) {
    CFRelease(url);
    CFRelease(stream);
    return CryptoX_Error;
  }

  CFErrorRef error;
  CFDataRef tempCertData = (CFDataRef)SecTransformExecutePtr(readTransform,
                                                             &error);
  if (!tempCertData || error) {
    CFRelease(url);
    CFRelease(stream);
    CFRelease(readTransform);
    return CryptoX_Error;
  }

  SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault,
                                                        tempCertData);
  if (!cert) {
    CFRelease(url);
    CFRelease(stream);
    CFRelease(readTransform);
    CFRelease(tempCertData);
    return CryptoX_Error;
  }

  CryptoX_Result result = CryptoX_Error;
  OSStatus status = SecCertificateCopyPublicKey(cert,
                                                (SecKeyRef*)aPublicKey);
  if (status == 0) {
    result = CryptoX_Success;
  }

  CFRelease(url);
  CFRelease(stream);
  CFRelease(readTransform);
  CFRelease(tempCertData);
  CFRelease(cert);

  return result;
}
Ejemplo n.º 19
0
/* AUDIT[securityd](done):
   receiver (unused) is a mach_port owned by this process.
   reply (checked by mig) is a caller provided mach_port.
   auditToken (ok) is a kernel provided audit token.
   request_id (checked by mig) is caller provided value, that matches the
       mig entry for this function.
   msg_id (ok) is caller provided value.
   msg_data (ok) is a caller provided data of length:
   msg_length (ok).
 */
kern_return_t securityd_server_request(mach_port_t receiver, mach_port_t reply,
        audit_token_t auditToken,
        uint32_t request_id, uint32_t msg_id, uint8_t *msg_data,
        mach_msg_type_number_t msg_length)
{
    CFTypeRef args_in = NULL;
    CFTypeRef args_out = NULL;
    bool sendResponse = true;
    const char *op_name;

    request_begin();

    if (msg_length) {
        CFDataRef data_in = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
            msg_data, msg_length, kCFAllocatorNull);
        if (data_in) {
            args_in = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,
                data_in, kCFPropertyListImmutable, NULL);
            CFRelease(data_in);
        }
    }

#if 0
    static int crash_counter = 0;
    if (crash_counter++) {
        secdebug("server", "crash test");
        exit(1);
    }
#endif

    SecTaskRef clientTask = 
#if CHECK_ENTITLEMENTS
    SecTaskCreateWithAuditToken(kCFAllocatorDefault, auditToken);
#else 
    NULL;
#endif
    CFArrayRef groups = SecTaskCopyAccessGroups(clientTask);
    SecAccessGroupsSetCurrent(groups);
    OSStatus status = errSecParam;
    switch(msg_id) {
        case sec_item_add_id:
            op_name = "SecItemAdd";
            if (isDictionary(args_in))
                status = _SecItemAdd(args_in, &args_out, groups);
            break;
        case sec_item_copy_matching_id:
            op_name = "SecItemCopyMatching";
            if (isDictionary(args_in))
                status = _SecItemCopyMatching(args_in, &args_out, groups);
            break;
        case sec_item_delete_id:
            op_name = "SecItemDelete";
            if (isDictionary(args_in))
                status = _SecItemDelete(args_in, groups);
            break;
        case sec_item_update_id:
            op_name = "SecItemUpdate";
            if (isArrayOfLength(args_in, 2)) {
                CFDictionaryRef
                    in0 = (CFDictionaryRef)CFArrayGetValueAtIndex(args_in, 0),
                    in1 = (CFDictionaryRef)CFArrayGetValueAtIndex(args_in, 1);
                if (isDictionary(in0) && isDictionary(in1))
                    status = _SecItemUpdate(in0, in1, groups);
            }
            break;
        case sec_trust_store_contains_id:
        {
            op_name = "SecTrustStoreContains";
            if (!isArray(args_in))
                break;
            CFIndex argc_in = CFArrayGetCount(args_in);
            if (argc_in != 2)
                break;
            CFStringRef domainName = CFArrayGetValueAtIndex(args_in, 0);
            CFDataRef digest = CFArrayGetValueAtIndex(args_in, 1);
            if (!isString(domainName) || !isData(digest))
                break;

            SecTrustStoreRef ts = SecTrustStoreForDomainName(domainName);
            status = !SecTrustStoreContainsCertificateWithDigest(ts, digest);
            break;
        }
        case sec_trust_store_set_trust_settings_id:
        {
            op_name = "SecTrustStoreSetTrustSettings";
            /* Open the trust store unconditially so we can abuse this method
               even in clients that just want to read from the truststore,
               and this call will force it to be created. */
            SecTrustStoreRef ts = SecTrustStoreForDomain(kSecTrustStoreDomainUser);
            if (!isArray(args_in))
                break;
            CFIndex argc_in = CFArrayGetCount(args_in);
            if (argc_in != 1 && argc_in != 2)
                break;
            if (!SecTaskGetBooleanValueForEntitlement(clientTask,
                kSecEntitlementModifyAnchorCertificates)) {
                status = errSecMissingEntitlement;
                break;
            }
            CFDataRef certificateData = (CFDataRef)CFArrayGetValueAtIndex(args_in, 0);
            if (!isData(certificateData))
                break;
            SecCertificateRef certificate = SecCertificateCreateWithData(NULL, certificateData);
            if (certificate) {
                CFTypeRef trustSettingsDictOrArray;
                if (argc_in < 2) {
                    trustSettingsDictOrArray = NULL;
                } else {
                    trustSettingsDictOrArray = CFArrayGetValueAtIndex(args_in, 1);
                    if (trustSettingsDictOrArray) {
                        CFTypeID tst = CFGetTypeID(trustSettingsDictOrArray);
                        if (tst != CFArrayGetTypeID() && tst != CFDictionaryGetTypeID()) {
                            CFRelease(certificate);
                            break;
                        }
                    }
                }
                status = _SecTrustStoreSetTrustSettings(ts, certificate, trustSettingsDictOrArray);
                CFRelease(certificate);
            }
            break;
        }
        case sec_trust_store_remove_certificate_id:
            op_name = "SecTrustStoreRemoveCertificate";
            if (SecTaskGetBooleanValueForEntitlement(clientTask,
                    kSecEntitlementModifyAnchorCertificates)) {
                SecTrustStoreRef ts = SecTrustStoreForDomain(kSecTrustStoreDomainUser);
                if (isData(args_in)) {
                    status = SecTrustStoreRemoveCertificateWithDigest(ts, args_in);
                }
            } else {
                status = errSecMissingEntitlement;
            }
            break;
        case sec_delete_all_id:
            op_name = "SecDeleteAll";
            if (SecTaskGetBooleanValueForEntitlement(clientTask,
                kSecEntitlementWipeDevice)) {
                status = SecItemDeleteAll();
            } else {
                status = errSecMissingEntitlement;
            }
            break;
        case sec_trust_evaluate_id:
            op_name = "SecTrustEvaluate";
            if (isDictionary(args_in)) {
                struct securityd_server_trust_evaluation_context *tec = malloc(sizeof(*tec));
                tec->reply = reply;
                tec->request_id = request_id;
                status = SecTrustServerEvaluateAsync(args_in,
                    securityd_server_trust_evaluate_done, tec);
                if (status == noErr || status == errSecWaitForCallback) {
                    sendResponse = false;
                } else {
                    free(tec);
                }
            }
            break;
        case sec_restore_keychain_id:
            op_name = "SecRestoreKeychain";
            if (SecTaskGetBooleanValueForEntitlement(clientTask,
                kSecEntitlementRestoreKeychain)) {
                status = _SecServerRestoreKeychain();
            } else {
                status = errSecMissingEntitlement;
            }
            break;
        case sec_migrate_keychain_id:
            op_name = "SecMigrateKeychain";
            if (isArray(args_in)) {
                if (SecTaskGetBooleanValueForEntitlement(clientTask,
                    kSecEntitlementMigrateKeychain)) {
                    status = _SecServerMigrateKeychain(args_in, &args_out);
                } else {
                    status = errSecMissingEntitlement;
                }
            }
            break;
        case sec_keychain_backup_id:
            op_name = "SecKeychainBackup";
            if (!args_in || isArray(args_in)) {
                if (SecTaskGetBooleanValueForEntitlement(clientTask,
                    kSecEntitlementRestoreKeychain)) {
                    status = _SecServerKeychainBackup(args_in, &args_out);
                } else {
                    status = errSecMissingEntitlement;
                }
            }
            break;
        case sec_keychain_restore_id:
            op_name = "SecKeychainRestore";
            if (isArray(args_in)) {
                if (SecTaskGetBooleanValueForEntitlement(clientTask,
                    kSecEntitlementRestoreKeychain)) {
                    status = _SecServerKeychainRestore(args_in, &args_out);
                } else {
                    status = errSecMissingEntitlement;
                }
            }
            break;
        default:
            op_name = "invalid_operation";
            status = errSecParam;
            break;
    }

    const char *proc_name;
#ifdef NDEBUG
    if (status == errSecMissingEntitlement) {
#endif
        pid_t pid;
        audit_token_to_au32(auditToken, NULL, NULL, NULL, NULL, NULL, &pid, NULL, NULL);
        int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
        struct kinfo_proc kp;
        size_t len = sizeof(kp);
        if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1 || len == 0)
            proc_name = strerror(errno);
        else
            proc_name = kp.kp_proc.p_comm;

#ifndef NDEBUG
    if (status == errSecMissingEntitlement) {
#endif
        asl_log(NULL, NULL, ASL_LEVEL_ERR,
            "%s[%u] %s: missing entitlement", proc_name, pid, op_name);
        /* Remap errSecMissingEntitlement -> errSecInteractionNotAllowed. */
        status = errSecInteractionNotAllowed;
    }

    secdebug("ipc", "%s[%u] %s: returning: %d", proc_name, pid, op_name,
        status);

    CFReleaseSafe(groups);
    CFReleaseSafe(clientTask);
    SecAccessGroupsSetCurrent(NULL);

    kern_return_t err = 0;
    if (sendResponse)
        err = securityd_server_send_reply(reply, request_id, status, args_out);

    CFReleaseSafe(args_in);

    return err;
}

extern boolean_t securityd_request_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);

union max_msg_size_union {
    union __RequestUnion__securityd_client_securityd_reply_subsystem reply;
};

static uint8_t reply_buffer[sizeof(union max_msg_size_union) + MAX_TRAILER_SIZE];

static void *handle_message(void *msg, CFIndex size,
        CFAllocatorRef allocator, void *info)
{
    mach_msg_header_t *message = (mach_msg_header_t *)msg;
    mach_msg_header_t *reply = (mach_msg_header_t *)reply_buffer;

    securityd_request_server(message, reply);

    return NULL;
}