#include "csutilities.h"
#include <Security/SecCertificatePriv.h>
#include <security_codesigning/requirement.h>
#include <security_utilities/hashing.h>
#include <security_utilities/debugging.h>
#include <security_utilities/errors.h>
namespace Security {
namespace CodeSigning {
static const SHA1::Digest gAppleAnchorHash =
{ 0x61, 0x1e, 0x5b, 0x66, 0x2c, 0x59, 0x3a, 0x08, 0xff, 0x58,
0xd1, 0x4a, 0xe2, 0x24, 0x52, 0xd1, 0x98, 0xdf, 0x6c, 0x60 };
bool isAppleCA(SecCertificateRef cert)
{
return verifyHash(cert, gAppleAnchorHash);
}
bool isAppleCA(const Hashing::Byte *sha1)
{
return !memcmp(sha1, gAppleAnchorHash, SHA1::digestLength);
}
void hashOfCertificate(const void *certData, size_t certLength, SHA1::Digest digest)
{
SHA1 hasher;
hasher(certData, certLength);
hasher.finish(digest);
}
void hashOfCertificate(SecCertificateRef cert, SHA1::Digest digest)
{
assert(cert);
CSSM_DATA certData;
MacOSError::check(SecCertificateGetData(cert, &certData));
hashOfCertificate(certData.Data, certData.Length, digest);
}
bool verifyHash(SecCertificateRef cert, const Hashing::Byte *digest)
{
SHA1::Digest dig;
hashOfCertificate(cert, dig);
return !memcmp(dig, digest, SHA1::digestLength);
}
bool certificateHasField(SecCertificateRef cert, const CSSM_OID &oid)
{
assert(cert);
CSSM_DATA *value;
switch (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &oid, &value)) {
case errSecSuccess:
MacOSError::check(SecCertificateReleaseFirstFieldValue(cert, &oid, value));
return true; case errSecUnknownTag:
break; default:
MacOSError::throwMe(rc); }
CSSM_DATA **values;
bool found = false;
if (SecCertificateCopyFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, &values))
return false; if (values)
for (CSSM_DATA **p = values; *p; p++) {
const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)(*p)->Data;
if (oid == ext->extnId) {
found = true;
break;
}
}
MacOSError::check(SecCertificateReleaseFieldValues(cert, &CSSMOID_X509V3CertificateExtensionCStruct, values));
return found;
}
bool certificateHasPolicy(SecCertificateRef cert, const CSSM_OID &policyOid)
{
bool matched = false;
assert(cert);
CSSM_DATA *data;
if (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_CertificatePolicies, &data))
MacOSError::throwMe(rc);
if (data && data->Data && data->Length == sizeof(CSSM_X509_EXTENSION)) {
const CSSM_X509_EXTENSION *ext = (const CSSM_X509_EXTENSION *)data->Data;
assert(ext->format == CSSM_X509_DATAFORMAT_PARSED);
const CE_CertPolicies *policies = (const CE_CertPolicies *)ext->value.parsedValue;
if (policies)
for (unsigned int n = 0; n < policies->numPolicies; n++) {
const CE_PolicyInformation &cp = policies->policies[n];
if (cp.certPolicyId == policyOid) {
matched = true;
break;
}
}
}
SecCertificateReleaseFirstFieldValue(cert, &CSSMOID_PolicyConstraints, data);
return matched;
}
Copyfile::Copyfile()
{
if (!(mState = copyfile_state_alloc()))
UnixError::throwMe();
}
void Copyfile::set(uint32_t flag, const void *value)
{
check(::copyfile_state_set(mState, flag, value));
}
void Copyfile::get(uint32_t flag, void *value)
{
check(::copyfile_state_set(mState, flag, value));
}
void Copyfile::operator () (const char *src, const char *dst, copyfile_flags_t flags)
{
check(::copyfile(src, dst, mState, flags));
}
void Copyfile::check(int rc)
{
if (rc < 0)
UnixError::throwMe();
}
MessageTrace::MessageTrace(const char *domain, const char *signature)
{
mAsl = asl_new(ASL_TYPE_MSG);
if (domain)
asl_set(mAsl, "com.apple.message.domain", domain);
if (signature)
asl_set(mAsl, "com.apple.message.signature", signature);
}
void MessageTrace::add(const char *key, const char *format, ...)
{
va_list args;
va_start(args, format);
char value[200];
vsnprintf(value, sizeof(value), format, args);
va_end(args);
asl_set(mAsl, (string("com.apple.message.") + key).c_str(), value);
}
void MessageTrace::send(const char *format, ...)
{
va_list args;
va_start(args, format);
asl_vlog(NULL, mAsl, ASL_LEVEL_NOTICE, format, args);
va_end(args);
}
} }