pkinit_apple_utils.c [plain text]
#include "pkinit_apple_utils.h"
#include "pkinit_asn1.h"
#include <sys/errno.h>
#include <assert.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <ctype.h>
#include <Security/Security.h>
static CSSM_VERSION vers = {2, 0};
static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }};
static void * cuAppMalloc (uint32 size, void *allocRef) {
return( malloc(size) );
}
static void cuAppFree (void *mem_ptr, void *allocRef) {
free(mem_ptr);
return;
}
static void * cuAppRealloc (void *ptr, uint32 size, void *allocRef) {
return( realloc( ptr, size ) );
}
static void * cuAppCalloc (uint32 num, uint32 size, void *allocRef) {
return( calloc( num, size ) );
}
static CSSM_API_MEMORY_FUNCS memFuncs = {
cuAppMalloc,
cuAppFree,
cuAppRealloc,
cuAppCalloc,
NULL
};
static CSSM_BOOL cssmInitd = CSSM_FALSE;
static CSSM_BOOL cuCssmStartup()
{
CSSM_RETURN crtn;
CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
if(cssmInitd) {
return CSSM_TRUE;
}
crtn = CSSM_Init (&vers,
CSSM_PRIVILEGE_SCOPE_NONE,
&testGuid,
CSSM_KEY_HIERARCHY_NONE,
&pvcPolicy,
NULL );
if(crtn != CSSM_OK)
{
return CSSM_FALSE;
}
else {
cssmInitd = CSSM_TRUE;
return CSSM_TRUE;
}
}
static CSSM_CL_HANDLE cuClStartup()
{
CSSM_CL_HANDLE clHand;
CSSM_RETURN crtn;
if(cuCssmStartup() == CSSM_FALSE) {
return 0;
}
crtn = CSSM_ModuleLoad(&gGuidAppleX509CL,
CSSM_KEY_HIERARCHY_NONE,
NULL, NULL); if(crtn) {
return 0;
}
crtn = CSSM_ModuleAttach (&gGuidAppleX509CL,
&vers,
&memFuncs, 0, CSSM_SERVICE_CL, 0, CSSM_KEY_HIERARCHY_NONE,
NULL, 0, NULL, &clHand);
if(crtn) {
return 0;
}
else {
return clHand;
}
}
static CSSM_RETURN cuClDetachUnload(
CSSM_CL_HANDLE clHand)
{
CSSM_RETURN crtn = CSSM_ModuleDetach(clHand);
if(crtn) {
return crtn;
}
return CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL);
}
int pkiDataToInt(
const CSSM_DATA *cdata,
krb5_int32 *i)
{
krb5_ui_4 len;
krb5_int32 rtn = 0;
krb5_ui_4 dex;
if((cdata->Length == 0) || (cdata->Data == NULL)) {
*i = 0;
return 0;
}
len = cdata->Length;
if(len > sizeof(krb5_int32)) {
return -1;
}
uint8 *cp = cdata->Data;
for(dex=0; dex<len; dex++) {
rtn = (rtn << 8) | *cp++;
}
*i = rtn;
return 0;
}
int pkiIntToData(
krb5_int32 num,
CSSM_DATA *cdata,
SecAsn1CoderRef coder)
{
krb5_ui_4 unum = (krb5_ui_4)num;
uint32 len = 0;
uint8 *cp = NULL;
unsigned i;
if(unum < 0x100) {
len = 1;
}
else if(unum < 0x10000) {
len = 2;
}
else if(unum < 0x1000000) {
len = 3;
}
else {
len = 4;
}
if(SecAsn1AllocItem(coder, cdata, len)) {
return ENOMEM;
}
cp = &cdata->Data[len - 1];
for(i=0; i<len; i++) {
*cp-- = unum & 0xff;
unum >>= 8;
}
return 0;
}
int pkiDataToKrb5Data(
const void *data,
unsigned dataLen,
krb5_data *kd)
{
assert(data != NULL);
assert(kd != NULL);
kd->data = (char *)malloc(dataLen);
if(kd->data == NULL) {
return ENOMEM;
}
kd->length = dataLen;
memmove(kd->data, data, dataLen);
return 0;
}
int pkiCssmDataToKrb5Data(
const CSSM_DATA *cd,
krb5_data *kd)
{
assert(cd != NULL);
return pkiDataToKrb5Data(cd->Data, cd->Length, kd);
}
int pkiKrb5DataToCssm(
const krb5_data *kd,
CSSM_DATA *cd,
SecAsn1CoderRef coder)
{
assert((cd != NULL) && (kd != NULL));
return SecAsn1AllocCopy(coder, kd->data, kd->length, cd);
}
krb5_boolean pkiCompareCssmData(
const CSSM_DATA *d1,
const CSSM_DATA *d2)
{
if((d1 == NULL) || (d2 == NULL)) {
return FALSE;
}
if(d1->Length != d2->Length) {
return FALSE;
}
if(memcmp(d1->Data, d2->Data, d1->Length)) {
return FALSE;
}
else {
return TRUE;
}
}
int pkiKrbTimestampToStr(
krb5_timestamp kts,
char **str) {
time_t gmt_time = kts;
struct tm *utc = gmtime(&gmt_time);
if (utc == NULL ||
utc->tm_year > 8099 || utc->tm_mon > 11 ||
utc->tm_mday > 31 || utc->tm_hour > 23 ||
utc->tm_min > 59 || utc->tm_sec > 59) {
return ASN1_BAD_GMTIME;
}
char *outStr = (char *)malloc(16);
sprintf(outStr, "%04d%02d%02d%02d%02d%02dZ",
utc->tm_year + 1900, utc->tm_mon + 1,
utc->tm_mday, utc->tm_hour, utc->tm_min, utc->tm_sec);
*str = outStr;
return 0;
}
int pkiTimeStrToKrbTimestamp(
const char *str,
unsigned len,
krb5_timestamp *kts) {
char szTemp[5];
unsigned x;
unsigned i;
char *cp;
struct tm tmp;
time_t t;
if(len != 15) {
return ASN1_BAD_LENGTH;
}
if((str == NULL) || (kts == NULL)) {
return -1;
}
cp = (char *)str;
memset(&tmp, 0, sizeof(tmp));
for(i=0; i<(len - 1); i++) {
if ( !(isdigit(cp[i])) ) {
return ASN1_BAD_TIMEFORMAT;
}
}
if(cp[len - 1] != 'Z' ) {
return ASN1_BAD_TIMEFORMAT;
}
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = *cp++;
szTemp[3] = *cp++;
szTemp[4] = '\0';
x = atoi( szTemp );
tmp.tm_year = x - 1900;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 12) || (x <= 0)) {
return ASN1_BAD_TIMEFORMAT;
}
tmp.tm_mon = x - 1;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 31) || (x <= 0)) {
return ASN1_BAD_TIMEFORMAT;
}
tmp.tm_mday = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 23) || (x < 0)) {
return ASN1_BAD_TIMEFORMAT;
}
tmp.tm_hour = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 59) || (x < 0)) {
return ASN1_BAD_TIMEFORMAT;
}
tmp.tm_min = x;
szTemp[0] = *cp++;
szTemp[1] = *cp++;
szTemp[2] = '\0';
x = atoi( szTemp );
if((x > 59) || (x < 0)) {
return ASN1_BAD_TIMEFORMAT;
}
tmp.tm_sec = x;
t = timegm(&tmp);
if(t == -1) {
return ASN1_BAD_TIMEFORMAT;
}
*kts = t;
return 0;
}
krb5_error_code pkiOsStatusToKrbErr(
OSStatus ortn)
{
return (krb5_error_code)ortn;
}
krb5_error_code pkiGetIssuerAndSerial(
const krb5_data *cert,
krb5_data *issuer_and_serial)
{
CSSM_HANDLE cacheHand = 0;
CSSM_RETURN crtn = CSSM_OK;
CSSM_DATA certData = { cert->length, (uint8 *)cert->data };
CSSM_HANDLE resultHand = 0;
CSSM_DATA_PTR derIssuer = NULL;
CSSM_DATA_PTR serial;
krb5_data krb_serial;
krb5_data krb_issuer;
uint32 numFields;
CSSM_CL_HANDLE clHand = cuClStartup();
if(clHand == 0) {
return CSSMERR_CSSM_ADDIN_LOAD_FAILED;
}
crtn = CSSM_CL_CertCache(clHand, &certData, &cacheHand);
if(crtn) {
pkiCssmErr("CSSM_CL_CertCache", crtn);
goto errOut;
}
crtn = CSSM_CL_CertGetFirstCachedFieldValue(clHand, cacheHand,
&CSSMOID_X509V1IssuerNameStd, &resultHand, &numFields, &derIssuer);
if(crtn) {
pkiCssmErr("CSSM_CL_CertGetFirstCachedFieldValue(issuer)", crtn);
goto errOut;
}
crtn = CSSM_CL_CertGetFirstCachedFieldValue(clHand, cacheHand,
&CSSMOID_X509V1SerialNumber, &resultHand, &numFields, &serial);
if(crtn) {
pkiCssmErr("CSSM_CL_CertGetFirstCachedFieldValue(serial)", crtn);
goto errOut;
}
PKI_CSSM_TO_KRB_DATA(derIssuer, &krb_issuer);
PKI_CSSM_TO_KRB_DATA(serial, &krb_serial);
crtn = pkinit_issuer_serial_encode(&krb_issuer, &krb_serial, issuer_and_serial);
errOut:
if(derIssuer) {
CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1IssuerNameStd, derIssuer);
}
if(serial) {
CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SerialNumber, serial);
}
if(cacheHand) {
CSSM_CL_CertAbortCache(clHand, cacheHand);
}
if(clHand) {
cuClDetachUnload(clHand);
}
return crtn;
}
unsigned pkiNssArraySize(
const void **array)
{
unsigned count = 0;
if (array) {
while (*array++) {
count++;
}
}
return count;
}