Bug Summary

File:s/cmd/crmftest/testcrmf.c
Warning:line 1268, 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=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/crmftest -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/cmd/crmftest -resource-dir /usr/lib/llvm-18/lib/clang/18 -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/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../dist/public/nss -I ../../../dist/private/nss -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../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 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-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 } 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
228SECStatus
229InitPKCS11(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
248void
249WriteItOut(void *arg, const char *buf, unsigned long len)
250{
251 PRFileDesc *fileDesc = (PRFileDesc *)arg;
252
253 PR_Write(fileDesc, (void *)buf, len);
254}
255
256CRMFCertExtCreationInfo *
257GetExtensions(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
279void
280FreeExtInfo(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
291int
292InjectCertName(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
316finish:
317 PORT_FreePORT_Free_Util(nameStr);
318 if (name)
319 CERT_DestroyName(name);
320 return irv;
321}
322
323int
324CreateCertRequest(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 = &notBefore;
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
480int
481Encode(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 }
505finish:
506 PR_Close(fileDesc);
507 return irv;
508}
509
510int
511AddProofOfPossession(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
544int
545Decode(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
615int
616GetBitsFromFile(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
638int
639DecodeCMMFCertRepContent(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
663int
664EncodeCMMFCertReply(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 }
704finish:
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. */
715int
716extractPubKeyFromNamedCert(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 }
735finish:
736 *pPubKey = caPubKey;
737 CERT_DestroyCertificate(caCert);
738 caCert = NULL((void*)0);
739 return rv;
740}
741
742int
743EncodeCMMFRecoveryMessage(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 }
820finish:
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
830int
831decodeCMMFRecoveryMessage(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 }
851finish:
852 if (repContent) {
853 CMMF_DestroyKeyRecRepContent(repContent);
854 }
855 SECITEM_FreeItemSECITEM_FreeItem_Util(&fileBits, PR_FALSE0);
856 return rv;
857}
858
859int
860DoCMMFStuff(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
924finish:
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
936int
937DoKeyRecovery(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
1171int
1172DoChallengeResponse(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)) {
39
Assuming 'myCert' is not equal to NULL
40
Taking false branch
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)) {
41
Assuming 'poolp' is not equal to NULL
42
Taking false branch
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)) {
43
Assuming 'myGenName' is not equal to NULL
44
Taking false branch
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++) {
45
Loop condition is true. Entering loop body
48
Loop condition is false. Execution continues on line 1224
1214 rv = CMMF_POPODecKeyChallContentSetNextChallenge(chalContent,
1215 randomNums[i],
1216 myGenName,
1217 pubKey,
1218 &pwdata);
1219 if (rv != SECSuccess) {
46
Assuming 'rv' is equal to SECSuccess
47
Taking false branch
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)) {
49
Assuming 'fileDesc' is not equal to NULL
50
Taking false branch
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) {
51
Assuming 'rv' is equal to SECSuccess
52
Taking false branch
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)) {
53
Assuming 'chalContent' is not equal to NULL
54
Taking false branch
1244 printf("Could not create the POPODecKeyChallContent from DER\n");
1245 return 906;
1246 }
1247 numChallengesFound =
1248 CMMF_POPODecKeyChallContentGetNumChallenges(chalContent);
1249 if (numChallengesFound != numChallengesSet) {
55
Assuming 'numChallengesFound' is equal to 'numChallengesSet'
56
Taking false branch
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++) {
57
Loop condition is true. Entering loop body
1256 publicValue = CMMF_POPODecKeyChallContentGetPublicValue(chalContent, i);
1257 if (publicValue == NULL((void*)0)) {
58
Assuming 'publicValue' is not equal to NULL
59
Taking false branch
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)) {
60
Assuming 'keyID' is not equal to NULL
61
Taking false branch
1265 printf("Could not make the keyID from the public value\n");
1266 return 909;
1267 }
1268 foundPrivKey = PK11_FindKeyByKeyID(privKey->pkcs11Slot, keyID, &pwdata);
62
Access to field 'pkcs11Slot' results in a dereference of a null pointer (loaded from variable 'privKey')
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
1343int
1344MakeCertRequest(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);
1362loser:
1363 return irv;
1364}
1365
1366int
1367DestroyPairReqAndMsg(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
1392int
1393DestroyPair(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
1409int
1410DoCRMFRequest(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
1432loser:
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
1446void
1447Usage(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
1479SECStatus
1480parsePositionalParam(const char *arg, PRUint32 *flags)
1481{
1482 if (!strcmp(arg, "crmf")) {
6
Assuming the condition is false
7
Taking false branch
1483 *flags |= TEST_MAKE_CRMF_REQ0x0001;
1484 } else if (!strcmp(arg, "dsa")) {
8
Assuming the condition is false
9
Taking false branch
1485 *flags |= TEST_MAKE_CRMF_REQ0x0001 | TEST_USE_DSA0x0002;
1486 doingDSA = PR_TRUE1;
1487 } else if (!strcmp(arg, "decode")) {
10
Assuming the condition is false
11
Taking false branch
1488 *flags |= TEST_DECODE_CRMF_REQ0x0004;
1489 } else if (!strcmp(arg, "cmmf")) {
12
Assuming the condition is false
13
Taking false branch
1490 *flags |= TEST_DO_CMMF_STUFF0x0008;
1491 } else if (!strcmp(arg, "recover")) {
14
Assuming the condition is false
15
Taking false branch
1492 *flags |= TEST_KEY_RECOVERY0x0010;
1493 } else if (!strcmp(arg, "challenge")) {
16
Taking true branch
1494 *flags |= TEST_CHALLENGE_RESPONSE0x0020;
1495 } else {
1496 printf("unknown positional paremeter: %s\n", arg);
1497 return SECFailure;
1498 }
1499 return SECSuccess;
17
Returning zero, which participates in a condition later
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
1508int
1509main(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);
1
Null pointer value stored to 'cryptPair.privKey'
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) {
2
Assuming the condition is true
3
Loop condition is true. Entering loop body
20
Execution continues on line 1525
21
Assuming the condition is true
22
Loop condition is true. Entering loop body
26
Execution continues on line 1525
27
Assuming the condition is false
28
Loop condition is false. Execution continues on line 1587
1526 switch (optstate->option) {
4
Control jumps to 'case 0:' at line 1575
23
Control jumps to 'case 100:' at line 1527
1527 case 'd':
1528 configdir = PORT_StrdupPORT_Strdup_Util(optstate->value);
1529 rv = NSS_Init(configdir);
1530 if (rv != SECSuccess) {
24
Assuming 'rv' is equal to SECSuccess
25
Taking false branch
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);
5
Calling 'parsePositionalParam'
18
Returning from 'parsePositionalParam'
1577 if (rv
18.1
'rv' is 0
) {
19
Taking false branch
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
29.1
'nssInit' is 1
) {
29
Assuming 'status' is not equal to PL_OPT_BAD
30
Taking false branch
1589 Usage();
1590 return 600;
1591 }
1592 if (!flags
30.1
'flags' is 32
)
31
Taking false branch
1593 flags = ~TEST_USE_DSA0x0002;
1594 db = CERT_GetDefaultCertDB();
1595 InitPKCS11();
1596
1597 if (flags & TEST_MAKE_CRMF_REQ0x0001) {
32
Taking false branch
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) {
33
Taking false branch
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) {
34
Taking false branch
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) {
35
Taking false branch
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) {
36
Taking true branch
1634 printf("Doing Challenge / Response\n");
1635 irv = DoChallengeResponse(WHICH_KEYcryptPair.privKey, WHICH_KEYcryptPair.pubKey);
37
Passing null pointer value via 1st parameter 'privKey'
38
Calling 'DoChallengeResponse'
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
1644loser:
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}