OSStatus SecPKCS12Import(CFDataRef pkcs12_data, CFDictionaryRef options, CFArrayRef *items) { pkcs12_context context = {}; SecAsn1CoderCreate(&context.coder); if (options) context.passphrase = CFDictionaryGetValue(options, kSecImportExportPassphrase); context.items = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); int status = p12decode(&context, pkcs12_data); if (!status) { CFMutableArrayRef certs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFDictionaryApplyFunction(context.items, collect_certs, certs); CFMutableArrayRef identities = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); build_trust_chains_context a_build_trust_chains_context = { identities, certs }; CFDictionaryApplyFunction(context.items, build_trust_chains, &a_build_trust_chains_context); CFReleaseSafe(certs); /* ignoring certs that weren't picked up as part of the certchain for found keys */ *items = identities; } CFReleaseSafe(context.items); SecAsn1CoderRelease(context.coder); switch (status) { case p12_noErr: return noErr; case p12_passwordErr: return errSecAuthFailed; case p12_decodeErr: return errSecDecode; default: return errSecInternal; }; return noErr; }
static void securityd_server_trust_evaluate_done(const void *userData, SecCertificatePathRef chain, CFArrayRef details, CFDictionaryRef info, SecTrustResultType result) { struct securityd_server_trust_evaluation_context *tec = (struct securityd_server_trust_evaluation_context *)userData; /* @@@ This code snippit is also in SecTrustServer.c. I'd factor it, but a better fix would be to change the interfaces here to not use single in/out args and do all the argument munging in server.c and client.c. */ CFDictionaryRef args_out; CFNumberRef resultNumber = NULL; CFArrayRef chain_certs = NULL; /* Proccess outgoing results. */ resultNumber = CFNumberCreate(NULL, kCFNumberSInt32Type, &result); chain_certs = SecCertificatePathCopyArray(chain); const void *out_keys[] = { kSecTrustChainKey, kSecTrustDetailsKey, kSecTrustInfoKey, kSecTrustResultKey }; const void *out_values[] = { chain_certs, details, info, resultNumber }; args_out = (CFTypeRef)CFDictionaryCreate(kCFAllocatorDefault, out_keys, out_values, sizeof(out_keys) / sizeof(*out_keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFReleaseSafe(chain_certs); CFReleaseSafe(resultNumber); /* Send back the response to the client. */ securityd_server_send_reply(tec->reply, tec->request_id, noErr, args_out); free(tec); }
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; }
/* Return the first certificate reference from the supplied array * whose data matches the given certificate, or NULL if none match. */ static SecCertificateRef sslGetMatchingCertInArray( SecCertificateRef certRef, CFArrayRef certArray) { SecCertificateRef matchedCert = NULL; if (certRef == NULL || certArray == NULL) { return NULL; } CFDataRef certData = SecCertificateCopyData(certRef); if (certData) { CFIndex idx, count = CFArrayGetCount(certArray); for(idx=0; idx<count; idx++) { SecCertificateRef aCert = (SecCertificateRef)CFArrayGetValueAtIndex(certArray, idx); CFDataRef aData = SecCertificateCopyData(aCert); if (aData && CFEqual(aData, certData)) { matchedCert = aCert; } CFReleaseSafe(aData); if (matchedCert) break; } CFReleaseSafe(certData); } return matchedCert; }
static void SecTrustServerEvaluateDone(const void *userData, SecCertificatePathRef chain, CFArrayRef details, CFDictionaryRef info, SecTrustResultType result) { struct SecTrustEvaluationContext *tec = (struct SecTrustEvaluationContext *)userData; /* @@@ This code snippit is also in server.c. I'd factor it, but a better fix would be to chage the interfaces here to not use single in/out args and do all the argument munging in server.c and client.c. */ CFDictionaryRef args_out; CFNumberRef resultNumber = NULL; CFArrayRef chain_certs = NULL; /* Proccess outgoing results. */ resultNumber = CFNumberCreate(NULL, kCFNumberSInt32Type, &result); chain_certs = SecCertificatePathCopyArray(chain); const void *out_keys[] = { kSecTrustChainKey, kSecTrustDetailsKey, kSecTrustInfoKey, kSecTrustResultKey }; const void *out_values[] = { chain_certs, details, info, resultNumber }; args_out = (CFTypeRef)CFDictionaryCreate(kCFAllocatorDefault, out_keys, out_values, sizeof(out_keys) / sizeof(*out_keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFReleaseSafe(chain_certs); CFReleaseSafe(resultNumber); /* Return the final result. */ tec->args_out = args_out; if (tec->running) { /* Stop the runloop in SecTrustServerEvaluate if it is running. */ CFRunLoopStop(CFRunLoopGetCurrent()); } }
OSStatus SecECKeyGeneratePair(CFDictionaryRef parameters, SecKeyRef *publicKey, SecKeyRef *privateKey) { OSStatus status = errSecParam; CFAllocatorRef allocator = NULL; /* @@@ get from parameters. */ SecKeyRef pubKey = NULL; SecKeyRef privKey = SecKeyCreate(allocator, &kSecECPrivateKeyDescriptor, (const void*) parameters, 0, kSecGenerateKey); require(privKey, errOut); /* Create SecKeyRef's from the pkcs1 encoded keys. */ pubKey = SecKeyCreate(allocator, &kSecECPublicKeyDescriptor, privKey->key, 0, kSecExtractPublicFromPrivate); require(pubKey, errOut); if (publicKey) { *publicKey = pubKey; pubKey = NULL; } if (privateKey) { *privateKey = privKey; privKey = NULL; } status = errSecSuccess; errOut: CFReleaseSafe(pubKey); CFReleaseSafe(privKey); return status; }
static FILE * open_bundle(const char * path, const char * mode) { char full_path[1024] = {}; CFStringRef path_cfstring = NULL; CFURLRef path_url = NULL; CFBundleRef bundle = NULL; CFURLRef exec = NULL; path_cfstring = CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, path); require_quiet(path_cfstring, out); path_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_cfstring, kCFURLPOSIXPathStyle, true); require_quiet(path_url, out); bundle = CFBundleCreate(kCFAllocatorDefault, path_url); require_quiet(bundle, out); exec = CFBundleCopyExecutableURL(bundle); require(exec, out); require(CFURLGetFileSystemRepresentation(exec, true, (uint8_t*)full_path, sizeof(full_path)), out); out: CFReleaseSafe(path_cfstring); CFReleaseSafe(path_url); CFReleaseSafe(bundle); CFReleaseSafe(exec); return fopen(full_path, "r"); }
CFArrayRef SecCreateSignedCertificateTimestampsArrayFromSerializedSCTList(const uint8_t *p, size_t listLen) { size_t encodedListLen; CFMutableArrayRef sctArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); require_quiet(sctArray, out); require(listLen > 2 , out); encodedListLen = SSLDecodeSize(p); p+=2; listLen-=2; require(encodedListLen==listLen, out); while (listLen > 0) { size_t itemLen; require(listLen >= 2, out); itemLen = SSLDecodeSize(p); p += 2; listLen-=2; require(itemLen <= listLen, out); CFDataRef sctData = CFDataCreate(kCFAllocatorDefault, p, itemLen); p += itemLen; listLen -= itemLen; require(sctData, out); CFArrayAppendValue(sctArray, sctData); CFReleaseSafe(sctData); } return sctArray; out: CFReleaseSafe(sctArray); return NULL; }
static void testRSAKeyDesc() { SecKeyRef pubKey = NULL; CFStringRef pubRef = NULL; long pubLength = 0; pubKey = SecKeyCreateRSAPublicKey(kCFAllocatorDefault, rsaPubKey, sizeof(rsaPubKey), kSecKeyEncodingBytes); require_quiet( pubKey, fail); pubRef = CFCopyDescription(pubKey); require_quiet(pubRef, fail); pubLength = CFStringGetLength(pubRef)+1; char *publicDescription = (char*)malloc(pubLength); require_quiet(publicDescription != NULL, fail); if(false == CFStringGetCString(pubRef, publicDescription, pubLength, kCFStringEncodingUTF8)) { free(publicDescription); goto fail; } ok_status(strncmp(rsaKeyDescription, publicDescription, strlen(rsaKeyDescription)-17), "rsa key descriptions don't match: %s %s", rsaKeyDescription, publicDescription); free(publicDescription); fail: CFReleaseSafe(pubRef); CFReleaseSafe(pubKey); }
static void asynchttp_timer_proc(asynchttp_t *http) { CFStringRef req_meth = http->request ? CFHTTPMessageCopyRequestMethod(http->request) : NULL; CFURLRef req_url = http->request ? CFHTTPMessageCopyRequestURL(http->request) : NULL; secnotice("http", "Timeout during %@ %@.", req_meth, req_url); CFReleaseSafe(req_url); CFReleaseSafe(req_meth); asynchttp_complete(http); }
static void test_add_managedconfiguration_item(void) { CFMutableDictionaryRef query = test_create_managedconfiguration_query(); const char *v_data = "public managedconfiguration password history data"; CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); CFDictionaryAddValue(query, kSecValueData, pwdata); ok_status(SecItemAdd(query, NULL), "test_add_managedconfiguration_item"); CFReleaseSafe(pwdata); CFReleaseSafe(query); }
static void test_add_lockdown_identity_items(void) { CFMutableDictionaryRef query = test_create_lockdown_identity_query(); const char *v_data = "lockdown identity data (which should be a cert + key)"; CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); CFDictionaryAddValue(query, kSecValueData, pwdata); ok_status(SecItemAdd(query, NULL), "test_add_lockdown_identity_items"); CFReleaseSafe(pwdata); CFReleaseSafe(query); }
OSStatus sslCreateSecTrust( SSLContext *ctx, CFArrayRef certChain, bool arePeerCerts, SecTrustRef *pTrust) /* RETURNED */ { OSStatus status = memFullErr; CFStringRef peerDomainName = NULL; CFTypeRef policies = NULL; SecTrustRef trust = NULL; if (CFArrayGetCount(certChain) == 0) { status = errSSLBadCert; goto errOut; } if (arePeerCerts) { if (ctx->peerDomainNameLen && ctx->peerDomainName) { CFIndex len = ctx->peerDomainNameLen; if (ctx->peerDomainName[len - 1] == 0) { len--; //secwarning("peerDomainName is zero terminated!"); } /* @@@ Double check that this is the correct encoding. */ require(peerDomainName = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)ctx->peerDomainName, len, kCFStringEncodingUTF8, false), errOut); } } /* If we are the client, our peer certificates must satisfy the ssl server policy. */ bool server = ctx->protocolSide == kSSLClientSide; require(policies = SecPolicyCreateSSL(server, peerDomainName), errOut); require_noerr(status = SecTrustCreateWithCertificates(certChain, policies, &trust), errOut); /* If we have trustedAnchors we set them here. */ if (ctx->trustedCerts) { require_noerr(status = SecTrustSetAnchorCertificates(trust, ctx->trustedCerts), errOut); require_noerr(status = SecTrustSetAnchorCertificatesOnly(trust, ctx->trustedCertsOnly), errOut); } status = noErr; errOut: CFReleaseSafe(peerDomainName); CFReleaseSafe(policies); *pTrust = trust; return status; }
static CF_RETURNS_RETAINED CFDictionaryRef SecKeyGenerateAttributeDictionaryFor(SecKeyRef key, CFTypeRef keyType, CFDataRef privateBlob) { CFAllocatorRef allocator = CFGetAllocator(key); DICT_DECLARE(25); CFDataRef pubKeyDigest = NULL, pubKeyBlob = NULL; CFDictionaryRef dict = NULL; size_t sizeValue = SecKeyGetSize(key, kSecKeyKeySizeInBits); CFNumberRef sizeInBits = CFNumberCreate(allocator, kCFNumberLongType, &sizeValue); /* encode the public key. */ require_noerr(SecKeyCopyPublicBytes(key, &pubKeyBlob), errOut); require(pubKeyBlob, errOut); /* Calculate the digest of the public key. */ require(pubKeyDigest = SecSHA1DigestCreate(allocator, CFDataGetBytePtr(pubKeyBlob), CFDataGetLength(pubKeyBlob)), errOut); DICT_ADDPAIR(kSecClass, kSecClassKey); DICT_ADDPAIR(kSecAttrKeyClass, privateBlob ? kSecAttrKeyClassPrivate : kSecAttrKeyClassPublic); DICT_ADDPAIR(kSecAttrApplicationLabel, pubKeyDigest); DICT_ADDPAIR(kSecAttrIsPermanent, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrIsPrivate, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrIsModifiable, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrKeyType, keyType); DICT_ADDPAIR(kSecAttrKeySizeInBits, sizeInBits); DICT_ADDPAIR(kSecAttrEffectiveKeySize, sizeInBits); DICT_ADDPAIR(kSecAttrIsSensitive, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrWasAlwaysSensitive, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrIsExtractable, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrWasNeverExtractable, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanEncrypt, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanDecrypt, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrCanDerive, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrCanSign, kCFBooleanTrue); DICT_ADDPAIR(kSecAttrCanVerify, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanSignRecover, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanVerifyRecover, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanWrap, kCFBooleanFalse); DICT_ADDPAIR(kSecAttrCanUnwrap, kCFBooleanTrue); DICT_ADDPAIR(kSecValueData, privateBlob ? privateBlob : pubKeyBlob); dict = DICT_CREATE(allocator); errOut: // @@@ Zero out key material. CFReleaseSafe(pubKeyDigest); CFReleaseSafe(pubKeyBlob); CFReleaseSafe(sizeInBits); return dict; }
SOSCoderRef SOSCoderCreateFromData(CFDataRef exportedData, CFErrorRef *error) { SOSCoderRef p = calloc(1, sizeof(struct __OpaqueSOSCoder)); const uint8_t *der = CFDataGetBytePtr(exportedData); const uint8_t *der_end = der + CFDataGetLength(exportedData); CFDataRef otr_data = NULL; ccder_tag tag; require(ccder_decode_tag(&tag, der, der_end),fail); switch (tag) { case CCDER_OCTET_STRING: // TODO: this code is safe to delete? { der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, der_end); p->waitingForDataPacket = false; } break; case CCDER_CONSTRUCTED_SEQUENCE: { const uint8_t *sequence_end = NULL; der = ccder_decode_sequence_tl(&sequence_end, der, der_end); require_action_quiet(sequence_end == der_end, fail, SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Extra data in SOS coder"), NULL, error)); der = der_decode_data(kCFAllocatorDefault, 0, &otr_data, error, der, sequence_end); der = der_decode_bool(&p->waitingForDataPacket, der, sequence_end); if (der != sequence_end) { // optionally a pending response der = der_decode_data(kCFAllocatorDefault, 0, &p->pendingResponse, error, der, sequence_end); } } break; default: SecCFDERCreateError(kSOSErrorDecodeFailure, CFSTR("Unsupported SOS Coder DER"), NULL, error); goto fail; } require(der, fail); p->sessRef = SecOTRSessionCreateFromData(NULL, otr_data); require(p->sessRef, fail); CFReleaseSafe(otr_data); return p; fail: SOSCoderDispose(p); CFReleaseSafe(otr_data); return NULL; }
bool SOSTransportMessageSendMessageIfNeeded(SOSTransportMessageRef transport, CFStringRef circle_id, CFStringRef peer_id, CFErrorRef *error) { SOSEnginePeerMessageSentBlock sent = NULL; CFDataRef message_to_send = NULL; bool ok = false; SOSPeerRef peer = SOSPeerCreateWithEngine(SOSTransportMessageGetEngine(transport), peer_id); CFDataRef coderData = SOSEngineGetCoderData(SOSTransportMessageGetEngine(transport), peer_id); require(coderData, fail); SOSCoderRef coder = SOSCoderCreateFromData(coderData, error); require(coder, fail); SOSPeerSetCoder(peer, coder); ok = SOSPeerCoderSendMessageIfNeeded(peer, &message_to_send, circle_id, peer_id, &sent, error); coder = SOSPeerGetCoder(peer); if (message_to_send) { CFDictionaryRef peer_dict = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, peer_id, message_to_send, NULL); CFDictionaryRef circle_peers = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, circle_id, peer_dict, NULL); ok = ok && SOSTransportMessageSendMessages(transport, circle_peers, error); SOSPeerCoderConsume(&sent, ok); CFReleaseSafe(peer_dict); CFReleaseSafe(circle_peers); } Block_release(sent); CFReleaseSafe(message_to_send); coderData = SOSCoderCopyDER(coder, error); if(!SOSEngineSetCoderData(SOSTransportMessageGetEngine(transport), peer_id, coderData, error)){ secerror("SOSTransportMessageSendMessageIfNeeded, Could not save peer state"); } CFReleaseNull(coderData); if (coder) SOSCoderDispose(coder); fail: CFReleaseNull(peer); return ok; }
static void tests(void) { CFDataRef attached_signed_data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, attached_signed_data_der, attached_signed_data_der_len, kCFAllocatorNull); CFDataRef detached_signed_data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, detached_signed_data_der, detached_signed_data_der_len, kCFAllocatorNull); CFDataRef attached_no_data_signed_data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, attached_no_data_signed_data_der, attached_no_data_signed_data_der_len, kCFAllocatorNull); CFDataRef detached_data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, detached_content, detached_content_len, kCFAllocatorNull); CFDataRef no_data = CFDataCreate(kCFAllocatorDefault, NULL, 0); SecPolicyRef policy = SecPolicyCreateBasicX509(); SecTrustRef trust = NULL; ok_status(SecCMSVerifyCopyDataAndAttributes(attached_signed_data, NULL, policy, &trust, NULL, NULL), "verify attached data"); CFRelease(trust); ok_status(SecCMSVerifyCopyDataAndAttributes(detached_signed_data, detached_data, policy, &trust, NULL, NULL), "verify detached data"); CFRelease(trust); ok_status(SecCMSVerifyCopyDataAndAttributes(attached_no_data_signed_data, NULL, policy, &trust, NULL, NULL), "verify attached no data"); CFRelease(trust); ok_status(SecCMSVerifyCopyDataAndAttributes(attached_no_data_signed_data, no_data, policy, &trust, NULL, NULL), "verify attached no data"); CFRelease(trust); SecCertificateRef cert = NULL; SecKeyRef privKey = NULL; SecIdentityRef identity = NULL; isnt(cert = SecCertificateCreateWithBytes(NULL, signer_der, signer_der_len), NULL, "create certificate"); isnt(privKey = SecKeyCreateRSAPrivateKey(NULL, privkey_der, privkey_der_len, kSecKeyEncodingPkcs1), NULL, "create private key"); isnt(identity = SecIdentityCreate(NULL, cert, privKey), NULL, "create identity"); CFReleaseSafe(privKey); CFMutableDataRef cms_data = CFDataCreateMutable(kCFAllocatorDefault, 0); ok_status(SecCMSCreateSignedData(identity, detached_data, NULL, NULL, cms_data), "create attached data"); //write_data("/var/tmp/attached", cms_data); CFDataSetLength(cms_data, 0); CFDictionaryRef detached_cms_dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kSecCMSSignDetached, (const void **)&kCFBooleanTrue, 1, NULL, NULL); ok_status(SecCMSCreateSignedData(identity, detached_data, detached_cms_dict, NULL, cms_data), "create attached data"); CFRelease(detached_cms_dict); //write_data("/var/tmp/detached", cms_data); CFDataSetLength(cms_data, 0); ok_status(SecCMSCreateSignedData(identity, NULL, NULL, NULL, cms_data), "create attached data"); //write_data("/var/tmp/empty_attached", cms_data); CFReleaseSafe(cms_data); CFReleaseSafe(cert); CFReleaseNull(identity); CFRelease(attached_signed_data); CFRelease(detached_signed_data); CFRelease(attached_no_data_signed_data); CFRelease(detached_data); CFRelease(no_data); CFRelease(policy); }
static int mySSLPrivKeyRSA_sign(void *key, tls_hash_algorithm hash, const uint8_t *plaintext, size_t plaintextLen, uint8_t *sig, size_t *sigLen) { SecKeyRef keyRef = key; SecKeyAlgorithm algo; switch (hash) { case tls_hash_algorithm_None: return SecKeyRawSign(keyRef, kSecPaddingPKCS1, plaintext, plaintextLen, sig, sigLen); case tls_hash_algorithm_SHA1: algo = kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1; break; case tls_hash_algorithm_SHA256: algo = kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256; break; case tls_hash_algorithm_SHA384: algo = kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384; break; case tls_hash_algorithm_SHA512: algo = kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512; break; default: /* Unsupported hash - Internal error */ return errSSLInternal; } int err = errSSLInternal; CFDataRef signature = NULL; CFDataRef data = NULL; data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, plaintext, plaintextLen, kCFAllocatorNull); require(data, errOut); signature = SecKeyCreateSignature(keyRef, algo, data , NULL); require(signature, errOut); CFIndex len = CFDataGetLength(signature); const uint8_t *p = CFDataGetBytePtr(signature); require(p, errOut); require(len>=*sigLen, errOut); memcpy(sig, p, len); *sigLen = len; err = noErr; errOut: CFReleaseSafe(data); CFReleaseSafe(signature); return err; }
// // Returns a malloced array of CSSM_RETURN values, with the length in numStatusCodes, // for the certificate specified by chain index in the given SecTrustRef. // // To match legacy behavior, the array actually allocates one element more than the // value of numStatusCodes; if the certificate is revoked, the additional element // at the end contains the CrlReason value. // // Caller must free the returned pointer. // static CSSM_RETURN *copyCssmStatusCodes(SecTrustRef trust, unsigned int index, unsigned int *numStatusCodes) { if (!trust || !numStatusCodes) { return NULL; } *numStatusCodes = 0; CFArrayRef details = SecTrustCopyFilteredDetails(trust); CFIndex chainLength = (details) ? CFArrayGetCount(details) : 0; if (!(index < chainLength)) { CFReleaseSafe(details); return NULL; } CFDictionaryRef detail = (CFDictionaryRef)CFArrayGetValueAtIndex(details, index); CFIndex ix, detailCount = CFDictionaryGetCount(detail); *numStatusCodes = (unsigned int)detailCount; // Allocate one more entry than we need; this is used to store a CrlReason // at the end of the array. CSSM_RETURN *statusCodes = (CSSM_RETURN*)malloc((detailCount+1) * sizeof(CSSM_RETURN)); statusCodes[*numStatusCodes] = 0; const unsigned int resultmaplen = sizeof(cssmresultmap) / sizeof(resultmap_entry_t); const void *keys[detailCount]; CFDictionaryGetKeysAndValues(detail, &keys[0], NULL); for (ix = 0; ix < detailCount; ix++) { CFStringRef key = (CFStringRef)keys[ix]; CSSM_RETURN statusCode = CSSM_OK; for (unsigned int mapix = 0; mapix < resultmaplen; mapix++) { CFStringRef str = (CFStringRef) cssmresultmap[mapix].checkstr; if (CFStringCompare(str, key, 0) == kCFCompareEqualTo) { statusCode = (CSSM_RETURN) cssmresultmap[mapix].resultcode; break; } } if (statusCode == CSSMERR_TP_CERT_REVOKED) { SInt32 reason; CFNumberRef number = (CFNumberRef)CFDictionaryGetValue(detail, key); if (number && CFNumberGetValue(number, kCFNumberSInt32Type, &reason)) { statusCodes[*numStatusCodes] = (CSSM_RETURN)reason; } } statusCodes[ix] = statusCode; } CFReleaseSafe(details); return statusCodes; }
bool SOSAccountPublishCloudParameters(SOSAccountRef account, CFErrorRef* error){ bool success = false; CFIndex cloud_der_len = der_sizeof_cloud_parameters( account->user_public, account->user_key_parameters, error); CFMutableDataRef cloudParameters = CFDataCreateMutableWithScratch(kCFAllocatorDefault, cloud_der_len); if (der_encode_cloud_parameters(account->user_public, account->user_key_parameters, error, CFDataGetMutableBytePtr(cloudParameters), CFDataGetMutablePastEndPtr(cloudParameters)) != NULL) { CFErrorRef changeError = NULL; if (SOSTrasnportKeyParameterPublishCloudParameters(account->key_transport, cloudParameters, error)) { success = true; } else { SOSCreateErrorWithFormat(kSOSErrorSendFailure, changeError, error, NULL, CFSTR("update parameters key failed [%@]"), cloudParameters); } CFReleaseSafe(changeError); } else { SOSCreateError(kSOSErrorEncodeFailure, CFSTR("Encoding parameters failed"), NULL, error); } CFReleaseNull(cloudParameters); return success; }
OSStatus SecTrustStoreSetTrustSettings(SecTrustStoreRef ts, SecCertificateRef certificate, CFTypeRef trustSettingsDictOrArray) { CFDataRef certificateData = NULL; OSStatus status = errSecParam; if (gSecurityd) { status = gSecurityd->sec_trust_store_set_trust_settings(ts, certificate, trustSettingsDictOrArray); } else { require(ts == (SecTrustStoreRef)kSecTrustStoreUserName, errOut); require(certificateData = SecCertificateCopyData(certificate), errOut); const void *values[] = { (const void *)certificateData, (const void *)trustSettingsDictOrArray }; CFArrayRef in = CFArrayCreate(kCFAllocatorDefault, values, (trustSettingsDictOrArray ? 2 : 1), &kCFTypeArrayCallBacks); if (in) { status = ServerCommandSendReceive(sec_trust_store_set_trust_settings_id, in, NULL); CFRelease(in); } else { status = errSecAllocate; } } errOut: CFReleaseSafe(certificateData); return status; }
/******************************************************** *********** SecItemCertificateSource object ************ ********************************************************/ static bool SecItemCertificateSourceCopyParents( SecCertificateSourceRef source, SecCertificateRef certificate, void *context, SecCertificateSourceParents callback) { /* FIXME: Search for things other than just subject of our issuer if we have a subjectID or authorityKeyIdentifier. */ CFDataRef normalizedIssuer = SecCertificateGetNormalizedIssuerContent(certificate); const void *keys[] = { kSecClass, kSecReturnRef, kSecMatchLimit, kSecAttrSubject }, *values[] = { kSecClassCertificate, kCFBooleanTrue, kSecMatchLimitAll, normalizedIssuer }; CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, 4, NULL, NULL); CFTypeRef results = NULL; /* We can make this async or run this on a queue now easily. */ OSStatus status = SecItemCopyMatching(query, &results); CFRelease(query); if (status) { secdebug("trust", "SecItemCopyMatching status: %lu", status); } callback(context, results); CFReleaseSafe(results); return true; }
OSStatus sslCreateSecTrust( SSLContext *ctx, SecTrustRef *pTrust) /* RETURNED */ { OSStatus status = errSecAllocate; SecTrustRef trust = NULL; require_noerr(status = tls_helper_create_peer_trust(ctx->hdsk, ctx->protocolSide==kSSLServerSide, &trust), errOut); /* If we have trustedAnchors we set them here. */ if (trust && ctx->trustedCerts) { require_noerr(status = SecTrustSetAnchorCertificates(trust, ctx->trustedCerts), errOut); require_noerr(status = SecTrustSetAnchorCertificatesOnly(trust, ctx->trustedCertsOnly), errOut); } status = errSecSuccess; errOut: if(status != noErr) { CFReleaseSafe(trust); *pTrust = NULL; } else { *pTrust = trust; } return status; }
CFErrorRef SecCreateCFErrorWithXPCObject(xpc_object_t xpc_error) { CFErrorRef result = NULL; if (xpc_get_type(xpc_error) == XPC_TYPE_DICTIONARY) { CFStringRef domain = NULL; const char * domain_string = xpc_dictionary_get_string(xpc_error, kDomainKey); if (domain_string != NULL) { domain = CFStringCreateWithCString(kCFAllocatorDefault, domain_string, kCFStringEncodingUTF8); } else { domain = sSecXPCErrorDomain; CFRetain(domain); } CFIndex code = (CFIndex) xpc_dictionary_get_int64(xpc_error, kCodeKey); const char *description = xpc_dictionary_get_string(xpc_error, kDescriptionKey); SecCFCreateErrorWithFormat(code, domain, NULL, &result, NULL, CFSTR("Remote error : %s"), description); CFReleaseSafe(domain); } else { SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &result, NULL, CFSTR("Remote error not dictionary!: %@"), xpc_error); } return result; }
// Start OTR negotiation if we haven't already done so. SOSCoderStatus SOSCoderStart(SOSCoderRef coder, CFErrorRef *error) { CFMutableStringRef action = CFStringCreateMutable(kCFAllocatorDefault, 0); CFStringRef beginState = NULL; SOSCoderStatus result = kSOSCoderFailure; CFMutableDataRef startPacket = NULL; require_action_quiet(coder->sessRef, coderFailure, CFStringAppend(action, CFSTR("*** no otr session ***"))); beginState = CFCopyDescription(coder->sessRef); require_action_quiet(!coder->waitingForDataPacket, negotiatingOut, CFStringAppend(action, CFSTR("waiting for peer to send first data packet"))); require_action_quiet(!SecOTRSGetIsReadyForMessages(coder->sessRef), coderFailure, CFStringAppend(action, CFSTR("otr session ready")); result = kSOSCoderDataReturned); require_action_quiet(SecOTRSGetIsIdle(coder->sessRef), negotiatingOut, CFStringAppend(action, CFSTR("otr negotiating already"))); require_action_quiet(startPacket = CFDataCreateMutable(kCFAllocatorDefault, 0), coderFailure, SOSCreateError(kSOSErrorAllocationFailure, CFSTR("alloc failed"), NULL, error)); require_quiet(SOSOTRSAppendStartPacket(coder->sessRef, startPacket, error), coderFailure); CFRetainAssign(coder->pendingResponse, startPacket); negotiatingOut: result = kSOSCoderNegotiating; coderFailure: // Uber state log if (result == kSOSCoderFailure && error && *error) CFStringAppendFormat(action, NULL, CFSTR(" %@"), *error); secnotice("coder", "%@ %s %@ %@ returned %s", beginState, SecOTRPacketTypeString(startPacket), action, coder->sessRef, SOSCoderString(result)); CFReleaseNull(startPacket); CFReleaseSafe(beginState); CFRelease(action); return result; }
bool SecCAIssuerCopyParents(SecCertificateRef certificate, dispatch_queue_t queue, void *context, void (*callback)(void *, CFArrayRef)) { CFArrayRef issuers = SecCertificateGetCAIssuers(certificate); if (!issuers) { /* certificate has no caissuer urls, we're done. */ callback(context, NULL); return true; } CFArrayRef parents = SecCAIssuerRequestCacheCopyParents(certificate, issuers); if (parents) { callback(context, parents); CFReleaseSafe(parents); return true; } /* Cache miss, let's issue a network request. */ SecCAIssuerRequestRef request = (SecCAIssuerRequestRef)calloc(1, sizeof(*request)); request->http.queue = queue; request->http.completed = SecCAIssuerRequestCompleted; CFRetain(certificate); request->certificate = certificate; request->issuers = issuers; request->issuerIX = 0; request->context = context; request->callback = callback; return SecCAIssuerRequestIssue(request); }
/* Create a URI suitable for use in an http GET request, will return NULL if the length would exceed 255 bytes. */ static CFURLRef createGetURL(CFURLRef responder, CFDataRef request) { CFURLRef getURL = NULL; CFMutableDataRef base64Request = NULL; CFStringRef base64RequestString = NULL; CFStringRef peRequest = NULL; CFIndex base64Len; base64Len = SecBase64Encode(NULL, CFDataGetLength(request), NULL, 0); /* Don't bother doing all the work below if we know the end result will exceed 255 bytes (minus one for the '/' separator makes 254). */ if (base64Len + CFURLGetBytes(responder, NULL, 0) > 254) return NULL; require(base64Request = CFDataCreateMutable(kCFAllocatorDefault, base64Len), errOut); CFDataSetLength(base64Request, base64Len); SecBase64Encode(CFDataGetBytePtr(request), CFDataGetLength(request), (char *)CFDataGetMutableBytePtr(base64Request), base64Len); require(base64RequestString = CFStringCreateWithBytes(kCFAllocatorDefault, CFDataGetBytePtr(base64Request), base64Len, kCFStringEncodingUTF8, false), errOut); require(peRequest = CFURLCreateStringByAddingPercentEscapes( kCFAllocatorDefault, base64RequestString, NULL, CFSTR("+/="), kCFStringEncodingUTF8), errOut); #if 1 CFStringRef urlString = CFURLGetString(responder); CFStringRef fullURL; if (CFStringHasSuffix(urlString, CFSTR("/"))) { fullURL = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@%@"), urlString, peRequest); } else { fullURL = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@/%@"), urlString, peRequest); } getURL = CFURLCreateWithString(kCFAllocatorDefault, fullURL, NULL); CFRelease(fullURL); #else getURL = CFURLCreateWithString(kCFAllocatorDefault, peRequest, responder); #endif errOut: CFReleaseSafe(base64Request); CFReleaseSafe(base64RequestString); CFReleaseSafe(peRequest); return getURL; }
static OSStatus DER_UTCTimeToCFDate(const SecAsn1Item * utcTime, CFAbsoluteTime *date) { char *string = (char *)utcTime->Data; int year, month, mday, hour, minute, second, hourOff, minOff; /* Verify time is formatted properly and capture information */ second = 0; hourOff = 0; minOff = 0; CAPTURE(year,string+0,loser); if (year < 50) { /* ASSUME that year # is in the 2000's, not the 1900's */ year += 2000; } else { year += 1900; } CAPTURE(month,string+2,loser); if ((month == 0) || (month > 12)) goto loser; CAPTURE(mday,string+4,loser); if ((mday == 0) || (mday > 31)) goto loser; CAPTURE(hour,string+6,loser); if (hour > 23) goto loser; CAPTURE(minute,string+8,loser); if (minute > 59) goto loser; if (ISDIGIT(string[10])) { CAPTURE(second,string+10,loser); if (second > 59) goto loser; string += 2; } if (string[10] == '+') { CAPTURE(hourOff,string+11,loser); if (hourOff > 23) goto loser; CAPTURE(minOff,string+13,loser); if (minOff > 59) goto loser; } else if (string[10] == '-') { CAPTURE(hourOff,string+11,loser); if (hourOff > 23) goto loser; hourOff = -hourOff; CAPTURE(minOff,string+13,loser); if (minOff > 59) goto loser; minOff = -minOff; } else if (string[10] != 'Z') { goto loser; } if (hourOff == 0 && minOff == 0) { *date = CFAbsoluteTimeForGregorianZuluMoment(year, month, mday, hour, minute, second); } else { CFTimeZoneRef tz = CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, (hourOff * 60 + minOff) * 60); *date = CFAbsoluteTimeForGregorianMoment(tz, year, month, mday, hour, minute, second); CFReleaseSafe(tz); } return SECSuccess; loser: return SECFailure; }
static void SOSTransportMessageDestroy(CFTypeRef aObj){ SOSTransportMessageRef transport = (SOSTransportMessageRef) aObj; if (transport->destroy) transport->destroy(transport); CFReleaseSafe(transport->account); }
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); }