]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/certSerialEncodeTest/certSerialEncodeTest.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / certSerialEncodeTest / certSerialEncodeTest.cpp
1 /* Copyright (c) 2006 Apple Computer, Inc.
2 *
3 * certSerialEncodeTest.cpp
4 *
5 * Verify proper encoding of unsigned integer as a DER_encoded signed integer.
6 * Verifies Radar 4471281.
7 *
8 */
9
10 #include <utilLib/common.h>
11 #include <utilLib/cspwrap.h>
12 #include <security_cdsa_utils/cuFileIo.h>
13 #include <clAppUtils/clutils.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <Security/cssm.h>
18 #include <Security/x509defs.h>
19 #include <Security/oidsattr.h>
20 #include <Security/oidscert.h>
21 #include <Security/oidsalg.h>
22 #include <Security/certextensions.h>
23 #include <Security/cssmapple.h>
24 #include <string.h>
25
26 #define SUBJ_KEY_LABEL "subjectKey"
27 #define ROOT_KEY_LABEL "rootKey"
28 /* default key and signature algorithm */
29 #define SIG_ALG_DEFAULT CSSM_ALGID_SHA1WithRSA
30 #define SIG_OID_DEFAULT CSSMOID_SHA1WithRSA
31 #define KEY_ALG_DEFAULT CSSM_ALGID_RSA
32
33 /* for write certs/keys option */
34 #define ROOT_CERT_FILE_NAME "ssRootCert.cer"
35 #define SUBJ_CERT_FILE_NAME "ssSubjCert.cer"
36
37 /* public key in ref form, TP supports this as of 1/30/02 */
38 #define PUB_KEY_IS_REF CSSM_TRUE
39
40 static void usage(char **argv)
41 {
42 printf("Usage: %s [options]\n", argv[0]);
43 printf("Options:\n");
44 printf(" w[rite certs]\n");
45 printf(" p(ause for MallocDebug)\n");
46 printf(" q(uiet)\n");
47 exit(1);
48 }
49
50 /*
51 * RDN components
52 */
53 static CSSM_APPLE_TP_NAME_OID rootRdn[] =
54 {
55 { "Apple Computer", &CSSMOID_OrganizationName },
56 { "The Big Cheesy Debug Root", &CSSMOID_CommonName }
57 };
58 #define NUM_ROOT_NAMES (sizeof(rootRdn) / sizeof(CSSM_APPLE_TP_NAME_OID))
59
60 /* test cases */
61 typedef struct {
62 uint32 serialIn; /* --> CSSM_TP_SubmitCredRequest */
63 CSSM_SIZE expectLen;
64 const uint8 *expect;
65 } SerialNumber;
66
67 /* 0x7f */
68 static const uint8 sn0_Data[1] = {0x7f};
69 static const SerialNumber sn0 = {0x7f, 1, sn0_Data };
70
71 /* 0x80 */
72 static const uint8 sn1_Data[2] = {0x00, 0x80};
73 static const SerialNumber sn1 = {0x80, 2, sn1_Data };
74
75 /* 0x7ff */
76 static const uint8 sn2_Data[2] = {0x07, 0xff};
77 static const SerialNumber sn2 = {0x7ff, 2, sn2_Data };
78
79 /* 0x80ff */
80 static const uint8 sn3_Data[3] = {0x00, 0x80, 0xff};
81 static const SerialNumber sn3 = {0x80ff, 3, sn3_Data };
82
83 /* 0xfffffff */
84 static const uint8 sn4_Data[4] = {0x0f, 0xff, 0xff, 0xff};
85 static const SerialNumber sn4 = {0xfffffff, 4, sn4_Data };
86
87 /* 0x0fffffff */
88 static const uint8 sn5_Data[4] = {0x0f, 0xff, 0xff, 0xff};
89 static const SerialNumber sn5 = {0x0fffffff, 4, sn5_Data };
90
91 /* 0x80000000 */
92 static const uint8 sn6_Data[5] = {0x00, 0x80, 0x00, 0x00, 0x00};
93 static const SerialNumber sn6 = {0x80000000, 5, sn6_Data };
94
95 static const SerialNumber *serialNumbers[] = {
96 &sn0, &sn1, &sn2, &sn3, &sn4, &sn5, &sn6
97 };
98 #define NUM_SERIAL_NUMS (sizeof(serialNumbers) / sizeof(serialNumbers[0]))
99
100 static int doTest(
101 CSSM_CL_HANDLE clHand, // CL handle
102 CSSM_CSP_HANDLE cspHand, // CSP handle
103 CSSM_TP_HANDLE tpHand, // TP handle
104 CSSM_KEY_PTR subjPubKey,
105 CSSM_KEY_PTR signerPrivKey,
106 uint32 serialNumIn,
107 CSSM_SIZE serialNumExpLen,
108 const uint8 *serialNumExp,
109 CSSM_BOOL quiet,
110 CSSM_BOOL writeBlobs)
111 {
112 CSSM_DATA refId; // mallocd by CSSM_TP_SubmitCredRequest
113 CSSM_APPLE_TP_CERT_REQUEST certReq;
114 CSSM_TP_REQUEST_SET reqSet;
115 sint32 estTime;
116 CSSM_BOOL confirmRequired;
117 CSSM_TP_RESULT_SET_PTR resultSet;
118 CSSM_ENCODED_CERT *encCert;
119 CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext;
120 CSSM_FIELD policyId;
121 CSSM_RETURN crtn;
122 CSSM_DATA *signedRootCert;
123 int ourRtn = 0;
124 CSSM_DATA_PTR foundSerial = NULL;
125 CSSM_HANDLE resultHand = 0;
126 uint32 numFields;
127
128 /* certReq for root */
129 memset(&certReq, 0, sizeof(CSSM_APPLE_TP_CERT_REQUEST));
130 certReq.cspHand = cspHand;
131 certReq.clHand = clHand;
132 certReq.serialNumber = serialNumIn;
133 certReq.numSubjectNames = NUM_ROOT_NAMES;
134 certReq.subjectNames = rootRdn;
135 certReq.numIssuerNames = 0;
136 certReq.issuerNames = NULL;
137 certReq.certPublicKey = subjPubKey;
138 certReq.issuerPrivateKey = signerPrivKey;
139 certReq.signatureAlg = CSSM_ALGID_SHA1WithRSA;
140 certReq.signatureOid = CSSMOID_SHA1WithRSA;
141 certReq.notBefore = 0; // now
142 certReq.notAfter = 10000; // seconds from now
143 certReq.numExtensions = 0;
144 certReq.extensions = NULL;
145
146 reqSet.NumberOfRequests = 1;
147 reqSet.Requests = &certReq;
148
149 /* a big CSSM_TP_CALLERAUTH_CONTEXT just to specify an OID */
150 memset(&CallerAuthContext, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
151 memset(&policyId, 0, sizeof(CSSM_FIELD));
152 policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN;
153 CallerAuthContext.Policy.NumberOfPolicyIds = 1;
154 CallerAuthContext.Policy.PolicyIds = &policyId;
155
156 /* generate root cert */
157 if(!quiet) {
158 printf("Creating root cert...\n");
159 }
160 crtn = CSSM_TP_SubmitCredRequest(tpHand,
161 NULL, // PreferredAuthority
162 CSSM_TP_AUTHORITY_REQUEST_CERTISSUE,
163 &reqSet,
164 &CallerAuthContext,
165 &estTime,
166 &refId);
167 if(crtn) {
168 printError("CSSM_TP_SubmitCredRequest", crtn);
169 ourRtn = -1;
170 goto errOut;
171 }
172 crtn = CSSM_TP_RetrieveCredResult(tpHand,
173 &refId,
174 NULL, // CallerAuthCredentials
175 &estTime,
176 &confirmRequired,
177 &resultSet);
178 if(crtn) {
179 printError("CSSM_TP_RetrieveCredResult", crtn);
180 ourRtn = -1;
181 goto errOut;
182 }
183 if(resultSet == NULL) {
184 printf("***CSSM_TP_RetrieveCredResult returned NULL result set.\n");
185 ourRtn = -1;
186 goto errOut;
187 }
188 encCert = (CSSM_ENCODED_CERT *)resultSet->Results;
189 signedRootCert = &encCert->CertBlob;
190 if(writeBlobs) {
191 writeFile(ROOT_CERT_FILE_NAME, signedRootCert->Data, signedRootCert->Length);
192 printf("...wrote %lu bytes to %s\n", signedRootCert->Length,
193 ROOT_CERT_FILE_NAME);
194 }
195
196 /* make sure it self-verifies */
197 crtn = CSSM_CL_CertVerify(clHand, 0 /* CCHandle */,
198 signedRootCert, signedRootCert,
199 NULL, 0);
200 if(crtn) {
201 cssmPerror("CSSM_CL_CertVerify", crtn);
202 printf("***Created cert does not self-verify\n");
203 ourRtn = -1;
204 goto errOut;
205 }
206
207 /* extract the field we're interested in verifying */
208 crtn = CSSM_CL_CertGetFirstFieldValue(clHand, signedRootCert,
209 &CSSMOID_X509V1SerialNumber, &resultHand, &numFields, &foundSerial);
210 if(crtn) {
211 cssmPerror("CSSM_CL_CertGetFirstFieldValue(serialNumber)", crtn);
212 printf("***Can't obtain serial number\n");
213 ourRtn = -1;
214 goto errOut;
215 }
216 CSSM_CL_CertAbortQuery(clHand, resultHand);
217 if(foundSerial->Length != serialNumExpLen) {
218 printf("***expected serialNumber len 0x%lu, got 0x%lu\n",
219 (unsigned long)serialNumExpLen, (unsigned long)foundSerial->Length);
220 ourRtn = -1;
221 goto errOut;
222 }
223 for(unsigned dex=0; dex<serialNumExpLen; dex++) {
224 if(foundSerial->Data[dex] != serialNumExp[dex]) {
225 printf("***SerialNumber mismatch at index %u: exp %02X got %02X\n",
226 dex, (unsigned)serialNumExp[dex],
227 (unsigned)foundSerial->Data[dex]);
228 ourRtn = -1;
229 }
230 }
231 /* free retrieved serial number and the result set itself */
232 CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SerialNumber, foundSerial);
233 CSSM_FREE(signedRootCert->Data);
234 CSSM_FREE(encCert);
235 CSSM_FREE(resultSet);
236 /* Per the spec, this is supposed to be Opaque to us and the TP is supposed to free
237 * it when it goes out of scope...but libsecurity_keychains's
238 * CertificateRequest::submitDotMac() frees this...that would have to change
239 * in order for the TP to free this properly. Someday maybe. No big deal.
240 */
241 CSSM_FREE(refId.Data);
242 errOut:
243 return ourRtn;
244 }
245
246 int main(int argc, char **argv)
247 {
248 CSSM_CL_HANDLE clHand; // CL handle
249 CSSM_CSP_HANDLE cspHand; // CSP handle
250 CSSM_TP_HANDLE tpHand; // TP handle
251 CSSM_KEY rootPubKey; // root's RSA public key blob
252 CSSM_KEY rootPrivKey; // root's RSA private key - ref format
253 CSSM_RETURN crtn;
254 int arg;
255 unsigned dex;
256 int ourRtn = 0;
257 uint32 keySizeInBits = 512;
258 CSSM_BOOL doPause = CSSM_FALSE;
259
260 /* user-spec'd variables */
261 CSSM_BOOL writeBlobs = CSSM_FALSE;
262 CSSM_BOOL quiet = CSSM_FALSE;
263
264 for(arg=1; arg<argc; arg++) {
265 switch(argv[arg][0]) {
266 case 'w':
267 writeBlobs = CSSM_TRUE;
268 break;
269 case 'q':
270 quiet = CSSM_TRUE;
271 break;
272 case 'p':
273 doPause = CSSM_TRUE;
274 break;
275 default:
276 usage(argv);
277 }
278 }
279
280 testStartBanner("certSerialEncodeTest", argc, argv);
281
282
283 /* connect to CL, TP, and CSP */
284 clHand = clStartup();
285 if(clHand == 0) {
286 return -1;
287 }
288 tpHand = tpStartup();
289 if(tpHand == 0) {
290 return -1;
291 }
292 cspHand = cspStartup();
293 if(cspHand == 0) {
294 return -1;
295 }
296
297 /* cook up key pair for self-signed cert */
298 crtn = cspGenKeyPair(cspHand,
299 CSSM_ALGID_RSA,
300 ROOT_KEY_LABEL,
301 strlen(ROOT_KEY_LABEL),
302 keySizeInBits,
303 &rootPubKey,
304 CSSM_FALSE, // pubIsRef - should work both ways, but not yet
305 CSSM_KEYUSE_VERIFY,
306 CSSM_KEYBLOB_RAW_FORMAT_NONE,
307 &rootPrivKey,
308 writeBlobs ? CSSM_FALSE : CSSM_TRUE, // privIsRef
309 CSSM_KEYUSE_SIGN,
310 CSSM_KEYBLOB_RAW_FORMAT_NONE,
311 CSSM_FALSE);
312 if(crtn) {
313 ourRtn = -1;
314 goto abort;
315 }
316
317 for(dex=0; dex<NUM_SERIAL_NUMS; dex++) {
318 const SerialNumber *sn = serialNumbers[dex];
319 if(!quiet) {
320 printf("...testing serial number 0x%lx\n", (unsigned long)sn->serialIn);
321 }
322 ourRtn = doTest(clHand, cspHand, tpHand,
323 &rootPubKey, &rootPrivKey,
324 sn->serialIn, sn->expectLen, sn->expect,
325 quiet, writeBlobs);
326 if(ourRtn) {
327 break;
328 }
329 if(doPause) {
330 fpurge(stdin);
331 printf("Pausing for MallocDebug. a to abort, anything else to continue: ");
332 if(getchar() == 'a') {
333 break;
334 }
335 }
336 }
337
338 cspFreeKey(cspHand, &rootPubKey);
339 cspFreeKey(cspHand, &rootPrivKey);
340
341 abort:
342 if(cspHand != 0) {
343 CSSM_ModuleDetach(cspHand);
344 }
345 if(clHand != 0) {
346 CSSM_ModuleDetach(clHand);
347 }
348 if(tpHand != 0) {
349 CSSM_ModuleDetach(tpHand);
350 }
351
352 if((ourRtn == 0) && !quiet) {
353 printf("certSerialEncodeTest test succeeded\n");
354 }
355 return ourRtn;
356 }
357
358