OSStatus sslReadAnchor( const char *anchorFile, SecCertificateRef *certRef) { OSStatus ortn; SecCertificateRef secCert; unsigned char *certData; unsigned certLen; CSSM_DATA cert; if(readFile(anchorFile, &certData, &certLen)) { return -1; } cert.Data = certData; cert.Length = certLen; ortn = SecCertificateCreateFromData(&cert, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &secCert); free(certData); if(ortn) { printf("***SecCertificateCreateFromData returned %d\n", (int)ortn); return ortn; } *certRef = secCert; return errSecSuccess; }
// Find a certificate in the database by a DER encoded certificate // "derCert" is the DER encoded certificate SecCertificateRef CERT_FindCertByDERCert(SecKeychainRef keychainOrArray, const SECItem *derCert) { // @@@ Technically this should look though keychainOrArray for a cert matching this one I guess. SecCertificateRef cert = NULL; OSStatus rv; rv = SecCertificateCreateFromData(derCert, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cert); if (rv && cert) { PORT_SetError(SEC_ERROR_NO_EMAIL_CERT); CFRelease(cert); cert = NULL; } return cert; }
// Generate a certificate key from the issuer and serialnumber, then look it up in the database. // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, CSSM_DATA_PTR *rawCerts, PRArenaPool *pl, const SecCmsIssuerAndSN *issuerAndSN) { SecCertificateRef certificate; int numRawCerts = SecCmsArrayCount((void **)rawCerts); int dex; OSStatus ortn; /* * First search the rawCerts array. */ for(dex=0; dex<numRawCerts; dex++) { ortn = SecCertificateCreateFromData(rawCerts[dex], CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certificate); if(ortn) { continue; } SecCmsIssuerAndSN *isn = CERT_GetCertIssuerAndSN(pl, certificate); if(isn == NULL) { CFRelease(certificate); continue; } if(!compareCssmData(&isn->derIssuer, &issuerAndSN->derIssuer)) { CFRelease(certificate); continue; } if(!compareCssmData(&isn->serialNumber, &issuerAndSN->serialNumber)) { CFRelease(certificate); continue; } /* got it */ dprintf("CERT_FindCertByIssuerAndSN: found cert %p\n", certificate); return certificate; } /* now search keychain(s) */ OSStatus status = SecCertificateFindByIssuerAndSN(keychainOrArray, &issuerAndSN->derIssuer, &issuerAndSN->serialNumber, &certificate); if (status) { PORT_SetError(SEC_ERROR_NO_EMAIL_CERT); certificate = NULL; } return certificate; }
/* * Cook up a SecCertificateRef from a krb5_data. */ static OSStatus pkiKrb5DataToSecCert( const krb5_data *rawCert, SecCertificateRef *secCert) /* RETURNED */ { CSSM_DATA certData; OSStatus ortn; assert((rawCert != NULL) && (secCert != NULL)); certData.Data = (uint8 *)rawCert->data; certData.Length = rawCert->length; ortn = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, secCert); if(ortn) { pkiCssmErr("SecCertificateCreateFromData", ortn); } return ortn; }
SecCertificateRef CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray, CSSM_DATA_PTR *rawCerts, const SECItem *subjKeyID) { SecCertificateRef certificate; int numRawCerts = SecCmsArrayCount((void **)rawCerts); int dex; OSStatus ortn; SECItem skid; /* * First search the rawCerts array. */ for(dex=0; dex<numRawCerts; dex++) { int match; ortn = SecCertificateCreateFromData(rawCerts[dex], CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certificate); if(ortn) { continue; } if(CERT_FindSubjectKeyIDExtension(certificate, &skid)) { CFRelease(certificate); /* not present */ continue; } match = compareCssmData(subjKeyID, &skid); SECITEM_FreeItem(&skid, PR_FALSE); if(match) { /* got it */ return certificate; } CFRelease(certificate); } /* now search keychain(s) */ OSStatus status = SecCertificateFindBySubjectKeyID(keychainOrArray,subjKeyID,&certificate); if (status) { PORT_SetError(SEC_ERROR_NO_EMAIL_CERT); certificate = NULL; } return certificate; }
/* * Add a certificate to an open Keychain. */ CSSM_RETURN cuAddCertToKC( SecKeychainRef keychain, const CSSM_DATA *cert, CSSM_CERT_TYPE certType, CSSM_CERT_ENCODING certEncoding, const char *printName, // C string const CSSM_DATA *keyLabel) // ?? { SecCertificateRef certificate; OSStatus rslt = SecCertificateCreateFromData(cert, certType, certEncoding, &certificate); if (!rslt) { rslt = SecCertificateAddToKeychain(certificate, keychain); CFRelease(certificate); } return rslt; }
/* * Obtain an array of all of the certificates in a message. Elements of the * returned array are SecCertificateRefs. The caller must CFRelease the returned * array. * This cannot be called until after CMSDecoderFinalizeMessage() is called. */ OSStatus CMSDecoderCopyAllCerts( CMSDecoderRef cmsDecoder, CFArrayRef *certs) /* RETURNED */ { if((cmsDecoder == NULL) || (certs == NULL)) { return errSecParam; } if(cmsDecoder->decState != DS_Final) { return errSecParam; } if(cmsDecoder->signedData == NULL) { /* message wasn't signed */ *certs = NULL; return errSecSuccess; } /* NULL_terminated array of CSSM_DATA ptrs */ CSSM_DATA_PTR *cssmCerts = SecCmsSignedDataGetCertificateList(cmsDecoder->signedData); if((cssmCerts == NULL) || (*cssmCerts == NULL)) { *certs = NULL; return errSecSuccess; } CFMutableArrayRef allCerts = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CSSM_DATA_PTR *cssmCert; for(cssmCert=cssmCerts; *cssmCert!=NULL; cssmCert++) { OSStatus ortn; SecCertificateRef cfCert; ortn = SecCertificateCreateFromData(*cssmCert, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cfCert); if(ortn) { CFRelease(allCerts); return ortn; } CFArrayAppendValue(allCerts, cfCert); /* the array holds the only needed refcount */ CFRelease(cfCert); } *certs = allCerts; return errSecSuccess; }
// import a collection of certs into the temporary or permanent cert database SECStatus CERT_ImportCerts(SecKeychainRef keychain, SECCertUsage usage, unsigned int ncerts, SECItem **derCerts, SecCertificateRef **retCerts, Boolean keepCerts, Boolean caOnly, char *nickname) { OSStatus rv = SECFailure; SecCertificateRef cert; unsigned int ci; // @@@ Do something with caOnly and nickname if (caOnly || nickname) abort(); for (ci = 0; ci < ncerts; ++ci) { rv = SecCertificateCreateFromData(derCerts[ci], CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cert); if (rv) break; if (keepCerts) { rv = SecCertificateAddToKeychain(cert, keychain); if (rv) { if (rv == errKCDuplicateItem) rv = noErr; else { CFRelease(cert); break; } } } if (retCerts) { // @@@ not yet abort(); } else CFRelease(cert); } return rv; }
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; }
int main(int argc, char **argv) { OSStatus err; int arg; char fullFileBase[100]; SSLProtocol negVersion; SSLCipherSuite negCipher; Boolean sessionWasResumed; unsigned char sessionID[MAX_SESSION_ID_LENGTH]; size_t sessionIDLength; CFArrayRef peerCerts = NULL; char *argp; otSocket listenSock; CFArrayRef serverCerts = nil; // required CFArrayRef encryptCerts = nil; // optional SecKeychainRef serverKc = nil; SecKeychainRef encryptKc = nil; int loopNum; int errCount = 0; SSLClientCertificateState certState; // obtained from sslServe /* user-spec'd parameters */ unsigned short portNum = DEFAULT_PORT; bool allowExpired = false; bool allowAnyRoot = false; char *fileBase = NULL; bool displayCerts = false; char cipherRestrict = '\0'; SSLProtocol attemptProt = kTLSProtocol1; bool protXOnly = false; // kSSLProtocol3Only, // kTLSProtocol1Only char *acceptedProts = NULL; // "23t" ==> SSLSetProtocolVersionEnabled bool quiet = false; bool resumableEnable = true; bool pause = false; char *keyChainName = NULL; char *encryptKeyChainName = NULL; int loops = 1; SSLAuthenticate authenticate = kNeverAuthenticate; bool nonBlocking = false; bool allowExpiredRoot = false; bool disableCertVerify = false; char *anchorFile = NULL; bool replaceAnchors = false; bool vfyCertState = false; SSLClientCertificateState expectCertState = kSSLClientCertNone; char *password = NULL; char *dhParamsFile = NULL; unsigned char *dhParams = NULL; unsigned dhParamsLen = 0; bool doIdSearch = false; bool completeCertChain = false; uint32_t sessionCacheTimeout = 0; bool disableAnonCiphers = false; CFMutableArrayRef acceptableDNList = NULL; for(arg=1; arg<argc; arg++) { argp = argv[arg]; switch(argp[0]) { case 'P': portNum = atoi(&argp[2]); break; case 'k': keyChainName = &argp[2]; break; case 'y': encryptKeyChainName = &argp[2]; break; case 'e': allowExpired = true; break; case 'E': allowExpiredRoot = true; break; case 'x': disableCertVerify = true; break; case 'a': if(++arg == argc) { /* requires another arg */ usage(argv); } anchorFile = argv[arg]; break; case 'A': if(++arg == argc) { /* requires another arg */ usage(argv); } anchorFile = argv[arg]; replaceAnchors = true; break; case 'T': if(argp[1] != '=') { usage(argv); } vfyCertState = true; switch(argp[2]) { case 'n': expectCertState = kSSLClientCertNone; break; case 'r': expectCertState = kSSLClientCertRequested; break; case 's': expectCertState = kSSLClientCertSent; break; case 'j': expectCertState = kSSLClientCertRejected; break; default: usage(argv); } break; case 'r': allowAnyRoot = true; break; case 'd': break; case 'c': displayCerts = true; break; case 'f': fileBase = &argp[2]; break; case 'C': cipherRestrict = argp[2]; break; case '2': attemptProt = kSSLProtocol2; break; case '3': attemptProt = kSSLProtocol3; break; case 't': attemptProt = kTLSProtocol1; break; case 'o': protXOnly = true; break; case 'g': if(argp[1] != '=') { usage(argv); } acceptedProts = &argp[2]; break; case 'R': resumableEnable = false; break; case 'b': nonBlocking = true; break; case 'u': if(argp[1] != '=') { usage(argv); } switch(argp[2]) { case 'a': authenticate = kAlwaysAuthenticate; break; case 'n': authenticate = kNeverAuthenticate; break; case 't': authenticate = kTryAuthenticate; break; default: usage(argv); } break; case 'D': if(++arg == argc) { /* requires another arg */ usage(argv); } dhParamsFile = argv[arg]; break; case 'z': password = &argp[2]; break; case 'H': doIdSearch = true; break; case 'M': completeCertChain = true; break; case 'i': sessionCacheTimeout = atoi(&argp[2]); break; case '4': disableAnonCiphers = true; break; case 'p': pause = true; break; case 'q': quiet = true; break; #if 0 case 'U': if(++arg == argc) { /* requires another arg */ usage(argv); } if(cspReadFile(argv[arg], &caCert, &caCertLen)) { printf("***Error reading file %s. Aborting.\n", argv[arg]); exit(1); } if(acceptableDNList == NULL) { acceptableDNList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); } certData.Data = caCert; certData.Length = caCertLen; ortn = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &secCert); if(ortn) { cssmPerror("SecCertificateCreateFromData", ortn); exit(1); } CFArrayAppendValue(acceptableDNList, secCert); CFRelease(secCert); break; #endif case 'l': if(argp[1] == '\0') { /* no loop count --> loop forever */ loops = 0; break; } else if(argp[1] != '=') { usage(argv); } loops = atoi(&argp[2]); break; default: usage(argv); } } #if NO_SERVER # if DEBUG securityd_init(NULL); # endif #endif /* get server cert and optional encryption cert as CFArrayRef */ if(keyChainName) { serverCerts = getSslCerts(keyChainName, false, completeCertChain, anchorFile, &serverKc); if(serverCerts == nil) { exit(1); } } else #if 0 if(doIdSearch) { OSStatus ortn = sslIdentityPicker(NULL, anchorFile, true, NULL, &serverCerts); if(ortn) { printf("***IdentitySearch failure; aborting.\n"); exit(1); } } if(password) { OSStatus ortn = SecKeychainUnlock(serverKc, strlen(password), password, true); if(ortn) { printf("SecKeychainUnlock returned %d\n", (int)ortn); /* oh well */ } } if(encryptKeyChainName) { encryptCerts = getSslCerts(encryptKeyChainName, true, completeCertChain, anchorFile, &encryptKc); if(encryptCerts == nil) { exit(1); } } #else (void) doIdSearch; (void) encryptKeyChainName; #endif if(protXOnly) { switch(attemptProt) { case kTLSProtocol1: attemptProt = kTLSProtocol1Only; break; case kSSLProtocol3: attemptProt = kSSLProtocol3Only; break; default: break; } } #if 0 if(dhParamsFile) { int r = cspReadFile(dhParamsFile, &dhParams, &dhParamsLen); if(r) { printf("***Error reading diffie-hellman params from %s; aborting\n", dhParamsFile); } } #else (void) dhParamsFile; #endif /* one-time only server port setup */ err = ListenForClients(portNum, nonBlocking, &listenSock); if(err) { printf("ListenForClients returned %d; aborting\n", (int)err); exit(1); } for(loopNum=1; ; loopNum++) { err = sslServe(listenSock, portNum, attemptProt, acceptedProts, serverCerts, password, encryptCerts, allowExpired, allowAnyRoot, allowExpiredRoot, disableCertVerify, anchorFile, replaceAnchors, cipherRestrict, authenticate, dhParams, dhParamsLen, acceptableDNList, resumableEnable, sessionCacheTimeout, disableAnonCiphers, quiet, pause, &negVersion, &negCipher, &certState, &sessionWasResumed, sessionID, &sessionIDLength, &peerCerts, argv); if(err) { errCount++; } if(!quiet) { SSLProtocol tryProt = attemptProt; showSSLResult(tryProt, acceptedProts, err, negVersion, negCipher, sessionWasResumed, sessionID, sessionIDLength, peerCerts, displayCerts, certState, fileBase ? fullFileBase : NULL); } errCount += verifyClientCertState(vfyCertState, expectCertState, certState); freePeerCerts(peerCerts); if(loops && (loopNum == loops)) { break; } }; endpointShutdown(listenSock); if(serverKc) { CFRelease(serverKc); } if(encryptKc) { CFRelease(encryptKc); } return errCount; }
/* ** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE ** verify a certificate by checking validity times against a certain time, ** that we trust the issuer, and that the signature on the certificate is ** valid. ** "cert" the certificate to verify ** "checkSig" only check signatures if true */ SECStatus CERT_VerifyCert(SecKeychainRef keychainOrArray, SecCertificateRef cert, const CSSM_DATA_PTR *otherCerts, /* intermediates */ CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef) { CFMutableArrayRef certificates = NULL; SecTrustRef trust = NULL; OSStatus rv; int numOtherCerts = SecCmsArrayCount((void **)otherCerts); int dex; /* * Certs to evaluate: first the leaf - our cert - then all the rest we know * about. It's OK for otherCerts to contain a copy of the leaf. */ certificates = CFArrayCreateMutable(NULL, numOtherCerts + 1, &kCFTypeArrayCallBacks); CFArrayAppendValue(certificates, cert); for(dex=0; dex<numOtherCerts; dex++) { SecCertificateRef intCert; rv = SecCertificateCreateFromData(otherCerts[dex], CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &intCert); if(rv) { goto loser; } CFArrayAppendValue(certificates, intCert); CFRelease(intCert); } rv = SecTrustCreateWithCertificates(certificates, policies, &trust); CFRelease(certificates); certificates = NULL; if (rv) goto loser; rv = SecTrustSetKeychains(trust, keychainOrArray); if (rv) goto loser; CFDateRef verifyDate = CFDateCreate(NULL, stime); rv = SecTrustSetVerifyDate(trust, verifyDate); CFRelease(verifyDate); if (rv) goto loser; if (trustRef) { *trustRef = trust; } else { SecTrustResultType result; /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */ rv = SecTrustEvaluate(trust, &result); if (rv) goto loser; switch (result) { case kSecTrustResultProceed: case kSecTrustResultUnspecified: /* TP Verification succeeded and there was either a UserTurst entry telling us to procceed, or no user trust setting was specified. */ CFRelease(trust); break; default: PORT_SetError(SEC_ERROR_UNTRUSTED_CERT); rv = SECFailure; goto loser; break; } } return SECSuccess; loser: if (trust) CFRelease(trust); if(certificates) CFRelease(certificates); return rv; }
OSStatus createPair(CFStringRef hostName,CFStringRef userName,SecKeychainRef keychainRef, uint32 keySizeInBits, CFDataRef *cert) { SecCertificateRef certRef = NULL; CSSM_DL_DB_HANDLE dlDbHand = {0, 0}; CSSM_CSP_HANDLE cspHand = 0; CSSM_TP_HANDLE tpHand = 0; CSSM_CL_HANDLE clHand = 0; CSSM_KEY_PTR pubKey = NULL; CSSM_KEY_PTR privKey = NULL; CSSM_DATA certData = {0, NULL}; char *hostStr = NULL; char *userStr = NULL; OSStatus ortn; CSSM_OID algOid = SR_CERT_SIGNATURE_ALG_OID; hostStr = secCopyCString(hostName); userStr = secCopyCString(userName); if (!hostStr || !userStr) // could not convert to UTF-8 { ortn = paramErr; goto xit; } // open keychain, connect to all the CDSA modules we'll need ortn = SecKeychainGetCSPHandle(keychainRef, &cspHand); if (ortn) goto xit; ortn = SecKeychainGetDLDBHandle(keychainRef, &dlDbHand); if (ortn) goto xit; tpHand = srTpStartup(); if (tpHand == 0) { ortn = ioErr; goto xit; } clHand = srClStartup(); if (clHand == 0) { ortn = ioErr; goto xit; } // generate key pair, private key stored in keychain ortn = generateKeyPair(cspHand, dlDbHand, SR_KEY_ALGORITHM, keySizeInBits, "FileVault Master Password Key", &pubKey, &privKey); if (ortn) goto xit; // generate the cert ortn = createRootCert(tpHand,clHand,cspHand,pubKey,privKey,hostStr,userStr, SR_CERT_SIGNATURE_ALGORITHM,&algOid,&certData); if (ortn) goto xit; // store the cert in the same DL/DB as the key pair [see SecCertificateCreateFromData] ortn = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certRef); if (ortn) goto xit; ortn = SecCertificateAddToKeychain(certRef, keychainRef); if (ortn) goto xit; // return the cert to caller *cert = CFDataCreate(NULL, certData.Data, certData.Length); // cleanup xit: if (certRef) CFRelease(certRef); if (certData.Data) free(certData.Data); if (hostStr) free(hostStr); if (userStr) free(userStr); if (tpHand) CSSM_ModuleDetach(tpHand); if (clHand) CSSM_ModuleDetach(clHand); if (pubKey) { CSSM_FreeKey(cspHand, NULL, // access cred pubKey, CSSM_FALSE); // delete APP_FREE(pubKey); } if (privKey) { CSSM_FreeKey(cspHand, NULL, // access cred privKey, CSSM_FALSE); // delete APP_FREE(privKey); } return ortn; }
int main(int argc, char **argv) { if(argc < 2) { usage(argv); } bool print_cert = false; bool allCerts = false; const char *emailAddress = NULL; bool addToKC = false; extern int optind; optind = 1; if(argv[1][0] != '-') { /* normal case, email address specified */ emailAddress = argv[1]; optind++; } extern char *optarg; int arg; while ((arg = getopt(argc, argv, "aphA")) != -1) { switch (arg) { case 'p': print_cert = true; break; case 'a': allCerts = true; break; case 'A': addToKC = true; break; case 'h': default: usage(argv); } } if(optind != argc) { usage(argv); } if(!allCerts && (emailAddress == NULL)) { printf("***You must specify either an email address or the -a option.\n"); exit(1); } OSStatus ortn; SecKeychainSearchRef srch; SecKeychainAttributeList attrList; SecKeychainAttribute attr; unsigned numCerts = 0; if(emailAddress) { attr.tag = kSecAlias; // i.e., email address attr.length = strlen(emailAddress); attr.data = (void *)emailAddress; attrList.count = 1; attrList.attr = &attr; } else { attrList.count = 0; attrList.attr = NULL; } ortn = SecKeychainSearchCreateFromAttributes(NULL, // default search list kSecCertificateItemClass, &attrList, &srch); if(ortn) { cssmPerror("SecKeychainSearchCreateFromAttributes", ortn); exit(1); } do { SecCertificateRef certRef = NULL; CSSM_DATA certData; ortn = SecKeychainSearchCopyNext(srch, (SecKeychainItemRef *)&certRef); if(ortn) { break; } ortn = SecCertificateGetData(certRef, &certData); if(ortn) { cssmPerror("SecCertificateGetData", ortn); continue; } printf("=== Cert %u ===\n", numCerts); printCertName(certData.Data, certData.Length, NameBoth); if(print_cert) { printCert(certData.Data, certData.Length, CSSM_FALSE); } if(addToKC) { /* * Can't call SecCertificateAddToKeychain directly since this * cert already has a keychain. */ SecCertificateRef newCertRef = NULL; ortn = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &newCertRef); if(ortn) { cssmPerror("SecCertificateCreateFromData", ortn); printf("***Error adding this cert to default keychain.\n"); } else { ortn = SecCertificateAddToKeychain(newCertRef, NULL); if(ortn) { cssmPerror("SecCertificateAddToKeychain", ortn); printf("***Error adding this cert to default keychain.\n"); } else { printf("...cert added to default keychain.\n"); } CFRelease(newCertRef); } } CFRelease(certRef); numCerts++; } while(ortn == noErr); printf("...%u certs found matching email address \'%s\'\n", numCerts, emailAddress ? emailAddress : "<any>"); CFRelease(srch); return 0; }
/* * Core test routine. * -- build a cert with issuer and subject as per specified name components * -- extract inferred label * -- compare inferred label to expected value * -- if labelIsCommonName true, verify that SecCertificateCopyCommonName() yields * the same string as inferred label */ static int doTest( const char *testName, bool quiet, CSSM_CSP_HANDLE cspHand, CSSM_CL_HANDLE clHand, CSSM_KEY_PTR privKey, CSSM_KEY_PTR pubKey, /* input names - one or two */ const void *name1Val, CSSM_SIZE name1Len, CSSM_BER_TAG berTag1, const CSSM_OID *name1Oid, const void *name2Val, // optional CSSM_SIZE name2Len, CSSM_BER_TAG berTag2, const CSSM_OID *name2Oid, /* expected label */ CFStringRef expectedLabel, bool labelIsCommonName) { if(!quiet) { printf("...%s\n", testName); } /* build the subject/issuer name */ NameOid nameArray[2] = { {name1Val, name1Len, name1Oid, berTag1 }, {name2Val, name2Len, name2Oid, berTag2 } }; unsigned numNames = name2Val ? 2 : 1; CSSM_X509_NAME *name = buildX509Name(nameArray, numNames); if(name == NULL) { printf("***buildX509Name screwup\n"); return -1; } /* build the cert template */ CSSM_DATA_PTR certTemp = CB_MakeCertTemplate( clHand, 0x123456, name, name, notBefore, notAfter, pubKey, SIG_ALG, NULL, NULL, // subject/issuer UniqueID NULL, 0); // extensions if(certTemp == NULL) { printf("***CB_MakeCertTemplate screwup\n"); return -1; } /* sign the cert */ CSSM_DATA signedCert = {0, NULL}; CSSM_CC_HANDLE sigHand; CSSM_RETURN crtn = CSSM_CSP_CreateSignatureContext(cspHand, SIG_ALG, NULL, // no passphrase for now privKey, &sigHand); if(crtn) { /* should never happen */ cssmPerror("CSSM_CSP_CreateSignatureContext", crtn); return 1; } crtn = CSSM_CL_CertSign(clHand, sigHand, certTemp, // CertToBeSigned NULL, // SignScope per spec 0, // ScopeSize per spec &signedCert); if(crtn) { cssmPerror("CSSM_CL_CertSign", crtn); return 1; } CSSM_DeleteContext(sigHand); CSSM_FREE(certTemp->Data); CSSM_FREE(certTemp); /* * OK, we have a signed cert. * Turn it into a SecCertificateRef and get the inferred label. */ OSStatus ortn; SecCertificateRef certRef; ortn = SecCertificateCreateFromData(&signedCert, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &certRef); if(ortn) { cssmPerror("SecCertificateCreateFromData", ortn); return -1; } CFStringRef inferredLabel; ortn = SecCertificateInferLabel(certRef, &inferredLabel); if(ortn) { cssmPerror("SecCertificateCreateFromData", ortn); return -1; } CFComparisonResult res = CFStringCompare(inferredLabel, expectedLabel, 0); if(res != kCFCompareEqualTo) { fprintf(stderr, "*** label miscompare in test '%s' ***\n", testName); fprintf(stderr, "expected label : "); CFShow(expectedLabel); fprintf(stderr, "inferred label : "); CFShow(inferredLabel); if(writeFile(CERT_FILE_OUT, signedCert.Data, signedCert.Length)) { fprintf(stderr, "***Error writing cert to %s\n", CERT_FILE_OUT); } else { fprintf(stderr, "...write %lu bytes to %s\n", (unsigned long)signedCert.Length, CERT_FILE_OUT); } return -1; } if(labelIsCommonName) { CFStringRef commonName = NULL; ortn = SecCertificateCopyCommonName(certRef, &commonName); if(ortn) { cssmPerror("SecCertificateCopyCommonName", ortn); return -1; } res = CFStringCompare(inferredLabel, commonName, 0); if(res != kCFCompareEqualTo) { printf("*** CommonName miscompare in test '%s' ***\n", testName); printf("Common Name : '"); CFShow(commonName); printf("'\n"); printf("inferred label : '"); CFShow(inferredLabel); printf("'\n"); if(writeFile(CERT_FILE_OUT, signedCert.Data, signedCert.Length)) { printf("***Error writing cert to %s\n", CERT_FILE_OUT); } else { printf("...write %lu bytes to %s\n", (unsigned long)signedCert.Length, CERT_FILE_OUT); } return -1; } CFRelease(commonName); } CFRelease(certRef); CSSM_FREE(signedCert.Data); CB_FreeX509Name(name); CFRelease(inferredLabel); return 0; }