]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/signerAndSubjSsl/signerAndSubjSsl.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / signerAndSubjSsl / signerAndSubjSsl.cpp
1 /* Copyright (c) 1998-2003,2005-2006 Apple Computer, Inc.
2 *
3 * signerAndSubjSsl.c
4 *
5 * Create two certs - a root, and a subject cert signed by the root.
6 * Includes subjectAltName extension for leaf cert.
7 * This version uses CSSM_TP_SubmitCredRequest to create the certs.
8 *
9 */
10
11 #include <utilLib/common.h>
12 #include <utilLib/cspwrap.h>
13 #include <security_cdsa_utils/cuFileIo.h>
14 #include <clAppUtils/clutils.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <Security/cssm.h>
19 #include <Security/x509defs.h>
20 #include <Security/oidsattr.h>
21 #include <Security/oidscert.h>
22 #include <Security/oidsalg.h>
23 #include <Security/certextensions.h>
24 #include <Security/cssmapple.h>
25 #include <string.h>
26
27 /* key labels */
28 #define SUBJ_KEY_LABEL "subjectKey"
29 #define ROOT_KEY_LABEL "rootKey"
30
31 /* default key and signature algorithm */
32 #define SIG_ALG_DEFAULT CSSM_ALGID_SHA1WithRSA
33 #define SIG_OID_DEFAULT CSSMOID_SHA1WithRSA
34 #define KEY_ALG_DEFAULT CSSM_ALGID_RSA
35
36 /* for write certs option */
37 #define ROOT_CERT_FILE_NAME "ssRootCert.der"
38 #define SUBJ_CERT_FILE_NAME "ssSubjCert.der"
39
40 /* public key in ref form, TP supports this as of 1/30/02 */
41 #define PUB_KEY_IS_REF CSSM_TRUE
42
43 static void usage(char **argv)
44 {
45 printf("Usage: %s [options]\n", argv[0]);
46 printf("Options:\n");
47 printf(" i=IP_Address for subjectAltName\n");
48 printf(" d=dnsName for subjectAltName\n");
49 printf(" k=keySizeInBits\n");
50 printf(" q(uiet)\n");
51 exit(1);
52 }
53
54 /*
55 * RDN components for root, subject
56 */
57 CSSM_APPLE_TP_NAME_OID rootRdn[] =
58 {
59 { "Apple Computer", &CSSMOID_OrganizationName },
60 { "The Big Cheese", &CSSMOID_Title }
61 };
62 #define NUM_ROOT_NAMES (sizeof(rootRdn) / sizeof(CSSM_APPLE_TP_NAME_OID))
63
64 CSSM_APPLE_TP_NAME_OID subjRdn[] =
65 {
66 { "Apple Computer", &CSSMOID_OrganizationName },
67 { "something.org", &CSSMOID_CommonName }
68 };
69 #define NUM_SUBJ_NAMES (sizeof(subjRdn) / sizeof(CSSM_APPLE_TP_NAME_OID))
70
71 /*
72 * Convert a string containing a dotted IP address to 4 bytes.
73 * Returns nonzero on error.
74 */
75 static int convertIp(
76 const char *str,
77 uint8 *buf)
78 {
79 char cbuf[4];
80 for(unsigned dex=0; dex<3; dex++) {
81 char *nextDot = strchr(str, '.');
82 if(nextDot == NULL) {
83 return 1;
84 }
85 memmove(cbuf, str, nextDot - str);
86 *buf = atoi(cbuf);
87 buf++; // next out char
88 str = nextDot + 1; // next in char after dot
89
90 }
91 /* str points to last char */
92 if(str == NULL) {
93 return 1;
94 }
95 *buf = atoi(str);
96 return 0;
97 }
98
99 int main(int argc, char **argv)
100 {
101 CSSM_CL_HANDLE clHand; // CL handle
102 CSSM_CSP_HANDLE cspHand; // CSP handle
103 CSSM_TP_HANDLE tpHand; // TP handle
104 CSSM_DATA signedRootCert; // from CSSM_CL_CertSign
105 CSSM_DATA signedSubjCert; // from CSSM_CL_CertSign
106 CSSM_KEY subjPubKey; // subject's RSA public key blob
107 CSSM_KEY subjPrivKey; // subject's RSA private key - ref format
108 CSSM_KEY rootPubKey; // root's RSA public key blob
109 CSSM_KEY rootPrivKey; // root's RSA private key - ref format
110 CSSM_RETURN crtn;
111 int arg;
112 unsigned errorCount = 0;
113 CSSM_DATA refId; // mallocd by CSSM_TP_SubmitCredRequest
114 CSSM_APPLE_TP_CERT_REQUEST certReq;
115 CSSM_TP_REQUEST_SET reqSet;
116 sint32 estTime;
117 CSSM_BOOL confirmRequired;
118 CSSM_TP_RESULT_SET_PTR resultSet;
119 CSSM_ENCODED_CERT *encCert;
120 CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext;
121 CSSM_FIELD policyId;
122 CE_GeneralNames genNames;
123 CE_GeneralName genName;
124 uint8 ipNameBuf[4];
125
126 /* user-spec'd variables */
127 CSSM_ALGORITHMS keyAlg = KEY_ALG_DEFAULT;
128 CSSM_ALGORITHMS sigAlg = SIG_ALG_DEFAULT;
129 CSSM_OID sigOid = SIG_OID_DEFAULT;
130 uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT;
131 char *ipAddrs = NULL;
132 char *dnsName = NULL;
133 CSSM_BOOL quiet = CSSM_FALSE;
134
135 /*
136 * Two extensions. Subject has two (KeyUsage and possibly
137 * subjectAltName); root has KeyUsage and BasicConstraints.
138 */
139 CE_DataAndType rootExts[2];
140 CE_DataAndType leafExts[2];
141 unsigned numLeafExts;
142
143 for(arg=1; arg<argc; arg++) {
144 char *argp = argv[arg];
145 switch(argp[0]) {
146 case 'k':
147 keySizeInBits = atoi(&argp[2]);
148 break;
149 case 'i':
150 ipAddrs = &argp[2];
151 break;
152 case 'd':
153 dnsName = &argp[2];
154 break;
155 case 'q':
156 quiet = CSSM_TRUE;
157 break;
158 default:
159 usage(argv);
160 }
161 }
162
163 if(ipAddrs && dnsName) {
164 printf("Max of one of {ipAddrs, dnsName} at a time, please.\n");
165 usage(argv);
166 }
167 if(ipAddrs) {
168 if(convertIp(ipAddrs, ipNameBuf)) {
169 printf("**Malformed IP address. Aborting.\n");
170 exit(1);
171 }
172 }
173
174 /* connect to CL, TP, and CSP */
175 clHand = clStartup();
176 if(clHand == 0) {
177 return 0;
178 }
179 tpHand = tpStartup();
180 if(tpHand == 0) {
181 return 0;
182 }
183 cspHand = cspStartup();
184 if(cspHand == 0) {
185 return 0;
186 }
187
188 /* subsequent errors to abort: to detach */
189
190 /* cook up an RSA key pair for the subject */
191 crtn = cspGenKeyPair(cspHand,
192 keyAlg,
193 SUBJ_KEY_LABEL,
194 strlen(SUBJ_KEY_LABEL),
195 keySizeInBits,
196 &subjPubKey,
197 #if PUB_KEY_IS_REF
198 CSSM_TRUE,
199 #else
200 CSSM_FALSE, // pubIsRef - should work both ways, but not yet
201 #endif
202 CSSM_KEYUSE_VERIFY,
203 CSSM_KEYBLOB_RAW_FORMAT_NONE,
204 &subjPrivKey,
205 CSSM_TRUE, // privIsRef - doesn't matter
206 CSSM_KEYUSE_SIGN,
207 CSSM_KEYBLOB_RAW_FORMAT_NONE,
208 CSSM_FALSE);
209 if(crtn) {
210 errorCount++;
211 goto abort;
212 }
213
214 /* and the root */
215 crtn = cspGenKeyPair(cspHand,
216 keyAlg,
217 ROOT_KEY_LABEL,
218 strlen(ROOT_KEY_LABEL),
219 keySizeInBits,
220 &rootPubKey,
221 CSSM_FALSE, // pubIsRef - should work both ways, but not yet
222 CSSM_KEYUSE_VERIFY,
223 CSSM_KEYBLOB_RAW_FORMAT_NONE,
224 &rootPrivKey,
225 CSSM_TRUE, // privIsRef - doesn't matter
226 CSSM_KEYUSE_SIGN,
227 CSSM_KEYBLOB_RAW_FORMAT_NONE,
228 CSSM_FALSE);
229 if(crtn) {
230 errorCount++;
231 goto abort;
232 }
233
234 /* A KeyUsage extension for both certs */
235 rootExts[0].type = DT_KeyUsage;
236 rootExts[0].critical = CSSM_FALSE;
237 rootExts[0].extension.keyUsage =
238 CE_KU_DigitalSignature | CE_KU_KeyCertSign;
239
240 leafExts[0].type = DT_KeyUsage;
241 leafExts[0].critical = CSSM_FALSE;
242 leafExts[0].extension.keyUsage = CE_KU_DigitalSignature;
243
244 /* BasicConstraints for root only */
245 rootExts[1].type = DT_BasicConstraints;
246 rootExts[1].critical = CSSM_TRUE;
247 rootExts[1].extension.basicConstraints.cA = CSSM_TRUE;
248 rootExts[1].extension.basicConstraints.pathLenConstraintPresent =
249 CSSM_TRUE;
250 rootExts[1].extension.basicConstraints.pathLenConstraint = 2;
251
252 /* possible subjectAltName for leaf */
253 numLeafExts = 1;
254 if(ipAddrs || dnsName) {
255 numLeafExts++;
256 leafExts[1].type = DT_SubjectAltName;
257 leafExts[1].critical = CSSM_TRUE;
258
259 genName.berEncoded = CSSM_FALSE;
260 if(ipAddrs) {
261 genName.name.Data = (uint8 *)ipNameBuf;
262 genName.name.Length = 4;
263 genName.nameType = GNT_IPAddress;
264 }
265 else {
266 genName.name.Data = (uint8 *)dnsName;
267 genName.nameType = GNT_DNSName;
268 genName.name.Length = strlen(dnsName);
269 }
270 genNames.numNames = 1;
271 genNames.generalName = &genName;
272 leafExts[1].extension.subjectAltName = genNames;
273 }
274
275 /* certReq for root */
276 memset(&certReq, 0, sizeof(CSSM_APPLE_TP_CERT_REQUEST));
277 certReq.cspHand = cspHand;
278 certReq.clHand = clHand;
279 certReq.serialNumber = 0x12345678;
280 certReq.numSubjectNames = NUM_ROOT_NAMES;
281 certReq.subjectNames = rootRdn;
282 certReq.numIssuerNames = 0;
283 certReq.issuerNames = NULL;
284 certReq.certPublicKey = &rootPubKey;
285 certReq.issuerPrivateKey = &rootPrivKey;
286 certReq.signatureAlg = sigAlg;
287 certReq.signatureOid = sigOid;
288 certReq.notBefore = 0; // now
289 certReq.notAfter = 10000; // seconds from now
290 certReq.numExtensions = 2;
291 certReq.extensions = rootExts;
292
293 reqSet.NumberOfRequests = 1;
294 reqSet.Requests = &certReq;
295
296 /* a big CSSM_TP_CALLERAUTH_CONTEXT just to specify an OID */
297 memset(&CallerAuthContext, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
298 memset(&policyId, 0, sizeof(CSSM_FIELD));
299 policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN;
300 CallerAuthContext.Policy.NumberOfPolicyIds = 1;
301 CallerAuthContext.Policy.PolicyIds = &policyId;
302
303 /* generate root cert */
304 crtn = CSSM_TP_SubmitCredRequest(tpHand,
305 NULL, // PreferredAuthority
306 CSSM_TP_AUTHORITY_REQUEST_CERTISSUE,
307 &reqSet,
308 &CallerAuthContext,
309 &estTime,
310 &refId);
311 if(crtn) {
312 printError("CSSM_TP_SubmitCredRequest", crtn);
313 errorCount++;
314 goto abort;
315 }
316 crtn = CSSM_TP_RetrieveCredResult(tpHand,
317 &refId,
318 NULL, // CallerAuthCredentials
319 &estTime,
320 &confirmRequired,
321 &resultSet);
322 if(crtn) {
323 printError("CSSM_TP_RetrieveCredResult", crtn);
324 errorCount++;
325 goto abort;
326 }
327 if(resultSet == NULL) {
328 printf("***CSSM_TP_RetrieveCredResult returned NULL result set.\n");
329 errorCount++;
330 goto abort;
331 }
332 encCert = (CSSM_ENCODED_CERT *)resultSet->Results;
333 signedRootCert = encCert->CertBlob;
334
335 writeFile(ROOT_CERT_FILE_NAME, signedRootCert.Data,
336 signedRootCert.Length);
337 if(!quiet) {
338 printf("...wrote %lu bytes to %s\n", signedRootCert.Length,
339 ROOT_CERT_FILE_NAME);
340 }
341
342 /* now a subject cert signed by the root cert */
343 certReq.serialNumber = 0x8765;
344 certReq.numSubjectNames = NUM_SUBJ_NAMES;
345 certReq.subjectNames = subjRdn;
346 certReq.numIssuerNames = NUM_ROOT_NAMES;
347 certReq.issuerNames = rootRdn;
348 certReq.certPublicKey = &subjPubKey;
349 certReq.issuerPrivateKey = &rootPrivKey;
350 certReq.numExtensions = numLeafExts;
351 certReq.extensions = leafExts;
352
353 crtn = CSSM_TP_SubmitCredRequest(tpHand,
354 NULL, // PreferredAuthority
355 CSSM_TP_AUTHORITY_REQUEST_CERTISSUE,
356 &reqSet,
357 &CallerAuthContext,
358 &estTime,
359 &refId);
360 if(crtn) {
361 printError("CSSM_TP_SubmitCredRequest (2)", crtn);
362 errorCount++;
363 goto abort;
364 }
365 crtn = CSSM_TP_RetrieveCredResult(tpHand,
366 &refId,
367 NULL, // CallerAuthCredentials
368 &estTime,
369 &confirmRequired,
370 &resultSet); // leaks.....
371 if(crtn) {
372 printError("CSSM_TP_RetrieveCredResult (2)", crtn);
373 errorCount++;
374 goto abort;
375 }
376 if(resultSet == NULL) {
377 printf("***CSSM_TP_RetrieveCredResult (2) returned NULL result set.\n");
378 errorCount++;
379 goto abort;
380 }
381 encCert = (CSSM_ENCODED_CERT *)resultSet->Results;
382 signedSubjCert = encCert->CertBlob;
383
384 writeFile(SUBJ_CERT_FILE_NAME, signedSubjCert.Data,
385 signedSubjCert.Length);
386 if(!quiet) {
387 printf("...wrote %lu bytes to %s\n", signedSubjCert.Length,
388 SUBJ_CERT_FILE_NAME);
389 }
390
391 /* free/delete certs and keys */
392 appFreeCssmData(&signedSubjCert, CSSM_FALSE);
393 appFreeCssmData(&signedRootCert, CSSM_FALSE);
394
395 cspFreeKey(cspHand, &rootPubKey);
396 cspFreeKey(cspHand, &subjPubKey);
397
398 abort:
399 if(cspHand != 0) {
400 CSSM_ModuleDetach(cspHand);
401 }
402 if(clHand != 0) {
403 CSSM_ModuleDetach(clHand);
404 }
405 if(tpHand != 0) {
406 CSSM_ModuleDetach(tpHand);
407 }
408
409 return 0;
410 }
411
412