Exemplo n.º 1
0
static int32_t ProcessCertificateTypeReturn(CFArrayRef items, SecCertificateRef* pCertOut, SecIdentityRef* pIdentityOut)
{
    assert(pCertOut != nullptr && *pCertOut == nullptr);
    assert(pIdentityOut != nullptr && *pIdentityOut == nullptr);

    if (items == nullptr)
    {
        return kErrOutItemsNull;
    }

    CFIndex itemCount = CFArrayGetCount(items);

    if (itemCount == 0)
    {
        return kErrOutItemsEmpty;
    }

    CFTypeRef bestItem = nullptr;

    for (CFIndex i = 0; i < itemCount; i++)
    {
        CFTypeRef current = CFArrayGetValueAtIndex(items, i);
        auto currentItemType = CFGetTypeID(current);

        if (currentItemType == SecIdentityGetTypeID())
        {
            bestItem = current;
            break;
        }
        else if (bestItem == nullptr && currentItemType == SecCertificateGetTypeID())
        {
            bestItem = current;
        }
    }

    if (bestItem == nullptr)
    {
        return -13;
    }

    if (CFGetTypeID(bestItem) == SecCertificateGetTypeID())
    {
        CFRetain(bestItem);
        *pCertOut = reinterpret_cast<SecCertificateRef>(const_cast<void*>(bestItem));
        return 1;
    }

    if (CFGetTypeID(bestItem) == SecIdentityGetTypeID())
    {
        CFRetain(bestItem);
        *pIdentityOut = reinterpret_cast<SecIdentityRef>(const_cast<void*>(bestItem));

        return 1;
    }

    return -19;
}
Exemplo n.º 2
0
extern "C" int32_t
AppleCryptoNative_X509DemuxAndRetainHandle(CFTypeRef handle, SecCertificateRef* pCertOut, SecIdentityRef* pIdentityOut)
{
    if (pCertOut != nullptr)
        *pCertOut = nullptr;
    if (pIdentityOut != nullptr)
        *pIdentityOut = nullptr;

    if (handle == nullptr || pCertOut == nullptr || pIdentityOut == nullptr)
        return kErrorBadInput;

    auto objectType = CFGetTypeID(handle);
    void* nonConstHandle = const_cast<void*>(handle);

    if (objectType == SecIdentityGetTypeID())
    {
        *pIdentityOut = reinterpret_cast<SecIdentityRef>(nonConstHandle);
    }
    else if (objectType == SecCertificateGetTypeID())
    {
        *pCertOut = reinterpret_cast<SecCertificateRef>(nonConstHandle);
    }
    else
    {
        return 0;
    }

    CFRetain(handle);
    return 1;
}
Exemplo n.º 3
0
static CFDictionaryRef
SecItemCopyAttributeDictionary(CFTypeRef ref) {
	CFDictionaryRef refDictionary = NULL;
	CFTypeID typeID = CFGetTypeID(ref);
	if (typeID == SecKeyGetTypeID()) {
		refDictionary = SecKeyCopyAttributeDictionary((SecKeyRef)ref);
	} else if (typeID == SecCertificateGetTypeID()) {
		refDictionary =
			SecCertificateCopyAttributeDictionary((SecCertificateRef)ref);
	} else if (typeID == SecIdentityGetTypeID()) {
        assert(false);
        SecIdentityRef identity = (SecIdentityRef)ref;
        SecCertificateRef cert = NULL;
        SecKeyRef key = NULL;
        if (!SecIdentityCopyCertificate(identity, &cert) &&
            !SecIdentityCopyPrivateKey(identity, &key)) 
        {
            CFDataRef data = SecCertificateCopyData(cert);
            CFDictionaryRef key_dict = SecKeyCopyAttributeDictionary(key);
            
            if (key_dict && data) {
                refDictionary = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, key_dict);
                CFDictionarySetValue((CFMutableDictionaryRef)refDictionary, 
                    CFSTR(CERTIFICATE_DATA_COLUMN_LABEL), data);
            }
            CFReleaseNull(key_dict);
            CFReleaseNull(data);
        }
        CFReleaseNull(cert);
        CFReleaseNull(key);
    } else {
		refDictionary = NULL;
	}
	return refDictionary;
}
/*
 * Assume incoming identity contains a root (e.g., created by
 * certtool) and add that cert to ST's trusted anchors. This
 * enables ST's verify of the incoming chain to succeed without 
 * a kludgy "AllowAnyRoot" specification.
 */
