#include "xar++.h"
#include "notarization.h"
#include <security_utilities/cfutilities.h>
#include <Security/Security.h>
namespace Security {
namespace CodeSigning {
Xar::Xar(const char *path)
{
mXar = 0;
mSigCMS = 0;
mSigClassic = 0;
if (path)
open(path);
}
void Xar::open(const char *path)
{
if ((mXar = ::xar_open(path, READ)) == NULL)
return;
mPath = std::string(path);
xar_signature_t sig = ::xar_signature_first(mXar);
while (sig && mSigCMS == NULL) {
const char *type = ::xar_signature_type(sig);
if (strcmp(type, "CMS") == 0) {
mSigCMS = sig;
} else if (strcmp(type, "RSA") == 0) {
mSigClassic = sig;
}
sig = ::xar_signature_next(sig);
}
}
Xar::~Xar()
{
if (mXar)
::xar_close(mXar);
}
static CFArrayRef copyCertChainFromSignature(xar_signature_t sig)
{
unsigned count = xar_signature_get_x509certificate_count(sig);
CFRef<CFMutableArrayRef> certs = makeCFMutableArray(0);
for (unsigned ix = 0; ix < count; ix++) {
const uint8_t *data;
uint32_t length;
if (xar_signature_get_x509certificate_data(sig, ix, &data, &length) == 0) {
CFTempData cdata(data, length);
CFRef<SecCertificateRef> cert = SecCertificateCreateWithData(NULL, cdata);
CFArrayAppendValue(certs, cert.get());
}
}
return certs.yield();
}
CFArrayRef Xar::copyCertChain()
{
if (mSigCMS)
return copyCertChainFromSignature(mSigCMS);
else if (mSigClassic)
return copyCertChainFromSignature(mSigClassic);
return NULL;
}
void Xar::registerStapledNotarization()
{
registerStapledTicketInPackage(mPath);
}
CFDataRef Xar::createPackageChecksum()
{
xar_signature_t sig = NULL;
if (mSigCMS) {
sig = mSigCMS;
} else if (mSigClassic) {
sig = mSigClassic;
} else {
return NULL;
}
uint8_t *data = NULL;
uint32_t length;
if (xar_signature_copy_signed_data(sig, &data, &length, NULL, NULL, NULL) != 0) {
secerror("Unable to extract package hash for package: %s", mPath.c_str());
return NULL;
}
return makeCFData(data, length);
}
SecCSDigestAlgorithm Xar::checksumDigestAlgorithm()
{
int32_t error = 0;
const char* value = NULL;
unsigned long size = 0;
if (mXar == NULL) {
secerror("Evaluating checksum digest on bad xar: %s", mPath.c_str());
return kSecCodeSignatureNoHash;
}
error = xar_prop_get((xar_file_t)mXar, "checksum/size", &value);
if (error == -1) {
secerror("Unable to extract package checksum size: %s", mPath.c_str());
return kSecCodeSignatureNoHash;
}
size = strtoul(value, NULL, 10);
switch (size) {
case CC_SHA1_DIGEST_LENGTH:
return kSecCodeSignatureHashSHA1;
case CC_SHA256_DIGEST_LENGTH:
return kSecCodeSignatureHashSHA256;
case CC_SHA512_DIGEST_LENGTH:
return kSecCodeSignatureHashSHA512;
case CC_MD5_DIGEST_LENGTH:
default:
return kSecCodeSignatureNoHash;
}
}
} }