#include <stdlib.h>
#include <strings.h>
#include <stdio.h>
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#include <Security/CMSDecoder.h>
#include <security_cdsa_utils/cuFileIo.h>
#include <utilLib/common.h>
#define LOOPS_DEF 100
#define SIGNED_FILE "noRoot.p7"
static void usage(char **argv)
{
printf("usage: %s [options]\n", argv[0]);
printf("Options:\n");
printf(" -l loops -- loops; default %d; 0=forever\n", LOOPS_DEF);
printf(" -i inFile -- input file; default is %s\n", SIGNED_FILE);
printf(" -K -- set empty KC list\n");
exit(1);
}
static OSStatus doDecode(
const void *cmsData,
size_t cmsDataLen,
SecPolicyRef policyRef,
CFArrayRef kcArray)
{
OSStatus ortn;
CMSDecoderRef cmsDecoder = NULL;
CMSDecoderCreate(&cmsDecoder);
if(kcArray) {
ortn = CMSDecoderSetSearchKeychain(cmsDecoder, kcArray);
if(ortn) {
cssmPerror("CMSDecoderSetSearchKeychain", ortn);
return ortn;
}
}
ortn = CMSDecoderUpdateMessage(cmsDecoder, cmsData, cmsDataLen);
if(ortn) {
cssmPerror("CMSDecoderUpdateMessage", ortn);
return ortn;
}
ortn = CMSDecoderFinalizeMessage(cmsDecoder);
if(ortn) {
cssmPerror("CMSDecoderFinalizeMessage", ortn);
return ortn;
}
CMSSignerStatus signerStatus;
ortn = CMSDecoderCopySignerStatus(cmsDecoder, 0, policyRef, true, &signerStatus, NULL, NULL);
if(ortn) {
cssmPerror("CMSDecoderCopySignerStatus", ortn);
return ortn;
}
if(signerStatus != kCMSSignerValid) {
printf("***Bad signerStatus (%d)\n", (int)signerStatus);
ortn = -1;
}
CFRelease(cmsDecoder);
return ortn;
}
int main(int argc, char **argv)
{
unsigned dex;
CFArrayRef emptyKCList = NULL;
unsigned char *blob = NULL;
unsigned blobLen;
SecPolicyRef policyRef = NULL;
unsigned loops = LOOPS_DEF;
char *blobFile = SIGNED_FILE;
bool emptyList = false;
extern char *optarg;
int arg;
while ((arg = getopt(argc, argv, "l:i:Kh")) != -1) {
switch (arg) {
case 'l':
loops = atoi(optarg);
break;
case 'i':
blobFile = optarg;
break;
case 'K':
emptyList = true;
emptyKCList = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
break;
case 'h':
usage(argv);
}
}
if(optind != argc) {
usage(argv);
}
if(readFile(blobFile, &blob, &blobLen)) {
printf("***Error reading %s\n", blobFile);
exit(1);
}
SecPolicySearchRef policySearch = NULL;
OSStatus ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
&CSSMOID_APPLE_X509_BASIC,
NULL, &policySearch);
if(ortn) {
cssmPerror("SecPolicySearchCreate", ortn);
exit(1);
}
ortn = SecPolicySearchCopyNext(policySearch, &policyRef);
if(ortn) {
cssmPerror("SecPolicySearchCopyNext", ortn);
exit(1);
}
CFRelease(policySearch);
CFAbsoluteTime startTimeFirst;
CFAbsoluteTime endTimeFirst;
CFAbsoluteTime startTimeMulti;
CFAbsoluteTime endTimeMulti;
startTimeFirst = CFAbsoluteTimeGetCurrent();
if(doDecode(blob, blobLen, policyRef, emptyKCList)) {
exit(1);
}
endTimeFirst = CFAbsoluteTimeGetCurrent();
startTimeMulti = CFAbsoluteTimeGetCurrent();
for(dex=0; dex<loops; dex++) {
if(doDecode(blob, blobLen, policyRef, emptyKCList)) {
exit(1);
}
}
endTimeMulti = CFAbsoluteTimeGetCurrent();
CFTimeInterval elapsed = endTimeMulti - startTimeMulti;
printf("First decode = %4.1f ms\n", (endTimeFirst - startTimeFirst) * 1000.0);
printf("Next decodes = %4.2f ms/op (%f s total for %u loops)\n",
elapsed * 1000.0 / loops, elapsed, loops);
return 0;
}