1/* Copyright (c) 1998,2005-2006 Apple Computer, Inc.
2 *
3 * makeCertPolicy.cpp - create a self signed cert with a Cert Policies extension
4 */
5
6#include <utilLib/common.h>
7#include <utilLib/cspwrap.h>
8#include <security_cdsa_utils/cuFileIo.h>
9#include <clAppUtils/CertBuilderApp.h>
10#include <clAppUtils/clutils.h>
11#include <stdlib.h>
12#include <stdio.h>
13#include <string.h>
14#include <Security/cssm.h>
15#include <Security/x509defs.h>
16#include <Security/oidsattr.h>
17#include <Security/oidscert.h>
18#include <Security/oidsalg.h>
19#include <Security/certextensions.h>
20#include <Security/cssmapple.h>
21#include <string.h>
22
23#define ROOT_KEY_LABEL		"rootKey"
24/* default key and signature algorithm */
25#define SIG_ALG_DEFAULT		CSSM_ALGID_SHA1WithRSA
26#define KEY_ALG_DEFAULT		CSSM_ALGID_RSA
27
28#define CPS_URI				"http://www.foo.com"
29
30static void usage(char **argv)
31{
32	printf("Usage: %s outFileName\n", argv[0]);
33	exit(1);
34}
35
36/*
37 * RDN components for root, subject
38 */
39CB_NameOid rootRdn[] =
40{
41	{ "Apple Computer DEBUG",			&CSSMOID_OrganizationName },
42	{ "Cert Policy Demo",				&CSSMOID_CommonName }
43};
44#define NUM_ROOT_NAMES	(sizeof(rootRdn) / sizeof(CB_NameOid))
45
46int main(int argc, char **argv)
47{
48	CSSM_CL_HANDLE	clHand;			// CL handle
49	CSSM_X509_NAME	*rootName;
50	CSSM_X509_TIME	*notBefore;		// UTC-style "not before" time
51	CSSM_X509_TIME	*notAfter;		// UTC-style "not after" time
52	CSSM_DATA_PTR	rawCert;		// from CSSM_CL_CertCreateTemplate
53	CSSM_DATA		signedRootCert;	// from CSSM_CL_CertSign
54	CSSM_CSP_HANDLE	cspHand;		// CSP handle
55	CSSM_KEY		rootPubKey;		// root's RSA public key blob
56	CSSM_KEY		rootPrivKey;	// root's RSA private key - ref format
57	CSSM_RETURN		crtn;
58	CSSM_CC_HANDLE	signContext;	// for signing/verifying the cert
59
60	/* user-spec'd variables */
61	const			char *outFileName;
62
63	if(argc != 2) {
64		usage(argv);
65	}
66	outFileName = argv[1];
67
68	/*
69	 * One extensions.
70	 */
71	CSSM_X509_EXTENSION 	ext;
72	CE_CertPolicies			cp;
73	CE_PolicyInformation	cpi;
74	CE_PolicyQualifierInfo	cpqi;
75
76	/* connect to CL and CSP */
77	clHand = clStartup();
78	if(clHand == 0) {
79		return 0;
80	}
81	cspHand = cspStartup();
82	if(cspHand == 0) {
83		return 0;
84	}
85
86	/* subsequent errors to abort: to detach */
87
88	/* cook up an RSA key pair */
89	crtn = cspGenKeyPair(cspHand,
90		KEY_ALG_DEFAULT,
91		ROOT_KEY_LABEL,
92		strlen(ROOT_KEY_LABEL),
93		512,
94		&rootPubKey,
95		CSSM_FALSE,			// pubIsRef - should work both ways, but not yet
96		CSSM_KEYUSE_VERIFY,
97		CSSM_KEYBLOB_RAW_FORMAT_NONE,
98		&rootPrivKey,
99		CSSM_FALSE,			// privIsRef
100		CSSM_KEYUSE_SIGN,
101		CSSM_KEYBLOB_RAW_FORMAT_NONE,
102		CSSM_FALSE);
103	if(crtn) {
104		printf("Error creatingt key pair, aborting.\n");
105		exit(1);
106	}
107
108	/*
109	 * Cook up various cert fields.
110	 * First, the RDNs for subject and issuer.
111	 */
112	rootName = CB_BuildX509Name(rootRdn, NUM_ROOT_NAMES);
113	if(rootName == NULL) {
114		printf("CB_BuildX509Name failure");
115		exit(1);
116	}
117
118	/* not before/after in generalized time format */
119	notBefore = CB_BuildX509Time(0);
120	notAfter  = CB_BuildX509Time(10000);
121
122	/* Here's what we do */
123	ext.extnId = CSSMOID_CertificatePolicies;
124	ext.critical = CSSM_FALSE;
125	ext.format = CSSM_X509_DATAFORMAT_PARSED;
126
127	cpqi.policyQualifierId = CSSMOID_QT_CPS;
128	cpqi.qualifier.Data = (uint8 *)CPS_URI;
129	cpqi.qualifier.Length = strlen(CPS_URI);
130
131	cpi.certPolicyId = CSSMOID_APPLE_CERT_POLICY;	/* what I'm testing today */
132	cpi.numPolicyQualifiers = 1;
133	cpi.policyQualifiers = &cpqi;
134
135	cp.numPolicies = 1;
136	cp.policies = &cpi;
137
138	ext.value.parsedValue = &cp;
139	ext.BERvalue.Data = NULL;
140	ext.BERvalue.Length = 0;
141
142	/* cook up root cert */
143	printf("Creating root cert...\n");
144	rawCert = CB_MakeCertTemplate(clHand,
145		0x12345678,			// serial number
146		rootName,
147		rootName,
148		notBefore,
149		notAfter,
150		&rootPubKey,
151		SIG_ALG_DEFAULT,
152		NULL,				// subjUniqueId
153		NULL,				// issuerUniqueId
154		&ext,				// extensions
155		1);					// numExtensions
156
157	if(rawCert == NULL) {
158		printf("CB_MakeCertTemplate failure");
159		exit(1);
160	}
161	/* Self-sign */
162	crtn = CSSM_CSP_CreateSignatureContext(cspHand,
163			SIG_ALG_DEFAULT,
164			NULL,			// AccessCred
165			&rootPrivKey,
166			&signContext);
167	if(crtn) {
168		printError("CSSM_CSP_CreateSignatureContext", crtn);
169		exit(1);
170	}
171	signedRootCert.Data = NULL;
172	signedRootCert.Length = 0;
173	crtn = CSSM_CL_CertSign(clHand,
174		signContext,
175		rawCert,			// CertToBeSigned
176		NULL,				// SignScope
177		0,					// ScopeSize,
178		&signedRootCert);
179	if(crtn) {
180		printError("CSSM_CL_CertSign", crtn);
181		exit(1);
182	}
183	crtn = CSSM_DeleteContext(signContext);
184	if(crtn) {
185		printError("CSSM_DeleteContext", crtn);
186		exit(1);
187	}
188	appFreeCssmData(rawCert, CSSM_TRUE);
189	writeFile(outFileName, signedRootCert.Data, signedRootCert.Length);
190	printf("...wrote %lu bytes to %s\n", signedRootCert.Length, outFileName);
191
192	/* Free the stuff we allocd to get here */
193	CB_FreeX509Name(rootName);
194	CB_FreeX509Time(notBefore);
195	CB_FreeX509Time(notAfter);
196	appFreeCssmData(&signedRootCert, CSSM_FALSE);
197
198	cspFreeKey(cspHand, &rootPubKey);
199	cspFreeKey(cspHand, &rootPrivKey);
200	return 0;
201}
202
203