From 09cd127cd2b00244402b87376d49d9d028d794c8 Mon Sep 17 00:00:00 2001 From: "nelsonb%netscape.com" Date: Thu, 3 Jun 2004 03:56:48 +0000 Subject: [PATCH] Make crmftest compile and run with NSS 3.10 shared libraries. Enhance the command line parsing to permit portions of the tests to be individually selected. The code still doesn't all run to completion without errors, but it gets MUCH farther than before. Bug 244329. git-svn-id: svn://10.0.0.236/trunk@157349 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/security/nss/cmd/crmftest/manifest.mn | 2 +- mozilla/security/nss/cmd/crmftest/testcrmf.c | 1271 ++++++++++------- 2 files changed, 730 insertions(+), 543 deletions(-) diff --git a/mozilla/security/nss/cmd/crmftest/manifest.mn b/mozilla/security/nss/cmd/crmftest/manifest.mn index 45f2b70e004..93786ee49e8 100644 --- a/mozilla/security/nss/cmd/crmftest/manifest.mn +++ b/mozilla/security/nss/cmd/crmftest/manifest.mn @@ -51,7 +51,7 @@ CSRCS = \ # The MODULE is always implicitly required. # Listing it here in REQUIRES makes it appear twice in the cc command line. -REQUIRES = dbm +# REQUIRES = dbm PROGRAM = crmftest diff --git a/mozilla/security/nss/cmd/crmftest/testcrmf.c b/mozilla/security/nss/cmd/crmftest/testcrmf.c index 79e0eebfd8f..9801b17e9e9 100644 --- a/mozilla/security/nss/cmd/crmftest/testcrmf.c +++ b/mozilla/security/nss/cmd/crmftest/testcrmf.c @@ -34,46 +34,111 @@ * * ***** END LICENSE BLOCK ***** */ +/* + * This program does 5 separate functions. By default, it does them all. + * It can be told to do any subset of them. + * It does them in this order: + * + * 1. Generate file of CRMF cert requests. + * Generates 2 keys pairs, one for signing, one for encryption. + * Can generate RSA or DSA (XXX - DSA is only useful for signing). + * Generate a cert request for each of the two public keys. + * Generate a single CRMF cert request message that requests both certs. + * Leave the generated CRMF request message in file + * configdir/CertReqMessages.der + * + * 2. Decode CRMF Request(s) Message. + * Reads in the file configdir/CertReqMessages.der + * (either generated by step 1 above, or user supplied). + * Decodes it. NOTHING MORE. Drops these decoded results on the floor. + * The CMMF response (below) contains a completely unrelated cert. :-( + * + * 3. CMMF "Stuff". + * a) Generates a CMMF response, containing a single cert chain, as if + * it was a response to a received CRMF request. But the cert is + * simply a user cert from the user's local soft token, whose + * nickname is given in the -p option. The CMMF response has no + * relationship to the request generated above. The CMMF message + * is placed in configdir/CertRepContent.der. + * b) Decodes the newly generated CMMF response found in file + * configdir/CertRepContent.der and discards the result. 8-/ + * c) Generate a CMMF Key Escrow message + * needs 2 nicknames: + * It takes the public and private keys for the cert identified + * by -p nickname, and wraps them with a sym key that is in turn + * wrapped with the pubkey in the CA cert, whose nickname is + * given with the -s option. + * Store the message in configdir/KeyRecRepContent.der + * d) Decode the CMMF Key Escrow message generated just above. + * Get it from file configdir/KeyRecRepContent.der + * This is just a decoder test. Results are discarded. + * + * 4. Key Recovery + * This code does not yet compile, and what it was intended to do + * has not been fully determined. + * + * 5. Challenge/Response. + * Haven't analyzed this code yet. + * + * + */ + +/* KNOWN BUGS: +** 1. generates BOTH signing and encryption cert requests, even for DSA keys. +** +** 2. Does not verify the siganture in the "Proof of Posession" in the +** decoded cert requests. It only checks syntax of the POP. +** 3. CMMF "Stuff" should be broken up into separate steps, each of +** which may be optionally selected. +*/ + +#include +#include "nspr.h" +#include "nss.h" #include "crmf.h" -#include "secrng.h" -#include "secpkcs5.h" +#include "secerr.h" #include "pk11func.h" -#include "pkcs11.h" -#include "secmod.h" -#include "secmodi.h" #include "key.h" -#include "prio.h" -#include "pqggen.h" #include "cmmf.h" -#include "seccomon.h" +#include "plgetopt.h" +#include "secutil.h" +#include "pk11pqg.h" + +#if 0 +#include "pkcs11.h" +#include "secmod.h" +#include "secmodi.h" +#include "pqggen.h" #include "secmod.h" -#include "prlock.h" #include "secmodi.h" #include "pkcs11.h" -#include "pk11func.h" #include "secitem.h" -#include "key.h" -#include "rsa.h" -#include "secpkcs5.h" #include "secasn1.h" #include "sechash.h" -#include "cert.h" -#include "secerr.h" -#include -#include "prprf.h" -#if !defined(XP_UNIX) && !defined(LINUX) -extern int getopt(int, char **, char*); -extern char *optarg; #endif -#define MAX_KEY_LEN 512 -int64 notBefore; +#define MAX_KEY_LEN 512 +#define PATH_LEN 150 +#define BUFF_SIZE 150 +#define UID_BITS 800 +#define BPB 8 +#define CRMF_FILE "CertReqMessages.der" + +PRTime notBefore; char *personalCert = NULL; char *recoveryEncrypter = NULL; char *caCertName = NULL; +char *configdir; +PRBool doingDSA = PR_FALSE; CERTCertDBHandle *db; -SECKEYKeyDBHandle *keydb; + +typedef struct { + SECKEYPrivateKey *privKey; + SECKEYPublicKey *pubKey; + CRMFCertRequest *certReq; + CRMFCertReqMsg *certReqMsg; +} TESTKeyPair; void debug_test(SECItem *src, char *filePath) @@ -93,19 +158,16 @@ debug_test(SECItem *src, char *filePath) SECStatus get_serial_number(long *dest) { - RNGContext *rng; SECStatus rv; if (dest == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - rng = RNG_CreateContext(); - if (rng == NULL) { - *dest = 0; - return SECFailure; - } - rv = RNG_GenerateRandomBytes(rng, (void*)dest, sizeof(long)); - RNG_DestroyContext(rng, PR_TRUE); + rv = PK11_GenerateRandom((unsigned char *)dest, sizeof(long)); + /* make serial number positive */ + if (*dest < 0L) + *dest = - *dest; return SECSuccess; } @@ -137,7 +199,7 @@ GetRSAParams(void) return NULL; rsaParams->keySizeInBits = MAX_KEY_LEN; - rsaParams->pe = 0x1001; + rsaParams->pe = 0x10001; return rsaParams; @@ -165,42 +227,53 @@ GetDSAParams(void) SECStatus rv; - rv = PQG_ParamGen(0, ¶ms, &vfy); + rv = PK11_PQG_ParamGen(0, ¶ms, &vfy); if (rv != SECSuccess) { return NULL; } - PQG_DestroyVerify(vfy); + PK11_PQG_DestroyVerify(vfy); return params; } +/* Generate a key pair, and then generate a subjectPublicKeyInfo +** for the public key in that pair. return all 3. +*/ CERTSubjectPublicKeyInfo * -GetSubjectPubKeyInfo(SECKEYPrivateKey **destPrivKey, - SECKEYPublicKey **destPubKey) { +GetSubjectPubKeyInfo(TESTKeyPair *pair) +{ CERTSubjectPublicKeyInfo *spki = NULL; SECKEYPrivateKey *privKey = NULL; SECKEYPublicKey *pubKey = NULL; PK11SlotInfo *keySlot = NULL; PK11SlotInfo *cryptoSlot = NULL; - PK11RSAGenParams *rsaParams = NULL; - PQGParams *dsaParams = NULL; keySlot = PK11_GetInternalKeySlot(); PK11_Authenticate(keySlot, PR_FALSE, NULL); + + /* the slot authentication logic in this program needs an OVERHAUL. */ cryptoSlot = PK11_GetInternalSlot(); PK11_Authenticate(cryptoSlot, PR_FALSE, NULL); PK11_FreeSlot(cryptoSlot); - rsaParams = GetRSAParams(); - privKey = PK11_GenerateKeyPair(keySlot, CKM_RSA_PKCS_KEY_PAIR_GEN, - (void*)rsaParams, &pubKey, PR_FALSE, - PR_FALSE, NULL); -/* dsaParams = GetDSAParams(); - if (dsaParams == NULL) { - PK11_FreeSlot(keySlot); - return NULL; + + if (!doingDSA) { + PK11RSAGenParams *rsaParams = GetRSAParams(); + if (rsaParams == NULL) { + PK11_FreeSlot(keySlot); + return NULL; + } + privKey = PK11_GenerateKeyPair(keySlot, CKM_RSA_PKCS_KEY_PAIR_GEN, + (void*)rsaParams, &pubKey, PR_FALSE, + PR_FALSE, NULL); + } else { + PQGParams *dsaParams = GetDSAParams(); + if (dsaParams == NULL) { + PK11_FreeSlot(keySlot); + return NULL; + } + privKey = PK11_GenerateKeyPair(keySlot, CKM_DSA_KEY_PAIR_GEN, + (void*)dsaParams, &pubKey, PR_FALSE, + PR_FALSE, NULL); } - privKey = PK11_GenerateKeyPair(keySlot, CKM_DSA_KEY_PAIR_GEN, - (void*)dsaParams, &pubKey, PR_FALSE, - PR_FALSE, NULL);*/ PK11_FreeSlot(keySlot); if (privKey == NULL || pubKey == NULL) { if (pubKey) { @@ -213,8 +286,8 @@ GetSubjectPubKeyInfo(SECKEYPrivateKey **destPrivKey, } spki = SECKEY_CreateSubjectPublicKeyInfo(pubKey); - *destPrivKey = privKey; - *destPubKey = pubKey; + pair->privKey = privKey; + pair->pubKey = pubKey; return spki; } @@ -222,6 +295,9 @@ GetSubjectPubKeyInfo(SECKEYPrivateKey **destPrivKey, SECStatus InitPKCS11(void) { +#if 1 + PK11_SetPasswordFunc(promptForPassword); +#else PK11SlotInfo *cryptoSlot, *keySlot; PK11_SetPasswordFunc(promptForPassword); @@ -231,20 +307,21 @@ InitPKCS11(void) if (PK11_NeedUserInit(cryptoSlot) && PK11_NeedLogin(cryptoSlot)) { if (SetSlotPassword (cryptoSlot) != SECSuccess) { - printf ("Initializing the PIN's failed.\n"); + printf ("Initializing the PINs failed.\n"); return SECFailure; } } if (PK11_NeedUserInit(keySlot) && PK11_NeedLogin(keySlot)) { if (SetSlotPassword (keySlot) != SECSuccess) { - printf ("Initializing the PIN's failed.\n"); + printf ("Initializing the PINs failed.\n"); return SECFailure; } } PK11_FreeSlot(cryptoSlot); PK11_FreeSlot(keySlot); +#endif return SECSuccess; } @@ -257,47 +334,25 @@ WriteItOut (void *arg, const char *buf, unsigned long len) PR_Write(fileDesc, (void*)buf, len); } -SECItem -GetRandomBitString(void) -{ -#define NUM_BITS 800 -#define BITS_IN_BYTE 8 - SECItem bitString; - int numBytes = NUM_BITS/BITS_IN_BYTE; - unsigned char *bits = PORT_ZNewArray(unsigned char, numBytes); - RNGContext *rng; - rng = RNG_CreateContext(); - RNG_GenerateRandomBytes(rng, (void*)bits, numBytes); - RNG_DestroyContext(rng, PR_TRUE); - bitString.data = bits; - bitString.len = NUM_BITS; - bitString.type = siBuffer; - return bitString; -} CRMFCertExtCreationInfo* GetExtensions(void) { - CRMFCertExtCreationInfo *extInfo; - CRMFCertExtension *currExt; - CRMFCertExtension *extension; - SECItem data; - PRBool prFalse = PR_FALSE; - unsigned char keyUsage[4]; + unsigned char keyUsage[4] = { 0x03, 0x02, 0x07, KU_DIGITAL_SIGNATURE }; + /* What are these magic numbers? */ + SECItem data = { 0, keyUsage, sizeof keyUsage }; - data.len = 4; - data.data = keyUsage; - keyUsage[0] = 0x03; - keyUsage[1] = 0x02; - keyUsage[2] = 0x07; - keyUsage[3] = KU_DIGITAL_SIGNATURE; - extension = CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE,prFalse, - &data); - extInfo = PORT_ZNew(CRMFCertExtCreationInfo); - extInfo->numExtensions = 1; - extInfo->extensions = PORT_ZNewArray(CRMFCertExtension*, 1); - extInfo->extensions[0] = extension; + CRMFCertExtension *extension = + CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE, PR_FALSE, &data); + CRMFCertExtCreationInfo *extInfo = + PORT_ZNew(CRMFCertExtCreationInfo); + + if (extension && extInfo) { + extInfo->numExtensions = 1; + extInfo->extensions = PORT_ZNewArray(CRMFCertExtension*, 1); + extInfo->extensions[0] = extension; + } return extInfo; } @@ -314,34 +369,66 @@ FreeExtInfo(CRMFCertExtCreationInfo *extInfo) } int -CreateCertRequest (CRMFCertRequest **inCertReq, SECKEYPrivateKey **privKey, - SECKEYPublicKey **pubKey) +InjectCertName( CRMFCertRequest * certReq, + CRMFCertTemplateField inTemplateField, + const char * inNameString) { - long serialNumber; - long version = 3; - char *issuerStr = PORT_Strdup ("CN=Javi's CA Shack, O=Information Systems"); - char *subjectStr = PORT_Strdup ("CN=Javi's CA Shack ID, O=Engineering, " - "C=US"); - CRMFCertRequest *certReq; - SECAlgorithmID * algID; - CERTName *issuer, *subject; - CRMFValidityCreationInfo validity; + char * nameStr; + CERTName * name; + int irv = 0; + + nameStr = PORT_Strdup(inNameString); + if (!nameStr) + return 5; + name = CERT_AsciiToName(nameStr); + if (name == NULL) { + printf ("Could not create CERTName structure from %s.\n", nameStr); + irv = 5; + goto finish; + } + + irv = CRMF_CertRequestSetTemplateField(certReq, inTemplateField, (void*)name); + if (irv != SECSuccess) { + printf ("Could not add name to cert template\n"); + irv = 6; + } + +finish: + PORT_Free(nameStr); + if (name) + CERT_DestroyName(name); + return irv; +} + +int +CreateCertRequest(TESTKeyPair *pair, long inRequestID) +{ + CERTCertificate * caCert; CERTSubjectPublicKeyInfo *spki; - SECStatus rv; - SECOidTag tag, tag2; - SECItem issuerUID, subjectUID; - CRMFCertExtCreationInfo *extInfo; - CRMFEncryptedKey *encKey; - CERTCertificate *caCert; - CRMFPKIArchiveOptions *pkiArchOpt; - - *inCertReq = NULL; - certReq = CRMF_CreateCertRequest(0x0ff02345); + CRMFCertExtCreationInfo * extInfo; + CRMFCertRequest * certReq; + CRMFEncryptedKey * encKey; + CRMFPKIArchiveOptions * pkiArchOpt; + SECAlgorithmID * algID; + long serialNumber; + long version = 3; + SECStatus rv; + CRMFValidityCreationInfo validity; + unsigned char UIDbuf[UID_BITS / BPB]; + SECItem issuerUID = { siBuffer, UIDbuf, UID_BITS }; + SECItem subjectUID = { siBuffer, UIDbuf, UID_BITS }; + /* len in bits */ + + pair->certReq = NULL; + certReq = CRMF_CreateCertRequest(inRequestID); if (certReq == NULL) { printf ("Could not initialize a certificate request.\n"); return 1; } - rv = CRMF_CertRequestSetTemplateField (certReq, crmfVersion, (void*)(&version)); + + /* set to version 3 */ + rv = CRMF_CertRequestSetTemplateField(certReq, crmfVersion, + (void*)(&version)); if (rv != SECSuccess) { printf("Could not add the version number to the " "Certificate Request.\n"); @@ -349,12 +436,12 @@ CreateCertRequest (CRMFCertRequest **inCertReq, SECKEYPrivateKey **privKey, return 2; } + /* set serial number */ if (get_serial_number(&serialNumber) != SECSuccess) { printf ("Could not generate a serial number for cert request.\n"); CRMF_DestroyCertRequest(certReq); return 3; } - rv = CRMF_CertRequestSetTemplateField (certReq, crmfSerialNumber, (void*)(&serialNumber)); if (rv != SECSuccess) { @@ -362,40 +449,28 @@ CreateCertRequest (CRMFCertRequest **inCertReq, SECKEYPrivateKey **privKey, CRMF_DestroyCertRequest(certReq); return 4; } - - issuer = CERT_AsciiToName(issuerStr); - if (issuer == NULL) { - printf ("Could not create CERTName structure from %s.\n", issuerStr); + + /* Set issuer name */ + rv = InjectCertName(certReq, crmfIssuer, + "CN=mozilla CA Shack,O=Information Systems"); + if (rv) { + printf ("Could not add issuer to cert template\n"); CRMF_DestroyCertRequest(certReq); return 5; } - rv = CRMF_CertRequestSetTemplateField (certReq, crmfIssuer, (void*) issuer); - PORT_Free(issuerStr); - CERT_DestroyName(issuer); - if (rv != SECSuccess) { - printf ("Could not add issuer to cert template\n"); + + /* Set Subject Name */ + rv = InjectCertName(certReq, crmfSubject, + "CN=mozilla CA Shack ID,O=Engineering,C=US"); + if (rv) { + printf ("Could not add Subject to cert template\n"); CRMF_DestroyCertRequest(certReq); - return 6; + return 5; } - subject = CERT_AsciiToName(subjectStr); - if (subject == NULL) { - printf ("Could not create CERTName structure from %s.\n", subjectStr); - CRMF_DestroyCertRequest(certReq); - return 7; - } - PORT_Free(subjectStr); - rv = CRMF_CertRequestSetTemplateField (certReq, crmfSubject, (void*)subject); - if (rv != SECSuccess) { - printf ("Could not add subject to cert template\n"); - CRMF_DestroyCertRequest(certReq); - return 8; - } - CERT_DestroyName(subject); - - algID = - SEC_PKCS5CreateAlgorithmID (SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC, - NULL, 1); + /* Set Algorithm ID */ + algID = PK11_CreatePBEAlgorithmID(SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC, + 1, NULL); if (algID == NULL) { printf ("Couldn't create algorithm ID\n"); CRMF_DestroyCertRequest(certReq); @@ -409,6 +484,7 @@ CreateCertRequest (CRMFCertRequest **inCertReq, SECKEYPrivateKey **privKey, return 10; } + /* Set Validity Dates */ validity.notBefore = ¬Before; validity.notAfter = NULL; notBefore = PR_Now(); @@ -419,7 +495,8 @@ CreateCertRequest (CRMFCertRequest **inCertReq, SECKEYPrivateKey **privKey, return 11; } - spki = GetSubjectPubKeyInfo(privKey, pubKey); + /* Generate a key pair and Add the spki to the request */ + spki = GetSubjectPubKeyInfo(pair); if (spki == NULL) { printf ("Could not create a Subject Public Key Info to add\n"); CRMF_DestroyCertRequest(certReq); @@ -433,25 +510,27 @@ CreateCertRequest (CRMFCertRequest **inCertReq, SECKEYPrivateKey **privKey, return 13; } - caCert = - CERT_FindCertByNickname(CERT_GetDefaultCertDB(), - caCertName); + /* Set the requested isser Unique ID */ + PK11_GenerateRandom(UIDbuf, sizeof UIDbuf); + CRMF_CertRequestSetTemplateField(certReq,crmfIssuerUID, (void*)&issuerUID); + + /* Set the requested Subject Unique ID */ + PK11_GenerateRandom(UIDbuf, sizeof UIDbuf); + CRMF_CertRequestSetTemplateField(certReq,crmfSubjectUID, (void*)&subjectUID); + + /* Add extensions - XXX need to understand these magic numbers */ + extInfo = GetExtensions(); + CRMF_CertRequestSetTemplateField(certReq, crmfExtension, (void*)extInfo); + FreeExtInfo(extInfo); + + /* get the recipient CA's cert */ + caCert = CERT_FindCertByNickname(db, caCertName); if (caCert == NULL) { printf ("Could not find the certificate for %s\n", caCertName); CRMF_DestroyCertRequest(certReq); return 50; } - - issuerUID = GetRandomBitString(); - subjectUID = GetRandomBitString(); - CRMF_CertRequestSetTemplateField(certReq,crmfIssuerUID, (void*)&issuerUID); - CRMF_CertRequestSetTemplateField(certReq,crmfSubjectUID, (void*)&subjectUID); - PORT_Free(issuerUID.data); - PORT_Free(subjectUID.data); - extInfo = GetExtensions(); - CRMF_CertRequestSetTemplateField(certReq, crmfExtension, (void*)extInfo); - FreeExtInfo(extInfo); - encKey = CRMF_CreateEncryptedKeyWithEncryptedValue(*privKey, caCert); + encKey = CRMF_CreateEncryptedKeyWithEncryptedValue(pair->privKey, caCert); CERT_DestroyCertificate(caCert); if (encKey == NULL) { printf ("Could not create Encrypted Key with Encrypted Value.\n"); @@ -469,22 +548,18 @@ CreateCertRequest (CRMFCertRequest **inCertReq, SECKEYPrivateKey **privKey, printf ("Could not add the PKIArchiveControl to Cert Request.\n"); return 16; } - *inCertReq = certReq; + pair->certReq = certReq; return 0; } int -Encode (CRMFCertReqMsg *inCertReq, - CRMFCertReqMsg *secondReq, char *configdir) +Encode(CRMFCertReqMsg *inCertReq1, CRMFCertReqMsg *inCertReq2) { -#define PATH_LEN 150 -#define CRMF_FILE "CertReqMessages.der" - char filePath[PATH_LEN]; - PRFileDesc *fileDesc; - SECStatus rv; - int irv = 0; + PRFileDesc *fileDesc; + SECStatus rv; + int irv = 0; CRMFCertReqMsg *msgArr[3]; - CRMFCertReqMsg *newMsg; + char filePath[PATH_LEN]; PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, CRMF_FILE); fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, @@ -494,36 +569,34 @@ Encode (CRMFCertReqMsg *inCertReq, irv = 14; goto finish; } -/* rv = CRMF_EncodeCertReqMsg (inCertReq, WriteItOut, (void*)fileDesc);*/ - msgArr[0] = inCertReq; - msgArr[1] = secondReq; + msgArr[0] = inCertReq1; + msgArr[1] = inCertReq2; msgArr[2] = NULL; rv = CRMF_EncodeCertReqMessages(msgArr, WriteItOut, (void*)fileDesc); if (rv != SECSuccess) { printf ("An error occurred while encoding.\n"); irv = 15; - goto finish; } - finish: +finish: PR_Close(fileDesc); return irv; } int -AddProofOfPossession(CRMFCertReqMsg *certReqMsg, SECKEYPrivateKey *privKey, - SECKEYPublicKey *pubKey, CRMFPOPChoice inPOPChoice) +AddProofOfPossession(TESTKeyPair *pair, + CRMFPOPChoice inPOPChoice) { switch(inPOPChoice){ case crmfSignature: - CRMF_CertReqMsgSetSignaturePOP(certReqMsg, privKey, pubKey, NULL, NULL, - NULL); + CRMF_CertReqMsgSetSignaturePOP(pair->certReqMsg, pair->privKey, + pair->pubKey, NULL, NULL, NULL); break; case crmfRAVerified: - CRMF_CertReqMsgSetRAVerifiedPOP(certReqMsg); + CRMF_CertReqMsgSetRAVerifiedPOP(pair->certReqMsg); break; case crmfKeyEncipherment: - CRMF_CertReqMsgSetKeyEnciphermentPOP(certReqMsg, + CRMF_CertReqMsgSetKeyEnciphermentPOP(pair->certReqMsg, crmfSubsequentMessage, crmfChallengeResp, NULL); break; @@ -535,7 +608,7 @@ AddProofOfPossession(CRMFCertReqMsg *certReqMsg, SECKEYPrivateKey *privKey, pendejo.data = lame; pendejo.len = 5; - CRMF_CertReqMsgSetKeyAgreementPOP(certReqMsg, crmfThisMessage, + CRMF_CertReqMsgSetKeyAgreementPOP(pair->certReqMsg, crmfThisMessage, crmfNoSubseqMess, &pendejo); } break; @@ -545,52 +618,34 @@ AddProofOfPossession(CRMFCertReqMsg *certReqMsg, SECKEYPrivateKey *privKey, return 0; } -#define BUFF_SIZE 150 int -Decode(char *configdir) +Decode(void) { - char filePath[PATH_LEN]; - unsigned char buffer[BUFF_SIZE]; - char *asn1Buff; - PRFileDesc *fileDesc; - PRInt32 fileLen = 0; - PRInt32 bytesRead; - CRMFCertReqMsg *certReqMsg; - CRMFCertRequest *certReq; - CRMFGetValidity validity= {NULL, NULL}; + PRFileDesc *fileDesc; + CRMFCertReqMsg *certReqMsg; + CRMFCertRequest *certReq; CRMFCertReqMessages *certReqMsgs; - int numMsgs, i; - long lame; + SECStatus rv; + int numMsgs, i; + long lame; + CRMFGetValidity validity = {NULL, NULL}; + SECItem item = { siBuffer, NULL, 0 }; + char filePath[PATH_LEN]; PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, CRMF_FILE); fileDesc = PR_Open(filePath, PR_RDONLY, 0644); - while (1) { - bytesRead = PR_Read(fileDesc, buffer, BUFF_SIZE); - if (bytesRead <= 0) break; - fileLen += bytesRead; + if (fileDesc == NULL) { + printf ("Could not open file %s\n", filePath); + return 214; } - if (bytesRead < 0) { - printf ("Error while getting the length of the file %s\n", filePath); - return 200; - } - + rv = SECU_FileToItem(&item, fileDesc); PR_Close(fileDesc); - fileDesc = PR_Open(filePath, PR_RDONLY, 0644); - asn1Buff = PORT_ZNewArray(char, fileLen); - bytesRead = PR_Read(fileDesc, asn1Buff, fileLen); - if (bytesRead != fileLen) { - printf ("Error while reading in the contents of %s\n", filePath); - return 201; + if (rv != SECSuccess) { + return 215; } - /*certReqMsg = CRMF_CreateCertReqMsgFromDER(asn1Buff, fileLen); - if (certReqMsg == NULL) { - printf ("Error while decoding the CertReqMsg\n"); - return 202; - } - certReq = CRMF_CertReqMsgGetCertRequest(certReqMsg); -*/ - certReqMsgs = CRMF_CreateCertReqMessagesFromDER(asn1Buff, fileLen); + + certReqMsgs = CRMF_CreateCertReqMessagesFromDER((char *)item.data, item.len); if (certReqMsgs == NULL) { printf ("Error decoding CertReqMessages.\n"); return 202; @@ -600,120 +655,103 @@ Decode(char *configdir) printf ("WARNING: The DER contained %d messages.\n", numMsgs); } for (i=0; i < numMsgs; i++) { + SECStatus rv; + printf("crmftest: Processing cert request %d\n", i); certReqMsg = CRMF_CertReqMessagesGetCertReqMsgAtIndex(certReqMsgs, i); if (certReqMsg == NULL) { printf ("ERROR: Could not access the message at index %d of %s\n", i, filePath); } - CRMF_CertReqMsgGetID(certReqMsg, &lame); + rv = CRMF_CertReqMsgGetID(certReqMsg, &lame); + if (rv) { + SECU_PrintError("crmftest", "CRMF_CertReqMsgGetID"); + } certReq = CRMF_CertReqMsgGetCertRequest(certReqMsg); - CRMF_CertRequestGetCertTemplateValidity(certReq, &validity); + if (!certReq) { + SECU_PrintError("crmftest", "CRMF_CertReqMsgGetCertRequest"); + } + rv = CRMF_CertRequestGetCertTemplateValidity(certReq, &validity); + if (rv) { + SECU_PrintError("crmftest", "CRMF_CertRequestGetCertTemplateValidity"); + } + /* XXX It's all parsed now. We probably should DO SOMETHING with it. + ** But nope. We just throw it all away. + ** Maybe this was intended to be no more than a decoder test. + */ CRMF_DestroyGetValidity(&validity); CRMF_DestroyCertRequest(certReq); CRMF_DestroyCertReqMsg(certReqMsg); } CRMF_DestroyCertReqMessages(certReqMsgs); - PORT_Free(asn1Buff); + SECITEM_FreeItem(&item, PR_FALSE); return 0; } -void -GetBitsFromFile(char *filePath, SECItem *fileBits) +int +GetBitsFromFile(const char *filePath, SECItem *item) { PRFileDesc *fileDesc; - int bytesRead, fileLen=0; - char buffer[BUFF_SIZE], *asn1Buf; + SECStatus rv; fileDesc = PR_Open(filePath, PR_RDONLY, 0644); - while (1) { - bytesRead = PR_Read(fileDesc, buffer, BUFF_SIZE); - if (bytesRead <= 0) break; - fileLen += bytesRead; - } - if (bytesRead < 0) { - printf ("Error while getting the length of file %s.\n", filePath); - goto loser; + if (fileDesc == NULL) { + printf ("Could not open file %s\n", filePath); + return 14; } + + rv = SECU_FileToItem(item, fileDesc); PR_Close(fileDesc); - - fileDesc = PR_Open(filePath, PR_RDONLY, 0644); - asn1Buf = PORT_ZNewArray(char, fileLen); - if (asn1Buf == NULL) { - printf ("Out of memory in function GetBitsFromFile\n"); - goto loser; + + if (rv != SECSuccess) { + item->data = NULL; + item->len = 0; + return 15; } - bytesRead = PR_Read(fileDesc, asn1Buf, fileLen); - if (bytesRead != fileLen) { - printf ("Error while reading the contents of %s\n", filePath); - goto loser; - } - fileBits->data = (unsigned char*)asn1Buf; - fileBits->len = fileLen; - return; - loser: - if (asn1Buf) { - PORT_Free(asn1Buf); - } - fileBits->data = NULL; - fileBits->len = 0; + return 0; } int DecodeCMMFCertRepContent(char *derFile) { - int fileLen=0; - char *asn1Buf; - SECItem fileBits; CMMFCertRepContent *certRepContent; - + int irv = 0; + SECItem fileBits = { siBuffer, NULL, 0 }; GetBitsFromFile(derFile, &fileBits); if (fileBits.data == NULL) { printf("Could not get bits from file %s\n", derFile); return 304; } - asn1Buf = (char*)fileBits.data; - fileLen = fileBits.len; - certRepContent = CMMF_CreateCertRepContentFromDER(db, asn1Buf, fileLen); + certRepContent = CMMF_CreateCertRepContentFromDER(db, + (char*)fileBits.data, fileBits.len); if (certRepContent == NULL) { printf ("Error while decoding %s\n", derFile); - return 303; + irv = 303; + } else { + /* That was fun. Now, let's throw it away! */ + CMMF_DestroyCertRepContent(certRepContent); } - CMMF_DestroyCertRepContent(certRepContent); - PORT_Free(asn1Buf); - return 0; + SECITEM_FreeItem(&fileBits, PR_FALSE); + return irv; } int -DoCMMFStuff(char *configdir) +EncodeCMMFCertReply(const char *filePath, + CERTCertificate *cert, + CERTCertList *list) { - CMMFCertResponse *certResp=NULL, *certResp2=NULL, *certResponses[3]; - CMMFCertRepContent *certRepContent=NULL; - CERTCertificate *cert=NULL, *caCert=NULL; - CERTCertList *list=NULL; - PRFileDesc *fileDesc=NULL; - char filePath[PATH_LEN]; - int rv = 0; - long random; - CMMFKeyRecRepContent *repContent=NULL; - SECKEYPrivateKey *privKey = NULL; - SECKEYPublicKey *caPubKey; - SECStatus srv; - SECItem fileBits; - + int rv = 0; + SECStatus srv; + PRFileDesc *fileDesc = NULL; + CMMFCertRepContent *certRepContent = NULL; + CMMFCertResponse *certResp = NULL; + CMMFCertResponse *certResponses[3]; + certResp = CMMF_CreateCertResponse(0xff123); CMMF_CertResponseSetPKIStatusInfoStatus(certResp, cmmfGranted); - cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), personalCert); - if (cert == NULL) { - printf ("Could not find the certificate for %s\n", personalCert); - rv = 416; - goto finish; - } + CMMF_CertResponseSetCertificate(certResp, cert); - certResp2 = CMMF_CreateCertResponse(0xff122); - CMMF_CertResponseSetPKIStatusInfoStatus(certResp2, cmmfGranted); - CMMF_CertResponseSetCertificate(certResp2, cert); - + certResponses[0] = certResp; certResponses[1] = NULL; certResponses[2] = NULL; @@ -721,10 +759,8 @@ DoCMMFStuff(char *configdir) certRepContent = CMMF_CreateCertRepContent(); CMMF_CertRepContentSetCertResponses(certRepContent, certResponses, 1); - list = CERT_GetCertChainFromCert(cert, PR_Now(), certUsageEmailSigner); CMMF_CertRepContentSetCAPubs(certRepContent, list); - PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, "CertRepContent.der"); fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0666); if (fileDesc == NULL) { @@ -735,20 +771,68 @@ DoCMMFStuff(char *configdir) srv = CMMF_EncodeCertRepContent(certRepContent, WriteItOut, (void*)fileDesc); - PORT_Assert (srv == SECSuccess); PR_Close(fileDesc); - rv = DecodeCMMFCertRepContent(filePath); - if (rv != 0) { - goto finish; + if (srv != SECSuccess) { + printf ("CMMF_EncodeCertRepContent failed,\n"); + rv = 401; } - random = 0xa4e7; - caCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), - caCertName); +finish: + if (certRepContent) { + CMMF_DestroyCertRepContent(certRepContent); + } + if (certResp) { + CMMF_DestroyCertResponse(certResp); + } + return rv; +} + + +/* Extract the public key from the cert whose nickname is given. */ +int +extractPubKeyFromNamedCert(const char * nickname, SECKEYPublicKey **pPubKey) +{ + CERTCertificate *caCert = NULL; + SECKEYPublicKey *caPubKey = NULL; + int rv = 0; + + caCert = CERT_FindCertByNickname(db, (char *)nickname); if (caCert == NULL) { printf ("Could not get the certifcate for %s\n", caCertName); rv = 411; goto finish; } + caPubKey = CERT_ExtractPublicKey(caCert); + if (caPubKey == NULL) { + printf ("Could not extract the public from the " + "certificate for \n%s\n", caCertName); + rv = 412; + } +finish: + *pPubKey = caPubKey; + CERT_DestroyCertificate(caCert); + caCert = NULL; + return rv; +} + +int +EncodeCMMFRecoveryMessage(const char * filePath, + CERTCertificate *cert, + CERTCertList *list) +{ + SECKEYPublicKey *caPubKey = NULL; + SECKEYPrivateKey *privKey = NULL; + CMMFKeyRecRepContent *repContent = NULL; + PRFileDesc *fileDesc; + int rv = 0; + SECStatus srv; + + /* Extract the public key from the cert whose nickname is given in + ** the -s option. + */ + rv = extractPubKeyFromNamedCert( caCertName, &caPubKey); + if (rv) + goto finish; + repContent = CMMF_CreateKeyRecRepContent(); if (repContent == NULL) { printf ("Could not allocate a CMMFKeyRecRepContent structure\n"); @@ -784,26 +868,14 @@ DoCMMFStuff(char *configdir) rv = 410; goto finish; } - caPubKey = CERT_ExtractPublicKey(caCert); - if (caPubKey == NULL) { - printf ("Could not extract the public from the " - "certificate for \n%s\n", caCertName); - rv = 412; - goto finish; - } - CERT_DestroyCertificate(caCert); - caCert = NULL; + srv = CMMF_KeyRecRepContentSetCertifiedKeyPair(repContent, cert, privKey, caPubKey); - SECKEY_DestroyPrivateKey(privKey); - SECKEY_DestroyPublicKey(caPubKey); if (srv != SECSuccess) { printf ("Could not set the Certified Key Pair\n"); rv = 413; goto finish; } - PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, - "KeyRecRepContent.der"); fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0666); if (fileDesc == NULL) { @@ -814,38 +886,121 @@ DoCMMFStuff(char *configdir) srv = CMMF_EncodeKeyRecRepContent(repContent, WriteItOut, (void*)fileDesc); - PORT_Assert (srv == SECSuccess); PR_Close(fileDesc); - CMMF_DestroyKeyRecRepContent(repContent); + if (srv != SECSuccess) { + printf ("CMMF_EncodeKeyRecRepContent failed\n"); + rv = 415; + } +finish: + if (privKey) + SECKEY_DestroyPrivateKey(privKey); + if (caPubKey) + SECKEY_DestroyPublicKey(caPubKey); + if (repContent) + CMMF_DestroyKeyRecRepContent(repContent); + return rv; +} + +int +decodeCMMFRecoveryMessage(const char * filePath) +{ + CMMFKeyRecRepContent *repContent = NULL; + int rv = 0; + SECItem fileBits = { siBuffer, NULL, 0 }; + GetBitsFromFile(filePath, &fileBits); + if (!fileBits.len) { + rv = 451; + goto finish; + } repContent = CMMF_CreateKeyRecRepContentFromDER(db, (const char *) fileBits.data, fileBits.len); if (repContent == NULL) { printf ("ERROR: CMMF_CreateKeyRecRepContentFromDER failed on file:\n" "\t%s\n", filePath); - rv = 415; - goto finish; + rv = 452; } - finish: +finish: if (repContent) { CMMF_DestroyKeyRecRepContent(repContent); } + SECITEM_FreeItem(&fileBits, PR_FALSE); + return rv; +} + +int +DoCMMFStuff(void) +{ + CERTCertificate *cert = NULL; + CERTCertList *list = NULL; + int rv = 0; + char filePath[PATH_LEN]; + + /* Do common setup for the following steps. + */ + PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, "CertRepContent.der"); + + cert = CERT_FindCertByNickname(db, personalCert); + if (cert == NULL) { + printf ("Could not find the certificate for %s\n", personalCert); + rv = 416; + goto finish; + } + list = CERT_GetCertChainFromCert(cert, PR_Now(), certUsageEmailSigner); + if (list == NULL) { + printf ("Could not find the certificate chain for %s\n", personalCert); + rv = 418; + goto finish; + } + + /* a) Generate the CMMF response message, using a user cert named + ** by -p option, rather than a cert generated from the CRMF + ** request itself. The CMMF message is placed in + ** configdir/CertRepContent.der. + */ + rv = EncodeCMMFCertReply(filePath, cert, list); + if (rv != 0) { + goto finish; + } + + /* b) Decode the CMMF Cert granting message encoded just above, + ** found in configdir/CertRepContent.der. + ** This only tests the decoding. The decoded content is discarded. + */ + rv = DecodeCMMFCertRepContent(filePath); + if (rv != 0) { + goto finish; + } + + /* c) Generate a CMMF Key Excrow message + ** It takes the public and private keys for the cert identified + ** by -p nickname, and wraps them with a sym key that is in turn + ** wrapped with the pubkey in the CA cert, whose nickname is + ** given by the -s option. + ** Store the message in configdir/KeyRecRepContent.der + */ + PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, + "KeyRecRepContent.der"); + + rv = EncodeCMMFRecoveryMessage(filePath, cert, list); + if (rv) + goto finish; + + /* d) Decode the CMMF Key Excrow message generated just above. + ** Get it from file configdir/KeyRecRepContent.der + ** This is just a decoder test. Results are discarded. + */ + + rv = decodeCMMFRecoveryMessage(filePath); + + finish: if (cert) { CERT_DestroyCertificate(cert); } if (list) { CERT_DestroyCertList(list); } - if (certResp) { - CMMF_DestroyCertResponse(certResp); - } - if (certResp2) { - CMMF_DestroyCertResponse(certResp2); - } - if (certRepContent) { - CMMF_DestroyCertRepContent(certRepContent); - } return rv; } @@ -864,47 +1019,52 @@ mapWrapKeyType(KeyType keyType) #define KNOWN_MESSAGE_LENGTH 20 /*160 bits*/ int -DoKeyRecovery(char *configdir, SECKEYPrivateKey *privKey) +DoKeyRecovery( SECKEYPrivateKey *privKey) { - SECKEYPublicKey *pubKey; - PK11SlotInfo *slot; - CK_OBJECT_HANDLE id; - CK_MECHANISM mech = { CKM_INVALID_MECHANISM, NULL, 0}; - unsigned char *known_message = (unsigned char*)"Known Crypto Message"; - unsigned char plaintext[KNOWN_MESSAGE_LENGTH]; - char filePath[PATH_LEN]; - CK_RV crv; - unsigned char *ciphertext; - CK_ULONG max_bytes_encrypted, bytes_encrypted; - unsigned char *text_compared; - CK_ULONG bytes_compared, bytes_decrypted; - SECKEYPrivateKey *unwrappedPrivKey, *caPrivKey; +#ifdef DOING_KEY_RECOVERY /* Doesn't compile yet. */ + SECKEYPublicKey *pubKey; + PK11SlotInfo *slot; + unsigned char *ciphertext; + unsigned char *text_compared; + SECKEYPrivateKey *unwrappedPrivKey; + SECKEYPrivateKey *caPrivKey; CMMFKeyRecRepContent *keyRecRep; - SECStatus rv; - CERTCertificate *caCert, *myCert; - SECKEYPublicKey *caPubKey; - PRFileDesc *fileDesc; - SECItem fileBits, nickname; CMMFCertifiedKeyPair *certKeyPair; + CERTCertificate *caCert; + CERTCertificate *myCert; + SECKEYPublicKey *caPubKey; + PRFileDesc *fileDesc; + CK_ULONG max_bytes_encrypted; + CK_ULONG bytes_encrypted; + CK_ULONG bytes_compared; + CK_ULONG bytes_decrypted; + CK_RV crv; + CK_OBJECT_HANDLE id; + CK_MECHANISM mech = { CKM_INVALID_MECHANISM, NULL, 0}; + SECStatus rv; + SECItem fileBits; + SECItem nickname; + unsigned char plaintext[KNOWN_MESSAGE_LENGTH]; + char filePath[PATH_LEN]; + static const unsigned char known_message[] = { "Known Crypto Message" }; - /*caCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), - caCertName);*/ - myCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), personalCert); + /*caCert = CERT_FindCertByNickname(db, caCertName);*/ + myCert = CERT_FindCertByNickname(db, personalCert); if (myCert == NULL) { printf ("Could not find the certificate for %s\n", personalCert); return 700; } - caCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), - recoveryEncrypter); + caCert = CERT_FindCertByNickname(db, recoveryEncrypter); if (caCert == NULL) { printf ("Could not find the certificate for %s\n", recoveryEncrypter); return 701; } caPubKey = CERT_ExtractPublicKey(caCert); - pubKey = SECKEY_ConvertToPublicKey(privKey); + pubKey = SECKEY_ConvertToPublicKey(privKey); max_bytes_encrypted = PK11_GetPrivateModulusLen(privKey); slot = PK11_GetBestSlot(mapWrapKeyType(privKey->keyType), NULL); - id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE); + id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE); + switch(privKey->keyType) { case rsaKey: mech.mechanism = CKM_RSA_PKCS; @@ -1036,9 +1196,11 @@ DoKeyRecovery(char *configdir, SECKEYPrivateKey *privKey) "KeyRecRepContent structure\n"); return 510; } + #define NICKNAME "Key Recovery Test Key" nickname.data = (unsigned char*)NICKNAME; nickname.len = PORT_Strlen(NICKNAME); + certKeyPair = CMMF_KeyRecRepContentGetCertKeyAtIndex(keyRecRep, 0); CMMF_DestroyKeyRecRepContent(keyRecRep); rv = CMMF_CertifiedKeyPairUnwrapPrivKey(certKeyPair, @@ -1086,11 +1248,12 @@ DoKeyRecovery(char *configdir, SECKEYPrivateKey *privKey) "\tRecovered plaintext: %s\n", known_message, plaintext); return 515; } +#endif return 0; } int -DoChallengeResponse(char *configdir, SECKEYPrivateKey *privKey, +DoChallengeResponse(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey) { CMMFPOPODecKeyChallContent *chalContent = NULL; @@ -1098,17 +1261,18 @@ DoChallengeResponse(char *configdir, SECKEYPrivateKey *privKey, CERTCertificate *myCert = NULL; CERTGeneralName *myGenName = NULL; PRArenaPool *poolp = NULL; - SECItem DecKeyChallBits; - long *randomNums; - int numChallengesFound=0; - int numChallengesSet = 1,i; - long retrieved; - char filePath[PATH_LEN]; - RNGContext *rng; - SECStatus rv; PRFileDesc *fileDesc; - SECItem *publicValue, *keyID; + SECItem *publicValue; + SECItem *keyID; SECKEYPrivateKey *foundPrivKey; + long *randomNums; + int numChallengesFound = 0; + int numChallengesSet = 1; + int i; + long retrieved; + SECStatus rv; + SECItem DecKeyChallBits; + char filePath[PATH_LEN]; chalContent = CMMF_CreatePOPODecKeyChallContent(); myCert = CERT_FindCertByNickname(db, personalCert); @@ -1128,19 +1292,18 @@ DoChallengeResponse(char *configdir, SECKEYPrivateKey *privKey, return 902; } randomNums = PORT_ArenaNewArray(poolp,long, numChallengesSet); - rng = RNG_CreateContext(); - RNG_GenerateRandomBytes(rng, randomNums, numChallengesSet*sizeof(long)); + PK11_GenerateRandom((unsigned char *)randomNums, + numChallengesSet * sizeof(long)); for (i=0; icertReq == NULL) { goto loser; } - status = CERT_OpenCertDB(certdb, PR_TRUE, certdb_name_cb, configdir); - if (status == SECSuccess) { - CERT_SetDefaultCertDB(certdb); - db = certdb; - } else { - PORT_Free(certdb); + + pair->certReqMsg = CRMF_CreateCertReqMsg(); + if (!pair->certReqMsg) { + irv = 999; + goto loser; } - loser: - return status; + /* copy certReq into certReqMsg */ + CRMF_CertReqMsgSetCertRequest(pair->certReqMsg, pair->certReq); + irv = AddProofOfPossession(pair, inPOPChoice); +loser: + return irv; } -char * -keydb_name_cb(void *arg, int dbVersion) +int +DestroyPairReqAndMsg(TESTKeyPair *pair) { - char *configdir = (char*) arg; - char *dbver; + SECStatus rv = SECSuccess; + int irv = 0; - switch(dbVersion){ - case 3: - dbver = "3"; - break; - case 2: - default: - dbver = ""; - break; + if (pair->certReq) { + rv = CRMF_DestroyCertRequest(pair->certReq); + pair->certReq = NULL; + if (rv != SECSuccess) { + printf ("Error when destroying cert request.\n"); + irv = 100; + } } - return PR_smprintf("%s/key%s.db", configdir, dbver); + if (pair->certReqMsg) { + rv = CRMF_DestroyCertReqMsg(pair->certReqMsg); + pair->certReqMsg = NULL; + if (rv != SECSuccess) { + printf ("Error when destroying cert request msg.\n"); + if (!irv) + irv = 101; + } + } + return irv; } -SECStatus -OpenKeyDB(char *configdir) +int +DestroyPair(TESTKeyPair *pair) { - SECKEYKeyDBHandle *keydb; + SECStatus rv = SECSuccess; + int irv = 0; - keydb = SECKEY_OpenKeyDB(PR_FALSE, keydb_name_cb, configdir); - if (keydb == NULL) { - return SECFailure; + if (pair->pubKey) { + SECKEY_DestroyPublicKey(pair->pubKey); + pair->pubKey = NULL; } - SECKEY_SetDefaultKeyDB(keydb); - return SECSuccess; + if (pair->privKey) { + SECKEY_DestroyPrivateKey(pair->privKey); + pair->privKey = NULL; + } + DestroyPairReqAndMsg(pair); + return irv; } -SECStatus -OpenSecModDB(char *configdir) +int +DoCRMFRequest(TESTKeyPair *signPair, TESTKeyPair *cryptPair) { - char *secmodname = PR_smprintf("%d/secmod.db", configdir); - if (secmodname == NULL) { - return SECFailure; - } - SECMOD_init(secmodname); - return SECSuccess; -} + int irv, tirv = 0; -void -CloseHCL(void) -{ - CERTCertDBHandle *certHandle; - SECKEYKeyDBHandle *keyHandle; - - certHandle = CERT_GetDefaultCertDB(); - if (certHandle) { - CERT_ClosePermCertDB(certHandle); - } - keyHandle = SECKEY_GetDefaultKeyDB(); - if (keyHandle) { - SECKEY_CloseKeyDB(keyHandle); - } -} - -SECStatus -InitHCL(char *configdir) -{ - SECStatus status; - SECStatus rv = SECFailure; - - RNG_RNGInit(); - RNG_SystemInfoForRNG(); - - status = OpenCertDB(configdir); - if (status != SECSuccess) { + /* Generate a key pair and a cert request for it. */ + irv = MakeCertRequest(signPair, crmfSignature, 0x0f020304); + if (irv != 0 || signPair->certReq == NULL) { goto loser; } - - status = OpenKeyDB(configdir); - if (status != SECSuccess) { - goto loser; - } - - status = OpenSecModDB(configdir); - if (status != SECSuccess) { - goto loser; - } - - rv = SECSuccess; - loser: - if (rv != SECSuccess) { - CloseHCL(); + if (!doingDSA) { + irv = MakeCertRequest(cryptPair, crmfKeyAgreement, 0x0f050607); + if (irv != 0 || cryptPair->certReq == NULL) { + goto loser; + } } - return rv; + + /* encode the cert request messages into a unified request message. + ** leave it in a file with a fixed name. :( + */ + irv = Encode(signPair->certReqMsg, cryptPair->certReqMsg); + +loser: + if (signPair->certReq) { + tirv = DestroyPairReqAndMsg(signPair); + if (tirv && !irv) + irv = tirv; + } + if (cryptPair->certReq) { + tirv = DestroyPairReqAndMsg(cryptPair); + if (tirv && !irv) + irv = tirv; + } + return irv; } + void Usage (void) { printf ("Usage:\n" "\tcrmftest -d [Database Directory] -p [Personal Cert]\n" "\t -e [Encrypter] -s [CA Certificate]\n\n" + "\t [crmf] [dsa] [decode] [cmmf] [recover] [challenge]\n" "Database Directory\n" "\tThis is the directory where the key3.db, cert7.db, and\n" "\tsecmod.db files are located. This is also the directory\n" @@ -1419,118 +1551,173 @@ Usage (void) "\tCA when doing all of the encoding.\n"); } +#define TEST_MAKE_CRMF_REQ 0x0001 +#define TEST_USE_DSA 0x0002 +#define TEST_DECODE_CRMF_REQ 0x0004 +#define TEST_DO_CMMF_STUFF 0x0008 +#define TEST_KEY_RECOVERY 0x0010 +#define TEST_CHALLENGE_RESPONSE 0x0020 + +SECStatus +parsePositionalParam(const char * arg, PRUint32 *flags) +{ + if (!strcmp(arg, "crmf")) { + *flags |= TEST_MAKE_CRMF_REQ; + } else if (!strcmp(arg, "dsa")) { + *flags |= TEST_MAKE_CRMF_REQ | TEST_USE_DSA; + doingDSA = PR_TRUE; + } else if (!strcmp(arg, "decode")) { + *flags |= TEST_DECODE_CRMF_REQ; + } else if (!strcmp(arg, "cmmf")) { + *flags |= TEST_DO_CMMF_STUFF; + } else if (!strcmp(arg, "recover")) { + *flags |= TEST_KEY_RECOVERY; + } else if (!strcmp(arg, "challenge")) { + *flags |= TEST_CHALLENGE_RESPONSE; + } else { + printf("unknown positional paremeter: %s\n", arg); + return SECFailure; + } + return SECSuccess; +} + +/* it's not clear, in some cases, whether the desired key is from +** the sign pair or the crypt pair, so we're guessing in some places. +** This define serves to remind us of the places where we're guessing. +*/ +#define WHICH_KEY cryptPair + int main(int argc, char **argv) { - CRMFCertRequest *certReq, *certReq2; - CRMFCertReqMsg *certReqMsg; - CRMFCertReqMsg *secondMsg; - char *configdir; - int irv; - SECStatus rv; - SECKEYPrivateKey *privKey; - SECKEYPublicKey *pubKey; - int o; - PRBool hclInit = PR_FALSE, pArg = PR_FALSE, eArg = PR_FALSE, - sArg = PR_FALSE; + TESTKeyPair signPair, cryptPair; + PLOptState *optstate; + PLOptStatus status; + int irv = 0; + PRUint32 flags = 0; + SECStatus rv; + PRBool nssInit = PR_FALSE; + PRBool pArg = PR_FALSE; + PRBool eArg = PR_FALSE; + PRBool sArg = PR_FALSE; + memset( &signPair, 0, sizeof signPair); + memset( &cryptPair, 0, sizeof cryptPair); printf ("\ncrmftest v1.0\n"); - while (-1 != (o = getopt(argc, argv, "d:p:e:s:"))) { - switch(o) { + optstate = PL_CreateOptState(argc, argv, "d:p:e:s:"); + while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { + switch (optstate->option) { case 'd': - configdir = PORT_Strdup(optarg); - rv = InitHCL(configdir); + configdir = PORT_Strdup(optstate->value); + rv = NSS_Init(configdir); if (rv != SECSuccess) { - printf ("InitHCL failed\n"); + printf ("NSS_Init (-d) failed\n"); return 101; } - hclInit = PR_TRUE; + nssInit = PR_TRUE; break; case 'p': - personalCert = PORT_Strdup(optarg); + personalCert = PORT_Strdup(optstate->value); if (personalCert == NULL) { + printf ("-p failed\n"); return 603; } pArg = PR_TRUE; break; case 'e': - recoveryEncrypter = PORT_Strdup(optarg); + recoveryEncrypter = PORT_Strdup(optstate->value); if (recoveryEncrypter == NULL) { + printf ("-e failed\n"); return 602; } eArg = PR_TRUE; break; case 's': - caCertName = PORT_Strdup(optarg); + caCertName = PORT_Strdup(optstate->value); if (caCertName == NULL) { + printf ("-s failed\n"); return 604; } sArg = PR_TRUE; break; + case 0: /* positional parameter */ + rv = parsePositionalParam(optstate->value, &flags); + if (rv) { + printf ("bad positional parameter.\n"); + return 605; + } + break; default: - Usage(); - return 601; + Usage(); + return 601; } } - if (!hclInit || !pArg || !eArg || !sArg) { + PL_DestroyOptState(optstate); + if (status == PL_OPT_BAD || !nssInit) { Usage(); return 600; } - + if (!flags) + flags = ~ TEST_USE_DSA; + db = CERT_GetDefaultCertDB(); InitPKCS11(); - - irv = CreateCertRequest(&certReq, &privKey, &pubKey); - if (irv != 0 || certReq == NULL) { - goto loser; + + if (flags & TEST_MAKE_CRMF_REQ) { + printf("Generating CRMF request\n"); + irv = DoCRMFRequest(&signPair, &cryptPair); + if (irv) + goto loser; } - certReqMsg = CRMF_CreateCertReqMsg(); - secondMsg = CRMF_CreateCertReqMsg(); - CRMF_CertReqMsgSetCertRequest(certReqMsg, certReq); - CRMF_CertReqMsgSetCertRequest(secondMsg, certReq); - - irv = AddProofOfPossession(certReqMsg, privKey, pubKey, crmfSignature); - irv = AddProofOfPossession(secondMsg, privKey, pubKey, crmfKeyAgreement); - irv = Encode (certReqMsg, secondMsg, configdir); - if (irv != 0) { - goto loser; - } - - rv = CRMF_DestroyCertRequest (certReq); - if (rv != SECSuccess) { - printf ("Error when destroy certificate request.\n"); - irv = 100; - goto loser; + if (flags & TEST_DECODE_CRMF_REQ) { + printf("Decoding CRMF request\n"); + irv = Decode(); + if (irv != 0) { + printf("Error while decoding\n"); + goto loser; + } } - rv = CRMF_DestroyCertReqMsg(certReqMsg); - CRMF_DestroyCertReqMsg(secondMsg); - - irv = Decode (configdir); - if (irv != 0) { - printf("Error while decoding\n"); - goto loser; + if (flags & TEST_DO_CMMF_STUFF) { + printf("Doing CMMF Stuff\n"); + if ((irv = DoCMMFStuff()) != 0) { + printf ("CMMF tests failed.\n"); + goto loser; + } } - if ((irv = DoCMMFStuff(configdir)) != 0) { - printf ("CMMF tests failed.\n"); - goto loser; + if (flags & TEST_KEY_RECOVERY) { + /* Requires some other options be set. + ** Once we know exactly what hey are, test for them here. + */ + printf("Doing Key Recovery\n"); + irv = DoKeyRecovery(WHICH_KEY.privKey); + if (irv != 0) { + printf ("Error doing key recovery\n"); + goto loser; + } } - if ((irv = DoKeyRecovery(configdir, privKey)) != 0) { - printf ("Error doing key recovery\n"); - goto loser; - } - - if ((irv = DoChallengeResponse(configdir, privKey, pubKey)) != 0) { - printf ("Error doing challenge-response\n"); - goto loser; + if (flags & TEST_CHALLENGE_RESPONSE) { + printf("Doing Challenge / Response\n"); + irv = DoChallengeResponse(WHICH_KEY.privKey, WHICH_KEY.pubKey); + if (irv != 0) { + printf ("Error doing challenge-response\n"); + goto loser; + } } printf ("Exiting successfully!!!\n\n"); irv = 0; loser: - CloseHCL(); + DestroyPair(&signPair); + DestroyPair(&cryptPair); + rv = NSS_Shutdown(); + if (rv) { + printf("NSS_Shutdown did not shutdown cleanly!\n"); + } PORT_Free(configdir); + if (irv) + printf("crmftest returning %d\n", irv); return irv; }