#include "csutilities.h"
#include <Security/SecCertificatePriv.h>
#include <security_codesigning/requirement.h>
#include <security_utilities/debugging.h>
#include <security_utilities/errors.h>
namespace Security {
namespace CodeSigning {
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);
}
size_t hashFileData(const char *path, SHA1 &hasher)
{
UnixPlusPlus::AutoFileDesc fd(path);
return hashFileData(fd, hasher);
}
size_t hashFileData(UnixPlusPlus::FileDesc fd, SHA1 &hasher, size_t limit )
{
unsigned char buffer[4096];
size_t total = 0;
for (;;) {
size_t size = sizeof(buffer);
if (limit && limit < size)
size = limit;
size_t got = fd.read(buffer, size);
total += got;
if (fd.atEnd())
break;
hasher(buffer, got);
if (limit && (limit -= got) == 0)
break;
}
return total;
}
bool certificateHasField(SecCertificateRef cert, const CssmOid &oid)
{
assert(cert);
CSSM_DATA *value;
switch (OSStatus rc = SecCertificateCopyFirstFieldValue(cert, &oid, &value)) {
case noErr:
MacOSError::check(SecCertificateReleaseFirstFieldValue(cert, &oid, value));
return true; case CSSMERR_CL_UNKNOWN_TAG:
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;
}
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();
}
} }