#include <Security/SecAsn1Coder.h>
#include <Security/X509Templates.h>
#include <Security/cssmapple.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <security_cdsa_utils/cuOidParser.h>
#include <security_cdsa_utils/cuFileIo.h>
static void usage(char **argv)
{
printf("Usage: %s certFile outFileBase [r for CRL, default is cert]\n",
argv[0]);
exit(1);
}
static unsigned nssArraySize(
const void **array)
{
unsigned count = 0;
if (array) {
while (*array++) {
count++;
}
}
return count;
}
int main(int argc, char **argv)
{
if(argc < 3) {
usage(argv);
}
bool doCert = true;
NSS_Certificate signedCert;
NSS_Crl signedCrl;
void *decodeTarget;
const SecAsn1Template *templ;
NSS_CertExtension ***extenp;
for(int arg=3; arg<argc; arg++) {
switch(argv[arg][0]) {
case 'r':
doCert = false; break;
default:
usage(argv);
}
}
if(doCert) {
memset(&signedCert, 0, sizeof(signedCert));
decodeTarget = &signedCert;
templ = kSecAsn1SignedCertTemplate;
extenp = &signedCert.tbs.extensions;
}
else {
memset(&signedCrl, 0, sizeof(signedCrl));
decodeTarget = &signedCrl;
templ = kSecAsn1SignedCrlTemplate;
extenp = &signedCrl.tbs.extensions;
}
const char *certFile = argv[1];
const char *outBase = argv[2];
unsigned char *rawCert;
unsigned rawCertLen;
if(readFile(certFile, &rawCert, &rawCertLen)) {
printf("***Can't read cert file. Abortihng.\n");
exit(1);
}
SecAsn1CoderRef coder;
CSSM_DATA rawItem = {rawCertLen, rawCert};
OSStatus ortn = SecAsn1CoderCreate(&coder);
if(ortn) {
cssmPerror("SecAsn1CoderCreate", ortn);
}
if(SecAsn1DecodeData(coder, &rawItem, templ, decodeTarget)) {
printf("SecAsn1DecodeData(signed) error\n");
exit(1);
}
NSS_CertExtension **extens = *extenp;
unsigned numExtens = nssArraySize((const void **)extens);
if(numExtens == 0) {
printf("There appear to be zero extensions in this item.\n");
exit(0);
}
OidParser parser;
char oidStr[OID_PARSER_STRING_SIZE];
char outFileName[200];
for(unsigned dex=0; dex<numExtens; dex++) {
NSS_CertExtension *exten = extens[dex];
parser.oidParse(exten->extnId.Data, exten->extnId.Length, oidStr);
printf("Extension %u : %s\n", dex, oidStr);
sprintf(outFileName, "%s_%u", outBase, dex);
if(writeFile(outFileName, exten->value.Data, exten->value.Length)) {
printf("***Error writing %s. Aborting.\n",
outFileName);
exit(1);
}
else {
printf("...wrote %lu bytes to %s\n",
exten->value.Length, outFileName);
}
}
SecAsn1CoderRelease(coder);
printf("..done.\n");
return 0;
}