Bug Summary

File:crmftest/testcrmf.c
Warning:line 1269, column 44
Access to field 'pkcs11Slot' results in a dereference of a null pointer (loaded from variable 'privKey')

Annotated Source Code

Press '?' to see keyboard shortcuts

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