numVars; i++) {
+ if (strcmp(varTable->variables[i]->name, key) == 0) {
+ retVal = varTable->variables[i]->value;
+ break;
+ }
+ }
+ return retVal;
+}
+
+char*
+passwordCallback(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ const char *passwd;
+ if (retry) {
+ return NULL;
+ }
+ passwd = CGITableFindValue((CGIVarTable*)arg, "dbPassword");
+ if (passwd == NULL) {
+ return NULL;
+ }
+ return PORT_Strdup(passwd);
+}
+
+ErrorCode
+initNSS(CGIVarTable *varTable)
+{
+ const char *nssDir;
+ PK11SlotInfo *keySlot;
+ SECStatus rv;
+
+ nssDir = CGITableFindValue(varTable,"NSSDirectory");
+ if (nssDir == NULL) {
+ missingVar = "NSSDirectory";
+ return REQ_CGI_VAR_NOT_PRESENT;
+ }
+ rv = NSS_Init(nssDir);
+ if (rv != SECSuccess) {
+ return NSS_INIT_FAILED;
+ }
+ PK11_SetPasswordFunc(passwordCallback);
+ keySlot = PK11_GetInternalKeySlot();
+ rv = PK11_Authenticate(keySlot, PR_FALSE, varTable);
+ PK11_FreeSlot(keySlot);
+ if (rv != SECSuccess) {
+ return AUTH_FAILED;
+ }
+ return NO_ERROR;
+}
+
+void
+dumpErrorMessage(ErrorCode errNum)
+{
+ spitOutHeaders();
+ printf("ErrorError processing "
+ "data
Received the error %d", errNum);
+ if (errNum == REQ_CGI_VAR_NOT_PRESENT) {
+ printf ("The missing variable is %s.", missingVar);
+ }
+ printf ("More useful information here in the future.");
+}
+
+ErrorCode
+initOldCertReq(CERTCertificateRequest *oldCertReq,
+ CERTName *subject, CERTSubjectPublicKeyInfo *spki)
+{
+ PLArenaPool *poolp;
+
+ poolp = oldCertReq->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SEC_ASN1EncodeInteger(poolp, &oldCertReq->version,
+ SEC_CERTIFICATE_VERSION_3);
+ CERT_CopyName(poolp, &oldCertReq->subject, subject);
+ SECKEY_CopySubjectPublicKeyInfo(poolp, &oldCertReq->subjectPublicKeyInfo,
+ spki);
+ oldCertReq->attributes = NULL;
+ return NO_ERROR;
+}
+
+ErrorCode
+addExtensions(CERTCertificate *newCert, CRMFCertRequest *certReq)
+{
+ int numExtensions, i;
+ void *extHandle;
+ ErrorCode rv = NO_ERROR;
+ CRMFCertExtension *ext;
+ SECStatus srv;
+
+ numExtensions = CRMF_CertRequestGetNumberOfExtensions(certReq);
+ if (numExtensions == 0) {
+ /* No extensions to add */
+ return NO_ERROR;
+ }
+ extHandle = CERT_StartCertExtensions(newCert);
+ if (extHandle == NULL) {
+ rv = COULD_NOT_START_EXTENSIONS;
+ goto loser;
+ }
+ for (i=0; idata, der->len);
+ PR_Close(outfile);
+
+}
+
+ErrorCode
+createNewCert(CERTCertificate**issuedCert,CERTCertificateRequest *oldCertReq,
+ CRMFCertReqMsg *currReq, CRMFCertRequest *certReq,
+ CERTCertificate *issuerCert, CGIVarTable *varTable)
+{
+ CERTCertificate *newCert = NULL;
+ CERTValidity *validity;
+ PRExplodedTime printableTime;
+ PRTime now, after;
+ ErrorCode rv=NO_ERROR;
+ SECKEYPrivateKey *issuerPrivKey;
+ SECItem derCert = { 0 };
+ SECOidTag signTag;
+ SECStatus srv;
+ long version;
+
+ now = PR_Now();
+ PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
+ printableTime.tm_month += 9;
+ after = PR_ImplodeTime(&printableTime);
+ validity = CERT_CreateValidity(now, after);
+ newCert = *issuedCert =
+ CERT_CreateCertificate(rand(), &(issuerCert->subject), validity,
+ oldCertReq);
+ if (newCert == NULL) {
+ rv = ERROR_CREATING_NEW_CERTIFICATE;
+ goto loser;
+ }
+ rv = addExtensions(newCert, certReq);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ issuerPrivKey = PK11_FindKeyByAnyCert(issuerCert, varTable);
+ if (issuerPrivKey == NULL) {
+ rv = COULD_NOT_FIND_ISSUER_PRIVATE_KEY;
+ }
+ signTag = SEC_GetSignatureAlgorithmOidTag(issuerPrivatekey->keytype,
+ SEC_OID_UNKNOWN);
+ if (signTag == SEC_OID_UNKNOWN) {
+ rv = UNSUPPORTED_SIGN_OPERATION_FOR_ISSUER;
+ goto loser;
+ }
+ srv = SECOID_SetAlgorithmID(newCert->arena, &newCert->signature,
+ signTag, 0);
+ if (srv != SECSuccess) {
+ rv = ERROR_SETTING_SIGN_ALG;
+ goto loser;
+ }
+ srv = CRMF_CertRequestGetCertTemplateVersion(certReq, &version);
+ if (srv != SECSuccess) {
+ /* No version included in the request */
+ *(newCert->version.data) = SEC_CERTIFICATE_VERSION_3;
+ } else {
+ SECITEM_FreeItem(&newCert->version, PR_FALSE);
+ SEC_ASN1EncodeInteger(newCert->arena, &newCert->version, version);
+ }
+ SEC_ASN1EncodeItem(newCert->arena, &derCert, newCert,
+ CERT_CertificateTemplate);
+ if (derCert.data == NULL) {
+ rv = ERROR_ENCODING_NEW_CERT;
+ goto loser;
+ }
+ srv = SEC_DerSignData(newCert->arena, &(newCert->derCert), derCert.data,
+ derCert.len, issuerPrivKey, signTag);
+ if (srv != SECSuccess) {
+ rv = ERROR_SIGNING_NEW_CERT;
+ goto loser;
+ }
+#ifdef WRITE_OUT_RESPONSE
+ writeOutItem("newcert.der", &newCert->derCert);
+#endif
+ return NO_ERROR;
+ loser:
+ *issuedCert = NULL;
+ if (newCert) {
+ CERT_DestroyCertificate(newCert);
+ }
+ return rv;
+
+}
+
+void
+formatCMMFResponse(char *nickname, char *base64Response)
+{
+ char *currLine, *nextLine;
+
+ printf("var retVal = crypto.importUserCertificates(\"%s\",\n", nickname);
+ currLine = base64Response;
+ while (1) {
+ nextLine = strchr(currLine, '\n');
+ if (nextLine == NULL) {
+ /* print out the last line here. */
+ printf ("\"%s\",\n", currLine);
+ break;
+ }
+ nextLine[0] = '\0';
+ printf("\"%s\\n\"+\n", currLine);
+ currLine = nextLine+1;
+ }
+ printf("true);\n"
+ "if(retVal == '') {\n"
+ "\tdocument.write(\"New Certificate Successfully Imported.
\");\n"
+ "} else {\n"
+ "\tdocument.write(\"Unable to import New Certificate
\");\n"
+ "\tdocument.write(\"crypto.importUserCertificates returned \");\n"
+ "\tdocument.write(retVal);\n"
+ "\tdocument.write(\"\");\n"
+ "}\n");
+}
+
+void
+spitOutCMMFResponse(char *nickname, char *base64Response)
+{
+ spitOutHeaders();
+ printf("\n\nCMMF Resonse Page\n\n\n"
+ "CMMF Response Page
\n"
+ "\n\n");
+}
+
+char*
+getNickname(CERTCertificate *cert)
+{
+ char *nickname;
+
+ if (cert->nickname != NULL) {
+ return cert->nickname;
+ }
+ nickname = CERT_GetCommonName(&cert->subject);
+ if (nickname != NULL) {
+ return nickname;
+ }
+ return CERT_NameToAscii(&cert->subject);
+}
+
+ErrorCode
+createCMMFResponse(CertResponseInfo *issuedCerts, int numCerts,
+ CERTCertificate *issuerCert, char **base64der)
+{
+ CMMFCertRepContent *certRepContent=NULL;
+ ErrorCode rv = NO_ERROR;
+ CMMFCertResponse **responses, *currResponse;
+ CERTCertList *caList;
+ int i;
+ SECStatus srv;
+ PLArenaPool *poolp;
+ SECItem *der;
+
+ certRepContent = CMMF_CreateCertRepContent();
+ if (certRepContent == NULL) {
+ rv = ERROR_CREATING_CERT_REP_CONTENT;
+ goto loser;
+ }
+ responses = PORT_NewArray(CMMFCertResponse*, numCerts);
+ if (responses == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ for (i=0; idata, der->len);
+ return NO_ERROR;
+ loser:
+ return rv;
+}
+
+ErrorCode
+issueCerts(CertResponseInfo *issuedCerts, int numCerts,
+ CERTCertificate *issuerCert)
+{
+ ErrorCode rv;
+ char *base64Response;
+
+ rv = createCMMFResponse(issuedCerts, numCerts, issuerCert, &base64Response);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ spitOutCMMFResponse(getNickname(issuedCerts[0].cert),base64Response);
+ return NO_ERROR;
+ loser:
+ return rv;
+}
+
+ErrorCode
+verifySignature(CGIVarTable *varTable, CRMFCertReqMsg *currReq,
+ CRMFCertRequest *certReq, CERTCertificate *newCert)
+{
+ SECStatus srv;
+ ErrorCode rv = NO_ERROR;
+ CRMFPOPOSigningKey *signKey = NULL;
+ SECAlgorithmID *algID = NULL;
+ SECItem *signature = NULL;
+ SECKEYPublicKey *pubKey = NULL;
+ SECItem *reqDER = NULL;
+
+ srv = CRMF_CertReqMsgGetPOPOSigningKey(currReq, &signKey);
+ if (srv != SECSuccess || signKey == NULL) {
+ rv = ERROR_RETRIEVING_POP_SIGN_KEY;
+ goto loser;
+ }
+ algID = CRMF_POPOSigningKeyGetAlgID(signKey);
+ if (algID == NULL) {
+ rv = ERROR_RETRIEVING_ALG_ID_FROM_SIGN_KEY;
+ goto loser;
+ }
+ signature = CRMF_POPOSigningKeyGetSignature(signKey);
+ if (signature == NULL) {
+ rv = ERROR_RETRIEVING_SIGNATURE_FROM_POP_SIGN_KEY;
+ goto loser;
+ }
+ /* Make the length the number of bytes instead of bits */
+ signature->len = (signature->len+7)/8;
+ pubKey = CERT_ExtractPublicKey(newCert);
+ if (pubKey == NULL) {
+ rv = ERROR_RETRIEVING_PUB_KEY_FROM_NEW_CERT;
+ goto loser;
+ }
+ reqDER = SEC_ASN1EncodeItem(NULL, NULL, certReq, CRMFCertRequestTemplate);
+ if (reqDER == NULL) {
+ rv = ERROR_ENCODING_CERT_REQ_FOR_POP;
+ goto loser;
+ }
+ srv = VFY_VerifyDataWithAlgorithmID(reqDER->data, reqDER->len, pubKey,
+ signature, &algID->algorithm, NULL, varTable);
+ if (srv != SECSuccess) {
+ rv = ERROR_VERIFYING_SIGNATURE_POP;
+ goto loser;
+ }
+ /* Fall thru in successfull case. */
+ loser:
+ if (pubKey != NULL) {
+ SECKEY_DestroyPublicKey(pubKey);
+ }
+ if (reqDER != NULL) {
+ SECITEM_FreeItem(reqDER, PR_TRUE);
+ }
+ if (signature != NULL) {
+ SECITEM_FreeItem(signature, PR_TRUE);
+ }
+ if (algID != NULL) {
+ SECOID_DestroyAlgorithmID(algID, PR_TRUE);
+ }
+ if (signKey != NULL) {
+ CRMF_DestroyPOPOSigningKey(signKey);
+ }
+ return rv;
+}
+
+ErrorCode
+doChallengeResponse(CGIVarTable *varTable, CRMFCertReqMsg *currReq,
+ CRMFCertRequest *certReq, CERTCertificate *newCert,
+ ChallengeCreationInfo *challs, int *numChall)
+{
+ CRMFPOPOPrivKey *privKey = NULL;
+ CRMFPOPOPrivKeyChoice privKeyChoice;
+ SECStatus srv;
+ ErrorCode rv = NO_ERROR;
+
+ srv = CRMF_CertReqMsgGetPOPKeyEncipherment(currReq, &privKey);
+ if (srv != SECSuccess || privKey == NULL) {
+ rv = ERROR_GETTING_KEY_ENCIPHERMENT;
+ goto loser;
+ }
+ privKeyChoice = CRMF_POPOPrivKeyGetChoice(privKey);
+ CRMF_DestroyPOPOPrivKey(privKey);
+ switch (privKeyChoice) {
+ case crmfSubsequentMessage:
+ challs = &challs[*numChall];
+ challs->random = rand();
+ challs->pubKey = CERT_ExtractPublicKey(newCert);
+ if (challs->pubKey == NULL) {
+ rv = ERROR_RETRIEVING_PUB_KEY_FOR_CHALL;
+ goto loser;
+ }
+ (*numChall)++;
+ rv = DO_CHALLENGE_RESPONSE;
+ break;
+ case crmfThisMessage:
+ /* There'd better be a PKIArchiveControl in this message */
+ if (!CRMF_CertRequestIsControlPresent(certReq,
+ crmfPKIArchiveOptionsControl)) {
+ rv = ERROR_NO_POP_FOR_PRIVKEY;
+ goto loser;
+ }
+ break;
+ default:
+ rv = ERROR_UNSUPPORTED_POPOPRIVKEY_TYPE;
+ goto loser;
+ }
+loser:
+ return rv;
+}
+
+ErrorCode
+doProofOfPossession(CGIVarTable *varTable, CRMFCertReqMsg *currReq,
+ CRMFCertRequest *certReq, CERTCertificate *newCert,
+ ChallengeCreationInfo *challs, int *numChall)
+{
+ CRMFPOPChoice popChoice;
+ ErrorCode rv = NO_ERROR;
+
+ popChoice = CRMF_CertReqMsgGetPOPType(currReq);
+ if (popChoice == crmfNoPOPChoice) {
+ rv = NO_POP_FOR_REQUEST;
+ goto loser;
+ }
+ switch (popChoice) {
+ case crmfSignature:
+ rv = verifySignature(varTable, currReq, certReq, newCert);
+ break;
+ case crmfKeyEncipherment:
+ rv = doChallengeResponse(varTable, currReq, certReq, newCert,
+ challs, numChall);
+ break;
+ case crmfRAVerified:
+ case crmfKeyAgreement:
+ default:
+ rv = UNSUPPORTED_POP;
+ goto loser;
+ }
+ loser:
+ return rv;
+}
+
+void
+convertB64ToJS(char *base64)
+{
+ int i;
+
+ for (i=0; base64[i] != '\0'; i++) {
+ if (base64[i] == '\n') {
+ printf ("\\n");
+ }else {
+ printf ("%c", base64[i]);
+ }
+ }
+}
+
+void
+formatChallenge(char *chall64, char *certRepContentDER,
+ ChallengeCreationInfo *challInfo, int numChalls)
+{
+ printf ("function respondToChallenge() {\n"
+ " var chalForm = document.chalForm;\n\n"
+ " chalForm.CertRepContent.value = '");
+ convertB64ToJS(certRepContentDER);
+ printf ("';\n"
+ " chalForm.ChallResponse.value = crypto.popChallengeResponse('");
+ convertB64ToJS(chall64);
+ printf("');\n"
+ " chalForm.submit();\n"
+ "}\n");
+
+}
+
+void
+spitOutChallenge(char *chall64, char *certRepContentDER,
+ ChallengeCreationInfo *challInfo, int numChalls,
+ char *nickname)
+{
+ int i;
+
+ spitOutHeaders();
+ printf("\n"
+ "\n"
+ "Challenge Page\n"
+ "\n"
+ "\n"
+ "\n"
+ "Cartman is now responding to the Challenge "
+ "presented by the CGI
\n"
+ "\n\n");
+}
+
+ErrorCode
+issueChallenge(CertResponseInfo *issuedCerts, int numCerts,
+ ChallengeCreationInfo *challInfo, int numChalls,
+ CERTCertificate *issuer, CGIVarTable *varTable)
+{
+ ErrorCode rv = NO_ERROR;
+ CMMFPOPODecKeyChallContent *chalContent = NULL;
+ int i;
+ SECStatus srv;
+ PLArenaPool *poolp;
+ CERTGeneralName *genName;
+ SECItem *challDER = NULL;
+ char *chall64, *certRepContentDER;
+
+ rv = createCMMFResponse(issuedCerts, numCerts, issuer,
+ &certRepContentDER);
+ if (rv != NO_ERROR) {
+ goto loser;
+ }
+ chalContent = CMMF_CreatePOPODecKeyChallContent();
+ if (chalContent == NULL) {
+ rv = ERROR_CREATING_EMPTY_CHAL_CONTENT;
+ goto loser;
+ }
+ poolp = PORT_NewArena(1024);
+ if (poolp == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ genName = CERT_GetCertificateNames(issuer, poolp);
+ if (genName == NULL) {
+ rv = ERROR_EXTRACTING_GEN_NAME_FROM_ISSUER;
+ goto loser;
+ }
+ for (i=0;idata, challDER->len);
+ SECITEM_FreeItem(challDER, PR_TRUE);
+ if (chall64 == NULL) {
+ rv = ERROR_CONVERTING_CHALL_TO_BASE64;
+ goto loser;
+ }
+ spitOutChallenge(chall64, certRepContentDER, challInfo, numChalls,
+ getNickname(issuedCerts[0].cert));
+ loser:
+ return rv;
+}
+
+
+ErrorCode
+processRequest(CGIVarTable *varTable)
+{
+ CERTCertDBHandle *certdb;
+ SECKEYKeyDBHandle *keydb;
+ CRMFCertReqMessages *certReqs = NULL;
+ const char *crmfReq;
+ const char *caNickname;
+ CERTCertificate *caCert = NULL;
+ CertResponseInfo *issuedCerts = NULL;
+ CERTSubjectPublicKeyInfo spki = { 0 };
+ ErrorCode rv=NO_ERROR;
+ PRBool doChallengeResponse = PR_FALSE;
+ SECItem der = { 0 };
+ SECStatus srv;
+ CERTCertificateRequest oldCertReq = { 0 };
+ CRMFCertReqMsg **reqMsgs = NULL,*currReq = NULL;
+ CRMFCertRequest **reqs = NULL, *certReq = NULL;
+ CERTName subject = { 0 };
+ int numReqs,i;
+ ChallengeCreationInfo *challInfo=NULL;
+ int numChalls = 0;
+
+ certdb = CERT_GetDefaultCertDB();
+ keydb = SECKEY_GetDefaultKeyDB();
+ crmfReq = CGITableFindValue(varTable, "CRMFRequest");
+ if (crmfReq == NULL) {
+ rv = CGI_VAR_MISSING;
+ missingVar = "CRMFRequest";
+ goto loser;
+ }
+ caNickname = CGITableFindValue(varTable, "CANickname");
+ if (caNickname == NULL) {
+ rv = CGI_VAR_MISSING;
+ missingVar = "CANickname";
+ goto loser;
+ }
+ caCert = CERT_FindCertByNickname(certdb, caNickname);
+ if (caCert == NULL) {
+ rv = COULD_NOT_FIND_CA;
+ goto loser;
+ }
+ srv = ATOB_ConvertAsciiToItem(&der, crmfReq);
+ if (srv != SECSuccess) {
+ rv = BAD_ASCII_FOR_REQ;
+ goto loser;
+ }
+ certReqs = CRMF_CreateCertReqMessagesFromDER(der.data, der.len);
+ SECITEM_FreeItem(&der, PR_FALSE);
+ if (certReqs == NULL) {
+ rv = COULD_NOT_DECODE_REQS;
+ goto loser;
+ }
+ numReqs = CRMF_CertReqMessagesGetNumMessages(certReqs);
+ issuedCerts = PORT_ZNewArray(CertResponseInfo, numReqs);
+ challInfo = PORT_ZNewArray(ChallengeCreationInfo, numReqs);
+ if (issuedCerts == NULL || challInfo == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ reqMsgs = PORT_ZNewArray(CRMFCertReqMsg*, numReqs);
+ reqs = PORT_ZNewArray(CRMFCertRequest*, numReqs);
+ if (reqMsgs == NULL || reqs == NULL) {
+ rv = OUT_OF_MEMORY;
+ goto loser;
+ }
+ for (i=0; i= form_output_len) {
+ form_output_len += DEFAULT_ALLOC_SIZE;
+ form_output = PORT_Realloc(form_output, form_output_len+1);
+ }
+ form_output_used += fread(&form_output[form_output_used], sizeof(char),
+ DEFAULT_ALLOC_SIZE, stdin);
+ }
+ ParseInputVariables(&varTable, form_output);
+ certRepContent = CGITableFindValue(&varTable, "CertRepContent");
+ if (certRepContent == NULL) {
+ errNum = initNSS(&varTable);
+ if (errNum != 0) {
+ goto loser;
+ }
+ errNum = processRequest(&varTable);
+ } else {
+ errNum = processChallengeResponse(&varTable, certRepContent);
+ }
+ if (errNum != NO_ERROR) {
+ goto loser;
+ }
+ goto done;
+loser:
+ dumpErrorMessage(errNum);
+done:
+ free (form_output);
+ return 0;
+}
+
diff --git a/nss/cmd/crmf-cgi/crmfcgi.html b/nss/cmd/crmf-cgi/crmfcgi.html
new file mode 100644
index 0000000..537b0f5
--- /dev/null
+++ b/nss/cmd/crmf-cgi/crmfcgi.html
@@ -0,0 +1,136 @@
+
+
+
+
+CRMF Test Page for PSM
+
+
+
+CRMF Test page for PSM
+This page is designed to be used in combination with the executable
+produced by ns/security/cmd/crmf-cgi in a CGI environment. In order
+to successfully use this page, modify its action to post to a a server
+where you have installed the crmfcgi executable and you'll be able to
+test the functionality.
+
+
+
+
diff --git a/nss/cmd/crmf-cgi/manifest.mn b/nss/cmd/crmf-cgi/manifest.mn
new file mode 100644
index 0000000..1212424
--- /dev/null
+++ b/nss/cmd/crmf-cgi/manifest.mn
@@ -0,0 +1,33 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+CORE_DEPTH = ../..
+MODULE = sectools
+
+EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ crmfcgi.c \
+ $(NULL)
+
+
+REQUIRES = nss dbm seccmd
+
+ifdef ATTACH_CGI
+DEFINES += -DATTACH_CGI
+endif
+
+ifdef WRITE_OUT_RESPONSE
+DEFINES += -DWRITE_OUT_RESPONSE
+endif
+
+PROGRAM = crmfcgi
+
+USE_STATIC_LIBS = 1
+
+INCLUDES =
+
+DEFINES = -DNSPR20
diff --git a/nss/cmd/crmftest/Makefile b/nss/cmd/crmftest/Makefile
new file mode 100644
index 0000000..369cdc8
--- /dev/null
+++ b/nss/cmd/crmftest/Makefile
@@ -0,0 +1,64 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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
+
+EXTRA_LIBS += $(DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX)
+
+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
+
+include ../platrules.mk
diff --git a/nss/cmd/crmftest/config.mk b/nss/cmd/crmftest/config.mk
new file mode 100644
index 0000000..9838ef1
--- /dev/null
+++ b/nss/cmd/crmftest/config.mk
@@ -0,0 +1,15 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# 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/nss/cmd/crmftest/manifest.mn b/nss/cmd/crmftest/manifest.mn
new file mode 100644
index 0000000..578729e
--- /dev/null
+++ b/nss/cmd/crmftest/manifest.mn
@@ -0,0 +1,25 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+CORE_DEPTH = ../..
+DEPTH = .
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+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/nss/cmd/crmftest/testcrmf.c b/nss/cmd/crmftest/testcrmf.c
new file mode 100644
index 0000000..ce3d7cf
--- /dev/null
+++ b/nss/cmd/crmftest/testcrmf.c
@@ -0,0 +1,1679 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * 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 "secerr.h"
+#include "pk11func.h"
+#include "key.h"
+#include "cmmf.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 "secmodi.h"
+#include "pkcs11.h"
+#include "secitem.h"
+#include "secasn1.h"
+#include "sechash.h"
+#endif
+
+#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;
+static secuPWData pwdata = { PW_NONE, 0 };
+char *configdir;
+PRBool doingDSA = PR_FALSE;
+
+CERTCertDBHandle *db;
+
+typedef struct {
+ SECKEYPrivateKey *privKey;
+ SECKEYPublicKey *pubKey;
+ CRMFCertRequest *certReq;
+ CRMFCertReqMsg *certReqMsg;
+} TESTKeyPair;
+
+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)
+{
+ SECStatus rv;
+
+ if (dest == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ rv = PK11_GenerateRandom((unsigned char *)dest, sizeof(long));
+ /* make serial number positive */
+ if (*dest < 0L)
+ *dest = - *dest;
+ return SECSuccess;
+}
+
+PK11RSAGenParams *
+GetRSAParams(void)
+{
+ PK11RSAGenParams *rsaParams;
+
+ rsaParams = PORT_ZNew(PK11RSAGenParams);
+
+ if (rsaParams == NULL)
+ return NULL;
+
+ rsaParams->keySizeInBits = MAX_KEY_LEN;
+ rsaParams->pe = 0x10001;
+
+ return rsaParams;
+
+}
+
+PQGParams*
+GetDSAParams(void)
+{
+ PQGParams *params = NULL;
+ PQGVerify *vfy = NULL;
+
+ SECStatus rv;
+
+ rv = PK11_PQG_ParamGen(0, ¶ms, &vfy);
+ if (rv != SECSuccess) {
+ return NULL;
+ }
+ 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(TESTKeyPair *pair)
+{
+ CERTSubjectPublicKeyInfo *spki = NULL;
+ SECKEYPrivateKey *privKey = NULL;
+ SECKEYPublicKey *pubKey = NULL;
+ PK11SlotInfo *keySlot = NULL;
+
+ keySlot = PK11_GetInternalKeySlot();
+ PK11_Authenticate(keySlot, PR_FALSE, &pwdata);
+
+
+ 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, &pwdata);
+ } 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, &pwdata);
+ }
+ PK11_FreeSlot(keySlot);
+ if (privKey == NULL || pubKey == NULL) {
+ if (pubKey) {
+ SECKEY_DestroyPublicKey(pubKey);
+ }
+ if (privKey) {
+ SECKEY_DestroyPrivateKey(privKey);
+ }
+ return NULL;
+ }
+
+ spki = SECKEY_CreateSubjectPublicKeyInfo(pubKey);
+ pair->privKey = privKey;
+ pair->pubKey = pubKey;
+ return spki;
+}
+
+
+SECStatus
+InitPKCS11(void)
+{
+ PK11SlotInfo *keySlot;
+
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ keySlot = PK11_GetInternalKeySlot();
+
+ if (PK11_NeedUserInit(keySlot) && PK11_NeedLogin(keySlot)) {
+ if (SECU_ChangePW(keySlot, NULL, NULL) != SECSuccess) {
+ printf ("Initializing the PINs failed.\n");
+ return SECFailure;
+ }
+ }
+
+ 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);
+}
+
+
+
+CRMFCertExtCreationInfo*
+GetExtensions(void)
+{
+ unsigned char keyUsage[4] = { 0x03, 0x02, 0x07, KU_DIGITAL_SIGNATURE };
+ /* What are these magic numbers? */
+ SECItem data = { 0, NULL, 0 };
+ CRMFCertExtension *extension;
+ CRMFCertExtCreationInfo *extInfo =
+ PORT_ZNew(CRMFCertExtCreationInfo);
+
+ data.data = keyUsage;
+ data.len = sizeof keyUsage;
+
+
+ extension =
+ CRMF_CreateCertExtension(SEC_OID_X509_KEY_USAGE, PR_FALSE, &data);
+ if (extension && extInfo) {
+ extInfo->numExtensions = 1;
+ extInfo->extensions = PORT_ZNewArray(CRMFCertExtension*, 1);
+ extInfo->extensions[0] = extension;
+ }
+ return extInfo;
+}
+
+void
+FreeExtInfo(CRMFCertExtCreationInfo *extInfo)
+{
+ int i;
+
+ for (i=0; inumExtensions; i++) {
+ CRMF_DestroyCertExtension(extInfo->extensions[i]);
+ }
+ PORT_Free(extInfo->extensions);
+ PORT_Free(extInfo);
+}
+
+int
+InjectCertName( CRMFCertRequest * certReq,
+ CRMFCertTemplateField inTemplateField,
+ const char * inNameString)
+{
+ 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;
+ 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, NULL, 0 };
+ SECItem subjectUID = { siBuffer, NULL, 0 };
+
+ /* len in bits */
+ issuerUID.data = UIDbuf;
+ issuerUID.len = UID_BITS;
+ subjectUID.data = UIDbuf;
+ subjectUID.len = UID_BITS;
+
+ pair->certReq = NULL;
+ certReq = CRMF_CreateCertRequest(inRequestID);
+ if (certReq == NULL) {
+ printf ("Could not initialize a certificate request.\n");
+ return 1;
+ }
+
+ /* 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");
+ CRMF_DestroyCertRequest(certReq);
+ 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) {
+ printf ("Could not add serial number to certificate template\n.");
+ CRMF_DestroyCertRequest(certReq);
+ return 4;
+ }
+
+ /* 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;
+ }
+
+ /* 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 5;
+ }
+
+ /* 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);
+ 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;
+ }
+
+ /* Set Validity Dates */
+ 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;
+ }
+
+ /* 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);
+ 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;
+ }
+
+ /* 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;
+ }
+ encKey = CRMF_CreateEncryptedKeyWithEncryptedValue(pair->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;
+ }
+ pair->certReq = certReq;
+ return 0;
+}
+
+int
+Encode(CRMFCertReqMsg *inCertReq1, CRMFCertReqMsg *inCertReq2)
+{
+ PRFileDesc *fileDesc;
+ SECStatus rv;
+ int irv = 0;
+ CRMFCertReqMsg *msgArr[3];
+ 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,
+ 0666);
+ if (fileDesc == NULL) {
+ printf ("Could not open file %s\n", filePath);
+ irv = 14;
+ goto finish;
+ }
+ 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;
+ }
+finish:
+ PR_Close(fileDesc);
+ return irv;
+}
+
+int
+AddProofOfPossession(TESTKeyPair *pair,
+ CRMFPOPChoice inPOPChoice)
+{
+
+ switch(inPOPChoice){
+ case crmfSignature:
+ CRMF_CertReqMsgSetSignaturePOP(pair->certReqMsg, pair->privKey,
+ pair->pubKey, NULL, NULL, &pwdata);
+ break;
+ case crmfRAVerified:
+ CRMF_CertReqMsgSetRAVerifiedPOP(pair->certReqMsg);
+ break;
+ case crmfKeyEncipherment:
+ CRMF_CertReqMsgSetKeyEnciphermentPOP(pair->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(pair->certReqMsg, crmfThisMessage,
+ crmfNoSubseqMess, &pendejo);
+ }
+ break;
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+
+int
+Decode(void)
+{
+ PRFileDesc *fileDesc;
+ CRMFCertReqMsg *certReqMsg;
+ CRMFCertRequest *certReq;
+ CRMFCertReqMessages *certReqMsgs;
+ 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);
+ if (fileDesc == NULL) {
+ printf ("Could not open file %s\n", filePath);
+ return 214;
+ }
+ rv = SECU_FileToItem(&item, fileDesc);
+ PR_Close(fileDesc);
+ if (rv != SECSuccess) {
+ return 215;
+ }
+
+ certReqMsgs = CRMF_CreateCertReqMessagesFromDER((char *)item.data, item.len);
+ 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++) {
+ 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);
+ }
+ rv = CRMF_CertReqMsgGetID(certReqMsg, &lame);
+ if (rv) {
+ SECU_PrintError("crmftest", "CRMF_CertReqMsgGetID");
+ }
+ certReq = CRMF_CertReqMsgGetCertRequest(certReqMsg);
+ if (!certReq) {
+ SECU_PrintError("crmftest", "CRMF_CertReqMsgGetCertRequest");
+ }
+ rv = CRMF_CertRequestGetCertTemplateValidity(certReq, &validity);
+ if (rv) {
+ SECU_PrintError("crmftest", "CRMF_CertRequestGetCertTemplateValidity");
+ }
+ if (!validity.notBefore) {
+ /* We encoded a notBefore, so somthing's wrong if it's not here. */
+ printf("ERROR: Validity period notBefore date missing.\n");
+ }
+ /* 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);
+ SECITEM_FreeItem(&item, PR_FALSE);
+ return 0;
+}
+
+int
+GetBitsFromFile(const char *filePath, SECItem *item)
+{
+ PRFileDesc *fileDesc;
+ SECStatus rv;
+
+ fileDesc = PR_Open(filePath, PR_RDONLY, 0644);
+ if (fileDesc == NULL) {
+ printf ("Could not open file %s\n", filePath);
+ return 14;
+ }
+
+ rv = SECU_FileToItem(item, fileDesc);
+ PR_Close(fileDesc);
+
+ if (rv != SECSuccess) {
+ item->data = NULL;
+ item->len = 0;
+ return 15;
+ }
+ return 0;
+}
+
+int
+DecodeCMMFCertRepContent(char *derFile)
+{
+ 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;
+ }
+ certRepContent = CMMF_CreateCertRepContentFromDER(db,
+ (char*)fileBits.data, fileBits.len);
+ if (certRepContent == NULL) {
+ printf ("Error while decoding %s\n", derFile);
+ irv = 303;
+ } else {
+ /* That was fun. Now, let's throw it away! */
+ CMMF_DestroyCertRepContent(certRepContent);
+ }
+ SECITEM_FreeItem(&fileBits, PR_FALSE);
+ return irv;
+}
+
+int
+EncodeCMMFCertReply(const char *filePath,
+ CERTCertificate *cert,
+ CERTCertList *list)
+{
+ 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);
+
+ CMMF_CertResponseSetCertificate(certResp, cert);
+
+ certResponses[0] = certResp;
+ certResponses[1] = NULL;
+ certResponses[2] = NULL;
+
+ certRepContent = CMMF_CreateCertRepContent();
+ CMMF_CertRepContentSetCertResponses(certRepContent, certResponses, 1);
+
+ CMMF_CertRepContentSetCAPubs(certRepContent, list);
+
+ 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);
+ PR_Close(fileDesc);
+ if (srv != SECSuccess) {
+ printf ("CMMF_EncodeCertRepContent failed,\n");
+ rv = 401;
+ }
+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");
+ 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, &pwdata);
+ if (privKey == NULL) {
+ printf ("Could not get the private key associated with the\n"
+ "certificate %s\n", personalCert);
+ rv = 410;
+ goto finish;
+ }
+
+ srv = CMMF_KeyRecRepContentSetCertifiedKeyPair(repContent, cert, privKey,
+ caPubKey);
+ if (srv != SECSuccess) {
+ printf ("Could not set the Certified Key Pair\n");
+ rv = 413;
+ goto finish;
+ }
+ 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);
+ PR_Close(fileDesc);
+ 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 = 452;
+ }
+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);
+ }
+ 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( SECKEYPrivateKey *privKey)
+{
+#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;
+ 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(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(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);
+ max_bytes_encrypted = PK11_GetPrivateModulusLen(privKey);
+ slot = PK11_GetBestSlotWithAttributes(mapWrapKeyType(privKey->keyType),
+ CKF_ENCRYPT, 0, 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, &pwdata);
+ 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, &pwdata);
+ 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;
+ }
+#endif
+ return 0;
+}
+
+int
+DoChallengeResponse(SECKEYPrivateKey *privKey,
+ SECKEYPublicKey *pubKey)
+{
+ CMMFPOPODecKeyChallContent *chalContent = NULL;
+ CMMFPOPODecKeyRespContent *respContent = NULL;
+ CERTCertificate *myCert = NULL;
+ CERTGeneralName *myGenName = NULL;
+ PLArenaPool *poolp = NULL;
+ PRFileDesc *fileDesc;
+ 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);
+ 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);
+ PK11_GenerateRandom((unsigned char *)randomNums,
+ numChallengesSet * sizeof(long));
+ for (i=0; ipkcs11Slot, keyID, &pwdata);
+ 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 (%ld), expected (%ld)\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; icertReq == NULL) {
+ goto loser;
+ }
+
+ pair->certReqMsg = CRMF_CreateCertReqMsg();
+ if (!pair->certReqMsg) {
+ irv = 999;
+ goto loser;
+ }
+ /* copy certReq into certReqMsg */
+ CRMF_CertReqMsgSetCertRequest(pair->certReqMsg, pair->certReq);
+ irv = AddProofOfPossession(pair, inPOPChoice);
+loser:
+ return irv;
+}
+
+int
+DestroyPairReqAndMsg(TESTKeyPair *pair)
+{
+ SECStatus rv = SECSuccess;
+ int irv = 0;
+
+ if (pair->certReq) {
+ rv = CRMF_DestroyCertRequest(pair->certReq);
+ pair->certReq = NULL;
+ if (rv != SECSuccess) {
+ printf ("Error when destroying cert request.\n");
+ irv = 100;
+ }
+ }
+ 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;
+}
+
+int
+DestroyPair(TESTKeyPair *pair)
+{
+ int irv = 0;
+
+ if (pair->pubKey) {
+ SECKEY_DestroyPublicKey(pair->pubKey);
+ pair->pubKey = NULL;
+ }
+ if (pair->privKey) {
+ SECKEY_DestroyPrivateKey(pair->privKey);
+ pair->privKey = NULL;
+ }
+ DestroyPairReqAndMsg(pair);
+ return irv;
+}
+
+int
+DoCRMFRequest(TESTKeyPair *signPair, TESTKeyPair *cryptPair)
+{
+ int irv, tirv = 0;
+
+ /* Generate a key pair and a cert request for it. */
+ irv = MakeCertRequest(signPair, crmfSignature, 0x0f020304);
+ if (irv != 0 || signPair->certReq == NULL) {
+ goto loser;
+ }
+
+ if (!doingDSA) {
+ irv = MakeCertRequest(cryptPair, crmfKeyAgreement, 0x0f050607);
+ if (irv != 0 || cryptPair->certReq == NULL) {
+ goto loser;
+ }
+ }
+
+ /* 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] [-P password]\n\n"
+ "\t [crmf] [dsa] [decode] [cmmf] [recover] [challenge]\n"
+ "\t [-f password_file]\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");
+}
+
+#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)
+{
+ TESTKeyPair signPair, cryptPair;
+ PLOptState *optstate;
+ PLOptStatus status;
+ char *password = NULL;
+ char *pwfile = NULL;
+ int irv = 0;
+ PRUint32 flags = 0;
+ SECStatus rv;
+ PRBool nssInit = PR_FALSE;
+ PRBool pArg = PR_FALSE;
+ PRBool eArg = PR_FALSE;
+ PRBool sArg = PR_FALSE;
+ PRBool PArg = PR_FALSE;
+
+ memset( &signPair, 0, sizeof signPair);
+ memset( &cryptPair, 0, sizeof cryptPair);
+ printf ("\ncrmftest v1.0\n");
+ optstate = PL_CreateOptState(argc, argv, "d:p:e:s:P:f:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'd':
+ configdir = PORT_Strdup(optstate->value);
+ rv = NSS_Init(configdir);
+ if (rv != SECSuccess) {
+ printf ("NSS_Init (-d) failed\n");
+ return 101;
+ }
+ nssInit = PR_TRUE;
+ break;
+ case 'p':
+ personalCert = PORT_Strdup(optstate->value);
+ if (personalCert == NULL) {
+ printf ("-p failed\n");
+ return 603;
+ }
+ pArg = PR_TRUE;
+ break;
+ case 'e':
+ recoveryEncrypter = PORT_Strdup(optstate->value);
+ if (recoveryEncrypter == NULL) {
+ printf ("-e failed\n");
+ return 602;
+ }
+ eArg = PR_TRUE;
+ break;
+ case 's':
+ caCertName = PORT_Strdup(optstate->value);
+ if (caCertName == NULL) {
+ printf ("-s failed\n");
+ return 604;
+ }
+ sArg = PR_TRUE;
+ break;
+ case 'P':
+ password = PORT_Strdup(optstate->value);
+ if (password == NULL) {
+ printf ("-P failed\n");
+ return 606;
+ }
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = password;
+ PArg = PR_TRUE;
+ break;
+ case 'f':
+ pwfile = PORT_Strdup(optstate->value);
+ if (pwfile == NULL) {
+ printf ("-f failed\n");
+ return 607;
+ }
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = pwfile;
+ break;
+ case 0: /* positional parameter */
+ rv = parsePositionalParam(optstate->value, &flags);
+ if (rv) {
+ printf ("bad positional parameter.\n");
+ return 605;
+ }
+ break;
+ default:
+ Usage();
+ return 601;
+ }
+ }
+ PL_DestroyOptState(optstate);
+ if (status == PL_OPT_BAD || !nssInit) {
+ Usage();
+ return 600;
+ }
+ if (!flags)
+ flags = ~ TEST_USE_DSA;
+ db = CERT_GetDefaultCertDB();
+ InitPKCS11();
+
+ if (flags & TEST_MAKE_CRMF_REQ) {
+ printf("Generating CRMF request\n");
+ irv = DoCRMFRequest(&signPair, &cryptPair);
+ if (irv)
+ 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;
+ }
+ }
+
+ if (flags & TEST_DO_CMMF_STUFF) {
+ printf("Doing CMMF Stuff\n");
+ if ((irv = DoCMMFStuff()) != 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 (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:
+ 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;
+}
diff --git a/nss/cmd/dbck/Makefile b/nss/cmd/dbck/Makefile
new file mode 100644
index 0000000..ea1d2f4
--- /dev/null
+++ b/nss/cmd/dbck/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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 ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+INCLUDES += -I ../../lib/softoken
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/nss/cmd/dbck/dbck.c b/nss/cmd/dbck/dbck.c
new file mode 100644
index 0000000..31e1150
--- /dev/null
+++ b/nss/cmd/dbck/dbck.c
@@ -0,0 +1,1353 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+** dbck.c
+**
+** utility for fixing corrupt cert databases
+**
+*/
+#include
+#include
+
+#include "secutil.h"
+#include "cdbhdl.h"
+#include "certdb.h"
+#include "cert.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "pcert.h"
+#include "nss.h"
+
+static char *progName;
+
+/* placeholders for pointer error types */
+static void *WrongEntry;
+static void *NoNickname;
+static void *NoSMime;
+
+typedef enum {
+/* 0*/ NoSubjectForCert = 0,
+/* 1*/ SubjectHasNoKeyForCert,
+/* 2*/ NoNicknameOrSMimeForSubject,
+/* 3*/ WrongNicknameForSubject,
+/* 4*/ NoNicknameEntry,
+/* 5*/ WrongSMimeForSubject,
+/* 6*/ NoSMimeEntry,
+/* 7*/ NoSubjectForNickname,
+/* 8*/ NoSubjectForSMime,
+/* 9*/ NicknameAndSMimeEntries,
+ NUM_ERROR_TYPES
+} dbErrorType;
+
+static char *dbErrorString[NUM_ERROR_TYPES] = {
+/* 0*/ "\nDid not find a subject entry for this certificate.",
+/* 1*/ "\nSubject has certKey which is not in db.",
+/* 2*/ "\nSubject does not have a nickname or email address.",
+/* 3*/ "\nUsing this subject's nickname, found a nickname entry for a different subject.",
+/* 4*/ "\nDid not find a nickname entry for this subject.",
+/* 5*/ "\nUsing this subject's email, found an S/MIME entry for a different subject.",
+/* 6*/ "\nDid not find an S/MIME entry for this subject.",
+/* 7*/ "\nDid not find a subject entry for this nickname.",
+/* 8*/ "\nDid not find a subject entry for this S/MIME profile.",
+};
+
+static char *errResult[NUM_ERROR_TYPES] = {
+ "Certificate entries that had no subject entry.",
+ "Subject entries with no corresponding Certificate entries.",
+ "Subject entries that had no nickname or S/MIME entries.",
+ "Redundant nicknames (subjects with the same nickname).",
+ "Subject entries that had no nickname entry.",
+ "Redundant email addresses (subjects with the same email address).",
+ "Subject entries that had no S/MIME entry.",
+ "Nickname entries that had no subject entry.",
+ "S/MIME entries that had no subject entry.",
+ "Subject entries with BOTH nickname and S/MIME entries."
+};
+
+
+enum {
+ GOBOTH = 0,
+ GORIGHT,
+ GOLEFT
+};
+
+typedef struct
+{
+ PRBool verbose;
+ PRBool dograph;
+ PRFileDesc *out;
+ PRFileDesc *graphfile;
+ int dbErrors[NUM_ERROR_TYPES];
+} dbDebugInfo;
+
+struct certDBEntryListNodeStr {
+ PRCList link;
+ certDBEntry entry;
+ void *appData;
+};
+typedef struct certDBEntryListNodeStr certDBEntryListNode;
+
+/*
+ * A list node for a cert db entry. The index is a unique identifier
+ * to use for creating generic maps of a db. This struct handles
+ * the cert, nickname, and smime db entry types, as all three have a
+ * single handle to a subject entry.
+ * This structure is pointed to by certDBEntryListNode->appData.
+ */
+typedef struct
+{
+ PLArenaPool *arena;
+ int index;
+ certDBEntryListNode *pSubject;
+} certDBEntryMap;
+
+/*
+ * Subject entry is special case, it has bidirectional handles. One
+ * subject entry can point to several certs (using the same DN), and
+ * a nickname and/or smime entry.
+ * This structure is pointed to by certDBEntryListNode->appData.
+ */
+typedef struct
+{
+ PLArenaPool *arena;
+ int index;
+ int numCerts;
+ certDBEntryListNode **pCerts;
+ certDBEntryListNode *pNickname;
+ certDBEntryListNode *pSMime;
+} certDBSubjectEntryMap;
+
+/*
+ * A map of a certdb.
+ */
+typedef struct
+{
+ int numCerts;
+ int numSubjects;
+ int numNicknames;
+ int numSMime;
+ int numRevocation;
+ certDBEntryListNode certs; /* pointer to head of cert list */
+ certDBEntryListNode subjects; /* pointer to head of subject list */
+ certDBEntryListNode nicknames; /* pointer to head of nickname list */
+ certDBEntryListNode smime; /* pointer to head of smime list */
+ certDBEntryListNode revocation; /* pointer to head of revocation list */
+} certDBArray;
+
+/* Cast list to the base element, a certDBEntryListNode. */
+#define LISTNODE_CAST(node) \
+ ((certDBEntryListNode *)(node))
+
+static void
+Usage(char *progName)
+{
+#define FPS fprintf(stderr,
+ FPS "Type %s -H for more detailed descriptions\n", progName);
+ FPS "Usage: %s -D [-d certdir] [-m] [-v [-f dumpfile]]\n",
+ progName);
+#ifdef DORECOVER
+ FPS " %s -R -o newdbname [-d certdir] [-aprsx] [-v [-f dumpfile]]\n",
+ progName);
+#endif
+ exit(-1);
+}
+
+static void
+LongUsage(char *progName)
+{
+ FPS "%-15s Display this help message.\n",
+ "-H");
+ FPS "%-15s Dump analysis. No changes will be made to the database.\n",
+ "-D");
+ FPS "%-15s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-15s Put database graph in ./mailfile (default is stdout).\n",
+ " -m");
+ FPS "%-15s Verbose mode. Dumps the entire contents of your cert8.db.\n",
+ " -v");
+ FPS "%-15s File to dump verbose output into. (default is stdout)\n",
+ " -f dumpfile");
+#ifdef DORECOVER
+ FPS "%-15s Repair the database. The program will look for broken\n",
+ "-R");
+ FPS "%-15s dependencies between subject entries and certificates,\n",
+ "");
+ FPS "%-15s between nickname entries and subjects, and between SMIME\n",
+ "");
+ FPS "%-15s profiles and subjects. Any duplicate entries will be\n",
+ "");
+ FPS "%-15s removed, any missing entries will be created.\n",
+ "");
+ FPS "%-15s File to store new database in (default is new_cert8.db)\n",
+ " -o newdbname");
+ FPS "%-15s Cert database directory (default is ~/.netscape)\n",
+ " -d certdir");
+ FPS "%-15s Prompt before removing any certificates.\n",
+ " -p");
+ FPS "%-15s Keep all possible certificates. Only remove certificates\n",
+ " -a");
+ FPS "%-15s which prevent creation of a consistent database. Thus any\n",
+ "");
+ FPS "%-15s expired or redundant entries will be kept.\n",
+ "");
+ FPS "%-15s Keep redundant nickname/email entries. It is possible\n",
+ " -r");
+ FPS "%-15s only one such entry will be usable.\n",
+ "");
+ FPS "%-15s Don't require an S/MIME profile in order to keep an S/MIME\n",
+ " -s");
+ FPS "%-15s cert. An empty profile will be created.\n",
+ "");
+ FPS "%-15s Keep expired certificates.\n",
+ " -x");
+ FPS "%-15s Verbose mode - report all activity while recovering db.\n",
+ " -v");
+ FPS "%-15s File to dump verbose output into.\n",
+ " -f dumpfile");
+ FPS "\n");
+#endif
+ exit(-1);
+#undef FPS
+}
+
+/*******************************************************************
+ *
+ * Functions for dbck.
+ *
+ ******************************************************************/
+
+void
+printHexString(PRFileDesc *out, SECItem *hexval)
+{
+ unsigned int i;
+ for (i = 0; i < hexval->len; i++) {
+ if (i != hexval->len - 1) {
+ PR_fprintf(out, "%02x:", hexval->data[i]);
+ } else {
+ PR_fprintf(out, "%02x", hexval->data[i]);
+ }
+ }
+ PR_fprintf(out, "\n");
+}
+
+
+SECStatus
+dumpCertificate(CERTCertificate *cert, int num, PRFileDesc *outfile)
+{
+ int userCert = 0;
+ CERTCertTrust *trust = cert->trust;
+ userCert = (SEC_GET_TRUST_FLAGS(trust, trustSSL) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustEmail) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustObjectSigning) & CERTDB_USER);
+ if (num >= 0) {
+ PR_fprintf(outfile, "Certificate: %3d\n", num);
+ } else {
+ PR_fprintf(outfile, "Certificate:\n");
+ }
+ PR_fprintf(outfile, "----------------\n");
+ if (userCert)
+ PR_fprintf(outfile, "(User Cert)\n");
+ PR_fprintf(outfile, "## SUBJECT: %s\n", cert->subjectName);
+ PR_fprintf(outfile, "## ISSUER: %s\n", cert->issuerName);
+ PR_fprintf(outfile, "## SERIAL NUMBER: ");
+ printHexString(outfile, &cert->serialNumber);
+ { /* XXX should be separate function. */
+ PRTime timeBefore, timeAfter;
+ PRExplodedTime beforePrintable, afterPrintable;
+ char *beforestr, *afterstr;
+ DER_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore);
+ DER_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter);
+ PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable);
+ PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable);
+ beforestr = PORT_Alloc(100);
+ afterstr = PORT_Alloc(100);
+ PR_FormatTime(beforestr, 100, "%a %b %d %H:%M:%S %Y", &beforePrintable);
+ PR_FormatTime(afterstr, 100, "%a %b %d %H:%M:%S %Y", &afterPrintable);
+ PR_fprintf(outfile, "## VALIDITY: %s to %s\n", beforestr, afterstr);
+ }
+ PR_fprintf(outfile, "\n");
+ return SECSuccess;
+}
+
+SECStatus
+dumpCertEntry(certDBEntryCert *entry, int num, PRFileDesc *outfile)
+{
+#if 0
+ NSSLOWCERTCertificate *cert;
+ /* should we check for existing duplicates? */
+ cert = nsslowcert_DecodeDERCertificate(&entry->cert.derCert,
+ entry->cert.nickname);
+#else
+ CERTCertificate *cert;
+ cert = CERT_DecodeDERCertificate(&entry->derCert, PR_FALSE, NULL);
+#endif
+ if (!cert) {
+ fprintf(stderr, "Failed to decode certificate.\n");
+ return SECFailure;
+ }
+ cert->trust = (CERTCertTrust *)&entry->trust;
+ dumpCertificate(cert, num, outfile);
+ CERT_DestroyCertificate(cert);
+ return SECSuccess;
+}
+
+SECStatus
+dumpSubjectEntry(certDBEntrySubject *entry, int num, PRFileDesc *outfile)
+{
+ char *subjectName = CERT_DerNameToAscii(&entry->derSubject);
+
+ PR_fprintf(outfile, "Subject: %3d\n", num);
+ PR_fprintf(outfile, "------------\n");
+ PR_fprintf(outfile, "## %s\n", subjectName);
+ if (entry->nickname)
+ PR_fprintf(outfile, "## Subject nickname: %s\n", entry->nickname);
+ if (entry->emailAddrs) {
+ unsigned int n;
+ for (n = 0; n < entry->nemailAddrs && entry->emailAddrs[n]; ++n) {
+ char * emailAddr = entry->emailAddrs[n];
+ if (emailAddr[0]) {
+ PR_fprintf(outfile, "## Subject email address: %s\n",
+ emailAddr);
+ }
+ }
+ }
+ PR_fprintf(outfile, "## This subject has %d cert(s).\n", entry->ncerts);
+ PR_fprintf(outfile, "\n");
+ PORT_Free(subjectName);
+ return SECSuccess;
+}
+
+SECStatus
+dumpNicknameEntry(certDBEntryNickname *entry, int num, PRFileDesc *outfile)
+{
+ PR_fprintf(outfile, "Nickname: %3d\n", num);
+ PR_fprintf(outfile, "-------------\n");
+ PR_fprintf(outfile, "## \"%s\"\n\n", entry->nickname);
+ return SECSuccess;
+}
+
+SECStatus
+dumpSMimeEntry(certDBEntrySMime *entry, int num, PRFileDesc *outfile)
+{
+ PR_fprintf(outfile, "S/MIME Profile: %3d\n", num);
+ PR_fprintf(outfile, "-------------------\n");
+ PR_fprintf(outfile, "## \"%s\"\n", entry->emailAddr);
+#ifdef OLDWAY
+ PR_fprintf(outfile, "## OPTIONS: ");
+ printHexString(outfile, &entry->smimeOptions);
+ PR_fprintf(outfile, "## TIMESTAMP: ");
+ printHexString(outfile, &entry->optionsDate);
+#else
+ SECU_PrintAny(stdout, &entry->smimeOptions, "## OPTIONS ", 0);
+ fflush(stdout);
+ if (entry->optionsDate.len && entry->optionsDate.data)
+ PR_fprintf(outfile, "## TIMESTAMP: %.*s\n",
+ entry->optionsDate.len, entry->optionsDate.data);
+#endif
+ PR_fprintf(outfile, "\n");
+ return SECSuccess;
+}
+
+SECStatus
+mapCertEntries(certDBArray *dbArray)
+{
+ certDBEntryCert *certEntry;
+ certDBEntrySubject *subjectEntry;
+ certDBEntryListNode *certNode, *subjNode;
+ certDBSubjectEntryMap *smap;
+ certDBEntryMap *map;
+ PLArenaPool *tmparena;
+ SECItem derSubject;
+ SECItem certKey;
+ PRCList *cElem, *sElem;
+
+ /* Arena for decoded entries */
+ tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (tmparena == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return SECFailure;
+ }
+
+ /* Iterate over cert entries and map them to subject entries.
+ * NOTE: mapSubjectEntries must be called first to alloc memory
+ * for array of subject->cert map.
+ */
+ for (cElem = PR_LIST_HEAD(&dbArray->certs.link);
+ cElem != &dbArray->certs.link; cElem = PR_NEXT_LINK(cElem)) {
+ certNode = LISTNODE_CAST(cElem);
+ certEntry = (certDBEntryCert *)&certNode->entry;
+ map = (certDBEntryMap *)certNode->appData;
+ CERT_NameFromDERCert(&certEntry->derCert, &derSubject);
+ CERT_KeyFromDERCert(tmparena, &certEntry->derCert, &certKey);
+ /* Loop over found subjects for cert's DN. */
+ for (sElem = PR_LIST_HEAD(&dbArray->subjects.link);
+ sElem != &dbArray->subjects.link; sElem = PR_NEXT_LINK(sElem)) {
+ subjNode = LISTNODE_CAST(sElem);
+ subjectEntry = (certDBEntrySubject *)&subjNode->entry;
+ if (SECITEM_ItemsAreEqual(&derSubject, &subjectEntry->derSubject)) {
+ unsigned int i;
+ /* Found matching subject name, create link. */
+ map->pSubject = subjNode;
+ /* Make sure subject entry has cert's key. */
+ for (i=0; incerts; i++) {
+ if (SECITEM_ItemsAreEqual(&certKey,
+ &subjectEntry->certKeys[i])) {
+ /* Found matching cert key. */
+ smap = (certDBSubjectEntryMap *)subjNode->appData;
+ smap->pCerts[i] = certNode;
+ break;
+ }
+ }
+ }
+ }
+ }
+ PORT_FreeArena(tmparena, PR_FALSE);
+ return SECSuccess;
+}
+
+SECStatus
+mapSubjectEntries(certDBArray *dbArray)
+{
+ certDBEntrySubject *subjectEntry;
+ certDBEntryListNode *subjNode;
+ certDBSubjectEntryMap *subjMap;
+ PRCList *sElem;
+
+ for (sElem = PR_LIST_HEAD(&dbArray->subjects.link);
+ sElem != &dbArray->subjects.link; sElem = PR_NEXT_LINK(sElem)) {
+ /* Iterate over subject entries and map subjects to nickname
+ * and smime entries. The cert<->subject map will be handled
+ * by a subsequent call to mapCertEntries.
+ */
+ subjNode = LISTNODE_CAST(sElem);
+ subjectEntry = (certDBEntrySubject *)&subjNode->entry;
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ /* need to alloc memory here for array of matching certs. */
+ subjMap->pCerts = PORT_ArenaAlloc(subjMap->arena,
+ subjectEntry->ncerts*sizeof(int));
+ subjMap->numCerts = subjectEntry->ncerts;
+ subjMap->pNickname = NoNickname;
+ subjMap->pSMime = NoSMime;
+
+ if (subjectEntry->nickname) {
+ /* Subject should have a nickname entry, so create a link. */
+ PRCList *nElem;
+ for (nElem = PR_LIST_HEAD(&dbArray->nicknames.link);
+ nElem != &dbArray->nicknames.link;
+ nElem = PR_NEXT_LINK(nElem)) {
+ certDBEntryListNode *nickNode;
+ certDBEntryNickname *nicknameEntry;
+ /* Look for subject's nickname in nickname entries. */
+ nickNode = LISTNODE_CAST(nElem);
+ nicknameEntry = (certDBEntryNickname *)&nickNode->entry;
+ if (PL_strcmp(subjectEntry->nickname,
+ nicknameEntry->nickname) == 0) {
+ /* Found a nickname entry for subject's nickname. */
+ if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject,
+ &nicknameEntry->subjectName)) {
+ certDBEntryMap *nickMap;
+ nickMap = (certDBEntryMap *)nickNode->appData;
+ /* Nickname and subject match. */
+ subjMap->pNickname = nickNode;
+ nickMap->pSubject = subjNode;
+ } else if (subjMap->pNickname == NoNickname) {
+ /* Nickname entry found is for diff. subject. */
+ subjMap->pNickname = WrongEntry;
+ }
+ }
+ }
+ }
+ if (subjectEntry->emailAddrs) {
+ unsigned int n;
+ for (n = 0; n < subjectEntry->nemailAddrs &&
+ subjectEntry->emailAddrs[n]; ++n) {
+ char * emailAddr = subjectEntry->emailAddrs[n];
+ if (emailAddr[0]) {
+ PRCList *mElem;
+ /* Subject should have an smime entry, so create a link. */
+ for (mElem = PR_LIST_HEAD(&dbArray->smime.link);
+ mElem != &dbArray->smime.link;
+ mElem = PR_NEXT_LINK(mElem)) {
+ certDBEntryListNode *smimeNode;
+ certDBEntrySMime *smimeEntry;
+ /* Look for subject's email in S/MIME entries. */
+ smimeNode = LISTNODE_CAST(mElem);
+ smimeEntry = (certDBEntrySMime *)&smimeNode->entry;
+ if (PL_strcmp(emailAddr,
+ smimeEntry->emailAddr) == 0) {
+ /* Found a S/MIME entry for subject's email. */
+ if (SECITEM_ItemsAreEqual(
+ &subjectEntry->derSubject,
+ &smimeEntry->subjectName)) {
+ certDBEntryMap *smimeMap;
+ /* S/MIME entry and subject match. */
+ subjMap->pSMime = smimeNode;
+ smimeMap = (certDBEntryMap *)smimeNode->appData;
+ smimeMap->pSubject = subjNode;
+ } else if (subjMap->pSMime == NoSMime) {
+ /* S/MIME entry found is for diff. subject. */
+ subjMap->pSMime = WrongEntry;
+ }
+ }
+ } /* end for */
+ } /* endif (emailAddr[0]) */
+ } /* end for */
+ } /* endif (subjectEntry->emailAddrs) */
+ }
+ return SECSuccess;
+}
+
+void
+printnode(dbDebugInfo *info, const char *str, int num)
+{
+ if (!info->dograph)
+ return;
+ if (num < 0) {
+ PR_fprintf(info->graphfile, str);
+ } else {
+ PR_fprintf(info->graphfile, str, num);
+ }
+}
+
+PRBool
+map_handle_is_ok(dbDebugInfo *info, void *mapPtr, int indent)
+{
+ if (mapPtr == NULL) {
+ if (indent > 0)
+ printnode(info, " ", -1);
+ if (indent >= 0)
+ printnode(info, "******************* ", -1);
+ return PR_FALSE;
+ } else if (mapPtr == WrongEntry) {
+ if (indent > 0)
+ printnode(info, " ", -1);
+ if (indent >= 0)
+ printnode(info, "??????????????????? ", -1);
+ return PR_FALSE;
+ } else {
+ return PR_TRUE;
+ }
+}
+
+/* these call each other */
+void print_smime_graph(dbDebugInfo *info, certDBEntryMap *smimeMap,
+ int direction);
+void print_nickname_graph(dbDebugInfo *info, certDBEntryMap *nickMap,
+ int direction);
+void print_subject_graph(dbDebugInfo *info, certDBSubjectEntryMap *subjMap,
+ int direction, int optindex, int opttype);
+void print_cert_graph(dbDebugInfo *info, certDBEntryMap *certMap,
+ int direction);
+
+/* Given an smime entry, print its unique identifier. If GOLEFT is
+ * specified, print the cert<-subject<-smime map, else just print
+ * the smime entry.
+ */
+void
+print_smime_graph(dbDebugInfo *info, certDBEntryMap *smimeMap, int direction)
+{
+ certDBSubjectEntryMap *subjMap;
+ certDBEntryListNode *subjNode;
+ if (direction == GOLEFT) {
+ /* Need to output subject and cert first, see print_subject_graph */
+ subjNode = smimeMap->pSubject;
+ if (map_handle_is_ok(info, (void *)subjNode, 1)) {
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ print_subject_graph(info, subjMap, GOLEFT,
+ smimeMap->index, certDBEntryTypeSMimeProfile);
+ } else {
+ printnode(info, "<---- S/MIME %5d ", smimeMap->index);
+ info->dbErrors[NoSubjectForSMime]++;
+ }
+ } else {
+ printnode(info, "S/MIME %5d ", smimeMap->index);
+ }
+}
+
+/* Given a nickname entry, print its unique identifier. If GOLEFT is
+ * specified, print the cert<-subject<-nickname map, else just print
+ * the nickname entry.
+ */
+void
+print_nickname_graph(dbDebugInfo *info, certDBEntryMap *nickMap, int direction)
+{
+ certDBSubjectEntryMap *subjMap;
+ certDBEntryListNode *subjNode;
+ if (direction == GOLEFT) {
+ /* Need to output subject and cert first, see print_subject_graph */
+ subjNode = nickMap->pSubject;
+ if (map_handle_is_ok(info, (void *)subjNode, 1)) {
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ print_subject_graph(info, subjMap, GOLEFT,
+ nickMap->index, certDBEntryTypeNickname);
+ } else {
+ printnode(info, "<---- Nickname %5d ", nickMap->index);
+ info->dbErrors[NoSubjectForNickname]++;
+ }
+ } else {
+ printnode(info, "Nickname %5d ", nickMap->index);
+ }
+}
+
+/* Given a subject entry, if going right print the graph of the nickname|smime
+ * that it maps to (by its unique identifier); and if going left
+ * print the list of certs that it points to.
+ */
+void
+print_subject_graph(dbDebugInfo *info, certDBSubjectEntryMap *subjMap,
+ int direction, int optindex, int opttype)
+{
+ certDBEntryMap *map;
+ certDBEntryListNode *node;
+ int i;
+ /* The first line of output always contains the cert id, subject id,
+ * and nickname|smime id. Subsequent lines may contain additional
+ * cert id's for the subject if going left or both directions.
+ * Ex. of printing the graph for a subject entry:
+ * Cert 3 <- Subject 5 -> Nickname 32
+ * Cert 8 /
+ * Cert 9 /
+ * means subject 5 has 3 certs, 3, 8, and 9, and corresponds
+ * to nickname entry 32.
+ * To accomplish the above, it is required to dump the entire first
+ * line left-to-right, regardless of the input direction, and then
+ * finish up any remaining cert entries. Hence the code is uglier
+ * than one may expect.
+ */
+ if (direction == GOLEFT || direction == GOBOTH) {
+ /* In this case, nothing should be output until the first cert is
+ * located and output (cert 3 in the above example).
+ */
+ if (subjMap->numCerts == 0 || subjMap->pCerts == NULL)
+ /* XXX uh-oh */
+ return;
+ /* get the first cert and dump it. */
+ node = subjMap->pCerts[0];
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going left here stops. */
+ print_cert_graph(info, map, GOLEFT);
+ } else {
+ info->dbErrors[SubjectHasNoKeyForCert]++;
+ }
+ /* Now it is safe to output the subject id. */
+ if (direction == GOLEFT)
+ printnode(info, "Subject %5d <---- ", subjMap->index);
+ else /* direction == GOBOTH */
+ printnode(info, "Subject %5d ----> ", subjMap->index);
+ }
+ if (direction == GORIGHT || direction == GOBOTH) {
+ /* Okay, now output the nickname|smime for this subject. */
+ if (direction != GOBOTH) /* handled above */
+ printnode(info, "Subject %5d ----> ", subjMap->index);
+ if (subjMap->pNickname) {
+ node = subjMap->pNickname;
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going right here stops. */
+ print_nickname_graph(info, map, GORIGHT);
+ }
+ }
+ if (subjMap->pSMime) {
+ node = subjMap->pSMime;
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going right here stops. */
+ print_smime_graph(info, map, GORIGHT);
+ }
+ }
+ if (!subjMap->pNickname && !subjMap->pSMime) {
+ printnode(info, "******************* ", -1);
+ info->dbErrors[NoNicknameOrSMimeForSubject]++;
+ }
+ if (subjMap->pNickname && subjMap->pSMime) {
+ info->dbErrors[NicknameAndSMimeEntries]++;
+ }
+ }
+ if (direction != GORIGHT) { /* going right has only one cert */
+ if (opttype == certDBEntryTypeNickname)
+ printnode(info, "Nickname %5d ", optindex);
+ else if (opttype == certDBEntryTypeSMimeProfile)
+ printnode(info, "S/MIME %5d ", optindex);
+ for (i=1 /* 1st one already done */; inumCerts; i++) {
+ printnode(info, "\n", -1); /* start a new line */
+ node = subjMap->pCerts[i];
+ if (map_handle_is_ok(info, (void *)node, 0)) {
+ map = (certDBEntryMap *)node->appData;
+ /* going left here stops. */
+ print_cert_graph(info, map, GOLEFT);
+ printnode(info, "/", -1);
+ }
+ }
+ }
+}
+
+/* Given a cert entry, print its unique identifer. If GORIGHT is specified,
+ * print the cert->subject->nickname|smime map, else just print
+ * the cert entry.
+ */
+void
+print_cert_graph(dbDebugInfo *info, certDBEntryMap *certMap, int direction)
+{
+ certDBSubjectEntryMap *subjMap;
+ certDBEntryListNode *subjNode;
+ if (direction == GOLEFT) {
+ printnode(info, "Cert %5d <---- ", certMap->index);
+ /* only want cert entry, terminate here. */
+ return;
+ }
+ /* Keep going right then. */
+ printnode(info, "Cert %5d ----> ", certMap->index);
+ subjNode = certMap->pSubject;
+ if (map_handle_is_ok(info, (void *)subjNode, 0)) {
+ subjMap = (certDBSubjectEntryMap *)subjNode->appData;
+ print_subject_graph(info, subjMap, GORIGHT, -1, -1);
+ } else {
+ info->dbErrors[NoSubjectForCert]++;
+ }
+}
+
+SECStatus
+computeDBGraph(certDBArray *dbArray, dbDebugInfo *info)
+{
+ PRCList *cElem, *sElem, *nElem, *mElem;
+ certDBEntryListNode *node;
+ certDBEntryMap *map;
+ certDBSubjectEntryMap *subjMap;
+
+ /* Graph is of this form:
+ *
+ * certs:
+ * cert ---> subject ---> (nickname|smime)
+ *
+ * subjects:
+ * cert <--- subject ---> (nickname|smime)
+ *
+ * nicknames and smime:
+ * cert <--- subject <--- (nickname|smime)
+ */
+
+ /* Print cert graph. */
+ for (cElem = PR_LIST_HEAD(&dbArray->certs.link);
+ cElem != &dbArray->certs.link; cElem = PR_NEXT_LINK(cElem)) {
+ /* Print graph of everything to right of cert entry. */
+ node = LISTNODE_CAST(cElem);
+ map = (certDBEntryMap *)node->appData;
+ print_cert_graph(info, map, GORIGHT);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ /* Print subject graph. */
+ for (sElem = PR_LIST_HEAD(&dbArray->subjects.link);
+ sElem != &dbArray->subjects.link; sElem = PR_NEXT_LINK(sElem)) {
+ /* Print graph of everything to both sides of subject entry. */
+ node = LISTNODE_CAST(sElem);
+ subjMap = (certDBSubjectEntryMap *)node->appData;
+ print_subject_graph(info, subjMap, GOBOTH, -1, -1);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ /* Print nickname graph. */
+ for (nElem = PR_LIST_HEAD(&dbArray->nicknames.link);
+ nElem != &dbArray->nicknames.link; nElem = PR_NEXT_LINK(nElem)) {
+ /* Print graph of everything to left of nickname entry. */
+ node = LISTNODE_CAST(nElem);
+ map = (certDBEntryMap *)node->appData;
+ print_nickname_graph(info, map, GOLEFT);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ /* Print smime graph. */
+ for (mElem = PR_LIST_HEAD(&dbArray->smime.link);
+ mElem != &dbArray->smime.link; mElem = PR_NEXT_LINK(mElem)) {
+ /* Print graph of everything to left of smime entry. */
+ node = LISTNODE_CAST(mElem);
+ if (node == NULL) break;
+ map = (certDBEntryMap *)node->appData;
+ print_smime_graph(info, map, GOLEFT);
+ printnode(info, "\n", -1);
+ }
+ printnode(info, "\n", -1);
+
+ return SECSuccess;
+}
+
+/*
+ * List the entries in the db, showing handles between entry types.
+ */
+void
+verboseOutput(certDBArray *dbArray, dbDebugInfo *info)
+{
+ int i, ref;
+ PRCList *elem;
+ certDBEntryListNode *node;
+ certDBEntryMap *map;
+ certDBSubjectEntryMap *smap;
+ certDBEntrySubject *subjectEntry;
+
+ /* List certs */
+ for (elem = PR_LIST_HEAD(&dbArray->certs.link);
+ elem != &dbArray->certs.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ map = (certDBEntryMap *)node->appData;
+ dumpCertEntry((certDBEntryCert*)&node->entry, map->index, info->out);
+ /* walk the cert handle to it's subject entry */
+ if (map_handle_is_ok(info, map->pSubject, -1)) {
+ smap = (certDBSubjectEntryMap *)map->pSubject->appData;
+ ref = smap->index;
+ PR_fprintf(info->out, "-->(subject %d)\n\n\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING SUBJECT ENTRY)\n\n\n");
+ }
+ }
+ /* List subjects */
+ for (elem = PR_LIST_HEAD(&dbArray->subjects.link);
+ elem != &dbArray->subjects.link; elem = PR_NEXT_LINK(elem)) {
+ int refs = 0;
+ node = LISTNODE_CAST(elem);
+ subjectEntry = (certDBEntrySubject *)&node->entry;
+ smap = (certDBSubjectEntryMap *)node->appData;
+ dumpSubjectEntry(subjectEntry, smap->index, info->out);
+ /* iterate over subject's certs */
+ for (i=0; inumCerts; i++) {
+ /* walk each subject handle to it's cert entries */
+ if (map_handle_is_ok(info, smap->pCerts[i], -1)) {
+ ref = ((certDBEntryMap *)smap->pCerts[i]->appData)->index;
+ PR_fprintf(info->out, "-->(%d. certificate %d)\n", i, ref);
+ } else {
+ PR_fprintf(info->out, "-->(%d. MISSING CERT ENTRY)\n", i);
+ }
+ }
+ if (subjectEntry->nickname) {
+ ++refs;
+ /* walk each subject handle to it's nickname entry */
+ if (map_handle_is_ok(info, smap->pNickname, -1)) {
+ ref = ((certDBEntryMap *)smap->pNickname->appData)->index;
+ PR_fprintf(info->out, "-->(nickname %d)\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING NICKNAME ENTRY)\n");
+ }
+ }
+ if (subjectEntry->nemailAddrs &&
+ subjectEntry->emailAddrs &&
+ subjectEntry->emailAddrs[0] &&
+ subjectEntry->emailAddrs[0][0]) {
+ ++refs;
+ /* walk each subject handle to it's smime entry */
+ if (map_handle_is_ok(info, smap->pSMime, -1)) {
+ ref = ((certDBEntryMap *)smap->pSMime->appData)->index;
+ PR_fprintf(info->out, "-->(s/mime %d)\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING S/MIME ENTRY)\n");
+ }
+ }
+ if (!refs) {
+ PR_fprintf(info->out, "-->(NO NICKNAME+S/MIME ENTRY)\n");
+ }
+ PR_fprintf(info->out, "\n\n");
+ }
+ for (elem = PR_LIST_HEAD(&dbArray->nicknames.link);
+ elem != &dbArray->nicknames.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ map = (certDBEntryMap *)node->appData;
+ dumpNicknameEntry((certDBEntryNickname*)&node->entry, map->index,
+ info->out);
+ if (map_handle_is_ok(info, map->pSubject, -1)) {
+ ref = ((certDBEntryMap *)map->pSubject->appData)->index;
+ PR_fprintf(info->out, "-->(subject %d)\n\n\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING SUBJECT ENTRY)\n\n\n");
+ }
+ }
+ for (elem = PR_LIST_HEAD(&dbArray->smime.link);
+ elem != &dbArray->smime.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ map = (certDBEntryMap *)node->appData;
+ dumpSMimeEntry((certDBEntrySMime*)&node->entry, map->index, info->out);
+ if (map_handle_is_ok(info, map->pSubject, -1)) {
+ ref = ((certDBEntryMap *)map->pSubject->appData)->index;
+ PR_fprintf(info->out, "-->(subject %d)\n\n\n", ref);
+ } else {
+ PR_fprintf(info->out, "-->(MISSING SUBJECT ENTRY)\n\n\n");
+ }
+ }
+ PR_fprintf(info->out, "\n\n");
+}
+
+
+/* A callback function, intended to be called from nsslowcert_TraverseDBEntries
+ * Builds a PRCList of DB entries of the specified type.
+ */
+SECStatus
+SEC_GetCertDBEntryList(SECItem *dbdata, SECItem *dbkey,
+ certDBEntryType entryType, void *pdata)
+{
+ certDBEntry * entry;
+ certDBEntryListNode * node;
+ PRCList * list = (PRCList *)pdata;
+
+ if (!dbdata || !dbkey || !pdata || !dbdata->data || !dbkey->data) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ entry = nsslowcert_DecodeAnyDBEntry(dbdata, dbkey, entryType, NULL);
+ if (!entry) {
+ return SECSuccess; /* skip it */
+ }
+ node = PORT_ArenaZNew(entry->common.arena, certDBEntryListNode);
+ if (!node) {
+ /* DestroyDBEntry(entry); */
+ PLArenaPool *arena = entry->common.arena;
+ PORT_Memset(&entry->common, 0, sizeof entry->common);
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+ }
+ node->entry = *entry; /* crude but effective. */
+ PR_INIT_CLIST(&node->link);
+ PR_INSERT_BEFORE(&node->link, list);
+ return SECSuccess;
+}
+
+
+int
+fillDBEntryArray(NSSLOWCERTCertDBHandle *handle, certDBEntryType type,
+ certDBEntryListNode *list)
+{
+ PRCList *elem;
+ certDBEntryListNode *node;
+ certDBEntryMap *mnode;
+ certDBSubjectEntryMap *smnode;
+ PLArenaPool *arena;
+ int count = 0;
+
+ /* Initialize a dummy entry in the list. The list head will be the
+ * next element, so this element is skipped by for loops.
+ */
+ PR_INIT_CLIST((PRCList *)list);
+ /* Collect all of the cert db entries for this type into a list. */
+ nsslowcert_TraverseDBEntries(handle, type, SEC_GetCertDBEntryList, list);
+
+ for (elem = PR_LIST_HEAD(&list->link);
+ elem != &list->link; elem = PR_NEXT_LINK(elem)) {
+ /* Iterate over the entries and ... */
+ node = (certDBEntryListNode *)elem;
+ if (type != certDBEntryTypeSubject) {
+ arena = PORT_NewArena(sizeof(*mnode));
+ mnode = PORT_ArenaZNew(arena, certDBEntryMap);
+ mnode->arena = arena;
+ /* ... assign a unique index number to each node, and ... */
+ mnode->index = count;
+ /* ... set the map pointer for the node. */
+ node->appData = (void *)mnode;
+ } else {
+ /* allocate some room for the cert pointers also */
+ arena = PORT_NewArena(sizeof(*smnode) + 20*sizeof(void *));
+ smnode = PORT_ArenaZNew(arena, certDBSubjectEntryMap);
+ smnode->arena = arena;
+ smnode->index = count;
+ node->appData = (void *)smnode;
+ }
+ count++;
+ }
+ return count;
+}
+
+void
+freeDBEntryList(PRCList *list)
+{
+ PRCList *next, *elem;
+ certDBEntryListNode *node;
+ certDBEntryMap *map;
+
+ for (elem = PR_LIST_HEAD(list); elem != list;) {
+ next = PR_NEXT_LINK(elem);
+ node = (certDBEntryListNode *)elem;
+ map = (certDBEntryMap *)node->appData;
+ PR_REMOVE_LINK(&node->link);
+ PORT_FreeArena(map->arena, PR_TRUE);
+ PORT_FreeArena(node->entry.common.arena, PR_TRUE);
+ elem = next;
+ }
+}
+
+void
+DBCK_DebugDB(NSSLOWCERTCertDBHandle *handle, PRFileDesc *out,
+ PRFileDesc *mailfile)
+{
+ int i, nCertsFound, nSubjFound, nErr;
+ int nCerts, nSubjects, nSubjCerts, nNicknames, nSMime, nRevocation;
+ PRCList *elem;
+ char c;
+ dbDebugInfo info;
+ certDBArray dbArray;
+
+ PORT_Memset(&dbArray, 0, sizeof(dbArray));
+ PORT_Memset(&info, 0, sizeof(info));
+ info.verbose = (PRBool)(out != NULL);
+ info.dograph = info.verbose;
+ info.out = (out) ? out : PR_STDOUT;
+ info.graphfile = mailfile ? mailfile : PR_STDOUT;
+
+ /* Fill the array structure with cert/subject/nickname/smime entries. */
+ dbArray.numCerts = fillDBEntryArray(handle, certDBEntryTypeCert,
+ &dbArray.certs);
+ dbArray.numSubjects = fillDBEntryArray(handle, certDBEntryTypeSubject,
+ &dbArray.subjects);
+ dbArray.numNicknames = fillDBEntryArray(handle, certDBEntryTypeNickname,
+ &dbArray.nicknames);
+ dbArray.numSMime = fillDBEntryArray(handle, certDBEntryTypeSMimeProfile,
+ &dbArray.smime);
+ dbArray.numRevocation= fillDBEntryArray(handle, certDBEntryTypeRevocation,
+ &dbArray.revocation);
+
+ /* Compute the map between the database entries. */
+ mapSubjectEntries(&dbArray);
+ mapCertEntries(&dbArray);
+ computeDBGraph(&dbArray, &info);
+
+ /* Store the totals for later reference. */
+ nCerts = dbArray.numCerts;
+ nSubjects = dbArray.numSubjects;
+ nNicknames = dbArray.numNicknames;
+ nSMime = dbArray.numSMime;
+ nRevocation= dbArray.numRevocation;
+ nSubjCerts = 0;
+ for (elem = PR_LIST_HEAD(&dbArray.subjects.link);
+ elem != &dbArray.subjects.link; elem = PR_NEXT_LINK(elem)) {
+ certDBSubjectEntryMap *smap;
+ smap = (certDBSubjectEntryMap *)LISTNODE_CAST(elem)->appData;
+ nSubjCerts += smap->numCerts;
+ }
+
+ if (info.verbose) {
+ /* Dump the database contents. */
+ verboseOutput(&dbArray, &info);
+ }
+
+ freeDBEntryList(&dbArray.certs.link);
+ freeDBEntryList(&dbArray.subjects.link);
+ freeDBEntryList(&dbArray.nicknames.link);
+ freeDBEntryList(&dbArray.smime.link);
+ freeDBEntryList(&dbArray.revocation.link);
+
+ PR_fprintf(info.out, "\n");
+ PR_fprintf(info.out, "Database statistics:\n");
+ PR_fprintf(info.out, "N0: Found %4d Certificate entries.\n",
+ nCerts);
+ PR_fprintf(info.out, "N1: Found %4d Subject entries (unique DN's).\n",
+ nSubjects);
+ PR_fprintf(info.out, "N2: Found %4d Cert keys within Subject entries.\n",
+ nSubjCerts);
+ PR_fprintf(info.out, "N3: Found %4d Nickname entries.\n",
+ nNicknames);
+ PR_fprintf(info.out, "N4: Found %4d S/MIME entries.\n",
+ nSMime);
+ PR_fprintf(info.out, "N5: Found %4d CRL entries.\n",
+ nRevocation);
+ PR_fprintf(info.out, "\n");
+
+ nErr = 0;
+ for (i=0; i < NUM_ERROR_TYPES; i++) {
+ PR_fprintf(info.out, "E%d: Found %4d %s\n",
+ i, info.dbErrors[i], errResult[i]);
+ nErr += info.dbErrors[i];
+ }
+ PR_fprintf(info.out, "--------------\n Found %4d errors in database.\n",
+ nErr);
+
+ PR_fprintf(info.out, "\nCertificates:\n");
+ PR_fprintf(info.out, "N0 == N2 + E%d + E%d\n", NoSubjectForCert,
+ SubjectHasNoKeyForCert);
+ nCertsFound = nSubjCerts +
+ info.dbErrors[NoSubjectForCert] +
+ info.dbErrors[SubjectHasNoKeyForCert];
+ c = (nCertsFound == nCerts) ? '=' : '!';
+ PR_fprintf(info.out, "%d %c= %d + %d + %d\n", nCerts, c, nSubjCerts,
+ info.dbErrors[NoSubjectForCert],
+ info.dbErrors[SubjectHasNoKeyForCert]);
+ PR_fprintf(info.out, "\nSubjects:\n");
+ PR_fprintf(info.out,
+ "N1 == N3 + N4 + E%d + E%d + E%d + E%d + E%d - E%d - E%d - E%d\n",
+ NoNicknameOrSMimeForSubject,
+ WrongNicknameForSubject,
+ NoNicknameEntry,
+ WrongSMimeForSubject,
+ NoSMimeEntry,
+ NoSubjectForNickname,
+ NoSubjectForSMime,
+ NicknameAndSMimeEntries);
+ nSubjFound = nNicknames + nSMime +
+ info.dbErrors[NoNicknameOrSMimeForSubject] +
+ info.dbErrors[WrongNicknameForSubject] +
+ info.dbErrors[NoNicknameEntry] +
+ info.dbErrors[WrongSMimeForSubject] +
+ info.dbErrors[NoSMimeEntry] -
+ info.dbErrors[NoSubjectForNickname] -
+ info.dbErrors[NoSubjectForSMime] -
+ info.dbErrors[NicknameAndSMimeEntries];
+ c = (nSubjFound == nSubjects) ? '=' : '!';
+ PR_fprintf(info.out,
+ "%2d %c= %2d + %2d + %2d + %2d + %2d + %2d + %2d - %2d - %2d - %2d\n",
+ nSubjects, c, nNicknames, nSMime,
+ info.dbErrors[NoNicknameOrSMimeForSubject],
+ info.dbErrors[WrongNicknameForSubject],
+ info.dbErrors[NoNicknameEntry],
+ info.dbErrors[WrongSMimeForSubject],
+ info.dbErrors[NoSMimeEntry],
+ info.dbErrors[NoSubjectForNickname],
+ info.dbErrors[NoSubjectForSMime],
+ info.dbErrors[NicknameAndSMimeEntries]);
+ PR_fprintf(info.out, "\n");
+}
+
+#ifdef DORECOVER
+#include "dbrecover.c"
+#endif /* DORECOVER */
+
+enum {
+ cmd_Debug = 0,
+ cmd_LongUsage,
+ cmd_Recover
+};
+
+enum {
+ opt_KeepAll = 0,
+ opt_CertDir,
+ opt_Dumpfile,
+ opt_InputDB,
+ opt_OutputDB,
+ opt_Mailfile,
+ opt_Prompt,
+ opt_KeepRedundant,
+ opt_KeepNoSMimeProfile,
+ opt_Verbose,
+ opt_KeepExpired
+};
+
+static secuCommandFlag dbck_commands[] =
+{
+ { /* cmd_Debug, */ 'D', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_LongUsage,*/ 'H', PR_FALSE, 0, PR_FALSE },
+ { /* cmd_Recover, */ 'R', PR_FALSE, 0, PR_FALSE }
+};
+
+static secuCommandFlag dbck_options[] =
+{
+ { /* opt_KeepAll, */ 'a', PR_FALSE, 0, PR_FALSE },
+ { /* opt_CertDir, */ 'd', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Dumpfile, */ 'f', PR_TRUE, 0, PR_FALSE },
+ { /* opt_InputDB, */ 'i', PR_TRUE, 0, PR_FALSE },
+ { /* opt_OutputDB, */ 'o', PR_TRUE, 0, PR_FALSE },
+ { /* opt_Mailfile, */ 'm', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Prompt, */ 'p', PR_FALSE, 0, PR_FALSE },
+ { /* opt_KeepRedundant, */ 'r', PR_FALSE, 0, PR_FALSE },
+ { /* opt_KeepNoSMimeProfile,*/ 's', PR_FALSE, 0, PR_FALSE },
+ { /* opt_Verbose, */ 'v', PR_FALSE, 0, PR_FALSE },
+ { /* opt_KeepExpired, */ 'x', PR_FALSE, 0, PR_FALSE }
+};
+
+#define CERT_DB_FMT "%s/cert%s.db"
+
+static char *
+dbck_certdb_name_cb(void *arg, int dbVersion)
+{
+ const char *configdir = (const char *)arg;
+ const char *dbver;
+ char *smpname = NULL;
+ char *dbname = NULL;
+
+ switch (dbVersion) {
+ case 8:
+ dbver = "8";
+ break;
+ case 7:
+ dbver = "7";
+ break;
+ case 6:
+ dbver = "6";
+ break;
+ case 5:
+ dbver = "5";
+ break;
+ case 4:
+ default:
+ dbver = "";
+ break;
+ }
+
+ /* make sure we return something allocated with PORT_ so we have properly
+ * matched frees at the end */
+ smpname = PR_smprintf(CERT_DB_FMT, configdir, dbver);
+ if (smpname) {
+ dbname = PORT_Strdup(smpname);
+ PR_smprintf_free(smpname);
+ }
+ return dbname;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ NSSLOWCERTCertDBHandle *certHandle;
+
+ PRFileDesc *mailfile = NULL;
+ PRFileDesc *dumpfile = NULL;
+
+ char * pathname = 0;
+ char * fullname = 0;
+ char * newdbname = 0;
+
+ PRBool removeExpired, requireProfile, singleEntry;
+ SECStatus rv;
+ secuCommand dbck;
+
+ dbck.numCommands = sizeof(dbck_commands) / sizeof(secuCommandFlag);
+ dbck.numOptions = sizeof(dbck_options) / sizeof(secuCommandFlag);
+ dbck.commands = dbck_commands;
+ dbck.options = dbck_options;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ rv = SECU_ParseCommandLine(argc, argv, progName, &dbck);
+
+ if (rv != SECSuccess)
+ Usage(progName);
+
+ if (dbck.commands[cmd_LongUsage].activated)
+ LongUsage(progName);
+
+ if (!dbck.commands[cmd_Debug].activated &&
+ !dbck.commands[cmd_Recover].activated) {
+ PR_fprintf(PR_STDERR, "Please specify -H, -D or -R.\n");
+ Usage(progName);
+ }
+
+ removeExpired = !(dbck.options[opt_KeepAll].activated ||
+ dbck.options[opt_KeepExpired].activated);
+
+ requireProfile = !(dbck.options[opt_KeepAll].activated ||
+ dbck.options[opt_KeepNoSMimeProfile].activated);
+
+ singleEntry = !(dbck.options[opt_KeepAll].activated ||
+ dbck.options[opt_KeepRedundant].activated);
+
+ if (dbck.options[opt_OutputDB].activated) {
+ newdbname = PL_strdup(dbck.options[opt_OutputDB].arg);
+ } else {
+ newdbname = PL_strdup("new_cert8.db");
+ }
+
+ /* Create a generic graph of the database. */
+ if (dbck.options[opt_Mailfile].activated) {
+ mailfile = PR_Open("./mailfile", PR_RDWR | PR_CREATE_FILE, 00660);
+ if (!mailfile) {
+ fprintf(stderr, "Unable to create mailfile.\n");
+ return -1;
+ }
+ }
+
+ /* Dump all debugging info while running. */
+ if (dbck.options[opt_Verbose].activated) {
+ if (dbck.options[opt_Dumpfile].activated) {
+ dumpfile = PR_Open(dbck.options[opt_Dumpfile].arg,
+ PR_RDWR | PR_CREATE_FILE, 00660);
+ if (!dumpfile) {
+ fprintf(stderr, "Unable to create dumpfile.\n");
+ return -1;
+ }
+ } else {
+ dumpfile = PR_STDOUT;
+ }
+ }
+
+ /* Set the cert database directory. */
+ if (dbck.options[opt_CertDir].activated) {
+ SECU_ConfigDirectory(dbck.options[opt_CertDir].arg);
+ }
+
+ pathname = SECU_ConfigDirectory(NULL);
+
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+ rv = NSS_NoDB_Init(pathname);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "NSS_NoDB_Init failed\n");
+ return -1;
+ }
+
+ certHandle = PORT_ZNew(NSSLOWCERTCertDBHandle);
+ if (!certHandle) {
+ SECU_PrintError(progName, "unable to get database handle");
+ return -1;
+ }
+ certHandle->ref = 1;
+
+#ifdef NOTYET
+ /* Open the possibly corrupt database. */
+ if (dbck.options[opt_InputDB].activated) {
+ PRFileInfo fileInfo;
+ fullname = PR_smprintf("%s/%s", pathname,
+ dbck.options[opt_InputDB].arg);
+ if (PR_GetFileInfo(fullname, &fileInfo) != PR_SUCCESS) {
+ fprintf(stderr, "Unable to read file \"%s\".\n", fullname);
+ return -1;
+ }
+ rv = CERT_OpenCertDBFilename(certHandle, fullname, PR_TRUE);
+ } else
+#endif
+ {
+ /* Use the default. */
+#ifdef NOTYET
+ fullname = SECU_CertDBNameCallback(NULL, CERT_DB_FILE_VERSION);
+ if (PR_GetFileInfo(fullname, &fileInfo) != PR_SUCCESS) {
+ fprintf(stderr, "Unable to read file \"%s\".\n", fullname);
+ return -1;
+ }
+#endif
+ rv = nsslowcert_OpenCertDB(certHandle,
+ PR_TRUE, /* readOnly */
+ NULL, /* rdb appName */
+ "", /* rdb prefix */
+ dbck_certdb_name_cb, /* namecb */
+ pathname, /* configDir */
+ PR_FALSE); /* volatile */
+ }
+
+ if (rv) {
+ SECU_PrintError(progName, "unable to open cert database");
+ return -1;
+ }
+
+ if (dbck.commands[cmd_Debug].activated) {
+ DBCK_DebugDB(certHandle, dumpfile, mailfile);
+ return 0;
+ }
+
+#ifdef DORECOVER
+ if (dbck.commands[cmd_Recover].activated) {
+ DBCK_ReconstructDBFromCerts(certHandle, newdbname,
+ dumpfile, removeExpired,
+ requireProfile, singleEntry,
+ dbck.options[opt_Prompt].activated);
+ return 0;
+ }
+#endif
+
+ if (mailfile)
+ PR_Close(mailfile);
+ if (dumpfile)
+ PR_Close(dumpfile);
+ if (certHandle) {
+ nsslowcert_ClosePermCertDB(certHandle);
+ PORT_Free(certHandle);
+ }
+ return -1;
+}
diff --git a/nss/cmd/dbck/dbrecover.c b/nss/cmd/dbck/dbrecover.c
new file mode 100644
index 0000000..372c73b
--- /dev/null
+++ b/nss/cmd/dbck/dbrecover.c
@@ -0,0 +1,670 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+enum {
+ dbInvalidCert = 0,
+ dbNoSMimeProfile,
+ dbOlderCert,
+ dbBadCertificate,
+ dbCertNotWrittenToDB
+};
+
+typedef struct dbRestoreInfoStr
+{
+ NSSLOWCERTCertDBHandle *handle;
+ PRBool verbose;
+ PRFileDesc *out;
+ int nCerts;
+ int nOldCerts;
+ int dbErrors[5];
+ PRBool removeType[3];
+ PRBool promptUser[3];
+} dbRestoreInfo;
+
+char *
+IsEmailCert(CERTCertificate *cert)
+{
+ char *email, *tmp1, *tmp2;
+ PRBool isCA;
+ int len;
+
+ if (!cert->subjectName) {
+ return NULL;
+ }
+
+ tmp1 = PORT_Strstr(cert->subjectName, "E=");
+ tmp2 = PORT_Strstr(cert->subjectName, "MAIL=");
+ /* XXX Nelson has cert for KTrilli which does not have either
+ * of above but is email cert (has cert->emailAddr).
+ */
+ if (!tmp1 && !tmp2 && !(cert->emailAddr && cert->emailAddr[0])) {
+ return NULL;
+ }
+
+ /* Server or CA cert, not personal email. */
+ isCA = CERT_IsCACert(cert, NULL);
+ if (isCA)
+ return NULL;
+
+ /* XXX CERT_IsCACert advertises checking the key usage ext.,
+ but doesn't appear to. */
+ /* Check the key usage extension. */
+ if (cert->keyUsagePresent) {
+ /* Must at least be able to sign or encrypt (not neccesarily
+ * both if it is one of a dual cert).
+ */
+ if (!((cert->rawKeyUsage & KU_DIGITAL_SIGNATURE) ||
+ (cert->rawKeyUsage & KU_KEY_ENCIPHERMENT)))
+ return NULL;
+
+ /* CA cert, not personal email. */
+ if (cert->rawKeyUsage & (KU_KEY_CERT_SIGN | KU_CRL_SIGN))
+ return NULL;
+ }
+
+ if (cert->emailAddr && cert->emailAddr[0]) {
+ email = PORT_Strdup(cert->emailAddr);
+ } else {
+ if (tmp1)
+ tmp1 += 2; /* "E=" */
+ else
+ tmp1 = tmp2 + 5; /* "MAIL=" */
+ len = strcspn(tmp1, ", ");
+ email = (char*)PORT_Alloc(len+1);
+ PORT_Strncpy(email, tmp1, len);
+ email[len] = '\0';
+ }
+
+ return email;
+}
+
+SECStatus
+deleteit(CERTCertificate *cert, void *arg)
+{
+ return SEC_DeletePermCertificate(cert);
+}
+
+/* Different than DeleteCertificate - has the added bonus of removing
+ * all certs with the same DN.
+ */
+SECStatus
+deleteAllEntriesForCert(NSSLOWCERTCertDBHandle *handle, CERTCertificate *cert,
+ PRFileDesc *outfile)
+{
+#if 0
+ certDBEntrySubject *subjectEntry;
+ certDBEntryNickname *nicknameEntry;
+ certDBEntrySMime *smimeEntry;
+ int i;
+#endif
+
+ if (outfile) {
+ PR_fprintf(outfile, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n");
+ PR_fprintf(outfile, "Deleting redundant certificate:\n");
+ dumpCertificate(cert, -1, outfile);
+ }
+
+ CERT_TraverseCertsForSubject(handle, cert->subjectList, deleteit, NULL);
+#if 0
+ CERT_LockDB(handle);
+ subjectEntry = ReadDBSubjectEntry(handle, &cert->derSubject);
+ /* It had better be there, or created a bad db. */
+ PORT_Assert(subjectEntry);
+ for (i=0; incerts; i++) {
+ DeleteDBCertEntry(handle, &subjectEntry->certKeys[i]);
+ }
+ DeleteDBSubjectEntry(handle, &cert->derSubject);
+ if (subjectEntry->emailAddr && subjectEntry->emailAddr[0]) {
+ smimeEntry = ReadDBSMimeEntry(handle, subjectEntry->emailAddr);
+ if (smimeEntry) {
+ if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject,
+ &smimeEntry->subjectName))
+ /* Only delete it if it's for this subject! */
+ DeleteDBSMimeEntry(handle, subjectEntry->emailAddr);
+ SEC_DestroyDBEntry((certDBEntry*)smimeEntry);
+ }
+ }
+ if (subjectEntry->nickname) {
+ nicknameEntry = ReadDBNicknameEntry(handle, subjectEntry->nickname);
+ if (nicknameEntry) {
+ if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject,
+ &nicknameEntry->subjectName))
+ /* Only delete it if it's for this subject! */
+ DeleteDBNicknameEntry(handle, subjectEntry->nickname);
+ SEC_DestroyDBEntry((certDBEntry*)nicknameEntry);
+ }
+ }
+ SEC_DestroyDBEntry((certDBEntry*)subjectEntry);
+ CERT_UnlockDB(handle);
+#endif
+ return SECSuccess;
+}
+
+void
+getCertsToDelete(char *numlist, int len, int *certNums, int nCerts)
+{
+ int j, num;
+ char *numstr, *numend, *end;
+
+ numstr = numlist;
+ end = numstr + len - 1;
+ while (numstr != end) {
+ numend = strpbrk(numstr, ", \n");
+ *numend = '\0';
+ if (PORT_Strlen(numstr) == 0)
+ return;
+ num = PORT_Atoi(numstr);
+ if (numstr == numlist)
+ certNums[0] = num;
+ for (j=1; jpromptUser[errtype] == PR_FALSE)
+ return (info->removeType[errtype]);
+ switch (errtype) {
+ case dbInvalidCert:
+ PR_fprintf(PR_STDOUT, "******** Expired ********\n");
+ PR_fprintf(PR_STDOUT, "Cert has expired.\n\n");
+ dumpCertificate(certs[0], -1, PR_STDOUT);
+ PR_fprintf(PR_STDOUT,
+ "Keep it? (y/n - this one, Y/N - all expired certs) [n] ");
+ break;
+ case dbNoSMimeProfile:
+ PR_fprintf(PR_STDOUT, "******** No Profile ********\n");
+ PR_fprintf(PR_STDOUT, "S/MIME cert has no profile.\n\n");
+ dumpCertificate(certs[0], -1, PR_STDOUT);
+ PR_fprintf(PR_STDOUT,
+ "Keep it? (y/n - this one, Y/N - all S/MIME w/o profile) [n] ");
+ break;
+ case dbOlderCert:
+ PR_fprintf(PR_STDOUT, "******* Redundant nickname/email *******\n\n");
+ PR_fprintf(PR_STDOUT, "These certs have the same nickname/email:\n");
+ for (i=0; ipromptUser[errtype] = PR_FALSE;
+ info->removeType[errtype] = PR_TRUE;
+ return PR_TRUE;
+ }
+ getCertsToDelete(response, nb, certNums, nCerts);
+ return PR_TRUE;
+ }
+ /* User doesn't want to be prompted for this type anymore. */
+ if (response[0] == 'Y') {
+ info->promptUser[errtype] = PR_FALSE;
+ info->removeType[errtype] = PR_FALSE;
+ return PR_FALSE;
+ } else if (response[0] == 'N') {
+ info->promptUser[errtype] = PR_FALSE;
+ info->removeType[errtype] = PR_TRUE;
+ return PR_TRUE;
+ }
+ return (response[0] != 'y') ? PR_TRUE : PR_FALSE;
+}
+
+SECStatus
+addCertToDB(certDBEntryCert *certEntry, dbRestoreInfo *info,
+ NSSLOWCERTCertDBHandle *oldhandle)
+{
+ SECStatus rv = SECSuccess;
+ PRBool allowOverride;
+ PRBool userCert;
+ SECCertTimeValidity validity;
+ CERTCertificate *oldCert = NULL;
+ CERTCertificate *dbCert = NULL;
+ CERTCertificate *newCert = NULL;
+ CERTCertTrust *trust;
+ certDBEntrySMime *smimeEntry = NULL;
+ char *email = NULL;
+ char *nickname = NULL;
+ int nCertsForSubject = 1;
+
+ oldCert = CERT_DecodeDERCertificate(&certEntry->derCert, PR_FALSE,
+ certEntry->nickname);
+ if (!oldCert) {
+ info->dbErrors[dbBadCertificate]++;
+ SEC_DestroyDBEntry((certDBEntry*)certEntry);
+ return SECSuccess;
+ }
+
+ oldCert->dbEntry = certEntry;
+ oldCert->trust = &certEntry->trust;
+ oldCert->dbhandle = oldhandle;
+
+ trust = oldCert->trust;
+
+ info->nOldCerts++;
+
+ if (info->verbose)
+ PR_fprintf(info->out, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n");
+
+ if (oldCert->nickname)
+ nickname = PORT_Strdup(oldCert->nickname);
+
+ /* Always keep user certs. Skip ahead. */
+ /* XXX if someone sends themselves a signed message, it is possible
+ for their cert to be imported as an "other" cert, not a user cert.
+ this mucks with smime entries... */
+ userCert = (SEC_GET_TRUST_FLAGS(trust, trustSSL) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustEmail) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustObjectSigning) & CERTDB_USER);
+ if (userCert)
+ goto createcert;
+
+ /* If user chooses so, ignore expired certificates. */
+ allowOverride = (PRBool)((oldCert->keyUsage == certUsageSSLServer) ||
+ (oldCert->keyUsage == certUsageSSLServerWithStepUp));
+ validity = CERT_CheckCertValidTimes(oldCert, PR_Now(), allowOverride);
+ /* If cert expired and user wants to delete it, ignore it. */
+ if ((validity != secCertTimeValid) &&
+ userSaysDeleteCert(&oldCert, 1, dbInvalidCert, info, 0)) {
+ info->dbErrors[dbInvalidCert]++;
+ if (info->verbose) {
+ PR_fprintf(info->out, "Deleting expired certificate:\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+ goto cleanup;
+ }
+
+ /* New database will already have default certs, don't attempt
+ to overwrite them. */
+ dbCert = CERT_FindCertByDERCert(info->handle, &oldCert->derCert);
+ if (dbCert) {
+ info->nCerts++;
+ if (info->verbose) {
+ PR_fprintf(info->out, "Added certificate to database:\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+ goto cleanup;
+ }
+
+ /* Determine if cert is S/MIME and get its email if so. */
+ email = IsEmailCert(oldCert);
+
+ /*
+ XXX Just create empty profiles?
+ if (email) {
+ SECItem *profile = CERT_FindSMimeProfile(oldCert);
+ if (!profile &&
+ userSaysDeleteCert(&oldCert, 1, dbNoSMimeProfile, info, 0)) {
+ info->dbErrors[dbNoSMimeProfile]++;
+ if (info->verbose) {
+ PR_fprintf(info->out,
+ "Deleted cert missing S/MIME profile.\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+ goto cleanup;
+ } else {
+ SECITEM_FreeItem(profile);
+ }
+ }
+ */
+
+createcert:
+
+ /* Sometimes happens... */
+ if (!nickname && userCert)
+ nickname = PORT_Strdup(oldCert->subjectName);
+
+ /* Create a new certificate, copy of the old one. */
+ newCert = CERT_NewTempCertificate(info->handle, &oldCert->derCert,
+ nickname, PR_FALSE, PR_TRUE);
+ if (!newCert) {
+ PR_fprintf(PR_STDERR, "Unable to create new certificate.\n");
+ dumpCertificate(oldCert, -1, PR_STDERR);
+ info->dbErrors[dbBadCertificate]++;
+ goto cleanup;
+ }
+
+ /* Add the cert to the new database. */
+ rv = CERT_AddTempCertToPerm(newCert, nickname, oldCert->trust);
+ if (rv) {
+ PR_fprintf(PR_STDERR, "Failed to write temp cert to perm database.\n");
+ dumpCertificate(oldCert, -1, PR_STDERR);
+ info->dbErrors[dbCertNotWrittenToDB]++;
+ goto cleanup;
+ }
+
+ if (info->verbose) {
+ PR_fprintf(info->out, "Added certificate to database:\n");
+ dumpCertificate(oldCert, -1, info->out);
+ }
+
+ /* If the cert is an S/MIME cert, and the first with it's subject,
+ * modify the subject entry to include the email address,
+ * CERT_AddTempCertToPerm does not do email addresses and S/MIME entries.
+ */
+ if (smimeEntry) { /*&& !userCert && nCertsForSubject == 1) { */
+#if 0
+ UpdateSubjectWithEmailAddr(newCert, email);
+#endif
+ SECItem emailProfile, profileTime;
+ rv = CERT_FindFullSMimeProfile(oldCert, &emailProfile, &profileTime);
+ /* calls UpdateSubjectWithEmailAddr */
+ if (rv == SECSuccess)
+ rv = CERT_SaveSMimeProfile(newCert, &emailProfile, &profileTime);
+ }
+
+ info->nCerts++;
+
+cleanup:
+
+ if (nickname)
+ PORT_Free(nickname);
+ if (email)
+ PORT_Free(email);
+ if (oldCert)
+ CERT_DestroyCertificate(oldCert);
+ if (dbCert)
+ CERT_DestroyCertificate(dbCert);
+ if (newCert)
+ CERT_DestroyCertificate(newCert);
+ if (smimeEntry)
+ SEC_DestroyDBEntry((certDBEntry*)smimeEntry);
+ return SECSuccess;
+}
+
+#if 0
+SECStatus
+copyDBEntry(SECItem *data, SECItem *key, certDBEntryType type, void *pdata)
+{
+ SECStatus rv;
+ NSSLOWCERTCertDBHandle *newdb = (NSSLOWCERTCertDBHandle *)pdata;
+ certDBEntryCommon common;
+ SECItem dbkey;
+
+ common.type = type;
+ common.version = CERT_DB_FILE_VERSION;
+ common.flags = data->data[2];
+ common.arena = NULL;
+
+ dbkey.len = key->len + SEC_DB_KEY_HEADER_LEN;
+ dbkey.data = (unsigned char *)PORT_Alloc(dbkey.len*sizeof(unsigned char));
+ PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], key->data, key->len);
+ dbkey.data[0] = type;
+
+ rv = WriteDBEntry(newdb, &common, &dbkey, data);
+
+ PORT_Free(dbkey.data);
+ return rv;
+}
+#endif
+
+int
+certIsOlder(CERTCertificate **cert1, CERTCertificate** cert2)
+{
+ return !CERT_IsNewer(*cert1, *cert2);
+}
+
+int
+findNewestSubjectForEmail(NSSLOWCERTCertDBHandle *handle, int subjectNum,
+ certDBArray *dbArray, dbRestoreInfo *info,
+ int *subjectWithSMime, int *smimeForSubject)
+{
+ int newestSubject;
+ int subjectsForEmail[50];
+ int i, j, ns, sNum;
+ certDBEntryListNode *subjects = &dbArray->subjects;
+ certDBEntryListNode *smime = &dbArray->smime;
+ certDBEntrySubject *subjectEntry1, *subjectEntry2;
+ certDBEntrySMime *smimeEntry;
+ CERTCertificate **certs;
+ CERTCertificate *cert;
+ CERTCertTrust *trust;
+ PRBool userCert;
+ int *certNums;
+
+ ns = 0;
+ subjectEntry1 = (certDBEntrySubject*)&subjects.entries[subjectNum];
+ subjectsForEmail[ns++] = subjectNum;
+
+ *subjectWithSMime = -1;
+ *smimeForSubject = -1;
+ newestSubject = subjectNum;
+
+ cert = CERT_FindCertByKey(handle, &subjectEntry1->certKeys[0]);
+ if (cert) {
+ trust = cert->trust;
+ userCert = (SEC_GET_TRUST_FLAGS(trust, trustSSL) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustEmail) & CERTDB_USER) ||
+ (SEC_GET_TRUST_FLAGS(trust, trustObjectSigning) & CERTDB_USER);
+ CERT_DestroyCertificate(cert);
+ }
+
+ /*
+ * XXX Should we make sure that subjectEntry1->emailAddr is not
+ * a null pointer or an empty string before going into the next
+ * two for loops, which pass it to PORT_Strcmp?
+ */
+
+ /* Loop over the remaining subjects. */
+ for (i=subjectNum+1; iemailAddr && subjectEntry2->emailAddr[0] &&
+ PORT_Strcmp(subjectEntry1->emailAddr,
+ subjectEntry2->emailAddr) == 0) {
+ /* Found a subject using the same email address. */
+ subjectsForEmail[ns++] = i;
+ }
+ }
+
+ /* Find the S/MIME entry for this email address. */
+ for (i=0; icommon.arena == NULL)
+ continue;
+ if (smimeEntry->emailAddr && smimeEntry->emailAddr[0] &&
+ PORT_Strcmp(subjectEntry1->emailAddr, smimeEntry->emailAddr) == 0) {
+ /* Find which of the subjects uses this S/MIME entry. */
+ for (j=0; jsubjectName,
+ &subjectEntry2->derSubject)) {
+ /* Found the subject corresponding to the S/MIME entry. */
+ *subjectWithSMime = sNum;
+ *smimeForSubject = i;
+ }
+ }
+ SEC_DestroyDBEntry((certDBEntry*)smimeEntry);
+ PORT_Memset(smimeEntry, 0, sizeof(certDBEntry));
+ break;
+ }
+ }
+
+ if (ns <= 1)
+ return subjectNum;
+
+ if (userCert)
+ return *subjectWithSMime;
+
+ /* Now find which of the subjects has the newest cert. */
+ certs = (CERTCertificate**)PORT_Alloc(ns*sizeof(CERTCertificate*));
+ certNums = (int*)PORT_Alloc((ns+1)*sizeof(int));
+ certNums[0] = 0;
+ for (i=0; icertKeys[0]);
+ certNums[i+1] = i;
+ }
+ /* Sort the array by validity. */
+ qsort(certs, ns, sizeof(CERTCertificate*),
+ (int (*)(const void *, const void *))certIsOlder);
+ newestSubject = -1;
+ for (i=0; iderSubject,
+ &certs[0]->derSubject))
+ newestSubject = sNum;
+ else
+ SEC_DestroyDBEntry((certDBEntry*)subjectEntry1);
+ }
+ if (info && userSaysDeleteCert(certs, ns, dbOlderCert, info, certNums)) {
+ for (i=1; i= 0 && certNums[i] != certNums[0]) {
+ deleteAllEntriesForCert(handle, certs[certNums[i]], info->out);
+ info->dbErrors[dbOlderCert]++;
+ }
+ }
+ }
+ CERT_DestroyCertArray(certs, ns);
+ return newestSubject;
+}
+
+NSSLOWCERTCertDBHandle *
+DBCK_ReconstructDBFromCerts(NSSLOWCERTCertDBHandle *oldhandle, char *newdbname,
+ PRFileDesc *outfile, PRBool removeExpired,
+ PRBool requireProfile, PRBool singleEntry,
+ PRBool promptUser)
+{
+ SECStatus rv;
+ dbRestoreInfo info;
+ certDBEntryContentVersion *oldContentVersion;
+ certDBArray dbArray;
+ int i;
+
+ PORT_Memset(&dbArray, 0, sizeof(dbArray));
+ PORT_Memset(&info, 0, sizeof(info));
+ info.verbose = (outfile) ? PR_TRUE : PR_FALSE;
+ info.out = (outfile) ? outfile : PR_STDOUT;
+ info.removeType[dbInvalidCert] = removeExpired;
+ info.removeType[dbNoSMimeProfile] = requireProfile;
+ info.removeType[dbOlderCert] = singleEntry;
+ info.promptUser[dbInvalidCert] = promptUser;
+ info.promptUser[dbNoSMimeProfile] = promptUser;
+ info.promptUser[dbOlderCert] = promptUser;
+
+ /* Allocate a handle to fill with CERT_OpenCertDB below. */
+ info.handle = PORT_ZNew(NSSLOWCERTCertDBHandle);
+ if (!info.handle) {
+ fprintf(stderr, "unable to get database handle");
+ return NULL;
+ }
+
+ /* Create a certdb with the most recent set of roots. */
+ rv = CERT_OpenCertDBFilename(info.handle, newdbname, PR_FALSE);
+
+ if (rv) {
+ fprintf(stderr, "could not open certificate database");
+ goto loser;
+ }
+
+ /* Create certificate, subject, nickname, and email records.
+ * mcom_db seems to have a sequential access bug. Though reads and writes
+ * should be allowed during traversal, they seem to screw up the sequence.
+ * So, stuff all the cert entries into an array, and loop over the array
+ * doing read/writes in the db.
+ */
+ fillDBEntryArray(oldhandle, certDBEntryTypeCert, &dbArray.certs);
+ for (elem = PR_LIST_HEAD(&dbArray->certs.link);
+ elem != &dbArray->certs.link; elem = PR_NEXT_LINK(elem)) {
+ node = LISTNODE_CAST(elem);
+ addCertToDB((certDBEntryCert*)&node->entry, &info, oldhandle);
+ /* entries get destroyed in addCertToDB */
+ }
+#if 0
+ rv = nsslowcert_TraverseDBEntries(oldhandle, certDBEntryTypeSMimeProfile,
+ copyDBEntry, info.handle);
+#endif
+
+ /* Fix up the pointers between (nickname|S/MIME) --> (subject).
+ * Create S/MIME entries for S/MIME certs.
+ * Have the S/MIME entry point to the last-expiring cert using
+ * an email address.
+ */
+#if 0
+ CERT_RedoHandlesForSubjects(info.handle, singleEntry, &info);
+#endif
+
+ freeDBEntryList(&dbArray.certs.link);
+
+ /* Copy over the version record. */
+ /* XXX Already exists - and _must_ be correct... */
+ /*
+ versionEntry = ReadDBVersionEntry(oldhandle);
+ rv = WriteDBVersionEntry(info.handle, versionEntry);
+ */
+
+ /* Copy over the content version record. */
+ /* XXX Can probably get useful info from old content version?
+ * Was this db created before/after this tool? etc.
+ */
+#if 0
+ oldContentVersion = ReadDBContentVersionEntry(oldhandle);
+ CERT_SetDBContentVersion(oldContentVersion->contentVersion, info.handle);
+#endif
+
+#if 0
+ /* Copy over the CRL & KRL records. */
+ rv = nsslowcert_TraverseDBEntries(oldhandle, certDBEntryTypeRevocation,
+ copyDBEntry, info.handle);
+ /* XXX Only one KRL, just do db->get? */
+ rv = nsslowcert_TraverseDBEntries(oldhandle, certDBEntryTypeKeyRevocation,
+ copyDBEntry, info.handle);
+#endif
+
+ PR_fprintf(info.out, "Database had %d certificates.\n", info.nOldCerts);
+
+ PR_fprintf(info.out, "Reconstructed %d certificates.\n", info.nCerts);
+ PR_fprintf(info.out, "(ax) Rejected %d expired certificates.\n",
+ info.dbErrors[dbInvalidCert]);
+ PR_fprintf(info.out, "(as) Rejected %d S/MIME certificates missing a profile.\n",
+ info.dbErrors[dbNoSMimeProfile]);
+ PR_fprintf(info.out, "(ar) Rejected %d certificates for which a newer certificate was found.\n",
+ info.dbErrors[dbOlderCert]);
+ PR_fprintf(info.out, " Rejected %d corrupt certificates.\n",
+ info.dbErrors[dbBadCertificate]);
+ PR_fprintf(info.out, " Rejected %d certificates which did not write to the DB.\n",
+ info.dbErrors[dbCertNotWrittenToDB]);
+
+ if (rv)
+ goto loser;
+
+ return info.handle;
+
+loser:
+ if (info.handle)
+ PORT_Free(info.handle);
+ return NULL;
+}
+
diff --git a/nss/cmd/dbck/manifest.mn b/nss/cmd/dbck/manifest.mn
new file mode 100644
index 0000000..ec8812e
--- /dev/null
+++ b/nss/cmd/dbck/manifest.mn
@@ -0,0 +1,22 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+CORE_DEPTH = ../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = \
+ dbck.c \
+ $(NULL)
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = dbm seccmd
+
+PROGRAM = dbck
+USE_STATIC_LIBS = 1
diff --git a/nss/cmd/dbtest/Makefile b/nss/cmd/dbtest/Makefile
new file mode 100644
index 0000000..a27a3ce
--- /dev/null
+++ b/nss/cmd/dbtest/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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 ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#include ../platlibs.mk
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
+
diff --git a/nss/cmd/dbtest/dbtest.c b/nss/cmd/dbtest/dbtest.c
new file mode 100644
index 0000000..a0355cc
--- /dev/null
+++ b/nss/cmd/dbtest/dbtest.c
@@ -0,0 +1,233 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+** dbtest.c
+**
+** QA test for cert and key databases, especially to open
+** database readonly (NSS_INIT_READONLY) and force initializations
+** even if the databases cannot be opened (NSS_INIT_FORCEOPEN)
+**
+*/
+#include
+#include
+
+#if defined(WIN32)
+#include "fcntl.h"
+#include "io.h"
+#endif
+
+#include "secutil.h"
+#include "pk11pub.h"
+
+#if defined(XP_UNIX)
+#include
+#endif
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "certdb.h"
+#include "nss.h"
+#include "../modutil/modutil.h"
+
+#include "plgetopt.h"
+
+static char *progName;
+
+char *dbDir = NULL;
+
+static char *dbName[]={"secmod.db", "cert8.db", "key3.db"};
+static char* dbprefix = "";
+static char* secmodName = "secmod.db";
+static char* userPassword = "";
+PRBool verbose;
+
+static char *
+getPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ int *success = (int *)arg;
+
+ if (retry) {
+ *success = 0;
+ return NULL;
+ }
+
+ *success = 1;
+ return PORT_Strdup(userPassword);
+}
+
+
+static void Usage(const char *progName)
+{
+ printf("Usage: %s [-r] [-f] [-i] [-d dbdir ] \n",
+ progName);
+ printf("%-20s open database readonly (NSS_INIT_READONLY)\n", "-r");
+ printf("%-20s Continue to force initializations even if the\n", "-f");
+ printf("%-20s databases cannot be opened (NSS_INIT_FORCEOPEN)\n", " ");
+ printf("%-20s Try to initialize the database\n", "-i");
+ printf("%-20s Supply a password with which to initialize the db\n", "-p");
+ printf("%-20s Directory with cert database (default is .\n",
+ "-d certdir");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ PLOptState *optstate;
+ PLOptStatus optstatus;
+
+ PRUint32 flags = 0;
+ Error ret;
+ SECStatus rv;
+ char * dbString = NULL;
+ PRBool doInitTest = PR_FALSE;
+ int i;
+
+ progName = strrchr(argv[0], '/');
+ if (!progName)
+ progName = strrchr(argv[0], '\\');
+ progName = progName ? progName+1 : argv[0];
+
+ optstate = PL_CreateOptState(argc, argv, "rfip:d:h");
+
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'h':
+ default : Usage(progName); break;
+
+ case 'r': flags |= NSS_INIT_READONLY; break;
+
+ case 'f': flags |= NSS_INIT_FORCEOPEN; break;
+
+ case 'i': doInitTest = PR_TRUE; break;
+
+ case 'p':
+ userPassword = PORT_Strdup(optstate->value);
+ break;
+
+ case 'd':
+ dbDir = PORT_Strdup(optstate->value);
+ break;
+
+ }
+ }
+ if (optstatus == PL_OPT_BAD)
+ Usage(progName);
+
+ if (!dbDir) {
+ dbDir = SECU_DefaultSSLDir(); /* Look in $SSL_DIR */
+ }
+ dbDir = SECU_ConfigDirectory(dbDir);
+ PR_fprintf(PR_STDERR, "dbdir selected is %s\n\n", dbDir);
+
+ if( dbDir[0] == '\0') {
+ PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
+ ret= DIR_DOESNT_EXIST_ERR;
+ goto loser;
+ }
+
+
+ PR_Init( PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+
+ /* get the status of the directory and databases and output message */
+ if(PR_Access(dbDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
+ } else if(PR_Access(dbDir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dbDir);
+ } else {
+ if( !( flags & NSS_INIT_READONLY ) &&
+ PR_Access(dbDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dbDir);
+ }
+ if (!doInitTest) {
+ for (i=0;i<3;i++) {
+ dbString=PR_smprintf("%s/%s",dbDir,dbName[i]);
+ PR_fprintf(PR_STDOUT, "database checked is %s\n",dbString);
+ if(PR_Access(dbString, PR_ACCESS_EXISTS) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_DOESNT_EXIST_ERR],
+ dbString);
+ } else if(PR_Access(dbString, PR_ACCESS_READ_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
+ dbString);
+ } else if( !( flags & NSS_INIT_READONLY ) &&
+ PR_Access(dbString, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
+ PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
+ dbString);
+ }
+ }
+ }
+ }
+
+
+ rv = NSS_Initialize(SECU_ConfigDirectory(dbDir), dbprefix, dbprefix,
+ secmodName, flags);
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ ret=NSS_INITIALIZE_FAILED_ERR;
+ } else {
+ ret=SUCCESS;
+ if (doInitTest) {
+ PK11SlotInfo * slot = PK11_GetInternalKeySlot();
+ SECStatus rv;
+ int passwordSuccess = 0;
+ int type = CKM_DES3_CBC;
+ SECItem keyid = { 0, NULL, 0 };
+ unsigned char keyIdData[] = { 0xff, 0xfe };
+ PK11SymKey *key = NULL;
+
+ keyid.data = keyIdData;
+ keyid.len = sizeof(keyIdData);
+
+ PK11_SetPasswordFunc(getPassword);
+ rv = PK11_InitPin(slot, (char *)NULL, userPassword);
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "Failed to Init DB: %s\n",
+ SECU_Strerror(PORT_GetError()));
+ ret = CHANGEPW_FAILED_ERR;
+ }
+ if (*userPassword && !PK11_IsLoggedIn(slot, &passwordSuccess)) {
+ PR_fprintf(PR_STDERR, "New DB did not log in after init\n");
+ ret = AUTHENTICATION_FAILED_ERR;
+ }
+ /* generate a symetric key */
+ key = PK11_TokenKeyGen(slot, type, NULL, 0, &keyid,
+ PR_TRUE, &passwordSuccess);
+
+ if (!key) {
+ PR_fprintf(PR_STDERR, "Could not generated symetric key: %s\n",
+ SECU_Strerror(PORT_GetError()));
+ exit (UNSPECIFIED_ERR);
+ }
+ PK11_FreeSymKey(key);
+ PK11_Logout(slot);
+
+ PK11_Authenticate(slot, PR_TRUE, &passwordSuccess);
+
+ if (*userPassword && !passwordSuccess) {
+ PR_fprintf(PR_STDERR, "New DB Did not initalize\n");
+ ret = AUTHENTICATION_FAILED_ERR;
+ }
+ key = PK11_FindFixedKey(slot, type, &keyid, &passwordSuccess);
+
+ if (!key) {
+ PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
+ SECU_Strerror(PORT_GetError()));
+ ret = UNSPECIFIED_ERR;
+ } else {
+ PK11_FreeSymKey(key);
+ }
+ PK11_FreeSlot(slot);
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
+ SECU_Strerror(PORT_GetError()));
+ exit(1);
+ }
+ }
+
+loser:
+ return ret;
+}
+
diff --git a/nss/cmd/dbtest/manifest.mn b/nss/cmd/dbtest/manifest.mn
new file mode 100644
index 0000000..8f9ec1f
--- /dev/null
+++ b/nss/cmd/dbtest/manifest.mn
@@ -0,0 +1,22 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+# DIRS =
+
+CSRCS = dbtest.c
+
+PROGRAM = dbtest
+
diff --git a/nss/cmd/derdump/Makefile b/nss/cmd/derdump/Makefile
new file mode 100644
index 0000000..c2039d8
--- /dev/null
+++ b/nss/cmd/derdump/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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 ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+include ../platrules.mk
+
diff --git a/nss/cmd/derdump/derdump.c b/nss/cmd/derdump/derdump.c
new file mode 100644
index 0000000..3184b1b
--- /dev/null
+++ b/nss/cmd/derdump/derdump.c
@@ -0,0 +1,105 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secutil.h"
+#include "nss.h"
+#include
+
+#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
+#if !defined(WIN32)
+extern int fprintf(FILE *, char *, ...);
+#endif
+#endif
+#include "plgetopt.h"
+
+static void Usage(char *progName)
+{
+ fprintf(stderr,
+ "Usage: %s [-r] [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s For formatted items, dump raw bytes as well\n",
+ "-r");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+ char *progName;
+ FILE *outFile;
+ PRFileDesc *inFile;
+ SECItem der;
+ SECStatus rv;
+ PRInt16 xp_error;
+ PRBool raw = PR_FALSE;
+ PLOptState *optstate;
+ PLOptStatus status;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ /* Parse command line arguments */
+ inFile = 0;
+ outFile = 0;
+ optstate = PL_CreateOptState(argc, argv, "i:o:r");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'i':
+ inFile = PR_Open(optstate->value, PR_RDONLY, 0);
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'r':
+ raw = PR_TRUE;
+ break;
+
+ default:
+ Usage(progName);
+ break;
+ }
+ }
+ if (status == PL_OPT_BAD)
+ Usage(progName);
+
+ if (!inFile) inFile = PR_STDIN;
+ if (!outFile) outFile = stdout;
+
+ rv = NSS_NoDB_Init(NULL); /* XXX */
+ if (rv != SECSuccess) {
+ SECU_PrintPRandOSError(progName);
+ return -1;
+ }
+
+ rv = SECU_ReadDERFromFile(&der, inFile, PR_FALSE, PR_FALSE);
+ if (rv == SECSuccess) {
+ rv = DER_PrettyPrint(outFile, &der, raw);
+ if (rv == SECSuccess)
+ return 0;
+ }
+
+ xp_error = PORT_GetError();
+ if (xp_error) {
+ SECU_PrintError(progName, "error %d", xp_error);
+ }
+ if (errno) {
+ SECU_PrintSystemError(progName, "errno=%d", errno);
+ }
+ return 1;
+}
diff --git a/nss/cmd/derdump/manifest.mn b/nss/cmd/derdump/manifest.mn
new file mode 100644
index 0000000..0b55037
--- /dev/null
+++ b/nss/cmd/derdump/manifest.mn
@@ -0,0 +1,21 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = derdump.c
+
+PROGRAM = derdump
diff --git a/nss/cmd/digest/Makefile b/nss/cmd/digest/Makefile
new file mode 100644
index 0000000..c2039d8
--- /dev/null
+++ b/nss/cmd/digest/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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 ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+
+include ../platrules.mk
+
diff --git a/nss/cmd/digest/digest.c b/nss/cmd/digest/digest.c
new file mode 100644
index 0000000..4502fc3
--- /dev/null
+++ b/nss/cmd/digest/digest.c
@@ -0,0 +1,224 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secutil.h"
+#include "pk11func.h"
+#include "secoid.h"
+
+#if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
+#if !defined(WIN32)
+extern int fread(char *, size_t, size_t, FILE*);
+extern int fwrite(char *, size_t, size_t, FILE*);
+extern int fprintf(FILE *, char *, ...);
+#endif
+#endif
+
+#include "plgetopt.h"
+
+static SECOidData *
+HashTypeToOID(HASH_HashType hashtype)
+{
+ SECOidTag hashtag;
+
+ if (hashtype <= HASH_AlgNULL || hashtype >= HASH_AlgTOTAL)
+ return NULL;
+
+ switch (hashtype) {
+ case HASH_AlgMD2:
+ hashtag = SEC_OID_MD2;
+ break;
+ case HASH_AlgMD5:
+ hashtag = SEC_OID_MD5;
+ break;
+ case HASH_AlgSHA1:
+ hashtag = SEC_OID_SHA1;
+ break;
+ default:
+ fprintf(stderr, "A new hash type has been added to HASH_HashType.\n");
+ fprintf(stderr, "This program needs to be updated!\n");
+ return NULL;
+ }
+
+ return SECOID_FindOIDByTag(hashtag);
+}
+
+static SECOidData *
+HashNameToOID(const char *hashName)
+{
+ HASH_HashType htype;
+ SECOidData *hashOID;
+
+ for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) {
+ hashOID = HashTypeToOID(htype);
+ if (PORT_Strcasecmp(hashName, hashOID->desc) == 0)
+ break;
+ }
+
+ if (htype == HASH_AlgTOTAL)
+ return NULL;
+
+ return hashOID;
+}
+
+static void
+Usage(char *progName)
+{
+ HASH_HashType htype;
+
+ fprintf(stderr,
+ "Usage: %s -t type [-i input] [-o output]\n",
+ progName);
+ fprintf(stderr, "%-20s Specify the digest method (must be one of\n",
+ "-t type");
+ fprintf(stderr, "%-20s ", "");
+ for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) {
+ fprintf(stderr, "%s", HashTypeToOID(htype)->desc);
+ if (htype == (HASH_AlgTOTAL - 2))
+ fprintf(stderr, " or ");
+ else if (htype != (HASH_AlgTOTAL - 1))
+ fprintf(stderr, ", ");
+ }
+ fprintf(stderr, " (case ignored))\n");
+ fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
+ "-i input");
+ fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
+ "-o output");
+ exit(-1);
+}
+
+static int
+DigestFile(FILE *outFile, FILE *inFile, SECOidData *hashOID)
+{
+ int nb;
+ unsigned char ibuf[4096], digest[32];
+ PK11Context *hashcx;
+ unsigned int len;
+ SECStatus rv;
+
+ hashcx = PK11_CreateDigestContext(hashOID->offset);
+ if (hashcx == NULL) {
+ return -1;
+ }
+ PK11_DigestBegin(hashcx);
+
+
+ for (;;) {
+ if (feof(inFile)) break;
+ nb = fread(ibuf, 1, sizeof(ibuf), inFile);
+ if (nb != sizeof(ibuf)) {
+ if (nb == 0) {
+ if (ferror(inFile)) {
+ PORT_SetError(SEC_ERROR_IO);
+ PK11_DestroyContext(hashcx,PR_TRUE);
+ return -1;
+ }
+ /* eof */
+ break;
+ }
+ }
+ rv = PK11_DigestOp(hashcx, ibuf, nb);
+ if (rv != SECSuccess) {
+ PK11_DestroyContext(hashcx, PR_TRUE);
+ return -1;
+ }
+ }
+
+ rv = PK11_DigestFinal(hashcx, digest, &len, 32);
+ PK11_DestroyContext(hashcx, PR_TRUE);
+
+ if (rv != SECSuccess) return -1;
+
+ nb = fwrite(digest, 1, len, outFile);
+ if (nb != len) {
+ PORT_SetError(SEC_ERROR_IO);
+ return -1;
+ }
+
+ return 0;
+}
+
+#include "nss.h"
+
+int
+main(int argc, char **argv)
+{
+ char *progName;
+ FILE *inFile, *outFile;
+ char *hashName;
+ SECOidData *hashOID;
+ PLOptState *optstate;
+ PLOptStatus status;
+ SECStatus rv;
+
+ progName = strrchr(argv[0], '/');
+ progName = progName ? progName+1 : argv[0];
+
+ inFile = NULL;
+ outFile = NULL;
+ hashName = NULL;
+
+ rv = NSS_Init("/tmp");
+ if (rv != SECSuccess) {
+ fprintf(stderr, "%s: NSS_Init failed in directory %s\n",
+ progName, "/tmp");
+ return -1;
+ }
+
+ /*
+ * Parse command line arguments
+ */
+ optstate = PL_CreateOptState(argc, argv, "t:i:o:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+ Usage(progName);
+ break;
+
+ case 'i':
+ inFile = fopen(optstate->value, "r");
+ if (!inFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 'o':
+ outFile = fopen(optstate->value, "w");
+ if (!outFile) {
+ fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
+ progName, optstate->value);
+ return -1;
+ }
+ break;
+
+ case 't':
+ hashName = strdup(optstate->value);
+ break;
+ }
+ }
+
+ if (!hashName) Usage(progName);
+
+ if (!inFile) inFile = stdin;
+ if (!outFile) outFile = stdout;
+
+ hashOID = HashNameToOID(hashName);
+ if (hashOID == NULL) {
+ fprintf(stderr, "%s: invalid digest type\n", progName);
+ Usage(progName);
+ }
+
+ if (DigestFile(outFile, inFile, hashOID)) {
+ fprintf(stderr, "%s: problem digesting data (%s)\n",
+ progName, SECU_Strerror(PORT_GetError()));
+ return -1;
+ }
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/nss/cmd/digest/manifest.mn b/nss/cmd/digest/manifest.mn
new file mode 100644
index 0000000..3e76406
--- /dev/null
+++ b/nss/cmd/digest/manifest.mn
@@ -0,0 +1,22 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+DEFINES = -DNSPR20
+
+CSRCS = digest.c
+
+PROGRAM = digest
+
diff --git a/nss/cmd/ecperf/Makefile b/nss/cmd/ecperf/Makefile
new file mode 100644
index 0000000..7b74b36
--- /dev/null
+++ b/nss/cmd/ecperf/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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 ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/nss/cmd/ecperf/ecperf.c b/nss/cmd/ecperf/ecperf.c
new file mode 100644
index 0000000..513d4ee
--- /dev/null
+++ b/nss/cmd/ecperf/ecperf.c
@@ -0,0 +1,726 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "blapi.h"
+#include "ec.h"
+#include "ecl-curve.h"
+#include "nss.h"
+#include "secutil.h"
+#include "pkcs11.h"
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#define __PASTE(x,y) x##y
+
+/*
+ * Get the NSS specific PKCS #11 function names.
+ */
+#undef CK_PKCS11_FUNCTION_INFO
+#undef CK_NEED_ARG_LIST
+
+#define CK_EXTERN extern
+#define CK_PKCS11_FUNCTION_INFO(func) \
+ CK_RV __PASTE(NS,func)
+#define CK_NEED_ARG_LIST 1
+
+#include "pkcs11f.h"
+
+
+
+/* mapping between ECCurveName enum and pointers to ECCurveParams */
+static SECOidTag ecCurve_oid_map[] = {
+ SEC_OID_UNKNOWN, /* ECCurve_noName */
+ SEC_OID_ANSIX962_EC_PRIME192V1, /* ECCurve_NIST_P192 */
+ SEC_OID_SECG_EC_SECP224R1, /* ECCurve_NIST_P224 */
+ SEC_OID_ANSIX962_EC_PRIME256V1, /* ECCurve_NIST_P256 */
+ SEC_OID_SECG_EC_SECP384R1, /* ECCurve_NIST_P384 */
+ SEC_OID_SECG_EC_SECP521R1, /* ECCurve_NIST_P521 */
+ SEC_OID_SECG_EC_SECT163K1, /* ECCurve_NIST_K163 */
+ SEC_OID_SECG_EC_SECT163R1, /* ECCurve_NIST_B163 */
+ SEC_OID_SECG_EC_SECT233K1, /* ECCurve_NIST_K233 */
+ SEC_OID_SECG_EC_SECT233R1, /* ECCurve_NIST_B233 */
+ SEC_OID_SECG_EC_SECT283K1, /* ECCurve_NIST_K283 */
+ SEC_OID_SECG_EC_SECT283R1, /* ECCurve_NIST_B283 */
+ SEC_OID_SECG_EC_SECT409K1, /* ECCurve_NIST_K409 */
+ SEC_OID_SECG_EC_SECT409R1, /* ECCurve_NIST_B409 */
+ SEC_OID_SECG_EC_SECT571K1, /* ECCurve_NIST_K571 */
+ SEC_OID_SECG_EC_SECT571R1, /* ECCurve_NIST_B571 */
+ SEC_OID_ANSIX962_EC_PRIME192V2,
+ SEC_OID_ANSIX962_EC_PRIME192V3,
+ SEC_OID_ANSIX962_EC_PRIME239V1,
+ SEC_OID_ANSIX962_EC_PRIME239V2,
+ SEC_OID_ANSIX962_EC_PRIME239V3,
+ SEC_OID_ANSIX962_EC_C2PNB163V1,
+ SEC_OID_ANSIX962_EC_C2PNB163V2,
+ SEC_OID_ANSIX962_EC_C2PNB163V3,
+ SEC_OID_ANSIX962_EC_C2PNB176V1,
+ SEC_OID_ANSIX962_EC_C2TNB191V1,
+ SEC_OID_ANSIX962_EC_C2TNB191V2,
+ SEC_OID_ANSIX962_EC_C2TNB191V3,
+ SEC_OID_ANSIX962_EC_C2PNB208W1,
+ SEC_OID_ANSIX962_EC_C2TNB239V1,
+ SEC_OID_ANSIX962_EC_C2TNB239V2,
+ SEC_OID_ANSIX962_EC_C2TNB239V3,
+ SEC_OID_ANSIX962_EC_C2PNB272W1,
+ SEC_OID_ANSIX962_EC_C2PNB304W1,
+ SEC_OID_ANSIX962_EC_C2TNB359V1,
+ SEC_OID_ANSIX962_EC_C2PNB368W1,
+ SEC_OID_ANSIX962_EC_C2TNB431R1,
+ SEC_OID_SECG_EC_SECP112R1,
+ SEC_OID_SECG_EC_SECP112R2,
+ SEC_OID_SECG_EC_SECP128R1,
+ SEC_OID_SECG_EC_SECP128R2,
+ SEC_OID_SECG_EC_SECP160K1,
+ SEC_OID_SECG_EC_SECP160R1,
+ SEC_OID_SECG_EC_SECP160R2,
+ SEC_OID_SECG_EC_SECP192K1,
+ SEC_OID_SECG_EC_SECP224K1,
+ SEC_OID_SECG_EC_SECP256K1,
+ SEC_OID_SECG_EC_SECT113R1,
+ SEC_OID_SECG_EC_SECT113R2,
+ SEC_OID_SECG_EC_SECT131R1,
+ SEC_OID_SECG_EC_SECT131R2,
+ SEC_OID_SECG_EC_SECT163R1,
+ SEC_OID_SECG_EC_SECT193R1,
+ SEC_OID_SECG_EC_SECT193R2,
+ SEC_OID_SECG_EC_SECT239K1,
+ SEC_OID_UNKNOWN /* ECCurve_pastLastCurve */
+};
+
+typedef SECStatus (*op_func) (void *, void *, void *);
+typedef SECStatus (*pk11_op_func) (CK_SESSION_HANDLE, void *, void *, void *);
+
+typedef struct ThreadDataStr {
+ op_func op;
+ void *p1;
+ void *p2;
+ void *p3;
+ int iters;
+ PRLock *lock;
+ int count;
+ SECStatus status;
+ int isSign;
+} ThreadData;
+
+void PKCS11Thread(void *data)
+{
+ ThreadData *threadData = (ThreadData *)data;
+ pk11_op_func op = (pk11_op_func) threadData->op;
+ int iters = threadData->iters;
+ unsigned char sigData [256];
+ SECItem sig;
+ CK_SESSION_HANDLE session;
+ CK_RV crv;
+
+ threadData->status = SECSuccess;
+ threadData->count = 0;
+
+ /* get our thread's session */
+ PR_Lock(threadData->lock);
+ crv = NSC_OpenSession(1, CKF_SERIAL_SESSION, NULL, 0, &session);
+ PR_Unlock(threadData->lock);
+
+ if (threadData->isSign) {
+ sig.data = sigData;
+ sig.len = sizeof(sigData);
+ threadData->p2 = (void *)&sig;
+ }
+
+ while (iters --) {
+ threadData->status = (*op)(session, threadData->p1,
+ threadData->p2, threadData->p3);
+ if (threadData->status != SECSuccess) {
+ break;
+ }
+ threadData->count++;
+ }
+ return;
+}
+
+void genericThread(void *data)
+{
+ ThreadData *threadData = (ThreadData *)data;
+ int iters = threadData->iters;
+ unsigned char sigData [256];
+ SECItem sig;
+
+ threadData->status = SECSuccess;
+ threadData->count = 0;
+
+ if (threadData->isSign) {
+ sig.data = sigData;
+ sig.len = sizeof(sigData);
+ threadData->p2 = (void *)&sig;
+ }
+
+ while (iters --) {
+ threadData->status = (*threadData->op)(threadData->p1,
+ threadData->p2, threadData->p3);
+ if (threadData->status != SECSuccess) {
+ break;
+ }
+ threadData->count++;
+ }
+ return;
+}
+
+
+/* Time iter repetitions of operation op. */
+SECStatus
+M_TimeOperation(void (*threadFunc)(void *),
+ op_func opfunc, char *op, void *param1, void *param2,
+ void *param3, int iters, int numThreads, PRLock *lock,
+ CK_SESSION_HANDLE session, int isSign, double *rate)
+{
+ double dUserTime;
+ int i, total;
+ PRIntervalTime startTime, totalTime;
+ PRThread **threadIDs;
+ ThreadData *threadData;
+ pk11_op_func pk11_op = (pk11_op_func) opfunc;
+ SECStatus rv;
+
+ /* verify operation works before testing performance */
+ if (session) {
+ rv = (*pk11_op)(session, param1, param2, param3);
+ } else {
+ rv = (*opfunc)(param1, param2, param3);
+ }
+ if (rv != SECSuccess) {
+ SECU_PrintError("Error:", op);
+ return rv;
+ }
+
+ /* get Data structures */
+ threadIDs = (PRThread **)PORT_Alloc(numThreads*sizeof(PRThread *));
+ threadData = (ThreadData *)PORT_Alloc(numThreads*sizeof(ThreadData));
+
+ startTime = PR_Now();
+ if (numThreads == 1) {
+ for (i=0; i < iters; i++) {
+ if (session) {
+ rv = (*pk11_op)(session, param1, param2, param3);
+ } else {
+ rv = (*opfunc)(param1, param2, param3);
+ }
+ }
+ total = iters;
+ } else {
+ for (i = 0; i < numThreads; i++) {
+ threadData[i].op = opfunc;
+ threadData[i].p1 = (void *)param1;
+ threadData[i].p2 = (void *)param2;
+ threadData[i].p3 = (void *)param3;
+ threadData[i].iters = iters;
+ threadData[i].lock = lock;
+ threadData[i].isSign = isSign;
+ threadIDs[i] = PR_CreateThread(PR_USER_THREAD, threadFunc,
+ (void *)&threadData[i], PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+ }
+
+ total = 0;
+ for (i = 0; i < numThreads; i++) {
+ PR_JoinThread(threadIDs[i]);
+ /* check the status */
+ total += threadData[i].count;
+ }
+
+ PORT_Free(threadIDs);
+ PORT_Free(threadData);
+ }
+
+ totalTime = PR_Now()- startTime;
+ /* SecondsToInterval seems to be broken here ... */
+ dUserTime = (double)totalTime/(double)1000000;
+ if (dUserTime) {
+ printf(" %-15s count:%4d sec: %3.2f op/sec: %6.2f\n",
+ op, total, dUserTime, (double)total/dUserTime);
+ if (rate) {
+ *rate = ((double)total)/dUserTime;
+ }
+ }
+ return SECSuccess;
+}
+
+#define GFP_POPULATE(params,name_v) \
+ params.name = name_v; \
+ if ((params.name < ECCurve_noName) || \
+ (params.name > ECCurve_pastLastCurve)) goto cleanup; \
+ params.type = ec_params_named; \
+ params.curveOID.data = NULL; \
+ params.curveOID.len = 0; \
+ params.curve.seed.data = NULL; \
+ params.curve.seed.len = 0; \
+ params.DEREncoding.data = NULL; \
+ params.DEREncoding.len = 0; \
+ params.arena = NULL; \
+ params.fieldID.size = ecCurve_map[name_v]->size; \
+ params.fieldID.type = ec_field_GFp; \
+ hexString2SECItem(params.arena, ¶ms.fieldID.u.prime, \
+ ecCurve_map[name_v]->irr); \
+ hexString2SECItem(params.arena, ¶ms.curve.a, \
+ ecCurve_map[name_v]->curvea); \
+ hexString2SECItem(params.arena, ¶ms.curve.b, \
+ ecCurve_map[name_v]->curveb); \
+ genenc[0] = '0'; \
+ genenc[1] = '4'; \
+ genenc[2] = '\0'; \
+ strcat(genenc, ecCurve_map[name_v]->genx); \
+ strcat(genenc, ecCurve_map[name_v]->geny); \
+ hexString2SECItem(params.arena, ¶ms.base, \
+ genenc); \
+ hexString2SECItem(params.arena, ¶ms.order, \
+ ecCurve_map[name_v]->order); \
+ params.cofactor = ecCurve_map[name_v]->cofactor;
+
+
+/* Test curve using specific field arithmetic. */
+#define ECTEST_NAMED_GFP(name_c, name_v) \
+ if (usefreebl) { \
+ printf("Testing %s using freebl implementation...\n", name_c); \
+ rv = ectest_curve_freebl(name_v, iterations, numThreads); \
+ if (rv != SECSuccess) goto cleanup; \
+ printf("... okay.\n"); \
+ } \
+ if (usepkcs11) { \
+ printf("Testing %s using pkcs11 implementation...\n", name_c); \
+ rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \
+ if (rv != SECSuccess) goto cleanup; \
+ printf("... okay.\n"); \
+ }
+
+/*
+ * Initializes a SECItem from a hexadecimal string
+ *
+ * Warning: This function ignores leading 00's, so any leading 00's
+ * in the hexadecimal string must be optional.
+ */
+static SECItem *
+hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
+{
+ int i = 0;
+ int byteval = 0;
+ int tmp = PORT_Strlen(str);
+
+ if ((tmp % 2) != 0) return NULL;
+
+ /* skip leading 00's unless the hex string is "00" */
+ while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
+ str += 2;
+ tmp -= 2;
+ }
+
+ item->data = (unsigned char *) PORT_Alloc( tmp/2);
+ if (item->data == NULL) return NULL;
+ item->len = tmp/2;
+
+ while (str[i]) {
+ if ((str[i] >= '0') && (str[i] <= '9'))
+ tmp = str[i] - '0';
+ else if ((str[i] >= 'a') && (str[i] <= 'f'))
+ tmp = str[i] - 'a' + 10;
+ else if ((str[i] >= 'A') && (str[i] <= 'F'))
+ tmp = str[i] - 'A' + 10;
+ else
+ return NULL;
+
+ byteval = byteval * 16 + tmp;
+ if ((i % 2) != 0) {
+ item->data[i/2] = byteval;
+ byteval = 0;
+ }
+ i++;
+ }
+
+ return item;
+}
+
+#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
+ (x)->pValue=(v); (x)->ulValueLen = (l);
+
+
+SECStatus
+PKCS11_Derive(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey,
+ CK_MECHANISM *pMech , int *dummy)
+{
+ CK_RV crv;
+ CK_OBJECT_HANDLE newKey;
+ CK_BBOOL cktrue = CK_TRUE;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
+ CK_ATTRIBUTE keyTemplate[3];
+ CK_ATTRIBUTE *attrs = keyTemplate;
+
+ PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
+ attrs++;
+ PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
+ attrs++;
+ PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, 1); attrs++;
+
+
+ crv = NSC_DeriveKey(session, pMech, *hKey, keyTemplate, 3, &newKey);
+ if (crv != CKR_OK) {
+ printf("Derive Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+PKCS11_Sign(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey,
+ SECItem *sig, SECItem *digest)
+{
+ CK_RV crv;
+ CK_MECHANISM mech;
+
+ mech.mechanism = CKM_ECDSA;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ crv = NSC_SignInit(session, &mech, *hKey);
+ if (crv != CKR_OK) {
+ printf("Sign Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+ crv = NSC_Sign(session, digest->data, digest->len, sig->data,
+ (CK_ULONG_PTR)&sig->len);
+ if (crv != CKR_OK) {
+ printf("Sign Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+PKCS11_Verify(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey,
+ SECItem *sig, SECItem *digest)
+{
+ CK_RV crv;
+ CK_MECHANISM mech;
+
+ mech.mechanism = CKM_ECDSA;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ crv = NSC_VerifyInit(session, &mech, *hKey);
+ if (crv != CKR_OK) {
+ printf("Verify Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+ crv = NSC_Verify(session, digest->data, digest->len, sig->data, sig->len);
+ if (crv != CKR_OK) {
+ printf("Verify Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+ecName2params(ECCurveName curve, SECKEYECParams * params)
+{
+ SECOidData *oidData = NULL;
+
+ if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve) ||
+ ((oidData = SECOID_FindOIDByTag(ecCurve_oid_map[curve])) == NULL)) {
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+ return SECFailure;
+ }
+
+ SECITEM_AllocItem(NULL, params, (2 + oidData->oid.len));
+ /*
+ * params->data needs to contain the ASN encoding of an object ID (OID)
+ * representing the named curve. The actual OID is in
+ * oidData->oid.data so we simply prepend 0x06 and OID length
+ */
+ params->data[0] = SEC_ASN1_OBJECT_ID;
+ params->data[1] = oidData->oid.len;
+ memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
+
+ return SECSuccess;
+}
+
+
+
+/* Performs basic tests of elliptic curve cryptography over prime fields.
+ * If tests fail, then it prints an error message, aborts, and returns an
+ * error code. Otherwise, returns 0. */
+SECStatus
+ectest_curve_pkcs11(ECCurveName curve, int iterations, int numThreads)
+{
+ CK_OBJECT_HANDLE ecPriv;
+ CK_OBJECT_HANDLE ecPub;
+ CK_SESSION_HANDLE session;
+ SECItem sig;
+ SECItem digest;
+ SECKEYECParams ecParams;
+ CK_MECHANISM mech;
+ CK_ECDH1_DERIVE_PARAMS ecdh_params;
+ unsigned char sigData [256];
+ unsigned char digestData[20];
+ unsigned char pubKeyData[256];
+ PRLock *lock = NULL;
+ double signRate, deriveRate;
+ CK_ATTRIBUTE template;
+ SECStatus rv;
+ CK_RV crv;
+
+ ecParams.data = NULL;
+ ecParams.len = 0;
+ rv = ecName2params(curve, &ecParams);
+ if (rv != SECSuccess) {
+ goto cleanup;
+ }
+
+ crv = NSC_OpenSession(1, CKF_SERIAL_SESSION, NULL, 0, &session);
+ if (crv != CKR_OK) {
+ printf("OpenSession Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+
+ PORT_Memset(digestData, 0xa5, sizeof(digestData));
+ digest.data = digestData;
+ digest.len = sizeof(digestData);
+ sig.data = sigData;
+ sig.len = sizeof(sigData);
+
+ template.type = CKA_EC_PARAMS;
+ template.pValue = ecParams.data;
+ template.ulValueLen = ecParams.len;
+ mech.mechanism = CKM_EC_KEY_PAIR_GEN;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+ crv = NSC_GenerateKeyPair(session, &mech,
+ &template, 1, NULL, 0, &ecPub, &ecPriv);
+ if (crv != CKR_OK) {
+ printf("GenerateKeyPair Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+
+ template.type = CKA_EC_POINT;
+ template.pValue = pubKeyData;
+ template.ulValueLen = sizeof(pubKeyData);
+ crv = NSC_GetAttributeValue(session, ecPub, &template, 1);
+ if (crv != CKR_OK) {
+ printf("GenerateKeyPair Failed CK_RV=0x%x\n", (int)crv);
+ return SECFailure;
+ }
+
+ ecdh_params.kdf = CKD_NULL;
+ ecdh_params.ulSharedDataLen = 0;
+ ecdh_params.pSharedData = NULL;
+ ecdh_params.ulPublicDataLen = template.ulValueLen;
+ ecdh_params.pPublicData = template.pValue;
+
+ mech.mechanism = CKM_ECDH1_DERIVE;
+ mech.pParameter = (void *)&ecdh_params;
+ mech.ulParameterLen = sizeof(ecdh_params);
+
+ lock = PR_NewLock();
+
+ rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Derive, "ECDH_Derive",
+ &ecPriv, &mech, NULL, iterations, numThreads,
+ lock, session, 0, &deriveRate);
+ if (rv != SECSuccess) goto cleanup;
+ rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Sign, "ECDSA_Sign",
+ (void *)&ecPriv, &sig, &digest, iterations, numThreads,
+ lock, session, 1, &signRate);
+ if (rv != SECSuccess) goto cleanup;
+ printf(" ECDHE max rate = %.2f\n", (deriveRate+signRate)/4.0);
+ /* get a signature */
+ rv = PKCS11_Sign(session, &ecPriv, &sig, &digest);
+ if (rv != SECSuccess) goto cleanup;
+ rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Verify, "ECDSA_Verify",
+ (void *)&ecPub, &sig, &digest, iterations, numThreads,
+ lock, session, 0, NULL);
+ if (rv != SECSuccess) goto cleanup;
+
+cleanup:
+ if (lock) {
+ PR_DestroyLock(lock);
+ }
+ return rv;
+}
+
+SECStatus
+ECDH_DeriveWrap(ECPrivateKey *priv, ECPublicKey *pub, int *dummy)
+{
+ SECItem secret;
+ unsigned char secretData[256];
+ SECStatus rv;
+
+ secret.data = secretData;
+ secret.len = sizeof(secretData);
+
+ rv = ECDH_Derive(&pub->publicValue, &pub->ecParams,
+ &priv->privateValue, 0, &secret);
+#ifdef notdef
+ if (rv == SECSuccess) {
+ PORT_Free(secret.data);
+ }
+#endif
+ return rv;
+}
+
+/* Performs basic tests of elliptic curve cryptography over prime fields.
+ * If tests fail, then it prints an error message, aborts, and returns an
+ * error code. Otherwise, returns 0. */
+SECStatus
+ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads)
+{
+ ECParams ecParams;
+ ECPrivateKey *ecPriv = NULL;
+ ECPublicKey ecPub;
+ SECItem sig;
+ SECItem digest;
+ unsigned char sigData [256];
+ unsigned char digestData[20];
+ double signRate, deriveRate;
+ char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
+ SECStatus rv;
+
+
+ GFP_POPULATE(ecParams, curve);
+
+ PORT_Memset(digestData, 0xa5, sizeof(digestData));
+ digest.data = digestData;
+ digest.len = sizeof(digestData);
+ sig.data = sigData;
+ sig.len = sizeof(sigData);
+
+ rv = EC_NewKey(&ecParams, &ecPriv);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ ecPub.ecParams = ecParams;
+ ecPub.publicValue = ecPriv->publicValue;
+
+ M_TimeOperation(genericThread, (op_func) ECDH_DeriveWrap, "ECDH_Derive",
+ ecPriv, &ecPub, NULL, iterations, numThreads, 0, 0, 0, &deriveRate);
+ if (rv != SECSuccess) goto cleanup;
+ M_TimeOperation(genericThread, (op_func) ECDSA_SignDigest, "ECDSA_Sign",
+ ecPriv, &sig, &digest, iterations, numThreads, 0, 0, 1, &signRate);
+ if (rv != SECSuccess) goto cleanup;
+ printf(" ECDHE max rate = %.2f\n", (deriveRate+signRate)/4.0);
+ rv = ECDSA_SignDigest(ecPriv, &sig, &digest);
+ if (rv != SECSuccess) goto cleanup;
+ M_TimeOperation(genericThread, (op_func) ECDSA_VerifyDigest, "ECDSA_Verify",
+ &ecPub, &sig, &digest, iterations, numThreads, 0, 0, 0, NULL);
+ if (rv != SECSuccess) goto cleanup;
+
+cleanup:
+ return rv;
+}
+
+/* Prints help information. */
+void
+printUsage(char *prog)
+{
+ printf("Usage: %s [-i iterations] [-t threads ] [-ans] [-fp] [-A]\n",prog);
+}
+
+/* Performs tests of elliptic curve cryptography over prime fields If
+ * tests fail, then it prints an error message, aborts, and returns an
+ * error code. Otherwise, returns 0. */
+int
+main(int argv, char **argc)
+{
+ int ansi = 0;
+ int nist = 0;
+ int secp = 0;
+ int usefreebl = 0;
+ int usepkcs11 = 0;
+ int i;
+ SECStatus rv = SECSuccess;
+ int iterations = 100;
+ int numThreads = 1;
+
+ /* read command-line arguments */
+ for (i = 1; i < argv; i++) {
+ if (strcasecmp(argc[i], "-i") == 0) {
+ i++;
+ iterations = atoi(argc[i]);
+ } else if (strcasecmp(argc[i], "-t") == 0) {
+ i++;
+ numThreads = atoi(argc[i]);
+ } else if (strcasecmp(argc[i], "-A") == 0) {
+ ansi = nist = secp = 1;
+ usepkcs11 = usefreebl = 1;
+ } else if (strcasecmp(argc[i], "-a") == 0) {
+ ansi = 1;
+ } else if (strcasecmp(argc[i], "-n") == 0) {
+ nist = 1;
+ } else if (strcasecmp(argc[i], "-s") == 0) {
+ secp = 1;
+ } else if (strcasecmp(argc[i], "-p") == 0) {
+ usepkcs11 = 1;
+ } else if (strcasecmp(argc[i], "-f") == 0) {
+ usefreebl = 1;
+ } else {
+ printUsage(argc[0]);
+ return 0;
+ }
+ }
+
+ if ((ansi | nist | secp) == 0) {
+ nist = 1;
+ }
+ if ((usepkcs11|usefreebl) == 0) {
+ usefreebl = 1;
+ }
+
+ rv = NSS_NoDB_Init(NULL);
+ if (rv != SECSuccess) {
+ SECU_PrintError("Error:", "NSS_NoDB_Init");
+ goto cleanup;
+ }
+
+ /* specific arithmetic tests */
+ if (nist) {
+ ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
+ ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192);
+ ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224);
+ ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
+ ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
+ ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
+ }
+ if (ansi) {
+ ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1);
+ ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2);
+ ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3);
+ ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1);
+ ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2);
+ ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3);
+ ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1);
+ }
+ if (secp) {
+ ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1);
+ ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2);
+ ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1);
+ ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2);
+ ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
+ ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
+ ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2);
+ ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1);
+ ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1);
+ ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1);
+ ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1);
+ ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1);
+ ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1);
+ ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1);
+ ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1);
+ }
+
+ cleanup:
+ if (rv != SECSuccess) {
+ printf("Error: exiting with error value\n");
+ }
+ return rv;
+}
diff --git a/nss/cmd/ecperf/manifest.mn b/nss/cmd/ecperf/manifest.mn
new file mode 100755
index 0000000..61fa880
--- /dev/null
+++ b/nss/cmd/ecperf/manifest.mn
@@ -0,0 +1,24 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH = ../..
+CORE_DEPTH = ../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken
+
+# This next line is used by .mk files
+# and gets translated into $LINCS in manifest.mnw
+REQUIRES = dbm seccmd
+
+# DIRS =
+
+CSRCS = ecperf.c
+
+PROGRAM = ecperf
+
+USE_STATIC_LIBS = 1
diff --git a/nss/cmd/fipstest/Makefile b/nss/cmd/fipstest/Makefile
new file mode 100755
index 0000000..2cf5c05
--- /dev/null
+++ b/nss/cmd/fipstest/Makefile
@@ -0,0 +1,49 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+#MKPROG = purify -cache-dir=/u/mcgreer/pcache -best-effort \
+# -always-use-cache-dir $(CC)
+
+#######################################################################
+# (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 ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/nss/cmd/fipstest/aes.sh b/nss/cmd/fipstest/aes.sh
new file mode 100644
index 0000000..ae5dd56
--- /dev/null
+++ b/nss/cmd/fipstest/aes.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# A Bourne shell script for running the NIST AES Algorithm Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+cbc_kat_requests="
+CBCGFSbox128.req
+CBCGFSbox192.req
+CBCGFSbox256.req
+CBCKeySbox128.req
+CBCKeySbox192.req
+CBCKeySbox256.req
+CBCVarKey128.req
+CBCVarKey192.req
+CBCVarKey256.req
+CBCVarTxt128.req
+CBCVarTxt192.req
+CBCVarTxt256.req
+"
+
+cbc_mct_requests="
+CBCMCT128.req
+CBCMCT192.req
+CBCMCT256.req
+"
+
+cbc_mmt_requests="
+CBCMMT128.req
+CBCMMT192.req
+CBCMMT256.req
+"
+
+ecb_kat_requests="
+ECBGFSbox128.req
+ECBGFSbox192.req
+ECBGFSbox256.req
+ECBKeySbox128.req
+ECBKeySbox192.req
+ECBKeySbox256.req
+ECBVarKey128.req
+ECBVarKey192.req
+ECBVarKey256.req
+ECBVarTxt128.req
+ECBVarTxt192.req
+ECBVarTxt256.req
+"
+
+ecb_mct_requests="
+ECBMCT128.req
+ECBMCT192.req
+ECBMCT256.req
+"
+
+ecb_mmt_requests="
+ECBMMT128.req
+ECBMMT192.req
+ECBMMT256.req
+"
+
+for request in $ecb_kat_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes kat ecb $request > $response
+done
+for request in $ecb_mmt_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes mmt ecb $request > $response
+done
+for request in $ecb_mct_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes mct ecb $request > $response
+done
+for request in $cbc_kat_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes kat cbc $request > $response
+done
+for request in $cbc_mmt_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes mmt cbc $request > $response
+done
+for request in $cbc_mct_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest aes mct cbc $request > $response
+done
diff --git a/nss/cmd/fipstest/dsa.sh b/nss/cmd/fipstest/dsa.sh
new file mode 100755
index 0000000..54a6ded
--- /dev/null
+++ b/nss/cmd/fipstest/dsa.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# A Bourne shell script for running the NIST DSA Validation System
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+request=KeyPair.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest dsa keypair $request > $response
+
+request=PQGGen.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest dsa pqggen $request > $response
+
+request=PQGVer.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest dsa pqgver $request > $response
+
+request=SigGen.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest dsa siggen $request > $response
+
+request=SigVer.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest dsa sigver $request > $response
diff --git a/nss/cmd/fipstest/ecdsa.sh b/nss/cmd/fipstest/ecdsa.sh
new file mode 100644
index 0000000..3d4f323
--- /dev/null
+++ b/nss/cmd/fipstest/ecdsa.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# A Bourne shell script for running the NIST ECDSA Validation System
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+request=KeyPair.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest ecdsa keypair $request > $response
+
+request=PKV.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest ecdsa pkv $request > $response
+
+request=SigGen.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest ecdsa siggen $request > $response
+
+request=SigVer.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest ecdsa sigver $request > $response
diff --git a/nss/cmd/fipstest/fipstest.c b/nss/cmd/fipstest/fipstest.c
new file mode 100644
index 0000000..cdd6b1a
--- /dev/null
+++ b/nss/cmd/fipstest/fipstest.c
@@ -0,0 +1,5370 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include
+#include
+#include
+
+#include "secitem.h"
+#include "blapi.h"
+#include "nssutil.h"
+#include "secerr.h"
+#include "secder.h"
+#include "secdig.h"
+#include "secoid.h"
+#include "ec.h"
+#include "hasht.h"
+#include "lowkeyi.h"
+#include "softoken.h"
+
+#if 0
+#include "../../lib/freebl/mpi/mpi.h"
+#endif
+
+#ifndef NSS_DISABLE_ECC
+extern SECStatus
+EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams);
+extern SECStatus
+EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
+ const ECParams *srcParams);
+#endif
+
+#define ENCRYPT 1
+#define DECRYPT 0
+#define BYTE unsigned char
+#define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001
+#define RSA_MAX_TEST_MODULUS_BITS 4096
+#define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS/8
+#define RSA_MAX_TEST_EXPONENT_BYTES 8
+#define PQG_TEST_SEED_BYTES 20
+
+SECStatus
+hex_to_byteval(const char *c2, unsigned char *byteval)
+{
+ int i;
+ unsigned char offset;
+ *byteval = 0;
+ for (i=0; i<2; i++) {
+ if (c2[i] >= '0' && c2[i] <= '9') {
+ offset = c2[i] - '0';
+ *byteval |= offset << 4*(1-i);
+ } else if (c2[i] >= 'a' && c2[i] <= 'f') {
+ offset = c2[i] - 'a';
+ *byteval |= (offset + 10) << 4*(1-i);
+ } else if (c2[i] >= 'A' && c2[i] <= 'F') {
+ offset = c2[i] - 'A';
+ *byteval |= (offset + 10) << 4*(1-i);
+ } else {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+}
+
+SECStatus
+byteval_to_hex(unsigned char byteval, char *c2, char a)
+{
+ int i;
+ unsigned char offset;
+ for (i=0; i<2; i++) {
+ offset = (byteval >> 4*(1-i)) & 0x0f;
+ if (offset < 10) {
+ c2[i] = '0' + offset;
+ } else {
+ c2[i] = a + offset - 10;
+ }
+ }
+ return SECSuccess;
+}
+
+void
+to_hex_str(char *str, const unsigned char *buf, unsigned int len)
+{
+ unsigned int i;
+ for (i=0; i 2*len) {
+ /*
+ * The input hex string is too long, but we allow it if the
+ * extra digits are leading 0's.
+ */
+ for (j = 0; j < nxdigit-2*len; j++) {
+ if (str[j] != '0') {
+ return PR_FALSE;
+ }
+ }
+ /* skip leading 0's */
+ str += nxdigit-2*len;
+ nxdigit = 2*len;
+ }
+ for (i=0, j=0; i< len; i++) {
+ if (2*i < 2*len-nxdigit) {
+ /* Handle a short input as if we padded it with leading 0's. */
+ if (2*i+1 < 2*len-nxdigit) {
+ buf[i] = 0;
+ } else {
+ char tmp[2];
+ tmp[0] = '0';
+ tmp[1] = str[j];
+ hex_to_byteval(tmp, &buf[i]);
+ j++;
+ }
+ } else {
+ hex_to_byteval(&str[j], &buf[i]);
+ j += 2;
+ }
+ }
+ return PR_TRUE;
+}
+
+SECStatus
+tdea_encrypt_buf(
+ int mode,
+ const unsigned char *key,
+ const unsigned char *iv,
+ unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
+ const unsigned char *input, unsigned int inputlen)
+{
+ SECStatus rv = SECFailure;
+ DESContext *cx;
+ unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
+ unsigned int doublechecklen = 0;
+
+ cx = DES_CreateContext(key, iv, mode, PR_TRUE);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (*outputlen != inputlen) {
+ goto loser;
+ }
+ DES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+
+ /*
+ * Doublecheck our result by decrypting the ciphertext and
+ * compare the output with the input plaintext.
+ */
+ cx = DES_CreateContext(key, iv, mode, PR_FALSE);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
+ output, *outputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (doublechecklen != *outputlen) {
+ goto loser;
+ }
+ DES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+ if (memcmp(doublecheck, input, inputlen) != 0) {
+ goto loser;
+ }
+ rv = SECSuccess;
+
+loser:
+ if (cx != NULL) {
+ DES_DestroyContext(cx, PR_TRUE);
+ }
+ return rv;
+}
+
+SECStatus
+tdea_decrypt_buf(
+ int mode,
+ const unsigned char *key,
+ const unsigned char *iv,
+ unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
+ const unsigned char *input, unsigned int inputlen)
+{
+ SECStatus rv = SECFailure;
+ DESContext *cx;
+ unsigned char doublecheck[8*20]; /* 1 to 20 blocks */
+ unsigned int doublechecklen = 0;
+
+ cx = DES_CreateContext(key, iv, mode, PR_FALSE);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = DES_Decrypt(cx, output, outputlen, maxoutputlen,
+ input, inputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (*outputlen != inputlen) {
+ goto loser;
+ }
+ DES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+
+ /*
+ * Doublecheck our result by encrypting the plaintext and
+ * compare the output with the input ciphertext.
+ */
+ cx = DES_CreateContext(key, iv, mode, PR_TRUE);
+ if (cx == NULL) {
+ goto loser;
+ }
+ rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck,
+ output, *outputlen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (doublechecklen != *outputlen) {
+ goto loser;
+ }
+ DES_DestroyContext(cx, PR_TRUE);
+ cx = NULL;
+ if (memcmp(doublecheck, input, inputlen) != 0) {
+ goto loser;
+ }
+ rv = SECSuccess;
+
+loser:
+ if (cx != NULL) {
+ DES_DestroyContext(cx, PR_TRUE);
+ }
+ return rv;
+}
+
+/*
+ * Perform the TDEA Known Answer Test (KAT) or Multi-block Message
+ * Test (MMT) in ECB or CBC mode. The KAT (there are five types)
+ * and MMT have the same structure: given the key and IV (CBC mode
+ * only), encrypt the given plaintext or decrypt the given ciphertext.
+ * So we can handle them the same way.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+tdea_kat_mmt(char *reqfn)
+{
+ char buf[180]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "CIPHERTEXT = <180 hex digits>\n".
+ */
+ FILE *req; /* input stream from the REQUEST file */
+ FILE *resp; /* output stream to the RESPONSE file */
+ int i, j;
+ int mode; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */
+ int crypt = DECRYPT; /* 1 means encrypt, 0 means decrypt */
+ unsigned char key[24]; /* TDEA 3 key bundle */
+ unsigned int numKeys = 0;
+ unsigned char iv[8]; /* for all modes except ECB */
+ unsigned char plaintext[8*20]; /* 1 to 20 blocks */
+ unsigned int plaintextlen;
+ unsigned char ciphertext[8*20]; /* 1 to 20 blocks */
+ unsigned int ciphertextlen;
+ SECStatus rv;
+
+ req = fopen(reqfn, "r");
+ resp = stdout;
+ while (fgets(buf, sizeof buf, req) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, resp);
+ continue;
+ }
+ /* [ENCRYPT] or [DECRYPT] */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
+ crypt = ENCRYPT;
+ } else {
+ crypt = DECRYPT;
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ /* NumKeys */
+ if (strncmp(&buf[0], "NumKeys", 7) == 0) {
+ i = 7;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ numKeys = buf[i];
+ fputs(buf, resp);
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* mode defaults to ECB, if dataset has IV mode will be set CBC */
+ mode = NSS_DES_EDE3;
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ memset(iv, 0, sizeof iv);
+ memset(plaintext, 0, sizeof plaintext);
+ plaintextlen = 0;
+ memset(ciphertext, 0, sizeof ciphertext);
+ ciphertextlen = 0;
+ fputs(buf, resp);
+ continue;
+ }
+ if (numKeys == 0) {
+ if (strncmp(buf, "KEYs", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ key[j+8] = key[j];
+ key[j+16] = key[j];
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ } else {
+ /* KEY1 = ... */
+ if (strncmp(buf, "KEY1", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ /* KEY2 = ... */
+ if (strncmp(buf, "KEY2", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=8; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ /* KEY3 = ... */
+ if (strncmp(buf, "KEY3", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=16; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ }
+
+ /* IV = ... */
+ if (strncmp(buf, "IV", 2) == 0) {
+ mode = NSS_DES_EDE3_CBC;
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j> 4;
+ in ^= in >> 2;
+ in ^= in >> 1;
+ return (BYTE)(out ^ !(in & 1));
+}
+
+/*
+ * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j]
+ * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes.
+ */
+void
+tdea_mct_next_keys(unsigned char *key,
+ const unsigned char *text_2, const unsigned char *text_1,
+ const unsigned char *text, unsigned int numKeys)
+{
+ int k;
+
+ /* key1[i+1] = key1[i] xor PT/CT[j] */
+ for (k=0; k<8; k++) {
+ key[k] ^= text[k];
+ }
+ /* key2 */
+ if (numKeys == 2 || numKeys == 3) {
+ /* key2 independent */
+ for (k=8; k<16; k++) {
+ /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */
+ key[k] ^= text_1[k-8];
+ }
+ } else {
+ /* key2 == key 1 */
+ for (k=8; k<16; k++) {
+ /* key2[i+1] = KEY2[i] xor PT/CT[j] */
+ key[k] = key[k-8];
+ }
+ }
+ /* key3 */
+ if (numKeys == 1 || numKeys == 2) {
+ /* key3 == key 1 */
+ for (k=16; k<24; k++) {
+ /* key3[i+1] = KEY3[i] xor PT/CT[j] */
+ key[k] = key[k-16];
+ }
+ } else {
+ /* key3 independent */
+ for (k=16; k<24; k++) {
+ /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */
+ key[k] ^= text_2[k-16];
+ }
+ }
+ /* set the parity bits */
+ for (k=0; k<24; k++) {
+ key[k] = odd_parity(key[k]);
+ }
+}
+
+/*
+ * Perform the Monte Carlo Test
+ *
+ * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC
+ * crypt = ENCRYPT || DECRYPT
+ * inputtext = plaintext or Cyphertext depending on the value of crypt
+ * inputlength is expected to be size 8 bytes
+ * iv = needs to be set for NSS_DES_EDE3_CBC mode
+ * resp = is the output response file.
+ */
+ void
+tdea_mct_test(int mode, unsigned char* key, unsigned int numKeys,
+ unsigned int crypt, unsigned char* inputtext,
+ unsigned int inputlength, unsigned char* iv, FILE *resp) {
+
+ int i, j;
+ unsigned char outputtext_1[8]; /* PT/CT[j-1] */
+ unsigned char outputtext_2[8]; /* PT/CT[j-2] */
+ char buf[80]; /* holds one line from the input REQUEST file. */
+ unsigned int outputlen;
+ unsigned char outputtext[8];
+
+
+ SECStatus rv;
+
+ if (mode == NSS_DES_EDE3 && iv != NULL) {
+ printf("IV must be NULL for NSS_DES_EDE3 mode");
+ goto loser;
+ } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) {
+ printf("IV must not be NULL for NSS_DES_EDE3_CBC mode");
+ goto loser;
+ }
+
+ /* loop 400 times */
+ for (i=0; i<400; i++) {
+ /* if i == 0 CV[0] = IV not necessary */
+ /* record the count and key values and plainText */
+ sprintf(buf, "COUNT = %d\n", i);
+ fputs(buf, resp);
+ /* Output KEY1[i] */
+ fputs("KEY1 = ", resp);
+ to_hex_str(buf, key, 8);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ /* Output KEY2[i] */
+ fputs("KEY2 = ", resp);
+ to_hex_str(buf, &key[8], 8);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ /* Output KEY3[i] */
+ fputs("KEY3 = ", resp);
+ to_hex_str(buf, &key[16], 8);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ if (mode == NSS_DES_EDE3_CBC) {
+ /* Output CV[i] */
+ fputs("IV = ", resp);
+ to_hex_str(buf, iv, 8);
+ fputs(buf, resp);
+ fputc('\n', resp);
+ }
+ if (crypt == ENCRYPT) {
+ /* Output PT[0] */
+ fputs("PLAINTEXT = ", resp);
+ } else {
+ /* Output CT[0] */
+ fputs("CIPHERTEXT = ", resp);
+ }
+
+ to_hex_str(buf, inputtext, inputlength);
+ fputs(buf, resp);
+ fputc('\n', resp);
+
+ /* loop 10,000 times */
+ for (j=0; j<10000; j++) {
+
+ outputlen = 0;
+ if (crypt == ENCRYPT) {
+ /* inputtext == ciphertext outputtext == plaintext*/
+ rv = tdea_encrypt_buf(mode, key,
+ (mode == NSS_DES_EDE3) ? NULL : iv,
+ outputtext, &outputlen, 8,
+ inputtext, 8);
+ } else {
+ /* inputtext == plaintext outputtext == ciphertext */
+ rv = tdea_decrypt_buf(mode, key,
+ (mode == NSS_DES_EDE3) ? NULL : iv,
+ outputtext, &outputlen, 8,
+ inputtext, 8);
+ }
+
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (outputlen != inputlength) {
+ goto loser;
+ }
+
+ if (mode == NSS_DES_EDE3_CBC) {
+ if (crypt == ENCRYPT) {
+ if (j == 0) {
+ /*P[j+1] = CV[0] */
+ memcpy(inputtext, iv, 8);
+ } else {
+ /* p[j+1] = C[j-1] */
+ memcpy(inputtext, outputtext_1, 8);
+ }
+ /* CV[j+1] = C[j] */
+ memcpy(iv, outputtext, 8);
+ if (j != 9999) {
+ /* save C[j-1] */
+ memcpy(outputtext_1, outputtext, 8);
+ }
+ } else { /* DECRYPT */
+ /* CV[j+1] = C[j] */
+ memcpy(iv, inputtext, 8);
+ /* C[j+1] = P[j] */
+ memcpy(inputtext, outputtext, 8);
+ }
+ } else {
+ /* ECB mode PT/CT[j+1] = CT/PT[j] */
+ memcpy(inputtext, outputtext, 8);
+ }
+
+ /* Save PT/CT[j-2] and PT/CT[j-1] */
+ if (j==9997) memcpy(outputtext_2, outputtext, 8);
+ if (j==9998) memcpy(outputtext_1, outputtext, 8);
+ /* done at the end of the for(j) loop */
+ }
+
+
+ if (crypt == ENCRYPT) {
+ /* Output CT[j] */
+ fputs("CIPHERTEXT = ", resp);
+ } else {
+ /* Output PT[j] */
+ fputs("PLAINTEXT = ", resp);
+ }
+ to_hex_str(buf, outputtext, 8);
+ fputs(buf, resp);
+ fputc('\n', resp);
+
+ /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2]
+ * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j]
+ */
+ tdea_mct_next_keys(key, outputtext_2,
+ outputtext_1, outputtext, numKeys);
+
+ if (mode == NSS_DES_EDE3_CBC) {
+ /* taken care of in the j=9999 iteration */
+ if (crypt == ENCRYPT) {
+ /* P[i] = C[j-1] */
+ /* CV[i] = C[j] */
+ } else {
+ /* taken care of in the j=9999 iteration */
+ /* CV[i] = C[j] */
+ /* C[i] = P[j] */
+ }
+ } else {
+ /* ECB PT/CT[i] = PT/CT[j] */
+ memcpy(inputtext, outputtext, 8);
+ }
+ /* done at the end of the for(i) loop */
+ fputc('\n', resp);
+ }
+
+loser:
+ return;
+}
+
+/*
+ * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes.
+ * by gathering the input from the request file, and then
+ * calling tdea_mct_test.
+ *
+ * reqfn is the pathname of the input REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+tdea_mct(int mode, char *reqfn)
+{
+ int i, j;
+ char buf[80]; /* holds one line from the input REQUEST file. */
+ FILE *req; /* input stream from the REQUEST file */
+ FILE *resp; /* output stream to the RESPONSE file */
+ unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */
+ unsigned char key[24]; /* TDEA 3 key bundle */
+ unsigned int numKeys = 0;
+ unsigned char plaintext[8]; /* PT[j] */
+ unsigned char ciphertext[8]; /* CT[j] */
+ unsigned char iv[8];
+
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ memset(plaintext, 0, sizeof plaintext);
+ memset(ciphertext, 0, sizeof ciphertext);
+ memset(iv, 0, sizeof iv);
+
+ req = fopen(reqfn, "r");
+ resp = stdout;
+ while (fgets(buf, sizeof buf, req) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, resp);
+ continue;
+ }
+ /* [ENCRYPT] or [DECRYPT] */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
+ crypt = ENCRYPT;
+ } else {
+ crypt = DECRYPT;
+ }
+ fputs(buf, resp);
+ continue;
+ }
+ /* NumKeys */
+ if (strncmp(&buf[0], "NumKeys", 7) == 0) {
+ i = 7;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ numKeys = atoi(&buf[i]);
+ continue;
+ }
+ /* KEY1 = ... */
+ if (strncmp(buf, "KEY1", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ continue;
+ }
+ /* KEY2 = ... */
+ if (strncmp(buf, "KEY2", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=8; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ continue;
+ }
+ /* KEY3 = ... */
+ if (strncmp(buf, "KEY3", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=16; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ continue;
+ }
+
+ /* IV = ... */
+ if (strncmp(buf, "IV", 2) == 0) {
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j\n".
+ */
+ FILE *aesreq; /* input stream from the REQUEST file */
+ FILE *aesresp; /* output stream to the RESPONSE file */
+ int i, j;
+ int mode; /* NSS_AES (ECB) or NSS_AES_CBC */
+ int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
+ unsigned char key[32]; /* 128, 192, or 256 bits */
+ unsigned int keysize;
+ unsigned char iv[16]; /* for all modes except ECB */
+ unsigned char plaintext[10*16]; /* 1 to 10 blocks */
+ unsigned int plaintextlen;
+ unsigned char ciphertext[10*16]; /* 1 to 10 blocks */
+ unsigned int ciphertextlen;
+ SECStatus rv;
+
+ aesreq = fopen(reqfn, "r");
+ aesresp = stdout;
+ while (fgets(buf, sizeof buf, aesreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* [ENCRYPT] or [DECRYPT] */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
+ encrypt = 1;
+ } else {
+ encrypt = 0;
+ }
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ mode = NSS_AES;
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ keysize = 0;
+ memset(iv, 0, sizeof iv);
+ memset(plaintext, 0, sizeof plaintext);
+ plaintextlen = 0;
+ memset(ciphertext, 0, sizeof ciphertext);
+ ciphertextlen = 0;
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* KEY = ... */
+ if (strncmp(buf, "KEY", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ keysize = j;
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* IV = ... */
+ if (strncmp(buf, "IV", 2) == 0) {
+ mode = NSS_AES_CBC;
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j\n".
+ */
+ FILE *aesreq; /* input stream from the REQUEST file */
+ FILE *aesresp; /* output stream to the RESPONSE file */
+ int i, j;
+ int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
+ unsigned char key[32]; /* 128, 192, or 256 bits */
+ unsigned int keysize;
+ unsigned char plaintext[16]; /* PT[j] */
+ unsigned char plaintext_1[16]; /* PT[j-1] */
+ unsigned char ciphertext[16]; /* CT[j] */
+ unsigned char ciphertext_1[16]; /* CT[j-1] */
+ unsigned char doublecheck[16];
+ unsigned int outputlen;
+ AESContext *cx = NULL; /* the operation being tested */
+ AESContext *cx2 = NULL; /* the inverse operation done in parallel
+ * to doublecheck our result.
+ */
+ SECStatus rv;
+
+ aesreq = fopen(reqfn, "r");
+ aesresp = stdout;
+ while (fgets(buf, sizeof buf, aesreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* [ENCRYPT] or [DECRYPT] */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
+ encrypt = 1;
+ } else {
+ encrypt = 0;
+ }
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ keysize = 0;
+ memset(plaintext, 0, sizeof plaintext);
+ memset(ciphertext, 0, sizeof ciphertext);
+ continue;
+ }
+ /* KEY = ... */
+ if (strncmp(buf, "KEY", 3) == 0) {
+ /* Key[0] = Key */
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ keysize = j;
+ continue;
+ }
+ /* PLAINTEXT = ... */
+ if (strncmp(buf, "PLAINTEXT", 9) == 0) {
+ /* sanity check */
+ if (!encrypt) {
+ goto loser;
+ }
+ /* PT[0] = PT */
+ i = 9;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j\n".
+ */
+ FILE *aesreq; /* input stream from the REQUEST file */
+ FILE *aesresp; /* output stream to the RESPONSE file */
+ int i, j;
+ int encrypt = 0; /* 1 means encrypt, 0 means decrypt */
+ unsigned char key[32]; /* 128, 192, or 256 bits */
+ unsigned int keysize;
+ unsigned char iv[16];
+ unsigned char plaintext[16]; /* PT[j] */
+ unsigned char plaintext_1[16]; /* PT[j-1] */
+ unsigned char ciphertext[16]; /* CT[j] */
+ unsigned char ciphertext_1[16]; /* CT[j-1] */
+ unsigned char doublecheck[16];
+ unsigned int outputlen;
+ AESContext *cx = NULL; /* the operation being tested */
+ AESContext *cx2 = NULL; /* the inverse operation done in parallel
+ * to doublecheck our result.
+ */
+ SECStatus rv;
+
+ aesreq = fopen(reqfn, "r");
+ aesresp = stdout;
+ while (fgets(buf, sizeof buf, aesreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* [ENCRYPT] or [DECRYPT] */
+ if (buf[0] == '[') {
+ if (strncmp(&buf[1], "ENCRYPT", 7) == 0) {
+ encrypt = 1;
+ } else {
+ encrypt = 0;
+ }
+ fputs(buf, aesresp);
+ continue;
+ }
+ /* "COUNT = x" begins a new data set */
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ memset(key, 0, sizeof key);
+ keysize = 0;
+ memset(iv, 0, sizeof iv);
+ memset(plaintext, 0, sizeof plaintext);
+ memset(ciphertext, 0, sizeof ciphertext);
+ continue;
+ }
+ /* KEY = ... */
+ if (strncmp(buf, "KEY", 3) == 0) {
+ /* Key[0] = Key */
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &key[j]);
+ }
+ keysize = j;
+ continue;
+ }
+ /* IV = ... */
+ if (strncmp(buf, "IV", 2) == 0) {
+ /* IV[0] = IV */
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j=0; j--) {
+ if (last < 0) {
+ last = (hash[i] & (1 << j)) ? 1 : 0;
+ fprintf(out, "%d ", last);
+ count = 1;
+ } else if (hash[i] & (1 << j)) {
+ if (last) {
+ count++;
+ } else {
+ last = 0;
+ fprintf(out, "%d ", count);
+ count = 1;
+ z++;
+ }
+ } else {
+ if (!last) {
+ count++;
+ } else {
+ last = 1;
+ fprintf(out, "%d ", count);
+ count = 1;
+ z++;
+ }
+ }
+ }
+ }
+ fprintf(out, "^\n");
+ fseek(out, start, SEEK_SET);
+ fprintf(out, "%d ", z);
+ fseek(out, 0, SEEK_END);
+}
+
+int get_next_line(FILE *req, char *key, char *val, FILE *rsp)
+{
+ int ignore = 0;
+ char *writeto = key;
+ int w = 0;
+ int c;
+ while ((c = fgetc(req)) != EOF) {
+ if (ignore) {
+ fprintf(rsp, "%c", c);
+ if (c == '\n') return ignore;
+ } else if (c == '\n') {
+ break;
+ } else if (c == '#') {
+ ignore = 1;
+ fprintf(rsp, "%c", c);
+ } else if (c == '=') {
+ writeto[w] = '\0';
+ w = 0;
+ writeto = val;
+ } else if (c == ' ' || c == '[' || c == ']') {
+ continue;
+ } else {
+ writeto[w++] = c;
+ }
+ }
+ writeto[w] = '\0';
+ return (c == EOF) ? -1 : ignore;
+}
+
+#ifndef NSS_DISABLE_ECC
+typedef struct curveNameTagPairStr {
+ char *curveName;
+ SECOidTag curveOidTag;
+} CurveNameTagPair;
+
+#define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
+/* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
+
+static CurveNameTagPair nameTagPair[] =
+{
+ { "sect163k1", SEC_OID_SECG_EC_SECT163K1},
+ { "nistk163", SEC_OID_SECG_EC_SECT163K1},
+ { "sect163r1", SEC_OID_SECG_EC_SECT163R1},
+ { "sect163r2", SEC_OID_SECG_EC_SECT163R2},
+ { "nistb163", SEC_OID_SECG_EC_SECT163R2},
+ { "sect193r1", SEC_OID_SECG_EC_SECT193R1},
+ { "sect193r2", SEC_OID_SECG_EC_SECT193R2},
+ { "sect233k1", SEC_OID_SECG_EC_SECT233K1},
+ { "nistk233", SEC_OID_SECG_EC_SECT233K1},
+ { "sect233r1", SEC_OID_SECG_EC_SECT233R1},
+ { "nistb233", SEC_OID_SECG_EC_SECT233R1},
+ { "sect239k1", SEC_OID_SECG_EC_SECT239K1},
+ { "sect283k1", SEC_OID_SECG_EC_SECT283K1},
+ { "nistk283", SEC_OID_SECG_EC_SECT283K1},
+ { "sect283r1", SEC_OID_SECG_EC_SECT283R1},
+ { "nistb283", SEC_OID_SECG_EC_SECT283R1},
+ { "sect409k1", SEC_OID_SECG_EC_SECT409K1},
+ { "nistk409", SEC_OID_SECG_EC_SECT409K1},
+ { "sect409r1", SEC_OID_SECG_EC_SECT409R1},
+ { "nistb409", SEC_OID_SECG_EC_SECT409R1},
+ { "sect571k1", SEC_OID_SECG_EC_SECT571K1},
+ { "nistk571", SEC_OID_SECG_EC_SECT571K1},
+ { "sect571r1", SEC_OID_SECG_EC_SECT571R1},
+ { "nistb571", SEC_OID_SECG_EC_SECT571R1},
+ { "secp160k1", SEC_OID_SECG_EC_SECP160K1},
+ { "secp160r1", SEC_OID_SECG_EC_SECP160R1},
+ { "secp160r2", SEC_OID_SECG_EC_SECP160R2},
+ { "secp192k1", SEC_OID_SECG_EC_SECP192K1},
+ { "secp192r1", SEC_OID_SECG_EC_SECP192R1},
+ { "nistp192", SEC_OID_SECG_EC_SECP192R1},
+ { "secp224k1", SEC_OID_SECG_EC_SECP224K1},
+ { "secp224r1", SEC_OID_SECG_EC_SECP224R1},
+ { "nistp224", SEC_OID_SECG_EC_SECP224R1},
+ { "secp256k1", SEC_OID_SECG_EC_SECP256K1},
+ { "secp256r1", SEC_OID_SECG_EC_SECP256R1},
+ { "nistp256", SEC_OID_SECG_EC_SECP256R1},
+ { "secp384r1", SEC_OID_SECG_EC_SECP384R1},
+ { "nistp384", SEC_OID_SECG_EC_SECP384R1},
+ { "secp521r1", SEC_OID_SECG_EC_SECP521R1},
+ { "nistp521", SEC_OID_SECG_EC_SECP521R1},
+
+ { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
+ { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
+ { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
+ { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
+ { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
+ { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
+
+ { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
+ { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
+ { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
+ { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
+ { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
+ { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
+ { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
+ { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
+ { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
+ { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
+ { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
+ { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
+ { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
+ { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
+ { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
+ { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
+ { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
+ { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
+ { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
+ { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
+
+ { "secp112r1", SEC_OID_SECG_EC_SECP112R1},
+ { "secp112r2", SEC_OID_SECG_EC_SECP112R2},
+ { "secp128r1", SEC_OID_SECG_EC_SECP128R1},
+ { "secp128r2", SEC_OID_SECG_EC_SECP128R2},
+
+ { "sect113r1", SEC_OID_SECG_EC_SECT113R1},
+ { "sect113r2", SEC_OID_SECG_EC_SECT113R2},
+ { "sect131r1", SEC_OID_SECG_EC_SECT131R1},
+ { "sect131r2", SEC_OID_SECG_EC_SECT131R2},
+};
+
+static SECItem *
+getECParams(const char *curve)
+{
+ SECItem *ecparams;
+ SECOidData *oidData = NULL;
+ SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
+ int i, numCurves;
+
+ if (curve != NULL) {
+ numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
+ for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
+ i++) {
+ if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
+ curveOidTag = nameTagPair[i].curveOidTag;
+ }
+ }
+
+ /* Return NULL if curve name is not recognized */
+ if ((curveOidTag == SEC_OID_UNKNOWN) ||
+ (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
+ fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
+ return NULL;
+ }
+
+ ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
+
+ /*
+ * ecparams->data needs to contain the ASN encoding of an object ID (OID)
+ * representing the named curve. The actual OID is in
+ * oidData->oid.data so we simply prepend 0x06 and OID length
+ */
+ ecparams->data[0] = SEC_ASN1_OBJECT_ID;
+ ecparams->data[1] = oidData->oid.len;
+ memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
+
+ return ecparams;
+}
+
+/*
+ * Perform the ECDSA Key Pair Generation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+ecdsa_keypair_test(char *reqfn)
+{
+ char buf[256]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * needs to be large enough to hold the longest
+ * line "Qx = <144 hex digits>\n".
+ */
+ FILE *ecdsareq; /* input stream from the REQUEST file */
+ FILE *ecdsaresp; /* output stream to the RESPONSE file */
+ char curve[16]; /* "nistxddd" */
+ ECParams *ecparams;
+ int N;
+ int i;
+ unsigned int len;
+
+ ecdsareq = fopen(reqfn, "r");
+ ecdsaresp = stdout;
+ strcpy(curve, "nist");
+ while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* [X-ddd] */
+ if (buf[0] == '[') {
+ const char *src;
+ char *dst;
+ SECItem *encodedparams;
+
+ src = &buf[1];
+ dst = &curve[4];
+ *dst++ = tolower(*src);
+ src += 2; /* skip the hyphen */
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst = '\0';
+ encodedparams = getECParams(curve);
+ if (encodedparams == NULL) {
+ goto loser;
+ }
+ if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
+ goto loser;
+ }
+ SECITEM_FreeItem(encodedparams, PR_TRUE);
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* N = x */
+ if (buf[0] == 'N') {
+ if (sscanf(buf, "N = %d", &N) != 1) {
+ goto loser;
+ }
+ for (i = 0; i < N; i++) {
+ ECPrivateKey *ecpriv;
+
+ if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
+ goto loser;
+ }
+ fputs("d = ", ecdsaresp);
+ to_hex_str(buf, ecpriv->privateValue.data,
+ ecpriv->privateValue.len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+ if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
+ != SECSuccess) {
+ goto loser;
+ }
+ len = ecpriv->publicValue.len;
+ if (len%2 == 0) {
+ goto loser;
+ }
+ len = (len-1)/2;
+ if (ecpriv->publicValue.data[0]
+ != EC_POINT_FORM_UNCOMPRESSED) {
+ goto loser;
+ }
+ fputs("Qx = ", ecdsaresp);
+ to_hex_str(buf, &ecpriv->publicValue.data[1], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+ fputs("Qy = ", ecdsaresp);
+ to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+ fputc('\n', ecdsaresp);
+ PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
+ }
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ continue;
+ }
+ }
+loser:
+ fclose(ecdsareq);
+}
+
+/*
+ * Perform the ECDSA Public Key Validation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+ecdsa_pkv_test(char *reqfn)
+{
+ char buf[256]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "Qx = <144 hex digits>\n".
+ */
+ FILE *ecdsareq; /* input stream from the REQUEST file */
+ FILE *ecdsaresp; /* output stream to the RESPONSE file */
+ char curve[16]; /* "nistxddd" */
+ ECParams *ecparams = NULL;
+ SECItem pubkey;
+ unsigned int i;
+ unsigned int len;
+ PRBool keyvalid = PR_TRUE;
+
+ ecdsareq = fopen(reqfn, "r");
+ ecdsaresp = stdout;
+ strcpy(curve, "nist");
+ pubkey.data = NULL;
+ while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* [X-ddd] */
+ if (buf[0] == '[') {
+ const char *src;
+ char *dst;
+ SECItem *encodedparams;
+
+ src = &buf[1];
+ dst = &curve[4];
+ *dst++ = tolower(*src);
+ src += 2; /* skip the hyphen */
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst = '\0';
+ if (ecparams != NULL) {
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ ecparams = NULL;
+ }
+ encodedparams = getECParams(curve);
+ if (encodedparams == NULL) {
+ goto loser;
+ }
+ if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
+ goto loser;
+ }
+ SECITEM_FreeItem(encodedparams, PR_TRUE);
+ len = (ecparams->fieldID.size + 7) >> 3;
+ if (pubkey.data != NULL) {
+ PORT_Free(pubkey.data);
+ pubkey.data = NULL;
+ }
+ SECITEM_AllocItem(NULL, &pubkey, 2*len+1);
+ if (pubkey.data == NULL) {
+ goto loser;
+ }
+ pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED;
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* Qx = ... */
+ if (strncmp(buf, "Qx", 2) == 0) {
+ fputs(buf, ecdsaresp);
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]);
+ continue;
+ }
+ /* Qy = ... */
+ if (strncmp(buf, "Qy", 2) == 0) {
+ fputs(buf, ecdsaresp);
+ if (!keyvalid) {
+ fputs("Result = F\n", ecdsaresp);
+ continue;
+ }
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ keyvalid = from_hex_str(&pubkey.data[1+len], len, &buf[i]);
+ if (!keyvalid) {
+ fputs("Result = F\n", ecdsaresp);
+ continue;
+ }
+ if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) {
+ fputs("Result = P\n", ecdsaresp);
+ } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
+ fputs("Result = F\n", ecdsaresp);
+ } else {
+ goto loser;
+ }
+ continue;
+ }
+ }
+loser:
+ if (ecparams != NULL) {
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ }
+ if (pubkey.data != NULL) {
+ PORT_Free(pubkey.data);
+ }
+ fclose(ecdsareq);
+}
+
+/*
+ * Perform the ECDSA Signature Generation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+ecdsa_siggen_test(char *reqfn)
+{
+ char buf[1024]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * needs to be large enough to hold the longest
+ * line "Msg = <256 hex digits>\n".
+ */
+ FILE *ecdsareq; /* input stream from the REQUEST file */
+ FILE *ecdsaresp; /* output stream to the RESPONSE file */
+ char curve[16]; /* "nistxddd" */
+ ECParams *ecparams = NULL;
+ int i, j;
+ unsigned int len;
+ unsigned char msg[512]; /* message to be signed (<= 128 bytes) */
+ unsigned int msglen;
+ unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
+ unsigned char sig[2*MAX_ECKEY_LEN];
+ SECItem signature, digest;
+
+ ecdsareq = fopen(reqfn, "r");
+ ecdsaresp = stdout;
+ strcpy(curve, "nist");
+ while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* [X-ddd] */
+ if (buf[0] == '[') {
+ const char *src;
+ char *dst;
+ SECItem *encodedparams;
+
+ src = &buf[1];
+ dst = &curve[4];
+ *dst++ = tolower(*src);
+ src += 2; /* skip the hyphen */
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst = '\0';
+ if (ecparams != NULL) {
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ ecparams = NULL;
+ }
+ encodedparams = getECParams(curve);
+ if (encodedparams == NULL) {
+ goto loser;
+ }
+ if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
+ goto loser;
+ }
+ SECITEM_FreeItem(encodedparams, PR_TRUE);
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ ECPrivateKey *ecpriv;
+
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ msglen = j;
+ if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
+ goto loser;
+ }
+ fputs(buf, ecdsaresp);
+
+ if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) {
+ goto loser;
+ }
+ if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue)
+ != SECSuccess) {
+ goto loser;
+ }
+ len = ecpriv->publicValue.len;
+ if (len%2 == 0) {
+ goto loser;
+ }
+ len = (len-1)/2;
+ if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
+ goto loser;
+ }
+ fputs("Qx = ", ecdsaresp);
+ to_hex_str(buf, &ecpriv->publicValue.data[1], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+ fputs("Qy = ", ecdsaresp);
+ to_hex_str(buf, &ecpriv->publicValue.data[1+len], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+
+ digest.type = siBuffer;
+ digest.data = sha1;
+ digest.len = sizeof sha1;
+ signature.type = siBuffer;
+ signature.data = sig;
+ signature.len = sizeof sig;
+ if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) {
+ goto loser;
+ }
+ len = signature.len;
+ if (len%2 != 0) {
+ goto loser;
+ }
+ len = len/2;
+ fputs("R = ", ecdsaresp);
+ to_hex_str(buf, &signature.data[0], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+ fputs("S = ", ecdsaresp);
+ to_hex_str(buf, &signature.data[len], len);
+ fputs(buf, ecdsaresp);
+ fputc('\n', ecdsaresp);
+
+ PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE);
+ continue;
+ }
+ }
+loser:
+ if (ecparams != NULL) {
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ }
+ fclose(ecdsareq);
+}
+
+/*
+ * Perform the ECDSA Signature Verification Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+ecdsa_sigver_test(char *reqfn)
+{
+ char buf[1024]; /* holds one line from the input REQUEST file.
+ * needs to be large enough to hold the longest
+ * line "Msg = <256 hex digits>\n".
+ */
+ FILE *ecdsareq; /* input stream from the REQUEST file */
+ FILE *ecdsaresp; /* output stream to the RESPONSE file */
+ char curve[16]; /* "nistxddd" */
+ ECPublicKey ecpub;
+ unsigned int i, j;
+ unsigned int flen; /* length in bytes of the field size */
+ unsigned int olen; /* length in bytes of the base point order */
+ unsigned char msg[512]; /* message that was signed (<= 128 bytes) */
+ unsigned int msglen;
+ unsigned char sha1[20]; /* SHA-1 hash (160 bits) */
+ unsigned char sig[2*MAX_ECKEY_LEN];
+ SECItem signature, digest;
+ PRBool keyvalid = PR_TRUE;
+ PRBool sigvalid = PR_TRUE;
+
+ ecdsareq = fopen(reqfn, "r");
+ ecdsaresp = stdout;
+ ecpub.ecParams.arena = NULL;
+ strcpy(curve, "nist");
+ while (fgets(buf, sizeof buf, ecdsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* [X-ddd] */
+ if (buf[0] == '[') {
+ const char *src;
+ char *dst;
+ SECItem *encodedparams;
+ ECParams *ecparams;
+
+ src = &buf[1];
+ dst = &curve[4];
+ *dst++ = tolower(*src);
+ src += 2; /* skip the hyphen */
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst = '\0';
+ encodedparams = getECParams(curve);
+ if (encodedparams == NULL) {
+ goto loser;
+ }
+ if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) {
+ goto loser;
+ }
+ SECITEM_FreeItem(encodedparams, PR_TRUE);
+ if (ecpub.ecParams.arena != NULL) {
+ PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
+ }
+ ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (ecpub.ecParams.arena == NULL) {
+ goto loser;
+ }
+ if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams)
+ != SECSuccess) {
+ goto loser;
+ }
+ PORT_FreeArena(ecparams->arena, PR_FALSE);
+ flen = (ecpub.ecParams.fieldID.size + 7) >> 3;
+ olen = ecpub.ecParams.order.len;
+ if (2*olen > sizeof sig) {
+ goto loser;
+ }
+ ecpub.publicValue.type = siBuffer;
+ ecpub.publicValue.data = NULL;
+ ecpub.publicValue.len = 0;
+ SECITEM_AllocItem(ecpub.ecParams.arena,
+ &ecpub.publicValue, 2*flen+1);
+ if (ecpub.publicValue.data == NULL) {
+ goto loser;
+ }
+ ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED;
+ fputs(buf, ecdsaresp);
+ continue;
+ }
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ msglen = j;
+ if (SHA1_HashBuf(sha1, msg, msglen) != SECSuccess) {
+ goto loser;
+ }
+ fputs(buf, ecdsaresp);
+
+ digest.type = siBuffer;
+ digest.data = sha1;
+ digest.len = sizeof sha1;
+
+ continue;
+ }
+ /* Qx = ... */
+ if (strncmp(buf, "Qx", 2) == 0) {
+ fputs(buf, ecdsaresp);
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen,
+ &buf[i]);
+ continue;
+ }
+ /* Qy = ... */
+ if (strncmp(buf, "Qy", 2) == 0) {
+ fputs(buf, ecdsaresp);
+ if (!keyvalid) {
+ continue;
+ }
+ i = 2;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ keyvalid = from_hex_str(&ecpub.publicValue.data[1+flen], flen,
+ &buf[i]);
+ if (!keyvalid) {
+ continue;
+ }
+ if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue)
+ != SECSuccess) {
+ if (PORT_GetError() == SEC_ERROR_BAD_KEY) {
+ keyvalid = PR_FALSE;
+ } else {
+ goto loser;
+ }
+ }
+ continue;
+ }
+ /* R = ... */
+ if (buf[0] == 'R') {
+ fputs(buf, ecdsaresp);
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ sigvalid = from_hex_str(sig, olen, &buf[i]);
+ continue;
+ }
+ /* S = ... */
+ if (buf[0] == 'S') {
+ fputs(buf, ecdsaresp);
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ if (sigvalid) {
+ sigvalid = from_hex_str(&sig[olen], olen, &buf[i]);
+ }
+ signature.type = siBuffer;
+ signature.data = sig;
+ signature.len = 2*olen;
+
+ if (!keyvalid || !sigvalid) {
+ fputs("Result = F\n", ecdsaresp);
+ } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest)
+ == SECSuccess) {
+ fputs("Result = P\n", ecdsaresp);
+ } else {
+ fputs("Result = F\n", ecdsaresp);
+ }
+ continue;
+ }
+ }
+loser:
+ if (ecpub.ecParams.arena != NULL) {
+ PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE);
+ }
+ fclose(ecdsareq);
+}
+#endif /* NSS_DISABLE_ECC */
+
+
+/*
+ * Read a value from the test and allocate the result.
+ */
+static unsigned char *
+alloc_value(char *buf, int *len)
+{
+ unsigned char * value;
+ int i, count;
+
+ if (strncmp(buf, "", 6) == 0) {
+ *len = 0;
+ return NULL;
+ }
+
+ /* find the length of the number */
+ for (count = 0; isxdigit(buf[count]); count++);
+ *len = count/2;
+
+ if (*len == 0) {
+ return NULL;
+ }
+
+ value = PORT_Alloc(*len);
+ if (!value) {
+ *len = 0;
+ return NULL;
+ }
+
+ for (i=0; i<*len; buf+=2 , i++) {
+ hex_to_byteval(buf, &value[i]);
+ }
+
+
+ return value;
+}
+
+PRBool
+isblankline(char *b)
+{
+ while (isspace(*b)) b++;
+ if ((*b == '\n') || (*b == 0)) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+static int debug = 0;
+
+/*
+ * Perform the Hash_DRBG (CAVS) for the RNG algorithm
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+drbg(char *reqfn)
+{
+ char buf[2000]; /* test case has some very long lines, returned bits
+ * as high as 800 bytes (6400 bits). That 1600 byte
+ * plus a tag */
+ char buf2[2000];
+ FILE *rngreq; /* input stream from the REQUEST file */
+ FILE *rngresp; /* output stream to the RESPONSE file */
+
+ unsigned int i, j;
+ PRBool predictionResistance = PR_FALSE;
+ unsigned char *nonce = NULL;
+ int nonceLen = 0;
+ unsigned char *personalizationString = NULL;
+ int personalizationStringLen = 0;
+ unsigned char *additionalInput = NULL;
+ int additionalInputLen = 0;
+ unsigned char *entropyInput = NULL;
+ int entropyInputLen = 0;
+ unsigned char predictedreturn_bytes[SHA256_LENGTH];
+ unsigned char return_bytes[SHA256_LENGTH];
+ int return_bytes_len = SHA256_LENGTH;
+ enum { NONE, INSTANTIATE, GENERATE, RESEED, RESULT } command =
+ NONE;
+ PRBool genResult = PR_FALSE;
+ SECStatus rv;
+
+ rngreq = fopen(reqfn, "r");
+ rngresp = stdout;
+ while (fgets(buf, sizeof buf, rngreq) != NULL) {
+ switch (command) {
+ case INSTANTIATE:
+ if (debug) {
+ fputs("# PRNGTEST_Instantiate(",rngresp);
+ to_hex_str(buf2,entropyInput, entropyInputLen);
+ fputs(buf2,rngresp);
+ fprintf(rngresp,",%d,",entropyInputLen);
+ to_hex_str(buf2,nonce, nonceLen);
+ fputs(buf2,rngresp);
+ fprintf(rngresp,",%d,",nonceLen);
+ to_hex_str(buf2,personalizationString,
+ personalizationStringLen);
+ fputs(buf2,rngresp);
+ fprintf(rngresp,",%d)\n", personalizationStringLen);
+ }
+ rv = PRNGTEST_Instantiate(entropyInput, entropyInputLen,
+ nonce, nonceLen,
+ personalizationString,
+ personalizationStringLen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ break;
+
+ case GENERATE:
+ case RESULT:
+ memset(return_bytes, 0, return_bytes_len);
+ if (debug) {
+ fputs("# PRNGTEST_Generate(returnbytes",rngresp);
+ fprintf(rngresp,",%d,", return_bytes_len);
+ to_hex_str(buf2,additionalInput, additionalInputLen);
+ fputs(buf2,rngresp);
+ fprintf(rngresp,",%d)\n",additionalInputLen);
+ }
+ rv = PRNGTEST_Generate((PRUint8 *) return_bytes,
+ return_bytes_len,
+ (PRUint8 *) additionalInput,
+ additionalInputLen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ if (command == RESULT) {
+ fputs("ReturnedBits = ", rngresp);
+ to_hex_str(buf2, return_bytes, return_bytes_len);
+ fputs(buf2, rngresp);
+ fputc('\n', rngresp);
+ if (debug) {
+ fputs("# PRNGTEST_Uninstantiate()\n",rngresp);
+ }
+ rv = PRNGTEST_Uninstantiate();
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ } else if (debug) {
+ fputs("#ReturnedBits = ", rngresp);
+ to_hex_str(buf2, return_bytes, return_bytes_len);
+ fputs(buf2, rngresp);
+ fputc('\n', rngresp);
+ }
+
+ memset(additionalInput, 0, additionalInputLen);
+ break;
+
+ case RESEED:
+ if (entropyInput || additionalInput) {
+ if (debug) {
+ fputs("# PRNGTEST_Reseed(",rngresp);
+ fprintf(rngresp,",%d,", return_bytes_len);
+ to_hex_str(buf2,entropyInput, entropyInputLen);
+ fputs(buf2,rngresp);
+ fprintf(rngresp,",%d,", entropyInputLen);
+ to_hex_str(buf2,additionalInput, additionalInputLen);
+ fputs(buf2,rngresp);
+ fprintf(rngresp,",%d)\n",additionalInputLen);
+ }
+ rv = PRNGTEST_Reseed(entropyInput, entropyInputLen,
+ additionalInput, additionalInputLen);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+ memset(entropyInput, 0, entropyInputLen);
+ memset(additionalInput, 0, additionalInputLen);
+ break;
+ case NONE:
+ break;
+
+ }
+ command = NONE;
+
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r' ) {
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ /* [Hash - SHA256] */
+ if (strncmp(buf, "[SHA-256]", 9) == 0) {
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ if (strncmp(buf, "[PredictionResistance", 21) == 0) {
+ i = 21;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ if (strncmp(buf, "False", 5) == 0) {
+ predictionResistance = PR_FALSE;
+ } else {
+ predictionResistance = PR_TRUE;
+ }
+
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ if (strncmp(buf, "[EntropyInputLen", 16) == 0) {
+ if (entropyInput) {
+ PORT_ZFree(entropyInput, entropyInputLen);
+ entropyInput = NULL;
+ entropyInputLen = 0;
+ }
+ if (sscanf(buf, "[EntropyInputLen = %d]", &entropyInputLen) != 1) {
+ goto loser;
+ }
+ entropyInputLen = entropyInputLen/8;
+ if (entropyInputLen > 0) {
+ entropyInput = PORT_Alloc(entropyInputLen);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ if (strncmp(buf, "[NonceLen", 9) == 0) {
+ if (nonce) {
+ PORT_ZFree(nonce, nonceLen);
+ nonce = NULL;
+ nonceLen = 0;
+ }
+
+ if (sscanf(buf, "[NonceLen = %d]", &nonceLen) != 1) {
+ goto loser;
+ }
+ nonceLen = nonceLen/8;
+ if (nonceLen > 0) {
+ nonce = PORT_Alloc(nonceLen);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ if (strncmp(buf, "[PersonalizationStringLen", 16) == 0) {
+ if (personalizationString) {
+ PORT_ZFree(personalizationString, personalizationStringLen);
+ personalizationString = NULL;
+ personalizationStringLen = 0;
+ }
+
+ if (sscanf(buf, "[PersonalizationStringLen = %d]", &personalizationStringLen) != 1) {
+ goto loser;
+ }
+ personalizationStringLen = personalizationStringLen / 8;
+ if (personalizationStringLen > 0) {
+ personalizationString = PORT_Alloc(personalizationStringLen);
+ }
+ fputs(buf, rngresp);
+
+ continue;
+ }
+
+ if (strncmp(buf, "[AdditionalInputLen", 16) == 0) {
+ if (additionalInput) {
+ PORT_ZFree(additionalInput, additionalInputLen);
+ additionalInput = NULL;
+ additionalInputLen = 0;
+ }
+
+ if (sscanf(buf, "[AdditionalInputLen = %d]", &additionalInputLen) != 1) {
+ goto loser;
+ }
+ additionalInputLen = additionalInputLen/8;
+ if (additionalInputLen > 0) {
+ additionalInput = PORT_Alloc(additionalInputLen);
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ if (strncmp(buf, "COUNT", 5) == 0) {
+ /* zeroize the variables for the test with this data set */
+ if (entropyInput) {
+ memset(entropyInput, 0, entropyInputLen);
+ }
+ if (nonce) {
+ memset(nonce, 0, nonceLen);
+ }
+ if (personalizationString) {
+ memset(personalizationString, 0, personalizationStringLen);
+ }
+ if (additionalInput) {
+ memset(additionalInput, 0, additionalInputLen);
+ }
+ genResult = PR_FALSE;
+
+ fputs(buf, rngresp);
+ continue;
+ }
+
+ /* EntropyInputReseed = ... */
+ if (strncmp(buf, "EntropyInputReseed", 18) == 0) {
+ if (entropyInput) {
+ memset(entropyInput, 0, entropyInputLen);
+ i = 18;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+
+ for (j=0; isxdigit(buf[i]); i+=2,j++) { /*j\n".
+ */
+ FILE *rngreq; /* input stream from the REQUEST file */
+ FILE *rngresp; /* output stream to the RESPONSE file */
+ unsigned int i, j;
+ unsigned char Q[DSA1_SUBPRIME_LEN];
+ PRBool hasQ = PR_FALSE;
+ unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */
+ unsigned char XKey[512/8];
+ unsigned char XSeed[512/8];
+ unsigned char GENX[DSA1_SIGNATURE_LEN];
+ unsigned char DSAX[DSA1_SUBPRIME_LEN];
+ SECStatus rv;
+
+ rngreq = fopen(reqfn, "r");
+ rngresp = stdout;
+ while (fgets(buf, sizeof buf, rngreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* [Xchange - SHA1] */
+ if (buf[0] == '[') {
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* Q = ... */
+ if (buf[0] == 'Q') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j 512 || b%8 != 0) {
+ goto loser;
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* XKey = ... */
+ if (strncmp(buf, "XKey", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j\n".
+ */
+ FILE *rngreq; /* input stream from the REQUEST file */
+ FILE *rngresp; /* output stream to the RESPONSE file */
+ unsigned int i, j;
+ unsigned char Q[DSA1_SUBPRIME_LEN];
+ PRBool hasQ = PR_FALSE;
+ unsigned int b; /* 160 <= b <= 512, b is a multiple of 8 */
+ unsigned char XKey[512/8];
+ unsigned char XSeed[512/8];
+ unsigned char GENX[2*SHA1_LENGTH];
+ unsigned char DSAX[DSA1_SUBPRIME_LEN];
+ SECStatus rv;
+
+ rngreq = fopen(reqfn, "r");
+ rngresp = stdout;
+ while (fgets(buf, sizeof buf, rngreq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* [Xchange - SHA1] */
+ if (buf[0] == '[') {
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* Q = ... */
+ if (buf[0] == 'Q') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j 512 || b%8 != 0) {
+ goto loser;
+ }
+ fputs(buf, rngresp);
+ continue;
+ }
+ /* XKey = ... */
+ if (strncmp(buf, "XKey", 4) == 0) {
+ i = 4;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j1024) {
+ fprintf(dsaresp,
+ "DSA key size must be a multiple of 64 between 512 "
+ "and 1024, inclusive");
+ goto loser;
+ }
+
+ /* Generate the parameters P, Q, and G */
+ if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
+ &pqg, &vfy) != SECSuccess) {
+ fprintf(dsaresp,
+ "ERROR: Unable to generate PQG parameters");
+ goto loser;
+ }
+ } else {
+ if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
+ fprintf(dsaresp,
+ "ERROR: Unable to generate PQG parameters");
+ goto loser;
+ }
+ }
+
+ /* output P, Q, and G */
+ to_hex_str(buf, pqg->prime.data, pqg->prime.len);
+ fprintf(dsaresp, "P = %s\n", buf);
+ to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
+ fprintf(dsaresp, "Q = %s\n", buf);
+ to_hex_str(buf, pqg->base.data, pqg->base.len);
+ fprintf(dsaresp, "G = %s\n\n", buf);
+ continue;
+ }
+ /* N = ...*/
+ if (buf[0] == 'N') {
+
+ if (sscanf(buf, "N = %d", &count) != 1) {
+ goto loser;
+ }
+ /* Generate a DSA key, and output the key pair for N times */
+ for (i = 0; i < count; i++) {
+ DSAPrivateKey *dsakey = NULL;
+ if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
+ fprintf(dsaresp, "ERROR: Unable to generate DSA key");
+ goto loser;
+ }
+ to_hex_str(buf, dsakey->privateValue.data,
+ dsakey->privateValue.len);
+ fprintf(dsaresp, "X = %s\n", buf);
+ to_hex_str(buf, dsakey->publicValue.data,
+ dsakey->publicValue.len);
+ fprintf(dsaresp, "Y = %s\n\n", buf);
+ PORT_FreeArena(dsakey->params.arena, PR_TRUE);
+ dsakey = NULL;
+ }
+ continue;
+ }
+
+ }
+loser:
+ fclose(dsareq);
+}
+
+/*
+ * pqg generation type
+ */
+typedef enum {
+ FIPS186_1,/* Generate/Verify P,Q & G according to FIPS 186-1 */
+ A_1_1_2, /* Generate Probable P & Q */
+ A_1_1_3, /* Verify Probable P & Q */
+ A_1_2_2, /* Verify Provable P & Q */
+ A_2_1, /* Generate Unverifiable G */
+ A_2_2, /* Assure Unverifiable G */
+ A_2_3, /* Generate Verifiable G */
+ A_2_4 /* Verify Verifiable G */
+} dsa_pqg_type;
+
+/*
+ * Perform the DSA Domain Parameter Validation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+dsa_pqgver_test(char *reqfn)
+{
+ char buf[800]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * 800 to hold (384 public key (x2 for HEX) + P = ...
+ */
+ FILE *dsareq; /* input stream from the REQUEST file */
+ FILE *dsaresp; /* output stream to the RESPONSE file */
+ int N;
+ int L;
+ unsigned int i, j;
+ PQGParams pqg;
+ PQGVerify vfy;
+ unsigned int pghSize; /* size for p, g, and h */
+ dsa_pqg_type type = FIPS186_1;
+
+ dsareq = fopen(reqfn, "r");
+ dsaresp = stdout;
+ memset(&pqg, 0, sizeof(pqg));
+ memset(&vfy, 0, sizeof(vfy));
+
+ while (fgets(buf, sizeof buf, dsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [A.xxxxx ] */
+ if (buf[0] == '[' && buf[1] == 'A') {
+
+ if (strncmp(&buf[1],"A.1.1.3",7) == 0) {
+ type = A_1_1_3;
+ } else if (strncmp(&buf[1],"A.2.2",5) == 0) {
+ type = A_2_2;
+ } else if (strncmp(&buf[1],"A.2.4",5) == 0) {
+ type = A_2_4;
+ } else if (strncmp(&buf[1],"A.1.2.2",7) == 0) {
+ type = A_1_2_2;
+ /* validate our output from PQGGEN */
+ } else if (strncmp(&buf[1],"A.1.1.2",7) == 0) {
+ type = A_2_4; /* validate PQ and G together */
+ } else {
+ fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]);
+ exit(1);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+
+ /* [Mod = x] */
+ if (buf[0] == '[') {
+
+ if (type == FIPS186_1) {
+ N=160;
+ if (sscanf(buf, "[mod = %d]", &L) != 1) {
+ goto loser;
+ }
+ } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
+ goto loser;
+ }
+
+ if (pqg.prime.data) { /* P */
+ SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
+ }
+ if (pqg.subPrime.data) { /* Q */
+ SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
+ }
+ if (pqg.base.data) { /* G */
+ SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
+ }
+ if (vfy.seed.data) { /* seed */
+ SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
+ }
+ if (vfy.h.data) { /* H */
+ SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
+ }
+
+ fputs(buf, dsaresp);
+
+ /*calculate the size of p, g, and h then allocate items */
+ pghSize = L/8;
+
+ pqg.base.data = vfy.h.data = NULL;
+ vfy.seed.len = pqg.base.len = vfy.h.len = 0;
+ SECITEM_AllocItem(NULL, &pqg.prime, pghSize);
+ SECITEM_AllocItem(NULL, &vfy.seed, pghSize*3);
+ if (type == A_2_2) {
+ SECITEM_AllocItem(NULL, &vfy.h, pghSize);
+ vfy.h.len = pghSize;
+ } else if (type == A_2_4) {
+ SECITEM_AllocItem(NULL, &vfy.h, 1);
+ vfy.h.len = 1;
+ }
+ pqg.prime.len = pghSize;
+ /* q is always N bits */
+ SECITEM_AllocItem(NULL, &pqg.subPrime, N/8);
+ pqg.subPrime.len = N/8;
+ vfy.counter = -1;
+
+ continue;
+ }
+ /* P = ... */
+ if (buf[0] == 'P') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j< pqg.prime.len; i+=2,j++) {
+ hex_to_byteval(&buf[i], &pqg.prime.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* Q = ... */
+ if (buf[0] == 'Q') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j< pqg.subPrime.len; i+=2,j++) {
+ hex_to_byteval(&buf[i], &pqg.subPrime.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* G = ... */
+ if (buf[0] == 'G') {
+ i = 1;
+ if (pqg.base.data) {
+ SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
+ }
+ SECITEM_AllocItem(NULL, &pqg.base, pghSize);
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j< pqg.base.len; i+=2,j++) {
+ hex_to_byteval(&buf[i], &pqg.base.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* Seed = ... or domain_parameter_seed = ... */
+ if (strncmp(buf, "Seed", 4) == 0) {
+ i = 4;
+ } else if (strncmp(buf, "domain_parameter_seed", 21) == 0) {
+ i = 21;
+ } else if (strncmp(buf,"firstseed",9) == 0) {
+ i = 9;
+ } else {
+ i = 0;
+ }
+ if (i) {
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &vfy.seed.data[j]);
+ }
+ vfy.seed.len = j;
+
+ fputs(buf, dsaresp);
+ if (type == A_2_4) {
+ SECStatus result;
+
+ /* Verify the Parameters */
+ SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (result == SECSuccess) {
+ fprintf(dsaresp, "Result = P\n");
+ } else {
+ fprintf(dsaresp, "Result = F\n");
+ }
+ }
+ continue;
+ }
+ if ((strncmp(buf,"pseed",5) == 0) ||
+ (strncmp(buf,"qseed",5) == 0))
+ {
+ i = 5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=vfy.seed.len; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &vfy.seed.data[j]);
+ }
+ vfy.seed.len = j;
+ fputs(buf, dsaresp);
+
+ continue;
+ }
+ if (strncmp(buf, "index", 4) == 0) {
+ i=5;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ hex_to_byteval(&buf[i], &vfy.h.data[0]);
+ vfy.h.len = 1;
+ fputs(buf, dsaresp);
+ }
+
+ /* c = ... or counter=*/
+ if (buf[0] == 'c') {
+ if (strncmp(buf,"counter", 7) == 0) {
+ if (sscanf(buf, "counter = %u", &vfy.counter) != 1) {
+ goto loser;
+ }
+ } else {
+ if (sscanf(buf, "c = %u", &vfy.counter) != 1) {
+ goto loser;
+ }
+ }
+
+ fputs(buf, dsaresp);
+ if (type == A_1_1_3) {
+ SECStatus result;
+ /* only verify P and Q, we have everything now. do it */
+ SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (result == SECSuccess) {
+ fprintf(dsaresp, "Result = P\n");
+ } else {
+ fprintf(dsaresp, "Result = F\n");
+ }
+ fprintf(dsaresp, "\n");
+ }
+ continue;
+ }
+ if (strncmp(buf,"pgen_counter", 12) == 0) {
+ if (sscanf(buf, "pgen_counter = %u", &vfy.counter) != 1) {
+ goto loser;
+ }
+ fputs(buf, dsaresp);
+ continue;
+ }
+ if (strncmp(buf,"qgen_counter", 12) == 0) {
+ fputs(buf, dsaresp);
+ if (type == A_1_2_2) {
+ SECStatus result;
+ /* only verify P and Q, we have everything now. do it */
+ SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (result == SECSuccess) {
+ fprintf(dsaresp, "Result = P\n");
+ } else {
+ fprintf(dsaresp, "Result = F\n");
+ }
+ fprintf(dsaresp, "\n");
+ }
+ continue;
+ }
+ /* H = ... */
+ if (buf[0] == 'H') {
+ SECStatus rv, result = SECFailure;
+
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &vfy.h.data[j]);
+ }
+ vfy.h.len = j;
+ fputs(buf, dsaresp);
+
+ /* this should be a byte value. Remove the leading zeros. If
+ * it doesn't reduce to a byte, PQG_VerifyParams will catch it
+ if (type == A_2_2) {
+ data_save = vfy.h.data;
+ while(vfy.h.data[0] && (vfy.h.len > 1)) {
+ vfy.h.data++;
+ vfy.h.len--;
+ }
+ } */
+
+ /* Verify the Parameters */
+ rv = PQG_VerifyParams(&pqg, &vfy, &result);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (result == SECSuccess) {
+ fprintf(dsaresp, "Result = P\n");
+ } else {
+ fprintf(dsaresp, "Result = F\n");
+ }
+ fprintf(dsaresp, "\n");
+ continue;
+ }
+ }
+loser:
+ fclose(dsareq);
+ if (pqg.prime.data) { /* P */
+ SECITEM_ZfreeItem(&pqg.prime, PR_FALSE);
+ }
+ if (pqg.subPrime.data) { /* Q */
+ SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE);
+ }
+ if (pqg.base.data) { /* G */
+ SECITEM_ZfreeItem(&pqg.base, PR_FALSE);
+ }
+ if (vfy.seed.data) { /* seed */
+ SECITEM_ZfreeItem(&vfy.seed, PR_FALSE);
+ }
+ if (vfy.h.data) { /* H */
+ SECITEM_ZfreeItem(&vfy.h, PR_FALSE);
+ }
+
+}
+
+/*
+ * Perform the DSA Public Key Validation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+dsa_pqggen_test(char *reqfn)
+{
+ char buf[800]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * 800 to hold seed = (384 public key (x2 for HEX)
+ */
+ FILE *dsareq; /* input stream from the REQUEST file */
+ FILE *dsaresp; /* output stream to the RESPONSE file */
+ int count; /* number of times to generate parameters */
+ int N;
+ int L;
+ int i;
+ unsigned int j;
+ PQGParams *pqg = NULL;
+ PQGVerify *vfy = NULL;
+ unsigned int keySizeIndex;
+ dsa_pqg_type type = FIPS186_1;
+
+ dsareq = fopen(reqfn, "r");
+ dsaresp = stdout;
+ while (fgets(buf, sizeof buf, dsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [A.xxxxx ] */
+ if (buf[0] == '[' && buf[1] == 'A') {
+ if (strncmp(&buf[1],"A.1.1.2",7) == 0) {
+ type = A_1_1_2;
+ } else if (strncmp(&buf[1],"A.2.1",5) == 0) {
+ fprintf(stderr, "NSS only Generates G with P&Q\n");
+ exit(1);
+ } else if (strncmp(&buf[1],"A.2.3",5) == 0) {
+ fprintf(stderr, "NSS only Generates G with P&Q\n");
+ exit(1);
+ } else if (strncmp(&buf[1],"A.1.2.1",7) == 0) {
+ fprintf(stderr, "NSS does not support Shawe-Taylor Primes\n");
+ exit(1);
+ } else {
+ fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]);
+ exit(1);
+ }
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [Mod = ... ] */
+ if (buf[0] == '[') {
+
+ if (type == FIPS186_1) {
+ N=160;
+ if (sscanf(buf, "[mod = %d]", &L) != 1) {
+ goto loser;
+ }
+ } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) {
+ goto loser;
+ }
+
+ fputs(buf, dsaresp);
+ fputc('\n', dsaresp);
+
+ if (type == FIPS186_1) {
+ /************************************************************
+ * PQG_ParamGenSeedLen doesn't take a key size, it takes an
+ * index that points to a valid key size.
+ */
+ keySizeIndex = PQG_PBITS_TO_INDEX(L);
+ if(keySizeIndex == -1 || L<512 || L>1024) {
+ fprintf(dsaresp,
+ "DSA key size must be a multiple of 64 between 512 "
+ "and 1024, inclusive");
+ goto loser;
+ }
+ }
+ continue;
+ }
+ /* N = ... */
+ if (buf[0] == 'N') {
+ if (sscanf(buf, "N = %d", &count) != 1) {
+ goto loser;
+ }
+ for (i = 0; i < count; i++) {
+ SECStatus rv;
+
+ if (type == FIPS186_1) {
+ rv = PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
+ &pqg, &vfy);
+ } else {
+ rv = PQG_ParamGenV2(L, N, N, &pqg, &vfy);
+ }
+ if (rv != SECSuccess) {
+ fprintf(dsaresp,
+ "ERROR: Unable to generate PQG parameters");
+ goto loser;
+ }
+ to_hex_str(buf, pqg->prime.data, pqg->prime.len);
+ fprintf(dsaresp, "P = %s\n", buf);
+ to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
+ fprintf(dsaresp, "Q = %s\n", buf);
+ to_hex_str(buf, pqg->base.data, pqg->base.len);
+ fprintf(dsaresp, "G = %s\n", buf);
+ if (type == FIPS186_1) {
+ to_hex_str(buf, vfy->seed.data, vfy->seed.len);
+ fprintf(dsaresp, "Seed = %s\n", buf);
+ fprintf(dsaresp, "c = %d\n", vfy->counter);
+ to_hex_str(buf, vfy->h.data, vfy->h.len);
+ fputs("H = ", dsaresp);
+ for (j=vfy->h.len; j< pqg->prime.len; j++) {
+ fprintf(dsaresp, "00");
+ }
+ fprintf(dsaresp, "%s\n", buf);
+ } else {
+ fprintf(dsaresp, "counter = %d\n", vfy->counter);
+ fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]);
+ to_hex_str(buf, vfy->seed.data, vfy->seed.len);
+ fprintf(dsaresp, "domain_parameter_seed = %s\n", buf);
+ }
+ fputc('\n', dsaresp);
+ if(pqg!=NULL) {
+ PQG_DestroyParams(pqg);
+ pqg = NULL;
+ }
+ if(vfy!=NULL) {
+ PQG_DestroyVerify(vfy);
+ vfy = NULL;
+ }
+ }
+
+ continue;
+ }
+
+ }
+loser:
+ fclose(dsareq);
+ if(pqg!=NULL) {
+ PQG_DestroyParams(pqg);
+ }
+ if(vfy!=NULL) {
+ PQG_DestroyVerify(vfy);
+ }
+}
+
+
+/*
+ * Perform the DSA Signature Generation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+dsa_siggen_test(char *reqfn)
+{
+ char buf[800]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * max for Msg = ....
+ */
+ FILE *dsareq; /* input stream from the REQUEST file */
+ FILE *dsaresp; /* output stream to the RESPONSE file */
+ int modulus;
+ int L;
+ int N;
+ int i, j;
+ PRBool use_dsa1 = PR_FALSE;
+ PQGParams *pqg = NULL;
+ PQGVerify *vfy = NULL;
+ DSAPrivateKey *dsakey = NULL;
+ int keySizeIndex; /* index for valid key sizes */
+ unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
+ unsigned char sig[DSA_MAX_SIGNATURE_LEN];
+ SECItem digest, signature;
+ HASH_HashType hashType = HASH_AlgNULL;
+ int hashNum = 0;
+
+ dsareq = fopen(reqfn, "r");
+ dsaresp = stdout;
+
+ while (fgets(buf, sizeof buf, dsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [Mod = x] */
+ if (buf[0] == '[') {
+ if(pqg!=NULL) {
+ PQG_DestroyParams(pqg);
+ pqg = NULL;
+ }
+ if(vfy!=NULL) {
+ PQG_DestroyVerify(vfy);
+ vfy = NULL;
+ }
+ if (dsakey != NULL) {
+ PORT_FreeArena(dsakey->params.arena, PR_TRUE);
+ dsakey = NULL;
+ }
+
+ if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, & N,
+ &hashNum) != 3) {
+ use_dsa1 = PR_TRUE;
+ hashNum = 1;
+ if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
+ goto loser;
+ }
+ }
+ fputs(buf, dsaresp);
+ fputc('\n', dsaresp);
+
+ /****************************************************************
+ * PQG_ParamGenSeedLen doesn't take a key size, it takes an index
+ * that points to a valid key size.
+ */
+ if (use_dsa1) {
+ keySizeIndex = PQG_PBITS_TO_INDEX(modulus);
+ if(keySizeIndex == -1 || modulus<512 || modulus>1024) {
+ fprintf(dsaresp,
+ "DSA key size must be a multiple of 64 between 512 "
+ "and 1024, inclusive");
+ goto loser;
+ }
+ /* Generate PQG and output PQG */
+ if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES,
+ &pqg, &vfy) != SECSuccess) {
+ fprintf(dsaresp,
+ "ERROR: Unable to generate PQG parameters");
+ goto loser;
+ }
+ } else {
+ if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) {
+ fprintf(dsaresp,
+ "ERROR: Unable to generate PQG parameters");
+ goto loser;
+ }
+ }
+ to_hex_str(buf, pqg->prime.data, pqg->prime.len);
+ fprintf(dsaresp, "P = %s\n", buf);
+ to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len);
+ fprintf(dsaresp, "Q = %s\n", buf);
+ to_hex_str(buf, pqg->base.data, pqg->base.len);
+ fprintf(dsaresp, "G = %s\n", buf);
+
+ /* create DSA Key */
+ if (DSA_NewKey(pqg, &dsakey) != SECSuccess) {
+ fprintf(dsaresp, "ERROR: Unable to generate DSA key");
+ goto loser;
+ }
+
+ hashType = sha_get_hashType(hashNum);
+ if (hashType == HASH_AlgNULL) {
+ fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)",hashNum);
+ goto loser;
+ }
+ continue;
+ }
+
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ unsigned char msg[128]; /* MAX msg 128 */
+ unsigned int len = 0;
+
+ if (hashType == HASH_AlgNULL) {
+ fprintf(dsaresp, "ERROR: Hash Alg not set");
+ goto loser;
+ }
+
+ memset(hashBuf, 0, sizeof hashBuf);
+ memset(sig, 0, sizeof sig);
+
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
+ fprintf(dsaresp, "ERROR: Unable to generate SHA% digest",
+ hashNum);
+ goto loser;
+ }
+
+
+ digest.type = siBuffer;
+ digest.data = hashBuf;
+ digest.len = fips_hashLen(hashType);
+ signature.type = siBuffer;
+ signature.data = sig;
+ signature.len = sizeof sig;
+
+ if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) {
+ fprintf(dsaresp, "ERROR: Unable to generate DSA signature");
+ goto loser;
+ }
+ len = signature.len;
+ if (len%2 != 0) {
+ goto loser;
+ }
+ len = len/2;
+
+ /* output the orginal Msg, and generated Y, R, and S */
+ fputs(buf, dsaresp);
+ to_hex_str(buf, dsakey->publicValue.data,
+ dsakey->publicValue.len);
+ fprintf(dsaresp, "Y = %s\n", buf);
+ to_hex_str(buf, &signature.data[0], len);
+ fprintf(dsaresp, "R = %s\n", buf);
+ to_hex_str(buf, &signature.data[len], len);
+ fprintf(dsaresp, "S = %s\n", buf);
+ fputc('\n', dsaresp);
+ continue;
+ }
+
+ }
+loser:
+ fclose(dsareq);
+ if(pqg != NULL) {
+ PQG_DestroyParams(pqg);
+ pqg = NULL;
+ }
+ if(vfy != NULL) {
+ PQG_DestroyVerify(vfy);
+ vfy = NULL;
+ }
+ if (dsakey) {
+ PORT_FreeArena(dsakey->params.arena, PR_TRUE);
+ dsakey = NULL;
+ }
+}
+
+ /*
+ * Perform the DSA Signature Verification Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+dsa_sigver_test(char *reqfn)
+{
+ char buf[800]; /* holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * max for Msg = ....
+ */
+ FILE *dsareq; /* input stream from the REQUEST file */
+ FILE *dsaresp; /* output stream to the RESPONSE file */
+ int L;
+ int N;
+ unsigned int i, j;
+ SECItem digest, signature;
+ DSAPublicKey pubkey;
+ unsigned int pgySize; /* size for p, g, and y */
+ unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */
+ unsigned char sig[DSA_MAX_SIGNATURE_LEN];
+ HASH_HashType hashType = HASH_AlgNULL;
+ int hashNum = 0;
+
+ dsareq = fopen(reqfn, "r");
+ dsaresp = stdout;
+ memset(&pubkey, 0, sizeof(pubkey));
+
+ while (fgets(buf, sizeof buf, dsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* [Mod = x] */
+ if (buf[0] == '[') {
+
+ if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, & N,
+ &hashNum) != 3) {
+ N=160;
+ hashNum = 1;
+ if (sscanf(buf, "[mod = %d]", &L) != 1) {
+ goto loser;
+ }
+ }
+
+ if (pubkey.params.prime.data) { /* P */
+ SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
+ }
+ if (pubkey.params.subPrime.data) { /* Q */
+ SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
+ }
+ if (pubkey.params.base.data) { /* G */
+ SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
+ }
+ if (pubkey.publicValue.data) { /* Y */
+ SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
+ }
+ fputs(buf, dsaresp);
+
+ /* calculate the size of p, g, and y then allocate items */
+ pgySize = L/8;
+ SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize);
+ SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize);
+ SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize);
+ pubkey.params.prime.len = pubkey.params.base.len = pgySize;
+ pubkey.publicValue.len = pgySize;
+
+ /* q always N/8 bytes */
+ SECITEM_AllocItem(NULL, &pubkey.params.subPrime, N/8);
+ pubkey.params.subPrime.len = N/8;
+
+ hashType = sha_get_hashType(hashNum);
+ if (hashType == HASH_AlgNULL) {
+ fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)",hashNum);
+ goto loser;
+ }
+
+ continue;
+ }
+ /* P = ... */
+ if (buf[0] == 'P') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ memset(pubkey.params.prime.data, 0, pubkey.params.prime.len);
+ for (j=0; j< pubkey.params.prime.len; i+=2,j++) {
+ hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* Q = ... */
+ if (buf[0] == 'Q') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len);
+ for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) {
+ hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* G = ... */
+ if (buf[0] == 'G') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ memset(pubkey.params.base.data, 0, pubkey.params.base.len);
+ for (j=0; j< pubkey.params.base.len; i+=2,j++) {
+ hex_to_byteval(&buf[i], &pubkey.params.base.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ unsigned char msg[128]; /* MAX msg 128 */
+ memset(hashBuf, 0, sizeof hashBuf);
+
+ if (hashType == HASH_AlgNULL) {
+ fprintf(dsaresp, "ERROR: Hash Alg not set");
+ goto loser;
+ }
+
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]); i+=2,j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) {
+ fprintf(dsaresp, "ERROR: Unable to generate SHA-%d digest",
+ hashNum);
+ goto loser;
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* Y = ... */
+ if (buf[0] == 'Y') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len);
+ for (j=0; j< pubkey.publicValue.len; i+=2,j++) {
+ hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* R = ... */
+ if (buf[0] == 'R') {
+ memset(sig, 0, sizeof sig);
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; j< pubkey.params.subPrime.len; i+=2,j++) {
+ hex_to_byteval(&buf[i], &sig[j]);
+ }
+
+ fputs(buf, dsaresp);
+ continue;
+ }
+
+ /* S = ... */
+ if (buf[0] == 'S') {
+ if (hashType == HASH_AlgNULL) {
+ fprintf(dsaresp, "ERROR: Hash Alg not set");
+ goto loser;
+ }
+
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=pubkey.params.subPrime.len;
+ j< pubkey.params.subPrime.len*2; i+=2,j++) {
+ hex_to_byteval(&buf[i], &sig[j]);
+ }
+ fputs(buf, dsaresp);
+
+ digest.type = siBuffer;
+ digest.data = hashBuf;
+ digest.len = fips_hashLen(hashType);
+ signature.type = siBuffer;
+ signature.data = sig;
+ signature.len = pubkey.params.subPrime.len*2;
+
+ if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) {
+ fprintf(dsaresp, "Result = P\n");
+ } else {
+ fprintf(dsaresp, "Result = F\n");
+ }
+ fprintf(dsaresp, "\n");
+ continue;
+ }
+ }
+loser:
+ fclose(dsareq);
+ if (pubkey.params.prime.data) { /* P */
+ SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE);
+ }
+ if (pubkey.params.subPrime.data) { /* Q */
+ SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE);
+ }
+ if (pubkey.params.base.data) { /* G */
+ SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE);
+ }
+ if (pubkey.publicValue.data) { /* Y */
+ SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE);
+ }
+}
+
+/*
+ * Perform the RSA Signature Generation Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+rsa_siggen_test(char *reqfn)
+{
+ char buf[2*RSA_MAX_TEST_MODULUS_BYTES+1];
+ /* buf holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * 2x for HEX output + 1 for \n
+ */
+ FILE *rsareq; /* input stream from the REQUEST file */
+ FILE *rsaresp; /* output stream to the RESPONSE file */
+ int i, j;
+ unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
+ unsigned int shaLength = 0; /* length of SHA */
+ HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */
+ SECOidTag shaOid = SEC_OID_UNKNOWN;
+ int modulus; /* the Modulus size */
+ int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT;
+ SECItem pe = {0, 0, 0 };
+ unsigned char pubEx[4];
+ int peCount = 0;
+
+ RSAPrivateKey *rsaBlapiPrivKey = NULL; /* holds RSA private and
+ * public keys */
+ RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */
+
+ rsareq = fopen(reqfn, "r");
+ rsaresp = stdout;
+
+ /* calculate the exponent */
+ for (i=0; i < 4; i++) {
+ if (peCount || (publicExponent &
+ ((unsigned long)0xff000000L >> (i*8)))) {
+ pubEx[peCount] =
+ (unsigned char)((publicExponent >> (3-i)*8) & 0xff);
+ peCount++;
+ }
+ }
+ pe.len = peCount;
+ pe.data = &pubEx[0];
+ pe.type = siBuffer;
+
+ while (fgets(buf, sizeof buf, rsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* [mod = ...] */
+ if (buf[0] == '[') {
+
+ if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
+ goto loser;
+ }
+ if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
+ fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
+ goto loser;
+ }
+
+ fputs(buf, rsaresp);
+
+ if (rsaBlapiPrivKey != NULL) {
+ PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
+ rsaBlapiPrivKey = NULL;
+ rsaBlapiPublicKey = NULL;
+ }
+
+ rsaBlapiPrivKey = RSA_NewKey(modulus, &pe);
+ if (rsaBlapiPrivKey == NULL) {
+ fprintf(rsaresp, "Error unable to create RSA key\n");
+ goto loser;
+ }
+
+ to_hex_str(buf, rsaBlapiPrivKey->modulus.data,
+ rsaBlapiPrivKey->modulus.len);
+ fprintf(rsaresp, "\nn = %s\n\n", buf);
+ to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data,
+ rsaBlapiPrivKey->publicExponent.len);
+ fprintf(rsaresp, "e = %s\n", buf);
+ /* convert private key to public key. Memory
+ * is freed with private key's arena */
+ rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc(
+ rsaBlapiPrivKey->arena,
+ sizeof(RSAPublicKey));
+
+ rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len;
+ rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data;
+ rsaBlapiPublicKey->publicExponent.len =
+ rsaBlapiPrivKey->publicExponent.len;
+ rsaBlapiPublicKey->publicExponent.data =
+ rsaBlapiPrivKey->publicExponent.data;
+ continue;
+ }
+
+ /* SHAAlg = ... */
+ if (strncmp(buf, "SHAAlg", 6) == 0) {
+ i = 6;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ /* set the SHA Algorithm */
+ if (strncmp(&buf[i], "SHA1", 4) == 0) {
+ shaAlg = HASH_AlgSHA1;
+ } else if (strncmp(&buf[i], "SHA224", 6) == 0) {
+ shaAlg = HASH_AlgSHA224;
+ } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
+ shaAlg = HASH_AlgSHA256;
+ } else if (strncmp(&buf[i], "SHA384", 6)== 0) {
+ shaAlg = HASH_AlgSHA384;
+ } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
+ shaAlg = HASH_AlgSHA512;
+ } else {
+ fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
+ goto loser;
+ }
+ fputs(buf, rsaresp);
+ continue;
+
+ }
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+
+ unsigned char msg[128]; /* MAX msg 128 */
+ unsigned int rsa_bytes_signed;
+ unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES];
+ SECStatus rv = SECFailure;
+ NSSLOWKEYPublicKey * rsa_public_key;
+ NSSLOWKEYPrivateKey * rsa_private_key;
+ NSSLOWKEYPrivateKey low_RSA_private_key = { NULL,
+ NSSLOWKEYRSAKey, };
+ NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
+ NSSLOWKEYRSAKey, };
+
+ low_RSA_private_key.u.rsa = *rsaBlapiPrivKey;
+ low_RSA_public_key.u.rsa = *rsaBlapiPublicKey;
+
+ rsa_private_key = &low_RSA_private_key;
+ rsa_public_key = &low_RSA_public_key;
+
+ memset(sha, 0, sizeof sha);
+ memset(msg, 0, sizeof msg);
+ rsa_bytes_signed = 0;
+ memset(rsa_computed_signature, 0, sizeof rsa_computed_signature);
+
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ for (j=0; isxdigit(buf[i]) && j < sizeof(msg); i+=2,j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+ shaLength = fips_hashLen(shaAlg);
+ if (fips_hashBuf(shaAlg,sha,msg,j) != SECSuccess) {
+ if (shaLength == 0) {
+ fprintf(rsaresp, "ERROR: SHAAlg not defined.");
+ }
+ fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
+ shaLength == 160 ? 1 : shaLength);
+ goto loser;
+ }
+ shaOid = fips_hashOid(shaAlg);
+
+ /* Perform RSA signature with the RSA private key. */
+ rv = RSA_HashSign( shaOid,
+ rsa_private_key,
+ rsa_computed_signature,
+ &rsa_bytes_signed,
+ nsslowkey_PrivateModulusLen(rsa_private_key),
+ sha,
+ shaLength);
+
+ if( rv != SECSuccess ) {
+ fprintf(rsaresp, "ERROR: RSA_HashSign failed");
+ goto loser;
+ }
+
+ /* Output the signature */
+ fputs(buf, rsaresp);
+ to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed);
+ fprintf(rsaresp, "S = %s\n", buf);
+
+ /* Perform RSA verification with the RSA public key. */
+ rv = RSA_HashCheckSign( shaOid,
+ rsa_public_key,
+ rsa_computed_signature,
+ rsa_bytes_signed,
+ sha,
+ shaLength);
+ if( rv != SECSuccess ) {
+ fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed");
+ goto loser;
+ }
+ continue;
+ }
+ }
+loser:
+ fclose(rsareq);
+
+ if (rsaBlapiPrivKey != NULL) {
+ /* frees private and public key */
+ PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE);
+ rsaBlapiPrivKey = NULL;
+ rsaBlapiPublicKey = NULL;
+ }
+
+}
+/*
+ * Perform the RSA Signature Verification Test.
+ *
+ * reqfn is the pathname of the REQUEST file.
+ *
+ * The output RESPONSE file is written to stdout.
+ */
+void
+rsa_sigver_test(char *reqfn)
+{
+ char buf[2*RSA_MAX_TEST_MODULUS_BYTES+7];
+ /* buf holds one line from the input REQUEST file
+ * or to the output RESPONSE file.
+ * s = 2x for HEX output + 1 for \n
+ */
+ FILE *rsareq; /* input stream from the REQUEST file */
+ FILE *rsaresp; /* output stream to the RESPONSE file */
+ int i, j;
+ unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */
+ unsigned int shaLength = 0; /* actual length of the digest */
+ HASH_HashType shaAlg = HASH_AlgNULL;
+ SECOidTag shaOid = SEC_OID_UNKNOWN;
+ int modulus = 0; /* the Modulus size */
+ unsigned char signature[513]; /* largest signature size + '\n' */
+ unsigned int signatureLength = 0; /* actual length of the signature */
+ PRBool keyvalid = PR_TRUE;
+
+ RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */
+
+ rsareq = fopen(reqfn, "r");
+ rsaresp = stdout;
+ memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey));
+
+ while (fgets(buf, sizeof buf, rsareq) != NULL) {
+ /* a comment or blank line */
+ if (buf[0] == '#' || buf[0] == '\n') {
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* [Mod = ...] */
+ if (buf[0] == '[') {
+ unsigned int flen; /* length in bytes of the field size */
+
+ if (rsaBlapiPublicKey.modulus.data) { /* n */
+ SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
+ }
+ if (sscanf(buf, "[mod = %d]", &modulus) != 1) {
+ goto loser;
+ }
+
+ if (modulus > RSA_MAX_TEST_MODULUS_BITS) {
+ fprintf(rsaresp,"ERROR: modulus greater than test maximum\n");
+ goto loser;
+ }
+
+ fputs(buf, rsaresp);
+
+ signatureLength = flen = modulus/8;
+
+ SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen);
+ if (rsaBlapiPublicKey.modulus.data == NULL) {
+ goto loser;
+ }
+ continue;
+ }
+
+ /* n = ... modulus */
+ if (buf[0] == 'n') {
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0],
+ rsaBlapiPublicKey.modulus.len,
+ &buf[i]);
+
+ if (!keyvalid) {
+ fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n");
+ goto loser;
+ }
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* SHAAlg = ... */
+ if (strncmp(buf, "SHAAlg", 6) == 0) {
+ i = 6;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ /* set the SHA Algorithm */
+ if (strncmp(&buf[i], "SHA1", 4) == 0) {
+ shaAlg = HASH_AlgSHA1;
+ } else if (strncmp(&buf[i], "SHA224", 6) == 0) {
+ shaAlg = HASH_AlgSHA224;
+ } else if (strncmp(&buf[i], "SHA256", 6) == 0) {
+ shaAlg = HASH_AlgSHA256;
+ } else if (strncmp(&buf[i], "SHA384", 6) == 0) {
+ shaAlg = HASH_AlgSHA384;
+ } else if (strncmp(&buf[i], "SHA512", 6) == 0) {
+ shaAlg = HASH_AlgSHA512;
+ } else {
+ fprintf(rsaresp, "ERROR: Unable to find SHAAlg type");
+ goto loser;
+ }
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* e = ... public Key */
+ if (buf[0] == 'e') {
+ unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES];
+ unsigned char t;
+
+ memset(data, 0, sizeof data);
+
+ if (rsaBlapiPublicKey.publicExponent.data) { /* e */
+ SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
+ }
+
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+ /* skip leading zero's */
+ while (isxdigit(buf[i])) {
+ hex_to_byteval(&buf[i], &t);
+ if (t == 0) {
+ i+=2;
+ } else break;
+ }
+
+ /* get the exponent */
+ for (j=0; isxdigit(buf[i]) && j < sizeof data; i+=2,j++) {
+ hex_to_byteval(&buf[i], &data[j]);
+ }
+
+ if (j == 0) { j = 1; } /* to handle 1 byte length exponents */
+
+ SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j);
+ if (rsaBlapiPublicKey.publicExponent.data == NULL) {
+ goto loser;
+ }
+
+ for (i=0; i < j; i++) {
+ rsaBlapiPublicKey.publicExponent.data[i] = data[i];
+ }
+
+ fputs(buf, rsaresp);
+ continue;
+ }
+
+ /* Msg = ... */
+ if (strncmp(buf, "Msg", 3) == 0) {
+ unsigned char msg[128]; /* MAX msg 128 */
+
+ memset(sha, 0, sizeof sha);
+ memset(msg, 0, sizeof msg);
+
+ i = 3;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+
+ for (j=0; isxdigit(buf[i]) && j < sizeof msg; i+=2,j++) {
+ hex_to_byteval(&buf[i], &msg[j]);
+ }
+
+ shaLength = fips_hashLen(shaAlg);
+ if (fips_hashBuf(shaAlg,sha,msg,j) != SECSuccess) {
+ if (shaLength == 0) {
+ fprintf(rsaresp, "ERROR: SHAAlg not defined.");
+ }
+ fprintf(rsaresp, "ERROR: Unable to generate SHA%x",
+ shaLength == 160 ? 1 : shaLength);
+ goto loser;
+ }
+
+ fputs(buf, rsaresp);
+ continue;
+
+ }
+
+ /* S = ... */
+ if (buf[0] == 'S') {
+ SECStatus rv = SECFailure;
+ NSSLOWKEYPublicKey * rsa_public_key;
+ NSSLOWKEYPublicKey low_RSA_public_key = { NULL,
+ NSSLOWKEYRSAKey, };
+
+ /* convert to a low RSA public key */
+ low_RSA_public_key.u.rsa = rsaBlapiPublicKey;
+ rsa_public_key = &low_RSA_public_key;
+
+ memset(signature, 0, sizeof(signature));
+ i = 1;
+ while (isspace(buf[i]) || buf[i] == '=') {
+ i++;
+ }
+
+ for (j=0; isxdigit(buf[i]) && j < sizeof signature; i+=2,j++) {
+ hex_to_byteval(&buf[i], &signature[j]);
+ }
+
+ signatureLength = j;
+ fputs(buf, rsaresp);
+
+ /* Perform RSA verification with the RSA public key. */
+ rv = RSA_HashCheckSign( shaOid,
+ rsa_public_key,
+ signature,
+ signatureLength,
+ sha,
+ shaLength);
+ if( rv == SECSuccess ) {
+ fputs("Result = P\n", rsaresp);
+ } else {
+ fputs("Result = F\n", rsaresp);
+ }
+ continue;
+ }
+ }
+loser:
+ fclose(rsareq);
+ if (rsaBlapiPublicKey.modulus.data) { /* n */
+ SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE);
+ }
+ if (rsaBlapiPublicKey.publicExponent.data) { /* e */
+ SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 2) exit (-1);
+
+ RNG_RNGInit();
+ SECOID_Init();
+
+ /*************/
+ /* TDEA */
+ /*************/
+ if (strcmp(argv[1], "tdea") == 0) {
+ /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=.req */
+ if (strcmp(argv[2], "kat") == 0) {
+ /* Known Answer Test (KAT) */
+ tdea_kat_mmt(argv[4]);
+ } else if (strcmp(argv[2], "mmt") == 0) {
+ /* Multi-block Message Test (MMT) */
+ tdea_kat_mmt(argv[4]);
+ } else if (strcmp(argv[2], "mct") == 0) {
+ /* Monte Carlo Test (MCT) */
+ if (strcmp(argv[3], "ecb") == 0) {
+ /* ECB mode */
+ tdea_mct(NSS_DES_EDE3, argv[4]);
+ } else if (strcmp(argv[3], "cbc") == 0) {
+ /* CBC mode */
+ tdea_mct(NSS_DES_EDE3_CBC, argv[4]);
+ }
+ }
+ /*************/
+ /* AES */
+ /*************/
+ } else if (strcmp(argv[1], "aes") == 0) {
+ /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=.req */
+ if ( strcmp(argv[2], "kat") == 0) {
+ /* Known Answer Test (KAT) */
+ aes_kat_mmt(argv[4]);
+ } else if (strcmp(argv[2], "mmt") == 0) {
+ /* Multi-block Message Test (MMT) */
+ aes_kat_mmt(argv[4]);
+ } else if (strcmp(argv[2], "mct") == 0) {
+ /* Monte Carlo Test (MCT) */
+ if ( strcmp(argv[3], "ecb") == 0) {
+ /* ECB mode */
+ aes_ecb_mct(argv[4]);
+ } else if (strcmp(argv[3], "cbc") == 0) {
+ /* CBC mode */
+ aes_cbc_mct(argv[4]);
+ }
+ }
+ /*************/
+ /* SHA */
+ /*************/
+ } else if (strcmp(argv[1], "sha") == 0) {
+ sha_test(argv[2]);
+ /*************/
+ /* RSA */
+ /*************/
+ } else if (strcmp(argv[1], "rsa") == 0) {
+ /* argv[2]=siggen|sigver */
+ /* argv[3]=.req */
+ if (strcmp(argv[2], "siggen") == 0) {
+ /* Signature Generation Test */
+ rsa_siggen_test(argv[3]);
+ } else if (strcmp(argv[2], "sigver") == 0) {
+ /* Signature Verification Test */
+ rsa_sigver_test(argv[3]);
+ }
+ /*************/
+ /* HMAC */
+ /*************/
+ } else if (strcmp(argv[1], "hmac") == 0) {
+ hmac_test(argv[2]);
+ /*************/
+ /* DSA */
+ /*************/
+ } else if (strcmp(argv[1], "dsa") == 0) {
+ /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */
+ /* argv[3]=.req */
+ if (strcmp(argv[2], "keypair") == 0) {
+ /* Key Pair Generation Test */
+ dsa_keypair_test(argv[3]);
+ } else if (strcmp(argv[2], "pqggen") == 0) {
+ /* Domain Parameter Generation Test */
+ dsa_pqggen_test(argv[3]);
+ } else if (strcmp(argv[2], "pqgver") == 0) {
+ /* Domain Parameter Validation Test */
+ dsa_pqgver_test(argv[3]);
+ } else if (strcmp(argv[2], "siggen") == 0) {
+ /* Signature Generation Test */
+ dsa_siggen_test(argv[3]);
+ } else if (strcmp(argv[2], "sigver") == 0) {
+ /* Signature Verification Test */
+ dsa_sigver_test(argv[3]);
+ }
+#ifndef NSS_DISABLE_ECC
+ /*************/
+ /* ECDSA */
+ /*************/
+ } else if (strcmp(argv[1], "ecdsa") == 0) {
+ /* argv[2]=keypair|pkv|siggen|sigver argv[3]=.req */
+ if ( strcmp(argv[2], "keypair") == 0) {
+ /* Key Pair Generation Test */
+ ecdsa_keypair_test(argv[3]);
+ } else if (strcmp(argv[2], "pkv") == 0) {
+ /* Public Key Validation Test */
+ ecdsa_pkv_test(argv[3]);
+ } else if (strcmp(argv[2], "siggen") == 0) {
+ /* Signature Generation Test */
+ ecdsa_siggen_test(argv[3]);
+ } else if (strcmp(argv[2], "sigver") == 0) {
+ /* Signature Verification Test */
+ ecdsa_sigver_test(argv[3]);
+ }
+#endif /* NSS_DISABLE_ECC */
+ /*************/
+ /* RNG */
+ /*************/
+ } else if (strcmp(argv[1], "rng") == 0) {
+ /* argv[2]=vst|mct argv[3]=.req */
+ if ( strcmp(argv[2], "vst") == 0) {
+ /* Variable Seed Test */
+ rng_vst(argv[3]);
+ } else if (strcmp(argv[2], "mct") == 0) {
+ /* Monte Carlo Test */
+ rng_mct(argv[3]);
+ }
+ } else if (strcmp(argv[1], "drbg") == 0) {
+ /* Variable Seed Test */
+ drbg(argv[2]);
+ } else if (strcmp(argv[1], "ddrbg") == 0) {
+ debug = 1;
+ drbg(argv[2]);
+ }
+ return 0;
+}
diff --git a/nss/cmd/fipstest/hmac.sh b/nss/cmd/fipstest/hmac.sh
new file mode 100755
index 0000000..5f6c21c
--- /dev/null
+++ b/nss/cmd/fipstest/hmac.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# A Bourne shell script for running the NIST HMAC Algorithm Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+hmac_requests="
+HMAC.req
+"
+
+for request in $hmac_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest hmac $request > $response
+done
+
diff --git a/nss/cmd/fipstest/manifest.mn b/nss/cmd/fipstest/manifest.mn
new file mode 100644
index 0000000..1cebd79
--- /dev/null
+++ b/nss/cmd/fipstest/manifest.mn
@@ -0,0 +1,23 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+PROGRAM = fipstest
+
+USE_STATIC_LIBS = 1
+
+EXPORTS = \
+ $(NULL)
+
+PRIVATE_EXPORTS = \
+ $(NULL)
+
+CSRCS = \
+ fipstest.c \
+ $(NULL)
+
diff --git a/nss/cmd/fipstest/rng.sh b/nss/cmd/fipstest/rng.sh
new file mode 100644
index 0000000..fa1da66
--- /dev/null
+++ b/nss/cmd/fipstest/rng.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# A Bourne shell script for running the NIST RNG Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+drbg_requests="
+SHA256_DRBG.req
+"
+
+for request in $drbg_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest drbg $request > $response
+done
diff --git a/nss/cmd/fipstest/rsa.sh b/nss/cmd/fipstest/rsa.sh
new file mode 100644
index 0000000..5d82c3f
--- /dev/null
+++ b/nss/cmd/fipstest/rsa.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# A Bourne shell script for running the NIST RSA Validation System
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+
+request=SigGen15.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest rsa siggen $request > $response
+
+request=SigVer15.req
+response=`echo $request | sed -e "s/req/rsp/"`
+echo $request $response
+fipstest rsa sigver $request > $response
diff --git a/nss/cmd/fipstest/sha.sh b/nss/cmd/fipstest/sha.sh
new file mode 100644
index 0000000..3f358cb
--- /dev/null
+++ b/nss/cmd/fipstest/sha.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# A Bourne shell script for running the NIST SHA Algorithm Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+sha_ShortMsg_requests="
+SHA1ShortMsg.req
+SHA256ShortMsg.req
+SHA384ShortMsg.req
+SHA512ShortMsg.req
+"
+
+sha_LongMsg_requests="
+SHA1LongMsg.req
+SHA256LongMsg.req
+SHA384LongMsg.req
+SHA512LongMsg.req
+"
+
+sha_Monte_requests="
+SHA1Monte.req
+SHA256Monte.req
+SHA384Monte.req
+SHA512Monte.req
+"
+for request in $sha_ShortMsg_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest sha $request > $response
+done
+for request in $sha_LongMsg_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest sha $request > $response
+done
+for request in $sha_Monte_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest sha $request > $response
+done
+
diff --git a/nss/cmd/fipstest/tdea.sh b/nss/cmd/fipstest/tdea.sh
new file mode 100644
index 0000000..711acba
--- /dev/null
+++ b/nss/cmd/fipstest/tdea.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# A Bourne shell script for running the NIST tdea Algorithm Validation Suite
+#
+# Before you run the script, set your PATH, LD_LIBRARY_PATH, ... environment
+# variables appropriately so that the fipstest command and the NSPR and NSS
+# shared libraries/DLLs are on the search path. Then run this script in the
+# directory where the REQUEST (.req) files reside. The script generates the
+# RESPONSE (.rsp) files in the same directory.
+
+#CBC_Known_Answer_tests
+#Initial Permutation KAT
+#Permutation Operation KAT
+#Subsitution Table KAT
+#Variable Key KAT
+#Variable PlainText KAT
+cbc_kat_requests="
+TCBCinvperm.req
+TCBCpermop.req
+TCBCsubtab.req
+TCBCvarkey.req
+TCBCvartext.req
+"
+
+#CBC Monte Carlo KATs
+cbc_monte_requests="
+TCBCMonte1.req
+TCBCMonte2.req
+TCBCMonte3.req
+"
+#Multi-block Message KATs
+cbc_mmt_requests="
+TCBCMMT1.req
+TCBCMMT2.req
+TCBCMMT3.req
+"
+
+ecb_kat_requests="
+TECBinvperm.req
+TECBpermop.req
+TECBsubtab.req
+TECBvarkey.req
+TECBvartext.req
+"
+
+ecb_monte_requests="
+TECBMonte1.req
+TECBMonte2.req
+TECBMonte3.req
+"
+
+ecb_mmt_requests="
+TECBMMT1.req
+TECBMMT2.req
+TECBMMT3.req
+"
+
+for request in $ecb_mmt_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea mmt ecb $request > $response
+done
+for request in $ecb_kat_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea kat ecb $request > $response
+done
+for request in $ecb_monte_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea mct ecb $request > $response
+done
+for request in $cbc_mmt_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea mmt cbc $request > $response
+done
+for request in $cbc_kat_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea kat cbc $request > $response
+done
+for request in $cbc_monte_requests; do
+ response=`echo $request | sed -e "s/req/rsp/"`
+ echo $request $response
+ fipstest tdea mct cbc $request > $response
+done
diff --git a/nss/cmd/httpserv/Makefile b/nss/cmd/httpserv/Makefile
new file mode 100644
index 0000000..7b74b36
--- /dev/null
+++ b/nss/cmd/httpserv/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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 ../platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+
+include ../platrules.mk
+
diff --git a/nss/cmd/httpserv/httpserv.c b/nss/cmd/httpserv/httpserv.c
new file mode 100644
index 0000000..875b62b
--- /dev/null
+++ b/nss/cmd/httpserv/httpserv.c
@@ -0,0 +1,1394 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include
+#include
+
+#include "secutil.h"
+
+#if defined(XP_UNIX)
+#include
+#endif
+
+#if defined(_WINDOWS)
+#include /* for getpid() */
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+#include "nspr.h"
+#include "prio.h"
+#include "prerror.h"
+#include "prnetdb.h"
+#include "prclist.h"
+#include "plgetopt.h"
+#include "pk11func.h"
+#include "nss.h"
+#include "nssb64.h"
+#include "sechash.h"
+#include "cert.h"
+#include "certdb.h"
+#include "ocsp.h"
+#include "ocspti.h"
+#include "ocspi.h"
+
+#ifndef PORT_Sprintf
+#define PORT_Sprintf sprintf
+#endif
+
+#ifndef PORT_Strstr
+#define PORT_Strstr strstr
+#endif
+
+#ifndef PORT_Malloc
+#define PORT_Malloc PR_Malloc
+#endif
+
+static int handle_connection( PRFileDesc *, PRFileDesc *, int );
+
+/* data and structures for shutdown */
+static int stopping;
+
+static PRBool noDelay;
+static int verbose;
+
+static PRThread * acceptorThread;
+
+static PRLogModuleInfo *lm;
+
+#define PRINTF if (verbose) printf
+#define FPRINTF if (verbose) fprintf
+#define FLUSH if (verbose) { fflush(stdout); fflush(stderr); }
+#define VLOG(arg) PR_LOG(lm,PR_LOG_DEBUG,arg)
+
+static void
+Usage(const char *progName)
+{
+ fprintf(stderr,
+
+"Usage: %s -p port [-Dbv]\n"
+" [-t threads] [-i pid_file]\n"
+" [-A nickname -C crl-filename]... [-O method]\n"
+" [-d dbdir] [-f password_file] [-w password] [-P dbprefix]\n"
+"-D means disable Nagle delays in TCP\n"
+"-b means try binding to the port and exit\n"
+"-v means verbose output\n"
+"-t threads -- specify the number of threads to use for connections.\n"
+"-i pid_file file to write the process id of httpserv\n"
+"Parameters -A, -C and -O are used to provide an OCSP server at /ocsp?\n"
+"-A a nickname of a CA certificate\n"
+"-C a CRL filename corresponding to the preceding CA nickname\n"
+"-O allowed HTTP methods for OCSP requests: get, post, all, random, get-unknown\n"
+" random means: randomly fail if request method is GET, POST always works\n"
+" get-unknown means: status unknown for GET, correct status for POST\n"
+"Multiple pairs of parameters -A and -C are allowed.\n"
+"If status for a cert from an unknown CA is requested, the cert from the\n"
+"first -A parameter will be used to sign the unknown status response.\n"
+"NSS database parameters are used only if OCSP parameters are used.\n"
+ ,progName);
+}
+
+static const char *
+errWarn(char * funcString)
+{
+ PRErrorCode perr = PR_GetError();
+ const char * errString = SECU_Strerror(perr);
+
+ fprintf(stderr, "httpserv: %s returned error %d:\n%s\n",
+ funcString, perr, errString);
+ return errString;
+}
+
+static void
+errExit(char * funcString)
+{
+ errWarn(funcString);
+ exit(3);
+}
+
+#define MAX_VIRT_SERVER_NAME_ARRAY_INDEX 10
+
+/**************************************************************************
+** Begin thread management routines and data.
+**************************************************************************/
+#define MIN_THREADS 3
+#define DEFAULT_THREADS 8
+#define MAX_THREADS 4096
+#define MAX_PROCS 25
+static int maxThreads = DEFAULT_THREADS;
+
+
+typedef struct jobStr {
+ PRCList link;
+ PRFileDesc *tcp_sock;
+ PRFileDesc *model_sock;
+ int requestCert;
+} JOB;
+
+static PZLock * qLock; /* this lock protects all data immediately below */
+static PRLock * lastLoadedCrlLock; /* this lock protects lastLoadedCrl variable */
+static PZCondVar * jobQNotEmptyCv;
+static PZCondVar * freeListNotEmptyCv;
+static PZCondVar * threadCountChangeCv;
+static int threadCount;
+static PRCList jobQ;
+static PRCList freeJobs;
+static JOB *jobTable;
+
+SECStatus
+setupJobs(int maxJobs)
+{
+ int i;
+
+ jobTable = (JOB *)PR_Calloc(maxJobs, sizeof(JOB));
+ if (!jobTable)
+ return SECFailure;
+
+ PR_INIT_CLIST(&jobQ);
+ PR_INIT_CLIST(&freeJobs);
+
+ for (i = 0; i < maxJobs; ++i) {
+ JOB * pJob = jobTable + i;
+ PR_APPEND_LINK(&pJob->link, &freeJobs);
+ }
+ return SECSuccess;
+}
+
+typedef int startFn(PRFileDesc *a, PRFileDesc *b, int c);
+
+typedef enum { rs_idle = 0, rs_running = 1, rs_zombie = 2 } runState;
+
+typedef struct perThreadStr {
+ PRFileDesc *a;
+ PRFileDesc *b;
+ int c;
+ int rv;
+ startFn * startFunc;
+ PRThread * prThread;
+ runState state;
+} perThread;
+
+static perThread *threads;
+
+void
+thread_wrapper(void * arg)
+{
+ perThread * slot = (perThread *)arg;
+
+ slot->rv = (* slot->startFunc)(slot->a, slot->b, slot->c);
+
+ /* notify the thread exit handler. */
+ PZ_Lock(qLock);
+ slot->state = rs_zombie;
+ --threadCount;
+ PZ_NotifyAllCondVar(threadCountChangeCv);
+ PZ_Unlock(qLock);
+}
+
+int
+jobLoop(PRFileDesc *a, PRFileDesc *b, int c)
+{
+ PRCList * myLink = 0;
+ JOB * myJob;
+
+ PZ_Lock(qLock);
+ do {
+ myLink = 0;
+ while (PR_CLIST_IS_EMPTY(&jobQ) && !stopping) {
+ PZ_WaitCondVar(jobQNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ if (!PR_CLIST_IS_EMPTY(&jobQ)) {
+ myLink = PR_LIST_HEAD(&jobQ);
+ PR_REMOVE_AND_INIT_LINK(myLink);
+ }
+ PZ_Unlock(qLock);
+ myJob = (JOB *)myLink;
+ /* myJob will be null when stopping is true and jobQ is empty */
+ if (!myJob)
+ break;
+ handle_connection( myJob->tcp_sock, myJob->model_sock,
+ myJob->requestCert);
+ PZ_Lock(qLock);
+ PR_APPEND_LINK(myLink, &freeJobs);
+ PZ_NotifyCondVar(freeListNotEmptyCv);
+ } while (PR_TRUE);
+ return 0;
+}
+
+
+SECStatus
+launch_threads(
+ startFn *startFunc,
+ PRFileDesc *a,
+ PRFileDesc *b,
+ int c,
+ PRBool local)
+{
+ int i;
+ SECStatus rv = SECSuccess;
+
+ /* create the thread management serialization structs */
+ qLock = PZ_NewLock(nssILockSelfServ);
+ jobQNotEmptyCv = PZ_NewCondVar(qLock);
+ freeListNotEmptyCv = PZ_NewCondVar(qLock);
+ threadCountChangeCv = PZ_NewCondVar(qLock);
+
+ /* create monitor for crl reload procedure */
+ lastLoadedCrlLock = PR_NewLock();
+
+ /* allocate the array of thread slots */
+ threads = PR_Calloc(maxThreads, sizeof(perThread));
+ if ( NULL == threads ) {
+ fprintf(stderr, "Oh Drat! Can't allocate the perThread array\n");
+ return SECFailure;
+ }
+ /* 5 is a little extra, intended to keep the jobQ from underflowing.
+ ** That is, from going empty while not stopping and clients are still
+ ** trying to contact us.
+ */
+ rv = setupJobs(maxThreads + 5);
+ if (rv != SECSuccess)
+ return rv;
+
+ PZ_Lock(qLock);
+ for (i = 0; i < maxThreads; ++i) {
+ perThread * slot = threads + i;
+
+ slot->state = rs_running;
+ slot->a = a;
+ slot->b = b;
+ slot->c = c;
+ slot->startFunc = startFunc;
+ slot->prThread = PR_CreateThread(PR_USER_THREAD,
+ thread_wrapper, slot, PR_PRIORITY_NORMAL,
+ (PR_TRUE==local)?PR_LOCAL_THREAD:PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD, 0);
+ if (slot->prThread == NULL) {
+ printf("httpserv: Failed to launch thread!\n");
+ slot->state = rs_idle;
+ rv = SECFailure;
+ break;
+ }
+
+ ++threadCount;
+ }
+ PZ_Unlock(qLock);
+
+ return rv;
+}
+
+#define DESTROY_CONDVAR(name) if (name) { \
+ PZ_DestroyCondVar(name); name = NULL; }
+#define DESTROY_LOCK(name) if (name) { \
+ PZ_DestroyLock(name); name = NULL; }
+
+
+void
+terminateWorkerThreads(void)
+{
+ VLOG(("httpserv: server_thead: waiting on stopping"));
+ PZ_Lock(qLock);
+ PZ_NotifyAllCondVar(jobQNotEmptyCv);
+ while (threadCount > 0) {
+ PZ_WaitCondVar(threadCountChangeCv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ /* The worker threads empty the jobQ before they terminate. */
+ PORT_Assert(PR_CLIST_IS_EMPTY(&jobQ));
+ PZ_Unlock(qLock);
+
+ DESTROY_CONDVAR(jobQNotEmptyCv);
+ DESTROY_CONDVAR(freeListNotEmptyCv);
+ DESTROY_CONDVAR(threadCountChangeCv);
+
+ PR_DestroyLock(lastLoadedCrlLock);
+ DESTROY_LOCK(qLock);
+ PR_Free(jobTable);
+ PR_Free(threads);
+}
+
+/**************************************************************************
+** End thread management routines.
+**************************************************************************/
+
+PRBool NoReuse = PR_FALSE;
+PRBool disableLocking = PR_FALSE;
+static secuPWData pwdata = { PW_NONE, 0 };
+
+struct caRevoInfoStr
+{
+ PRCList link;
+ char *nickname;
+ char *crlFilename;
+ CERTCertificate *cert;
+ CERTOCSPCertID *id;
+ CERTSignedCrl *crl;
+};
+typedef struct caRevoInfoStr caRevoInfo;
+/* Created during app init. No locks necessary,
+ * because later on, only read access will occur. */
+static caRevoInfo *caRevoInfos = NULL;
+
+static enum {
+ ocspGetOnly, ocspPostOnly, ocspGetAndPost, ocspRandomGetFailure, ocspGetUnknown
+} ocspMethodsAllowed = ocspGetAndPost;
+
+static const char stopCmd[] = { "GET /stop " };
+static const char getCmd[] = { "GET " };
+static const char EOFmsg[] = { "EOF\r\n\r\n\r\n" };
+static const char outHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: Generic Web Server\r\n"
+ "Date: Tue, 26 Aug 1997 22:10:05 GMT\r\n"
+ "Content-type: text/plain\r\n"
+ "\r\n"
+};
+static const char outOcspHeader[] = {
+ "HTTP/1.0 200 OK\r\n"
+ "Server: Generic OCSP Server\r\n"
+ "Content-type: application/ocsp-response\r\n"
+ "\r\n"
+};
+static const char outBadRequestHeader[] = {
+ "HTTP/1.0 400 Bad Request\r\n"
+ "Server: Generic OCSP Server\r\n"
+ "\r\n"
+};
+
+void stop_server()
+{
+ stopping = 1;
+ PR_Interrupt(acceptorThread);
+ PZ_TraceFlush();
+}
+
+/* Will only work if the original input to url encoding was
+ * a base64 encoded buffer. Will only decode the sequences used
+ * for encoding the special base64 characters, and fail if any
+ * other encoded chars are found.
+ * Will return SECSuccess if input could be processed.
+ * Coversion is done in place.
+ */
+static SECStatus
+urldecode_base64chars_inplace(char *buf)
+{
+ char *walk;
+ size_t remaining_bytes;
+
+ if (!buf || !*buf)
+ return SECFailure;
+
+ walk = buf;
+ remaining_bytes = strlen(buf) + 1; /* include terminator */
+
+ while (*walk) {
+ if (*walk == '%') {
+ if (!PL_strncasecmp(walk, "%2B", 3)) {
+ *walk = '+';
+ } else if (!PL_strncasecmp(walk, "%2F", 3)) {
+ *walk = '/';
+ } else if (!PL_strncasecmp(walk, "%3D", 3)) {
+ *walk = '=';
+ } else {
+ return SECFailure;
+ }
+ remaining_bytes -= 3;
+ ++walk;
+ memmove(walk, walk+2, remaining_bytes);
+ } else {
+ ++walk;
+ --remaining_bytes;
+ }
+ }
+ return SECSuccess;
+}
+
+int
+handle_connection(
+ PRFileDesc *tcp_sock,
+ PRFileDesc *model_sock,
+ int requestCert
+ )
+{
+ PRFileDesc * ssl_sock = NULL;
+ PRFileDesc * local_file_fd = NULL;
+ char * pBuf; /* unused space at end of buf */
+ const char * errString;
+ PRStatus status;
+ int bufRem; /* unused bytes at end of buf */
+ int bufDat; /* characters received in buf */
+ int newln = 0; /* # of consecutive newlns */
+ int firstTime = 1;
+ int reqLen;
+ int rv;
+ int numIOVs;
+ PRSocketOptionData opt;
+ PRIOVec iovs[16];
+ char msgBuf[160];
+ char buf[10240];
+ char fileName[513];
+ char *getData = NULL; /* inplace conversion */
+ SECItem postData;
+ PRBool isOcspRequest = PR_FALSE;
+ PRBool isPost;
+
+ postData.data = NULL;
+ postData.len = 0;
+
+ pBuf = buf;
+ bufRem = sizeof buf;
+
+ VLOG(("httpserv: handle_connection: starting"));
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ PR_SetSocketOption(tcp_sock, &opt);
+
+ VLOG(("httpserv: handle_connection: starting\n"));
+ ssl_sock = tcp_sock;
+
+ if (noDelay) {
+ opt.option = PR_SockOpt_NoDelay;
+ opt.value.no_delay = PR_TRUE;
+ status = PR_SetSocketOption(ssl_sock, &opt);
+ if (status != PR_SUCCESS) {
+ errWarn("PR_SetSocketOption(PR_SockOpt_NoDelay, PR_TRUE)");
+ if (ssl_sock) {
+ PR_Close(ssl_sock);
+ }
+ return SECFailure;
+ }
+ }
+
+ while (1) {
+ const char *post;
+ const char *foundStr = NULL;
+ const char *tmp = NULL;
+
+ newln = 0;
+ reqLen = 0;
+
+ rv = PR_Read(ssl_sock, pBuf, bufRem - 1);
+ if (rv == 0 ||
+ (rv < 0 && PR_END_OF_FILE_ERROR == PR_GetError())) {
+ if (verbose)
+ errWarn("HDX PR_Read hit EOF");
+ break;
+ }
+ if (rv < 0) {
+ errWarn("HDX PR_Read");
+ goto cleanup;
+ }
+ /* NULL termination */
+ pBuf[rv] = 0;
+ if (firstTime) {
+ firstTime = 0;
+ }
+
+ pBuf += rv;
+ bufRem -= rv;
+ bufDat = pBuf - buf;
+ /* Parse the input, starting at the beginning of the buffer.
+ * Stop when we detect two consecutive \n's (or \r\n's)
+ * as this signifies the end of the GET or POST portion.
+ * The posted data follows.
+ */
+ while (reqLen < bufDat && newln < 2) {
+ int octet = buf[reqLen++];
+ if (octet == '\n') {
+ newln++;
+ } else if (octet != '\r') {
+ newln = 0;
+ }
+ }
+
+ /* came to the end of the buffer, or second newln
+ * If we didn't get an empty line (CRLFCRLF) then keep on reading.
+ */
+ if (newln < 2)
+ continue;
+
+ /* we're at the end of the HTTP request.
+ * If the request is a POST, then there will be one more
+ * line of data.
+ * This parsing is a hack, but ok for SSL test purposes.
+ */
+ post = PORT_Strstr(buf, "POST ");
+ if (!post || *post != 'P')
+ break;
+
+ postData.data = (void*)(buf + reqLen);
+
+ tmp = "content-length: ";
+ foundStr = PL_strcasestr(buf, tmp);
+ if (foundStr) {
+ int expectedPostLen;
+ int havePostLen;
+
+ expectedPostLen = atoi(foundStr+strlen(tmp));
+ havePostLen = bufDat - reqLen;
+ if (havePostLen >= expectedPostLen) {
+ postData.len = expectedPostLen;
+ break;
+ }
+ } else {
+ /* use legacy hack */
+ /* It's a post, so look for the next and final CR/LF. */
+ while (reqLen < bufDat && newln < 3) {
+ int octet = buf[reqLen++];
+ if (octet == '\n') {
+ newln++;
+ }
+ }
+ if (newln == 3)
+ break;
+ }
+ } /* read loop */
+
+ bufDat = pBuf - buf;
+ if (bufDat) do { /* just close if no data */
+ /* Have either (a) a complete get, (b) a complete post, (c) EOF */
+ if (reqLen > 0) {
+ PRBool isGetOrPost = PR_FALSE;
+ unsigned skipChars = 0;
+ isPost = PR_FALSE;
+
+ if (!strncmp(buf, getCmd, sizeof getCmd - 1)) {
+ isGetOrPost = PR_TRUE;
+ skipChars = 4;
+ }
+ else if (!strncmp(buf, "POST ", 5)) {
+ isGetOrPost = PR_TRUE;
+ isPost = PR_TRUE;
+ skipChars = 5;
+ }
+
+ if (isGetOrPost) {
+ char * fnBegin = buf;
+ char * fnEnd;
+ char * fnstart = NULL;
+ PRFileInfo info;
+
+ fnBegin += skipChars;
+
+ fnEnd = strpbrk(fnBegin, " \r\n");
+ if (fnEnd) {
+ int fnLen = fnEnd - fnBegin;
+ if (fnLen < sizeof fileName) {
+ strncpy(fileName, fnBegin, fnLen);
+ fileName[fnLen] = 0; /* null terminate */
+ fnstart = fileName;
+ /* strip initial / because our root is the current directory*/
+ while (*fnstart && *fnstart=='/')
+ ++fnstart;
+ }
+ }
+ if (fnstart) {
+ if (!strncmp(fnstart, "ocsp", 4)) {
+ if (isPost) {
+ if (postData.data) {
+ isOcspRequest = PR_TRUE;
+ }
+ } else {
+ if (!strncmp(fnstart, "ocsp/", 5)) {
+ isOcspRequest = PR_TRUE;
+ getData = fnstart + 5;
+ }
+ }
+ } else {
+ /* try to open the file named.
+ * If successful, then write it to the client.
+ */
+ status = PR_GetFileInfo(fnstart, &info);
+ if (status == PR_SUCCESS &&
+ info.type == PR_FILE_FILE &&
+ info.size >= 0 ) {
+ local_file_fd = PR_Open(fnstart, PR_RDONLY, 0);
+ }
+ }
+ }
+ }
+ }
+
+ numIOVs = 0;
+
+ iovs[numIOVs].iov_base = (char *)outHeader;
+ iovs[numIOVs].iov_len = (sizeof(outHeader)) - 1;
+ numIOVs++;
+
+ if (isOcspRequest && caRevoInfos) {
+ CERTOCSPRequest *request = NULL;
+ PRBool failThisRequest = PR_FALSE;
+
+ if (ocspMethodsAllowed == ocspGetOnly && postData.len) {
+ failThisRequest = PR_TRUE;
+ } else if (ocspMethodsAllowed == ocspPostOnly && getData) {
+ failThisRequest = PR_TRUE;
+ } else if (ocspMethodsAllowed == ocspRandomGetFailure && getData) {
+ if (!(rand() % 2)) {
+ failThisRequest = PR_TRUE;
+ }
+ }
+
+ if (failThisRequest) {
+ PR_Write(ssl_sock, outBadRequestHeader, strlen(outBadRequestHeader));
+ break;
+ }
+ /* get is base64, post is binary.
+ * If we have base64, convert into the (empty) postData array.
+ */
+ if (getData) {
+ if (urldecode_base64chars_inplace(getData) == SECSuccess) {
+ NSSBase64_DecodeBuffer(NULL, &postData, getData, strlen(getData));
+ }
+ }
+ if (postData.len) {
+ request = CERT_DecodeOCSPRequest(&postData);
+ }
+ if (!request || !request->tbsRequest ||
+ !request->tbsRequest->requestList ||
+ !request->tbsRequest->requestList[0]) {
+ PORT_Sprintf(msgBuf, "Cannot decode OCSP request.\r\n");
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else {
+ /* TODO: support more than one request entry */
+ CERTOCSPCertID *reqid = request->tbsRequest->requestList[0]->reqCert;
+ const caRevoInfo *revoInfo = NULL;
+ PRBool unknown = PR_FALSE;
+ PRBool revoked = PR_FALSE;
+ PRTime nextUpdate = 0;
+ PRTime revoDate = 0;
+ PRCList *caRevoIter;
+
+ caRevoIter = &caRevoInfos->link;
+ do {
+ CERTOCSPCertID *caid;
+
+ revoInfo = (caRevoInfo*)caRevoIter;
+ caid = revoInfo->id;
+
+ if (SECOID_CompareAlgorithmID(&reqid->hashAlgorithm,
+ &caid->hashAlgorithm) == SECEqual
+ &&
+ SECITEM_CompareItem(&reqid->issuerNameHash,
+ &caid->issuerNameHash) == SECEqual
+ &&
+ SECITEM_CompareItem(&reqid->issuerKeyHash,
+ &caid->issuerKeyHash) == SECEqual) {
+ break;
+ }
+ revoInfo = NULL;
+ caRevoIter = PR_NEXT_LINK(caRevoIter);
+ } while (caRevoIter != &caRevoInfos->link);
+
+ if (!revoInfo) {
+ unknown = PR_TRUE;
+ revoInfo = caRevoInfos;
+ } else {
+ CERTCrl *crl = &revoInfo->crl->crl;
+ CERTCrlEntry *entry = NULL;
+ DER_DecodeTimeChoice(&nextUpdate, &crl->nextUpdate);
+ if (crl->entries) {
+ int iv = 0;
+ /* assign, not compare */
+ while ((entry = crl->entries[iv++])) {
+ if (SECITEM_CompareItem(&reqid->serialNumber,
+ &entry->serialNumber) == SECEqual) {
+ break;
+ }
+ }
+ }
+ if (entry) {
+ /* revoked status response */
+ revoked = PR_TRUE;
+ DER_DecodeTimeChoice(&revoDate, &entry->revocationDate);
+ } else {
+ /* else good status response */
+ if (!isPost && ocspMethodsAllowed == ocspGetUnknown) {
+ unknown = PR_TRUE;
+ nextUpdate = PR_Now() + 60*60*24 * PR_USEC_PER_SEC; /*tomorrow*/
+ revoDate = PR_Now() - 60*60*24 * PR_USEC_PER_SEC; /*yesterday*/
+ }
+ }
+ }
+
+ {
+ PRTime now = PR_Now();
+ PLArenaPool *arena = NULL;
+ CERTOCSPSingleResponse *sr;
+ CERTOCSPSingleResponse **singleResponses;
+ SECItem *ocspResponse;
+
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (unknown) {
+ sr = CERT_CreateOCSPSingleResponseUnknown(arena, reqid, now,
+ &nextUpdate);
+ } else if (revoked) {
+ sr = CERT_CreateOCSPSingleResponseRevoked(arena, reqid, now,
+ &nextUpdate, revoDate, NULL);
+ } else {
+ sr = CERT_CreateOCSPSingleResponseGood(arena, reqid, now,
+ &nextUpdate);
+ }
+
+ /* meaning of value 2: one entry + one end marker */
+ singleResponses = PORT_ArenaNewArray(arena, CERTOCSPSingleResponse*, 2);
+ singleResponses[0] = sr;
+ singleResponses[1] = NULL;
+ ocspResponse = CERT_CreateEncodedOCSPSuccessResponse(arena,
+ revoInfo->cert, ocspResponderID_byName, now,
+ singleResponses, &pwdata);
+
+ if (!ocspResponse) {
+ PORT_Sprintf(msgBuf, "Failed to encode response\r\n");
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else {
+ PR_Write(ssl_sock, outOcspHeader, strlen(outOcspHeader));
+ PR_Write(ssl_sock, ocspResponse->data, ocspResponse->len);
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+ }
+ break;
+ }
+ } else if (local_file_fd) {
+ PRInt32 bytes;
+ int errLen;
+ bytes = PR_TransmitFile(ssl_sock, local_file_fd, outHeader,
+ sizeof outHeader - 1,
+ PR_TRANSMITFILE_KEEP_OPEN,
+ PR_INTERVAL_NO_TIMEOUT);
+ if (bytes >= 0) {
+ bytes -= sizeof outHeader - 1;
+ FPRINTF(stderr,
+ "httpserv: PR_TransmitFile wrote %d bytes from %s\n",
+ bytes, fileName);
+ break;
+ }
+ errString = errWarn("PR_TransmitFile");
+ errLen = PORT_Strlen(errString);
+ errLen = PR_MIN(errLen, sizeof msgBuf - 1);
+ PORT_Memcpy(msgBuf, errString, errLen);
+ msgBuf[errLen] = 0;
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else if (reqLen <= 0) { /* hit eof */
+ PORT_Sprintf(msgBuf, "Get or Post incomplete after %d bytes.\r\n",
+ bufDat);
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ } else if (reqLen < bufDat) {
+ PORT_Sprintf(msgBuf, "Discarded %d characters.\r\n",
+ bufDat - reqLen);
+
+ iovs[numIOVs].iov_base = msgBuf;
+ iovs[numIOVs].iov_len = PORT_Strlen(msgBuf);
+ numIOVs++;
+ }
+
+ if (reqLen > 0) {
+ if (verbose > 1)
+ fwrite(buf, 1, reqLen, stdout); /* display it */
+
+ iovs[numIOVs].iov_base = buf;
+ iovs[numIOVs].iov_len = reqLen;
+ numIOVs++;
+ }
+
+ rv = PR_Writev(ssl_sock, iovs, numIOVs, PR_INTERVAL_NO_TIMEOUT);
+ if (rv < 0) {
+ errWarn("PR_Writev");
+ break;
+ }
+
+ } while (0);
+
+cleanup:
+ if (ssl_sock) {
+ PR_Close(ssl_sock);
+ } else if (tcp_sock) {
+ PR_Close(tcp_sock);
+ }
+ if (local_file_fd)
+ PR_Close(local_file_fd);
+ VLOG(("httpserv: handle_connection: exiting\n"));
+
+ /* do a nice shutdown if asked. */
+ if (!strncmp(buf, stopCmd, sizeof stopCmd - 1)) {
+ VLOG(("httpserv: handle_connection: stop command"));
+ stop_server();
+ }
+ VLOG(("httpserv: handle_connection: exiting"));
+ return SECSuccess; /* success */
+}
+
+#ifdef XP_UNIX
+
+void sigusr1_handler(int sig)
+{
+ VLOG(("httpserv: sigusr1_handler: stop server"));
+ stop_server();
+}
+
+#endif
+
+SECStatus
+do_accepts(
+ PRFileDesc *listen_sock,
+ PRFileDesc *model_sock,
+ int requestCert
+ )
+{
+ PRNetAddr addr;
+ PRErrorCode perr;
+#ifdef XP_UNIX
+ struct sigaction act;
+#endif
+
+ VLOG(("httpserv: do_accepts: starting"));
+ PR_SetThreadPriority( PR_GetCurrentThread(), PR_PRIORITY_HIGH);
+
+ acceptorThread = PR_GetCurrentThread();
+#ifdef XP_UNIX
+ /* set up the signal handler */
+ act.sa_handler = sigusr1_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ if (sigaction(SIGUSR1, &act, NULL)) {
+ fprintf(stderr, "Error installing signal handler.\n");
+ exit(1);
+ }
+#endif
+ while (!stopping) {
+ PRFileDesc *tcp_sock;
+ PRCList *myLink;
+
+ FPRINTF(stderr, "\n\n\nhttpserv: About to call accept.\n");
+ tcp_sock = PR_Accept(listen_sock, &addr, PR_INTERVAL_NO_TIMEOUT);
+ if (tcp_sock == NULL) {
+ perr = PR_GetError();
+ if ((perr != PR_CONNECT_RESET_ERROR &&
+ perr != PR_PENDING_INTERRUPT_ERROR) || verbose) {
+ errWarn("PR_Accept");
+ }
+ if (perr == PR_CONNECT_RESET_ERROR) {
+ FPRINTF(stderr,
+ "Ignoring PR_CONNECT_RESET_ERROR error - continue\n");
+ continue;
+ }
+ stopping = 1;
+ break;
+ }
+
+ VLOG(("httpserv: do_accept: Got connection\n"));
+
+ PZ_Lock(qLock);
+ while (PR_CLIST_IS_EMPTY(&freeJobs) && !stopping) {
+ PZ_WaitCondVar(freeListNotEmptyCv, PR_INTERVAL_NO_TIMEOUT);
+ }
+ if (stopping) {
+ PZ_Unlock(qLock);
+ if (tcp_sock) {
+ PR_Close(tcp_sock);
+ }
+ break;
+ }
+ myLink = PR_LIST_HEAD(&freeJobs);
+ PR_REMOVE_AND_INIT_LINK(myLink);
+ /* could release qLock here and reaquire it 7 lines below, but
+ ** why bother for 4 assignment statements?
+ */
+ {
+ JOB * myJob = (JOB *)myLink;
+ myJob->tcp_sock = tcp_sock;
+ myJob->model_sock = model_sock;
+ myJob->requestCert = requestCert;
+ }
+
+ PR_APPEND_LINK(myLink, &jobQ);
+ PZ_NotifyCondVar(jobQNotEmptyCv);
+ PZ_Unlock(qLock);
+ }
+
+ FPRINTF(stderr, "httpserv: Closing listen socket.\n");
+ VLOG(("httpserv: do_accepts: exiting"));
+ if (listen_sock) {
+ PR_Close(listen_sock);
+ }
+ return SECSuccess;
+}
+
+PRFileDesc *
+getBoundListenSocket(unsigned short port)
+{
+ PRFileDesc * listen_sock;
+ int listenQueueDepth = 5 + (2 * maxThreads);
+ PRStatus prStatus;
+ PRNetAddr addr;
+ PRSocketOptionData opt;
+
+ addr.inet.family = PR_AF_INET;
+ addr.inet.ip = PR_INADDR_ANY;
+ addr.inet.port = PR_htons(port);
+
+ listen_sock = PR_NewTCPSocket();
+ if (listen_sock == NULL) {
+ errExit("PR_NewTCPSocket");
+ }
+
+ opt.option = PR_SockOpt_Nonblocking;
+ opt.value.non_blocking = PR_FALSE;
+ prStatus = PR_SetSocketOption(listen_sock, &opt);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_SetSocketOption(PR_SockOpt_Nonblocking)");
+ }
+
+ opt.option=PR_SockOpt_Reuseaddr;
+ opt.value.reuse_addr = PR_TRUE;
+ prStatus = PR_SetSocketOption(listen_sock, &opt);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_SetSocketOption(PR_SockOpt_Reuseaddr)");
+ }
+
+#ifndef WIN95
+ /* Set PR_SockOpt_Linger because it helps prevent a server bind issue
+ * after clean shutdown . See bug 331413 .
+ * Don't do it in the WIN95 build configuration because clean shutdown is
+ * not implemented, and PR_SockOpt_Linger causes a hang in ssl.sh .
+ * See bug 332348 */
+ opt.option=PR_SockOpt_Linger;
+ opt.value.linger.polarity = PR_TRUE;
+ opt.value.linger.linger = PR_SecondsToInterval(1);
+ prStatus = PR_SetSocketOption(listen_sock, &opt);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_SetSocketOption(PR_SockOpt_Linger)");
+ }
+#endif
+
+ prStatus = PR_Bind(listen_sock, &addr);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_Bind");
+ }
+
+ prStatus = PR_Listen(listen_sock, listenQueueDepth);
+ if (prStatus < 0) {
+ PR_Close(listen_sock);
+ errExit("PR_Listen");
+ }
+ return listen_sock;
+}
+
+void
+server_main(
+ PRFileDesc * listen_sock,
+ int requestCert,
+ SECKEYPrivateKey ** privKey,
+ CERTCertificate ** cert,
+ const char *expectedHostNameVal)
+{
+ PRFileDesc *model_sock = NULL;
+
+ /* Now, do the accepting, here in the main thread. */
+ do_accepts(listen_sock, model_sock, requestCert);
+
+ terminateWorkerThreads();
+
+ if (model_sock) {
+ PR_Close(model_sock);
+ }
+
+}
+
+int numChildren;
+PRProcess * child[MAX_PROCS];
+
+PRProcess *
+haveAChild(int argc, char **argv, PRProcessAttr * attr)
+{
+ PRProcess * newProcess;
+
+ newProcess = PR_CreateProcess(argv[0], argv, NULL, attr);
+ if (!newProcess) {
+ errWarn("Can't create new process.");
+ } else {
+ child[numChildren++] = newProcess;
+ }
+ return newProcess;
+}
+
+/* slightly adjusted version of ocsp_CreateCertID (not using issuer) */
+static CERTOCSPCertID *
+ocsp_CreateSelfCAID(PLArenaPool *arena, CERTCertificate *cert, PRTime time)
+{
+ CERTOCSPCertID *certID;
+ void *mark = PORT_ArenaMark(arena);
+ SECStatus rv;
+
+ PORT_Assert(arena != NULL);
+
+ certID = PORT_ArenaZNew(arena, CERTOCSPCertID);
+ if (certID == NULL) {
+ goto loser;
+ }
+
+ rv = SECOID_SetAlgorithmID(arena, &certID->hashAlgorithm, SEC_OID_SHA1,
+ NULL);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ if (CERT_GetSubjectNameDigest(arena, cert, SEC_OID_SHA1,
+ &(certID->issuerNameHash)) == NULL) {
+ goto loser;
+ }
+ certID->issuerSHA1NameHash.data = certID->issuerNameHash.data;
+ certID->issuerSHA1NameHash.len = certID->issuerNameHash.len;
+
+ if (CERT_GetSubjectNameDigest(arena, cert, SEC_OID_MD5,
+ &(certID->issuerMD5NameHash)) == NULL) {
+ goto loser;
+ }
+
+ if (CERT_GetSubjectNameDigest(arena, cert, SEC_OID_MD2,
+ &(certID->issuerMD2NameHash)) == NULL) {
+ goto loser;
+ }
+
+ if (CERT_GetSubjectPublicKeyDigest(arena, cert, SEC_OID_SHA1,
+ &certID->issuerKeyHash) == NULL) {
+ goto loser;
+ }
+ certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data;
+ certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len;
+ /* cache the other two hash algorithms as well */
+ if (CERT_GetSubjectPublicKeyDigest(arena, cert, SEC_OID_MD5,
+ &certID->issuerMD5KeyHash) == NULL) {
+ goto loser;
+ }
+ if (CERT_GetSubjectPublicKeyDigest(arena, cert, SEC_OID_MD2,
+ &certID->issuerMD2KeyHash) == NULL) {
+ goto loser;
+ }
+
+ PORT_ArenaUnmark(arena, mark);
+ return certID;
+
+loser:
+ PORT_ArenaRelease(arena, mark);
+ return NULL;
+}
+
+/* slightly adjusted version of CERT_CreateOCSPCertID */
+CERTOCSPCertID*
+cert_CreateSelfCAID(CERTCertificate *cert, PRTime time)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTOCSPCertID *certID;
+ PORT_Assert(arena != NULL);
+ if (!arena)
+ return NULL;
+
+ certID = ocsp_CreateSelfCAID(arena, cert, time);
+ if (!certID) {
+ PORT_FreeArena(arena, PR_FALSE);
+ return NULL;
+ }
+ certID->poolp = arena;
+ return certID;
+}
+
+int
+main(int argc, char **argv)
+{
+ char * progName = NULL;
+ const char * dir = ".";
+ char * passwd = NULL;
+ char * pwfile = NULL;
+ const char * pidFile = NULL;
+ char * tmp;
+ PRFileDesc * listen_sock;
+ int optionsFound = 0;
+ unsigned short port = 0;
+ SECStatus rv;
+ PRStatus prStatus;
+ PRBool bindOnly = PR_FALSE;
+ PRBool useLocalThreads = PR_FALSE;
+ PLOptState *optstate;
+ PLOptStatus status;
+ char emptyString[] = { "" };
+ char* certPrefix = emptyString;
+ caRevoInfo *revoInfo = NULL;
+ PRCList *caRevoIter = NULL;
+ PRBool provideOcsp = PR_FALSE;
+
+ tmp = strrchr(argv[0], '/');
+ tmp = tmp ? tmp + 1 : argv[0];
+ progName = strrchr(tmp, '\\');
+ progName = progName ? progName + 1 : tmp;
+
+ PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ /* please keep this list of options in ASCII collating sequence.
+ ** numbers, then capital letters, then lower case, alphabetical.
+ */
+ optstate = PL_CreateOptState(argc, argv,
+ "A:C:DO:P:bd:f:hi:p:t:vw:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ ++optionsFound;
+ switch(optstate->option) {
+ /* A first, must be followed by C. Any other order is an error.
+ * A creates the object. C completes and moves into list.
+ */
+ case 'A':
+ provideOcsp = PR_TRUE;
+ if (revoInfo) { Usage(progName); exit(0); }
+ revoInfo = PORT_New(caRevoInfo);
+ revoInfo->nickname = PORT_Strdup(optstate->value);
+ break;
+ case 'C':
+ if (!revoInfo) { Usage(progName); exit(0); }
+ revoInfo->crlFilename = PORT_Strdup(optstate->value);
+ if (!caRevoInfos) {
+ PR_INIT_CLIST(&revoInfo->link);
+ caRevoInfos = revoInfo;
+ } else {
+ PR_APPEND_LINK(&revoInfo->link, &caRevoInfos->link);
+ }
+ revoInfo = NULL;
+ break;
+
+ case 'O':
+ if (!PL_strcasecmp(optstate->value, "all")) {
+ ocspMethodsAllowed = ocspGetAndPost;
+ } else if (!PL_strcasecmp(optstate->value, "get")) {
+ ocspMethodsAllowed = ocspGetOnly;
+ } else if (!PL_strcasecmp(optstate->value, "post")) {
+ ocspMethodsAllowed = ocspPostOnly;
+ } else if (!PL_strcasecmp(optstate->value, "random")) {
+ ocspMethodsAllowed = ocspRandomGetFailure;
+ } else if (!PL_strcasecmp(optstate->value, "get-unknown")) {
+ ocspMethodsAllowed = ocspGetUnknown;
+ } else {
+ Usage(progName); exit(0);
+ }
+ break;
+
+ case 'D': noDelay = PR_TRUE; break;
+
+ case 'P': certPrefix = PORT_Strdup(optstate->value); break;
+
+ case 'b': bindOnly = PR_TRUE; break;
+
+ case 'd': dir = optstate->value; break;
+
+ case 'f':
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = pwfile = PORT_Strdup(optstate->value);
+ break;
+
+ case 'h': Usage(progName); exit(0); break;
+
+ case 'i': pidFile = optstate->value; break;
+
+ case 'p': port = PORT_Atoi(optstate->value); break;
+
+ case 't':
+ maxThreads = PORT_Atoi(optstate->value);
+ if ( maxThreads > MAX_THREADS ) maxThreads = MAX_THREADS;
+ if ( maxThreads < MIN_THREADS ) maxThreads = MIN_THREADS;
+ break;
+
+ case 'v': verbose++; break;
+
+ case 'w':
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = passwd = PORT_Strdup(optstate->value);
+ break;
+
+ default:
+ case '?':
+ fprintf(stderr, "Unrecognized or bad option specified.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(4);
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+ if (status == PL_OPT_BAD) {
+ fprintf(stderr, "Unrecognized or bad option specified.\n");
+ fprintf(stderr, "Run '%s -h' for usage information.\n", progName);
+ exit(5);
+ }
+ if (!optionsFound) {
+ Usage(progName);
+ exit(51);
+ }
+
+ /* The -b (bindOnly) option is only used by the ssl.sh test
+ * script on Linux to determine whether a previous httpserv
+ * process has fully died and freed the port. (Bug 129701)
+ */
+ if (bindOnly) {
+ listen_sock = getBoundListenSocket(port);
+ if (!listen_sock) {
+ exit(1);
+ }
+ if (listen_sock) {
+ PR_Close(listen_sock);
+ }
+ exit(0);
+ }
+
+ if (port == 0) {
+ fprintf(stderr, "Required argument 'port' must be non-zero value\n");
+ exit(7);
+ }
+
+ if (pidFile) {
+ FILE *tmpfile=fopen(pidFile,"w+");
+
+ if (tmpfile) {
+ fprintf(tmpfile,"%d",getpid());
+ fclose(tmpfile);
+ }
+ }
+
+ tmp = getenv("TMP");
+ if (!tmp)
+ tmp = getenv("TMPDIR");
+ if (!tmp)
+ tmp = getenv("TEMP");
+ /* we're an ordinary single process server. */
+ listen_sock = getBoundListenSocket(port);
+ prStatus = PR_SetFDInheritable(listen_sock, PR_FALSE);
+ if (prStatus != PR_SUCCESS)
+ errExit("PR_SetFDInheritable");
+
+ lm = PR_NewLogModule("TestCase");
+
+ /* set our password function */
+ PK11_SetPasswordFunc(SECU_GetModulePassword);
+
+ if (provideOcsp) {
+ /* Call the NSS initialization routines */
+ rv = NSS_Initialize(dir, certPrefix, certPrefix, SECMOD_DB, NSS_INIT_READONLY);
+ if (rv != SECSuccess) {
+ fputs("NSS_Init failed.\n", stderr);
+ exit(8);
+ }
+
+ if (caRevoInfos) {
+ caRevoIter = &caRevoInfos->link;
+ do {
+ PRFileDesc *inFile;
+ int rv = SECFailure;
+ SECItem crlDER;
+ crlDER.data = NULL;
+
+ revoInfo = (caRevoInfo*)caRevoIter;
+ revoInfo->cert = CERT_FindCertByNickname(
+ CERT_GetDefaultCertDB(), revoInfo->nickname);
+ if (!revoInfo->cert) {
+ fprintf(stderr, "cannot find cert with nickname %s\n",
+ revoInfo->nickname);
+ exit(1);
+ }
+ inFile = PR_Open(revoInfo->crlFilename, PR_RDONLY, 0);
+ if (inFile) {
+ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
+ PR_Close(inFile);
+ inFile = NULL;
+ }
+ if (rv != SECSuccess) {
+ fprintf(stderr, "unable to read crl file %s\n",
+ revoInfo->crlFilename);
+ exit(1);
+ }
+ revoInfo->crl =
+ CERT_DecodeDERCrlWithFlags(NULL, &crlDER, SEC_CRL_TYPE,
+ CRL_DECODE_DEFAULT_OPTIONS);
+ if (!revoInfo->crl) {
+ fprintf(stderr, "unable to decode crl file %s\n",
+ revoInfo->crlFilename);
+ exit(1);
+ }
+ if (CERT_CompareName(&revoInfo->crl->crl.name,
+ &revoInfo->cert->subject) != SECEqual) {
+ fprintf(stderr, "CRL %s doesn't match cert identified by preceding nickname %s\n",
+ revoInfo->crlFilename, revoInfo->nickname);
+ exit(1);
+ }
+ revoInfo->id = cert_CreateSelfCAID(revoInfo->cert, PR_Now());
+ caRevoIter = PR_NEXT_LINK(caRevoIter);
+ } while (caRevoIter != &caRevoInfos->link);
+ }
+ }
+
+/* allocate the array of thread slots, and launch the worker threads. */
+ rv = launch_threads(&jobLoop, 0, 0, 0, useLocalThreads);
+
+ if (rv == SECSuccess) {
+ server_main(listen_sock, 0, 0, 0,
+ 0);
+ }
+
+ VLOG(("httpserv: server_thread: exiting"));
+
+ if (provideOcsp) {
+ if (caRevoInfos) {
+ PRCList *caRevoIter;
+
+ caRevoIter = &caRevoInfos->link;
+ do {
+ caRevoInfo *revoInfo = (caRevoInfo*)caRevoIter;
+ if (revoInfo->nickname)
+ PORT_Free(revoInfo->nickname);
+ if (revoInfo->crlFilename)
+ PORT_Free(revoInfo->crlFilename);
+ if (revoInfo->cert)
+ CERT_DestroyCertificate(revoInfo->cert);
+ if (revoInfo->id)
+ CERT_DestroyOCSPCertID(revoInfo->id);
+ if (revoInfo->crl)
+ SEC_DestroyCrl(revoInfo->crl);
+
+ caRevoIter = PR_NEXT_LINK(caRevoIter);
+ } while (caRevoIter != &caRevoInfos->link);
+
+ }
+ if (NSS_Shutdown() != SECSuccess) {
+ SECU_PrintError(progName, "NSS_Shutdown");
+ PR_Cleanup();
+ exit(1);
+ }
+ }
+ if (passwd) {
+ PORT_Free(passwd);
+ }
+ if (pwfile) {
+ PORT_Free(pwfile);
+ }
+ if (certPrefix && certPrefix != emptyString) {
+ PORT_Free(certPrefix);
+ }
+ PR_Cleanup();
+ printf("httpserv: normal termination\n");
+ return 0;
+}
+
diff --git a/nss/cmd/httpserv/manifest.mn b/nss/cmd/httpserv/manifest.mn
new file mode 100644
index 0000000..e969661
--- /dev/null
+++ b/nss/cmd/httpserv/manifest.mn
@@ -0,0 +1,20 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+CORE_DEPTH = ../..
+
+DEFINES += -DNSPR20
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = httpserv.c
+
+# The MODULE is always implicitly required.
+# Listing it here in REQUIRES makes it appear twice in the cc command line.
+REQUIRES = seccmd dbm
+
+PROGRAM = httpserv
+
diff --git a/nss/cmd/lib/Makefile b/nss/cmd/lib/Makefile
new file mode 100644
index 0000000..0fb6c90
--- /dev/null
+++ b/nss/cmd/lib/Makefile
@@ -0,0 +1,49 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+export:: private_export
+
+
diff --git a/nss/cmd/lib/basicutil.c b/nss/cmd/lib/basicutil.c
new file mode 100644
index 0000000..94c28f5
--- /dev/null
+++ b/nss/cmd/lib/basicutil.c
@@ -0,0 +1,725 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+** secutil.c - various functions used by security stuff
+**
+*/
+
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "prerror.h"
+#include "prprf.h"
+#include "plgetopt.h"
+#include "prenv.h"
+#include "prnetdb.h"
+
+#include "basicutil.h"
+#include
+#include
+#include
+
+#ifdef XP_UNIX
+#include
+#endif
+
+#include "secoid.h"
+
+extern long DER_GetInteger(const SECItem *src);
+
+static PRBool wrapEnabled = PR_TRUE;
+
+void
+SECU_EnableWrap(PRBool enable)
+{
+ wrapEnabled = enable;
+}
+
+PRBool
+SECU_GetWrapEnabled(void)
+{
+ return wrapEnabled;
+}
+
+void
+SECU_PrintErrMsg(FILE *out, int level, const char *progName, const char *msg,
+ ...)
+{
+ va_list args;
+ PRErrorCode err = PORT_GetError();
+ const char * errString = PORT_ErrorToString(err);
+
+ va_start(args, msg);
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s: ", progName);
+ vfprintf(out, msg, args);
+ if (errString != NULL && PORT_Strlen(errString) > 0)
+ fprintf(out, ": %s\n", errString);
+ else
+ fprintf(out, ": error %d\n", (int)err);
+
+ va_end(args);
+}
+
+void
+SECU_PrintError(const char *progName, const char *msg, ...)
+{
+ va_list args;
+ PRErrorCode err = PORT_GetError();
+ const char * errName = PR_ErrorToName(err);
+ const char * errString = PR_ErrorToString(err, 0);
+
+ va_start(args, msg);
+
+ fprintf(stderr, "%s: ", progName);
+ vfprintf(stderr, msg, args);
+
+ if (errName != NULL) {
+ fprintf(stderr, ": %s", errName);
+ } else {
+ fprintf(stderr, ": error %d", (int)err);
+ }
+
+ if (errString != NULL && PORT_Strlen(errString) > 0)
+ fprintf(stderr, ": %s\n", errString);
+
+ va_end(args);
+}
+
+void
+SECU_PrintSystemError(const char *progName, const char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ fprintf(stderr, "%s: ", progName);
+ vfprintf(stderr, msg, args);
+ fprintf(stderr, ": %s\n", strerror(errno));
+ va_end(args);
+}
+
+SECStatus
+secu_StdinToItem(SECItem *dst)
+{
+ unsigned char buf[1000];
+ PRInt32 numBytes;
+ PRBool notDone = PR_TRUE;
+
+ dst->len = 0;
+ dst->data = NULL;
+
+ while (notDone) {
+ numBytes = PR_Read(PR_STDIN, buf, sizeof(buf));
+
+ if (numBytes < 0) {
+ return SECFailure;
+ }
+
+ if (numBytes == 0)
+ break;
+
+ if (dst->data) {
+ unsigned char * p = dst->data;
+ dst->data = (unsigned char*)PORT_Realloc(p, dst->len + numBytes);
+ if (!dst->data) {
+ PORT_Free(p);
+ }
+ } else {
+ dst->data = (unsigned char*)PORT_Alloc(numBytes);
+ }
+ if (!dst->data) {
+ return SECFailure;
+ }
+ PORT_Memcpy(dst->data + dst->len, buf, numBytes);
+ dst->len += numBytes;
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+SECU_FileToItem(SECItem *dst, PRFileDesc *src)
+{
+ PRFileInfo info;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+
+ if (src == PR_STDIN)
+ return secu_StdinToItem(dst);
+
+ prStatus = PR_GetOpenFileInfo(src, &info);
+
+ if (prStatus != PR_SUCCESS) {
+ PORT_SetError(SEC_ERROR_IO);
+ return SECFailure;
+ }
+
+ /* XXX workaround for 3.1, not all utils zero dst before sending */
+ dst->data = 0;
+ if (!SECITEM_AllocItem(NULL, dst, info.size))
+ goto loser;
+
+ numBytes = PR_Read(src, dst->data, info.size);
+ if (numBytes != info.size) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+
+ return SECSuccess;
+loser:
+ SECITEM_FreeItem(dst, PR_FALSE);
+ dst->data = NULL;
+ return SECFailure;
+}
+
+SECStatus
+SECU_TextFileToItem(SECItem *dst, PRFileDesc *src)
+{
+ PRFileInfo info;
+ PRInt32 numBytes;
+ PRStatus prStatus;
+ unsigned char *buf;
+
+ if (src == PR_STDIN)
+ return secu_StdinToItem(dst);
+
+ prStatus = PR_GetOpenFileInfo(src, &info);
+
+ if (prStatus != PR_SUCCESS) {
+ PORT_SetError(SEC_ERROR_IO);
+ return SECFailure;
+ }
+
+ buf = (unsigned char*)PORT_Alloc(info.size);
+ if (!buf)
+ return SECFailure;
+
+ numBytes = PR_Read(src, buf, info.size);
+ if (numBytes != info.size) {
+ PORT_SetError(SEC_ERROR_IO);
+ goto loser;
+ }
+
+ if (buf[numBytes-1] == '\n') numBytes--;
+#ifdef _WINDOWS
+ if (buf[numBytes-1] == '\r') numBytes--;
+#endif
+
+ /* XXX workaround for 3.1, not all utils zero dst before sending */
+ dst->data = 0;
+ if (!SECITEM_AllocItem(NULL, dst, numBytes))
+ goto loser;
+
+ memcpy(dst->data, buf, numBytes);
+
+ PORT_Free(buf);
+ return SECSuccess;
+loser:
+ PORT_Free(buf);
+ return SECFailure;
+}
+
+#define INDENT_MULT 4
+void
+SECU_Indent(FILE *out, int level)
+{
+ int i;
+
+ for (i = 0; i < level; i++) {
+ fprintf(out, " ");
+ }
+}
+
+void SECU_Newline(FILE *out)
+{
+ fprintf(out, "\n");
+}
+
+void
+SECU_PrintAsHex(FILE *out, const SECItem *data, const char *m, int level)
+{
+ unsigned i;
+ int column = 0;
+ PRBool isString = PR_TRUE;
+ PRBool isWhiteSpace = PR_TRUE;
+ PRBool printedHex = PR_FALSE;
+ unsigned int limit = 15;
+
+ if ( m ) {
+ SECU_Indent(out, level); fprintf(out, "%s:", m);
+ level++;
+ if (wrapEnabled)
+ fprintf(out, "\n");
+ }
+
+ if (wrapEnabled) {
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ }
+ if (!data->len) {
+ fprintf(out, "(empty)\n");
+ return;
+ }
+ /* take a pass to see if it's all printable. */
+ for (i = 0; i < data->len; i++) {
+ unsigned char val = data->data[i];
+ if (!val || !isprint(val)) {
+ isString = PR_FALSE;
+ break;
+ }
+ if (isWhiteSpace && !isspace(val)) {
+ isWhiteSpace = PR_FALSE;
+ }
+ }
+
+ /* Short values, such as bit strings (which are printed with this
+ ** function) often look like strings, but we want to see the bits.
+ ** so this test assures that short values will be printed in hex,
+ ** perhaps in addition to being printed as strings.
+ ** The threshold size (4 bytes) is arbitrary.
+ */
+ if (!isString || data->len <= 4) {
+ for (i = 0; i < data->len; i++) {
+ if (i != data->len - 1) {
+ fprintf(out, "%02x:", data->data[i]);
+ column += 3;
+ } else {
+ fprintf(out, "%02x", data->data[i]);
+ column += 2;
+ break;
+ }
+ if (wrapEnabled &&
+ (column > 76 || (i % 16 == limit))) {
+ SECU_Newline(out);
+ SECU_Indent(out, level);
+ column = level*INDENT_MULT;
+ limit = i % 16;
+ }
+ }
+ printedHex = PR_TRUE;
+ }
+ if (isString && !isWhiteSpace) {
+ if (printedHex != PR_FALSE) {
+ SECU_Newline(out);
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ }
+ for (i = 0; i < data->len; i++) {
+ unsigned char val = data->data[i];
+
+ if (val) {
+ fprintf(out,"%c",val);
+ column++;
+ } else {
+ column = 77;
+ }
+ if (wrapEnabled && column > 76) {
+ SECU_Newline(out);
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ }
+ }
+ }
+
+ if (column != level*INDENT_MULT) {
+ SECU_Newline(out);
+ }
+}
+
+const char *hex = "0123456789abcdef";
+
+const char printable[257] = {
+ "................" /* 0x */
+ "................" /* 1x */
+ " !\"#$%&'()*+,-./" /* 2x */
+ "0123456789:;<=>?" /* 3x */
+ "@ABCDEFGHIJKLMNO" /* 4x */
+ "PQRSTUVWXYZ[\\]^_" /* 5x */
+ "`abcdefghijklmno" /* 6x */
+ "pqrstuvwxyz{|}~." /* 7x */
+ "................" /* 8x */
+ "................" /* 9x */
+ "................" /* ax */
+ "................" /* bx */
+ "................" /* cx */
+ "................" /* dx */
+ "................" /* ex */
+ "................" /* fx */
+};
+
+void
+SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len)
+{
+ const unsigned char *cp = (const unsigned char *)vp;
+ char buf[80];
+ char *bp;
+ char *ap;
+
+ fprintf(out, "%s [Len: %d]\n", msg, len);
+ memset(buf, ' ', sizeof buf);
+ bp = buf;
+ ap = buf + 50;
+ while (--len >= 0) {
+ unsigned char ch = *cp++;
+ *bp++ = hex[(ch >> 4) & 0xf];
+ *bp++ = hex[ch & 0xf];
+ *bp++ = ' ';
+ *ap++ = printable[ch];
+ if (ap - buf >= 66) {
+ *ap = 0;
+ fprintf(out, " %s\n", buf);
+ memset(buf, ' ', sizeof buf);
+ bp = buf;
+ ap = buf + 50;
+ }
+ }
+ if (bp > buf) {
+ *ap = 0;
+ fprintf(out, " %s\n", buf);
+ }
+}
+
+
+/* This expents i->data[0] to be the MSB of the integer.
+** if you want to print a DER-encoded integer (with the tag and length)
+** call SECU_PrintEncodedInteger();
+*/
+void
+SECU_PrintInteger(FILE *out, const SECItem *i, const char *m, int level)
+{
+ int iv;
+
+ if (!i || !i->len || !i->data) {
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: (null)\n", m);
+ } else {
+ fprintf(out, "(null)\n");
+ }
+ } else if (i->len > 4) {
+ SECU_PrintAsHex(out, i, m, level);
+ } else {
+ if (i->type == siUnsignedInteger && *i->data & 0x80) {
+ /* Make sure i->data has zero in the highest bite
+ * if i->data is an unsigned integer */
+ SECItem tmpI;
+ char data[] = {0, 0, 0, 0, 0};
+
+ PORT_Memcpy(data + 1, i->data, i->len);
+ tmpI.len = i->len + 1;
+ tmpI.data = (void*)data;
+
+ iv = DER_GetInteger(&tmpI);
+ } else {
+ iv = DER_GetInteger(i);
+ }
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: %d (0x%x)\n", m, iv, iv);
+ } else {
+ fprintf(out, "%d (0x%x)\n", iv, iv);
+ }
+ }
+}
+
+#if defined(DEBUG) || defined(FORCE_PR_ASSERT)
+/* Returns true iff a[i].flag has a duplicate in a[i+1 : count-1] */
+static PRBool HasShortDuplicate(int i, secuCommandFlag *a, int count)
+{
+ char target = a[i].flag;
+ int j;
+
+ /* duplicate '\0' flags are okay, they are used with long forms */
+ for (j = i+1; j < count; j++) {
+ if (a[j].flag && a[j].flag == target) {
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+/* Returns true iff a[i].longform has a duplicate in a[i+1 : count-1] */
+static PRBool HasLongDuplicate(int i, secuCommandFlag *a, int count)
+{
+ int j;
+ char *target = a[i].longform;
+
+ if (!target)
+ return PR_FALSE;
+
+ for (j = i+1; j < count; j++) {
+ if (a[j].longform && strcmp(a[j].longform, target) == 0) {
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+/* Returns true iff a has no short or long form duplicates
+ */
+PRBool HasNoDuplicates(secuCommandFlag *a, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (a[i].flag && HasShortDuplicate(i, a, count)) {
+ return PR_FALSE;
+ }
+ if (a[i].longform && HasLongDuplicate(i, a, count)) {
+ return PR_FALSE;
+ }
+ }
+ return PR_TRUE;
+}
+#endif
+
+SECStatus
+SECU_ParseCommandLine(int argc, char **argv, char *progName,
+ const secuCommand *cmd)
+{
+ PRBool found;
+ PLOptState *optstate;
+ PLOptStatus status;
+ char *optstring;
+ PLLongOpt *longopts = NULL;
+ int i, j;
+ int lcmd = 0, lopt = 0;
+
+ PR_ASSERT(HasNoDuplicates(cmd->commands, cmd->numCommands));
+ PR_ASSERT(HasNoDuplicates(cmd->options, cmd->numOptions));
+
+ optstring = (char *)PORT_Alloc(cmd->numCommands + 2*cmd->numOptions+1);
+ if (optstring == NULL)
+ return SECFailure;
+
+ j = 0;
+ for (i=0; inumCommands; i++) {
+ if (cmd->commands[i].flag) /* single character option ? */
+ optstring[j++] = cmd->commands[i].flag;
+ if (cmd->commands[i].longform)
+ lcmd++;
+ }
+ for (i=0; inumOptions; i++) {
+ if (cmd->options[i].flag) {
+ optstring[j++] = cmd->options[i].flag;
+ if (cmd->options[i].needsArg)
+ optstring[j++] = ':';
+ }
+ if (cmd->options[i].longform)
+ lopt++;
+ }
+
+ optstring[j] = '\0';
+
+ if (lcmd + lopt > 0) {
+ longopts = PORT_NewArray(PLLongOpt, lcmd+lopt+1);
+ if (!longopts) {
+ PORT_Free(optstring);
+ return SECFailure;
+ }
+
+ j = 0;
+ for (i=0; jnumCommands; i++) {
+ if (cmd->commands[i].longform) {
+ longopts[j].longOptName = cmd->commands[i].longform;
+ longopts[j].longOption = 0;
+ longopts[j++].valueRequired = cmd->commands[i].needsArg;
+ }
+ }
+ lopt += lcmd;
+ for (i=0; jnumOptions; i++) {
+ if (cmd->options[i].longform) {
+ longopts[j].longOptName = cmd->options[i].longform;
+ longopts[j].longOption = 0;
+ longopts[j++].valueRequired = cmd->options[i].needsArg;
+ }
+ }
+ longopts[j].longOptName = NULL;
+ }
+
+ optstate = PL_CreateLongOptState(argc, argv, optstring, longopts);
+ if (!optstate) {
+ PORT_Free(optstring);
+ PORT_Free(longopts);
+ return SECFailure;
+ }
+ /* Parse command line arguments */
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ const char *optstatelong;
+ char option = optstate->option;
+
+ /* positional parameter, single-char option or long opt? */
+ if (optstate->longOptIndex == -1) {
+ /* not a long opt */
+ if (option == '\0')
+ continue; /* it's a positional parameter */
+ optstatelong = "";
+ } else {
+ /* long opt */
+ if (option == '\0')
+ option = '\377'; /* force unequal with all flags */
+ optstatelong = longopts[optstate->longOptIndex].longOptName;
+ }
+
+ found = PR_FALSE;
+
+ for (i=0; inumCommands; i++) {
+ if (cmd->commands[i].flag == option ||
+ cmd->commands[i].longform == optstatelong) {
+ cmd->commands[i].activated = PR_TRUE;
+ if (optstate->value) {
+ cmd->commands[i].arg = (char *)optstate->value;
+ }
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ for (i=0; inumOptions; i++) {
+ if (cmd->options[i].flag == option ||
+ cmd->options[i].longform == optstatelong) {
+ cmd->options[i].activated = PR_TRUE;
+ if (optstate->value) {
+ cmd->options[i].arg = (char *)optstate->value;
+ } else if (cmd->options[i].needsArg) {
+ status = PL_OPT_BAD;
+ goto loser;
+ }
+ found = PR_TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ status = PL_OPT_BAD;
+ break;
+ }
+ }
+
+loser:
+ PL_DestroyOptState(optstate);
+ PORT_Free(optstring);
+ if (longopts)
+ PORT_Free(longopts);
+ if (status == PL_OPT_BAD)
+ return SECFailure;
+ return SECSuccess;
+}
+
+char *
+SECU_GetOptionArg(const secuCommand *cmd, int optionNum)
+{
+ if (optionNum < 0 || optionNum >= cmd->numOptions)
+ return NULL;
+ if (cmd->options[optionNum].activated)
+ return PL_strdup(cmd->options[optionNum].arg);
+ else
+ return NULL;
+}
+
+
+void
+SECU_PrintPRandOSError(const char *progName)
+{
+ char buffer[513];
+ PRInt32 errLen = PR_GetErrorTextLength();
+ if (errLen > 0 && errLen < sizeof buffer) {
+ PR_GetErrorText(buffer);
+ }
+ SECU_PrintError(progName, "function failed");
+ if (errLen > 0 && errLen < sizeof buffer) {
+ PR_fprintf(PR_STDERR, "\t%s\n", buffer);
+ }
+}
+
+SECOidTag
+SECU_StringToSignatureAlgTag(const char *alg)
+{
+ SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
+
+ if (alg) {
+ if (!PL_strcmp(alg, "MD2")) {
+ hashAlgTag = SEC_OID_MD2;
+ } else if (!PL_strcmp(alg, "MD4")) {
+ hashAlgTag = SEC_OID_MD4;
+ } else if (!PL_strcmp(alg, "MD5")) {
+ hashAlgTag = SEC_OID_MD5;
+ } else if (!PL_strcmp(alg, "SHA1")) {
+ hashAlgTag = SEC_OID_SHA1;
+ } else if (!PL_strcmp(alg, "SHA224")) {
+ hashAlgTag = SEC_OID_SHA224;
+ } else if (!PL_strcmp(alg, "SHA256")) {
+ hashAlgTag = SEC_OID_SHA256;
+ } else if (!PL_strcmp(alg, "SHA384")) {
+ hashAlgTag = SEC_OID_SHA384;
+ } else if (!PL_strcmp(alg, "SHA512")) {
+ hashAlgTag = SEC_OID_SHA512;
+ }
+ }
+ return hashAlgTag;
+}
+
+/* Caller ensures that dst is at least item->len*2+1 bytes long */
+void
+SECU_SECItemToHex(const SECItem * item, char * dst)
+{
+ if (dst && item && item->data) {
+ unsigned char * src = item->data;
+ unsigned int len = item->len;
+ for (; len > 0; --len, dst += 2) {
+ sprintf(dst, "%02x", *src++);
+ }
+ *dst = '\0';
+ }
+}
+
+static unsigned char nibble(char c) {
+ c = PORT_Tolower(c);
+ return ( c >= '0' && c <= '9') ? c - '0' :
+ ( c >= 'a' && c <= 'f') ? c - 'a' +10 : -1;
+}
+
+SECStatus
+SECU_SECItemHexStringToBinary(SECItem* srcdest)
+{
+ int i;
+
+ if (!srcdest) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ if (srcdest->len < 4 || (srcdest->len % 2) ) {
+ /* too short to convert, or even number of characters */
+ PORT_SetError(SEC_ERROR_BAD_DATA);
+ return SECFailure;
+ }
+ if (PORT_Strncasecmp((const char*)srcdest->data, "0x", 2)) {
+ /* wrong prefix */
+ PORT_SetError(SEC_ERROR_BAD_DATA);
+ return SECFailure;
+ }
+
+ /* 1st pass to check for hex characters */
+ for (i=2; ilen; i++) {
+ char c = PORT_Tolower(srcdest->data[i]);
+ if (! ( ( c >= '0' && c <= '9') ||
+ ( c >= 'a' && c <= 'f')
+ ) ) {
+ PORT_SetError(SEC_ERROR_BAD_DATA);
+ return SECFailure;
+ }
+ }
+
+ /* 2nd pass to convert */
+ for (i=2; ilen; i+=2) {
+ srcdest->data[(i-2)/2] = (nibble(srcdest->data[i]) << 4) +
+ nibble(srcdest->data[i+1]);
+ }
+
+ /* adjust length */
+ srcdest->len -= 2;
+ srcdest->len /= 2;
+ return SECSuccess;
+}
diff --git a/nss/cmd/lib/basicutil.h b/nss/cmd/lib/basicutil.h
new file mode 100644
index 0000000..fec1cf4
--- /dev/null
+++ b/nss/cmd/lib/basicutil.h
@@ -0,0 +1,132 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef _BASIC_UTILS_H_
+#define _BASIC_UTILS_H_
+
+#include "seccomon.h"
+#include "secitem.h"
+#include "secoid.h"
+#include "secoidt.h"
+#include "secport.h"
+#include "prerror.h"
+#include "base64.h"
+#include "secasn1.h"
+#include "secder.h"
+#include
+
+#ifdef SECUTIL_NEW
+typedef int (*SECU_PPFunc)(PRFileDesc *out, SECItem *item,
+ char *msg, int level);
+#else
+typedef int (*SECU_PPFunc)(FILE *out, SECItem *item, char *msg, int level);
+#endif
+
+/* print out an error message */
+extern void SECU_PrintError(const char *progName, const char *msg, ...);
+
+/* print out a system error message */
+extern void SECU_PrintSystemError(const char *progName, const char *msg, ...);
+
+/* print a formatted error message */
+extern void SECU_PrintErrMsg(FILE *out, int level, const char *progName,
+ const char *msg, ...);
+
+/* Read the contents of a file into a SECItem */
+extern SECStatus SECU_FileToItem(SECItem *dst, PRFileDesc *src);
+extern SECStatus SECU_TextFileToItem(SECItem *dst, PRFileDesc *src);
+
+/* Indent based on "level" */
+extern void SECU_Indent(FILE *out, int level);
+
+/* Print a newline to out */
+extern void SECU_Newline(FILE *out);
+
+/* Print integer value and hex */
+extern void SECU_PrintInteger(FILE *out, const SECItem *i, const char *m,
+ int level);
+
+/* Print SECItem as hex */
+extern void SECU_PrintAsHex(FILE *out, const SECItem *i, const char *m,
+ int level);
+
+/* dump a buffer in hex and ASCII */
+extern void SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len);
+
+#ifdef HAVE_EPV_TEMPLATE
+/* Dump contents of private key */
+extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
+#endif
+
+/* Init PKCS11 stuff */
+extern SECStatus SECU_PKCS11Init(PRBool readOnly);
+
+/* Dump contents of signed data */
+extern int SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
+ int level, SECU_PPFunc inner);
+
+extern void SECU_PrintString(FILE *out, const SECItem *si, const char *m,
+ int level);
+extern void SECU_PrintAny(FILE *out, const SECItem *i, const char *m, int level);
+
+extern void SECU_PrintPRandOSError(const char *progName);
+
+/* Caller ensures that dst is at least item->len*2+1 bytes long */
+void
+SECU_SECItemToHex(const SECItem * item, char * dst);
+
+/* Requires 0x prefix. Case-insensitive. Will do in-place replacement if
+ * successful */
+SECStatus
+SECU_SECItemHexStringToBinary(SECItem* srcdest);
+
+/*
+ *
+ * Utilities for parsing security tools command lines
+ *
+ */
+
+/* A single command flag */
+typedef struct {
+ char flag;
+ PRBool needsArg;
+ char *arg;
+ PRBool activated;
+ char *longform;
+} secuCommandFlag;
+
+/* A full array of command/option flags */
+typedef struct
+{
+ int numCommands;
+ int numOptions;
+
+ secuCommandFlag *commands;
+ secuCommandFlag *options;
+} secuCommand;
+
+/* fill the "arg" and "activated" fields for each flag */
+SECStatus
+SECU_ParseCommandLine(int argc, char **argv, char *progName,
+ const secuCommand *cmd);
+char *
+SECU_GetOptionArg(const secuCommand *cmd, int optionNum);
+
+/*
+ *
+ * Error messaging
+ *
+ */
+
+void printflags(char *trusts, unsigned int flags);
+
+#if !defined(XP_UNIX) && !defined(XP_OS2)
+extern int ffs(unsigned int i);
+#endif
+
+#include "secerr.h"
+
+extern const char *hex;
+extern const char printable[];
+
+#endif /* _BASIC_UTILS_H_ */
diff --git a/nss/cmd/lib/berparse.c b/nss/cmd/lib/berparse.c
new file mode 100644
index 0000000..9e65361
--- /dev/null
+++ b/nss/cmd/lib/berparse.c
@@ -0,0 +1,375 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "secutil.h"
+
+typedef enum {
+ tagDone, lengthDone, leafDone, compositeDone,
+ notDone,
+ parseError, parseComplete
+} ParseState;
+
+typedef unsigned char Byte;
+typedef void (*ParseProc)(BERParse *h, unsigned char **buf, int *len);
+typedef struct {
+ SECArb arb;
+ int pos; /* length from global start to item start */
+ SECArb *parent;
+} ParseStackElem;
+
+struct BERParseStr {
+ PLArenaPool *his;
+ PLArenaPool *mine;
+ ParseProc proc;
+ int stackDepth;
+ ParseStackElem *stackPtr;
+ ParseStackElem *stack;
+ int pending; /* bytes remaining to complete this part */
+ int pos; /* running length of consumed characters */
+ ParseState state;
+ PRBool keepLeaves;
+ PRBool derOnly;
+ BERFilterProc filter;
+ void *filterArg;
+ BERNotifyProc before;
+ void *beforeArg;
+ BERNotifyProc after;
+ void *afterArg;
+};
+
+#define UNKNOWN -1
+
+static unsigned char NextChar(BERParse *h, unsigned char **buf, int *len)
+{
+ unsigned char c = *(*buf)++;
+ (*len)--;
+ h->pos++;
+ if (h->filter)
+ (*h->filter)(h->filterArg, &c, 1);
+ return c;
+}
+
+static void ParseTag(BERParse *h, unsigned char **buf, int *len)
+{
+ SECArb* arb = &(h->stackPtr->arb);
+ arb->tag = NextChar(h, buf, len);
+
+ PORT_Assert(h->state == notDone);
+
+ /*
+ * NOTE: This does not handle the high-tag-number form
+ */
+ if ((arb->tag & DER_HIGH_TAG_NUMBER) == DER_HIGH_TAG_NUMBER) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return;
+ }
+
+ h->pending = UNKNOWN;
+ arb->length = UNKNOWN;
+ if (arb->tag & DER_CONSTRUCTED) {
+ arb->body.cons.numSubs = 0;
+ arb->body.cons.subs = NULL;
+ } else {
+ arb->body.item.len = UNKNOWN;
+ arb->body.item.data = NULL;
+ }
+
+ h->state = tagDone;
+}
+
+static void ParseLength(BERParse *h, unsigned char **buf, int *len)
+{
+ Byte b;
+ SECArb *arb = &(h->stackPtr->arb);
+
+ PORT_Assert(h->state == notDone);
+
+ if (h->pending == UNKNOWN) {
+ b = NextChar(h, buf, len);
+ if ((b & 0x80) == 0) { /* short form */
+ arb->length = b;
+ /*
+ * if the tag and the length are both zero bytes, then this
+ * should be the marker showing end of list for the
+ * indefinite length composite
+ */
+ if (arb->length == 0 && arb->tag == 0)
+ h->state = compositeDone;
+ else
+ h->state = lengthDone;
+ return;
+ }
+
+ h->pending = b & 0x7f;
+ /* 0 implies this is an indefinite length */
+ if (h->pending > 4) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return;
+ }
+ arb->length = 0;
+ }
+
+ while ((*len > 0) && (h->pending > 0)) {
+ b = NextChar(h, buf, len);
+ arb->length = (arb->length << 8) + b;
+ h->pending--;
+ }
+ if (h->pending == 0) {
+ if (h->derOnly && (arb->length == 0))
+ h->state = parseError;
+ else
+ h->state = lengthDone;
+ }
+ return;
+}
+
+static void ParseLeaf(BERParse *h, unsigned char **buf, int *len)
+{
+ int count;
+ SECArb *arb = &(h->stackPtr->arb);
+
+ PORT_Assert(h->state == notDone);
+ PORT_Assert(h->pending >= 0);
+
+ if (*len < h->pending)
+ count = *len;
+ else
+ count = h->pending;
+
+ if (h->keepLeaves)
+ memcpy(arb->body.item.data + arb->body.item.len, *buf, count);
+ if (h->filter)
+ (*h->filter)(h->filterArg, *buf, count);
+ *buf += count;
+ *len -= count;
+ arb->body.item.len += count;
+ h->pending -= count;
+ h->pos += count;
+ if (h->pending == 0) {
+ h->state = leafDone;
+ }
+ return;
+}
+
+static void CreateArbNode(BERParse *h)
+{
+ SECArb *arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
+
+ *arb = h->stackPtr->arb;
+
+ /*
+ * Special case closing the root
+ */
+ if (h->stackPtr == h->stack) {
+ PORT_Assert(arb->tag & DER_CONSTRUCTED);
+ h->state = parseComplete;
+ } else {
+ SECArb *parent = h->stackPtr->parent;
+ parent->body.cons.subs = DS_ArenaGrow(
+ h->his, parent->body.cons.subs,
+ (parent->body.cons.numSubs) * sizeof(SECArb*),
+ (parent->body.cons.numSubs + 1) * sizeof(SECArb*));
+ parent->body.cons.subs[parent->body.cons.numSubs] = arb;
+ parent->body.cons.numSubs++;
+ h->proc = ParseTag;
+ h->state = notDone;
+ h->pending = UNKNOWN;
+ }
+ if (h->after)
+ (*h->after)(h->afterArg, arb, h->stackPtr - h->stack, PR_FALSE);
+}
+
+SECStatus BER_ParseSome(BERParse *h, unsigned char *buf, int len)
+{
+ if (h->state == parseError) return PR_TRUE;
+
+ while (len) {
+ (*h->proc)(h, &buf, &len);
+ if (h->state == parseComplete) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ if (h->state == parseError) return PR_TRUE;
+ PORT_Assert(h->state != parseComplete);
+
+ if (h->state <= compositeDone) {
+ if (h->proc == ParseTag) {
+ PORT_Assert(h->state == tagDone);
+ h->proc = ParseLength;
+ h->state = notDone;
+ } else if (h->proc == ParseLength) {
+ SECArb *arb = &(h->stackPtr->arb);
+ PORT_Assert(h->state == lengthDone || h->state == compositeDone);
+
+ if (h->before)
+ (*h->before)(h->beforeArg, arb,
+ h->stackPtr - h->stack, PR_TRUE);
+
+ /*
+ * Check to see if this is the end of an indefinite
+ * length composite
+ */
+ if (h->state == compositeDone) {
+ SECArb *parent = h->stackPtr->parent;
+ PORT_Assert(parent);
+ PORT_Assert(parent->tag & DER_CONSTRUCTED);
+ if (parent->length != 0) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ /*
+ * NOTE: This does not check for an indefinite length
+ * composite being contained inside a definite length
+ * composite. It is not clear that is legal.
+ */
+ h->stackPtr--;
+ CreateArbNode(h);
+ } else {
+ h->stackPtr->pos = h->pos;
+
+
+ if (arb->tag & DER_CONSTRUCTED) {
+ SECArb *parent;
+ /*
+ * Make sure there is room on the stack before we
+ * stick anything else there.
+ */
+ PORT_Assert(h->stackPtr - h->stack < h->stackDepth);
+ if (h->stackPtr - h->stack == h->stackDepth - 1) {
+ int newDepth = h->stackDepth * 2;
+ h->stack = DS_ArenaGrow(h->mine, h->stack,
+ sizeof(ParseStackElem) * h->stackDepth,
+ sizeof(ParseStackElem) * newDepth);
+ h->stackPtr = h->stack + h->stackDepth + 1;
+ h->stackDepth = newDepth;
+ }
+ parent = &(h->stackPtr->arb);
+ h->stackPtr++;
+ h->stackPtr->parent = parent;
+ h->proc = ParseTag;
+ h->state = notDone;
+ h->pending = UNKNOWN;
+ } else {
+ if (arb->length < 0) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ arb->body.item.len = 0;
+ if (arb->length > 0 && h->keepLeaves) {
+ arb->body.item.data =
+ PORT_ArenaAlloc(h->his, arb->length);
+ } else {
+ arb->body.item.data = NULL;
+ }
+ h->proc = ParseLeaf;
+ h->state = notDone;
+ h->pending = arb->length;
+ }
+ }
+ } else {
+ ParseStackElem *parent;
+ PORT_Assert(h->state = leafDone);
+ PORT_Assert(h->proc == ParseLeaf);
+
+ for (;;) {
+ CreateArbNode(h);
+ if (h->stackPtr == h->stack)
+ break;
+ parent = (h->stackPtr - 1);
+ PORT_Assert(parent->arb.tag & DER_CONSTRUCTED);
+ if (parent->arb.length == 0) /* need explicit end */
+ break;
+ if (parent->pos + parent->arb.length > h->pos)
+ break;
+ if (parent->pos + parent->arb.length < h->pos) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ h->state = parseError;
+ return PR_TRUE;
+ }
+ h->stackPtr = parent;
+ }
+ }
+
+ }
+ }
+ return PR_FALSE;
+}
+BERParse *BER_ParseInit(PLArenaPool *arena, PRBool derOnly)
+{
+ BERParse *h;
+ PLArenaPool *temp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (temp == NULL) {
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+ h = PORT_ArenaAlloc(temp, sizeof(BERParse));
+ if (h == NULL) {
+ PORT_FreeArena(temp, PR_FALSE);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return NULL;
+ }
+ h->his = arena;
+ h->mine = temp;
+ h->proc = ParseTag;
+ h->stackDepth = 20;
+ h->stack = PORT_ArenaZAlloc(h->mine,
+ sizeof(ParseStackElem) * h->stackDepth);
+ h->stackPtr = h->stack;
+ h->state = notDone;
+ h->pos = 0;
+ h->keepLeaves = PR_TRUE;
+ h->before = NULL;
+ h->after = NULL;
+ h->filter = NULL;
+ h->derOnly = derOnly;
+ return h;
+}
+
+SECArb *BER_ParseFini(BERParse *h)
+{
+ PLArenaPool *myArena = h->mine;
+ SECArb *arb;
+
+ if (h->state != parseComplete) {
+ arb = NULL;
+ } else {
+ arb = PORT_ArenaAlloc(h->his, sizeof(SECArb));
+ *arb = h->stackPtr->arb;
+ }
+
+ PORT_FreeArena(myArena, PR_FALSE);
+
+ return arb;
+}
+
+
+void BER_SetFilter(BERParse *h, BERFilterProc proc, void *instance)
+{
+ h->filter = proc;
+ h->filterArg = instance;
+}
+
+void BER_SetLeafStorage(BERParse *h, PRBool keep)
+{
+ h->keepLeaves = keep;
+}
+
+void BER_SetNotifyProc(BERParse *h, BERNotifyProc proc, void *instance,
+ PRBool beforeData)
+{
+ if (beforeData) {
+ h->before = proc;
+ h->beforeArg = instance;
+ } else {
+ h->after = proc;
+ h->afterArg = instance;
+ }
+}
+
+
+
diff --git a/nss/cmd/lib/config.mk b/nss/cmd/lib/config.mk
new file mode 100644
index 0000000..b8c03de
--- /dev/null
+++ b/nss/cmd/lib/config.mk
@@ -0,0 +1,15 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#
+# Override TARGETS variable so that only static libraries
+# are specifed as dependencies within rules.mk.
+#
+
+TARGETS = $(LIBRARY)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+PROGRAM =
+
diff --git a/nss/cmd/lib/derprint.c b/nss/cmd/lib/derprint.c
new file mode 100644
index 0000000..b4eb0ff
--- /dev/null
+++ b/nss/cmd/lib/derprint.c
@@ -0,0 +1,590 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "secutil.h"
+#include "secoid.h"
+
+#ifdef __sun
+extern int fprintf(FILE *strm, const char *format, .../* args */);
+extern int fflush(FILE *stream);
+#endif
+
+#define RIGHT_MARGIN 24
+/*#define RAW_BYTES 1 */
+
+static int prettyColumn = 0;
+
+static int
+getInteger256(const unsigned char *data, unsigned int nb)
+{
+ int val;
+
+ switch (nb) {
+ case 1:
+ val = data[0];
+ break;
+ case 2:
+ val = (data[0] << 8) | data[1];
+ break;
+ case 3:
+ val = (data[0] << 16) | (data[1] << 8) | data[2];
+ break;
+ case 4:
+ val = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+ break;
+ default:
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ return val;
+}
+
+static int
+prettyNewline(FILE *out)
+{
+ int rv;
+
+ if (prettyColumn != -1) {
+ rv = fprintf(out, "\n");
+ prettyColumn = -1;
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+ return 0;
+}
+
+static int
+prettyIndent(FILE *out, unsigned level)
+{
+ unsigned int i;
+ int rv;
+
+ if (prettyColumn == -1) {
+ prettyColumn = level;
+ for (i = 0; i < level; i++) {
+ rv = fprintf(out, " ");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintByte(FILE *out, unsigned char item, unsigned int level)
+{
+ int rv;
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ rv = fprintf(out, "%02x ", item);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ prettyColumn++;
+ if (prettyColumn >= RIGHT_MARGIN) {
+ return prettyNewline(out);
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintLeaf(FILE *out, const unsigned char *data,
+ unsigned int len, unsigned int lv)
+{
+ unsigned int i;
+ int rv;
+
+ for (i = 0; i < len; i++) {
+ rv = prettyPrintByte(out, *data++, lv);
+ if (rv < 0)
+ return rv;
+ }
+ return prettyNewline(out);
+}
+
+static int
+prettyPrintStringStart(FILE *out, const unsigned char *str,
+ unsigned int len, unsigned int level)
+{
+#define BUF_SIZE 100
+ unsigned char buf[BUF_SIZE];
+ int rv;
+
+ if (len >= BUF_SIZE)
+ len = BUF_SIZE - 1;
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ memcpy(buf, str, len);
+ buf[len] = '\000';
+
+ rv = fprintf(out, "\"%s\"", buf);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ return 0;
+#undef BUF_SIZE
+}
+
+static int
+prettyPrintString(FILE *out, const unsigned char *str,
+ unsigned int len, unsigned int level, PRBool raw)
+{
+ int rv;
+
+ rv = prettyPrintStringStart(out, str, len, level);
+ if (rv < 0)
+ return rv;
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ if (raw) {
+ rv = prettyPrintLeaf(out, str, len, level);
+ if (rv < 0)
+ return rv;
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintTime(FILE *out, const unsigned char *str,
+ unsigned int len, unsigned int level, PRBool raw, PRBool utc)
+{
+ SECItem time_item;
+ int rv;
+
+ rv = prettyPrintStringStart(out, str, len, level);
+ if (rv < 0)
+ return rv;
+
+ time_item.data = (unsigned char *)str;
+ time_item.len = len;
+
+ rv = fprintf(out, " (");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ if (utc)
+ SECU_PrintUTCTime(out, &time_item, NULL, 0);
+ else
+ SECU_PrintGeneralizedTime(out, &time_item, NULL, 0);
+
+ rv = fprintf(out, ")");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ if (raw) {
+ rv = prettyPrintLeaf(out, str, len, level);
+ if (rv < 0)
+ return rv;
+ }
+
+ return 0;
+}
+
+static int
+prettyPrintObjectID(FILE *out, const unsigned char *data,
+ unsigned int len, unsigned int level, PRBool raw)
+{
+ SECOidData *oiddata;
+ SECItem oiditem;
+ unsigned int i;
+ unsigned long val;
+ int rv;
+
+
+ /*
+ * First print the Object Id in numeric format
+ */
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ val = data[0];
+ i = val % 40;
+ val = val / 40;
+ rv = fprintf(out, "%lu %u ", val, i);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ val = 0;
+ for (i = 1; i < len; ++i) {
+ unsigned long j;
+
+ j = data[i];
+ val = (val << 7) | (j & 0x7f);
+ if (j & 0x80)
+ continue;
+ rv = fprintf(out, "%lu ", val);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ val = 0;
+ }
+
+ /*
+ * Now try to look it up and print a symbolic version.
+ */
+ oiditem.data = (unsigned char *)data;
+ oiditem.len = len;
+ oiddata = SECOID_FindOID(&oiditem);
+ if (oiddata != NULL) {
+ i = PORT_Strlen(oiddata->desc);
+ if ((prettyColumn + 1 + (i / 3)) > RIGHT_MARGIN) {
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+ }
+
+ rv = prettyIndent(out, level);
+ if (rv < 0)
+ return rv;
+
+ rv = fprintf(out, "(%s)", oiddata->desc);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+
+ /*
+ * Finally, on a new line, print the raw bytes (if requested).
+ */
+ if (raw) {
+ rv = prettyNewline(out);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ for (i = 0; i < len; i++) {
+ rv = prettyPrintByte(out, *data++, level);
+ if (rv < 0)
+ return rv;
+ }
+ }
+
+ return prettyNewline(out);
+}
+
+static char *prettyTagType [32] = {
+ "End of Contents",
+ "Boolean",
+ "Integer",
+ "Bit String",
+ "Octet String",
+ "NULL",
+ "Object Identifier",
+ "0x07",
+ "0x08",
+ "0x09",
+ "Enumerated",
+ "0x0B",
+ "UTF8 String",
+ "0x0D",
+ "0x0E",
+ "0x0F",
+ "Sequence",
+ "Set",
+ "0x12",
+ "Printable String",
+ "T61 String",
+ "0x15",
+ "IA5 String",
+ "UTC Time",
+ "Generalized Time",
+ "0x19",
+ "Visible String",
+ "0x1B",
+ "Universal String",
+ "0x1D",
+ "BMP String",
+ "High-Tag-Number"
+};
+
+static int
+prettyPrintTag(FILE *out, const unsigned char *src, const unsigned char *end,
+ unsigned char *codep, unsigned int level, PRBool raw)
+{
+ int rv;
+ unsigned char code, tagnum;
+
+ if (src >= end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ code = *src;
+ tagnum = code & SEC_ASN1_TAGNUM_MASK;
+
+ /*
+ * NOTE: This code does not (yet) handle the high-tag-number form!
+ */
+ if (tagnum == SEC_ASN1_HIGH_TAG_NUMBER) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ if (raw)
+ rv = prettyPrintByte(out, code, level);
+ else
+ rv = prettyIndent(out, level);
+
+ if (rv < 0)
+ return rv;
+
+ if (code & SEC_ASN1_CONSTRUCTED) {
+ rv = fprintf(out, "C-");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+ }
+
+ switch (code & SEC_ASN1_CLASS_MASK) {
+ case SEC_ASN1_UNIVERSAL:
+ rv = fprintf(out, "%s ", prettyTagType[tagnum]);
+ break;
+ case SEC_ASN1_APPLICATION:
+ rv = fprintf(out, "Application: %d ", tagnum);
+ break;
+ case SEC_ASN1_CONTEXT_SPECIFIC:
+ rv = fprintf(out, "[%d] ", tagnum);
+ break;
+ case SEC_ASN1_PRIVATE:
+ rv = fprintf(out, "Private: %d ", tagnum);
+ break;
+ }
+
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ *codep = code;
+
+ return 1;
+}
+
+static int
+prettyPrintLength(FILE *out, const unsigned char *data, const unsigned char *end,
+ int *lenp, PRBool *indefinitep, unsigned int lv, PRBool raw)
+{
+ unsigned char lbyte;
+ int lenLen;
+ int rv;
+
+ if (data >= end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ rv = fprintf(out, " ");
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ *indefinitep = PR_FALSE;
+
+ lbyte = *data++;
+ if (lbyte >= 0x80) {
+ /* Multibyte length */
+ unsigned nb = (unsigned) (lbyte & 0x7f);
+ if (nb > 4) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ if (nb > 0) {
+ int il;
+
+ if ((data + nb) > end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ il = getInteger256(data, nb);
+ if (il < 0) return -1;
+ *lenp = (unsigned) il;
+ } else {
+ *lenp = 0;
+ *indefinitep = PR_TRUE;
+ }
+ lenLen = nb + 1;
+ if (raw) {
+ int i;
+
+ rv = prettyPrintByte(out, lbyte, lv);
+ if (rv < 0)
+ return rv;
+ for (i = 0; i < nb; i++) {
+ rv = prettyPrintByte(out, data[i], lv);
+ if (rv < 0)
+ return rv;
+ }
+ }
+ } else {
+ *lenp = lbyte;
+ lenLen = 1;
+ if (raw) {
+ rv = prettyPrintByte(out, lbyte, lv);
+ if (rv < 0)
+ return rv;
+ }
+ }
+ if (*indefinitep)
+ rv = fprintf(out, "(indefinite)\n");
+ else
+ rv = fprintf(out, "(%d)\n", *lenp);
+ if (rv < 0) {
+ PORT_SetError(SEC_ERROR_IO);
+ return rv;
+ }
+
+ prettyColumn = -1;
+ return lenLen;
+}
+
+static int
+prettyPrintItem(FILE *out, const unsigned char *data, const unsigned char *end,
+ unsigned int lv, PRBool raw)
+{
+ int slen;
+ int lenLen;
+ const unsigned char *orig = data;
+ int rv;
+
+ while (data < end) {
+ unsigned char code;
+ PRBool indefinite;
+
+ slen = prettyPrintTag(out, data, end, &code, lv, raw);
+ if (slen < 0)
+ return slen;
+ data += slen;
+
+ lenLen = prettyPrintLength(out, data, end, &slen, &indefinite, lv, raw);
+ if (lenLen < 0)
+ return lenLen;
+ data += lenLen;
+
+ /*
+ * Just quit now if slen more bytes puts us off the end.
+ */
+ if ((data + slen) > end) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+
+ if (code & SEC_ASN1_CONSTRUCTED) {
+ if (slen > 0 || indefinite) {
+ slen = prettyPrintItem(out, data,
+ slen == 0 ? end : data + slen,
+ lv+1, raw);
+ if (slen < 0)
+ return slen;
+ data += slen;
+ }
+ } else if (code == 0) {
+ if (slen != 0 || lenLen != 1) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ break;
+ } else {
+ switch (code) {
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ rv = prettyPrintString(out, data, slen, lv+1, raw);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_UTC_TIME:
+ rv = prettyPrintTime(out, data, slen, lv+1, raw, PR_TRUE);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_GENERALIZED_TIME:
+ rv = prettyPrintTime(out, data, slen, lv+1, raw, PR_FALSE);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_OBJECT_ID:
+ rv = prettyPrintObjectID(out, data, slen, lv+1, raw);
+ if (rv < 0)
+ return rv;
+ break;
+ case SEC_ASN1_BOOLEAN: /* could do nicer job */
+ case SEC_ASN1_INTEGER: /* could do nicer job */
+ case SEC_ASN1_BIT_STRING: /* could do nicer job */
+ case SEC_ASN1_OCTET_STRING:
+ case SEC_ASN1_NULL:
+ case SEC_ASN1_ENUMERATED: /* could do nicer job, as INTEGER */
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_T61_STRING: /* print as printable string? */
+ case SEC_ASN1_UNIVERSAL_STRING:
+ case SEC_ASN1_BMP_STRING:
+ default:
+ rv = prettyPrintLeaf(out, data, slen, lv+1);
+ if (rv < 0)
+ return rv;
+ break;
+ }
+ data += slen;
+ }
+ }
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ return data - orig;
+}
+
+SECStatus
+DER_PrettyPrint(FILE *out, const SECItem *it, PRBool raw)
+{
+ int rv;
+
+ prettyColumn = -1;
+
+ rv = prettyPrintItem(out, it->data, it->data + it->len, 0, raw);
+ if (rv < 0)
+ return SECFailure;
+ return SECSuccess;
+}
diff --git a/nss/cmd/lib/ffs.c b/nss/cmd/lib/ffs.c
new file mode 100644
index 0000000..8456181
--- /dev/null
+++ b/nss/cmd/lib/ffs.c
@@ -0,0 +1,19 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#if !defined(XP_UNIX) && !defined(XP_OS2)
+
+int ffs( unsigned int i)
+{
+ int rv = 1;
+
+ if (!i) return 0;
+
+ while (!(i & 1)) {
+ i >>= 1;
+ ++rv;
+ }
+
+ return rv;
+}
+#endif
diff --git a/nss/cmd/lib/manifest.mn b/nss/cmd/lib/manifest.mn
new file mode 100644
index 0000000..87440c0
--- /dev/null
+++ b/nss/cmd/lib/manifest.mn
@@ -0,0 +1,39 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+CORE_DEPTH = ../..
+
+LIBRARY_NAME = sectool
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+DEFINES = -DNSPR20
+
+ifdef NSS_BUILD_SOFTOKEN_ONLY
+PRIVATE_EXPORTS = basicutil.h \
+ pk11table.h \
+ $(NULL)
+
+CSRCS = basicutil.c \
+ pk11table.c \
+ $(NULL)
+else
+PRIVATE_EXPORTS = basicutil.h \
+ secutil.h \
+ pk11table.h \
+ $(NULL)
+
+CSRCS = basicutil.c \
+ secutil.c \
+ secpwd.c \
+ derprint.c \
+ moreoids.c \
+ pppolicy.c \
+ ffs.c \
+ pk11table.c \
+ $(NULL)
+endif
+
+NO_MD_RELEASE = 1
diff --git a/nss/cmd/lib/moreoids.c b/nss/cmd/lib/moreoids.c
new file mode 100644
index 0000000..6c18476
--- /dev/null
+++ b/nss/cmd/lib/moreoids.c
@@ -0,0 +1,159 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "secoid.h"
+#include "secmodt.h" /* for CKM_INVALID_MECHANISM */
+
+#define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
+#define OD(oid,tag,desc,mech,ext) { OI(oid), tag, desc, mech, ext }
+#define ODN(oid,desc) \
+ { OI(oid), 0, desc, CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION }
+
+#define OIDT static const unsigned char
+
+/* OIW Security Special Interest Group defined algorithms. */
+#define OIWSSIG 0x2B, 13, 3, 2
+
+OIDT oiwMD5RSA[] = { OIWSSIG, 3 };
+OIDT oiwDESCBC[] = { OIWSSIG, 7 };
+OIDT oiwRSAsig[] = { OIWSSIG, 11 };
+OIDT oiwDSA [] = { OIWSSIG, 12 };
+OIDT oiwMD5RSAsig[] = { OIWSSIG, 25 };
+OIDT oiwSHA1 [] = { OIWSSIG, 26 };
+OIDT oiwDSASHA1[] = { OIWSSIG, 27 };
+OIDT oiwDSASHA1param[] = { OIWSSIG, 28 };
+OIDT oiwSHA1RSA[] = { OIWSSIG, 29 };
+
+
+/* Microsoft OIDs. (1 3 6 1 4 1 311 ... ) */
+#define MICROSOFT 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37
+
+OIDT mCTL[] = { MICROSOFT, 10, 3, 1 }; /* Cert Trust List signing */
+OIDT mTSS[] = { MICROSOFT, 10, 3, 2 }; /* Time Stamp Signing */
+OIDT mSGC[] = { MICROSOFT, 10, 3, 3 }; /* Server gated cryptography */
+OIDT mEFS[] = { MICROSOFT, 10, 3, 4 }; /* Encrypted File System */
+OIDT mSMIME[] = { MICROSOFT, 16, 4 }; /* SMIME encryption key prefs */
+
+OIDT mECRTT[] = { MICROSOFT, 20, 2 }; /* Enrollment cert type xtn */
+OIDT mEAGNT[] = { MICROSOFT, 20, 2, 1 }; /* Enrollment Agent */
+OIDT mKPSCL[] = { MICROSOFT, 20, 2, 2 }; /* KP SmartCard Logon */
+OIDT mNTPN [] = { MICROSOFT, 20, 2, 3 }; /* NT Principal Name */
+OIDT mCASRV[] = { MICROSOFT, 21, 1 }; /* CertServ CA version */
+
+/* AOL OIDs (1 3 6 1 4 1 1066 ... ) */
+#define AOL 0x2B, 0x06, 0x01, 0x04, 0x01, 0x88, 0x2A
+
+/* PKIX IDs (1 3 6 1 5 5 7 ...) */
+#define ID_PKIX 0x2B, 6, 1, 5, 5, 7
+/* PKIX Access Descriptors (methods for Authority Info Access Extns) */
+#define ID_AD ID_PKIX, 48
+
+OIDT padOCSP[] = { ID_AD, 1 }; /* OCSP method */
+OIDT padCAissuer[] = { ID_AD, 2 }; /* URI (for CRL ?) */
+OIDT padTimeStamp[] = { ID_AD, 3 }; /* time stamping */
+
+/* ISO Cert Extension type OIDs (id-ce) (2 5 29 ...) */
+#define X500 0x55
+#define X520_ATTRIBUTE_TYPE X500, 0x04
+#define X500_ALG X500, 0x08
+#define X500_ALG_ENCRYPTION X500_ALG, 0x01
+#define ID_CE X500, 29
+
+OIDT cePlcyObs[] = { ID_CE, 3 }; /* Cert policies, obsolete. */
+OIDT cePlcyCns[] = { ID_CE, 36 }; /* Cert policy constraints. */
+
+/* US Company arc (2 16 840 1 ...) */
+#define USCOM 0x60, 0x86, 0x48, 0x01
+#define USGOV USCOM, 0x65
+#define USDOD USGOV, 2
+#define ID_INFOSEC USDOD, 1
+
+/* Verisign PKI OIDs (2 16 840 1 113733 1 ...) */
+#define VERISIGN_PKI USCOM, 0x86, 0xf8, 0x45, 1
+#define VERISIGN_XTN VERISIGN_PKI, 6
+#define VERISIGN_POL VERISIGN_PKI, 7 /* Cert policies */
+#define VERISIGN_TNET VERISIGN_POL, 23 /* Verisign Trust Network */
+
+OIDT vcx7[] = { VERISIGN_XTN, 7 }; /* Cert Extension 7 (?) */
+OIDT vcp1[] = { VERISIGN_TNET, 1 }; /* class 1 cert policy */
+OIDT vcp2[] = { VERISIGN_TNET, 2 }; /* class 2 cert policy */
+OIDT vcp3[] = { VERISIGN_TNET, 3 }; /* class 3 cert policy */
+OIDT vcp4[] = { VERISIGN_TNET, 4 }; /* class 4 cert policy */
+
+
+/* ------------------------------------------------------------------- */
+static const SECOidData oids[] = {
+/* OIW Security Special Interest Group OIDs */
+ ODN( oiwMD5RSA, "OIWSecSIG MD5 with RSA"),
+ ODN( oiwDESCBC, "OIWSecSIG DES CBC"),
+ ODN( oiwRSAsig, "OIWSecSIG RSA signature"),
+ ODN( oiwDSA , "OIWSecSIG DSA"),
+ ODN( oiwMD5RSAsig, "OIWSecSIG MD5 with RSA signature"),
+ ODN( oiwSHA1 , "OIWSecSIG SHA1"),
+ ODN( oiwDSASHA1, "OIWSecSIG DSA with SHA1"),
+ ODN( oiwDSASHA1param, "OIWSecSIG DSA with SHA1 with params"),
+ ODN( oiwSHA1RSA, "OIWSecSIG MD5 with RSA"),
+
+/* Microsoft OIDs */
+ ODN( mCTL, "Microsoft Cert Trust List signing"),
+ ODN( mTSS, "Microsoft Time Stamp signing"),
+ ODN( mSGC, "Microsoft SGC SSL server"),
+ ODN( mEFS, "Microsoft Encrypted File System"),
+ ODN( mSMIME, "Microsoft SMIME preferences"),
+ ODN( mECRTT, "Microsoft Enrollment Cert Type Extension"),
+ ODN( mEAGNT, "Microsoft Enrollment Agent"),
+ ODN( mKPSCL, "Microsoft KP SmartCard Logon"),
+ ODN( mNTPN, "Microsoft NT Principal Name"),
+ ODN( mCASRV, "Microsoft CertServ CA version"),
+
+/* PKIX OIDs */
+ ODN( padOCSP, "PKIX OCSP method"),
+ ODN( padCAissuer, "PKIX CA Issuer method"),
+ ODN( padTimeStamp, "PKIX Time Stamping method"),
+
+/* ID_CE OIDs. */
+ ODN( cePlcyObs, "Certificate Policies (Obsolete)"),
+ ODN( cePlcyCns, "Certificate Policy Constraints"),
+
+/* Verisign OIDs. */
+ ODN( vcx7, "Verisign Cert Extension 7 (?)"),
+ ODN( vcp1, "Verisign Class 1 Certificate Policy"),
+ ODN( vcp2, "Verisign Class 2 Certificate Policy"),
+ ODN( vcp3, "Verisign Class 3 Certificate Policy"),
+ ODN( vcp4, "Verisign Class 4 Certificate Policy"),
+
+};
+
+static const unsigned int numOids = (sizeof oids) / (sizeof oids[0]);
+
+/* Fetch and register an oid if it hasn't been done already */
+void
+SECU_cert_fetchOID(SECOidTag *data, const SECOidData *src)
+{
+ if (*data == SEC_OID_UNKNOWN) {
+ /* AddEntry does the right thing if someone else has already
+ * added the oid. (that is return that oid tag) */
+ *data = SECOID_AddEntry(src);
+ }
+}
+
+SECStatus
+SECU_RegisterDynamicOids(void)
+{
+ unsigned int i;
+ SECStatus rv = SECSuccess;
+
+ for (i = 0; i < numOids; ++i) {
+ SECOidTag tag = SECOID_AddEntry(&oids[i]);
+ if (tag == SEC_OID_UNKNOWN) {
+ rv = SECFailure;
+#ifdef DEBUG_DYN_OIDS
+ fprintf(stderr, "Add OID[%d] failed\n", i);
+ } else {
+ fprintf(stderr, "Add OID[%d] returned tag %d\n", i, tag);
+#endif
+ }
+ }
+ return rv;
+}
diff --git a/nss/cmd/lib/pk11table.c b/nss/cmd/lib/pk11table.c
new file mode 100644
index 0000000..d979835
--- /dev/null
+++ b/nss/cmd/lib/pk11table.c
@@ -0,0 +1,1420 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "pk11table.h"
+
+const char *_valueString[] = {
+ "None",
+ "Variable",
+ "CK_ULONG",
+ "Data",
+ "UTF8",
+ "CK_INFO",
+ "CK_SLOT_INFO",
+ "CK_TOKEN_INFO",
+ "CK_SESSION_INFO",
+ "CK_ATTRIBUTE",
+ "CK_MECHANISM",
+ "CK_MECHANISM_INFO",
+ "CK_C_INITIALIZE_ARGS",
+ "CK_FUNCTION_LIST"
+};
+
+const char **valueString = &_valueString[0];
+const int valueCount = sizeof(_valueString)/sizeof(_valueString[0]);
+
+const char *_constTypeString[] = {
+ "None",
+ "Bool",
+ "InfoFlags",
+ "SlotFlags",
+ "TokenFlags",
+ "SessionFlags",
+ "MechanismFlags",
+ "InitializeFlags",
+ "Users",
+ "SessionState",
+ "Object",
+ "Hardware",
+ "KeyType",
+ "CertificateType",
+ "Attribute",
+ "Mechanism",
+ "Result",
+ "Trust",
+ "AvailableSizes",
+ "CurrentSize"
+};
+
+const char **constTypeString = &_constTypeString[0];
+const int constTypeCount = sizeof(_constTypeString)/sizeof(_constTypeString[0]);
+
+#define mkEntry(x,t) { #x, x, Const##t, ConstNone }
+#define mkEntry2(x,t,t2) { #x, x, Const##t, Const##t2 }
+
+const Constant _consts[] = {
+ mkEntry(CK_FALSE, Bool),
+ mkEntry(CK_TRUE, Bool),
+
+ mkEntry(CKF_TOKEN_PRESENT, SlotFlags),
+ mkEntry(CKF_REMOVABLE_DEVICE, SlotFlags),
+ mkEntry(CKF_HW_SLOT, SlotFlags),
+
+ mkEntry(CKF_RNG, TokenFlags),
+ mkEntry(CKF_WRITE_PROTECTED, TokenFlags),
+ mkEntry(CKF_LOGIN_REQUIRED, TokenFlags),
+ mkEntry(CKF_USER_PIN_INITIALIZED, TokenFlags),
+ mkEntry(CKF_RESTORE_KEY_NOT_NEEDED, TokenFlags),
+ mkEntry(CKF_CLOCK_ON_TOKEN, TokenFlags),
+ mkEntry(CKF_PROTECTED_AUTHENTICATION_PATH, TokenFlags),
+ mkEntry(CKF_DUAL_CRYPTO_OPERATIONS, TokenFlags),
+ mkEntry(CKF_TOKEN_INITIALIZED, TokenFlags),
+ mkEntry(CKF_SECONDARY_AUTHENTICATION, TokenFlags),
+ mkEntry(CKF_USER_PIN_COUNT_LOW, TokenFlags),
+ mkEntry(CKF_USER_PIN_FINAL_TRY, TokenFlags),
+ mkEntry(CKF_USER_PIN_LOCKED, TokenFlags),
+ mkEntry(CKF_USER_PIN_TO_BE_CHANGED, TokenFlags),
+ mkEntry(CKF_SO_PIN_COUNT_LOW, TokenFlags),
+ mkEntry(CKF_SO_PIN_FINAL_TRY, TokenFlags),
+ mkEntry(CKF_SO_PIN_LOCKED, TokenFlags),
+ mkEntry(CKF_SO_PIN_TO_BE_CHANGED, TokenFlags),
+
+ mkEntry(CKF_RW_SESSION, SessionFlags),
+ mkEntry(CKF_SERIAL_SESSION, SessionFlags),
+
+ mkEntry(CKF_HW, MechanismFlags),
+ mkEntry(CKF_ENCRYPT, MechanismFlags),
+ mkEntry(CKF_DECRYPT, MechanismFlags),
+ mkEntry(CKF_DIGEST, MechanismFlags),
+ mkEntry(CKF_SIGN, MechanismFlags),
+ mkEntry(CKF_SIGN_RECOVER, MechanismFlags),
+ mkEntry(CKF_VERIFY, MechanismFlags),
+ mkEntry(CKF_VERIFY_RECOVER, MechanismFlags),
+ mkEntry(CKF_GENERATE, MechanismFlags),
+ mkEntry(CKF_GENERATE_KEY_PAIR, MechanismFlags),
+ mkEntry(CKF_WRAP, MechanismFlags),
+ mkEntry(CKF_UNWRAP, MechanismFlags),
+ mkEntry(CKF_DERIVE, MechanismFlags),
+ mkEntry(CKF_EC_FP, MechanismFlags),
+ mkEntry(CKF_EC_F_2M, MechanismFlags),
+ mkEntry(CKF_EC_ECPARAMETERS, MechanismFlags),
+ mkEntry(CKF_EC_NAMEDCURVE, MechanismFlags),
+ mkEntry(CKF_EC_UNCOMPRESS, MechanismFlags),
+ mkEntry(CKF_EC_COMPRESS, MechanismFlags),
+
+ mkEntry(CKF_LIBRARY_CANT_CREATE_OS_THREADS, InitializeFlags),
+ mkEntry(CKF_OS_LOCKING_OK, InitializeFlags),
+
+ mkEntry(CKU_SO, Users),
+ mkEntry(CKU_USER, Users),
+
+ mkEntry(CKS_RO_PUBLIC_SESSION, SessionState),
+ mkEntry(CKS_RO_USER_FUNCTIONS, SessionState),
+ mkEntry(CKS_RW_PUBLIC_SESSION, SessionState),
+ mkEntry(CKS_RW_USER_FUNCTIONS, SessionState),
+ mkEntry(CKS_RW_SO_FUNCTIONS, SessionState),
+
+ mkEntry(CKO_DATA, Object),
+ mkEntry(CKO_CERTIFICATE, Object),
+ mkEntry(CKO_PUBLIC_KEY, Object),
+ mkEntry(CKO_PRIVATE_KEY, Object),
+ mkEntry(CKO_SECRET_KEY, Object),
+ mkEntry(CKO_HW_FEATURE, Object),
+ mkEntry(CKO_DOMAIN_PARAMETERS, Object),
+ mkEntry(CKO_KG_PARAMETERS, Object),
+ mkEntry(CKO_NSS_CRL, Object),
+ mkEntry(CKO_NSS_SMIME, Object),
+ mkEntry(CKO_NSS_TRUST, Object),
+ mkEntry(CKO_NSS_BUILTIN_ROOT_LIST, Object),
+
+ mkEntry(CKH_MONOTONIC_COUNTER, Hardware),
+ mkEntry(CKH_CLOCK, Hardware),
+
+ mkEntry(CKK_RSA, KeyType),
+ mkEntry(CKK_DSA, KeyType),
+ mkEntry(CKK_DH, KeyType),
+ mkEntry(CKK_ECDSA, KeyType),
+ mkEntry(CKK_EC, KeyType),
+ mkEntry(CKK_X9_42_DH, KeyType),
+ mkEntry(CKK_KEA, KeyType),
+ mkEntry(CKK_GENERIC_SECRET, KeyType),
+ mkEntry(CKK_RC2, KeyType),
+ mkEntry(CKK_RC4, KeyType),
+ mkEntry(CKK_DES, KeyType),
+ mkEntry(CKK_DES2, KeyType),
+ mkEntry(CKK_DES3, KeyType),
+ mkEntry(CKK_CAST, KeyType),
+ mkEntry(CKK_CAST3, KeyType),
+ mkEntry(CKK_CAST5, KeyType),
+ mkEntry(CKK_CAST128, KeyType),
+ mkEntry(CKK_RC5, KeyType),
+ mkEntry(CKK_IDEA, KeyType),
+ mkEntry(CKK_SKIPJACK, KeyType),
+ mkEntry(CKK_BATON, KeyType),
+ mkEntry(CKK_JUNIPER, KeyType),
+ mkEntry(CKK_CDMF, KeyType),
+ mkEntry(CKK_AES, KeyType),
+ mkEntry(CKK_CAMELLIA, KeyType),
+ mkEntry(CKK_NSS_PKCS8, KeyType),
+
+ mkEntry(CKC_X_509, CertType),
+ mkEntry(CKC_X_509_ATTR_CERT, CertType),
+
+ mkEntry2(CKA_CLASS, Attribute, Object),
+ mkEntry2(CKA_TOKEN, Attribute, Bool),
+ mkEntry2(CKA_PRIVATE, Attribute, Bool),
+ mkEntry2(CKA_LABEL, Attribute, None),
+ mkEntry2(CKA_APPLICATION, Attribute, None),
+ mkEntry2(CKA_VALUE, Attribute, None),
+ mkEntry2(CKA_OBJECT_ID, Attribute, None),
+ mkEntry2(CKA_CERTIFICATE_TYPE, Attribute, CertType),
+ mkEntry2(CKA_ISSUER, Attribute, None),
+ mkEntry2(CKA_SERIAL_NUMBER, Attribute, None),
+ mkEntry2(CKA_AC_ISSUER, Attribute, None),
+ mkEntry2(CKA_OWNER, Attribute, None),
+ mkEntry2(CKA_ATTR_TYPES, Attribute, None),
+ mkEntry2(CKA_TRUSTED, Attribute, Bool),
+ mkEntry2(CKA_KEY_TYPE, Attribute, KeyType),
+ mkEntry2(CKA_SUBJECT, Attribute, None),
+ mkEntry2(CKA_ID, Attribute, None),
+ mkEntry2(CKA_SENSITIVE, Attribute, Bool),
+ mkEntry2(CKA_ENCRYPT, Attribute, Bool),
+ mkEntry2(CKA_DECRYPT, Attribute, Bool),
+ mkEntry2(CKA_WRAP, Attribute, Bool),
+ mkEntry2(CKA_UNWRAP, Attribute, Bool),
+ mkEntry2(CKA_SIGN, Attribute, Bool),
+ mkEntry2(CKA_SIGN_RECOVER, Attribute, Bool),
+ mkEntry2(CKA_VERIFY, Attribute, Bool),
+ mkEntry2(CKA_VERIFY_RECOVER, Attribute, Bool),
+ mkEntry2(CKA_DERIVE, Attribute, Bool),
+ mkEntry2(CKA_START_DATE, Attribute, None),
+ mkEntry2(CKA_END_DATE, Attribute, None),
+ mkEntry2(CKA_MODULUS, Attribute, None),
+ mkEntry2(CKA_MODULUS_BITS, Attribute, None),
+ mkEntry2(CKA_PUBLIC_EXPONENT, Attribute, None),
+ mkEntry2(CKA_PRIVATE_EXPONENT, Attribute, None),
+ mkEntry2(CKA_PRIME_1, Attribute, None),
+ mkEntry2(CKA_PRIME_2, Attribute, None),
+ mkEntry2(CKA_EXPONENT_1, Attribute, None),
+ mkEntry2(CKA_EXPONENT_2, Attribute, None),
+ mkEntry2(CKA_COEFFICIENT, Attribute, None),
+ mkEntry2(CKA_PRIME, Attribute, None),
+ mkEntry2(CKA_SUBPRIME, Attribute, None),
+ mkEntry2(CKA_BASE, Attribute, None),
+ mkEntry2(CKA_PRIME_BITS, Attribute, None),
+ mkEntry2(CKA_SUB_PRIME_BITS, Attribute, None),
+ mkEntry2(CKA_VALUE_BITS, Attribute, None),
+ mkEntry2(CKA_VALUE_LEN, Attribute, None),
+ mkEntry2(CKA_EXTRACTABLE, Attribute, Bool),
+ mkEntry2(CKA_LOCAL, Attribute, Bool),
+ mkEntry2(CKA_NEVER_EXTRACTABLE, Attribute, Bool),
+ mkEntry2(CKA_ALWAYS_SENSITIVE, Attribute, Bool),
+ mkEntry2(CKA_KEY_GEN_MECHANISM, Attribute, Mechanism),
+ mkEntry2(CKA_MODIFIABLE, Attribute, Bool),
+ mkEntry2(CKA_ECDSA_PARAMS, Attribute, None),
+ mkEntry2(CKA_EC_PARAMS, Attribute, None),
+ mkEntry2(CKA_EC_POINT, Attribute, None),
+ mkEntry2(CKA_SECONDARY_AUTH, Attribute, None),
+ mkEntry2(CKA_AUTH_PIN_FLAGS, Attribute, None),
+ mkEntry2(CKA_HW_FEATURE_TYPE, Attribute, Hardware),
+ mkEntry2(CKA_RESET_ON_INIT, Attribute, Bool),
+ mkEntry2(CKA_HAS_RESET, Attribute, Bool),
+ mkEntry2(CKA_NSS_URL, Attribute, None),
+ mkEntry2(CKA_NSS_EMAIL, Attribute, None),
+ mkEntry2(CKA_NSS_SMIME_INFO, Attribute, None),
+ mkEntry2(CKA_NSS_SMIME_TIMESTAMP, Attribute, None),
+ mkEntry2(CKA_NSS_PKCS8_SALT, Attribute, None),
+ mkEntry2(CKA_NSS_PASSWORD_CHECK, Attribute, None),
+ mkEntry2(CKA_NSS_EXPIRES, Attribute, None),
+ mkEntry2(CKA_NSS_KRL, Attribute, None),
+ mkEntry2(CKA_NSS_PQG_COUNTER, Attribute, None),
+ mkEntry2(CKA_NSS_PQG_SEED, Attribute, None),
+ mkEntry2(CKA_NSS_PQG_H, Attribute, None),
+ mkEntry2(CKA_NSS_PQG_SEED_BITS, Attribute, None),
+ mkEntry2(CKA_TRUST_DIGITAL_SIGNATURE, Attribute, Trust),
+ mkEntry2(CKA_TRUST_NON_REPUDIATION, Attribute, Trust),
+ mkEntry2(CKA_TRUST_KEY_ENCIPHERMENT, Attribute, Trust),
+ mkEntry2(CKA_TRUST_DATA_ENCIPHERMENT, Attribute, Trust),
+ mkEntry2(CKA_TRUST_KEY_AGREEMENT, Attribute, Trust),
+ mkEntry2(CKA_TRUST_KEY_CERT_SIGN, Attribute, Trust),
+ mkEntry2(CKA_TRUST_CRL_SIGN, Attribute, Trust),
+ mkEntry2(CKA_TRUST_SERVER_AUTH, Attribute, Trust),
+ mkEntry2(CKA_TRUST_CLIENT_AUTH, Attribute, Trust),
+ mkEntry2(CKA_TRUST_CODE_SIGNING, Attribute, Trust),
+ mkEntry2(CKA_TRUST_EMAIL_PROTECTION, Attribute, Trust),
+ mkEntry2(CKA_TRUST_IPSEC_END_SYSTEM, Attribute, Trust),
+ mkEntry2(CKA_TRUST_IPSEC_TUNNEL, Attribute, Trust),
+ mkEntry2(CKA_TRUST_IPSEC_USER, Attribute, Trust),
+ mkEntry2(CKA_TRUST_TIME_STAMPING, Attribute, Trust),
+ mkEntry2(CKA_CERT_SHA1_HASH, Attribute, None),
+ mkEntry2(CKA_CERT_MD5_HASH, Attribute, None),
+ mkEntry2(CKA_NETSCAPE_DB, Attribute, None),
+ mkEntry2(CKA_NETSCAPE_TRUST, Attribute, Trust),
+
+ mkEntry(CKM_RSA_PKCS, Mechanism),
+ mkEntry(CKM_RSA_9796, Mechanism),
+ mkEntry(CKM_RSA_X_509, Mechanism),
+ mkEntry(CKM_RSA_PKCS_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_MD2_RSA_PKCS, Mechanism),
+ mkEntry(CKM_MD5_RSA_PKCS, Mechanism),
+ mkEntry(CKM_SHA1_RSA_PKCS, Mechanism),
+ mkEntry(CKM_RIPEMD128_RSA_PKCS, Mechanism),
+ mkEntry(CKM_RIPEMD160_RSA_PKCS, Mechanism),
+ mkEntry(CKM_RSA_PKCS_OAEP, Mechanism),
+ mkEntry(CKM_RSA_X9_31_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_RSA_X9_31, Mechanism),
+ mkEntry(CKM_SHA1_RSA_X9_31, Mechanism),
+ mkEntry(CKM_DSA_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_DSA, Mechanism),
+ mkEntry(CKM_DSA_SHA1, Mechanism),
+ mkEntry(CKM_DH_PKCS_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_DH_PKCS_DERIVE, Mechanism),
+ mkEntry(CKM_X9_42_DH_DERIVE, Mechanism),
+ mkEntry(CKM_X9_42_DH_HYBRID_DERIVE, Mechanism),
+ mkEntry(CKM_X9_42_MQV_DERIVE, Mechanism),
+ mkEntry(CKM_SHA256_RSA_PKCS, Mechanism),
+ mkEntry(CKM_SHA384_RSA_PKCS, Mechanism),
+ mkEntry(CKM_SHA512_RSA_PKCS, Mechanism),
+ mkEntry(CKM_RC2_KEY_GEN, Mechanism),
+ mkEntry(CKM_RC2_ECB, Mechanism),
+ mkEntry(CKM_RC2_CBC, Mechanism),
+ mkEntry(CKM_RC2_MAC, Mechanism),
+ mkEntry(CKM_RC2_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_RC2_CBC_PAD, Mechanism),
+ mkEntry(CKM_RC4_KEY_GEN, Mechanism),
+ mkEntry(CKM_RC4, Mechanism),
+ mkEntry(CKM_DES_KEY_GEN, Mechanism),
+ mkEntry(CKM_DES_ECB, Mechanism),
+ mkEntry(CKM_DES_CBC, Mechanism),
+ mkEntry(CKM_DES_MAC, Mechanism),
+ mkEntry(CKM_DES_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_DES_CBC_PAD, Mechanism),
+ mkEntry(CKM_DES2_KEY_GEN, Mechanism),
+ mkEntry(CKM_DES3_KEY_GEN, Mechanism),
+ mkEntry(CKM_DES3_ECB, Mechanism),
+ mkEntry(CKM_DES3_CBC, Mechanism),
+ mkEntry(CKM_DES3_MAC, Mechanism),
+ mkEntry(CKM_DES3_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_DES3_CBC_PAD, Mechanism),
+ mkEntry(CKM_CDMF_KEY_GEN, Mechanism),
+ mkEntry(CKM_CDMF_ECB, Mechanism),
+ mkEntry(CKM_CDMF_CBC, Mechanism),
+ mkEntry(CKM_CDMF_MAC, Mechanism),
+ mkEntry(CKM_CDMF_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CDMF_CBC_PAD, Mechanism),
+ mkEntry(CKM_MD2, Mechanism),
+ mkEntry(CKM_MD2_HMAC, Mechanism),
+ mkEntry(CKM_MD2_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_MD5, Mechanism),
+ mkEntry(CKM_MD5_HMAC, Mechanism),
+ mkEntry(CKM_MD5_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_SHA_1, Mechanism),
+ mkEntry(CKM_SHA_1_HMAC, Mechanism),
+ mkEntry(CKM_SHA_1_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_RIPEMD128, Mechanism),
+ mkEntry(CKM_RIPEMD128_HMAC, Mechanism),
+ mkEntry(CKM_RIPEMD128_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_RIPEMD160, Mechanism),
+ mkEntry(CKM_RIPEMD160_HMAC, Mechanism),
+ mkEntry(CKM_RIPEMD160_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_SHA256, Mechanism),
+ mkEntry(CKM_SHA256_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_SHA256_HMAC, Mechanism),
+ mkEntry(CKM_SHA384, Mechanism),
+ mkEntry(CKM_SHA384_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_SHA384_HMAC, Mechanism),
+ mkEntry(CKM_SHA512, Mechanism),
+ mkEntry(CKM_SHA512_HMAC_GENERAL, Mechanism),
+ mkEntry(CKM_SHA512_HMAC, Mechanism),
+ mkEntry(CKM_CAST_KEY_GEN, Mechanism),
+ mkEntry(CKM_CAST_ECB, Mechanism),
+ mkEntry(CKM_CAST_CBC, Mechanism),
+ mkEntry(CKM_CAST_MAC, Mechanism),
+ mkEntry(CKM_CAST_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CAST_CBC_PAD, Mechanism),
+ mkEntry(CKM_CAST3_KEY_GEN, Mechanism),
+ mkEntry(CKM_CAST3_ECB, Mechanism),
+ mkEntry(CKM_CAST3_CBC, Mechanism),
+ mkEntry(CKM_CAST3_MAC, Mechanism),
+ mkEntry(CKM_CAST3_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CAST3_CBC_PAD, Mechanism),
+ mkEntry(CKM_CAST5_KEY_GEN, Mechanism),
+ mkEntry(CKM_CAST128_KEY_GEN, Mechanism),
+ mkEntry(CKM_CAST5_ECB, Mechanism),
+ mkEntry(CKM_CAST128_ECB, Mechanism),
+ mkEntry(CKM_CAST5_CBC, Mechanism),
+ mkEntry(CKM_CAST128_CBC, Mechanism),
+ mkEntry(CKM_CAST5_MAC, Mechanism),
+ mkEntry(CKM_CAST128_MAC, Mechanism),
+ mkEntry(CKM_CAST5_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CAST128_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CAST5_CBC_PAD, Mechanism),
+ mkEntry(CKM_CAST128_CBC_PAD, Mechanism),
+ mkEntry(CKM_RC5_KEY_GEN, Mechanism),
+ mkEntry(CKM_RC5_ECB, Mechanism),
+ mkEntry(CKM_RC5_CBC, Mechanism),
+ mkEntry(CKM_RC5_MAC, Mechanism),
+ mkEntry(CKM_RC5_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_RC5_CBC_PAD, Mechanism),
+ mkEntry(CKM_IDEA_KEY_GEN, Mechanism),
+ mkEntry(CKM_IDEA_ECB, Mechanism),
+ mkEntry(CKM_IDEA_CBC, Mechanism),
+ mkEntry(CKM_IDEA_MAC, Mechanism),
+ mkEntry(CKM_IDEA_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_IDEA_CBC_PAD, Mechanism),
+ mkEntry(CKM_GENERIC_SECRET_KEY_GEN, Mechanism),
+ mkEntry(CKM_CONCATENATE_BASE_AND_KEY, Mechanism),
+ mkEntry(CKM_CONCATENATE_BASE_AND_DATA, Mechanism),
+ mkEntry(CKM_CONCATENATE_DATA_AND_BASE, Mechanism),
+ mkEntry(CKM_XOR_BASE_AND_DATA, Mechanism),
+ mkEntry(CKM_EXTRACT_KEY_FROM_KEY, Mechanism),
+ mkEntry(CKM_SSL3_PRE_MASTER_KEY_GEN, Mechanism),
+ mkEntry(CKM_SSL3_MASTER_KEY_DERIVE, Mechanism),
+ mkEntry(CKM_SSL3_KEY_AND_MAC_DERIVE, Mechanism),
+ mkEntry(CKM_SSL3_MASTER_KEY_DERIVE_DH, Mechanism),
+ mkEntry(CKM_TLS_PRE_MASTER_KEY_GEN, Mechanism),
+ mkEntry(CKM_TLS_MASTER_KEY_DERIVE, Mechanism),
+ mkEntry(CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256, Mechanism),
+ mkEntry(CKM_TLS_KEY_AND_MAC_DERIVE, Mechanism),
+ mkEntry(CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256, Mechanism),
+ mkEntry(CKM_TLS_MASTER_KEY_DERIVE_DH, Mechanism),
+ mkEntry(CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256, Mechanism),
+ mkEntry(CKM_SSL3_MD5_MAC, Mechanism),
+ mkEntry(CKM_SSL3_SHA1_MAC, Mechanism),
+ mkEntry(CKM_MD5_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_MD2_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_SHA1_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_SHA256_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_SHA384_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_SHA512_KEY_DERIVATION, Mechanism),
+ mkEntry(CKM_PBE_MD2_DES_CBC, Mechanism),
+ mkEntry(CKM_PBE_MD5_DES_CBC, Mechanism),
+ mkEntry(CKM_PBE_MD5_CAST_CBC, Mechanism),
+ mkEntry(CKM_PBE_MD5_CAST3_CBC, Mechanism),
+ mkEntry(CKM_PBE_MD5_CAST5_CBC, Mechanism),
+ mkEntry(CKM_PBE_MD5_CAST128_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_CAST5_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_CAST128_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_RC4_128, Mechanism),
+ mkEntry(CKM_PBE_SHA1_RC4_40, Mechanism),
+ mkEntry(CKM_PBE_SHA1_DES3_EDE_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_DES2_EDE_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_RC2_128_CBC, Mechanism),
+ mkEntry(CKM_PBE_SHA1_RC2_40_CBC, Mechanism),
+ mkEntry(CKM_PKCS5_PBKD2, Mechanism),
+ mkEntry(CKM_PBA_SHA1_WITH_SHA1_HMAC, Mechanism),
+ mkEntry(CKM_KEY_WRAP_LYNKS, Mechanism),
+ mkEntry(CKM_KEY_WRAP_SET_OAEP, Mechanism),
+ mkEntry(CKM_SKIPJACK_KEY_GEN, Mechanism),
+ mkEntry(CKM_SKIPJACK_ECB64, Mechanism),
+ mkEntry(CKM_SKIPJACK_CBC64, Mechanism),
+ mkEntry(CKM_SKIPJACK_OFB64, Mechanism),
+ mkEntry(CKM_SKIPJACK_CFB64, Mechanism),
+ mkEntry(CKM_SKIPJACK_CFB32, Mechanism),
+ mkEntry(CKM_SKIPJACK_CFB16, Mechanism),
+ mkEntry(CKM_SKIPJACK_CFB8, Mechanism),
+ mkEntry(CKM_SKIPJACK_WRAP, Mechanism),
+ mkEntry(CKM_SKIPJACK_PRIVATE_WRAP, Mechanism),
+ mkEntry(CKM_SKIPJACK_RELAYX, Mechanism),
+ mkEntry(CKM_KEA_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_KEA_KEY_DERIVE, Mechanism),
+ mkEntry(CKM_FORTEZZA_TIMESTAMP, Mechanism),
+ mkEntry(CKM_BATON_KEY_GEN, Mechanism),
+ mkEntry(CKM_BATON_ECB128, Mechanism),
+ mkEntry(CKM_BATON_ECB96, Mechanism),
+ mkEntry(CKM_BATON_CBC128, Mechanism),
+ mkEntry(CKM_BATON_COUNTER, Mechanism),
+ mkEntry(CKM_BATON_SHUFFLE, Mechanism),
+ mkEntry(CKM_BATON_WRAP, Mechanism),
+ mkEntry(CKM_ECDSA_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_EC_KEY_PAIR_GEN, Mechanism),
+ mkEntry(CKM_ECDSA, Mechanism),
+ mkEntry(CKM_ECDSA_SHA1, Mechanism),
+ mkEntry(CKM_ECDH1_DERIVE, Mechanism),
+ mkEntry(CKM_ECDH1_COFACTOR_DERIVE, Mechanism),
+ mkEntry(CKM_ECMQV_DERIVE, Mechanism),
+ mkEntry(CKM_JUNIPER_KEY_GEN, Mechanism),
+ mkEntry(CKM_JUNIPER_ECB128, Mechanism),
+ mkEntry(CKM_JUNIPER_CBC128, Mechanism),
+ mkEntry(CKM_JUNIPER_COUNTER, Mechanism),
+ mkEntry(CKM_JUNIPER_SHUFFLE, Mechanism),
+ mkEntry(CKM_JUNIPER_WRAP, Mechanism),
+ mkEntry(CKM_FASTHASH, Mechanism),
+ mkEntry(CKM_AES_KEY_GEN, Mechanism),
+ mkEntry(CKM_AES_ECB, Mechanism),
+ mkEntry(CKM_AES_CBC, Mechanism),
+ mkEntry(CKM_AES_MAC, Mechanism),
+ mkEntry(CKM_AES_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_AES_CBC_PAD, Mechanism),
+ mkEntry(CKM_CAMELLIA_KEY_GEN, Mechanism),
+ mkEntry(CKM_CAMELLIA_ECB, Mechanism),
+ mkEntry(CKM_CAMELLIA_CBC, Mechanism),
+ mkEntry(CKM_CAMELLIA_MAC, Mechanism),
+ mkEntry(CKM_CAMELLIA_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_CAMELLIA_CBC_PAD, Mechanism),
+ mkEntry(CKM_SEED_KEY_GEN, Mechanism),
+ mkEntry(CKM_SEED_ECB, Mechanism),
+ mkEntry(CKM_SEED_CBC, Mechanism),
+ mkEntry(CKM_SEED_MAC, Mechanism),
+ mkEntry(CKM_SEED_MAC_GENERAL, Mechanism),
+ mkEntry(CKM_SEED_CBC_PAD, Mechanism),
+ mkEntry(CKM_SEED_ECB_ENCRYPT_DATA, Mechanism),
+ mkEntry(CKM_SEED_CBC_ENCRYPT_DATA, Mechanism),
+ mkEntry(CKM_DSA_PARAMETER_GEN, Mechanism),
+ mkEntry(CKM_DH_PKCS_PARAMETER_GEN, Mechanism),
+ mkEntry(CKM_NSS_AES_KEY_WRAP, Mechanism),
+ mkEntry(CKM_NSS_AES_KEY_WRAP_PAD, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_DES_CBC, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN, Mechanism),
+ mkEntry(CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, Mechanism),
+ mkEntry(CKM_TLS_PRF_GENERAL, Mechanism),
+ mkEntry(CKM_NSS_TLS_PRF_GENERAL_SHA256, Mechanism),
+
+ mkEntry(CKR_OK, Result),
+ mkEntry(CKR_CANCEL, Result),
+ mkEntry(CKR_HOST_MEMORY, Result),
+ mkEntry(CKR_SLOT_ID_INVALID, Result),
+ mkEntry(CKR_GENERAL_ERROR, Result),
+ mkEntry(CKR_FUNCTION_FAILED, Result),
+ mkEntry(CKR_ARGUMENTS_BAD, Result),
+ mkEntry(CKR_NO_EVENT, Result),
+ mkEntry(CKR_NEED_TO_CREATE_THREADS, Result),
+ mkEntry(CKR_CANT_LOCK, Result),
+ mkEntry(CKR_ATTRIBUTE_READ_ONLY, Result),
+ mkEntry(CKR_ATTRIBUTE_SENSITIVE, Result),
+ mkEntry(CKR_ATTRIBUTE_TYPE_INVALID, Result),
+ mkEntry(CKR_ATTRIBUTE_VALUE_INVALID, Result),
+ mkEntry(CKR_DATA_INVALID, Result),
+ mkEntry(CKR_DATA_LEN_RANGE, Result),
+ mkEntry(CKR_DEVICE_ERROR, Result),
+ mkEntry(CKR_DEVICE_MEMORY, Result),
+ mkEntry(CKR_DEVICE_REMOVED, Result),
+ mkEntry(CKR_ENCRYPTED_DATA_INVALID, Result),
+ mkEntry(CKR_ENCRYPTED_DATA_LEN_RANGE, Result),
+ mkEntry(CKR_FUNCTION_CANCELED, Result),
+ mkEntry(CKR_FUNCTION_NOT_PARALLEL, Result),
+ mkEntry(CKR_FUNCTION_NOT_SUPPORTED, Result),
+ mkEntry(CKR_KEY_HANDLE_INVALID, Result),
+ mkEntry(CKR_KEY_SIZE_RANGE, Result),
+ mkEntry(CKR_KEY_TYPE_INCONSISTENT, Result),
+ mkEntry(CKR_KEY_NOT_NEEDED, Result),
+ mkEntry(CKR_KEY_CHANGED, Result),
+ mkEntry(CKR_KEY_NEEDED, Result),
+ mkEntry(CKR_KEY_INDIGESTIBLE, Result),
+ mkEntry(CKR_KEY_FUNCTION_NOT_PERMITTED, Result),
+ mkEntry(CKR_KEY_NOT_WRAPPABLE, Result),
+ mkEntry(CKR_KEY_UNEXTRACTABLE, Result),
+ mkEntry(CKR_KEY_PARAMS_INVALID, Result),
+ mkEntry(CKR_MECHANISM_INVALID, Result),
+ mkEntry(CKR_MECHANISM_PARAM_INVALID, Result),
+ mkEntry(CKR_OBJECT_HANDLE_INVALID, Result),
+ mkEntry(CKR_OPERATION_ACTIVE, Result),
+ mkEntry(CKR_OPERATION_NOT_INITIALIZED, Result),
+ mkEntry(CKR_PIN_INCORRECT, Result),
+ mkEntry(CKR_PIN_INVALID, Result),
+ mkEntry(CKR_PIN_LEN_RANGE, Result),
+ mkEntry(CKR_PIN_EXPIRED, Result),
+ mkEntry(CKR_PIN_LOCKED, Result),
+ mkEntry(CKR_SESSION_CLOSED, Result),
+ mkEntry(CKR_SESSION_COUNT, Result),
+ mkEntry(CKR_SESSION_HANDLE_INVALID, Result),
+ mkEntry(CKR_SESSION_PARALLEL_NOT_SUPPORTED, Result),
+ mkEntry(CKR_SESSION_READ_ONLY, Result),
+ mkEntry(CKR_SESSION_EXISTS, Result),
+ mkEntry(CKR_SESSION_READ_ONLY_EXISTS, Result),
+ mkEntry(CKR_SESSION_READ_WRITE_SO_EXISTS, Result),
+ mkEntry(CKR_SIGNATURE_INVALID, Result),
+ mkEntry(CKR_SIGNATURE_LEN_RANGE, Result),
+ mkEntry(CKR_TEMPLATE_INCOMPLETE, Result),
+ mkEntry(CKR_TEMPLATE_INCONSISTENT, Result),
+ mkEntry(CKR_TOKEN_NOT_PRESENT, Result),
+ mkEntry(CKR_TOKEN_NOT_RECOGNIZED, Result),
+ mkEntry(CKR_TOKEN_WRITE_PROTECTED, Result),
+ mkEntry(CKR_UNWRAPPING_KEY_HANDLE_INVALID, Result),
+ mkEntry(CKR_UNWRAPPING_KEY_SIZE_RANGE, Result),
+ mkEntry(CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, Result),
+ mkEntry(CKR_USER_ALREADY_LOGGED_IN, Result),
+ mkEntry(CKR_USER_NOT_LOGGED_IN, Result),
+ mkEntry(CKR_USER_PIN_NOT_INITIALIZED, Result),
+ mkEntry(CKR_USER_TYPE_INVALID, Result),
+ mkEntry(CKR_USER_ANOTHER_ALREADY_LOGGED_IN, Result),
+ mkEntry(CKR_USER_TOO_MANY_TYPES, Result),
+ mkEntry(CKR_WRAPPED_KEY_INVALID, Result),
+ mkEntry(CKR_WRAPPED_KEY_LEN_RANGE, Result),
+ mkEntry(CKR_WRAPPING_KEY_HANDLE_INVALID, Result),
+ mkEntry(CKR_WRAPPING_KEY_SIZE_RANGE, Result),
+ mkEntry(CKR_WRAPPING_KEY_TYPE_INCONSISTENT, Result),
+ mkEntry(CKR_RANDOM_SEED_NOT_SUPPORTED, Result),
+ mkEntry(CKR_RANDOM_NO_RNG, Result),
+ mkEntry(CKR_DOMAIN_PARAMS_INVALID, Result),
+ mkEntry(CKR_BUFFER_TOO_SMALL, Result),
+ mkEntry(CKR_SAVED_STATE_INVALID, Result),
+ mkEntry(CKR_INFORMATION_SENSITIVE, Result),
+ mkEntry(CKR_STATE_UNSAVEABLE, Result),
+ mkEntry(CKR_CRYPTOKI_NOT_INITIALIZED, Result),
+ mkEntry(CKR_CRYPTOKI_ALREADY_INITIALIZED, Result),
+ mkEntry(CKR_MUTEX_BAD, Result),
+ mkEntry(CKR_MUTEX_NOT_LOCKED, Result),
+ mkEntry(CKR_VENDOR_DEFINED, Result),
+
+ mkEntry(CKT_NSS_TRUSTED, Trust),
+ mkEntry(CKT_NSS_TRUSTED_DELEGATOR, Trust),
+ mkEntry(CKT_NSS_NOT_TRUSTED, Trust),
+ mkEntry(CKT_NSS_MUST_VERIFY_TRUST, Trust),
+ mkEntry(CKT_NSS_TRUST_UNKNOWN, Trust),
+ mkEntry(CKT_NSS_VALID_DELEGATOR, Trust),
+
+ mkEntry(CK_EFFECTIVELY_INFINITE, AvailableSizes),
+ mkEntry(CK_UNAVAILABLE_INFORMATION, CurrentSize),
+};
+
+const Constant *consts = &_consts[0];
+const int constCount = sizeof(_consts)/sizeof(_consts[0]);
+
+const Commands _commands[] = {
+ {"C_Initialize", F_C_Initialize,
+"C_Initialize pInitArgs\n\n"
+"C_Initialize initializes the PKCS #11 library.\n"
+" pInitArgs if this is not NULL_PTR it gets cast to and dereferenced\n",
+ {ArgInitializeArgs, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_Finalize", F_C_Finalize,
+"C_Finalize pReserved\n\n"
+"C_Finalize indicates that an application is done with the PKCS #11 library.\n"
+" pReserved reserved. Should be NULL_PTR\n",
+ {ArgInitializeArgs, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetInfo", F_C_GetInfo,
+"C_GetInfo pInfo\n\n"
+"C_GetInfo returns general information about PKCS #11.\n"
+" pInfo location that receives information\n",
+ {ArgInfo|ArgOut, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetFunctionList", F_C_GetFunctionList,
+"C_GetFunctionList ppFunctionList\n\n"
+"C_GetFunctionList returns the function list.\n"
+" ppFunctionList receives pointer to function list\n",
+ {ArgFunctionList|ArgOut, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetSlotList", F_C_GetSlotList,
+"C_GetSlotList tokenPresent pSlotList pulCount\n\n"
+"C_GetSlotList obtains a list of slots in the system.\n"
+" tokenPresent only slots with tokens?\n"
+" pSlotList receives array of slot IDs\n"
+" pulCount receives number of slots\n",
+ {ArgULong, ArgULong|ArgArray|ArgOut, ArgULong|ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetSlotInfo", F_C_GetSlotInfo,
+"C_GetSlotInfo slotID pInfo\n\n"
+"C_GetSlotInfo obtains information about a particular slot in the system.\n"
+" slotID the ID of the slot\n"
+" pInfo receives the slot information\n",
+ {ArgULong, ArgSlotInfo|ArgOut, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetTokenInfo", F_C_GetTokenInfo,
+"C_GetTokenInfo slotID pInfo\n\n"
+"C_GetTokenInfo obtains information about a particular token in the system.\n"
+" slotID ID of the token's slot\n"
+" pInfo receives the token information\n",
+ {ArgULong, ArgTokenInfo|ArgOut, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetMechanismList", F_C_GetMechanismList,
+"C_GetMechanismList slotID pMechanismList pulCount\n\n"
+"C_GetMechanismList obtains a list of mechanism types supported by a token.\n"
+" slotID ID of token's slot\n"
+" pMechanismList gets mech. array\n"
+" pulCount gets # of mechs.\n",
+ {ArgULong, ArgULong|ArgArray|ArgOut, ArgULong|ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetMechanismInfo", F_C_GetMechanismInfo,
+"C_GetMechanismInfo slotID type pInfo\n\n"
+"C_GetMechanismInfo obtains information about a particular mechanism possibly\n"
+"supported by a token.\n"
+" slotID ID of the token's slot\n"
+" type type of mechanism\n"
+" pInfo receives mechanism info\n",
+ {ArgULong, ArgULong, ArgMechanismInfo|ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_InitToken", F_C_InitToken,
+"C_InitToken slotID pPin ulPinLen pLabel\n\n"
+"C_InitToken initializes a token.\n"
+" slotID ID of the token's slot\n"
+" pPin the SO's initial PIN\n"
+" ulPinLen length in bytes of the PIN\n"
+" pLabel 32-byte token label (blank padded)\n",
+ {ArgULong, ArgUTF8, ArgULong, ArgUTF8, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_InitPIN", F_C_InitPIN,
+"C_InitPIN hSession pPin ulPinLen\n\n"
+"C_InitPIN initializes the normal user's PIN.\n"
+" hSession the session's handle\n"
+" pPin the normal user's PIN\n"
+" ulPinLen length in bytes of the PIN\n",
+ {ArgULong, ArgUTF8, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_SetPIN", F_C_SetPIN,
+"C_SetPIN hSession pOldPin ulOldLen pNewPin ulNewLen\n\n"
+"C_SetPIN modifies the PIN of the user who is logged in.\n"
+" hSession the session's handle\n"
+" pOldPin the old PIN\n"
+" ulOldLen length of the old PIN\n"
+" pNewPin the new PIN\n"
+" ulNewLen length of the new PIN\n",
+ {ArgULong, ArgUTF8, ArgULong, ArgUTF8, ArgULong,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_OpenSession", F_C_OpenSession,
+"C_OpenSession slotID flags phSession\n\n"
+"C_OpenSession opens a session between an application and a token.\n"
+" slotID the slot's ID\n"
+" flags from\n"
+" phSession gets session handle\n",
+ {ArgULong, ArgULong, ArgULong|ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_CloseSession", F_C_CloseSession,
+"C_CloseSession hSession\n\n"
+"C_CloseSession closes a session between an application and a token.\n"
+" hSession the session's handle\n",
+ {ArgULong, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_CloseAllSessions", F_C_CloseAllSessions,
+"C_CloseAllSessions slotID\n\n"
+"C_CloseAllSessions closes all sessions with a token.\n"
+" slotID the token's slot\n",
+ {ArgULong, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetSessionInfo", F_C_GetSessionInfo,
+"C_GetSessionInfo hSession pInfo\n\n"
+"C_GetSessionInfo obtains information about the session.\n"
+" hSession the session's handle\n"
+" pInfo receives session info\n",
+ {ArgULong, ArgSessionInfo|ArgOut, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetOperationState", F_C_GetOperationState,
+"C_GetOperationState hSession pOpState pulOpStateLen\n\n"
+"C_GetOperationState obtains the state of the cryptographic operation in a\n"
+"session.\n"
+" hSession session's handle\n"
+" pOpState gets state\n"
+" pulOpStateLen gets state length\n",
+ {ArgULong, ArgChar|ArgOut, ArgULong|ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_SetOperationState", F_C_SetOperationState,
+"C_SetOperationState hSession pOpState ulOpStateLen hEncKey hAuthKey\n\n"
+"C_SetOperationState restores the state of the cryptographic operation in a\n"
+"session.\n"
+" hSession session's handle\n"
+" pOpState holds state\n"
+" ulOpStateLen holds state length\n"
+" hEncKey en/decryption key\n"
+" hAuthnKey sign/verify key\n",
+ {ArgULong, ArgChar|ArgOut, ArgULong, ArgULong, ArgULong,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_Login", F_C_Login,
+"C_Login hSession userType pPin ulPinLen\n\n"
+"C_Login logs a user into a token.\n"
+" hSession the session's handle\n"
+" userType the user type\n"
+" pPin the user's PIN\n"
+" ulPinLen the length of the PIN\n",
+ {ArgULong, ArgULong, ArgVar, ArgULong, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_Logout", F_C_Logout,
+"C_Logout hSession\n\n"
+"C_Logout logs a user out from a token.\n"
+" hSession the session's handle\n",
+ {ArgULong, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_CreateObject", F_C_CreateObject,
+"C_CreateObject hSession pTemplate ulCount phObject\n\n"
+"C_CreateObject creates a new object.\n"
+" hSession the session's handle\n"
+" pTemplate the object's template\n"
+" ulCount attributes in template\n"
+" phObject gets new object's handle.\n",
+ {ArgULong, ArgAttribute|ArgArray, ArgULong, ArgULong|ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_CopyObject", F_C_CopyObject,
+"C_CopyObject hSession hObject pTemplate ulCount phNewObject\n\n"
+"C_CopyObject copies an object creating a new object for the copy.\n"
+" hSession the session's handle\n"
+" hObject the object's handle\n"
+" pTemplate template for new object\n"
+" ulCount attributes in template\n"
+" phNewObject receives handle of copy\n",
+ {ArgULong, ArgULong, ArgAttribute|ArgArray, ArgULong, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_DestroyObject", F_C_DestroyObject,
+"C_DestroyObject hSession hObject\n\n"
+"C_DestroyObject destroys an object.\n"
+" hSession the session's handle\n"
+" hObject the object's handle\n",
+ {ArgULong, ArgULong, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetObjectSize", F_C_GetObjectSize,
+"C_GetObjectSize hSession hObject pulSize\n\n"
+"C_GetObjectSize gets the size of an object in bytes.\n"
+" hSession the session's handle\n"
+" hObject the object's handle\n"
+" pulSize receives size of object\n",
+ {ArgULong, ArgULong, ArgULong|ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetAttributeValue", F_C_GetAttributeValue,
+"C_GetAttributeValue hSession hObject pTemplate ulCount\n\n"
+"C_GetAttributeValue obtains the value of one or more object attributes.\n"
+" hSession the session's handle\n"
+" hObject the object's handle\n"
+" pTemplate specifies attrs; gets vals\n"
+" ulCount attributes in template\n",
+ {ArgULong, ArgULong, ArgAttribute|ArgArray, ArgULong, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_SetAttributeValue", F_C_SetAttributeValue,
+"C_SetAttributeValue hSession hObject pTemplate ulCount\n\n"
+"C_SetAttributeValue modifies the value of one or more object attributes\n"
+" hSession the session's handle\n"
+" hObject the object's handle\n"
+" pTemplate specifies attrs and values\n"
+" ulCount attributes in template\n",
+ {ArgULong, ArgULong, ArgAttribute|ArgArray, ArgULong, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_FindObjectsInit", F_C_FindObjectsInit,
+"C_FindObjectsInit hSession pTemplate ulCount\n\n"
+"C_FindObjectsInit initializes a search for token and session objects that\n"
+"match a template.\n"
+" hSession the session's handle\n"
+" pTemplate attribute values to match\n"
+" ulCount attrs in search template\n",
+ {ArgULong, ArgAttribute|ArgArray, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_FindObjectsFinal", F_C_FindObjectsFinal,
+"C_FindObjectsFinal hSession\n\n"
+"C_FindObjectsFinal finishes a search for token and session objects.\n"
+" hSession the session's handle\n",
+ {ArgULong, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_FindObjects", F_C_FindObjects,
+"C_FindObjects hSession phObject ulMaxObjectCount pulObjectCount\n\n"
+"C_FindObjects continues a search for token and session objects that match\n"
+"a template obtaining additional object handles.\n"
+" hSession session's handle\n"
+" phObject gets obj. handles\n"
+" ulMaxObjectCount max handles to get\n"
+" pulObjectCount actual # returned\n",
+ {ArgULong, ArgULong|ArgOut, ArgULong, ArgULong|ArgOut, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_EncryptInit", F_C_EncryptInit,
+"C_EncryptInit hSession pMechanism hKey\n\n"
+"C_EncryptInit initializes an encryption operation.\n"
+" hSession the session's handle\n"
+" pMechanism the encryption mechanism\n"
+" hKey handle of encryption key\n",
+ {ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_EncryptUpdate", F_C_EncryptUpdate,
+"C_EncryptUpdate hSession pPart ulPartLen pEncryptedPart pulEncryptedPartLen\n"
+"\n"
+"C_EncryptUpdate continues a multiple-part encryption operation.\n"
+" hSession session's handle\n"
+" pPart the plaintext data\n"
+" ulPartLen plaintext data len\n"
+" pEncryptedPart gets ciphertext\n"
+" pulEncryptedPartLen gets c-text size\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_EncryptFinal", F_C_EncryptFinal,
+"C_EncryptFinal hSession pLastEncryptedPart pulLastEncryptedPartLen\n\n"
+"C_EncryptFinal finishes a multiple-part encryption operation.\n"
+" hSession session handle\n"
+" pLastEncryptedPart last c-text\n"
+" pulLastEncryptedPartLen gets last size\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_Encrypt", F_C_Encrypt,
+"C_Encrypt hSession pData ulDataLen pEncryptedData pulEncryptedDataLen\n\n"
+"C_Encrypt encrypts single-part data.\n"
+" hSession session's handle\n"
+" pData the plaintext data\n"
+" ulDataLen bytes of plaintext\n"
+" pEncryptedData gets ciphertext\n"
+" pulEncryptedDataLen gets c-text size\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_DecryptInit", F_C_DecryptInit,
+"C_DecryptInit hSession pMechanism hKey\n\n"
+"C_DecryptInit initializes a decryption operation.\n"
+" hSession the session's handle\n"
+" pMechanism the decryption mechanism\n"
+" hKey handle of decryption key\n",
+ {ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_DecryptUpdate", F_C_DecryptUpdate,
+"C_DecryptUpdate hSession pEncryptedPart ulEncryptedPartLen pPart pulPartLen\n"
+"\n"
+"C_DecryptUpdate continues a multiple-part decryption operation.\n"
+" hSession session's handle\n"
+" pEncryptedPart encrypted data\n"
+" ulEncryptedPartLen input length\n"
+" pPart gets plaintext\n"
+" pulPartLen p-text size\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_DecryptFinal", F_C_DecryptFinal,
+"C_DecryptFinal hSession pLastPart pulLastPartLen\n\n"
+"C_DecryptFinal finishes a multiple-part decryption operation.\n"
+" hSession the session's handle\n"
+" pLastPart gets plaintext\n"
+" pulLastPartLen p-text size\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_Decrypt", F_C_Decrypt,
+"C_Decrypt hSession pEncryptedData ulEncryptedDataLen pData pulDataLen\n\n"
+"C_Decrypt decrypts encrypted data in a single part.\n"
+" hSession session's handle\n"
+" pEncryptedData ciphertext\n"
+" ulEncryptedDataLen ciphertext length\n"
+" pData gets plaintext\n"
+" pulDataLen gets p-text size\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_DigestInit", F_C_DigestInit,
+"C_DigestInit hSession pMechanism\n\n"
+"C_DigestInit initializes a message-digesting operation.\n"
+" hSession the session's handle\n"
+" pMechanism the digesting mechanism\n",
+ {ArgULong, ArgMechanism, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_DigestUpdate", F_C_DigestUpdate,
+"C_DigestUpdate hSession pPart ulPartLen\n\n"
+"C_DigestUpdate continues a multiple-part message-digesting operation.\n"
+" hSession the session's handle\n"
+" pPart data to be digested\n"
+" ulPartLen bytes of data to be digested\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_DigestKey", F_C_DigestKey,
+"C_DigestKey hSession hKey\n\n"
+"C_DigestKey continues a multi-part message-digesting operation by digesting\n"
+"the value of a secret key as part of the data already digested.\n"
+" hSession the session's handle\n"
+" hKey secret key to digest\n",
+ {ArgULong, ArgULong, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_DigestFinal", F_C_DigestFinal,
+"C_DigestFinal hSession pDigest pulDigestLen\n\n"
+"C_DigestFinal finishes a multiple-part message-digesting operation.\n"
+" hSession the session's handle\n"
+" pDigest gets the message digest\n"
+" pulDigestLen gets byte count of digest\n",
+ {ArgULong, ArgChar|ArgOut, ArgULong|ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_Digest", F_C_Digest,
+"C_Digest hSession pData ulDataLen pDigest pulDigestLen\n\n"
+"C_Digest digests data in a single part.\n"
+" hSession the session's handle\n"
+" pData data to be digested\n"
+" ulDataLen bytes of data to digest\n"
+" pDigest gets the message digest\n"
+" pulDigestLen gets digest length\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_SignInit", F_C_SignInit,
+"C_SignInit hSession pMechanism hKey\n\n"
+"C_SignInit initializes a signature (private key encryption operation where\n"
+"the signature is (will be) an appendix to the data and plaintext cannot be\n"
+"recovered from the signature.\n"
+" hSession the session's handle\n"
+" pMechanism the signature mechanism\n"
+" hKey handle of signature key\n",
+ {ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_SignUpdate", F_C_SignUpdate,
+"C_SignUpdate hSession pPart ulPartLen\n\n"
+"C_SignUpdate continues a multiple-part signature operation where the\n"
+"signature is (will be) an appendix to the data and plaintext cannot be\n"
+"recovered from the signature.\n"
+" hSession the session's handle\n"
+" pPart the data to sign\n"
+" ulPartLen count of bytes to sign\n",
+ {ArgULong, ArgChar|ArgOut, ArgULong|ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_SignFinal", F_C_SignFinal,
+"C_SignFinal hSession pSignature pulSignatureLen\n\n"
+"C_SignFinal finishes a multiple-part signature operation returning the\n"
+"signature.\n"
+" hSession the session's handle\n"
+" pSignature gets the signature\n"
+" pulSignatureLen gets signature length\n",
+ {ArgULong, ArgChar|ArgOut, ArgULong|ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_SignRecoverInit", F_C_SignRecoverInit,
+"C_SignRecoverInit hSession pMechanism hKey\n\n"
+"C_SignRecoverInit initializes a signature operation where the data can be\n"
+"recovered from the signature.\n"
+" hSession the session's handle\n"
+" pMechanism the signature mechanism\n"
+" hKey handle of the signature key\n",
+ {ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_SignRecover", F_C_SignRecover,
+"C_SignRecover hSession pData ulDataLen pSignature pulSignatureLen\n\n"
+"C_SignRecover signs data in a single operation where the data can be\n"
+"recovered from the signature.\n"
+" hSession the session's handle\n"
+" pData the data to sign\n"
+" ulDataLen count of bytes to sign\n"
+" pSignature gets the signature\n"
+" pulSignatureLen gets signature length\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_Sign", F_C_Sign,
+"C_Sign hSession pData ulDataLen pSignature pulSignatureLen\n\n"
+"C_Sign signs (encrypts with private key) data in a single part where the\n"
+"signature is (will be) an appendix to the data and plaintext cannot be\n"
+"recovered from the signature.\n"
+" hSession the session's handle\n"
+" pData the data to sign\n"
+" ulDataLen count of bytes to sign\n"
+" pSignature gets the signature\n"
+" pulSignatureLen gets signature length\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_VerifyInit", F_C_VerifyInit,
+"C_VerifyInit hSession pMechanism hKey\n\n"
+"C_VerifyInit initializes a verification operation where the signature is an\n"
+"appendix to the data and plaintext cannot cannot be recovered from the\n"
+"signature (e.g. DSA).\n"
+" hSession the session's handle\n"
+" pMechanism the verification mechanism\n"
+" hKey verification key\n",
+ {ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_VerifyUpdate", F_C_VerifyUpdate,
+"C_VerifyUpdate hSession pPart ulPartLen\n\n"
+"C_VerifyUpdate continues a multiple-part verification operation where the\n"
+"signature is an appendix to the data and plaintext cannot be recovered from\n"
+"the signature.\n"
+" hSession the session's handle\n"
+" pPart signed data\n"
+" ulPartLen length of signed data\n",
+ {ArgULong, ArgChar|ArgOut, ArgULong|ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_VerifyFinal", F_C_VerifyFinal,
+"C_VerifyFinal hSession pSignature ulSignatureLen\n\n"
+"C_VerifyFinal finishes a multiple-part verification operation checking the\n"
+"signature.\n"
+" hSession the session's handle\n"
+" pSignature signature to verify\n"
+" ulSignatureLen signature length\n",
+ {ArgULong, ArgChar|ArgOut, ArgULong|ArgOut, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_VerifyRecoverInit", F_C_VerifyRecoverInit,
+"C_VerifyRecoverInit hSession pMechanism hKey\n\n"
+"C_VerifyRecoverInit initializes a signature verification operation where the\n"
+"data is recovered from the signature.\n"
+" hSession the session's handle\n"
+" pMechanism the verification mechanism\n"
+" hKey verification key\n",
+ {ArgULong, ArgMechanism, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_VerifyRecover", F_C_VerifyRecover,
+"C_VerifyRecover hSession pSignature ulSignatureLen pData pulDataLen\n\n"
+"C_VerifyRecover verifies a signature in a single-part operation where the\n"
+"data is recovered from the signature.\n"
+" hSession the session's handle\n"
+" pSignature signature to verify\n"
+" ulSignatureLen signature length\n"
+" pData gets signed data\n"
+" pulDataLen gets signed data len\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_Verify", F_C_Verify,
+"C_Verify hSession pData ulDataLen pSignature ulSignatureLen\n\n"
+"C_Verify verifies a signature in a single-part operation where the signature\n"
+"is an appendix to the data and plaintext cannot be recovered from the\n"
+"signature.\n"
+" hSession the session's handle\n"
+" pData signed data\n"
+" ulDataLen length of signed data\n"
+" pSignature signature\n"
+" ulSignatureLen signature length*/\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_DigestEncryptUpdate", F_C_DigestEncryptUpdate,
+"C_DigestEncryptUpdate hSession pPart ulPartLen pEncryptedPart \\\n"
+" pulEncryptedPartLen\n\n"
+"C_DigestEncryptUpdate continues a multiple-part digesting and encryption\n"
+"operation.\n"
+" hSession session's handle\n"
+" pPart the plaintext data\n"
+" ulPartLen plaintext length\n"
+" pEncryptedPart gets ciphertext\n"
+" pulEncryptedPartLen gets c-text length\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_DecryptDigestUpdate", F_C_DecryptDigestUpdate,
+"C_DecryptDigestUpdate hSession pEncryptedPart ulEncryptedPartLen pPart \\\n"
+" pulPartLen\n\n"
+"C_DecryptDigestUpdate continues a multiple-part decryption and digesting\n"
+"operation.\n"
+" hSession session's handle\n"
+" pEncryptedPart ciphertext\n"
+" ulEncryptedPartLen ciphertext length\n"
+" pPart gets plaintext\n"
+" pulPartLen gets plaintext len\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_SignEncryptUpdate", F_C_SignEncryptUpdate,
+"C_SignEncryptUpdate hSession pPart ulPartLen pEncryptedPart \\\n"
+" pulEncryptedPartLen\n\n"
+"C_SignEncryptUpdate continues a multiple-part signing and encryption\n"
+"operation.\n"
+" hSession session's handle\n"
+" pPart the plaintext data\n"
+" ulPartLen plaintext length\n"
+" pEncryptedPart gets ciphertext\n"
+" pulEncryptedPartLen gets c-text length\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_DecryptVerifyUpdate", F_C_DecryptVerifyUpdate,
+"C_DecryptVerifyUpdate hSession pEncryptedPart ulEncryptedPartLen pPart \\\n"
+" pulPartLen\n\n"
+"C_DecryptVerifyUpdate continues a multiple-part decryption and verify\n"
+"operation.\n"
+" hSession session's handle\n"
+" pEncryptedPart ciphertext\n"
+" ulEncryptedPartLen ciphertext length\n"
+" pPart gets plaintext\n"
+" pulPartLen gets p-text length\n",
+ {ArgULong, ArgChar, ArgULong, ArgChar|ArgOut, ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GenerateKeyPair", F_C_GenerateKeyPair,
+"C_GenerateKeyPair hSession pMechanism pPublicKeyTemplate \\\n"
+" ulPublicKeyAttributeCount pPrivateKeyTemplate ulPrivateKeyAttributeCount \\\n"
+" phPublicKey phPrivateKey\n\n"
+"C_GenerateKeyPair generates a public-key/private-key pair creating new key\n"
+"objects.\n"
+" hSession sessionhandle\n"
+" pMechanism key-genmech.\n"
+" pPublicKeyTemplate templatefor pub. key\n"
+" ulPublicKeyAttributeCount # pub. attrs.\n"
+" pPrivateKeyTemplate templatefor priv. key\n"
+" ulPrivateKeyAttributeCount # priv. attrs.\n"
+" phPublicKey gets pub. keyhandle\n"
+" phPrivateKey getspriv. keyhandle\n",
+ {ArgULong, ArgMechanism, ArgAttribute|ArgArray, ArgULong,
+ ArgAttribute|ArgArray,
+ ArgULong, ArgULong|ArgOut, ArgULong|ArgOut, ArgNone, ArgNone }},
+ {"C_GenerateKey", F_C_GenerateKey,
+"C_GenerateKey hSession pMechanism pTemplate ulCount phKey\n\n"
+"C_GenerateKey generates a secret key creating a new key object.\n"
+" hSession the session's handle\n"
+" pMechanism key generation mech.\n"
+" pTemplate template for new key\n"
+" ulCount # of attrs in template\n"
+" phKey gets handle of new key\n",
+ {ArgULong, ArgMechanism, ArgAttribute|ArgArray, ArgULong,
+ ArgULong|ArgOut,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_WrapKey", F_C_WrapKey,
+"C_WrapKey hSession pMechanism hWrappingKey hKey pWrappedKey pulWrappedKeyLen\n\n"
+"C_WrapKey wraps (i.e. encrypts) a key.\n"
+" hSession the session's handle\n"
+" pMechanism the wrapping mechanism\n"
+" hWrappingKey wrapping key\n"
+" hKey key to be wrapped\n"
+" pWrappedKey gets wrapped key\n"
+" pulWrappedKeyLen gets wrapped key size\n",
+ {ArgULong, ArgMechanism, ArgULong, ArgULong, ArgULong,
+ ArgChar|ArgOut, ArgULong|ArgOut, ArgNone, ArgNone, ArgNone }},
+ {"C_UnwrapKey", F_C_UnwrapKey,
+"C_UnwrapKey hSession pMechanism hUnwrappingKey pWrappedKey ulWrappedKeyLen \\\n"
+" pTemplate ulAttributeCount phKey\n\n"
+"C_UnwrapKey unwraps (decrypts) a wrapped key creating a new key object.\n"
+" hSession session's handle\n"
+" pMechanism unwrapping mech.\n"
+" hUnwrappingKey unwrapping key\n"
+" pWrappedKey the wrapped key\n"
+" ulWrappedKeyLen wrapped key len\n"
+" pTemplate new key template\n"
+" ulAttributeCount template length\n"
+" phKey gets new handle\n",
+ {ArgULong, ArgMechanism, ArgULong, ArgChar, ArgULong,
+ ArgAttribute|ArgArray, ArgULong, ArgULong|ArgOut, ArgNone, ArgNone }},
+ {"C_DeriveKey", F_C_DeriveKey,
+"C_DeriveKey hSession pMechanism hBaseKey pTemplate ulAttributeCount phKey\n\n"
+"C_DeriveKey derives a key from a base key creating a new key object.\n"
+" hSession session's handle\n"
+" pMechanism key deriv. mech.\n"
+" hBaseKey base key\n"
+" pTemplate new key template\n"
+" ulAttributeCount template length\n"
+" phKey gets new handle\n",
+ {ArgULong, ArgMechanism, ArgULong, ArgAttribute|ArgArray, ArgULong,
+ ArgULong|ArgOut, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_SeedRandom", F_C_SeedRandom,
+"C_SeedRandom hSession pSeed ulSeedLen\n\n"
+"C_SeedRandom mixes additional seed material into the token's random number\n"
+"generator.\n"
+" hSession the session's handle\n"
+" pSeed the seed material\n"
+" ulSeedLen length of seed material\n",
+ {ArgULong, ArgChar, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GenerateRandom", F_C_GenerateRandom,
+"C_GenerateRandom hSession RandomData ulRandomLen\n\n"
+"C_GenerateRandom generates random data.\n"
+" hSession the session's handle\n"
+" RandomData receives the random data\n"
+" ulRandomLen # of bytes to generate\n",
+ {ArgULong, ArgChar, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_GetFunctionStatus", F_C_GetFunctionStatus,
+"C_GetFunctionStatus hSession\n\n"
+"C_GetFunctionStatus is a legacy function; it obtains an updated status of\n"
+"a function running in parallel with an application.\n"
+" hSession the session's handle\n",
+ {ArgULong, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_CancelFunction", F_C_CancelFunction,
+"C_CancelFunction hSession\n\n"
+"C_CancelFunction is a legacy function; it cancels a function running in\n"
+"parallel.\n"
+" hSession the session's handle\n",
+ {ArgULong, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"C_WaitForSlotEvent", F_C_WaitForSlotEvent,
+"C_WaitForSlotEvent flags pSlot pRserved\n\n"
+"C_WaitForSlotEvent waits for a slot event (token insertion removal etc.)\n"
+"to occur.\n"
+" flags blocking/nonblocking flag\n"
+" pSlot location that receives the slot ID\n"
+" pRserved reserved. Should be NULL_PTR\n",
+ {ArgULong, ArgULong|ArgArray, ArgVar, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"NewArray", F_NewArray,
+"NewArray varName varType array size\n\n"
+"Creates a new array variable.\n"
+" varName variable name of the new array\n"
+" varType data type of the new array\n"
+" size number of elements in the array\n",
+ {ArgVar|ArgNew, ArgVar, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"NewInitArg", F_NewInitializeArgs,
+"NewInitArg varName flags string\n\n"
+"Creates a new init variable.\n"
+" varName variable name of the new initArg\n"
+" flags value to set the flags field\n"
+" string string parameter for init arg\n",
+ {ArgVar|ArgNew, ArgULong, ArgVar|ArgNew, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"NewTemplate", F_NewTemplate,
+"NewTemplate varName attributeList\n\n"
+"Create a new empty template and populate the attribute list\n"
+" varName variable name of the new template\n"
+" attributeList comma separated list of CKA_ATTRIBUTE types\n",
+ {ArgVar|ArgNew, ArgVar, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"NewMechanism", F_NewMechanism,
+"NewMechanism varName mechanismType\n\n"
+"Create a new CK_MECHANISM object with type NULL parameters and specified type\n"
+" varName variable name of the new mechansim\n"
+" mechanismType CKM_ mechanism type value to set int the type field\n",
+ {ArgVar|ArgNew, ArgULong, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"BuildTemplate", F_BuildTemplate,
+"BuildTemplate template\n\n"
+"Allocates space for the value in a template which has the sizes filled in,\n"
+"but no values allocated yet.\n"
+" template variable name of the template\n",
+ {ArgAttribute, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"SetTemplate", F_SetTemplate,
+"SetTemplate template index value\n\n"
+"Sets a particular element of a template to a CK_ULONG\n"
+" template variable name of the template\n"
+" index index into the template to the element to change\n"
+" value 32 bit value to set in the template\n",
+ {ArgAttribute, ArgULong, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"SetString", F_SetStringVar,
+"SetString varName string\n\n"
+"Sets a particular variable to a string value\n"
+" variable variable name of new string\n"
+" string String to set the variable to\n",
+ {ArgVar|ArgNew, ArgVar, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Set", F_SetVar,
+"Set varName value\n\n"
+"Sets a particular variable to CK_ULONG\n"
+" variable name of the new variable\n"
+" value 32 bit value to set variable to\n",
+ {ArgVar|ArgNew, ArgULong, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Print", F_Print,
+"Print varName\n\n"
+"prints a variable\n"
+" variable name of the variable to print\n",
+ {ArgVar, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Delete", F_Delete,
+"Delete varName\n\n"
+"delete a variable\n"
+" variable name of the variable to delete\n",
+ {ArgVar|ArgNew, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Load", F_Load,
+"load libraryName\n\n"
+"load a pkcs #11 module\n"
+" libraryName Name of a shared library\n",
+ {ArgVar, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Save", F_SaveVar,
+"Save filename variable\n\n"
+"Saves the binary value of 'variable' in file 'filename'\n"
+" fileName target file to save the variable in\n"
+" variable variable to save\n",
+ {ArgVar|ArgNew, ArgVar, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Restore", F_RestoreVar,
+"Restore filename variable\n\n"
+"Restores a variable from a file\n"
+" fileName target file to restore the variable from\n"
+" variable variable to restore\n",
+ {ArgVar|ArgNew, ArgVar, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Increment", F_Increment,
+"Increment variable value\n\n"
+"Increment a variable by value\n",
+ {ArgVar, ArgULong, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Decrement", F_Decrement,
+"Decrement variable value\n\n"
+"Decrement a variable by value\n",
+ {ArgVar, ArgULong, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"List", F_List,
+"List all the variables\n",
+ {ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Unload", F_Unload,
+"Unload the currrently loaded PKCS #11 library\n",
+ {ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Run", F_Run,
+"Run filename\n\n"
+"reads filename as script of commands to execute\n",
+ {ArgVar|ArgNew, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Time", F_Time,
+"Time pkcs11 command\n\n"
+"Execute a pkcs #11 command and time the results\n",
+ {ArgVar|ArgFull, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"System", F_System,
+ "Set System Flag",
+ {ArgULong, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"LoopRun", F_Loop,
+"LoopRun filename var start end step\n\n"
+"Run in a loop. Loop exit if scrip does and explicit quit (Quit QuitIf etc.)",
+ {ArgVar|ArgNew, ArgVar|ArgNew, ArgULong, ArgULong, ArgULong,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Help", F_Help,
+"Help [command]\n\n"
+"print general help, or help for a specific command\n",
+ {ArgVar|ArgOpt, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"QuitIf", F_QuitIf,
+"QuitIf arg1 comparator arg2\n\n"
+"Exit from this program if Condition is valid, valid comparators:\n"
+" < > <= >= = !=\n",
+ {ArgULong, ArgVar|ArgNew, ArgULong, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"QuitIfString", F_QuitIfString,
+"QuitIfString arg1 comparator arg2\n\n"
+"Exit from this program if Condition is valid, valid comparators:\n"
+" = !=\n",
+ {ArgVar|ArgNew, ArgVar|ArgNew, ArgVar|ArgNew, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+ {"Quit", F_Quit,
+"Exit from this program",
+ {ArgNone, ArgNone, ArgNone, ArgNone, ArgNone,
+ ArgNone, ArgNone, ArgNone, ArgNone, ArgNone }},
+};
+
+const Commands *commands= &_commands[0];
+const int commandCount = sizeof(_commands) / sizeof(_commands[0]);
+
+const Topics _topics[] = {
+ { "variables",
+"Variables are random strings of characters. These should begin with alpha\n"
+" characters, and should not contain any spaces, nor should they match any\n"
+" built-in constants. There is some checking in the code for these things,\n"
+" but it's not 100% and using invalid variable names can cause problems.\n"
+" Variables are created by any 'OUT' parameter. If the variable does not\n"
+" exist, it will be created. For in parameters variables must already exist.\n"
+ },
+ { "constants",
+"pk11util recognizes *lots* of constants. All CKA_, CKF_, CKO_, CKU_, CKS_,\n"
+" CKC_, CKK_, CKH_, CKM_, CKT_ values from the PKCS #11 spec are recognized.\n"
+" Constants can be specified with their fully qualified CK?_ value, or the\n"
+" prefix can be dropped. Constants are matched case insensitve.\n"
+ },
+ { "arrays",
+"Arrays are special variables which represent 'C' arrays. Each array \n"
+" variable can be referenced as a group (using just the name), or as \n"
+" individual elements (with the [int] operator). Example:\n"
+" print myArray # prints the full array.\n"
+" print myArray[3] # prints the 3rd elemement of the array \n"
+ },
+ { "sizes",
+"Size operaters returns the size in bytes of a variable, or the number of\n"
+" elements in an array.\n"
+" size(var) and sizeof(var) return the size of var in bytes.\n"
+" sizea(var) and sizeofarray(var) return the number of elements in var.\n"
+" If var is not an array, sizea(var) returns 1.\n"
+ },
+};
+
+const Topics *topics= &_topics[0];
+const int topicCount = sizeof(_topics) / sizeof(_topics[0]);
+
+const char *
+getName(CK_ULONG value, ConstType type)
+{
+ int i;
+
+ for (i=0; i < constCount; i++) {
+ if (consts[i].type == type && consts[i].value == value) {
+ return consts[i].name;
+ }
+ if (type == ConstNone && consts[i].value == value) {
+ return consts[i].name;
+ }
+ }
+
+ return NULL;
+}
+
+const char *
+getNameFromAttribute(CK_ATTRIBUTE_TYPE type)
+{
+ return getName(type, ConstAttribute);
+}
+
+int totalKnownType(ConstType type) {
+ int count = 0;
+ int i;
+
+ for (i=0; i < constCount; i++) {
+ if (consts[i].type == type) count++;
+ }
+ return count;
+}
diff --git a/nss/cmd/lib/pk11table.h b/nss/cmd/lib/pk11table.h
new file mode 100644
index 0000000..cdc4325
--- /dev/null
+++ b/nss/cmd/lib/pk11table.h
@@ -0,0 +1,180 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef _PK11_TABLE_H_
+#define _PK11_TABLE_H_
+
+/*
+ * Supported functions..
+ */
+#include
+#include "nspr.h"
+#include "prtypes.h"
+
+typedef enum {
+ F_No_Function,
+#undef CK_NEED_ARG_LIST
+#define CK_PKCS11_FUNCTION_INFO(func) F_##func,
+#include "pkcs11f.h"
+#undef CK_NEED_ARG_LISt
+#undef CK_PKCS11_FUNCTION_INFO
+ F_SetVar,
+ F_SetStringVar,
+ F_NewArray,
+ F_NewInitializeArgs,
+ F_NewTemplate,
+ F_NewMechanism,
+ F_BuildTemplate,
+ F_SetTemplate,
+ F_Print,
+ F_SaveVar,
+ F_RestoreVar,
+ F_Increment,
+ F_Decrement,
+ F_Delete,
+ F_List,
+ F_Run,
+ F_Load,
+ F_Unload,
+ F_System,
+ F_Loop,
+ F_Time,
+ F_Help,
+ F_Quit,
+ F_QuitIf,
+ F_QuitIfString
+} FunctionType;
+
+/*
+ * Supported Argument Types
+ */
+typedef enum {
+ ArgNone,
+ ArgVar,
+ ArgULong,
+ ArgChar,
+ ArgUTF8,
+ ArgInfo,
+ ArgSlotInfo,
+ ArgTokenInfo,
+ ArgSessionInfo,
+ ArgAttribute,
+ ArgMechanism,
+ ArgMechanismInfo,
+ ArgInitializeArgs,
+ ArgFunctionList,
+/* Modifier Flags */
+ ArgMask = 0xff,
+ ArgOut = 0x100,
+ ArgArray = 0x200,
+ ArgNew = 0x400,
+ ArgFile = 0x800,
+ ArgStatic = 0x1000,
+ ArgOpt = 0x2000,
+ ArgFull = 0x4000
+} ArgType;
+
+typedef enum _constType
+{
+ ConstNone,
+ ConstBool,
+ ConstInfoFlags,
+ ConstSlotFlags,
+ ConstTokenFlags,
+ ConstSessionFlags,
+ ConstMechanismFlags,
+ ConstInitializeFlags,
+ ConstUsers,
+ ConstSessionState,
+ ConstObject,
+ ConstHardware,
+ ConstKeyType,
+ ConstCertType,
+ ConstAttribute,
+ ConstMechanism,
+ ConstResult,
+ ConstTrust,
+ ConstAvailableSizes,
+ ConstCurrentSize
+} ConstType;
+
+typedef struct _constant {
+ const char *name;
+ CK_ULONG value;
+ ConstType type;
+ ConstType attrType;
+} Constant ;
+
+/*
+ * Values structures.
+ */
+typedef struct _values {
+ ArgType type;
+ ConstType constType;
+ int size;
+ char *filename;
+ void *data;
+ int reference;
+ int arraySize;
+} Value;
+
+/*
+ * Variables
+ */
+typedef struct _variable Variable;
+struct _variable {
+ Variable *next;
+ char *vname;
+ Value *value;
+};
+
+/* NOTE: if you change MAX_ARGS, you need to change the commands array
+ * below as well.
+ */
+
+#define MAX_ARGS 10
+/*
+ * structure for master command array
+ */
+typedef struct _commands {
+ char *fname;
+ FunctionType fType;
+ char *helpString;
+ ArgType args[MAX_ARGS];
+} Commands;
+
+typedef struct _module {
+ PRLibrary *library;
+ CK_FUNCTION_LIST *functionList;
+} Module;
+
+typedef struct _topics {
+ char *name;
+ char *helpString;
+} Topics;
+
+/*
+ * the command array itself. Make name to function and it's arguments
+ */
+
+extern const char **valueString;
+extern const int valueCount;
+extern const char **constTypeString;
+extern const int constTypeCount;
+extern const Constant *consts;
+extern const int constCount;
+extern const Commands *commands;
+extern const int commandCount;
+extern const Topics *topics;
+extern const int topicCount;
+
+extern const char *
+getName(CK_ULONG value, ConstType type);
+
+extern const char *
+getNameFromAttribute(CK_ATTRIBUTE_TYPE type);
+
+extern int totalKnownType(ConstType type);
+
+#endif /* _PK11_TABLE_H_ */
+
diff --git a/nss/cmd/lib/pppolicy.c b/nss/cmd/lib/pppolicy.c
new file mode 100644
index 0000000..7a5bd0b
--- /dev/null
+++ b/nss/cmd/lib/pppolicy.c
@@ -0,0 +1,265 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Support for various policy related extensions
+ */
+
+#include "seccomon.h"
+#include "secport.h"
+#include "secder.h"
+#include "cert.h"
+#include "secoid.h"
+#include "secasn1.h"
+#include "secerr.h"
+#include "nspr.h"
+#include "secutil.h"
+
+/* This implementation is derived from the one in nss/lib/certdb/policyxtn.c .
+** The chief difference is the addition of the OPTIONAL flag to many
+** parts. The idea is to be able to parse and print as much of the
+** policy extension as possible, even if some parts are invalid.
+**
+** If this approach still is unable to decode policy extensions that
+** contain invalid parts, then the next approach will be to parse
+** the PolicyInfos as a SEQUENCE of ANYs, and then parse each of them
+** as PolicyInfos, with the PolicyQualifiers being ANYs, and finally
+** parse each of the PolicyQualifiers.
+*/
+
+static const SEC_ASN1Template secu_PolicyQualifierTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTPolicyQualifier) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(CERTPolicyQualifier, qualifierID) },
+ { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL,
+ offsetof(CERTPolicyQualifier, qualifierValue) },
+ { 0 }
+};
+
+static const SEC_ASN1Template secu_PolicyInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(CERTPolicyInfo) },
+ { SEC_ASN1_OBJECT_ID,
+ offsetof(CERTPolicyInfo, policyID) },
+ { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_OPTIONAL,
+ offsetof(CERTPolicyInfo, policyQualifiers),
+ secu_PolicyQualifierTemplate },
+ { 0 }
+};
+
+static const SEC_ASN1Template secu_CertificatePoliciesTemplate[] = {
+ { SEC_ASN1_SEQUENCE_OF,
+ offsetof(CERTCertificatePolicies, policyInfos),
+ secu_PolicyInfoTemplate, sizeof(CERTCertificatePolicies) }
+};
+
+
+static CERTCertificatePolicies *
+secu_DecodeCertificatePoliciesExtension(SECItem *extnValue)
+{
+ PLArenaPool *arena = NULL;
+ SECStatus rv;
+ CERTCertificatePolicies *policies;
+ CERTPolicyInfo **policyInfos, *policyInfo;
+ CERTPolicyQualifier **policyQualifiers, *policyQualifier;
+ SECItem newExtnValue;
+
+ /* make a new arena */
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if ( !arena ) {
+ goto loser;
+ }
+
+ /* allocate the certifiate policies structure */
+ policies = PORT_ArenaZNew(arena, CERTCertificatePolicies);
+ if ( policies == NULL ) {
+ goto loser;
+ }
+
+ policies->arena = arena;
+
+ /* copy the DER into the arena, since Quick DER returns data that points
+ into the DER input, which may get freed by the caller */
+ rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* decode the policy info */
+ rv = SEC_QuickDERDecodeItem(arena, policies,
+ secu_CertificatePoliciesTemplate,
+ &newExtnValue);
+
+ if ( rv != SECSuccess ) {
+ goto loser;
+ }
+
+ /* initialize the oid tags */
+ policyInfos = policies->policyInfos;
+ while (policyInfos != NULL && *policyInfos != NULL ) {
+ policyInfo = *policyInfos;
+ policyInfo->oid = SECOID_FindOIDTag(&policyInfo->policyID);
+ policyQualifiers = policyInfo->policyQualifiers;
+ while ( policyQualifiers && *policyQualifiers != NULL ) {
+ policyQualifier = *policyQualifiers;
+ policyQualifier->oid =
+ SECOID_FindOIDTag(&policyQualifier->qualifierID);
+ policyQualifiers++;
+ }
+ policyInfos++;
+ }
+
+ return(policies);
+
+loser:
+ if ( arena != NULL ) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+
+ return(NULL);
+}
+
+
+static char *
+itemToString(SECItem *item)
+{
+ char *string;
+
+ string = PORT_ZAlloc(item->len+1);
+ if (string == NULL) return NULL;
+ PORT_Memcpy(string,item->data,item->len);
+ string[item->len] = 0;
+ return string;
+}
+
+static SECStatus
+secu_PrintUserNoticeQualifier(FILE *out, SECItem * qualifierValue,
+ char *msg, int level)
+{
+ CERTUserNotice *userNotice = NULL;
+ if (qualifierValue)
+ userNotice = CERT_DecodeUserNotice(qualifierValue);
+ if (userNotice) {
+ if (userNotice->noticeReference.organization.len != 0) {
+ char *string =
+ itemToString(&userNotice->noticeReference.organization);
+ SECItem **itemList = userNotice->noticeReference.noticeNumbers;
+
+ while (itemList && *itemList) {
+ SECU_PrintInteger(out,*itemList,string,level+1);
+ itemList++;
+ }
+ PORT_Free(string);
+ }
+ if (userNotice->displayText.len != 0) {
+ SECU_PrintString(out,&userNotice->displayText,
+ "Display Text", level+1);
+ }
+ CERT_DestroyUserNotice(userNotice);
+ return SECSuccess;
+ }
+ return SECFailure; /* caller will print this value */
+}
+
+static SECStatus
+secu_PrintPolicyQualifier(FILE *out,CERTPolicyQualifier *policyQualifier,
+ char *msg,int level)
+{
+ SECStatus rv;
+ SECItem * qualifierValue = &policyQualifier->qualifierValue;
+
+ SECU_PrintObjectID(out, &policyQualifier->qualifierID ,
+ "Policy Qualifier Name", level);
+ if (!qualifierValue->data) {
+ SECU_Indent(out, level);
+ fprintf(out,"Error: missing qualifier\n");
+ } else
+ switch (policyQualifier->oid) {
+ case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
+ rv = secu_PrintUserNoticeQualifier(out, qualifierValue, msg, level);
+ if (SECSuccess == rv)
+ break;
+ /* fall through on error */
+ case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
+ default:
+ SECU_PrintAny(out, qualifierValue, "Policy Qualifier Data", level);
+ break;
+ }
+ return SECSuccess;
+}
+
+static SECStatus
+secu_PrintPolicyInfo(FILE *out,CERTPolicyInfo *policyInfo,char *msg,int level)
+{
+ CERTPolicyQualifier **policyQualifiers;
+
+ policyQualifiers = policyInfo->policyQualifiers;
+ SECU_PrintObjectID(out, &policyInfo->policyID , "Policy Name", level);
+
+ while (policyQualifiers && *policyQualifiers != NULL) {
+ secu_PrintPolicyQualifier(out,*policyQualifiers,"",level+1);
+ policyQualifiers++;
+ }
+ return SECSuccess;
+}
+
+void
+SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTCertificatePolicies *policies = NULL;
+ CERTPolicyInfo **policyInfos;
+
+ if (msg) {
+ SECU_Indent(out, level);
+ fprintf(out,"%s: \n",msg);
+ level++;
+ }
+ policies = secu_DecodeCertificatePoliciesExtension(value);
+ if (policies == NULL) {
+ SECU_PrintAny(out, value, "Invalid Policy Data", level);
+ return;
+ }
+
+ policyInfos = policies->policyInfos;
+ while (policyInfos && *policyInfos != NULL) {
+ secu_PrintPolicyInfo(out,*policyInfos,"",level);
+ policyInfos++;
+ }
+
+ CERT_DestroyCertificatePoliciesExtension(policies);
+}
+
+
+void
+SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value,
+ char *msg, int level)
+{
+ CERTPrivKeyUsagePeriod * prd;
+ PLArenaPool * arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if ( !arena ) {
+ goto loser;
+ }
+ prd = CERT_DecodePrivKeyUsagePeriodExtension(arena, value);
+ if (!prd) {
+ goto loser;
+ }
+ if (prd->notBefore.data) {
+ SECU_PrintGeneralizedTime(out, &prd->notBefore, "Not Before", level);
+ }
+ if (prd->notAfter.data) {
+ SECU_PrintGeneralizedTime(out, &prd->notAfter, "Not After ", level);
+ }
+ if (!prd->notBefore.data && !prd->notAfter.data) {
+ SECU_Indent(out, level);
+ fprintf(out, "Error: notBefore or notAfter MUST be present.\n");
+loser:
+ SECU_PrintAny(out, value, msg, level);
+ }
+ if (arena) {
+ PORT_FreeArena(arena, PR_FALSE);
+ }
+}
diff --git a/nss/cmd/lib/secpwd.c b/nss/cmd/lib/secpwd.c
new file mode 100644
index 0000000..2c4579d
--- /dev/null
+++ b/nss/cmd/lib/secpwd.c
@@ -0,0 +1,164 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "secutil.h"
+
+/*
+ * NOTE: The contents of this file are NOT used by the client.
+ * (They are part of the security library as a whole, but they are
+ * NOT USED BY THE CLIENT.) Do not change things on behalf of the
+ * client (like localizing strings), or add things that are only
+ * for the client (put them elsewhere).
+ */
+
+
+#ifdef XP_UNIX
+#include
+#endif
+
+#if defined(XP_UNIX) || defined(XP_BEOS)
+#include /* for isatty() */
+#endif
+
+#if defined(_WINDOWS)
+#include
+#include
+#define QUIET_FGETS quiet_fgets
+static char * quiet_fgets (char *buf, int length, FILE *input);
+#else
+#define QUIET_FGETS fgets
+#endif
+
+static void echoOff(int fd)
+{
+#if defined(XP_UNIX)
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag &= ~ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+#endif
+}
+
+static void echoOn(int fd)
+{
+#if defined(XP_UNIX)
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag |= ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+#endif
+}
+
+char *SEC_GetPassword(FILE *input, FILE *output, char *prompt,
+ PRBool (*ok)(char *))
+{
+#if defined(_WINDOWS)
+ int isTTY = (input == stdin);
+#define echoOn(x)
+#define echoOff(x)
+#else
+ int infd = fileno(input);
+ int isTTY = isatty(infd);
+#endif
+ char phrase[200] = {'\0'}; /* ensure EOF doesn't return junk */
+
+ for (;;) {
+ /* Prompt for password */
+ if (isTTY) {
+ fprintf(output, "%s", prompt);
+ fflush (output);
+ echoOff(infd);
+ }
+
+ QUIET_FGETS ( phrase, sizeof(phrase), input);
+
+ if (isTTY) {
+ fprintf(output, "\n");
+ echoOn(infd);
+ }
+
+ /* stomp on newline */
+ phrase[PORT_Strlen(phrase)-1] = 0;
+
+ /* Validate password */
+ if (!(*ok)(phrase)) {
+ /* Not weird enough */
+ if (!isTTY) return 0;
+ fprintf(output, "Password must be at least 8 characters long with one or more\n");
+ fprintf(output, "non-alphabetic characters\n");
+ continue;
+ }
+ return (char*) PORT_Strdup(phrase);
+ }
+}
+
+
+
+PRBool SEC_CheckPassword(char *cp)
+{
+ int len;
+ char *end;
+
+ len = PORT_Strlen(cp);
+ if (len < 8) {
+ return PR_FALSE;
+ }
+ end = cp + len;
+ while (cp < end) {
+ unsigned char ch = *cp++;
+ if (!((ch >= 'A') && (ch <= 'Z')) &&
+ !((ch >= 'a') && (ch <= 'z'))) {
+ /* pass phrase has at least one non alphabetic in it */
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
+PRBool SEC_BlindCheckPassword(char *cp)
+{
+ if (cp != NULL) {
+ return PR_TRUE;
+ }
+ return PR_FALSE;
+}
+
+/* Get a password from the input terminal, without echoing */
+
+#if defined(_WINDOWS)
+static char * quiet_fgets (char *buf, int length, FILE *input)
+ {
+ int c;
+ char *end = buf;
+
+ /* fflush (input); */
+ memset (buf, 0, length);
+
+ if (!isatty(fileno(input))) {
+ return fgets(buf,length,input);
+ }
+
+ while (1)
+ {
+ c = getch(); /* getch gets a character from the console */
+
+ if (c == '\b')
+ {
+ if (end > buf)
+ end--;
+ }
+
+ else if (--length > 0)
+ *end++ = c;
+
+ if (!c || c == '\n' || c == '\r')
+ break;
+ }
+
+ return buf;
+ }
+#endif
diff --git a/nss/cmd/lib/secutil.c b/nss/cmd/lib/secutil.c
new file mode 100644
index 0000000..97331c9
--- /dev/null
+++ b/nss/cmd/lib/secutil.c
@@ -0,0 +1,3795 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+** secutil.c - various functions used by security stuff
+**
+*/
+
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+#include "prerror.h"
+#include "prprf.h"
+#include "plgetopt.h"
+#include "prenv.h"
+#include "prnetdb.h"
+
+#include "cryptohi.h"
+#include "secutil.h"
+#include "secpkcs7.h"
+#include "secpkcs5.h"
+#include
+#include
+#include
+
+#ifdef XP_UNIX
+#include
+#endif
+
+/* for SEC_TraverseNames */
+#include "cert.h"
+#include "certt.h"
+#include "certdb.h"
+
+/* #include "secmod.h" */
+#include "pk11func.h"
+#include "secoid.h"
+
+static char consoleName[] = {
+#ifdef XP_UNIX
+ "/dev/tty"
+#else
+#ifdef XP_OS2
+ "\\DEV\\CON"
+#else
+ "CON:"
+#endif
+#endif
+};
+
+#include "nssutil.h"
+#include "ssl.h"
+#include "sslproto.h"
+
+static PRBool utf8DisplayEnabled = PR_FALSE;
+
+void
+SECU_EnableUtf8Display(PRBool enable)
+{
+ utf8DisplayEnabled = enable;
+}
+
+PRBool
+SECU_GetUtf8DisplayEnabled(void)
+{
+ return utf8DisplayEnabled;
+}
+
+static void
+secu_ClearPassword(char *p)
+{
+ if (p) {
+ PORT_Memset(p, 0, PORT_Strlen(p));
+ PORT_Free(p);
+ }
+}
+
+char *
+SECU_GetPasswordString(void *arg, char *prompt)
+{
+#ifndef _WINDOWS
+ char *p = NULL;
+ FILE *input, *output;
+
+ /* open terminal */
+ input = fopen(consoleName, "r");
+ if (input == NULL) {
+ fprintf(stderr, "Error opening input terminal for read\n");
+ return NULL;
+ }
+
+ output = fopen(consoleName, "w");
+ if (output == NULL) {
+ fprintf(stderr, "Error opening output terminal for write\n");
+ fclose(input);
+ return NULL;
+ }
+
+ p = SEC_GetPassword (input, output, prompt, SEC_BlindCheckPassword);
+
+
+ fclose(input);
+ fclose(output);
+
+ return p;
+
+#else
+ /* Win32 version of above. opening the console may fail
+ on windows95, and certainly isn't necessary.. */
+
+ char *p = NULL;
+
+ p = SEC_GetPassword (stdin, stdout, prompt, SEC_BlindCheckPassword);
+ return p;
+
+#endif
+}
+
+
+/*
+ * p a s s w o r d _ h a r d c o d e
+ *
+ * A function to use the password passed in the -f(pwfile) argument
+ * of the command line.
+ * After use once, null it out otherwise PKCS11 calls us forever.?
+ *
+ */
+char *
+SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char* phrases, *phrase;
+ PRFileDesc *fd;
+ PRInt32 nb;
+ char *pwFile = arg;
+ int i;
+ const long maxPwdFileSize = 4096;
+ char* tokenName = NULL;
+ int tokenLen = 0;
+
+ if (!pwFile)
+ return 0;
+
+ if (retry) {
+ return 0; /* no good retrying - the files contents will be the same */
+ }
+
+ phrases = PORT_ZAlloc(maxPwdFileSize);
+
+ if (!phrases) {
+ return 0; /* out of memory */
+ }
+
+ fd = PR_Open(pwFile, PR_RDONLY, 0);
+ if (!fd) {
+ fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
+ PORT_Free(phrases);
+ return NULL;
+ }
+
+ nb = PR_Read(fd, phrases, maxPwdFileSize);
+
+ PR_Close(fd);
+
+ if (nb == 0) {
+ fprintf(stderr,"password file contains no data\n");
+ PORT_Free(phrases);
+ return NULL;
+ }
+
+ if (slot) {
+ tokenName = PK11_GetTokenName(slot);
+ if (tokenName) {
+ tokenLen = PORT_Strlen(tokenName);
+ }
+ }
+ i = 0;
+ do
+ {
+ int startphrase = i;
+ int phraseLen;
+
+ /* handle the Windows EOL case */
+ while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb) i++;
+ /* terminate passphrase */
+ phrases[i++] = '\0';
+ /* clean up any EOL before the start of the next passphrase */
+ while ( (isource != PW_NONE) {
+ PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n");
+ return NULL;
+ }
+
+ switch (pwdata->source) {
+ case PW_NONE:
+ sprintf(prompt, "Enter Password or Pin for \"%s\":",
+ PK11_GetTokenName(slot));
+ return SECU_GetPasswordString(NULL, prompt);
+ case PW_FROMFILE:
+ /* Instead of opening and closing the file every time, get the pw
+ * once, then keep it in memory (duh).
+ */
+ pw = SECU_FilePasswd(slot, retry, pwdata->data);
+ pwdata->source = PW_PLAINTEXT;
+ pwdata->data = PL_strdup(pw);
+ /* it's already been dup'ed */
+ return pw;
+ case PW_EXTERNAL:
+ sprintf(prompt,
+ "Press Enter, then enter PIN for \"%s\" on external device.\n",
+ PK11_GetTokenName(slot));
+ (void) SECU_GetPasswordString(NULL, prompt);
+ /* Fall Through */
+ case PW_PLAINTEXT:
+ return PL_strdup(pwdata->data);
+ default:
+ break;
+ }
+
+ PR_fprintf(PR_STDERR, "Password check failed: No password found.\n");
+ return NULL;
+}
+
+char *
+secu_InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char *p0 = NULL;
+ char *p1 = NULL;
+ FILE *input, *output;
+ secuPWData *pwdata = arg;
+
+ if (pwdata->source == PW_FROMFILE) {
+ return SECU_FilePasswd(slot, retry, pwdata->data);
+ }
+ if (pwdata->source == PW_PLAINTEXT) {
+ return PL_strdup(pwdata->data);
+ }
+
+ /* PW_NONE - get it from tty */
+ /* open terminal */
+#ifdef _WINDOWS
+ input = stdin;
+#else
+ input = fopen(consoleName, "r");
+#endif
+ if (input == NULL) {
+ PR_fprintf(PR_STDERR, "Error opening input terminal for read\n");
+ return NULL;
+ }
+
+ /* we have no password, so initialize database with one */
+ PR_fprintf(PR_STDERR,
+ "Enter a password which will be used to encrypt your keys.\n"
+ "The password should be at least 8 characters long,\n"
+ "and should contain at least one non-alphabetic character.\n\n");
+
+ output = fopen(consoleName, "w");
+ if (output == NULL) {
+ PR_fprintf(PR_STDERR, "Error opening output terminal for write\n");
+#ifndef _WINDOWS
+ fclose(input);
+#endif
+ return NULL;
+ }
+
+
+ for (;;) {
+ if (p0)
+ PORT_Free(p0);
+ p0 = SEC_GetPassword(input, output, "Enter new password: ",
+ SEC_BlindCheckPassword);
+
+ if (p1)
+ PORT_Free(p1);
+ p1 = SEC_GetPassword(input, output, "Re-enter password: ",
+ SEC_BlindCheckPassword);
+ if (p0 && p1 && !PORT_Strcmp(p0, p1)) {
+ break;
+ }
+ PR_fprintf(PR_STDERR, "Passwords do not match. Try again.\n");
+ }
+
+ /* clear out the duplicate password string */
+ secu_ClearPassword(p1);
+
+ fclose(input);
+ fclose(output);
+
+ return p0;
+}
+
+SECStatus
+SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile)
+{
+ return SECU_ChangePW2(slot, passwd, 0, pwFile, 0);
+}
+
+SECStatus
+SECU_ChangePW2(PK11SlotInfo *slot, char *oldPass, char *newPass,
+ char *oldPwFile, char *newPwFile)
+{
+ SECStatus rv;
+ secuPWData pwdata, newpwdata;
+ char *oldpw = NULL, *newpw = NULL;
+
+ if (oldPass) {
+ pwdata.source = PW_PLAINTEXT;
+ pwdata.data = oldPass;
+ } else if (oldPwFile) {
+ pwdata.source = PW_FROMFILE;
+ pwdata.data = oldPwFile;
+ } else {
+ pwdata.source = PW_NONE;
+ pwdata.data = NULL;
+ }
+
+ if (newPass) {
+ newpwdata.source = PW_PLAINTEXT;
+ newpwdata.data = newPass;
+ } else if (newPwFile) {
+ newpwdata.source = PW_FROMFILE;
+ newpwdata.data = newPwFile;
+ } else {
+ newpwdata.source = PW_NONE;
+ newpwdata.data = NULL;
+ }
+
+ if (PK11_NeedUserInit(slot)) {
+ newpw = secu_InitSlotPassword(slot, PR_FALSE, &pwdata);
+ rv = PK11_InitPin(slot, (char*)NULL, newpw);
+ goto done;
+ }
+
+ for (;;) {
+ oldpw = SECU_GetModulePassword(slot, PR_FALSE, &pwdata);
+
+ if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
+ if (pwdata.source == PW_NONE) {
+ PR_fprintf(PR_STDERR, "Invalid password. Try again.\n");
+ } else {
+ PR_fprintf(PR_STDERR, "Invalid password.\n");
+ PORT_Memset(oldpw, 0, PL_strlen(oldpw));
+ PORT_Free(oldpw);
+ return SECFailure;
+ }
+ } else
+ break;
+
+ PORT_Free(oldpw);
+ }
+
+ newpw = secu_InitSlotPassword(slot, PR_FALSE, &newpwdata);
+
+ if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
+ PR_fprintf(PR_STDERR, "Failed to change password.\n");
+ return SECFailure;
+ }
+
+ PORT_Memset(oldpw, 0, PL_strlen(oldpw));
+ PORT_Free(oldpw);
+
+ PR_fprintf(PR_STDOUT, "Password changed successfully.\n");
+
+done:
+ PORT_Memset(newpw, 0, PL_strlen(newpw));
+ PORT_Free(newpw);
+ return SECSuccess;
+}
+
+struct matchobj {
+ SECItem index;
+ char *nname;
+ PRBool found;
+};
+
+char *
+SECU_DefaultSSLDir(void)
+{
+ char *dir;
+ static char sslDir[1000];
+
+ dir = PR_GetEnv("SSL_DIR");
+ if (!dir)
+ return NULL;
+
+ sprintf(sslDir, "%s", dir);
+
+ if (sslDir[strlen(sslDir)-1] == '/')
+ sslDir[strlen(sslDir)-1] = 0;
+
+ return sslDir;
+}
+
+char *
+SECU_AppendFilenameToDir(char *dir, char *filename)
+{
+ static char path[1000];
+
+ if (dir[strlen(dir)-1] == '/')
+ sprintf(path, "%s%s", dir, filename);
+ else
+ sprintf(path, "%s/%s", dir, filename);
+ return path;
+}
+
+char *
+SECU_ConfigDirectory(const char* base)
+{
+ static PRBool initted = PR_FALSE;
+ const char *dir = ".netscape";
+ char *home;
+ static char buf[1000];
+
+ if (initted) return buf;
+
+
+ if (base == NULL || *base == 0) {
+ home = PR_GetEnv("HOME");
+ if (!home) home = "";
+
+ if (*home && home[strlen(home) - 1] == '/')
+ sprintf (buf, "%.900s%s", home, dir);
+ else
+ sprintf (buf, "%.900s/%s", home, dir);
+ } else {
+ sprintf(buf, "%.900s", base);
+ if (buf[strlen(buf) - 1] == '/')
+ buf[strlen(buf) - 1] = 0;
+ }
+
+
+ initted = PR_TRUE;
+ return buf;
+}
+
+/*Turn off SSL for now */
+/* This gets called by SSL when server wants our cert & key */
+int
+SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey)
+{
+ SECKEYPrivateKey *key;
+ CERTCertificate *cert;
+ int errsave;
+
+ if (arg == NULL) {
+ fprintf(stderr, "no key/cert name specified for client auth\n");
+ return -1;
+ }
+ cert = PK11_FindCertFromNickname(arg, NULL);
+ errsave = PORT_GetError();
+ if (!cert) {
+ if (errsave == SEC_ERROR_BAD_PASSWORD)
+ fprintf(stderr, "Bad password\n");
+ else if (errsave > 0)
+ fprintf(stderr, "Unable to read cert (error %d)\n", errsave);
+ else if (errsave == SEC_ERROR_BAD_DATABASE)
+ fprintf(stderr, "Unable to get cert from database (%d)\n", errsave);
+ else
+ fprintf(stderr, "SECKEY_FindKeyByName: internal error %d\n", errsave);
+ return -1;
+ }
+
+ key = PK11_FindKeyByAnyCert(arg,NULL);
+ if (!key) {
+ fprintf(stderr, "Unable to get key (%d)\n", PORT_GetError());
+ return -1;
+ }
+
+
+ *pRetCert = cert;
+ *pRetKey = key;
+
+ return 0;
+}
+
+SECStatus
+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii,
+ PRBool warnOnPrivateKeyInAsciiFile)
+{
+ SECStatus rv;
+ if (ascii) {
+ /* First convert ascii to binary */
+ SECItem filedata;
+ char *asc, *body;
+
+ /* Read in ascii data */
+ rv = SECU_FileToItem(&filedata, inFile);
+ if (rv != SECSuccess)
+ return rv;
+ asc = (char *)filedata.data;
+ if (!asc) {
+ fprintf(stderr, "unable to read data from input file\n");
+ return SECFailure;
+ }
+
+ if (warnOnPrivateKeyInAsciiFile && strstr(asc, "PRIVATE KEY")) {
+ fprintf(stderr, "Warning: ignoring private key. Consider to use "
+ "pk12util.\n");
+ }
+
+ /* check for headers and trailers and remove them */
+ if ((body = strstr(asc, "-----BEGIN")) != NULL) {
+ char *trailer = NULL;
+ asc = body;
+ body = PORT_Strchr(body, '\n');
+ if (!body)
+ body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */
+ if (body)
+ trailer = strstr(++body, "-----END");
+ if (trailer != NULL) {
+ *trailer = '\0';
+ } else {
+ fprintf(stderr, "input has header but no trailer\n");
+ PORT_Free(filedata.data);
+ return SECFailure;
+ }
+ } else {
+ /* need one additional byte for zero terminator */
+ rv = SECITEM_ReallocItemV2(NULL, &filedata, filedata.len+1);
+ if (rv != SECSuccess) {
+ PORT_Free(filedata.data);
+ return rv;
+ }
+ body = (char*)filedata.data;
+ body[filedata.len-1] = '\0';
+ }
+
+ /* Convert to binary */
+ rv = ATOB_ConvertAsciiToItem(der, body);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "error converting ascii to binary (%s)\n",
+ SECU_Strerror(PORT_GetError()));
+ PORT_Free(filedata.data);
+ return SECFailure;
+ }
+
+ PORT_Free(filedata.data);
+ } else {
+ /* Read in binary der */
+ rv = SECU_FileToItem(der, inFile);
+ if (rv != SECSuccess) {
+ fprintf(stderr, "error converting der (%s)\n",
+ SECU_Strerror(PORT_GetError()));
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+}
+
+#define INDENT_MULT 4
+
+SECStatus
+SECU_StripTagAndLength(SECItem *i)
+{
+ unsigned int start;
+
+ if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
+ return SECFailure;
+ }
+ start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
+ if (i->len < start) {
+ return SECFailure;
+ }
+ i->data += start;
+ i->len -= start;
+ return SECSuccess;
+}
+
+
+
+static void
+secu_PrintRawStringQuotesOptional(FILE *out, SECItem *si, const char *m,
+ int level, PRBool quotes)
+{
+ int column;
+ unsigned int i;
+
+ if ( m ) {
+ SECU_Indent(out, level); fprintf(out, "%s: ", m);
+ column = (level * INDENT_MULT) + strlen(m) + 2;
+ level++;
+ } else {
+ SECU_Indent(out, level);
+ column = level*INDENT_MULT;
+ }
+ if (quotes) {
+ fprintf(out, "\""); column++;
+ }
+
+ for (i = 0; i < si->len; i++) {
+ unsigned char val = si->data[i];
+ unsigned char c;
+ if (SECU_GetWrapEnabled() && column > 76) {
+ SECU_Newline(out);
+ SECU_Indent(out, level); column = level*INDENT_MULT;
+ }
+
+ if (utf8DisplayEnabled) {
+ if (val < 32)
+ c = '.';
+ else
+ c = val;
+ } else {
+ c = printable[val];
+ }
+ fprintf(out,"%c", c);
+ column++;
+ }
+
+ if (quotes) {
+ fprintf(out, "\""); column++;
+ }
+ if (SECU_GetWrapEnabled() &&
+ (column != level*INDENT_MULT || column > 76)) {
+ SECU_Newline(out);
+ }
+}
+
+static void
+secu_PrintRawString(FILE *out, SECItem *si, const char *m, int level)
+{
+ secu_PrintRawStringQuotesOptional(out, si, m, level, PR_TRUE);
+}
+
+void
+SECU_PrintString(FILE *out, const SECItem *si, const char *m, int level)
+{
+ SECItem my = *si;
+
+ if (SECSuccess != SECU_StripTagAndLength(&my) || !my.len)
+ return;
+ secu_PrintRawString(out, &my, m, level);
+}
+
+/* print an unencoded boolean */
+static void
+secu_PrintBoolean(FILE *out, SECItem *i, const char *m, int level)
+{
+ int val = 0;
+
+ if ( i->data && i->len ) {
+ val = i->data[0];
+ }
+
+ if (!m) {
+ m = "Boolean";
+ }
+ SECU_Indent(out, level);
+ fprintf(out, "%s: %s\n", m, (val ? "True" : "False"));
+}
+
+/*
+ * Format and print "time". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+static void
+secu_PrintTime(FILE *out, const PRTime time, const char *m, int level)
+{
+ PRExplodedTime printableTime;
+ char *timeString;
+
+ /* Convert to local time */
+ PR_ExplodeTime(time, PR_GMTParameters, &printableTime);
+
+ timeString = PORT_Alloc(256);
+ if (timeString == NULL)
+ return;
+
+ if (m != NULL) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: ", m);
+ }
+
+ if (PR_FormatTime(timeString, 256, "%a %b %d %H:%M:%S %Y", &printableTime)) {
+ fputs(timeString, out);
+ }
+
+ if (m != NULL)
+ fprintf(out, "\n");
+
+ PORT_Free(timeString);
+}
+
+/*
+ * Format and print the UTC Time "t". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+void
+SECU_PrintUTCTime(FILE *out, const SECItem *t, const char *m, int level)
+{
+ PRTime time;
+ SECStatus rv;
+
+ rv = DER_UTCTimeToTime(&time, t);
+ if (rv != SECSuccess)
+ return;
+
+ secu_PrintTime(out, time, m, level);
+}
+
+/*
+ * Format and print the Generalized Time "t". If the tag message "m"
+ * is not NULL, * do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+void
+SECU_PrintGeneralizedTime(FILE *out, const SECItem *t, const char *m, int level)
+{
+ PRTime time;
+ SECStatus rv;
+
+
+ rv = DER_GeneralizedTimeToTime(&time, t);
+ if (rv != SECSuccess)
+ return;
+
+ secu_PrintTime(out, time, m, level);
+}
+
+/*
+ * Format and print the UTC or Generalized Time "t". If the tag message
+ * "m" is not NULL, do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+void
+SECU_PrintTimeChoice(FILE *out, const SECItem *t, const char *m, int level)
+{
+ switch (t->type) {
+ case siUTCTime:
+ SECU_PrintUTCTime(out, t, m, level);
+ break;
+
+ case siGeneralizedTime:
+ SECU_PrintGeneralizedTime(out, t, m, level);
+ break;
+
+ default:
+ PORT_Assert(0);
+ break;
+ }
+}
+
+
+/* This prints a SET or SEQUENCE */
+static void
+SECU_PrintSet(FILE *out, const SECItem *t, const char *m, int level)
+{
+ int type = t->data[0] & SEC_ASN1_TAGNUM_MASK;
+ int constructed = t->data[0] & SEC_ASN1_CONSTRUCTED;
+ const char * label;
+ SECItem my = *t;
+
+ if (!constructed) {
+ SECU_PrintAsHex(out, t, m, level);
+ return;
+ }
+ if (SECSuccess != SECU_StripTagAndLength(&my))
+ return;
+
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: ", m);
+ }
+
+ if (type == SEC_ASN1_SET)
+ label = "Set ";
+ else if (type == SEC_ASN1_SEQUENCE)
+ label = "Sequence ";
+ else
+ label = "";
+ fprintf(out,"%s{\n", label); /* } */
+
+ while (my.len >= 2) {
+ SECItem tmp = my;
+
+ if (tmp.data[1] & 0x80) {
+ unsigned int i;
+ unsigned int lenlen = tmp.data[1] & 0x7f;
+ if (lenlen > sizeof tmp.len)
+ break;
+ tmp.len = 0;
+ for (i=0; i < lenlen; i++) {
+ tmp.len = (tmp.len << 8) | tmp.data[2+i];
+ }
+ tmp.len += lenlen + 2;
+ } else {
+ tmp.len = tmp.data[1] + 2;
+ }
+ if (tmp.len > my.len) {
+ tmp.len = my.len;
+ }
+ my.data += tmp.len;
+ my.len -= tmp.len;
+ SECU_PrintAny(out, &tmp, NULL, level + 1);
+ }
+ SECU_Indent(out, level); fprintf(out, /* { */ "}\n");
+}
+
+static void
+secu_PrintContextSpecific(FILE *out, const SECItem *i, const char *m, int level)
+{
+ int type = i->data[0] & SEC_ASN1_TAGNUM_MASK;
+ int constructed = i->data[0] & SEC_ASN1_CONSTRUCTED;
+ SECItem tmp;
+
+ if (constructed) {
+ char * m2;
+ if (!m)
+ m2 = PR_smprintf("[%d]", type);
+ else
+ m2 = PR_smprintf("%s: [%d]", m, type);
+ if (m2) {
+ SECU_PrintSet(out, i, m2, level);
+ PR_smprintf_free(m2);
+ }
+ return;
+ }
+
+ SECU_Indent(out, level);
+ if (m) {
+ fprintf(out, "%s: ", m);
+ }
+ fprintf(out,"[%d]\n", type);
+
+ tmp = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&tmp))
+ SECU_PrintAsHex(out, &tmp, m, level+1);
+}
+
+static void
+secu_PrintOctetString(FILE *out, const SECItem *i, const char *m, int level)
+{
+ SECItem tmp = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&tmp))
+ SECU_PrintAsHex(out, &tmp, m, level);
+}
+
+static void
+secu_PrintBitString(FILE *out, const SECItem *i, const char *m, int level)
+{
+ int unused_bits;
+ SECItem tmp = *i;
+
+ if (SECSuccess != SECU_StripTagAndLength(&tmp) || tmp.len < 2)
+ return;
+
+ unused_bits = *tmp.data++;
+ tmp.len--;
+
+ SECU_PrintAsHex(out, &tmp, m, level);
+ if (unused_bits) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "(%d least significant bits unused)\n", unused_bits);
+ }
+}
+
+/* in a decoded bit string, the len member is a bit length. */
+static void
+secu_PrintDecodedBitString(FILE *out, const SECItem *i, const char *m, int level)
+{
+ int unused_bits;
+ SECItem tmp = *i;
+
+
+ unused_bits = (tmp.len & 0x7) ? 8 - (tmp.len & 7) : 0;
+ DER_ConvertBitString(&tmp); /* convert length to byte length */
+
+ SECU_PrintAsHex(out, &tmp, m, level);
+ if (unused_bits) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "(%d least significant bits unused)\n", unused_bits);
+ }
+}
+
+
+/* Print a DER encoded Boolean */
+void
+SECU_PrintEncodedBoolean(FILE *out, const SECItem *i, const char *m, int level)
+{
+ SECItem my = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ secu_PrintBoolean(out, &my, m, level);
+}
+
+/* Print a DER encoded integer */
+void
+SECU_PrintEncodedInteger(FILE *out, const SECItem *i, const char *m, int level)
+{
+ SECItem my = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ SECU_PrintInteger(out, &my, m, level);
+}
+
+/* Print a DER encoded OID */
+void
+SECU_PrintEncodedObjectID(FILE *out, const SECItem *i, const char *m, int level)
+{
+ SECItem my = *i;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ SECU_PrintObjectID(out, &my, m, level);
+}
+
+static void
+secu_PrintBMPString(FILE *out, const SECItem *i, const char *m, int level)
+{
+ unsigned char * s;
+ unsigned char * d;
+ int len;
+ SECItem tmp = {0, 0, 0};
+ SECItem my = *i;
+
+ if (SECSuccess != SECU_StripTagAndLength(&my))
+ goto loser;
+ if (my.len % 2)
+ goto loser;
+ len = (int)(my.len / 2);
+ tmp.data = (unsigned char *)PORT_Alloc(len);
+ if (!tmp.data)
+ goto loser;
+ tmp.len = len;
+ for (s = my.data, d = tmp.data ; len > 0; len--) {
+ PRUint32 bmpChar = (s[0] << 8) | s[1]; s += 2;
+ if (!isprint(bmpChar))
+ goto loser;
+ *d++ = (unsigned char)bmpChar;
+ }
+ secu_PrintRawString(out, &tmp, m, level);
+ PORT_Free(tmp.data);
+ return;
+
+loser:
+ SECU_PrintAsHex(out, i, m, level);
+ if (tmp.data)
+ PORT_Free(tmp.data);
+}
+
+static void
+secu_PrintUniversalString(FILE *out, const SECItem *i, const char *m, int level)
+{
+ unsigned char * s;
+ unsigned char * d;
+ int len;
+ SECItem tmp = {0, 0, 0};
+ SECItem my = *i;
+
+ if (SECSuccess != SECU_StripTagAndLength(&my))
+ goto loser;
+ if (my.len % 4)
+ goto loser;
+ len = (int)(my.len / 4);
+ tmp.data = (unsigned char *)PORT_Alloc(len);
+ if (!tmp.data)
+ goto loser;
+ tmp.len = len;
+ for (s = my.data, d = tmp.data ; len > 0; len--) {
+ PRUint32 bmpChar = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
+ s += 4;
+ if (!isprint(bmpChar))
+ goto loser;
+ *d++ = (unsigned char)bmpChar;
+ }
+ secu_PrintRawString(out, &tmp, m, level);
+ PORT_Free(tmp.data);
+ return;
+
+loser:
+ SECU_PrintAsHex(out, i, m, level);
+ if (tmp.data)
+ PORT_Free(tmp.data);
+}
+
+static void
+secu_PrintUniversal(FILE *out, const SECItem *i, const char *m, int level)
+{
+ switch (i->data[0] & SEC_ASN1_TAGNUM_MASK) {
+ case SEC_ASN1_ENUMERATED:
+ case SEC_ASN1_INTEGER:
+ SECU_PrintEncodedInteger(out, i, m, level);
+ break;
+ case SEC_ASN1_OBJECT_ID:
+ SECU_PrintEncodedObjectID(out, i, m, level);
+ break;
+ case SEC_ASN1_BOOLEAN:
+ SECU_PrintEncodedBoolean(out, i, m, level);
+ break;
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_T61_STRING:
+ SECU_PrintString(out, i, m, level);
+ break;
+ case SEC_ASN1_GENERALIZED_TIME:
+ SECU_PrintGeneralizedTime(out, i, m, level);
+ break;
+ case SEC_ASN1_UTC_TIME:
+ SECU_PrintUTCTime(out, i, m, level);
+ break;
+ case SEC_ASN1_NULL:
+ SECU_Indent(out, level);
+ if (m && m[0])
+ fprintf(out, "%s: NULL\n", m);
+ else
+ fprintf(out, "NULL\n");
+ break;
+ case SEC_ASN1_SET:
+ case SEC_ASN1_SEQUENCE:
+ SECU_PrintSet(out, i, m, level);
+ break;
+ case SEC_ASN1_OCTET_STRING:
+ secu_PrintOctetString(out, i, m, level);
+ break;
+ case SEC_ASN1_BIT_STRING:
+ secu_PrintBitString(out, i, m, level);
+ break;
+ case SEC_ASN1_BMP_STRING:
+ secu_PrintBMPString(out, i, m, level);
+ break;
+ case SEC_ASN1_UNIVERSAL_STRING:
+ secu_PrintUniversalString(out, i, m, level);
+ break;
+ default:
+ SECU_PrintAsHex(out, i, m, level);
+ break;
+ }
+}
+
+void
+SECU_PrintAny(FILE *out, const SECItem *i, const char *m, int level)
+{
+ if ( i && i->len && i->data ) {
+ switch (i->data[0] & SEC_ASN1_CLASS_MASK) {
+ case SEC_ASN1_CONTEXT_SPECIFIC:
+ secu_PrintContextSpecific(out, i, m, level);
+ break;
+ case SEC_ASN1_UNIVERSAL:
+ secu_PrintUniversal(out, i, m, level);
+ break;
+ default:
+ SECU_PrintAsHex(out, i, m, level);
+ break;
+ }
+ }
+}
+
+static int
+secu_PrintValidity(FILE *out, CERTValidity *v, char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintTimeChoice(out, &v->notBefore, "Not Before", level+1);
+ SECU_PrintTimeChoice(out, &v->notAfter, "Not After ", level+1);
+ return 0;
+}
+
+/* This function does NOT expect a DER type and length. */
+SECOidTag
+SECU_PrintObjectID(FILE *out, const SECItem *oid, const char *m, int level)
+{
+ SECOidData *oiddata;
+ char * oidString = NULL;
+
+ oiddata = SECOID_FindOID(oid);
+ if (oiddata != NULL) {
+ const char *name = oiddata->desc;
+ SECU_Indent(out, level);
+ if (m != NULL)
+ fprintf(out, "%s: ", m);
+ fprintf(out, "%s\n", name);
+ return oiddata->offset;
+ }
+ oidString = CERT_GetOidString(oid);
+ if (oidString) {
+ SECU_Indent(out, level);
+ if (m != NULL)
+ fprintf(out, "%s: ", m);
+ fprintf(out, "%s\n", oidString);
+ PR_smprintf_free(oidString);
+ return SEC_OID_UNKNOWN;
+ }
+ SECU_PrintAsHex(out, oid, m, level);
+ return SEC_OID_UNKNOWN;
+}
+
+typedef struct secuPBEParamsStr {
+ SECItem salt;
+ SECItem iterationCount;
+ SECItem keyLength;
+ SECAlgorithmID cipherAlg;
+ SECAlgorithmID kdfAlg;
+} secuPBEParams;
+
+SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
+
+/* SECOID_PKCS5_PBKDF2 */
+const SEC_ASN1Template secuKDF2Params[] =
+{
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
+ { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
+ { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
+ { SEC_ASN1_INTEGER, offsetof(secuPBEParams, keyLength) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { 0 }
+};
+
+/* PKCS5v1 & PKCS12 */
+const SEC_ASN1Template secuPBEParamsTemp[] =
+{
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
+ { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
+ { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
+ { 0 }
+};
+
+/* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
+const SEC_ASN1Template secuPBEV2Params[] =
+{
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams)},
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, cipherAlg),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { 0 }
+};
+
+void
+secu_PrintRSAPSSParams(FILE *out, SECItem *value, char *m, int level)
+{
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECStatus rv;
+ SECKEYRSAPSSParams param;
+ SECAlgorithmID maskHashAlg;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf (out, "%s:\n", m);
+ }
+
+ if (!pool) {
+ SECU_Indent(out, level);
+ fprintf(out, "Out of memory\n");
+ return;
+ }
+
+ PORT_Memset(¶m, 0, sizeof param);
+
+ rv = SEC_QuickDERDecodeItem(pool, ¶m,
+ SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate),
+ value);
+ if (rv == SECSuccess) {
+ if (!param.hashAlg) {
+ SECU_Indent(out, level+1);
+ fprintf(out, "Hash algorithm: default, SHA-1\n");
+ } else {
+ SECU_PrintObjectID(out, ¶m.hashAlg->algorithm,
+ "Hash algorithm", level+1);
+ }
+ if (!param.maskAlg) {
+ SECU_Indent(out, level+1);
+ fprintf(out, "Mask algorithm: default, MGF1\n");
+ SECU_Indent(out, level+1);
+ fprintf(out, "Mask hash algorithm: default, SHA-1\n");
+ } else {
+ SECU_PrintObjectID(out, ¶m.maskAlg->algorithm,
+ "Mask algorithm", level+1);
+ rv = SEC_QuickDERDecodeItem(pool, &maskHashAlg,
+ SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
+ ¶m.maskAlg->parameters);
+ if (rv == SECSuccess) {
+ SECU_PrintObjectID(out, &maskHashAlg.algorithm,
+ "Mask hash algorithm", level+1);
+ } else {
+ SECU_Indent(out, level+1);
+ fprintf(out, "Invalid mask generation algorithm parameters\n");
+ }
+ }
+ if (!param.saltLength.data) {
+ SECU_Indent(out, level+1);
+ fprintf(out, "Salt length: default, %i (0x%2X)\n", 20, 20);
+ } else {
+ SECU_PrintInteger(out, ¶m.saltLength, "Salt Length", level+1);
+ }
+ } else {
+ SECU_Indent(out, level+1);
+ fprintf(out, "Invalid RSA-PSS parameters\n");
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+void
+secu_PrintKDF2Params(FILE *out, SECItem *value, char *m, int level)
+{
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECStatus rv;
+ secuPBEParams param;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf (out, "%s:\n", m);
+ }
+
+ if (!pool) {
+ SECU_Indent(out, level);
+ fprintf(out, "Out of memory\n");
+ return;
+ }
+
+ PORT_Memset(¶m, 0, sizeof param);
+ rv = SEC_QuickDERDecodeItem(pool, ¶m, secuKDF2Params, value);
+ if (rv == SECSuccess) {
+ SECU_PrintAsHex(out, ¶m.salt, "Salt", level+1);
+ SECU_PrintInteger(out, ¶m.iterationCount, "Iteration Count",
+ level+1);
+ SECU_PrintInteger(out, ¶m.keyLength, "Key Length", level+1);
+ SECU_PrintAlgorithmID(out, ¶m.kdfAlg, "KDF algorithm", level+1);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+void
+secu_PrintPKCS5V2Params(FILE *out, SECItem *value, char *m, int level)
+{
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECStatus rv;
+ secuPBEParams param;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf (out, "%s:\n", m);
+ }
+
+ if (!pool) {
+ SECU_Indent(out, level);
+ fprintf(out, "Out of memory\n");
+ return;
+ }
+
+ PORT_Memset(¶m, 0, sizeof param);
+ rv = SEC_QuickDERDecodeItem(pool, ¶m, secuPBEV2Params, value);
+ if (rv == SECSuccess) {
+ SECU_PrintAlgorithmID(out, ¶m.kdfAlg, "KDF", level+1);
+ SECU_PrintAlgorithmID(out, ¶m.cipherAlg, "Cipher", level+1);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+void
+secu_PrintPBEParams(FILE *out, SECItem *value, char *m, int level)
+{
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECStatus rv;
+ secuPBEParams param;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf (out, "%s:\n", m);
+ }
+
+ if (!pool) {
+ SECU_Indent(out, level);
+ fprintf(out, "Out of memory\n");
+ return;
+ }
+
+ PORT_Memset(¶m, 0, sizeof(secuPBEParams));
+ rv = SEC_QuickDERDecodeItem(pool, ¶m, secuPBEParamsTemp, value);
+ if (rv == SECSuccess) {
+ SECU_PrintAsHex(out, ¶m.salt, "Salt", level+1);
+ SECU_PrintInteger(out, ¶m.iterationCount, "Iteration Count",
+ level+1);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+/* This function does NOT expect a DER type and length. */
+void
+SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, int level)
+{
+ SECOidTag algtag;
+ SECU_PrintObjectID(out, &a->algorithm, m, level);
+
+ algtag = SECOID_GetAlgorithmTag(a);
+ if (SEC_PKCS5IsAlgorithmPBEAlgTag(algtag)) {
+ switch (algtag) {
+ case SEC_OID_PKCS5_PBKDF2:
+ secu_PrintKDF2Params(out, &a->parameters, "Parameters", level+1);
+ break;
+ case SEC_OID_PKCS5_PBES2:
+ secu_PrintPKCS5V2Params(out, &a->parameters, "Encryption", level+1);
+ break;
+ case SEC_OID_PKCS5_PBMAC1:
+ secu_PrintPKCS5V2Params(out, &a->parameters, "MAC", level+1);
+ break;
+ default:
+ secu_PrintPBEParams(out, &a->parameters, "Parameters", level+1);
+ break;
+ }
+ return;
+ }
+
+ if (algtag == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
+ secu_PrintRSAPSSParams(out, &a->parameters, "Parameters", level+1);
+ return;
+ }
+
+ if (a->parameters.len == 0
+ || (a->parameters.len == 2
+ && PORT_Memcmp(a->parameters.data, "\005\000", 2) == 0)) {
+ /* No arguments or NULL argument */
+ } else {
+ /* Print args to algorithm */
+ SECU_PrintAsHex(out, &a->parameters, "Args", level+1);
+ }
+}
+
+static void
+secu_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m, int level)
+{
+ SECItem *value;
+ int i;
+ char om[100];
+
+ if (m) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ }
+
+ /*
+ * Should make this smarter; look at the type field and then decode
+ * and print the value(s) appropriately!
+ */
+ SECU_PrintObjectID(out, &(attr->type), "Type", level+1);
+ if (attr->values != NULL) {
+ i = 0;
+ while ((value = attr->values[i++]) != NULL) {
+ sprintf(om, "Value (%d)%s", i, attr->encoded ? " (encoded)" : "");
+ if (attr->encoded || attr->typeTag == NULL) {
+ SECU_PrintAny(out, value, om, level+1);
+ } else {
+ switch (attr->typeTag->offset) {
+ default:
+ SECU_PrintAsHex(out, value, om, level+1);
+ break;
+ case SEC_OID_PKCS9_CONTENT_TYPE:
+ SECU_PrintObjectID(out, value, om, level+1);
+ break;
+ case SEC_OID_PKCS9_SIGNING_TIME:
+ SECU_PrintTimeChoice(out, value, om, level+1);
+ break;
+ }
+ }
+ }
+ }
+}
+
+#ifndef NSS_DISABLE_ECC
+static void
+secu_PrintECPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
+{
+ SECItem curveOID = { siBuffer, NULL, 0};
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &pk->u.ec.publicValue, "PublicValue", level+1);
+ /* For named curves, the DEREncodedParams field contains an
+ * ASN Object ID (0x06 is SEC_ASN1_OBJECT_ID).
+ */
+ if ((pk->u.ec.DEREncodedParams.len > 2) &&
+ (pk->u.ec.DEREncodedParams.data[0] == 0x06)) {
+ curveOID.len = pk->u.ec.DEREncodedParams.data[1];
+ curveOID.data = pk->u.ec.DEREncodedParams.data + 2;
+ SECU_PrintObjectID(out, &curveOID, "Curve", level +1);
+ }
+}
+#endif /* NSS_DISABLE_ECC */
+
+void
+SECU_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &pk->u.rsa.modulus, "Modulus", level+1);
+ SECU_PrintInteger(out, &pk->u.rsa.publicExponent, "Exponent", level+1);
+ if (pk->u.rsa.publicExponent.len == 1 &&
+ pk->u.rsa.publicExponent.data[0] == 1) {
+ SECU_Indent(out, level +1); fprintf(out, "Error: INVALID RSA KEY!\n");
+ }
+}
+
+void
+SECU_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &pk->u.dsa.params.prime, "Prime", level+1);
+ SECU_PrintInteger(out, &pk->u.dsa.params.subPrime, "Subprime", level+1);
+ SECU_PrintInteger(out, &pk->u.dsa.params.base, "Base", level+1);
+ SECU_PrintInteger(out, &pk->u.dsa.publicValue, "PublicValue", level+1);
+}
+
+static void
+secu_PrintSubjectPublicKeyInfo(FILE *out, PLArenaPool *arena,
+ CERTSubjectPublicKeyInfo *i, char *msg, int level)
+{
+ SECKEYPublicKey *pk;
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", msg);
+ SECU_PrintAlgorithmID(out, &i->algorithm, "Public Key Algorithm", level+1);
+
+ pk = SECKEY_ExtractPublicKey(i);
+ if (pk) {
+ switch (pk->keyType) {
+ case rsaKey:
+ SECU_PrintRSAPublicKey(out, pk, "RSA Public Key", level +1);
+ break;
+
+ case dsaKey:
+ SECU_PrintDSAPublicKey(out, pk, "DSA Public Key", level +1);
+ break;
+
+#ifndef NSS_DISABLE_ECC
+ case ecKey:
+ secu_PrintECPublicKey(out, pk, "EC Public Key", level +1);
+ break;
+#endif
+
+ case dhKey:
+ case fortezzaKey:
+ case keaKey:
+ SECU_Indent(out, level);
+ fprintf(out, "unable to format this SPKI algorithm type\n");
+ goto loser;
+ default:
+ SECU_Indent(out, level);
+ fprintf(out, "unknown SPKI algorithm type\n");
+ goto loser;
+ }
+ PORT_FreeArena(pk->arena, PR_FALSE);
+ } else {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing public key");
+loser:
+ if (i->subjectPublicKey.data) {
+ SECU_PrintAny(out, &i->subjectPublicKey, "Raw", level);
+ }
+ }
+}
+
+static void
+printStringWithoutCRLF(FILE *out, const char *str)
+{
+ const char *c = str;
+ while (*c) {
+ if (*c != '\r' && *c != '\n') {
+ fputc(*c, out);
+ }
+ ++c;
+ }
+}
+
+int
+SECU_PrintDumpDerIssuerAndSerial(FILE *out, SECItem *der, char *m,
+ int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificate *c;
+ int rv = SEC_ERROR_NO_MEMORY;
+ char *derIssuerB64;
+ char *derSerialB64;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate */
+ c = PORT_ArenaZNew(arena, CERTCertificate);
+ if (!c)
+ goto loser;
+ c->arena = arena;
+ rv = SEC_ASN1DecodeItem(arena, c,
+ SEC_ASN1_GET(CERT_CertificateTemplate), der);
+ if (rv) {
+ SECU_PrintErrMsg(out, 0, "Error", "Parsing extension");
+ goto loser;
+ }
+
+ SECU_PrintName(out, &c->subject, "Subject", 0);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ SECU_PrintName(out, &c->issuer, "Issuer", 0);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ SECU_PrintInteger(out, &c->serialNumber, "Serial Number", 0);
+
+ derIssuerB64 = BTOA_ConvertItemToAscii(&c->derIssuer);
+ derSerialB64 = BTOA_ConvertItemToAscii(&c->serialNumber);
+
+ fprintf(out, "Issuer DER Base64:\n");
+ if (SECU_GetWrapEnabled()) {
+ fprintf(out, "%s\n", derIssuerB64);
+ } else {
+ printStringWithoutCRLF(out, derIssuerB64);
+ fputs("\n", out);
+ }
+
+ fprintf(out, "Serial DER Base64:\n");
+ if (SECU_GetWrapEnabled()) {
+ fprintf(out, "%s\n", derSerialB64);
+ } else {
+ printStringWithoutCRLF(out, derSerialB64);
+ fputs("\n", out);
+ }
+
+ PORT_Free(derIssuerB64);
+ PORT_Free(derSerialB64);
+
+ fprintf(out, "Serial DER as C source: \n{ %d, \"", c->serialNumber.len);
+
+ {
+ int i;
+ for (i=0; i < c->serialNumber.len; ++i) {
+ unsigned char *chardata = (unsigned char*)(c->serialNumber.data);
+ unsigned char c = *(chardata + i);
+
+ fprintf(out, "\\x%02x", c);
+ }
+ fprintf(out, "\" }\n");
+ }
+
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+static SECStatus
+secu_PrintX509InvalidDate(FILE *out, SECItem *value, char *msg, int level)
+{
+ SECItem decodedValue;
+ SECStatus rv;
+ PRTime invalidTime;
+ char *formattedTime = NULL;
+
+ decodedValue.data = NULL;
+ rv = SEC_ASN1DecodeItem (NULL, &decodedValue,
+ SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
+ value);
+ if (rv == SECSuccess) {
+ rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
+ if (rv == SECSuccess) {
+ formattedTime = CERT_GenTime2FormattedAscii
+ (invalidTime, "%a %b %d %H:%M:%S %Y");
+ SECU_Indent(out, level +1);
+ fprintf (out, "%s: %s\n", msg, formattedTime);
+ PORT_Free (formattedTime);
+ }
+ }
+ PORT_Free (decodedValue.data);
+ return (rv);
+}
+
+static SECStatus
+PrintExtKeyUsageExtension (FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTOidSequence *os;
+ SECItem **op;
+
+ os = CERT_DecodeOidSequence(value);
+ if( (CERTOidSequence *)NULL == os ) {
+ return SECFailure;
+ }
+
+ for( op = os->oids; *op; op++ ) {
+ SECU_PrintObjectID(out, *op, msg, level + 1);
+ }
+ CERT_DestroyOidSequence(os);
+ return SECSuccess;
+}
+
+static SECStatus
+secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level) {
+ CERTBasicConstraints constraints;
+ SECStatus rv;
+
+ SECU_Indent(out, level);
+ if (msg) {
+ fprintf(out,"%s: ",msg);
+ }
+ rv = CERT_DecodeBasicConstraintValue(&constraints,value);
+ if (rv == SECSuccess && constraints.isCA) {
+ if (constraints.pathLenConstraint >= 0) {
+ fprintf(out,"Is a CA with a maximum path length of %d.\n",
+ constraints.pathLenConstraint);
+ } else {
+ fprintf(out,"Is a CA with no maximum path length.\n");
+ }
+ } else {
+ fprintf(out,"Is not a CA.\n");
+ }
+ return SECSuccess;
+}
+
+static const char * const nsTypeBits[] = {
+ "SSL Client",
+ "SSL Server",
+ "S/MIME",
+ "Object Signing",
+ "Reserved",
+ "SSL CA",
+ "S/MIME CA",
+ "ObjectSigning CA"
+};
+
+/* NSCertType is merely a bit string whose bits are displayed symbolically */
+static SECStatus
+secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
+{
+ int unused;
+ int NS_Type;
+ int i;
+ int found = 0;
+ SECItem my = *value;
+
+ if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ SECU_PrintAny(out, value, "Data", level);
+ return SECSuccess;
+ }
+
+ unused = (my.len == 2) ? (my.data[0] & 0x0f) : 0;
+ NS_Type = my.data[1] & (0xff << unused);
+
+
+ SECU_Indent(out, level);
+ if (msg) {
+ fprintf(out,"%s: ",msg);
+ } else {
+ fprintf(out,"Netscape Certificate Type: ");
+ }
+ for (i=0; i < 8; i++) {
+ if ( (0x80 >> i) & NS_Type) {
+ fprintf(out, "%c%s", (found ? ',' : '<'), nsTypeBits[i]);
+ found = 1;
+ }
+ }
+ fprintf(out, (found ? ">\n" : "none\n"));
+ return SECSuccess;
+}
+
+static const char * const usageBits[] = {
+ "Digital Signature", /* 0x80 */
+ "Non-Repudiation", /* 0x40 */
+ "Key Encipherment", /* 0x20 */
+ "Data Encipherment", /* 0x10 */
+ "Key Agreement", /* 0x08 */
+ "Certificate Signing", /* 0x04 */
+ "CRL Signing", /* 0x02 */
+ "Encipher Only", /* 0x01 */
+ "Decipher Only", /* 0x0080 */
+ NULL
+};
+
+/* X509KeyUsage is merely a bit string whose bits are displayed symbolically */
+static void
+secu_PrintX509KeyUsage(FILE *out, SECItem *value, char *msg, int level)
+{
+ int unused;
+ int usage;
+ int i;
+ int found = 0;
+ SECItem my = *value;
+
+ if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ SECU_PrintAny(out, value, "Data", level);
+ return;
+ }
+
+ unused = (my.len >= 2) ? (my.data[0] & 0x0f) : 0;
+ usage = (my.len == 2) ? (my.data[1] & (0xff << unused)) << 8
+ : (my.data[1] << 8) |
+ (my.data[2] & (0xff << unused));
+
+ SECU_Indent(out, level);
+ fprintf(out, "Usages: ");
+ for (i=0; usageBits[i]; i++) {
+ if ( (0x8000 >> i) & usage) {
+ if (found)
+ SECU_Indent(out, level + 2);
+ fprintf(out, "%s\n", usageBits[i]);
+ found = 1;
+ }
+ }
+ if (!found) {
+ fprintf(out, "(none)\n");
+ }
+}
+
+static void
+secu_PrintIPAddress(FILE *out, SECItem *value, char *msg, int level)
+{
+ PRStatus st;
+ PRNetAddr addr;
+ char addrBuf[80];
+
+ memset(&addr, 0, sizeof addr);
+ if (value->len == 4) {
+ addr.inet.family = PR_AF_INET;
+ memcpy(&addr.inet.ip, value->data, value->len);
+ } else if (value->len == 16) {
+ addr.ipv6.family = PR_AF_INET6;
+ memcpy(addr.ipv6.ip.pr_s6_addr, value->data, value->len);
+ if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
+ /* convert to IPv4. */
+ addr.inet.family = PR_AF_INET;
+ memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr[12], 4);
+ memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
+ }
+ } else {
+ goto loser;
+ }
+
+ st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf);
+ if (st == PR_SUCCESS) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: %s\n", msg, addrBuf);
+ } else {
+loser:
+ SECU_PrintAsHex(out, value, msg, level);
+ }
+}
+
+
+static void
+secu_PrintGeneralName(FILE *out, CERTGeneralName *gname, char *msg, int level)
+{
+ char label[40];
+ if (msg && msg[0]) {
+ SECU_Indent(out, level++); fprintf(out, "%s: \n", msg);
+ }
+ switch (gname->type) {
+ case certOtherName :
+ SECU_PrintAny( out, &gname->name.OthName.name, "Other Name", level);
+ SECU_PrintObjectID(out, &gname->name.OthName.oid, "OID", level+1);
+ break;
+ case certDirectoryName :
+ SECU_PrintName(out, &gname->name.directoryName, "Directory Name", level);
+ break;
+ case certRFC822Name :
+ secu_PrintRawString( out, &gname->name.other, "RFC822 Name", level);
+ break;
+ case certDNSName :
+ secu_PrintRawString( out, &gname->name.other, "DNS name", level);
+ break;
+ case certURI :
+ secu_PrintRawString( out, &gname->name.other, "URI", level);
+ break;
+ case certIPAddress :
+ secu_PrintIPAddress(out, &gname->name.other, "IP Address", level);
+ break;
+ case certRegisterID :
+ SECU_PrintObjectID( out, &gname->name.other, "Registered ID", level);
+ break;
+ case certX400Address :
+ SECU_PrintAny( out, &gname->name.other, "X400 Address", level);
+ break;
+ case certEDIPartyName :
+ SECU_PrintAny( out, &gname->name.other, "EDI Party", level);
+ break;
+ default:
+ PR_snprintf(label, sizeof label, "unknown type [%d]",
+ (int)gname->type - 1);
+ SECU_PrintAsHex(out, &gname->name.other, label, level);
+ break;
+ }
+}
+
+static void
+secu_PrintGeneralNames(FILE *out, CERTGeneralName *gname, char *msg, int level)
+{
+ CERTGeneralName *name = gname;
+ do {
+ secu_PrintGeneralName(out, name, msg, level);
+ name = CERT_GetNextGeneralName(name);
+ } while (name && name != gname);
+}
+
+
+static void
+secu_PrintAuthKeyIDExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTAuthKeyID *kid = NULL;
+ PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ kid = CERT_DecodeAuthKeyID(pool, value);
+ if (!kid) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ } else {
+ int keyIDPresent = (kid->keyID.data && kid->keyID.len);
+ int issuerPresent = kid->authCertIssuer != NULL;
+ int snPresent = (kid->authCertSerialNumber.data &&
+ kid->authCertSerialNumber.len);
+
+ if (keyIDPresent)
+ SECU_PrintAsHex(out, &kid->keyID, "Key ID", level);
+ if (issuerPresent)
+ secu_PrintGeneralName(out, kid->authCertIssuer, "Issuer", level);
+ if (snPresent)
+ SECU_PrintInteger(out, &kid->authCertSerialNumber,
+ "Serial Number", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
+static void
+secu_PrintAltNameExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTGeneralName * nameList;
+ CERTGeneralName * current;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ nameList = current = CERT_DecodeAltNameExtension(pool, value);
+ if (!current) {
+ if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
+ /* Decoder found empty sequence, which is invalid. */
+ PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
+ }
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ } else {
+ do {
+ secu_PrintGeneralName(out, current, msg, level);
+ current = CERT_GetNextGeneralName(current);
+ } while (current != nameList);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+static void
+secu_PrintCRLDistPtsExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTCrlDistributionPoints * dPoints;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ dPoints = CERT_DecodeCRLDistributionPoints(pool, value);
+ if (dPoints && dPoints->distPoints && dPoints->distPoints[0]) {
+ CRLDistributionPoint ** pPoints = dPoints->distPoints;
+ CRLDistributionPoint * pPoint;
+ while (NULL != (pPoint = *pPoints++)) {
+ SECU_Indent(out, level); fputs("Distribution point:\n", out);
+ if (pPoint->distPointType == generalName &&
+ pPoint->distPoint.fullName != NULL) {
+ secu_PrintGeneralNames(out, pPoint->distPoint.fullName, NULL,
+ level + 1);
+ } else if (pPoint->distPointType == relativeDistinguishedName &&
+ pPoint->distPoint.relativeName.avas) {
+ SECU_PrintRDN(out, &pPoint->distPoint.relativeName, "RDN",
+ level + 1);
+ } else if (pPoint->derDistPoint.data) {
+ SECU_PrintAny(out, &pPoint->derDistPoint, "Point", level + 1);
+ }
+ if (pPoint->reasons.data) {
+ secu_PrintDecodedBitString(out, &pPoint->reasons, "Reasons",
+ level + 1);
+ }
+ if (pPoint->crlIssuer) {
+ secu_PrintGeneralName(out, pPoint->crlIssuer, "CRL issuer",
+ level + 1);
+ }
+ }
+ } else {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Data", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
+static void
+secu_PrintNameConstraintSubtree(FILE *out, CERTNameConstraint *value,
+ char *msg, int level)
+{
+ CERTNameConstraint *head = value;
+ SECU_Indent(out, level); fprintf(out, "%s Subtree:\n", msg);
+ level++;
+ do {
+ secu_PrintGeneralName(out, &value->name, NULL, level);
+ if (value->min.data)
+ SECU_PrintInteger(out, &value->min, "Minimum", level+1);
+ if (value->max.data)
+ SECU_PrintInteger(out, &value->max, "Maximum", level+1);
+ value = CERT_GetNextNameConstraint(value);
+ } while (value != head);
+}
+
+static void
+secu_PrintNameConstraintsExtension(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTNameConstraints * cnstrnts;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ cnstrnts = CERT_DecodeNameConstraintsExtension(pool, value);
+ if (!cnstrnts) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Raw", level);
+ } else {
+ if (cnstrnts->permited)
+ secu_PrintNameConstraintSubtree(out, cnstrnts->permited,
+ "Permitted", level);
+ if (cnstrnts->excluded)
+ secu_PrintNameConstraintSubtree(out, cnstrnts->excluded,
+ "Excluded", level);
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
+static void
+secu_PrintAuthorityInfoAcess(FILE *out, SECItem *value, char *msg, int level)
+{
+ CERTAuthInfoAccess **infos = NULL;
+ PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+
+ if (!pool) {
+ SECU_PrintError("Error", "Allocating new ArenaPool");
+ return;
+ }
+ infos = CERT_DecodeAuthInfoAccessExtension(pool, value);
+ if (!infos) {
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, value, "Raw", level);
+ } else {
+ CERTAuthInfoAccess *info;
+ while (NULL != (info = *infos++)) {
+ if (info->method.data) {
+ SECU_PrintObjectID(out, &info->method, "Method", level);
+ } else {
+ SECU_Indent(out,level);
+ fprintf(out, "Error: missing method\n");
+ }
+ if (info->location) {
+ secu_PrintGeneralName(out, info->location, "Location", level);
+ } else {
+ SECU_PrintAny(out, &info->derLocation, "Location", level);
+ }
+ }
+ }
+ PORT_FreeArena(pool, PR_FALSE);
+}
+
+
+void
+SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
+ char *msg, int level)
+{
+ SECOidTag oidTag;
+
+ if ( extensions ) {
+ if (msg && *msg) {
+ SECU_Indent(out, level++); fprintf(out, "%s:\n", msg);
+ }
+
+ while ( *extensions ) {
+ SECItem *tmpitem;
+
+ tmpitem = &(*extensions)->id;
+ SECU_PrintObjectID(out, tmpitem, "Name", level);
+
+ tmpitem = &(*extensions)->critical;
+ if ( tmpitem->len ) {
+ secu_PrintBoolean(out, tmpitem, "Critical", level);
+ }
+
+ oidTag = SECOID_FindOIDTag (&((*extensions)->id));
+ tmpitem = &((*extensions)->value);
+
+ switch (oidTag) {
+ case SEC_OID_X509_INVALID_DATE:
+ case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
+ secu_PrintX509InvalidDate(out, tmpitem, "Date", level );
+ break;
+ case SEC_OID_X509_CERTIFICATE_POLICIES:
+ SECU_PrintPolicy(out, tmpitem, "Data", level );
+ break;
+ case SEC_OID_NS_CERT_EXT_BASE_URL:
+ case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
+ case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
+ case SEC_OID_NS_CERT_EXT_CA_CRL_URL:
+ case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
+ case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
+ case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
+ case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
+ case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
+ case SEC_OID_OCSP_RESPONDER:
+ SECU_PrintString(out,tmpitem, "URL", level);
+ break;
+ case SEC_OID_NS_CERT_EXT_COMMENT:
+ SECU_PrintString(out,tmpitem, "Comment", level);
+ break;
+ case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
+ SECU_PrintString(out,tmpitem, "ServerName", level);
+ break;
+ case SEC_OID_NS_CERT_EXT_CERT_TYPE:
+ secu_PrintNSCertType(out,tmpitem,"Data",level);
+ break;
+ case SEC_OID_X509_BASIC_CONSTRAINTS:
+ secu_PrintBasicConstraints(out,tmpitem,"Data",level);
+ break;
+ case SEC_OID_X509_EXT_KEY_USAGE:
+ PrintExtKeyUsageExtension(out, tmpitem, NULL, level);
+ break;
+ case SEC_OID_X509_KEY_USAGE:
+ secu_PrintX509KeyUsage(out, tmpitem, NULL, level );
+ break;
+ case SEC_OID_X509_AUTH_KEY_ID:
+ secu_PrintAuthKeyIDExtension(out, tmpitem, NULL, level );
+ break;
+ case SEC_OID_X509_SUBJECT_ALT_NAME:
+ case SEC_OID_X509_ISSUER_ALT_NAME:
+ secu_PrintAltNameExtension(out, tmpitem, NULL, level );
+ break;
+ case SEC_OID_X509_CRL_DIST_POINTS:
+ secu_PrintCRLDistPtsExtension(out, tmpitem, NULL, level );
+ break;
+ case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
+ SECU_PrintPrivKeyUsagePeriodExtension(out, tmpitem, NULL,
+ level );
+ break;
+ case SEC_OID_X509_NAME_CONSTRAINTS:
+ secu_PrintNameConstraintsExtension(out, tmpitem, NULL, level);
+ break;
+ case SEC_OID_X509_AUTH_INFO_ACCESS:
+ secu_PrintAuthorityInfoAcess(out, tmpitem, NULL, level);
+ break;
+
+ case SEC_OID_X509_CRL_NUMBER:
+ case SEC_OID_X509_REASON_CODE:
+
+ /* PKIX OIDs */
+ case SEC_OID_PKIX_OCSP:
+ case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
+ case SEC_OID_PKIX_OCSP_NONCE:
+ case SEC_OID_PKIX_OCSP_CRL:
+ case SEC_OID_PKIX_OCSP_RESPONSE:
+ case SEC_OID_PKIX_OCSP_NO_CHECK:
+ case SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF:
+ case SEC_OID_PKIX_OCSP_SERVICE_LOCATOR:
+ case SEC_OID_PKIX_REGCTRL_REGTOKEN:
+ case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
+ case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
+ case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
+ case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
+ case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
+ case SEC_OID_PKIX_REGINFO_UTF8_PAIRS:
+ case SEC_OID_PKIX_REGINFO_CERT_REQUEST:
+
+ /* Netscape extension OIDs. */
+ case SEC_OID_NS_CERT_EXT_NETSCAPE_OK:
+ case SEC_OID_NS_CERT_EXT_ISSUER_LOGO:
+ case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO:
+ case SEC_OID_NS_CERT_EXT_ENTITY_LOGO:
+ case SEC_OID_NS_CERT_EXT_USER_PICTURE:
+
+ /* x.509 v3 Extensions */
+ case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
+ case SEC_OID_X509_SUBJECT_KEY_ID:
+ case SEC_OID_X509_POLICY_MAPPINGS:
+ case SEC_OID_X509_POLICY_CONSTRAINTS:
+
+
+ default:
+ SECU_PrintAny(out, tmpitem, "Data", level);
+ break;
+ }
+
+ SECU_Newline(out);
+ extensions++;
+ }
+ }
+}
+
+/* An RDN is a subset of a DirectoryName, and we already know how to
+ * print those, so make a directory name out of the RDN, and print it.
+ */
+void
+SECU_PrintRDN(FILE *out, CERTRDN *rdn, const char *msg, int level)
+{
+ CERTName name;
+ CERTRDN *rdns[2];
+
+ name.arena = NULL;
+ name.rdns = rdns;
+ rdns[0] = rdn;
+ rdns[1] = NULL;
+ SECU_PrintName(out, &name, msg, level);
+}
+
+void
+SECU_PrintNameQuotesOptional(FILE *out, CERTName *name, const char *msg,
+ int level, PRBool quotes)
+{
+ char *nameStr = NULL;
+ char *str;
+ SECItem my;
+
+ if (!name) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return;
+ }
+ if (!name->rdns || !name->rdns[0]) {
+ str = "(empty)";
+ } else {
+ str = nameStr = CERT_NameToAscii(name);
+ }
+ if (!str) {
+ str = "!Invalid AVA!";
+ }
+ my.data = (unsigned char *)str;
+ my.len = PORT_Strlen(str);
+#if 1
+ secu_PrintRawStringQuotesOptional(out, &my, msg, level, quotes);
+#else
+ SECU_Indent(out, level); fprintf(out, "%s: ", msg);
+ fprintf(out, str);
+ SECU_Newline(out);
+#endif
+ PORT_Free(nameStr);
+}
+
+void
+SECU_PrintName(FILE *out, CERTName *name, const char *msg, int level)
+{
+ SECU_PrintNameQuotesOptional(out, name, msg, level, PR_TRUE);
+}
+
+void
+printflags(char *trusts, unsigned int flags)
+{
+ if (flags & CERTDB_VALID_CA)
+ if (!(flags & CERTDB_TRUSTED_CA) &&
+ !(flags & CERTDB_TRUSTED_CLIENT_CA))
+ PORT_Strcat(trusts, "c");
+ if (flags & CERTDB_TERMINAL_RECORD)
+ if (!(flags & CERTDB_TRUSTED))
+ PORT_Strcat(trusts, "p");
+ if (flags & CERTDB_TRUSTED_CA)
+ PORT_Strcat(trusts, "C");
+ if (flags & CERTDB_TRUSTED_CLIENT_CA)
+ PORT_Strcat(trusts, "T");
+ if (flags & CERTDB_TRUSTED)
+ PORT_Strcat(trusts, "P");
+ if (flags & CERTDB_USER)
+ PORT_Strcat(trusts, "u");
+ if (flags & CERTDB_SEND_WARN)
+ PORT_Strcat(trusts, "w");
+ if (flags & CERTDB_INVISIBLE_CA)
+ PORT_Strcat(trusts, "I");
+ if (flags & CERTDB_GOVT_APPROVED_CA)
+ PORT_Strcat(trusts, "G");
+ return;
+}
+
+/* callback for listing certs through pkcs11 */
+SECStatus
+SECU_PrintCertNickname(CERTCertListNode *node, void *data)
+{
+ CERTCertTrust trust;
+ CERTCertificate* cert;
+ FILE *out;
+ char trusts[30];
+ char *name;
+
+ cert = node->cert;
+
+ PORT_Memset (trusts, 0, sizeof (trusts));
+ out = (FILE *)data;
+
+ name = node->appData;
+ if (!name || !name[0]) {
+ name = cert->nickname;
+ }
+ if (!name || !name[0]) {
+ name = cert->emailAddr;
+ }
+ if (!name || !name[0]) {
+ name = "(NULL)";
+ }
+
+ if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
+ printflags(trusts, trust.sslFlags);
+ PORT_Strcat(trusts, ",");
+ printflags(trusts, trust.emailFlags);
+ PORT_Strcat(trusts, ",");
+ printflags(trusts, trust.objectSigningFlags);
+ } else {
+ PORT_Memcpy(trusts,",,",3);
+ }
+ fprintf(out, "%-60s %-5s\n", name, trusts);
+
+ return (SECSuccess);
+}
+
+int
+SECU_DecodeAndPrintExtensions(FILE *out, SECItem *any, char *m, int level)
+{
+ CERTCertExtension **extensions = NULL;
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ int rv = 0;
+
+ if (!arena)
+ return SEC_ERROR_NO_MEMORY;
+
+ rv = SEC_QuickDERDecodeItem(arena, &extensions,
+ SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate), any);
+ if (!rv)
+ SECU_PrintExtensions(out, extensions, m, level);
+ else
+ SECU_PrintAny(out, any, m, level);
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+/* print a decoded SET OF or SEQUENCE OF Extensions */
+int
+SECU_PrintSetOfExtensions(FILE *out, SECItem **any, char *m, int level)
+{
+ int rv = 0;
+ if (m && *m) {
+ SECU_Indent(out, level++); fprintf(out, "%s:\n", m);
+ }
+ while (any && any[0]) {
+ rv |= SECU_DecodeAndPrintExtensions(out, any[0], "", level);
+ any++;
+ }
+ return rv;
+}
+
+/* print a decoded SET OF or SEQUENCE OF "ANY" */
+int
+SECU_PrintSetOfAny(FILE *out, SECItem **any, char *m, int level)
+{
+ int rv = 0;
+ if (m && *m) {
+ SECU_Indent(out, level++); fprintf(out, "%s:\n", m);
+ }
+ while (any && any[0]) {
+ SECU_PrintAny(out, any[0], "", level);
+ any++;
+ }
+ return rv;
+}
+
+int
+SECU_PrintCertAttribute(FILE *out, CERTAttribute *attr, char *m, int level)
+{
+ int rv = 0;
+ SECOidTag tag;
+ tag = SECU_PrintObjectID(out, &attr->attrType, "Attribute Type", level);
+ if (tag == SEC_OID_PKCS9_EXTENSION_REQUEST) {
+ rv = SECU_PrintSetOfExtensions(out, attr->attrValue, "Extensions", level);
+ } else {
+ rv = SECU_PrintSetOfAny(out, attr->attrValue, "Attribute Values", level);
+ }
+ return rv;
+}
+
+int
+SECU_PrintCertAttributes(FILE *out, CERTAttribute **attrs, char *m, int level)
+{
+ int rv = 0;
+ while (attrs[0]) {
+ rv |= SECU_PrintCertAttribute(out, attrs[0], m, level+1);
+ attrs++;
+ }
+ return rv;
+}
+
+int /* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
+SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificateRequest *cr;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate request */
+ cr = PORT_ArenaZNew(arena, CERTCertificateRequest);
+ if (!cr)
+ goto loser;
+ cr->arena = arena;
+ rv = SEC_QuickDERDecodeItem(arena, cr,
+ SEC_ASN1_GET(CERT_CertificateRequestTemplate), der);
+ if (rv)
+ goto loser;
+
+ /* Pretty print it out */
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &cr->version, "Version", level+1);
+ SECU_PrintName(out, &cr->subject, "Subject", level+1);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
+ "Subject Public Key Info", level+1);
+ if (cr->attributes)
+ SECU_PrintCertAttributes(out, cr->attributes, "Attributes", level+1);
+ rv = 0;
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int
+SECU_PrintCertificate(FILE *out, const SECItem *der, const char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificate *c;
+ int rv = SEC_ERROR_NO_MEMORY;
+ int iv;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate */
+ c = PORT_ArenaZNew(arena, CERTCertificate);
+ if (!c)
+ goto loser;
+ c->arena = arena;
+ rv = SEC_ASN1DecodeItem(arena, c,
+ SEC_ASN1_GET(CERT_CertificateTemplate), der);
+ if (rv) {
+ SECU_Indent(out, level);
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, der, "Raw", level);
+ goto loser;
+ }
+ /* Pretty print it out */
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ iv = c->version.len ? DER_GetInteger(&c->version) : 0; /* version is optional */
+ SECU_Indent(out, level+1); fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
+
+ SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level+1);
+ SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level+1);
+ SECU_PrintName(out, &c->issuer, "Issuer", level+1);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ secu_PrintValidity(out, &c->validity, "Validity", level+1);
+ SECU_PrintName(out, &c->subject, "Subject", level+1);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
+ "Subject Public Key Info", level+1);
+ if (c->issuerID.data)
+ secu_PrintDecodedBitString(out, &c->issuerID, "Issuer Unique ID", level+1);
+ if (c->subjectID.data)
+ secu_PrintDecodedBitString(out, &c->subjectID, "Subject Unique ID", level+1);
+ SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level+1);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int
+SECU_PrintCertificateBasicInfo(FILE *out, const SECItem *der, const char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCertificate *c;
+ int rv = SEC_ERROR_NO_MEMORY;
+ int iv;
+
+ if (!arena)
+ return rv;
+
+ /* Decode certificate */
+ c = PORT_ArenaZNew(arena, CERTCertificate);
+ if (!c)
+ goto loser;
+ c->arena = arena;
+ rv = SEC_ASN1DecodeItem(arena, c,
+ SEC_ASN1_GET(CERT_CertificateTemplate), der);
+ if (rv) {
+ SECU_Indent(out, level);
+ SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
+ SECU_PrintAny(out, der, "Raw", level);
+ goto loser;
+ }
+ /* Pretty print it out */
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level+1);
+ SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level+1);
+ SECU_PrintName(out, &c->issuer, "Issuer", level+1);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+ secu_PrintValidity(out, &c->validity, "Validity", level+1);
+ SECU_PrintName(out, &c->subject, "Subject", level+1);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int
+SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ int rv = SEC_ERROR_NO_MEMORY;
+ CERTSubjectPublicKeyInfo spki;
+
+ if (!arena)
+ return rv;
+
+ PORT_Memset(&spki, 0, sizeof spki);
+ rv = SEC_ASN1DecodeItem(arena, &spki,
+ SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate),
+ der);
+ if (!rv) {
+ if (m && *m) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ }
+ secu_PrintSubjectPublicKeyInfo(out, arena, &spki,
+ "Subject Public Key Info", level+1);
+ }
+
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+#ifdef HAVE_EPV_TEMPLATE
+int
+SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ SECKEYEncryptedPrivateKeyInfo key;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ PORT_Memset(&key, 0, sizeof(key));
+ rv = SEC_ASN1DecodeItem(arena, &key,
+ SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), der);
+ if (rv)
+ goto loser;
+
+ /* Pretty print it out */
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintAlgorithmID(out, &key.algorithm, "Encryption Algorithm",
+ level+1);
+ SECU_PrintAsHex(out, &key.encryptedData, "Encrypted Data", level+1);
+loser:
+ PORT_FreeArena(arena, PR_TRUE);
+ return rv;
+}
+#endif
+
+int
+SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
+{
+ unsigned char fingerprint[SHA256_LENGTH];
+ char *fpStr = NULL;
+ int err = PORT_GetError();
+ SECStatus rv;
+ SECItem fpItem;
+
+ /* Print SHA-256 fingerprint */
+ memset(fingerprint, 0, sizeof fingerprint);
+ rv = PK11_HashBuf(SEC_OID_SHA256, fingerprint, derCert->data, derCert->len);
+ fpItem.data = fingerprint;
+ fpItem.len = SHA256_LENGTH;
+ fpStr = CERT_Hexify(&fpItem, 1);
+ SECU_Indent(out, level); fprintf(out, "%s (SHA-256):", m);
+ if (SECU_GetWrapEnabled()) {
+ fprintf(out, "\n");
+ SECU_Indent(out, level+1);
+ }
+ else {
+ fprintf(out, " ");
+ }
+ fprintf(out, "%s\n", fpStr);
+ PORT_Free(fpStr);
+ fpStr = NULL;
+ if (rv != SECSuccess && !err)
+ err = PORT_GetError();
+
+ /* print SHA1 fingerprint */
+ memset(fingerprint, 0, sizeof fingerprint);
+ rv = PK11_HashBuf(SEC_OID_SHA1,fingerprint, derCert->data, derCert->len);
+ fpItem.data = fingerprint;
+ fpItem.len = SHA1_LENGTH;
+ fpStr = CERT_Hexify(&fpItem, 1);
+ SECU_Indent(out, level); fprintf(out, "%s (SHA1):", m);
+ if (SECU_GetWrapEnabled()) {
+ fprintf(out, "\n");
+ SECU_Indent(out, level+1);
+ }
+ else {
+ fprintf(out, " ");
+ }
+ fprintf(out, "%s\n", fpStr);
+ PORT_Free(fpStr);
+ if (SECU_GetWrapEnabled())
+ fprintf(out, "\n");
+
+ if (err)
+ PORT_SetError(err);
+ if (err || rv != SECSuccess)
+ return SECFailure;
+
+ return 0;
+}
+
+/*
+** PKCS7 Support
+*/
+
+/* forward declaration */
+static int
+secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *, int);
+
+/*
+** secu_PrintPKCS7EncContent
+** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
+*/
+static void
+secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
+ char *m, int level)
+{
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Content Type: %s\n",
+ (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
+ : "Unknown");
+ SECU_PrintAlgorithmID(out, &(src->contentEncAlg),
+ "Content Encryption Algorithm", level+1);
+ SECU_PrintAsHex(out, &(src->encContent),
+ "Encrypted Content", level+1);
+}
+
+/*
+** secu_PrintRecipientInfo
+** Prints a PKCS7RecipientInfo type
+*/
+static void
+secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
+ int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(info->version), "Version", level + 1);
+
+ SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
+ level + 1);
+ SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "Serial Number", level + 1);
+
+ /* Parse and display encrypted key */
+ SECU_PrintAlgorithmID(out, &(info->keyEncAlg),
+ "Key Encryption Algorithm", level + 1);
+ SECU_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
+}
+
+/*
+** secu_PrintSignerInfo
+** Prints a PKCS7SingerInfo type
+*/
+static void
+secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m, int level)
+{
+ SEC_PKCS7Attribute *attr;
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(info->version), "Version", level + 1);
+
+ SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
+ level + 1);
+ SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
+ "Serial Number", level + 1);
+
+ SECU_PrintAlgorithmID(out, &(info->digestAlg), "Digest Algorithm",
+ level + 1);
+
+ if (info->authAttr != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Authenticated Attributes:\n");
+ iv = 0;
+ while ((attr = info->authAttr[iv++]) != NULL) {
+ sprintf(om, "Attribute (%d)", iv);
+ secu_PrintAttribute(out, attr, om, level + 2);
+ }
+ }
+
+ /* Parse and display signature */
+ SECU_PrintAlgorithmID(out, &(info->digestEncAlg),
+ "Digest Encryption Algorithm", level + 1);
+ SECU_PrintAsHex(out, &(info->encDigest), "Encrypted Digest", level + 1);
+
+ if (info->unAuthAttr != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Unauthenticated Attributes:\n");
+ iv = 0;
+ while ((attr = info->unAuthAttr[iv++]) != NULL) {
+ sprintf(om, "Attribute (%x)", iv);
+ secu_PrintAttribute(out, attr, om, level + 2);
+ }
+ }
+}
+
+/* callers of this function must make sure that the CERTSignedCrl
+ from which they are extracting the CERTCrl has been fully-decoded.
+ Otherwise it will not have the entries even though the CRL may have
+ some */
+
+void
+SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level)
+{
+ CERTCrlEntry *entry;
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ /* version is optional */
+ iv = crl->version.len ? DER_GetInteger(&crl->version) : 0;
+ SECU_Indent(out, level+1);
+ fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
+ SECU_PrintAlgorithmID(out, &(crl->signatureAlg), "Signature Algorithm",
+ level + 1);
+ SECU_PrintName(out, &(crl->name), "Issuer", level + 1);
+ SECU_PrintTimeChoice(out, &(crl->lastUpdate), "This Update", level + 1);
+ if (crl->nextUpdate.data && crl->nextUpdate.len) /* is optional */
+ SECU_PrintTimeChoice(out, &(crl->nextUpdate), "Next Update", level + 1);
+
+ if (crl->entries != NULL) {
+ iv = 0;
+ while ((entry = crl->entries[iv++]) != NULL) {
+ sprintf(om, "Entry %d (0x%x):\n", iv, iv);
+ SECU_Indent(out, level + 1); fputs(om, out);
+ SECU_PrintInteger(out, &(entry->serialNumber), "Serial Number",
+ level + 2);
+ SECU_PrintTimeChoice(out, &(entry->revocationDate),
+ "Revocation Date", level + 2);
+ SECU_PrintExtensions(out, entry->extensions,
+ "Entry Extensions", level + 2);
+ }
+ }
+ SECU_PrintExtensions(out, crl->extensions, "CRL Extensions", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Signed
+** Pretty print a PKCS7 signed data type (up to version 1).
+*/
+static int
+secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
+ const char *m, int level)
+{
+ SECAlgorithmID *digAlg; /* digest algorithms */
+ SECItem *aCert; /* certificate */
+ CERTSignedCrl *aCrl; /* certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* signer information */
+ int rv, iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
+ sprintf(om, "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ /* Now for the content */
+ rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
+ "Content Information", level + 1);
+ if (rv != 0)
+ return rv;
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
+ iv = 0;
+ while ((aCert = src->rawCerts[iv++]) != NULL) {
+ sprintf(om, "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ SECU_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signed Revocation Lists:\n");
+ iv = 0;
+ while ((aCrl = src->crls[iv++]) != NULL) {
+ sprintf(om, "Signed Revocation List (%x)", iv);
+ SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
+ SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "Signature Algorithm", level+3);
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
+ level+3);
+ SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
+ level + 3);
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signer Information List:\n");
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv++]) != NULL) {
+ sprintf(om, "Signer Information (%x)", iv);
+ secu_PrintSignerInfo(out, sigInfo, om, level + 2);
+ }
+ }
+
+ return 0;
+}
+
+/*
+** secu_PrintPKCS7Enveloped
+** Pretty print a PKCS7 enveloped data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
+ const char *m, int level)
+{
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
+ int iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7SignedEnveloped
+** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
+*/
+static int
+secu_PrintPKCS7SignedAndEnveloped(FILE *out,
+ SEC_PKCS7SignedAndEnvelopedData *src,
+ const char *m, int level)
+{
+ SECAlgorithmID *digAlg; /* pointer for digest algorithms */
+ SECItem *aCert; /* pointer for certificate */
+ CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
+ SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
+ SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
+ int rv, iv;
+ char om[100];
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ /* Parse and list recipients (this is not optional) */
+ if (src->recipientInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Recipient Information List:\n");
+ iv = 0;
+ while ((recInfo = src->recipientInfos[iv++]) != NULL) {
+ sprintf(om, "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ /* Parse and list digest algorithms (if any) */
+ if (src->digestAlgorithms != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
+ iv = 0;
+ while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
+ sprintf(om, "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+
+ /* Parse and list certificates (if any) */
+ if (src->rawCerts != NULL) {
+ SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
+ iv = 0;
+ while ((aCert = src->rawCerts[iv++]) != NULL) {
+ sprintf(om, "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ SECU_PrintCertificate);
+ if (rv)
+ return rv;
+ }
+ }
+
+ /* Parse and list CRL's (if any) */
+ if (src->crls != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signed Revocation Lists:\n");
+ iv = 0;
+ while ((aCrl = src->crls[iv++]) != NULL) {
+ sprintf(om, "Signed Revocation List (%x)", iv);
+ SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
+ SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
+ "Signature Algorithm", level+3);
+ DER_ConvertBitString(&aCrl->signatureWrap.signature);
+ SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
+ level+3);
+ SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
+ level + 3);
+ }
+ }
+
+ /* Parse and list signatures (if any) */
+ if (src->signerInfos != NULL) {
+ SECU_Indent(out, level + 1);
+ fprintf(out, "Signer Information List:\n");
+ iv = 0;
+ while ((sigInfo = src->signerInfos[iv++]) != NULL) {
+ sprintf(om, "Signer Information (%x)", iv);
+ secu_PrintSignerInfo(out, sigInfo, om, level + 2);
+ }
+ }
+
+ return 0;
+}
+
+int
+SECU_PrintCrl (FILE *out, SECItem *der, char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTCrl *c = NULL;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+ do {
+ /* Decode CRL */
+ c = PORT_ArenaZNew(arena, CERTCrl);
+ if (!c)
+ break;
+
+ rv = SEC_QuickDERDecodeItem(arena, c, SEC_ASN1_GET(CERT_CrlTemplate), der);
+ if (rv != SECSuccess)
+ break;
+ SECU_PrintCRLInfo (out, c, m, level);
+ } while (0);
+ PORT_FreeArena (arena, PR_FALSE);
+ return rv;
+}
+
+
+/*
+** secu_PrintPKCS7Encrypted
+** Pretty print a PKCS7 encrypted data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
+ const char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ secu_PrintPKCS7EncContent(out, &src->encContentInfo,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Digested
+** Pretty print a PKCS7 digested data type (up to version 1).
+*/
+static void
+secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
+ const char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
+ level + 1);
+ secu_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
+ level + 1);
+ SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
+}
+
+/*
+** secu_PrintPKCS7ContentInfo
+** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
+** appropriate function
+*/
+static int
+secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
+ char *m, int level)
+{
+ const char *desc;
+ SECOidTag kind;
+ int rv;
+
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ level++;
+
+ if (src->contentTypeTag == NULL)
+ src->contentTypeTag = SECOID_FindOID(&(src->contentType));
+
+ if (src->contentTypeTag == NULL) {
+ desc = "Unknown";
+ kind = SEC_OID_PKCS7_DATA;
+ } else {
+ desc = src->contentTypeTag->desc;
+ kind = src->contentTypeTag->offset;
+ }
+
+ if (src->content.data == NULL) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", desc);
+ level++;
+ SECU_Indent(out, level); fprintf(out, "\n");
+ return 0;
+ }
+
+ rv = 0;
+ switch (kind) {
+ case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
+ rv = secu_PrintPKCS7Signed(out, src->content.signedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
+ secu_PrintPKCS7Enveloped(out, src->content.envelopedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
+ rv = secu_PrintPKCS7SignedAndEnveloped(out,
+ src->content.signedAndEnvelopedData,
+ desc, level);
+ break;
+
+ case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
+ secu_PrintPKCS7Digested(out, src->content.digestedData, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
+ secu_PrintPKCS7Encrypted(out, src->content.encryptedData, desc, level);
+ break;
+
+ default:
+ SECU_PrintAsHex(out, src->content.data, desc, level);
+ break;
+ }
+
+ return rv;
+}
+
+/*
+** SECU_PrintPKCS7ContentInfo
+** Decode and print any major PKCS7 data type (up to version 1).
+*/
+int
+SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
+{
+ SEC_PKCS7ContentInfo *cinfo;
+ int rv;
+
+ cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (cinfo != NULL) {
+ /* Send it to recursive parsing and printing module */
+ rv = secu_PrintPKCS7ContentInfo(out, cinfo, m, level);
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ } else {
+ rv = -1;
+ }
+
+ return rv;
+}
+
+/*
+** End of PKCS7 functions
+*/
+
+void
+printFlags(FILE *out, unsigned int flags, int level)
+{
+ if ( flags & CERTDB_TERMINAL_RECORD ) {
+ SECU_Indent(out, level); fprintf(out, "Terminal Record\n");
+ }
+ if ( flags & CERTDB_TRUSTED ) {
+ SECU_Indent(out, level); fprintf(out, "Trusted\n");
+ }
+ if ( flags & CERTDB_SEND_WARN ) {
+ SECU_Indent(out, level); fprintf(out, "Warn When Sending\n");
+ }
+ if ( flags & CERTDB_VALID_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Valid CA\n");
+ }
+ if ( flags & CERTDB_TRUSTED_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Trusted CA\n");
+ }
+ if ( flags & CERTDB_NS_TRUSTED_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Netscape Trusted CA\n");
+ }
+ if ( flags & CERTDB_USER ) {
+ SECU_Indent(out, level); fprintf(out, "User\n");
+ }
+ if ( flags & CERTDB_TRUSTED_CLIENT_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Trusted Client CA\n");
+ }
+ if ( flags & CERTDB_GOVT_APPROVED_CA ) {
+ SECU_Indent(out, level); fprintf(out, "Step-up\n");
+ }
+}
+
+void
+SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level)
+{
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ SECU_Indent(out, level+1); fprintf(out, "SSL Flags:\n");
+ printFlags(out, trust->sslFlags, level+2);
+ SECU_Indent(out, level+1); fprintf(out, "Email Flags:\n");
+ printFlags(out, trust->emailFlags, level+2);
+ SECU_Indent(out, level+1); fprintf(out, "Object Signing Flags:\n");
+ printFlags(out, trust->objectSigningFlags, level+2);
+}
+
+int SECU_PrintDERName(FILE *out, SECItem *der, const char *m, int level)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTName *name;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ name = PORT_ArenaZNew(arena, CERTName);
+ if (!name)
+ goto loser;
+
+ rv = SEC_ASN1DecodeItem(arena, name, SEC_ASN1_GET(CERT_NameTemplate), der);
+ if (rv)
+ goto loser;
+
+ SECU_PrintName(out, name, m, level);
+ if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
+ SECU_Newline(out);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+typedef enum {
+ noSignature = 0,
+ withSignature = 1
+} SignatureOptionType;
+
+static int
+secu_PrintSignedDataSigOpt(FILE *out, SECItem *der, const char *m,
+ int level, SECU_PPFunc inner,
+ SignatureOptionType withSignature)
+{
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ CERTSignedData *sd;
+ int rv = SEC_ERROR_NO_MEMORY;
+
+ if (!arena)
+ return rv;
+
+ /* Strip off the signature */
+ sd = PORT_ArenaZNew(arena, CERTSignedData);
+ if (!sd)
+ goto loser;
+
+ rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate),
+ der);
+ if (rv)
+ goto loser;
+
+ if (m) {
+ SECU_Indent(out, level); fprintf(out, "%s:\n", m);
+ } else {
+ level -= 1;
+ }
+ rv = (*inner)(out, &sd->data, "Data", level+1);
+
+ if (withSignature) {
+ SECU_PrintAlgorithmID(out, &sd->signatureAlgorithm, "Signature Algorithm",
+ level+1);
+ DER_ConvertBitString(&sd->signature);
+ SECU_PrintAsHex(out, &sd->signature, "Signature", level+1);
+ }
+ SECU_PrintFingerprints(out, der, "Fingerprint", level+1);
+loser:
+ PORT_FreeArena(arena, PR_FALSE);
+ return rv;
+}
+
+int SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
+ int level, SECU_PPFunc inner)
+{
+ return secu_PrintSignedDataSigOpt(out, der, m, level, inner,
+ withSignature);
+}
+
+int SECU_PrintSignedContent(FILE *out, SECItem *der, char *m,
+ int level, SECU_PPFunc inner)
+{
+ return secu_PrintSignedDataSigOpt(out, der, m, level, inner,
+ noSignature);
+}
+
+SECStatus
+SEC_PrintCertificateAndTrust(CERTCertificate *cert,
+ const char *label,
+ CERTCertTrust *trust)
+{
+ SECStatus rv;
+ SECItem data;
+ CERTCertTrust certTrust;
+
+ data.data = cert->derCert.data;
+ data.len = cert->derCert.len;
+
+ rv = SECU_PrintSignedData(stdout, &data, label, 0,
+ SECU_PrintCertificate);
+ if (rv) {
+ return(SECFailure);
+ }
+ if (trust) {
+ SECU_PrintTrustFlags(stdout, trust,
+ "Certificate Trust Flags", 1);
+ } else if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) {
+ SECU_PrintTrustFlags(stdout, &certTrust,
+ "Certificate Trust Flags", 1);
+ }
+
+ printf("\n");
+
+ return(SECSuccess);
+}
+
+
+static char *
+bestCertName(CERTCertificate *cert) {
+ if (cert->nickname) {
+ return cert->nickname;
+ }
+ if (cert->emailAddr && cert->emailAddr[0]) {
+ return cert->emailAddr;
+ }
+ return cert->subjectName;
+}
+
+void
+SECU_printCertProblemsOnDate(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig,
+ SECCertificateUsage certUsage, void *pinArg, PRBool verbose,
+ PRTime datetime)
+{
+ CERTVerifyLog log;
+ CERTVerifyLogNode *node;
+
+ PRErrorCode err = PORT_GetError();
+
+ log.arena = PORT_NewArena(512);
+ log.head = log.tail = NULL;
+ log.count = 0;
+ CERT_VerifyCertificate(handle, cert, checksig, certUsage, datetime, pinArg, &log, NULL);
+
+ SECU_displayVerifyLog(outfile, &log, verbose);
+
+ for (node = log.head; node; node = node->next) {
+ if (node->cert)
+ CERT_DestroyCertificate(node->cert);
+ }
+ PORT_FreeArena(log.arena, PR_FALSE);
+
+ PORT_SetError(err); /* restore original error code */
+}
+
+void
+SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log,
+ PRBool verbose)
+{
+ CERTVerifyLogNode *node = NULL;
+ unsigned int depth = (unsigned int)-1;
+ unsigned int flags = 0;
+ char * errstr = NULL;
+
+ if (log->count > 0) {
+ fprintf(outfile,"PROBLEM WITH THE CERT CHAIN:\n");
+ for (node = log->head; node; node = node->next) {
+ if (depth != node->depth) {
+ depth = node->depth;
+ fprintf(outfile,"CERT %d. %s %s:\n", depth,
+ bestCertName(node->cert),
+ depth ? "[Certificate Authority]": "");
+ if (verbose) {
+ const char * emailAddr;
+ emailAddr = CERT_GetFirstEmailAddress(node->cert);
+ if (emailAddr) {
+ fprintf(outfile,"Email Address(es): ");
+ do {
+ fprintf(outfile, "%s\n", emailAddr);
+ emailAddr = CERT_GetNextEmailAddress(node->cert,
+ emailAddr);
+ } while (emailAddr);
+ }
+ }
+ }
+ fprintf(outfile, " ERROR %ld: %s\n", node->error,
+ SECU_Strerror(node->error));
+ errstr = NULL;
+ switch (node->error) {
+ case SEC_ERROR_INADEQUATE_KEY_USAGE:
+ flags = (unsigned int)node->arg;
+ switch (flags) {
+ case KU_DIGITAL_SIGNATURE:
+ errstr = "Cert cannot sign.";
+ break;
+ case KU_KEY_ENCIPHERMENT:
+ errstr = "Cert cannot encrypt.";
+ break;
+ case KU_KEY_CERT_SIGN:
+ errstr = "Cert cannot sign other certs.";
+ break;
+ default:
+ errstr = "[unknown usage].";
+ break;
+ }
+ case SEC_ERROR_INADEQUATE_CERT_TYPE:
+ flags = (unsigned int)node->arg;
+ switch (flags) {
+ case NS_CERT_TYPE_SSL_CLIENT:
+ case NS_CERT_TYPE_SSL_SERVER:
+ errstr = "Cert cannot be used for SSL.";
+ break;
+ case NS_CERT_TYPE_SSL_CA:
+ errstr = "Cert cannot be used as an SSL CA.";
+ break;
+ case NS_CERT_TYPE_EMAIL:
+ errstr = "Cert cannot be used for SMIME.";
+ break;
+ case NS_CERT_TYPE_EMAIL_CA:
+ errstr = "Cert cannot be used as an SMIME CA.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING:
+ errstr = "Cert cannot be used for object signing.";
+ break;
+ case NS_CERT_TYPE_OBJECT_SIGNING_CA:
+ errstr = "Cert cannot be used as an object signing CA.";
+ break;
+ default:
+ errstr = "[unknown usage].";
+ break;
+ }
+ case SEC_ERROR_UNKNOWN_ISSUER:
+ case SEC_ERROR_UNTRUSTED_ISSUER:
+ case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
+ errstr = node->cert->issuerName;
+ break;
+ default:
+ break;
+ }
+ if (errstr) {
+ fprintf(stderr," %s\n",errstr);
+ }
+ }
+ }
+}
+
+void
+SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig,
+ SECCertificateUsage certUsage, void *pinArg, PRBool verbose)
+{
+ SECU_printCertProblemsOnDate(outfile, handle, cert, checksig,
+ certUsage, pinArg, verbose, PR_Now());
+}
+
+SECStatus
+SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl, PRFileDesc *outFile,
+ PRBool ascii, char *url)
+{
+ PORT_Assert(derCrl != NULL);
+ if (!derCrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (outFile != NULL) {
+ if (ascii) {
+ PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CRL_HEADER,
+ BTOA_DataToAscii(derCrl->data, derCrl->len),
+ NS_CRL_TRAILER);
+ } else {
+ if (PR_Write(outFile, derCrl->data, derCrl->len) != derCrl->len) {
+ return SECFailure;
+ }
+ }
+ }
+ if (slot) {
+ CERTSignedCrl *newCrl = PK11_ImportCRL(slot, derCrl, url,
+ SEC_CRL_TYPE, NULL, 0, NULL, 0);
+ if (newCrl != NULL) {
+ SEC_DestroyCrl(newCrl);
+ return SECSuccess;
+ }
+ return SECFailure;
+ }
+ if (!outFile && !slot) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+SECStatus
+SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
+ SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode)
+{
+ SECItem der;
+ SECKEYPrivateKey *caPrivateKey = NULL;
+ SECStatus rv;
+ PLArenaPool *arena;
+ SECOidTag algID;
+ void *dummy;
+
+ PORT_Assert(issuer != NULL && signCrl != NULL);
+ if (!issuer || !signCrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ arena = signCrl->arena;
+
+ caPrivateKey = PK11_FindKeyByAnyCert(issuer, NULL);
+ if (caPrivateKey == NULL) {
+ *resCode = noKeyFound;
+ return SECFailure;
+ }
+
+ algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType, hashAlgTag);
+ if (algID == SEC_OID_UNKNOWN) {
+ *resCode = noSignatureMatch;
+ rv = SECFailure;
+ goto done;
+ }
+
+ if (!signCrl->crl.signatureAlg.parameters.data) {
+ rv = SECOID_SetAlgorithmID(arena, &signCrl->crl.signatureAlg, algID, 0);
+ if (rv != SECSuccess) {
+ *resCode = failToEncode;
+ goto done;
+ }
+ }
+
+ der.len = 0;
+ der.data = NULL;
+ dummy = SEC_ASN1EncodeItem(arena, &der, &signCrl->crl,
+ SEC_ASN1_GET(CERT_CrlTemplate));
+ if (!dummy) {
+ *resCode = failToEncode;
+ rv = SECFailure;
+ goto done;
+ }
+
+ rv = SECU_DerSignDataCRL(arena, &signCrl->signatureWrap,
+ der.data, der.len, caPrivateKey, algID);
+ if (rv != SECSuccess) {
+ *resCode = failToSign;
+ goto done;
+ }
+
+ signCrl->derCrl = PORT_ArenaZNew(arena, SECItem);
+ if (signCrl->derCrl == NULL) {
+ *resCode = noMem;
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ rv = SECFailure;
+ goto done;
+ }
+
+ signCrl->derCrl->len = 0;
+ signCrl->derCrl->data = NULL;
+ dummy = SEC_ASN1EncodeItem (arena, signCrl->derCrl, signCrl,
+ SEC_ASN1_GET(CERT_SignedCrlTemplate));
+ if (!dummy) {
+ *resCode = failToEncode;
+ rv = SECFailure;
+ goto done;
+ }
+
+done:
+ if (caPrivateKey) {
+ SECKEY_DestroyPrivateKey(caPrivateKey);
+ }
+ return rv;
+}
+
+
+
+SECStatus
+SECU_CopyCRL(PLArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl)
+{
+ void *dummy;
+ SECStatus rv = SECSuccess;
+ SECItem der;
+
+ PORT_Assert(destArena && srcCrl && destCrl);
+ if (!destArena || !srcCrl || !destCrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ der.len = 0;
+ der.data = NULL;
+ dummy = SEC_ASN1EncodeItem (destArena, &der, srcCrl,
+ SEC_ASN1_GET(CERT_CrlTemplate));
+ if (!dummy) {
+ return SECFailure;
+ }
+
+ rv = SEC_QuickDERDecodeItem(destArena, destCrl,
+ SEC_ASN1_GET(CERT_CrlTemplate), &der);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
+ destCrl->arena = destArena;
+
+ return rv;
+}
+
+SECStatus
+SECU_DerSignDataCRL(PLArenaPool *arena, CERTSignedData *sd,
+ unsigned char *buf, int len, SECKEYPrivateKey *pk,
+ SECOidTag algID)
+{
+ SECItem it;
+ SECStatus rv;
+
+ it.data = 0;
+
+ /* XXX We should probably have some asserts here to make sure the key type
+ * and algID match
+ */
+
+ /* Sign input buffer */
+ rv = SEC_SignData(&it, buf, len, pk, algID);
+ if (rv) goto loser;
+
+ /* Fill out SignedData object */
+ PORT_Memset(sd, 0, sizeof(*sd));
+ sd->data.data = buf;
+ sd->data.len = len;
+ sd->signature.data = it.data;
+ sd->signature.len = it.len << 3; /* convert to bit string */
+ rv = SECOID_SetAlgorithmID(arena, &sd->signatureAlgorithm, algID, 0);
+ if (rv) goto loser;
+
+ return rv;
+
+ loser:
+ PORT_Free(it.data);
+ return rv;
+}
+
+#if 0
+
+/* we need access to the private function cert_FindExtension for this code to work */
+
+CERTAuthKeyID *
+SECU_FindCRLAuthKeyIDExten (PLArenaPool *arena, CERTSignedCrl *scrl)
+{
+ SECItem encodedExtenValue;
+ SECStatus rv;
+ CERTAuthKeyID *ret;
+ CERTCrl* crl;
+
+ if (!scrl) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ crl = &scrl->crl;
+
+ encodedExtenValue.data = NULL;
+ encodedExtenValue.len = 0;
+
+ rv = cert_FindExtension(crl->extensions, SEC_OID_X509_AUTH_KEY_ID,
+ &encodedExtenValue);
+ if ( rv != SECSuccess ) {
+ return (NULL);
+ }
+
+ ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue);
+
+ PORT_Free(encodedExtenValue.data);
+ encodedExtenValue.data = NULL;
+
+ return(ret);
+}
+
+#endif
+
+/*
+ * Find the issuer of a Crl. Use the authorityKeyID if it exists.
+ */
+CERTCertificate *
+SECU_FindCrlIssuer(CERTCertDBHandle *dbhandle, SECItem* subject,
+ CERTAuthKeyID* authorityKeyID, PRTime validTime)
+{
+ CERTCertificate *issuerCert = NULL;
+ CERTCertList *certList = NULL;
+ CERTCertTrust trust;
+
+ if (!subject) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ certList =
+ CERT_CreateSubjectCertList(NULL, dbhandle, subject,
+ validTime, PR_TRUE);
+ if (certList) {
+ CERTCertListNode *node = CERT_LIST_HEAD(certList);
+
+ /* XXX and authoritykeyid in the future */
+ while ( ! CERT_LIST_END(node, certList) ) {
+ CERTCertificate *cert = node->cert;
+ /* check cert CERTCertTrust data is allocated, check cert
+ usage extension, check that cert has pkey in db. Select
+ the first (newest) user cert */
+ if (CERT_GetCertTrust(cert, &trust) == SECSuccess &&
+ CERT_CheckCertUsage(cert, KU_CRL_SIGN) == SECSuccess &&
+ CERT_IsUserCert(cert)) {
+
+ issuerCert = CERT_DupCertificate(cert);
+ break;
+ }
+ node = CERT_LIST_NEXT(node);
+ }
+ CERT_DestroyCertList(certList);
+ }
+ return(issuerCert);
+}
+
+
+/* Encodes and adds extensions to the CRL or CRL entries. */
+SECStatus
+SECU_EncodeAndAddExtensionValue(PLArenaPool *arena, void *extHandle,
+ void *value, PRBool criticality, int extenType,
+ EXTEN_EXT_VALUE_ENCODER EncodeValueFn)
+{
+ SECItem encodedValue;
+ SECStatus rv;
+
+ encodedValue.data = NULL;
+ encodedValue.len = 0;
+ do {
+ rv = (*EncodeValueFn)(arena, value, &encodedValue);
+ if (rv != SECSuccess)
+ break;
+
+ rv = CERT_AddExtension(extHandle, extenType, &encodedValue,
+ criticality, PR_TRUE);
+ if (rv != SECSuccess)
+ break;
+ } while (0);
+
+ return (rv);
+}
+
+CERTCertificate*
+SECU_FindCertByNicknameOrFilename(CERTCertDBHandle *handle,
+ char *name, PRBool ascii,
+ void *pwarg)
+{
+ CERTCertificate *the_cert;
+ the_cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
+ if (the_cert) {
+ return the_cert;
+ }
+ the_cert = PK11_FindCertFromNickname(name, pwarg);
+ if (!the_cert) {
+ /* Don't have a cert with name "name" in the DB. Try to
+ * open a file with such name and get the cert from there.*/
+ SECStatus rv;
+ SECItem item = {0, NULL, 0};
+ PRFileDesc* fd = PR_Open(name, PR_RDONLY, 0777);
+ if (!fd) {
+ return NULL;
+ }
+ rv = SECU_ReadDERFromFile(&item, fd, ascii, PR_FALSE);
+ PR_Close(fd);
+ if (rv != SECSuccess || !item.len) {
+ PORT_Free(item.data);
+ return NULL;
+ }
+ the_cert = CERT_NewTempCertificate(handle, &item,
+ NULL /* nickname */,
+ PR_FALSE /* isPerm */,
+ PR_TRUE /* copyDER */);
+ PORT_Free(item.data);
+ }
+ return the_cert;
+}
+
+/* Convert a SSL/TLS protocol version string into the respective numeric value
+ * defined by the SSL_LIBRARY_VERSION_* constants,
+ * while accepting a flexible set of case-insensitive identifiers.
+ *
+ * Caller must specify bufLen, allowing the function to operate on substrings.
+ */
+static SECStatus
+SECU_GetSSLVersionFromName(const char *buf, size_t bufLen, PRUint16 *version)
+{
+ if (!buf || !version) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (!PL_strncasecmp(buf, "ssl2", bufLen)) {
+ *version = SSL_LIBRARY_VERSION_2;
+ return SECSuccess;
+ }
+ if (!PL_strncasecmp(buf, "ssl3", bufLen)) {
+ *version = SSL_LIBRARY_VERSION_3_0;
+ return SECSuccess;
+ }
+ if (!PL_strncasecmp(buf, "tls1.0", bufLen)) {
+ *version = SSL_LIBRARY_VERSION_TLS_1_0;
+ return SECSuccess;
+ }
+ if (!PL_strncasecmp(buf, "tls1.1", bufLen)) {
+ *version = SSL_LIBRARY_VERSION_TLS_1_1;
+ return SECSuccess;
+ }
+ if (!PL_strncasecmp(buf, "tls1.2", bufLen)) {
+ *version = SSL_LIBRARY_VERSION_TLS_1_2;
+ return SECSuccess;
+ }
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+}
+
+SECStatus
+SECU_ParseSSLVersionRangeString(const char *input,
+ const SSLVersionRange defaultVersionRange,
+ const PRBool defaultEnableSSL2,
+ SSLVersionRange *vrange, PRBool *enableSSL2)
+{
+ const char *colonPos;
+ size_t colonIndex;
+ const char *maxStr;
+
+ if (!input || !vrange || !enableSSL2) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (!strcmp(input, ":")) {
+ /* special value, use default */
+ *enableSSL2 = defaultEnableSSL2;
+ *vrange = defaultVersionRange;
+ return SECSuccess;
+ }
+
+ colonPos = strchr(input, ':');
+ if (!colonPos) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ colonIndex = colonPos - input;
+ maxStr = colonPos + 1;
+
+ if (!colonIndex) {
+ /* colon was first character, min version is empty */
+ *enableSSL2 = defaultEnableSSL2;
+ vrange->min = defaultVersionRange.min;
+ } else {
+ PRUint16 version;
+ /* colonIndex is equivalent to the length of the min version substring */
+ if (SECU_GetSSLVersionFromName(input, colonIndex, &version) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (version == SSL_LIBRARY_VERSION_2) {
+ *enableSSL2 = PR_TRUE;
+ vrange->min = defaultVersionRange.min;
+ } else {
+ *enableSSL2 = PR_FALSE;
+ vrange->min = version;
+ }
+ }
+
+ if (!*maxStr) {
+ vrange->max = defaultVersionRange.max;
+ } else {
+ PRUint16 version;
+ /* if max version is empty, then maxStr points to the string terminator */
+ if (SECU_GetSSLVersionFromName(maxStr, strlen(maxStr), &version)
+ != SECSuccess) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (version == SSL_LIBRARY_VERSION_2) {
+ /* consistency checking, require that min allows enableSSL2, too */
+ if (!*enableSSL2) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ /* we use 0 because SSL_LIBRARY_VERSION_NONE is private: */
+ vrange->min = 0;
+ vrange->max = 0;
+ } else {
+ vrange->max = version;
+ }
+ }
+
+ return SECSuccess;
+}
diff --git a/nss/cmd/lib/secutil.h b/nss/cmd/lib/secutil.h
new file mode 100644
index 0000000..9f2744a
--- /dev/null
+++ b/nss/cmd/lib/secutil.h
@@ -0,0 +1,438 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef _SEC_UTIL_H_
+#define _SEC_UTIL_H_
+
+#include "seccomon.h"
+#include "secitem.h"
+#include "secport.h"
+#include "prerror.h"
+#include "base64.h"
+#include "key.h"
+#include "secpkcs7.h"
+#include "secasn1.h"
+#include "secder.h"
+#include
+
+#include "basicutil.h"
+#include "sslerr.h"
+#include "sslt.h"
+
+
+#define SEC_CT_PRIVATE_KEY "private-key"
+#define SEC_CT_PUBLIC_KEY "public-key"
+#define SEC_CT_CERTIFICATE "certificate"
+#define SEC_CT_CERTIFICATE_REQUEST "certificate-request"
+#define SEC_CT_CERTIFICATE_ID "certificate-identity"
+#define SEC_CT_PKCS7 "pkcs7"
+#define SEC_CT_CRL "crl"
+#define SEC_CT_NAME "name"
+
+#define NS_CERTREQ_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----"
+#define NS_CERTREQ_TRAILER "-----END NEW CERTIFICATE REQUEST-----"
+
+#define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----"
+#define NS_CERT_TRAILER "-----END CERTIFICATE-----"
+
+#define NS_CRL_HEADER "-----BEGIN CRL-----"
+#define NS_CRL_TRAILER "-----END CRL-----"
+
+#define SECU_Strerror PORT_ErrorToString
+
+
+typedef struct {
+ enum {
+ PW_NONE = 0,
+ PW_FROMFILE = 1,
+ PW_PLAINTEXT = 2,
+ PW_EXTERNAL = 3
+ } source;
+ char *data;
+} secuPWData;
+
+/*
+** Change a password on a token, or initialize a token with a password
+** if it does not already have one.
+** Use passwd to send the password in plaintext, pwFile to specify a
+** file containing the password, or NULL for both to prompt the user.
+*/
+SECStatus SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile);
+
+/*
+** Change a password on a token, or initialize a token with a password
+** if it does not already have one.
+** In this function, you can specify both the old and new passwords
+** as either a string or file. NOTE: any you don't specify will
+** be prompted for
+*/
+SECStatus SECU_ChangePW2(PK11SlotInfo *slot, char *oldPass, char *newPass,
+ char *oldPwFile, char *newPwFile);
+
+/* These were stolen from the old sec.h... */
+/*
+** Check a password for legitimacy. Passwords must be at least 8
+** characters long and contain one non-alphabetic. Return DSTrue if the
+** password is ok, DSFalse otherwise.
+*/
+extern PRBool SEC_CheckPassword(char *password);
+
+/*
+** Blind check of a password. Complement to SEC_CheckPassword which
+** ignores length and content type, just retuning DSTrue is the password
+** exists, DSFalse if NULL
+*/
+extern PRBool SEC_BlindCheckPassword(char *password);
+
+/*
+** Get a password.
+** First prompt with "msg" on "out", then read the password from "in".
+** The password is then checked using "chkpw".
+*/
+extern char *SEC_GetPassword(FILE *in, FILE *out, char *msg,
+ PRBool (*chkpw)(char *));
+
+char *SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg);
+
+char *SECU_GetPasswordString(void *arg, char *prompt);
+
+/*
+** Write a dongle password.
+** Uses MD5 to hash constant system data (hostname, etc.), and then
+** creates RC4 key to encrypt a password "pw" into a file "fd".
+*/
+extern SECStatus SEC_WriteDongleFile(int fd, char *pw);
+
+/*
+** Get a dongle password.
+** Uses MD5 to hash constant system data (hostname, etc.), and then
+** creates RC4 key to decrypt and return a password from file "fd".
+*/
+extern char *SEC_ReadDongleFile(int fd);
+
+
+/* End stolen headers */
+
+/* Just sticks the two strings together with a / if needed */
+char *SECU_AppendFilenameToDir(char *dir, char *filename);
+
+/* Returns result of getenv("SSL_DIR") or NULL */
+extern char *SECU_DefaultSSLDir(void);
+
+/*
+** Should be called once during initialization to set the default
+** directory for looking for cert.db, key.db, and cert-nameidx.db files
+** Removes trailing '/' in 'base'
+** If 'base' is NULL, defaults to set to .netscape in home directory.
+*/
+extern char *SECU_ConfigDirectory(const char* base);
+
+/*
+** Basic callback function for SSL_GetClientAuthDataHook
+*/
+extern int
+SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
+ struct CERTDistNamesStr *caNames,
+ struct CERTCertificateStr **pRetCert,
+ struct SECKEYPrivateKeyStr **pRetKey);
+
+extern PRBool SECU_GetWrapEnabled(void);
+extern void SECU_EnableWrap(PRBool enable);
+
+extern PRBool SECU_GetUtf8DisplayEnabled(void);
+extern void SECU_EnableUtf8Display(PRBool enable);
+
+/* revalidate the cert and print information about cert verification
+ * failure at time == now */
+extern void
+SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig,
+ SECCertificateUsage certUsage, void *pinArg, PRBool verbose);
+
+/* revalidate the cert and print information about cert verification
+ * failure at specified time */
+extern void
+SECU_printCertProblemsOnDate(FILE *outfile, CERTCertDBHandle *handle,
+ CERTCertificate *cert, PRBool checksig, SECCertificateUsage certUsage,
+ void *pinArg, PRBool verbose, PRTime datetime);
+
+/* print out CERTVerifyLog info. */
+extern void
+SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log,
+ PRBool verbose);
+
+/* Read in a DER from a file, may be ascii */
+extern SECStatus
+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii,
+ PRBool warnOnPrivateKeyInAsciiFile);
+
+/* Print integer value and hex */
+extern void SECU_PrintInteger(FILE *out, const SECItem *i, const char *m,
+ int level);
+
+/* Print ObjectIdentifier symbolically */
+extern SECOidTag SECU_PrintObjectID(FILE *out, const SECItem *oid,
+ const char *m, int level);
+
+/* Print AlgorithmIdentifier symbolically */
+extern void SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m,
+ int level);
+
+/*
+ * Format and print the UTC Time "t". If the tag message "m" is not NULL,
+ * do indent formatting based on "level" and add a newline afterward;
+ * otherwise just print the formatted time string only.
+ */
+extern void SECU_PrintUTCTime(FILE *out, const SECItem *t, const char *m,
+ int level);
+
+/*
+ * Format and print the Generalized Time "t". If the tag message "m"
+ * is not NULL, * do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+extern void SECU_PrintGeneralizedTime(FILE *out, const SECItem *t,
+ const char *m, int level);
+
+/*
+ * Format and print the UTC or Generalized Time "t". If the tag message
+ * "m" is not NULL, do indent formatting based on "level" and add a newline
+ * afterward; otherwise just print the formatted time string only.
+ */
+extern void SECU_PrintTimeChoice(FILE *out, const SECItem *t, const char *m,
+ int level);
+
+/* callback for listing certs through pkcs11 */
+extern SECStatus SECU_PrintCertNickname(CERTCertListNode* cert, void *data);
+
+/* Dump all certificate nicknames in a database */
+extern SECStatus
+SECU_PrintCertificateNames(CERTCertDBHandle *handle, PRFileDesc* out,
+ PRBool sortByName, PRBool sortByTrust);
+
+/* See if nickname already in database. Return 1 true, 0 false, -1 error */
+int SECU_CheckCertNameExists(CERTCertDBHandle *handle, char *nickname);
+
+/* Dump contents of cert req */
+extern int SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m,
+ int level);
+
+/* Dump contents of certificate */
+extern int SECU_PrintCertificate(FILE *out, const SECItem *der, const char *m,
+ int level);
+
+extern int SECU_PrintCertificateBasicInfo(FILE *out, const SECItem *der, const char *m,
+ int level);
+
+extern int SECU_PrintDumpDerIssuerAndSerial(FILE *out, SECItem *der, char *m,
+ int level);
+
+/* Dump contents of a DER certificate name (issuer or subject) */
+extern int SECU_PrintDERName(FILE *out, SECItem *der, const char *m, int level);
+
+/* print trust flags on a cert */
+extern void SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m,
+ int level);
+
+extern int SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m,
+ int level);
+
+#ifdef HAVE_EPV_TEMPLATE
+/* Dump contents of private key */
+extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
+#endif
+
+/* Dump contents of an RSA public key */
+extern void SECU_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level);
+
+/* Dump contents of a DSA public key */
+extern void SECU_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level);
+
+/* Print the MD5 and SHA1 fingerprints of a cert */
+extern int SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m,
+ int level);
+
+/* Pretty-print any PKCS7 thing */
+extern int SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m,
+ int level);
+
+/* Init PKCS11 stuff */
+extern SECStatus SECU_PKCS11Init(PRBool readOnly);
+
+/* Dump contents of signed data */
+extern int SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
+ int level, SECU_PPFunc inner);
+
+/* Dump contents of signed data, excluding the signature */
+extern int SECU_PrintSignedContent(FILE *out, SECItem *der, char *m, int level,
+ SECU_PPFunc inner);
+
+/* Print cert data and its trust flags */
+extern SECStatus SEC_PrintCertificateAndTrust(CERTCertificate *cert,
+ const char *label,
+ CERTCertTrust *trust);
+
+extern int SECU_PrintCrl(FILE *out, SECItem *der, char *m, int level);
+
+extern void
+SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level);
+
+extern void SECU_PrintString(FILE *out, const SECItem *si, const char *m,
+ int level);
+extern void SECU_PrintAny(FILE *out, const SECItem *i, const char *m, int level);
+
+extern void SECU_PrintPolicy(FILE *out, SECItem *value, char *msg, int level);
+extern void SECU_PrintPrivKeyUsagePeriodExtension(FILE *out, SECItem *value,
+ char *msg, int level);
+
+extern void SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
+ char *msg, int level);
+
+extern void SECU_PrintNameQuotesOptional(FILE *out, CERTName *name,
+ const char *msg, int level,
+ PRBool quotes);
+extern void SECU_PrintName(FILE *out, CERTName *name, const char *msg,
+ int level);
+extern void SECU_PrintRDN(FILE *out, CERTRDN *rdn, const char *msg, int level);
+
+#ifdef SECU_GetPassword
+/* Convert a High public Key to a Low public Key */
+extern SECKEYLowPublicKey *SECU_ConvHighToLow(SECKEYPublicKey *pubHighKey);
+#endif
+
+extern char *SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg);
+
+extern SECStatus DER_PrettyPrint(FILE *out, const SECItem *it, PRBool raw);
+
+extern char *SECU_SECModDBName(void);
+
+/* Fetch and register an oid if it hasn't been done already */
+extern void SECU_cert_fetchOID(SECOidTag *data, const SECOidData *src);
+
+extern SECStatus SECU_RegisterDynamicOids(void);
+
+/* Identifies hash algorithm tag by its string representation. */
+extern SECOidTag SECU_StringToSignatureAlgTag(const char *alg);
+
+/* Store CRL in output file or pk11 db. Also
+ * encodes with base64 and exports to file if ascii flag is set
+ * and file is not NULL. */
+extern SECStatus SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl,
+ PRFileDesc *outFile, PRBool ascii, char *url);
+
+
+/*
+** DER sign a single block of data using private key encryption and the
+** MD5 hashing algorithm. This routine first computes a digital signature
+** using SEC_SignData, then wraps it with an CERTSignedData and then der
+** encodes the result.
+** "arena" is the memory arena to use to allocate data from
+** "sd" returned CERTSignedData
+** "result" the final der encoded data (memory is allocated)
+** "buf" the input data to sign
+** "len" the amount of data to sign
+** "pk" the private key to encrypt with
+*/
+extern SECStatus SECU_DerSignDataCRL(PLArenaPool *arena, CERTSignedData *sd,
+ unsigned char *buf, int len,
+ SECKEYPrivateKey *pk, SECOidTag algID);
+
+typedef enum {
+ noKeyFound = 1,
+ noSignatureMatch = 2,
+ failToEncode = 3,
+ failToSign = 4,
+ noMem = 5
+} SignAndEncodeFuncExitStat;
+
+extern SECStatus
+SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
+ SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode);
+
+extern SECStatus
+SECU_CopyCRL(PLArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl);
+
+/*
+** Finds the crl Authority Key Id extension. Returns NULL if no such extension
+** was found.
+*/
+CERTAuthKeyID *
+SECU_FindCRLAuthKeyIDExten (PLArenaPool *arena, CERTSignedCrl *crl);
+
+/*
+ * Find the issuer of a crl. Cert usage should be checked before signing a crl.
+ */
+CERTCertificate *
+SECU_FindCrlIssuer(CERTCertDBHandle *dbHandle, SECItem* subject,
+ CERTAuthKeyID* id, PRTime validTime);
+
+
+/* call back function used in encoding of an extension. Called from
+ * SECU_EncodeAndAddExtensionValue */
+typedef SECStatus (* EXTEN_EXT_VALUE_ENCODER) (PLArenaPool *extHandleArena,
+ void *value, SECItem *encodedValue);
+
+/* Encodes and adds extensions to the CRL or CRL entries. */
+SECStatus
+SECU_EncodeAndAddExtensionValue(PLArenaPool *arena, void *extHandle,
+ void *value, PRBool criticality, int extenType,
+ EXTEN_EXT_VALUE_ENCODER EncodeValueFn);
+
+/* Caller ensures that dst is at least item->len*2+1 bytes long */
+void
+SECU_SECItemToHex(const SECItem * item, char * dst);
+
+/* Requires 0x prefix. Case-insensitive. Will do in-place replacement if
+ * successful */
+SECStatus
+SECU_SECItemHexStringToBinary(SECItem* srcdest);
+
+/* Parse a version range string, with "min" and "max" version numbers,
+ * separated by colon (":"), and return the result in vr and v2.
+ *
+ * Both min and max values are optional.
+ * The following syntax is used to specify the enabled protocol versions:
+ * A string with only a max value is expected as ":{max}",
+ * and all implemented versions less than or equal to max will be enabled.
+ * A string with only a min value is expected as "{min}:",
+ * and all implemented versions greater than or equal to min will be enabled.
+ * A string consisting of a colon only means "all versions enabled".
+ *
+ * Because output parameter type SSLVersionRange doesn't allow to set
+ * version 2 values, we use a separate boolean output parameter
+ * to return whether SSL 2 is enabled.
+ *
+ * In order to avoid a link dependency from libsectool to libssl,
+ * the caller must provide the desired default values for the min/max values,
+ * by providing defaultEnableSSL2 and defaultVersionRange
+ * (which can be obtained from libssl by calling SSL_VersionRangeGetSupported).
+ */
+SECStatus
+SECU_ParseSSLVersionRangeString(const char *input,
+ const SSLVersionRange defaultVersionRange,
+ const PRBool defaultEnableSSL2,
+ SSLVersionRange *vrange,
+ PRBool *enableSSL2);
+
+/*
+ *
+ * Error messaging
+ *
+ */
+
+void printflags(char *trusts, unsigned int flags);
+
+#if !defined(XP_UNIX) && !defined(XP_OS2)
+extern int ffs(unsigned int i);
+#endif
+
+/* Finds certificate by searching it in the DB or by examinig file
+ * in the local directory. */
+CERTCertificate*
+SECU_FindCertByNicknameOrFilename(CERTCertDBHandle *handle,
+ char *name, PRBool ascii,
+ void *pwarg);
+#include "secerr.h"
+#include "sslerr.h"
+
+#endif /* _SEC_UTIL_H_ */
diff --git a/nss/cmd/libpkix/Makefile b/nss/cmd/libpkix/Makefile
new file mode 100755
index 0000000..1de5ef2
--- /dev/null
+++ b/nss/cmd/libpkix/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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 $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
+
diff --git a/nss/cmd/libpkix/config.mk b/nss/cmd/libpkix/config.mk
new file mode 100644
index 0000000..672f6ff
--- /dev/null
+++ b/nss/cmd/libpkix/config.mk
@@ -0,0 +1,9 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+TARGETS = $(LIBRARY)
+SHARED_LIBRARY =
+IMPORT_LIBRARY =
+PROGRAM =
diff --git a/nss/cmd/libpkix/manifest.mn b/nss/cmd/libpkix/manifest.mn
new file mode 100755
index 0000000..4f232a5
--- /dev/null
+++ b/nss/cmd/libpkix/manifest.mn
@@ -0,0 +1,11 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+PKIX_DEPTH = .
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../..
+
+DIRS = testutil pkix_pl pkix sample_apps perf pkixutil \
+ $(NULL)
diff --git a/nss/cmd/libpkix/perf/Makefile b/nss/cmd/libpkix/perf/Makefile
new file mode 100755
index 0000000..b724102
--- /dev/null
+++ b/nss/cmd/libpkix/perf/Makefile
@@ -0,0 +1,46 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
+
diff --git a/nss/cmd/libpkix/perf/libpkix_buildthreads.c b/nss/cmd/libpkix/perf/libpkix_buildthreads.c
new file mode 100644
index 0000000..adb0a29
--- /dev/null
+++ b/nss/cmd/libpkix/perf/libpkix_buildthreads.c
@@ -0,0 +1,349 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * libpkixBuildThreads.c
+ *
+ * libpkix Builder Performance Evaluation application (multi-threaded)
+ *
+ */
+
+#include
+#include
+
+#include "secutil.h"
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "nss.h"
+
+#include "pkix.h"
+#include "pkix_tools.h"
+#include "pkix_pl_cert.h"
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+#undef pkixTempResult
+#define PERF_DECREF(obj) \
+ { \
+ PKIX_Error *pkixTempResult = NULL; \
+ if (obj){ \
+ pkixTempResult = PKIX_PL_Object_DecRef \
+ ((PKIX_PL_Object *)(obj), plContext); \
+ obj = NULL; \
+ } \
+ }
+
+static void finish(char* message, int code);
+
+typedef struct ThreadDataStr tData;
+
+struct ThreadDataStr {
+ CERTCertificate* anchor;
+ char* eecertName;
+ PRIntervalTime duration;
+ CERTCertDBHandle *handle;
+ PRUint32 iterations;
+};
+
+#define PKIX_LOGGER_ON 1
+
+#ifdef PKIX_LOGGER_ON
+
+char *logLevels[] = {
+ "None",
+ "Fatal Error",
+ "Error",
+ "Warning",
+ "Debug",
+ "Trace"
+};
+
+static PKIX_Error *loggerCallback(
+ PKIX_Logger *logger,
+ PKIX_PL_String *message,
+ PKIX_UInt32 logLevel,
+ PKIX_ERRORCLASS logComponent,
+ void *plContext)
+{
+ char *msg = NULL;
+ static int callCount = 0;
+
+ msg = PKIX_String2ASCII(message, plContext);
+ printf("Logging %s (%s): %s\n",
+ logLevels[logLevel],
+ PKIX_ERRORCLASSNAMES[logComponent],
+ msg);
+ PR_Free((void *)msg);
+
+ return(NULL);
+}
+
+#endif /* PKIX_LOGGER_ON */
+
+static void ThreadEntry(void* data)
+{
+ tData* tdata = (tData*) data;
+ PRIntervalTime duration = tdata->duration;
+ PRIntervalTime start = PR_IntervalNow();
+
+ PKIX_List *anchors = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ CERTCertificate* nsseecert;
+ PKIX_PL_Cert *eeCert = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_PL_Date *nowDate = NULL;
+ void *state = NULL; /* only relevant with non-blocking I/O */
+ void *nbioContext = NULL; /* only relevant with non-blocking I/O */
+
+ PR_ASSERT(duration);
+ if (!duration){
+ return;
+ }
+
+ do {
+
+ /* libpkix code */
+
+ /* keep more update time, testing cache */
+ PKIX_PL_Date_Create_UTCTime(NULL, &nowDate, plContext);
+
+ /* CertUsage is 0x10 and no NSS arena */
+ /* We haven't determined how we obtain the value of wincx */
+
+ nsseecert = CERT_FindCertByNicknameOrEmailAddr(tdata->handle,
+ tdata->eecertName);
+ if (!nsseecert) finish("Unable to find eecert.\n", 1);
+
+ pkix_pl_Cert_CreateWithNSSCert
+ (nsseecert, &eeCert, plContext);
+
+ PKIX_List_Create(&anchors, plContext);
+
+ /*
+ * This code is retired.
+ * pkix_pl_Cert_CreateWithNSSCert
+ * (tdata->anchor, &anchorCert, NULL);
+ * PKIX_TrustAnchor_CreateWithCert(anchorCert, &anchor, NULL);
+ * PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, NULL);
+ */
+
+ PKIX_ProcessingParams_Create(anchors, &procParams, plContext);
+
+ PKIX_ProcessingParams_SetRevocationEnabled
+ (procParams, PKIX_TRUE, plContext);
+
+ PKIX_ProcessingParams_SetDate
+ (procParams, nowDate, plContext);
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_ComCertSelParams_Create(&certSelParams, plContext);
+
+ PKIX_ComCertSelParams_SetCertificate
+ (certSelParams, eeCert, plContext);
+
+ PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext);
+
+ PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, certSelParams, plContext);
+
+ PKIX_ProcessingParams_SetTargetCertConstraints
+ (procParams, certSelector, plContext);
+
+ PKIX_PL_Pk11CertStore_Create(&certStore, plContext);
+
+ PKIX_List_Create(&certStores, plContext);
+ PKIX_List_AppendItem
+ (certStores, (PKIX_PL_Object *)certStore, plContext);
+ PKIX_ProcessingParams_SetCertStores
+ (procParams, certStores, plContext);
+
+ PKIX_BuildChain
+ (procParams,
+ &nbioContext,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+
+ /*
+ * As long as we use only CertStores with blocking I/O, we
+ * know we must be done at this point.
+ */
+
+ if (!buildResult){
+ (void) fprintf(stderr, "libpkix BuildChain failed.\n");
+ PORT_Assert(0);
+ return;
+ }
+
+ tdata->iterations ++;
+
+ PERF_DECREF(nowDate);
+ PERF_DECREF(anchors);
+ PERF_DECREF(procParams);
+ PERF_DECREF(buildResult);
+ PERF_DECREF(certStore);
+ PERF_DECREF(certStores);
+ PERF_DECREF(certSelParams);
+ PERF_DECREF(certSelector);
+ PERF_DECREF(eeCert);
+
+ } while ((PR_IntervalNow() - start) < duration);
+
+
+}
+
+static void
+Test(
+ CERTCertificate* anchor,
+ char* eecertName,
+ PRIntervalTime duration,
+ CERTCertDBHandle *handle,
+ PRUint32 threads)
+{
+ tData data;
+ tData** alldata;
+ PRIntervalTime starttime, endtime, elapsed;
+ PRUint32 msecs;
+ float total = 0;
+ PRThread** pthreads = NULL;
+ PRUint32 i = 0;
+
+ data.duration = duration;
+ data.anchor = anchor;
+ data.eecertName = eecertName;
+ data.handle = handle;
+
+ data.iterations = 0;
+
+ starttime = PR_IntervalNow();
+ pthreads = (PRThread**)PR_Malloc(threads*sizeof (PRThread*));
+ alldata = (tData**)PR_Malloc(threads*sizeof (tData*));
+ for (i = 0; i < threads; i++){
+ alldata[i] = (tData*)PR_Malloc(sizeof (tData));
+ *alldata[i] = data;
+ pthreads[i] =
+ PR_CreateThread(PR_USER_THREAD,
+ ThreadEntry,
+ (void*) alldata[i],
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ }
+
+ for (i = 0; i < threads; i++) {
+ tData* args = alldata[i];
+ PR_JoinThread(pthreads[i]);
+ total += args->iterations;
+ PR_Free((void*)args);
+ }
+
+ PR_Free((void*) pthreads);
+ PR_Free((void*) alldata);
+ endtime = PR_IntervalNow();
+
+ endtime = PR_IntervalNow();
+ elapsed = endtime - starttime;
+ msecs = PR_IntervalToMilliseconds(elapsed);
+ total /= msecs;
+ total *= 1000;
+ (void) fprintf(stdout, "%f operations per second.\n", total);
+}
+
+
+static void finish(char* message, int code)
+{
+ (void) printf(message);
+ exit(code);
+}
+
+static void usage(char* progname)
+{
+ (void) printf("Usage : %s <-d certStoreDirectory> "
+ " \n\n", progname);
+ finish("", 0);
+}
+
+int
+libpkix_buildthreads(int argc, char** argv)
+{
+ CERTCertDBHandle *handle = NULL;
+ CERTCertificate* eecert = NULL;
+ PRIntervalTime duration = PR_SecondsToInterval(1);
+ PRUint32 threads = 1;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ PKIX_Logger *logger = NULL;
+ void *wincx = NULL;
+
+ /* if (argc != 5) -- when TrustAnchor used to be on command line */
+ if (argc != 4)
+ {
+ usage(argv[0]);
+ }
+ if (atoi(argv[1]) > 0)
+ {
+ duration = PR_SecondsToInterval(atoi(argv[1]));
+ }
+ if (atoi(argv[2]) > 0)
+ {
+ threads = atoi(argv[2]);
+ }
+
+ PKIX_PL_NssContext_Create(certificateUsageEmailSigner, PKIX_FALSE,
+ NULL, &plContext);
+
+ handle = CERT_GetDefaultCertDB();
+ PR_ASSERT(handle);
+
+#ifdef PKIX_LOGGER_ON
+
+ /* set logger to log trace and up */
+ PKIX_SetLoggers(NULL, plContext);
+ PKIX_Logger_Create(loggerCallback, NULL, &logger, plContext);
+ PKIX_Logger_SetMaxLoggingLevel
+ (logger, PKIX_LOGGER_LEVEL_WARNING, plContext);
+ PKIX_AddLogger(logger, plContext);
+
+#endif /* PKIX_LOGGER_ON */
+
+ /*
+ * This code is retired
+ * anchor = CERT_FindCertByNicknameOrEmailAddr(handle, argv[3]);
+ * if (!anchor) finish("Unable to find anchor.\n", 1);
+ *
+ * eecert = CERT_FindCertByNicknameOrEmailAddr(handle, argv[4]);
+
+ * if (!eecert) finish("Unable to find eecert.\n", 1);
+ *
+ * Test(anchor, eecert, duration, threads);
+ */
+
+ Test(NULL, argv[3], duration, handle, threads);
+
+ PERF_DECREF(logger);
+
+ PKIX_Shutdown(plContext);
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/perf/manifest.mn b/nss/cmd/libpkix/perf/manifest.mn
new file mode 100755
index 0000000..005c96c
--- /dev/null
+++ b/nss/cmd/libpkix/perf/manifest.mn
@@ -0,0 +1,21 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+PKIX_DEPTH = ..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = libpkix_buildthreads.c \
+ nss_threads.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtoolperf
+
+SOURCE_LIB_DIR = $(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/nss/cmd/libpkix/perf/nss_threads.c b/nss/cmd/libpkix/perf/nss_threads.c
new file mode 100644
index 0000000..eadf5f0
--- /dev/null
+++ b/nss/cmd/libpkix/perf/nss_threads.c
@@ -0,0 +1,164 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * nssThreads.c
+ *
+ * NSS Performance Evaluation application (multi-threaded)
+ *
+ */
+
+#include
+#include
+
+#include "secutil.h"
+
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "prlong.h"
+
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "nss.h"
+
+typedef struct ThreadDataStr tData;
+
+struct ThreadDataStr {
+ CERTCertificate* cert;
+ PRIntervalTime duration;
+ PRUint32 iterations;
+};
+
+static void ThreadEntry(void* data)
+{
+ tData* tdata = (tData*) data;
+ PRIntervalTime duration = tdata->duration;
+ PRTime now = PR_Now();
+ PRIntervalTime start = PR_IntervalNow();
+
+ PR_ASSERT(duration);
+ if (!duration)
+ {
+ return;
+ }
+ do {
+ SECStatus rv = CERT_VerifyCertificate
+ (CERT_GetDefaultCertDB(),
+ tdata->cert,
+ PR_TRUE,
+ certificateUsageEmailSigner,
+ now,
+ NULL,
+ NULL,
+ NULL);
+ if (rv != SECSuccess)
+ {
+ (void) fprintf(stderr, "Validation failed.\n");
+ PORT_Assert(0);
+ return;
+ }
+ tdata->iterations ++;
+ } while ((PR_IntervalNow() - start) < duration);
+}
+
+static void Test(CERTCertificate* cert, PRIntervalTime duration, PRUint32 threads)
+{
+ tData data;
+ tData** alldata;
+ PRIntervalTime starttime, endtime, elapsed;
+ PRUint32 msecs;
+ float total = 0;
+ PRThread** pthreads = NULL;
+ PRUint32 i = 0;
+
+ data.duration = duration;
+ data.cert = cert;
+ data.iterations = 0;
+
+ starttime = PR_IntervalNow();
+ pthreads = (PRThread**)PR_Malloc(threads*sizeof (PRThread*));
+ alldata = (tData**)PR_Malloc(threads*sizeof (tData*));
+ for (i = 0; i < threads; i++)
+ {
+ alldata[i] = (tData*)PR_Malloc(sizeof (tData));
+ *alldata[i] = data;
+ pthreads[i] =
+ PR_CreateThread(PR_USER_THREAD,
+ ThreadEntry,
+ (void*) alldata[i],
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ }
+ for (i = 0; i < threads; i++)
+ {
+ tData* args = alldata[i];
+ PR_JoinThread(pthreads[i]);
+ total += args->iterations;
+ PR_Free((void*)args);
+ }
+ PR_Free((void*) pthreads);
+ PR_Free((void*) alldata);
+ endtime = PR_IntervalNow();
+
+ endtime = PR_IntervalNow();
+ elapsed = endtime - starttime;
+ msecs = PR_IntervalToMilliseconds(elapsed);
+ total /= msecs;
+ total *= 1000;
+ (void) fprintf(stdout, "%f operations per second.\n", total);
+}
+
+
+static void finish(char* message, int code)
+{
+ (void) printf(message);
+ exit(code);
+}
+
+static void usage(char* progname)
+{
+ (void) printf("Usage : %s \n\n",
+ progname);
+ finish("", 0);
+}
+
+int nss_threads(int argc, char** argv)
+{
+ SECStatus rv = SECSuccess;
+ CERTCertDBHandle *handle = NULL;
+ CERTCertificate* cert = NULL;
+ PRIntervalTime duration = PR_SecondsToInterval(1);
+ PRUint32 threads = 1;
+ if (argc != 4)
+ {
+ usage(argv[0]);
+ }
+ if (atoi(argv[1]) > 0)
+ {
+ duration = PR_SecondsToInterval(atoi(argv[1]));
+ }
+ if (atoi(argv[2]) > 0)
+ {
+ threads = atoi(argv[2]);
+ }
+
+ handle = CERT_GetDefaultCertDB();
+ PR_ASSERT(handle);
+ cert = CERT_FindCertByNicknameOrEmailAddr(handle, argv[3]);
+ if (!cert)
+ {
+ finish("Unable to find certificate.\n", 1);
+ }
+ Test(cert, duration, threads);
+
+ CERT_DestroyCertificate(cert);
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/Makefile b/nss/cmd/libpkix/pkix/Makefile
new file mode 100755
index 0000000..ab4ffbd
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/Makefile
@@ -0,0 +1,48 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
+
diff --git a/nss/cmd/libpkix/pkix/certsel/Makefile b/nss/cmd/libpkix/pkix/certsel/Makefile
new file mode 100755
index 0000000..09ca5f1
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/certsel/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/nss/cmd/libpkix/pkix/certsel/manifest.mn b/nss/cmd/libpkix/pkix/certsel/manifest.mn
new file mode 100755
index 0000000..2e8198c
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/certsel/manifest.mn
@@ -0,0 +1,21 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_certselector.c \
+ test_comcertselparams.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolcertsel
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/nss/cmd/libpkix/pkix/certsel/test_certselector.c b/nss/cmd/libpkix/pkix/certsel/test_certselector.c
new file mode 100644
index 0000000..70b1059
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/certsel/test_certselector.c
@@ -0,0 +1,1959 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_certselector.c
+ *
+ * Test Cert Selector
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_CERTSELECTOR_KEYUSAGE_NUM_CERTS 5
+#define PKIX_TEST_CERTSELECTOR_EXTKEYUSAGE_NUM_CERTS 2
+#define PKIX_TEST_CERTSELECTOR_CERTVALID_NUM_CERTS 2
+#define PKIX_TEST_CERTSELECTOR_ISSUER_NUM_CERTS 4
+#define PKIX_TEST_CERTSELECTOR_SERIALNUMBER_NUM_CERTS 1
+
+static void *plContext = NULL;
+
+/*
+ * The first three certs are used to obtain policies to test
+ * policy matching. Changing the table could break tests.
+ */
+static char *certList[] = {
+#define POLICY1CERT 0
+ "GoodCACert.crt",
+#define ANYPOLICYCERT 1
+ "anyPolicyCACert.crt",
+#define POLICY2CERT 2
+ "PoliciesP12CACert.crt",
+#define SUBJECTCERT 3
+ "PoliciesP3CACert.crt",
+ "PoliciesP1234CACert.crt",
+ "pathLenConstraint0CACert.crt",
+ "pathLenConstraint1CACert.crt",
+ "pathLenConstraint6CACert.crt",
+ "TrustAnchorRootCertificate.crt",
+ "GoodsubCACert.crt",
+ "AnyPolicyTest14EE.crt",
+ "UserNoticeQualifierTest16EE.crt"
+ };
+#define NUMCERTS (sizeof (certList)/sizeof (certList[0]))
+
+/*
+ * Following are Certs values for NameConstraints tests
+ *
+ * Cert0:nameConstraintsDN1subCA1Cert.crt:
+ * Subject:CN=nameConstraints DN1 subCA1,OU=permittedSubtree1,
+ * O=Test Certificates,C=US
+ * Permitted Name:(OU=permittedSubtree2,OU=permittedSubtree1,
+ * O=Test Certificates,C=US)
+ * Excluded Name: (EMPTY)
+ * Cert1:nameConstraintsDN3subCA2Cert.crt:
+ * Subject:CN=nameConstraints DN3 subCA2,O=Test Certificates,C=US
+ * Permitted Name:(O=Test Certificates,C=US)
+ * Excluded Name:(EMPTY)
+ * Cert2:nameConstraintsDN2CACert.crt
+ * Subject:CN=nameConstraints DN2 CA,O=Test Certificates,C=US
+ * Permitted Name:(OU=permittedSubtree1,O=Test Certificates,C=US,
+ * OU=permittedSubtree2,O=Test Certificates,C=US)
+ * Excluded Name:(EMPTY)
+ * Cert3:nameConstraintsDN3subCA1Cert.crt
+ * Subject:CN=nameConstraints DN3 subCA1,O=Test Certificates,C=US
+ * Permitted Name:(EMPTY)
+ * Excluded Name:(OU=excludedSubtree2,O=Test Certificates,C=US)
+ * Cert4:nameConstraintsDN4CACert.crt
+ * Subject:CN=nameConstraints DN4 CA,O=Test Certificates,C=US
+ * Permitted Name:(EMPTY)
+ * Excluded Name:(OU=excludedSubtree1,O=Test Certificates,C=US,
+ * OU=excludedSubtree2,O=Test Certificates,C=US)
+ * Cert5:nameConstraintsDN5CACert.crt
+ * Subject:CN=nameConstraints DN5 CA,O=Test Certificates,C=US
+ * Permitted Name:(OU=permittedSubtree1,O=Test Certificates,C=US)
+ * Excluded Name:(OU=excludedSubtree1,OU=permittedSubtree1,
+ * O=Test Certificates,C=US)
+ * Cert6:ValidDNnameConstraintsTest1EE.crt
+ * Subject:CN=Valid DN nameConstraints EE Certificate Test1,
+ * OU=permittedSubtree1,O=Test Certificates,C=US
+ *
+ */
+static char *ncCertList[] = {
+ "nameConstraintsDN1subCA1Cert.crt",
+ "nameConstraintsDN3subCA2Cert.crt",
+ "nameConstraintsDN2CACert.crt",
+ "nameConstraintsDN3subCA1Cert.crt",
+ "nameConstraintsDN4CACert.crt",
+ "nameConstraintsDN5CACert.crt",
+ "ValidDNnameConstraintsTest1EE.crt"
+};
+#define NUMNCCERTS (sizeof (ncCertList)/sizeof (ncCertList[0]))
+
+static char *sanCertList[] = {
+ "InvalidDNnameConstraintsTest3EE.crt",
+ "InvalidDNSnameConstraintsTest38EE.crt"
+};
+#define NUMSANCERTS (sizeof (sanCertList)/sizeof (sanCertList[0]))
+
+/*
+ * This function calls the CertSelector pointed to by "selector" for each
+ * cert in the List pointed to by "certs", and compares the results against
+ * the bit array given by the UInt32 "expectedResults". If the first cert is
+ * expected to pass, the lower-order bit of "expectedResults" should be 1.
+ * If the second cert is expected to pass, the second bit of "expectedResults"
+ * should be 1, and so on. If more than 32 certs are provided, only the first
+ * 32 will be checked. It is not an error to provide more bits than needed.
+ * (For example, if you expect every cert to pass, "expectedResult" can be
+ * set to 0xFFFFFFFF, even if the chain has fewer than 32 certs.)
+ */
+static
+void testSelector(
+ PKIX_CertSelector *selector,
+ PKIX_List *certs,
+ PKIX_UInt32 expectedResults)
+{
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 numCerts = 0;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_CertSelector_MatchCallback callback = NULL;
+ PKIX_Error *errReturn = NULL;
+ PKIX_Boolean result = PKIX_TRUE;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetMatchCallback
+ (selector, &callback, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (certs, &numCerts, plContext));
+ if (numCerts > 32) {
+ numCerts = 32;
+ }
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (certs, i, (PKIX_PL_Object **)&cert, plContext));
+ errReturn = callback(selector, cert, &result, plContext);
+
+ if (errReturn || result == PKIX_FALSE) {
+ if ((expectedResults & 1) == 1) {
+ testError("selector unexpectedly failed");
+ (void) printf(" processing cert:\t%d\n", i);
+ }
+ } else {
+ if ((expectedResults & 1) == 0) {
+ testError("selector unexpectedly passed");
+ (void) printf(" processing cert:\t%d\n", i);
+ }
+ }
+
+ expectedResults = expectedResults >> 1;
+ PKIX_TEST_DECREF_BC(cert);
+ PKIX_TEST_DECREF_BC(errReturn);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(errReturn);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function gets a policy from the Cert pointed to by "cert", according
+ * to the index provided by "index", creates an immutable List containing the
+ * OID of that policy, and stores the result at "pPolicyList".
+ */
+static void testGetPolicyFromCert(
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 index,
+ PKIX_List **pPolicyList)
+{
+ PKIX_List *policyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *firstPolicy = NULL;
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_List *list = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation
+ (cert, &policyInfo, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (policyInfo,
+ index,
+ (PKIX_PL_Object **)&firstPolicy,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId
+ (firstPolicy, &policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&list, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (list, (PKIX_PL_Object *)policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable(list, plContext));
+
+ *pPolicyList = list;
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(policyInfo);
+ PKIX_TEST_DECREF_AC(firstPolicy);
+ PKIX_TEST_DECREF_AC(policyOID);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This custom matchCallback will pass any Certificate which has no
+ * CertificatePolicies extension and any Certificate whose Policies
+ * extension include a CertPolicyQualifier.
+ */
+static PKIX_Error *
+custom_CertSelector_MatchCallback(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 numPolicies = 0;
+ PKIX_List *certPolicies = NULL;
+ PKIX_List *quals = NULL;
+ PKIX_PL_CertPolicyInfo *policy = NULL;
+ PKIX_Error *error = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ *pResult = PKIX_TRUE;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation
+ (cert, &certPolicies, plContext));
+
+ if (certPolicies) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (certPolicies, &numPolicies, plContext));
+
+ for (i = 0; i < numPolicies; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (certPolicies,
+ i,
+ (PKIX_PL_Object **)&policy,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_CertPolicyInfo_GetPolQualifiers
+ (policy, &quals, plContext));
+ if (quals) {
+ goto cleanup;
+ }
+ PKIX_TEST_DECREF_BC(policy);
+ }
+ PKIX_TEST_DECREF_BC(certPolicies);
+ *pResult = PKIX_FALSE;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create
+ (PKIX_CERTSELECTOR_ERROR,
+ NULL,
+ NULL,
+ PKIX_TESTPOLICYEXTWITHNOPOLICYQUALIFIERS,
+ &error,
+ plContext));
+
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(certPolicies);
+ PKIX_TEST_DECREF_AC(policy);
+ PKIX_TEST_DECREF_AC(quals);
+
+ return(error);
+}
+
+/*
+ * This custom matchCallback will pass any Certificate whose
+ * CertificatePolicies extension asserts the Policy specified by
+ * the OID in the CertSelectorContext object.
+ */
+static PKIX_Error *
+custom_CertSelector_MatchOIDCallback(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 numPolicies = 0;
+ PKIX_Boolean match = PKIX_FALSE;
+ PKIX_PL_Object *certSelectorContext = NULL;
+ PKIX_PL_OID *constraintOID = NULL;
+ PKIX_List *certPolicies = NULL;
+ PKIX_PL_CertPolicyInfo *policy = NULL;
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_PL_String *errorDesc = NULL;
+ PKIX_Error *error = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ *pResult = PKIX_TRUE;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetCertSelectorContext
+ (selector, &certSelectorContext, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_CheckType
+ (certSelectorContext, PKIX_OID_TYPE, plContext));
+
+ constraintOID = (PKIX_PL_OID *)certSelectorContext;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation
+ (cert, &certPolicies, plContext));
+
+ if (certPolicies) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (certPolicies, &numPolicies, plContext));
+
+ for (i = 0; i < numPolicies; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (certPolicies,
+ i,
+ (PKIX_PL_Object **)&policy,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_CertPolicyInfo_GetPolicyId
+ (policy, &policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)policyOID,
+ (PKIX_PL_Object *)constraintOID,
+ &match,
+ plContext));
+
+ if (match) {
+ goto cleanup;
+ }
+ PKIX_TEST_DECREF_BC(policy);
+ PKIX_TEST_DECREF_BC(policyOID);
+ }
+ }
+
+ PKIX_TEST_DECREF_BC(certSelectorContext);
+ PKIX_TEST_DECREF_BC(certPolicies);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create
+ (PKIX_CERTSELECTOR_ERROR,
+ NULL,
+ NULL,
+ PKIX_TESTNOMATCHINGPOLICY,
+ &error,
+ plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(certSelectorContext);
+ PKIX_TEST_DECREF_AC(certPolicies);
+ PKIX_TEST_DECREF_AC(policy);
+ PKIX_TEST_DECREF_AC(policyOID);
+ PKIX_TEST_DECREF_AC(errorDesc);
+
+ return(error);
+}
+
+static
+void testSubjectMatch(
+ PKIX_List *certs,
+ PKIX_PL_Cert *certNameToMatch)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *subjParams = NULL;
+ PKIX_PL_X500Name *subjectName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Subject name match");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&subjParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject
+ (certNameToMatch, &subjectName, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubject
+ (subjParams, subjectName, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, subjParams, plContext));
+ testSelector(selector, certs, 0x008);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(subjParams);
+ PKIX_TEST_DECREF_AC(subjectName);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testBasicConstraintsMatch(
+ PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *bcParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Basic Constraints match");
+ subTest(" pathLenContraint = -2: pass only EE's");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&bcParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetBasicConstraints
+ (bcParams, -2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, bcParams, plContext));
+ testSelector(selector, certs, 0xC00);
+
+ subTest(" pathLenContraint = -1: pass all certs");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetBasicConstraints
+ (bcParams, -1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, bcParams, plContext));
+ testSelector(selector, certs, 0xFFF);
+
+ subTest(" pathLenContraint = 1: pass only certs with pathLen >= 1");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetBasicConstraints
+ (bcParams, 1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, bcParams, plContext));
+ testSelector(selector, certs, 0x3DF);
+
+ subTest(" pathLenContraint = 2: pass only certs with pathLen >= 2");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetBasicConstraints
+ (bcParams, 2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, bcParams, plContext));
+ testSelector(selector, certs, 0x39F);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(bcParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testPolicyMatch(
+ PKIX_List *certs,
+ PKIX_PL_Cert *NIST1Cert, /* a source for policy NIST1 */
+ PKIX_PL_Cert *NIST2Cert, /* a source for policy NIST2 */
+ PKIX_PL_Cert *anyPolicyCert) /* a source for policy anyPolicy */
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_List *emptyList = NULL; /* no members */
+ PKIX_List *policy1List = NULL; /* OIDs */
+ PKIX_List *policy2List = NULL; /* OIDs */
+ PKIX_List *anyPolicyList = NULL; /* OIDs */
+ PKIX_ComCertSelParams *polParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Policy match");
+ testGetPolicyFromCert(NIST1Cert, 0, &policy1List);
+ testGetPolicyFromCert(NIST2Cert, 1, &policy2List);
+ testGetPolicyFromCert(anyPolicyCert, 0, &anyPolicyList);
+
+ subTest(" Pass certs with any CertificatePolicies extension");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&emptyList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_Create(&polParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetPolicy
+ (polParams, emptyList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, polParams, plContext));
+ testSelector(selector, certs, 0xEFF);
+ PKIX_TEST_DECREF_BC(polParams);
+
+ subTest(" Pass only certs with policy NIST1");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_Create(&polParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetPolicy
+ (polParams, policy1List, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, polParams, plContext));
+ testSelector(selector, certs, 0xEF5);
+ PKIX_TEST_DECREF_BC(polParams);
+
+ subTest(" Pass only certs with policy NIST2");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_Create(&polParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetPolicy
+ (polParams, policy2List, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, polParams, plContext));
+ testSelector(selector, certs, 0x814);
+ PKIX_TEST_DECREF_BC(polParams);
+
+ subTest(" Pass only certs with policy anyPolicy");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_Create(&polParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetPolicy
+ (polParams, anyPolicyList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, polParams, plContext));
+ testSelector(selector, certs, 0x002);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(emptyList);
+ PKIX_TEST_DECREF_AC(policy1List);
+ PKIX_TEST_DECREF_AC(policy2List);
+ PKIX_TEST_DECREF_AC(anyPolicyList);
+ PKIX_TEST_DECREF_AC(polParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testCertificateMatch(
+ PKIX_List *certs,
+ PKIX_PL_Cert *certToMatch)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Certificate match");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (¶ms, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate
+ (params, certToMatch, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+ testSelector(selector, certs, 0x008);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(params);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testNameConstraintsMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_CertNameConstraints *permitNameConstraints1 = NULL;
+ PKIX_PL_CertNameConstraints *permitNameConstraints2 = NULL;
+ PKIX_PL_CertNameConstraints *permitNameConstraints3 = NULL;
+ PKIX_PL_CertNameConstraints *excludeNameConstraints1 = NULL;
+ PKIX_PL_CertNameConstraints *excludeNameConstraints2 = NULL;
+ PKIX_PL_CertNameConstraints *excludeNameConstraints3 = NULL;
+ PKIX_UInt32 numCerts = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test NameConstraints Cert Selector");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (certs, &numCerts, plContext));
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints ");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (certs, 0, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints
+ (cert, &permitNameConstraints1, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints ");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (certs, 1, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints
+ (cert, &permitNameConstraints2, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints ");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (certs, 2, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints
+ (cert, &permitNameConstraints3, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints ");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (certs, 3, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints
+ (cert, &excludeNameConstraints1, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints ");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (certs, 4, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints
+ (cert, &excludeNameConstraints2, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" PKIX_PL_Cert_GetNameConstraints ");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (certs, 5, (PKIX_PL_Object **)&cert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints
+ (cert, &excludeNameConstraints3, plContext));
+ PKIX_TEST_DECREF_BC(cert);
+
+ subTest(" Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (¶ms, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+
+ subTest(" CertNameConstraints testing permitted NONE");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints
+ (params, permitNameConstraints1, plContext));
+ testSelector(selector, certs, 0x0);
+
+ subTest(" PKIX_ComCertSelParams_SetNameConstraint Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints
+ (params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+
+ subTest(" CertNameConstraints testing permitted ALL");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints
+ (params, permitNameConstraints2, plContext));
+ testSelector(selector, certs, 0x07F);
+
+ subTest(" CertNameConstraints testing permitted TWO");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints
+ (params, permitNameConstraints3, plContext));
+ testSelector(selector, certs, 0x0041);
+
+ subTest(" PKIX_ComCertSelParams_SetNameConstraint Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints
+ (params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+
+ subTest(" CertNameConstraints testing excluded");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints
+ (params, excludeNameConstraints1, plContext));
+ testSelector(selector, certs, 0x07F);
+
+ subTest(" CertNameConstraints testing excluded");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints
+ (params, excludeNameConstraints2, plContext));
+ testSelector(selector, certs, 0x07F);
+
+ subTest(" CertNameConstraints testing excluded");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints
+ (params, excludeNameConstraints3, plContext));
+ testSelector(selector, certs, 0x41);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(permitNameConstraints1);
+ PKIX_TEST_DECREF_AC(permitNameConstraints2);
+ PKIX_TEST_DECREF_AC(permitNameConstraints3);
+ PKIX_TEST_DECREF_AC(excludeNameConstraints1);
+ PKIX_TEST_DECREF_AC(excludeNameConstraints2);
+ PKIX_TEST_DECREF_AC(excludeNameConstraints3);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testPathToNamesMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_List *nameList = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test PathToName Cert Selector");
+
+ subTest(" PKIX_PL_GeneralName List create");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&nameList, plContext));
+
+ subTest(" Add directory name ");
+ name = createGeneralName
+ (PKIX_DIRECTORY_NAME,
+ "O=NotATest Certificates,C=US",
+ plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (nameList, (PKIX_PL_Object *)name, plContext));
+
+ subTest(" Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (¶ms, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames
+ (params, nameList, plContext));
+
+ subTest(" Permitting THREE");
+ testSelector(selector, certs, 0x58);
+
+ subTest(" Remove directory name ");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem
+ (nameList, 0, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames
+ (params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+
+ subTest(" Add directory name ");
+ name = createGeneralName
+ (PKIX_DIRECTORY_NAME,
+ "OU=permittedSubtree1,O=Test Certificates,C=US",
+ plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (nameList, (PKIX_PL_Object *)name, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames
+ (params, nameList, plContext));
+
+ subTest(" Permitting SIX");
+ testSelector(selector, certs, 0x5F);
+
+ subTest(" Remove directory name ");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem
+ (nameList, 0, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" PKIX_ComCertSelParams_SetNameConstraint Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames
+ (params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+
+ subTest(" Add directory name ");
+ name = createGeneralName
+ (PKIX_DIRECTORY_NAME,
+ "O=Test Certificates,C=US",
+ plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (nameList, (PKIX_PL_Object *)name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames
+ (params, nameList, plContext));
+
+ subTest(" Permitting FOUR");
+ testSelector(selector, certs, 0x47);
+
+ subTest(" Only directory name ");
+ name = createGeneralName
+ (PKIX_DIRECTORY_NAME,
+ "OU=permittedSubtree1,O=Test Certificates,C=US",
+ plContext);
+
+ subTest(" PKIX_ComCertSelParams_AddPathToName");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddPathToName
+ (params, name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" Permitting FOUR");
+ testSelector(selector, certs, 0x47);
+
+ subTest(" PKIX_ComCertSelParams_SetNameConstraint Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames
+ (params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+ PKIX_TEST_DECREF_BC(nameList);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&nameList, plContext));
+
+ subTest(" Add directory name ");
+ name = createGeneralName
+ (PKIX_DIRECTORY_NAME, "CN=Valid DN nameConstraints EE "
+ "Certificate Test1,OU=permittedSubtree1,"
+ "O=Test Certificates,C=US",
+ plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (nameList, (PKIX_PL_Object *)name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames
+ (params, nameList, plContext));
+
+ subTest(" Permitting SIX");
+ testSelector(selector, certs, 0x7e);
+
+ subTest(" Add directory name ");
+ name = createGeneralName
+ (PKIX_DIRECTORY_NAME,
+ "OU=permittedSubtree1,O=Test",
+ plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (nameList, (PKIX_PL_Object *)name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames
+ (params, nameList, plContext));
+
+ subTest(" Permitting SIX");
+ testSelector(selector, certs, 0x58);
+
+ subTest(" Add directory name ");
+ name = createGeneralName
+ (PKIX_DIRECTORY_NAME, "O=Test Certificates,C=US", plContext);
+
+ subTest(" PKIX_ComCertSelParams_SetPathToNames Reset");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames
+ (params, NULL, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddPathToName
+ (params, name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" Permitting FOUR");
+ testSelector(selector, certs, 0x47);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(nameList);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testSubjAltNamesMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_List *nameList = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test SubjAltNames Cert Selector");
+
+ subTest(" PKIX_PL_GeneralName List create");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&nameList, plContext));
+
+ subTest(" Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (¶ms, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+
+ subTest(" Add directory name ");
+ name = createGeneralName
+ (PKIX_DIRECTORY_NAME,
+ "CN=Invalid DN nameConstraints EE Certificate Test3,"
+ "OU=excludedSubtree1,O=Test Certificates,C=US",
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (nameList, (PKIX_PL_Object *)name, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjAltNames
+ (params, nameList, plContext));
+
+ PKIX_TEST_DECREF_BC(name);
+ PKIX_TEST_DECREF_BC(nameList);
+
+ subTest(" Permitting ONE");
+ testSelector(selector, certs, 0x1);
+
+ subTest(" Add DNS name ");
+ name = createGeneralName
+ (PKIX_DNS_NAME,
+ "mytestcertificates.gov",
+ plContext);
+
+ subTest(" PKIX_ComCertSelParams_AddSubjAltName");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddSubjAltName
+ (params, name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+
+ subTest(" Permitting NONE");
+ testSelector(selector, certs, 0x0);
+
+ subTest(" PKIX_ComCertSelParams_SetMatchAllSubjAltNames to FALSE");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetMatchAllSubjAltNames
+ (params, PKIX_FALSE, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+
+ subTest(" Permitting TWO");
+ testSelector(selector, certs, 0x3);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(name);
+ PKIX_TEST_DECREF_AC(nameList);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testCertificateValidMatch(
+ PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_String *stringRep = NULL;
+ PKIX_PL_Date *testDate = NULL;
+ char *asciiRep = "050501000000Z";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("CertificateValid match");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (¶ms, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiRep, 0, &stringRep, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Date_Create_UTCTime(stringRep, &testDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificateValid
+ (params, testDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+ testSelector(selector, certs, 0xFFFFFFFF);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(stringRep);
+ PKIX_TEST_DECREF_AC(testDate);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void test_customCallback1(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("custom matchCallback");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (custom_CertSelector_MatchCallback,
+ NULL,
+ &selector,
+ plContext));
+
+ testSelector(selector, certs, 0x900);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void test_customCallback2
+ (PKIX_List *certs,
+ PKIX_PL_Cert *anyPolicyCert) /* a source for policy anyPolicy */
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_List *anyPolicyList = NULL; /* OIDs */
+ PKIX_PL_OID *policyOID = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("custom matchCallback with CertSelectorContext");
+
+ testGetPolicyFromCert(anyPolicyCert, 0, &anyPolicyList);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (anyPolicyList, 0, (PKIX_PL_Object **)&policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (custom_CertSelector_MatchOIDCallback,
+ (PKIX_PL_Object *)policyOID,
+ &selector,
+ plContext));
+
+ testSelector(selector, certs, (1 << ANYPOLICYCERT));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(anyPolicyList);
+ PKIX_TEST_DECREF_AC(policyOID);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testExtendedKeyUsageMatch(char *certDir)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_OID *ekuOid = NULL;
+ PKIX_List *ekuOidList = NULL;
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_UInt32 numCert = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Extended KeyUsage Cert Selector");
+
+ subTest(" PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ subTest(" Create Extended Key Usage OID List");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&ekuOidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ ("1.3.6.1.5.5.7.3.2", &ekuOid, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (ekuOidList, (PKIX_PL_Object *)ekuOid, plContext));
+
+ PKIX_TEST_DECREF_BC(ekuOid);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ ("1.3.6.1.5.5.7.3.3", &ekuOid, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (ekuOidList, (PKIX_PL_Object *)ekuOid, plContext));
+
+ PKIX_TEST_DECREF_BC(ekuOid);
+
+ subTest(" PKIX_ComCertSelParams_SetExtendedKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetExtendedKeyUsage
+ (goodParams, ekuOidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, certDir, 0, &dirString, plContext));
+
+ subTest(" PKIX_PL_CollectionCertStoreContext_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
+ (dirString, &certStore, plContext));
+
+ subTest(" PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, goodParams, plContext));
+
+ subTest(" PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback
+ (certStore, &certCallback, NULL));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback
+ (certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (certList, &numCert, plContext));
+
+ if (numCert != PKIX_TEST_CERTSELECTOR_EXTKEYUSAGE_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Cert number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(ekuOid);
+ PKIX_TEST_DECREF_AC(ekuOidList);
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certList);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testKeyUsageMatch(char *certDir)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_UInt32 numCert = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test KeyUsage Cert Selector");
+
+ subTest(" PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetKeyUsage
+ (goodParams, PKIX_CRL_SIGN, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, certDir, 0, &dirString, plContext));
+
+ subTest(" PKIX_PL_CollectionCertStoreContext_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
+ (dirString, &certStore, plContext));
+
+ subTest(" PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, goodParams, plContext));
+
+ subTest(" PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback
+ (certStore, &certCallback, NULL));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback
+ (certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (certList, &numCert, plContext));
+
+ if (numCert != PKIX_TEST_CERTSELECTOR_KEYUSAGE_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Cert number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certList);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testCertValidMatch(char *certDir)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_Date *validDate = NULL;
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_UInt32 numCert = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test CertValid Cert Selector");
+
+ subTest(" PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ validDate = createDate("050601000000Z", plContext);
+
+ subTest(" PKIX_ComCertSelParams_SetCertificateValid");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificateValid
+ (goodParams, validDate, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, certDir, 0, &dirString, plContext));
+
+ subTest(" PKIX_PL_CollectionCertStoreContext_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
+ (dirString, &certStore, plContext));
+
+ subTest(" PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, goodParams, plContext));
+
+ subTest(" PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback
+ (certStore, &certCallback, NULL));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback
+ (certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (certList, &numCert, plContext));
+
+ if (numCert != PKIX_TEST_CERTSELECTOR_CERTVALID_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Cert number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(validDate);
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certList);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testIssuerMatch(char *certDir)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+ PKIX_PL_String *issuerStr = NULL;
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ char *issuerName = "CN=science,O=mit,C=US";
+ PKIX_UInt32 numCert = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Issuer Cert Selector");
+
+ subTest(" PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, issuerName, 0, &issuerStr, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create
+ (issuerStr, &issuer, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetIssuer");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetIssuer
+ (goodParams, issuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, certDir, 0, &dirString, plContext));
+
+ subTest(" PKIX_PL_CollectionCertStoreContext_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
+ (dirString, &certStore, plContext));
+
+ subTest(" PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, goodParams, plContext));
+
+ subTest(" PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback
+ (certStore, &certCallback, NULL));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback
+ (certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (certList, &numCert, plContext));
+
+ if (numCert != PKIX_TEST_CERTSELECTOR_ISSUER_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Cert number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(issuer);
+ PKIX_TEST_DECREF_AC(issuerStr);
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certList);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testSerialNumberVersionMatch(char *certDir)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_BigInt *serialNumber = NULL;
+ PKIX_PL_String *serialNumberStr = NULL;
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CertCallback certCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_UInt32 numCert = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Serial Number Cert Selector");
+
+ subTest(" PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "01", 0, &serialNumberStr, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create
+ (serialNumberStr, &serialNumber, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetSerialNumber");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSerialNumber
+ (goodParams, serialNumber, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetVersion");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetVersion
+ (goodParams, 0, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, certDir, 0, &dirString, plContext));
+
+ subTest(" PKIX_PL_CollectionCertStoreContext_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
+ (dirString, &certStore, plContext));
+
+ subTest(" PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, goodParams, plContext));
+
+ subTest(" PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback
+ (certStore, &certCallback, NULL));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback
+ (certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (certList, &numCert, plContext));
+
+ PKIX_TEST_DECREF_BC(certList);
+
+ if (numCert != 0) {
+ pkixTestErrorMsg = "unexpected Version mismatch";
+ }
+
+ subTest(" PKIX_ComCertSelParams_SetVersion");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetVersion
+ (goodParams, 2, plContext));
+
+ subTest(" Getting data from Cert Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(certCallback
+ (certStore, certSelector, &nbioContext, &certList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (certList, &numCert, plContext));
+
+ if (numCert != PKIX_TEST_CERTSELECTOR_SERIALNUMBER_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Serial Number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(serialNumber);
+ PKIX_TEST_DECREF_AC(serialNumberStr);
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certList);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testSubjKeyIdMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_ByteArray *selSubjKeyId = NULL;
+ PKIX_UInt32 item = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Subject Key Id Cert Selector");
+
+ item = 2;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (certs, item, (PKIX_PL_Object **)&cert, plContext));
+
+ subTest(" PKIX_PL_Cert_GetSubjectKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectKeyIdentifier
+ (cert, &selSubjKeyId, plContext));
+
+ subTest(" Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (¶ms, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, params, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetSubjKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjKeyIdentifier
+ (params, selSubjKeyId, plContext));
+
+ subTest(" Select One");
+ testSelector(selector, certs, 1<- \n\n");
+}
+
+int test_certselector(int argc, char *argv[]) {
+
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_CertSelector *emptySelector = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_List *nameConstraintsCerts = NULL;
+ PKIX_List *subjAltNamesCerts = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_Cert *policy1Cert = NULL;
+ PKIX_PL_Cert *policy2Cert = NULL;
+ PKIX_PL_Cert *anyPolicyCert = NULL;
+ PKIX_PL_Cert *subjectCert = NULL;
+ PKIX_ComCertSelParams *selParams = NULL;
+ char *certDir = NULL;
+ char *dirName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CertSelector");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 3) {
+ printUsage();
+ return (0);
+ }
+
+ dirName = argv[j+1];
+ certDir = argv[j+3];
+
+ /* Create a List of certs to use in testing the selector */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certs, plContext));
+
+ for (i = 0; i < NUMCERTS; i++) {
+
+ cert = createCert(dirName, certList[i], plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (certs, (PKIX_PL_Object *)cert, plContext));
+ if (i == POLICY1CERT) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)cert, plContext));
+ policy1Cert = cert;
+ }
+ if (i == ANYPOLICYCERT) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)cert, plContext));
+ anyPolicyCert = cert;
+ }
+ if (i == POLICY2CERT) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)cert, plContext));
+ policy2Cert = cert;
+ }
+ if (i == SUBJECTCERT) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)cert, plContext));
+ subjectCert = cert;
+ }
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create
+ (&nameConstraintsCerts, plContext));
+
+ for (i = 0; i < NUMNCCERTS; i++) {
+
+ cert = createCert(dirName, ncCertList[i], plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (nameConstraintsCerts,
+ (PKIX_PL_Object *)cert,
+ plContext));
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create
+ (&subjAltNamesCerts, plContext));
+
+ for (i = 0; i < NUMSANCERTS; i++) {
+
+ cert = createCert(dirName, sanCertList[i], plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (subjAltNamesCerts,
+ (PKIX_PL_Object *)cert,
+ plContext));
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ subTest("test_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &emptySelector, plContext));
+
+ subTest("Default Match, no parameters set");
+ testSelector(emptySelector, certs, 0xFFFFFFFF);
+
+ testSubjectMatch(certs, subjectCert);
+
+ testBasicConstraintsMatch(certs);
+
+ testPolicyMatch(certs, policy1Cert, policy2Cert, anyPolicyCert);
+
+ testCertificateMatch(certs, subjectCert);
+
+ testCertificateValidMatch(certs);
+
+ subTest("Combination: pass only EE certs that assert some policy");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_Create(&selParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetBasicConstraints
+ (selParams, -2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (emptySelector, selParams, plContext));
+ testSelector(emptySelector, certs, 0xC00);
+
+ testNameConstraintsMatch(nameConstraintsCerts);
+
+ testPathToNamesMatch(nameConstraintsCerts);
+
+ testSubjAltNamesMatch(subjAltNamesCerts);
+
+ testExtendedKeyUsageMatch(certDir);
+
+ testKeyUsageMatch(certDir);
+
+ testIssuerMatch(certDir);
+
+ testSerialNumberVersionMatch(certDir);
+
+ testCertValidMatch(certDir);
+
+ testSubjKeyIdMatch(nameConstraintsCerts);
+
+ testAuthKeyIdMatch(nameConstraintsCerts);
+
+ testSubjPKAlgIdMatch(nameConstraintsCerts);
+
+ testSubjPublicKeyMatch(nameConstraintsCerts);
+
+ test_CertSelector_Duplicate(emptySelector);
+
+ test_customCallback1(certs);
+
+ test_customCallback2(certs, anyPolicyCert);
+
+ subTest("test_CertSelector_Destroy");
+
+ PKIX_TEST_DECREF_BC(emptySelector);
+
+
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(emptySelector);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(policy1Cert);
+ PKIX_TEST_DECREF_AC(policy2Cert);
+ PKIX_TEST_DECREF_AC(anyPolicyCert);
+ PKIX_TEST_DECREF_AC(subjectCert);
+ PKIX_TEST_DECREF_AC(selParams);
+ PKIX_TEST_DECREF_AC(nameConstraintsCerts);
+ PKIX_TEST_DECREF_AC(subjAltNamesCerts);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CertSelector");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c b/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c
new file mode 100644
index 0000000..b0c0dca
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c
@@ -0,0 +1,920 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_comcertselparams.c
+ *
+ * Test Common Cert Selector Params
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static
+void test_CreateOIDList(PKIX_List *certPolicyInfos, PKIX_List **pPolicyOIDs)
+{
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 numInfos = 0;
+ PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL;
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_List *certPolicies = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ /* Convert from List of CertPolicyInfos to List of OIDs */
+ if (certPolicyInfos) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (certPolicyInfos, &numInfos, plContext));
+ }
+
+ if (numInfos > 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create
+ (&certPolicies, plContext));
+ }
+ for (i = 0; i < numInfos; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (certPolicyInfos,
+ i,
+ (PKIX_PL_Object **)&certPolicyInfo,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId
+ (certPolicyInfo, &policyOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (certPolicies, (PKIX_PL_Object *)policyOID, plContext));
+ PKIX_TEST_DECREF_BC(certPolicyInfo);
+ PKIX_TEST_DECREF_BC(policyOID);
+ }
+
+ *pPolicyOIDs = certPolicies;
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(certPolicyInfo);
+ PKIX_TEST_DECREF_AC(policyOID);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void test_NameConstraints(char *dirName)
+{
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_CertNameConstraints *getNameConstraints = NULL;
+ PKIX_PL_CertNameConstraints *setNameConstraints = NULL;
+ PKIX_ComCertSelParams *goodParams = NULL;
+ char *expectedAscii =
+ "[\n"
+ "\t\tPermitted Name: (OU=permittedSubtree1,"
+ "O=Test Certificates,C=US, OU=permittedSubtree2,"
+ "O=Test Certificates,C=US)\n"
+ "\t\tExcluded Name: (EMPTY)\n"
+ "\t]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Create Cert for NameConstraints test");
+
+ goodCert = createCert
+ (dirName, "nameConstraintsDN2CACert.crt", plContext);
+
+ subTest("PKIX_PL_Cert_GetNameConstraints");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints
+ (goodCert, &setNameConstraints, plContext));
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetNameConstraints");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints
+ (goodParams, setNameConstraints, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetNameConstraints");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetNameConstraints
+ (goodParams, &getNameConstraints, plContext));
+
+ subTest("Compare NameConstraints");
+ testEqualsHelper((PKIX_PL_Object *)setNameConstraints,
+ (PKIX_PL_Object *)getNameConstraints,
+ PKIX_TRUE,
+ plContext);
+
+ subTest("Compare NameConstraints with canned string");
+ testToStringHelper
+ ((PKIX_PL_Object *)getNameConstraints,
+ expectedAscii,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(getNameConstraints);
+ PKIX_TEST_DECREF_AC(setNameConstraints);
+ PKIX_TEST_DECREF_AC(goodParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void test_PathToNames(void)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_List *setGenNames = NULL;
+ PKIX_List *getGenNames = NULL;
+ PKIX_PL_GeneralName *rfc822GenName = NULL;
+ PKIX_PL_GeneralName *dnsGenName = NULL;
+ PKIX_PL_GeneralName *dirGenName = NULL;
+ PKIX_PL_GeneralName *uriGenName = NULL;
+ PKIX_PL_GeneralName *oidGenName = NULL;
+ char *rfc822Name = "john.doe@labs.com";
+ char *dnsName = "comcast.net";
+ char *dirName = "cn=john, ou=labs, o=sun, c=us";
+ char *uriName = "http://comcast.net";
+ char *oidName = "1.2.840.11";
+ char *expectedAscii =
+ "(john.doe@labs.com, "
+ "comcast.net, "
+ "CN=john,OU=labs,O=sun,C=us, "
+ "http://comcast.net)";
+ char *expectedAsciiAll =
+ "(john.doe@labs.com, "
+ "comcast.net, "
+ "CN=john,OU=labs,O=sun,C=us, "
+ "http://comcast.net, "
+ "1.2.840.11)";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_GeneralName_Create");
+ dnsGenName = createGeneralName(PKIX_DNS_NAME, dnsName, plContext);
+ uriGenName = createGeneralName(PKIX_URI_NAME, uriName, plContext);
+ oidGenName = createGeneralName(PKIX_OID_NAME, oidName, plContext);
+ dirGenName = createGeneralName(PKIX_DIRECTORY_NAME, dirName, plContext);
+ rfc822GenName = createGeneralName
+ (PKIX_RFC822_NAME,
+ rfc822Name,
+ plContext);
+
+ subTest("PKIX_PL_GeneralName List create and append");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setGenNames, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setGenNames, (PKIX_PL_Object *)rfc822GenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setGenNames, (PKIX_PL_Object *)dnsGenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setGenNames, (PKIX_PL_Object *)dirGenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setGenNames, (PKIX_PL_Object *)uriGenName, plContext));
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames
+ (goodParams, setGenNames, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPathToNames
+ (goodParams, &getGenNames, plContext));
+
+ subTest("Compare GeneralName List");
+ testEqualsHelper((PKIX_PL_Object *)setGenNames,
+ (PKIX_PL_Object *)getGenNames,
+ PKIX_TRUE,
+ plContext);
+
+ subTest("Compare GeneralName List with canned string");
+ testToStringHelper
+ ((PKIX_PL_Object *)getGenNames,
+ expectedAscii,
+ plContext);
+
+ subTest("PKIX_ComCertSelParams_AddPathToName");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddPathToName
+ (goodParams, oidGenName, plContext));
+
+ PKIX_TEST_DECREF_BC(getGenNames);
+
+ subTest("PKIX_ComCertSelParams_GetPathToNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPathToNames
+ (goodParams, &getGenNames, plContext));
+
+ subTest("Compare GeneralName List with canned string");
+ testToStringHelper
+ ((PKIX_PL_Object *)getGenNames,
+ expectedAsciiAll,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(setGenNames);
+ PKIX_TEST_DECREF_AC(getGenNames);
+ PKIX_TEST_DECREF_AC(rfc822GenName);
+ PKIX_TEST_DECREF_AC(dnsGenName);
+ PKIX_TEST_DECREF_AC(dirGenName);
+ PKIX_TEST_DECREF_AC(uriGenName);
+ PKIX_TEST_DECREF_AC(oidGenName);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void test_SubjAltNames(void)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_List *setGenNames = NULL;
+ PKIX_List *getGenNames = NULL;
+ PKIX_PL_GeneralName *rfc822GenName = NULL;
+ PKIX_PL_GeneralName *dnsGenName = NULL;
+ PKIX_PL_GeneralName *dirGenName = NULL;
+ PKIX_PL_GeneralName *uriGenName = NULL;
+ PKIX_PL_GeneralName *oidGenName = NULL;
+ PKIX_Boolean matchAll = PKIX_TRUE;
+ char *rfc822Name = "john.doe@labs.com";
+ char *dnsName = "comcast.net";
+ char *dirName = "cn=john, ou=labs, o=sun, c=us";
+ char *uriName = "http://comcast.net";
+ char *oidName = "1.2.840.11";
+ char *expectedAscii =
+ "(john.doe@labs.com, "
+ "comcast.net, "
+ "CN=john,OU=labs,O=sun,C=us, "
+ "http://comcast.net)";
+ char *expectedAsciiAll =
+ "(john.doe@labs.com, "
+ "comcast.net, "
+ "CN=john,OU=labs,O=sun,C=us, "
+ "http://comcast.net, "
+ "1.2.840.11)";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_GeneralName_Create");
+ dnsGenName = createGeneralName(PKIX_DNS_NAME, dnsName, plContext);
+ uriGenName = createGeneralName(PKIX_URI_NAME, uriName, plContext);
+ oidGenName = createGeneralName(PKIX_OID_NAME, oidName, plContext);
+ dirGenName = createGeneralName(PKIX_DIRECTORY_NAME, dirName, plContext);
+ rfc822GenName = createGeneralName
+ (PKIX_RFC822_NAME,
+ rfc822Name,
+ plContext);
+
+ subTest("PKIX_PL_GeneralName List create and append");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setGenNames, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setGenNames, (PKIX_PL_Object *)rfc822GenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setGenNames, (PKIX_PL_Object *)dnsGenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setGenNames, (PKIX_PL_Object *)dirGenName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setGenNames, (PKIX_PL_Object *)uriGenName, plContext));
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjAltNames
+ (goodParams, setGenNames, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubjAltNames
+ (goodParams, &getGenNames, plContext));
+
+ subTest("Compare GeneralName List");
+ testEqualsHelper((PKIX_PL_Object *)setGenNames,
+ (PKIX_PL_Object *)getGenNames,
+ PKIX_TRUE,
+ plContext);
+
+ subTest("Compare GeneralName List with canned string");
+ testToStringHelper
+ ((PKIX_PL_Object *)getGenNames,
+ expectedAscii,
+ plContext);
+
+
+ subTest("PKIX_ComCertSelParams_AddSubjAltName");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddSubjAltName
+ (goodParams, oidGenName, plContext));
+
+ PKIX_TEST_DECREF_BC(getGenNames);
+
+ subTest("PKIX_ComCertSelParams_GetSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubjAltNames
+ (goodParams, &getGenNames, plContext));
+
+ subTest("Compare GeneralName List with canned string");
+ testToStringHelper
+ ((PKIX_PL_Object *)getGenNames,
+ expectedAsciiAll,
+ plContext);
+
+ subTest("PKIX_ComCertSelParams_GetMatchAllSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetMatchAllSubjAltNames
+ (goodParams, &matchAll, plContext));
+ if (matchAll != PKIX_TRUE) {
+ testError("unexpected mismatch ");
+ }
+
+ subTest("PKIX_ComCertSelParams_SetMatchAllSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetMatchAllSubjAltNames
+ (goodParams, PKIX_FALSE, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetMatchAllSubjAltNames
+ (goodParams, &matchAll, plContext));
+ if (matchAll != PKIX_FALSE) {
+ testError("unexpected mismatch ");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(setGenNames);
+ PKIX_TEST_DECREF_AC(getGenNames);
+ PKIX_TEST_DECREF_AC(rfc822GenName);
+ PKIX_TEST_DECREF_AC(dnsGenName);
+ PKIX_TEST_DECREF_AC(dirGenName);
+ PKIX_TEST_DECREF_AC(uriGenName);
+ PKIX_TEST_DECREF_AC(oidGenName);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void test_KeyUsages(void)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_OID *ekuOid = NULL;
+ PKIX_List *setExtKeyUsage = NULL;
+ PKIX_List *getExtKeyUsage = NULL;
+ PKIX_UInt32 getKeyUsage = 0;
+ PKIX_UInt32 setKeyUsage = 0x1FF;
+ PKIX_Boolean isEqual = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetKeyUsage
+ (goodParams, setKeyUsage, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetKeyUsage
+ (goodParams, &getKeyUsage, plContext));
+
+ if (setKeyUsage != getKeyUsage) {
+ testError("unexpected KeyUsage mismatch ");
+ }
+
+ subTest("PKIX_PL_OID List create and append");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setExtKeyUsage, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ ("1.3.6.1.5.5.7.3.1", &ekuOid, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setExtKeyUsage, (PKIX_PL_Object *)ekuOid, plContext));
+ PKIX_TEST_DECREF_BC(ekuOid);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ ("1.3.6.1.5.5.7.3.8", &ekuOid, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setExtKeyUsage, (PKIX_PL_Object *)ekuOid, plContext));
+ PKIX_TEST_DECREF_BC(ekuOid);
+
+ subTest("PKIX_ComCertSelParams_SetExtendedKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetExtendedKeyUsage
+ (goodParams, setExtKeyUsage, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetExtendedKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetExtendedKeyUsage
+ (goodParams, &getExtKeyUsage, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setExtKeyUsage,
+ (PKIX_PL_Object *)getExtKeyUsage,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected ExtKeyUsage mismatch ");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(ekuOid);
+ PKIX_TEST_DECREF_AC(setExtKeyUsage);
+ PKIX_TEST_DECREF_AC(getExtKeyUsage);
+ PKIX_TEST_DECREF_AC(goodParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void test_Version_Issuer_SerialNumber(void)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_UInt32 version = 0;
+ PKIX_PL_X500Name *setIssuer = NULL;
+ PKIX_PL_X500Name *getIssuer = NULL;
+ PKIX_PL_String *str = NULL;
+ PKIX_PL_BigInt *setSerialNumber = NULL;
+ PKIX_PL_BigInt *getSerialNumber = NULL;
+ PKIX_Boolean isEqual = PKIX_FALSE;
+ char *bigInt = "999999999999999999";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ /* Version */
+ subTest("PKIX_ComCertSelParams_SetVersion");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetVersion
+ (goodParams, 2, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetVersion");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetVersion
+ (goodParams, &version, plContext));
+
+ if (version != 2) {
+ testError("unexpected Version mismatch ");
+ }
+
+ /* Issuer */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "CN=Test,O=Sun,C=US", 0, &str, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create
+ (str, &setIssuer, plContext));
+
+ PKIX_TEST_DECREF_BC(str);
+
+ subTest("PKIX_ComCertSelParams_SetIssuer");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetIssuer
+ (goodParams, setIssuer, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetIssuer");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetIssuer
+ (goodParams, &getIssuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setIssuer,
+ (PKIX_PL_Object *)getIssuer,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Issuer mismatch ");
+ }
+
+ /* Serial Number */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, bigInt, PL_strlen(bigInt), &str, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create
+ (str, &setSerialNumber, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetSerialNumber");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSerialNumber
+ (goodParams, setSerialNumber, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetSerialNumber");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSerialNumber
+ (goodParams, &getSerialNumber, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setSerialNumber,
+ (PKIX_PL_Object *)getSerialNumber,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Serial Number mismatch ");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(str);
+ PKIX_TEST_DECREF_AC(setIssuer);
+ PKIX_TEST_DECREF_AC(getIssuer);
+ PKIX_TEST_DECREF_AC(setSerialNumber);
+ PKIX_TEST_DECREF_AC(getSerialNumber);
+ PKIX_TEST_DECREF_AC(goodParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void test_SubjKeyId_AuthKeyId(void)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_ByteArray *setKeyId = NULL;
+ PKIX_PL_ByteArray *getKeyId = NULL;
+ PKIX_Boolean isEqual = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ /* Subject Key Identifier */
+ subTest("PKIX_PL_ByteArray_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create
+ ((void*)"66099", 1, &setKeyId, plContext));
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetSubjectKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjKeyIdentifier
+ (goodParams, setKeyId, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetSubjectKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubjKeyIdentifier
+ (goodParams, &getKeyId, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setKeyId,
+ (PKIX_PL_Object *)getKeyId,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Subject Key Id mismatch ");
+ }
+
+ PKIX_TEST_DECREF_BC(setKeyId);
+ PKIX_TEST_DECREF_BC(getKeyId);
+
+ /* Authority Key Identifier */
+ subTest("PKIX_PL_ByteArray_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create
+ ((void*)"11022", 1, &setKeyId, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetAuthorityKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetAuthorityKeyIdentifier
+ (goodParams, setKeyId, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetAuthorityKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_GetAuthorityKeyIdentifier
+ (goodParams, &getKeyId, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setKeyId,
+ (PKIX_PL_Object *)getKeyId,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Auth Key Id mismatch ");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setKeyId);
+ PKIX_TEST_DECREF_AC(getKeyId);
+ PKIX_TEST_DECREF_AC(goodParams);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void test_SubjAlgId_SubjPublicKey(char *dirName)
+{
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_PL_OID *setAlgId = NULL;
+ PKIX_PL_OID *getAlgId = NULL;
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_PublicKey *setPublicKey = NULL;
+ PKIX_PL_PublicKey *getPublicKey = NULL;
+ PKIX_Boolean isEqual = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ /* Subject Algorithm Identifier */
+ subTest("PKIX_PL_OID_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ ("1.1.2.3", &setAlgId, plContext));
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetSubjPKAlgId");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjPKAlgId
+ (goodParams, setAlgId, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetSubjPKAlgId");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubjPKAlgId
+ (goodParams, &getAlgId, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setAlgId,
+ (PKIX_PL_Object *)getAlgId,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Subject Public Key Alg mismatch "
+ "");
+ }
+
+ /* Subject Public Key */
+ subTest("Getting Cert for Subject Public Key");
+
+ goodCert = createCert
+ (dirName, "nameConstraintsDN2CACert.crt", plContext);
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey
+ (goodCert, &setPublicKey, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetSubjPubKey");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjPubKey
+ (goodParams, setPublicKey, plContext));
+
+ subTest("PKIX_ComCertSelParams_GetSubjPubKey");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubjPubKey
+ (goodParams, &getPublicKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setPublicKey,
+ (PKIX_PL_Object *)getPublicKey,
+ &isEqual,
+ plContext));
+
+ if (isEqual == PKIX_FALSE) {
+ testError("unexpected Subject Public Key mismatch "
+ "");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setAlgId);
+ PKIX_TEST_DECREF_AC(getAlgId);
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(setPublicKey);
+ PKIX_TEST_DECREF_AC(getPublicKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void printUsage(void) {
+ (void) printf("\nUSAGE:\ttest_comcertselparams \n\n");
+}
+
+int test_comcertselparams(int argc, char *argv[]) {
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_PL_Cert *testCert = NULL;
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_PL_CertBasicConstraints *goodBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *diffBasicConstraints = NULL;
+ PKIX_List *testPolicyInfos = NULL; /* CertPolicyInfos */
+ PKIX_List *cert2PolicyInfos = NULL; /* CertPolicyInfos */
+
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_ComCertSelParams *equalParams = NULL;
+ PKIX_PL_X500Name *goodSubject = NULL;
+ PKIX_PL_X500Name *equalSubject = NULL;
+ PKIX_PL_X500Name *diffSubject = NULL;
+ PKIX_PL_X500Name *testSubject = NULL;
+ PKIX_Int32 goodMinPathLength = 0;
+ PKIX_Int32 equalMinPathLength = 0;
+ PKIX_Int32 diffMinPathLength = 0;
+ PKIX_Int32 testMinPathLength = 0;
+ PKIX_List *goodPolicies = NULL; /* OIDs */
+ PKIX_List *equalPolicies = NULL; /* OIDs */
+ PKIX_List *testPolicies = NULL; /* OIDs */
+ PKIX_List *cert2Policies = NULL; /* OIDs */
+
+ PKIX_PL_Date *testDate = NULL;
+ PKIX_PL_Date *goodDate = NULL;
+ PKIX_PL_Date *equalDate = NULL;
+ PKIX_PL_String *stringRep = NULL;
+ char *asciiRep = NULL;
+ char *dirName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 2) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("ComCertSelParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ dirName = argv[j+1];
+
+ asciiRep = "050501000000Z";
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_String_Create
+ (PKIX_ESCASCII, asciiRep, 0, &stringRep, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Date_Create_UTCTime(stringRep, &testDate, plContext));
+
+ testCert = createCert
+ (dirName, "PoliciesP1234CACert.crt", plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject
+ (testCert, &testSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetBasicConstraints
+ (testCert, &goodBasicConstraints, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetPathLenConstraint
+ (goodBasicConstraints, &testMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation
+ (testCert, &testPolicyInfos, plContext));
+
+ /* Convert from List of CertPolicyInfos to List of OIDs */
+ test_CreateOIDList(testPolicyInfos, &testPolicies);
+
+ subTest("Create goodParams and set its fields");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&goodParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubject
+ (goodParams, testSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints
+ (goodParams, testMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificateValid
+ (goodParams, testDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPolicy
+ (goodParams, testPolicies, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate
+ (goodParams, testCert, plContext));
+
+ subTest("Duplicate goodParams and verify copy");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)goodParams,
+ (PKIX_PL_Object **)&equalParams,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubject
+ (goodParams, &goodSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetBasicConstraints
+ (goodParams, &goodMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_GetCertificate
+ (goodParams, &goodCert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificateValid
+ (goodParams, &goodDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPolicy
+ (goodParams, &goodPolicies, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubject
+ (equalParams, &equalSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetBasicConstraints
+ (equalParams, &equalMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPolicy
+ (equalParams, &equalPolicies, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificate
+ (equalParams, &equalCert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificateValid
+ (equalParams, &equalDate, plContext));
+
+ testEqualsHelper
+ ((PKIX_PL_Object *)goodSubject,
+ (PKIX_PL_Object *)equalSubject,
+ PKIX_TRUE,
+ plContext);
+
+ if (goodMinPathLength != equalMinPathLength) {
+ testError("unexpected mismatch");
+ (void) printf("goodMinPathLength:\t%d\n", goodMinPathLength);
+ (void) printf("equalMinPathLength:\t%d\n", equalMinPathLength);
+ }
+
+ testEqualsHelper((PKIX_PL_Object *)goodPolicies,
+ (PKIX_PL_Object *)equalPolicies,
+ PKIX_TRUE,
+ plContext);
+
+ testEqualsHelper((PKIX_PL_Object *)goodCert,
+ (PKIX_PL_Object *)equalCert,
+ PKIX_TRUE,
+ plContext);
+
+ testEqualsHelper((PKIX_PL_Object *)goodDate,
+ (PKIX_PL_Object *)equalDate,
+ PKIX_TRUE,
+ plContext);
+
+ PKIX_TEST_DECREF_BC(equalSubject);
+ PKIX_TEST_DECREF_BC(equalPolicies);
+ PKIX_TEST_DECREF_BC(equalCert);
+ PKIX_TEST_DECREF_AC(equalDate);
+
+ subTest("Set different values and verify differences");
+
+ diffCert = createCert
+ (dirName, "pathLenConstraint6CACert.crt", plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject
+ (diffCert, &diffSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetBasicConstraints
+ (diffCert, &diffBasicConstraints, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetPathLenConstraint
+ (diffBasicConstraints, &diffMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation
+ (diffCert, &cert2PolicyInfos, plContext));
+ test_CreateOIDList(cert2PolicyInfos, &cert2Policies);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubject(
+ equalParams, diffSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints
+ (equalParams, diffMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPolicy
+ (equalParams, cert2Policies, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubject
+ (equalParams, &equalSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetBasicConstraints
+ (equalParams, &equalMinPathLength, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPolicy
+ (equalParams, &equalPolicies, plContext));
+
+ testEqualsHelper
+ ((PKIX_PL_Object *)goodSubject,
+ (PKIX_PL_Object *)equalSubject,
+ PKIX_FALSE,
+ plContext);
+
+ if (goodMinPathLength == equalMinPathLength) {
+ testError("unexpected match");
+ (void) printf("goodMinPathLength:\t%d\n", goodMinPathLength);
+ (void) printf("equalMinPathLength:\t%d\n", equalMinPathLength);
+ }
+
+ testEqualsHelper
+ ((PKIX_PL_Object *)goodPolicies,
+ (PKIX_PL_Object *)equalPolicies,
+ PKIX_FALSE,
+ plContext);
+
+ test_NameConstraints(dirName);
+ test_PathToNames();
+ test_SubjAltNames();
+ test_KeyUsages();
+ test_Version_Issuer_SerialNumber();
+ test_SubjKeyId_AuthKeyId();
+ test_SubjAlgId_SubjPublicKey(dirName);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(testSubject);
+ PKIX_TEST_DECREF_AC(goodSubject);
+ PKIX_TEST_DECREF_AC(equalSubject);
+ PKIX_TEST_DECREF_AC(diffSubject);
+ PKIX_TEST_DECREF_AC(testSubject);
+ PKIX_TEST_DECREF_AC(goodPolicies);
+ PKIX_TEST_DECREF_AC(equalPolicies);
+ PKIX_TEST_DECREF_AC(testPolicies);
+ PKIX_TEST_DECREF_AC(cert2Policies);
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(equalParams);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_DECREF_AC(testCert);
+ PKIX_TEST_DECREF_AC(goodBasicConstraints);
+ PKIX_TEST_DECREF_AC(diffBasicConstraints);
+ PKIX_TEST_DECREF_AC(testPolicyInfos);
+ PKIX_TEST_DECREF_AC(cert2PolicyInfos);
+ PKIX_TEST_DECREF_AC(stringRep);
+ PKIX_TEST_DECREF_AC(testDate);
+ PKIX_TEST_DECREF_AC(goodDate);
+
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ComCertSelParams");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/checker/Makefile b/nss/cmd/libpkix/pkix/checker/Makefile
new file mode 100755
index 0000000..09ca5f1
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/checker/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/nss/cmd/libpkix/pkix/checker/manifest.mn b/nss/cmd/libpkix/pkix/checker/manifest.mn
new file mode 100755
index 0000000..3101e02
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/checker/manifest.mn
@@ -0,0 +1,19 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_certchainchecker.c
+
+LIBRARY_NAME=pkixtoolchecker
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c b/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c
new file mode 100755
index 0000000..f3cedb2
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c
@@ -0,0 +1,222 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_certchainchecker.c
+ *
+ * Test Cert Chain Checker
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+
+static
+PKIX_Error *dummyChecker_Check(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions,
+ void **pNBIOContext,
+ void *plContext)
+{
+ goto cleanup;
+
+cleanup:
+
+ return(NULL);
+}
+
+
+static
+void test_CertChainChecker_Duplicate(PKIX_CertChainChecker *original)
+{
+ PKIX_Boolean originalForward = PKIX_FALSE;
+ PKIX_Boolean copyForward = PKIX_FALSE;
+ PKIX_Boolean originalForwardDir = PKIX_FALSE;
+ PKIX_Boolean copyForwardDir = PKIX_FALSE;
+ PKIX_CertChainChecker *copy = NULL;
+ PKIX_CertChainChecker_CheckCallback originalCallback = NULL;
+ PKIX_CertChainChecker_CheckCallback copyCallback = NULL;
+ PKIX_PL_Object *originalState = NULL;
+ PKIX_PL_Object *copyState = NULL;
+ PKIX_List *originalList = NULL;
+ PKIX_List *copyList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("CertChainChecker_Duplicate");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)original,
+ (PKIX_PL_Object **)©,
+ plContext));
+
+ subTest("CertChainChecker_GetCheckCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCheckCallback
+ (original, &originalCallback, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCheckCallback
+ (copy, ©Callback, plContext));
+ if (originalCallback != copyCallback) {
+ pkixTestErrorMsg = "CheckCallback functions are not equal!";
+ goto cleanup;
+ }
+
+ subTest("CertChainChecker_IsForwardCheckingSupported");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertChainChecker_IsForwardCheckingSupported
+ (original, &originalForward, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertChainChecker_IsForwardCheckingSupported
+ (copy, ©Forward, plContext));
+ if (originalForward != copyForward) {
+ pkixTestErrorMsg = "ForwardChecking booleans are not equal!";
+ goto cleanup;
+ }
+
+ subTest("CertChainChecker_IsForwardDirectionExpected");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertChainChecker_IsForwardDirectionExpected
+ (original, &originalForwardDir, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertChainChecker_IsForwardDirectionExpected
+ (copy, ©ForwardDir, plContext));
+ if (originalForwardDir != copyForwardDir) {
+ pkixTestErrorMsg = "ForwardDirection booleans are not equal!";
+ goto cleanup;
+ }
+
+ subTest("CertChainChecker_GetCertChainCheckerState");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertChainChecker_GetCertChainCheckerState
+ (original, &originalState, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertChainChecker_GetCertChainCheckerState
+ (copy, ©State, plContext));
+ testEqualsHelper(originalState, copyState, PKIX_TRUE, plContext);
+
+ subTest("CertChainChecker_GetSupportedExtensions");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertChainChecker_GetSupportedExtensions
+ (original, &originalList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertChainChecker_GetSupportedExtensions
+ (copy, ©List, plContext));
+ testEqualsHelper
+ ((PKIX_PL_Object *)originalList,
+ (PKIX_PL_Object *)copyList,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(copy);
+ PKIX_TEST_DECREF_AC(originalState);
+ PKIX_TEST_DECREF_AC(copyState);
+ PKIX_TEST_DECREF_AC(originalList);
+ PKIX_TEST_DECREF_AC(copyList);
+
+ PKIX_TEST_RETURN();
+}
+
+int test_certchainchecker(int argc, char *argv[]) {
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_PL_OID *bcOID = NULL;
+ PKIX_PL_OID *ncOID = NULL;
+ PKIX_PL_OID *cpOID = NULL;
+ PKIX_PL_OID *pmOID = NULL;
+ PKIX_PL_OID *pcOID = NULL;
+ PKIX_PL_OID *iaOID = NULL;
+ PKIX_CertChainChecker *dummyChecker = NULL;
+ PKIX_List *supportedExtensions = NULL;
+ PKIX_PL_Object *initialState = NULL;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CertChainChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create
+ (&supportedExtensions, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (PKIX_BASICCONSTRAINTS_OID, &bcOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (supportedExtensions, (PKIX_PL_Object *)bcOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (PKIX_NAMECONSTRAINTS_OID, &ncOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (supportedExtensions, (PKIX_PL_Object *)ncOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (PKIX_CERTIFICATEPOLICIES_OID, &cpOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (supportedExtensions, (PKIX_PL_Object *)cpOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (PKIX_POLICYMAPPINGS_OID, &pmOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (supportedExtensions, (PKIX_PL_Object *)pmOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (PKIX_POLICYCONSTRAINTS_OID, &pcOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (supportedExtensions, (PKIX_PL_Object *)pcOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (PKIX_INHIBITANYPOLICY_OID, &iaOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (supportedExtensions, (PKIX_PL_Object *)iaOID, plContext));
+
+ PKIX_TEST_DECREF_BC(bcOID);
+ PKIX_TEST_DECREF_BC(ncOID);
+ PKIX_TEST_DECREF_BC(cpOID);
+ PKIX_TEST_DECREF_BC(pmOID);
+ PKIX_TEST_DECREF_BC(pcOID);
+ PKIX_TEST_DECREF_BC(iaOID);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)supportedExtensions, plContext));
+
+ initialState = (PKIX_PL_Object *)supportedExtensions;
+
+ subTest("CertChainChecker_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_Create
+ (dummyChecker_Check, /* PKIX_CertChainChecker_CheckCallback */
+ PKIX_FALSE, /* forwardCheckingSupported */
+ PKIX_FALSE, /* forwardDirectionExpected */
+ supportedExtensions,
+ NULL, /* PKIX_PL_Object *initialState */
+ &dummyChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertChainChecker_SetCertChainCheckerState
+ (dummyChecker, initialState, plContext));
+
+ test_CertChainChecker_Duplicate(dummyChecker);
+
+ subTest("CertChainChecker_Destroy");
+ PKIX_TEST_DECREF_BC(dummyChecker);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dummyChecker);
+ PKIX_TEST_DECREF_AC(initialState);
+ PKIX_TEST_DECREF_AC(supportedExtensions);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CertChainChecker");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/crlsel/Makefile b/nss/cmd/libpkix/pkix/crlsel/Makefile
new file mode 100755
index 0000000..09ca5f1
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/crlsel/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/nss/cmd/libpkix/pkix/crlsel/manifest.mn b/nss/cmd/libpkix/pkix/crlsel/manifest.mn
new file mode 100755
index 0000000..dfac43b
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/crlsel/manifest.mn
@@ -0,0 +1,21 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_crlselector.c \
+ test_comcrlselparams.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolcrlsel
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c b/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c
new file mode 100644
index 0000000..b2420f4
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c
@@ -0,0 +1,441 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_comcrlselparams.c
+ *
+ * Test ComCRLSelParams Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testIssuer(PKIX_ComCRLSelParams *goodObject)
+{
+ PKIX_PL_String *issuer1String = NULL;
+ PKIX_PL_String *issuer2String = NULL;
+ PKIX_PL_String *issuer3String = NULL;
+ PKIX_PL_X500Name *issuerName1 = NULL;
+ PKIX_PL_X500Name *issuerName2 = NULL;
+ PKIX_PL_X500Name *issuerName3 = NULL;
+ PKIX_List *setIssuerList = NULL;
+ PKIX_List *getIssuerList = NULL;
+ PKIX_PL_String *issuerListString = NULL;
+ char *name1 = "CN=yassir,OU=bcn,OU=east,O=sun,C=us";
+ char *name2 = "CN=richard,OU=bcn,OU=east,O=sun,C=us";
+ char *name3 = "CN=hanfei,OU=bcn,OU=east,O=sun,C=us";
+ PKIX_Int32 length;
+ PKIX_Boolean result = PKIX_FALSE;
+ char *expectedAscii =
+ "(CN=yassir,OU=bcn,OU=east,O=sun,"
+ "C=us, CN=richard,OU=bcn,OU=east,O=sun,C=us, "
+ "CN=hanfei,OU=bcn,OU=east,O=sun,C=us)";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams Create Issuers");
+
+ length = PL_strlen(name1);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_UTF8,
+ name1,
+ length,
+ &issuer1String,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(issuer1String,
+ &issuerName1,
+ plContext));
+
+ length = PL_strlen(name2);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_UTF8,
+ name2,
+ length,
+ &issuer2String,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(issuer2String,
+ &issuerName2,
+ plContext));
+
+ length = PL_strlen(name3);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_UTF8,
+ name3,
+ length,
+ &issuer3String,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create
+ (issuer3String,
+ &issuerName3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setIssuerList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setIssuerList,
+ (PKIX_PL_Object *)issuerName1,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setIssuerList,
+ (PKIX_PL_Object *)issuerName2,
+ plContext));
+
+ subTest("PKIX_ComCRLSelParams_AddIssuerName");
+
+ /* Test adding an issuer to an empty list */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_AddIssuerName
+ (goodObject, issuerName3, plContext));
+
+ subTest("PKIX_ComCRLSelParams_GetIssuerNames");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetIssuerNames
+ (goodObject, &getIssuerList, plContext));
+
+ /* DECREF for GetIssuerNames */
+ PKIX_TEST_DECREF_BC(getIssuerList);
+ /* DECREF for AddIssuerName so next SetIssuerName start clean */
+ PKIX_TEST_DECREF_BC(getIssuerList);
+
+ /* Test setting issuer names on the list */
+ subTest("PKIX_ComCRLSelParams_SetIssuerNames");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetIssuerNames
+ (goodObject, setIssuerList, plContext));
+
+ subTest("PKIX_ComCRLSelParams_GetIssuerNames");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetIssuerNames
+ (goodObject, &getIssuerList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setIssuerList,
+ (PKIX_PL_Object *)getIssuerList,
+ &result,
+ plContext));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg = "unexpected Issuers mismatch";
+ }
+
+ /* Test adding an issuer to existing list */
+ subTest("PKIX_ComCRLSelParams_AddIssuerName");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_AddIssuerName
+ (goodObject, issuerName3, plContext));
+
+ subTest("PKIX_ComCRLSelParams_GetIssuerNames");
+ PKIX_TEST_DECREF_BC(getIssuerList);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetIssuerNames
+ (goodObject, &getIssuerList, plContext));
+
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)getIssuerList,
+ &issuerListString,
+ plContext));
+
+ testToStringHelper((PKIX_PL_Object *)getIssuerList,
+ expectedAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(issuer1String);
+ PKIX_TEST_DECREF_AC(issuer2String);
+ PKIX_TEST_DECREF_AC(issuer3String);
+ PKIX_TEST_DECREF_AC(issuerListString);
+ PKIX_TEST_DECREF_AC(issuerName1);
+ PKIX_TEST_DECREF_AC(issuerName2);
+ PKIX_TEST_DECREF_AC(issuerName3);
+ PKIX_TEST_DECREF_AC(setIssuerList);
+ PKIX_TEST_DECREF_AC(getIssuerList);
+
+ PKIX_TEST_RETURN();
+
+}
+
+static
+void testCertificateChecking(
+ char *dataCentralDir,
+ char *goodInput,
+ PKIX_ComCRLSelParams *goodObject)
+{
+ PKIX_PL_Cert *setCert = NULL;
+ PKIX_PL_Cert *getCert = NULL;
+ PKIX_Boolean result = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Test CertificateChecking Cert Create");
+ setCert = createCert(dataCentralDir, goodInput, plContext);
+ if (setCert == NULL) {
+ pkixTestErrorMsg = "create certificate failed";
+ goto cleanup;
+ }
+
+ subTest("PKIX_ComCRLSelParams_SetCertificateChecking");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetCertificateChecking
+ (goodObject, setCert, plContext));
+
+ subTest("PKIX_ComCRLSelParams_GetCertificateChecking");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_GetCertificateChecking
+ (goodObject, &getCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setCert,
+ (PKIX_PL_Object *)getCert,
+ &result, plContext));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg = "unexpected Cert mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setCert);
+ PKIX_TEST_DECREF_AC(getCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testDateAndTime(PKIX_ComCRLSelParams *goodObject){
+
+ PKIX_PL_Date *setDate = NULL;
+ PKIX_PL_Date *getDate = NULL;
+ char *asciiDate = "040329134847Z";
+ PKIX_Boolean result = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams_Date Create");
+ setDate = createDate(asciiDate, plContext);
+
+ subTest("PKIX_ComCRLSelParams_SetDateAndTime");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCRLSelParams_SetDateAndTime
+ (goodObject, setDate, plContext));
+
+ subTest("PKIX_ComCRLSelParams_GetDateAndTime");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCRLSelParams_GetDateAndTime
+ (goodObject, &getDate, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setDate,
+ (PKIX_PL_Object *)getDate,
+ &result, plContext));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg = "unexpected DateAndTime mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setDate);
+ PKIX_TEST_DECREF_AC(getDate);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testMaxMinCRLNumbers(PKIX_ComCRLSelParams *goodObject){
+ PKIX_PL_BigInt *setMaxCrlNumber = NULL;
+ PKIX_PL_BigInt *getMaxCrlNumber = NULL;
+ PKIX_PL_BigInt *setMinCrlNumber = NULL;
+ PKIX_PL_BigInt *getMinCrlNumber = NULL;
+ char *asciiCrlNumber1 = "01";
+ char *asciiCrlNumber99999 = "0909090909";
+ PKIX_PL_String *crlNumber1String = NULL;
+ PKIX_PL_String *crlNumber99999String = NULL;
+
+ PKIX_Boolean result = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams_SetMinCRLNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiCrlNumber1,
+ PL_strlen(asciiCrlNumber1),
+ &crlNumber1String,
+ NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create
+ (crlNumber1String, &setMinCrlNumber, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetMinCRLNumber
+ (goodObject, setMinCrlNumber, NULL));
+
+ subTest("PKIX_ComCRLSelParams_GetMinCRLNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCRLSelParams_GetMinCRLNumber
+ (goodObject, &getMinCrlNumber, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setMinCrlNumber,
+ (PKIX_PL_Object *)getMinCrlNumber,
+ &result, NULL));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg = "unexpected Minimum CRL Number mismatch";
+ }
+
+ subTest("PKIX_ComCRLSelParams_SetMaxCRLNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ asciiCrlNumber99999,
+ PL_strlen(asciiCrlNumber99999),
+ &crlNumber99999String,
+ NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create
+ (crlNumber99999String, &setMaxCrlNumber, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetMaxCRLNumber
+ (goodObject, setMaxCrlNumber, NULL));
+
+ subTest("PKIX_ComCRLSelParams_GetMaxCRLNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCRLSelParams_GetMaxCRLNumber
+ (goodObject, &getMaxCrlNumber, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)setMaxCrlNumber,
+ (PKIX_PL_Object *)getMaxCrlNumber,
+ &result, NULL));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg = "unexpected Maximum CRL Number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setMaxCrlNumber);
+ PKIX_TEST_DECREF_AC(getMaxCrlNumber);
+ PKIX_TEST_DECREF_AC(setMinCrlNumber);
+ PKIX_TEST_DECREF_AC(getMinCrlNumber);
+ PKIX_TEST_DECREF_AC(crlNumber1String);
+ PKIX_TEST_DECREF_AC(crlNumber99999String);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testDuplicate(PKIX_ComCRLSelParams *goodObject){
+
+ PKIX_ComCRLSelParams *dupObject = NULL;
+ PKIX_Boolean result = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams_Duplicate");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)goodObject,
+ (PKIX_PL_Object **)&dupObject,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)goodObject,
+ (PKIX_PL_Object *)dupObject,
+ &result, plContext));
+
+ if (result != PKIX_TRUE) {
+ pkixTestErrorMsg =
+ "unexpected Duplicate ComCRLSelParams mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dupObject);
+ PKIX_TEST_RETURN();
+}
+
+static
+void printUsage(char *pName){
+ printf("\nUSAGE: %s \n\n", pName);
+}
+
+/* Functional tests for ComCRLSelParams public functions */
+
+int test_comcrlselparams(int argc, char *argv[]){
+
+ char *dataCentralDir = NULL;
+ char *goodInput = "yassir2yassir";
+ PKIX_ComCRLSelParams *goodObject = NULL;
+ PKIX_ComCRLSelParams *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("ComCRLSelParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2){
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dataCentralDir = argv[j+1];
+
+ subTest("PKIX_ComCRLSelParams_Create");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create
+ (&goodObject,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create
+ (&diffObject,
+ plContext));
+
+ testIssuer(goodObject);
+
+ testCertificateChecking(dataCentralDir, goodInput, goodObject);
+
+ testDateAndTime(goodObject);
+
+ testMaxMinCRLNumbers(goodObject);
+
+ testDuplicate(goodObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodObject,
+ goodObject,
+ diffObject,
+ NULL,
+ ComCRLSelParams,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodObject);
+ PKIX_TEST_DECREF_AC(diffObject);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ComCRLSelParams");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c b/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c
new file mode 100644
index 0000000..d614e11
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c
@@ -0,0 +1,173 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_crlselector.c
+ *
+ * Test CRLSelector Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testGetMatchCallback(PKIX_CRLSelector *goodObject)
+{
+ PKIX_CRLSelector_MatchCallback mCallback = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("testGetMatchCallback");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_GetMatchCallback
+ (goodObject, &mCallback, plContext));
+
+ if (mCallback == NULL) {
+ pkixTestErrorMsg = "MatchCallback is NULL";
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+}
+
+static
+void testGetCRLSelectorContext(PKIX_CRLSelector *goodObject)
+{
+ PKIX_PL_Object *context = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("testGetCRLSelectorContext");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_GetCRLSelectorContext
+ (goodObject, (void *)&context, plContext));
+
+ if (context == NULL) {
+ pkixTestErrorMsg = "CRLSelectorContext is NULL";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(context);
+ PKIX_TEST_RETURN();
+}
+
+static
+void testCommonCRLSelectorParams(PKIX_CRLSelector *goodObject){
+ PKIX_ComCRLSelParams *setParams = NULL;
+ PKIX_ComCRLSelParams *getParams = NULL;
+ PKIX_PL_Date *setDate = NULL;
+ char *asciiDate = "040329134847Z";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create
+ (&setParams,
+ plContext));
+
+ subTest("PKIX_ComCRLSelParams_Date Create");
+
+ setDate = createDate(asciiDate, plContext);
+
+ subTest("PKIX_ComCRLSelParams_SetDateAndTime");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetDateAndTime
+ (setParams, setDate, plContext));
+
+ subTest("PKIX_CRLSelector_SetCommonCRLSelectorParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_SetCommonCRLSelectorParams(
+ goodObject, setParams, plContext));
+
+ subTest("PKIX_CRLSelector_GetCommonCRLSelectorParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_GetCommonCRLSelectorParams(
+ goodObject, &getParams, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)setParams,
+ (PKIX_PL_Object *)getParams,
+ PKIX_TRUE,
+ plContext);
+
+ testHashcodeHelper((PKIX_PL_Object *)setParams,
+ (PKIX_PL_Object *)getParams,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setDate);
+ PKIX_TEST_DECREF_AC(setParams);
+ PKIX_TEST_DECREF_AC(getParams);
+
+ PKIX_TEST_RETURN();
+}
+
+/* Functional tests for CRLSelector public functions */
+
+int test_crlselector(int argc, char *argv[]){
+
+ PKIX_PL_Date *context = NULL;
+ PKIX_CRLSelector *goodObject = NULL;
+ PKIX_CRLSelector *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *asciiDate = "040329134847Z";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CRLSelector");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ context = createDate(asciiDate, plContext);
+
+ subTest("PKIX_CRLSelector_Create");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create
+ (NULL,
+ (PKIX_PL_Object *)context,
+ &goodObject,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create
+ (NULL,
+ (PKIX_PL_Object *)context,
+ &diffObject,
+ plContext));
+
+ testGetMatchCallback(goodObject);
+
+ testGetCRLSelectorContext(goodObject);
+
+ testCommonCRLSelectorParams(goodObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodObject,
+ goodObject,
+ diffObject,
+ NULL,
+ CRLSelector,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodObject);
+ PKIX_TEST_DECREF_AC(diffObject);
+ PKIX_TEST_DECREF_AC(context);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CRLSelector");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/manifest.mn b/nss/cmd/libpkix/pkix/manifest.mn
new file mode 100755
index 0000000..895bf52
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/manifest.mn
@@ -0,0 +1,11 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+PKIX_DEPTH = ..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+DIRS = certsel checker crlsel params results store top util \
+ $(NULL)
diff --git a/nss/cmd/libpkix/pkix/params/Makefile b/nss/cmd/libpkix/pkix/params/Makefile
new file mode 100755
index 0000000..09ca5f1
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/params/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/nss/cmd/libpkix/pkix/params/manifest.mn b/nss/cmd/libpkix/pkix/params/manifest.mn
new file mode 100755
index 0000000..a2e7e67
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/params/manifest.mn
@@ -0,0 +1,23 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_procparams.c \
+ test_trustanchor.c \
+ test_valparams.c \
+ test_resourcelimits.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolparams
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/nss/cmd/libpkix/pkix/params/test_procparams.c b/nss/cmd/libpkix/pkix/params/test_procparams.c
new file mode 100644
index 0000000..19cf7f9
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/params/test_procparams.c
@@ -0,0 +1,519 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_procparams.c
+ *
+ * Test ProcessingParams Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ProcessingParams_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+}
+
+static
+void testGetAnchors(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_ProcessingParams *equalObject){
+
+ PKIX_List *goodAnchors = NULL;
+ PKIX_List *equalAnchors = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_GetTrustAnchors");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetTrustAnchors
+ (goodObject, &goodAnchors, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetTrustAnchors
+ (equalObject, &equalAnchors, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)goodAnchors,
+ (PKIX_PL_Object *)equalAnchors,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodAnchors);
+ PKIX_TEST_DECREF_AC(equalAnchors);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testGetSetDate(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_ProcessingParams *equalObject){
+
+ PKIX_PL_Date *setDate = NULL;
+ PKIX_PL_Date *getDate = NULL;
+ char *asciiDate = "040329134847Z";
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetDate");
+
+ setDate = createDate(asciiDate, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ProcessingParams_SetDate(goodObject, setDate, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ProcessingParams_GetDate
+ (goodObject, &getDate, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)setDate,
+ (PKIX_PL_Object *)getDate,
+ PKIX_TRUE,
+ plContext);
+
+ /* we want to make sure that goodObject and equalObject are "equal" */
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ProcessingParams_SetDate
+ (equalObject, setDate, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setDate);
+ PKIX_TEST_DECREF_AC(getDate);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+PKIX_Error *userChecker1cb(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresolvedCriticalExtensions, /* list of PKIX_PL_OID */
+ void **pNBIOContext,
+ void *plContext)
+{
+ return(NULL);
+}
+
+static
+void testGetSetCertChainCheckers(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_ProcessingParams *equalObject){
+
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_List *setCheckersList = NULL;
+ PKIX_List *getCheckersList = NULL;
+ PKIX_PL_Date *date = NULL;
+ char *asciiDate = "040329134847Z";
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetCertChainCheckers");
+
+ date = createDate(asciiDate, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_Create
+ (userChecker1cb,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *) date,
+ &checker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create
+ (&setCheckersList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setCheckersList, (PKIX_PL_Object *) checker, plContext));
+ PKIX_TEST_DECREF_BC(checker);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertChainCheckers
+ (goodObject, setCheckersList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_Create
+ (userChecker1cb,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ NULL,
+ (PKIX_PL_Object *) date,
+ &checker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertChainChecker
+ (goodObject, checker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetCertChainCheckers
+ (goodObject, &getCheckersList, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setCheckersList);
+ PKIX_TEST_DECREF_AC(getCheckersList);
+ PKIX_TEST_DECREF_AC(date);
+ PKIX_TEST_DECREF_BC(checker);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+PKIX_Error *userChecker2cb(
+ PKIX_RevocationChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_UInt32 *pResult,
+ void *plContext)
+{
+ return(NULL);
+}
+
+static
+void testGetSetRevocationCheckers(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_ProcessingParams *equalObject){
+
+ PKIX_RevocationChecker *checker = NULL;
+ PKIX_List *setCheckersList = NULL;
+ PKIX_List *getCheckersList = NULL;
+ PKIX_PL_Date *date = NULL;
+ char *asciiDate = "040329134847Z";
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetRevocationCheckers");
+
+ date = createDate(asciiDate, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_RevocationChecker_Create
+ (userChecker2cb,
+ (PKIX_PL_Object *) date,
+ &checker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create
+ (&setCheckersList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setCheckersList,
+ (PKIX_PL_Object *) checker,
+ plContext));
+ PKIX_TEST_DECREF_BC(checker);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers
+ (goodObject, setCheckersList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_RevocationChecker_Create
+ (userChecker2cb,
+ (PKIX_PL_Object *) date,
+ &checker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddRevocationChecker
+ (goodObject, checker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetRevocationCheckers
+ (goodObject, &getCheckersList, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setCheckersList);
+ PKIX_TEST_DECREF_AC(getCheckersList);
+ PKIX_TEST_DECREF_AC(date);
+ PKIX_TEST_DECREF_BC(checker);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testGetSetResourceLimits(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_ProcessingParams *equalObject)
+
+{
+ PKIX_ResourceLimits *resourceLimits1 = NULL;
+ PKIX_ResourceLimits *resourceLimits2 = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetResourceLimits");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create
+ (&resourceLimits1, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create
+ (&resourceLimits2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout
+ (resourceLimits1, 3, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth
+ (resourceLimits1, 3, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime
+ (resourceLimits1, 2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetResourceLimits
+ (goodObject, resourceLimits1, plContext));
+
+ PKIX_TEST_DECREF_BC(resourceLimits2);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetResourceLimits
+ (goodObject, &resourceLimits2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetResourceLimits
+ (equalObject, resourceLimits2, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(resourceLimits1);
+ PKIX_TEST_DECREF_AC(resourceLimits2);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testGetSetConstraints(PKIX_ProcessingParams *goodObject){
+
+ PKIX_CertSelector *setConstraints = NULL;
+ PKIX_CertSelector *getConstraints = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetTargetCertConstraints");
+
+ /*
+ * After createConstraints is implemented
+ * setConstraints = createConstraints();
+ */
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ProcessingParams_SetTargetCertConstraints
+ (goodObject, setConstraints, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ProcessingParams_GetTargetCertConstraints
+ (goodObject, &getConstraints, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)setConstraints,
+ (PKIX_PL_Object *)getConstraints,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(setConstraints);
+ PKIX_TEST_DECREF_AC(getConstraints);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testGetSetInitialPolicies(
+ PKIX_ProcessingParams *goodObject,
+ char *asciiPolicyOID)
+{
+ PKIX_PL_OID *policyOID = NULL;
+ PKIX_List* setPolicyList = NULL;
+ PKIX_List* getPolicyList = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetInitialPolicies");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (asciiPolicyOID, &policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&setPolicyList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (setPolicyList, (PKIX_PL_Object *)policyOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_SetImmutable(setPolicyList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetInitialPolicies
+ (goodObject, setPolicyList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_GetInitialPolicies
+ (goodObject, &getPolicyList, plContext));
+
+ testEqualsHelper
+ ((PKIX_PL_Object *)setPolicyList,
+ (PKIX_PL_Object *)getPolicyList,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(policyOID);
+ PKIX_TEST_DECREF_AC(setPolicyList);
+ PKIX_TEST_DECREF_AC(getPolicyList);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testGetSetPolicyQualifiersRejected(
+ PKIX_ProcessingParams *goodObject,
+ PKIX_Boolean rejected)
+{
+ PKIX_Boolean getRejected = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ProcessingParams_Get/SetPolicyQualifiersRejected");
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ProcessingParams_SetPolicyQualifiersRejected
+ (goodObject, rejected, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ProcessingParams_GetPolicyQualifiersRejected
+ (goodObject, &getRejected, plContext));
+
+ if (rejected != getRejected) {
+ testError
+ ("GetPolicyQualifiersRejected returned unexpected value");
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void printUsage(char *pName){
+ printf("\nUSAGE: %s \n\n", pName);
+}
+
+int test_procparams(int argc, char *argv[]) {
+
+ PKIX_ProcessingParams *goodObject = NULL;
+ PKIX_ProcessingParams *equalObject = NULL;
+ PKIX_ProcessingParams *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *dataCentralDir = NULL;
+ PKIX_UInt32 j = 0;
+
+ char *oidAnyPolicy = PKIX_CERTIFICATEPOLICIES_ANYPOLICY_OID;
+ char *oidNist1Policy = "2.16.840.1.101.3.2.1.48.2";
+
+ char *goodInput = "yassir2yassir";
+ char *diffInput = "yassir2bcn";
+
+ char *expectedAscii =
+ "[\n"
+ "\tTrust Anchors: \n"
+ "\t********BEGIN LIST OF TRUST ANCHORS********\n"
+ "\t\t"
+ "([\n"
+ "\tTrusted CA Name: "
+ "CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ ", [\n"
+ "\tTrusted CA Name: OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ ")\n"
+ "\t********END LIST OF TRUST ANCHORS********\n"
+ "\tDate: \t\tMon Mar 29 08:48:47 2004\n"
+ "\tTarget Constraints: (null)\n"
+ "\tInitial Policies: (2.5.29.32.0)\n"
+ "\tQualifiers Rejected: FALSE\n"
+ "\tCert Stores: (EMPTY)\n"
+ "\tResource Limits: [\n"
+ "\tMaxTime: 2\n"
+ "\tMaxFanout: 3\n"
+ "\tMaxDepth: 3\n"
+ "]\n\n"
+ "\tCRL Checking Enabled: 0\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("ProcessingParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2){
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dataCentralDir = argv[j+1];
+
+ subTest("PKIX_ProcessingParams_Create");
+ goodObject = createProcessingParams
+ (dataCentralDir,
+ goodInput,
+ diffInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ plContext);
+
+ equalObject = createProcessingParams
+ (dataCentralDir,
+ goodInput,
+ diffInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ plContext);
+
+ diffObject = createProcessingParams
+ (dataCentralDir,
+ diffInput,
+ goodInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ plContext);
+
+ testGetAnchors(goodObject, equalObject);
+ testGetSetDate(goodObject, equalObject);
+ testGetSetCertChainCheckers(goodObject, equalObject);
+ testGetSetRevocationCheckers(goodObject, equalObject);
+ testGetSetResourceLimits(goodObject, equalObject);
+
+ /*
+ * XXX testGetSetConstraints(goodObject);
+ */
+
+ testGetSetInitialPolicies(goodObject, oidAnyPolicy);
+ testGetSetInitialPolicies(equalObject, oidAnyPolicy);
+ testGetSetInitialPolicies(diffObject, oidNist1Policy);
+ testGetSetPolicyQualifiersRejected(goodObject, PKIX_FALSE);
+ testGetSetPolicyQualifiersRejected(equalObject, PKIX_FALSE);
+ testGetSetPolicyQualifiersRejected(diffObject, PKIX_TRUE);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodObject,
+ equalObject,
+ diffObject,
+ NULL, /* expectedAscii, */
+ ProcessingParams,
+ PKIX_FALSE);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ProcessingParams");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/params/test_resourcelimits.c b/nss/cmd/libpkix/pkix/params/test_resourcelimits.c
new file mode 100644
index 0000000..54cdb32
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/params/test_resourcelimits.c
@@ -0,0 +1,114 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_resourcelimits.c
+ *
+ * Test ResourceLimits Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ResourceLimits_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+}
+
+int test_resourcelimits(int argc, char *argv[]) {
+
+ PKIX_ResourceLimits *goodObject = NULL;
+ PKIX_ResourceLimits *equalObject = NULL;
+ PKIX_ResourceLimits *diffObject = NULL;
+ PKIX_UInt32 maxTime = 0;
+ PKIX_UInt32 maxFanout = 0;
+ PKIX_UInt32 maxDepth = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *expectedAscii =
+ "[\n"
+ "\tMaxTime: 10\n"
+ "\tMaxFanout: 5\n"
+ "\tMaxDepth: 5\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("ResourceLimits");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_ResourceLimits_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create
+ (&goodObject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create
+ (&diffObject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create
+ (&equalObject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime
+ (goodObject, 10, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_GetMaxTime
+ (goodObject, &maxTime, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime
+ (equalObject, maxTime, plContext));
+ maxTime++;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime
+ (diffObject, maxTime, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout
+ (goodObject, 5, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_GetMaxFanout
+ (goodObject, &maxFanout, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout
+ (equalObject, maxFanout, plContext));
+ maxFanout++;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout
+ (diffObject, maxFanout, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth
+ (goodObject, 5, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_GetMaxDepth
+ (goodObject, &maxDepth, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth
+ (equalObject, maxDepth, plContext));
+ maxDepth++;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth
+ (diffObject, maxDepth, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ ResourceLimits,
+ PKIX_FALSE);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ResourceLimits");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/params/test_trustanchor.c b/nss/cmd/libpkix/pkix/params/test_trustanchor.c
new file mode 100644
index 0000000..b09ecb5
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/params/test_trustanchor.c
@@ -0,0 +1,262 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_trustanchor.c
+ *
+ * Test TrustAnchor Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static
+void createTrustAnchors(
+ char *dirName,
+ char *goodInput,
+ PKIX_TrustAnchor **goodObject,
+ PKIX_TrustAnchor **equalObject,
+ PKIX_TrustAnchor **diffObject)
+{
+ subTest("PKIX_TrustAnchor_CreateWithNameKeyPair ");
+ *goodObject = createTrustAnchor
+ (dirName, goodInput, PKIX_FALSE, plContext);
+
+ subTest("PKIX_TrustAnchor_CreateWithNameKeyPair ");
+ *equalObject = createTrustAnchor
+ (dirName, goodInput, PKIX_FALSE, plContext);
+
+ subTest("PKIX_TrustAnchor_CreateWithCert ");
+ *diffObject = createTrustAnchor
+ (dirName, goodInput, PKIX_TRUE, plContext);
+}
+
+static
+void testGetCAName(
+ PKIX_PL_Cert *diffCert,
+ PKIX_TrustAnchor *equalObject){
+
+ PKIX_PL_X500Name *diffCAName = NULL;
+ PKIX_PL_X500Name *equalCAName = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_TrustAnchor_GetCAName");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject
+ (diffCert, &diffCAName, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_GetCAName
+ (equalObject, &equalCAName, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)diffCAName,
+ (PKIX_PL_Object *)equalCAName,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(diffCAName);
+ PKIX_TEST_DECREF_AC(equalCAName);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testGetCAPublicKey(
+ PKIX_PL_Cert *diffCert,
+ PKIX_TrustAnchor *equalObject){
+
+ PKIX_PL_PublicKey *diffPubKey = NULL;
+ PKIX_PL_PublicKey *equalPubKey = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_TrustAnchor_GetCAPublicKey");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey
+ (diffCert, &diffPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_GetCAPublicKey
+ (equalObject, &equalPubKey, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)diffPubKey,
+ (PKIX_PL_Object *)equalPubKey,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(diffPubKey);
+ PKIX_TEST_DECREF_AC(equalPubKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testGetNameConstraints(char *dirName)
+{
+ PKIX_TrustAnchor *goodObject = NULL;
+ PKIX_TrustAnchor *equalObject = NULL;
+ PKIX_TrustAnchor *diffObject = NULL;
+ PKIX_PL_Cert *diffCert;
+ PKIX_PL_CertNameConstraints *diffNC = NULL;
+ PKIX_PL_CertNameConstraints *equalNC = NULL;
+ char *goodInput = "nameConstraintsDN5CACert.crt";
+ char *expectedAscii =
+ "[\n"
+ "\tTrusted CA Name: CN=nameConstraints DN5 CA,"
+ "O=Test Certificates,C=US\n"
+ "\tTrusted CA PublicKey: PKCS #1 RSA Encryption\n"
+ "\tInitial Name Constraints:[\n"
+ "\t\tPermitted Name: (OU=permittedSubtree1,"
+ "O=Test Certificates,C=US)\n"
+ "\t\tExcluded Name: (OU=excludedSubtree1,"
+ "OU=permittedSubtree1,O=Test Certificates,C=US)\n"
+ "\t]\n"
+ "\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Create TrustAnchors and compare");
+
+ createTrustAnchors
+ (dirName, goodInput, &goodObject, &equalObject, &diffObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ TrustAnchor,
+ PKIX_TRUE);
+
+ subTest("PKIX_TrustAnchor_GetTrustedCert");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_GetTrustedCert
+ (diffObject, &diffCert, plContext));
+
+ subTest("PKIX_PL_Cert_GetNameConstraints");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints
+ (diffCert, &diffNC, plContext));
+
+ subTest("PKIX_TrustAnchor_GetNameConstraints");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_GetNameConstraints
+ (equalObject, &equalNC, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)diffNC,
+ (PKIX_PL_Object *)equalNC,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(diffNC);
+ PKIX_TEST_DECREF_AC(equalNC);
+ PKIX_TEST_DECREF_BC(diffCert);
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_TrustAnchor_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+}
+
+static
+void printUsage(void) {
+ (void) printf("\nUSAGE:\ttest_trustanchor \n\n");
+}
+
+int test_trustanchor(int argc, char *argv[]) {
+
+ PKIX_TrustAnchor *goodObject = NULL;
+ PKIX_TrustAnchor *equalObject = NULL;
+ PKIX_TrustAnchor *diffObject = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *goodInput = "yassir2yassir";
+ char *expectedAscii =
+ "[\n"
+ "\tTrusted CA Name: "
+ "CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n";
+ char *dirName = NULL;
+ char *dataCentralDir = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("TrustAnchor");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 3) {
+ printUsage();
+ return (0);
+ }
+
+ dirName = argv[j+1];
+ dataCentralDir = argv[j+2];
+
+ createTrustAnchors
+ (dataCentralDir,
+ goodInput,
+ &goodObject,
+ &equalObject,
+ &diffObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ TrustAnchor,
+ PKIX_TRUE);
+
+ subTest("PKIX_TrustAnchor_GetTrustedCert");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_GetTrustedCert
+ (diffObject, &diffCert, plContext));
+
+ testGetCAName(diffCert, equalObject);
+ testGetCAPublicKey(diffCert, equalObject);
+
+ testGetNameConstraints(dirName);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(diffCert);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("TrustAnchor");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/params/test_valparams.c b/nss/cmd/libpkix/pkix/params/test_valparams.c
new file mode 100644
index 0000000..454d8ae
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/params/test_valparams.c
@@ -0,0 +1,268 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_valparams.c
+ *
+ * Test ValidateParams Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ValidateParams_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+}
+
+static
+void testGetProcParams(
+ PKIX_ValidateParams *goodObject,
+ PKIX_ValidateParams *equalObject){
+
+ PKIX_ProcessingParams *goodProcParams = NULL;
+ PKIX_ProcessingParams *equalProcParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ValidateParams_GetProcessingParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams
+ (goodObject, &goodProcParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams
+ (equalObject, &equalProcParams, plContext));
+
+ testEqualsHelper
+ ((PKIX_PL_Object *)goodProcParams,
+ (PKIX_PL_Object *)equalProcParams,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodProcParams);
+ PKIX_TEST_DECREF_AC(equalProcParams);
+
+ PKIX_TEST_RETURN();
+}
+
+
+static
+void testGetCertChain(
+ PKIX_ValidateParams *goodObject,
+ PKIX_ValidateParams *equalObject){
+
+ PKIX_List *goodChain = NULL;
+ PKIX_List *equalChain = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ValidateParams_GetCertChain");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetCertChain
+ (goodObject, &goodChain, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetCertChain
+ (equalObject, &equalChain, plContext));
+
+ testEqualsHelper
+ ((PKIX_PL_Object *)goodChain,
+ (PKIX_PL_Object *)equalChain,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodChain);
+ PKIX_TEST_DECREF_AC(equalChain);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void printUsage(char *pName){
+ printf("\nUSAGE: %s \n\n", pName);
+}
+
+int test_valparams(int argc, char *argv[]) {
+
+ PKIX_ValidateParams *goodObject = NULL;
+ PKIX_ValidateParams *equalObject = NULL;
+ PKIX_ValidateParams *diffObject = NULL;
+ PKIX_List *chain = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *dirName = NULL;
+
+ char *goodInput = "yassir2yassir";
+ char *diffInput = "yassir2bcn";
+
+ char *expectedAscii =
+ "[\n"
+ "\tProcessing Params: \n"
+ "\t********BEGIN PROCESSING PARAMS********\n"
+ "\t\t"
+ "[\n"
+ "\tTrust Anchors: \n"
+ "\t********BEGIN LIST OF TRUST ANCHORS********\n"
+ "\t\t"
+"([\n"
+ "\tTrusted CA Name: "
+ "CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ ", [\n"
+ "\tTrusted CA Name: OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ ")\n"
+ "\t********END LIST OF TRUST ANCHORS********\n"
+ "\tDate: \t\t(null)\n"
+ "\tTarget Constraints: (null)\n"
+ "\tInitial Policies: (null)\n"
+ "\tQualifiers Rejected: FALSE\n"
+ "\tCert Stores: (EMPTY)\n"
+ "\tCRL Checking Enabled: 0\n"
+ "]\n"
+ "\n"
+ "\t********END PROCESSING PARAMS********\n"
+ "\tChain: \t\t"
+ "([\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 37bc66ec\n"
+ "\tIssuer: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tSubject: OU=bcn,OU=east,O=sun,C=us\n"
+ "\tValidity: [From: Thu Aug 19 16:19:56 1999\n"
+ "\t To: Fri Aug 18 16:19:56 2000]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(0)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ", [\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 37bc65af\n"
+ "\tIssuer: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tSubject: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tValidity: [From: Thu Aug 19 16:14:39 1999\n"
+ "\t To: Fri Aug 18 16:14:39 2000]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(0)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ")\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("ValidateParams");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2){
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dirName = argv[j+1];
+
+ subTest("PKIX_ValidateParams_Create");
+ chain = createCertChain(dirName, diffInput, goodInput, plContext);
+ goodObject = createValidateParams
+ (dirName,
+ goodInput,
+ diffInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+ equalObject = createValidateParams
+ (dirName,
+ goodInput,
+ diffInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+ diffObject = createValidateParams
+ (dirName,
+ diffInput,
+ goodInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ testGetProcParams(goodObject, equalObject);
+ testGetCertChain(goodObject, equalObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodObject,
+ equalObject,
+ diffObject,
+ NULL, /* expectedAscii, */
+ ValidateParams,
+ PKIX_FALSE);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(chain);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ValidateParams");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/results/Makefile b/nss/cmd/libpkix/pkix/results/Makefile
new file mode 100755
index 0000000..09ca5f1
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/results/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/nss/cmd/libpkix/pkix/results/manifest.mn b/nss/cmd/libpkix/pkix/results/manifest.mn
new file mode 100755
index 0000000..5a8b936
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/results/manifest.mn
@@ -0,0 +1,23 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_buildresult.c \
+ test_policynode.c \
+ test_verifynode.c \
+ test_valresult.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolresults
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/nss/cmd/libpkix/pkix/results/test_buildresult.c b/nss/cmd/libpkix/pkix/results/test_buildresult.c
new file mode 100644
index 0000000..983af29
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/results/test_buildresult.c
@@ -0,0 +1,218 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_buildresult.c
+ *
+ * Test BuildResult Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_BuildResult_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+}
+
+static
+void testGetValidateResult(
+ PKIX_BuildResult *goodObject,
+ PKIX_BuildResult *equalObject){
+
+ PKIX_ValidateResult *goodValResult = NULL;
+ PKIX_ValidateResult *equalValResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_BuildResult_GetValidateResult");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetValidateResult
+ (goodObject, &goodValResult, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetValidateResult
+ (equalObject, &equalValResult, NULL));
+
+ testEqualsHelper
+ ((PKIX_PL_Object *)goodValResult,
+ (PKIX_PL_Object *)equalValResult,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodValResult);
+ PKIX_TEST_DECREF_AC(equalValResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testGetCertChain(
+ PKIX_BuildResult *goodObject,
+ PKIX_BuildResult *equalObject){
+
+ PKIX_List *goodChain = NULL;
+ PKIX_List *equalChain = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_BuildResult_GetCertChain");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain
+ (goodObject, &goodChain, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain
+ (equalObject, &equalChain, NULL));
+
+ testEqualsHelper
+ ((PKIX_PL_Object *)goodChain,
+ (PKIX_PL_Object *)equalChain,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodChain);
+ PKIX_TEST_DECREF_AC(equalChain);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void printUsage(char *pName){
+ printf("\nUSAGE: %s \n\n", pName);
+}
+
+int test_buildresult(int argc, char *argv[]) {
+
+ PKIX_BuildResult *goodObject = NULL;
+ PKIX_BuildResult *equalObject = NULL;
+ PKIX_BuildResult *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *dirName = NULL;
+ PKIX_UInt32 j = 0;
+
+ char *goodInput = "yassir2yassir";
+ char *diffInput = "yassir2bcn";
+
+ char *expectedAscii =
+ "[\n"
+ "\tValidateResult: \t\t"
+ "[\n"
+ "\tTrustAnchor: \t\t"
+ "[\n"
+ "\tTrusted CA Name: "
+ "CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ "\tPubKey: \t\t"
+ "ANSI X9.57 DSA Signature\n"
+ "\tPolicyTree: \t\t(null)\n"
+ "]\n"
+ "\tCertChain: \t\t("
+ "[\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 37bc65af\n"
+ "\tIssuer: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tSubject: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tValidity: [From: Thu Aug 19 16:14:39 1999\n"
+ "\t To: Fri Aug 18 16:14:39 2000]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(0)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ", [\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 37bc66ec\n"
+ "\tIssuer: CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tSubject: OU=bcn,OU=east,O=sun,C=us\n"
+ "\tValidity: [From: Thu Aug 19 16:19:56 1999\n"
+ "\t To: Fri Aug 18 16:19:56 2000]\n"
+ "\tSubjectAltNames: (null)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (2.5.29.15, 2.5.29.19)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: CA(0)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ")\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("BuildResult");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2){
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dirName = argv[j+1];
+
+ subTest("pkix_BuildResult_Create");
+
+ goodObject = createBuildResult
+ (dirName, goodInput, diffInput, goodInput, diffInput, plContext);
+ equalObject = createBuildResult
+ (dirName, goodInput, diffInput, goodInput, diffInput, plContext);
+ diffObject = createBuildResult
+ (dirName, diffInput, goodInput, diffInput, goodInput, plContext);
+
+ testGetValidateResult(goodObject, equalObject);
+ testGetCertChain(goodObject, equalObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodObject,
+ equalObject,
+ diffObject,
+ NULL, /* expectedAscii, */
+ BuildResult,
+ PKIX_FALSE);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("BuildResult");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/results/test_policynode.c b/nss/cmd/libpkix/pkix/results/test_policynode.c
new file mode 100644
index 0000000..6ec5a58
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/results/test_policynode.c
@@ -0,0 +1,679 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_policynode.c
+ *
+ * Test PolicyNode Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+test_GetChildren(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode)
+{
+
+/*
+ * Caution: be careful where you insert this test. PKIX_PolicyNode_GetChildren
+ * is required by the API to return an immutable List, and it does it by setting
+ * the List immutable. We don't make a copy because the assumption is that
+ * certificate and policy processing have been completed before the user gets at
+ * the public API. So subsequent tests of functions that modify the policy tree,
+ * such as Prune, will fail if called after the execution of this test.
+ */
+
+ PKIX_Boolean isImmutable = PKIX_FALSE;
+ PKIX_List *goodList = NULL;
+ PKIX_List *equalList = NULL;
+ PKIX_List *diffList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetChildren");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetChildren
+ (goodNode, &goodList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetChildren
+ (equalNode, &equalList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetChildren
+ (diffNode, &diffList, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodList, equalList, diffList, NULL, List, NULL);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsImmutable
+ (goodList, &isImmutable, plContext));
+
+ if (isImmutable != PKIX_TRUE) {
+ testError("PKIX_PolicyNode_GetChildren returned a mutable List");
+ }
+
+cleanup:
+ PKIX_TEST_DECREF_AC(goodList);
+ PKIX_TEST_DECREF_AC(equalList);
+ PKIX_TEST_DECREF_AC(diffList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_GetParent(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode,
+ char *expectedAscii)
+{
+ PKIX_PolicyNode *goodParent = NULL;
+ PKIX_PolicyNode *equalParent = NULL;
+ PKIX_PolicyNode *diffParent = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetParent");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetParent
+ (goodNode, &goodParent, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetParent
+ (equalNode, &equalParent, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetParent
+ (diffNode, &diffParent, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodParent,
+ equalParent,
+ diffParent,
+ expectedAscii,
+ CertPolicyNode,
+ NULL);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(goodParent);
+ PKIX_TEST_DECREF_AC(equalParent);
+ PKIX_TEST_DECREF_AC(diffParent);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This test is the same as testDuplicateHelper, except that it
+ * produces a more useful "Actual value" and "Expected value"
+ * in the case of an unexpected mismatch.
+ */
+static void
+test_DuplicateHelper(PKIX_PolicyNode *object, void *plContext)
+{
+ PKIX_PolicyNode *newObject = NULL;
+ PKIX_Boolean cmpResult;
+ PKIX_PL_String *original = NULL;
+ PKIX_PL_String *copy = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("testing pkix_PolicyNode_Duplicate");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)object,
+ (PKIX_PL_Object **)&newObject,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)object,
+ (PKIX_PL_Object *)newObject,
+ &cmpResult,
+ plContext));
+
+ if (!cmpResult){
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)object, &original, plContext));
+ testError("unexpected mismatch");
+ (void) printf
+ ("original value:\t%s\n", original->escAsciiString);
+
+ if (newObject) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)newObject, ©, plContext));
+ (void) printf
+ ("copy value:\t%s\n", copy->escAsciiString);
+ } else {
+ (void) printf("copy value:\t(NULL)\n");
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(newObject);
+ PKIX_TEST_DECREF_AC(original);
+ PKIX_TEST_DECREF_AC(copy);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_GetValidPolicy(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode,
+ char *expectedAscii)
+{
+ PKIX_PL_OID *goodPolicy = NULL;
+ PKIX_PL_OID *equalPolicy = NULL;
+ PKIX_PL_OID *diffPolicy = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetValidPolicy");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetValidPolicy
+ (goodNode, &goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetValidPolicy
+ (equalNode, &equalPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetValidPolicy
+ (diffNode, &diffPolicy, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodPolicy, equalPolicy, diffPolicy, expectedAscii, OID, NULL);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+
+
+ PKIX_TEST_RETURN();
+}
+
+static void test_GetPolicyQualifiers(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode,
+ char *expectedAscii)
+{
+ PKIX_Boolean isImmutable = PKIX_FALSE;
+ PKIX_List *goodList = NULL;
+ PKIX_List *equalList = NULL;
+ PKIX_List *diffList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetPolicyQualifiers");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetPolicyQualifiers
+ (goodNode, &goodList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetPolicyQualifiers
+ (equalNode, &equalList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetPolicyQualifiers
+ (diffNode, &diffList, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodList, equalList, diffList, expectedAscii, List, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsImmutable
+ (goodList, &isImmutable, plContext));
+
+ if (isImmutable != PKIX_TRUE) {
+ testError
+ ("PKIX_PolicyNode_GetPolicyQualifiers returned a mutable List");
+ }
+cleanup:
+ PKIX_TEST_DECREF_AC(goodList);
+ PKIX_TEST_DECREF_AC(equalList);
+ PKIX_TEST_DECREF_AC(diffList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void test_GetExpectedPolicies(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode,
+ char *expectedAscii)
+{
+ PKIX_Boolean isImmutable = PKIX_FALSE;
+ PKIX_List *goodList = NULL;
+ PKIX_List *equalList = NULL;
+ PKIX_List *diffList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetExpectedPolicies");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetExpectedPolicies
+ (goodNode, &goodList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetExpectedPolicies
+ (equalNode, &equalList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetExpectedPolicies
+ (diffNode, &diffList, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodList, equalList, diffList, expectedAscii, List, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsImmutable
+ (goodList, &isImmutable, plContext));
+
+ if (isImmutable != PKIX_TRUE) {
+ testError
+ ("PKIX_PolicyNode_GetExpectedPolicies returned a mutable List");
+ }
+cleanup:
+ PKIX_TEST_DECREF_AC(goodList);
+ PKIX_TEST_DECREF_AC(equalList);
+ PKIX_TEST_DECREF_AC(diffList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void test_IsCritical(
+ PKIX_PolicyNode *goodNode,
+ PKIX_PolicyNode *equalNode,
+ PKIX_PolicyNode *diffNode)
+{
+ PKIX_Boolean goodBool = PKIX_FALSE;
+ PKIX_Boolean equalBool = PKIX_FALSE;
+ PKIX_Boolean diffBool = PKIX_FALSE;
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_IsCritical");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_IsCritical
+ (goodNode, &goodBool, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_IsCritical
+ (equalNode, &equalBool, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_IsCritical
+ (diffNode, &diffBool, plContext));
+
+ if ((!goodBool) || (!equalBool) || (diffBool)) {
+ testError("IsCritical returned unexpected value");
+ }
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void test_GetDepth(
+ PKIX_PolicyNode *depth1Node,
+ PKIX_PolicyNode *depth2Node,
+ PKIX_PolicyNode *depth3Node)
+{
+ PKIX_UInt32 depth1 = 0;
+ PKIX_UInt32 depth2 = 0;
+ PKIX_UInt32 depth3 = 0;
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PolicyNode_GetDepth");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetDepth
+ (depth1Node, &depth1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetDepth
+ (depth2Node, &depth2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PolicyNode_GetDepth
+ (depth3Node, &depth3, plContext));
+
+ if ((depth1 != 1) || (depth2 != 2) || (depth3 != 3)) {
+ testError("GetDepth returned unexpected value");
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void printUsage(void) {
+ (void) printf("\nUSAGE:\ttest_policynode \n\n");
+}
+
+int test_policynode(int argc, char *argv[]) {
+
+ /*
+ * Create a tree with parent = anyPolicy,
+ * child1 with Nist1+Nist2, child2 with Nist1.
+ * Give each child another child, with policies Nist2
+ * and Nist1, respectively. Pruning with a depth of two
+ * should have no effect. Give one of the children
+ * another child. Then pruning with a depth of three
+ * should reduce the tree to a single strand, as child1
+ * and child3 are removed.
+ *
+ * parent (anyPolicy)
+ * / \
+ * child1(Nist1+Nist2) child2(Nist1)
+ * | |
+ * child3(Nist2) child4(Nist1)
+ * |
+ * child5(Nist1)
+ *
+ */
+ char *asciiAnyPolicy = "2.5.29.32.0";
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_CertPolicyInfo *nist1Policy = NULL;
+ PKIX_PL_CertPolicyInfo *nist2Policy = NULL;
+ PKIX_List *policyQualifierList = NULL;
+ PKIX_PL_OID *oidAnyPolicy = NULL;
+ PKIX_PL_OID *oidNist1Policy = NULL;
+ PKIX_PL_OID *oidNist2Policy = NULL;
+ PKIX_List *expectedAnyList = NULL;
+ PKIX_List *expectedNist1List = NULL;
+ PKIX_List *expectedNist2List = NULL;
+ PKIX_List *expectedNist1Nist2List = NULL;
+ PKIX_List *emptyList = NULL;
+ PKIX_PolicyNode *parentNode = NULL;
+ PKIX_PolicyNode *childNode1 = NULL;
+ PKIX_PolicyNode *childNode2 = NULL;
+ PKIX_PolicyNode *childNode3 = NULL;
+ PKIX_PolicyNode *childNode4 = NULL;
+ PKIX_PolicyNode *childNode5 = NULL;
+ PKIX_PL_String *parentString = NULL;
+ PKIX_Boolean pDelete = PKIX_FALSE;
+ char *expectedParentAscii =
+ "{2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30 5C "
+ "1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 65"
+ " 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D 2"
+ "0 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 69 "
+ "73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 66"
+ " 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20 6"
+ "F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1[(1.3"
+ ".6.1.5.5.7.2.2:[30 5C 1A 5A 71 31 3A 20 20 54 68 69 7"
+ "3 20 69 73 20 74 68 65 20 75 73 65 72 20 6E 6F 74 69 "
+ "63 65 20 66 72 6F 6D 20 71 75 61 6C 69 66 69 65 72 20"
+ " 31 2E 20 20 54 68 69 73 20 63 65 72 74 69 66 69 63 6"
+ "1 74 65 20 69 73 20 66 6F 72 20 74 65 73 74 20 70 75 "
+ "72 70 6F 73 65 73 20 6F 6E 6C 79])], 2.16.840.1.101.3"
+ ".2.1.48.2[(1.3.6.1.5.5.7.2.2:[30 5A 1A 58 71 32 3A 20"
+ " 20 54 68 69 73 20 69 73 20 74 68 65 20 75 73 65 72 2"
+ "0 6E 6F 74 69 63 65 20 66 72 6F 6D 20 71 75 61 6C 69 "
+ "66 69 65 72 20 32 2E 20 20 54 68 69 73 20 75 73 65 72"
+ " 20 6E 6F 74 69 63 65 20 73 68 6F 75 6C 64 20 6E 6F 7"
+ "4 20 62 65 20 64 69 73 70 6C 61 79 65 64])]),1}\n"
+ ". {2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30 5"
+ "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
+ "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
+ " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
+ "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
+ "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
+ " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.2),2}";
+ char *expectedValidAscii =
+ "2.16.840.1.101.3.2.1.48.2";
+ char *expectedQualifiersAscii =
+ /* "(1.3.6.1.5.5.7.2.2)"; */
+ "(1.3.6.1.5.5.7.2.2:[30 5C 1A 5A 71 31 3A 20 20 54 68 "
+ "69 73 20 69 73 20 74 68 65 20 75 73 65 72 20 6E 6F 74"
+ " 69 63 65 20 66 72 6F 6D 20 71 75 61 6C 69 66 69 65 7"
+ "2 20 31 2E 20 20 54 68 69 73 20 63 65 72 74 69 66 69 "
+ "63 61 74 65 20 69 73 20 66 6F 72 20 74 65 73 74 20 70"
+ " 75 72 70 6F 73 65 73 20 6F 6E 6C 79])";
+ char *expectedPoliciesAscii =
+ "(2.16.840.1.101.3.2.1.48.1)";
+ char *expectedTree =
+ "{2.5.29.32.0,{},Critical,(2.5.29.32.0),0}\n"
+ ". {2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30 5"
+ "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
+ "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
+ " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
+ "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
+ "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
+ " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1[(1"
+ ".3.6.1.5.5.7.2.2:[30 5C 1A 5A 71 31 3A 20 20 54 68 69"
+ " 73 20 69 73 20 74 68 65 20 75 73 65 72 20 6E 6F 74 6"
+ "9 63 65 20 66 72 6F 6D 20 71 75 61 6C 69 66 69 65 72 "
+ "20 31 2E 20 20 54 68 69 73 20 63 65 72 74 69 66 69 63"
+ " 61 74 65 20 69 73 20 66 6F 72 20 74 65 73 74 20 70 7"
+ "5 72 70 6F 73 65 73 20 6F 6E 6C 79])], 2.16.840.1.101"
+ ".3.2.1.48.2[(1.3.6.1.5.5.7.2.2:[30 5A 1A 58 71 32 3A "
+ "20 20 54 68 69 73 20 69 73 20 74 68 65 20 75 73 65 72"
+ " 20 6E 6F 74 69 63 65 20 66 72 6F 6D 20 71 75 61 6C 6"
+ "9 66 69 65 72 20 32 2E 20 20 54 68 69 73 20 75 73 65 "
+ "72 20 6E 6F 74 69 63 65 20 73 68 6F 75 6C 64 20 6E 6F"
+ " 74 20 62 65 20 64 69 73 70 6C 61 79 65 64])]"
+ "),1}\n"
+ ". . {2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30"
+ " 5C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 6"
+ "8 65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F "
+ "6D 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68"
+ " 69 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 2"
+ "0 66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 "
+ "20 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.2)"
+ ",2}\n"
+ ". {2.16.840.1.101.3.2.1.48.1,(1.3.6.1.5.5.7.2.2:[30 5"
+ "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
+ "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
+ " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
+ "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
+ "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
+ " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1),1}\n"
+ ". . {2.16.840.1.101.3.2.1.48.1,(EMPTY),Not Critical,"
+ "(2.16.840.1.101.3.2.1.48.1),2}\n"
+ ". . . {2.16.840.1.101.3.2.1.48.1,{},Critical,(2.16.84"
+ "0.1.101.3.2.1.48.1),3}";
+ char *expectedPrunedTree =
+ "{2.5.29.32.0,{},Critical,(2.5.29.32.0),0}\n"
+ ". {2.16.840.1.101.3.2.1.48.1,(1.3.6.1.5.5.7.2.2:[30 5"
+ "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
+ "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
+ " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
+ "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
+ "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
+ " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1),1}\n"
+ ". . {2.16.840.1.101.3.2.1.48.1,(EMPTY),Not Critical,"
+ "(2.16.840.1.101.3.2.1.48.1),2}\n"
+ ". . . {2.16.840.1.101.3.2.1.48.1,{},Critical,(2.16.84"
+ "0.1.101.3.2.1.48.1),3}";
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *dirName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 2) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("PolicyNode");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ dirName = argv[j+1];
+
+ subTest("Creating OID objects");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (asciiAnyPolicy, &oidAnyPolicy, plContext));
+
+ /* Read certificates to get real policies, qualifiers */
+
+ cert = createCert
+ (dirName, "UserNoticeQualifierTest16EE.crt", plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation
+ (cert, &expectedNist1Nist2List, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (expectedNist1Nist2List,
+ 0,
+ (PKIX_PL_Object **)&nist1Policy,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (expectedNist1Nist2List,
+ 1,
+ (PKIX_PL_Object **)&nist2Policy,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers
+ (nist1Policy, &policyQualifierList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId
+ (nist1Policy, &oidNist1Policy, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId
+ (nist2Policy, &oidNist2Policy, plContext));
+
+ subTest("Creating expectedPolicy List objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_Create(&expectedAnyList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_Create(&expectedNist1List, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_Create(&expectedNist2List, plContext));
+
+
+ subTest("Populating expectedPolicy List objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (expectedAnyList, (PKIX_PL_Object *)oidAnyPolicy, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (expectedNist1List,
+ (PKIX_PL_Object *)oidNist1Policy,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (expectedNist2List,
+ (PKIX_PL_Object *)oidNist2Policy,
+ plContext));
+
+ subTest("Creating PolicyNode objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&emptyList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
+ (oidAnyPolicy,
+ NULL,
+ PKIX_TRUE,
+ expectedAnyList,
+ &parentNode,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
+ (oidNist2Policy,
+ policyQualifierList,
+ PKIX_TRUE,
+ expectedNist1Nist2List,
+ &childNode1,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
+ (oidNist1Policy,
+ policyQualifierList,
+ PKIX_TRUE,
+ expectedNist1List,
+ &childNode2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
+ (oidNist2Policy,
+ policyQualifierList,
+ PKIX_TRUE,
+ expectedNist2List,
+ &childNode3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
+ (oidNist1Policy,
+ emptyList,
+ PKIX_FALSE,
+ expectedNist1List,
+ &childNode4,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
+ (oidNist1Policy,
+ NULL,
+ PKIX_TRUE,
+ expectedNist1List,
+ &childNode5,
+ plContext));
+
+ subTest("Creating the PolicyNode tree");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent
+ (parentNode, childNode1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent
+ (parentNode, childNode2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent
+ (childNode1, childNode3, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent
+ (childNode2, childNode4, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent
+ (childNode4, childNode5, plContext));
+
+ subTest("Displaying PolicyNode objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)parentNode, &parentString, plContext));
+ (void) printf("parentNode is\n\t%s\n", parentString->escAsciiString);
+
+ testToStringHelper
+ ((PKIX_PL_Object*)parentNode, expectedTree, plContext);
+
+ test_DuplicateHelper(parentNode, plContext);
+
+ test_GetParent(childNode3, childNode3, childNode4, expectedParentAscii);
+ test_GetValidPolicy
+ (childNode1, childNode3, parentNode, expectedValidAscii);
+ test_GetPolicyQualifiers
+ (childNode1, childNode3, childNode4, expectedQualifiersAscii);
+ test_GetExpectedPolicies
+ (childNode2, childNode4, childNode3, expectedPoliciesAscii);
+ test_IsCritical(childNode1, childNode2, childNode4);
+ test_GetDepth(childNode2, childNode4, childNode5);
+
+ subTest("pkix_PolicyNode_Prune");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Prune
+ (parentNode, 2, &pDelete, plContext));
+
+ testToStringHelper
+ ((PKIX_PL_Object*)parentNode, expectedTree, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Prune
+ (parentNode, 3, &pDelete, plContext));
+
+ testToStringHelper
+ ((PKIX_PL_Object*)parentNode, expectedPrunedTree, plContext);
+
+ test_GetChildren(parentNode, parentNode, childNode2);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(nist1Policy);
+ PKIX_TEST_DECREF_AC(nist2Policy);
+ PKIX_TEST_DECREF_AC(policyQualifierList);
+ PKIX_TEST_DECREF_AC(oidAnyPolicy);
+ PKIX_TEST_DECREF_AC(oidNist1Policy);
+ PKIX_TEST_DECREF_AC(oidNist2Policy);
+ PKIX_TEST_DECREF_AC(expectedAnyList);
+ PKIX_TEST_DECREF_AC(expectedNist1List);
+ PKIX_TEST_DECREF_AC(expectedNist2List);
+ PKIX_TEST_DECREF_AC(expectedNist1Nist2List);
+ PKIX_TEST_DECREF_AC(emptyList);
+ PKIX_TEST_DECREF_AC(parentNode);
+ PKIX_TEST_DECREF_AC(childNode1);
+ PKIX_TEST_DECREF_AC(childNode2);
+ PKIX_TEST_DECREF_AC(childNode3);
+ PKIX_TEST_DECREF_AC(childNode4);
+ PKIX_TEST_DECREF_AC(childNode5);
+ PKIX_TEST_DECREF_AC(parentString);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("PolicyNode");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/results/test_valresult.c b/nss/cmd/libpkix/pkix/results/test_valresult.c
new file mode 100644
index 0000000..b914e4a
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/results/test_valresult.c
@@ -0,0 +1,207 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_valresult.c
+ *
+ * Test ValidateResult Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ValidateResult_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+}
+
+static
+void testGetPublicKey(
+ PKIX_ValidateResult *goodObject,
+ PKIX_ValidateResult *equalObject){
+
+ PKIX_PL_PublicKey *goodPubKey = NULL;
+ PKIX_PL_PublicKey *equalPubKey = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ValidateResult_GetPublicKey");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetPublicKey
+ (goodObject, &goodPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetPublicKey
+ (equalObject, &equalPubKey, plContext));
+
+ testEqualsHelper
+ ((PKIX_PL_Object *)goodPubKey,
+ (PKIX_PL_Object *)equalPubKey,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodPubKey);
+ PKIX_TEST_DECREF_AC(equalPubKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testGetTrustAnchor(
+ PKIX_ValidateResult *goodObject,
+ PKIX_ValidateResult *equalObject){
+
+ PKIX_TrustAnchor *goodAnchor = NULL;
+ PKIX_TrustAnchor *equalAnchor = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ValidateResult_GetTrustAnchor");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetTrustAnchor
+ (goodObject, &goodAnchor, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetTrustAnchor
+ (equalObject, &equalAnchor, plContext));
+
+ testEqualsHelper
+ ((PKIX_PL_Object *)goodAnchor,
+ (PKIX_PL_Object *)equalAnchor,
+ PKIX_TRUE,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodAnchor);
+ PKIX_TEST_DECREF_AC(equalAnchor);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testGetPolicyTree(
+ PKIX_ValidateResult *goodObject,
+ PKIX_ValidateResult *equalObject){
+
+ PKIX_PolicyNode *goodTree = NULL;
+ PKIX_PolicyNode *equalTree = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_ValidateResult_GetPolicyTree");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetPolicyTree
+ (goodObject, &goodTree, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetPolicyTree
+ (equalObject, &equalTree, plContext));
+
+ if (goodTree) {
+ testEqualsHelper
+ ((PKIX_PL_Object *)goodTree,
+ (PKIX_PL_Object *)equalTree,
+ PKIX_TRUE,
+ plContext);
+ } else if (equalTree) {
+ pkixTestErrorMsg = "Mismatch: NULL and non-NULL Policy Trees";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodTree);
+ PKIX_TEST_DECREF_AC(equalTree);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void printUsage(char *pName){
+ printf("\nUSAGE: %s \n\n", pName);
+}
+
+int test_valresult(int argc, char *argv[]) {
+
+ PKIX_ValidateResult *goodObject = NULL;
+ PKIX_ValidateResult *equalObject = NULL;
+ PKIX_ValidateResult *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *goodInput = "yassir2yassir";
+ char *diffInput = "yassir2bcn";
+ char *dirName = NULL;
+
+ char *expectedAscii =
+ "[\n"
+ "\tTrustAnchor: \t\t"
+ "[\n"
+ "\tTrusted CA Name: "
+ "CN=yassir,OU=bcn,OU=east,O=sun,C=us\n"
+ "\tTrusted CA PublicKey: ANSI X9.57 DSA Signature\n"
+ "\tInitial Name Constraints:(null)\n"
+ "]\n"
+ "\tPubKey: \t\t"
+ "ANSI X9.57 DSA Signature\n"
+ "\tPolicyTree: \t\t(null)\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("ValidateResult");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2){
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dirName = argv[j+1];
+
+ subTest("pkix_ValidateResult_Create");
+
+ goodObject = createValidateResult
+ (dirName, goodInput, diffInput, plContext);
+ equalObject = createValidateResult
+ (dirName, goodInput, diffInput, plContext);
+ diffObject = createValidateResult
+ (dirName, diffInput, goodInput, plContext);
+
+ testGetPublicKey(goodObject, equalObject);
+ testGetTrustAnchor(goodObject, equalObject);
+ testGetPolicyTree(goodObject, equalObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP
+ (goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ ValidateResult,
+ PKIX_FALSE);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ValidateResult");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/results/test_verifynode.c b/nss/cmd/libpkix/pkix/results/test_verifynode.c
new file mode 100644
index 0000000..2b8e1c3
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/results/test_verifynode.c
@@ -0,0 +1,120 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_verifynode.c
+ *
+ * Test VerifyNode Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static
+void printUsage(void) {
+ (void) printf("\nUSAGE:\ttest_verifynode path cert1 cert2 cert3\n\n");
+}
+
+int test_verifynode(int argc, char *argv[]) {
+
+ /*
+ * Create a tree with parent = cert1, child=cert2, grandchild=cert3
+ */
+ PKIX_PL_Cert *cert1 = NULL;
+ PKIX_PL_Cert *cert2 = NULL;
+ PKIX_PL_Cert *cert3 = NULL;
+ PKIX_VerifyNode *parentNode = NULL;
+ PKIX_VerifyNode *childNode = NULL;
+ PKIX_VerifyNode *grandChildNode = NULL;
+ PKIX_PL_String *parentString = NULL;
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *dirName = NULL;
+ char *twoNodeAscii = "CERT[Issuer:CN=Trust Anchor,O=Test Cert"
+ "ificates,C=US, Subject:CN=Trust Anchor,O=Test Certif"
+ "icates,C=US], depth=0, error=(null)\n. CERT[Issuer:C"
+ "N=Trust Anchor,O=Test Certificates,C=US, Subject:CN="
+ "Good CA,O=Test Certificates,C=US], depth=1, error=(null)";
+ char *threeNodeAscii = "CERT[Issuer:CN=Trust Anchor,O=Test Ce"
+ "rtificates,C=US, Subject:CN=Trust Anchor,O=Test Cert"
+ "ificates,C=US], depth=0, error=(null)\n. CERT[Issuer"
+ ":CN=Trust Anchor,O=Test Certificates,C=US, Subject:C"
+ "N=Good CA,O=Test Certificates,C=US], depth=1, error="
+ "(null)\n. . CERT[Issuer:CN=Good CA,O=Test Certificat"
+ "es,C=US, Subject:CN=Valid EE Certificate Test1,O=Tes"
+ "t Certificates,C=US], depth=2, error=(null)";
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 3) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("VerifyNode");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ dirName = argv[++j];
+
+ subTest("Creating Certs");
+
+ cert1 = createCert
+ (dirName, argv[++j], plContext);
+
+ cert2 = createCert
+ (dirName, argv[++j], plContext);
+
+ cert3 = createCert
+ (dirName, argv[++j], plContext);
+
+ subTest("Creating VerifyNode objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_VerifyNode_Create
+ (cert1, 0, NULL, &parentNode, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_VerifyNode_Create
+ (cert2, 1, NULL, &childNode, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_VerifyNode_Create
+ (cert3, 2, NULL, &grandChildNode, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_VerifyNode_AddToChain
+ (parentNode, childNode, plContext));
+
+ subTest("Creating VerifyNode ToString objects");
+
+ testToStringHelper
+ ((PKIX_PL_Object *)parentNode, twoNodeAscii, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_VerifyNode_AddToChain
+ (parentNode, grandChildNode, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)parentNode, &parentString, plContext));
+ (void) printf("parentNode is\n\t%s\n", parentString->escAsciiString);
+
+ testToStringHelper
+ ((PKIX_PL_Object *)parentNode, threeNodeAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(cert1);
+ PKIX_TEST_DECREF_AC(cert2);
+ PKIX_TEST_DECREF_AC(parentNode);
+ PKIX_TEST_DECREF_AC(childNode);
+ PKIX_TEST_DECREF_AC(parentString);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("VerifyNode");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/store/Makefile b/nss/cmd/libpkix/pkix/store/Makefile
new file mode 100755
index 0000000..09ca5f1
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/store/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/nss/cmd/libpkix/pkix/store/manifest.mn b/nss/cmd/libpkix/pkix/store/manifest.mn
new file mode 100755
index 0000000..566a346
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/store/manifest.mn
@@ -0,0 +1,19 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_store.c
+
+LIBRARY_NAME=pkixtoolstore
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/nss/cmd/libpkix/pkix/store/test_store.c b/nss/cmd/libpkix/pkix/store/test_store.c
new file mode 100755
index 0000000..62a2619
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/store/test_store.c
@@ -0,0 +1,196 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_certstore.c
+ *
+ * Test CertStore Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static
+PKIX_Error *testCRLCallback(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrls, /* list of PKIX_PL_Crl */
+ void *plContext)
+{
+ return (0);
+}
+
+static
+PKIX_Error *testCRLContinue(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCrls, /* list of PKIX_PL_Crl */
+ void *plContext)
+{
+ return (0);
+}
+
+static
+PKIX_Error *testCertCallback(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCerts, /* list of PKIX_PL_Cert */
+ void *plContext)
+{
+ return (0);
+}
+
+static
+PKIX_Error *testCertContinue(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *selector,
+ void **pNBIOContext,
+ PKIX_List **pCerts, /* list of PKIX_PL_Cert */
+ void *plContext)
+{
+ return (0);
+}
+
+static char *catDirName(char *platform, char *dir, void *plContext)
+{
+ char *pathName = NULL;
+ PKIX_UInt32 dirLen;
+ PKIX_UInt32 platformLen;
+
+ PKIX_TEST_STD_VARS();
+
+ dirLen = PL_strlen(dir);
+ platformLen = PL_strlen(platform);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc
+ (platformLen + dirLen + 2, (void **)&pathName, plContext));
+
+ PL_strcpy(pathName, platform);
+ PL_strcat(pathName, "/");
+ PL_strcat(pathName, dir);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (pathName);
+}
+
+static
+void testCertStore(char *crlDir)
+{
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_PL_Object *getCertStoreContext = NULL;
+ PKIX_CertStore_CertCallback certCallback = NULL;
+ PKIX_CertStore_CRLCallback crlCallback = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ crlDir,
+ 0,
+ &dirString,
+ plContext));
+
+ subTest("PKIX_CertStore_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_Create
+ (testCertCallback,
+ testCRLCallback,
+ testCertContinue,
+ testCRLContinue,
+ NULL, /* trustCallback */
+ (PKIX_PL_Object *) dirString,
+ PKIX_TRUE, /* cacheFlag */
+ PKIX_TRUE, /* local */
+ &certStore,
+ plContext));
+
+ subTest("PKIX_CertStore_GetCertCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback
+ (certStore, &certCallback, plContext));
+
+ if (certCallback != testCertCallback) {
+ testError("PKIX_CertStore_GetCertCallback unexpected mismatch");
+ }
+
+ subTest("PKIX_CertStore_GetCRLCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback
+ (certStore, &crlCallback, plContext));
+
+ if (crlCallback != testCRLCallback) {
+ testError("PKIX_CertStore_GetCRLCallback unexpected mismatch");
+ }
+
+ subTest("PKIX_CertStore_GetCertStoreContext");
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertStore_GetCertStoreContext
+ (certStore, &getCertStoreContext, plContext));
+
+ if ((PKIX_PL_Object *)dirString != getCertStoreContext) {
+ testError("PKIX_CertStore_GetCertStoreContext unexpected mismatch");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(getCertStoreContext);
+
+ PKIX_TEST_RETURN();
+}
+
+
+static
+void printUsage(char *pName){
+ printf("\nUSAGE: %s testName \n\n", pName);
+}
+
+/* Functional tests for CertStore public functions */
+
+int test_store(int argc, char *argv[]) {
+
+ char *platformDir = NULL;
+ char *dataDir = NULL;
+ char *combinedDir = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < (3 + j)) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ startTests(argv[1 + j]);
+
+ dataDir = argv[2 + j];
+ platformDir = argv[3 + j];
+ combinedDir = catDirName(platformDir, dataDir, plContext);
+
+ testCertStore(combinedDir);
+
+
+cleanup:
+
+ pkixTestErrorResult = PKIX_PL_Free(combinedDir, plContext);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CertStore");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/top/Makefile b/nss/cmd/libpkix/pkix/top/Makefile
new file mode 100755
index 0000000..09ca5f1
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/Makefile
@@ -0,0 +1,47 @@
+#! gmake
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#######################################################################
+# (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) #
+#######################################################################
+
+include $(PKIX_DEPTH)/config.mk
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platlibs.mk
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include $(PLAT_DEPTH)/platrules.mk
diff --git a/nss/cmd/libpkix/pkix/top/manifest.mn b/nss/cmd/libpkix/pkix/top/manifest.mn
new file mode 100755
index 0000000..a7d997d
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/manifest.mn
@@ -0,0 +1,33 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_basicchecker.c \
+ test_basicconstraintschecker.c \
+ test_buildchain.c \
+ test_buildchain_uchecker.c \
+ test_buildchain_partialchain.c \
+ test_buildchain_resourcelimits.c \
+ test_customcrlchecker.c \
+ test_defaultcrlchecker2stores.c \
+ test_ocsp.c \
+ test_policychecker.c \
+ test_subjaltnamechecker.c \
+ test_validatechain.c \
+ test_validatechain_bc.c \
+ test_validatechain_NB.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtooltop
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/nss/cmd/libpkix/pkix/top/test_basicchecker.c b/nss/cmd/libpkix/pkix/top/test_basicchecker.c
new file mode 100644
index 0000000..74fb9aa
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_basicchecker.c
@@ -0,0 +1,243 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_basicchecker.c
+ *
+ * Test Basic Checking
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static
+void testPass(char *dirName, char *goodInput, char *diffInput, char *dateAscii){
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Basic-Common-Fields ");
+ /*
+ * Tests the Expiration, NameChaining, and Signature Checkers
+ */
+
+ chain = createCertChain(dirName, goodInput, diffInput, plContext);
+
+ valParams = createValidateParams
+ (dirName,
+ goodInput,
+ diffInput,
+ dateAscii,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)verifyTree, &verifyString, plContext));
+ (void) printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testNameChainingFail(
+ char *dirName,
+ char *goodInput,
+ char *diffInput,
+ char *dateAscii)
+{
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("NameChaining ");
+
+ chain = createCertChain(dirName, diffInput, goodInput, plContext);
+
+ valParams = createValidateParams
+ (dirName,
+ goodInput,
+ diffInput,
+ dateAscii,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testDateFail(char *dirName, char *goodInput, char *diffInput){
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ chain = createCertChain(dirName, goodInput, diffInput, plContext);
+
+ subTest("Expiration ");
+ valParams = createValidateParams
+ (dirName,
+ goodInput,
+ diffInput,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, NULL, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testSignatureFail(
+ char *dirName,
+ char *goodInput,
+ char *diffInput,
+ char *dateAscii)
+{
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Signature ");
+
+ chain = createCertChain(dirName, diffInput, goodInput, plContext);
+
+ valParams = createValidateParams
+ (dirName,
+ goodInput,
+ diffInput,
+ dateAscii,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, NULL, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void printUsage(char *pName){
+ printf("\nUSAGE: %s \n\n", pName);
+}
+
+int test_basicchecker(int argc, char *argv[]) {
+
+ char *goodInput = "yassir2yassir";
+ char *diffInput = "yassir2bcn";
+ char *dateAscii = "991201000000Z";
+ char *dirName = NULL;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("SignatureChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 2){
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dirName = argv[j+1];
+
+ /* The NameChaining, Expiration, and Signature Checkers all pass */
+ testPass(dirName, goodInput, diffInput, dateAscii);
+
+ /* Individual Checkers fail */
+ testNameChainingFail(dirName, goodInput, diffInput, dateAscii);
+ testDateFail(dirName, goodInput, diffInput);
+
+ /*
+ * XXX
+ * since the signature check is done last, we need to create
+ * certs whose name chaining passes, but their signatures fail;
+ * we currently don't have any such certs.
+ */
+ /* testSignatureFail(goodInput, diffInput, dateAscii); */
+
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("SignatureChecker");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_basicconstraintschecker.c b/nss/cmd/libpkix/pkix/top/test_basicconstraintschecker.c
new file mode 100644
index 0000000..3d57b64
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_basicconstraintschecker.c
@@ -0,0 +1,144 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_basicconstraintschecker.c
+ *
+ * Test Basic Constraints Checking
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_MAX_CERTS 10
+
+static void *plContext = NULL;
+
+static
+void printUsage1(char *pName){
+ printf("\nUSAGE: %s test-name [ENE|EE] ", pName);
+ printf("cert [certs].\n");
+}
+
+static
+void printUsageMax(PKIX_UInt32 numCerts){
+ printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n",
+ numCerts, PKIX_TEST_MAX_CERTS);
+}
+
+int test_basicconstraintschecker(int argc, char *argv[]){
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *certNames[PKIX_TEST_MAX_CERTS];
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean testValid = PKIX_FALSE;
+ char *dirName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 4){
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ startTests("BasicConstraintsChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2+j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2+j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ dirName = argv[3+j];
+
+ chainLength = (argc - j) - 4;
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ }
+
+ for (i = 0; i < chainLength; i++) {
+ certNames[i] = argv[(4+j)+i];
+ certs[i] = NULL;
+ }
+
+ subTest(argv[1+j]);
+
+ subTest("Basic-Constraints - Create Cert Chain");
+
+ chain = createCertChainPlus
+ (dirName, certNames, certs, chainLength, plContext);
+
+ /*
+ * Error occurs when creating Cert, this is critical and test
+ * should not continue. Since we expect error, we assume this
+ * error is the one that is expected, so undo the error count.
+ *
+ * This work needs future enhancement. We will introduce another
+ * flag ESE, in addition to the existing EE(expect validation
+ * error) and ENE(expect no validation error). ESE stands for
+ * "expect setup error". When running with ESE, if any of the setup
+ * calls such creating Cert Chain fails, the test can end and
+ * considered to be successful.
+ */
+ if (testValid == PKIX_FALSE && chain == NULL) {
+ testErrorUndo("Cert Error - Create failed");
+ goto cleanup;
+ }
+
+ subTest("Basic-Constraints - Create Params");
+
+ valParams = createValidateParams
+ (dirName,
+ argv[4+j],
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("Basic-Constraints - Validate Chain");
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("BasicConstraintsChecker");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_buildchain.c b/nss/cmd/libpkix/pkix/top/test_buildchain.c
new file mode 100644
index 0000000..9aef730
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_buildchain.c
@@ -0,0 +1,471 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_buildchain.c
+ *
+ * Test BuildChain function
+ *
+ */
+
+/* #define debuggingWithoutRevocation */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define LDAP_PORT 389
+static PKIX_Boolean usebind = PKIX_FALSE;
+static PKIX_Boolean useLDAP = PKIX_FALSE;
+static char buf[PR_NETDB_BUF_SIZE];
+static char *serverName = NULL;
+static char *sepPtr = NULL;
+static PRNetAddr netAddr;
+static PRHostEnt hostent;
+static PKIX_UInt32 portNum = 0;
+static PRIntn hostenum = 0;
+static PRStatus prstatus = PR_FAILURE;
+static void *ipaddr = NULL;
+
+
+static void *plContext = NULL;
+
+static void printUsage(void) {
+ (void) printf("\nUSAGE:\ttest_buildchain [-arenas] [usebind] "
+ "servername[:port] [ENE|EE]\n"
+ "\t "
+ " \n\n");
+ (void) printf
+ ("Builds a chain of certificates from to \n"
+ "using the certs and CRLs in . "
+ "servername[:port] gives\n"
+ "the address of an LDAP server. If port is not"
+ " specified, port 389 is used. \"-\" means no LDAP server.\n"
+ "If ENE is specified, then an Error is Not Expected. "
+ "EE indicates an Error is Expected.\n");
+}
+
+static PKIX_Error *
+createLdapCertStore(
+ char *hostname,
+ PRIntervalTime timeout,
+ PKIX_CertStore **pLdapCertStore,
+ void* plContext)
+{
+ PRIntn backlog = 0;
+
+ char *bindname = "";
+ char *auth = "";
+
+ LDAPBindAPI bindAPI;
+ LDAPBindAPI *bindPtr = NULL;
+ PKIX_PL_LdapDefaultClient *ldapClient = NULL;
+ PKIX_CertStore *ldapCertStore = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (usebind) {
+ bindPtr = &bindAPI;
+ bindAPI.selector = SIMPLE_AUTH;
+ bindAPI.chooser.simple.bindName = bindname;
+ bindAPI.chooser.simple.authentication = auth;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapDefaultClient_CreateByName
+ (hostname, timeout, bindPtr, &ldapClient, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapCertStore_Create
+ ((PKIX_PL_LdapClient *)ldapClient,
+ &ldapCertStore,
+ plContext));
+
+ *pLdapCertStore = ldapCertStore;
+cleanup:
+
+ PKIX_TEST_DECREF_AC(ldapClient);
+
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+
+}
+
+int test_buildchain(int argc, char *argv[])
+{
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ char *dirName = NULL;
+ PKIX_PL_String *dirNameString = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_UInt32 actualMinorVersion = 0;
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_CertStore *ldapCertStore = NULL;
+ PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; /* blocking */
+ /* PRIntervalTime timeout = PR_INTERVAL_NO_WAIT; =0 for non-blocking */
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_List *revCheckers = NULL;
+ char * asciiResult = NULL;
+ PKIX_Boolean result = PKIX_FALSE;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ PKIX_List *expectedCerts = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ PKIX_PL_String *actualCertsString = NULL;
+ PKIX_PL_String *expectedCertsString = NULL;
+ void *state = NULL;
+ char *actualCertsAscii = NULL;
+ char *expectedCertsAscii = NULL;
+ PRPollDesc *pollDesc = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("BuildChain");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /*
+ * arguments:
+ * [optional] -arenas
+ * [optional] usebind
+ * servername or servername:port ( - for no server)
+ * testname
+ * EE or ENE
+ * cert directory
+ * target cert (end entity)
+ * intermediate certs
+ * trust anchor
+ */
+
+ /* optional argument "usebind" for Ldap CertStore */
+ if (argv[j + 1]) {
+ if (PORT_Strcmp(argv[j + 1], "usebind") == 0) {
+ usebind = PKIX_TRUE;
+ j++;
+ }
+ }
+
+ if (PORT_Strcmp(argv[++j], "-") == 0) {
+ useLDAP = PKIX_FALSE;
+ } else {
+ serverName = argv[j];
+ useLDAP = PKIX_TRUE;
+ }
+
+ subTest(argv[++j]);
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[++j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ dirName = argv[++j];
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&expectedCerts, plContext));
+
+ for (k = ++j; k < (PKIX_UInt32)argc; k++) {
+
+ dirCert = createCert(dirName, argv[k], plContext);
+
+ if (k == (PKIX_UInt32)(argc - 1)) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)dirCert, plContext));
+ trustedCert = dirCert;
+ } else {
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (expectedCerts,
+ (PKIX_PL_Object *)dirCert,
+ plContext));
+
+ if (k == j) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)dirCert, plContext));
+ targetCert = dirCert;
+ }
+ }
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert
+ (trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create
+ (anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetCertificate
+ (certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ProcessingParams_SetTargetCertConstraints
+ (procParams, certSelector, plContext));
+
+ /* create CertStores */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, dirName, 0, &dirNameString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStores, plContext));
+
+ if (useLDAP == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(createLdapCertStore
+ (serverName, timeout, &ldapCertStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (certStores,
+ (PKIX_PL_Object *)ldapCertStore,
+ plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_CollectionCertStore_Create
+ (dirNameString, &certStore, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (certStores, (PKIX_PL_Object *)certStore, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores
+ (procParams, certStores, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey
+ (trustedCert, &trustedPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (expectedCerts, &numCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_DefaultRevChecker_Initialize
+ (certStores,
+ NULL, /* testDate, may be NULL */
+ trustedPubKey,
+ numCerts,
+ &revChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (revCheckers, (PKIX_PL_Object *)revChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers
+ (procParams, revCheckers, plContext));
+
+#ifdef debuggingWithoutRevocation
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
+ (procParams, PKIX_FALSE, plContext));
+#endif
+
+ /* build cert chain using processing params and return buildResult */
+
+ pkixTestErrorResult = PKIX_BuildChain
+ (procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ &verifyTree,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_BuildChain
+ (procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ &verifyTree,
+ plContext);
+ }
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void) printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED");
+ }
+ } else {
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void) printf("EXPECTED NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ (void) printf("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+ }
+
+ subTest("Displaying VerifyNode objects");
+
+ if (verifyTree == NULL) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, "(null)", 0, &verifyString, plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)verifyTree, &verifyString, plContext));
+ }
+
+ (void) printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+
+ if (pkixTestErrorResult) {
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ goto cleanup;
+ }
+
+ if (buildResult) {
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_BuildResult_GetCertChain
+ (buildResult, &certs, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetItem
+ (certs,
+ i,
+ (PKIX_PL_Object**)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Free(asciiResult, NULL));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Object_Equals
+ ((PKIX_PL_Object*)certs,
+ (PKIX_PL_Object*)expectedCerts,
+ &result,
+ plContext));
+
+ if (!result) {
+ testError("BUILT CERTCHAIN IS "
+ "NOT THE ONE THAT WAS EXPECTED");
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)certs,
+ &actualCertsString,
+ plContext));
+
+ actualCertsAscii = PKIX_String2ASCII
+ (actualCertsString, plContext);
+ if (actualCertsAscii == NULL) {
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)expectedCerts,
+ &expectedCertsString,
+ plContext));
+
+ expectedCertsAscii = PKIX_String2ASCII
+ (expectedCertsString, plContext);
+ if (expectedCertsAscii == NULL) {
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ (void) printf("Actual value:\t%s\n", actualCertsAscii);
+ (void) printf("Expected value:\t%s\n",
+ expectedCertsAscii);
+ }
+
+ }
+
+cleanup:
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+
+ PKIX_PL_Free(asciiResult, NULL);
+ PKIX_PL_Free(actualCertsAscii, plContext);
+ PKIX_PL_Free(expectedCertsAscii, plContext);
+
+ PKIX_TEST_DECREF_AC(state);
+ PKIX_TEST_DECREF_AC(actualCertsString);
+ PKIX_TEST_DECREF_AC(expectedCertsString);
+ PKIX_TEST_DECREF_AC(expectedCerts);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStores);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(revChecker);
+ PKIX_TEST_DECREF_AC(ldapCertStore);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(dirNameString);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(trustedCert);
+ PKIX_TEST_DECREF_AC(trustedPubKey);
+
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(targetCert);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BuildChain");
+
+ return (0);
+
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_buildchain_partialchain.c b/nss/cmd/libpkix/pkix/top/test_buildchain_partialchain.c
new file mode 100644
index 0000000..18ebcde
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_buildchain_partialchain.c
@@ -0,0 +1,821 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_buildchain_partialchain.c
+ *
+ * Test BuildChain function
+ *
+ */
+
+#define debuggingWithoutRevocation
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define LDAP_PORT 389
+static PKIX_Boolean usebind = PKIX_FALSE;
+static PKIX_Boolean useLDAP = PKIX_FALSE;
+static char buf[PR_NETDB_BUF_SIZE];
+static char *serverName = NULL;
+static char *sepPtr = NULL;
+static PRNetAddr netAddr;
+static PRHostEnt hostent;
+static PKIX_UInt32 portNum = 0;
+static PRIntn hostenum = 0;
+static PRStatus prstatus = PR_FAILURE;
+static void *ipaddr = NULL;
+
+
+static void *plContext = NULL;
+
+static void printUsage(void) {
+ (void) printf("\nUSAGE:\ttest_buildchain [-arenas] [usebind] "
+ "servername[:port] [ENE|EE]\n"
+ "\t "
+ " \n\n");
+ (void) printf
+ ("Builds a chain of certificates from to \n"
+ "using the certs and CRLs in . "
+ "servername[:port] gives\n"
+ "the address of an LDAP server. If port is not"
+ " specified, port 389 is used. \"-\" means no LDAP server.\n"
+ "If ENE is specified, then an Error is Not Expected. "
+ "EE indicates an Error is Expected.\n");
+}
+
+static PKIX_Error *
+createLdapCertStore(
+ char *hostname,
+ PRIntervalTime timeout,
+ PKIX_CertStore **pLdapCertStore,
+ void* plContext)
+{
+ PRIntn backlog = 0;
+
+ char *bindname = "";
+ char *auth = "";
+
+ LDAPBindAPI bindAPI;
+ LDAPBindAPI *bindPtr = NULL;
+ PKIX_PL_LdapDefaultClient *ldapClient = NULL;
+ PKIX_CertStore *ldapCertStore = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (usebind) {
+ bindPtr = &bindAPI;
+ bindAPI.selector = SIMPLE_AUTH;
+ bindAPI.chooser.simple.bindName = bindname;
+ bindAPI.chooser.simple.authentication = auth;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapDefaultClient_CreateByName
+ (hostname, timeout, bindPtr, &ldapClient, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapCertStore_Create
+ ((PKIX_PL_LdapClient *)ldapClient,
+ &ldapCertStore,
+ plContext));
+
+ *pLdapCertStore = ldapCertStore;
+cleanup:
+
+ PKIX_TEST_DECREF_AC(ldapClient);
+
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+
+}
+
+/* Test with all Certs in the partial list, no leaf */
+static PKIX_Error *
+testWithNoLeaf(
+ PKIX_PL_Cert *trustedCert,
+ PKIX_List *listOfCerts,
+ PKIX_PL_Cert *targetCert,
+ PKIX_List *certStores,
+ PKIX_Boolean testValid,
+ void* plContext)
+{
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *hintCerts = NULL;
+ PKIX_List *revCheckers = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PRPollDesc *pollDesc = NULL;
+ void *state = NULL;
+ char *asciiResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert
+ (trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create
+ (anchors, &procParams, plContext));
+
+ /* create CertSelector with no target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints
+ (procParams, certSelector, plContext));
+
+ /* create hintCerts */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)listOfCerts,
+ (PKIX_PL_Object **)&hintCerts,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetHintCerts
+ (procParams, hintCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores
+ (procParams, certStores, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey
+ (trustedCert, &trustedPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (listOfCerts, &numCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_DefaultRevChecker_Initialize
+ (certStores,
+ NULL, /* testDate, may be NULL */
+ trustedPubKey,
+ numCerts,
+ &revChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (revCheckers, (PKIX_PL_Object *)revChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers
+ (procParams, revCheckers, plContext));
+
+#ifdef debuggingWithoutRevocation
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
+ (procParams, PKIX_FALSE, plContext));
+#endif
+
+ /* build cert chain using processing params and return buildResult */
+
+ pkixTestErrorResult = PKIX_BuildChain
+ (procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_BuildChain
+ (procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+ }
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void) printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED");
+ }
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ goto cleanup;
+ }
+
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void) printf("EXPECTED NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ (void) printf("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+
+ if (buildResult) {
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_BuildResult_GetCertChain
+ (buildResult, &certs, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetItem
+ (certs,
+ i,
+ (PKIX_PL_Object**)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Free(asciiResult, NULL));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+ }
+
+cleanup:
+ PKIX_PL_Free(asciiResult, NULL);
+
+ PKIX_TEST_DECREF_AC(state);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(revChecker);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(hintCerts);
+ PKIX_TEST_DECREF_AC(trustedPubKey);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+
+}
+
+/* Test with all Certs in the partial list, leaf duplicates the first one */
+static PKIX_Error *
+testWithDuplicateLeaf(
+ PKIX_PL_Cert *trustedCert,
+ PKIX_List *listOfCerts,
+ PKIX_PL_Cert *targetCert,
+ PKIX_List *certStores,
+ PKIX_Boolean testValid,
+ void* plContext)
+{
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *hintCerts = NULL;
+ PKIX_List *revCheckers = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PRPollDesc *pollDesc = NULL;
+ void *state = NULL;
+ char *asciiResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert
+ (trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create
+ (anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate
+ (certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints
+ (procParams, certSelector, plContext));
+
+ /* create hintCerts */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)listOfCerts,
+ (PKIX_PL_Object **)&hintCerts,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetHintCerts
+ (procParams, hintCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores
+ (procParams, certStores, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey
+ (trustedCert, &trustedPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (listOfCerts, &numCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_DefaultRevChecker_Initialize
+ (certStores,
+ NULL, /* testDate, may be NULL */
+ trustedPubKey,
+ numCerts,
+ &revChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (revCheckers, (PKIX_PL_Object *)revChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers
+ (procParams, revCheckers, plContext));
+
+#ifdef debuggingWithoutRevocation
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
+ (procParams, PKIX_FALSE, plContext));
+#endif
+
+ /* build cert chain using processing params and return buildResult */
+
+ pkixTestErrorResult = PKIX_BuildChain
+ (procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_BuildChain
+ (procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+ }
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void) printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED");
+ }
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ goto cleanup;
+ }
+
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void) printf("EXPECTED NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ (void) printf("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+
+ if (buildResult) {
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_BuildResult_GetCertChain
+ (buildResult, &certs, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetItem
+ (certs,
+ i,
+ (PKIX_PL_Object**)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Free(asciiResult, NULL));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+ }
+
+cleanup:
+ PKIX_PL_Free(asciiResult, NULL);
+
+ PKIX_TEST_DECREF_AC(state);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(revChecker);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(hintCerts);
+ PKIX_TEST_DECREF_AC(trustedPubKey);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+
+}
+
+/* Test with all Certs except the leaf in the partial list */
+static PKIX_Error *
+testWithLeafAndChain(
+ PKIX_PL_Cert *trustedCert,
+ PKIX_List *listOfCerts,
+ PKIX_PL_Cert *targetCert,
+ PKIX_List *certStores,
+ PKIX_Boolean testValid,
+ void* plContext)
+{
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *hintCerts = NULL;
+ PKIX_List *revCheckers = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_PL_PublicKey *trustedPubKey = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PRPollDesc *pollDesc = NULL;
+ void *state = NULL;
+ char *asciiResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert
+ (trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create
+ (anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate
+ (certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints
+ (procParams, certSelector, plContext));
+
+ /* create hintCerts */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate
+ ((PKIX_PL_Object *)listOfCerts,
+ (PKIX_PL_Object **)&hintCerts,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem
+ (hintCerts, 0, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetHintCerts
+ (procParams, hintCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores
+ (procParams, certStores, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey
+ (trustedCert, &trustedPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (listOfCerts, &numCerts, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_DefaultRevChecker_Initialize
+ (certStores,
+ NULL, /* testDate, may be NULL */
+ trustedPubKey,
+ numCerts,
+ &revChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (revCheckers, (PKIX_PL_Object *)revChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers
+ (procParams, revCheckers, plContext));
+
+#ifdef debuggingWithoutRevocation
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
+ (procParams, PKIX_FALSE, plContext));
+#endif
+
+ /* build cert chain using processing params and return buildResult */
+
+ pkixTestErrorResult = PKIX_BuildChain
+ (procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_BuildChain
+ (procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+ }
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void) printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED");
+ }
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ goto cleanup;
+ }
+
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void) printf("EXPECTED NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ (void) printf("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+
+ if (buildResult) {
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_BuildResult_GetCertChain
+ (buildResult, &certs, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetItem
+ (certs,
+ i,
+ (PKIX_PL_Object**)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Free(asciiResult, NULL));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(state);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(revChecker);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(hintCerts);
+ PKIX_TEST_DECREF_AC(trustedPubKey);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+
+}
+
+int test_buildchain_partialchain(int argc, char *argv[])
+{
+ PKIX_UInt32 actualMinorVersion = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_Boolean ene = PKIX_TRUE; /* expect no error */
+ PKIX_List *listOfCerts = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_PL_Cert *trusted = NULL;
+ PKIX_PL_Cert *target = NULL;
+ PKIX_CertStore *ldapCertStore = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_PL_String *dirNameString = NULL;
+ char *dirName = NULL;
+
+ PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; /* blocking */
+ /* PRIntervalTime timeout = PR_INTERVAL_NO_WAIT; =0 for non-blocking */
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("BuildChain");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /*
+ * arguments:
+ * [optional] -arenas
+ * [optional] usebind
+ * servername or servername:port ( - for no server)
+ * testname
+ * EE or ENE
+ * cert directory
+ * target cert (end entity)
+ * intermediate certs
+ * trust anchor
+ */
+
+ /* optional argument "usebind" for Ldap CertStore */
+ if (argv[j + 1]) {
+ if (PORT_Strcmp(argv[j + 1], "usebind") == 0) {
+ usebind = PKIX_TRUE;
+ j++;
+ }
+ }
+
+ if (PORT_Strcmp(argv[++j], "-") == 0) {
+ useLDAP = PKIX_FALSE;
+ } else {
+ serverName = argv[j];
+ useLDAP = PKIX_TRUE;
+ }
+
+ subTest(argv[++j]);
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[++j], "ENE") == 0) {
+ ene = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[j], "EE") == 0) {
+ ene = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ dirName = argv[++j];
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&listOfCerts, plContext));
+
+ for (k = ++j; k < ((PKIX_UInt32)argc); k++) {
+
+ dirCert = createCert(dirName, argv[k], plContext);
+
+ if (k == ((PKIX_UInt32)(argc - 1))) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)dirCert, plContext));
+ trusted = dirCert;
+ } else {
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (listOfCerts,
+ (PKIX_PL_Object *)dirCert,
+ plContext));
+
+ if (k == j) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)dirCert, plContext));
+ target = dirCert;
+ }
+ }
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ /* create CertStores */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, dirName, 0, &dirNameString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStores, plContext));
+
+ if (useLDAP == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(createLdapCertStore
+ (serverName, timeout, &ldapCertStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (certStores,
+ (PKIX_PL_Object *)ldapCertStore,
+ plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_CollectionCertStore_Create
+ (dirNameString, &certStore, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (certStores, (PKIX_PL_Object *)certStore, plContext));
+ }
+
+ subTest("testWithNoLeaf");
+ PKIX_TEST_EXPECT_NO_ERROR(testWithNoLeaf
+ (trusted, listOfCerts, target, certStores, ene, plContext));
+
+ subTest("testWithDuplicateLeaf");
+ PKIX_TEST_EXPECT_NO_ERROR(testWithDuplicateLeaf
+ (trusted, listOfCerts, target, certStores, ene, plContext));
+
+ subTest("testWithLeafAndChain");
+ PKIX_TEST_EXPECT_NO_ERROR(testWithLeafAndChain
+ (trusted, listOfCerts, target, certStores, ene, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(listOfCerts);
+ PKIX_TEST_DECREF_AC(certStores);
+ PKIX_TEST_DECREF_AC(ldapCertStore);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(dirNameString);
+ PKIX_TEST_DECREF_AC(trusted);
+ PKIX_TEST_DECREF_AC(target);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BuildChain");
+
+ return (0);
+
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_buildchain_resourcelimits.c b/nss/cmd/libpkix/pkix/top/test_buildchain_resourcelimits.c
new file mode 100644
index 0000000..065a5f8
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_buildchain_resourcelimits.c
@@ -0,0 +1,497 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_buildchain_resourcelimits.c
+ *
+ * Test BuildChain function with constraints on resources
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TESTUSERCHECKER_TYPE (PKIX_NUMTYPES+30)
+
+static void *plContext = NULL;
+static PKIX_Boolean usebind = PKIX_FALSE;
+static PKIX_Boolean useLDAP = PKIX_FALSE;
+static char buf[PR_NETDB_BUF_SIZE];
+static char *serverName = NULL;
+
+static void printUsage(void) {
+ (void) printf("\nUSAGE:\ttest_buildchain_resourcelimits [-arenas] "
+ "[usebind] servername[:port]\\\n\t\t [ENE|EE]"
+ " \\\n\t\t"
+ " \n\n");
+ (void) printf
+ ("Builds a chain of certificates from to \n"
+ "using the certs and CRLs in . "
+ "servername[:port] gives\n"
+ "the address of an LDAP server. If port is not"
+ " specified, port 389 is used.\n\"-\" means no LDAP server.\n\n"
+ "If ENE is specified, then an Error is Not Expected.\n"
+ "EE indicates an Error is Expected.\n");
+}
+
+static PKIX_Error *
+createLdapCertStore(
+ char *hostname,
+ PRIntervalTime timeout,
+ PKIX_CertStore **pLdapCertStore,
+ void* plContext)
+{
+ PRIntn backlog = 0;
+
+ char *bindname = "";
+ char *auth = "";
+
+ LDAPBindAPI bindAPI;
+ LDAPBindAPI *bindPtr = NULL;
+ PKIX_PL_LdapDefaultClient *ldapClient = NULL;
+ PKIX_CertStore *ldapCertStore = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (usebind) {
+ bindPtr = &bindAPI;
+ bindAPI.selector = SIMPLE_AUTH;
+ bindAPI.chooser.simple.bindName = bindname;
+ bindAPI.chooser.simple.authentication = auth;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapDefaultClient_CreateByName
+ (hostname, timeout, bindPtr, &ldapClient, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapCertStore_Create
+ ((PKIX_PL_LdapClient *)ldapClient, &ldapCertStore, plContext));
+
+ *pLdapCertStore = ldapCertStore;
+cleanup:
+
+ PKIX_TEST_DECREF_AC(ldapClient);
+
+ PKIX_TEST_RETURN();
+
+ return (pkixTestErrorResult);
+
+}
+
+static void Test_BuildResult(
+ PKIX_ProcessingParams *procParams,
+ PKIX_Boolean testValid,
+ PKIX_List *expectedCerts,
+ void *plContext)
+{
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_PL_String *actualCertsString = NULL;
+ PKIX_PL_String *expectedCertsString = NULL;
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_Boolean result;
+ PKIX_Boolean supportForward = PKIX_FALSE;
+ PKIX_UInt32 numCerts, i;
+ char *asciiResult = NULL;
+ char *actualCertsAscii = NULL;
+ char *expectedCertsAscii = NULL;
+ void *state = NULL;
+ PRPollDesc *pollDesc = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ pkixTestErrorResult = PKIX_BuildChain
+ (procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_BuildChain
+ (procParams,
+ (void **)&pollDesc,
+ &state,
+ &buildResult,
+ NULL,
+ plContext);
+ }
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void) printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED!\n");
+ }
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ goto cleanup;
+ }
+
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void) printf("EXPECTED NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ testError("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+
+ if (buildResult){
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_BuildResult_GetCertChain
+ (buildResult, &certs, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++){
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetItem
+ (certs,
+ i,
+ (PKIX_PL_Object**)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Free(asciiResult, NULL));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Object_Equals
+ ((PKIX_PL_Object*)certs,
+ (PKIX_PL_Object*)expectedCerts,
+ &result,
+ plContext));
+
+ if (!result){
+ testError("BUILT CERTCHAIN IS "
+ "NOT THE ONE THAT WAS EXPECTED");
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)certs,
+ &actualCertsString,
+ plContext));
+
+ actualCertsAscii = PKIX_String2ASCII
+ (actualCertsString, plContext);
+ if (actualCertsAscii == NULL){
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)expectedCerts,
+ &expectedCertsString,
+ plContext));
+
+ expectedCertsAscii = PKIX_String2ASCII
+ (expectedCertsString, plContext);
+ if (expectedCertsAscii == NULL){
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ (void) printf("Actual value:\t%s\n", actualCertsAscii);
+ (void) printf("Expected value:\t%s\n",
+ expectedCertsAscii);
+ }
+
+ }
+
+cleanup:
+
+ PKIX_PL_Free(asciiResult, NULL);
+ PKIX_PL_Free(actualCertsAscii, plContext);
+ PKIX_PL_Free(expectedCertsAscii, plContext);
+ PKIX_TEST_DECREF_AC(state);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(actualCertsString);
+ PKIX_TEST_DECREF_AC(expectedCertsString);
+
+ PKIX_TEST_RETURN();
+
+}
+
+int test_buildchain_resourcelimits(int argc, char *argv[])
+{
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_CertChainChecker *checker = NULL;
+ PKIX_ResourceLimits *resourceLimits = NULL;
+ char *dirName = NULL;
+ PKIX_PL_String *dirNameString = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_UInt32 actualMinorVersion = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_CertStore *ldapCertStore = NULL;
+ PRIntervalTime timeout = 0; /* 0 for non-blocking */
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *certStores = NULL;
+ PKIX_List *expectedCerts = NULL;
+ PKIX_Boolean testValid = PKIX_FALSE;
+ PKIX_Boolean usebind = PKIX_FALSE;
+ PKIX_Boolean useLDAP = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5){
+ printUsage();
+ return (0);
+ }
+
+ startTests("BuildChain_ResourceLimits");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /*
+ * arguments:
+ * [optional] -arenas
+ * [optional] usebind
+ * servername or servername:port ( - for no server)
+ * testname
+ * EE or ENE
+ * cert directory
+ * target cert (end entity)
+ * intermediate certs
+ * trust anchor
+ */
+
+ /* optional argument "usebind" for Ldap CertStore */
+ if (argv[j + 1]) {
+ if (PORT_Strcmp(argv[j + 1], "usebind") == 0) {
+ usebind = PKIX_TRUE;
+ j++;
+ }
+ }
+
+ if (PORT_Strcmp(argv[++j], "-") == 0) {
+ useLDAP = PKIX_FALSE;
+ } else {
+ serverName = argv[j];
+ }
+
+ subTest(argv[++j]);
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[++j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ dirName = argv[++j];
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&expectedCerts, plContext));
+
+ for (k = ++j; k < argc; k++) {
+
+ dirCert = createCert(dirName, argv[k], plContext);
+
+ if (k == (argc - 1)) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)dirCert, plContext));
+ trustedCert = dirCert;
+ } else {
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (expectedCerts,
+ (PKIX_PL_Object *)dirCert,
+ plContext));
+
+ if (k == j) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)dirCert, plContext));
+ targetCert = dirCert;
+ }
+ }
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert
+ (trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create
+ (anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetCertificate
+ (certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ProcessingParams_SetTargetCertConstraints
+ (procParams, certSelector, plContext));
+
+ /* create CertStores */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ dirName,
+ 0,
+ &dirNameString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
+ (dirNameString, &certStore, plContext));
+
+#if 0
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create
+ (&certStore, plContext));
+#endif
+
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStores, plContext));
+
+ if (useLDAP == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(createLdapCertStore
+ (serverName, timeout, &ldapCertStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (certStores,
+ (PKIX_PL_Object *)ldapCertStore,
+ plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (certStores, (PKIX_PL_Object *)certStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores
+ (procParams, certStores, plContext));
+
+ /* set resource limits */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create
+ (&resourceLimits, plContext));
+
+ /* need longer time when running dbx for memory leak checking */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime
+ (resourceLimits, 60, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout
+ (resourceLimits, 2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth
+ (resourceLimits, 2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetResourceLimits
+ (procParams, resourceLimits, plContext));
+
+ /* build cert chain using processing params and return buildResult */
+
+ subTest("Testing ResourceLimits MaxFanout & MaxDepth - ");
+ Test_BuildResult
+ (procParams,
+ testValid,
+ expectedCerts,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout
+ (resourceLimits, 1, plContext));
+
+ subTest("Testing ResourceLimits MaxFanout - ");
+ Test_BuildResult
+ (procParams,
+ PKIX_FALSE,
+ expectedCerts,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout
+ (resourceLimits, 2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth
+ (resourceLimits, 1, plContext));
+
+ subTest("Testing ResourceLimits MaxDepth - ");
+ Test_BuildResult
+ (procParams,
+ PKIX_FALSE,
+ expectedCerts,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout
+ (resourceLimits, 0, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth
+ (resourceLimits, 0, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime
+ (resourceLimits, 0, plContext));
+
+ subTest("Testing ResourceLimits No checking - ");
+ Test_BuildResult
+ (procParams,
+ testValid,
+ expectedCerts,
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(expectedCerts);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStores);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(ldapCertStore);
+ PKIX_TEST_DECREF_AC(dirNameString);
+ PKIX_TEST_DECREF_AC(trustedCert);
+ PKIX_TEST_DECREF_AC(targetCert);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(checker);
+ PKIX_TEST_DECREF_AC(resourceLimits);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BuildChain_UserChecker");
+
+ return (0);
+
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_buildchain_uchecker.c b/nss/cmd/libpkix/pkix/top/test_buildchain_uchecker.c
new file mode 100644
index 0000000..c84881f
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_buildchain_uchecker.c
@@ -0,0 +1,373 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_buildchain_uchecker.c
+ *
+ * Test BuildChain User Checker function
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+static PKIX_UInt32 numUserCheckerCalled = 0;
+
+static
+void printUsage(void){
+ (void) printf("\nUSAGE:\ttest_buildchain_uchecker [ENE|EE] "
+ "[-|[F]] "
+ " \n\n");
+ (void) printf
+ ("Builds a chain of certificates between "
+ " and \n"
+ "using the certs and CRLs in .\n"
+ "If is not an empty string, its value is used as\n"
+ "user defined checker's critical extension OID.\n"
+ "A - for is no OID and F is for supportingForward.\n"
+ "If ENE is specified, then an Error is Not Expected.\n"
+ "If EE is specified, an Error is Expected.\n");
+}
+
+static PKIX_Error *
+testUserChecker(
+ PKIX_CertChainChecker *checker,
+ PKIX_PL_Cert *cert,
+ PKIX_List *unresExtOIDs,
+ void **pNBIOContext,
+ void *plContext)
+{
+ numUserCheckerCalled++;
+ return(0);
+}
+
+int test_buildchain_uchecker(int argc, char *argv[])
+{
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_CertChainChecker *checker = NULL;
+ char *dirName = NULL;
+ PKIX_PL_String *dirNameString = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *certStores = NULL;
+ char * asciiResult = NULL;
+ PKIX_Boolean result;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ PKIX_Boolean supportForward = PKIX_FALSE;
+ PKIX_List *expectedCerts = NULL;
+ PKIX_List *userOIDs = NULL;
+ PKIX_PL_OID *oid = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_PL_String *actualCertsString = NULL;
+ PKIX_PL_String *expectedCertsString = NULL;
+ char *actualCertsAscii = NULL;
+ char *expectedCertsAscii = NULL;
+ char *oidString = NULL;
+ void *buildState = NULL; /* needed by pkix_build for non-blocking I/O */
+ void *nbioContext = NULL; /* needed by pkix_build for non-blocking I/O */
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5){
+ printUsage();
+ return (0);
+ }
+
+ startTests("BuildChain_UserChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2+j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2+j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ /* OID specified at argv[3+j] */
+
+ if (*argv[3+j] != '-') {
+
+ if (*argv[3+j] == 'F') {
+ supportForward = PKIX_TRUE;
+ oidString = argv[3+j]+1;
+ } else {
+ oidString = argv[3+j];
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create
+ (&userOIDs, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (oidString, &oid, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (userOIDs, (PKIX_PL_Object *)oid, plContext));
+ PKIX_TEST_DECREF_BC(oid);
+ }
+
+ subTest(argv[1+j]);
+
+ dirName = argv[4+j];
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&expectedCerts, plContext));
+
+ chainLength = argc - j - 5;
+
+ for (k = 0; k < chainLength; k++){
+
+ dirCert = createCert(dirName, argv[5+k+j], plContext);
+
+ if (k == (chainLength - 1)){
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)dirCert, plContext));
+ trustedCert = dirCert;
+ } else {
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (expectedCerts,
+ (PKIX_PL_Object *)dirCert,
+ plContext));
+
+ if (k == 0){
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)dirCert,
+ plContext));
+ targetCert = dirCert;
+ }
+ }
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ /* create processing params with list of trust anchors */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert
+ (trustedCert, &anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (anchors, (PKIX_PL_Object *)anchor, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create
+ (anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetCertificate
+ (certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ProcessingParams_SetTargetCertConstraints
+ (procParams, certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_Create
+ (testUserChecker,
+ supportForward,
+ PKIX_FALSE,
+ userOIDs,
+ NULL,
+ &checker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertChainChecker
+ (procParams, checker, plContext));
+
+
+ /* create CertStores */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ dirName,
+ 0,
+ &dirNameString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
+ (dirNameString, &certStore, plContext));
+
+#if 0
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create
+ (&certStore, plContext));
+#endif
+
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStores, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (certStores, (PKIX_PL_Object *)certStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores
+ (procParams, certStores, plContext));
+
+ /* build cert chain using processing params and return buildResult */
+
+ pkixTestErrorResult = PKIX_BuildChain
+ (procParams,
+ &nbioContext,
+ &buildState,
+ &buildResult,
+ NULL,
+ plContext);
+
+ if (testValid == PKIX_TRUE) { /* ENE */
+ if (pkixTestErrorResult){
+ (void) printf("UNEXPECTED RESULT RECEIVED!\n");
+ } else {
+ (void) printf("EXPECTED RESULT RECEIVED!\n");
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ }
+ } else { /* EE */
+ if (pkixTestErrorResult){
+ (void) printf("EXPECTED RESULT RECEIVED!\n");
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ } else {
+ testError("UNEXPECTED RESULT RECEIVED");
+ }
+ }
+
+ if (buildResult){
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_BuildResult_GetCertChain
+ (buildResult, &certs, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ printf("\n");
+
+ for (i = 0; i < numCerts; i++){
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_GetItem
+ (certs,
+ i,
+ (PKIX_PL_Object**)&cert,
+ plContext));
+
+ asciiResult = PKIX_Cert2ASCII(cert);
+
+ printf("CERT[%d]:\n%s\n", i, asciiResult);
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Free(asciiResult, plContext));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Object_Equals
+ ((PKIX_PL_Object*)certs,
+ (PKIX_PL_Object*)expectedCerts,
+ &result,
+ plContext));
+
+ if (!result){
+ testError("BUILT CERTCHAIN IS "
+ "NOT THE ONE THAT WAS EXPECTED");
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)certs,
+ &actualCertsString,
+ plContext));
+
+ actualCertsAscii = PKIX_String2ASCII
+ (actualCertsString, plContext);
+ if (actualCertsAscii == NULL){
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)expectedCerts,
+ &expectedCertsString,
+ plContext));
+
+ expectedCertsAscii = PKIX_String2ASCII
+ (expectedCertsString, plContext);
+ if (expectedCertsAscii == NULL){
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ (void) printf("Actual value:\t%s\n", actualCertsAscii);
+ (void) printf("Expected value:\t%s\n",
+ expectedCertsAscii);
+
+ if (chainLength - 1 != numUserCheckerCalled) {
+ pkixTestErrorMsg =
+ "PKIX user defined checker not called";
+ }
+
+ goto cleanup;
+ }
+
+ }
+
+cleanup:
+ PKIX_PL_Free(asciiResult, plContext);
+ PKIX_PL_Free(actualCertsAscii, plContext);
+ PKIX_PL_Free(expectedCertsAscii, plContext);
+
+ PKIX_TEST_DECREF_AC(actualCertsString);
+ PKIX_TEST_DECREF_AC(expectedCertsString);
+ PKIX_TEST_DECREF_AC(expectedCerts);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(certStores);
+ PKIX_TEST_DECREF_AC(dirNameString);
+ PKIX_TEST_DECREF_AC(trustedCert);
+ PKIX_TEST_DECREF_AC(targetCert);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(buildResult);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(userOIDs);
+ PKIX_TEST_DECREF_AC(checker);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BuildChain_UserChecker");
+
+ return (0);
+
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_customcrlchecker.c b/nss/cmd/libpkix/pkix/top/test_customcrlchecker.c
new file mode 100644
index 0000000..9baeadd
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_customcrlchecker.c
@@ -0,0 +1,464 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_customcrlchecker.c
+ *
+ * Test Custom CRL Checking
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_MAX_CERTS 10
+#define PKIX_TEST_COLLECTIONCERTSTORE_NUM_CRLS 5
+
+static void *plContext = NULL;
+char *dirName = NULL; /* also used in callback */
+
+static
+void printUsage1(char *pName){
+ printf("\nUSAGE: %s test-purpose [ENE|EE] ", pName);
+ printf("cert [certs].\n");
+}
+
+static
+void printUsageMax(PKIX_UInt32 numCerts){
+ printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n",
+ numCerts, PKIX_TEST_MAX_CERTS);
+}
+
+static PKIX_Error *
+getCRLCallback(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *crlSelector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ char *crlFileNames[] = {"chem.crl",
+ "phys.crl",
+ "prof.crl",
+ "sci.crl",
+ "test.crl",
+ 0 };
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_UInt32 i = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&crlList, plContext));
+
+ while (crlFileNames[i]) {
+
+ crl = createCRL(dirName, crlFileNames[i++], plContext);
+
+ if (crl != NULL) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (crlList, (PKIX_PL_Object *)crl, plContext));
+
+ PKIX_TEST_DECREF_BC(crl);
+ }
+ }
+
+ *pCrlList = crlList;
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (0); /* this function is called by libpkix */
+
+}
+
+static PKIX_Error *
+getCRLContinue(
+ PKIX_CertStore *store,
+ PKIX_CRLSelector *crlSelector,
+ void **pNBIOContext,
+ PKIX_List **pCrlList,
+ void *plContext)
+{
+ return (NULL);
+}
+
+static PKIX_Error *
+getCertCallback(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *certSelector,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ return (NULL);
+}
+
+static PKIX_Error *
+getCertContinue(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *certSelector,
+ void **pNBIOContext,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ return (NULL);
+}
+
+static PKIX_Error *
+testCRLSelectorMatchCallback(
+ PKIX_CRLSelector *selector,
+ PKIX_PL_CRL *crl,
+ void *plContext)
+{
+ PKIX_ComCRLSelParams *comCrlSelParams = NULL;
+ PKIX_List *issuerList = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+ PKIX_PL_X500Name *crlIssuer = NULL;
+ PKIX_UInt32 numIssuers = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_Boolean result = PKIX_FALSE;
+ PKIX_Error *error = NULL;
+ char *errorText = "Not an error, CRL Select mismatch";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Custom_Selector_MatchCallback");
+
+ if (selector != NULL) {
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CRLSelector_GetCommonCRLSelectorParams
+ (selector, &comCrlSelParams, plContext));
+ }
+
+ if (crl != NULL) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetIssuer
+ (crl, &crlIssuer, plContext));
+ }
+
+ if (comCrlSelParams != NULL) {
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCRLSelParams_GetIssuerNames
+ (comCrlSelParams, &issuerList, plContext));
+ }
+
+ if (issuerList != NULL) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (issuerList, &numIssuers, plContext));
+
+ for (i = 0; i < numIssuers; i++){
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
+ (issuerList,
+ i, (PKIX_PL_Object **)&issuer,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals
+ ((PKIX_PL_Object *)crlIssuer,
+ (PKIX_PL_Object *)issuer,
+ &result,
+ plContext));
+
+ if (result != PKIX_TRUE) {
+ break;
+ }
+
+ if (i == numIssuers-1) {
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_Error_Create
+ (0,
+ NULL,
+ NULL,
+ PKIX_TESTNOTANERRORCRLSELECTMISMATCH,
+ &error,
+ plContext));
+
+ PKIX_TEST_DECREF_AC(issuer);
+ issuer = NULL;
+ break;
+ }
+
+ PKIX_TEST_DECREF_AC(issuer);
+
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(comCrlSelParams);
+ PKIX_TEST_DECREF_AC(crlIssuer);
+ PKIX_TEST_DECREF_AC(issuer);
+ PKIX_TEST_DECREF_AC(issuerList);
+
+ PKIX_TEST_RETURN();
+
+ return (error);
+
+}
+
+static PKIX_Error *
+testAddIssuerName(PKIX_ComCRLSelParams *comCrlSelParams, char *issuerName)
+{
+ PKIX_PL_String *issuerString = NULL;
+ PKIX_PL_X500Name *issuer = NULL;
+ PKIX_UInt32 length = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ComCRLSelParams_AddIssuerName");
+
+ length = PL_strlen(issuerName);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_UTF8,
+ issuerName,
+ length,
+ &issuerString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(issuerString,
+ &issuer,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_AddIssuerName
+ (comCrlSelParams, issuer, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(issuerString);
+ PKIX_TEST_DECREF_AC(issuer);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+static PKIX_Error *
+testCustomCertStore(PKIX_ValidateParams *valParams)
+{
+ PKIX_CertStore_CRLCallback crlCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ char *issuerName1 = "cn=science,o=mit,c=us";
+ char *issuerName2 = "cn=physics,o=mit,c=us";
+ char *issuerName3 = "cn=prof noall,o=mit,c=us";
+ char *issuerName4 = "cn=testing CRL,o=test,c=us";
+ PKIX_ComCRLSelParams *comCrlSelParams = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_UInt32 numCrl = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CollectionCertStore_Create");
+
+ /* Create CRLSelector, link in CollectionCertStore */
+
+ subTest("PKIX_ComCRLSelParams_AddIssuerNames");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create
+ (&comCrlSelParams, plContext));
+
+
+ testAddIssuerName(comCrlSelParams, issuerName1);
+ testAddIssuerName(comCrlSelParams, issuerName2);
+ testAddIssuerName(comCrlSelParams, issuerName3);
+ testAddIssuerName(comCrlSelParams, issuerName4);
+
+
+ subTest("PKIX_CRLSelector_SetCommonCRLSelectorParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create
+ (testCRLSelectorMatchCallback,
+ NULL,
+ &crlSelector,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_SetCommonCRLSelectorParams
+ (crlSelector, comCrlSelParams, plContext));
+
+ /* Create CertStore, link in CRLSelector */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams
+ (valParams, &procParams, plContext));
+
+ subTest("PKIX_CertStore_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_Create
+ (getCertCallback,
+ getCRLCallback,
+ getCertContinue,
+ getCRLContinue,
+ NULL, /* trustCallback */
+ (PKIX_PL_Object *)crlSelector, /* fake */
+ PKIX_FALSE, /* cacheFlag */
+ PKIX_TRUE, /* localFlag */
+ &certStore,
+ plContext));
+
+
+ subTest("PKIX_ProcessingParams_AddCertStore");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore
+ (procParams, certStore, plContext));
+
+ subTest("PKIX_ProcessingParams_SetRevocationEnabled");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
+ (procParams, PKIX_TRUE, plContext));
+
+ subTest("PKIX_CertStore_GetCRLCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback
+ (certStore,
+ &crlCallback,
+ NULL));
+
+ subTest("Getting CRL by CRL Callback");
+ PKIX_TEST_EXPECT_NO_ERROR(crlCallback
+ (certStore,
+ crlSelector,
+ &nbioContext,
+ &crlList,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength
+ (crlList,
+ &numCrl,
+ plContext));
+
+ if (numCrl != PKIX_TEST_COLLECTIONCERTSTORE_NUM_CRLS) {
+ pkixTestErrorMsg = "unexpected CRL number mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(crlList);
+ PKIX_TEST_DECREF_AC(comCrlSelParams);
+ PKIX_TEST_DECREF_AC(crlSelector);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+/*
+ * Validate Certificate Chain with Certificate Revocation List
+ * Certificate Chain is built based on input certs' sequence.
+ * CRL is fetched from the directory specified in CollectionCertStore.
+ * while CollectionCertStore is linked in CertStore Object which then
+ * linked in ProcessParam. During validation, CRLChecker will invoke
+ * the crlCallback (this test uses PKIX_PL_CollectionCertStore_GetCRL)
+ * to get CRL data for revocation check.
+ * This test set criteria in CRLSelector which is linked in
+ * CommonCRLSelectorParam. When CRL data is fetched into cache for
+ * revocation check, CRL's are filtered based on the criteria set.
+ */
+
+int test_customcrlchecker(int argc, char *argv[]){
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *certNames[PKIX_TEST_MAX_CERTS];
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ char *anchorName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ startTests("CRL Checker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2+j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2+j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ chainLength = (argc - j) - 5;
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ }
+
+ for (i = 0; i < chainLength; i++) {
+
+ certNames[i] = argv[(5 + j) +i];
+ certs[i] = NULL;
+ }
+
+ dirName = argv[3+j];
+
+ subTest(argv[1+j]);
+
+ subTest("Custom-CRL-Checker - Create Cert Chain");
+
+ chain = createCertChainPlus
+ (dirName, certNames, certs, chainLength, plContext);
+
+ subTest("Custom-CRL-Checker - Create Params");
+
+ anchorName = argv[4+j];
+
+ valParams = createValidateParams
+ (dirName,
+ anchorName,
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("Custom-CRL-Checker - Set Processing Params for CertStore");
+
+ testCustomCertStore(valParams);
+
+ subTest("Custom-CRL-Checker - Validate Chain");
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CRL Checker");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_defaultcrlchecker2stores.c b/nss/cmd/libpkix/pkix/top/test_defaultcrlchecker2stores.c
new file mode 100644
index 0000000..81690c2
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_defaultcrlchecker2stores.c
@@ -0,0 +1,241 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_defaultcrlchecker2stores.c
+ *
+ * Test Default CRL with multiple CertStore Checking
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_MAX_CERTS 10
+
+static void *plContext = NULL;
+
+static
+void printUsage1(char *pName){
+ printf("\nUSAGE: %s test-purpose [ENE|EE] ", pName);
+ printf("crl-directory cert [certs].\n");
+}
+
+static
+void printUsageMax(PKIX_UInt32 numCerts){
+ printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n",
+ numCerts, PKIX_TEST_MAX_CERTS);
+}
+
+static PKIX_Error *
+getCertCallback(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *certSelector,
+ PKIX_List **pCerts,
+ void *plContext)
+{
+ return (NULL);
+}
+
+static PKIX_Error *
+testDefaultMultipleCertStores(PKIX_ValidateParams *valParams,
+ char *crlDir1,
+ char *crlDir2)
+{
+ PKIX_PL_String *dirString1 = NULL;
+ PKIX_PL_String *dirString2 = NULL;
+ PKIX_CertStore *certStore1 = NULL;
+ PKIX_CertStore *certStore2 = NULL;
+ PKIX_List *certStoreList = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CollectionCertStore_Create");
+
+ /* Create CollectionCertStore */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ crlDir1,
+ 0,
+ &dirString1,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
+ (dirString1,
+ &certStore1,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII,
+ crlDir2,
+ 0,
+ &dirString2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
+ (dirString2,
+ &certStore2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams
+ (valParams, &procParams, plContext));
+
+ /* Add multiple CollectionCertStores */
+
+ subTest("PKIX_ProcessingParams_SetCertStores");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStoreList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (certStoreList, (PKIX_PL_Object *)certStore1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores
+ (procParams, certStoreList, plContext));
+
+ subTest("PKIX_ProcessingParams_AddCertStore");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore
+ (procParams, certStore2, plContext));
+
+ subTest("PKIX_ProcessingParams_SetRevocationEnabled");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
+ (procParams, PKIX_TRUE, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString1);
+ PKIX_TEST_DECREF_AC(dirString2);
+ PKIX_TEST_DECREF_AC(certStore1);
+ PKIX_TEST_DECREF_AC(certStore2);
+ PKIX_TEST_DECREF_AC(certStoreList);
+ PKIX_TEST_DECREF_AC(procParams);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+/*
+ * Validate Certificate Chain with Certificate Revocation List
+ * Certificate Chain is build based on input certs' sequence.
+ * CRL is fetched from the directory specified in CollectionCertStore.
+ * while CollectionCertStore is linked in CertStore Object which then
+ * linked in ProcessParam. During validation, CRLChecker will invoke
+ * the crlCallback (this test uses PKIX_PL_CollectionCertStore_GetCRL)
+ * to get CRL data for revocation check.
+ * This test gets CRL's from two CertStores, each has a valid CRL
+ * required for revocation check to pass.
+ */
+
+int test_defaultcrlchecker2stores(int argc, char *argv[]){
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *certNames[PKIX_TEST_MAX_CERTS];
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ char *dirName = NULL;
+ char *anchorName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 6) {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ startTests("CRL Checker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2+j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2+j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ chainLength = (argc - j) - 7;
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ }
+
+ for (i = 0; i < chainLength; i++) {
+
+ certNames[i] = argv[(7+j)+i];
+ certs[i] = NULL;
+ }
+
+
+ subTest(argv[1+j]);
+
+ subTest("Default-CRL-Checker");
+
+ subTest("Default-CRL-Checker - Create Cert Chain");
+
+ dirName = argv[3+j];
+
+ chain = createCertChainPlus
+ (dirName, certNames, certs, chainLength, plContext);
+
+ subTest("Default-CRL-Checker - Create Params");
+
+ anchorName = argv[6+j];
+
+ valParams = createValidateParams
+ (dirName,
+ anchorName,
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("Multiple-CertStores");
+
+ testDefaultMultipleCertStores(valParams, argv[4+j], argv[5+j]);
+
+ subTest("Default-CRL-Checker - Validate Chain");
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)verifyTree, &verifyString, plContext));
+ (void) printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(chain);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CRL Checker");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_ocsp.c b/nss/cmd/libpkix/pkix/top/test_ocsp.c
new file mode 100644
index 0000000..98fd21e
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_ocsp.c
@@ -0,0 +1,316 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_ocspchecker.c
+ *
+ * Test OcspChecker function
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static
+void printUsage(void){
+ (void) printf("\nUSAGE:\nOcspChecker -d TestName "
+ "[ENE|EE] "
+ "\n\n");
+ (void) printf
+ ("Validates a chain of certificates between "
+ " and \n"
+ "using the certs and CRLs in and "
+ "pkcs11 db from . "
+ "If ENE is specified,\n"
+ "then an Error is Not Expected. "
+ "If EE is specified, an Error is Expected.\n");
+}
+
+static
+char *createFullPathName(
+ char *dirName,
+ char *certFile,
+ void *plContext)
+{
+ PKIX_UInt32 certFileLen;
+ PKIX_UInt32 dirNameLen;
+ char *certPathName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certFileLen = PL_strlen(certFile);
+ dirNameLen = PL_strlen(dirName);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc
+ (dirNameLen + certFileLen + 2,
+ (void **)&certPathName,
+ plContext));
+
+ PL_strcpy(certPathName, dirName);
+ PL_strcat(certPathName, "/");
+ PL_strcat(certPathName, certFile);
+ printf("certPathName = %s\n", certPathName);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (certPathName);
+}
+
+static PKIX_Error *
+testDefaultCertStore(PKIX_ValidateParams *valParams, char *crlDir)
+{
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_Date *validity = NULL;
+ PKIX_List *revCheckers = NULL;
+ PKIX_RevocationChecker *revChecker = NULL;
+ PKIX_PL_Object *revCheckerContext = NULL;
+ PKIX_OcspChecker *ocspChecker = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CollectionCertStoreContext_Create");
+
+ /* Create CollectionCertStore */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, crlDir, 0, &dirString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
+ (dirString, &certStore, plContext));
+
+ /* Create CertStore */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams
+ (valParams, &procParams, plContext));
+
+ subTest("PKIX_ProcessingParams_AddCertStore");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore
+ (procParams, certStore, plContext));
+
+ subTest("PKIX_ProcessingParams_SetRevocationEnabled");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
+ (procParams, PKIX_FALSE, plContext));
+
+ /* create current Date */
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Date_CreateFromPRTime
+ (PR_Now(), &validity, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ /* create revChecker */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_OcspChecker_Initialize
+ (validity,
+ NULL, /* pwArg */
+ NULL, /* Use default responder */
+ &revChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_RevocationChecker_GetRevCheckerContext
+ (revChecker, &revCheckerContext, plContext));
+
+ /* Check that this object is a ocsp checker */
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_CheckType
+ (revCheckerContext, PKIX_OCSPCHECKER_TYPE, plContext));
+
+ ocspChecker = (PKIX_OcspChecker *)revCheckerContext;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_OcspChecker_SetVerifyFcn
+ (ocspChecker,
+ PKIX_PL_OcspResponse_UseBuildChain,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (revCheckers, (PKIX_PL_Object *)revChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers
+ (procParams, revCheckers, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(revChecker);
+ PKIX_TEST_DECREF_AC(ocspChecker);
+ PKIX_TEST_DECREF_AC(validity);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+int test_ocsp(int argc, char *argv[]){
+
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ PKIX_List *chainCerts = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ char *dirCertName = NULL;
+ char *anchorCertName = NULL;
+ char *dirName = NULL;
+ char *databaseDir = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("OcspChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2+j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2+j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ subTest(argv[1+j]);
+
+ dirName = argv[3+j];
+
+ chainLength = argc - j - 5;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&chainCerts, plContext));
+
+ for (k = 0; k < chainLength; k++) {
+
+ dirCert = createCert(dirName, argv[5+k+j], plContext);
+
+ if (k == 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
+ ((PKIX_PL_Object *)dirCert, plContext));
+ targetCert = dirCert;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (chainCerts, (PKIX_PL_Object *)dirCert, plContext));
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ /* create processing params with list of trust anchors */
+
+ anchorCertName = argv[4+j];
+ trustedCert = createCert(dirName, anchorCertName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert
+ (trustedCert, &anchor, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (anchors, (PKIX_PL_Object *)anchor, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create
+ (anchors, &procParams, plContext));
+
+ /* create CertSelector with target certificate in params */
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ComCertSelParams_SetCertificate
+ (certSelParams, targetCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_Create
+ (NULL, NULL, &certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams
+ (certSelector, certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_ProcessingParams_SetTargetCertConstraints
+ (procParams, certSelector, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_Create
+ (procParams, chainCerts, &valParams, plContext));
+
+ testDefaultCertStore(valParams, dirName);
+
+ pkixTestErrorResult = PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext);
+
+
+ if (pkixTestErrorResult) {
+ if (testValid == PKIX_FALSE) { /* EE */
+ (void) printf("EXPECTED ERROR RECEIVED!\n");
+ } else { /* ENE */
+ testError("UNEXPECTED ERROR RECEIVED");
+ }
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult);
+ } else {
+ if (testValid == PKIX_TRUE) { /* ENE */
+ (void) printf("EXPECTED SUCCESSFUL VALIDATION!\n");
+ } else { /* EE */
+ (void) printf("UNEXPECTED SUCCESSFUL VALIDATION!\n");
+ }
+ }
+
+ subTest("Displaying VerifyTree");
+
+ if (verifyTree == NULL) {
+ (void) printf("VerifyTree is NULL\n");
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)verifyTree, &verifyString, plContext));
+ (void) printf("verifyTree is\n%s\n",
+ verifyString->escAsciiString);
+ PKIX_TEST_DECREF_BC(verifyString);
+ PKIX_TEST_DECREF_BC(verifyTree);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(chainCerts);
+ PKIX_TEST_DECREF_AC(anchors);
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(trustedCert);
+ PKIX_TEST_DECREF_AC(targetCert);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("OcspChecker");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_policychecker.c b/nss/cmd/libpkix/pkix/top/test_policychecker.c
new file mode 100644
index 0000000..2b59c69
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_policychecker.c
@@ -0,0 +1,562 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_policychecker.c
+ *
+ * Test Policy Checking
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_MAX_CERTS 10
+
+static void *plContext = NULL;
+
+static
+void printUsage(char *testname) {
+ char *fmt =
+ "USAGE: %s testname"
+ " [ENE|EE] \"{OID[:OID]*}\" [A|E|P] cert [cert]*\n"
+ "(The quotes are needed around the OID argument for dbx.)\n"
+ "(The optional arg A indicates initialAnyPolicyInhibit.)\n"
+ "(The optional arg E indicates initialExplicitPolicy.)\n"
+ "(The optional arg P indicates initialPolicyMappingInhibit.)\n";
+ printf(fmt, testname);
+}
+
+static
+void printUsageMax(PKIX_UInt32 numCerts)
+{
+ printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n",
+ numCerts, PKIX_TEST_MAX_CERTS);
+}
+
+static
+PKIX_List *policySetParse(char *policyString)
+{
+ char *p = NULL;
+ char *oid = NULL;
+ char c = '\0';
+ PKIX_Boolean validString = PKIX_FALSE;
+ PKIX_PL_OID *plOID = NULL;
+ PKIX_List *policySet = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ p = policyString;
+
+ /*
+ * There may or may not be quotes around the initial-policy-set
+ * string. If they are omitted, dbx will strip off the curly braces.
+ * If they are included, dbx will strip off the quotes, but if you
+ * are running directly from a script, without dbx, the quotes will
+ * not be stripped. We need to be able to handle both cases.
+ */
+ if (*p == '"') {
+ p++;
+ }
+
+ if ('{' != *p++) {
+ return (NULL);
+ }
+ oid = p;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&policySet, plContext));
+
+ /* scan to the end of policyString */
+ while (!validString) {
+ /* scan to the end of the current OID string */
+ c = *oid;
+ while ((c != '\0') && (c != ':') && (c != '}')) {
+ c = *++oid;
+ }
+
+ if ((c != ':') || (c != '}')) {
+ *oid = '\0'; /* store a null terminator */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (p, &plOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (policySet,
+ (PKIX_PL_Object *)plOID,
+ plContext));
+
+ PKIX_TEST_DECREF_BC(plOID);
+ plOID = NULL;
+ if (c == '}') {
+ /*
+ * Any exit but this one means
+ * we were given a badly-formed string.
+ */
+ validString = PKIX_TRUE;
+ }
+ p = ++oid;
+ }
+ }
+
+
+cleanup:
+ if (!validString) {
+ PKIX_TEST_DECREF_AC(plOID);
+ PKIX_TEST_DECREF_AC(policySet);
+ policySet = NULL;
+ }
+
+ PKIX_TEST_RETURN();
+
+ return (policySet);
+}
+
+/*
+ * FUNCTION: treeToStringHelper
+ * This function obtains the string representation of a PolicyNode
+ * Tree and compares it to the expected value.
+ * PARAMETERS:
+ * "parent" - a PolicyNode, the root of a PolicyNodeTree;
+ * must be non-NULL.
+ * "expected" - the desired string.
+ * THREAD SAFETY:
+ * Thread Safe
+ *
+ * Multiple threads can safely call this function without worrying
+ * about conflicts, even if they're operating on the same object.
+ * RETURNS:
+ * Nothing.
+ */
+static void
+treeToStringHelper(PKIX_PolicyNode *parent, char *expected)
+{
+ PKIX_PL_String *stringRep = NULL;
+ char *actual = NULL;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object *)parent, &stringRep, plContext));
+
+ actual = PKIX_String2ASCII(stringRep, plContext);
+ if (actual == NULL){
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ if (PL_strcmp(actual, expected) != 0){
+ testError("unexpected mismatch");
+ (void) printf("Actual value:\t%s\n", actual);
+ (void) printf("Expected value:\t%s\n", expected);
+ }
+
+cleanup:
+
+ PKIX_PL_Free(actual, plContext);
+
+ PKIX_TEST_DECREF_AC(stringRep);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testPass(char *dirName, char *goodInput, char *diffInput, char *dateAscii){
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Basic-Common-Fields ");
+ /*
+ * Tests the Expiration, NameChaining, and Signature Checkers
+ */
+
+ chain = createCertChain(dirName, goodInput, diffInput, plContext);
+
+ valParams = createValidateParams
+ (dirName,
+ goodInput,
+ diffInput,
+ dateAscii,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, NULL, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testNistTest1(char *dirName)
+{
+#define PKIX_TEST_NUM_CERTS 2
+ char *trustAnchor =
+ "TrustAnchorRootCertificate.crt";
+ char *intermediateCert =
+ "GoodCACert.crt";
+ char *endEntityCert =
+ "ValidCertificatePathTest1EE.crt";
+ char *certNames[PKIX_TEST_NUM_CERTS];
+ char *asciiAnyPolicy = "2.5.29.32.0";
+ PKIX_PL_Cert *certs[PKIX_TEST_NUM_CERTS] = { NULL, NULL };
+
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_List *chain = NULL;
+ PKIX_PL_OID *anyPolicyOID = NULL;
+ PKIX_List *initialPolicies = NULL;
+ char *anchorName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("testNistTest1: Creating the cert chain");
+ /*
+ * Create a chain, but don't include the first certName.
+ * That's the anchor, and is supplied separately from
+ * the chain.
+ */
+ certNames[0] = intermediateCert;
+ certNames[1] = endEntityCert;
+ chain = createCertChainPlus
+ (dirName, certNames, certs, PKIX_TEST_NUM_CERTS, plContext);
+
+ subTest("testNistTest1: Creating the Validate Parameters");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (asciiAnyPolicy, &anyPolicyOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_Create(&initialPolicies, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (initialPolicies, (PKIX_PL_Object *)anyPolicyOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable
+ (initialPolicies, plContext));
+
+ valParams = createValidateParams
+ (dirName,
+ trustAnchor,
+ NULL,
+ NULL,
+ initialPolicies,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("testNistTest1: Validating the chain");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, NULL, plContext));
+
+
+cleanup:
+
+ PKIX_PL_Free(anchorName, plContext);
+
+ PKIX_TEST_DECREF_AC(anyPolicyOID);
+ PKIX_TEST_DECREF_AC(initialPolicies);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(chain);
+
+ PKIX_TEST_RETURN();
+}
+
+static
+void testNistTest2(char *dirName)
+{
+#define PKIX_TEST_NUM_CERTS 2
+ char *trustAnchor =
+ "TrustAnchorRootCertificate.crt";
+ char *intermediateCert =
+ "GoodCACert.crt";
+ char *endEntityCert =
+ "ValidCertificatePathTest1EE.crt";
+ char *certNames[PKIX_TEST_NUM_CERTS];
+ char *asciiNist1Policy = "2.16.840.1.101.3.2.1.48.1";
+ PKIX_PL_Cert *certs[PKIX_TEST_NUM_CERTS] = { NULL, NULL };
+
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_List *chain = NULL;
+ PKIX_PL_OID *Nist1PolicyOID = NULL;
+ PKIX_List *initialPolicies = NULL;
+ char *anchorName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("testNistTest2: Creating the cert chain");
+ /*
+ * Create a chain, but don't include the first certName.
+ * That's the anchor, and is supplied separately from
+ * the chain.
+ */
+ certNames[0] = intermediateCert;
+ certNames[1] = endEntityCert;
+ chain = createCertChainPlus
+ (dirName, certNames, certs, PKIX_TEST_NUM_CERTS, plContext);
+
+ subTest("testNistTest2: Creating the Validate Parameters");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
+ (asciiNist1Policy, &Nist1PolicyOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_Create(&initialPolicies, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (initialPolicies, (PKIX_PL_Object *)Nist1PolicyOID, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable
+ (initialPolicies, plContext));
+
+ valParams = createValidateParams
+ (dirName,
+ trustAnchor,
+ NULL,
+ NULL,
+ initialPolicies,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("testNistTest2: Validating the chain");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, NULL, plContext));
+
+
+cleanup:
+
+ PKIX_PL_Free(anchorName, plContext);
+
+ PKIX_TEST_DECREF_AC(Nist1PolicyOID);
+ PKIX_TEST_DECREF_AC(initialPolicies);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(chain);
+
+ PKIX_TEST_RETURN();
+}
+
+static void printValidPolicyTree(PKIX_ValidateResult *valResult)
+{
+ PKIX_PolicyNode* validPolicyTree = NULL;
+ PKIX_PL_String *treeString = NULL;
+
+ PKIX_TEST_STD_VARS();
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateResult_GetPolicyTree
+ (valResult, &validPolicyTree, plContext));
+ if (validPolicyTree) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)validPolicyTree,
+ &treeString,
+ plContext));
+ (void) printf("validPolicyTree is\n\t%s\n",
+ treeString->escAsciiString);
+ } else {
+ (void) printf("validPolicyTree is NULL\n");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(validPolicyTree);
+ PKIX_TEST_DECREF_AC(treeString);
+
+ PKIX_TEST_RETURN();
+}
+
+int test_policychecker(int argc, char *argv[])
+{
+
+ PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
+ PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
+ PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
+ PKIX_Boolean expectedResult = PKIX_FALSE;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 initArgs = 0;
+ PKIX_UInt32 firstCert = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_Int32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_ProcessingParams *procParams = NULL;
+ char *firstTrustAnchor = "yassir2yassir";
+ char *secondTrustAnchor = "yassir2bcn";
+ char *dateAscii = "991201000000Z";
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_List *userInitialPolicySet = NULL; /* List of PKIX_PL_OID */
+ char *certNames[PKIX_TEST_MAX_CERTS];
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_List *chain = NULL;
+ PKIX_Error *validationError = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ char *dirName = NULL;
+ char *dataCentralDir = NULL;
+ char *anchorName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /*
+ * Perform hard-coded tests if no command line args.
+ * If command line args are provided, they must be:
+ * arg[1]: test name
+ * arg[2]: "ENE" or "EE", for "expect no error" or "expect error"
+ * arg[3]: directory for certificates
+ * arg[4]: user-initial-policy-set, consisting of braces
+ * containing zero or more OID sequences, separated by commas
+ * arg[5]: (optional) "E", indicating initialExplicitPolicy
+ * arg[firstCert]: the path and filename of the trust anchor certificate
+ * arg[firstCert+1..(n-1)]: successive certificates in the chain
+ * arg[n]: the end entity certificate
+ *
+ * Example: test_policychecker test1EE ENE
+ * {2.5.29.32.0,2.5.29.32.3.6} Anchor CA EndEntity
+ */
+
+ dirName = argv[3+j];
+ dataCentralDir = argv[4+j];
+
+ if (argc <= 5 || ((6 == argc) && (j))) {
+
+ testPass
+ (dataCentralDir,
+ firstTrustAnchor,
+ secondTrustAnchor,
+ dateAscii);
+
+ testNistTest1(dirName);
+
+ testNistTest2(dirName);
+
+ goto cleanup;
+ }
+
+ if (argc < (7 + j)) {
+ printUsage(argv[0]);
+ pkixTestErrorMsg = "Invalid command line arguments.";
+ goto cleanup;
+ }
+
+ if (PORT_Strcmp(argv[2+j], "ENE") == 0) {
+ expectedResult = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2+j], "EE") == 0) {
+ expectedResult = PKIX_FALSE;
+ } else {
+ printUsage(argv[0]);
+ pkixTestErrorMsg = "Invalid command line arguments.";
+ goto cleanup;
+ }
+
+ userInitialPolicySet = policySetParse(argv[5+j]);
+ if (!userInitialPolicySet) {
+ printUsage(argv[0]);
+ pkixTestErrorMsg = "Invalid command line arguments.";
+ goto cleanup;
+ }
+
+ for (initArgs = 0; initArgs < 3; initArgs++) {
+ if (PORT_Strcmp(argv[6+j+initArgs], "A") == 0) {
+ initialAnyPolicyInhibit = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[6+j+initArgs], "E") == 0) {
+ initialExplicitPolicy = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[6+j+initArgs], "P") == 0) {
+ initialPolicyMappingInhibit = PKIX_TRUE;
+ } else {
+ break;
+ }
+ }
+
+ firstCert = initArgs + j + 6;
+ chainLength = argc - (firstCert + 1);
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ pkixTestErrorMsg = "Invalid command line arguments.";
+ goto cleanup;
+ }
+
+ /*
+ * Create a chain, but don't include the first certName.
+ * That's the anchor, and is supplied separately from
+ * the chain.
+ */
+ for (i = 0; i < chainLength; i++) {
+
+ certNames[i] = argv[i + (firstCert + 1)];
+ certs[i] = NULL;
+ }
+ chain = createCertChainPlus
+ (dirName, certNames, certs, chainLength, plContext);
+
+ subTest(argv[1+j]);
+
+ valParams = createValidateParams
+ (dirName,
+ argv[firstCert],
+ NULL,
+ NULL,
+ userInitialPolicySet,
+ initialPolicyMappingInhibit,
+ initialAnyPolicyInhibit,
+ initialExplicitPolicy,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ if (expectedResult == PKIX_TRUE) {
+ subTest(" (expecting successful validation)");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+
+ printValidPolicyTree(valResult);
+
+ } else {
+ subTest(" (expecting validation to fail)");
+ validationError = PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext);
+ if (!validationError) {
+ printValidPolicyTree(valResult);
+ pkixTestErrorMsg = "Should have thrown an error here.";
+ }
+ PKIX_TEST_DECREF_BC(validationError);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)verifyTree, &verifyString, plContext));
+ (void) printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+
+cleanup:
+
+ PKIX_PL_Free(anchorName, plContext);
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(userInitialPolicySet);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(validationError);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("PolicyChecker");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_subjaltnamechecker.c b/nss/cmd/libpkix/pkix/top/test_subjaltnamechecker.c
new file mode 100644
index 0000000..239e1e1
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_subjaltnamechecker.c
@@ -0,0 +1,266 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_subjaltnamechecker.c
+ *
+ * Test Subject Alternative Name Checking
+ *
+ */
+
+/*
+ * There is no subjaltnamechecker. Instead, targetcertchecker is doing
+ * the job for checking subject alternative names' validity. For testing,
+ * in order to enter names with various type, we create this test excutable
+ * to parse different scenario.
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+#define PKIX_TEST_MAX_CERTS 10
+
+static void *plContext = NULL;
+
+static
+void printUsage1(char *pName){
+ printf("\nUSAGE: %s test-name [ENE|EE] ", pName);
+ printf("cert [certs].\n");
+}
+
+static
+void printUsage2(char *name) {
+ printf("\ninvalid test-name syntax - %s", name);
+ printf("\ntest-name syntax: [01][DNORU]:+...");
+ printf("\n [01] 1 - match all; 0 - match one");
+ printf("\n name - type can be specified as");
+ printf("\n [DNORU] D-Directory name");
+ printf("\n N-DNS name");
+ printf("\n O-OID name");
+ printf("\n R-RFC822 name");
+ printf("\n U-URI name");
+ printf("\n + separator for more names\n\n");
+}
+
+static
+void printUsageMax(PKIX_UInt32 numCerts){
+ printf("\nUSAGE ERROR: number of certs %d exceed maximum %d\n",
+ numCerts, PKIX_TEST_MAX_CERTS);
+}
+
+static
+PKIX_UInt32 getNameType(char *name){
+ PKIX_UInt32 nameType;
+
+ PKIX_TEST_STD_VARS();
+
+ switch (*name) {
+ case 'D':
+ nameType = PKIX_DIRECTORY_NAME;
+ break;
+ case 'N':
+ nameType = PKIX_DNS_NAME;
+ break;
+ case 'O':
+ nameType = PKIX_OID_NAME;
+ break;
+ case 'R':
+ nameType = PKIX_RFC822_NAME;
+ break;
+ case 'U':
+ nameType = PKIX_URI_NAME;
+ break;
+ default:
+ printUsage2(name);
+ nameType = 0xFFFF;
+ }
+
+ goto cleanup;
+
+cleanup:
+ PKIX_TEST_RETURN();
+ return (nameType);
+}
+
+int test_subjaltnamechecker(int argc, char *argv[]){
+
+ PKIX_List *chain = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *selParams = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_GeneralName *name = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ char *certNames[PKIX_TEST_MAX_CERTS];
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ char *nameStr;
+ char *nameEnd;
+ char *names[PKIX_TEST_MAX_CERTS];
+ PKIX_UInt32 numNames = 0;
+ PKIX_UInt32 nameType;
+ PKIX_Boolean matchAll = PKIX_TRUE;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ char *dirName = NULL;
+ char *anchorName = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ startTests("SubjAltNameConstraintChecker");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ j++; /* skip test-purpose string */
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2+j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2+j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ /* taking out leading and trailing ", if any */
+ nameStr = argv[1+j];
+ subTest(nameStr);
+ if (*nameStr == '"'){
+ nameStr++;
+ nameEnd = nameStr;
+ while (*nameEnd != '"' && *nameEnd != '\0') {
+ nameEnd++;
+ }
+ *nameEnd = '\0';
+ }
+
+ /* extract first [0|1] inidcating matchAll or not */
+ matchAll = (*nameStr == '0')?PKIX_FALSE:PKIX_TRUE;
+ nameStr++;
+
+ numNames = 0;
+ while (*nameStr != '\0') {
+ names[numNames++] = nameStr;
+ while (*nameStr != '+' && *nameStr != '\0') {
+ nameStr++;
+ }
+ if (*nameStr == '+') {
+ *nameStr = '\0';
+ nameStr++;
+ }
+ }
+
+ chainLength = (argc - j) - 4;
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ }
+
+ for (i = 0; i < chainLength; i++) {
+ certNames[i] = argv[(4+j)+i];
+ certs[i] = NULL;
+ }
+
+ /* SubjAltName for validation */
+
+ subTest("Add Subject Alt Name for NameConstraint checking");
+
+ subTest("Create Selector and ComCertSelParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create
+ (NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create
+ (&selParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_CertSelector_SetCommonCertSelectorParams
+ (selector, selParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetMatchAllSubjAltNames");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetMatchAllSubjAltNames
+ (selParams, matchAll, plContext));
+
+ subTest("PKIX_ComCertSelParams_AddSubjAltName(s)");
+ for (i = 0; i < numNames; i++) {
+ nameType = getNameType(names[i]);
+ if (nameType == 0xFFFF) {
+ return (0);
+ }
+ nameStr = names[i] + 2;
+ name = createGeneralName(nameType, nameStr, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_AddSubjAltName
+ (selParams, name, plContext));
+ PKIX_TEST_DECREF_BC(name);
+ }
+
+ subTest("SubjAltName-Constraints - Create Cert Chain");
+
+ dirName = argv[3+j];
+
+ chain = createCertChainPlus
+ (dirName, certNames, certs, chainLength, plContext);
+
+ subTest("SubjAltName-Constraints - Create Params");
+
+ valParams = createValidateParams
+ (dirName,
+ argv[4+j],
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("PKIX_ValidateParams_getProcessingParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams
+ (valParams, &procParams, plContext));
+
+ subTest("PKIX_ProcessingParams_SetTargetCertConstraints");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints
+ (procParams, selector, plContext));
+
+ subTest("Subject Alt Name - Validate Chain");
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+ }
+
+cleanup:
+
+ PKIX_PL_Free(anchorName, plContext);
+
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(chain);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(selector);
+ PKIX_TEST_DECREF_AC(selParams);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(name);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("SubjAltNameConstraintsChecker");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_validatechain.c b/nss/cmd/libpkix/pkix/top/test_validatechain.c
new file mode 100644
index 0000000..33e4fa9
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_validatechain.c
@@ -0,0 +1,232 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_validatechain.c
+ *
+ * Test ValidateChain function
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static
+void printUsage(void){
+ (void) printf("\nUSAGE:\nvalidateChain TestName [ENE|EE] "
+ " \n\n");
+ (void) printf
+ ("Validates a chain of certificates between "
+ " and \n"
+ "using the certs and CRLs in . "
+ "If ENE is specified,\n"
+ "then an Error is Not Expected. "
+ "If EE is specified, an Error is Expected.\n");
+}
+
+static
+char *createFullPathName(
+ char *dirName,
+ char *certFile,
+ void *plContext)
+{
+ PKIX_UInt32 certFileLen;
+ PKIX_UInt32 dirNameLen;
+ char *certPathName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certFileLen = PL_strlen(certFile);
+ dirNameLen = PL_strlen(dirName);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc
+ (dirNameLen + certFileLen + 2,
+ (void **)&certPathName,
+ plContext));
+
+ PL_strcpy(certPathName, dirName);
+ PL_strcat(certPathName, "/");
+ PL_strcat(certPathName, certFile);
+ printf("certPathName = %s\n", certPathName);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (certPathName);
+}
+
+static PKIX_Error *
+testDefaultCertStore(PKIX_ValidateParams *valParams, char *crlDir)
+{
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_Date *validity = NULL;
+ PKIX_List *revCheckers = NULL;
+ PKIX_RevocationChecker *ocspChecker = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CollectionCertStoreContext_Create");
+
+ /* Create CollectionCertStore */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
+ (PKIX_ESCASCII, crlDir, 0, &dirString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
+ (dirString, &certStore, plContext));
+
+ /* Create CertStore */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams
+ (valParams, &procParams, plContext));
+
+ subTest("PKIX_ProcessingParams_AddCertStore");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore
+ (procParams, certStore, plContext));
+
+ subTest("PKIX_ProcessingParams_SetRevocationEnabled");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
+ (procParams, PKIX_TRUE, plContext));
+
+ /* create current Date */
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Date_CreateFromPRTime
+ (PR_Now(), &validity, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));
+
+ /* create revChecker */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_OcspChecker_Initialize
+ (validity,
+ NULL, /* pwArg */
+ NULL, /* Use default responder */
+ &ocspChecker,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
+ (revCheckers, (PKIX_PL_Object *)ocspChecker, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers
+ (procParams, revCheckers, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(revCheckers);
+ PKIX_TEST_DECREF_AC(ocspChecker);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+int test_validatechain(int argc, char *argv[]){
+
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 k = 0;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_Boolean testValid = PKIX_TRUE;
+ PKIX_List *chainCerts = NULL;
+ PKIX_PL_Cert *dirCert = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+ char *dirCertName = NULL;
+ char *anchorCertName = NULL;
+ char *dirName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("ValidateChain");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ENE = expect no error; EE = expect error */
+ if (PORT_Strcmp(argv[2+j], "ENE") == 0) {
+ testValid = PKIX_TRUE;
+ } else if (PORT_Strcmp(argv[2+j], "EE") == 0) {
+ testValid = PKIX_FALSE;
+ } else {
+ printUsage();
+ return (0);
+ }
+
+ subTest(argv[1+j]);
+
+ dirName = argv[3+j];
+
+ chainLength = argc - j - 5;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&chainCerts, plContext));
+
+ for (k = 0; k < chainLength; k++) {
+
+ dirCert = createCert(dirName, argv[5+k+j], plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR
+ (PKIX_List_AppendItem
+ (chainCerts, (PKIX_PL_Object *)dirCert, plContext));
+
+ PKIX_TEST_DECREF_BC(dirCert);
+ }
+
+ valParams = createValidateParams
+ (dirName,
+ argv[4+j],
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chainCerts,
+ plContext);
+
+ testDefaultCertStore(valParams, dirName);
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain
+ (valParams, &valResult, &verifyTree, plContext));
+ }
+
+ subTest("Displaying VerifyNode objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
+ ((PKIX_PL_Object*)verifyTree, &verifyString, plContext));
+ (void) printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+
+ PKIX_TEST_DECREF_AC(chainCerts);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ValidateChain");
+
+ return (0);
+}
diff --git a/nss/cmd/libpkix/pkix/top/test_validatechain_NB.c b/nss/cmd/libpkix/pkix/top/test_validatechain_NB.c
new file mode 100644
index 0000000..d5b5ff6
--- /dev/null
+++ b/nss/cmd/libpkix/pkix/top/test_validatechain_NB.c
@@ -0,0 +1,369 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * test_validatechain_NB.c
+ *
+ * Test ValidateChain (nonblocking I/O) function
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static
+void printUsage(void){
+ (void) printf("\nUSAGE:\ntest_validateChain_NB TestName [ENE|EE] "
+ "