OSStatus
EAPOLClientSetACLForIdentity(SecIdentityRef identity)
{
    SecKeyRef		private_key = NULL;
    CFArrayRef		trusted_apps = NULL;
    OSStatus		status;

    status = SecIdentityCopyPrivateKey(identity, &private_key);
    if (status != noErr) {
	goto done;
    }
    trusted_apps = copy_trusted_applications(TRUE);
    if (trusted_apps == NULL) {
	status = errSecParam;
	goto done;
    }
    status 
	= EAPSecKeychainItemSetAccessForTrustedApplications((SecKeychainItemRef)
							    private_key,
							    trusted_apps);
 done:
    my_CFRelease(&private_key);
    my_CFRelease(&trusted_apps);
    return (status);
}
示例#2
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;
}
示例#3
0
SecKeyRef _crypt_get_private_key() {
    
    uint8_t keyData[strlen(AIRPORT_PRIVATE_KEY_P12)];
    size_t keyDataLen = base64_decode(AIRPORT_PRIVATE_KEY_P12, keyData);
    
    CFDataRef key = CFDataCreate(NULL, keyData, keyDataLen);
    
    CFMutableDictionaryRef options = CFDictionaryCreateMutable(NULL, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(options, kSecImportExportPassphrase, CFSTR(""));
    
    CFArrayRef items = NULL;
    
    OSStatus error = SecPKCS12Import(key, options, &items);
    
    SecKeyRef privateKey = NULL;
    
    if (error == noErr && CFArrayGetCount(items) > 0) {
        CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
        SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
        error = SecIdentityCopyPrivateKey(identity, &privateKey);
        if (error != noErr)
            privateKey = NULL;
    }
    
    CFRelease(items);
    CFRelease(options);
    
    return privateKey;
    
}
示例#4
0
extern "C" int32_t AppleCryptoNative_X509CopyPrivateKeyFromIdentity(SecIdentityRef identity, SecKeyRef* pPrivateKeyOut)
{
    if (pPrivateKeyOut != nullptr)
        *pPrivateKeyOut = nullptr;

    // This function handles null inputs for both identity and key
    return SecIdentityCopyPrivateKey(identity, pPrivateKeyOut);
}
示例#5
0
int
nss_cms_FindCertAndKeyByRecipientList(SecCmsRecipient **recipient_list, void *wincx)
{
    SecCmsRecipient *recipient;
    SecCertificateRef cert = NULL;
    SecPrivateKeyRef privKey = NULL;
    SecIdentityRef identity = NULL;
    CFTypeRef keychainOrArray = NULL; // @@@ The caller should be able to pass this in somehow.
    int index;

    for (index = 0; recipient_list[index] != NULL; ++index)
    {
	recipient = recipient_list[index];

	switch (recipient->kind)
	{
	case RLIssuerSN:
	    identity = CERT_FindIdentityByIssuerAndSN(keychainOrArray, recipient->id.issuerAndSN);
	    break;
	case RLSubjKeyID:
	    identity = CERT_FindIdentityBySubjectKeyID(keychainOrArray, recipient->id.subjectKeyID);
	    break;
	}

	if (identity)
	    break;
    }

    if (!recipient)
	goto loser;

    if (SecIdentityCopyCertificate(identity, &cert))
	goto loser;
    if (SecIdentityCopyPrivateKey(identity, &privKey))
	goto loser;
    CFRelease(identity);

    recipient->cert = cert;
    recipient->privkey = privKey;

    return index;

loser:
    if (identity)
	CFRelease(identity);
    if (cert)
	CFRelease(cert);
    if (privKey)
	CFRelease(privKey);

    return -1;
}
void signData(SecIdentityRef identity, const uint8_t *from, int flen, uint8_t *to, size_t *tlen)
{
  SecKeyRef privateKey = NULL;
  OSStatus status;

  status = SecIdentityCopyPrivateKey(identity,  &privateKey);
  if (status != noErr)
    {
      printErrorStatusMsg("signData: SecIdentityCopyPrivateKey", status);
      *tlen = 0;
      return;
    }

  status = SecKeyRawSign(privateKey, kSecPaddingPKCS1, from, flen, to, tlen);
  CFRelease(privateKey);
  if (status != noErr)
    {
      printErrorStatusMsg("signData: SecKeyRawSign", status);
      *tlen = 0;
      return;
    }
}
示例#7
0
SecCmsSignerInfoRef
SecCmsSignerInfoCreate(SecCmsMessageRef cmsg, SecIdentityRef identity, SECOidTag digestalgtag)
{
    SecCmsSignerInfoRef signerInfo = NULL;
    SecCertificateRef cert = NULL;
    SecPrivateKeyRef signingKey = NULL;

    if (SecIdentityCopyCertificate(identity, &cert))
	goto loser;
    if (SecIdentityCopyPrivateKey(identity, &signingKey))
	goto loser;

    signerInfo = nss_cmssignerinfo_create(cmsg, SecCmsSignerIDIssuerSN, cert, NULL, NULL, signingKey, digestalgtag);

loser:
    if (cert)
	CFRelease(cert);
    if (signingKey)
	CFRelease(signingKey);

    return signerInfo;
}
示例#8
0
/*
 * In Mac OS terms, get the keychain on which a given identity resides.
 */
static krb5_error_code pkinit_cert_to_db(
    krb5_pkinit_signing_cert_t   idRef,
    krb5_pkinit_cert_db_t        *dbRef)
{
    SecKeychainRef kcRef = NULL;
    SecKeyRef keyRef = NULL;
    OSStatus ortn;

    /* that's an identity - get the associated key's keychain */
    ortn = SecIdentityCopyPrivateKey((SecIdentityRef)idRef, &keyRef);
    if(ortn) {
        pkiCssmErr("SecIdentityCopyPrivateKey", ortn);
        return ortn;
    }
    ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)keyRef, &kcRef);
    if(ortn) {
        pkiCssmErr("SecKeychainItemCopyKeychain", ortn);
    }
    else {
        *dbRef = (krb5_pkinit_cert_db_t)kcRef;
    }
    CFRelease(keyRef);
    return ortn;
}
示例#9
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;
}
示例#10
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;
}
示例#11
0
int findEncryptionIdentities(CFTypeRef *identityOrArray)
{
	/*
		Similar code is available in Leopard9A311 and later as "DIHLFVCopyEncryptionIdentities".
		See <rdar://problem/4816811> FV: Add SecTokenBasedEncryptionIdentities call
		We reproduce it here for two reasons:
		1)	The semantics of DIHLFVCopyEncryptionIdentities are different, 
			returning either a CFData or CFArray
		2)	We don' have to introduce a dependence on DiskImages.framework here


		Since CSSM searching for attributes is an AND, not an OR, we need to get all
		identities then check each one for a good key usage. If we built up a search
		using an OR predicate, we would want to specify this for key usage:
		
		uint32_t keyuse = CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP;
	*/
	OSStatus status = noErr;
	CFArrayRef searchList = NULL;
	CFMutableArrayRef idArray = NULL;			// holds all SecIdentityRefs found

	status = SecKeychainCopyDomainSearchList(kSecPreferencesDomainDynamic, &searchList);
	if (status)
		return status;
		
	CFIndex count = searchList ? CFArrayGetCount(searchList) : 0;
	if (!count)
		return errSecNoSuchKeychain;

	// Search for all identities
	uint32_t keyuse = 0;
	SecIdentitySearchRef srchRef = NULL;
	status = SecIdentitySearchCreate(searchList, keyuse, &srchRef);
	if (status)
		return status;

	while (!status)
	{
		SecIdentityRef identity = NULL;
		status = SecIdentitySearchCopyNext(srchRef, &identity);
		if (status == errSecItemNotFound)	// done
			break;
		if (status)
			return status;

		SecKeyRef privateKeyRef = NULL;
		status = SecIdentityCopyPrivateKey(identity, &privateKeyRef);
		if (status)
			continue;
		bool canEncrypt = encryptionEnabled(privateKeyRef);
		CFRelease(privateKeyRef);
		if (!canEncrypt)
			continue;
			
		// add the identity to the array
		if (!idArray)
			idArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
		CFArrayAppendValue(idArray, identity);
	}

	if ((status == noErr || status == errSecItemNotFound) && idArray && CFArrayGetCount(idArray))
	{
		if (idArray)
		{
			*identityOrArray = idArray;
			::CFRetain(*identityOrArray);
		}
		status = noErr;
	}
	else
	if (idArray)
		CFRelease(idArray);

	return status;
}
static void tests(void)
{
    CFDataRef message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
        _user_one_p12, sizeof(_user_one_p12), kCFAllocatorNull);
    CFArrayRef items = NULL;
    SecCertificateRef cert = NULL;
    SecKeyRef pkey = NULL;

    is_status(SecPKCS12Import(message, NULL, NULL), errSecAuthFailed,
        "try null password on a known good p12");

    CFStringRef password = CFSTR("user-one");
    CFDictionaryRef options = CFDictionaryCreate(NULL,
        (const void **)&kSecImportExportPassphrase,
        (const void **)&password, 1,
        &kCFTypeDictionaryKeyCallBacks,
        &kCFTypeDictionaryValueCallBacks);
    ok_status(SecPKCS12Import(message, options, &items), "import user one");

    is(CFArrayGetCount(items), 1, "one identity");
    CFDictionaryRef item = CFArrayGetValueAtIndex(items, 0);
    SecIdentityRef identity = NULL;
    ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data");

    ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef");
    ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key");
    ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate");

    CFReleaseNull(items);
    CFReleaseNull(message);
    CFReleaseNull(options);
    CFReleaseNull(password);
    CFReleaseNull(cert);
    CFReleaseNull(pkey);

    message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
        _user_two_p12, sizeof(_user_two_p12), kCFAllocatorNull);
    items = NULL;
    password = CFSTR("user-two");
    options = CFDictionaryCreate(NULL,
        (const void **)&kSecImportExportPassphrase,
        (const void **)&password, 1,
        &kCFTypeDictionaryKeyCallBacks,
        &kCFTypeDictionaryValueCallBacks);

    ok_status(SecPKCS12Import(message, options, &items), "import user two");
    is(CFArrayGetCount(items), 1, "one identity");
    item = CFArrayGetValueAtIndex(items, 0);
    ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data");

    ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef");
    ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key");
    ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate");

    CFReleaseNull(items);
    CFReleaseNull(message);
    CFReleaseNull(options);
    CFReleaseNull(password);
    CFReleaseNull(cert);
    CFReleaseNull(pkey);



    message = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
                                          ECDSA_fails_import_p12, ECDSA_fails_import_p12_len, kCFAllocatorNull);
    items = NULL;
    password = CFSTR("test");
    options = CFDictionaryCreate(NULL,
                                 (const void **)&kSecImportExportPassphrase,
                                 (const void **)&password, 1,
                                 &kCFTypeDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks);

    ok_status(SecPKCS12Import(message, options, &items), "import ECDSA_fails_import_p12");
    is(CFArrayGetCount(items), 1, "one identity");
    item = CFArrayGetValueAtIndex(items, 0);
    ok(identity = (SecIdentityRef)CFDictionaryGetValue(item, kSecImportItemIdentity), "pull identity from imported data");

    ok(CFGetTypeID(identity)==SecIdentityGetTypeID(),"this is a SecIdentityRef");
    ok_status(SecIdentityCopyPrivateKey(identity, &pkey),"get private key");
    ok_status(SecIdentityCopyCertificate(identity, &cert), "get certificate");

    CFDataRef pubdata = NULL;
    SecKeyRef pubkey = NULL;

    ok_status(SecKeyCopyPublicBytes(pkey, &pubdata), "pub key from priv key");
    ok(pubkey = SecKeyCreateECPublicKey(kCFAllocatorDefault,
        CFDataGetBytePtr(pubdata), CFDataGetLength(pubdata), kSecKeyEncodingBytes),
       "recreate seckey");

    /* Sign something. */
    uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, };
    size_t sigLen = SecKeyGetSize(pkey, kSecKeySignatureSize);
    uint8_t sig[sigLen];
    ok_status(SecKeyRawSign(pkey, kSecPaddingPKCS1,
                            something, sizeof(something), sig, &sigLen), "sign something");
    ok_status(SecKeyRawVerify(pubkey, kSecPaddingPKCS1,
                              something, sizeof(something), sig, sigLen), "verify sig on something");


    CFReleaseNull(pubdata);
    CFReleaseNull(pubkey);
    CFReleaseNull(pkey);

    ok(pkey = SecKeyCreateECPrivateKey(kCFAllocatorDefault,
        ECDSA_fails_import_priv_only, ECDSA_fails_import_priv_only_len,
        kSecKeyEncodingPkcs1), "import privkey without pub");
    ok_status(SecKeyCopyPublicBytes(pkey, &pubdata), "pub key from priv key");
    ok(pubkey = SecKeyCreateECPublicKey(kCFAllocatorDefault,
        CFDataGetBytePtr(pubdata), CFDataGetLength(pubdata), kSecKeyEncodingBytes),
       "recreate seckey");
    ok_status(SecKeyRawVerify(pubkey, kSecPaddingPKCS1,
        something, sizeof(something), sig, sigLen), "verify sig on something");

    CFReleaseNull(pubdata);
    CFReleaseNull(pubkey);
    CFReleaseNull(pkey);
    CFReleaseNull(items);
    CFReleaseNull(message);
    CFReleaseNull(options);
    CFReleaseNull(password);
    CFReleaseNull(cert);

}
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;
}