#include "drmaker.h"
#include "csutilities.h"
#include <Security/oidsbase.h>
#include <Security/SecCertificatePriv.h>
namespace Security {
namespace CodeSigning {
static const uint8_t adcSdkMarker[] = { APPLE_EXTENSION_OID, 2, 1 }; const CSSM_DATA adcSdkMarkerOID = { sizeof(adcSdkMarker), (uint8_t *)adcSdkMarker };
static const uint8_t caspianSdkMarker[] = { APPLE_EXTENSION_OID, 2, 6 }; const CSSM_DATA devIdSdkMarkerOID = { sizeof(caspianSdkMarker), (uint8_t *)caspianSdkMarker };
static const uint8_t caspianLeafMarker[] = { APPLE_EXTENSION_OID, 1, 13 }; const CSSM_DATA devIdLeafMarkerOID = { sizeof(caspianLeafMarker), (uint8_t *)caspianLeafMarker };
DRMaker::DRMaker(const Requirement::Context &context)
: ctx(context)
{
}
DRMaker::~DRMaker()
{
}
Requirement *DRMaker::make()
{
if (ctx.certCount() == 0)
return NULL;
this->put(opAnd);
this->ident(ctx.identifier);
if (isAppleCA(ctx.cert(Requirement::anchorCert))
#if defined(TEST_APPLE_ANCHOR)
|| !memcmp(anchorHash, Requirement::testAppleAnchorHash(), SHA1::digestLength)
#endif
)
appleAnchor();
else
nonAppleAnchor();
return Maker::make();
}
void DRMaker::nonAppleAnchor()
{
CFRef<CFStringRef> leafOrganization;
MacOSError::check(SecCertificateCopySubjectComponent(ctx.cert(Requirement::leafCert),
&CSSMOID_OrganizationName, &leafOrganization.aref()));
int slot = Requirement::leafCert; if (leafOrganization) {
while (SecCertificateRef ca = ctx.cert(slot+1)) { CFRef<CFStringRef> caOrganization;
MacOSError::check(SecCertificateCopySubjectComponent(ca, &CSSMOID_OrganizationName, &caOrganization.aref()));
if (!caOrganization || CFStringCompare(leafOrganization, caOrganization, 0) != kCFCompareEqualTo)
break;
slot++;
}
if (slot == ctx.certCount() - 1) slot = Requirement::anchorCert; }
SHA1::Digest authorityHash;
hashOfCertificate(ctx.cert(slot), authorityHash);
this->anchor(slot, authorityHash);
}
void DRMaker::appleAnchor()
{
if (isIOSSignature()) {
CFRef<CFStringRef> leafCN;
MacOSError::check(SecCertificateCopySubjectComponent(ctx.cert(Requirement::leafCert),
&CSSMOID_CommonName, &leafCN.aref()));
this->put(opAnd);
this->anchorGeneric(); this->put(opAnd);
this->put(opCertField); this->put(0); this->put("subject.CN"); this->put(matchEqual); this->putData(leafCN); this->put(opCertGeneric); this->put(1); this->putData(adcSdkMarkerOID.Data, adcSdkMarkerOID.Length); this->put(matchExists); return;
}
if (isDeveloperIDSignature()) {
CFRef<CFStringRef> teamID;
MacOSError::check(SecCertificateCopySubjectComponent(ctx.cert(Requirement::leafCert),
&CSSMOID_OrganizationalUnitName, &teamID.aref()));
this->put(opAnd);
this->anchorGeneric();
this->put(opAnd);
this->put(opCertGeneric); this->put(1); this->putData(caspianSdkMarker, sizeof(caspianSdkMarker));
this->put(matchExists);
this->put(opAnd);
this->put(opCertGeneric); this->put(0); this->putData(caspianLeafMarker, sizeof(caspianLeafMarker));
this->put(matchExists);
this->put(opCertField); this->put(0); this->put("subject.OU"); this->put(matchEqual); this->putData(teamID); return;
}
this->anchor();
}
bool DRMaker::isIOSSignature()
{
if (ctx.certCount() == 3) if (SecCertificateRef intermediate = ctx.cert(1)) if (certificateHasField(intermediate, CssmOid::overlay(adcSdkMarkerOID)))
return true;
return false;
}
bool DRMaker::isDeveloperIDSignature()
{
if (ctx.certCount() == 3) if (SecCertificateRef intermediate = ctx.cert(1)) if (certificateHasField(intermediate, CssmOid::overlay(devIdSdkMarkerOID)))
return true;
return false;
}
} }