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; }