#include <Security/SecIdentity.h>
#include <Security/SecCertificateInternal.h>
#include <Security/SecKeyPriv.h>
+#include <utilities/SecCFWrappers.h>
#include <CommonCrypto/CommonDigest.h>
#include <AssertMacros.h>
PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
rv = SECFailure;
goto loser;
- break;
}
}
return rv;
}
-static CFTypeRef CERT_FindItemInAllAvailableKeychains(CFDictionaryRef query) {
+static CF_RETURNS_RETAINED CFTypeRef CERT_FindItemInAllAvailableKeychains(CFDictionaryRef query) {
CFTypeRef item = NULL;
CFMutableDictionaryRef q = NULL;
CFDictionaryRef whoAmI = NULL;
return (SecCertificateRef)result;
}
-CF_RETURNS_RETAINED CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Boolean includeRoot)
+CF_RETURNS_RETAINED CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Boolean includeRoot, Boolean mustIncludeRoot)
{
CFMutableArrayRef certs = NULL;
SecPolicyRef policy = NULL;
CFArrayRef wrappedCert = NULL;
policy = SecPolicyCreateBasicX509();
- if (!policy)
+ if (!policy) {
goto out;
+ }
wrappedCert = CERT_CertListFromCert(cert);
- if (SecTrustCreateWithCertificates(wrappedCert, policy, &trust))
+ if (SecTrustCreateWithCertificates(wrappedCert, policy, &trust)) {
goto out;
+ }
SecTrustResultType result;
- if (SecTrustEvaluate(trust, &result))
+ if (SecTrustEvaluate(trust, &result)) {
goto out;
+ }
CFIndex idx, count = SecTrustGetCertificateCount(trust);
/* If we weren't able to build a chain to a self-signed cert, warn. */
if (lastCert && (0 == SecCertificateIsSelfSigned(lastCert, &isSelfSigned)) && !isSelfSigned) {
CFStringRef commonName = NULL;
(void)SecCertificateCopyCommonName(cert, &commonName);
- fprintf(stderr, "Warning: unable to build chain to self-signed root for signer \"%s\"",
+ fprintf(stderr, "Warning: unable to build chain to self-signed root for signer \"%s\"\n",
commonName ? CFStringGetCStringPtr(commonName, kCFStringEncodingUTF8) : "");
if (commonName) { CFRelease(commonName); }
+
+ // we don't have a root, so if the caller required one, fail
+ if (mustIncludeRoot) {
+ goto out;
+ }
}
/* We don't drop the root if there is only 1 certificate in the chain. */
- if (!includeRoot && count > 1) { count--; }
+ if (isSelfSigned && !includeRoot && count > 1) {
+ count--;
+ }
certs = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks);
- for(idx = 0; idx < count; idx++)
+ for(idx = 0; idx < count; idx++) {
CFArrayAppendValue(certs, SecTrustGetCertificateAtIndex(trust, idx));
+ }
out:
- if (trust) CFRelease(trust);
- if (policy) CFRelease(policy);
- if (wrappedCert) CFRelease(wrappedCert);
+ if (trust) { CFRelease(trust); }
+ if (policy) { CFRelease(policy); }
+ if (wrappedCert) { CFRelease(wrappedCert); }
return certs;
}
-CFArrayRef CERT_CertListFromCert(SecCertificateRef cert)
+CF_RETURNS_RETAINED CFArrayRef CERT_CertListFromCert(SecCertificateRef cert)
{
const void *value = cert;
return cert ? CFArrayCreate(NULL, &value, 1, &kCFTypeArrayCallBacks) : NULL;
void *mark;
mark = PORT_ArenaMark(pl);
- CFDataRef serial_data = NULL;
CFDataRef issuer_data = SecCertificateCopyIssuerSequence(cert);
- if (!issuer_data)
- goto loser;
- serial_data = SecCertificateCopySerialNumberData(cert, NULL);
- if (!serial_data)
+ CFDataRef serial_data = SecCertificateCopySerialNumberData(cert, NULL);
+ if (!issuer_data || !serial_data) {
goto loser;
-
- SecAsn1Item serialNumber = { CFDataGetLength(serial_data),
- (uint8_t *)CFDataGetBytePtr(serial_data) };
- SecAsn1Item issuer = { CFDataGetLength(issuer_data),
- (uint8_t *)CFDataGetBytePtr(issuer_data) };
-
- /* Allocate the SecCmsIssuerAndSN struct. */
+ }
+
+ SecAsn1Item serialNumber = {
+ .Length = CFDataGetLength(serial_data),
+ .Data = (uint8_t *)CFDataGetBytePtr(serial_data)
+ };
+ SecAsn1Item issuer = {
+ .Length = CFDataGetLength(issuer_data),
+ .Data = (uint8_t *)CFDataGetBytePtr(issuer_data)
+ };
+
+ /* Allocate the SecCmsIssuerAndSN struct. */
certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN));
- if (certIssuerAndSN == NULL)
- goto loser;
+ if (certIssuerAndSN == NULL) {
+ goto loser;
+ }
/* Copy the issuer. */
certIssuerAndSN->derIssuer.Data = (uint8_t *) PORT_ArenaAlloc(pl, issuer.Length);
- if (!certIssuerAndSN->derIssuer.Data)
- goto loser;
+ 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_t *) PORT_ArenaAlloc(pl, serialNumber.Length);
- if (!certIssuerAndSN->serialNumber.Data)
- goto loser;
+ if (!certIssuerAndSN->serialNumber.Data) {
+ goto loser;
+ }
PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber.Data, serialNumber.Length);
certIssuerAndSN->serialNumber.Length = serialNumber.Length;
CFRelease(issuer_data);
PORT_ArenaUnmark(pl, mark);
-
+
return certIssuerAndSN;
loser:
- if (serial_data)
- CFRelease(serial_data);
- if (issuer_data)
- CFRelease(issuer_data);
+ CFReleaseNull(serial_data);
+ CFReleaseNull(issuer_data);
PORT_ArenaRelease(pl, mark);
PORT_SetError(SEC_INTERNAL_ONLY);
// 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
-static CFTypeRef CERT_FindByIssuerAndSN (CFTypeRef keychainOrArray, CFTypeRef class, const SecCmsIssuerAndSN *issuerAndSN)
+static CF_RETURNS_RETAINED CFTypeRef CERT_FindByIssuerAndSN (CFTypeRef keychainOrArray, CFTypeRef class, const SecCmsIssuerAndSN *issuerAndSN)
{
CFTypeRef ident = NULL;
CFDictionaryRef query = NULL;
// Generate a certificate key from the Subject Key ID, then look it up in the database.
// Return the cert if found. "subjKeyID" is the Subject Key ID to look for
-static CFTypeRef CERT_FindBySubjectKeyID (CFTypeRef keychainOrArray, CFTypeRef class, const SecAsn1Item *subjKeyID)
+static CF_RETURNS_RETAINED CFTypeRef CERT_FindBySubjectKeyID (CFTypeRef keychainOrArray, CFTypeRef class, const SecAsn1Item *subjKeyID)
{
CFTypeRef ident = NULL;
CFDictionaryRef query = NULL;
return pubKey;
}
-void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey)
+void SECKEY_DestroyPublicKey(SecPublicKeyRef CF_CONSUMED pubKey)
{
CFRelease(pubKey);
}