2 * Copyright (c) 2003-2004,2006,2009-2017 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 * trusted_cert_utils.c
26 #include "trusted_cert_utils.h"
27 #include <Security/SecPolicyPriv.h>
28 #include <Security/SecBasePriv.h>
29 #include <Security/SecTrust.h>
30 #include <Security/SecTrustSettings.h>
31 #include <Security/cssmapple.h>
32 #include <Security/oidsalg.h>
33 #include <utilities/fileIo.h>
34 #include <security_cdsa_utils/cuPem.h>
36 static int indentSize
= 0;
37 void indentIncr(void) { indentSize
+= 3; }
38 void indentDecr(void) { indentSize
-= 3; }
47 for (dex
=0; dex
<indentSize
; dex
++) {
57 bool doEllipsis
= false;
63 for(dex
=0; dex
<len
; dex
++) {
79 const unsigned char *buf
,
83 bool doEllipsis
= false;
89 for(dex
=0; dex
<len
; dex
++) {
90 printf("%02X ", *buf
++);
97 /* print the contents of a CFString */
101 CFDataRef strData
= CFStringCreateExternalRepresentation(NULL
, cfstr
,
102 kCFStringEncodingUTF8
, true);
105 if(strData
== NULL
) {
106 printf("<<string decode error>>");
109 const char *cp
= (const char *)CFDataGetBytePtr(strData
);
110 CFIndex len
= CFDataGetLength(strData
);
111 for(dex
=0; dex
<len
; dex
++) {
117 /* print a CFDateRef */
118 static const char *months
[12] = {
119 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
120 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
126 CFAbsoluteTime absTime
= CFDateGetAbsoluteTime(dateRef
);
128 printf("<<Malformed CFDateeRef>>\n");
131 CFGregorianDate gregDate
= CFAbsoluteTimeGetGregorianDate(absTime
, NULL
);
132 const char *month
= "Unknown";
133 if((gregDate
.month
> 12) || (gregDate
.month
<= 0)) {
134 printf("Huh? GregDate.month > 11. These amps only GO to 11.\n");
137 month
= months
[gregDate
.month
- 1];
139 printf("%s %d, %d %02d:%02d",
140 month
, gregDate
.day
, (int)gregDate
.year
, gregDate
.hour
, gregDate
.minute
);
143 /* print a CFNumber */
148 if(!CFNumberGetValue(cfNum
, kCFNumberSInt32Type
, &s
)) {
149 printf("***CFNumber overflow***");
152 printf("%d", (int)s
);
155 /* print a CFNumber as a SecTrustSettingsResult */
156 void printResultType(
160 if(!CFNumberGetValue(cfNum
, kCFNumberSInt32Type
, &n
)) {
161 printf("***CFNumber overflow***");
167 case kSecTrustSettingsResultInvalid
: s
= "kSecTrustSettingsResultInvalid"; break;
168 case kSecTrustSettingsResultTrustRoot
: s
= "kSecTrustSettingsResultTrustRoot"; break;
169 case kSecTrustSettingsResultTrustAsRoot
: s
= "kSecTrustSettingsResultTrustAsRoot"; break;
170 case kSecTrustSettingsResultDeny
: s
= "kSecTrustSettingsResultDeny"; break;
171 case kSecTrustSettingsResultUnspecified
: s
= "kSecTrustSettingsResultUnspecified"; break;
173 sprintf(bogus
, "Unknown SecTrustSettingsResult (%d)", (int)n
);
180 /* print a CFNumber as SecTrustSettingsKeyUsage */
185 if(!CFNumberGetValue(cfNum
, kCFNumberSInt32Type
, &s
)) {
186 printf("***CFNumber overflow***");
189 uint32 n
= (uint32
)s
;
190 if(n
== kSecTrustSettingsKeyUseAny
) {
199 if(n
& kSecTrustSettingsKeyUseSignature
) {
200 printf("Signature ");
202 if(n
& kSecTrustSettingsKeyUseEnDecryptData
) {
203 printf("EnDecryptData ");
205 if(n
& kSecTrustSettingsKeyUseEnDecryptKey
) {
206 printf("EnDecryptKey ");
208 if(n
& kSecTrustSettingsKeyUseSignCert
) {
211 if(n
& kSecTrustSettingsKeyUseSignRevocation
) {
212 printf("SignRevocation ");
214 if(n
& kSecTrustSettingsKeyUseKeyExchange
) {
215 printf("KeyExchange ");
220 /* print a CFNumber as CSSM_RETURN string */
225 if(!CFNumberGetValue(cfNum
, kCFNumberSInt32Type
, &s
)) {
226 printf("***CFNumber overflow***");
229 printf("%s", cssmErrorString((CSSM_RETURN
)s
));
232 /* convert an OID to a SecPolicyRef */
233 SecPolicyRef
oidToPolicy(
237 SecPolicyRef policyRef
= NULL
;
239 ortn
= SecPolicyCopy(CSSM_CERT_X_509v3
, oid
, &policyRef
);
241 cssmPerror("SecPolicyCopy", ortn
);
252 static OidString oidStrings
[] =
254 { &CSSMOID_APPLE_ISIGN
, "iSign" },
255 { &CSSMOID_APPLE_X509_BASIC
, "Apple X509 Basic" },
256 { &CSSMOID_APPLE_TP_SSL
, "SSL" },
257 { &CSSMOID_APPLE_TP_SMIME
, "SMIME" },
258 { &CSSMOID_APPLE_TP_EAP
, "EAP" },
259 { &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING
, "SW Update Signing" },
260 { &CSSMOID_APPLE_TP_IP_SEC
, "IPSec" },
261 { &CSSMOID_APPLE_TP_ICHAT
, "iChat" },
262 { &CSSMOID_APPLE_TP_RESOURCE_SIGN
, "Resource Signing" },
263 { &CSSMOID_APPLE_TP_PKINIT_CLIENT
, "PKINIT Client" },
264 { &CSSMOID_APPLE_TP_PKINIT_SERVER
, "PKINIT Server" },
265 { &CSSMOID_APPLE_TP_CODE_SIGNING
, "Code Signing" },
266 { &CSSMOID_APPLE_TP_PACKAGE_SIGNING
, "Package Signing" },
267 { &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT
, "Mac App Store" },
268 { &CSSMOID_APPLE_TP_APPLEID_SHARING
, "AppleID Sharing" }
270 #define NUM_OID_STRINGS (sizeof(oidStrings) / sizeof(oidStrings[0]))
272 /* convert a policy string to a SecPolicyRef */
273 SecPolicyRef
oidStringToPolicy(
276 /* OID string to an OID pointer */
277 const CSSM_OID
*oid
= NULL
;
280 for(dex
=0; dex
<NUM_OID_STRINGS
; dex
++) {
281 OidString
*os
= &oidStrings
[dex
];
282 if(!strcmp(oidStr
, os
->oidStr
)) {
291 /* OID to SecPolicyRef */
292 return oidToPolicy(oid
);
295 /* CSSM_OID --> OID string */
296 const char *oidToOidString(
300 static char unknownOidString
[200];
302 for(dex
=0; dex
<NUM_OID_STRINGS
; dex
++) {
303 OidString
*os
= &oidStrings
[dex
];
304 if(compareOids(oid
, os
->oid
)) {
308 sprintf(unknownOidString
, "Unknown OID length %ld, value { ", oid
->Length
);
309 for(dex
=0; dex
<oid
->Length
; dex
++) {
311 sprintf(tmp
, "%02X ", oid
->Data
[dex
]);
312 strcat(unknownOidString
, tmp
);
314 strcat(unknownOidString
, " }");
315 return unknownOidString
;
318 /* compare OIDs; returns 1 if identical, else returns 0 */
320 const CSSM_OID
*oid1
,
321 const CSSM_OID
*oid2
)
323 if((oid1
== NULL
) || (oid2
== NULL
)) {
326 if(oid1
->Length
!= oid2
->Length
) {
329 if(memcmp(oid1
->Data
, oid2
->Data
, oid1
->Length
)) {
335 /* app path string to SecTrustedApplicationRef */
336 SecTrustedApplicationRef
appPathToAppRef(
339 SecTrustedApplicationRef appRef
= NULL
;
342 if(appPath
== NULL
) {
345 ortn
= SecTrustedApplicationCreateFromPath(appPath
, &appRef
);
347 cssmPerror("SecTrustedApplicationCreateFromPath", ortn
);
354 const char *fileName
,
355 SecCertificateRef
*certRef
)
357 unsigned char *cp
= NULL
;
361 unsigned char *decoded
= NULL
;
362 unsigned decodedLen
= 0;
364 if(readFileSizet(fileName
, &cp
, &len
)) {
365 printf("***Error reading file %s\n", fileName
);
368 if(isPem(cp
, (unsigned) len
)) {
369 if(pemDecode(cp
, (unsigned) len
, &decoded
, &decodedLen
)) {
370 fprintf(stderr
, "Error decoding cert file %s\n", fileName
);
373 certData
.Length
= decodedLen
;
374 certData
.Data
= decoded
;
377 certData
.Length
= len
;
380 ortn
= SecCertificateCreateFromData(&certData
,
381 CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, certRef
);
387 cssmPerror("SecCertificateCreateFromData", ortn
);
393 /* policy string --> CSSM_OID */
394 const CSSM_OID
*policyStringToOid(
400 if(!strcmp(policy
, "ssl")) {
401 return &CSSMOID_APPLE_TP_SSL
;
403 else if(!strcmp(policy
, "smime")) {
404 return &CSSMOID_APPLE_TP_SMIME
;
406 else if(!strcmp(policy
, "codeSign")) {
407 return &CSSMOID_APPLE_TP_CODE_SIGNING
;
409 else if(!strcmp(policy
, "IPSec")) {
410 return &CSSMOID_APPLE_TP_IP_SEC
;
412 else if(!strcmp(policy
, "basic")) {
413 return &CSSMOID_APPLE_X509_BASIC
;
415 else if(!strcmp(policy
, "swUpdate")) {
416 return &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING
;
418 else if(!strcmp(policy
, "pkgSign")) {
419 return &CSSMOID_APPLE_TP_PACKAGE_SIGNING
;
421 else if(!strcmp(policy
, "eap")) {
422 return &CSSMOID_APPLE_TP_EAP
;
424 else if(!strcmp(policy
, "macappstore")) {
425 return &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT
;
427 else if(!strcmp(policy
, "appleID")) {
428 return &CSSMOID_APPLE_TP_APPLEID_SHARING
;
430 else if(!strcmp(policy
, "timestamping")) {
431 return &CSSMOID_APPLE_TP_TIMESTAMPING
;
434 fprintf(stderr
, "***unknown policy spec (%s)\n", policy
);
439 CFOptionFlags
revCheckOptionStringToFlags(
440 const char *revCheckOption
)
442 CFOptionFlags result
= 0;
443 if(revCheckOption
== NULL
) {
446 else if(!strcmp(revCheckOption
, "ocsp")) {
447 result
|= kSecRevocationOCSPMethod
;
449 else if(!strcmp(revCheckOption
, "crl")) {
450 result
|= kSecRevocationCRLMethod
;
452 else if(!strcmp(revCheckOption
, "require")) {
453 result
|= kSecRevocationRequirePositiveResponse
;
455 else if(!strcmp(revCheckOption
, "offline")) {
456 result
|= kSecRevocationNetworkAccessDisabled
;
458 else if(!strcmp(revCheckOption
, "online")) {
459 result
|= kSecRevocationOnlineCheck
;