/* * Ensure that the policy being evaluated is accessible via * SecPolicySearch*(). Not really part of the test, but a handy place * to catch this common error before checking in TP changes. */ static int verifySecPolicy( const CSSM_OID *oid) { SecPolicySearchRef srchRef = NULL; OSStatus ortn; ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, oid, NULL, &srchRef); if(ortn) { cssmPerror("SecPolicySearchCreate", ortn); return -1; } SecPolicyRef policyRef = NULL; ortn = SecPolicySearchCopyNext(srchRef, &policyRef); if(ortn) { cssmPerror("SecPolicySearchCopyNext", ortn); printf("***The TP policy used in this test is not accessible via SecPolicySearchCopyNext().\n"); printf(" You probably forgot to add the policy to the theOidList table in PolicyCursor.cpp\n"); printf(" in the libsecurity_keychain project.\n"); } CFRelease(srchRef); if(policyRef) { CFRelease(policyRef); } return ortn; }
int dbOpenCloseEval(TestParams *testParams) { int ourRtn = 0; for(unsigned loop=0; loop<testParams->numLoops; loop++) { if(testParams->verbose) { printf("dbOpenClose thread %d: loop %d\n", testParams->threadNum, loop); } else if(!testParams->quiet) { printChar(testParams->progressChar); } /* attach to existing DB - don't create */ CSSM_DB_HANDLE dbHand = cuDbStartupByName(dlHand, (char *)DB_NAME, CSSM_FALSE, // don't create testParams->quiet); if(dbHand == 0) { printf("***dbOpenClose: error attaching to db %s\n", DB_NAME); ourRtn = -1; break; } CSSM_DL_DB_HANDLE dlDbHand = {dlHand, dbHand}; CSSM_RETURN crtn = CSSM_DL_DbClose(dlDbHand); if(crtn) { cssmPerror("CSSM_DL_DbClose", crtn); printf("***Error closing %s\n", DB_NAME); ourRtn = -1; break; } } return ourRtn; }
/* print a CFData as an X509 Name (i.e., subject or issuer) */ void printCfName( CFDataRef nameData, OidParser &parser) { SecAsn1CoderRef coder = NULL; OSStatus ortn; ortn = SecAsn1CoderCreate(&coder); if(ortn) { cssmPerror("SecAsn1CoderCreate", ortn); return; } /* subsequent errors to errOut: */ NSS_Name nssName = {NULL}; unsigned numRdns; ortn = SecAsn1Decode(coder, CFDataGetBytePtr(nameData), CFDataGetLength(nameData), kSecAsn1NameTemplate, &nssName); if(ortn) { printf("***Error decoding NSS_Name\n"); goto errOut; } numRdns = nssArraySize((const void **)nssName.rdns); for(unsigned dex=0; dex<numRdns; dex++) { printRdn(nssName.rdns[dex], parser); } errOut: if(coder) { SecAsn1CoderRelease(coder); } }
SECURITY_STATUS schan_imp_handshake(schan_imp_session session) { struct mac_session *s = (struct mac_session*)session; int status; TRACE("(%p/%p)\n", s, s->context); status = SSLHandshake(s->context); if (status == noErr) { TRACE("Handshake completed\n"); return SEC_E_OK; } else if (status == errSSLWouldBlock) { TRACE("Continue...\n"); return SEC_I_CONTINUE_NEEDED; } else if (errSecErrnoBase <= status && status <= errSecErrnoLimit) { ERR("Handshake failed: %s\n", strerror(status)); return SEC_E_INTERNAL_ERROR; } else { ERR("Handshake failed: %d\n", status); cssmPerror("SSLHandshake", status); return SEC_E_INTERNAL_ERROR; } /* Never reached */ return SEC_E_OK; }
/* * 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; } }
/* generate key pair, optionally storing the public key in encrypted form */ static int genKeyPair( bool pubKeyIsEncrypted, SecKeychainRef kcRef, SecKeyRef *pubKeyRef, SecKeyRef *privKeyRef) { /* gather keygen args */ CSSM_ALGORITHMS keyAlg = KEY_ALG; uint32 keySizeInBits = KEYSIZE; CSSM_KEYUSE pubKeyUsage = CSSM_KEYUSE_ANY; uint32 pubKeyAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT; if(pubKeyIsEncrypted) { pubKeyAttr |= CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT; } CSSM_KEYUSE privKeyUsage = CSSM_KEYUSE_ANY; uint32 privKeyAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE; OSStatus ortn = SecKeyCreatePair(kcRef, keyAlg, keySizeInBits, 0, pubKeyUsage, pubKeyAttr, privKeyUsage, privKeyAttr, NULL, // default initial access for now pubKeyRef, privKeyRef); if(ortn) { cssmPerror("SecKeyCreatePair", ortn); return 1; } return 0; }
static int p12Parse( const CSSM_DATA &rawBlob, P12ParseInfo &pinfo, unsigned depth) // print indent depth { NSS_P12_DecodedPFX pfx; memset(&pfx, 0, sizeof(pfx)); if(pinfo.mCoder.decodeItem(rawBlob, NSS_P12_DecodedPFXTemplate, &pfx)) { printf("***Error on top-level decode of NSS_P12_DecodedPFX\n"); return 1; } doIndent(depth); printf("version = %u\n", (unsigned)dataToInt(pfx.version)); NSS_P7_DecodedContentInfo &dci = pfx.authSafe; doIndent(depth); printf("contentType = %s\n", oidStr(dci.contentType, pinfo.mParser)); doIndent(depth); printf("type = %s\n", p7ContentInfoTypeStr(dci.type)); int rtn = 0; if(nssCompareCssmData(&dci.contentType, &CSSMOID_PKCS7_Data)) { doIndent(depth); printf("AuthenticatedSafe Length %u {\n", (unsigned)dci.content.data->Length); rtn = authSafeParse(*dci.content.data, pinfo, depth+3); doIndent(depth); printf("}\n"); } else { printf("Not parsing any other content type today.\n"); } if(pfx.macData) { doIndent(depth); printf("Mac Data {\n"); p12MacParse(*pfx.macData, pinfo, depth+3); doIndent(depth); printf("}\n"); if(pinfo.mPwd.Data == NULL) { doIndent(depth); printf("=== MAC not verified (no passphrase)===\n"); } else { CSSM_RETURN crtn = p12VerifyMac_app(pfx, pinfo.mCspHand, pinfo.mPwd, pinfo.mCoder); doIndent(depth); if(crtn) { cssmPerror("p12VerifyMac", crtn); doIndent(depth); printf("***MAC verify failure.\n"); } else { printf("MAC verifies OK.\n"); } } } return 0; }
/* * Given keyFileBase and key type, init a CSSM_KEY from contents of * keyFileBase. */ static int rt_readKey( CSSM_CSP_HANDLE cspHandle, const char *keyFileBase, CSSM_BOOL isPub, CSSM_ALGORITHMS alg, CSSM_KEY_PTR key) { char fileName[KEY_FILE_NAME_MAX_LEN]; int irtn; CSSM_DATA_PTR keyData = &key->KeyData; CSSM_KEYHEADER_PTR hdr = &key->KeyHeader; CSSM_RETURN crtn; CSSM_KEY_SIZE keySize; memset(key, 0, sizeof(CSSM_KEY)); rtKeyFileName(keyFileBase, isPub, fileName); irtn = readFile(fileName, &keyData->Data, (unsigned *)&keyData->Length); if(irtn) { printf("***error %d reading key file %s\n", irtn, fileName); return irtn; } hdr->HeaderVersion = CSSM_KEYHEADER_VERSION; hdr->BlobType = CSSM_KEYBLOB_RAW; /* Infer format from algorithm and key class */ switch(alg) { case CSSM_ALGID_RSA: if(isPub) { hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; } else { hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; } break; case CSSM_ALGID_DSA: hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186; break; default: printf("rt_readKey needs work\n"); exit(1); } hdr->AlgorithmId = alg; hdr->KeyClass = isPub ? CSSM_KEYCLASS_PUBLIC_KEY : CSSM_KEYCLASS_PRIVATE_KEY; hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE; hdr->KeyUsage = CSSM_KEYUSE_ANY; /* ask the CSP for key size */ crtn = CSSM_QueryKeySizeInBits(cspHandle, NULL, key, &keySize); if(crtn) { cssmPerror("CSSM_QueryKeySizeInBits", crtn); return 1; } hdr->LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; return 0; }
/* * No cert- or CDSA-related exceptions thrown by remainder. * This is the core initializer: have the CL parse and cache the cert. */ CSSM_RETURN CertParser::initWithData( const CSSM_DATA &certData) { assert(mClHand != 0); CSSM_RETURN crtn = CSSM_CL_CertCache(mClHand, &certData, &mCacheHand); #if CP_DEBUG if(crtn) { cssmPerror("CSSM_CL_CertCache", crtn); } #endif return crtn; }
/* convert an OID to a SecPolicyRef */ SecPolicyRef oidToPolicy( const CSSM_OID *oid) { OSStatus ortn; SecPolicyRef policyRef = NULL; ortn = SecPolicyCopy(CSSM_CERT_X_509v3, oid, &policyRef); if(ortn) { cssmPerror("SecPolicyCopy", ortn); return NULL; } return policyRef; }
/* Do SecTrustSetUserTrustLegacy() followed by SecTrustGetUserTrust() */ static int doSetVerifyUserTrust( SecCertificateRef certRef, SecPolicyRef policy, SecTrustResultType result) { OSStatus ortn; ortn = SecTrustSetUserTrustLegacy(certRef, policy, result); if(ortn) { cssmPerror("SecTrustSetUserTrustLegacy", ortn); return -1; } return doGetUserTrust(certRef, policy, result); }
extern int trust_settings_import(int argc, char * const *argv) { extern char *optarg; extern int optind; OSStatus ortn; int arg; char *settingsFile = NULL; unsigned char *settingsData = NULL; size_t settingsLen = 0; CFDataRef settings = NULL; SecTrustSettingsDomain domain = kSecTrustSettingsDomainUser; int rtn; if(argc < 2) { return 2; /* @@@ Return 2 triggers usage message. */ } optind = 1; while ((arg = getopt(argc, argv, "dh")) != -1) { switch (arg) { case 'd': domain = kSecTrustSettingsDomainAdmin; break; default: return 2; } } if(optind != (argc - 1)) { /* no args left for settings file */ return 2; } settingsFile = argv[optind]; rtn = readFileSizet(settingsFile, &settingsData, &settingsLen); if(rtn) { fprintf(stderr, "Error (%d) reading %s.\n", rtn, settingsFile); return 1; } settings = CFDataCreate(NULL, (const UInt8 *)settingsData, settingsLen); free(settingsData); ortn = SecTrustSettingsImportExternalRepresentation(domain, settings); CFRelease(settings); if(ortn) { cssmPerror("SecTrustSettingsImportExternalRepresentation", ortn); rtn = 1; } else if(!do_quiet) { fprintf(stdout, "...Trust Settings imported successfully.\n"); rtn = 0; } return rtn; }
extern int trust_settings_export(int argc, char * const *argv) { extern char *optarg; extern int optind; OSStatus ortn; int arg; CFDataRef settings = NULL; SecTrustSettingsDomain domain = kSecTrustSettingsDomainUser; int rtn; char *settingsFile = NULL; unsigned len; if(argc < 2) { return 2; /* @@@ Return 2 triggers usage message. */ } optind = 1; while ((arg = getopt(argc, argv, "dsh")) != -1) { switch (arg) { case 'd': domain = kSecTrustSettingsDomainAdmin; break; case 's': domain = kSecTrustSettingsDomainSystem; break; default: return 2; } } if(optind != (argc - 1)) { /* no args left for settings file */ return 2; } settingsFile = argv[optind]; ortn = SecTrustSettingsCreateExternalRepresentation(domain, &settings); if(ortn) { cssmPerror("SecTrustSettingsCreateExternalRepresentation", ortn); return 1; } len = (unsigned) CFDataGetLength(settings); rtn = writeFile(settingsFile, CFDataGetBytePtr(settings), len); if(rtn) { fprintf(stderr, "Error (%d) writing %s.\n", rtn, settingsFile); } else if(!do_quiet) { fprintf(stdout, "...Trust Settings exported successfully.\n"); } CFRelease(settings); return rtn; }
/* do a SecTrustEvaluate, ensure resultType is as specified */ static int doEval( CFArrayRef certs, SecPolicyRef policy, SecTrustResultType expectedResult, bool quiet) { OSStatus ortn; SecTrustRef trustRef = NULL; SecTrustResultType result; int ourRtn = 0; ortn = SecTrustCreateWithCertificates(certs, policy, &trustRef); if(ortn) { cssmPerror("SecTrustCreateWithCertificates", ortn); return -1; } ortn = SecTrustEvaluate(trustRef, &result); if(ortn) { /* shouldn't fail no matter what resultType we expect */ cssmPerror("SecTrustEvaluate", ortn); ourRtn = -1; goto errOut; } if(expectedResult == result) { if(!quiet) { printf("...got %s as expected\n", secTrustResultStr(result)); } } else { printf("***Expected %s, got %s\n", secTrustResultStr(expectedResult), secTrustResultStr(result)); ourRtn = -1; } errOut: CFRelease(trustRef); return ourRtn; }
/* print cert's label (the one SecCertificate infers) */ OSStatus printCertLabel( SecCertificateRef certRef) { OSStatus ortn; CFStringRef label; ortn = SecCertificateInferLabel(certRef, &label); if(ortn) { cssmPerror("SecCertificateInferLabel", ortn); return ortn; } printCfStr(label); CFRelease(label); return noErr; }
/* frees all the fields we fetched */ CertParser::~CertParser() { if(mClHand && mCacheHand) { CSSM_RETURN crtn = CSSM_CL_CertAbortCache(mClHand, mCacheHand); if(crtn) { /* almost certainly a bug */ printf("Internal Error: CertParser error on free."); cssmPerror("CSSM_CL_CertAbortCache", crtn); } } vector<CP_FetchedField *>::iterator iter; for(iter=mFetchedFields.begin(); iter!=mFetchedFields.end(); iter++) { delete *iter; } }
/* encrypt something with a public key */ static int pubKeyEncrypt( SecKeyRef pubKeyRef) { const CSSM_KEY *cssmKey; OSStatus ortn; CSSM_CSP_HANDLE cspHand; ortn = SecKeyGetCSSMKey(pubKeyRef, &cssmKey); if(ortn) { cssmPerror("SecKeyGetCSSMKey", ortn); return -1; } ortn = SecKeyGetCSPHandle(pubKeyRef, &cspHand); if(ortn) { cssmPerror("SecKeyGetCSPHandle", ortn); return -1; } char *ptext = "something to encrypt"; CSSM_DATA ptextData = {strlen(ptext), (uint8 *)ptext}; CSSM_DATA ctextData = { 0, NULL }; CSSM_RETURN crtn; crtn = cspEncrypt(cspHand, CSSM_ALGID_RSA, 0, CSSM_PADDING_PKCS1, // mode/pad cssmKey, NULL, 0, 0, // effect/rounds NULL, // IV &ptextData, &ctextData, CSSM_FALSE); if(crtn) { return -1; } /* slighyly hazardous, allocated by CSPDL's allocator */ free(ctextData.Data); return 0; }
/* * Determine if specified SecCertificateRef is a self-signed cert. * We do this by comparing the subject and issuerr names; no cryptographic * verification is performed. * * Returns true if the cert appears to be a root. */ static bool isCertRefRoot( SecCertificateRef certRef) { bool brtn = false; #if 0 /* just search for the two attrs we want */ UInt32 tags[2] = {kSecSubjectItemAttr, kSecIssuerItemAttr}; SecKeychainAttributeInfo attrInfo; attrInfo.count = 2; attrInfo.tag = tags; attrInfo.format = NULL; SecKeychainAttributeList *attrList = NULL; SecKeychainAttribute *attr1 = NULL; SecKeychainAttribute *attr2 = NULL; OSStatus ortn = SecKeychainItemCopyAttributesAndData( (SecKeychainItemRef)certRef, &attrInfo, NULL, // itemClass &attrList, NULL, // length - don't need the data NULL); // outData if(ortn) { cssmPerror("SecKeychainItemCopyAttributesAndData", ortn); /* may want to be a bit more robust here, but this should * never happen */ return false; } /* subsequent errors to errOut: */ if((attrList == NULL) || (attrList->count != 2)) { printf("***Unexpected result fetching label attr\n"); goto errOut; } /* rootness is just byte-for-byte compare of the two names */ attr1 = &attrList->attr[0]; attr2 = &attrList->attr[1]; if(attr1->length == attr2->length) { if(memcmp(attr1->data, attr2->data, attr1->length) == 0) { brtn = true; } } errOut: SecKeychainItemFreeAttributesAndData(attrList, NULL); #endif return brtn; }
/* app path string to SecTrustedApplicationRef */ SecTrustedApplicationRef appPathToAppRef( const char *appPath) { SecTrustedApplicationRef appRef = NULL; OSStatus ortn; if(appPath == NULL) { return NULL; } ortn = SecTrustedApplicationCreateFromPath(appPath, &appRef); if(ortn) { cssmPerror("SecTrustedApplicationCreateFromPath", ortn); return NULL; } return appRef; }
/* Do a SecTrustGetUserTrust(), ensure result is as specified */ static int doGetUserTrust( SecCertificateRef certRef, SecPolicyRef policy, SecTrustResultType expectedResult) { SecTrustResultType foundResult; OSStatus ortn = SecTrustGetUserTrust(certRef, policy, &foundResult); if(ortn) { cssmPerror("SecTrustGetUserTrust", ortn); return -1; } if(foundResult != expectedResult) { printf("***Expected current resultType %s; found %s\n", secTrustResultStr(expectedResult), secTrustResultStr(foundResult)); return -1; } return 0; }
/* * Print subject and/or issuer of a cert. */ void printCertName( const unsigned char *cert, unsigned certLen, WhichName whichName) { CSSM_CL_HANDLE clHand = getClHand(); CSSM_HANDLE cacheHand; CSSM_DATA certData = {certLen, (uint8 *)cert}; CSSM_RETURN crtn; bool printSubj = false; bool printIssuer = false; switch(whichName) { case NameBoth: printSubj = true; printIssuer = true; break; case NameSubject: printSubj = true; break; case NameIssuer: printIssuer = true; break; default: printf("***BRRZAP! Illegal whichName argument\n"); return; } crtn = CSSM_CL_CertCache(clHand, &certData, &cacheHand); if(crtn) { printf("***Error parsing cert\n"); cssmPerror("CSSM_CL_CertCache", crtn); return; } if(printSubj) { printOneCertName(clHand, cacheHand, "Subject", &CSSMOID_X509V1SubjectNameStd); } if(printIssuer) { printOneCertName(clHand, cacheHand, "Issuer", &CSSMOID_X509V1IssuerNameStd); } CSSM_CL_CertAbortCache(clHand, cacheHand); return; }
int main(int argc, char **argv) { bool quiet = false; int arg; while ((arg = getopt(argc, argv, "qh")) != -1) { switch (arg) { case 'q': quiet = true; break; case 'h': usage(argv); } } unsigned numCerts = argc - optind; if(numCerts == 0) { usage(argv); } CFMutableArrayRef certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); for(int dex=optind; dex<argc; dex++) { SecCertificateRef certRef = certFromFile(argv[dex]); if(certRef == NULL) { exit(1); } CFArrayAppendValue(certArray, certRef); CFRelease(certRef); } OSStatus ortn; SecPolicyRef policyRef = NULL; ortn = SecPolicyCopy(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL, &policyRef); if(ortn) { cssmPerror("SecPolicyCopy", ortn); exit(1); } int ourRtn = doTest(certArray, policyRef, quiet); CFRelease(policyRef); CFRelease(certArray); return ourRtn; }
static void printOneCertName( CSSM_CL_HANDLE clHand, CSSM_HANDLE cacheHand, const char *title, const CSSM_OID *oid) { CSSM_HANDLE resultHand = 0; CSSM_DATA_PTR field = NULL; uint32 numFields; CSSM_RETURN crtn; crtn = CSSM_CL_CertGetFirstCachedFieldValue(clHand, cacheHand, oid, &resultHand, &numFields, &field); if(crtn) { printf("***Error parsing cert\n"); cssmPerror("CSSM_CL_CertGetFirstCachedFieldValue", crtn); return; } printName(title, field->Data, field->Length); CSSM_CL_FreeFieldValue(clHand, oid, field); }
int readCertFile( const char *fileName, SecCertificateRef *certRef) { unsigned char *cp = NULL; unsigned len = 0; CSSM_DATA certData; OSStatus ortn; unsigned char *decoded = NULL; unsigned decodedLen = 0; if(readFile(fileName, &cp, &len)) { printf("***Error reading file %s\n", fileName); return -1; } if(isPem(cp, len)) { if(pemDecode(cp, len, &decoded, &decodedLen)) { fprintf(stderr, "Error decoding cert file %s\n", fileName); return -1; } certData.Length = decodedLen; certData.Data = decoded; } else { certData.Length = len; certData.Data = cp; } ortn = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, certRef); free(cp); if(decoded) { free(decoded); } if(ortn) { cssmPerror("SecCertificateCreateFromData", ortn); return -1; } return 0; }
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; }
int main(int argc, char **argv) { RingBuffer serverToClientRing; RingBuffer clientToServerRing; unsigned numBufs = DEFAULT_NUM_BUFS; unsigned bufSize = DEFAULT_BUF_SIZE; unsigned chunkSize = DEFAULT_CHUNK; unsigned char clientBuf[DEFAULT_CHUNK]; unsigned char serverBuf[DEFAULT_CHUNK]; RingBufferArgs clientArgs; RingBufferArgs serverArgs; bool abortFlag = false; pthread_t client_thread = NULL; int result; OSStatus ortn; unsigned char sessionTicket[SESSION_TICKET_SIZE]; int ourRtn = 0; CFArrayRef idArray = NULL; /* for SSLSetCertificate */ CFArrayRef anchorArray = NULL; /* trusted roots */ char *hostName = NULL; /* user-spec'd variables */ char *kcName = NULL; unsigned xferSize = DEFAULT_XFER; bool pauseOnError = false; bool runForever = false; bool skipPAC = false; extern int optind; extern char *optarg; int arg; optind = 1; while ((arg = getopt(argc, argv, "x:c:k:h:np")) != -1) { switch (arg) { case 'x': { unsigned xsize = atoi(optarg); if(xsize == 0) { runForever = true; /* and leave xferSize alone */ } else { xferSize = xsize; } break; } case 'k': kcName = optarg; break; case 'n': skipPAC = true; break; case 'h': /* mainly to test EAP session ticket and ServerName simultaneously */ hostName = optarg; break; case 'p': pauseOnError = true; break; default: usage(argv); } } if(optind != argc) { usage(argv); } /* set up ring buffers */ ringBufSetup(&serverToClientRing, "serveToClient", numBufs, bufSize); ringBufSetup(&clientToServerRing, "clientToServe", numBufs, bufSize); /* get optional server SecIdentity */ if(kcName) { SecKeychainRef kcRef = NULL; SecCertificateRef anchorCert = NULL; SecIdentityRef idRef = NULL; idArray = getSslCerts(kcName, CSSM_FALSE, /* encryptOnly */ CSSM_FALSE, /* completeCertChain */ NULL, /* anchorFile */ &kcRef); if(idArray == NULL) { printf("***Can't get signing cert from %s\n", kcName); exit(1); } idRef = (SecIdentityRef)CFArrayGetValueAtIndex(idArray, 0); ortn = SecIdentityCopyCertificate(idRef, &anchorCert); if(ortn) { cssmPerror("SecIdentityCopyCertificate", ortn); exit(1); } anchorArray = CFArrayCreate(NULL, (const void **)&anchorCert, 1, &kCFTypeArrayCallBacks); CFRelease(kcRef); CFRelease(anchorCert); } /* set up server side */ memset(&serverArgs, 0, sizeof(serverArgs)); serverArgs.xferSize = xferSize; serverArgs.xferBuf = serverBuf; serverArgs.chunkSize = chunkSize; serverArgs.ringWrite = &serverToClientRing; serverArgs.ringRead = &clientToServerRing; serverArgs.goFlag = &clientArgs.iAmReady; serverArgs.abortFlag = &abortFlag; serverArgs.pauseOnError = pauseOnError; appGetRandomBytes(serverArgs.sharedSecret, SHARED_SECRET_SIZE); if(!skipPAC) { serverArgs.setMasterSecret = true; } serverArgs.idArray = idArray; serverArgs.trustedRoots = anchorArray; /* set up client side */ memset(&clientArgs, 0, sizeof(clientArgs)); clientArgs.xferSize = xferSize; clientArgs.xferBuf = clientBuf; clientArgs.chunkSize = chunkSize; clientArgs.ringWrite = &clientToServerRing; clientArgs.ringRead = &serverToClientRing; clientArgs.goFlag = &serverArgs.iAmReady; clientArgs.abortFlag = &abortFlag; clientArgs.pauseOnError = pauseOnError; memmove(clientArgs.sharedSecret, serverArgs.sharedSecret, SHARED_SECRET_SIZE); clientArgs.hostName = hostName; /* for now set up an easily recognizable ticket */ for(unsigned dex=0; dex<SESSION_TICKET_SIZE; dex++) { sessionTicket[dex] = dex; } clientArgs.sessionTicket = sessionTicket; clientArgs.sessionTicketLen = SESSION_TICKET_SIZE; /* client always tries setting the master secret in this test */ clientArgs.setMasterSecret = true; clientArgs.trustedRoots = anchorArray; /* fire up client thread */ result = pthread_create(&client_thread, NULL, rbClientThread, &clientArgs); if(result) { printf("***pthread_create returned %d, aborting\n", result); exit(1); } /* * And the server pseudo thread. This returns when all data has been transferred. */ ortn = rbServerThread(&serverArgs); if(abortFlag) { printf("***Test aborted.\n"); exit(1); } printf("\n"); printf("SSL Protocol Version : %s\n", sslGetProtocolVersionString(serverArgs.negotiatedProt)); printf("SSL Cipher : %s\n", sslGetCipherSuiteString(serverArgs.negotiatedCipher)); if(skipPAC) { if(clientArgs.sessionWasResumed) { printf("***skipPAC true, but client reported sessionWasResumed\n"); ourRtn = -1; } if(serverArgs.sessionWasResumed) { printf("***skipPAC true, but server reported sessionWasResumed\n"); ourRtn = -1; } if(ourRtn == 0) { printf("...PAC session attempted by client; refused by server;\n"); printf(" Normal session proceeded correctly.\n"); } } else { if(!clientArgs.sessionWasResumed) { printf("***client reported !sessionWasResumed\n"); ourRtn = -1; } if(!serverArgs.sessionWasResumed) { printf("***server reported !sessionWasResumed\n"); ourRtn = -1; } if(memcmp(clientBuf, serverBuf, DEFAULT_CHUNK)) { printf("***Data miscompare***\n"); ourRtn = -1; } if(ourRtn == 0) { printf("...PAC session resumed correctly.\n"); } } /* FIXME other stuff? */ return ourRtn; }
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; }
int main(int argc, char **argv) { bool verbose = false; int arg; while ((arg = getopt(argc, argv, "vh")) != -1) { switch (arg) { case 'v': verbose = true; break; case 'h': usage(argv); } } if(optind != argc) { usage(argv); } printNoDialog(); /* initial setup */ verboseDisp(verbose, "deleting keychain"); unlink(KEYCHAIN_NAME); verboseDisp(verbose, "creating keychain"); SecKeychainRef kcRef = NULL; OSStatus ortn = SecKeychainCreate(KEYCHAIN_NAME, strlen(KEYCHAIN_PWD), KEYCHAIN_PWD, false, NULL, &kcRef); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } /* * 1. Generate key pair with cleartext public key. * Ensure we can use the public key when keychain is locked with no * user interaction. */ /* generate key pair, cleartext public key */ verboseDisp(verbose, "creating key pair, cleartext public key"); SecKeyRef pubKeyRef = NULL; SecKeyRef privKeyRef = NULL; if(genKeyPair(false, kcRef, &pubKeyRef, &privKeyRef)) { exit(1); } /* Use generated cleartext public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); CFDataRef exportData = NULL; ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } CFRelease(exportData); verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } /* reset */ verboseDisp(verbose, "deleting keys"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } ortn = SecKeychainItemDelete((SecKeychainItemRef)privKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); CFRelease(privKeyRef); /* * 2. Generate key pair with encrypted public key. * Ensure that user interaction is required when we use the public key * when keychain is locked. */ verboseDisp(verbose, "programmatically unlocking keychain"); ortn = SecKeychainUnlock(kcRef, strlen(KEYCHAIN_PWD), KEYCHAIN_PWD, TRUE); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } /* generate key pair, encrypted public key */ verboseDisp(verbose, "creating key pair, encrypted public key"); if(genKeyPair(true, kcRef, &pubKeyRef, &privKeyRef)) { exit(1); } /* Use generated encrypted public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); printExpectDialog(); ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } /* we'll use that exported blob later to test import */ if(!didGetDialog()) { exit(1); } verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); printExpectDialog(); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } if(!didGetDialog()) { exit(1); } /* reset */ printNoDialog(); verboseDisp(verbose, "locking keychain"); SecKeychainLock(kcRef); verboseDisp(verbose, "deleting keys"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } ortn = SecKeychainItemDelete((SecKeychainItemRef)privKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); CFRelease(privKeyRef); /* * 3. Import public key, storing in cleartext. Ensure that the import * doesn't require unlock, and ensure we can use the public key * when keychain is locked with no user interaction. */ printNoDialog(); verboseDisp(verbose, "locking keychain"); SecKeychainLock(kcRef); /* import public key - default is in the clear */ verboseDisp(verbose, "importing public key, store in the clear (default)"); CFArrayRef outArray = NULL; SecExternalFormat format = kSecFormatOpenSSL; SecExternalItemType type = kSecItemTypePublicKey; ortn = SecKeychainItemImport(exportData, NULL, &format, &type, 0, NULL, kcRef, &outArray); if(ortn) { cssmPerror("SecKeychainItemImport", ortn); exit(1); } CFRelease(exportData); if(CFArrayGetCount(outArray) != 1) { printf("***Unexpected outArray size (%ld) after import\n", (long)CFArrayGetCount(outArray)); exit(1); } pubKeyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); if(CFGetTypeID(pubKeyRef) != SecKeyGetTypeID()) { printf("***Unexpected item type after import\n"); exit(1); } /* Use imported cleartext public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); exportData = NULL; ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainItemExport", ortn); exit(1); } /* we'll use exportData again */ verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } /* reset */ verboseDisp(verbose, "deleting key"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); /* * Import public key, storing in encrypted form. * Ensure that user interaction is required when we use the public key * when keychain is locked. */ /* import public key, encrypted in the keychain */ SecKeyImportExportParameters impExpParams; memset(&impExpParams, 0, sizeof(impExpParams)); impExpParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; impExpParams.keyAttributes = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT; verboseDisp(verbose, "importing public key, store encrypted"); printExpectDialog(); outArray = NULL; format = kSecFormatOpenSSL; type = kSecItemTypePublicKey; ortn = SecKeychainItemImport(exportData, NULL, &format, &type, 0, &impExpParams, kcRef, &outArray); if(ortn) { cssmPerror("SecKeychainItemImport", ortn); exit(1); } if(!didGetDialog()) { exit(1); } CFRelease(exportData); if(CFArrayGetCount(outArray) != 1) { printf("***Unexpected outArray size (%ld) after import\n", (long)CFArrayGetCount(outArray)); exit(1); } pubKeyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); if(CFGetTypeID(pubKeyRef) != SecKeyGetTypeID()) { printf("***Unexpected item type after import\n"); exit(1); } /* Use imported encrypted public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); printExpectDialog(); ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainItemExport", ortn); exit(1); } if(!didGetDialog()) { exit(1); } CFRelease(exportData); verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); printExpectDialog(); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } if(!didGetDialog()) { exit(1); } SecKeychainDelete(kcRef); printf("...test succeeded.\n"); return 0; }
/* * Log CSSM error. */ void cuPrintError(const char *op, CSSM_RETURN err) { cssmPerror(op, err); }
/* * Display a Trust Settings array as obtained from * SecTrustSettingsCopyTrustSettings(). */ static int displayTrustSettings( CFArrayRef trustSettings) { /* must always be there though it may be empty */ if(trustSettings == NULL) { fprintf(stderr, "***displayTrustSettings: missing trust settings array"); return -1; } if(CFGetTypeID(trustSettings) != CFArrayGetTypeID()) { fprintf(stderr, "***displayTrustSettings: malformed trust settings array"); return -1; } int ourRtn = 0; CFIndex numUseConstraints = CFArrayGetCount(trustSettings); indentIncr(); indent(); printf("Number of trust settings : %ld\n", (long)numUseConstraints); OSStatus ortn; SecPolicyRef certPolicy; SecTrustedApplicationRef certApp; CFDictionaryRef ucDict; CFStringRef policyStr; CFNumberRef cfNum; CFIndex ucDex; /* grind thru the trust settings dictionaries */ for(ucDex=0; ucDex<numUseConstraints; ucDex++) { indent(); printf("Trust Setting %ld:\n", (long)ucDex); indentIncr(); ucDict = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, ucDex); if(CFGetTypeID(ucDict) != CFDictionaryGetTypeID()) { fprintf(stderr, "***displayTrustSettings: malformed usage constraints dictionary"); ourRtn = -1; goto nextAp; } /* policy - optional */ certPolicy = (SecPolicyRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsPolicy); if(certPolicy != NULL) { if(CFGetTypeID(certPolicy) != SecPolicyGetTypeID()) { fprintf(stderr, "***displayTrustSettings: malformed certPolicy"); ourRtn = -1; goto nextAp; } CSSM_OID policyOid; ortn = SecPolicyGetOID(certPolicy, &policyOid); if(ortn) { cssmPerror("SecPolicyGetOID", ortn); ourRtn = -1; goto nextAp; } indent(); printf("Policy OID : %s\n", oidToOidString(&policyOid)); } /* app - optional */ certApp = (SecTrustedApplicationRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsApplication); if(certApp != NULL) { if(CFGetTypeID(certApp) != SecTrustedApplicationGetTypeID()) { fprintf(stderr, "***displayTrustSettings: malformed certApp"); ourRtn = -1; goto nextAp; } CFDataRef appPath = NULL; ortn = SecTrustedApplicationCopyData(certApp, &appPath); if(ortn) { cssmPerror("SecTrustedApplicationCopyData", ortn); ourRtn = -1; goto nextAp; } indent(); printf("Application : %s", CFDataGetBytePtr(appPath)); printf("\n"); CFRelease(appPath); } /* policy string */ policyStr = (CFStringRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsPolicyString); if(policyStr != NULL) { if(CFGetTypeID(policyStr) != CFStringGetTypeID()) { fprintf(stderr, "***displayTrustSettings: malformed policyStr"); ourRtn = -1; goto nextAp; } indent(); printf("Policy String : "); printCfStr(policyStr); printf("\n"); } /* Allowed error */ cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsAllowedError); if(cfNum != NULL) { if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) { fprintf(stderr, "***displayTrustSettings: malformed allowedError"); ourRtn = -1; goto nextAp; } indent(); printf("Allowed Error : "); printCssmErr(cfNum); printf("\n"); } /* ResultType */ cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsResult); if(cfNum != NULL) { if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) { fprintf(stderr, "***displayTrustSettings: malformed ResultType"); ourRtn = -1; goto nextAp; } indent(); printf("Result Type : "); printResultType(cfNum); printf("\n"); } /* key usage */ cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsKeyUsage); if(cfNum != NULL) { if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) { fprintf(stderr, "***displayTrustSettings: malformed keyUsage"); ourRtn = -1; goto nextAp; } indent(); printf("Key Usage : "); printKeyUsage(cfNum); printf("\n"); } nextAp: indentDecr(); } indentDecr(); return ourRtn; }