OSStatus addIdentityAsTrustedRoot(
	SSLContextRef 	ctx,
	CFArrayRef		identArray)
{
	CFIndex numItems = CFArrayGetCount(identArray);
	if(numItems == 0) {
		printf("***addIdentityAsTrustedRoot: empty identArray\n");
		return errSecParam;
	}
	
	/* Root should be the last item - could be identity, could be cert */
	CFTypeRef theItem = CFArrayGetValueAtIndex(identArray, numItems - 1);
	if(CFGetTypeID(theItem) == SecIdentityGetTypeID()) {
		/* identity */
		SecCertificateRef certRef;
		OSStatus ortn = SecIdentityCopyCertificate(
			(SecIdentityRef)theItem, &certRef);
		if(ortn) {
			cssmPerror("SecIdentityCopyCertificate", ortn);
			printf("***Error gettting cert from identity\n");
			return ortn;
		}
		ortn = addTrustedSecCert(ctx, certRef, false);
		CFRelease(certRef);
		return ortn;
	}
	else if(CFGetTypeID(theItem) == SecCertificateGetTypeID()) {
		/* certificate */
		return addTrustedSecCert(ctx, (SecCertificateRef)theItem, false);
	}
	else {
		printf("***Bogus item in identity array\n");
		return errSecParam;
	}
}
char *
_mongoc_secure_transport_extract_subject (const char *filename, const char *passphrase)
{
   bool success;
   char *retval = NULL;
   CFArrayRef items = NULL;
   SecExternalItemType type = kSecItemTypeCertificate;


   success = _mongoc_secure_transport_import_pem (filename, passphrase, &items, &type);

   if (!success) {
      return NULL;
   }

   if (type == kSecItemTypeAggregate) {
      for (CFIndex i = 0; i < CFArrayGetCount (items); ++i) {
         CFTypeID item_id = CFGetTypeID (CFArrayGetValueAtIndex (items, i));

         if (item_id == SecCertificateGetTypeID()) {
            retval = _mongoc_secure_transport_RFC2253_from_cert ((SecCertificateRef)CFArrayGetValueAtIndex (items, i));
            break;
         }
      }
   } else if (type == kSecItemTypeCertificate) {
      retval = _mongoc_secure_transport_RFC2253_from_cert ((SecCertificateRef)items);
   }

   if (items) {
      CFRelease (items);
   }

   return retval;
}
static CFType typeFromCFTypeRef(CFTypeRef type)
{
    ASSERT(type);

    if (type == tokenNullTypeRef())
        return Null;

    CFTypeID typeID = CFGetTypeID(type);
    if (typeID == CFArrayGetTypeID())
        return CFArray;
    if (typeID == CFBooleanGetTypeID())
        return CFBoolean;
    if (typeID == CFDataGetTypeID())
        return CFData;
    if (typeID == CFDictionaryGetTypeID())
        return CFDictionary;
    if (typeID == CFNullGetTypeID())
        return CFNull;
    if (typeID == CFNumberGetTypeID())
        return CFNumber;
    if (typeID == CFStringGetTypeID())
        return CFString;
    if (typeID == CFURLGetTypeID())
        return CFURL;
#if PLATFORM(MAC)
    if (typeID == SecCertificateGetTypeID())
        return SecCertificate;
#endif

    ASSERT_NOT_REACHED();
    return Unknown;
}
Exemplo n.º 7
0
/*
 * Specify recipients of the message. Implies that the message will be encrypted. 
 */
OSStatus CMSEncoderAddRecipients(
	CMSEncoderRef		cmsEncoder,
	CFTypeRef			recipientOrArray)
{
	if(cmsEncoder == NULL) {
		return errSecParam;
	}
	if(cmsEncoder->encState != ES_Init) {
		return errSecParam;
	}
	return cmsAppendToArray(recipientOrArray, &cmsEncoder->recipients, 
			SecCertificateGetTypeID());
}
Exemplo n.º 8
0
/* 
 * Specify additional certs to include in a signed message. 
 */
OSStatus CMSEncoderAddSupportingCerts(
	CMSEncoderRef		cmsEncoder,
	CFTypeRef			certOrArray)
{
	if(cmsEncoder == NULL) {
		return errSecParam;
	}
	if(cmsEncoder->encState != ES_Init) {
		return errSecParam;
	}
	return cmsAppendToArray(certOrArray, &cmsEncoder->otherCerts, 
			SecCertificateGetTypeID());
}
Exemplo n.º 9
0
bool
mongoc_secure_transport_setup_ca (
   mongoc_stream_tls_secure_transport_t *secure_transport,
   mongoc_ssl_opt_t *opt)
{
   if (opt->ca_file) {
      CFArrayRef items;
      SecExternalItemType type = kSecItemTypeCertificate;
      bool success = _mongoc_secure_transport_import_pem (
         opt->ca_file, NULL, &items, &type);

      if (!success) {
         MONGOC_ERROR ("Can't find certificate in \"%s\"", opt->ca_file);
         return false;
      }

      if (type == kSecItemTypeAggregate) {
         CFMutableArrayRef anchors = CFArrayCreateMutable (
            kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);

         for (CFIndex i = 0; i < CFArrayGetCount (items); ++i) {
            CFTypeID item_id = CFGetTypeID (CFArrayGetValueAtIndex (items, i));

            if (item_id == SecCertificateGetTypeID ()) {
               CFArrayAppendValue (anchors, CFArrayGetValueAtIndex (items, i));
            }
         }
         secure_transport->anchors = anchors;
         CFRelease (items);
      } else if (type == kSecItemTypeCertificate) {
         secure_transport->anchors = items;
      } else {
         CFRelease (items);
      }

      /* This should be SSLSetCertificateAuthorities But the /TLS/ tests fail
       * when it is */
      success = !SSLSetTrustedRoots (
         secure_transport->ssl_ctx_ref, secure_transport->anchors, true);
      TRACE ("Setting certificate authority %s (%s)",
             success ? "succeeded" : "failed",
             opt->ca_file);
      return true;
   }

   TRACE ("%s", "No CA provided, using defaults");
   return false;
}
static void encodeCertificateChain(Encoder& encoder, CFArrayRef certificateChain)
{
    CFIndex size = CFArrayGetCount(certificateChain);
    Vector<CFTypeRef, 32> values(size);

    CFArrayGetValues(certificateChain, CFRangeMake(0, size), values.data());

    encoder << static_cast<uint64_t>(size);

    for (CFIndex i = 0; i < size; ++i) {
        ASSERT(values[i]);
        ASSERT(CFGetTypeID(values[i]) == SecCertificateGetTypeID());

        auto data = adoptCF(SecCertificateCopyData((SecCertificateRef)values[i]));
        encodeCFData(encoder, data.get());
    }
}
Exemplo n.º 11
0
/*
 * Export items specified as SecKeychainItemRefs.
 */
