tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

testcrmf.c (52668B)


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