1 /* Copyright (c) 2006 Apple Computer, Inc.
3 * certSerialEncodeTest.cpp
5 * Verify proper encoding of unsigned integer as a DER_encoded signed integer.
6 * Verifies Radar 4471281.
10 #include <utilLib/common.h>
11 #include <utilLib/cspwrap.h>
12 #include <security_cdsa_utils/cuFileIo.h>
13 #include <clAppUtils/clutils.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>
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
33 /* for write certs/keys option */
34 #define ROOT_CERT_FILE_NAME "ssRootCert.cer"
35 #define SUBJ_CERT_FILE_NAME "ssSubjCert.cer"
37 /* public key in ref form, TP supports this as of 1/30/02 */
38 #define PUB_KEY_IS_REF CSSM_TRUE
40 static void usage(char **argv
)
42 printf("Usage: %s [options]\n", argv
[0]);
44 printf(" w[rite certs]\n");
45 printf(" p(ause for MallocDebug)\n");
53 static CSSM_APPLE_TP_NAME_OID rootRdn
[] =
55 { "Apple Computer", &CSSMOID_OrganizationName
},
56 { "The Big Cheesy Debug Root", &CSSMOID_CommonName
}
58 #define NUM_ROOT_NAMES (sizeof(rootRdn) / sizeof(CSSM_APPLE_TP_NAME_OID))
62 uint32 serialIn
; /* --> CSSM_TP_SubmitCredRequest */
68 static const uint8 sn0_Data
[1] = {0x7f};
69 static const SerialNumber sn0
= {0x7f, 1, sn0_Data
};
72 static const uint8 sn1_Data
[2] = {0x00, 0x80};
73 static const SerialNumber sn1
= {0x80, 2, sn1_Data
};
76 static const uint8 sn2_Data
[2] = {0x07, 0xff};
77 static const SerialNumber sn2
= {0x7ff, 2, sn2_Data
};
80 static const uint8 sn3_Data
[3] = {0x00, 0x80, 0xff};
81 static const SerialNumber sn3
= {0x80ff, 3, sn3_Data
};
84 static const uint8 sn4_Data
[4] = {0x0f, 0xff, 0xff, 0xff};
85 static const SerialNumber sn4
= {0xfffffff, 4, sn4_Data
};
88 static const uint8 sn5_Data
[4] = {0x0f, 0xff, 0xff, 0xff};
89 static const SerialNumber sn5
= {0x0fffffff, 4, sn5_Data
};
92 static const uint8 sn6_Data
[5] = {0x00, 0x80, 0x00, 0x00, 0x00};
93 static const SerialNumber sn6
= {0x80000000, 5, sn6_Data
};
95 static const SerialNumber
*serialNumbers
[] = {
96 &sn0
, &sn1
, &sn2
, &sn3
, &sn4
, &sn5
, &sn6
98 #define NUM_SERIAL_NUMS (sizeof(serialNumbers) / sizeof(serialNumbers[0]))
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
,
107 CSSM_SIZE serialNumExpLen
,
108 const uint8
*serialNumExp
,
110 CSSM_BOOL writeBlobs
)
112 CSSM_DATA refId
; // mallocd by CSSM_TP_SubmitCredRequest
113 CSSM_APPLE_TP_CERT_REQUEST certReq
;
114 CSSM_TP_REQUEST_SET reqSet
;
116 CSSM_BOOL confirmRequired
;
117 CSSM_TP_RESULT_SET_PTR resultSet
;
118 CSSM_ENCODED_CERT
*encCert
;
119 CSSM_TP_CALLERAUTH_CONTEXT CallerAuthContext
;
122 CSSM_DATA
*signedRootCert
;
124 CSSM_DATA_PTR foundSerial
= NULL
;
125 CSSM_HANDLE resultHand
= 0;
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
;
146 reqSet
.NumberOfRequests
= 1;
147 reqSet
.Requests
= &certReq
;
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
;
156 /* generate root cert */
158 printf("Creating root cert...\n");
160 crtn
= CSSM_TP_SubmitCredRequest(tpHand
,
161 NULL
, // PreferredAuthority
162 CSSM_TP_AUTHORITY_REQUEST_CERTISSUE
,
168 printError("CSSM_TP_SubmitCredRequest", crtn
);
172 crtn
= CSSM_TP_RetrieveCredResult(tpHand
,
174 NULL
, // CallerAuthCredentials
179 printError("CSSM_TP_RetrieveCredResult", crtn
);
183 if(resultSet
== NULL
) {
184 printf("***CSSM_TP_RetrieveCredResult returned NULL result set.\n");
188 encCert
= (CSSM_ENCODED_CERT
*)resultSet
->Results
;
189 signedRootCert
= &encCert
->CertBlob
;
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
);
196 /* make sure it self-verifies */
197 crtn
= CSSM_CL_CertVerify(clHand
, 0 /* CCHandle */,
198 signedRootCert
, signedRootCert
,
201 cssmPerror("CSSM_CL_CertVerify", crtn
);
202 printf("***Created cert does not self-verify\n");
207 /* extract the field we're interested in verifying */
208 crtn
= CSSM_CL_CertGetFirstFieldValue(clHand
, signedRootCert
,
209 &CSSMOID_X509V1SerialNumber
, &resultHand
, &numFields
, &foundSerial
);
211 cssmPerror("CSSM_CL_CertGetFirstFieldValue(serialNumber)", crtn
);
212 printf("***Can't obtain serial number\n");
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
);
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
]);
231 /* free retrieved serial number and the result set itself */
232 CSSM_CL_FreeFieldValue(clHand
, &CSSMOID_X509V1SerialNumber
, foundSerial
);
233 CSSM_FREE(signedRootCert
->Data
);
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.
241 CSSM_FREE(refId
.Data
);
246 int main(int argc
, char **argv
)
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
257 uint32 keySizeInBits
= 512;
258 CSSM_BOOL doPause
= CSSM_FALSE
;
260 /* user-spec'd variables */
261 CSSM_BOOL writeBlobs
= CSSM_FALSE
;
262 CSSM_BOOL quiet
= CSSM_FALSE
;
264 for(arg
=1; arg
<argc
; arg
++) {
265 switch(argv
[arg
][0]) {
267 writeBlobs
= CSSM_TRUE
;
280 testStartBanner("certSerialEncodeTest", argc
, argv
);
283 /* connect to CL, TP, and CSP */
284 clHand
= clStartup();
288 tpHand
= tpStartup();
292 cspHand
= cspStartup();
297 /* cook up key pair for self-signed cert */
298 crtn
= cspGenKeyPair(cspHand
,
301 strlen(ROOT_KEY_LABEL
),
304 CSSM_FALSE
, // pubIsRef - should work both ways, but not yet
306 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
308 writeBlobs
? CSSM_FALSE
: CSSM_TRUE
, // privIsRef
310 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
317 for(dex
=0; dex
<NUM_SERIAL_NUMS
; dex
++) {
318 const SerialNumber
*sn
= serialNumbers
[dex
];
320 printf("...testing serial number 0x%lx\n", (unsigned long)sn
->serialIn
);
322 ourRtn
= doTest(clHand
, cspHand
, tpHand
,
323 &rootPubKey
, &rootPrivKey
,
324 sn
->serialIn
, sn
->expectLen
, sn
->expect
,
331 printf("Pausing for MallocDebug. a to abort, anything else to continue: ");
332 if(getchar() == 'a') {
338 cspFreeKey(cspHand
, &rootPubKey
);
339 cspFreeKey(cspHand
, &rootPrivKey
);
343 CSSM_ModuleDetach(cspHand
);
346 CSSM_ModuleDetach(clHand
);
349 CSSM_ModuleDetach(tpHand
);
352 if((ourRtn
== 0) && !quiet
) {
353 printf("certSerialEncodeTest test succeeded\n");