void P12Coder::exportKeychainItems(
	CFArrayRef				items)
{
	assert(items != NULL);
	CFIndex numItems = CFArrayGetCount(items);
	for(CFIndex dex=0; dex<numItems; dex++) {
		const void *item = CFArrayGetValueAtIndex(items, dex);
		if(item == NULL) {
			p12ErrorLog("exportKeychainItems: NULL item\n");
			MacOSError::throwMe(errSecParam);
		}
		CFTypeID itemType = CFGetTypeID(item);
		if(itemType == SecCertificateGetTypeID()) {
			addSecCert((SecCertificateRef)item);
		}
		else if(itemType == SecKeyGetTypeID()) {
			addSecKey((SecKeyRef)item);
		}
		else {
			p12ErrorLog("exportKeychainItems: unknown item\n");
			MacOSError::throwMe(errSecParam);		
		}
	}
}
Exemplo n.º 12
0
/*
 * Store the specified certificate (or, more likely, some platform-dependent
 * reference to it) as the specified principal's certificate. Passing
 * in NULL for the client_cert has the effect of deleting the relevant entry
 * in the cert storage.
 */
krb5_error_code krb5_pkinit_set_client_cert(
    const char                  *principal,     /* full principal string */
    krb5_pkinit_cert_t          client_cert)
{
    SecCertificateRef certRef = (SecCertificateRef)client_cert;
    OSStatus ortn;
    CSSM_DATA issuerSerial = {0, NULL};
    CFDataRef cfIssuerSerial = NULL;
    CFDictionaryRef existDict = NULL;
    CFMutableDictionaryRef newDict = NULL;
    CFStringRef keyStr = NULL;
    krb5_error_code ourRtn = 0;

    if(certRef != NULL) {
        if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) {
            return KRB5KRB_ERR_GENERIC;
        }

        /* Cook up DER-encoded issuer/serial number */
        ortn = pkinit_get_cert_issuer_sn(certRef, &issuerSerial);
        if(ortn) {
            ourRtn = KRB5KRB_ERR_GENERIC;
            goto errOut;
        }
    }

    /*
     * Obtain the existing pref for kPkinitClientCertKey as a CFDictionary, or
     * cook up a new one.
     */
    ortn = pkinit_get_pref_dict(&existDict);
    if(ortn == noErr) {
        /* dup to a mutable dictionary */
        newDict = CFDictionaryCreateMutableCopy(NULL, 0, existDict);
    }
    else {
        if(certRef == NULL) {
            /* no existing entry, nothing to delete, we're done */
            return 0;
        }
        newDict = CFDictionaryCreateMutable(NULL, 0,
                                            &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    }
    if(newDict == NULL) {
        ourRtn = ENOMEM;
        goto errOut;
    }

    /* issuer / serial number ==> that dictionary */
    keyStr = CFStringCreateWithCString(NULL, principal, kCFStringEncodingASCII);
    if(certRef == NULL) {
        CFDictionaryRemoveValue(newDict, keyStr);
    }
    else {
        cfIssuerSerial = CFDataCreate(NULL, issuerSerial.Data, issuerSerial.Length);
        CFDictionarySetValue(newDict, keyStr, cfIssuerSerial);
    }

    /* dictionary ==> prefs */
    CFPreferencesSetValue(CFSTR(kPkinitClientCertKey), newDict,
                          CFSTR(kPkinitClientCertApp), kCFPreferencesCurrentUser, kCFPreferencesAnyHost);
    if(CFPreferencesSynchronize(CFSTR(kPkinitClientCertApp), kCFPreferencesCurrentUser,
                                kCFPreferencesAnyHost)) {
        ourRtn = 0;
    }
    else {
        ourRtn = EACCES;   /* any better ideas? */
    }
errOut:
    if(cfIssuerSerial) {
        CFRelease(cfIssuerSerial);
    }
    if(issuerSerial.Data) {
        free(issuerSerial.Data);
    }
    if(existDict) {
        CFRelease(existDict);
    }
    if(newDict) {
        CFRelease(newDict);
    }
    if(keyStr) {
        CFRelease(keyStr);
    }
    return ourRtn;
}
Exemplo n.º 13
0
OSStatus
parseIncomingCerts(
	SSLContext			*ctx,
	CFArrayRef			certs,
	CFArrayRef			*destCertChain,	/* &ctx->{localCertChain,encryptCertChain} */
	SSLPubKey			**sslPubKey,	/* &ctx->signingPubKey, etc. */
	SSLPrivKey			**sslPrivKey,	/* &ctx->signingPrivKeyRef, etc. */
	CFIndex				*signerAlg)		/* optional */
{
	OSStatus			ortn;
	CFIndex				ix, numCerts;
	SecIdentityRef 		identity;
	CFMutableArrayRef	certChain = NULL;	/* Retained */
	SecCertificateRef	leafCert = NULL;	/* Retained */
	SecKeyRef			pubKey = NULL;		/* Retained */
	SecKeyRef           privKey = NULL;		/* Retained */
	SecTrustRef         trust = NULL;		/* Retained */
	SecTrustResultType	trustResult;

	assert(ctx != NULL);
	assert(destCertChain != NULL);		/* though its referent may be NULL */
	assert(sslPubKey != NULL);
	assert(sslPrivKey != NULL);

	if (certs == NULL) {
		sslErrorLog("parseIncomingCerts: NULL incoming cert array\n");
		ortn = errSSLBadCert;
		goto errOut;
	}
	numCerts = CFArrayGetCount(certs);
	if (numCerts == 0) {
		sslErrorLog("parseIncomingCerts: empty incoming cert array\n");
		ortn = errSSLBadCert;
		goto errOut;
	}

	/*
	 * Certs[0] is an SecIdentityRef from which we extract subject cert,
	 * privKey, pubKey.
	 *
	 * 1. ensure the first element is a SecIdentityRef.
	 */
	identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0);
	if (identity == NULL) {
		sslErrorLog("parseIncomingCerts: bad cert array (1)\n");
		ortn = paramErr;
		goto errOut;
	}
	if (CFGetTypeID(identity) != SecIdentityGetTypeID()) {
		sslErrorLog("parseIncomingCerts: bad cert array (2)\n");
		ortn = paramErr;
		goto errOut;
	}

	/*
	 * 2. Extract cert, keys and convert to local format.
	 */
	ortn = SecIdentityCopyCertificate(identity, &leafCert);
	if (ortn) {
		sslErrorLog("parseIncomingCerts: bad cert array (3)\n");
		goto errOut;
	}

	/* Fetch private key from identity */
	ortn = SecIdentityCopyPrivateKey(identity, &privKey);
	if (ortn) {
		sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n",
			(int)ortn);
		goto errOut;
	}

	/* Convert the input array of SecIdentityRef at the start to an array of
	   all certificates. */
	certChain = CFArrayCreateMutable(kCFAllocatorDefault, numCerts,
		&kCFTypeArrayCallBacks);
	if (!certChain) {
		ortn = memFullErr;
		goto errOut;
	}
	CFArrayAppendValue(certChain, leafCert);
	for (ix = 1; ix < numCerts; ++ix) {
		SecCertificateRef intermediate =
			(SecCertificateRef)CFArrayGetValueAtIndex(certs, ix);
		if (intermediate == NULL) {
			sslErrorLog("parseIncomingCerts: bad cert array (5)\n");
			ortn = paramErr;
			goto errOut;
		}
		if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) {
			sslErrorLog("parseIncomingCerts: bad cert array (6)\n");
			ortn = paramErr;
			goto errOut;
		}

		CFArrayAppendValue(certChain, intermediate);
	}

	/* Obtain public key from cert */
