PageRenderTime 99ms CodeModel.GetById 9ms app.highlight 77ms RepoModel.GetById 2ms app.codeStats 0ms

/security/nss/cmd/crmftest/testcrmf.c

http://github.com/zpao/v8monkey
C | 1710 lines | 1405 code | 144 blank | 161 comment | 291 complexity | 99f64fee1db535c070d4ca45a3c17bd9 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file