#include <security_pkcs12/pkcs12Coder.h>
#include <stdlib.h>
#include <stdio.h>
#include <Security/cssmtype.h>
#include <security_cdsa_utils/cuPrintCert.h>
#include <security_cdsa_utils/cuCdsaUtils.h>
#include "p12GetPassKey.h"
#include "p12.h"
#define P12_DECODE_VIA_CPP 0
static void printUcStr(
CFStringRef cfstr)
{
CFIndex len = CFStringGetLength(cfstr) + 1;
char *outStr = (char *)malloc(len);
if(CFStringGetCString(cfstr, outStr, len, kCFStringEncodingASCII)) {
printf("%s\n", outStr);
}
else {
printf("***Error converting from unicode to ASCII\n");
}
free(outStr);
}
static void printDataAsHex(
CFDataRef d,
unsigned maxToPrint = 0) {
unsigned i;
bool more = false;
uint32 len = CFDataGetLength(d);
const uint8 *cp = CFDataGetBytePtr(d);
if((maxToPrint != 0) && (len > maxToPrint)) {
len = maxToPrint;
more = true;
}
for(i=0; i<len; i++) {
printf("%02X ", ((unsigned char *)cp)[i]);
}
if(more) {
printf("...\n");
}
else {
printf("\n");
}
}
static void printAlgAsString(
CSSM_ALGORITHMS alg)
{
char *s = "unknown alg";
switch(alg) {
case CSSM_ALGID_RSA:
s = "RSA";
break;
case CSSM_ALGID_DSA:
s = "DSA";
break;
case CSSM_ALGID_FEE:
s = "FEE";
break;
default:
break;
}
printf("%s\n", s);
}
#if P12_DECODE_VIA_CPP
static void printBagAttrs(
P12SafeBag &bag)
{
CFStringRef friendlyName = bag.friendlyName();
if(friendlyName) {
printf(" friendlyName : ");
printUcStr(friendlyName);
CFRelease(friendlyName);
}
CFDataRef keyId = bag.localKeyId();
if(keyId) {
printf(" localKeyId : ");
printDataAsHex(keyId, 16);
CFRelease(keyId);
}
if((friendlyName == NULL) && (keyId == NULL)) {
printf(" <no attributes found>\n");
}
}
OSStatus p12Decode(
const CSSM_DATA &pfx,
CSSM_CSP_HANDLE cspHand,
CFStringRef pwd,
bool verbose,
unsigned loops)
{
OSStatus ourRtn;
for(unsigned loop=0; loop<loops; loop++) {
{
P12Coder coder;
CFDataRef cfd = CFDataCreate(NULL, pfx.Data, pfx.Length);
ourRtn = noErr;
try {
coder.setCsp(cspHand);
coder.setMacPassPhrase(pwd);
coder.decode(cfd);
}
catch(...) {
printf("***decode error\n");
ourRtn = 1;
}
CFRelease(cfd);
try {
unsigned i;
unsigned numCerts = coder.numCerts();
printf("\n%u certs found\n", numCerts);
for(i=0; i<numCerts; i++) {
P12CertBag *cert = coder.getCert(i);
printf("=== Cert %u ===\n", i);
printBagAttrs(*cert);
if(verbose) {
CSSM_DATA &certData = cert->certData();
printCert(certData.Data, certData.Length,
CSSM_FALSE);
}
printf("\n");
}
unsigned numCrls = coder.numCrls();
printf("%u crls found\n", numCrls);
for(i=0; i<numCrls; i++) {
P12CrlBag *crl = coder.getCrl(i);
printf("=== Crl %u ===\n", i);
printBagAttrs(*crl);
if(verbose) {
CSSM_DATA &crlData = crl->crlData();
printCrl(crlData.Data, crlData.Length, CSSM_FALSE);
}
printf("\n");
}
unsigned numKeys = coder.numKeys();
printf("%u keys found\n", numKeys);
for(i=0; i<numKeys; i++) {
P12KeyBag *key = coder.getKey(i);
printf("\n=== Key %u ===\n", i);
printBagAttrs(*key);
CSSM_KEY_PTR ckey = key->key();
CSSM_KEYHEADER &hdr = ckey->KeyHeader;
printf(" Key Alg : ");
printAlgAsString(hdr.AlgorithmId);
printf(" Key Size : %u bits\n",
(unsigned)hdr.LogicalKeySizeInBits);
printf("\n");
}
unsigned numBlobs = coder.numOpaqueBlobs();
printf("%u blobs found\n", numBlobs);
}
catch(...) {
printf("***exception extracting fields\n");
ourRtn = 1;
}
}
if(loops > 1) {
fpurge(stdin);
printf("CR to continue: ");
getchar();
}
if(ourRtn) {
return ourRtn;
}
}
return ourRtn;
}
#else
static void printBagAttrs(
CFStringRef friendlyName,
CFDataRef localKeyId)
{
if(friendlyName) {
printf(" friendlyName : ");
printUcStr(friendlyName);
}
if(localKeyId) {
printf(" localKeyId : ");
printDataAsHex(localKeyId, 20);
}
if((friendlyName == NULL) && (localKeyId == NULL)) {
printf(" <no attributes found>\n");
}
}
static void releaseAttrs(
CFStringRef friendlyName,
CFDataRef localKeyId,
SecPkcs12AttrsRef attrs)
{
if(friendlyName) {
CFRelease(friendlyName);
}
if(localKeyId) {
CFRelease(localKeyId);
}
if(attrs) {
SecPkcs12AttrsRelease(attrs);
}
}
static void printOsError(
const char *op,
OSStatus ortn)
{
cssmPerror(op, ortn);
printf("\n");
}
#define GET_CERTS_WORKING 1
OSStatus p12Decode(
const CSSM_DATA &pfx,
CSSM_CSP_HANDLE cspHand,
CFStringRef pwd, bool usePassKey, bool verbose,
unsigned loops)
{
OSStatus ortn;
CSSM_KEY passKey;
CSSM_KEY_PTR passKeyPtr = NULL;
CFDataRef cfd = CFDataCreate(NULL, pfx.Data, pfx.Length);
if(usePassKey) {
ortn = p12GetPassKey(cspHand, GPK_Decode, true, &passKey);
if(ortn) {
return ortn;
}
passKeyPtr = &passKey;
}
for(unsigned loop=0; loop<loops; loop++) {
SecPkcs12CoderRef coder;
ortn = SecPkcs12CoderCreate(&coder);
if(ortn) {
printOsError("SecPkcs12CoderCreate", ortn);
return ortn;
}
ortn = SecPkcs12SetCspHandle(coder, cspHand);
if(ortn) {
printOsError("SecPkcs12SetCspHandle", ortn);
return ortn;
}
if(usePassKey) {
ortn = SecPkcs12SetMACPassKey(coder, passKeyPtr);
if(ortn) {
printOsError("SecPkcs12SetMACPassKey", ortn);
return ortn;
}
}
else {
ortn = SecPkcs12SetMACPassphrase(coder, pwd);
if(ortn) {
printOsError("SecPkcs12SetMACPassphrase", ortn);
return ortn;
}
}
ortn = SecPkcs12Decode(coder, cfd);
if(ortn) {
printOsError("SecPkcs12Decode", ortn);
return ortn;
}
CFIndex i;
CFStringRef fname;
CFDataRef keyId;
CFIndex numCerts;
SecPkcs12CertificateCount(coder, &numCerts);
printf("\n=== %ld certs found ===\n", numCerts);
#if GET_CERTS_WORKING
for(i=0; i<numCerts; i++) {
SecCertificateRef secCert;
ortn = SecPkcs12CopyCertificate(coder,
i,
&secCert,
&fname,
&keyId,
NULL); if(ortn) {
printOsError("SecPkcs12CopyCertificate", ortn);
return ortn;
}
printf("Cert %ld:\n", i);
printBagAttrs(fname, keyId);
if(verbose) {
CSSM_DATA certData;
ortn = SecCertificateGetData(secCert, &certData);
if(ortn) {
printOsError("SecCertificateGetData", ortn);
return ortn;
}
printCert(certData.Data, certData.Length,
CSSM_FALSE);
}
releaseAttrs(fname, keyId, NULL);
CFRelease(secCert);
printf("\n");
}
#endif
CFIndex numCrls;
SecPkcs12CrlCount(coder, &numCrls);
printf("=== %ld crls found ===\n", numCrls);
for(i=0; i<numCrls; i++) {
CFDataRef crl;
ortn = SecPkcs12CopyCrl(coder,
i,
&crl,
&fname,
&keyId,
NULL); if(ortn) {
printOsError("SecPkcs12CopyCrl", ortn);
return ortn;
}
printf("Crl %ld:\n", i);
printBagAttrs(fname, keyId);
if(verbose) {
const CSSM_DATA crlData = {
CFDataGetLength(crl),
(uint8 *)CFDataGetBytePtr(crl) };
printCrl(crlData.Data, crlData.Length, CSSM_FALSE);
}
releaseAttrs(fname, keyId, NULL);
CFRelease(crl);
printf("\n");
}
CFIndex numKeys;
SecPkcs12PrivateKeyCount(coder, &numKeys);
printf("=== %ld keys found ===\n", numKeys);
for(i=0; i<numKeys; i++) {
CSSM_KEY_PTR key;
ortn = SecPkcs12GetCssmPrivateKey(coder,
i,
&key,
&fname,
&keyId,
NULL);
printf("Key %ld:\n", i);
printBagAttrs(fname, keyId);
CSSM_KEYHEADER &hdr = key->KeyHeader;
printf(" Key Alg : ");
printAlgAsString(hdr.AlgorithmId);
printf(" Key Size : %u bits\n",
(unsigned)hdr.LogicalKeySizeInBits);
printf("\n");
releaseAttrs(fname, keyId, NULL);
}
CFIndex numBlobs;
SecPkcs12OpaqueBlobCount(coder, &numBlobs);
if(numBlobs != 0) {
printf("%ld blobs found\n", numBlobs);
}
SecPkcs12CoderRelease(coder);
if(loops > 1) {
fpurge(stdin);
printf("CR to continue: ");
getchar();
}
}
return 0;
}
#endif