#if TARGET_OS_IOS
	ortn = SecTrustCreateWithCertificates(certChain, NULL, &trust);
#else
	{
		SecPolicyRef policy = SecPolicyCreateBasicX509();
		ortn = SecTrustCreateWithCertificates(certChain, policy, &trust);
		CFReleaseSafe(policy);
		if (!ortn) {
			/* We are only interested in getting the public key from the leaf
			 * cert here, so for best performance, don't try to build a chain
			 * or search any keychains.
			 */
			CFArrayRef emptyArray = CFArrayCreate(NULL, NULL, 0, NULL);
			(void)SecTrustSetAnchorCertificates(trust, emptyArray);
			(void)SecTrustSetKeychains(trust, emptyArray);
			CFReleaseSafe(emptyArray);
		}
	}
#endif
	if (ortn) {
		sslErrorLog("parseIncomingCerts: SecTrustCreateWithCertificates err %d\n",
			(int)ortn);
		goto errOut;
	}
	ortn = SecTrustEvaluate(trust, &trustResult);
	if (ortn) {
		sslErrorLog("parseIncomingCerts: SecTrustEvaluate err %d\n",
			(int)ortn);
		goto errOut;
	}
	pubKey = SecTrustCopyPublicKey(trust);
	if (pubKey == NULL) {
		sslErrorLog("parseIncomingCerts: SecTrustCopyPublicKey failed\n");
		ortn = -67712; // errSecInvalidKeyRef
		goto errOut;
	}

	/* SUCCESS */
