X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_smime/lib/cert.c?ds=inline diff --git a/Security/libsecurity_smime/lib/cert.c b/Security/libsecurity_smime/lib/cert.c deleted file mode 100644 index adf30c15..00000000 --- a/Security/libsecurity_smime/lib/cert.c +++ /dev/null @@ -1,828 +0,0 @@ -/* - * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include "cert.h" -#include "cmstpriv.h" -#include "cmslocal.h" -#include "secitem.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* for errKCDuplicateItem */ -#include - -#define CERT_DEBUG 0 -#if CERT_DEBUG -#define dprintf(args...) printf(args) -#else -#define dprintf(args...) -#endif - -/* @@@ Remove this once it's back in the appropriate header. */ -static const uint8 X509V1IssuerNameStd[] = {INTEL_X509V3_CERT_R08, 23}; -static const CSSM_OID OID_X509V1IssuerNameStd = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1IssuerNameStd}; - -/* - * Normalize a Printable String. Per RFC2459 (4.1.2.4), printable strings are case - * insensitive and we're supposed to ignore leading and trailing - * whitespace, and collapse multiple whitespace characters into one. - */ -static void -CERT_NormalizeString(CSSM_DATA_PTR string) -{ - char *pD, *pCh, *pEos; - - if (!string->Length) - return; - - pD = pCh = (char *)string->Data; - pEos = pCh + string->Length - 1; - - /* Strip trailing NULL terminators */ - while(*pEos == 0) - pEos--; - - /* Remove trailing spaces */ - while(isspace(*pEos)) - pEos--; - - /* Point to one past last non-space character */ - pEos++; - - /* skip all leading whitespace */ - while(isspace(*pCh) && (pCh < pEos)) - pCh++; - - /* Eliminate multiple whitespace and convent to upper case. - * pCh points to first non-white char. - * pD still points to start of string. */ - while(pCh < pEos) - { - char ch = *pCh++; - *pD++ = toupper(ch); - if(isspace(ch)) - { - /* skip 'til next nonwhite */ - while(isspace(*pCh) && (pCh < pEos)) - pCh++; - } - } - - string->Length = pD - (char *)string->Data; -} - -/* - * Normalize an RDN. Per RFC2459 (4.1.2.4), printable strings are case - * insensitive and we're supposed to ignore leading and trailing - * whitespace, and collapse multiple whitespace characters into one. - * - * Incoming NSS_Name is assumed to be entirely within specifed coder's - * address space; we'll be munging some of that and possibly replacing - * some pointers with others allocated from the same space. - */ -void -CERT_NormalizeX509NameNSS(NSS_Name *nssName) -{ - NSS_RDN *rdn; - - for (rdn = *nssName->rdns; rdn; ++rdn) - { - NSS_ATV *attr; - for (attr = *rdn->atvs; attr; ++attr) - { - /* - * attr->value is an ASN_ANY containing an encoded - * string. We only normalize Prinatable String types. - * If we find one, decode it, normalize it, encode the - * result, and put the encoding back in attr->value. - * We temporarily "leak" the original string, which only - * has a lifetime of the incoming SecNssCoder. - */ - NSS_TaggedItem *attrVal = &attr->value; - if(attrVal->tag != SEC_ASN1_PRINTABLE_STRING) - continue; - - CERT_NormalizeString(&attrVal->item); - } - } -} - -SecCertificateRef CERT_FindCertByNicknameOrEmailAddr(SecKeychainRef keychainOrArray, char *name) -{ - SecCertificateRef certificate; - OSStatus status=SecCertificateFindByEmail(keychainOrArray,name,&certificate); - return status==noErr?certificate:NULL; -} - -SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey) -{ - CFRetain(pubKey); - return pubKey; -} - -void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey) -{ - CFRelease(pubKey); -} - -SecPublicKeyRef SECKEY_CopyPrivateKey(SecPublicKeyRef privKey) -{ - CFRetain(privKey); - return privKey; -} - -void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey) -{ - CFRelease(privKey); -} - -void CERT_DestroyCertificate(SecCertificateRef cert) -{ - CFRelease(cert); -} - -SecCertificateRef CERT_DupCertificate(SecCertificateRef cert) -{ - CFRetain(cert); - return cert; -} - -SecIdentityRef CERT_FindIdentityByUsage(SecKeychainRef keychainOrArray, - char *nickname, SECCertUsage usage, Boolean validOnly, void *proto_win) -{ - SecIdentityRef identityRef = NULL; - SecCertificateRef cert = CERT_FindCertByNicknameOrEmailAddr(keychainOrArray, nickname); - if (!cert) - return NULL; - - SecIdentityCreateWithCertificate(keychainOrArray, cert, &identityRef); - CFRelease(cert); - - return identityRef; -} - -SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray, - char *nickname,SECCertUsage usage,Boolean validOnly,void *proto_win) -{ - SecItemClass itemClass = kSecCertificateItemClass; - SecKeychainSearchRef searchRef; - SecKeychainItemRef itemRef = NULL; - OSStatus status; - SecKeychainAttribute attrs[1]; - const char *serialNumber = "12345678"; - // const SecKeychainAttributeList attrList; -#if 0 - attrs[1].tag = kSecLabelItemAttr; - attrs[1].length = strlen(nickname)+1; - attrs[1].data = nickname; -#else - attrs[1].tag = kSecSerialNumberItemAttr; - attrs[1].length = (UInt32)strlen(serialNumber)+1; - attrs[1].data = (uint8 *)serialNumber; -#endif - SecKeychainAttributeList attrList = { 0, attrs }; - // 12 34 56 78 - status = SecKeychainSearchCreateFromAttributes(keychainOrArray,itemClass,&attrList,&searchRef); - if (status) - { - printf("CERT_FindUserCertByUsage: SecKeychainSearchCreateFromAttributes:%d",(int)status); - return NULL; - } - status = SecKeychainSearchCopyNext(searchRef,&itemRef); - if (status) - printf("CERT_FindUserCertByUsage: SecKeychainSearchCopyNext:%d",(int)status); - CFRelease(searchRef); - return (SecCertificateRef)itemRef; -} - -/* -startNewClass(X509Certificate) -CertType, kSecCertTypeItemAttr, "CertType", 0, NULL, UINT32) -CertEncoding, kSecCertEncodingItemAttr, "CertEncoding", 0, NULL, UINT32) -PrintName, kSecLabelItemAttr, "PrintName", 0, NULL, BLOB) -Alias, kSecAlias, "Alias", 0, NULL, BLOB) -Subject, kSecSubjectItemAttr, "Subject", 0, NULL, BLOB) -Issuer, kSecIssuerItemAttr, "Issuer", 0, NULL, BLOB) -SerialNumber, kSecSerialNumberItemAttr, "SerialNumber", 0, NULL, BLOB) -SubjectKeyIdentifier, kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", 0, NULL, BLOB) -PublicKeyHash, kSecPublicKeyHashItemAttr, "PublicKeyHash", 0, NULL, BLOB) -endNewClass() -*/ - -CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Boolean includeRoot) -{ - SecPolicySearchRef searchRef = NULL; - SecPolicyRef policy = NULL; - CFArrayRef wrappedCert = NULL; - SecTrustRef trust = NULL; - CFArrayRef certChain = NULL; - CSSM_TP_APPLE_EVIDENCE_INFO *statusChain; - CFDataRef actionData = NULL; - OSStatus status = 0; - - if (!cert) - goto loser; - - status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &searchRef); - if (status) - goto loser; - status = SecPolicySearchCopyNext(searchRef, &policy); - if (status) - goto loser; - - wrappedCert = CERT_CertListFromCert(cert); - status = SecTrustCreateWithCertificates(wrappedCert, policy, &trust); - if (status) - goto loser; - - /* Tell SecTrust that we don't care if any certs in the chain have expired, - nor do we want to stop when encountering a cert with a trust setting; - we always want to build the full chain. - */ - CSSM_APPLE_TP_ACTION_DATA localActionData = { - CSSM_APPLE_TP_ACTION_VERSION, - CSSM_TP_ACTION_ALLOW_EXPIRED | CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT - }; - actionData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)&localActionData, sizeof(localActionData), kCFAllocatorNull); - if (!actionData) - goto loser; - - status = SecTrustSetParameters(trust, CSSM_TP_ACTION_DEFAULT, actionData); - if (status) - goto loser; - - status = SecTrustEvaluate(trust, NULL); - if (status) - goto loser; - - status = SecTrustGetResult(trust, NULL, &certChain, &statusChain); - if (status) - goto loser; - - /* We don't drop the root if there is only 1 (self signed) certificate in the chain. */ - if (!includeRoot && CFArrayGetCount(certChain) > 1) - { - CFMutableArrayRef subChain = CFArrayCreateMutableCopy(NULL, 0, certChain); - CFRelease(certChain); - certChain = subChain; - if (subChain) - CFArrayRemoveValueAtIndex(subChain, CFArrayGetCount(subChain) - 1); - } - -loser: - if (searchRef) - CFRelease(searchRef); - if (policy) - CFRelease(policy); - if (wrappedCert) - CFRelease(wrappedCert); - if (trust) - CFRelease(trust); - if (actionData) - CFRelease(actionData); - if (certChain && status) - { - CFRelease(certChain); - certChain = NULL; - } - - return certChain; -} - -CFArrayRef CERT_CertListFromCert(SecCertificateRef cert) -{ - const void *value = cert; - return cert ? CFArrayCreate(NULL, &value, 1, &kCFTypeArrayCallBacks) : NULL; -} - -CFArrayRef CERT_DupCertList(CFArrayRef oldList) -{ - CFRetain(oldList); - return oldList; -} - -// Extract a public key object from a SubjectPublicKeyInfo -SecPublicKeyRef CERT_ExtractPublicKey(SecCertificateRef cert) -{ - SecPublicKeyRef keyRef = NULL; - SecCertificateCopyPublicKey(cert,&keyRef); - return keyRef; -} - -SECStatus CERT_CheckCertUsage (SecCertificateRef cert,unsigned char usage) -{ - // abort(); - // @@@ It's all good, it's ok. - return SECSuccess; -} - -// Find a certificate in the database by a email address -// "emailAddr" is the email address to look up -SecCertificateRef CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray, char *emailAddr) -{ - abort(); - return NULL; -} - -// 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; -} - -static int compareCssmData( - const CSSM_DATA *d1, - const CSSM_DATA *d2) -{ - if((d1 == NULL) || (d2 == NULL)) { - return 0; - } - if(d1->Length != d2->Length) { - return 0; - } - if(memcmp(d1->Data, d2->Data, d1->Length)) { - return 0; - } - return 1; -} - -// 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; dexderIssuer, &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; -} - -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; dexdata. -SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert, SECItem *retItem) -{ - CSSM_DATA_PTR fieldValue = NULL; - OSStatus ortn; - CSSM_X509_EXTENSION *extp; - CE_SubjectKeyID *skid; - - ortn = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_SubjectKeyIdentifier, - &fieldValue); - if(ortn || (fieldValue == NULL)) { - /* this cert doesn't have that extension */ - return SECFailure; - } - extp = (CSSM_X509_EXTENSION *)fieldValue->Data; - skid = (CE_SubjectKeyID *)extp->value.parsedValue; - retItem->Data = (uint8 *)PORT_Alloc(skid->Length); - retItem->Length = skid->Length; - memmove(retItem->Data, skid->Data, retItem->Length); - SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_SubjectKeyIdentifier, - fieldValue); - return SECSuccess; -} - -// Extract the issuer and serial number from a certificate -SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert) -{ - OSStatus status; - SecCmsIssuerAndSN *certIssuerAndSN; - CSSM_CL_HANDLE clHandle; - CSSM_DATA_PTR serialNumber = 0; - CSSM_DATA_PTR issuer = 0; - CSSM_DATA certData = {}; - CSSM_HANDLE resultsHandle = 0; - uint32 numberOfFields = 0; - CSSM_RETURN result; - void *mark; - - mark = PORT_ArenaMark(pl); - - status = SecCertificateGetCLHandle(cert, &clHandle); - if (status) - goto loser; - status = SecCertificateGetData(cert, &certData); - if (status) - goto loser; - - /* Get the issuer from the cert. */ - result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, - &OID_X509V1IssuerNameStd, &resultsHandle, &numberOfFields, &issuer); - - if (result || numberOfFields < 1) - goto loser; - result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); - if (result) - goto loser; - - - /* Get the serialNumber from the cert. */ - result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, - &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber); - if (result || numberOfFields < 1) - goto loser; - result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle); - if (result) - goto loser; - - /* Allocate the SecCmsIssuerAndSN struct. */ - certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN)); - if (certIssuerAndSN == NULL) - goto loser; - - /* Copy the issuer. */ - certIssuerAndSN->derIssuer.Data = (uint8 *) PORT_ArenaAlloc(pl, issuer->Length); - if (!certIssuerAndSN->derIssuer.Data) - goto loser; - PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer->Data, issuer->Length); - certIssuerAndSN->derIssuer.Length = issuer->Length; - - /* Copy the serialNumber. */ - certIssuerAndSN->serialNumber.Data = (uint8 *) PORT_ArenaAlloc(pl, serialNumber->Length); - if (!certIssuerAndSN->serialNumber.Data) - goto loser; - PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber->Data, serialNumber->Length); - certIssuerAndSN->serialNumber.Length = serialNumber->Length; - - PORT_ArenaUnmark(pl, mark); - - CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); - CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); - - return certIssuerAndSN; - -loser: - PORT_ArenaRelease(pl, mark); - - if (serialNumber) - CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber); - if (issuer) - CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer); - - PORT_SetError(SEC_INTERNAL_ONLY); - return NULL; -} - -// 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; -} - -SECStatus CERT_SaveSMimeProfile(SecCertificateRef cert, SECItem *emailProfile,SECItem *profileTime) -{ - fprintf(stderr, "WARNING: CERT_SaveSMimeProfile unimplemented\n"); - return SECSuccess; -} - -// Check the hostname to make sure that it matches the shexp that -// is given in the common name of the certificate. -SECStatus CERT_VerifyCertName(SecCertificateRef cert, const char *hostname) -{ - fprintf(stderr, "WARNING: CERT_VerifyCertName unimplemented\n"); - return SECSuccess; -} - -/* -** 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