]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/anchorTest/anchorTest.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / anchorTest / anchorTest.cpp
1 /*
2 * anchorTest.cpp - test cert encode/decode using known good system
3 * anchors
4 */
5 #include <stdio.h>
6 #include <string.h>
7 #include <Security/cssm.h>
8 #include <Security/x509defs.h>
9 #include <Security/oidsattr.h>
10 #include <Security/oidscert.h>
11 #include <Security/certextensions.h>
12 #include <Security/SecTrust.h>
13 #include <Security/SecTrustSettingsPriv.h>
14 #include <security_cdsa_utils/cuOidParser.h>
15 #include <security_cdsa_utils/cuPrintCert.h>
16 #include <utilLib/common.h>
17 #include <utilLib/cspwrap.h>
18 #include <security_cdsa_utils/cuFileIo.h>
19 #include <clAppUtils/clutils.h>
20 #include <clAppUtils/certVerify.h>
21 #include <clAppUtils/tpUtils.h>
22 #include <Security/SecAsn1Coder.h>
23 #include <Security/X509Templates.h>
24
25 #define ENC_TBS_BLOB "encodedTbs.der"
26 #define DEC_TBS_BLOB "decodedTbs.der"
27
28 static void usage(char **argv)
29 {
30 printf("Usage: %s [options]\n", argv[0]);
31 printf("Options:\n");
32 printf(" w -- writeBlobs\n");
33 printf(" e -- allow expired roots\n");
34 printf(" t -- use Trust Settings\n");
35 printf(" q -- quiet\n");
36 printf(" v -- verbose\n");
37 exit(1);
38 }
39
40 /*
41 * Certs for which we skip the "compare TBS blob" test, enumerated by
42 * DER-encoded issuer name.
43 *
44 * Get this formatted data from the extractCertFields program.
45 *
46 * All of these have non-standard KeyUsage encoding (legal but it's
47 * not the same as ours or everyone else's).
48 */
49 /*
50 Country : HU
51 Locality : Budapest
52 Org : NetLock Halozatbiztonsagi Kft.
53 OrgUnit : Tanusitvanykiadok
54 Common Name : NetLock Expressz (Class C) Tanusitvanykiado
55 */
56 static const uint8 anchor_46_derIssuer_bytes[] = {
57 0x30, 0x81, 0x9b, 0x31, 0x0b, 0x30, 0x09, 0x06,
58 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55,
59 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
60 0x07, 0x13, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70,
61 0x65, 0x73, 0x74, 0x31, 0x27, 0x30, 0x25, 0x06,
62 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1e, 0x4e, 0x65,
63 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x20, 0x48, 0x61,
64 0x6c, 0x6f, 0x7a, 0x61, 0x74, 0x62, 0x69, 0x7a,
65 0x74, 0x6f, 0x6e, 0x73, 0x61, 0x67, 0x69, 0x20,
66 0x4b, 0x66, 0x74, 0x2e, 0x31, 0x1a, 0x30, 0x18,
67 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x11, 0x54,
68 0x61, 0x6e, 0x75, 0x73, 0x69, 0x74, 0x76, 0x61,
69 0x6e, 0x79, 0x6b, 0x69, 0x61, 0x64, 0x6f, 0x6b,
70 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04,
71 0x03, 0x13, 0x2b, 0x4e, 0x65, 0x74, 0x4c, 0x6f,
72 0x63, 0x6b, 0x20, 0x45, 0x78, 0x70, 0x72, 0x65,
73 0x73, 0x73, 0x7a, 0x20, 0x28, 0x43, 0x6c, 0x61,
74 0x73, 0x73, 0x20, 0x43, 0x29, 0x20, 0x54, 0x61,
75 0x6e, 0x75, 0x73, 0x69, 0x74, 0x76, 0x61, 0x6e,
76 0x79, 0x6b, 0x69, 0x61, 0x64, 0x6f
77 };
78 static const CSSM_DATA anchor_46_derIssuer = { 158, (uint8 *)anchor_46_derIssuer_bytes };
79
80 /*
81 Country : HU
82 State : Hungary
83 Locality : Budapest
84 Org : NetLock Halozatbiztonsagi Kft.
85 OrgUnit : Tanusitvanykiadok
86 Common Name : NetLock Kozjegyzoi (Class A) Tanusitvanykiado
87 */
88 static const uint8 anchor_53_derIssuer_bytes[] = {
89 0x30, 0x81, 0xaf, 0x31, 0x0b, 0x30, 0x09, 0x06,
90 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55,
91 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,
92 0x08, 0x13, 0x07, 0x48, 0x75, 0x6e, 0x67, 0x61,
93 0x72, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03,
94 0x55, 0x04, 0x07, 0x13, 0x08, 0x42, 0x75, 0x64,
95 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x27, 0x30,
96 0x25, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1e,
97 0x4e, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x20,
98 0x48, 0x61, 0x6c, 0x6f, 0x7a, 0x61, 0x74, 0x62,
99 0x69, 0x7a, 0x74, 0x6f, 0x6e, 0x73, 0x61, 0x67,
100 0x69, 0x20, 0x4b, 0x66, 0x74, 0x2e, 0x31, 0x1a,
101 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
102 0x11, 0x54, 0x61, 0x6e, 0x75, 0x73, 0x69, 0x74,
103 0x76, 0x61, 0x6e, 0x79, 0x6b, 0x69, 0x61, 0x64,
104 0x6f, 0x6b, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03,
105 0x55, 0x04, 0x03, 0x13, 0x2d, 0x4e, 0x65, 0x74,
106 0x4c, 0x6f, 0x63, 0x6b, 0x20, 0x4b, 0x6f, 0x7a,
107 0x6a, 0x65, 0x67, 0x79, 0x7a, 0x6f, 0x69, 0x20,
108 0x28, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x41,
109 0x29, 0x20, 0x54, 0x61, 0x6e, 0x75, 0x73, 0x69,
110 0x74, 0x76, 0x61, 0x6e, 0x79, 0x6b, 0x69, 0x61,
111 0x64, 0x6f
112 };
113 static const CSSM_DATA anchor_53_derIssuer = { 178, (uint8 *)anchor_53_derIssuer_bytes };
114
115 /*
116 Country : HU
117 Locality : Budapest
118 Org : NetLock Halozatbiztonsagi Kft.
119 OrgUnit : Tanusitvanykiadok
120 Common Name : NetLock Uzleti (Class B) Tanusitvanykiado
121 */
122 static const uint8 anchor_60_derIssuer_bytes[] = {
123 0x30, 0x81, 0x99, 0x31, 0x0b, 0x30, 0x09, 0x06,
124 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55,
125 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
126 0x07, 0x13, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70,
127 0x65, 0x73, 0x74, 0x31, 0x27, 0x30, 0x25, 0x06,
128 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1e, 0x4e, 0x65,
129 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x20, 0x48, 0x61,
130 0x6c, 0x6f, 0x7a, 0x61, 0x74, 0x62, 0x69, 0x7a,
131 0x74, 0x6f, 0x6e, 0x73, 0x61, 0x67, 0x69, 0x20,
132 0x4b, 0x66, 0x74, 0x2e, 0x31, 0x1a, 0x30, 0x18,
133 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x11, 0x54,
134 0x61, 0x6e, 0x75, 0x73, 0x69, 0x74, 0x76, 0x61,
135 0x6e, 0x79, 0x6b, 0x69, 0x61, 0x64, 0x6f, 0x6b,
136 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04,
137 0x03, 0x13, 0x29, 0x4e, 0x65, 0x74, 0x4c, 0x6f,
138 0x63, 0x6b, 0x20, 0x55, 0x7a, 0x6c, 0x65, 0x74,
139 0x69, 0x20, 0x28, 0x43, 0x6c, 0x61, 0x73, 0x73,
140 0x20, 0x42, 0x29, 0x20, 0x54, 0x61, 0x6e, 0x75,
141 0x73, 0x69, 0x74, 0x76, 0x61, 0x6e, 0x79, 0x6b,
142 0x69, 0x61, 0x64, 0x6f
143 };
144 static const CSSM_DATA anchor_60_derIssuer = { 156, (uint8 *)anchor_60_derIssuer_bytes };
145
146 /*
147 Country : TR
148 Locality : Ankara
149 Org : (c) 2005 TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş.
150 Common Name : TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı
151 Serial Number : 01
152 Not Before : 10:27:17 May 13, 2005
153 Not After : 10:27:17 Mar 22, 2015
154 */
155 static const uint8 turk1_derIssuer_bytes[] = {
156 0x30, 0x81, 0xb7, 0x31, 0x3f, 0x30, 0x3d, 0x06,
157 0x03, 0x55, 0x04, 0x03, 0x0c, 0x36, 0x54, 0xc3,
158 0x9c, 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54,
159 0x20, 0x45, 0x6c, 0x65, 0x6b, 0x74, 0x72, 0x6f,
160 0x6e, 0x69, 0x6b, 0x20, 0x53, 0x65, 0x72, 0x74,
161 0x69, 0x66, 0x69, 0x6b, 0x61, 0x20, 0x48, 0x69,
162 0x7a, 0x6d, 0x65, 0x74, 0x20, 0x53, 0x61, 0xc4,
163 0x9f, 0x6c, 0x61, 0x79, 0xc4, 0xb1, 0x63, 0xc4,
164 0xb1, 0x73, 0xc4, 0xb1, 0x31, 0x0b, 0x30, 0x09,
165 0x06, 0x03, 0x55, 0x04, 0x06, 0x0c, 0x02, 0x54,
166 0x52, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55,
167 0x04, 0x07, 0x0c, 0x06, 0x41, 0x4e, 0x4b, 0x41,
168 0x52, 0x41, 0x31, 0x56, 0x30, 0x54, 0x06, 0x03,
169 0x55, 0x04, 0x0a, 0x0c, 0x4d, 0x28, 0x63, 0x29,
170 0x20, 0x32, 0x30, 0x30, 0x35, 0x20, 0x54, 0xc3,
171 0x9c, 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54,
172 0x20, 0x42, 0x69, 0x6c, 0x67, 0x69, 0x20, 0xc4,
173 0xb0, 0x6c, 0x65, 0x74, 0x69, 0xc5, 0x9f, 0x69,
174 0x6d, 0x20, 0x76, 0x65, 0x20, 0x42, 0x69, 0x6c,
175 0x69, 0xc5, 0x9f, 0x69, 0x6d, 0x20, 0x47, 0xc3,
176 0xbc, 0x76, 0x65, 0x6e, 0x6c, 0x69, 0xc4, 0x9f,
177 0x69, 0x20, 0x48, 0x69, 0x7a, 0x6d, 0x65, 0x74,
178 0x6c, 0x65, 0x72, 0x69, 0x20, 0x41, 0x2e, 0xc5,
179 0x9e, 0x2e
180 };
181 static const CSSM_DATA turk1_derIssuer = { 186, (uint8 *)turk1_derIssuer_bytes };
182
183 /*
184 Country : TR
185 Locality : Ankara
186 Org : TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Kasım 2005
187 Common Name : TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı
188 Serial Number : 01
189 Not Before : 10:07:57 Nov 7, 2005
190 Not After : 10:07:57 Sep 16, 2015
191 */
192 static const uint8 turk2_derIssuer_bytes[] = {
193 0x30, 0x81, 0xbe, 0x31, 0x3f, 0x30, 0x3d, 0x06,
194 0x03, 0x55, 0x04, 0x03, 0x0c, 0x36, 0x54, 0xc3,
195 0x9c, 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54,
196 0x20, 0x45, 0x6c, 0x65, 0x6b, 0x74, 0x72, 0x6f,
197 0x6e, 0x69, 0x6b, 0x20, 0x53, 0x65, 0x72, 0x74,
198 0x69, 0x66, 0x69, 0x6b, 0x61, 0x20, 0x48, 0x69,
199 0x7a, 0x6d, 0x65, 0x74, 0x20, 0x53, 0x61, 0xc4,
200 0x9f, 0x6c, 0x61, 0x79, 0xc4, 0xb1, 0x63, 0xc4,
201 0xb1, 0x73, 0xc4, 0xb1, 0x31, 0x0b, 0x30, 0x09,
202 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x54,
203 0x52, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55,
204 0x04, 0x07, 0x0c, 0x06, 0x41, 0x6e, 0x6b, 0x61,
205 0x72, 0x61, 0x31, 0x5d, 0x30, 0x5b, 0x06, 0x03,
206 0x55, 0x04, 0x0a, 0x0c, 0x54, 0x54, 0xc3, 0x9c,
207 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20,
208 0x42, 0x69, 0x6c, 0x67, 0x69, 0x20, 0xc4, 0xb0,
209 0x6c, 0x65, 0x74, 0x69, 0xc5, 0x9f, 0x69, 0x6d,
210 0x20, 0x76, 0x65, 0x20, 0x42, 0x69, 0x6c, 0x69,
211 0xc5, 0x9f, 0x69, 0x6d, 0x20, 0x47, 0xc3, 0xbc,
212 0x76, 0x65, 0x6e, 0x6c, 0x69, 0xc4, 0x9f, 0x69,
213 0x20, 0x48, 0x69, 0x7a, 0x6d, 0x65, 0x74, 0x6c,
214 0x65, 0x72, 0x69, 0x20, 0x41, 0x2e, 0xc5, 0x9e,
215 0x2e, 0x20, 0x28, 0x63, 0x29, 0x20, 0x4b, 0x61,
216 0x73, 0xc4, 0xb1, 0x6d, 0x20, 0x32, 0x30, 0x30,
217 0x35
218 };
219 static const CSSM_DATA turk2_derIssuer = { 193, (uint8 *)turk2_derIssuer_bytes };
220
221 /*
222 Country : TR
223 Locality : Ankara
224 Org : TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş. (c) Aralık 2007
225 Common Name : TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı
226 Serial Number : 01
227 Not Before : 18:37:19 Dec 25, 2007
228 Not After : 18:37:19 Dec 22, 2017
229 */
230 static const uint8 turk3_derIssuer_bytes[] = {
231 0x30, 0x81, 0xbf, 0x31, 0x3f, 0x30, 0x3d, 0x06,
232 0x03, 0x55, 0x04, 0x03, 0x0c, 0x36, 0x54, 0xc3,
233 0x9c, 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54,
234 0x20, 0x45, 0x6c, 0x65, 0x6b, 0x74, 0x72, 0x6f,
235 0x6e, 0x69, 0x6b, 0x20, 0x53, 0x65, 0x72, 0x74,
236 0x69, 0x66, 0x69, 0x6b, 0x61, 0x20, 0x48, 0x69,
237 0x7a, 0x6d, 0x65, 0x74, 0x20, 0x53, 0x61, 0xc4,
238 0x9f, 0x6c, 0x61, 0x79, 0xc4, 0xb1, 0x63, 0xc4,
239 0xb1, 0x73, 0xc4, 0xb1, 0x31, 0x0b, 0x30, 0x09,
240 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x54,
241 0x52, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55,
242 0x04, 0x07, 0x0c, 0x06, 0x41, 0x6e, 0x6b, 0x61,
243 0x72, 0x61, 0x31, 0x5e, 0x30, 0x5c, 0x06, 0x03,
244 0x55, 0x04, 0x0a, 0x0c, 0x55, 0x54, 0xc3, 0x9c,
245 0x52, 0x4b, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20,
246 0x42, 0x69, 0x6c, 0x67, 0x69, 0x20, 0xc4, 0xb0,
247 0x6c, 0x65, 0x74, 0x69, 0xc5, 0x9f, 0x69, 0x6d,
248 0x20, 0x76, 0x65, 0x20, 0x42, 0x69, 0x6c, 0x69,
249 0xc5, 0x9f, 0x69, 0x6d, 0x20, 0x47, 0xc3, 0xbc,
250 0x76, 0x65, 0x6e, 0x6c, 0x69, 0xc4, 0x9f, 0x69,
251 0x20, 0x48, 0x69, 0x7a, 0x6d, 0x65, 0x74, 0x6c,
252 0x65, 0x72, 0x69, 0x20, 0x41, 0x2e, 0xc5, 0x9e,
253 0x2e, 0x20, 0x28, 0x63, 0x29, 0x20, 0x41, 0x72,
254 0x61, 0x6c, 0xc4, 0xb1, 0x6b, 0x20, 0x32, 0x30,
255 0x30, 0x37
256 };
257 static const CSSM_DATA turk3_derIssuer = { 194, (uint8 *)turk3_derIssuer_bytes };
258
259 /*
260 Cert File Name: globalSignRoot.cer
261 Country : BE
262 Org : GlobalSign nv-sa
263 OrgUnit : Root CA
264 Common Name : GlobalSign Root CA
265 */
266 static const uint8 globalSignRoot_derIssuer_bytes[] = {
267 0x30, 0x57, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
268 0x55, 0x04, 0x06, 0x13, 0x02, 0x42, 0x45, 0x31,
269 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a,
270 0x13, 0x10, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c,
271 0x53, 0x69, 0x67, 0x6e, 0x20, 0x6e, 0x76, 0x2d,
272 0x73, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03,
273 0x55, 0x04, 0x0b, 0x13, 0x07, 0x52, 0x6f, 0x6f,
274 0x74, 0x20, 0x43, 0x41, 0x31, 0x1b, 0x30, 0x19,
275 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47,
276 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67,
277 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43,
278 0x41
279 };
280 static const CSSM_DATA globalSignRoot_derIssuer = { 89, (uint8 *)globalSignRoot_derIssuer_bytes };
281
282 /***********************
283 Cert File Name: swisssign.der
284 Subject Name :
285 Country : CH
286 Org : SwissSign
287 Common Name : SwissSign CA (RSA IK May 6 1999 18:00:58)
288 Email addrs : ca@SwissSign.com
289
290 This one has a bogus AuthorityKeyId, with a value of {0x30, 0} inside the octet string.
291 ***********************/
292 static const uint8 swisssign_derIssuer_bytes[] = {
293 0x30, 0x76, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
294 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x31,
295 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a,
296 0x13, 0x09, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53,
297 0x69, 0x67, 0x6e, 0x31, 0x32, 0x30, 0x30, 0x06,
298 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x77,
299 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6e, 0x20,
300 0x43, 0x41, 0x20, 0x28, 0x52, 0x53, 0x41, 0x20,
301 0x49, 0x4b, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x36,
302 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x31, 0x38,
303 0x3a, 0x30, 0x30, 0x3a, 0x35, 0x38, 0x29, 0x31,
304 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48,
305 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10,
306 0x63, 0x61, 0x40, 0x53, 0x77, 0x69, 0x73, 0x73,
307 0x53, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d
308
309 };
310 static const CSSM_DATA swisssign_derIssuer = { 120, (uint8 *)swisssign_derIssuer_bytes };
311
312 /*
313 * Simple class to hold arrays of fields.
314 */
315 class FieldArray {
316 public:
317 /*
318 * Create from existing field array obtained from
319 * CSSM_CL_CertGetAllFields(). We'll do the CSSM_CL_FreeFields()
320 * in our destructor.
321 */
322 FieldArray(
323 CSSM_FIELD *fields,
324 uint32 numFields,
325 CSSM_CL_HANDLE clHand);
326
327 /*
328 * Create empty array of specified size. We don't own the fields
329 * themselves.
330 */
331 FieldArray(
332 uint32 size);
333
334 ~FieldArray();
335
336 /*
337 * Append a field - no realloc!
338 */
339 void appendField(CSSM_FIELD &field);
340
341 /* get specified field */
342 CSSM_FIELD &fieldAt(uint32 index);
343
344 /* get nth occurence of field matching specified OID */
345 int fieldForOid(
346 const CSSM_OID &oid,
347 unsigned n, // n == 0 --> first one
348 CSSM_FIELD *&found); // RETURNED
349
350 CSSM_FIELD *mFields;
351 uint32 mNumFields; // sizeof of *fields
352 uint32 mMallocdSize; // if NULL, read-only
353 CSSM_CL_HANDLE mClHand;
354 };
355
356 FieldArray::FieldArray(
357 CSSM_FIELD *fields,
358 uint32 numFields,
359 CSSM_CL_HANDLE clHand)
360 {
361 mFields = fields;
362 mNumFields = numFields;
363 mMallocdSize = 0;
364 mClHand = clHand;
365 }
366
367 FieldArray::FieldArray(
368 uint32 size)
369 {
370 unsigned len = sizeof(CSSM_FIELD) * size;
371 mFields = (CSSM_FIELD_PTR)malloc(len);
372 memset(mFields, 0, len);
373 mNumFields = 0;
374 mMallocdSize = size;
375 mClHand = 0;
376 }
377
378 FieldArray::~FieldArray()
379 {
380 if(mMallocdSize != 0) {
381 /*
382 * Just free the array of fields we mallocd, not the fields
383 * themselves
384 */
385 free(mFields);
386 }
387 else {
388 /* The CL mallocd these fields, tell it to free the whole thing */
389 CSSM_RETURN crtn = CSSM_CL_FreeFields(mClHand,
390 mNumFields, &mFields);
391 if(crtn) {
392 printError("CSSM_CL_FreeFields", crtn);
393 }
394 }
395 mFields = NULL;
396 mNumFields = 0;
397 mMallocdSize = 0;
398 }
399
400 void FieldArray::appendField(
401 CSSM_FIELD &field)
402 {
403 if(mMallocdSize == 0) {
404 printf("***Attempt to append to a read-only FieldArray\n");
405 exit(1);
406 }
407 if(mNumFields >= mMallocdSize) {
408 printf("***Attempt to append past present size of FieldArray\n");
409 exit(1);
410 }
411 mFields[mNumFields] = field;
412 mNumFields++;
413 }
414
415 CSSM_FIELD &FieldArray::fieldAt(
416 uint32 index)
417 {
418 if(index >= mNumFields) {
419 printf("***Attempt to access past present size of FieldArray\n");
420 exit(1);
421 }
422 return mFields[index];
423 }
424
425 /* get nth occurence of field matching specified OID */
426 /* returns nonzero on error */
427 int FieldArray::fieldForOid(
428 const CSSM_OID &oid,
429 unsigned n, // n == 0 --> first one
430 CSSM_FIELD *&found) // RETURNED
431 {
432 unsigned foundDex = 0;
433 for(unsigned dex=0; dex<mNumFields; dex++) {
434 CSSM_FIELD &field = mFields[dex];
435 if(appCompareCssmData(&field.FieldOid, &oid)) {
436 if(foundDex == n) {
437 found = &field;
438 return 0;
439 }
440 foundDex++;
441 }
442 }
443 printf("FieldArray::fieldForOid field not found\n");
444 return 1;
445 }
446
447 /*
448 * How many items in a NULL-terminated array of pointers?
449 */
450 static unsigned nssArraySize(
451 const void **array)
452 {
453 unsigned count = 0;
454 if (array) {
455 while (*array++) {
456 count++;
457 }
458 }
459 return count;
460 }
461
462 static void doPrintCert(
463 const CSSM_DATA &cert)
464 {
465 printCert(cert.Data, cert.Length, CSSM_TRUE);
466 }
467
468 /*
469 * The extensions whose presence causes us to skip the "compare
470 * encoded and original TBS" test.
471 */
472 #define USE_SKIPPED_EXTENS 1
473 #if USE_SKIPPED_EXTENS
474 static const CSSM_OID *skippedExtens[] = { // %%% FIXME: this is a workaround for <rdar://8265523>; shouldn't need to skip!
475 &CSSMOID_PolicyMappings,
476 &CSSMOID_PolicyConstraints
477 };
478 #define NUM_SKIPPED_EXTENS \
479 (sizeof(skippedExtens) / sizeof(skippedExtens[0]))
480 #endif /* USE_SKIPPED_EXTENS */
481
482 static const CSSM_DATA *skippedCerts[] = {
483 &anchor_46_derIssuer,
484 &anchor_53_derIssuer,
485 &anchor_60_derIssuer,
486 &turk1_derIssuer,
487 &turk2_derIssuer,
488 &turk3_derIssuer,
489 &globalSignRoot_derIssuer,
490 &swisssign_derIssuer
491 };
492 #define NUM_SKIPPED_CERTS (sizeof(skippedCerts) / sizeof(skippedCerts[0]))
493
494 static bool skipThisCert(
495 const NSS_TBSCertificate &tbs)
496 {
497 /* search by extension - currently unused */
498 unsigned dex;
499 #if USE_SKIPPED_EXTENS
500 unsigned numExtens = nssArraySize((const void **)tbs.extensions);
501 /* skip this section if that's empty - compiler warning causes failure */
502 for(dex=0; dex<numExtens; dex++) {
503 NSS_CertExtension *exten = tbs.extensions[dex];
504 CSSM_OID *oid = &exten->extnId;
505 for(unsigned skipDex=0; skipDex<NUM_SKIPPED_EXTENS; skipDex++) {
506 if(appCompareCssmData(skippedExtens[skipDex], oid)) {
507 return true;
508 }
509 }
510 }
511 #endif /* USE_SKIPPED_EXTENS */
512
513 /* search by specific issuer */
514 for(dex=0; dex<NUM_SKIPPED_CERTS; dex++) {
515 if(appCompareCssmData(skippedCerts[dex], &tbs.derIssuer)) {
516 return true;
517 }
518 }
519 return false;
520 }
521
522 /*
523 * Given a field OID, figure out what WE think this field is.
524 */
525
526 /* the field types we grok */
527 typedef enum {
528 FT_Unknown, // probably means we're out of sync with the CL
529 FT_Normal, // standard component of TBS
530 FT_ReadOnly, // Read only, don't use to create template
531 FT_NotTBS, // part of top-level cert, don't use to create TBS
532 FT_ExtenParsed, // extension the CL SHOULD HAVE parsed
533 FT_ExtenUnknown // extension the CL should NOT have parsed
534 } FieldType;
535
536 /* map OID --> FieldType */
537 typedef struct {
538 const CSSM_OID *oid;
539 FieldType type;
540 } FieldOidType;
541
542 /*
543 * The CL-specific mapping table.
544 * This has to change whenever the CL is modified to add or delete
545 * an extension or field!
546 * For newbies, a tip: this basically has to stay in sync with the
547 * fieldFuncTable array in Security/AppleX509CL/CertFields.cpp.
548 */
549 FieldOidType knownFields[] = {
550 { &CSSMOID_X509V1Version, FT_Normal },
551 { &CSSMOID_X509V1SerialNumber, FT_Normal },
552 { &CSSMOID_X509V1IssuerNameCStruct, FT_Normal },
553 { &CSSMOID_X509V1SubjectNameCStruct, FT_Normal },
554 { &CSSMOID_X509V1SignatureAlgorithmTBS, FT_Normal },
555 { &CSSMOID_X509V1SignatureAlgorithm, FT_NotTBS },
556 { &CSSMOID_X509V1ValidityNotBefore, FT_Normal },
557 { &CSSMOID_X509V1ValidityNotAfter, FT_Normal },
558 { &CSSMOID_X509V1CertificateIssuerUniqueId, FT_Normal },
559 { &CSSMOID_X509V1CertificateSubjectUniqueId, FT_Normal },
560 /* only one of these two can be set - use the SubjectPublicKeyInfo
561 * version */
562 { &CSSMOID_X509V1SubjectPublicKeyCStruct, FT_Normal },
563 { &CSSMOID_CSSMKeyStruct, FT_ReadOnly },
564 { &CSSMOID_X509V1Signature, FT_NotTBS },
565 { &CSSMOID_X509V1IssuerName, FT_ReadOnly }, // DER encoded
566 { &CSSMOID_X509V1SubjectName, FT_ReadOnly }, // DER encoded
567 { &CSSMOID_X509V1IssuerNameStd, FT_ReadOnly }, // DER encoded
568 { &CSSMOID_X509V1SubjectNameStd,FT_ReadOnly }, // DER encoded
569
570 /* Extensions */
571 { &CSSMOID_KeyUsage, FT_ExtenParsed },
572 { &CSSMOID_BasicConstraints, FT_ExtenParsed },
573 { &CSSMOID_ExtendedKeyUsage, FT_ExtenParsed } ,
574 { &CSSMOID_SubjectKeyIdentifier, FT_ExtenParsed } ,
575 { &CSSMOID_AuthorityKeyIdentifier, FT_ExtenParsed } ,
576 { &CSSMOID_SubjectAltName, FT_ExtenParsed } ,
577 { &CSSMOID_IssuerAltName, FT_ExtenParsed } ,
578 { &CSSMOID_CertificatePolicies, FT_ExtenParsed } ,
579 { &CSSMOID_NetscapeCertType, FT_ExtenParsed } ,
580 { &CSSMOID_CrlDistributionPoints, FT_ExtenParsed },
581 { &CSSMOID_AuthorityInfoAccess, FT_ExtenParsed },
582 { &CSSMOID_SubjectInfoAccess, FT_ExtenParsed },
583 { &CSSMOID_X509V3CertificateExtensionCStruct, FT_ExtenUnknown },
584 { &CSSMOID_QC_Statements, FT_ExtenParsed },
585 { &CSSMOID_NameConstraints, FT_ExtenParsed },
586 { &CSSMOID_PolicyMappings, FT_ExtenParsed },
587 { &CSSMOID_PolicyConstraints, FT_ExtenParsed },
588 // { &CSSMOID_InhibitAnyPolicy, FT_ExtenParsed } //%%% FIXME: CSSMOID_InhibitAnyPolicy not exported!?
589 };
590 #define NUM_KNOWN_FIELDS (sizeof(knownFields) / sizeof(knownFields[0]))
591
592 static FieldType typeForOid(
593 const CSSM_OID &oid)
594 {
595 for(unsigned dex=0; dex<NUM_KNOWN_FIELDS; dex++) {
596 FieldOidType &ft = knownFields[dex];
597 if(appCompareCssmData(&oid, ft.oid)) {
598 return ft.type;
599 }
600 }
601 /* not found */
602 return FT_Unknown;
603 }
604
605 static const char *fieldTypeStr(
606 FieldType type)
607 {
608 switch(type) {
609 case FT_Unknown: return "FT_Unknown";
610 case FT_Normal: return "FT_Normal";
611 case FT_ReadOnly: return "FT_ReadOnly";
612 case FT_NotTBS: return "FT_NotTBS";
613 case FT_ExtenParsed: return "FT_ExtenParsed";
614 case FT_ExtenUnknown: return "FT_ExtenUnknown";
615 default:
616 printf("***BRRZAP!\n");
617 exit(1);
618 }
619 }
620
621 static const uint8 emptyAuthKeyId[2] = {0x30, 0};
622
623 /*
624 * Extensions come in two flavors - parsed and not. However the
625 * CL will give us an unparsed version for extensions it normally
626 * understands but failed to decode. Detect that, and basic
627 * extension formatting screwups, here.
628 */
629 static int vfyExtens(
630 FieldArray &extenFields,
631 const CSSM_DATA &cert, // for error display only
632 CSSM_BOOL quiet)
633 {
634 for(unsigned dex=0; dex<extenFields.mNumFields; dex++) {
635 CSSM_FIELD &extenField = extenFields.fieldAt(dex);
636 FieldType type = typeForOid(extenField.FieldOid);
637 FieldType expectType;
638
639 /* first verify well-formed extension field */
640 CSSM_DATA &fieldValue = extenField.FieldValue;
641 CSSM_X509_EXTENSION *exten = (CSSM_X509_EXTENSION *)fieldValue.Data;
642 if((exten == NULL) ||
643 (fieldValue.Length != sizeof(CSSM_X509_EXTENSION))) {
644 doPrintCert(cert);
645 printf("***Malformed CSSM_X509_EXTENSION\n");
646 if(testError(quiet)) {
647 return 1;
648 }
649 /* well let's limp along */
650 continue;
651 }
652
653 /* currently (since Radar 3593624), these are both always valid */
654 if((exten->BERvalue.Data == NULL) ||
655 (exten->value.parsedValue == NULL)) { /* actually, one of three variants */
656 printf("***Malformed CSSM_X509_EXTENSION (1)\n");
657 return 1;
658 }
659
660 switch(exten->format) {
661 case CSSM_X509_DATAFORMAT_ENCODED:
662 if(type != FT_ExtenUnknown) {
663 doPrintCert(cert);
664 printf("***Entension format ENCODED, expected PARSED\n");
665 if(testError(quiet)) {
666 return 1;
667 }
668 }
669
670 /*
671 * Now make sure that the underlying extension ID isn't
672 * one that the CL was SUPPOSED to parse
673 */
674 // %%% FIXME: need to investigate why these are not fully parsed: <rdar://8265523>
675 if(appCompareCssmData(&exten->extnId, &CSSMOID_PolicyConstraints)) {
676 printf("...skipping policyConstraints extension per <rdar://8265523> (fix me!)\n");
677 break;
678 }
679 if(appCompareCssmData(&exten->extnId, &CSSMOID_PolicyMappings)) {
680 printf("...skipping policyMappings extension per <rdar://8265523> (fix me!)\n");
681 break;
682 }
683
684 expectType = typeForOid(exten->extnId);
685 if(expectType != FT_Unknown) {
686 /*
687 * Swisscom root has an authorityKeyId extension with an illegal value,
688 * data inside the octet string is <30 00>, no context-specific wrapper
689 * or tag.
690 * Instead of a hopeless complaint about that cert, let's just tolerate it
691 * like this...
692 */
693 if(appCompareCssmData(&exten->extnId, &CSSMOID_AuthorityKeyIdentifier) &&
694 (exten->BERvalue.Length == 2) &&
695 !memcmp(emptyAuthKeyId, exten->BERvalue.Data, 2)) {
696 printf("...skipping bogus swisssign AuthorityKeyId\n");
697 break;
698 }
699 doPrintCert(cert);
700 printf("***underlying exten type %s, expect Unknown\n",
701 fieldTypeStr(expectType));
702 if(testError(quiet)) {
703 return 1;
704 }
705 }
706 break;
707
708 case CSSM_X509_DATAFORMAT_PARSED:
709 if(type != FT_ExtenParsed) {
710 doPrintCert(cert);
711 printf("***Entension format PARSED, expected ENCODED\n");
712 if(testError(quiet)) {
713 return 1;
714 }
715 }
716 if(exten->value.parsedValue == NULL) {
717 doPrintCert(cert);
718 printf("***Parsed extension with NULL parsedValue\n");
719 if(testError(quiet)) {
720 return 1;
721 }
722 }
723 break;
724
725 default:
726 doPrintCert(cert);
727 printf("***Unknown Entension format %u\n",
728 exten->format);
729 if(testError(quiet)) {
730 return 1;
731 }
732 break;
733
734 } /* switch(exten.format) */
735 }
736 return 0;
737 }
738
739 /*
740 * Here's the hard part.
741 * Given a raw cert and its components in two FieldArrays, crate a TBS
742 * cert from scratch from those fields and ensure that the result
743 * is the same as the raw TBS field in the original cert.
744 */
745 static int buildTbs(
746 CSSM_CL_HANDLE clHand,
747 const CSSM_DATA &rawCert,
748 FieldArray &allFields, // on entry, standard fields
749 FieldArray &extenFields, // extensions only
750 CSSM_BOOL quiet,
751 CSSM_BOOL verbose,
752 CSSM_BOOL writeBlobs)
753 {
754 /*
755 * First do raw BER-decode in two ways - one to get the
756 * extensions as they actuallly appear in the cert, and one
757 * to get the raw undecoded TBS.
758 */
759 SecAsn1CoderRef coder;
760 OSStatus ortn = SecAsn1CoderCreate(&coder);
761 if(ortn) {
762 cssmPerror("SecAsn1CoderCreate", ortn);
763 return testError(quiet);
764 }
765
766 NSS_SignedCertOrCRL signedCert; // with TBS as ASN_ANY
767 memset(&signedCert, 0, sizeof(signedCert));
768 if(SecAsn1DecodeData(coder, &rawCert, kSecAsn1SignedCertOrCRLTemplate,
769 &signedCert)) {
770 doPrintCert(rawCert);
771 printf("***Error decoding cert to kSecAsn1SignedCertOrCRL\n");
772 return testError(quiet);
773 }
774
775 NSS_Certificate fullCert; // fully decoded
776 memset(&fullCert, 0, sizeof(fullCert));
777 if(SecAsn1DecodeData(coder, &rawCert, kSecAsn1SignedCertTemplate,
778 &fullCert)) {
779 doPrintCert(rawCert);
780 printf("***Error decoding cert to kSecAsn1Certificate\n");
781 return testError(quiet);
782 }
783
784 NSS_TBSCertificate &tbs = fullCert.tbs;
785 unsigned numExtens = nssArraySize((const void **)tbs.extensions);
786 if(numExtens != extenFields.mNumFields) {
787 /* The CL told us the wrong number of extensions */
788 doPrintCert(rawCert);
789 printf("***NSS says %u extens, CL says %u\n", numExtens,
790 (unsigned)extenFields.mNumFields);
791 return testError(quiet);
792 }
793
794 if(skipThisCert(tbs)) {
795 if(verbose) {
796 printf(" ...skipping TBS blob check\n");
797 }
798 SecAsn1CoderRelease(coder);
799 return 0;
800 }
801
802 /*
803 * The CL returns extension fields in an order which differs from
804 * the order of the extensions in the actual cert (because it
805 * does a table-based lookup, field by field, when doing a
806 * CSSM_CL_CertGetAllFields()). We have to add the extensions
807 * from extenFields to allFields in the order they appear in
808 * OUR decoded fullCert.
809 */
810 unsigned numUnknowns = 0;
811 for(unsigned dex=0; dex<numExtens; dex++) {
812 NSS_CertExtension *exten = tbs.extensions[dex];
813 CSSM_OID &oid = exten->extnId;
814 FieldType type = typeForOid(oid);
815 CSSM_FIELD *found = NULL;
816 int rtn;
817 switch(type) {
818 case FT_ExtenParsed:
819 /*
820 * look for this exact extension
821 * NOTE we're assuming that only one copy of
822 * each specific parsed extension exists. The
823 * 509 spec does't specifically require this but
824 * I've never seen a case of multiple extensions
825 * of the same type in one cert.
826 */
827 rtn = extenFields.fieldForOid(oid, 0, found);
828 break;
829 case FT_Unknown:
830 /* search for nth unparsed exten field */
831 rtn = extenFields.fieldForOid(
832 CSSMOID_X509V3CertificateExtensionCStruct,
833 numUnknowns++,
834 found);
835 break;
836 default:
837 /* caller was already supposed to check this */
838 doPrintCert(rawCert);
839 printf("***HEY! buildTBS was given a bogus extension!\n");
840 return 1;
841 }
842 if(rtn) {
843 doPrintCert(rawCert);
844 printf("***buildTBS could not find extension in CL's fields\n");
845 return testError(quiet);
846 }
847
848 allFields.appendField(*found);
849 } /* processing extensions */
850
851 /*
852 * OK, the field array in allFields is ready to go down to
853 * the CL.
854 */
855 CSSM_RETURN crtn;
856 CSSM_DATA clTbs = {0, NULL};
857 crtn = CSSM_CL_CertCreateTemplate(clHand,
858 allFields.mNumFields,
859 allFields.mFields,
860 &clTbs);
861 if(crtn) {
862 doPrintCert(rawCert);
863 printError("CSSM_CL_CertCreateTemplate", crtn);
864 return testError(quiet);
865 }
866
867 /*
868 * The moment of truth. Is that template identical to the
869 * raw undecoded TBS blob we got by decoding a NSS_SignedCertOrCRL?
870 */
871 int ourRtn = 0;
872 if(!appCompareCssmData(&clTbs, &signedCert.tbsBlob)) {
873 doPrintCert(rawCert);
874 printf("***Encoded TBS does not match decoded TBS.\n");
875 if(writeBlobs) {
876 writeFile(ENC_TBS_BLOB, clTbs.Data, clTbs.Length);
877 writeFile(DEC_TBS_BLOB, signedCert.tbsBlob.Data,
878 signedCert.tbsBlob.Length);
879 printf("...wrote TBS blobs to %s and %s\n",
880 ENC_TBS_BLOB, DEC_TBS_BLOB);
881 }
882 ourRtn = testError(quiet);
883 }
884 CSSM_FREE(clTbs.Data);
885 SecAsn1CoderRelease(coder);
886 return ourRtn;
887 }
888
889 /* verify root with itself using TP */
890 static int verifyRoot(
891 CSSM_TP_HANDLE tpHand,
892 CSSM_CL_HANDLE clHand,
893 CSSM_CSP_HANDLE cspHand,
894 const CSSM_DATA &cert,
895 CSSM_BOOL allowExpired,
896 CSSM_BOOL useTrustSettings,
897 CSSM_BOOL quiet)
898 {
899 BlobList blobs;
900 blobs.addBlob(cert, CSSM_TRUE);
901 int i;
902
903 const char *certStatus;
904 if(useTrustSettings) {
905 /*
906 * CSSM_CERT_STATUS_IS_IN_INPUT_CERTS
907 * CSSM_CERT_STATUS_IS_ROOT
908 * CSSM_CERT_STATUS_TRUST_SETTINGS_FOUND_SYSTEM
909 * CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST
910 */
911 certStatus = "0:0x314";
912 }
913 else {
914 /*
915 * CSSM_CERT_STATUS_IS_IN_INPUT_CERTS (new since radar 3855635 was fixed)
916 * CSSM_CERT_STATUS_IS_IN_ANCHORS
917 * CSSM_CERT_STATUS_IS_ROOT
918 */
919 certStatus = "0:0x1C";
920 }
921
922 /* try one with allowExpiredRoot false, then true on error and if so
923 * enabled to make sure we know what's going wrong */
924 CSSM_BOOL expireEnable = CSSM_FALSE;
925 for(int dex=0; dex<2; dex++) {
926 i = certVerifySimple(tpHand, clHand, cspHand,
927 blobs, // certs
928 blobs, // and roots
929 CSSM_FALSE, // useSystemAnchors
930 CSSM_TRUE, // leaf is CA
931 expireEnable,
932 CVP_Basic,
933 NULL, // SSL host
934 CSSM_FALSE, // SSL client
935 NULL, // sender email
936 0, // key use
937 NULL, // expected error str
938 0, NULL, // per-cert errors
939 1, &certStatus, // per-cert status
940 useTrustSettings,
941 quiet,
942 CSSM_FALSE); // verbose
943 if(i == 0) {
944 /* success */
945 if(dex == 1) {
946 printf("...warning: expired root detected. Be aware.\n");
947 }
948 return 0;
949 }
950 if(!allowExpired) {
951 /* no second chance */
952 return i;
953 }
954 expireEnable = CSSM_TRUE;
955 if(useTrustSettings) {
956 /* now expect EXPIRED, IS_ROOT, IS_IN_INPUT_CERTS, TRUST_SETTINGS_FOUND_SYSTEM,
957 * CSSM_CERT_STATUS_TRUST_SETTINGS_TRUST */
958 certStatus = "0:0x315";
959 }
960 else {
961 /* now expect EXPIRED, IS_ROOT, IS_IN_ANCHORS, IS_IN_INPUT_CERTS */
962 certStatus = "0:0x1d";
963 }
964 }
965 return i;
966 }
967
968
969 static int doTest(
970 CSSM_CL_HANDLE clHand,
971 CSSM_TP_HANDLE tpHand,
972 CSSM_CSP_HANDLE cspHand,
973 const CSSM_DATA &cert,
974 CSSM_BOOL allowExpired,
975 CSSM_BOOL quiet,
976 CSSM_BOOL verbose,
977 CSSM_BOOL writeBlobs,
978 CSSM_BOOL useTrustSettings)
979 {
980 /* first see if this anchor self-verifies. */
981 if(verifyRoot(tpHand, clHand, cspHand, cert, allowExpired,
982 useTrustSettings, quiet)) {
983 doPrintCert(cert);
984 printf("***This anchor does not self-verify!\n");
985 return testError(quiet);
986 }
987
988 /* have the CL parse it to the best of its ability */
989 CSSM_FIELD_PTR certFields;
990 uint32 numFields;
991 CSSM_RETURN crtn = CSSM_CL_CertGetAllFields(clHand, &cert, &numFields,
992 &certFields);
993 if(crtn) {
994 printError("CSSM_CL_CertGetAllFields", crtn);
995 doPrintCert(cert);
996 printf("***The CL can not parse this anchor!\n");
997 return testError(quiet);
998 }
999
1000 /* save, this object does the free fields when it goes out of scope */
1001 FieldArray parsed(certFields, numFields, clHand);
1002
1003 /*
1004 * We're going to build a TBSCert from these received fields.
1005 * Extensions need to be processed specially because they
1006 * come back from the CL ordered differently than they appear
1007 * in the cert.
1008 *
1009 * First make two buckets for making copies of incoming fields.
1010 */
1011 FieldArray forCreate(numFields); // for creating template
1012 FieldArray extenFields(numFields);
1013
1014 for(unsigned dex=0; dex<numFields; dex++) {
1015 CSSM_FIELD &parsedField = parsed.fieldAt(dex);
1016 FieldType type = typeForOid(parsedField.FieldOid);
1017 switch(type) {
1018 case FT_Normal:
1019 forCreate.appendField(parsedField);
1020 break;
1021 case FT_ReadOnly:
1022 case FT_NotTBS:
1023 /* ignore */
1024 break;
1025 case FT_ExtenParsed:
1026 case FT_ExtenUnknown:
1027 /* extensions, save and process later */
1028 extenFields.appendField(parsedField);
1029 break;
1030 default:
1031 doPrintCert(cert);
1032 printf("***This anchor contains an unknown field!\n");
1033 if(testError(quiet)) {
1034 return 1;
1035 }
1036 /* well let's limp along */
1037 forCreate.appendField(parsedField);
1038 break;
1039 }
1040 }
1041
1042 /* basic extension verification */
1043 if(vfyExtens(extenFields, cert, quiet)) {
1044 return 1;
1045 }
1046 return buildTbs(clHand, cert, forCreate, extenFields, quiet,
1047 verbose, writeBlobs);
1048 }
1049
1050 int main(int argc, char **argv)
1051 {
1052 CSSM_BOOL quiet = CSSM_FALSE;
1053 CSSM_BOOL verbose = CSSM_FALSE;
1054 CSSM_BOOL writeBlobs = CSSM_FALSE;
1055 CSSM_BOOL allowExpired = CSSM_FALSE;
1056 CSSM_BOOL useTrustSettings = CSSM_FALSE;
1057
1058 for(int arg=1; arg<argc; arg++) {
1059 switch(argv[arg][0]) {
1060 case 'q':
1061 quiet = CSSM_TRUE;
1062 break;
1063 case 'v':
1064 verbose = CSSM_TRUE;
1065 break;
1066 case 'w':
1067 writeBlobs = CSSM_TRUE;
1068 break;
1069 case 't':
1070 useTrustSettings = CSSM_TRUE;
1071 break;
1072 case 'e':
1073 allowExpired = CSSM_TRUE;
1074 break;
1075 default:
1076 usage(argv);
1077 }
1078 }
1079
1080 printf("Starting anchorTest; args: ");
1081 for(int i=1; i<argc; i++) {
1082 printf("%s ", argv[i]);
1083 }
1084 printf("\n");
1085
1086 /* get system anchors only; convert to CSSM */
1087 CFArrayRef cfAnchors;
1088 OSStatus ortn;
1089 CSSM_DATA *anchors;
1090 unsigned numAnchors;
1091 ortn = getSystemAnchors(&cfAnchors, &anchors, &numAnchors);
1092 if(ortn) {
1093 exit(1);
1094 }
1095 if(numAnchors < 50) {
1096 printf("***Hey! I can only find %u anchors; there should be way more than that.\n",
1097 numAnchors);
1098 exit(1);
1099 }
1100
1101 CSSM_CL_HANDLE clHand = clStartup();
1102 CSSM_TP_HANDLE tpHand = tpStartup();
1103 CSSM_CSP_HANDLE cspHand = cspStartup();
1104 if((clHand == 0) || (tpHand == 0) || (cspHand == 0)) {
1105 return 0;
1106 }
1107
1108 int rtn = 0;
1109 for(unsigned dex=0; dex<numAnchors; dex++) {
1110 if(!quiet) {
1111 printf("...anchor %u\n", dex);
1112 }
1113 rtn = doTest(clHand, tpHand, cspHand, anchors[dex], allowExpired,
1114 quiet, verbose, writeBlobs, useTrustSettings);
1115 if(rtn) {
1116 break;
1117 }
1118 }
1119 if(rtn == 0) {
1120 if(!quiet) {
1121 printf("...%s success.\n", argv[0]);
1122 }
1123 }
1124 return rtn;
1125 }