errOut:
	CFReleaseSafe(trust);
	CFReleaseSafe(leafCert);
	CFReleaseSafe(*destCertChain);
    sslFreePubKey(sslPubKey);
    sslFreePrivKey(sslPrivKey);

	if (ortn) {
		CFReleaseSafe(certChain);
		CFReleaseSafe(pubKey);
		CFReleaseSafe(privKey);

		*destCertChain = NULL;
	} else {
		*destCertChain = certChain;
		*sslPubKey = (SSLPubKey*)pubKey;
		*sslPrivKey = (SSLPrivKey*)privKey;
	}

	return ortn;
}
Exemplo n.º 14
0
OSStatus
parseIncomingCerts(
	SSLContext		*ctx,
	CFArrayRef		certs,
	SSLCertificate	**destCert,		/* &ctx->{localCert,encryptCert} */
	CSSM_KEY_PTR	*pubKey,		/* &ctx->signingPubKey, etc. */
	SecKeyRef		*privKeyRef,	/* &ctx->signingPrivKeyRef, etc. */
	CSSM_ALGORITHMS	*signerAlg)		/* optional */
{
	CFIndex				numCerts;
	CFIndex				cert;
	SSLCertificate		*certChain = NULL;
	SSLCertificate		*thisSslCert;
	OSStatus			ortn;
	SecIdentityRef 		identity;
	SecCertificateRef	certRef;
	SecKeyRef			keyRef;
	CSSM_DATA			certData;
	CSSM_CL_HANDLE		clHand;		// carefully derive from a SecCertificateRef
	CSSM_RETURN			crtn;
	CSSM_KEY_PTR        *pubKey;
	SecKeyRef           *privKeyRef;

	assert(ctx != NULL);
	assert(destCert != NULL);		/* though its referent may be NULL */
	assert(sslPubKey != NULL);
	assert(sslPrivKeyRef != NULL);

	pubKey = &sslPubKey->key;
	privKeyRef = &sslPrivKey->key;

	sslDeleteCertificateChain(*destCert, ctx);
	*destCert = NULL;
	*pubKey   = NULL;
	*privKeyRef = NULL;

	if(certs == NULL) {
		sslErrorLog("parseIncomingCerts: NULL incoming cert array\n");
		return errSSLBadCert;
	}
	numCerts = CFArrayGetCount(certs);
	if(numCerts == 0) {
		sslErrorLog("parseIncomingCerts: empty incoming cert array\n");
		return errSSLBadCert;
	}

	/*
	 * Certs[0] is an SecIdentityRef from which we extract subject cert,
	 * privKeyRef, pubKey.
	 *
	 * 1. ensure the first element is a SecIdentityRef.
	 */
	identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0);
	if(identity == NULL) {
		sslErrorLog("parseIncomingCerts: bad cert array (1)\n");
		return paramErr;
	}
	if(CFGetTypeID(identity) != SecIdentityGetTypeID()) {
		sslErrorLog("parseIncomingCerts: bad cert array (2)\n");
		return paramErr;
	}

	/*
	 * 2. Extract cert, keys and convert to local format.
	 */
	ortn = SecIdentityCopyCertificate(identity, &certRef);
	if(ortn) {
		sslErrorLog("parseIncomingCerts: bad cert array (3)\n");
		return ortn;
	}
	ortn = secCertToSslCert(ctx, certRef, &thisSslCert);
	if(ortn) {
		sslErrorLog("parseIncomingCerts: bad cert array (4)\n");
		return ortn;
	}
	/* enqueue onto head of cert chain */
	thisSslCert->next = certChain;
	certChain = thisSslCert;

	if(signerAlg != NULL) {
		ortn = sslCertSignerAlg(certRef, signerAlg);
		if(ortn) {
			return ortn;
		}
	}

	/* fetch private key from identity */
	ortn = SecIdentityCopyPrivateKey(identity, &keyRef);
	if(ortn) {
		sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n",
			(int)ortn);
		return ortn;
	}
	*privKeyRef = keyRef;

	/* obtain public key from cert */
	ortn = SecCertificateGetCLHandle(certRef, &clHand);
	if(ortn) {
		sslErrorLog("parseIncomingCerts: SecCertificateGetCLHandle err %d\n",
			(int)ortn);
		return ortn;
	}
	certData.Data = thisSslCert->derCert.data;
	certData.Length = thisSslCert->derCert.length;
	crtn = CSSM_CL_CertGetKeyInfo(clHand, &certData, pubKey);
	if(crtn) {
		sslErrorLog("parseIncomingCerts: CSSM_CL_CertGetKeyInfo err\n");
		return (OSStatus)crtn;
	}

	/* OK, that's the subject cert. Fetch optional remaining certs. */
	/*
	 * Convert: CFArray of SecCertificateRefs --> chain of SSLCertificates.
	 * Incoming certs have root last; SSLCertificate chain has root
	 * first.
	 */
	for(cert=1; cert<numCerts; cert++) {
		certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certs, cert);
		if(certRef == NULL) {
			sslErrorLog("parseIncomingCerts: bad cert array (5)\n");
			return paramErr;
		}
		if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) {
			sslErrorLog("parseIncomingCerts: bad cert array (6)\n");
			return paramErr;
		}

		/* Extract cert, convert to local format.
		*/
		ortn = secCertToSslCert(ctx, certRef, &thisSslCert);
		if(ortn) {
			sslErrorLog("parseIncomingCerts: bad cert array (7)\n");
			return ortn;
		}
		/* enqueue onto head of cert chain */
		thisSslCert->next = certChain;
		certChain = thisSslCert;
	}

	/* SUCCESS */
	*destCert = certChain;
	return noErr;

	/* free certChain, everything in it, other vars, return ortn */
	sslDeleteCertificateChain(certChain, ctx);
	/* FIXME - anything else? */
	return ortn;
}
bool
mongoc_secure_transport_setup_certificate (mongoc_stream_tls_secure_transport_t *secure_transport,
                                           mongoc_ssl_opt_t *opt)
{
   bool success;
   CFArrayRef items;
   SecIdentityRef id;
   SecKeyRef key = NULL;
   SecCertificateRef cert = NULL;
   SecExternalItemType type = kSecItemTypeCertificate;

   if (!opt->pem_file) {
      MONGOC_INFO ("No private key provided, the server won't be able to verify us");
      return false;
   }

   success = _mongoc_secure_transport_import_pem (opt->pem_file, opt->pem_pwd, &items, &type);
   if (!success) {
      MONGOC_ERROR ("Can't find certificate in: '%s'", opt->pem_file);
      return false;
   }

   if (type != kSecItemTypeAggregate) {
      MONGOC_ERROR ("Cannot work with keys of type \"%d\". Please file a JIRA", type);
      CFRelease (items);
      return false;
   }

   for (CFIndex i = 0; i < CFArrayGetCount (items); ++i) {
      CFTypeID item_id = CFGetTypeID (CFArrayGetValueAtIndex (items, i));

      if (item_id == SecCertificateGetTypeID()) {
         cert = (SecCertificateRef) CFArrayGetValueAtIndex (items, i);
      } else if (item_id == SecKeyGetTypeID()) {
         key = (SecKeyRef) CFArrayGetValueAtIndex (items, i);
      }
   }

   if (!cert || !key) {
      MONGOC_ERROR ("Couldn't find valid private key");
      CFRelease (items);
      return false;
   }

   id = SecIdentityCreate (kCFAllocatorDefault, cert, key);
   secure_transport->my_cert = CFArrayCreateMutableCopy(kCFAllocatorDefault, (CFIndex)2, items);

   CFArraySetValueAtIndex(secure_transport->my_cert, 0, id);
   CFArraySetValueAtIndex(secure_transport->my_cert, 1, cert);

   /*
    *  Secure Transport assumes the following:
    *    * The certificate references remain valid for the lifetime of the session.
    *    * The identity specified in certRefs[0] is capable of signing.
    */
   success = !SSLSetCertificate (secure_transport->ssl_ctx_ref, secure_transport->my_cert);
   MONGOC_DEBUG("Setting client certificate %s", success ? "succeeded" : "failed");

   CFRelease (items);
   return true;
}
OSStatus SecCertificateRequestGetResult(
        SecCertificateRequestRef certRequestRef,
        SecKeychainRef keychain,
        sint32 *estimatedTime,
        SecCertificateRef *certificateRef)
{
	BEGIN_SECAPI

	CssmData certData;
	*certificateRef = NULL;
	CertificateRequest::required(certRequestRef)->getResult(estimatedTime, certData);
	if(certData.data() != NULL) {
		/*
		 * Convert to SecCertifcateRef, optionally import. 
		 */
		CFDataRef cfCert = CFDataCreate(NULL, (UInt8 *)certData.data(), certData.Length);
		SecExternalItemType itemType = kSecItemTypeCertificate;
		CFArrayRef outItems = NULL;
		bool freeKcRef = false;
		OSStatus ortn;
		
		if(keychain == NULL) {
			/* 
			 * Unlike most Sec* calls, if the keychain argument to SecKeychainItemImport()
			 * is NULL, the item is not imported to the default keychain. At our
			 * interface, however, a NULL keychain means "import to the default
			 * keychain". 
			 */
			ortn = SecKeychainCopyDefault(&keychain);
			if(ortn) {
				certReqDbg("GetResult: SecKeychainCopyDefault failure");
				/* oh well, there's nothing we can do about this */
			}
			else {
				freeKcRef = true;
			}
		}
		ortn = SecKeychainItemImport(cfCert, NULL,
			NULL,			// format, don't care
			&itemType,
			0,				// flags
			NULL,			// keyParams
			keychain,		// optional, like ours
			&outItems);
		CFRelease(cfCert);
		if(freeKcRef) {
			CFRelease(keychain);
		}
		if(ortn) {
			certReqDbg("SecCertificateRequestGetResult: SecKeychainItemImport failure");
			MacOSError::throwMe(ortn);
		}
		CFIndex numItems = CFArrayGetCount(outItems);
		switch(numItems) {
			case 0:
				certReqDbg("SecCertificateRequestGetResult: import zero items");
				MacOSError::throwMe(errSecInternalComponent);
			default:
				certReqDbg("SecCertificateRequestGetResult: import %d items", 
					(int)numItems);
				/* but drop thru anyway, take the first one */
			case 1:
				SecCertificateRef certRef = 
					(SecCertificateRef)(CFArrayGetValueAtIndex(outItems, 0));
				if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) {
					certReqDbg("SecCertificateRequestGetResult: bad type");
				}
				else {
					CFRetain(certRef);
					*certificateRef = certRef;
				}
		}
		CFRelease(outItems);
	}	
	END_SECAPI
}
Exemplo n.º 17
0
int
trusted_cert_dump(int argc, char * const *argv)
{
    CFArrayRef certArray = NULL;
    OSStatus ortn = noErr;
    CFIndex numCerts;
    CFIndex dex;
    CFArrayRef trustSettings;
    int ourRtn = 0;
    SecTrustSettingsDomain domain = kSecTrustSettingsDomainUser;

    extern char *optarg;
    extern int optind;
    int arg;

    optind = 1;
    while ((arg = getopt(argc, argv, "sdh")) != -1) {
        switch (arg) {
        case 's':
            domain = kSecTrustSettingsDomainSystem;
            break;
        case 'd':
            domain = kSecTrustSettingsDomainAdmin;
            break;
        default:
        case 'h':
            return 2; /* @@@ Return 2 triggers usage message. */
        }
    }

    if(optind != argc) {
        return 2; /* @@@ Return 2 triggers usage message. */
    }

    ortn = SecTrustSettingsCopyCertificates(domain, &certArray);
    if(ortn) {
        cssmPerror("SecTrustSettingsCopyCertificates", ortn);
        return 1;
    }
    numCerts = CFArrayGetCount(certArray);
    printf("Number of trusted certs = %ld\n", (long)numCerts);

    for(dex=0; dex<numCerts; dex++) {
        SecCertificateRef certRef =
            (SecCertificateRef)CFArrayGetValueAtIndex(certArray, dex);
        if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) {
            fprintf(stderr, "***Bad CFGetTypeID for cert %ld\n", (long)dex);
            ourRtn = -1;
            break;
        }

        /* always print the cert's label */
        printf("Cert %ld: ", dex);
        printCertLabel(certRef);
        printf("\n");

        /* see if the cert has any usage constraints (it should!) */
        ortn = SecTrustSettingsCopyTrustSettings(certRef, domain, &trustSettings);
        if(ortn) {
            cssmPerror("SecTrustSettingsCopyTrustSettings", ortn);
            ourRtn = -1;
            continue;
        }
        if(displayTrustSettings(trustSettings)) {
            ourRtn = -1;
        }
    }
    CFRelease(certArray);

    return ourRtn;
}
static int do_keychain_import(
	SecKeychainRef		kcRef,
	CFDataRef			inData,
	SecExternalFormat   externFormat,
	SecExternalItemType itemType,
	SecAccessRef		access,
	Boolean				nonExtractable,
	const char			*passphrase,
	const char			*fileName,
	char				**attrNames,
	char				**attrValues,
	unsigned			numExtendedAttributes)
{
	SecKeyImportExportParameters	keyParams;
	OSStatus		ortn;
	CFStringRef		fileStr;
	CFArrayRef		outArray = NULL;
	int				result = 0;
	int				numCerts = 0;
	int				numKeys = 0;
	int				numIdentities = 0;
	int				tryCount = 0;
	CFIndex			dex;
	CFIndex			numItems = 0;
	CFStringRef		passStr = NULL;
	CFStringRef		promptStr = NULL;
	CFStringRef		retryStr = NULL;

	/*
	 * Specify some kind of passphrase in case caller doesn't know this
	 * is a wrapped object
	 */
	memset(&keyParams, 0, sizeof(SecKeyImportExportParameters));
	keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
	if(passphrase != NULL) {
		passStr = CFStringCreateWithCString(NULL, passphrase, kCFStringEncodingASCII);
		keyParams.passphrase = passStr;
	}
	else {
		keyParams.flags = kSecKeySecurePassphrase;
	}
	if(nonExtractable) {
        // explicitly set the key attributes, omitting the CSSM_KEYATTR_EXTRACTABLE bit
        keyParams.keyAttributes = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE;
    }
	keyParams.accessRef = access;

	fileStr = CFStringCreateWithCString(NULL, fileName, kCFStringEncodingUTF8);
	if (fileStr) {
		CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, fileStr, kCFURLPOSIXPathStyle, FALSE);
		if (fileURL) {
			CFStringRef nameStr = CFURLCopyLastPathComponent(fileURL);
			if (nameStr) {
				safe_CFRelease(&fileStr);
				fileStr = nameStr;
			}
			safe_CFRelease(&fileURL);
		}
	}
	promptStr = CFStringCreateWithFormat(NULL, NULL, KC_IMPORT_KEY_PASSWORD_MESSAGE, fileStr);
	retryStr = CFStringCreateWithFormat(NULL, NULL, KC_IMPORT_KEY_PASSWORD_RETRYMESSAGE, fileStr);

	while (TRUE)
	{
		keyParams.alertPrompt = (tryCount == 0) ? promptStr : retryStr;

		ortn = SecKeychainItemImport(inData,
									 fileStr,
									 &externFormat,
									 &itemType,
									 0,		/* flags not used (yet) */
									 &keyParams,
									 kcRef,
									 &outArray);

		if(ortn) {
			if (ortn == errSecPkcs12VerifyFailure && ++tryCount < 3) {
				continue;
			}
			sec_perror("SecKeychainItemImport", ortn);
			result = 1;
			goto cleanup;
		}
		break;
	}

	/*
	 * Parse returned items & report to user
	 */
	if(outArray == NULL) {
		sec_error("No keychain items found");
		result = 1;
		goto cleanup;
	}
	numItems = CFArrayGetCount(outArray);
	for(dex=0; dex<numItems; dex++) {
		CFTypeRef item = CFArrayGetValueAtIndex(outArray, dex);
		CFTypeID itemType = CFGetTypeID(item);
		if(itemType == SecIdentityGetTypeID()) {
			numIdentities++;
		}
		else if(itemType == SecCertificateGetTypeID()) {
			numCerts++;
		}
		else if(itemType == SecKeyGetTypeID()) {
			numKeys++;
		}
		else {
			sec_error("Unexpected item type returned from SecKeychainItemImport");
			result = 1;
			goto cleanup;
		}
	}
	if(numIdentities) {
		char *str;
		if(numIdentities > 1) {
			str = "identities";
		}
		else {
			str = "identity";
		}
		fprintf(stdout, "%d %s imported.\n", numIdentities, str);
	}
	if(numKeys) {
		char *str;
		if(numKeys > 1) {
			str = "keys";
		}
		else {
			str = "key";
		}
		fprintf(stdout, "%d %s imported.\n", numKeys, str);
	}
	if(numCerts) {
		char *str;
		if(numCerts > 1) {
			str = "certificates";
		}
		else {
			str = "certificate";
		}
		fprintf(stdout, "%d %s imported.\n", numCerts, str);
	}

	/* optionally apply extended attributes */
	if(numExtendedAttributes) {
		unsigned attrDex;
		for(attrDex=0; attrDex<numExtendedAttributes; attrDex++) {
			CFStringRef attrNameStr = CFStringCreateWithCString(NULL, attrNames[attrDex],
				kCFStringEncodingASCII);
			CFDataRef attrValueData = CFDataCreate(NULL, (const UInt8 *)attrValues[attrDex],
				strlen(attrValues[attrDex]));
			for(dex=0; dex<numItems; dex++) {
				SecKeychainItemRef itemRef =
					(SecKeychainItemRef)CFArrayGetValueAtIndex(outArray, dex);
				ortn = SecKeychainItemSetExtendedAttribute(itemRef, attrNameStr, attrValueData);
				if(ortn) {
					cssmPerror("SecKeychainItemSetExtendedAttribute", ortn);
					result = 1;
					break;
				}
			}	/* for each imported item */
			CFRelease(attrNameStr);
			CFRelease(attrValueData);
			if(result) {
				break;
			}
		}	/* for each extended attribute */
	}

