security/nss/cmd/crmftest/testcrmf.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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

mercurial