X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/sec/Security/SecSCEP.c diff --git a/sec/Security/SecSCEP.c b/sec/Security/SecSCEP.c deleted file mode 100644 index 6b25f1ac..00000000 --- a/sec/Security/SecSCEP.c +++ /dev/null @@ -1,884 +0,0 @@ -/* - * Copyright (c) 2008-2010 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include "SecSCEP.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef enum { - messageType = 2, - pkiStatus = 3, - failInfo = 4, - senderNonce = 5, - recipientNonce = 6, - transId = 7 -} scep_attr_t; - -static CFDataRef scep_oid(scep_attr_t type) -{ -/* +-------------------+-----------------------------------------------+ - | Name | ASN.1 Definition | - +-------------------+-----------------------------------------------+ - | id-VeriSign | OBJECT_IDENTIFIER ::= {2 16 US(840) 1 | - | | VeriSign(113733)} | - | id-pki | OBJECT_IDENTIFIER ::= {id-VeriSign pki(1)} | - | id-attributes | OBJECT_IDENTIFIER ::= {id-pki attributes(9)} | - | id-messageType | OBJECT_IDENTIFIER ::= {id-attributes | - | | messageType(2)} | - | id-pkiStatus | OBJECT_IDENTIFIER ::= {id-attributes | - | | pkiStatus(3)} | - | id-failInfo | OBJECT_IDENTIFIER ::= {id-attributes | - | | failInfo(4)} | - | id-senderNonce | OBJECT_IDENTIFIER ::= {id-attributes | - | | senderNonce(5)} | - | id-recipientNonce | OBJECT_IDENTIFIER ::= {id-attributes | - | | recipientNonce(6)} | - | id-transId | OBJECT_IDENTIFIER ::= {id-attributes | - | | transId(7)} | - | id-extensionReq | OBJECT_IDENTIFIER ::= {id-attributes | - | | extensionReq(8)} | - +-------------------+-----------------------------------------------+ */ - uint8_t oid_scep_attrs[] = - { 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0 }; - /* messageType:2 pkiStatus:3 failInfo:4 senderNonce:5 recipientNonce:6 transId:7 */ - if ((type < messageType) || (type > transId)) - return NULL; - - oid_scep_attrs[sizeof(oid_scep_attrs) - 1] = type; - return CFDataCreate(kCFAllocatorDefault, oid_scep_attrs, sizeof(oid_scep_attrs)); -} - -static const char CertRep[] = "3"; -static const char PKCSReq[] = "19"; -static const char GetCertInitial[] = "20"; -static const char GetCert[] = "21"; -static const char GetCRL[] = "22"; -static const char PKIStatusSUCCESS[] = "0"; -static const char PKIStatusFAILURE[] = "2"; -static const char PKIStatusPENDING[] = "3"; - -static CFDataRef -printable_string_data(size_t length, const char *bytes) -{ - DERSize der_length_len = DERLengthOfLength(length); - size_t value_length = sizeof(SecASN1PrintableString) + der_length_len + length; - CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, value_length); - CFDataSetLength(data, value_length); - uint8_t *ptr = (uint8_t *)CFDataGetBytePtr(data); - *ptr++ = SecASN1PrintableString; - DEREncodeLength(length, ptr, &der_length_len); - ptr += der_length_len; - memcpy(ptr, bytes, length); - return (CFDataRef)data; -} - -#define scep_result(value) printable_string_data(sizeof(value)-1, value) - -static CFTypeRef -dictionary_array_value_1(CFDictionaryRef attrs, CFTypeRef attr) -{ - CFTypeRef value = NULL; - CFArrayRef attr_values = NULL; - - require(attr_values = (CFArrayRef)CFDictionaryGetValue(attrs, attr), out); - require(CFArrayGetCount(attr_values) == 1, out); - value = CFArrayGetValueAtIndex(attr_values, 0); -out: - return value; -} - -/* @@@ consider splitting into function returning single value - and function creating printable string from c str */ -static bool scep_attr_has_val(CFDictionaryRef attrs, scep_attr_t attr, const char *val) -{ - bool result = false; - CFDataRef msgtype_value_data = printable_string_data(strlen(val), val); - CFArrayRef msgtype_value_datas = CFArrayCreate(kCFAllocatorDefault, - (const void **)&msgtype_value_data, 1, &kCFTypeArrayCallBacks); - CFRelease(msgtype_value_data); - CFDataRef msgtype_oid_data = scep_oid(attr); - CFArrayRef msgtype_values = (CFArrayRef)CFDictionaryGetValue(attrs, msgtype_oid_data); - CFRelease(msgtype_oid_data); - if (msgtype_values && CFEqual(msgtype_value_datas, msgtype_values)) - result = true; - CFRelease(msgtype_value_datas); - - return result; -} - -static CFDataRef hexencode(CFDataRef data) -{ - CFIndex ix, length = CFDataGetLength(data); - const uint8_t *bin_data = CFDataGetBytePtr(data); - uint8_t *hex_data = calloc(1, 2*length + 1); - require(length && bin_data && hex_data, out); - - for (ix = 0; ix < length; ix++) - snprintf((char *)&hex_data[2*ix], 3, "%02X", bin_data[ix]); - - return CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, hex_data, - 2*length, kCFAllocatorMalloc); -out: - if (hex_data) - free(hex_data); - return NULL; -} - -static CFDataRef pubkeyhash(SecKeyRef key) -{ - CFTypeRef key_type = NULL; - CFDictionaryRef pubkey_attrs = NULL; - CFDataRef hash_pubkey_data = NULL, pubkey_data = NULL; - uint8_t pubkey_hash[CC_SHA1_DIGEST_LENGTH]; - - require(pubkey_attrs = SecKeyCopyAttributeDictionary(key), out); - require( (key_type = CFDictionaryGetValue(pubkey_attrs, kSecAttrKeyClass)) && - CFEqual(key_type, kSecAttrKeyClassPublic), out); - require(pubkey_data = CFDictionaryGetValue(pubkey_attrs, kSecValueData), out); - require((unsigned long)CFDataGetLength(pubkey_data)<=UINT32_MAX, out); /* Correct as long as CFIndex is long */ - CCDigest(kCCDigestSHA1, CFDataGetBytePtr(pubkey_data), (CC_LONG)CFDataGetLength(pubkey_data), pubkey_hash); - hash_pubkey_data = CFDataCreate(kCFAllocatorDefault, pubkey_hash, sizeof(pubkey_hash)); -out: - CFReleaseSafe(pubkey_attrs); - return hash_pubkey_data; -} - -static void generate_sender_nonce(CFMutableDictionaryRef dict) -{ - /* random sender nonce, to be verified against recipient nonce in reply */ - CFDataRef senderNonce_oid_data = scep_oid(senderNonce); - uint8_t senderNonce_value[18] = { 4, 16, }; - SecRandomCopyBytes(kSecRandomDefault, sizeof(senderNonce_value) - 2, senderNonce_value + 2); - CFDataRef senderNonce_value_data = CFDataCreate(kCFAllocatorDefault, - senderNonce_value, sizeof(senderNonce_value)); - if (senderNonce_oid_data && senderNonce_value_data) - CFDictionarySetValue(dict, senderNonce_oid_data, senderNonce_value_data); - CFReleaseNull(senderNonce_oid_data); - CFReleaseNull(senderNonce_value_data); -} - -SecIdentityRef SecSCEPCreateTemporaryIdentity(SecKeyRef publicKey, SecKeyRef privateKey) -{ - int key_usage = kSecKeyUsageDigitalSignature | kSecKeyUsageKeyEncipherment; - CFDictionaryRef self_signed_parameters = NULL; - CFNumberRef key_usage_num = NULL; - SecCertificateRef self_signed_certificate = NULL; - SecIdentityRef self_signed_identity = NULL; - CFStringRef cn_uuid = NULL; - CFArrayRef cn_dn = NULL, cn_dns = NULL, unique_rdns = NULL; - - key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage); - require(key_usage_num, out); - - const void *key[] = { kSecCertificateKeyUsage }; - const void *val[] = { key_usage_num }; - self_signed_parameters = CFDictionaryCreate(kCFAllocatorDefault, - key, val, array_size(key), - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - require(self_signed_parameters, out); - - char uuid_string[37] = {}; - uuid_t uuid; - uuid_generate_random(uuid); - uuid_unparse(uuid, uuid_string); - cn_uuid = CFStringCreateWithCString(kCFAllocatorDefault, uuid_string, kCFStringEncodingASCII); - require(cn_uuid, out); - const void * cn[] = { kSecOidCommonName, cn_uuid }; - cn_dn = CFArrayCreate(kCFAllocatorDefault, cn, 2, NULL); - require(cn_dn, out); - cn_dns = CFArrayCreate(kCFAllocatorDefault, (const void **)&cn_dn, 1, NULL); - require(cn_dns, out); - unique_rdns = CFArrayCreate(kCFAllocatorDefault, (const void **)&cn_dns, 1, NULL); - require(unique_rdns, out); - - self_signed_certificate = SecGenerateSelfSignedCertificate(unique_rdns, self_signed_parameters, publicKey, privateKey); - require(self_signed_certificate, out); - self_signed_identity = SecIdentityCreate(kCFAllocatorDefault, self_signed_certificate, privateKey); - -out: - CFReleaseSafe(key_usage_num); - CFReleaseSafe(self_signed_parameters); - CFReleaseSafe(self_signed_certificate); - CFReleaseSafe(unique_rdns); - CFReleaseSafe(cn_dns); - CFReleaseSafe(cn_dn); - CFReleaseSafe(cn_uuid); - - return self_signed_identity; -} - -CFDataRef -SecSCEPGenerateCertificateRequest(CFArrayRef subject, CFDictionaryRef parameters, - SecKeyRef publicKey, SecKeyRef privateKey, - SecIdentityRef signer, CFTypeRef recipients) -{ - CFDataRef csr = NULL; - CFMutableDataRef enveloped_data = NULL; - CFMutableDictionaryRef simple_attr = NULL; - SecIdentityRef self_signed_identity = NULL; - CFMutableDataRef signed_request = NULL; - SecCertificateRef recipient = NULL; - - if (CFGetTypeID(recipients) == SecCertificateGetTypeID()) { - recipient = (SecCertificateRef)recipients; - } else if (CFGetTypeID(recipients) == CFArrayGetTypeID()) { - CFIndex recipient_count = CFArrayGetCount(recipients); - if (recipient_count > 1) { - /* get the encryption cert */ - recipient = (SecCertificateRef)CFArrayGetValueAtIndex(recipients, 0); - } else if (recipient_count == 1) { - /* if there is at least one we'll assume it's sign+encrypt */ - recipient = (SecCertificateRef)CFArrayGetValueAtIndex(recipients, 0); - } - } - require(recipient, out); - - require(csr = SecGenerateCertificateRequest(subject, parameters, publicKey, privateKey), out); - require(enveloped_data = CFDataCreateMutable(kCFAllocatorDefault, 0), out); - require_noerr(SecCMSCreateEnvelopedData(recipient, parameters, csr, enveloped_data), out); - CFReleaseNull(csr); - - simple_attr = CFDictionaryCreateMutable(kCFAllocatorDefault, 3, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - - /* generate a transaction id: hex encoded pubkey hash */ - CFDataRef public_key_hash = pubkeyhash(publicKey); - CFDataRef public_key_hash_hex = hexencode(public_key_hash); - CFReleaseSafe(public_key_hash); - CFDataRef transid_oid_data = scep_oid(transId); - CFDataRef transid_data = printable_string_data(CFDataGetLength(public_key_hash_hex), - (const char *)CFDataGetBytePtr(public_key_hash_hex)); - CFReleaseSafe(public_key_hash_hex); - - CFDictionarySetValue(simple_attr, transid_oid_data, transid_data); - CFReleaseNull(transid_oid_data); - CFReleaseNull(transid_data); - - /* message type: PKCSReq (19) */ - CFDataRef msgtype_value_data = NULL; - CFDataRef msgtype_oid_data = NULL; - require(msgtype_oid_data = scep_oid(messageType), out); - require(msgtype_value_data = printable_string_data(strlen(PKCSReq), PKCSReq), out); - - CFDictionarySetValue(simple_attr, msgtype_oid_data, msgtype_value_data); - CFReleaseNull(msgtype_oid_data); - CFReleaseNull(msgtype_value_data); - - /* random sender nonce, to be verified against recipient nonce in reply */ - generate_sender_nonce(simple_attr); - - /* XXX/cs remove auto-generation once managedconfig is no longer using this */ - if (signer) { - self_signed_identity = signer; - CFRetain(self_signed_identity); - } else { - self_signed_identity = SecSCEPCreateTemporaryIdentity(publicKey, privateKey); - - /* Add our temporary cert to the keychain for CMS decryption of - the reply. If we happened to have picked an existing UUID - we fail. We should pick a different UUID and try again. */ - require(self_signed_identity, out); - CFDictionaryRef identity_add = CFDictionaryCreate(NULL, - &kSecValueRef, (const void **)&self_signed_identity, 1, NULL, NULL); - require_noerr_action(SecItemAdd(identity_add, NULL), out, - CFReleaseSafe(identity_add)); - CFReleaseSafe(identity_add); - } - require(self_signed_identity, out); - - signed_request = CFDataCreateMutable(kCFAllocatorDefault, 0); - require_noerr_action(SecCMSCreateSignedData(self_signed_identity, enveloped_data, - parameters, simple_attr, signed_request), out, CFReleaseNull(signed_request)); - - -out: - - CFReleaseSafe(simple_attr); - CFReleaseSafe(self_signed_identity); - CFReleaseSafe(enveloped_data); - CFReleaseSafe(csr); - return signed_request; -} - - -CFDataRef -SecSCEPCertifyRequest(CFDataRef request, SecIdentityRef ca_identity, CFDataRef serialno, bool pend_request) -{ - CFDictionaryRef simple_attr = NULL; - SecCertificateRef ca_certificate = NULL; - SecKeyRef ca_public_key = NULL; - SecCertificateRef cert = NULL; - SecPolicyRef policy = NULL; - CFDataRef cert_pkcs7 = NULL; - CFMutableDataRef cert_msg = NULL; - CFMutableDataRef signed_reply = NULL; - SecTrustRef trust = NULL; - CFDataRef signed_content = NULL; - CFDictionaryRef signed_attributes = NULL; - SecCertificateRef signer_cert = NULL; - CFDataRef transid_oid_data = NULL, senderNonce_oid_data = NULL, transid_value = NULL; - CFDataRef subject = NULL, extensions = NULL, senderNonce_value = NULL; - CFStringRef challenge = NULL; - SecKeyRef tbsPublicKey = NULL; - CFMutableDataRef encrypted_content = NULL; - SecCertificateRef recipient = NULL; - CFDictionaryRef parameters = NULL; - - require_noerr(SecIdentityCopyCertificate(ca_identity, &ca_certificate), out); - ca_public_key = SecCertificateCopyPublicKey(ca_certificate); /*@@@*/ - - /* unwrap outer layer: */ - policy = SecPolicyCreateBasicX509(); - - require_noerr(SecCMSVerifyCopyDataAndAttributes(request, NULL, - policy, &trust, &signed_content, &signed_attributes), out); - /* remember signer: is signer certified by us, then re-certify, no challenge needed */ - SecTrustResultType result; - require_noerr(SecTrustEvaluate(trust, &result), out); - require (signer_cert = SecTrustGetCertificateAtIndex(trust, 0), out); - bool recertify = !SecCertificateIsSignedBy(signer_cert, ca_public_key); - - /* msgType should be certreq msg */ - require(scep_attr_has_val(signed_attributes, messageType, PKCSReq), out); - - /* remember transaction id just for reuse */ - require(transid_oid_data = scep_oid(transId), out); - require(transid_value = - dictionary_array_value_1(signed_attributes, transid_oid_data), out); - - /* senderNonce becomes recipientNonce */ - require(senderNonce_oid_data = scep_oid(senderNonce), out); - require(senderNonce_value = - dictionary_array_value_1(signed_attributes, senderNonce_oid_data), out); - - /* decrypt the request */ - encrypted_content = CFDataCreateMutable(kCFAllocatorDefault, 0); - require_noerr(SecCMSDecryptEnvelopedData(signed_content, encrypted_content, &recipient), out); - require(recipient && CFEqual(ca_certificate, recipient), out); - - /* verify CSR */ - require(SecVerifyCertificateRequest(encrypted_content, &tbsPublicKey, &challenge, &subject, &extensions), out); - CFReleaseNull(encrypted_content); - - /* @@@ - // alternatively send a pending message - // pkistatus {{id-attributes pkiStatus(3)} "FAILURE"} - // failInfo {{id-attributes failInfo(4)} "the reason to reject"} - */ - - /* verify challenge - this would need to be a callout that can determine - the challenge appropriate for the subject */ - if (!recertify) - require( challenge && (CFStringGetTypeID() == CFGetTypeID(challenge)) && - CFEqual(CFSTR("magic"), challenge), out); - - require(cert_msg = CFDataCreateMutable(kCFAllocatorDefault, 0), out); - - if (!pend_request) { - /* sign cert */ - cert = SecIdentitySignCertificate(ca_identity, serialno, - tbsPublicKey, subject, extensions); - - /* degenerate cms with cert */ - require (cert_pkcs7 = SecCMSCreateCertificatesOnlyMessage(cert), out); - CFReleaseNull(cert); - - /* envelope for client */ - require_noerr(SecCMSCreateEnvelopedData(signer_cert, NULL, cert_pkcs7, cert_msg), out); - CFReleaseNull(cert_pkcs7); - } - - CFDataRef pki_status_oid = scep_oid(pkiStatus); - CFDataRef pki_status_value = pend_request ? scep_result(PKIStatusPENDING) : scep_result(PKIStatusSUCCESS); - CFDataRef message_type_oid = scep_oid(messageType), message_type_value = scep_result(CertRep); - const void *oid[] = { transid_oid_data, pki_status_oid, message_type_oid }; - const void *value[] = { transid_value, pki_status_value, message_type_value }; - simple_attr = CFDictionaryCreate(kCFAllocatorDefault, oid, value, array_size(oid), - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFReleaseSafe(pki_status_oid); CFReleaseSafe(pki_status_value); - CFReleaseSafe(message_type_oid); CFReleaseSafe(message_type_value); - - /* sign with ra/ca cert and add attributes */ - signed_reply = CFDataCreateMutable(kCFAllocatorDefault, 0); - const void *signing_params[] = { kSecCMSCertChainMode }; - const void *signing_params_vals[] = { kSecCMSCertChainModeNone }; - parameters = CFDictionaryCreate(kCFAllocatorDefault, signing_params, signing_params_vals, array_size(signing_params), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - require_noerr_action(SecCMSCreateSignedData(ca_identity, cert_msg, parameters, simple_attr, signed_reply), out, CFReleaseNull(signed_reply)); - -out: - CFReleaseSafe(ca_certificate); - CFReleaseSafe(ca_public_key); - CFReleaseSafe(cert); - CFReleaseSafe(cert_pkcs7); - CFReleaseSafe(cert_msg); - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(signed_content); - CFReleaseSafe(signed_attributes); - CFReleaseSafe(transid_oid_data); - CFReleaseSafe(senderNonce_oid_data); - CFReleaseSafe(subject); - CFReleaseSafe(extensions); - CFReleaseSafe(challenge); - CFReleaseSafe(tbsPublicKey); - CFReleaseSafe(encrypted_content); - CFReleaseSafe(simple_attr); - CFReleaseSafe(recipient); - CFReleaseSafe(parameters); - - return signed_reply; -} - -static CFStringRef -copy_signed_attr_printable_string_value(CFDictionaryRef signed_attributes, scep_attr_t attr) -{ - CFStringRef printable_string = NULL; - CFDataRef key_oid = NULL; - - key_oid = scep_oid(attr); - require(key_oid, out); - - CFArrayRef values = (CFArrayRef)CFDictionaryGetValue(signed_attributes, key_oid); - require_quiet(values && (CFGetTypeID(values) == CFArrayGetTypeID()) - && (CFArrayGetCount(values) == 1), out); - CFDataRef value = CFArrayGetValueAtIndex(values, 0); - const uint8_t *bytes = CFDataGetBytePtr(value); - size_t length = CFDataGetLength(value); - require(length >= 2, out); - require(bytes[0] == 0x13, out); - /* no scep responses defined that are longer */ - require(!(bytes[1] & 0x80) && (bytes[1] == length-2), out); - printable_string = CFStringCreateWithBytes(kCFAllocatorDefault, - bytes + 2, length - 2, kCFStringEncodingASCII, false); -out: - CFReleaseSafe(key_oid); - - return printable_string; -} - -CFArrayRef -SecSCEPVerifyReply(CFDataRef request, CFDataRef reply, CFTypeRef ca_certificates, - CFErrorRef *server_error) -{ - SecKeyRef ca_public_key = NULL; - SecCertificateRef cert = NULL; - SecPolicyRef policy = NULL; - CFDataRef cert_msg = NULL; - CFMutableDataRef enc_cert_msg = NULL; - SecTrustRef trust = NULL; - CFDataRef signed_content = NULL; - CFDictionaryRef signed_attributes = NULL; - CFDictionaryRef attributes = NULL; - SecCertificateRef signer_cert = NULL; - - CFMutableDataRef encrypted_content = NULL; - SecCertificateRef recipient = NULL; - CFArrayRef certificates = NULL; - - SecCertificateRef reply_signer = NULL; - - CFStringRef msg_type = NULL; - CFStringRef pki_status = NULL; - - if (CFGetTypeID(ca_certificates) == SecCertificateGetTypeID()) { - reply_signer = (SecCertificateRef)ca_certificates; - } else if (CFGetTypeID(ca_certificates) == CFArrayGetTypeID()) { - CFIndex reply_signer_count = CFArrayGetCount(ca_certificates); - if (reply_signer_count > 1) { - /* get the signer cert */ - reply_signer = (SecCertificateRef)CFArrayGetValueAtIndex(ca_certificates, 1); - } else if (reply_signer_count == 1) { - /* if there is at least one we'll assume it's sign+encrypt */ - reply_signer = (SecCertificateRef)CFArrayGetValueAtIndex(ca_certificates, 0); - } - } - require(reply_signer, out); - - /* unwrap outer layer */ - policy = SecPolicyCreateBasicX509(); - CFArrayRef additional_certificates = CFArrayCreate(kCFAllocatorDefault, (const void **)&reply_signer, 1, &kCFTypeArrayCallBacks); - require_noerr(SecCMSVerifySignedData(reply, NULL, - policy, &trust, additional_certificates, &signed_content, &attributes), out); - CFReleaseSafe(additional_certificates); - if (attributes) - signed_attributes = CFDictionaryGetValue(attributes, kSecCMSSignedAttributes); - - /* response should be signed by ra */ - SecTrustResultType result; - require_noerr(SecTrustEvaluate(trust, &result), out); - require(signer_cert = SecTrustGetCertificateAtIndex(trust, 0), out); - require(CFEqual(reply_signer, signer_cert), out); - - /* msgType should be certreq msg */ - require(signed_attributes, out); - msg_type = copy_signed_attr_printable_string_value(signed_attributes, messageType); - pki_status = copy_signed_attr_printable_string_value(signed_attributes, pkiStatus); - - if (msg_type || pki_status) { - require(msg_type && CFEqual(msg_type, CFSTR("3")), out); - - require(pki_status, out); - if (CFEqual(pki_status, CFSTR("2"))) { - goto out; // FAILURE, the end (return NULL) - } else if (CFEqual(pki_status, CFSTR("3"))) { - CFDataRef transid_oid_data = NULL, transid_value = NULL; - require(transid_oid_data = scep_oid(transId), out); - require(transid_value = dictionary_array_value_1(signed_attributes, transid_oid_data), out); - CFDictionaryRef err_dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&transid_oid_data, (const void **)&transid_value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - *server_error = CFErrorCreate(kCFAllocatorDefault, - CFSTR("PENDING"), 3, err_dict); - CFReleaseSafe(err_dict); - CFReleaseSafe(transid_oid_data); - goto out; - } - require(CFEqual(pki_status, CFSTR("0")), out); - } - - // can we decode the request? - encrypted_content = CFDataCreateMutable(kCFAllocatorDefault, 0); - require_noerr(SecCMSDecryptEnvelopedData(signed_content, encrypted_content, &recipient), out); - require(recipient, out); - // verify recipient belongs with our private key - - // verify CSR: - require(certificates = SecCMSCertificatesOnlyMessageCopyCertificates(encrypted_content), out); - - // recipient is either our temporary self-signed cert or the old cert we just used - // to recertify. if we have new certificates and have stored them successfully we - // can now get rid of the cert. - /* XXX/cs - This should move outside of thise function when we force a signer - to be passed in */ - CFDictionaryRef cert_delete = CFDictionaryCreate(NULL, - &kSecValueRef, (const void **)&recipient, 1, NULL, NULL); - require_noerr_action(SecItemDelete(cert_delete), out, - CFReleaseSafe(cert_delete)); - CFReleaseSafe(cert_delete); - -out: - CFReleaseSafe(ca_public_key); - CFReleaseSafe(cert); - CFReleaseSafe(cert_msg); - CFReleaseSafe(enc_cert_msg); - CFReleaseSafe(trust); - CFReleaseSafe(policy); - CFReleaseSafe(signed_content); - CFReleaseSafe(encrypted_content); - CFReleaseSafe(recipient); - CFReleaseSafe(msg_type); - CFReleaseSafe(pki_status); - CFReleaseSafe(attributes); - - return certificates; -} - -OSStatus SecSCEPValidateCACertMessage(CFArrayRef certs, - CFDataRef ca_fingerprint, - SecCertificateRef *ca_certificate, - SecCertificateRef *ra_signing_certificate, - SecCertificateRef *ra_encryption_certificate) -{ - OSStatus status = errSecParam; - SecCertificateRef _ca_certificate = NULL, _ra_signing_certificate = NULL, - _ra_encryption_certificate = NULL, _ra_certificate = NULL; - - CFIndex j, count = CFArrayGetCount(certs); - CFMutableArrayRef chain = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); - SecPolicyRef policy = SecPolicyCreateBasicX509(); - SecTrustRef trust = NULL; - require(chain, out); - for (j=0; j 1) { - SecCertificateRef leaf = SecTrustGetCertificateAtIndex(trust, 0); - SecCertificateRef ca_leaf = SecTrustGetCertificateAtIndex(trust, chain_count - 1); - if (!_ca_certificate) { - if (ca_fingerprint) { - secdebug("scep", "checking ca %@ against fingerprint %@", ca_leaf, ca_fingerprint); - uint8_t ca_hash[CC_SHA1_DIGEST_LENGTH]; /*max(md5,sha-1)*/ - CFDataRef ca_cert_data = SecCertificateCopyData(ca_leaf); - require(ca_cert_data, out); - size_t ca_data_len = CFDataGetLength(ca_cert_data); - size_t ca_fingerprint_len = CFDataGetLength(ca_fingerprint); - const uint8_t *ca_data = CFDataGetBytePtr(ca_cert_data); - require(ca_data_len && ca_data, out); - require(ca_data_len