1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
3 * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved.
5 * Export of this software from the United States of America may require
6 * a specific license from the United States Government. It is the
7 * responsibility of any person or organization contemplating export to
8 * obtain such a license before exporting.
10 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
11 * distribute this software and its documentation for any purpose and
12 * without fee is hereby granted, provided that the above copyright
13 * notice appear in all copies and that both that copyright notice and
14 * this permission notice appear in supporting documentation, and that
15 * the name of Apple Inc. not be used in advertising or publicity pertaining
16 * to distribution of the software without specific, written prior
17 * permission. Apple Inc. makes no representations about the suitability of
18 * this software for any purpose. It is provided "as is" without express
19 * or implied warranty.
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
23 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28 * pkinit_apple_utils.c - PKINIT utilities, Mac OS X version
30 * Created 19 May 2004 by Doug Mitchell at Apple.
35 #include "pkinit_apple_utils.h"
36 #include "pkinit_asn1.h"
37 #include <sys/errno.h>
43 #include <Security/Security.h>
46 * Cruft needed to attach to a module
48 static CSSM_VERSION vers = {2, 0};
49 static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }};
52 * Standard app-level memory functions required by CDSA.
54 static void * cuAppMalloc (CSSM_SIZE size, void *allocRef) {
55 return( malloc(size) );
58 static void cuAppFree (void *mem_ptr, void *allocRef) {
63 static void * cuAppRealloc (void *ptr, CSSM_SIZE size, void *allocRef) {
64 return( realloc( ptr, size ) );
67 static void * cuAppCalloc (uint32 num, CSSM_SIZE size, void *allocRef) {
68 return( calloc( num, size ) );
71 static CSSM_API_MEMORY_FUNCS memFuncs = {
80 * Init CSSM; returns CSSM_FALSE on error. Reusable.
82 static CSSM_BOOL cssmInitd = CSSM_FALSE;
84 static CSSM_BOOL cuCssmStartup()
87 CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
92 crtn = CSSM_Init (&vers,
93 CSSM_PRIVILEGE_SCOPE_NONE,
95 CSSM_KEY_HIERARCHY_NONE,
103 cssmInitd = CSSM_TRUE;
108 CSSM_CL_HANDLE pkiClStartup(void)
110 CSSM_CL_HANDLE clHand;
113 if(cuCssmStartup() == CSSM_FALSE) {
116 crtn = CSSM_ModuleLoad(&gGuidAppleX509CL,
117 CSSM_KEY_HIERARCHY_NONE,
118 NULL, /* eventHandler */
119 NULL); /* AppNotifyCallbackCtx */
123 crtn = CSSM_ModuleAttach (&gGuidAppleX509CL,
125 &memFuncs, /* memFuncs */
126 0, /* SubserviceID */
127 CSSM_SERVICE_CL, /* SubserviceFlags - Where is this used? */
129 CSSM_KEY_HIERARCHY_NONE,
130 NULL, /* FunctionTable */
131 0, /* NumFuncTable */
142 CSSM_RETURN pkiClDetachUnload(
143 CSSM_CL_HANDLE clHand)
145 CSSM_RETURN crtn = CSSM_ModuleDetach(clHand);
149 return CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL);
153 * CSSM_DATA <--> krb5_ui_4
155 krb5_error_code pkiDataToInt(
156 const CSSM_DATA *cdata,
157 krb5_int32 *i) /* RETURNED */
164 if((cdata->Length == 0) || (cdata->Data == NULL)) {
169 if(len > sizeof(krb5_int32)) {
170 return ASN1_BAD_LENGTH;
174 for(dex=0; dex<len; dex++) {
175 rtn = (rtn << 8) | *cp++;
181 krb5_error_code pkiIntToData(
184 SecAsn1CoderRef coder)
186 krb5_ui_4 unum = (krb5_ui_4)num;
194 else if(unum < 0x10000) {
197 else if(unum < 0x1000000) {
203 if(SecAsn1AllocItem(coder, cdata, len)) {
206 cp = &cdata->Data[len - 1];
207 for(i=0; i<len; i++) {
215 * raw data --> krb5_data
217 krb5_error_code pkiDataToKrb5Data(
222 assert(data != NULL);
224 kd->data = (char *)malloc(dataLen);
225 if(kd->data == NULL) {
228 kd->length = dataLen;
229 memmove(kd->data, data, dataLen);
234 * CSSM_DATA <--> krb5_data
236 * CSSM_DATA data is managed by a SecAsn1CoderRef; krb5_data data is mallocd.
238 * Both return nonzero on error.
240 krb5_error_code pkiCssmDataToKrb5Data(
245 return pkiDataToKrb5Data(cd->Data, cd->Length, kd);
248 krb5_error_code pkiKrb5DataToCssm(
251 SecAsn1CoderRef coder)
253 assert((cd != NULL) && (kd != NULL));
254 if(SecAsn1AllocCopy(coder, kd->data, kd->length, cd)) {
261 * CFDataRef --> krb5_data, mallocing the destination contents.
263 krb5_error_code pkiCfDataToKrb5Data(
265 krb5_data *kd) /* content mallocd and RETURNED */
267 return pkiDataToKrb5Data(CFDataGetBytePtr(cfData),
268 CFDataGetLength(cfData), kd);
271 krb5_boolean pkiCompareCssmData(
275 if((d1 == NULL) || (d2 == NULL)) {
278 if(d1->Length != d2->Length) {
281 if(memcmp(d1->Data, d2->Data, d1->Length)) {
290 * krb5_timestamp --> a mallocd string in generalized format
292 krb5_error_code pkiKrbTimestampToStr(
294 char **str) /* mallocd and RETURNED */
297 time_t gmt_time = kts;
298 struct tm *utc = gmtime(&gmt_time);
300 utc->tm_year > 8099 || utc->tm_mon > 11 ||
301 utc->tm_mday > 31 || utc->tm_hour > 23 ||
302 utc->tm_min > 59 || utc->tm_sec > 59) {
303 return ASN1_BAD_GMTIME;
305 if (asprintf(&outStr, "%04d%02d%02d%02d%02d%02dZ",
306 utc->tm_year + 1900, utc->tm_mon + 1,
307 utc->tm_mday, utc->tm_hour, utc->tm_min, utc->tm_sec) < 0) {
314 krb5_error_code pkiTimeStrToKrbTimestamp(
317 krb5_timestamp *kts) /* RETURNED */
327 return ASN1_BAD_LENGTH;
330 if((str == NULL) || (kts == NULL)) {
331 return KRB5_CRYPTO_INTERNAL;
335 memset(&tmp, 0, sizeof(tmp));
337 /* check that all characters except last are digits */
338 for(i=0; i<(len - 1); i++) {
339 if ( !(isdigit(cp[i])) ) {
340 return ASN1_BAD_TIMEFORMAT;
344 /* check last character is a 'Z' */
345 if(cp[len - 1] != 'Z' ) {
346 return ASN1_BAD_TIMEFORMAT;
356 /* by definition - tm_year is year - 1900 */
357 tmp.tm_year = x - 1900;
364 /* in the string, months are from 1 to 12 */
365 if((x > 12) || (x <= 0)) {
366 return ASN1_BAD_TIMEFORMAT;
368 /* in a tm, 0 to 11 */
377 if((x > 31) || (x <= 0)) {
378 return ASN1_BAD_TIMEFORMAT;
387 if((x > 23) || (x < 0)) {
388 return ASN1_BAD_TIMEFORMAT;
397 if((x > 59) || (x < 0)) {
398 return ASN1_BAD_TIMEFORMAT;
407 if((x > 59) || (x < 0)) {
408 return ASN1_BAD_TIMEFORMAT;
413 return ASN1_BAD_TIMEFORMAT;
420 * How many items in a NULL-terminated array of pointers?
422 unsigned pkiNssArraySize(
434 #endif /* APPLE_PKINIT */