Beispiel #1
0
//
// Generate the CMS signature for a (finished) CodeDirectory.
//
CFDataRef SecCodeSigner::Signer::signCodeDirectory(const CodeDirectory *cd)
{
	assert(state.mSigner);
	CFRef<CFMutableDictionaryRef> defaultTSContext = NULL;
    
	// a null signer generates a null signature blob
	if (state.mSigner == SecIdentityRef(kCFNull))
		return CFDataCreate(NULL, NULL, 0);
	
	// generate CMS signature
	CFRef<CMSEncoderRef> cms;
	MacOSError::check(CMSEncoderCreate(&cms.aref()));
	MacOSError::check(CMSEncoderSetCertificateChainMode(cms, kCMSCertificateChainWithRoot));
	CMSEncoderAddSigners(cms, state.mSigner);
	MacOSError::check(CMSEncoderSetHasDetachedContent(cms, true));
	
	if (signingTime) {
		MacOSError::check(CMSEncoderAddSignedAttributes(cms, kCMSAttrSigningTime));
		MacOSError::check(CMSEncoderSetSigningTime(cms, signingTime));
	}
	
	MacOSError::check(CMSEncoderUpdateContent(cms, cd, cd->length()));
    
    // Set up to call Timestamp server if requested
    
    if (state.mWantTimeStamp)
    {
        CFRef<CFErrorRef> error = NULL;
        defaultTSContext = SecCmsTSAGetDefaultContext(&error.aref());
        if (error)
            MacOSError::throwMe(errSecDataNotAvailable);
            
        if (state.mNoTimeStampCerts || state.mTimestampService) {
            if (state.mTimestampService)
                CFDictionarySetValue(defaultTSContext, kTSAContextKeyURL, state.mTimestampService);
            if (state.mNoTimeStampCerts)
                CFDictionarySetValue(defaultTSContext, kTSAContextKeyNoCerts, kCFBooleanTrue);
       }
            
        CmsMessageSetTSAContext(cms, defaultTSContext);
    }
    
	CFDataRef signature;
	MacOSError::check(CMSEncoderCopyEncodedContent(cms, &signature));

	return signature;
}
//
// Pre-Signing contexts
//
PreSigningContext::PreSigningContext(const SecCodeSigner::Signer &signer)
{
	// construct a cert chain
	if (signer.signingIdentity() != SecIdentityRef(kCFNull)) {
		CFRef<SecCertificateRef> signingCert;
		MacOSError::check(SecIdentityCopyCertificate(signer.signingIdentity(), &signingCert.aref()));
		CFRef<SecPolicyRef> policy = SecPolicyCreateWithOID(kSecPolicyAppleCodeSigning);
		CFRef<SecTrustRef> trust;
		MacOSError::check(SecTrustCreateWithCertificates(CFArrayRef(signingCert.get()), policy, &trust.aref()));
		SecTrustResultType result;
		MacOSError::check(SecTrustEvaluate(trust, &result));
		CSSM_TP_APPLE_EVIDENCE_INFO *info;
		MacOSError::check(SecTrustGetResult(trust, &result, &mCerts.aref(), &info));
		this->certs = mCerts;
	}
	
	// other stuff
	this->identifier = signer.signingIdentifier();
}
Beispiel #3
0
//
// Contemplate the object-to-be-signed and set up the Signer state accordingly.
//
void SecCodeSigner::Signer::prepare(SecCSFlags flags)
{
	// get the Info.plist out of the rep for some creative defaulting
	CFRef<CFDictionaryRef> infoDict;
	if (CFRef<CFDataRef> infoData = rep->component(cdInfoSlot))
		infoDict.take(makeCFDictionaryFrom(infoData));

	// work out the canonical identifier
	identifier = state.mIdentifier;
	if (identifier.empty()) {
		identifier = rep->recommendedIdentifier(state);
		if (identifier.find('.') == string::npos)
			identifier = state.mIdentifierPrefix + identifier;
		if (identifier.find('.') == string::npos && state.isAdhoc())
			identifier = identifier + "-" + uniqueName();
		secdebug("signer", "using default identifier=%s", identifier.c_str());
	} else
		secdebug("signer", "using explicit identifier=%s", identifier.c_str());
	
	// work out the CodeDirectory flags word
	if (state.mCdFlagsGiven) {
		cdFlags = state.mCdFlags;
		secdebug("signer", "using explicit cdFlags=0x%x", cdFlags);
	} else {
		cdFlags = 0;
		if (infoDict)
			if (CFTypeRef csflags = CFDictionaryGetValue(infoDict, CFSTR("CSFlags"))) {
				if (CFGetTypeID(csflags) == CFNumberGetTypeID()) {
					cdFlags = cfNumber<uint32_t>(CFNumberRef(csflags));
					secdebug("signer", "using numeric cdFlags=0x%x from Info.plist", cdFlags);
				} else if (CFGetTypeID(csflags) == CFStringGetTypeID()) {
					cdFlags = cdTextFlags(cfString(CFStringRef(csflags)));
					secdebug("signer", "using text cdFlags=0x%x from Info.plist", cdFlags);
				} else
					MacOSError::throwMe(errSecCSBadDictionaryFormat);
			}
	}
	if (state.mSigner == SecIdentityRef(kCFNull))	// ad-hoc signing requested...
		cdFlags |= kSecCodeSignatureAdhoc;	// ... so note that
	
	// prepare the resource directory, if any
	string rpath = rep->resourcesRootPath();
	if (!rpath.empty()) {
		// explicitly given resource rules always win
		CFCopyRef<CFDictionaryRef> resourceRules = state.mResourceRules;
		
		// embedded resource rules come next
		if (!resourceRules && infoDict)
			if (CFTypeRef spec = CFDictionaryGetValue(infoDict, _kCFBundleResourceSpecificationKey)) {
				if (CFGetTypeID(spec) == CFStringGetTypeID())
					if (CFRef<CFDataRef> data = cfLoadFile(rpath + "/" + cfString(CFStringRef(spec))))
						if (CFDictionaryRef dict = makeCFDictionaryFrom(data))
							resourceRules.take(dict);
				if (!resourceRules)	// embedded rules present but unacceptable
					MacOSError::throwMe(errSecCSResourceRulesInvalid);
			}

		// finally, ask the DiskRep for its default
		if (!resourceRules)
			resourceRules.take(rep->defaultResourceRules(state));
		
		// build the resource directory
		ResourceBuilder resources(rpath, cfget<CFDictionaryRef>(resourceRules, "rules"), digestAlgorithm());
		rep->adjustResources(resources);	// DiskRep-specific adjustments
		CFRef<CFDictionaryRef> rdir = resources.build();
		resourceDirectory.take(CFPropertyListCreateXMLData(NULL, rdir));
	}
	
	// screen and set the signing time
	CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
	if (state.mSigningTime == CFDateRef(kCFNull)) {
		signingTime = 0;		// no time at all
	} else if (!state.mSigningTime) {
		signingTime = now;		// default
	} else {
		CFAbsoluteTime time = CFDateGetAbsoluteTime(state.mSigningTime);
		if (time > now)	// not allowed to post-date a signature
			MacOSError::throwMe(errSecCSBadDictionaryFormat);
		signingTime = time;
	}
	
	pagesize = state.mPageSize ? cfNumber<size_t>(state.mPageSize) : rep->pageSize(state);
    
    // Timestamping setup
    CFRef<SecIdentityRef> mTSAuth;	// identity for client-side authentication to the Timestamp server
}
Beispiel #4
0
int findFirstEncryptionPublicKeyOnToken(SecKeyRef *publicKey, SecKeychainRef *keychainRef, CFDataRef *label)
{
	if (!publicKey || !keychainRef)
		return paramErr;

	OSStatus status = noErr;
	CFArrayRef identityArray = NULL;
	SecKeyRef tmpKeyRef = NULL;
	SecCertificateRef certificate = NULL;
	SecKeychainRef tmpKeychainRef = NULL;
		
	try
	{
		status = findEncryptionIdentities((CFTypeRef *)&identityArray);
		if (status)
			MacOSError::throwMe(status);

		if (!identityArray || 
			(CFGetTypeID(identityArray)!=CFArrayGetTypeID()) ||
			(CFArrayGetCount(identityArray)==0))
			MacOSError::throwMe(paramErr);

		CFTypeRef tmpref = CFArrayGetValueAtIndex(identityArray, 0);
		if (CFGetTypeID(tmpref)!=SecIdentityGetTypeID())
			MacOSError::throwMe(paramErr);
			
		status = SecIdentityCopyCertificate(SecIdentityRef(tmpref), &certificate);
		if (status)
			MacOSError::throwMe(status);

		if (!certificate)
			MacOSError::throwMe(errKCItemNotFound);
		
		status = findCertificatePublicKeyHash(certificate, label);
		if (status)
			MacOSError::throwMe(status);

		status = SecKeychainItemCopyKeychain(SecKeychainItemRef(certificate), &tmpKeychainRef);
		if (status)
			MacOSError::throwMe(status);

		status = SecCertificateCopyPublicKey(certificate, &tmpKeyRef);
		if (status)
			MacOSError::throwMe(status);
		
		// Found an encryption key
		*publicKey = tmpKeyRef;
		*keychainRef = tmpKeychainRef;
	}
	catch (const MacOSError &err)
	{
		status = err.osStatus();
		cssmPerror("findFirstEncryptionPublicKeyOnToken", status);
	}
	catch (...)
	{
		fprintf(stderr, "findFirstEncryptionPublicKeyOnToken: unknown exception\n");
		status = errKCItemNotFound;
	}
	
	if (status)
	{
		if (identityArray)
			CFRelease(identityArray);
		if (certificate)
			CFRelease(certificate);
	}

	if (identityArray)
		CFRelease(identityArray);
	if (certificate)
		CFRelease(certificate);
	
	return status;
}