security/nss/cmd/crmftest/testcrmf.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

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

mercurial