]> git.saurik.com Git - apple/security.git/blob - SecurityTool/trusted_cert_utils.c
Security-58286.270.3.0.1.tar.gz
[apple/security.git] / SecurityTool / trusted_cert_utils.c
1 /*
2 * Copyright (c) 2003-2004,2006,2009-2017 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 *
23 * trusted_cert_utils.c
24 */
25
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>
35
36 static int indentSize = 0;
37 void indentIncr(void) { indentSize += 3; }
38 void indentDecr(void) { indentSize -= 3; }
39
40 void indent(void)
41 {
42 int dex;
43 if(indentSize < 0) {
44 /* bug */
45 indentSize = 0;
46 }
47 for (dex=0; dex<indentSize; dex++) {
48 putchar(' ');
49 }
50 }
51
52 void printAscii(
53 const char *buf,
54 unsigned len,
55 unsigned maxLen)
56 {
57 bool doEllipsis = false;
58 unsigned dex;
59 if(len > maxLen) {
60 len = maxLen;
61 doEllipsis = true;
62 }
63 for(dex=0; dex<len; dex++) {
64 char c = *buf++;
65 if(isalnum(c)) {
66 putchar(c);
67 }
68 else {
69 putchar('.');
70 }
71 fflush(stdout);
72 }
73 if(doEllipsis) {
74 printf("...etc.");
75 }
76 }
77
78 void printHex(
79 const unsigned char *buf,
80 unsigned len,
81 unsigned maxLen)
82 {
83 bool doEllipsis = false;
84 unsigned dex;
85 if(len > maxLen) {
86 len = maxLen;
87 doEllipsis = true;
88 }
89 for(dex=0; dex<len; dex++) {
90 printf("%02X ", *buf++);
91 }
92 if(doEllipsis) {
93 printf("...etc.");
94 }
95 }
96
97 /* print the contents of a CFString */
98 void printCfStr(
99 CFStringRef cfstr)
100 {
101 CFDataRef strData = CFStringCreateExternalRepresentation(NULL, cfstr,
102 kCFStringEncodingUTF8, true);
103 CFIndex dex;
104
105 if(strData == NULL) {
106 printf("<<string decode error>>");
107 return;
108 }
109 const char *cp = (const char *)CFDataGetBytePtr(strData);
110 CFIndex len = CFDataGetLength(strData);
111 for(dex=0; dex<len; dex++) {
112 putchar(*cp++);
113 }
114 CFRelease(strData);
115 }
116
117 /* print a CFDateRef */
118 static const char *months[12] = {
119 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
120 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
121 };
122
123 void printCFDate(
124 CFDateRef dateRef)
125 {
126 CFAbsoluteTime absTime = CFDateGetAbsoluteTime(dateRef);
127 if(absTime == 0.0) {
128 printf("<<Malformed CFDateeRef>>\n");
129 return;
130 }
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");
135 }
136 else {
137 month = months[gregDate.month - 1];
138 }
139 printf("%s %d, %d %02d:%02d",
140 month, gregDate.day, (int)gregDate.year, gregDate.hour, gregDate.minute);
141 }
142
143 /* print a CFNumber */
144 void printCfNumber(
145 CFNumberRef cfNum)
146 {
147 SInt32 s;
148 if(!CFNumberGetValue(cfNum, kCFNumberSInt32Type, &s)) {
149 printf("***CFNumber overflow***");
150 return;
151 }
152 printf("%d", (int)s);
153 }
154
155 /* print a CFNumber as a SecTrustSettingsResult */
156 void printResultType(
157 CFNumberRef cfNum)
158 {
159 SInt32 n;
160 if(!CFNumberGetValue(cfNum, kCFNumberSInt32Type, &n)) {
161 printf("***CFNumber overflow***");
162 return;
163 }
164 const char *s;
165 char bogus[100];
166 switch(n) {
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;
172 default:
173 sprintf(bogus, "Unknown SecTrustSettingsResult (%d)", (int)n);
174 s = bogus;
175 break;
176 }
177 printf("%s", s);
178 }
179
180 /* print a CFNumber as SecTrustSettingsKeyUsage */
181 void printKeyUsage(
182 CFNumberRef cfNum)
183 {
184 SInt32 s;
185 if(!CFNumberGetValue(cfNum, kCFNumberSInt32Type, &s)) {
186 printf("***CFNumber overflow***");
187 return;
188 }
189 uint32 n = (uint32)s;
190 if(n == kSecTrustSettingsKeyUseAny) {
191 printf("<any>");
192 return;
193 }
194 else if(n == 0) {
195 printf("<none>");
196 return;
197 }
198 printf("< ");
199 if(n & kSecTrustSettingsKeyUseSignature) {
200 printf("Signature ");
201 }
202 if(n & kSecTrustSettingsKeyUseEnDecryptData) {
203 printf("EnDecryptData ");
204 }
205 if(n & kSecTrustSettingsKeyUseEnDecryptKey) {
206 printf("EnDecryptKey ");
207 }
208 if(n & kSecTrustSettingsKeyUseSignCert) {
209 printf("SignCert ");
210 }
211 if(n & kSecTrustSettingsKeyUseSignRevocation) {
212 printf("SignRevocation ");
213 }
214 if(n & kSecTrustSettingsKeyUseKeyExchange) {
215 printf("KeyExchange ");
216 }
217 printf(" >");
218 }
219
220 /* print a CFNumber as CSSM_RETURN string */
221 void printCssmErr(
222 CFNumberRef cfNum)
223 {
224 SInt32 s;
225 if(!CFNumberGetValue(cfNum, kCFNumberSInt32Type, &s)) {
226 printf("***CFNumber overflow***");
227 return;
228 }
229 printf("%s", cssmErrorString((CSSM_RETURN)s));
230 }
231
232 /* convert an OID to a SecPolicyRef */
233 SecPolicyRef oidToPolicy(
234 const CSSM_OID *oid)
235 {
236 OSStatus ortn;
237 SecPolicyRef policyRef = NULL;
238
239 ortn = SecPolicyCopy(CSSM_CERT_X_509v3, oid, &policyRef);
240 if(ortn) {
241 cssmPerror("SecPolicyCopy", ortn);
242 return NULL;
243 }
244 return policyRef;
245 }
246
247 typedef struct {
248 const CSSM_OID *oid;
249 const char *oidStr;
250 } OidString;
251
252 static OidString oidStrings[] =
253 {
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" }
269 };
270 #define NUM_OID_STRINGS (sizeof(oidStrings) / sizeof(oidStrings[0]))
271
272 /* convert a policy string to a SecPolicyRef */
273 SecPolicyRef oidStringToPolicy(
274 const char *oidStr)
275 {
276 /* OID string to an OID pointer */
277 const CSSM_OID *oid = NULL;
278 unsigned dex;
279
280 for(dex=0; dex<NUM_OID_STRINGS; dex++) {
281 OidString *os = &oidStrings[dex];
282 if(!strcmp(oidStr, os->oidStr)) {
283 oid = os->oid;
284 break;
285 }
286 }
287 if(oid == NULL) {
288 return NULL;
289 }
290
291 /* OID to SecPolicyRef */
292 return oidToPolicy(oid);
293 }
294
295 /* CSSM_OID --> OID string */
296 const char *oidToOidString(
297 const CSSM_OID *oid)
298 {
299 unsigned dex;
300 static char unknownOidString[200];
301
302 for(dex=0; dex<NUM_OID_STRINGS; dex++) {
303 OidString *os = &oidStrings[dex];
304 if(compareOids(oid, os->oid)) {
305 return os->oidStr;
306 }
307 }
308 sprintf(unknownOidString, "Unknown OID length %ld, value { ", oid->Length);
309 for(dex=0; dex<oid->Length; dex++) {
310 char tmp[6];
311 sprintf(tmp, "%02X ", oid->Data[dex]);
312 strcat(unknownOidString, tmp);
313 }
314 strcat(unknownOidString, " }");
315 return unknownOidString;
316 }
317
318 /* compare OIDs; returns 1 if identical, else returns 0 */
319 int compareOids(
320 const CSSM_OID *oid1,
321 const CSSM_OID *oid2)
322 {
323 if((oid1 == NULL) || (oid2 == NULL)) {
324 return 0;
325 }
326 if(oid1->Length != oid2->Length) {
327 return 0;
328 }
329 if(memcmp(oid1->Data, oid2->Data, oid1->Length)) {
330 return 0;
331 }
332 return 1;
333 }
334
335 /* app path string to SecTrustedApplicationRef */
336 SecTrustedApplicationRef appPathToAppRef(
337 const char *appPath)
338 {
339 SecTrustedApplicationRef appRef = NULL;
340 OSStatus ortn;
341
342 if(appPath == NULL) {
343 return NULL;
344 }
345 ortn = SecTrustedApplicationCreateFromPath(appPath, &appRef);
346 if(ortn) {
347 cssmPerror("SecTrustedApplicationCreateFromPath", ortn);
348 return NULL;
349 }
350 return appRef;
351 }
352
353 int readCertFile(
354 const char *fileName,
355 SecCertificateRef *certRef)
356 {
357 unsigned char *cp = NULL;
358 size_t len = 0;
359 CSSM_DATA certData;
360 OSStatus ortn;
361 unsigned char *decoded = NULL;
362 unsigned decodedLen = 0;
363
364 if(readFileSizet(fileName, &cp, &len)) {
365 printf("***Error reading file %s\n", fileName);
366 return -1;
367 }
368 if(isPem(cp, (unsigned) len)) {
369 if(pemDecode(cp, (unsigned) len, &decoded, &decodedLen)) {
370 fprintf(stderr, "Error decoding cert file %s\n", fileName);
371 return -1;
372 }
373 certData.Length = decodedLen;
374 certData.Data = decoded;
375 }
376 else {
377 certData.Length = len;
378 certData.Data = cp;
379 }
380 ortn = SecCertificateCreateFromData(&certData,
381 CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, certRef);
382 free(cp);
383 if(decoded) {
384 free(decoded);
385 }
386 if(ortn) {
387 cssmPerror("SecCertificateCreateFromData", ortn);
388 return -1;
389 }
390 return 0;
391 }
392
393 /* policy string --> CSSM_OID */
394 const CSSM_OID *policyStringToOid(
395 const char *policy)
396 {
397 if(policy == NULL) {
398 return NULL;
399 }
400 if(!strcmp(policy, "ssl")) {
401 return &CSSMOID_APPLE_TP_SSL;
402 }
403 else if(!strcmp(policy, "smime")) {
404 return &CSSMOID_APPLE_TP_SMIME;
405 }
406 else if(!strcmp(policy, "codeSign")) {
407 return &CSSMOID_APPLE_TP_CODE_SIGNING;
408 }
409 else if(!strcmp(policy, "IPSec")) {
410 return &CSSMOID_APPLE_TP_IP_SEC;
411 }
412 else if(!strcmp(policy, "basic")) {
413 return &CSSMOID_APPLE_X509_BASIC;
414 }
415 else if(!strcmp(policy, "swUpdate")) {
416 return &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING;
417 }
418 else if(!strcmp(policy, "pkgSign")) {
419 return &CSSMOID_APPLE_TP_PACKAGE_SIGNING;
420 }
421 else if(!strcmp(policy, "eap")) {
422 return &CSSMOID_APPLE_TP_EAP;
423 }
424 else if(!strcmp(policy, "macappstore")) {
425 return &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT;
426 }
427 else if(!strcmp(policy, "appleID")) {
428 return &CSSMOID_APPLE_TP_APPLEID_SHARING;
429 }
430 else if(!strcmp(policy, "timestamping")) {
431 return &CSSMOID_APPLE_TP_TIMESTAMPING;
432 }
433 else {
434 fprintf(stderr, "***unknown policy spec (%s)\n", policy);
435 return NULL;
436 }
437 }
438
439 CFOptionFlags revCheckOptionStringToFlags(
440 const char *revCheckOption)
441 {
442 CFOptionFlags result = 0;
443 if(revCheckOption == NULL) {
444 return result;
445 }
446 else if(!strcmp(revCheckOption, "ocsp")) {
447 result |= kSecRevocationOCSPMethod;
448 }
449 else if(!strcmp(revCheckOption, "crl")) {
450 result |= kSecRevocationCRLMethod;
451 }
452 else if(!strcmp(revCheckOption, "require")) {
453 result |= kSecRevocationRequirePositiveResponse;
454 }
455 else if(!strcmp(revCheckOption, "offline")) {
456 result |= kSecRevocationNetworkAccessDisabled;
457 }
458 else if(!strcmp(revCheckOption, "online")) {
459 result |= kSecRevocationOnlineCheck;
460 }
461 return result;
462 }