File: | s/cmd/crmftest/testcrmf.c |
Warning: | line 1241, column 19 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* This Source Code Form is subject to the terms of the Mozilla Public | |||
2 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |||
4 | ||||
5 | /* | |||
6 | * This program does 5 separate functions. By default, it does them all. | |||
7 | * It can be told to do any subset of them. | |||
8 | * It does them in this order: | |||
9 | * | |||
10 | * 1. Generate file of CRMF cert requests. | |||
11 | * Generates 2 keys pairs, one for signing, one for encryption. | |||
12 | * Can generate RSA or DSA (XXX - DSA is only useful for signing). | |||
13 | * Generate a cert request for each of the two public keys. | |||
14 | * Generate a single CRMF cert request message that requests both certs. | |||
15 | * Leave the generated CRMF request message in file | |||
16 | * configdir/CertReqMessages.der | |||
17 | * | |||
18 | * 2. Decode CRMF Request(s) Message. | |||
19 | * Reads in the file configdir/CertReqMessages.der | |||
20 | * (either generated by step 1 above, or user supplied). | |||
21 | * Decodes it. NOTHING MORE. Drops these decoded results on the floor. | |||
22 | * The CMMF response (below) contains a completely unrelated cert. :-( | |||
23 | * | |||
24 | * 3. CMMF "Stuff". | |||
25 | * a) Generates a CMMF response, containing a single cert chain, as if | |||
26 | * it was a response to a received CRMF request. But the cert is | |||
27 | * simply a user cert from the user's local soft token, whose | |||
28 | * nickname is given in the -p option. The CMMF response has no | |||
29 | * relationship to the request generated above. The CMMF message | |||
30 | * is placed in configdir/CertRepContent.der. | |||
31 | * b) Decodes the newly generated CMMF response found in file | |||
32 | * configdir/CertRepContent.der and discards the result. 8-/ | |||
33 | * c) Generate a CMMF Key Escrow message | |||
34 | * needs 2 nicknames: | |||
35 | * It takes the public and private keys for the cert identified | |||
36 | * by -p nickname, and wraps them with a sym key that is in turn | |||
37 | * wrapped with the pubkey in the CA cert, whose nickname is | |||
38 | * given with the -s option. | |||
39 | * Store the message in configdir/KeyRecRepContent.der | |||
40 | * d) Decode the CMMF Key Escrow message generated just above. | |||
41 | * Get it from file configdir/KeyRecRepContent.der | |||
42 | * This is just a decoder test. Results are discarded. | |||
43 | * | |||
44 | * 4. Key Recovery | |||
45 | * This code does not yet compile, and what it was intended to do | |||
46 | * has not been fully determined. | |||
47 | * | |||
48 | * 5. Challenge/Response. | |||
49 | * Haven't analyzed this code yet. | |||
50 | * | |||
51 | * | |||
52 | */ | |||
53 | ||||
54 | /* KNOWN BUGS: | |||
55 | ** 1. generates BOTH signing and encryption cert requests, even for DSA keys. | |||
56 | ** | |||
57 | ** 2. Does not verify the siganture in the "Proof of Posession" in the | |||
58 | ** decoded cert requests. It only checks syntax of the POP. | |||
59 | ** 3. CMMF "Stuff" should be broken up into separate steps, each of | |||
60 | ** which may be optionally selected. | |||
61 | */ | |||
62 | ||||
63 | #include <stdio.h> | |||
64 | #include "nspr.h" | |||
65 | #include "nss.h" | |||
66 | #include "crmf.h" | |||
67 | #include "secerr.h" | |||
68 | #include "pk11func.h" | |||
69 | #include "keyhi.h" | |||
70 | #include "cmmf.h" | |||
71 | #include "plgetopt.h" | |||
72 | #include "secutil.h" | |||
73 | #include "pk11pqg.h" | |||
74 | ||||
75 | #if 0 | |||
76 | #include "pkcs11.h" | |||
77 | #include "secmod.h" | |||
78 | #include "secmodi.h" | |||
79 | #include "pqggen.h" | |||
80 | #include "secmod.h" | |||
81 | #include "secmodi.h" | |||
82 | #include "pkcs11.h" | |||
83 | #include "secitem.h" | |||
84 | #include "secasn1.h" | |||
85 | #include "sechash.h" | |||
86 | #endif | |||
87 | ||||
88 | #define MAX_KEY_LEN1024 1024 | |||
89 | #define PATH_LEN150 150 | |||
90 | #define BUFF_SIZE150 150 | |||
91 | #define UID_BITS800 800 | |||
92 | #define BPB8 8 | |||
93 | #define CRMF_FILE"CertReqMessages.der" "CertReqMessages.der" | |||
94 | ||||
95 | PRTime notBefore; | |||
96 | char *personalCert = NULL((void*)0); | |||
97 | char *recoveryEncrypter = NULL((void*)0); | |||
98 | char *caCertName = NULL((void*)0); | |||
99 | static secuPWData pwdata = { PW_NONE, 0 }; | |||
100 | char *configdir; | |||
101 | PRBool doingDSA = PR_FALSE0; | |||
102 | ||||
103 | CERTCertDBHandle *db; | |||
104 | ||||
105 | typedef struct { | |||
106 | SECKEYPrivateKey *privKey; | |||
107 | SECKEYPublicKey *pubKey; | |||
108 | CRMFCertRequest *certReq; | |||
109 | CRMFCertReqMsg *certReqMsg; | |||
110 | } TESTKeyPair; | |||
111 | ||||
112 | void | |||
113 | debug_test(SECItem *src, char *filePath) | |||
114 | { | |||
115 | PRFileDesc *fileDesc; | |||
116 | ||||
117 | fileDesc = PR_Open(filePath, PR_WRONLY0x02 | PR_CREATE_FILE0x08 | PR_TRUNCATE0x20, | |||
118 | 0666); | |||
119 | if (fileDesc == NULL((void*)0)) { | |||
120 | printf("Could not cretae file %s.\n", filePath); | |||
121 | return; | |||
122 | } | |||
123 | PR_Write(fileDesc, src->data, src->len); | |||
124 | } | |||
125 | ||||
126 | SECStatus | |||
127 | get_serial_number(long *dest) | |||
128 | { | |||
129 | SECStatus rv; | |||
130 | ||||
131 | if (dest == NULL((void*)0)) { | |||
132 | PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS); | |||
133 | return SECFailure; | |||
134 | } | |||
135 | rv = PK11_GenerateRandom((unsigned char *)dest, sizeof(long)); | |||
136 | if (rv != SECSuccess) { | |||
137 | /* PK11_GenerateRandom calls PORT_SetError */ | |||
138 | return SECFailure; | |||
139 | } | |||
140 | /* make serial number positive */ | |||
141 | if (*dest < 0L) | |||
142 | *dest = -*dest; | |||
143 | return SECSuccess; | |||
144 | } | |||
145 | ||||
146 | PK11RSAGenParams * | |||
147 | GetRSAParams(void) | |||
148 | { | |||
149 | PK11RSAGenParams *rsaParams; | |||
150 | ||||
151 | rsaParams = PORT_ZNew(PK11RSAGenParams)(PK11RSAGenParams *)PORT_ZAlloc_Util(sizeof(PK11RSAGenParams) ); | |||
152 | ||||
153 | if (rsaParams == NULL((void*)0)) | |||
154 | return NULL((void*)0); | |||
155 | ||||
156 | rsaParams->keySizeInBits = MAX_KEY_LEN1024; | |||
157 | rsaParams->pe = 0x10001; | |||
158 | ||||
159 | return rsaParams; | |||
160 | } | |||
161 | ||||
162 | PQGParams * | |||
163 | GetDSAParams(void) | |||
164 | { | |||
165 | PQGParams *params = NULL((void*)0); | |||
166 | PQGVerify *vfy = NULL((void*)0); | |||
167 | ||||
168 | SECStatus rv; | |||
169 | ||||
170 | rv = PK11_PQG_ParamGen(0, ¶ms, &vfy); | |||
171 | if (rv != SECSuccess) { | |||
172 | return NULL((void*)0); | |||
173 | } | |||
174 | PK11_PQG_DestroyVerify(vfy); | |||
175 | return params; | |||
176 | } | |||
177 | ||||
178 | /* Generate a key pair, and then generate a subjectPublicKeyInfo | |||
179 | ** for the public key in that pair. return all 3. | |||
180 | */ | |||
181 | CERTSubjectPublicKeyInfo * | |||
182 | GetSubjectPubKeyInfo(TESTKeyPair *pair) | |||
183 | { | |||
184 | CERTSubjectPublicKeyInfo *spki = NULL((void*)0); | |||
185 | SECKEYPrivateKey *privKey = NULL((void*)0); | |||
186 | SECKEYPublicKey *pubKey = NULL((void*)0); | |||
187 | PK11SlotInfo *keySlot = NULL((void*)0); | |||
188 | ||||
189 | keySlot = PK11_GetInternalKeySlot(); | |||
190 | PK11_Authenticate(keySlot, PR_FALSE0, &pwdata); | |||
191 | ||||
192 | if (!doingDSA) { | |||
193 | PK11RSAGenParams *rsaParams = GetRSAParams(); | |||
194 | if (rsaParams == NULL((void*)0)) { | |||
195 | PK11_FreeSlot(keySlot); | |||
196 | return NULL((void*)0); | |||
197 | } | |||
198 | privKey = PK11_GenerateKeyPair(keySlot, CKM_RSA_PKCS_KEY_PAIR_GEN0x00000000UL, | |||
199 | (void *)rsaParams, &pubKey, PR_FALSE0, | |||
200 | PR_FALSE0, &pwdata); | |||
201 | } else { | |||
202 | PQGParams *dsaParams = GetDSAParams(); | |||
203 | if (dsaParams == NULL((void*)0)) { | |||
204 | PK11_FreeSlot(keySlot); | |||
205 | return NULL((void*)0); | |||
206 | } | |||
207 | privKey = PK11_GenerateKeyPair(keySlot, CKM_DSA_KEY_PAIR_GEN0x00000010UL, | |||
208 | (void *)dsaParams, &pubKey, PR_FALSE0, | |||
209 | PR_FALSE0, &pwdata); | |||
210 | } | |||
211 | PK11_FreeSlot(keySlot); | |||
212 | if (privKey == NULL((void*)0) || pubKey == NULL((void*)0)) { | |||
213 | if (pubKey) { | |||
214 | SECKEY_DestroyPublicKey(pubKey); | |||
215 | } | |||
216 | if (privKey) { | |||
217 | SECKEY_DestroyPrivateKey(privKey); | |||
218 | } | |||
219 | return NULL((void*)0); | |||
220 | } | |||
221 | ||||
222 | spki = SECKEY_CreateSubjectPublicKeyInfo(pubKey); | |||
223 | pair->privKey = privKey; | |||
224 | pair->pubKey = pubKey; | |||
225 | return spki; | |||
226 | } | |||
227 | ||||
228 | SECStatus | |||
229 | InitPKCS11(void) | |||
230 | { | |||
231 | PK11SlotInfo *keySlot; | |||
232 | ||||
233 | PK11_SetPasswordFunc(SECU_GetModulePassword); | |||
234 | ||||
235 | keySlot = PK11_GetInternalKeySlot(); | |||
236 | ||||
237 | if (PK11_NeedUserInit(keySlot) && PK11_NeedLogin(keySlot)) { | |||
238 | if (SECU_ChangePW(keySlot, NULL((void*)0), NULL((void*)0)) != SECSuccess) { | |||
239 | printf("Initializing the PINs failed.\n"); | |||
240 | return SECFailure; | |||
241 | } | |||
242 | } | |||
243 | ||||
244 | PK11_FreeSlot(keySlot); | |||
245 | return SECSuccess; | |||
246 | } | |||
247 | ||||
248 | void | |||
249 | WriteItOut(void *arg, const char *buf, unsigned long len) | |||
250 | { | |||
251 | PRFileDesc *fileDesc = (PRFileDesc *)arg; | |||
252 | ||||
253 | PR_Write(fileDesc, (void *)buf, len); | |||
254 | } | |||
255 | ||||
256 | CRMFCertExtCreationInfo * | |||
257 | GetExtensions(void) | |||
258 | { | |||
259 | unsigned char keyUsage[4] = { 0x03, 0x02, 0x07, KU_DIGITAL_SIGNATURE(0x80) }; | |||
260 | /* What are these magic numbers? */ | |||
261 | SECItem data = { 0, NULL((void*)0), 0 }; | |||
262 | CRMFCertExtension *extension; | |||
263 | CRMFCertExtCreationInfo *extInfo = | |||
264 | PORT_ZNew(CRMFCertExtCreationInfo)(CRMFCertExtCreationInfo *)PORT_ZAlloc_Util(sizeof(CRMFCertExtCreationInfo )); | |||
265 | ||||
266 | data.data = keyUsage; | |||
267 | data.len = sizeof keyUsage; | |||
268 | ||||
269 | extension = | |||
270 | CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE, PR_FALSE0, &data); | |||
271 | if (extension && extInfo) { | |||
272 | extInfo->numExtensions = 1; | |||
273 | extInfo->extensions = PORT_ZNewArray(CRMFCertExtension *, 1)(CRMFCertExtension * *)PORT_ZAlloc_Util(sizeof(CRMFCertExtension *) * (1)); | |||
274 | extInfo->extensions[0] = extension; | |||
275 | } | |||
276 | return extInfo; | |||
277 | } | |||
278 | ||||
279 | void | |||
280 | FreeExtInfo(CRMFCertExtCreationInfo *extInfo) | |||
281 | { | |||
282 | int i; | |||
283 | ||||
284 | for (i = 0; i < extInfo->numExtensions; i++) { | |||
285 | CRMF_DestroyCertExtension(extInfo->extensions[i]); | |||
286 | } | |||
287 | PORT_FreePORT_Free_Util(extInfo->extensions); | |||
288 | PORT_FreePORT_Free_Util(extInfo); | |||
289 | } | |||
290 | ||||
291 | int | |||
292 | InjectCertName(CRMFCertRequest *certReq, | |||
293 | CRMFCertTemplateField inTemplateField, | |||
294 | const char *inNameString) | |||
295 | { | |||
296 | char *nameStr; | |||
297 | CERTName *name; | |||
298 | int irv = 0; | |||
299 | ||||
300 | nameStr = PORT_StrdupPORT_Strdup_Util(inNameString); | |||
301 | if (!nameStr) | |||
302 | return 5; | |||
303 | name = CERT_AsciiToName(nameStr); | |||
304 | if (name == NULL((void*)0)) { | |||
305 | printf("Could not create CERTName structure from %s.\n", nameStr); | |||
306 | irv = 5; | |||
307 | goto finish; | |||
308 | } | |||
309 | ||||
310 | irv = CRMF_CertRequestSetTemplateField(certReq, inTemplateField, (void *)name); | |||
311 | if (irv != SECSuccess) { | |||
312 | printf("Could not add name to cert template\n"); | |||
313 | irv = 6; | |||
314 | } | |||
315 | ||||
316 | finish: | |||
317 | PORT_FreePORT_Free_Util(nameStr); | |||
318 | if (name) | |||
319 | CERT_DestroyName(name); | |||
320 | return irv; | |||
321 | } | |||
322 | ||||
323 | int | |||
324 | CreateCertRequest(TESTKeyPair *pair, long inRequestID) | |||
325 | { | |||
326 | CERTCertificate *caCert; | |||
327 | CERTSubjectPublicKeyInfo *spki; | |||
328 | CRMFCertExtCreationInfo *extInfo; | |||
329 | CRMFCertRequest *certReq; | |||
330 | CRMFEncryptedKey *encKey; | |||
331 | CRMFPKIArchiveOptions *pkiArchOpt; | |||
332 | SECAlgorithmID *algID; | |||
333 | long serialNumber; | |||
334 | long version = 3; | |||
335 | SECStatus rv; | |||
336 | CRMFValidityCreationInfo validity; | |||
337 | unsigned char UIDbuf[UID_BITS800 / BPB8]; | |||
338 | SECItem issuerUID = { siBuffer, NULL((void*)0), 0 }; | |||
339 | SECItem subjectUID = { siBuffer, NULL((void*)0), 0 }; | |||
340 | ||||
341 | /* len in bits */ | |||
342 | issuerUID.data = UIDbuf; | |||
343 | issuerUID.len = UID_BITS800; | |||
344 | subjectUID.data = UIDbuf; | |||
345 | subjectUID.len = UID_BITS800; | |||
346 | ||||
347 | pair->certReq = NULL((void*)0); | |||
348 | certReq = CRMF_CreateCertRequest(inRequestID); | |||
349 | if (certReq == NULL((void*)0)) { | |||
350 | printf("Could not initialize a certificate request.\n"); | |||
351 | return 1; | |||
352 | } | |||
353 | ||||
354 | /* set to version 3 */ | |||
355 | rv = CRMF_CertRequestSetTemplateField(certReq, crmfVersion, | |||
356 | (void *)(&version)); | |||
357 | if (rv != SECSuccess) { | |||
358 | printf("Could not add the version number to the " | |||
359 | "Certificate Request.\n"); | |||
360 | CRMF_DestroyCertRequest(certReq); | |||
361 | return 2; | |||
362 | } | |||
363 | ||||
364 | /* set serial number */ | |||
365 | if (get_serial_number(&serialNumber) != SECSuccess) { | |||
366 | printf("Could not generate a serial number for cert request.\n"); | |||
367 | CRMF_DestroyCertRequest(certReq); | |||
368 | return 3; | |||
369 | } | |||
370 | rv = CRMF_CertRequestSetTemplateField(certReq, crmfSerialNumber, | |||
371 | (void *)(&serialNumber)); | |||
372 | if (rv != SECSuccess) { | |||
373 | printf("Could not add serial number to certificate template\n."); | |||
374 | CRMF_DestroyCertRequest(certReq); | |||
375 | return 4; | |||
376 | } | |||
377 | ||||
378 | /* Set issuer name */ | |||
379 | rv = InjectCertName(certReq, crmfIssuer, | |||
380 | "CN=mozilla CA Shack,O=Information Systems"); | |||
381 | if (rv) { | |||
382 | printf("Could not add issuer to cert template\n"); | |||
383 | CRMF_DestroyCertRequest(certReq); | |||
384 | return 5; | |||
385 | } | |||
386 | ||||
387 | /* Set Subject Name */ | |||
388 | rv = InjectCertName(certReq, crmfSubject, | |||
389 | "CN=mozilla CA Shack ID,O=Engineering,C=US"); | |||
390 | if (rv) { | |||
391 | printf("Could not add Subject to cert template\n"); | |||
392 | CRMF_DestroyCertRequest(certReq); | |||
393 | return 5; | |||
394 | } | |||
395 | ||||
396 | /* Set Algorithm ID */ | |||
397 | algID = PK11_CreatePBEAlgorithmID(SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC, | |||
398 | 1, NULL((void*)0)); | |||
399 | if (algID == NULL((void*)0)) { | |||
400 | printf("Couldn't create algorithm ID\n"); | |||
401 | CRMF_DestroyCertRequest(certReq); | |||
402 | return 9; | |||
403 | } | |||
404 | rv = CRMF_CertRequestSetTemplateField(certReq, crmfSigningAlg, (void *)algID); | |||
405 | SECOID_DestroyAlgorithmIDSECOID_DestroyAlgorithmID_Util(algID, PR_TRUE1); | |||
406 | if (rv != SECSuccess) { | |||
407 | printf("Could not add the signing algorithm to the cert template.\n"); | |||
408 | CRMF_DestroyCertRequest(certReq); | |||
409 | return 10; | |||
410 | } | |||
411 | ||||
412 | /* Set Validity Dates */ | |||
413 | validity.notBefore = ¬Before; | |||
414 | validity.notAfter = NULL((void*)0); | |||
415 | notBefore = PR_Now(); | |||
416 | rv = CRMF_CertRequestSetTemplateField(certReq, crmfValidity, (void *)(&validity)); | |||
417 | if (rv != SECSuccess) { | |||
418 | printf("Could not add validity to cert template\n"); | |||
419 | CRMF_DestroyCertRequest(certReq); | |||
420 | return 11; | |||
421 | } | |||
422 | ||||
423 | /* Generate a key pair and Add the spki to the request */ | |||
424 | spki = GetSubjectPubKeyInfo(pair); | |||
425 | if (spki == NULL((void*)0)) { | |||
426 | printf("Could not create a Subject Public Key Info to add\n"); | |||
427 | CRMF_DestroyCertRequest(certReq); | |||
428 | return 12; | |||
429 | } | |||
430 | rv = CRMF_CertRequestSetTemplateField(certReq, crmfPublicKey, (void *)spki); | |||
431 | SECKEY_DestroySubjectPublicKeyInfo(spki); | |||
432 | if (rv != SECSuccess) { | |||
433 | printf("Could not add the public key to the template\n"); | |||
434 | CRMF_DestroyCertRequest(certReq); | |||
435 | return 13; | |||
436 | } | |||
437 | ||||
438 | /* Set the requested isser Unique ID */ | |||
439 | PK11_GenerateRandom(UIDbuf, sizeof UIDbuf); | |||
440 | CRMF_CertRequestSetTemplateField(certReq, crmfIssuerUID, (void *)&issuerUID); | |||
441 | ||||
442 | /* Set the requested Subject Unique ID */ | |||
443 | PK11_GenerateRandom(UIDbuf, sizeof UIDbuf); | |||
444 | CRMF_CertRequestSetTemplateField(certReq, crmfSubjectUID, (void *)&subjectUID); | |||
445 | ||||
446 | /* Add extensions - XXX need to understand these magic numbers */ | |||
447 | extInfo = GetExtensions(); | |||
448 | CRMF_CertRequestSetTemplateField(certReq, crmfExtension, (void *)extInfo); | |||
449 | FreeExtInfo(extInfo); | |||
450 | ||||
451 | /* get the recipient CA's cert */ | |||
452 | caCert = CERT_FindCertByNickname(db, caCertName); | |||
453 | if (caCert == NULL((void*)0)) { | |||
454 | printf("Could not find the certificate for %s\n", caCertName); | |||
455 | CRMF_DestroyCertRequest(certReq); | |||
456 | return 50; | |||
457 | } | |||
458 | encKey = CRMF_CreateEncryptedKeyWithEncryptedValue(pair->privKey, caCert); | |||
459 | CERT_DestroyCertificate(caCert); | |||
460 | if (encKey == NULL((void*)0)) { | |||
461 | printf("Could not create Encrypted Key with Encrypted Value.\n"); | |||
462 | return 14; | |||
463 | } | |||
464 | pkiArchOpt = CRMF_CreatePKIArchiveOptions(crmfEncryptedPrivateKey, encKey); | |||
465 | CRMF_DestroyEncryptedKey(encKey); | |||
466 | if (pkiArchOpt == NULL((void*)0)) { | |||
467 | printf("Could not create PKIArchiveOptions.\n"); | |||
468 | return 15; | |||
469 | } | |||
470 | rv = CRMF_CertRequestSetPKIArchiveOptions(certReq, pkiArchOpt); | |||
471 | CRMF_DestroyPKIArchiveOptions(pkiArchOpt); | |||
472 | if (rv != SECSuccess) { | |||
473 | printf("Could not add the PKIArchiveControl to Cert Request.\n"); | |||
474 | return 16; | |||
475 | } | |||
476 | pair->certReq = certReq; | |||
477 | return 0; | |||
478 | } | |||
479 | ||||
480 | int | |||
481 | Encode(CRMFCertReqMsg *inCertReq1, CRMFCertReqMsg *inCertReq2) | |||
482 | { | |||
483 | PRFileDesc *fileDesc; | |||
484 | SECStatus rv; | |||
485 | int irv = 0; | |||
486 | CRMFCertReqMsg *msgArr[3]; | |||
487 | char filePath[PATH_LEN150]; | |||
488 | ||||
489 | PR_snprintf(filePath, PATH_LEN150, "%s/%s", configdir, CRMF_FILE"CertReqMessages.der"); | |||
490 | fileDesc = PR_Open(filePath, PR_WRONLY0x02 | PR_CREATE_FILE0x08 | PR_TRUNCATE0x20, | |||
491 | 0666); | |||
492 | if (fileDesc == NULL((void*)0)) { | |||
493 | printf("Could not open file %s\n", filePath); | |||
494 | irv = 14; | |||
495 | goto finish; | |||
496 | } | |||
497 | msgArr[0] = inCertReq1; | |||
498 | msgArr[1] = inCertReq2; | |||
499 | msgArr[2] = NULL((void*)0); | |||
500 | rv = CRMF_EncodeCertReqMessages(msgArr, WriteItOut, (void *)fileDesc); | |||
501 | if (rv != SECSuccess) { | |||
502 | printf("An error occurred while encoding.\n"); | |||
503 | irv = 15; | |||
504 | } | |||
505 | finish: | |||
506 | PR_Close(fileDesc); | |||
507 | return irv; | |||
508 | } | |||
509 | ||||
510 | int | |||
511 | AddProofOfPossession(TESTKeyPair *pair, | |||
512 | CRMFPOPChoice inPOPChoice) | |||
513 | { | |||
514 | ||||
515 | switch (inPOPChoice) { | |||
516 | case crmfSignature: | |||
517 | CRMF_CertReqMsgSetSignaturePOP(pair->certReqMsg, pair->privKey, | |||
518 | pair->pubKey, NULL((void*)0), NULL((void*)0), &pwdata); | |||
519 | break; | |||
520 | case crmfRAVerified: | |||
521 | CRMF_CertReqMsgSetRAVerifiedPOP(pair->certReqMsg); | |||
522 | break; | |||
523 | case crmfKeyEncipherment: | |||
524 | CRMF_CertReqMsgSetKeyEnciphermentPOP(pair->certReqMsg, | |||
525 | crmfSubsequentMessage, | |||
526 | crmfChallengeResp, NULL((void*)0)); | |||
527 | break; | |||
528 | case crmfKeyAgreement: { | |||
529 | SECItem pendejo; | |||
530 | unsigned char lame[] = { 0xf0, 0x0f, 0xf0, 0x0f, 0xf0 }; | |||
531 | ||||
532 | pendejo.data = lame; | |||
533 | pendejo.len = 5; | |||
534 | ||||
535 | CRMF_CertReqMsgSetKeyAgreementPOP(pair->certReqMsg, crmfThisMessage, | |||
536 | crmfNoSubseqMess, &pendejo); | |||
537 | } break; | |||
538 | default: | |||
539 | return 1; | |||
540 | } | |||
541 | return 0; | |||
542 | } | |||
543 | ||||
544 | int | |||
545 | Decode(void) | |||
546 | { | |||
547 | PRFileDesc *fileDesc; | |||
548 | CRMFCertReqMsg *certReqMsg; | |||
549 | CRMFCertRequest *certReq; | |||
550 | CRMFCertReqMessages *certReqMsgs; | |||
551 | SECStatus rv; | |||
552 | int numMsgs, i; | |||
553 | long lame; | |||
554 | CRMFGetValidity validity = { NULL((void*)0), NULL((void*)0) }; | |||
555 | SECItem item = { siBuffer, NULL((void*)0), 0 }; | |||
556 | char filePath[PATH_LEN150]; | |||
557 | ||||
558 | PR_snprintf(filePath, PATH_LEN150, "%s/%s", configdir, CRMF_FILE"CertReqMessages.der"); | |||
559 | fileDesc = PR_Open(filePath, PR_RDONLY0x01, 0644); | |||
560 | if (fileDesc == NULL((void*)0)) { | |||
561 | printf("Could not open file %s\n", filePath); | |||
562 | return 214; | |||
563 | } | |||
564 | rv = SECU_FileToItem(&item, fileDesc); | |||
565 | PR_Close(fileDesc); | |||
566 | if (rv != SECSuccess) { | |||
567 | return 215; | |||
568 | } | |||
569 | ||||
570 | certReqMsgs = CRMF_CreateCertReqMessagesFromDER((char *)item.data, item.len); | |||
571 | if (certReqMsgs == NULL((void*)0)) { | |||
572 | printf("Error decoding CertReqMessages.\n"); | |||
573 | return 202; | |||
574 | } | |||
575 | numMsgs = CRMF_CertReqMessagesGetNumMessages(certReqMsgs); | |||
576 | if (numMsgs <= 0) { | |||
577 | printf("WARNING: The DER contained %d messages.\n", numMsgs); | |||
578 | } | |||
579 | for (i = 0; i < numMsgs; i++) { | |||
580 | printf("crmftest: Processing cert request %d\n", i); | |||
581 | certReqMsg = CRMF_CertReqMessagesGetCertReqMsgAtIndex(certReqMsgs, i); | |||
582 | if (certReqMsg == NULL((void*)0)) { | |||
583 | printf("ERROR: Could not access the message at index %d of %s\n", | |||
584 | i, filePath); | |||
585 | } | |||
586 | rv = CRMF_CertReqMsgGetID(certReqMsg, &lame); | |||
587 | if (rv) { | |||
588 | SECU_PrintError("crmftest", "CRMF_CertReqMsgGetID"); | |||
589 | } | |||
590 | certReq = CRMF_CertReqMsgGetCertRequest(certReqMsg); | |||
591 | if (!certReq) { | |||
592 | SECU_PrintError("crmftest", "CRMF_CertReqMsgGetCertRequest"); | |||
593 | } | |||
594 | rv = CRMF_CertRequestGetCertTemplateValidity(certReq, &validity); | |||
595 | if (rv) { | |||
596 | SECU_PrintError("crmftest", "CRMF_CertRequestGetCertTemplateValidity"); | |||
597 | } | |||
598 | if (!validity.notBefore) { | |||
599 | /* We encoded a notBefore, so somthing's wrong if it's not here. */ | |||
600 | printf("ERROR: Validity period notBefore date missing.\n"); | |||
601 | } | |||
602 | /* XXX It's all parsed now. We probably should DO SOMETHING with it. | |||
603 | ** But nope. We just throw it all away. | |||
604 | ** Maybe this was intended to be no more than a decoder test. | |||
605 | */ | |||
606 | CRMF_DestroyGetValidity(&validity); | |||
607 | CRMF_DestroyCertRequest(certReq); | |||
608 | CRMF_DestroyCertReqMsg(certReqMsg); | |||
609 | } | |||
610 | CRMF_DestroyCertReqMessages(certReqMsgs); | |||
611 | SECITEM_FreeItemSECITEM_FreeItem_Util(&item, PR_FALSE0); | |||
612 | return 0; | |||
613 | } | |||
614 | ||||
615 | int | |||
616 | GetBitsFromFile(const char *filePath, SECItem *item) | |||
617 | { | |||
618 | PRFileDesc *fileDesc; | |||
619 | SECStatus rv; | |||
620 | ||||
621 | fileDesc = PR_Open(filePath, PR_RDONLY0x01, 0644); | |||
622 | if (fileDesc == NULL((void*)0)) { | |||
623 | printf("Could not open file %s\n", filePath); | |||
624 | return 14; | |||
625 | } | |||
626 | ||||
627 | rv = SECU_FileToItem(item, fileDesc); | |||
628 | PR_Close(fileDesc); | |||
629 | ||||
630 | if (rv != SECSuccess) { | |||
631 | item->data = NULL((void*)0); | |||
632 | item->len = 0; | |||
633 | return 15; | |||
634 | } | |||
635 | return 0; | |||
636 | } | |||
637 | ||||
638 | int | |||
639 | DecodeCMMFCertRepContent(char *derFile) | |||
640 | { | |||
641 | CMMFCertRepContent *certRepContent; | |||
642 | int irv = 0; | |||
643 | SECItem fileBits = { siBuffer, NULL((void*)0), 0 }; | |||
644 | ||||
645 | GetBitsFromFile(derFile, &fileBits); | |||
646 | if (fileBits.data == NULL((void*)0)) { | |||
647 | printf("Could not get bits from file %s\n", derFile); | |||
648 | return 304; | |||
649 | } | |||
650 | certRepContent = CMMF_CreateCertRepContentFromDER(db, | |||
651 | (char *)fileBits.data, fileBits.len); | |||
652 | if (certRepContent == NULL((void*)0)) { | |||
653 | printf("Error while decoding %s\n", derFile); | |||
654 | irv = 303; | |||
655 | } else { | |||
656 | /* That was fun. Now, let's throw it away! */ | |||
657 | CMMF_DestroyCertRepContent(certRepContent); | |||
658 | } | |||
659 | SECITEM_FreeItemSECITEM_FreeItem_Util(&fileBits, PR_FALSE0); | |||
660 | return irv; | |||
661 | } | |||
662 | ||||
663 | int | |||
664 | EncodeCMMFCertReply(const char *filePath, | |||
665 | CERTCertificate *cert, | |||
666 | CERTCertList *list) | |||
667 | { | |||
668 | int rv = 0; | |||
669 | SECStatus srv; | |||
670 | PRFileDesc *fileDesc = NULL((void*)0); | |||
671 | CMMFCertRepContent *certRepContent = NULL((void*)0); | |||
672 | CMMFCertResponse *certResp = NULL((void*)0); | |||
673 | CMMFCertResponse *certResponses[3]; | |||
674 | ||||
675 | certResp = CMMF_CreateCertResponse(0xff123); | |||
676 | CMMF_CertResponseSetPKIStatusInfoStatus(certResp, cmmfGranted); | |||
677 | ||||
678 | CMMF_CertResponseSetCertificate(certResp, cert); | |||
679 | ||||
680 | certResponses[0] = certResp; | |||
681 | certResponses[1] = NULL((void*)0); | |||
682 | certResponses[2] = NULL((void*)0); | |||
683 | ||||
684 | certRepContent = CMMF_CreateCertRepContent(); | |||
685 | CMMF_CertRepContentSetCertResponses(certRepContent, certResponses, 1); | |||
686 | ||||
687 | CMMF_CertRepContentSetCAPubs(certRepContent, list); | |||
688 | ||||
689 | fileDesc = PR_Open(filePath, PR_WRONLY0x02 | PR_CREATE_FILE0x08 | PR_TRUNCATE0x20, | |||
690 | 0666); | |||
691 | if (fileDesc == NULL((void*)0)) { | |||
692 | printf("Could not open file %s\n", filePath); | |||
693 | rv = 400; | |||
694 | goto finish; | |||
695 | } | |||
696 | ||||
697 | srv = CMMF_EncodeCertRepContent(certRepContent, WriteItOut, | |||
698 | (void *)fileDesc); | |||
699 | PR_Close(fileDesc); | |||
700 | if (srv != SECSuccess) { | |||
701 | printf("CMMF_EncodeCertRepContent failed,\n"); | |||
702 | rv = 401; | |||
703 | } | |||
704 | finish: | |||
705 | if (certRepContent) { | |||
706 | CMMF_DestroyCertRepContent(certRepContent); | |||
707 | } | |||
708 | if (certResp) { | |||
709 | CMMF_DestroyCertResponse(certResp); | |||
710 | } | |||
711 | return rv; | |||
712 | } | |||
713 | ||||
714 | /* Extract the public key from the cert whose nickname is given. */ | |||
715 | int | |||
716 | extractPubKeyFromNamedCert(const char *nickname, SECKEYPublicKey **pPubKey) | |||
717 | { | |||
718 | CERTCertificate *caCert = NULL((void*)0); | |||
719 | SECKEYPublicKey *caPubKey = NULL((void*)0); | |||
720 | int rv = 0; | |||
721 | ||||
722 | caCert = CERT_FindCertByNickname(db, (char *)nickname); | |||
723 | if (caCert == NULL((void*)0)) { | |||
724 | printf("Could not get the certifcate for %s\n", caCertName); | |||
725 | rv = 411; | |||
726 | goto finish; | |||
727 | } | |||
728 | caPubKey = CERT_ExtractPublicKey(caCert); | |||
729 | if (caPubKey == NULL((void*)0)) { | |||
730 | printf("Could not extract the public from the " | |||
731 | "certificate for \n%s\n", | |||
732 | caCertName); | |||
733 | rv = 412; | |||
734 | } | |||
735 | finish: | |||
736 | *pPubKey = caPubKey; | |||
737 | CERT_DestroyCertificate(caCert); | |||
738 | caCert = NULL((void*)0); | |||
739 | return rv; | |||
740 | } | |||
741 | ||||
742 | int | |||
743 | EncodeCMMFRecoveryMessage(const char *filePath, | |||
744 | CERTCertificate *cert, | |||
745 | CERTCertList *list) | |||
746 | { | |||
747 | SECKEYPublicKey *caPubKey = NULL((void*)0); | |||
748 | SECKEYPrivateKey *privKey = NULL((void*)0); | |||
749 | CMMFKeyRecRepContent *repContent = NULL((void*)0); | |||
750 | PRFileDesc *fileDesc; | |||
751 | int rv = 0; | |||
752 | SECStatus srv; | |||
753 | ||||
754 | /* Extract the public key from the cert whose nickname is given in | |||
755 | ** the -s option. | |||
756 | */ | |||
757 | rv = extractPubKeyFromNamedCert(caCertName, &caPubKey); | |||
758 | if (rv) | |||
759 | goto finish; | |||
760 | ||||
761 | repContent = CMMF_CreateKeyRecRepContent(); | |||
762 | if (repContent == NULL((void*)0)) { | |||
763 | printf("Could not allocate a CMMFKeyRecRepContent structure\n"); | |||
764 | rv = 407; | |||
765 | goto finish; | |||
766 | } | |||
767 | srv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(repContent, | |||
768 | cmmfGrantedWithMods); | |||
769 | if (srv != SECSuccess) { | |||
770 | printf("Error trying to set PKIStatusInfo for " | |||
771 | "CMMFKeyRecRepContent.\n"); | |||
772 | rv = 406; | |||
773 | goto finish; | |||
774 | } | |||
775 | srv = CMMF_KeyRecRepContentSetNewSignCert(repContent, cert); | |||
776 | if (srv != SECSuccess) { | |||
777 | printf("Error trying to set the new signing certificate for " | |||
778 | "key recovery\n"); | |||
779 | rv = 408; | |||
780 | goto finish; | |||
781 | } | |||
782 | srv = CMMF_KeyRecRepContentSetCACerts(repContent, list); | |||
783 | if (srv != SECSuccess) { | |||
784 | printf("Errory trying to add the list of CA certs to the " | |||
785 | "CMMFKeyRecRepContent structure.\n"); | |||
786 | rv = 409; | |||
787 | goto finish; | |||
788 | } | |||
789 | privKey = PK11_FindKeyByAnyCert(cert, &pwdata); | |||
790 | if (privKey == NULL((void*)0)) { | |||
791 | printf("Could not get the private key associated with the\n" | |||
792 | "certificate %s\n", | |||
793 | personalCert); | |||
794 | rv = 410; | |||
795 | goto finish; | |||
796 | } | |||
797 | ||||
798 | srv = CMMF_KeyRecRepContentSetCertifiedKeyPair(repContent, cert, privKey, | |||
799 | caPubKey); | |||
800 | if (srv != SECSuccess) { | |||
801 | printf("Could not set the Certified Key Pair\n"); | |||
802 | rv = 413; | |||
803 | goto finish; | |||
804 | } | |||
805 | fileDesc = PR_Open(filePath, PR_WRONLY0x02 | PR_CREATE_FILE0x08 | PR_TRUNCATE0x20, | |||
806 | 0666); | |||
807 | if (fileDesc == NULL((void*)0)) { | |||
808 | printf("Could not open file %s\n", filePath); | |||
809 | rv = 414; | |||
810 | goto finish; | |||
811 | } | |||
812 | ||||
813 | srv = CMMF_EncodeKeyRecRepContent(repContent, WriteItOut, | |||
814 | (void *)fileDesc); | |||
815 | PR_Close(fileDesc); | |||
816 | if (srv != SECSuccess) { | |||
817 | printf("CMMF_EncodeKeyRecRepContent failed\n"); | |||
818 | rv = 415; | |||
819 | } | |||
820 | finish: | |||
821 | if (privKey) | |||
822 | SECKEY_DestroyPrivateKey(privKey); | |||
823 | if (caPubKey) | |||
824 | SECKEY_DestroyPublicKey(caPubKey); | |||
825 | if (repContent) | |||
826 | CMMF_DestroyKeyRecRepContent(repContent); | |||
827 | return rv; | |||
828 | } | |||
829 | ||||
830 | int | |||
831 | decodeCMMFRecoveryMessage(const char *filePath) | |||
832 | { | |||
833 | CMMFKeyRecRepContent *repContent = NULL((void*)0); | |||
834 | int rv = 0; | |||
835 | SECItem fileBits = { siBuffer, NULL((void*)0), 0 }; | |||
836 | ||||
837 | GetBitsFromFile(filePath, &fileBits); | |||
838 | if (!fileBits.len) { | |||
839 | rv = 451; | |||
840 | goto finish; | |||
841 | } | |||
842 | repContent = | |||
843 | CMMF_CreateKeyRecRepContentFromDER(db, (const char *)fileBits.data, | |||
844 | fileBits.len); | |||
845 | if (repContent == NULL((void*)0)) { | |||
846 | printf("ERROR: CMMF_CreateKeyRecRepContentFromDER failed on file:\n" | |||
847 | "\t%s\n", | |||
848 | filePath); | |||
849 | rv = 452; | |||
850 | } | |||
851 | finish: | |||
852 | if (repContent) { | |||
853 | CMMF_DestroyKeyRecRepContent(repContent); | |||
854 | } | |||
855 | SECITEM_FreeItemSECITEM_FreeItem_Util(&fileBits, PR_FALSE0); | |||
856 | return rv; | |||
857 | } | |||
858 | ||||
859 | int | |||
860 | DoCMMFStuff(void) | |||
861 | { | |||
862 | CERTCertificate *cert = NULL((void*)0); | |||
863 | CERTCertList *list = NULL((void*)0); | |||
864 | int rv = 0; | |||
865 | char filePath[PATH_LEN150]; | |||
866 | ||||
867 | /* Do common setup for the following steps. | |||
868 | */ | |||
869 | PR_snprintf(filePath, PATH_LEN150, "%s/%s", configdir, "CertRepContent.der"); | |||
870 | ||||
871 | cert = CERT_FindCertByNickname(db, personalCert); | |||
872 | if (cert == NULL((void*)0)) { | |||
873 | printf("Could not find the certificate for %s\n", personalCert); | |||
874 | rv = 416; | |||
875 | goto finish; | |||
876 | } | |||
877 | list = CERT_GetCertChainFromCert(cert, PR_Now(), certUsageEmailSigner); | |||
878 | if (list == NULL((void*)0)) { | |||
879 | printf("Could not find the certificate chain for %s\n", personalCert); | |||
880 | rv = 418; | |||
881 | goto finish; | |||
882 | } | |||
883 | ||||
884 | /* a) Generate the CMMF response message, using a user cert named | |||
885 | ** by -p option, rather than a cert generated from the CRMF | |||
886 | ** request itself. The CMMF message is placed in | |||
887 | ** configdir/CertRepContent.der. | |||
888 | */ | |||
889 | rv = EncodeCMMFCertReply(filePath, cert, list); | |||
890 | if (rv != 0) { | |||
891 | goto finish; | |||
892 | } | |||
893 | ||||
894 | /* b) Decode the CMMF Cert granting message encoded just above, | |||
895 | ** found in configdir/CertRepContent.der. | |||
896 | ** This only tests the decoding. The decoded content is discarded. | |||
897 | */ | |||
898 | rv = DecodeCMMFCertRepContent(filePath); | |||
899 | if (rv != 0) { | |||
900 | goto finish; | |||
901 | } | |||
902 | ||||
903 | /* c) Generate a CMMF Key Excrow message | |||
904 | ** It takes the public and private keys for the cert identified | |||
905 | ** by -p nickname, and wraps them with a sym key that is in turn | |||
906 | ** wrapped with the pubkey in the CA cert, whose nickname is | |||
907 | ** given by the -s option. | |||
908 | ** Store the message in configdir/KeyRecRepContent.der | |||
909 | */ | |||
910 | PR_snprintf(filePath, PATH_LEN150, "%s/%s", configdir, | |||
911 | "KeyRecRepContent.der"); | |||
912 | ||||
913 | rv = EncodeCMMFRecoveryMessage(filePath, cert, list); | |||
914 | if (rv) | |||
915 | goto finish; | |||
916 | ||||
917 | /* d) Decode the CMMF Key Excrow message generated just above. | |||
918 | ** Get it from file configdir/KeyRecRepContent.der | |||
919 | ** This is just a decoder test. Results are discarded. | |||
920 | */ | |||
921 | ||||
922 | rv = decodeCMMFRecoveryMessage(filePath); | |||
923 | ||||
924 | finish: | |||
925 | if (cert) { | |||
926 | CERT_DestroyCertificate(cert); | |||
927 | } | |||
928 | if (list) { | |||
929 | CERT_DestroyCertList(list); | |||
930 | } | |||
931 | return rv; | |||
932 | } | |||
933 | ||||
934 | #define KNOWN_MESSAGE_LENGTH20 20 /*160 bits*/ | |||
935 | ||||
936 | int | |||
937 | DoKeyRecovery(SECKEYPrivateKey *privKey) | |||
938 | { | |||
939 | #ifdef DOING_KEY_RECOVERY /* Doesn't compile yet. */ | |||
940 | SECKEYPublicKey *pubKey; | |||
941 | PK11SlotInfo *slot; | |||
942 | unsigned char *ciphertext; | |||
943 | unsigned char *text_compared; | |||
944 | SECKEYPrivateKey *unwrappedPrivKey; | |||
945 | SECKEYPrivateKey *caPrivKey; | |||
946 | CMMFKeyRecRepContent *keyRecRep; | |||
947 | CMMFCertifiedKeyPair *certKeyPair; | |||
948 | CERTCertificate *caCert; | |||
949 | CERTCertificate *myCert; | |||
950 | SECKEYPublicKey *caPubKey; | |||
951 | PRFileDesc *fileDesc; | |||
952 | CK_ULONG max_bytes_encrypted; | |||
953 | CK_ULONG bytes_encrypted; | |||
954 | CK_ULONG bytes_compared; | |||
955 | CK_ULONG bytes_decrypted; | |||
956 | CK_RV crv; | |||
957 | CK_OBJECT_HANDLE id; | |||
958 | CK_MECHANISM mech = { CKM_INVALID_MECHANISM0xffffffffUL, NULL((void*)0), 0 }; | |||
959 | SECStatus rv; | |||
960 | SECItem fileBits; | |||
961 | SECItem nickname; | |||
962 | unsigned char plaintext[KNOWN_MESSAGE_LENGTH20]; | |||
963 | char filePath[PATH_LEN150]; | |||
964 | static const unsigned char known_message[] = { "Known Crypto Message" }; | |||
965 | ||||
966 | /*caCert = CERT_FindCertByNickname(db, caCertName);*/ | |||
967 | myCert = CERT_FindCertByNickname(db, personalCert); | |||
968 | if (myCert == NULL((void*)0)) { | |||
969 | printf("Could not find the certificate for %s\n", personalCert); | |||
970 | return 700; | |||
971 | } | |||
972 | caCert = CERT_FindCertByNickname(db, recoveryEncrypter); | |||
973 | if (caCert == NULL((void*)0)) { | |||
974 | printf("Could not find the certificate for %s\n", recoveryEncrypter); | |||
975 | return 701; | |||
976 | } | |||
977 | caPubKey = CERT_ExtractPublicKey(caCert); | |||
978 | pubKey = SECKEY_ConvertToPublicKey(privKey); | |||
979 | max_bytes_encrypted = PK11_GetPrivateModulusLen(privKey); | |||
980 | slot = PK11_GetBestSlotWithAttributes(mapWrapKeyType(privKey->keyType), | |||
981 | CKF_ENCRYPT0x00000100UL, 0, NULL((void*)0)); | |||
982 | id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE0); | |||
983 | ||||
984 | switch (privKey->keyType) { | |||
985 | case rsaKey: | |||
986 | mech.mechanism = CKM_RSA_PKCS0x00000001UL; | |||
987 | break; | |||
988 | case dsaKey: | |||
989 | mech.mechanism = CKM_DSA0x00000011UL; | |||
990 | break; | |||
991 | case dhKey: | |||
992 | mech.mechanism = CKM_DH_PKCS_DERIVE0x00000021UL; | |||
993 | break; | |||
994 | default: | |||
995 | printf("Bad Key type in key recovery.\n"); | |||
996 | return 512; | |||
997 | } | |||
998 | PK11_EnterSlotMonitor(slot); | |||
999 | crv = PK11_GETTAB(slot)->C_EncryptInit(slot->session, &mech, id); | |||
1000 | if (crv != CKR_OK0x00000000UL) { | |||
1001 | PK11_ExitSlotMonitor(slot); | |||
1002 | PK11_FreeSlot(slot); | |||
1003 | printf("C_EncryptInit failed in KeyRecovery\n"); | |||
1004 | return 500; | |||
1005 | } | |||
1006 | ciphertext = PORT_NewArray(unsigned char, max_bytes_encrypted)(unsigned char *)PORT_Alloc_Util(sizeof(unsigned char) * (max_bytes_encrypted )); | |||
1007 | if (ciphertext == NULL((void*)0)) { | |||
1008 | PK11_ExitSlotMonitor(slot); | |||
1009 | PK11_FreeSlot(slot); | |||
1010 | printf("Could not allocate memory for ciphertext.\n"); | |||
1011 | return 501; | |||
1012 | } | |||
1013 | bytes_encrypted = max_bytes_encrypted; | |||
1014 | crv = PK11_GETTAB(slot)->C_Encrypt(slot->session, | |||
1015 | known_message, | |||
1016 | KNOWN_MESSAGE_LENGTH20, | |||
1017 | ciphertext, | |||
1018 | &bytes_encrypted); | |||
1019 | PK11_ExitSlotMonitor(slot); | |||
1020 | PK11_FreeSlot(slot); | |||
1021 | if (crv != CKR_OK0x00000000UL) { | |||
1022 | PORT_FreePORT_Free_Util(ciphertext); | |||
1023 | return 502; | |||
1024 | } | |||
1025 | /* Always use the smaller of these two values . . . */ | |||
1026 | bytes_compared = (bytes_encrypted > KNOWN_MESSAGE_LENGTH20) | |||
1027 | ? KNOWN_MESSAGE_LENGTH20 | |||
1028 | : bytes_encrypted; | |||
1029 | ||||
1030 | /* If there was a failure, the plaintext */ | |||
1031 | /* goes at the end, therefore . . . */ | |||
1032 | text_compared = (bytes_encrypted > KNOWN_MESSAGE_LENGTH20) | |||
1033 | ? (ciphertext + bytes_encrypted - | |||
1034 | KNOWN_MESSAGE_LENGTH20) | |||
1035 | : ciphertext; | |||
1036 | ||||
1037 | keyRecRep = CMMF_CreateKeyRecRepContent(); | |||
1038 | if (keyRecRep == NULL((void*)0)) { | |||
1039 | PORT_FreePORT_Free_Util(ciphertext); | |||
1040 | PK11_FreeSlot(slot); | |||
1041 | CMMF_DestroyKeyRecRepContent(keyRecRep); | |||
1042 | printf("Could not allocate a CMMFKeyRecRepContent structre.\n"); | |||
1043 | return 503; | |||
1044 | } | |||
1045 | rv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(keyRecRep, | |||
1046 | cmmfGranted); | |||
1047 | if (rv != SECSuccess) { | |||
1048 | PORT_FreePORT_Free_Util(ciphertext); | |||
1049 | PK11_FreeSlot(slot); | |||
1050 | CMMF_DestroyKeyRecRepContent(keyRecRep); | |||
1051 | printf("Could not set the status for the KeyRecRepContent\n"); | |||
1052 | return 504; | |||
1053 | } | |||
1054 | /* The myCert here should correspond to the certificate corresponding | |||
1055 | * to the private key, but for this test any certificate will do. | |||
1056 | */ | |||
1057 | rv = CMMF_KeyRecRepContentSetCertifiedKeyPair(keyRecRep, myCert, | |||
1058 | privKey, caPubKey); | |||
1059 | if (rv != SECSuccess) { | |||
1060 | PORT_FreePORT_Free_Util(ciphertext); | |||
1061 | PK11_FreeSlot(slot); | |||
1062 | CMMF_DestroyKeyRecRepContent(keyRecRep); | |||
1063 | printf("Could not set the Certified Key Pair\n"); | |||
1064 | return 505; | |||
1065 | } | |||
1066 | PR_snprintf(filePath, PATH_LEN150, "%s/%s", configdir, | |||
1067 | "KeyRecRepContent.der"); | |||
1068 | fileDesc = PR_Open(filePath, PR_WRONLY0x02 | PR_CREATE_FILE0x08 | PR_TRUNCATE0x20, | |||
1069 | 0666); | |||
1070 | if (fileDesc == NULL((void*)0)) { | |||
1071 | PORT_FreePORT_Free_Util(ciphertext); | |||
1072 | PK11_FreeSlot(slot); | |||
1073 | CMMF_DestroyKeyRecRepContent(keyRecRep); | |||
1074 | printf("Could not open file %s\n", filePath); | |||
1075 | return 506; | |||
1076 | } | |||
1077 | rv = CMMF_EncodeKeyRecRepContent(keyRecRep, WriteItOut, fileDesc); | |||
1078 | CMMF_DestroyKeyRecRepContent(keyRecRep); | |||
1079 | PR_Close(fileDesc); | |||
1080 | ||||
1081 | if (rv != SECSuccess) { | |||
1082 | PORT_FreePORT_Free_Util(ciphertext); | |||
1083 | PK11_FreeSlot(slot); | |||
1084 | printf("Error while encoding CMMFKeyRecRepContent\n"); | |||
1085 | return 507; | |||
1086 | } | |||
1087 | GetBitsFromFile(filePath, &fileBits); | |||
1088 | if (fileBits.data == NULL((void*)0)) { | |||
1089 | PORT_FreePORT_Free_Util(ciphertext); | |||
1090 | PK11_FreeSlot(slot); | |||
1091 | printf("Could not get the bits from file %s\n", filePath); | |||
1092 | return 508; | |||
1093 | } | |||
1094 | keyRecRep = | |||
1095 | CMMF_CreateKeyRecRepContentFromDER(db, (const char *)fileBits.data, | |||
1096 | fileBits.len); | |||
1097 | if (keyRecRep == NULL((void*)0)) { | |||
1098 | printf("Could not decode the KeyRecRepContent in file %s\n", | |||
1099 | filePath); | |||
1100 | PORT_FreePORT_Free_Util(ciphertext); | |||
1101 | PK11_FreeSlot(slot); | |||
1102 | return 509; | |||
1103 | } | |||
1104 | caPrivKey = PK11_FindKeyByAnyCert(caCert, &pwdata); | |||
1105 | if (CMMF_KeyRecRepContentGetPKIStatusInfoStatus(keyRecRep) != | |||
1106 | cmmfGranted) { | |||
1107 | PORT_FreePORT_Free_Util(ciphertext); | |||
1108 | PK11_FreeSlot(slot); | |||
1109 | CMMF_DestroyKeyRecRepContent(keyRecRep); | |||
1110 | printf("A bad status came back with the " | |||
1111 | "KeyRecRepContent structure\n"); | |||
1112 | return 510; | |||
1113 | } | |||
1114 | ||||
1115 | #define NICKNAME "Key Recovery Test Key" | |||
1116 | nickname.data = (unsigned char *)NICKNAME; | |||
1117 | nickname.len = PORT_Strlen(NICKNAME)strlen(NICKNAME); | |||
1118 | ||||
1119 | certKeyPair = CMMF_KeyRecRepContentGetCertKeyAtIndex(keyRecRep, 0); | |||
1120 | CMMF_DestroyKeyRecRepContent(keyRecRep); | |||
1121 | rv = CMMF_CertifiedKeyPairUnwrapPrivKey(certKeyPair, | |||
1122 | caPrivKey, | |||
1123 | &nickname, | |||
1124 | PK11_GetInternalKeySlot(), | |||
1125 | db, | |||
1126 | &unwrappedPrivKey, &pwdata); | |||
1127 | CMMF_DestroyCertifiedKeyPair(certKeyPair); | |||
1128 | if (rv != SECSuccess) { | |||
1129 | printf("Unwrapping the private key failed.\n"); | |||
1130 | return 511; | |||
1131 | } | |||
1132 | /*Now let's try to decrypt the ciphertext with the "recovered" key*/ | |||
1133 | PK11_EnterSlotMonitor(slot); | |||
1134 | crv = | |||
1135 | PK11_GETTAB(slot)->C_DecryptInit(unwrappedPrivKey->pkcs11Slot->session, | |||
1136 | &mech, | |||
1137 | unwrappedPrivKey->pkcs11ID); | |||
1138 | if (crv != CKR_OK0x00000000UL) { | |||
1139 | PK11_ExitSlotMonitor(slot); | |||
1140 | PORT_FreePORT_Free_Util(ciphertext); | |||
1141 | PK11_FreeSlot(slot); | |||
1142 | printf("Decrypting with the recovered key failed.\n"); | |||
1143 | return 513; | |||
1144 | } | |||
1145 | bytes_decrypted = KNOWN_MESSAGE_LENGTH20; | |||
1146 | crv = PK11_GETTAB(slot)->C_Decrypt(unwrappedPrivKey->pkcs11Slot->session, | |||
1147 | ciphertext, | |||
1148 | bytes_encrypted, plaintext, | |||
1149 | &bytes_decrypted); | |||
1150 | SECKEY_DestroyPrivateKey(unwrappedPrivKey); | |||
1151 | PK11_ExitSlotMonitor(slot); | |||
1152 | PORT_FreePORT_Free_Util(ciphertext); | |||
1153 | if (crv != CKR_OK0x00000000UL) { | |||
1154 | PK11_FreeSlot(slot); | |||
1155 | printf("Decrypting the ciphertext with recovered key failed.\n"); | |||
1156 | return 514; | |||
1157 | } | |||
1158 | if ((bytes_decrypted != KNOWN_MESSAGE_LENGTH20) || | |||
1159 | (PORT_Memcmpmemcmp(plaintext, known_message, KNOWN_MESSAGE_LENGTH20) != 0)) { | |||
1160 | PK11_FreeSlot(slot); | |||
1161 | printf("The recovered plaintext does not equal the known message:\n" | |||
1162 | "\tKnown message: %s\n" | |||
1163 | "\tRecovered plaintext: %s\n", | |||
1164 | known_message, plaintext); | |||
1165 | return 515; | |||
1166 | } | |||
1167 | #endif | |||
1168 | return 0; | |||
1169 | } | |||
1170 | ||||
1171 | int | |||
1172 | DoChallengeResponse(SECKEYPrivateKey *privKey, | |||
1173 | SECKEYPublicKey *pubKey) | |||
1174 | { | |||
1175 | CMMFPOPODecKeyChallContent *chalContent = NULL((void*)0); | |||
1176 | CMMFPOPODecKeyRespContent *respContent = NULL((void*)0); | |||
1177 | CERTCertificate *myCert = NULL((void*)0); | |||
1178 | CERTGeneralName *myGenName = NULL((void*)0); | |||
1179 | PLArenaPool *poolp = NULL((void*)0); | |||
1180 | PRFileDesc *fileDesc; | |||
1181 | SECItem *publicValue; | |||
1182 | SECItem *keyID; | |||
1183 | SECKEYPrivateKey *foundPrivKey; | |||
1184 | long *randomNums; | |||
1185 | int numChallengesFound = 0; | |||
1186 | int numChallengesSet = 1; | |||
1187 | int i; | |||
1188 | long retrieved; | |||
1189 | SECStatus rv; | |||
1190 | SECItem DecKeyChallBits; | |||
1191 | char filePath[PATH_LEN150]; | |||
1192 | ||||
1193 | chalContent = CMMF_CreatePOPODecKeyChallContent(); | |||
1194 | myCert = CERT_FindCertByNickname(db, personalCert); | |||
1195 | if (myCert == NULL((void*)0)) { | |||
1196 | printf("Could not find the certificate for %s\n", personalCert); | |||
1197 | return 900; | |||
1198 | } | |||
1199 | poolp = PORT_NewArenaPORT_NewArena_Util(1024); | |||
1200 | if (poolp == NULL((void*)0)) { | |||
1201 | printf("Could no allocate a new arena in DoChallengeResponse\n"); | |||
1202 | return 901; | |||
1203 | } | |||
1204 | myGenName = CERT_GetCertificateNames(myCert, poolp); | |||
1205 | if (myGenName == NULL((void*)0)) { | |||
1206 | printf("Could not get the general names for %s certificate\n", | |||
1207 | personalCert); | |||
1208 | return 902; | |||
1209 | } | |||
1210 | randomNums = PORT_ArenaNewArray(poolp, long, numChallengesSet)(long *)PORT_ArenaAlloc_Util(poolp, sizeof(long) * (numChallengesSet )); | |||
1211 | PK11_GenerateRandom((unsigned char *)randomNums, | |||
1212 | numChallengesSet * sizeof(long)); | |||
1213 | for (i = 0; i < numChallengesSet; i++) { | |||
1214 | rv = CMMF_POPODecKeyChallContentSetNextChallenge(chalContent, | |||
1215 | randomNums[i], | |||
1216 | myGenName, | |||
1217 | pubKey, | |||
1218 | &pwdata); | |||
1219 | if (rv != SECSuccess) { | |||
1220 | printf("Could not set the challenge in DoChallengeResponse\n"); | |||
1221 | return 903; | |||
1222 | } | |||
1223 | } | |||
1224 | PR_snprintf(filePath, PATH_LEN150, "%s/POPODecKeyChallContent.der", | |||
1225 | configdir); | |||
1226 | fileDesc = PR_Open(filePath, PR_WRONLY0x02 | PR_CREATE_FILE0x08 | PR_TRUNCATE0x20, | |||
1227 | 0666); | |||
1228 | if (fileDesc == NULL((void*)0)) { | |||
1229 | printf("Could not open file %s\n", filePath); | |||
1230 | return 904; | |||
1231 | } | |||
1232 | rv = CMMF_EncodePOPODecKeyChallContent(chalContent, WriteItOut, | |||
1233 | (void *)fileDesc); | |||
1234 | PR_Close(fileDesc); | |||
1235 | CMMF_DestroyPOPODecKeyChallContent(chalContent); | |||
1236 | if (rv != SECSuccess) { | |||
1237 | printf("Could not encode the POPODecKeyChallContent.\n"); | |||
1238 | return 905; | |||
1239 | } | |||
1240 | GetBitsFromFile(filePath, &DecKeyChallBits); | |||
1241 | chalContent = CMMF_CreatePOPODecKeyChallContentFromDER((const char *)DecKeyChallBits.data, DecKeyChallBits.len); | |||
| ||||
1242 | SECITEM_FreeItemSECITEM_FreeItem_Util(&DecKeyChallBits, PR_FALSE0); | |||
1243 | if (chalContent == NULL((void*)0)) { | |||
1244 | printf("Could not create the POPODecKeyChallContent from DER\n"); | |||
1245 | return 906; | |||
1246 | } | |||
1247 | numChallengesFound = | |||
1248 | CMMF_POPODecKeyChallContentGetNumChallenges(chalContent); | |||
1249 | if (numChallengesFound != numChallengesSet) { | |||
1250 | printf("Number of Challenges Found (%d) does not equal the number " | |||
1251 | "set (%d)\n", | |||
1252 | numChallengesFound, numChallengesSet); | |||
1253 | return 907; | |||
1254 | } | |||
1255 | for (i = 0; i < numChallengesSet; i++) { | |||
1256 | publicValue = CMMF_POPODecKeyChallContentGetPublicValue(chalContent, i); | |||
1257 | if (publicValue == NULL((void*)0)) { | |||
1258 | printf("Could not get the public value for challenge at index %d\n", | |||
1259 | i); | |||
1260 | return 908; | |||
1261 | } | |||
1262 | keyID = PK11_MakeIDFromPubKey(publicValue); | |||
1263 | SECITEM_FreeItemSECITEM_FreeItem_Util(publicValue, PR_TRUE1); | |||
1264 | if (keyID == NULL((void*)0)) { | |||
1265 | printf("Could not make the keyID from the public value\n"); | |||
1266 | return 909; | |||
1267 | } | |||
1268 | foundPrivKey = PK11_FindKeyByKeyID(privKey->pkcs11Slot, keyID, &pwdata); | |||
1269 | SECITEM_FreeItemSECITEM_FreeItem_Util(keyID, PR_TRUE1); | |||
1270 | if (foundPrivKey == NULL((void*)0)) { | |||
1271 | printf("Could not find the private key corresponding to the public" | |||
1272 | " value.\n"); | |||
1273 | return 910; | |||
1274 | } | |||
1275 | rv = CMMF_POPODecKeyChallContDecryptChallenge(chalContent, i, | |||
1276 | foundPrivKey); | |||
1277 | if (rv != SECSuccess) { | |||
1278 | printf("Could not decrypt the challenge at index %d\n", i); | |||
1279 | return 911; | |||
1280 | } | |||
1281 | rv = CMMF_POPODecKeyChallContentGetRandomNumber(chalContent, i, | |||
1282 | &retrieved); | |||
1283 | if (rv != SECSuccess) { | |||
1284 | printf("Could not get the random number from the challenge at " | |||
1285 | "index %d\n", | |||
1286 | i); | |||
1287 | return 912; | |||
1288 | } | |||
1289 | if (retrieved != randomNums[i]) { | |||
1290 | printf("Retrieved the number (%ld), expected (%ld)\n", retrieved, | |||
1291 | randomNums[i]); | |||
1292 | return 913; | |||
1293 | } | |||
1294 | } | |||
1295 | CMMF_DestroyPOPODecKeyChallContent(chalContent); | |||
1296 | PR_snprintf(filePath, PATH_LEN150, "%s/POPODecKeyRespContent.der", | |||
1297 | configdir); | |||
1298 | fileDesc = PR_Open(filePath, PR_WRONLY0x02 | PR_CREATE_FILE0x08 | PR_TRUNCATE0x20, | |||
1299 | 0666); | |||
1300 | if (fileDesc == NULL((void*)0)) { | |||
1301 | printf("Could not open file %s\n", filePath); | |||
1302 | return 914; | |||
1303 | } | |||
1304 | rv = CMMF_EncodePOPODecKeyRespContent(randomNums, numChallengesSet, | |||
1305 | WriteItOut, fileDesc); | |||
1306 | PR_Close(fileDesc); | |||
1307 | if (rv != 0) { | |||
1308 | printf("Could not encode the POPODecKeyRespContent\n"); | |||
1309 | return 915; | |||
1310 | } | |||
1311 | GetBitsFromFile(filePath, &DecKeyChallBits); | |||
1312 | respContent = | |||
1313 | CMMF_CreatePOPODecKeyRespContentFromDER((const char *)DecKeyChallBits.data, | |||
1314 | DecKeyChallBits.len); | |||
1315 | if (respContent == NULL((void*)0)) { | |||
1316 | printf("Could not decode the contents of the file %s\n", filePath); | |||
1317 | return 916; | |||
1318 | } | |||
1319 | numChallengesFound = | |||
1320 | CMMF_POPODecKeyRespContentGetNumResponses(respContent); | |||
1321 | if (numChallengesFound != numChallengesSet) { | |||
1322 | printf("Number of responses found (%d) does not match the number " | |||
1323 | "of challenges set (%d)\n", | |||
1324 | numChallengesFound, numChallengesSet); | |||
1325 | return 917; | |||
1326 | } | |||
1327 | for (i = 0; i < numChallengesSet; i++) { | |||
1328 | rv = CMMF_POPODecKeyRespContentGetResponse(respContent, i, &retrieved); | |||
1329 | if (rv != SECSuccess) { | |||
1330 | printf("Could not retrieve the response at index %d\n", i); | |||
1331 | return 918; | |||
1332 | } | |||
1333 | if (retrieved != randomNums[i]) { | |||
1334 | printf("Retrieved the number (%ld), expected (%ld)\n", retrieved, | |||
1335 | randomNums[i]); | |||
1336 | return 919; | |||
1337 | } | |||
1338 | } | |||
1339 | CMMF_DestroyPOPODecKeyRespContent(respContent); | |||
1340 | return 0; | |||
1341 | } | |||
1342 | ||||
1343 | int | |||
1344 | MakeCertRequest(TESTKeyPair *pair, CRMFPOPChoice inPOPChoice, long inRequestID) | |||
1345 | { | |||
1346 | int irv; | |||
1347 | ||||
1348 | /* Generate a key pair and a cert request for it. */ | |||
1349 | irv = CreateCertRequest(pair, inRequestID); | |||
1350 | if (irv != 0 || pair->certReq == NULL((void*)0)) { | |||
1351 | goto loser; | |||
1352 | } | |||
1353 | ||||
1354 | pair->certReqMsg = CRMF_CreateCertReqMsg(); | |||
1355 | if (!pair->certReqMsg) { | |||
1356 | irv = 999; | |||
1357 | goto loser; | |||
1358 | } | |||
1359 | /* copy certReq into certReqMsg */ | |||
1360 | CRMF_CertReqMsgSetCertRequest(pair->certReqMsg, pair->certReq); | |||
1361 | irv = AddProofOfPossession(pair, inPOPChoice); | |||
1362 | loser: | |||
1363 | return irv; | |||
1364 | } | |||
1365 | ||||
1366 | int | |||
1367 | DestroyPairReqAndMsg(TESTKeyPair *pair) | |||
1368 | { | |||
1369 | SECStatus rv = SECSuccess; | |||
1370 | int irv = 0; | |||
1371 | ||||
1372 | if (pair->certReq) { | |||
1373 | rv = CRMF_DestroyCertRequest(pair->certReq); | |||
1374 | pair->certReq = NULL((void*)0); | |||
1375 | if (rv != SECSuccess) { | |||
1376 | printf("Error when destroying cert request.\n"); | |||
1377 | irv = 100; | |||
1378 | } | |||
1379 | } | |||
1380 | if (pair->certReqMsg) { | |||
1381 | rv = CRMF_DestroyCertReqMsg(pair->certReqMsg); | |||
1382 | pair->certReqMsg = NULL((void*)0); | |||
1383 | if (rv != SECSuccess) { | |||
1384 | printf("Error when destroying cert request msg.\n"); | |||
1385 | if (!irv) | |||
1386 | irv = 101; | |||
1387 | } | |||
1388 | } | |||
1389 | return irv; | |||
1390 | } | |||
1391 | ||||
1392 | int | |||
1393 | DestroyPair(TESTKeyPair *pair) | |||
1394 | { | |||
1395 | int irv = 0; | |||
1396 | ||||
1397 | if (pair->pubKey) { | |||
1398 | SECKEY_DestroyPublicKey(pair->pubKey); | |||
1399 | pair->pubKey = NULL((void*)0); | |||
1400 | } | |||
1401 | if (pair->privKey) { | |||
1402 | SECKEY_DestroyPrivateKey(pair->privKey); | |||
1403 | pair->privKey = NULL((void*)0); | |||
1404 | } | |||
1405 | DestroyPairReqAndMsg(pair); | |||
1406 | return irv; | |||
1407 | } | |||
1408 | ||||
1409 | int | |||
1410 | DoCRMFRequest(TESTKeyPair *signPair, TESTKeyPair *cryptPair) | |||
1411 | { | |||
1412 | int irv, tirv = 0; | |||
1413 | ||||
1414 | /* Generate a key pair and a cert request for it. */ | |||
1415 | irv = MakeCertRequest(signPair, crmfSignature, 0x0f020304); | |||
1416 | if (irv != 0 || signPair->certReq == NULL((void*)0)) { | |||
1417 | goto loser; | |||
1418 | } | |||
1419 | ||||
1420 | if (!doingDSA) { | |||
1421 | irv = MakeCertRequest(cryptPair, crmfKeyAgreement, 0x0f050607); | |||
1422 | if (irv != 0 || cryptPair->certReq == NULL((void*)0)) { | |||
1423 | goto loser; | |||
1424 | } | |||
1425 | } | |||
1426 | ||||
1427 | /* encode the cert request messages into a unified request message. | |||
1428 | ** leave it in a file with a fixed name. :( | |||
1429 | */ | |||
1430 | irv = Encode(signPair->certReqMsg, cryptPair->certReqMsg); | |||
1431 | ||||
1432 | loser: | |||
1433 | if (signPair->certReq) { | |||
1434 | tirv = DestroyPairReqAndMsg(signPair); | |||
1435 | if (tirv && !irv) | |||
1436 | irv = tirv; | |||
1437 | } | |||
1438 | if (cryptPair->certReq) { | |||
1439 | tirv = DestroyPairReqAndMsg(cryptPair); | |||
1440 | if (tirv && !irv) | |||
1441 | irv = tirv; | |||
1442 | } | |||
1443 | return irv; | |||
1444 | } | |||
1445 | ||||
1446 | void | |||
1447 | Usage(void) | |||
1448 | { | |||
1449 | printf("Usage:\n" | |||
1450 | "\tcrmftest -d [Database Directory] -p [Personal Cert]\n" | |||
1451 | "\t -e [Encrypter] -s [CA Certificate] [-P password]\n\n" | |||
1452 | "\t [crmf] [dsa] [decode] [cmmf] [recover] [challenge]\n" | |||
1453 | "\t [-f password_file]\n" | |||
1454 | "Database Directory\n" | |||
1455 | "\tThis is the directory where the key3.db, cert7.db, and\n" | |||
1456 | "\tsecmod.db files are located. This is also the directory\n" | |||
1457 | "\twhere the program will place CRMF/CMMF der files\n" | |||
1458 | "Personal Cert\n" | |||
1459 | "\tThis is the certificate that already exists in the cert\n" | |||
1460 | "\tdatabase to use while encoding the response. The private\n" | |||
1461 | "\tkey associated with the certificate must also exist in the\n" | |||
1462 | "\tkey database.\n" | |||
1463 | "Encrypter\n" | |||
1464 | "\tThis is the certificate to use when encrypting the the \n" | |||
1465 | "\tkey recovery response. The private key for this cert\n" | |||
1466 | "\tmust also be present in the key database.\n" | |||
1467 | "CA Certificate\n" | |||
1468 | "\tThis is the nickname of the certificate to use as the\n" | |||
1469 | "\tCA when doing all of the encoding.\n"); | |||
1470 | } | |||
1471 | ||||
1472 | #define TEST_MAKE_CRMF_REQ0x0001 0x0001 | |||
1473 | #define TEST_USE_DSA0x0002 0x0002 | |||
1474 | #define TEST_DECODE_CRMF_REQ0x0004 0x0004 | |||
1475 | #define TEST_DO_CMMF_STUFF0x0008 0x0008 | |||
1476 | #define TEST_KEY_RECOVERY0x0010 0x0010 | |||
1477 | #define TEST_CHALLENGE_RESPONSE0x0020 0x0020 | |||
1478 | ||||
1479 | SECStatus | |||
1480 | parsePositionalParam(const char *arg, PRUint32 *flags) | |||
1481 | { | |||
1482 | if (!strcmp(arg, "crmf")) { | |||
1483 | *flags |= TEST_MAKE_CRMF_REQ0x0001; | |||
1484 | } else if (!strcmp(arg, "dsa")) { | |||
1485 | *flags |= TEST_MAKE_CRMF_REQ0x0001 | TEST_USE_DSA0x0002; | |||
1486 | doingDSA = PR_TRUE1; | |||
1487 | } else if (!strcmp(arg, "decode")) { | |||
1488 | *flags |= TEST_DECODE_CRMF_REQ0x0004; | |||
1489 | } else if (!strcmp(arg, "cmmf")) { | |||
1490 | *flags |= TEST_DO_CMMF_STUFF0x0008; | |||
1491 | } else if (!strcmp(arg, "recover")) { | |||
1492 | *flags |= TEST_KEY_RECOVERY0x0010; | |||
1493 | } else if (!strcmp(arg, "challenge")) { | |||
1494 | *flags |= TEST_CHALLENGE_RESPONSE0x0020; | |||
1495 | } else { | |||
1496 | printf("unknown positional paremeter: %s\n", arg); | |||
1497 | return SECFailure; | |||
1498 | } | |||
1499 | return SECSuccess; | |||
1500 | } | |||
1501 | ||||
1502 | /* it's not clear, in some cases, whether the desired key is from | |||
1503 | ** the sign pair or the crypt pair, so we're guessing in some places. | |||
1504 | ** This define serves to remind us of the places where we're guessing. | |||
1505 | */ | |||
1506 | #define WHICH_KEYcryptPair cryptPair | |||
1507 | ||||
1508 | int | |||
1509 | main(int argc, char **argv) | |||
1510 | { | |||
1511 | TESTKeyPair signPair, cryptPair; | |||
1512 | PLOptState *optstate; | |||
1513 | PLOptStatus status; | |||
1514 | char *password = NULL((void*)0); | |||
1515 | char *pwfile = NULL((void*)0); | |||
1516 | int irv = 0; | |||
1517 | PRUint32 flags = 0; | |||
1518 | SECStatus rv; | |||
1519 | PRBool nssInit = PR_FALSE0; | |||
1520 | ||||
1521 | memset(&signPair, 0, sizeof signPair); | |||
1522 | memset(&cryptPair, 0, sizeof cryptPair); | |||
1523 | printf("\ncrmftest v1.0\n"); | |||
1524 | optstate = PL_CreateOptState(argc, argv, "d:p:e:s:P:f:"); | |||
1525 | while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { | |||
| ||||
1526 | switch (optstate->option) { | |||
1527 | case 'd': | |||
1528 | configdir = PORT_StrdupPORT_Strdup_Util(optstate->value); | |||
1529 | rv = NSS_Init(configdir); | |||
1530 | if (rv != SECSuccess) { | |||
1531 | printf("NSS_Init (-d) failed\n"); | |||
1532 | return 101; | |||
1533 | } | |||
1534 | nssInit = PR_TRUE1; | |||
1535 | break; | |||
1536 | case 'p': | |||
1537 | personalCert = PORT_StrdupPORT_Strdup_Util(optstate->value); | |||
1538 | if (personalCert == NULL((void*)0)) { | |||
1539 | printf("-p failed\n"); | |||
1540 | return 603; | |||
1541 | } | |||
1542 | break; | |||
1543 | case 'e': | |||
1544 | recoveryEncrypter = PORT_StrdupPORT_Strdup_Util(optstate->value); | |||
1545 | if (recoveryEncrypter == NULL((void*)0)) { | |||
1546 | printf("-e failed\n"); | |||
1547 | return 602; | |||
1548 | } | |||
1549 | break; | |||
1550 | case 's': | |||
1551 | caCertName = PORT_StrdupPORT_Strdup_Util(optstate->value); | |||
1552 | if (caCertName == NULL((void*)0)) { | |||
1553 | printf("-s failed\n"); | |||
1554 | return 604; | |||
1555 | } | |||
1556 | break; | |||
1557 | case 'P': | |||
1558 | password = PORT_StrdupPORT_Strdup_Util(optstate->value); | |||
1559 | if (password == NULL((void*)0)) { | |||
1560 | printf("-P failed\n"); | |||
1561 | return 606; | |||
1562 | } | |||
1563 | pwdata.source = PW_PLAINTEXT; | |||
1564 | pwdata.data = password; | |||
1565 | break; | |||
1566 | case 'f': | |||
1567 | pwfile = PORT_StrdupPORT_Strdup_Util(optstate->value); | |||
1568 | if (pwfile == NULL((void*)0)) { | |||
1569 | printf("-f failed\n"); | |||
1570 | return 607; | |||
1571 | } | |||
1572 | pwdata.source = PW_FROMFILE; | |||
1573 | pwdata.data = pwfile; | |||
1574 | break; | |||
1575 | case 0: /* positional parameter */ | |||
1576 | rv = parsePositionalParam(optstate->value, &flags); | |||
1577 | if (rv
| |||
1578 | printf("bad positional parameter.\n"); | |||
1579 | return 605; | |||
1580 | } | |||
1581 | break; | |||
1582 | default: | |||
1583 | Usage(); | |||
1584 | return 601; | |||
1585 | } | |||
1586 | } | |||
1587 | PL_DestroyOptState(optstate); | |||
1588 | if (status == PL_OPT_BAD || !nssInit
| |||
1589 | Usage(); | |||
1590 | return 600; | |||
1591 | } | |||
1592 | if (!flags
| |||
1593 | flags = ~TEST_USE_DSA0x0002; | |||
1594 | db = CERT_GetDefaultCertDB(); | |||
1595 | InitPKCS11(); | |||
1596 | ||||
1597 | if (flags & TEST_MAKE_CRMF_REQ0x0001) { | |||
1598 | printf("Generating CRMF request\n"); | |||
1599 | irv = DoCRMFRequest(&signPair, &cryptPair); | |||
1600 | if (irv) | |||
1601 | goto loser; | |||
1602 | } | |||
1603 | ||||
1604 | if (flags & TEST_DECODE_CRMF_REQ0x0004) { | |||
1605 | printf("Decoding CRMF request\n"); | |||
1606 | irv = Decode(); | |||
1607 | if (irv != 0) { | |||
1608 | printf("Error while decoding\n"); | |||
1609 | goto loser; | |||
1610 | } | |||
1611 | } | |||
1612 | ||||
1613 | if (flags & TEST_DO_CMMF_STUFF0x0008) { | |||
1614 | printf("Doing CMMF Stuff\n"); | |||
1615 | if ((irv = DoCMMFStuff()) != 0) { | |||
1616 | printf("CMMF tests failed.\n"); | |||
1617 | goto loser; | |||
1618 | } | |||
1619 | } | |||
1620 | ||||
1621 | if (flags & TEST_KEY_RECOVERY0x0010) { | |||
1622 | /* Requires some other options be set. | |||
1623 | ** Once we know exactly what hey are, test for them here. | |||
1624 | */ | |||
1625 | printf("Doing Key Recovery\n"); | |||
1626 | irv = DoKeyRecovery(WHICH_KEYcryptPair.privKey); | |||
1627 | if (irv != 0) { | |||
1628 | printf("Error doing key recovery\n"); | |||
1629 | goto loser; | |||
1630 | } | |||
1631 | } | |||
1632 | ||||
1633 | if (flags & TEST_CHALLENGE_RESPONSE0x0020) { | |||
1634 | printf("Doing Challenge / Response\n"); | |||
1635 | irv = DoChallengeResponse(WHICH_KEYcryptPair.privKey, WHICH_KEYcryptPair.pubKey); | |||
1636 | if (irv != 0) { | |||
1637 | printf("Error doing challenge-response\n"); | |||
1638 | goto loser; | |||
1639 | } | |||
1640 | } | |||
1641 | printf("Exiting successfully!!!\n\n"); | |||
1642 | irv = 0; | |||
1643 | ||||
1644 | loser: | |||
1645 | DestroyPair(&signPair); | |||
1646 | DestroyPair(&cryptPair); | |||
1647 | rv = NSS_Shutdown(); | |||
1648 | if (rv) { | |||
1649 | printf("NSS_Shutdown did not shutdown cleanly!\n"); | |||
1650 | } | |||
1651 | PORT_FreePORT_Free_Util(configdir); | |||
1652 | if (irv) | |||
1653 | printf("crmftest returning %d\n", irv); | |||
1654 | return irv; | |||
1655 | } |