cleanup:
	safe_CFRelease(&fileStr);
	safe_CFRelease(&outArray);
	safe_CFRelease(&passStr);
	safe_CFRelease(&promptStr);
	safe_CFRelease(&retryStr);

	return result;
}
static OSStatus
parseIncomingCerts(CFArrayRef			certs,
                   SSLCertificate       **destCertChain, /* &ctx->{localCertChain,encryptCertChain} */
                   tls_private_key_t    *sslPrivKey)	 /* &ctx->signingPrivKeyRef, etc. */
{
    OSStatus			ortn;
    CFIndex				ix, numCerts;
    SecIdentityRef 		identity;
    SSLCertificate      *certChain = NULL;	/* Retained */
    SecCertificateRef	leafCert = NULL;	/* Retained */
    SecKeyRef           privKey = NULL;	/* Retained */

    assert(destCertChain != NULL);		/* though its referent may be NULL */
    assert(sslPrivKey != NULL);

    if (certs == NULL) {
        sslErrorLog("parseIncomingCerts: NULL incoming cert array\n");
        ortn = errSSLBadCert;
        goto errOut;
    }
    numCerts = CFArrayGetCount(certs);
    if (numCerts == 0) {
        sslErrorLog("parseIncomingCerts: empty incoming cert array\n");
        ortn = errSSLBadCert;
        goto errOut;
    }

    certChain=sslMalloc(numCerts*sizeof(SSLCertificate));
    if (!certChain) {
        ortn = errSecAllocate;
        goto errOut;
    }

    /*
     * Certs[0] is an SecIdentityRef from which we extract subject cert,
     * privKey, pubKey.
     *
     * 1. ensure the first element is a SecIdentityRef.
     */
    identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0);
    if (identity == NULL) {
        sslErrorLog("parseIncomingCerts: bad cert array (1)\n");
        ortn = errSecParam;
        goto errOut;
    }
    if (CFGetTypeID(identity) != SecIdentityGetTypeID()) {
        sslErrorLog("parseIncomingCerts: bad cert array (2)\n");
        ortn = errSecParam;
        goto errOut;
    }

    /*
     * 2. Extract cert, keys and convert to local format.
     */
    ortn = SecIdentityCopyCertificate(identity, &leafCert);
    if (ortn) {
        sslErrorLog("parseIncomingCerts: bad cert array (3)\n");
        goto errOut;
    }

    /* Fetch private key from identity */
    ortn = SecIdentityCopyPrivateKey(identity, &privKey);
    if (ortn) {
        sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n",
                    (int)ortn);
        goto errOut;
    }

    /* Convert the input array of SecIdentityRef at the start to an array of
     all certificates. */
    SSLCopyBufferFromData(SecCertificateGetBytePtr(leafCert), SecCertificateGetLength(leafCert), &certChain[0].derCert);
    certChain[0].next = NULL;

    for (ix = 1; ix < numCerts; ++ix) {
        SecCertificateRef intermediate =
        (SecCertificateRef)CFArrayGetValueAtIndex(certs, ix);
        if (intermediate == NULL) {
            sslErrorLog("parseIncomingCerts: bad cert array (5)\n");
            ortn = errSecParam;
            goto errOut;
        }
        if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) {
            sslErrorLog("parseIncomingCerts: bad cert array (6)\n");
            ortn = errSecParam;
            goto errOut;
        }

        SSLCopyBufferFromData(SecCertificateGetBytePtr(intermediate), SecCertificateGetLength(intermediate), &certChain[ix].derCert);
        certChain[ix].next = NULL;
        certChain[ix-1].next = &certChain[ix];

    }

    size_t size = SecKeyGetBlockSize(privKey);
    tls_private_key_desc_t desc;

    if(SecKeyGetAlgorithmId(privKey) == kSecRSAAlgorithmID) {
        desc.type = tls_private_key_type_rsa;
        desc.rsa.sign = mySSLPrivKeyRSA_sign;
        desc.rsa.decrypt = mySSLPrivKeyRSA_decrypt;
        desc.rsa.size = SecKeyGetBlockSize(privKey);
    } else if (SecKeyGetAlgorithmId(privKey) == kSecECDSAAlgorithmID) {
        desc.type = tls_private_key_type_ecdsa;
        desc.ecdsa.sign = mySSLPrivKeyECDSA_sign;
        desc.ecdsa.curve = SecECKeyGetNamedCurve(privKey);
#if TARGET_OS_IPHONE
        /* Compute signature size from key size */
        desc.ecdsa.size  = 8+2*size;
#else
        desc.ecdsa.size  = size;
#endif
    } else {
        ortn = errSecParam;
        goto errOut;
    }
    *sslPrivKey = tls_private_key_create(&desc, privKey, (tls_private_key_ctx_release)&CFRelease);
    if(*sslPrivKey)
        ortn = errSecSuccess;
    else
        ortn = errSecAllocate;
    
    /* SUCCESS */
errOut:
    CFReleaseSafe(leafCert);

    if (ortn) {
        free(certChain);
        CFReleaseSafe(privKey);
        *destCertChain = NULL;
    } else {
        *destCertChain = certChain;
    }
    
    return ortn;
}