- SecPointer<Certificate> certificatePtr(Identity::required(identityRef)->certificate());
- Required(certificateRef) = certificatePtr->handle();
-
-#if SECTRUST_OSX
- /* convert outgoing item to a unified SecCertificateRef */
- CssmData certData = certificatePtr->data();
- CFDataRef data = NULL;
- if (certData.Data && certData.Length) {
- data = CFDataCreate(NULL, certData.Data, certData.Length);
+ if (!identityRef || !certificateRef) {
+ return errSecParam;
+ }
+ CFTypeID itemType = CFGetTypeID(identityRef);
+ if (itemType == SecIdentityGetTypeID()) {
+ SecPointer<Certificate> certificatePtr(Identity::required(identityRef)->certificate());
+ Required(certificateRef) = certificatePtr->handle();
+
+ /* convert outgoing certificate item to a unified SecCertificateRef */
+ CssmData certData = certificatePtr->data();
+ CFDataRef data = NULL;
+ if (certData.Data && certData.Length) {
+ data = CFDataCreate(NULL, certData.Data, certData.Length);
+ }
+ if (!data) {
+ *certificateRef = NULL;
+ syslog(LOG_ERR, "ERROR: SecIdentityCopyCertificate failed to retrieve certificate data (length=%ld, data=0x%lX)",
+ (long)certData.Length, (uintptr_t)certData.Data);
+ return errSecInternal;
+ }
+ SecCertificateRef tmpRef = *certificateRef;
+ *certificateRef = SecCertificateCreateWithKeychainItem(NULL, data, tmpRef);
+ if (data) {
+ CFRelease(data);
+ }
+ if (tmpRef) {
+ CFRelease(tmpRef);
+ }
+ }
+ else if (itemType == SecCertificateGetTypeID()) {
+ // rdar://24483382
+ // reconstituting a persistent identity reference could return the certificate
+ SecCertificateRef certificate = (SecCertificateRef)identityRef;
+
+ /* convert outgoing certificate item to a unified SecCertificateRef, if needed */
+ if (SecCertificateIsItemImplInstance(certificate)) {
+ *certificateRef = SecCertificateCreateFromItemImplInstance(certificate);
+ }
+ else {
+ *certificateRef = (SecCertificateRef) CFRetain(certificate);
+ }
+ return errSecSuccess;