diff options
author | bishakhabanerjee%netscape.com <devnull@localhost> | 2002-07-30 18:44:36 +0000 |
---|---|---|
committer | bishakhabanerjee%netscape.com <devnull@localhost> | 2002-07-30 18:44:36 +0000 |
commit | 35679ede3e52ca0347648faf4f2181d8da6849bf (patch) | |
tree | 541434822da2cdb8421be503b4cac65828f94344 /security/nss/cmd/crmftest | |
parent | ca3351accfec25c363644dce87f83943f387475f (diff) | |
parent | 551b0fd09e1d495bac1c8e37da3bae2cdc39156c (diff) | |
download | nss-hg-35679ede3e52ca0347648faf4f2181d8da6849bf.tar.gz |
Checking in riceman+bmo@mail.rit.edu's patch for bug 133702
Diffstat (limited to 'security/nss/cmd/crmftest')
-rw-r--r-- | security/nss/cmd/crmftest/Makefile | 99 | ||||
-rw-r--r-- | security/nss/cmd/crmftest/config.mk | 43 | ||||
-rw-r--r-- | security/nss/cmd/crmftest/manifest.mn | 53 | ||||
-rw-r--r-- | security/nss/cmd/crmftest/testcrmf.c | 1533 |
4 files changed, 1728 insertions, 0 deletions
diff --git a/security/nss/cmd/crmftest/Makefile b/security/nss/cmd/crmftest/Makefile new file mode 100644 index 000000000..5df669763 --- /dev/null +++ b/security/nss/cmd/crmftest/Makefile @@ -0,0 +1,99 @@ +#! gmake +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape security libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +####################################################################### +# (1) Include initial platform-independent assignments (MANDATORY). # +####################################################################### + +include manifest.mn + +####################################################################### +# (2) Include "global" configuration information. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/config.mk + +####################################################################### +# (3) Include "component" configuration information. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (4) Include "local" platform-dependent assignments (OPTIONAL). # +####################################################################### +include config.mk + +ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.2) +OS_LIBS += -lsvld +endif + +ifeq ($(OS_TARGET)$(OS_RELEASE), SunOS5.6) +OS_LIBS += -ldl -lxnet -lposix4 -lsocket -lnsl +endif + +ifeq (,$(filter-out WIN%,$(OS_TARGET))) +EXTRA_LIBS += $(DIST)/lib/crmf.lib +else +EXTRA_LIBS += $(DIST)/lib/libcrmf.$(LIB_SUFFIX) +endif + +include ../platlibs.mk + +####################################################################### +# (5) Execute "global" rules. (OPTIONAL) # +####################################################################### + +include $(CORE_DEPTH)/coreconf/rules.mk + +####################################################################### +# (6) Execute "component" rules. (OPTIONAL) # +####################################################################### + + + +####################################################################### +# (7) Execute "local" rules. (OPTIONAL). # +####################################################################### + +LDDIST = $(DIST)/lib + +ifeq (,$(filter-out WIN%,$(OS_TARGET))) +EXTRA_LIBS += $(LDDIST)/sectool.lib +endif + +lame: + echo $(CPU_ARCH) + +include ../platrules.mk diff --git a/security/nss/cmd/crmftest/config.mk b/security/nss/cmd/crmftest/config.mk new file mode 100644 index 000000000..7343609f8 --- /dev/null +++ b/security/nss/cmd/crmftest/config.mk @@ -0,0 +1,43 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape security libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +# +# Override TARGETS variable so that only static libraries +# are specifed as dependencies within rules.mk. +# + +TARGETS = $(PROGRAM) +SHARED_LIBRARY = +IMPORT_LIBRARY = +LIBRARY = + diff --git a/security/nss/cmd/crmftest/manifest.mn b/security/nss/cmd/crmftest/manifest.mn new file mode 100644 index 000000000..b27e4a3d8 --- /dev/null +++ b/security/nss/cmd/crmftest/manifest.mn @@ -0,0 +1,53 @@ +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Netscape security libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +CORE_DEPTH = ../../.. +DEPTH = . + +# MODULE public and private header directories are implicitly REQUIRED. +MODULE = security + +EXPORTS = \ + $(NULL) + +CSRCS = \ + testcrmf.c \ + $(NULL) + + +# The MODULE is always implicitly required. +# Listing it here in REQUIRES makes it appear twice in the cc command line. +REQUIRES = dbm + +PROGRAM = crmftest + diff --git a/security/nss/cmd/crmftest/testcrmf.c b/security/nss/cmd/crmftest/testcrmf.c new file mode 100644 index 000000000..e9bb08bdb --- /dev/null +++ b/security/nss/cmd/crmftest/testcrmf.c @@ -0,0 +1,1533 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1994-2000 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. If you wish to allow use of your + * version of this file only under the terms of the GPL and not to + * allow others to use your version of this file under the MPL, + * indicate your decision by deleting the provisions above and + * replace them with the notice and other provisions required by + * the GPL. If you do not delete the provisions above, a recipient + * may use your version of this file under either the MPL or the + * GPL. + */ + +#include "crmf.h" +#include "secrng.h" +#include "secpkcs5.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 "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 <stdio.h> +#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; +char *personalCert = NULL; +char *recoveryEncrypter = NULL; +char *caCertName = NULL; + +CERTCertDBHandle *db; +SECKEYKeyDBHandle *keydb; + +void +debug_test(SECItem *src, char *filePath) +{ + PRFileDesc *fileDesc; + + fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, + 0666); + if (fileDesc == NULL) { + printf ("Could not cretae file %s.\n", filePath); + return; + } + PR_Write(fileDesc, src->data, src->len); + +} + +SECStatus +get_serial_number(long *dest) +{ + RNGContext *rng; + SECStatus rv; + + if (dest == NULL) { + 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); + return SECSuccess; +} + +char * +promptForPassword (PK11SlotInfo *slot, PRBool retry, void *cx) +{ + char passWord[80]; + char *retPass = NULL; + + if (retry) { + printf ("Incorrect password. Please re-enter the password.\n"); + } + printf ("WARNING: Password will be echoed to the screen.\n"); + printf ("Please enter the password for slot \"%s\":", + PK11_GetTokenName(slot)); + scanf ("%s", passWord); + retPass = PORT_Strdup(passWord); + return retPass; +} + +PK11RSAGenParams * +GetRSAParams(void) +{ + PK11RSAGenParams *rsaParams; + + rsaParams = PORT_ZNew(PK11RSAGenParams); + + if (rsaParams == NULL) + return NULL; + + rsaParams->keySizeInBits = MAX_KEY_LEN; + rsaParams->pe = 0x1001; + + return rsaParams; + +} + +SECStatus +SetSlotPassword(PK11SlotInfo *slot) +{ + char userPin[80]; + + printf ("Initialization of PIN's for your Database.\n"); + printf ("------------------------------------------\n"); + printf ("Please enter the PIN's for your Database.\n"); + printf ("Warning: ALL PIN'S WILL BE ECHOED TO SCREEN!!!\n"); + printf ("Now enter the PIN for the user: "); + scanf ("%s", userPin); + return PK11_InitPin (slot, NULL, userPin); +} + +PQGParams* +GetDSAParams(void) +{ + PQGParams *params = NULL; + PQGVerify *vfy = NULL; + + SECStatus rv; + + rv = PQG_ParamGen(0, ¶ms, &vfy); + if (rv != SECSuccess) { + return NULL; + } + PQG_DestroyVerify(vfy); + return params; +} + +CERTSubjectPublicKeyInfo * +GetSubjectPubKeyInfo(SECKEYPrivateKey **destPrivKey, + SECKEYPublicKey **destPubKey) { + 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); + 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; + } + 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) { + SECKEY_DestroyPublicKey(pubKey); + } + if (privKey) { + SECKEY_DestroyPrivateKey(privKey); + } + return NULL; + } + + spki = SECKEY_CreateSubjectPublicKeyInfo(pubKey); + *destPrivKey = privKey; + *destPubKey = pubKey; + return spki; +} + + +SECStatus +InitPKCS11(void) +{ + PK11SlotInfo *cryptoSlot, *keySlot; + + PK11_SetPasswordFunc(promptForPassword); + + cryptoSlot = PK11_GetInternalSlot(); + keySlot = PK11_GetInternalKeySlot(); + + if (PK11_NeedUserInit(cryptoSlot) && PK11_NeedLogin(cryptoSlot)) { + if (SetSlotPassword (cryptoSlot) != SECSuccess) { + printf ("Initializing the PIN's failed.\n"); + return SECFailure; + } + } + + if (PK11_NeedUserInit(keySlot) && PK11_NeedLogin(keySlot)) { + if (SetSlotPassword (keySlot) != SECSuccess) { + printf ("Initializing the PIN's failed.\n"); + return SECFailure; + } + } + + PK11_FreeSlot(cryptoSlot); + PK11_FreeSlot(keySlot); + return SECSuccess; +} + + +void +WriteItOut (void *arg, const char *buf, unsigned long len) +{ + PRFileDesc *fileDesc = (PRFileDesc*)arg; + + 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]; + + 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; + return extInfo; +} + +void +FreeExtInfo(CRMFCertExtCreationInfo *extInfo) +{ + int i; + + for (i=0; i<extInfo->numExtensions; i++) { + CRMF_DestroyCertExtension(extInfo->extensions[i]); + } + PORT_Free(extInfo->extensions); + PORT_Free(extInfo); +} + +int +CreateCertRequest (CRMFCertRequest **inCertReq, SECKEYPrivateKey **privKey, + SECKEYPublicKey **pubKey) +{ + 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; + CERTSubjectPublicKeyInfo *spki; + SECStatus rv; + SECOidTag tag, tag2; + SECItem issuerUID, subjectUID; + CRMFCertExtCreationInfo *extInfo; + CRMFEncryptedKey *encKey; + CERTCertificate *caCert; + CRMFPKIArchiveOptions *pkiArchOpt; + + *inCertReq = NULL; + certReq = CRMF_CreateCertRequest(0x0ff02345); + if (certReq == NULL) { + printf ("Could not initialize a certificate request.\n"); + return 1; + } + rv = CRMF_CertRequestSetTemplateField (certReq, crmfVersion, (void*)(&version)); + if (rv != SECSuccess) { + printf("Could not add the version number to the " + "Certificate Request.\n"); + CRMF_DestroyCertRequest(certReq); + return 2; + } + + 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) { + printf ("Could not add serial number to certificate template\n."); + CRMF_DestroyCertRequest(certReq); + return 4; + } + + issuer = CERT_AsciiToName(issuerStr); + if (issuer == NULL) { + printf ("Could not create CERTName structure from %s.\n", issuerStr); + 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"); + CRMF_DestroyCertRequest(certReq); + return 6; + } + + 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); + if (algID == NULL) { + printf ("Couldn't create algorithm ID\n"); + CRMF_DestroyCertRequest(certReq); + return 9; + } + rv = CRMF_CertRequestSetTemplateField(certReq, crmfSigningAlg, (void*)algID); + SECOID_DestroyAlgorithmID(algID, PR_TRUE); + if (rv != SECSuccess) { + printf ("Could not add the signing algorithm to the cert template.\n"); + CRMF_DestroyCertRequest(certReq); + return 10; + } + + validity.notBefore = ¬Before; + validity.notAfter = NULL; + notBefore = PR_Now(); + rv = CRMF_CertRequestSetTemplateField(certReq, crmfValidity,(void*)(&validity)); + if (rv != SECSuccess) { + printf ("Could not add validity to cert template\n"); + CRMF_DestroyCertRequest(certReq); + return 11; + } + + spki = GetSubjectPubKeyInfo(privKey, pubKey); + if (spki == NULL) { + printf ("Could not create a Subject Public Key Info to add\n"); + CRMF_DestroyCertRequest(certReq); + return 12; + } + rv = CRMF_CertRequestSetTemplateField(certReq, crmfPublicKey, (void*)spki); + SECKEY_DestroySubjectPublicKeyInfo(spki); + if (rv != SECSuccess) { + printf ("Could not add the public key to the template\n"); + CRMF_DestroyCertRequest(certReq); + return 13; + } + + caCert = + CERT_FindCertByNickname(CERT_GetDefaultCertDB(), + 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); + CERT_DestroyCertificate(caCert); + if (encKey == NULL) { + printf ("Could not create Encrypted Key with Encrypted Value.\n"); + return 14; + } + pkiArchOpt = CRMF_CreatePKIArchiveOptions(crmfEncryptedPrivateKey, encKey); + CRMF_DestroyEncryptedKey(encKey); + if (pkiArchOpt == NULL) { + printf ("Could not create PKIArchiveOptions.\n"); + return 15; + } + rv = CRMF_CertRequestSetPKIArchiveOptions(certReq, pkiArchOpt); + CRMF_DestroyPKIArchiveOptions(pkiArchOpt); + if (rv != SECSuccess) { + printf ("Could not add the PKIArchiveControl to Cert Request.\n"); + return 16; + } + *inCertReq = certReq; + return 0; +} + +int +Encode (CRMFCertReqMsg *inCertReq, + CRMFCertReqMsg *secondReq, char *configdir) +{ +#define PATH_LEN 150 +#define CRMF_FILE "CertReqMessages.der" + char filePath[PATH_LEN]; + PRFileDesc *fileDesc; + SECStatus rv; + int irv = 0; + CRMFCertReqMsg *msgArr[3]; + CRMFCertReqMsg *newMsg; + + PR_snprintf(filePath, PATH_LEN, "%s/%s", configdir, CRMF_FILE); + fileDesc = PR_Open (filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, + 0666); + if (fileDesc == NULL) { + printf ("Could not open file %s\n", filePath); + irv = 14; + goto finish; + } +/* rv = CRMF_EncodeCertReqMsg (inCertReq, WriteItOut, (void*)fileDesc);*/ + msgArr[0] = inCertReq; + msgArr[1] = secondReq; + 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: + PR_Close(fileDesc); + return irv; +} + +int +AddProofOfPossession(CRMFCertReqMsg *certReqMsg, SECKEYPrivateKey *privKey, + SECKEYPublicKey *pubKey, CRMFPOPChoice inPOPChoice) +{ + + switch(inPOPChoice){ + case crmfSignature: + CRMF_CertReqMsgSetSignaturePOP(certReqMsg, privKey, pubKey, NULL, NULL, + NULL); + break; + case crmfRAVerified: + CRMF_CertReqMsgSetRAVerifiedPOP(certReqMsg); + break; + case crmfKeyEncipherment: + CRMF_CertReqMsgSetKeyEnciphermentPOP(certReqMsg, + crmfSubsequentMessage, + crmfChallengeResp, NULL); + break; + case crmfKeyAgreement: + { + SECItem pendejo; + unsigned char lame[] = { 0xf0, 0x0f, 0xf0, 0x0f, 0xf0 }; + + pendejo.data = lame; + pendejo.len = 5; + + CRMF_CertReqMsgSetKeyAgreementPOP(certReqMsg, crmfThisMessage, + crmfNoSubseqMess, &pendejo); + } + break; + default: + return 1; + } + return 0; +} + +#define BUFF_SIZE 150 + +int +Decode(char *configdir) +{ + 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}; + CRMFCertReqMessages *certReqMsgs; + int numMsgs, i; + long lame; + + 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 (bytesRead < 0) { + printf ("Error while getting the length of the file %s\n", filePath); + return 200; + } + + 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; + } + /*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); + if (certReqMsgs == NULL) { + printf ("Error decoding CertReqMessages.\n"); + return 202; + } + numMsgs = CRMF_CertReqMessagesGetNumMessages(certReqMsgs); + if (numMsgs <= 0) { + printf ("WARNING: The DER contained %d messages.\n", numMsgs); + } + for (i=0; i < numMsgs; 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); + certReq = CRMF_CertReqMsgGetCertRequest(certReqMsg); + CRMF_CertRequestGetCertTemplateValidity(certReq, &validity); + CRMF_DestroyGetValidity(&validity); + CRMF_DestroyCertRequest(certReq); + CRMF_DestroyCertReqMsg(certReqMsg); + } + CRMF_DestroyCertReqMessages(certReqMsgs); + PORT_Free(asn1Buff); + return 0; +} + +void +GetBitsFromFile(char *filePath, SECItem *fileBits) +{ + PRFileDesc *fileDesc; + int bytesRead, fileLen=0; + char buffer[BUFF_SIZE], *asn1Buf; + + 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; + } + 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; + } + 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; +} + +int +DecodeCMMFCertRepContent(char *derFile) +{ + int fileLen=0; + char *asn1Buf; + SECItem fileBits; + CMMFCertRepContent *certRepContent; + + + 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); + if (certRepContent == NULL) { + printf ("Error while decoding %s\n", derFile); + return 303; + } + CMMF_DestroyCertRepContent(certRepContent); + PORT_Free(asn1Buf); + return 0; +} + +int +DoCMMFStuff(char *configdir) +{ + 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; + + 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; + + 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) { + printf ("Could not open file %s\n", filePath); + rv = 400; + goto finish; + } + + srv = CMMF_EncodeCertRepContent(certRepContent, WriteItOut, + (void*)fileDesc); + PORT_Assert (srv == SECSuccess); + PR_Close(fileDesc); + rv = DecodeCMMFCertRepContent(filePath); + if (rv != 0) { + goto finish; + } + random = 0xa4e7; + caCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), + caCertName); + if (caCert == NULL) { + printf ("Could not get the certifcate for %s\n", caCertName); + rv = 411; + goto finish; + } + repContent = CMMF_CreateKeyRecRepContent(); + if (repContent == NULL) { + printf ("Could not allocate a CMMFKeyRecRepContent structure\n"); + rv = 407; + goto finish; + } + srv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(repContent, + cmmfGrantedWithMods); + if (srv != SECSuccess) { + printf ("Error trying to set PKIStatusInfo for " + "CMMFKeyRecRepContent.\n"); + rv = 406; + goto finish; + } + srv = CMMF_KeyRecRepContentSetNewSignCert(repContent, cert); + if (srv != SECSuccess) { + printf ("Error trying to set the new signing certificate for " + "key recovery\n"); + rv = 408; + goto finish; + } + srv = CMMF_KeyRecRepContentSetCACerts(repContent, list); + if (srv != SECSuccess) { + printf ("Errory trying to add the list of CA certs to the " + "CMMFKeyRecRepContent structure.\n"); + rv = 409; + goto finish; + } + privKey = PK11_FindKeyByAnyCert(cert, NULL); + if (privKey == NULL) { + printf ("Could not get the private key associated with the\n" + "certificate %s\n", personalCert); + 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) { + printf ("Could not open file %s\n", filePath); + rv = 414; + goto finish; + } + + srv = CMMF_EncodeKeyRecRepContent(repContent, WriteItOut, + (void*)fileDesc); + PORT_Assert (srv == SECSuccess); + PR_Close(fileDesc); + CMMF_DestroyKeyRecRepContent(repContent); + GetBitsFromFile(filePath, &fileBits); + 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; + } + finish: + if (repContent) { + CMMF_DestroyKeyRecRepContent(repContent); + } + 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; +} + +static CK_MECHANISM_TYPE +mapWrapKeyType(KeyType keyType) +{ + switch (keyType) { + case rsaKey: + return CKM_RSA_PKCS; + default: + break; + } + return CKM_INVALID_MECHANISM; +} + +#define KNOWN_MESSAGE_LENGTH 20 /*160 bits*/ + +int +DoKeyRecovery(char *configdir, 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; + CMMFKeyRecRepContent *keyRecRep; + SECStatus rv; + CERTCertificate *caCert, *myCert; + SECKEYPublicKey *caPubKey; + PRFileDesc *fileDesc; + SECItem fileBits, nickname; + CMMFCertifiedKeyPair *certKeyPair; + + /*caCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), + caCertName);*/ + myCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), personalCert); + if (myCert == NULL) { + printf ("Could not find the certificate for %s\n", personalCert); + return 700; + } + caCert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), + recoveryEncrypter); + if (caCert == NULL) { + printf ("Could not find the certificate for %s\n", recoveryEncrypter); + return 701; + } + caPubKey = CERT_ExtractPublicKey(caCert); + pubKey = SECKEY_ConvertToPublicKey(privKey); + max_bytes_encrypted = PK11_GetPrivateModulusLen(privKey); + slot = PK11_GetBestSlot(mapWrapKeyType(privKey->keyType), NULL); + id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE); + switch(privKey->keyType) { + case rsaKey: + mech.mechanism = CKM_RSA_PKCS; + break; + case dsaKey: + mech.mechanism = CKM_DSA; + break; + case dhKey: + mech.mechanism = CKM_DH_PKCS_DERIVE; + break; + default: + printf ("Bad Key type in key recovery.\n"); + return 512; + + } + PK11_EnterSlotMonitor(slot); + crv = PK11_GETTAB(slot)->C_EncryptInit(slot->session, &mech, id); + if (crv != CKR_OK) { + PK11_ExitSlotMonitor(slot); + PK11_FreeSlot(slot); + printf ("C_EncryptInit failed in KeyRecovery\n"); + return 500; + } + ciphertext = PORT_NewArray(unsigned char, max_bytes_encrypted); + if (ciphertext == NULL) { + PK11_ExitSlotMonitor(slot); + PK11_FreeSlot(slot); + printf ("Could not allocate memory for ciphertext.\n"); + return 501; + } + bytes_encrypted = max_bytes_encrypted; + crv = PK11_GETTAB(slot)->C_Encrypt(slot->session, + known_message, + KNOWN_MESSAGE_LENGTH, + ciphertext, + &bytes_encrypted); + PK11_ExitSlotMonitor(slot); + PK11_FreeSlot(slot); + if (crv != CKR_OK) { + PORT_Free(ciphertext); + return 502; + } + /* Always use the smaller of these two values . . . */ + bytes_compared = ( bytes_encrypted > KNOWN_MESSAGE_LENGTH ) + ? KNOWN_MESSAGE_LENGTH + : bytes_encrypted; + + /* If there was a failure, the plaintext */ + /* goes at the end, therefore . . . */ + text_compared = ( bytes_encrypted > KNOWN_MESSAGE_LENGTH ) + ? (ciphertext + bytes_encrypted - + KNOWN_MESSAGE_LENGTH ) + : ciphertext; + + keyRecRep = CMMF_CreateKeyRecRepContent(); + if (keyRecRep == NULL) { + PORT_Free(ciphertext); + PK11_FreeSlot(slot); + CMMF_DestroyKeyRecRepContent(keyRecRep); + printf ("Could not allocate a CMMFKeyRecRepContent structre.\n"); + return 503; + } + rv = CMMF_KeyRecRepContentSetPKIStatusInfoStatus(keyRecRep, + cmmfGranted); + if (rv != SECSuccess) { + PORT_Free(ciphertext); + PK11_FreeSlot(slot); + CMMF_DestroyKeyRecRepContent(keyRecRep); + printf ("Could not set the status for the KeyRecRepContent\n"); + return 504; + } + /* The myCert here should correspond to the certificate corresponding + * to the private key, but for this test any certificate will do. + */ + rv = CMMF_KeyRecRepContentSetCertifiedKeyPair(keyRecRep, myCert, + privKey, caPubKey); + if (rv != SECSuccess) { + PORT_Free(ciphertext); + PK11_FreeSlot(slot); + CMMF_DestroyKeyRecRepContent(keyRecRep); + printf ("Could not set the Certified Key Pair\n"); + return 505; + } + 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) { + PORT_Free(ciphertext); + PK11_FreeSlot(slot); + CMMF_DestroyKeyRecRepContent(keyRecRep); + printf ("Could not open file %s\n", filePath); + return 506; + } + rv = CMMF_EncodeKeyRecRepContent(keyRecRep, WriteItOut, fileDesc); + CMMF_DestroyKeyRecRepContent(keyRecRep); + PR_Close(fileDesc); + + if (rv != SECSuccess) { + PORT_Free(ciphertext); + PK11_FreeSlot(slot); + printf ("Error while encoding CMMFKeyRecRepContent\n"); + return 507; + } + GetBitsFromFile(filePath, &fileBits); + if (fileBits.data == NULL) { + PORT_Free(ciphertext); + PK11_FreeSlot(slot); + printf ("Could not get the bits from file %s\n", filePath); + return 508; + } + keyRecRep = + CMMF_CreateKeyRecRepContentFromDER(db,(const char*)fileBits.data, + fileBits.len); + if (keyRecRep == NULL) { + printf ("Could not decode the KeyRecRepContent in file %s\n", + filePath); + PORT_Free(ciphertext); + PK11_FreeSlot(slot); + return 509; + } + caPrivKey = PK11_FindKeyByAnyCert(caCert, NULL); + if (CMMF_KeyRecRepContentGetPKIStatusInfoStatus(keyRecRep) != + cmmfGranted) { + PORT_Free(ciphertext); + PK11_FreeSlot(slot); + CMMF_DestroyKeyRecRepContent(keyRecRep); + printf ("A bad status came back with the " + "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, + caPrivKey, + &nickname, + PK11_GetInternalKeySlot(), + db, + &unwrappedPrivKey, NULL); + CMMF_DestroyCertifiedKeyPair(certKeyPair); + if (rv != SECSuccess) { + printf ("Unwrapping the private key failed.\n"); + return 511; + } + /*Now let's try to decrypt the ciphertext with the "recovered" key*/ + PK11_EnterSlotMonitor(slot); + crv = + PK11_GETTAB(slot)->C_DecryptInit(unwrappedPrivKey->pkcs11Slot->session, + &mech, + unwrappedPrivKey->pkcs11ID); + if (crv != CKR_OK) { + PK11_ExitSlotMonitor(slot); + PORT_Free(ciphertext); + PK11_FreeSlot(slot); + printf ("Decrypting with the recovered key failed.\n"); + return 513; + } + bytes_decrypted = KNOWN_MESSAGE_LENGTH; + crv = PK11_GETTAB(slot)->C_Decrypt(unwrappedPrivKey->pkcs11Slot->session, + ciphertext, + bytes_encrypted, plaintext, + &bytes_decrypted); + SECKEY_DestroyPrivateKey(unwrappedPrivKey); + PK11_ExitSlotMonitor(slot); + PORT_Free(ciphertext); + if (crv != CKR_OK) { + PK11_FreeSlot(slot); + printf ("Decrypting the ciphertext with recovered key failed.\n"); + return 514; + } + if ((bytes_decrypted != KNOWN_MESSAGE_LENGTH) || + (PORT_Memcmp(plaintext, known_message, KNOWN_MESSAGE_LENGTH) != 0)) { + PK11_FreeSlot(slot); + printf ("The recovered plaintext does not equal the known message:\n" + "\tKnown message: %s\n" + "\tRecovered plaintext: %s\n", known_message, plaintext); + return 515; + } + return 0; +} + +int +DoChallengeResponse(char *configdir, SECKEYPrivateKey *privKey, + SECKEYPublicKey *pubKey) +{ + CMMFPOPODecKeyChallContent *chalContent = NULL; + CMMFPOPODecKeyRespContent *respContent = NULL; + 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; + SECKEYPrivateKey *foundPrivKey; + + chalContent = CMMF_CreatePOPODecKeyChallContent(); + myCert = CERT_FindCertByNickname(db, personalCert); + if (myCert == NULL) { + printf ("Could not find the certificate for %s\n", personalCert); + return 900; + } + poolp = PORT_NewArena(1024); + if (poolp == NULL) { + printf("Could no allocate a new arena in DoChallengeResponse\n"); + return 901; + } + myGenName = CERT_GetCertificateNames(myCert, poolp); + if (myGenName == NULL) { + printf ("Could not get the general names for %s certificate\n", + personalCert); + return 902; + } + randomNums = PORT_ArenaNewArray(poolp,long, numChallengesSet); + rng = RNG_CreateContext(); + RNG_GenerateRandomBytes(rng, randomNums, numChallengesSet*sizeof(long)); + for (i=0; i<numChallengesSet; i++) { + rv = CMMF_POPODecKeyChallContentSetNextChallenge(chalContent, + randomNums[i], + myGenName, + pubKey, + NULL); + } + RNG_DestroyContext(rng, PR_TRUE); + if (rv != SECSuccess) { + printf ("Could not set the challenge in DoChallengeResponse\n"); + return 903; + } + PR_snprintf(filePath, PATH_LEN, "%s/POPODecKeyChallContent.der", + configdir); + fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, + 0666); + if (fileDesc == NULL) { + printf ("Could not open file %s\n", filePath); + return 904; + } + rv = CMMF_EncodePOPODecKeyChallContent(chalContent,WriteItOut, + (void*)fileDesc); + PR_Close(fileDesc); + CMMF_DestroyPOPODecKeyChallContent(chalContent); + if (rv != SECSuccess) { + printf ("Could not encode the POPODecKeyChallContent.\n"); + return 905; + } + GetBitsFromFile(filePath, &DecKeyChallBits); + chalContent = + CMMF_CreatePOPODecKeyChallContentFromDER + ((const char*)DecKeyChallBits.data, DecKeyChallBits.len); + PORT_Free(DecKeyChallBits.data); + if (chalContent == NULL) { + printf ("Could not create the POPODecKeyChallContent from DER\n"); + return 906; + } + numChallengesFound = + CMMF_POPODecKeyChallContentGetNumChallenges(chalContent); + if (numChallengesFound != numChallengesSet) { + printf ("Number of Challenges Found (%d) does not equal the number " + "set (%d)\n", numChallengesFound, numChallengesSet); + return 907; + } + for (i=0; i<numChallengesSet; i++) { + publicValue = CMMF_POPODecKeyChallContentGetPublicValue(chalContent, i); + if (publicValue == NULL) { + printf("Could not get the public value for challenge at index %d\n", + i); + return 908; + } + keyID = PK11_MakeIDFromPubKey(publicValue); + if (keyID == NULL) { + printf ("Could not make the keyID from the public value\n"); + return 909; + } + foundPrivKey = PK11_FindKeyByKeyID(privKey->pkcs11Slot,keyID, NULL); + if (foundPrivKey == NULL) { + printf ("Could not find the private key corresponding to the public" + " value.\n"); + return 910; + } + rv = CMMF_POPODecKeyChallContDecryptChallenge(chalContent, i, + foundPrivKey); + if (rv != SECSuccess) { + printf ("Could not decrypt the challenge at index %d\n", i); + return 911; + } + rv = CMMF_POPODecKeyChallContentGetRandomNumber(chalContent, i, + &retrieved); + if (rv != SECSuccess) { + printf ("Could not get the random number from the challenge at " + "index %d\n", i); + return 912; + } + if (retrieved != randomNums[i]) { + printf ("Retrieved the number (%d), expected (%d)\n", retrieved, + randomNums[i]); + return 913; + } + } + CMMF_DestroyPOPODecKeyChallContent(chalContent); + PR_snprintf(filePath, PATH_LEN, "%s/POPODecKeyRespContent.der", + configdir); + fileDesc = PR_Open(filePath, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, + 0666); + if (fileDesc == NULL) { + printf ("Could not open file %s\n", filePath); + return 914; + } + rv = CMMF_EncodePOPODecKeyRespContent(randomNums, numChallengesSet, + WriteItOut, fileDesc); + PR_Close(fileDesc); + if (rv != 0) { + printf ("Could not encode the POPODecKeyRespContent\n"); + return 915; + } + GetBitsFromFile(filePath, &DecKeyChallBits); + respContent = + CMMF_CreatePOPODecKeyRespContentFromDER((const char*)DecKeyChallBits.data, + DecKeyChallBits.len); + if (respContent == NULL) { + printf ("Could not decode the contents of the file %s\n", filePath); + return 916; + } + numChallengesFound = + CMMF_POPODecKeyRespContentGetNumResponses(respContent); + if (numChallengesFound != numChallengesSet) { + printf ("Number of responses found (%d) does not match the number " + "of challenges set (%d)\n", + numChallengesFound, numChallengesSet); + return 917; + } + for (i=0; i<numChallengesSet; i++) { + rv = CMMF_POPODecKeyRespContentGetResponse(respContent, i, &retrieved); + if (rv != SECSuccess) { + printf ("Could not retrieve the response at index %d\n", i); + return 918; + } + if (retrieved != randomNums[i]) { + printf ("Retrieved the number (%ld), expected (%ld)\n", retrieved, + randomNums[i]); + return 919; + } + + } + CMMF_DestroyPOPODecKeyRespContent(respContent); + return 0; +} + +char * +certdb_name_cb(void *arg, int dbVersion) +{ + char *configdir = (char *)arg; + char *dbver; + + switch (dbVersion) { + case 7: + dbver = "7"; + break; + case 6: + dbver = "6"; + break; + case 5: + dbver = "5"; + break; + case 4: + default: + dbver = ""; + break; + } + return PR_smprintf("%s/cert%s.db", configdir, dbver); +} + +SECStatus +OpenCertDB(char *configdir) +{ + CERTCertDBHandle *certdb; + SECStatus status = SECFailure; + + certdb = PORT_ZNew(CERTCertDBHandle); + if (certdb == 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); + } + loser: + return status; +} + +char * +keydb_name_cb(void *arg, int dbVersion) +{ + char *configdir = (char*) arg; + char *dbver; + + switch(dbVersion){ + case 3: + dbver = "3"; + break; + case 2: + default: + dbver = ""; + break; + } + return PR_smprintf("%s/key%s.db", configdir, dbver); +} + +SECStatus +OpenKeyDB(char *configdir) +{ + SECKEYKeyDBHandle *keydb; + + keydb = SECKEY_OpenKeyDB(PR_FALSE, keydb_name_cb, configdir); + if (keydb == NULL) { + return SECFailure; + } + SECKEY_SetDefaultKeyDB(keydb); + return SECSuccess; +} + +SECStatus +OpenSecModDB(char *configdir) +{ + char *secmodname = PR_smprintf("%d/secmod.db", configdir); + if (secmodname == NULL) { + return SECFailure; + } + SECMOD_init(secmodname); + return SECSuccess; +} + +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) { + 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(); + } + return rv; +} +void +Usage (void) +{ + printf ("Usage:\n" + "\tcrmftest -d [Database Directory] -p [Personal Cert]\n" + "\t -e [Encrypter] -s [CA Certificate]\n\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" + "\twhere the program will place CRMF/CMMF der files\n" + "Personal Cert\n" + "\tThis is the certificate that already exists in the cert\n" + "\tdatabase to use while encoding the response. The private\n" + "\tkey associated with the certificate must also exist in the\n" + "\tkey database.\n" + "Encrypter\n" + "\tThis is the certificate to use when encrypting the the \n" + "\tkey recovery response. The private key for this cert\n" + "\tmust also be present in the key database.\n" + "CA Certificate\n" + "\tThis is the nickname of the certificate to use as the\n" + "\tCA when doing all of the encoding.\n"); +} + +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; + + printf ("\ncrmftest v1.0\n"); + while (-1 != (o = getopt(argc, argv, "d:p:e:s:"))) { + switch(o) { + case 'd': + configdir = PORT_Strdup(optarg); + rv = InitHCL(configdir); + if (rv != SECSuccess) { + printf ("InitHCL failed\n"); + return 101; + } + hclInit = PR_TRUE; + break; + case 'p': + personalCert = PORT_Strdup(optarg); + if (personalCert == NULL) { + return 603; + } + pArg = PR_TRUE; + break; + case 'e': + recoveryEncrypter = PORT_Strdup(optarg); + if (recoveryEncrypter == NULL) { + return 602; + } + eArg = PR_TRUE; + break; + case 's': + caCertName = PORT_Strdup(optarg); + if (caCertName == NULL) { + return 604; + } + sArg = PR_TRUE; + break; + default: + Usage(); + return 601; + } + } + if (!hclInit || !pArg || !eArg || !sArg) { + Usage(); + return 600; + } + + InitPKCS11(); + + irv = CreateCertRequest(&certReq, &privKey, &pubKey); + if (irv != 0 || certReq == NULL) { + 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; + } + + rv = CRMF_DestroyCertReqMsg(certReqMsg); + CRMF_DestroyCertReqMsg(secondMsg); + + irv = Decode (configdir); + if (irv != 0) { + printf("Error while decoding\n"); + goto loser; + } + + if ((irv = DoCMMFStuff(configdir)) != 0) { + printf ("CMMF tests failed.\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; + } + printf ("Exiting successfully!!!\n\n"); + irv = 0; + + loser: + CloseHCL(); + PORT_Free(configdir); + return irv; +} |