summaryrefslogtreecommitdiffstats
path: root/security/nss/cmd/lib
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--security/nss/cmd/lib/Makefile48
-rw-r--r--security/nss/cmd/lib/basicutil.c868
-rw-r--r--security/nss/cmd/lib/basicutil.h139
-rw-r--r--security/nss/cmd/lib/berparse.c388
-rw-r--r--security/nss/cmd/lib/derprint.c596
-rw-r--r--security/nss/cmd/lib/exports.gyp27
-rw-r--r--security/nss/cmd/lib/ffs.c21
-rw-r--r--security/nss/cmd/lib/lib.gyp37
-rw-r--r--security/nss/cmd/lib/manifest.mn42
-rw-r--r--security/nss/cmd/lib/moreoids.c167
-rw-r--r--security/nss/cmd/lib/pk11table.c1517
-rw-r--r--security/nss/cmd/lib/pk11table.h178
-rw-r--r--security/nss/cmd/lib/pppolicy.c263
-rw-r--r--security/nss/cmd/lib/secpwd.c163
-rw-r--r--security/nss/cmd/lib/secutil.c4735
-rw-r--r--security/nss/cmd/lib/secutil.h450
-rw-r--r--security/nss/cmd/libpkix/Makefile46
-rw-r--r--security/nss/cmd/libpkix/manifest.mn11
-rw-r--r--security/nss/cmd/libpkix/perf/Makefile44
-rw-r--r--security/nss/cmd/libpkix/perf/libpkix_buildthreads.c337
-rw-r--r--security/nss/cmd/libpkix/perf/manifest.mn22
-rw-r--r--security/nss/cmd/libpkix/perf/nss_threads.c158
-rw-r--r--security/nss/cmd/libpkix/pkix/Makefile46
-rw-r--r--security/nss/cmd/libpkix/pkix/certsel/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/certsel/manifest.mn22
-rw-r--r--security/nss/cmd/libpkix/pkix/certsel/test_certselector.c1677
-rw-r--r--security/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c800
-rw-r--r--security/nss/cmd/libpkix/pkix/checker/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/checker/manifest.mn20
-rw-r--r--security/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c185
-rw-r--r--security/nss/cmd/libpkix/pkix/crlsel/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/crlsel/manifest.mn22
-rw-r--r--security/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c406
-rw-r--r--security/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c168
-rw-r--r--security/nss/cmd/libpkix/pkix/manifest.mn11
-rw-r--r--security/nss/cmd/libpkix/pkix/params/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/params/manifest.mn24
-rw-r--r--security/nss/cmd/libpkix/pkix/params/test_procparams.c478
-rw-r--r--security/nss/cmd/libpkix/pkix/params/test_resourcelimits.c99
-rw-r--r--security/nss/cmd/libpkix/pkix/params/test_trustanchor.c251
-rw-r--r--security/nss/cmd/libpkix/pkix/params/test_valparams.c261
-rw-r--r--security/nss/cmd/libpkix/pkix/results/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/results/manifest.mn24
-rw-r--r--security/nss/cmd/libpkix/pkix/results/test_buildresult.c212
-rw-r--r--security/nss/cmd/libpkix/pkix/results/test_policynode.c612
-rw-r--r--security/nss/cmd/libpkix/pkix/results/test_valresult.c199
-rw-r--r--security/nss/cmd/libpkix/pkix/results/test_verifynode.c112
-rw-r--r--security/nss/cmd/libpkix/pkix/store/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/store/manifest.mn20
-rw-r--r--security/nss/cmd/libpkix/pkix/store/test_store.c194
-rw-r--r--security/nss/cmd/libpkix/pkix/top/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/top/manifest.mn34
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_basicchecker.c238
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_basicconstraintschecker.c145
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_buildchain.c418
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_buildchain_partialchain.c725
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_buildchain_resourcelimits.c438
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_buildchain_uchecker.c327
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_customcrlchecker.c435
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_defaultcrlchecker2stores.c230
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_ocsp.c288
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_policychecker.c535
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_subjaltnamechecker.c261
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_validatechain.c221
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_validatechain_NB.c351
-rw-r--r--security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.c233
-rw-r--r--security/nss/cmd/libpkix/pkix/util/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix/util/manifest.mn24
-rw-r--r--security/nss/cmd/libpkix/pkix/util/test_error.c385
-rw-r--r--security/nss/cmd/libpkix/pkix/util/test_list.c765
-rw-r--r--security/nss/cmd/libpkix/pkix/util/test_list2.c118
-rw-r--r--security/nss/cmd/libpkix/pkix/util/test_logger.c314
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/Makefile46
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/manifest.mn11
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/manifest.mn25
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/test_colcertstore.c247
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/test_ekuchecker.c275
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/test_httpcertstore.c300
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/test_pk11certstore.c580
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/module/test_socket.c571
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/manifest.mn29
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_authorityinfoaccess.c105
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_cert.c2088
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_crl.c302
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_crlentry.c208
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_date.c106
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_generalname.c123
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_nameconstraints.c127
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_subjectinfoaccess.c121
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/pki/test_x500name.c169
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/Makefile45
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/manifest.mn38
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/stress_test.c146
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_bigint.c189
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_bytearray.c231
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_hashtable.c380
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_mem.c133
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_monitorlock.c104
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_mutex.c102
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_mutex2.c166
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_mutex3.c104
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_object.c281
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_oid.c212
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_rwlock.c204
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_string.c434
-rw-r--r--security/nss/cmd/libpkix/pkix_pl/system/test_string2.c337
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkixlibs.mk27
-rwxr-xr-xsecurity/nss/cmd/libpkix/pkixrules.mk7
-rw-r--r--security/nss/cmd/libpkix/pkixutil/Makefile43
-rw-r--r--security/nss/cmd/libpkix/pkixutil/manifest.mn41
-rw-r--r--security/nss/cmd/libpkix/pkixutil/pkixutil.c299
-rw-r--r--security/nss/cmd/libpkix/sample_apps/Makefile46
-rw-r--r--security/nss/cmd/libpkix/sample_apps/build_chain.c242
-rw-r--r--security/nss/cmd/libpkix/sample_apps/dumpcert.c182
-rw-r--r--security/nss/cmd/libpkix/sample_apps/dumpcrl.c186
-rw-r--r--security/nss/cmd/libpkix/sample_apps/manifest.mn23
-rw-r--r--security/nss/cmd/libpkix/sample_apps/validate_chain.c220
-rw-r--r--security/nss/cmd/libpkix/testutil/Makefile50
-rw-r--r--security/nss/cmd/libpkix/testutil/config.mk8
-rw-r--r--security/nss/cmd/libpkix/testutil/manifest.mn27
-rw-r--r--security/nss/cmd/libpkix/testutil/pkixutil.def48
-rw-r--r--security/nss/cmd/libpkix/testutil/testutil.c576
-rw-r--r--security/nss/cmd/libpkix/testutil/testutil.h292
-rw-r--r--security/nss/cmd/libpkix/testutil/testutil_nss.c579
-rw-r--r--security/nss/cmd/libpkix/testutil/testutil_nss.h119
127 files changed, 34589 insertions, 0 deletions
diff --git a/security/nss/cmd/lib/Makefile b/security/nss/cmd/lib/Makefile
new file mode 100644
index 0000000000..b1f9d1a31e
--- /dev/null
+++ b/security/nss/cmd/lib/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). #
+#######################################################################
+
+
+
diff --git a/security/nss/cmd/lib/basicutil.c b/security/nss/cmd/lib/basicutil.c
new file mode 100644
index 0000000000..3ccacd7356
--- /dev/null
+++ b/security/nss/cmd/lib/basicutil.c
@@ -0,0 +1,868 @@
+/* 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 <stdarg.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#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; i < cmd->numCommands; i++) {
+ if (cmd->commands[i].flag) /* single character option ? */
+ optstring[j++] = cmd->commands[i].flag;
+ if (cmd->commands[i].longform)
+ lcmd++;
+ }
+ for (i = 0; i < cmd->numOptions; 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; j < lcmd && i < cmd->numCommands; 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; j < lopt && i < cmd->numOptions; 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; i < cmd->numCommands; 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; i < cmd->numOptions; 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 errLenInt = PR_GetErrorTextLength();
+ size_t errLen = errLenInt < 0 ? 0 : (size_t)errLenInt;
+ 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) {
+ snprintf(dst, 3, "%02x", *src++);
+ }
+ }
+}
+
+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)
+{
+ unsigned 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; i < srcdest->len; 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; i < srcdest->len; 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;
+}
+
+SECItem *
+SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
+{
+ int i = 0;
+ int byteval = 0;
+ int tmp = PORT_Strlen(str);
+
+ PORT_Assert(item);
+
+ if ((tmp % 2) != 0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ item = SECITEM_AllocItem(arena, item, tmp / 2);
+ if (item == NULL) {
+ return NULL;
+ }
+
+ 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 {
+ if (!arena) {
+ SECITEM_FreeItem(item, PR_FALSE);
+ }
+ return NULL;
+ }
+
+ byteval = byteval * 16 + tmp;
+ if ((i % 2) != 0) {
+ item->data[i / 2] = byteval;
+ byteval = 0;
+ }
+ i++;
+ }
+
+ return item;
+}
+
+/* mapping between ECCurveName enum and SECOidTags */
+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_WTLS_1 */
+ SEC_OID_UNKNOWN, /* ECCurve_WTLS_8 */
+ SEC_OID_UNKNOWN, /* ECCurve_WTLS_9 */
+ SEC_OID_CURVE25519,
+ SEC_OID_UNKNOWN /* ECCurve_pastLastCurve */
+};
+
+SECStatus
+SECU_ecName2params(ECCurveName curve, SECItem *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;
+ }
+
+ if (SECITEM_AllocItem(NULL, params, (2 + oidData->oid.len)) == NULL) {
+ return SECFailure;
+ }
+ /*
+ * 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;
+}
diff --git a/security/nss/cmd/lib/basicutil.h b/security/nss/cmd/lib/basicutil.h
new file mode 100644
index 0000000000..ba76b1798f
--- /dev/null
+++ b/security/nss/cmd/lib/basicutil.h
@@ -0,0 +1,139 @@
+/* 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 "ecl-exp.h"
+#include <stdio.h>
+
+#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);
+
+/* Dump contents of private key */
+extern int SECU_PrintPrivateKey(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);
+
+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);
+
+/*
+** Read a hex string into a SecItem.
+*/
+extern SECItem *SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item,
+ const char *str);
+
+extern SECStatus SECU_ecName2params(ECCurveName curve, SECItem *params);
+
+/*
+ *
+ * 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/security/nss/cmd/lib/berparse.c b/security/nss/cmd/lib/berparse.c
new file mode 100644
index 0000000000..8cd1ebae08
--- /dev/null
+++ b/security/nss/cmd/lib/berparse.c
@@ -0,0 +1,388 @@
+/* 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/security/nss/cmd/lib/derprint.c b/security/nss/cmd/lib/derprint.c
new file mode 100644
index 0000000000..b86179e30a
--- /dev/null
+++ b/security/nss/cmd/lib/derprint.c
@@ -0,0 +1,596 @@
+/* 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"
+
+#include <stdint.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:
+ /* If the most significant bit of data[0] is 1, val would be negative.
+ * Treat it as an error.
+ */
+ if (data[0] & 0x80) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ 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;
+
+ if (len == 0) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return -1;
+ }
+ 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;
+ }
+ }
+
+ rv = prettyNewline(out);
+ if (rv < 0)
+ return rv;
+
+ if (raw) {
+ rv = prettyPrintLeaf(out, data, len, level);
+ if (rv < 0)
+ return rv;
+ }
+
+ return 0;
+}
+
+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++;
+ lenLen = 1;
+ 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;
+ if (raw) {
+ unsigned 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;
+ 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 > end || slen > (end - data)) {
+ 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/security/nss/cmd/lib/exports.gyp b/security/nss/cmd/lib/exports.gyp
new file mode 100644
index 0000000000..f6b469397f
--- /dev/null
+++ b/security/nss/cmd/lib/exports.gyp
@@ -0,0 +1,27 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'cmd_lib_exports',
+ 'type': 'none',
+ 'copies': [
+ {
+ 'files': [
+ 'basicutil.h',
+ 'pk11table.h',
+ 'secutil.h'
+ ],
+ 'destination': '<(nss_private_dist_dir)/<(module)'
+ }
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss'
+ }
+}
diff --git a/security/nss/cmd/lib/ffs.c b/security/nss/cmd/lib/ffs.c
new file mode 100644
index 0000000000..d1cbf67e28
--- /dev/null
+++ b/security/nss/cmd/lib/ffs.c
@@ -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/. */
+#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/security/nss/cmd/lib/lib.gyp b/security/nss/cmd/lib/lib.gyp
new file mode 100644
index 0000000000..c5835a8696
--- /dev/null
+++ b/security/nss/cmd/lib/lib.gyp
@@ -0,0 +1,37 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'sectool',
+ 'type': 'static_library',
+ 'standalone_static_library': 1,
+ 'sources': [
+ 'basicutil.c',
+ 'derprint.c',
+ 'ffs.c',
+ 'moreoids.c',
+ 'pk11table.c',
+ 'pppolicy.c',
+ 'secpwd.c',
+ 'secutil.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:nss_exports'
+ ]
+ }
+ ],
+ 'target_defaults': {
+ 'defines': [
+ 'NSPR20',
+ 'NSS_USE_STATIC_LIBS'
+ ]
+ },
+ 'variables': {
+ 'module': 'nss'
+ }
+} \ No newline at end of file
diff --git a/security/nss/cmd/lib/manifest.mn b/security/nss/cmd/lib/manifest.mn
new file mode 100644
index 0000000000..86233e63d7
--- /dev/null
+++ b/security/nss/cmd/lib/manifest.mn
@@ -0,0 +1,42 @@
+#
+# 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
+SHARED_LIBRARY = $(NULL)
+
+# 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
+
+USE_STATIC_LIBS = 1
diff --git a/security/nss/cmd/lib/moreoids.c b/security/nss/cmd/lib/moreoids.c
new file mode 100644
index 0000000000..ed5022cef2
--- /dev/null
+++ b/security/nss/cmd/lib/moreoids.c
@@ -0,0 +1,167 @@
+/* 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/security/nss/cmd/lib/pk11table.c b/security/nss/cmd/lib/pk11table.c
new file mode 100644
index 0000000000..06f7591394
--- /dev/null
+++ b/security/nss/cmd/lib/pk11table.c
@@ -0,0 +1,1517 @@
+/* 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_F_P, 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_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_NSS_DB, Attribute, None),
+ mkEntry2(CKA_NSS_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_AES_CMAC, Mechanism),
+ mkEntry(CKM_AES_CMAC_GENERAL, 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_NSS_PBE_SHA1_DES_CBC, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_40_BIT_RC4, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_128_BIT_RC4, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC, Mechanism),
+ mkEntry(CKM_NSS_PBE_SHA1_HMAC_KEY_GEN, Mechanism),
+ mkEntry(CKM_NSS_PBE_MD5_HMAC_KEY_GEN, Mechanism),
+ mkEntry(CKM_NSS_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_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 unsigned 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)
+{
+ unsigned 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);
+}
+
+unsigned int
+totalKnownType(ConstType type)
+{
+ unsigned int count = 0;
+ unsigned int i;
+
+ for (i = 0; i < constCount; i++) {
+ if (consts[i].type == type)
+ count++;
+ }
+ return count;
+}
diff --git a/security/nss/cmd/lib/pk11table.h b/security/nss/cmd/lib/pk11table.h
new file mode 100644
index 0000000000..3dea8204d1
--- /dev/null
+++ b/security/nss/cmd/lib/pk11table.h
@@ -0,0 +1,178 @@
+/* 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 <pkcs11.h>
+#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 unsigned 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 unsigned int totalKnownType(ConstType type);
+
+#endif /* _PK11_TABLE_H_ */
diff --git a/security/nss/cmd/lib/pppolicy.c b/security/nss/cmd/lib/pppolicy.c
new file mode 100644
index 0000000000..aaf45599d2
--- /dev/null
+++ b/security/nss/cmd/lib/pppolicy.c
@@ -0,0 +1,263 @@
+/* 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/security/nss/cmd/lib/secpwd.c b/security/nss/cmd/lib/secpwd.c
new file mode 100644
index 0000000000..472bc2615b
--- /dev/null
+++ b/security/nss/cmd/lib/secpwd.c
@@ -0,0 +1,163 @@
+/* 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 <termios.h>
+#include <unistd.h> /* for isatty() */
+#endif
+
+#if defined(_WINDOWS)
+#include <conio.h>
+#include <io.h>
+#define QUIET_FGETS quiet_fgets
+static char *quiet_fgets(char *buf, int length, FILE *input);
+#else
+#define QUIET_FGETS fgets
+#endif
+
+#if !defined(_WINDOWS)
+static void
+echoOff(int fd)
+{
+ if (isatty(fd)) {
+ struct termios tio;
+ tcgetattr(fd, &tio);
+ tio.c_lflag &= ~ECHO;
+ tcsetattr(fd, TCSAFLUSH, &tio);
+ }
+}
+
+static void
+echoOn(int fd)
+{
+ 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[500] = { '\0' }; /* ensure EOF doesn't return junk */
+
+ for (;;) {
+ /* Prompt for password */
+ if (isTTY) {
+ fprintf(output, "%s", prompt);
+ fflush(output);
+ echoOff(infd);
+ }
+
+ if (QUIET_FGETS(phrase, sizeof(phrase), input) == NULL) {
+ return NULL;
+ }
+
+ 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 NULL;
+ 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/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c
new file mode 100644
index 0000000000..de10ce9186
--- /dev/null
+++ b/security/nss/cmd/lib/secutil.c
@@ -0,0 +1,4735 @@
+/* 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 <stdarg.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#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;
+
+/* The minimum password/pin length (in Unicode characters) in FIPS mode,
+ * defined in lib/softoken/pkcs11i.h. */
+#define FIPS_MIN_PIN 7
+
+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 ((i < nb) && (phrases[i] == '\r' || phrases[i] == '\n')) {
+ phrases[i++] = '\0';
+ }
+ /* now analyze the current passphrase */
+ phrase = &phrases[startphrase];
+ if (!tokenName)
+ break;
+ if (PORT_Strncmp(phrase, tokenName, tokenLen))
+ continue;
+ phraseLen = PORT_Strlen(phrase);
+ if (phraseLen < (tokenLen + 1))
+ continue;
+ if (phrase[tokenLen] != ':')
+ continue;
+ phrase = &phrase[tokenLen + 1];
+ break;
+
+ } while (i < nb);
+
+ phrase = PORT_Strdup((char *)phrase);
+ PORT_Free(phrases);
+ return phrase;
+}
+
+char *
+SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg)
+{
+ char prompt[255];
+ secuPWData *pwdata = (secuPWData *)arg;
+ secuPWData pwnull = { PW_NONE, 0 };
+ secuPWData pwxtrn = { PW_EXTERNAL, "external" };
+
+ if (pwdata == NULL)
+ pwdata = &pwnull;
+
+ if (PK11_ProtectedAuthenticationPath(slot)) {
+ pwdata = &pwxtrn;
+ }
+ if (retry && pwdata->source != PW_NONE) {
+ PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n");
+ return NULL;
+ }
+
+ switch (pwdata->source) {
+ case PW_NONE:
+ snprintf(prompt, sizeof(prompt), "Enter Password or Pin for \"%s\":",
+ PK11_GetTokenName(slot));
+ return SECU_GetPasswordString(NULL, prompt);
+ case PW_FROMFILE:
+ return SECU_FilePasswd(slot, retry, pwdata->data);
+ case PW_EXTERNAL:
+ snprintf(prompt, sizeof(prompt),
+ "Press Enter, then enter PIN for \"%s\" on external device.\n",
+ PK11_GetTokenName(slot));
+ char *pw = SECU_GetPasswordString(NULL, prompt);
+ PORT_Free(pw);
+ /* 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 */
+ if (PK11_IsFIPS()) {
+ PR_fprintf(PR_STDERR,
+ "Enter a password which will be used to encrypt your keys.\n"
+ "The password should be at least %d characters long,\n"
+ "and should consist of at least three character classes.\n"
+ "The available character classes are: digits (0-9), ASCII\n"
+ "lowercase letters, ASCII uppercase letters, ASCII\n"
+ "non-alphanumeric characters, and non-ASCII characters.\n\n"
+ "If an ASCII uppercase letter appears at the beginning of\n"
+ "the password, it is not counted toward its character class.\n"
+ "Similarly, if a digit appears at the end of the password,\n"
+ "it is not counted toward its character class.\n\n",
+ FIPS_MIN_PIN);
+ } else {
+ 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);
+ rv = SECFailure;
+ goto done;
+ }
+ } else
+ break;
+
+ PORT_Free(oldpw);
+ }
+
+ newpw = secu_InitSlotPassword(slot, PR_FALSE, &newpwdata);
+
+ rv = PK11_ChangePW(slot, oldpw, newpw);
+ if (rv != SECSuccess) {
+ PR_fprintf(PR_STDERR, "Failed to change password.\n");
+ } else {
+ PR_fprintf(PR_STDOUT, "Password changed successfully.\n");
+ }
+
+ PORT_Memset(oldpw, 0, PL_strlen(oldpw));
+ PORT_Free(oldpw);
+
+done:
+ if (newpw) {
+ PORT_Memset(newpw, 0, PL_strlen(newpw));
+ PORT_Free(newpw);
+ }
+ return rv;
+}
+
+struct matchobj {
+ SECItem index;
+ char *nname;
+ PRBool found;
+};
+
+char *
+SECU_DefaultSSLDir(void)
+{
+ char *dir;
+ static char sslDir[1000];
+
+ dir = PR_GetEnvSecure("SSL_DIR");
+ if (!dir)
+ return NULL;
+
+ if (strlen(dir) >= PR_ARRAY_SIZE(sslDir)) {
+ return NULL;
+ }
+ snprintf(sslDir, sizeof(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] == '/')
+ snprintf(path, sizeof(path), "%s%s", dir, filename);
+ else
+ snprintf(path, sizeof(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_GetEnvSecure("HOME");
+ if (!home)
+ home = "";
+
+ if (*home && home[strlen(home) - 1] == '/')
+ snprintf(buf, sizeof(buf), "%.900s%s", home, dir);
+ else
+ snprintf(buf, sizeof(buf), "%.900s/%s", home, dir);
+ } else {
+ snprintf(buf, sizeof(buf), "%.900s", base);
+ if (buf[strlen(buf) - 1] == '/')
+ buf[strlen(buf) - 1] = 0;
+ }
+
+ initted = PR_TRUE;
+ return buf;
+}
+
+SECStatus
+SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii,
+ PRBool warnOnPrivateKeyInAsciiFile)
+{
+ SECStatus rv;
+ if (ascii) {
+ /* First convert ascii to binary */
+ SECItem filedata;
+
+ /* Read in ascii data */
+ rv = SECU_FileToItem(&filedata, inFile);
+ if (rv != SECSuccess)
+ return rv;
+ if (!filedata.data) {
+ fprintf(stderr, "unable to read data from input file\n");
+ return SECFailure;
+ }
+ /* need one additional byte for zero terminator */
+ rv = SECITEM_ReallocItemV2(NULL, &filedata, filedata.len + 1);
+ if (rv != SECSuccess) {
+ PORT_Free(filedata.data);
+ return rv;
+ }
+ char *asc = (char *)filedata.data;
+ asc[filedata.len - 1] = '\0';
+
+ if (warnOnPrivateKeyInAsciiFile && strstr(asc, "PRIVATE KEY")) {
+ fprintf(stderr, "Warning: ignoring private key. Consider to use "
+ "pk12util.\n");
+ }
+
+ char *body;
+ /* 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 {
+ body = asc;
+ }
+
+ /* 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
+
+/*
+ * remove the tag and length and just leave the bare BER data
+ */
+SECStatus
+SECU_StripTagAndLength(SECItem *i)
+{
+ unsigned int start;
+ PRBool isIndefinite;
+
+ if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ isIndefinite = (i->data[1] == 0x80);
+ start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
+ if (i->len < start) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ i->data += start;
+ i->len -= start;
+ /* we are using indefinite encoding, drop the trailing zero */
+ if (isIndefinite) {
+ if (i->len <= 1) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ /* verify tags are zero */
+ if ((i->data[i->len - 1] != 0) || (i->data[i->len - 2] != 0)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ i->len -= 2;
+ }
+
+ return SECSuccess;
+}
+
+/*
+ * Create a new SECItem which points to the current BER tag and length with
+ * all it's data. For indefinite encoding, this will also include the trailing
+ * indefinite markers
+ * The 'in' item is advanced to point to the next BER tag.
+ * You don't want to use this in an actual BER/DER parser as NSS already
+ * has 3 to choose from)
+ */
+SECStatus
+SECU_ExtractBERAndStep(SECItem *in, SECItem *out)
+{
+ if (!in || !in->data || in->len < 2) { /* must be at least tag and length */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ *out = *in;
+
+ /* first handle indefinite encoding */
+ if (out->data[1] == 0x80) {
+ SECItem this = *out;
+ SECItem next;
+ this.data += 2;
+ this.len -= 2;
+ out->len = 2;
+ /* walk through all the entries until we find the '0' */
+ while ((this.len >= 2) && (this.data[0] != 0)) {
+ SECStatus rv = SECU_ExtractBERAndStep(&this, &next);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ out->len += next.len;
+ }
+ if ((this.len < 2) || ((this.data[0] != 0) && (this.data[1] != 0))) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ out->len += 2; /* include the trailing zeros */
+ in->data += out->len;
+ in->len -= out->len;
+ return SECSuccess;
+ }
+
+ /* now handle normal DER encoding */
+ if (out->data[1] & 0x80) {
+ unsigned int i;
+ unsigned int lenlen = out->data[1] & 0x7f;
+ unsigned int len = 0;
+ if (lenlen > sizeof out->len) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ for (i = 0; i < lenlen; i++) {
+ len = (len << 8) | out->data[2 + i];
+ }
+ out->len = len + lenlen + 2;
+ } else {
+ out->len = out->data[1] + 2;
+ }
+ if (out->len > in->len) {
+ /* we've ran into a truncated file */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ in->data += out->len;
+ in->len -= out->len;
+ 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;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &tmp)) {
+ break;
+ }
+ 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 */
+SECOidTag
+SECU_PrintEncodedObjectID(FILE *out, const SECItem *i, const char *m, int level)
+{
+ SECItem my = *i;
+ SECOidTag tag = SEC_OID_UNKNOWN;
+ if (SECSuccess == SECU_StripTagAndLength(&my))
+ tag = SECU_PrintObjectID(out, &my, m, level);
+ return tag;
+}
+
+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 & 0xFF))
+ 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(&param, 0, sizeof param);
+
+ rv = SEC_QuickDERDecodeItem(pool, &param,
+ 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, &param.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, &param.maskAlg->algorithm,
+ "Mask algorithm", level + 1);
+ rv = SEC_QuickDERDecodeItem(pool, &maskHashAlg,
+ SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
+ &param.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, &param.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(&param, 0, sizeof param);
+ rv = SEC_QuickDERDecodeItem(pool, &param, secuKDF2Params, value);
+ if (rv == SECSuccess) {
+ SECU_PrintAsHex(out, &param.salt, "Salt", level + 1);
+ SECU_PrintInteger(out, &param.iterationCount, "Iteration Count",
+ level + 1);
+ SECU_PrintInteger(out, &param.keyLength, "Key Length", level + 1);
+ SECU_PrintAlgorithmID(out, &param.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(&param, 0, sizeof param);
+ rv = SEC_QuickDERDecodeItem(pool, &param, secuPBEV2Params, value);
+ if (rv == SECSuccess) {
+ SECU_PrintAlgorithmID(out, &param.kdfAlg, "KDF", level + 1);
+ SECU_PrintAlgorithmID(out, &param.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(&param, 0, sizeof(secuPBEParams));
+ rv = SEC_QuickDERDecodeItem(pool, &param, secuPBEParamsTemp, value);
+ if (rv == SECSuccess) {
+ SECU_PrintAsHex(out, &param.salt, "Salt", level + 1);
+ SECU_PrintInteger(out, &param.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 (a->parameters.len == 0 ||
+ (a->parameters.len == 2 &&
+ PORT_Memcmp(a->parameters.data, "\005\000", 2) == 0)) {
+ /* No arguments or NULL argument */
+ } else if (algtag == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
+ secu_PrintRSAPSSParams(out, &a->parameters, "Parameters", level + 1);
+ } 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) {
+ snprintf(om, sizeof(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;
+ }
+ }
+ }
+ }
+}
+
+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;
+ curveOID.len = PR_MIN(curveOID.len, pk->u.ec.DEREncodedParams.len - 2);
+ SECU_PrintObjectID(out, &curveOID, "Curve", level + 1);
+ }
+}
+
+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;
+
+ case ecKey:
+ secu_PrintECPublicKey(out, pk, "EC Public Key", level + 1);
+ break;
+
+ 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);
+
+ {
+ unsigned int i;
+ for (i = 0; i < c->serialNumber.len; ++i) {
+ unsigned char *chardata = (unsigned char *)(c->serialNumber.data);
+ unsigned char ch = *(chardata + i);
+
+ fprintf(out, "\\x%02x", ch);
+ }
+ 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;
+}
+
+/* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
+int
+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;
+
+ 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;
+}
+
+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;
+}
+
+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 */
+typedef enum {
+ secuPKCS7Unknown = 0,
+ secuPKCS7PKCS12AuthSafe,
+ secuPKCS7PKCS12Safe
+} secuPKCS7State;
+
+static int
+secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, secuPKCS7State,
+ const char *, int);
+static int
+secu_PrintDERPKCS7ContentInfo(FILE *, SECItem *, secuPKCS7State,
+ const char *, int);
+
+/*
+** secu_PrintPKCS7EncContent
+** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
+*/
+static int
+secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
+ secuPKCS7State state, const 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);
+ return 0;
+}
+
+/*
+** secu_PrintRecipientInfo
+** Prints a PKCS7RecipientInfo type
+*/
+static void
+secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info,
+ const 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,
+ const 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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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,
+ secuPKCS7State state, 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) {
+ snprintf(om, sizeof(om), "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ /* Now for the content */
+ rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
+ state, "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) {
+ snprintf(om, sizeof(om), "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ (SECU_PPFunc)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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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 int
+secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
+ secuPKCS7State state, 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) {
+ snprintf(om, sizeof(om), "Recipient Information (%x)", iv);
+ secu_PrintRecipientInfo(out, recInfo, om, level + 2);
+ }
+ }
+
+ return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
+ "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,
+ secuPKCS7State state, 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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(om), "Digest Algorithm (%x)", iv);
+ SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
+ }
+ }
+
+ rv = secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
+ "Encrypted Content Information", level + 1);
+ if (rv)
+ 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) {
+ snprintf(om, sizeof(om), "Certificate (%x)", iv);
+ rv = SECU_PrintSignedData(out, aCert, om, level + 2,
+ (SECU_PPFunc)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) {
+ snprintf(om, sizeof(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) {
+ snprintf(om, sizeof(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 int
+secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
+ secuPKCS7State state, const char *m, int level)
+{
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ SECU_PrintInteger(out, &(src->version), "Version", level + 1);
+
+ return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
+ "Encrypted Content Information", level + 1);
+}
+
+/*
+** secu_PrintPKCS7Digested
+** Pretty print a PKCS7 digested data type (up to version 1).
+*/
+static int
+secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
+ secuPKCS7State state, 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, state,
+ "Content Information", level + 1);
+ SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
+ return 0;
+}
+
+static int
+secu_PrintPKCS12Attributes(FILE *out, SECItem *item, const char *m, int level)
+{
+ SECItem my = *item;
+ SECItem attribute;
+ SECItem attributeID;
+ SECItem attributeValues;
+
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SET)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ level++;
+
+ while (my.len) {
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &attribute)) {
+ return SECFailure;
+ }
+ if ((attribute.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&attribute)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ /* attribute ID */
+ if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeID)) {
+ return SECFailure;
+ }
+ if ((attributeID.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OBJECT_ID) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ SECU_PrintEncodedObjectID(out, &attributeID, "Attribute ID", level);
+
+ /* attribute values */
+ if (!attribute.len) { /* skip if there aren't any */
+ continue;
+ }
+ if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeValues)) {
+ return SECFailure;
+ }
+ if (SECSuccess != SECU_StripTagAndLength(&attributeValues)) {
+ return SECFailure;
+ }
+ while (attributeValues.len) {
+ SECItem tmp;
+ if (SECSuccess != SECU_ExtractBERAndStep(&attributeValues, &tmp)) {
+ return SECFailure;
+ }
+ SECU_PrintAny(out, &tmp, NULL, level + 1);
+ }
+ }
+ return SECSuccess;
+}
+
+static int
+secu_PrintPKCS12Bag(FILE *out, SECItem *item, const char *desc, int level)
+{
+ SECItem my = *item;
+ SECItem bagID;
+ SECItem bagValue;
+ SECItem bagAttributes;
+ SECOidTag bagTag;
+ SECStatus rv;
+ int i;
+ char *m;
+
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ /* bagId BAG-TYPE.&id ({PKCS12BagSet}) */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagID)) {
+ return SECFailure;
+ }
+ if ((bagID.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OBJECT_ID) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ m = PR_smprintf("%s ID", desc);
+ bagTag = SECU_PrintEncodedObjectID(out, &bagID, m ? m : "Bag ID", level);
+ if (m)
+ PR_smprintf_free(m);
+
+ /* bagValue [0] EXPLICIT BAG-TYPE.&type({PKCS12BagSet}{@bagID}) */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagValue)) {
+ return SECFailure;
+ }
+ if ((bagValue.data[0] & (SEC_ASN1_CLASS_MASK | SEC_ASN1_TAGNUM_MASK)) !=
+ (SEC_ASN1_CONTEXT_SPECIFIC | 0)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ if (SECSuccess != SECU_StripTagAndLength(&bagValue)) {
+ return SECFailure;
+ }
+
+ rv = SECSuccess;
+ switch (bagTag) {
+ case SEC_OID_PKCS12_V1_KEY_BAG_ID:
+ /* Future we need to print out raw private keys. Not a priority since
+ * p12util can't create files with unencrypted private keys, but
+ * some tools can and do */
+ SECU_PrintAny(out, &bagValue, "Private Key", level);
+ break;
+ case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
+ rv = SECU_PrintPrivateKey(out, &bagValue,
+ "Encrypted Private Key", level);
+ break;
+ case SEC_OID_PKCS12_V1_CERT_BAG_ID:
+ rv = secu_PrintPKCS12Bag(out, &bagValue, "Certificate Bag", level + 1);
+ break;
+ case SEC_OID_PKCS12_V1_CRL_BAG_ID:
+ rv = secu_PrintPKCS12Bag(out, &bagValue, "Crl Bag", level + 1);
+ break;
+ case SEC_OID_PKCS12_V1_SECRET_BAG_ID:
+ rv = secu_PrintPKCS12Bag(out, &bagValue, "Secret Bag", level + 1);
+ break;
+ /* from recursive call from CRL and certificate Bag */
+ case SEC_OID_PKCS9_X509_CRL:
+ case SEC_OID_PKCS9_X509_CERT:
+ case SEC_OID_PKCS9_SDSI_CERT:
+ /* unwrap the octect string */
+ rv = SECU_StripTagAndLength(&bagValue);
+ if (rv != SECSuccess) {
+ break;
+ }
+ /* fall through */
+ case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
+ case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
+ case SEC_OID_PKCS12_SDSI_CERT_BAG:
+ if (strcmp(desc, "Crl Bag") == 0) {
+ rv = SECU_PrintSignedData(out, &bagValue, NULL, level + 1,
+ (SECU_PPFunc)SECU_PrintCrl);
+ } else {
+ rv = SECU_PrintSignedData(out, &bagValue, NULL, level + 1,
+ (SECU_PPFunc)SECU_PrintCertificate);
+ }
+ break;
+ case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID:
+ for (i = 1; my.len; i++) {
+ SECItem nextBag;
+ rv = SECU_ExtractBERAndStep(&bagValue, &nextBag);
+ if (rv != SECSuccess) {
+ break;
+ }
+ m = PR_smprintf("Nested Bag %d", i);
+ rv = secu_PrintPKCS12Bag(out, &nextBag,
+ m ? m : "Nested Bag", level + 1);
+ if (m)
+ PR_smprintf_free(m);
+ if (rv != SECSuccess) {
+ break;
+ }
+ }
+ break;
+ default:
+ m = PR_smprintf("%s Value", desc);
+ SECU_PrintAny(out, &bagValue, m ? m : "Bag Value", level);
+ if (m)
+ PR_smprintf_free(m);
+ }
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ /* bagAttributes SET OF PKCS12Attributes OPTIONAL */
+ if (my.len &&
+ (my.data[0] == (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SET))) {
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagAttributes)) {
+ return SECFailure;
+ }
+ m = PR_smprintf("%s Attributes", desc);
+ rv = secu_PrintPKCS12Attributes(out, &bagAttributes,
+ m ? m : "Bag Attributes", level);
+ if (m)
+ PR_smprintf_free(m);
+ }
+ return rv;
+}
+
+static int
+secu_PrintPKCS7Data(FILE *out, SECItem *item, secuPKCS7State state,
+ const char *desc, int level)
+{
+ SECItem my = *item;
+ SECItem nextbag;
+ int i;
+ SECStatus rv;
+
+ /* walk down each safe */
+ switch (state) {
+ case secuPKCS7PKCS12AuthSafe:
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ for (i = 1; my.len; i++) {
+ char *m;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
+ return SECFailure;
+ }
+ m = PR_smprintf("Safe %d", i);
+ rv = secu_PrintDERPKCS7ContentInfo(out, &nextbag,
+ secuPKCS7PKCS12Safe,
+ m ? m : "Safe", level);
+ if (m)
+ PR_smprintf_free(m);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+ case secuPKCS7PKCS12Safe:
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ for (i = 1; my.len; i++) {
+ char *m;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
+ return SECFailure;
+ }
+ m = PR_smprintf("Bag %d", i);
+ rv = secu_PrintPKCS12Bag(out, &nextbag,
+ m ? m : "Bag", level);
+ if (m)
+ PR_smprintf_free(m);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ }
+ return SECSuccess;
+ case secuPKCS7Unknown:
+ SECU_PrintAsHex(out, item, desc, level);
+ break;
+ }
+ return SECSuccess;
+}
+
+/*
+** secu_PrintPKCS7ContentInfo
+** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
+** appropriate function
+*/
+static int
+secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
+ secuPKCS7State state, const 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_UNKNOWN;
+ } 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, "<no content>\n");
+ return 0;
+ }
+
+ rv = 0;
+ switch (kind) {
+ case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
+ rv = secu_PrintPKCS7Signed(out, src->content.signedData,
+ state, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
+ rv = secu_PrintPKCS7Enveloped(out, src->content.envelopedData,
+ state, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
+ rv = secu_PrintPKCS7SignedAndEnveloped(out,
+ src->content.signedAndEnvelopedData,
+ state, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
+ rv = secu_PrintPKCS7Digested(out, src->content.digestedData,
+ state, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
+ rv = secu_PrintPKCS7Encrypted(out, src->content.encryptedData,
+ state, desc, level);
+ break;
+
+ case SEC_OID_PKCS7_DATA:
+ rv = secu_PrintPKCS7Data(out, src->content.data, state, 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).
+*/
+static int
+secu_PrintDERPKCS7ContentInfo(FILE *out, SECItem *der, secuPKCS7State state,
+ const 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, state, m, level);
+ SEC_PKCS7DestroyContentInfo(cinfo);
+ } else {
+ rv = -1;
+ }
+
+ return rv;
+}
+
+int
+SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
+{
+ return secu_PrintDERPKCS7ContentInfo(out, der, secuPKCS7Unknown, m, level);
+}
+
+/*
+** 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 signatureOption)
+{
+ 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 (signatureOption == 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;
+ PK11SlotList *slotList;
+ PRBool falseAttributeFound = PR_FALSE;
+ PRBool trueAttributeFound = PR_FALSE;
+ const char *moz_policy_ca_info = NULL;
+
+ data.data = cert->derCert.data;
+ data.len = cert->derCert.len;
+
+ rv = SECU_PrintSignedData(stdout, &data, label, 0,
+ (SECU_PPFunc)SECU_PrintCertificate);
+ if (rv) {
+ return (SECFailure);
+ }
+
+ slotList = PK11_GetAllSlotsForCert(cert, NULL);
+ if (slotList) {
+ PK11SlotListElement *se = PK11_GetFirstSafe(slotList);
+ for (; se; se = PK11_GetNextSafe(slotList, se, PR_FALSE)) {
+ CK_OBJECT_HANDLE handle = PK11_FindCertInSlot(se->slot, cert, NULL);
+ if (handle != CK_INVALID_HANDLE) {
+ PORT_SetError(0);
+ if (PK11_HasAttributeSet(se->slot, handle,
+ CKA_NSS_MOZILLA_CA_POLICY, PR_FALSE)) {
+ trueAttributeFound = PR_TRUE;
+ } else if (!PORT_GetError()) {
+ falseAttributeFound = PR_TRUE;
+ }
+ }
+ }
+ PK11_FreeSlotList(slotList);
+ }
+
+ if (trueAttributeFound) {
+ moz_policy_ca_info = "true (attribute present)";
+ } else if (falseAttributeFound) {
+ moz_policy_ca_info = "false (attribute present)";
+ } else {
+ moz_policy_ca_info = "false (attribute missing)";
+ }
+ SECU_Indent(stdout, 1);
+ printf("Mozilla-CA-Policy: %s\n", moz_policy_ca_info);
+
+ 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);
+ }
+
+ /* The distrust fields are hard-coded in nssckbi and read-only.
+ * If verifying some cert, with vfychain, for instance, the certificate may
+ * not have a defined slot if not imported. */
+ if (cert->slot != NULL && cert->distrust != NULL) {
+ const unsigned int kDistrustFieldSize = 13;
+ fprintf(stdout, "\n");
+ SECU_Indent(stdout, 1);
+ fprintf(stdout, "%s:\n", "Certificate Distrust Dates");
+ if (cert->distrust->serverDistrustAfter.len == kDistrustFieldSize) {
+ SECU_PrintTimeChoice(stdout,
+ &cert->distrust->serverDistrustAfter,
+ "Server Distrust After", 2);
+ }
+ if (cert->distrust->emailDistrustAfter.len == kDistrustFieldSize) {
+ SECU_PrintTimeChoice(stdout,
+ &cert->distrust->emailDistrustAfter,
+ "E-mail Distrust After", 2);
+ }
+ }
+
+ 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)((char *)node->arg - (char *)NULL);
+ 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;
+ }
+ break;
+ case SEC_ERROR_INADEQUATE_CERT_TYPE:
+ flags = (unsigned int)((char *)node->arg - (char *)NULL);
+ 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;
+ }
+ 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:
+ 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 != SECSuccess) {
+ goto loser;
+ }
+
+ /* Fill out SignedData object */
+ PORT_Memset(sd, 0, sizeof(*sd));
+ sd->data.data = buf;
+ sd->data.len = len;
+ rv = SECITEM_CopyItem(arena, &sd->signature, &it);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+ sd->signature.len <<= 3; /* convert to bit string */
+ rv = SECOID_SetAlgorithmID(arena, &sd->signatureAlgorithm, algID, 0);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
+loser:
+ PORT_Free(it.data);
+ return rv;
+}
+
+/*
+ * 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_FindCertByNicknameOrEmailAddrCX(handle, name, pwarg);
+ 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, "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;
+ }
+
+ if (!PL_strncasecmp(buf, "tls1.3", bufLen)) {
+ *version = SSL_LIBRARY_VERSION_TLS_1_3;
+ return SECSuccess;
+ }
+
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+}
+
+SECStatus
+SECU_ParseSSLVersionRangeString(const char *input,
+ const SSLVersionRange defaultVersionRange,
+ SSLVersionRange *vrange)
+{
+ const char *colonPos;
+ size_t colonIndex;
+ const char *maxStr;
+
+ if (!input || !vrange) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ // We don't support SSL2 any longer.
+ if (defaultVersionRange.min < SSL_LIBRARY_VERSION_3_0 ||
+ defaultVersionRange.max < SSL_LIBRARY_VERSION_3_0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ if (!strcmp(input, ":")) {
+ /* special value, use default */
+ *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 */
+ 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;
+ }
+
+ 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;
+ }
+
+ vrange->max = version;
+ }
+
+ if (vrange->min > vrange->max) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ return SECSuccess;
+}
+
+static SSLNamedGroup
+groupNameToNamedGroup(char *name)
+{
+ if (PL_strlen(name) == 4) {
+ if (!strncmp(name, "P256", 4)) {
+ return ssl_grp_ec_secp256r1;
+ }
+ if (!strncmp(name, "P384", 4)) {
+ return ssl_grp_ec_secp384r1;
+ }
+ if (!strncmp(name, "P521", 4)) {
+ return ssl_grp_ec_secp521r1;
+ }
+ }
+ if (PL_strlen(name) == 6) {
+ if (!strncmp(name, "x25519", 6)) {
+ return ssl_grp_ec_curve25519;
+ }
+ if (!strncmp(name, "FF2048", 6)) {
+ return ssl_grp_ffdhe_2048;
+ }
+ if (!strncmp(name, "FF3072", 6)) {
+ return ssl_grp_ffdhe_3072;
+ }
+ if (!strncmp(name, "FF4096", 6)) {
+ return ssl_grp_ffdhe_4096;
+ }
+ if (!strncmp(name, "FF6144", 6)) {
+ return ssl_grp_ffdhe_6144;
+ }
+ if (!strncmp(name, "FF8192", 6)) {
+ return ssl_grp_ffdhe_8192;
+ }
+ }
+
+ return ssl_grp_none;
+}
+
+static SECStatus
+countItems(const char *arg, unsigned int *numItems)
+{
+ char *str = PORT_Strdup(arg);
+ if (!str) {
+ return SECFailure;
+ }
+ char *p = strtok(str, ",");
+ while (p) {
+ ++(*numItems);
+ p = strtok(NULL, ",");
+ }
+ PORT_Free(str);
+ str = NULL;
+ return SECSuccess;
+}
+
+SECStatus
+parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
+ unsigned int *enabledGroupsCount)
+{
+ SSLNamedGroup *groups;
+ char *str;
+ char *p;
+ unsigned int numValues = 0;
+ unsigned int count = 0;
+
+ if (countItems(arg, &numValues) != SECSuccess) {
+ return SECFailure;
+ }
+ groups = PORT_ZNewArray(SSLNamedGroup, numValues);
+ if (!groups) {
+ return SECFailure;
+ }
+
+ /* Get group names. */
+ str = PORT_Strdup(arg);
+ if (!str) {
+ goto done;
+ }
+ p = strtok(str, ",");
+ while (p) {
+ SSLNamedGroup group = groupNameToNamedGroup(p);
+ if (group == ssl_grp_none) {
+ count = 0;
+ goto done;
+ }
+ groups[count++] = group;
+ p = strtok(NULL, ",");
+ }
+
+done:
+ PORT_Free(str);
+ if (!count) {
+ PORT_Free(groups);
+ return SECFailure;
+ }
+
+ *enabledGroupsCount = count;
+ *enabledGroups = groups;
+ return SECSuccess;
+}
+
+SSLSignatureScheme
+schemeNameToScheme(const char *name)
+{
+#define compareScheme(x) \
+ do { \
+ if (!PORT_Strncmp(name, #x, PORT_Strlen(#x))) { \
+ return ssl_sig_##x; \
+ } \
+ } while (0)
+
+ compareScheme(rsa_pkcs1_sha1);
+ compareScheme(rsa_pkcs1_sha256);
+ compareScheme(rsa_pkcs1_sha384);
+ compareScheme(rsa_pkcs1_sha512);
+ compareScheme(ecdsa_sha1);
+ compareScheme(ecdsa_secp256r1_sha256);
+ compareScheme(ecdsa_secp384r1_sha384);
+ compareScheme(ecdsa_secp521r1_sha512);
+ compareScheme(rsa_pss_rsae_sha256);
+ compareScheme(rsa_pss_rsae_sha384);
+ compareScheme(rsa_pss_rsae_sha512);
+ compareScheme(ed25519);
+ compareScheme(ed448);
+ compareScheme(rsa_pss_pss_sha256);
+ compareScheme(rsa_pss_pss_sha384);
+ compareScheme(rsa_pss_pss_sha512);
+ compareScheme(dsa_sha1);
+ compareScheme(dsa_sha256);
+ compareScheme(dsa_sha384);
+ compareScheme(dsa_sha512);
+
+#undef compareScheme
+
+ return ssl_sig_none;
+}
+
+SECStatus
+parseSigSchemeList(const char *arg, const SSLSignatureScheme **enabledSigSchemes,
+ unsigned int *enabledSigSchemeCount)
+{
+ SSLSignatureScheme *schemes;
+ unsigned int numValues = 0;
+ unsigned int count = 0;
+
+ if (countItems(arg, &numValues) != SECSuccess) {
+ return SECFailure;
+ }
+ schemes = PORT_ZNewArray(SSLSignatureScheme, numValues);
+ if (!schemes) {
+ return SECFailure;
+ }
+
+ /* Get group names. */
+ char *str = PORT_Strdup(arg);
+ if (!str) {
+ goto done;
+ }
+ char *p = strtok(str, ",");
+ while (p) {
+ SSLSignatureScheme scheme = schemeNameToScheme(p);
+ if (scheme == ssl_sig_none) {
+ count = 0;
+ goto done;
+ }
+ schemes[count++] = scheme;
+ p = strtok(NULL, ",");
+ }
+
+done:
+ PORT_Free(str);
+ if (!count) {
+ PORT_Free(schemes);
+ return SECFailure;
+ }
+
+ *enabledSigSchemeCount = count;
+ *enabledSigSchemes = schemes;
+ return SECSuccess;
+}
+
+/* Parse the exporter spec in the form: LABEL[:OUTPUT-LENGTH[:CONTEXT]] */
+static SECStatus
+parseExporter(const char *arg,
+ secuExporter *exporter)
+{
+ SECStatus rv = SECSuccess;
+
+ char *str = PORT_Strdup(arg);
+ if (!str) {
+ rv = SECFailure;
+ goto done;
+ }
+
+ char *labelEnd = strchr(str, ':');
+ if (labelEnd) {
+ *labelEnd = '\0';
+ labelEnd++;
+
+ /* To extract CONTEXT, first skip OUTPUT-LENGTH */
+ char *outputEnd = strchr(labelEnd, ':');
+ if (outputEnd) {
+ *outputEnd = '\0';
+ outputEnd++;
+
+ exporter->hasContext = PR_TRUE;
+ exporter->context.data = (unsigned char *)PORT_Strdup(outputEnd);
+ exporter->context.len = strlen(outputEnd);
+ if (PORT_Strncasecmp((char *)exporter->context.data, "0x", 2) == 0) {
+ rv = SECU_SECItemHexStringToBinary(&exporter->context);
+ if (rv != SECSuccess) {
+ goto done;
+ }
+ }
+ }
+ }
+
+ if (labelEnd && *labelEnd != '\0') {
+ long int outputLength = strtol(labelEnd, NULL, 10);
+ if (!(outputLength > 0 && outputLength <= UINT_MAX)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+ goto done;
+ }
+ exporter->outputLength = outputLength;
+ } else {
+ exporter->outputLength = 20;
+ }
+
+ char *label = PORT_Strdup(str);
+ exporter->label.data = (unsigned char *)label;
+ exporter->label.len = strlen(label);
+ if (PORT_Strncasecmp((char *)exporter->label.data, "0x", 2) == 0) {
+ rv = SECU_SECItemHexStringToBinary(&exporter->label);
+ if (rv != SECSuccess) {
+ goto done;
+ }
+ }
+
+done:
+ PORT_Free(str);
+
+ return rv;
+}
+
+SECStatus
+parseExporters(const char *arg,
+ const secuExporter **enabledExporters,
+ unsigned int *enabledExporterCount)
+{
+ secuExporter *exporters;
+ unsigned int numValues = 0;
+ unsigned int count = 0;
+
+ if (countItems(arg, &numValues) != SECSuccess) {
+ return SECFailure;
+ }
+ exporters = PORT_ZNewArray(secuExporter, numValues);
+ if (!exporters) {
+ return SECFailure;
+ }
+
+ /* Get exporter definitions. */
+ char *str = PORT_Strdup(arg);
+ if (!str) {
+ goto done;
+ }
+ char *p = strtok(str, ",");
+ while (p) {
+ SECStatus rv = parseExporter(p, &exporters[count++]);
+ if (rv != SECSuccess) {
+ count = 0;
+ goto done;
+ }
+ p = strtok(NULL, ",");
+ }
+
+done:
+ PORT_Free(str);
+ if (!count) {
+ PORT_Free(exporters);
+ return SECFailure;
+ }
+
+ *enabledExporterCount = count;
+ *enabledExporters = exporters;
+ return SECSuccess;
+}
+
+static SECStatus
+exportKeyingMaterial(PRFileDesc *fd, const secuExporter *exporter)
+{
+ SECStatus rv = SECSuccess;
+ unsigned char *out = PORT_Alloc(exporter->outputLength);
+
+ if (!out) {
+ fprintf(stderr, "Unable to allocate buffer for keying material\n");
+ return SECFailure;
+ }
+ rv = SSL_ExportKeyingMaterial(fd,
+ (char *)exporter->label.data,
+ exporter->label.len,
+ exporter->hasContext,
+ exporter->context.data,
+ exporter->context.len,
+ out,
+ exporter->outputLength);
+ if (rv != SECSuccess) {
+ goto done;
+ }
+ fprintf(stdout, "Exported Keying Material:\n");
+ secu_PrintRawString(stdout, (SECItem *)&exporter->label, "Label", 1);
+ if (exporter->hasContext) {
+ SECU_PrintAsHex(stdout, &exporter->context, "Context", 1);
+ }
+ SECU_Indent(stdout, 1);
+ fprintf(stdout, "Length: %u\n", exporter->outputLength);
+ SECItem temp = { siBuffer, out, exporter->outputLength };
+ SECU_PrintAsHex(stdout, &temp, "Keying Material", 1);
+
+done:
+ PORT_Free(out);
+ return rv;
+}
+
+SECStatus
+exportKeyingMaterials(PRFileDesc *fd,
+ const secuExporter *exporters,
+ unsigned int exporterCount)
+{
+ unsigned int i;
+
+ for (i = 0; i < exporterCount; i++) {
+ SECStatus rv = exportKeyingMaterial(fd, &exporters[i]);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+ }
+
+ return SECSuccess;
+}
+
+SECStatus
+readPSK(const char *arg, SECItem *psk, SECItem *label)
+{
+ SECStatus rv = SECFailure;
+ char *str = PORT_Strdup(arg);
+ if (!str) {
+ goto cleanup;
+ }
+
+ char *pskBytes = strtok(str, ":");
+ if (!pskBytes) {
+ goto cleanup;
+ }
+ if (PORT_Strncasecmp(pskBytes, "0x", 2) != 0) {
+ goto cleanup;
+ }
+
+ psk = SECU_HexString2SECItem(NULL, psk, &pskBytes[2]);
+ if (!psk || !psk->data || psk->len != strlen(&str[2]) / 2) {
+ goto cleanup;
+ }
+
+ SECItem labelItem = { siBuffer, NULL, 0 };
+ char *inLabel = strtok(NULL, ":");
+ if (inLabel) {
+ labelItem.data = (unsigned char *)PORT_Strdup(inLabel);
+ if (!labelItem.data) {
+ goto cleanup;
+ }
+ labelItem.len = strlen(inLabel);
+
+ if (PORT_Strncasecmp(inLabel, "0x", 2) == 0) {
+ rv = SECU_SECItemHexStringToBinary(&labelItem);
+ if (rv != SECSuccess) {
+ SECITEM_FreeItem(&labelItem, PR_FALSE);
+ goto cleanup;
+ }
+ }
+ rv = SECSuccess;
+ } else {
+ PRUint8 defaultLabel[] = { 'C', 'l', 'i', 'e', 'n', 't', '_',
+ 'i', 'd', 'e', 'n', 't', 'i', 't', 'y' };
+ SECItem src = { siBuffer, defaultLabel, sizeof(defaultLabel) };
+ rv = SECITEM_CopyItem(NULL, &labelItem, &src);
+ }
+ if (rv == SECSuccess) {
+ *label = labelItem;
+ }
+
+cleanup:
+ PORT_Free(str);
+ return rv;
+}
+
+static SECStatus
+secu_PrintPKCS12DigestInfo(FILE *out, const SECItem *t, char *m, int level)
+{
+ SECItem my = *t;
+ SECItem rawDigestAlgID;
+ SECItem digestData;
+ SECStatus rv;
+ PLArenaPool *arena;
+ SECAlgorithmID digestAlgID;
+ char *mAlgID = NULL;
+ char *mDigest = NULL;
+
+ /* strip the outer sequence */
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ /* get the algorithm ID */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &rawDigestAlgID)) {
+ return SECFailure;
+ }
+ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (arena == NULL) {
+ return SECFailure;
+ }
+#define DIGEST_ALGID_STRING "Digest Algorithm ID"
+ if (m)
+ mAlgID = PR_smprintf("%s " DIGEST_ALGID_STRING, m);
+ rv = SEC_QuickDERDecodeItem(arena, &digestAlgID,
+ SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
+ &rawDigestAlgID);
+ if (rv == SECSuccess) {
+ SECU_PrintAlgorithmID(out, &digestAlgID,
+ mAlgID ? mAlgID : DIGEST_ALGID_STRING, level);
+ }
+ if (mAlgID)
+ PR_smprintf_free(mAlgID);
+ PORT_FreeArena(arena, PR_FALSE);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ /* get the mac data */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &digestData)) {
+ return SECFailure;
+ }
+ if ((digestData.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OCTET_STRING) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+#define DIGEST_STRING "Digest"
+ if (m)
+ mDigest = PR_smprintf("%s " DIGEST_STRING, m);
+ secu_PrintOctetString(out, &digestData,
+ mDigest ? mDigest : DIGEST_STRING, level);
+ if (mDigest)
+ PR_smprintf_free(mDigest);
+ return SECSuccess;
+}
+
+static SECStatus
+secu_PrintPKCS12MacData(FILE *out, const SECItem *t, char *m, int level)
+{
+ SECItem my = *t;
+ SECItem hash;
+ SECItem salt;
+
+ if (m) {
+ SECU_Indent(out, level);
+ fprintf(out, "%s: \n", m);
+ level++;
+ }
+
+ /* strip the outer sequence */
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &hash)) {
+ return SECFailure;
+ }
+ if (SECSuccess != secu_PrintPKCS12DigestInfo(out, &hash, "Mac", level)) {
+ return SECFailure;
+ }
+
+ /* handle the salt */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &salt)) {
+ return SECFailure;
+ ;
+ }
+ if ((salt.data[0] & SEC_ASN1_TAGNUM_MASK) != SEC_ASN1_OCTET_STRING) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ secu_PrintOctetString(out, &salt, "Mac Salt", level);
+
+ if (my.len &&
+ ((my.data[0] & SEC_ASN1_TAGNUM_MASK) == SEC_ASN1_INTEGER)) {
+ SECItem iterator;
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &iterator)) {
+ return SECFailure;
+ }
+ SECU_PrintEncodedInteger(out, &iterator, "Iterations", level);
+ }
+ return SECSuccess;
+}
+
+SECStatus
+SECU_PrintPKCS12(FILE *out, const SECItem *t, char *m, int level)
+{
+ SECItem my = *t;
+ SECItem authSafe;
+ SECItem macData;
+
+ SECU_Indent(out, level);
+ fprintf(out, "%s:\n", m);
+ level++;
+
+ /* strip the outer sequence */
+ if ((my.data[0] != (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) ||
+ SECSuccess != SECU_StripTagAndLength(&my)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ return SECFailure;
+ }
+ /* print and remove the optional version number */
+ if (my.len && ((my.data[0] & SEC_ASN1_TAGNUM_MASK) == SEC_ASN1_INTEGER)) {
+ SECItem version;
+
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &version)) {
+ return SECFailure;
+ }
+ SECU_PrintEncodedInteger(out, &version, "Version", level);
+ }
+
+ /* print the authSafe */
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &authSafe)) {
+ return SECFailure;
+ }
+ if (SECSuccess != secu_PrintDERPKCS7ContentInfo(out, &authSafe,
+ secuPKCS7PKCS12AuthSafe,
+ "AuthSafe", level)) {
+ return SECFailure;
+ }
+
+ /* print the mac data (optional) */
+ if (!my.len) {
+ return SECSuccess;
+ }
+ if (SECSuccess != SECU_ExtractBERAndStep(&my, &macData)) {
+ return SECFailure;
+ }
+ if (SECSuccess != secu_PrintPKCS12MacData(out, &macData,
+ "Mac Data", level)) {
+ return SECFailure;
+ }
+
+ if (my.len) {
+ fprintf(out, "Unknown extra data found \n");
+ }
+ return SECSuccess;
+}
diff --git a/security/nss/cmd/lib/secutil.h b/security/nss/cmd/lib/secutil.h
new file mode 100644
index 0000000000..b5f86ad061
--- /dev/null
+++ b/security/nss/cmd/lib/secutil.h
@@ -0,0 +1,450 @@
+/* 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 "keyhi.h"
+#include "secpkcs7.h"
+#include "secasn1.h"
+#include "secder.h"
+#include <stdio.h>
+
+#include "basicutil.h"
+#include "sslerr.h"
+#include "sslt.h"
+#include "blapi.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_PKCS12 "pkcs12"
+#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 PR_GetEnvSecure("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);
+
+/* Dump contents of private key */
+extern int SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level);
+
+/* 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);
+/* Pretty-print a pkcs12 file */
+extern SECStatus SECU_PrintPKCS12(FILE *out, const 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".
+ *
+ * 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 defaultVersionRange (which can be obtained from libssl by
+ * calling SSL_VersionRangeGetSupported).
+ */
+SECStatus
+SECU_ParseSSLVersionRangeString(const char *input,
+ const SSLVersionRange defaultVersionRange,
+ SSLVersionRange *vrange);
+
+SECStatus parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
+ unsigned int *enabledGroupsCount);
+SECStatus parseSigSchemeList(const char *arg,
+ const SSLSignatureScheme **enabledSigSchemes,
+ unsigned int *enabledSigSchemeCount);
+typedef struct {
+ SECItem label;
+ PRBool hasContext;
+ SECItem context;
+ unsigned int outputLength;
+} secuExporter;
+
+SECStatus parseExporters(const char *arg,
+ const secuExporter **enabledExporters,
+ unsigned int *enabledExporterCount);
+
+SECStatus exportKeyingMaterials(PRFileDesc *fd,
+ const secuExporter *exporters,
+ unsigned int exporterCount);
+
+SECStatus readPSK(const char *arg, SECItem *psk, SECItem *label);
+
+/*
+ *
+ * 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/security/nss/cmd/libpkix/Makefile b/security/nss/cmd/libpkix/Makefile
new file mode 100644
index 0000000000..1de5ef2694
--- /dev/null
+++ b/security/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/security/nss/cmd/libpkix/manifest.mn b/security/nss/cmd/libpkix/manifest.mn
new file mode 100644
index 0000000000..4f232a5100
--- /dev/null
+++ b/security/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/security/nss/cmd/libpkix/perf/Makefile b/security/nss/cmd/libpkix/perf/Makefile
new file mode 100644
index 0000000000..3181547e2c
--- /dev/null
+++ b/security/nss/cmd/libpkix/perf/Makefile
@@ -0,0 +1,44 @@
+#! 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/security/nss/cmd/libpkix/perf/libpkix_buildthreads.c b/security/nss/cmd/libpkix/perf/libpkix_buildthreads.c
new file mode 100644
index 0000000000..4b8d438112
--- /dev/null
+++ b/security/nss/cmd/libpkix/perf/libpkix_buildthreads.c
@@ -0,0 +1,337 @@
+/* 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 <stdio.h>
+#include <string.h>
+
+#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> <duration> <threads> "
+ "<anchorNickname> <eecertNickname>\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/security/nss/cmd/libpkix/perf/manifest.mn b/security/nss/cmd/libpkix/perf/manifest.mn
new file mode 100644
index 0000000000..f70040234a
--- /dev/null
+++ b/security/nss/cmd/libpkix/perf/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR = $(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/perf/nss_threads.c b/security/nss/cmd/libpkix/perf/nss_threads.c
new file mode 100644
index 0000000000..202f128b61
--- /dev/null
+++ b/security/nss/cmd/libpkix/perf/nss_threads.c
@@ -0,0 +1,158 @@
+/* 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 <stdio.h>
+#include <string.h>
+
+#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 <duration> <threads> <certnickname>\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/security/nss/cmd/libpkix/pkix/Makefile b/security/nss/cmd/libpkix/pkix/Makefile
new file mode 100644
index 0000000000..1de5ef2694
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/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/security/nss/cmd/libpkix/pkix/certsel/Makefile b/security/nss/cmd/libpkix/pkix/certsel/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/certsel/Makefile
@@ -0,0 +1,45 @@
+#! 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/security/nss/cmd/libpkix/pkix/certsel/manifest.mn b/security/nss/cmd/libpkix/pkix/certsel/manifest.mn
new file mode 100644
index 0000000000..d9da6e1674
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/certsel/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/certsel/test_certselector.c b/security/nss/cmd/libpkix/pkix/certsel/test_certselector.c
new file mode 100644
index 0000000000..1fde3739b8
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/certsel/test_certselector.c
@@ -0,0 +1,1677 @@
+/* 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(&params, 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 <cert0-permitted>");
+ 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 <cert1-permitted>");
+ 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 <cert2-permitted>");
+ 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 <cert3-excluded>");
+ 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 <cert4-excluded>");
+ 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 <cert5-excluded>");
+ 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(&params, 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 <O=NotATest Certificates,C=US>");
+ 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(&params, 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 <O=NotATest Certificates,C=US...>");
+ 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 <OU=permittedSubtree1,O=Test...>");
+ 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 <OU=permittedSubtree1,O=Test...>");
+ 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 <O=Test Certificates,C=US...>");
+ 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 <OU=permittedSubtree1,O=Test ...>");
+ 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 <CN=Valid DN nameConstraints EE...>");
+ 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 <OU=permittedSubtree1,O=Test>");
+ 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 <O=Test Certificates,C=US>");
+ 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(&params, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" Add directory name <CN=Invalid DN nameConstraints EE...>");
+ 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 <mytestcertificates.gov>");
+ 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(&params, 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(&params, 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 << item);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selSubjKeyId);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(selector);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAuthKeyIdMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_ByteArray *selAuthKeyId = NULL;
+ PKIX_UInt32 item = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Auth Key Id Cert Selector");
+
+ item = 3;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, item, (PKIX_PL_Object **)&cert, plContext));
+
+ subTest(" PKIX_PL_Cert_GetAuthorityKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityKeyIdentifier(cert, &selAuthKeyId, 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(&params, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetAuthorityKeyIdentifier");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetAuthorityKeyIdentifier(params, selAuthKeyId, plContext));
+
+ subTest(" Select TWO");
+ testSelector(selector, certs, (1 << item) | (1 << 1));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selAuthKeyId);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(selector);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testSubjPKAlgIdMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_OID *selAlgId = NULL;
+ PKIX_UInt32 item = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Subject Public Key Algorithm Id Cert Selector");
+
+ item = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, item, (PKIX_PL_Object **)&cert, plContext));
+
+ subTest(" PKIX_PL_Cert_GetSubjectPublicKeyAlgId");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKeyAlgId(cert, &selAlgId, 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(&params, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetSubjPKAlgId");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjPKAlgId(params, selAlgId, plContext));
+
+ subTest(" Select All");
+ testSelector(selector, certs, 0x7F);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selAlgId);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(selector);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testSubjPublicKeyMatch(PKIX_List *certs)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *params = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_PublicKey *selPublicKey = NULL;
+ PKIX_UInt32 item = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test Subject Public Key Cert Selector");
+
+ item = 5;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, item, (PKIX_PL_Object **)&cert, plContext));
+
+ subTest(" PKIX_PL_Cert_GetSubjectPublicKey");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(cert, &selPublicKey, 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(&params, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext));
+
+ subTest(" PKIX_ComCertSelParams_SetSubjPubKey");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjPubKey(params, selPublicKey, plContext));
+
+ subTest(" Select ONE");
+ testSelector(selector, certs, 1 << item);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selPublicKey);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(params);
+ PKIX_TEST_DECREF_AC(selector);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+test_CertSelector_Duplicate(PKIX_CertSelector *selector)
+{
+ PKIX_Int32 goodBasicConstraints = 0;
+ PKIX_Int32 equalBasicConstraints = 0;
+ PKIX_CertSelector *dupSelector = NULL;
+ PKIX_ComCertSelParams *goodParams = NULL;
+ PKIX_ComCertSelParams *equalParams = NULL;
+ PKIX_CertSelector_MatchCallback goodCallback = NULL;
+ PKIX_CertSelector_MatchCallback equalCallback = NULL;
+ PKIX_PL_X500Name *goodSubject = NULL;
+ PKIX_PL_X500Name *equalSubject = NULL;
+ PKIX_List *goodPolicy = NULL;
+ PKIX_List *equalPolicy = NULL;
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Date *goodDate = NULL;
+ PKIX_PL_Date *equalDate = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("test_CertSelector_Duplicate");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate((PKIX_PL_Object *)selector,
+ (PKIX_PL_Object **)&dupSelector,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetCommonCertSelectorParams(selector, &goodParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetCommonCertSelectorParams(dupSelector, &equalParams, plContext));
+ /* There is no equals function, so look at components separately. */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubject(goodParams, &goodSubject, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetSubject(equalParams, &equalSubject, plContext));
+ if (goodSubject && equalSubject) {
+ testEqualsHelper((PKIX_PL_Object *)goodSubject,
+ (PKIX_PL_Object *)equalSubject,
+ PKIX_TRUE,
+ plContext);
+ } else {
+ if PKIX_EXACTLY_ONE_NULL (goodSubject, equalSubject) {
+ pkixTestErrorMsg = "Subject Names are not equal!";
+ goto cleanup;
+ }
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPolicy(goodParams, &goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetPolicy(equalParams, &equalPolicy, plContext));
+ if (goodPolicy && equalPolicy) {
+ testEqualsHelper((PKIX_PL_Object *)goodPolicy,
+ (PKIX_PL_Object *)equalPolicy,
+ PKIX_TRUE,
+ plContext);
+ } else {
+ if PKIX_EXACTLY_ONE_NULL (goodPolicy, equalPolicy) {
+ pkixTestErrorMsg = "Policy Lists are not equal!";
+ goto cleanup;
+ }
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificate(goodParams, &goodCert, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificate(equalParams, &equalCert, plContext));
+ if (goodCert && equalCert) {
+ testEqualsHelper((PKIX_PL_Object *)goodCert,
+ (PKIX_PL_Object *)equalCert,
+ PKIX_TRUE,
+ plContext);
+ } else {
+ if PKIX_EXACTLY_ONE_NULL (goodCert, equalCert) {
+ pkixTestErrorMsg = "Cert Lists are not equal!";
+ goto cleanup;
+ }
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificateValid(goodParams, &goodDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetCertificateValid(equalParams, &equalDate, plContext));
+ if (goodCert && equalCert) {
+ testEqualsHelper((PKIX_PL_Object *)goodDate,
+ (PKIX_PL_Object *)equalDate,
+ PKIX_TRUE,
+ plContext);
+ } else {
+ if PKIX_EXACTLY_ONE_NULL (goodDate, equalDate) {
+ pkixTestErrorMsg = "Date Lists are not equal!";
+ goto cleanup;
+ }
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetBasicConstraints(goodParams, &goodBasicConstraints, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_GetBasicConstraints(equalParams, &equalBasicConstraints, plContext));
+ if (goodBasicConstraints != equalBasicConstraints) {
+ pkixTestErrorMsg = "BasicConstraints are not equal!";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetMatchCallback(selector, &goodCallback, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_GetMatchCallback(dupSelector, &equalCallback, plContext));
+ if (goodCallback != equalCallback) {
+ pkixTestErrorMsg = "MatchCallbacks are not equal!";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dupSelector);
+ PKIX_TEST_DECREF_AC(goodParams);
+ PKIX_TEST_DECREF_AC(equalParams);
+ PKIX_TEST_DECREF_AC(goodSubject);
+ PKIX_TEST_DECREF_AC(equalSubject);
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(goodDate);
+ PKIX_TEST_DECREF_AC(equalDate);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_certselector <NIST_FILES_DIR> <cert-dir>\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/security/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c b/security/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c
new file mode 100644
index 0000000000..57f192a42f
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/certsel/test_comcertselparams.c
@@ -0,0 +1,800 @@
+/* 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 <expect TRUE>");
+ }
+
+ 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 <expect FALSE>");
+ }
+
+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 <expect equal>");
+ }
+
+ 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 <expect equal>");
+ }
+
+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 <expect 2>");
+ }
+
+ /* 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 <expect equal>");
+ }
+
+ /* 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 <expect equal>");
+ }
+
+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 <expect equal>");
+ }
+
+ 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 <expect equal>");
+ }
+
+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 "
+ "<expect equal>");
+ }
+
+ /* 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 "
+ "<expect equal>");
+ }
+
+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 <NIST_FILES_DIR> \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/security/nss/cmd/libpkix/pkix/checker/Makefile b/security/nss/cmd/libpkix/pkix/checker/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/checker/Makefile
@@ -0,0 +1,45 @@
+#! 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/security/nss/cmd/libpkix/pkix/checker/manifest.mn b/security/nss/cmd/libpkix/pkix/checker/manifest.mn
new file mode 100644
index 0000000000..54e1486e68
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/checker/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c b/security/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c
new file mode 100644
index 0000000000..5fab3a6920
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/checker/test_certchainchecker.c
@@ -0,0 +1,185 @@
+/* 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 **)&copy,
+ plContext));
+
+ subTest("CertChainChecker_GetCheckCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCheckCallback(original, &originalCallback, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCheckCallback(copy, &copyCallback, 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, &copyForward, 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, &copyForwardDir, 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, &copyState, 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, &copyList, 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/security/nss/cmd/libpkix/pkix/crlsel/Makefile b/security/nss/cmd/libpkix/pkix/crlsel/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/crlsel/Makefile
@@ -0,0 +1,45 @@
+#! 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/security/nss/cmd/libpkix/pkix/crlsel/manifest.mn b/security/nss/cmd/libpkix/pkix/crlsel/manifest.mn
new file mode 100644
index 0000000000..3b13298aa6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/crlsel/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c b/security/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c
new file mode 100644
index 0000000000..fcc5ef5a33
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/crlsel/test_comcrlselparams.c
@@ -0,0 +1,406 @@
+/* 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 <central-data-dir>\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/security/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c b/security/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c
new file mode 100644
index 0000000000..f17406be5d
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/crlsel/test_crlselector.c
@@ -0,0 +1,168 @@
+/* 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/security/nss/cmd/libpkix/pkix/manifest.mn b/security/nss/cmd/libpkix/pkix/manifest.mn
new file mode 100644
index 0000000000..895bf52b2b
--- /dev/null
+++ b/security/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/security/nss/cmd/libpkix/pkix/params/Makefile b/security/nss/cmd/libpkix/pkix/params/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/Makefile
@@ -0,0 +1,45 @@
+#! 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/security/nss/cmd/libpkix/pkix/params/manifest.mn b/security/nss/cmd/libpkix/pkix/params/manifest.mn
new file mode 100644
index 0000000000..c7629a6207
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/params/test_procparams.c b/security/nss/cmd/libpkix/pkix/params/test_procparams.c
new file mode 100644
index 0000000000..419322a1e7
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/test_procparams.c
@@ -0,0 +1,478 @@
+/* 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 <central-data-dir>\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/security/nss/cmd/libpkix/pkix/params/test_resourcelimits.c b/security/nss/cmd/libpkix/pkix/params/test_resourcelimits.c
new file mode 100644
index 0000000000..f52c3ef87f
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/test_resourcelimits.c
@@ -0,0 +1,99 @@
+/* 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/security/nss/cmd/libpkix/pkix/params/test_trustanchor.c b/security/nss/cmd/libpkix/pkix/params/test_trustanchor.c
new file mode 100644
index 0000000000..4bd9d174ce
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/test_trustanchor.c
@@ -0,0 +1,251 @@
+/* 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>");
+ *goodObject = createTrustAnchor(dirName, goodInput, PKIX_FALSE, plContext);
+
+ subTest("PKIX_TrustAnchor_CreateWithNameKeyPair <equalObject>");
+ *equalObject = createTrustAnchor(dirName, goodInput, PKIX_FALSE, plContext);
+
+ subTest("PKIX_TrustAnchor_CreateWithCert <diffObject>");
+ *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 <NIST_FILES_DIR> <central-data-dir>\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/security/nss/cmd/libpkix/pkix/params/test_valparams.c b/security/nss/cmd/libpkix/pkix/params/test_valparams.c
new file mode 100644
index 0000000000..6419062c40
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/params/test_valparams.c
@@ -0,0 +1,261 @@
+/* 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 <central-data-dir>\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/security/nss/cmd/libpkix/pkix/results/Makefile b/security/nss/cmd/libpkix/pkix/results/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/Makefile
@@ -0,0 +1,45 @@
+#! 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/security/nss/cmd/libpkix/pkix/results/manifest.mn b/security/nss/cmd/libpkix/pkix/results/manifest.mn
new file mode 100644
index 0000000000..7e4caeac60
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/results/test_buildresult.c b/security/nss/cmd/libpkix/pkix/results/test_buildresult.c
new file mode 100644
index 0000000000..8b13e8eea6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/test_buildresult.c
@@ -0,0 +1,212 @@
+/* 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 <central-data-dir>\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/security/nss/cmd/libpkix/pkix/results/test_policynode.c b/security/nss/cmd/libpkix/pkix/results/test_policynode.c
new file mode 100644
index 0000000000..38ac1d95e6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/test_policynode.c
@@ -0,0 +1,612 @@
+/* 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, &copy, 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 <NIST_FILES_DIR> \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/security/nss/cmd/libpkix/pkix/results/test_valresult.c b/security/nss/cmd/libpkix/pkix/results/test_valresult.c
new file mode 100644
index 0000000000..7760a431e3
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/test_valresult.c
@@ -0,0 +1,199 @@
+/* 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 <central-data-dir>\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/security/nss/cmd/libpkix/pkix/results/test_verifynode.c b/security/nss/cmd/libpkix/pkix/results/test_verifynode.c
new file mode 100644
index 0000000000..21c61aa96c
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/results/test_verifynode.c
@@ -0,0 +1,112 @@
+/* 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/security/nss/cmd/libpkix/pkix/store/Makefile b/security/nss/cmd/libpkix/pkix/store/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/store/Makefile
@@ -0,0 +1,45 @@
+#! 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/security/nss/cmd/libpkix/pkix/store/manifest.mn b/security/nss/cmd/libpkix/pkix/store/manifest.mn
new file mode 100644
index 0000000000..b939ffdcfd
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/store/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/.
+
+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
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/store/test_store.c b/security/nss/cmd/libpkix/pkix/store/test_store.c
new file mode 100644
index 0000000000..59606b8929
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/store/test_store.c
@@ -0,0 +1,194 @@
+/* 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 <data-dir> <platform-dir>\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/security/nss/cmd/libpkix/pkix/top/Makefile b/security/nss/cmd/libpkix/pkix/top/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/Makefile
@@ -0,0 +1,45 @@
+#! 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/security/nss/cmd/libpkix/pkix/top/manifest.mn b/security/nss/cmd/libpkix/pkix/top/manifest.mn
new file mode 100644
index 0000000000..8840204f7f
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/manifest.mn
@@ -0,0 +1,34 @@
+#
+# 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
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/top/test_basicchecker.c b/security/nss/cmd/libpkix/pkix/top/test_basicchecker.c
new file mode 100644
index 0000000000..e2743b343f
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_basicchecker.c
@@ -0,0 +1,238 @@
+/* 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 <pass>");
+ /*
+ * 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 <fail>");
+
+ 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 <fail>");
+ 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 <fail>");
+
+ 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 <central-data-dir>\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/security/nss/cmd/libpkix/pkix/top/test_basicconstraintschecker.c b/security/nss/cmd/libpkix/pkix/top/test_basicconstraintschecker.c
new file mode 100644
index 0000000000..eba5153ac0
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_basicconstraintschecker.c
@@ -0,0 +1,145 @@
+/* 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/security/nss/cmd/libpkix/pkix/top/test_buildchain.c b/security/nss/cmd/libpkix/pkix/top/test_buildchain.c
new file mode 100644
index 0000000000..5c9ec5968b
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_buildchain.c
@@ -0,0 +1,418 @@
+/* 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] <testName> [ENE|EE]\n"
+ "\t <certStoreDirectory> <targetCert>"
+ " <intermediate Certs...> <trustedCert>\n\n");
+ (void)printf("Builds a chain of certificates from <targetCert> to <trustedCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>. "
+ "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/security/nss/cmd/libpkix/pkix/top/test_buildchain_partialchain.c b/security/nss/cmd/libpkix/pkix/top/test_buildchain_partialchain.c
new file mode 100644
index 0000000000..4861a8e326
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_buildchain_partialchain.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/. */
+/*
+ * 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] <testName> [ENE|EE]\n"
+ "\t <certStoreDirectory> <targetCert>"
+ " <intermediate Certs...> <trustedCert>\n\n");
+ (void)printf("Builds a chain of certificates from <targetCert> to <trustedCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>. "
+ "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/security/nss/cmd/libpkix/pkix/top/test_buildchain_resourcelimits.c b/security/nss/cmd/libpkix/pkix/top/test_buildchain_resourcelimits.c
new file mode 100644
index 0000000000..1b28435b01
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_buildchain_resourcelimits.c
@@ -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/. */
+/*
+ * 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<testName> [ENE|EE]"
+ " <certStoreDirectory>\\\n\t\t<targetCert>"
+ " <intermediate Certs...> <trustedCert>\n\n");
+ (void)printf("Builds a chain of certificates from <targetCert> to <trustedCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>. "
+ "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 - <pass>");
+ Test_BuildResult(procParams,
+ testValid,
+ expectedCerts,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(resourceLimits, 1, plContext));
+
+ subTest("Testing ResourceLimits MaxFanout - <fail>");
+ 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 - <fail>");
+ 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 - <pass>");
+ 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/security/nss/cmd/libpkix/pkix/top/test_buildchain_uchecker.c b/security/nss/cmd/libpkix/pkix/top/test_buildchain_uchecker.c
new file mode 100644
index 0000000000..43f06ec2ac
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_buildchain_uchecker.c
@@ -0,0 +1,327 @@
+/* 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]<userOID>] "
+ "<trustedCert> <targetCert> <certStoreDirectory>\n\n");
+ (void)printf("Builds a chain of certificates between "
+ "<trustedCert> and <targetCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>.\n"
+ "If <userOID> is not an empty string, its value is used as\n"
+ "user defined checker's critical extension OID.\n"
+ "A - for <userOID> 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/security/nss/cmd/libpkix/pkix/top/test_customcrlchecker.c b/security/nss/cmd/libpkix/pkix/top/test_customcrlchecker.c
new file mode 100644
index 0000000000..d2c667ae74
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_customcrlchecker.c
@@ -0,0 +1,435 @@
+/* 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/security/nss/cmd/libpkix/pkix/top/test_defaultcrlchecker2stores.c b/security/nss/cmd/libpkix/pkix/top/test_defaultcrlchecker2stores.c
new file mode 100644
index 0000000000..3ce4513177
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_defaultcrlchecker2stores.c
@@ -0,0 +1,230 @@
+/* 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/security/nss/cmd/libpkix/pkix/top/test_ocsp.c b/security/nss/cmd/libpkix/pkix/top/test_ocsp.c
new file mode 100644
index 0000000000..e97e57096e
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_ocsp.c
@@ -0,0 +1,288 @@
+/* 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 <certStoreDirectory> TestName "
+ "[ENE|EE] <certLocationDirectory> <trustedCert> "
+ "<targetCert>\n\n");
+ (void)printf("Validates a chain of certificates between "
+ "<trustedCert> and <targetCert>\n"
+ "using the certs and CRLs in <certLocationDirectory> and "
+ "pkcs11 db from <certStoreDirectory>. "
+ "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/security/nss/cmd/libpkix/pkix/top/test_policychecker.c b/security/nss/cmd/libpkix/pkix/top/test_policychecker.c
new file mode 100644
index 0000000000..1318f13ba6
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_policychecker.c
@@ -0,0 +1,535 @@
+/* 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 <pass>");
+ /*
+ * 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/security/nss/cmd/libpkix/pkix/top/test_subjaltnamechecker.c b/security/nss/cmd/libpkix/pkix/top/test_subjaltnamechecker.c
new file mode 100644
index 0000000000..3f9711e691
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_subjaltnamechecker.c
@@ -0,0 +1,261 @@
+/* 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]:<name>+...");
+ 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/security/nss/cmd/libpkix/pkix/top/test_validatechain.c b/security/nss/cmd/libpkix/pkix/top/test_validatechain.c
new file mode 100644
index 0000000000..98cb7b018c
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_validatechain.c
@@ -0,0 +1,221 @@
+/* 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] "
+ "<certStoreDirectory> <trustedCert> <targetCert>\n\n");
+ (void)printf("Validates a chain of certificates between "
+ "<trustedCert> and <targetCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>. "
+ "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/security/nss/cmd/libpkix/pkix/top/test_validatechain_NB.c b/security/nss/cmd/libpkix/pkix/top/test_validatechain_NB.c
new file mode 100644
index 0000000000..ad73a5df76
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_validatechain_NB.c
@@ -0,0 +1,351 @@
+/* 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] "
+ "<certStoreDirectory> <trustedCert> <targetCert>\n\n");
+ (void)printf("Validates a chain of certificates between "
+ "<trustedCert> and <targetCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>. "
+ "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 *
+testSetupCertStore(PKIX_ValidateParams *valParams, char *ldapName)
+{
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_LdapDefaultClient *ldapClient = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CollectionCertStoreContext_Create");
+
+ /* Create LDAPCertStore */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapDefaultClient_CreateByName(ldapName,
+ 0, /* timeout */
+ NULL, /* bindPtr */
+ &ldapClient,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_LdapCertStore_Create((PKIX_PL_LdapClient *)ldapClient,
+ &certStore,
+ plContext));
+
+ 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));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dirString);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(ldapClient);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+static char *levels[] = {
+ "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)
+{
+#define resultSize 150
+ char *msg = NULL;
+ char result[resultSize];
+
+ PKIX_TEST_STD_VARS();
+
+ msg = PKIX_String2ASCII(message, plContext);
+ PR_snprintf(result, resultSize,
+ "Logging %s (%s): %s",
+ levels[logLevel],
+ PKIX_ERRORCLASSNAMES[logComponent],
+ msg);
+ subTest(result);
+
+cleanup:
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(msg, plContext));
+ PKIX_TEST_RETURN();
+}
+
+static void
+testLogErrors(
+ PKIX_ERRORCLASS module,
+ PKIX_UInt32 loggingLevel,
+ PKIX_List *loggers,
+ void *plContext)
+{
+ PKIX_Logger *logger = NULL;
+ PKIX_PL_String *component = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_Create(loggerCallback, NULL, &logger, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetLoggingComponent(logger, module, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetMaxLoggingLevel(logger, loggingLevel, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(loggers, (PKIX_PL_Object *)logger, plContext));
+
+cleanup:
+ PKIX_TEST_DECREF_AC(logger);
+ PKIX_TEST_DECREF_AC(component);
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_validatechain_NB(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;
+ char *dirCertName = NULL;
+ char *anchorCertName = NULL;
+ char *dirName = NULL;
+ PKIX_UInt32 certIndex = 0;
+ PKIX_UInt32 anchorIndex = 0;
+ PKIX_UInt32 checkerIndex = 0;
+ PKIX_Boolean revChecking = PKIX_FALSE;
+ PKIX_List *checkers = NULL;
+ PRPollDesc *pollDesc = NULL;
+ PRErrorCode errorCode = 0;
+ PKIX_PL_Socket *socket = NULL;
+ char *ldapName = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ PKIX_List *loggers = NULL;
+ PKIX_Logger *logger = NULL;
+ char *logging = NULL;
+ PKIX_PL_String *component = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("ValidateChain_NB");
+
+ 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);
+
+ ldapName = PR_GetEnvSecure("LDAP");
+ /* Is LDAP set in the environment? */
+ if ((ldapName == NULL) || (*ldapName == '\0')) {
+ testError("LDAP not set in environment");
+ goto cleanup;
+ }
+
+ pkixTestErrorResult = pkix_pl_Socket_CreateByName(PKIX_FALSE, /* isServer */
+ PR_SecondsToInterval(30), /* try 30 secs for connect */
+ ldapName,
+ &errorCode,
+ &socket,
+ plContext);
+
+ if (pkixTestErrorResult != NULL) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)pkixTestErrorResult, plContext);
+ pkixTestErrorResult = NULL;
+ testError("Unable to connect to LDAP Server");
+ goto cleanup;
+ }
+
+ PKIX_TEST_DECREF_BC(socket);
+
+ testSetupCertStore(valParams, ldapName);
+
+ logging = PR_GetEnvSecure("LOGGING");
+ /* Is LOGGING set in the environment? */
+ if ((logging != NULL) && (*logging != '\0')) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&loggers, plContext));
+
+ testLogErrors(PKIX_VALIDATE_ERROR, 2, loggers, plContext);
+ testLogErrors(PKIX_CERTCHAINCHECKER_ERROR, 2, loggers, plContext);
+ testLogErrors(PKIX_LDAPDEFAULTCLIENT_ERROR, 2, loggers, plContext);
+ testLogErrors(PKIX_CERTSTORE_ERROR, 2, loggers, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_SetLoggers(loggers, plContext));
+ }
+
+ pkixTestErrorResult = PKIX_ValidateChain_NB(valParams,
+ &certIndex,
+ &anchorIndex,
+ &checkerIndex,
+ &revChecking,
+ &checkers,
+ (void **)&pollDesc,
+ &valResult,
+ &verifyTree,
+ plContext);
+
+ while (pollDesc != NULL) {
+
+ if (PR_Poll(pollDesc, 1, 0) < 0) {
+ testError("PR_Poll failed");
+ }
+
+ pkixTestErrorResult = PKIX_ValidateChain_NB(valParams,
+ &certIndex,
+ &anchorIndex,
+ &checkerIndex,
+ &revChecking,
+ &checkers,
+ (void **)&pollDesc,
+ &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 NON-ERROR RECEIVED!\n");
+ } else { /* EE */
+ (void)printf("UNEXPECTED NON-ERROR RECEIVED!\n");
+ }
+ }
+
+cleanup:
+
+ if (verifyTree) {
+ 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_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(checkers);
+ PKIX_TEST_DECREF_AC(chainCerts);
+ PKIX_TEST_DECREF_AC(valParams);
+ PKIX_TEST_DECREF_AC(valResult);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("ValidateChain_NB");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.c b/security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.c
new file mode 100644
index 0000000000..480ec2643c
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/top/test_validatechain_bc.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/. */
+/*
+ * validateChainBasicConstraints.c
+ *
+ * Tests Cert Chain Validation
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_cert.h"
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "secitem.h"
+#include "keythi.h"
+#include "nss.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ printf("\nUSAGE: incorrect.\n");
+}
+
+static PKIX_PL_Cert *
+createCert(char *inFileName)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ void *buf = NULL;
+ PRFileDesc *inFile = NULL;
+ PKIX_UInt32 len;
+ SECItem certDER;
+ SECStatus rv;
+ /* default: NULL cert (failure case) */
+ PKIX_PL_Cert *cert = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certDER.data = NULL;
+
+ inFile = PR_Open(inFileName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ pkixTestErrorMsg = "Unable to open cert file";
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)certDER.data;
+ len = certDER.len;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_Create(byteArray, &cert, plContext));
+
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ } else {
+ pkixTestErrorMsg = "Unable to read DER from cert file";
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ }
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+
+ return (cert);
+}
+
+int
+test_validatechain_bc(int argc, char *argv[])
+{
+
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+
+ char *trustedCertFile = NULL;
+ char *chainCertFile = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *chainCert = NULL;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 3) {
+ printUsage();
+ return (0);
+ }
+
+ startTests("ValidateChainBasicConstraints");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ chainLength = (argc - j) - 2;
+
+ /* create processing params with list of trust anchors */
+ trustedCertFile = argv[1 + j];
+ trustedCert = createCert(trustedCertFile);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(trustedCert, &subject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(certSelParams, -1, 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_DECREF_BC(subject);
+
+ 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));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_FALSE, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ PKIX_TEST_DECREF_BC(certSelector);
+
+ /* create cert chain */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certs, plContext));
+ for (i = 0; i < chainLength; i++) {
+ chainCertFile = argv[i + (2 + j)];
+ chainCert = createCert(chainCertFile);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certs, (PKIX_PL_Object *)chainCert, plContext));
+
+ PKIX_TEST_DECREF_BC(chainCert);
+ }
+
+ /* create validate params with processing params and cert chain */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_Create(procParams, certs, &valParams, plContext));
+
+ /* validate cert chain using processing params and return valResult */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+
+ if (valResult != NULL) {
+ printf("SUCCESSFULLY VALIDATED with Basic Constraint ");
+ printf("Cert Selector minimum path length to be -1\n");
+ PKIX_TEST_DECREF_BC(valResult);
+ }
+
+ 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);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(certSelParams, 6, plContext));
+
+ /* validate cert chain using processing params and return valResult */
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+
+ if (valResult != NULL) {
+ printf("SUCCESSFULLY VALIDATED with Basic Constraint ");
+ printf("Cert Selector minimum path length to be 6\n");
+ }
+
+ PKIX_TEST_DECREF_BC(trustedCert);
+ PKIX_TEST_DECREF_BC(anchor);
+ PKIX_TEST_DECREF_BC(anchors);
+ PKIX_TEST_DECREF_BC(certs);
+ PKIX_TEST_DECREF_BC(procParams);
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ printf("FAILED TO VALIDATE\n");
+ }
+
+ 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_AC(verifyString);
+ PKIX_TEST_DECREF_AC(verifyTree);
+
+ PKIX_TEST_DECREF_AC(certSelParams);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(valParams);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ endTests("ValidateChainBasicConstraints");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/util/Makefile b/security/nss/cmd/libpkix/pkix/util/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/Makefile
@@ -0,0 +1,45 @@
+#! 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/security/nss/cmd/libpkix/pkix/util/manifest.mn b/security/nss/cmd/libpkix/pkix/util/manifest.mn
new file mode 100644
index 0000000000..c7790c401b
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_error.c \
+ test_list.c \
+ test_list2.c \
+ test_logger.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtoolutil
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix/util/test_error.c b/security/nss/cmd/libpkix/pkix/util/test_error.c
new file mode 100644
index 0000000000..9cddecc827
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/test_error.c
@@ -0,0 +1,385 @@
+/* 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_error.c
+ *
+ * Tests Error Object Creation, ToString, Callbacks and Destroy
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createErrors(
+ PKIX_Error **error,
+ PKIX_Error **error2,
+ PKIX_Error **error3,
+ PKIX_Error **error5,
+ PKIX_Error **error6,
+ PKIX_Error **error7,
+ char *infoChar)
+
+{
+ PKIX_PL_String *infoString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ infoChar,
+ PL_strlen(infoChar),
+ &infoString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_MEM_ERROR,
+ NULL,
+ NULL,
+ PKIX_TESTANOTHERERRORMESSAGE,
+ error2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_OBJECT_ERROR,
+ *error2,
+ (PKIX_PL_Object *)infoString,
+ PKIX_TESTERRORMESSAGE,
+ error,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_OBJECT_ERROR,
+ *error2,
+ (PKIX_PL_Object *)infoString,
+ PKIX_TESTERRORMESSAGE,
+ error3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_OBJECT_ERROR,
+ NULL,
+ (PKIX_PL_Object *)infoString,
+ 0,
+ error5,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_MEM_ERROR,
+ *error5,
+ (PKIX_PL_Object *)infoString,
+ 0,
+ error6,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_Create(PKIX_OBJECT_ERROR,
+ *error6,
+ (PKIX_PL_Object *)infoString,
+ 0,
+ error7,
+ plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(infoString);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetErrorClass(PKIX_Error *error, PKIX_Error *error2)
+{
+ PKIX_ERRORCLASS errClass;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetErrorClass(error, &errClass, plContext));
+
+ if (errClass != PKIX_OBJECT_ERROR) {
+ testError("Incorrect Class Returned");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetErrorClass(error2, &errClass, plContext));
+
+ if (errClass != PKIX_MEM_ERROR) {
+ testError("Incorrect Class Returned");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetErrorClass(PKIX_ALLOC_ERROR(),
+ &errClass, plContext));
+ if (errClass != PKIX_FATAL_ERROR) {
+ testError("Incorrect Class Returned");
+ }
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetDescription(
+ PKIX_Error *error,
+ PKIX_Error *error2,
+ PKIX_Error *error3,
+ char *descChar,
+ char *descChar2)
+{
+
+ PKIX_PL_String *targetString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetDescription(error, &targetString, plContext));
+ temp = PKIX_String2ASCII(targetString, plContext);
+ PKIX_TEST_DECREF_BC(targetString);
+
+ if (temp) {
+ if (PL_strcmp(temp, descChar) != 0) {
+ testError("Incorrect description returned");
+ }
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetDescription(error2, &targetString, plContext));
+ temp = PKIX_String2ASCII(targetString, plContext);
+ PKIX_TEST_DECREF_BC(targetString);
+
+ if (temp) {
+ if (PL_strcmp(temp, descChar2) != 0) {
+ testError("Incorrect description returned");
+ }
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetDescription(error3, &targetString, plContext));
+ temp = PKIX_String2ASCII(targetString, plContext);
+ PKIX_TEST_DECREF_BC(targetString);
+
+ if (temp) {
+ if (PL_strcmp(temp, descChar) != 0) {
+ testError("Incorrect description returned");
+ }
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCause(PKIX_Error *error, PKIX_Error *error2, PKIX_Error *error3)
+{
+
+ PKIX_Error *error4 = NULL;
+ PKIX_PL_String *targetString = NULL;
+ char *temp = NULL;
+ PKIX_Boolean boolResult;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetCause(error, &error4, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)error2,
+ (PKIX_PL_Object *)error4,
+ &boolResult, plContext));
+ if (!boolResult)
+ testError("Incorrect Cause returned");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)error4,
+ &targetString, plContext));
+
+ temp = PKIX_String2ASCII(targetString, plContext);
+ if (temp) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_DECREF_BC(targetString);
+ PKIX_TEST_DECREF_BC(error4);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetCause(error3, &error4, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)error2,
+ (PKIX_PL_Object *)error4,
+ &boolResult, plContext));
+ if (!boolResult)
+ testError("Incorrect Cause returned");
+
+ PKIX_TEST_DECREF_BC(error4);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSupplementaryInfo(PKIX_Error *error, char *infoChar)
+{
+
+ PKIX_PL_Object *targetString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetSupplementaryInfo(error, &targetString, plContext));
+ temp = PKIX_String2ASCII((PKIX_PL_String *)targetString, plContext);
+ PKIX_TEST_DECREF_BC(targetString);
+
+ if (temp) {
+ if (PL_strcmp(temp, infoChar) != 0) {
+ testError("Incorrect info returned");
+ }
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testPrimitiveError(void)
+{
+ PKIX_PL_String *targetString = NULL;
+ PKIX_PL_String *targetStringCopy = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)PKIX_ALLOC_ERROR(),
+ &targetString, plContext));
+
+ temp = PKIX_String2ASCII(targetString, plContext);
+ if (temp) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ targetStringCopy = targetString;
+
+ PKIX_TEST_DECREF_BC(targetString);
+
+ /*
+ * We need to DECREF twice, b/c the PKIX_ALLOC_ERROR object
+ * which holds a cached copy of the stringRep can never be DECREF'd
+ */
+ PKIX_TEST_DECREF_BC(targetStringCopy);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testChaining(PKIX_Error *error7)
+{
+ PKIX_PL_String *targetString = NULL;
+ PKIX_Error *tempError = NULL;
+ char *temp = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)error7,
+ &targetString, plContext));
+
+ temp = PKIX_String2ASCII(targetString, plContext);
+ if (temp) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ for (i = 0, tempError = error7; i < 2; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Error_GetCause(tempError, &tempError, plContext));
+ if (tempError == NULL) {
+ testError("Unexpected end to error chain");
+ break;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_DecRef((PKIX_PL_Object *)tempError, plContext));
+ }
+
+ PKIX_TEST_DECREF_BC(targetString);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(PKIX_Error *error)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(error);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_error(int argc, char *argv[])
+{
+
+ PKIX_Error *error, *error2, *error3, *error5, *error6, *error7;
+ char *descChar = "Error Message";
+ char *descChar2 = "Another Error Message";
+ char *infoChar = "Auxiliary Info";
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Errors");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_Error_Create");
+ createErrors(&error,
+ &error2,
+ &error3,
+ &error5,
+ &error6,
+ &error7,
+ infoChar);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(error,
+ error,
+ error2,
+ NULL,
+ Error,
+ PKIX_TRUE);
+
+ subTest("PKIX_Error_GetErrorClass");
+ testGetErrorClass(error, error2);
+
+ subTest("PKIX_Error_GetDescription");
+ testGetDescription(error, error2, error3, descChar, descChar2);
+
+ subTest("PKIX_Error_GetCause");
+ testGetCause(error, error2, error3);
+
+ subTest("PKIX_Error_GetSupplementaryInfo");
+ testGetSupplementaryInfo(error, infoChar);
+
+ subTest("Primitive Error Type");
+ testPrimitiveError();
+
+ subTest("Error Chaining");
+ testChaining(error7);
+
+ subTest("PKIX_Error_Destroy");
+ testDestroy(error);
+ testDestroy(error2);
+ testDestroy(error3);
+ testDestroy(error5);
+ testDestroy(error6);
+ testDestroy(error7);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Errors");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/util/test_list.c b/security/nss/cmd/libpkix/pkix/util/test_list.c
new file mode 100644
index 0000000000..e5e6e507ba
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/test_list.c
@@ -0,0 +1,765 @@
+/* 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_list.c
+ *
+ * Tests List Objects
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createLists(PKIX_List **list, PKIX_List **list2)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(list, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(list2, plContext));
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testReverseList(void)
+{
+ PKIX_List *firstList = NULL;
+ PKIX_List *reverseList = NULL;
+ PKIX_UInt32 length, i;
+ char *testItemString = "one";
+ char *testItemString2 = "two";
+ PKIX_PL_String *testItem = NULL;
+ PKIX_PL_String *testItem2 = NULL;
+ PKIX_PL_Object *retrievedItem1 = NULL;
+ PKIX_PL_Object *retrievedItem2 = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&firstList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_ReverseList(firstList, &reverseList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(reverseList, &length, plContext));
+ if (length != 0) {
+ testError("Incorrect Length returned");
+ }
+
+ PKIX_TEST_DECREF_BC(reverseList);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString,
+ 0,
+ &testItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString2,
+ 0,
+ &testItem2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(firstList,
+ (PKIX_PL_Object *)testItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_ReverseList(firstList, &reverseList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(reverseList, &length, plContext));
+ if (length != 1) {
+ testError("Incorrect Length returned");
+ }
+
+ PKIX_TEST_DECREF_BC(reverseList);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(firstList,
+ (PKIX_PL_Object *)testItem2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(firstList,
+ (PKIX_PL_Object *)testItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(firstList,
+ (PKIX_PL_Object *)testItem2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_ReverseList(firstList, &reverseList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(reverseList, &length, plContext));
+ if (length != 4) {
+ testError("Incorrect Length returned");
+ }
+
+ for (i = 0; i < length; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(firstList,
+ i,
+ &retrievedItem1,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(reverseList,
+ (length - 1) - i,
+ &retrievedItem2,
+ plContext));
+
+ testEqualsHelper(retrievedItem1, retrievedItem2, PKIX_TRUE, plContext);
+
+ PKIX_TEST_DECREF_BC(retrievedItem1);
+ PKIX_TEST_DECREF_BC(retrievedItem2);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstList);
+ PKIX_TEST_DECREF_AC(reverseList);
+
+ PKIX_TEST_DECREF_AC(testItem);
+ PKIX_TEST_DECREF_AC(testItem2);
+
+ PKIX_TEST_DECREF_AC(retrievedItem1);
+ PKIX_TEST_DECREF_AC(retrievedItem2);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testZeroLengthList(PKIX_List *list)
+{
+ PKIX_UInt32 length;
+ PKIX_Boolean empty;
+ char *testItemString = "hello";
+ PKIX_PL_String *testItem = NULL;
+ PKIX_PL_String *retrievedItem = NULL;
+ PKIX_List *diffList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&diffList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(list, &length, plContext));
+
+ if (length != 0) {
+ testError("Incorrect Length returned");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsEmpty(list, &empty, plContext));
+ if (!empty) {
+ testError("Incorrect result for PKIX_List_IsEmpty");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString,
+ 0,
+ &testItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_InsertItem(list, 0, (PKIX_PL_Object *)testItem, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_SetItem(list, 0, (PKIX_PL_Object *)testItem, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_GetItem(list,
+ 0,
+ (PKIX_PL_Object **)&retrievedItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(list, 0, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(diffList,
+ (PKIX_PL_Object *)testItem,
+ plContext));
+
+ testDuplicateHelper((PKIX_PL_Object *)diffList, plContext);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(list, list, diffList, "(EMPTY)", List, PKIX_TRUE);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(diffList, &length, plContext));
+ if (length != 1) {
+ testError("Incorrect Length returned");
+ }
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(list, 1, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(diffList, 0, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(diffList, &length, plContext));
+ if (length != 0) {
+ testError("Incorrect Length returned");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(testItem);
+ PKIX_TEST_DECREF_AC(diffList);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetLength(PKIX_List *list)
+{
+ PKIX_UInt32 length;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(list, &length, plContext));
+
+ if (length != 3) {
+ testError("Incorrect Length returned");
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSetItem(
+ PKIX_List *list,
+ char *testItemString,
+ char *testItemString2,
+ char *testItemString3,
+ PKIX_PL_String **testItem,
+ PKIX_PL_String **testItem2,
+ PKIX_PL_String **testItem3)
+{
+ PKIX_PL_Object *tempItem = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString,
+ PL_strlen(testItemString),
+ testItem,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString2,
+ PL_strlen(testItemString2),
+ testItem2,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString3,
+ PL_strlen(testItemString3),
+ testItem3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)*testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)*testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)*testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, 0, (PKIX_PL_Object *)*testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, 1, (PKIX_PL_Object *)*testItem2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, 2, (PKIX_PL_Object *)*testItem3, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, 0, &tempItem, plContext));
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ if (PL_strcmp(testItemString, temp) != 0)
+ testError("GetItem from list is incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_DECREF_BC(tempItem);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, 1, &tempItem, plContext));
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ if (PL_strcmp(testItemString2, temp) != 0)
+ testError("GetItem from list is incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(tempItem);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, 2, &tempItem, plContext));
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ if (PL_strcmp(testItemString3, temp) != 0)
+ testError("GetItem from list is incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(tempItem);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, 0, (PKIX_PL_Object *)*testItem3, plContext));
+ temp = PKIX_String2ASCII(*testItem3, plContext);
+ if (temp) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, 0, &tempItem, plContext));
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ if (PL_strcmp(testItemString3, temp) != 0)
+ testError("GetItem from list is incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(tempItem);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testInsertItem(
+ PKIX_List *list,
+ PKIX_PL_String *testItem,
+ char *testItemString)
+{
+ PKIX_PL_Object *tempItem = NULL;
+ PKIX_PL_String *outputString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_InsertItem(list, 0, (PKIX_PL_Object *)testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, 0, &tempItem, plContext));
+
+ temp = PKIX_String2ASCII((PKIX_PL_String *)tempItem, plContext);
+ if (temp) {
+ if (PL_strcmp(testItemString, temp) != 0)
+ testError("GetItem from list is incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(tempItem);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, c, b, c)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_DECREF_BC(outputString);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAppendItem(PKIX_List *list, PKIX_PL_String *testItem)
+{
+ PKIX_UInt32 length2;
+ PKIX_PL_String *outputString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(list, &length2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list,
+ (PKIX_PL_Object *)testItem,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, c, b, c, a)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+ PKIX_TEST_DECREF_BC(outputString);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testNestedLists(
+ PKIX_List *list,
+ PKIX_List *list2,
+ PKIX_PL_String *testItem,
+ PKIX_PL_String *testItem2)
+{
+ PKIX_PL_String *outputString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list2, (PKIX_PL_Object *)testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list2,
+ (PKIX_PL_Object *)NULL,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list2,
+ (PKIX_PL_Object *)testItem,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list2,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, (null), a)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_InsertItem(list, 1,
+ (PKIX_PL_Object *)list2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, (a, (null), a), c, b, c, a)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDeleteItem(
+ PKIX_List *list,
+ PKIX_List *list2,
+ PKIX_PL_String *testItem2,
+ PKIX_PL_String *testItem3)
+{
+ PKIX_PL_String *outputString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(list, 5, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, (a, (null), a), c, b, c)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(list, 1, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, c, b, c)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(list, 0, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(c, b, c)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(list2, 1, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list2,
+ &outputString,
+ plContext));
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, a)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list2,
+ (PKIX_PL_Object *)testItem2,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list2,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, a, b)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_DeleteItem(list2, 2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list2,
+ &outputString,
+ plContext));
+
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, a)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list2,
+ (PKIX_PL_Object *)testItem3,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list2,
+ &outputString,
+ plContext));
+ temp = PKIX_String2ASCII(outputString, plContext);
+ if (temp) {
+ if (PL_strcmp("(a, a, c)", temp) != 0)
+ testError("List toString is Incorrect");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(outputString);
+
+ PKIX_TEST_DECREF_BC(list2);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+#if testContainsFunction
+/* This test requires pkix_List_Contains to be in nss.def */
+static void
+testContains(void)
+{
+
+ PKIX_List *list;
+ PKIX_PL_String *testItem, *testItem2, *testItem3, *testItem4;
+ char *testItemString = "a";
+ char *testItemString2 = "b";
+ char *testItemString3 = "c";
+ char *testItemString4 = "d";
+ PKIX_Boolean found = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+ subTest("pkix_ListContains");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString,
+ PL_strlen(testItemString),
+ &testItem,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString2,
+ PL_strlen(testItemString2),
+ &testItem2,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString3,
+ PL_strlen(testItemString3),
+ &testItem3,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ testItemString4,
+ PL_strlen(testItemString4),
+ &testItem4,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&list, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)testItem, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)testItem2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)testItem3, plContext));
+
+ subTest("pkix_List_Contains <object missing>");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_List_Contains(list, (PKIX_PL_Object *)testItem4, &found, plContext));
+
+ if (found) {
+ testError("Contains found item that wasn't there!");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)testItem4, plContext));
+
+ subTest("pkix_List_Contains <object present>");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_List_Contains(list, (PKIX_PL_Object *)testItem4, &found, plContext));
+
+ if (!found) {
+ testError("Contains missed item that was present!");
+ }
+
+ PKIX_TEST_DECREF_BC(list);
+ PKIX_TEST_DECREF_BC(testItem);
+ PKIX_TEST_DECREF_BC(testItem2);
+ PKIX_TEST_DECREF_BC(testItem3);
+ PKIX_TEST_DECREF_BC(testItem4);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+#endif
+
+static void
+testErrorHandling(void)
+{
+ PKIX_List *emptylist = NULL;
+ PKIX_List *list = NULL;
+ PKIX_PL_Object *tempItem = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&list, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_GetItem(list, 4, &tempItem, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_GetItem(list, 1, NULL, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_SetItem(list, 4, tempItem, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_SetItem(NULL, 1, tempItem, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_InsertItem(list, 4, tempItem, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_InsertItem(NULL, 1, tempItem, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_AppendItem(NULL, tempItem, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(list, 5, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(NULL, 1, plContext));
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_GetLength(list, NULL, plContext));
+
+ PKIX_TEST_DECREF_BC(list);
+ PKIX_TEST_DECREF_BC(emptylist);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(PKIX_List *list)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(list);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_list(int argc, char *argv[])
+{
+
+ PKIX_List *list, *list2;
+ PKIX_PL_String *testItem, *testItem2, *testItem3;
+ char *testItemString = "a";
+ char *testItemString2 = "b";
+ char *testItemString3 = "c";
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Lists");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_List_Create");
+ createLists(&list, &list2);
+
+ subTest("pkix_List_ReverseList");
+ testReverseList();
+
+ subTest("Zero-length List");
+ testZeroLengthList(list);
+
+ subTest("PKIX_List_Get/SetItem");
+ testGetSetItem(list,
+ testItemString,
+ testItemString2,
+ testItemString3,
+ &testItem,
+ &testItem2,
+ &testItem3);
+
+ subTest("PKIX_List_GetLength");
+ testGetLength(list);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(list,
+ list,
+ list2,
+ "(c, b, c)",
+ List,
+ PKIX_TRUE);
+
+ subTest("PKIX_List_InsertItem");
+ testInsertItem(list, testItem, testItemString);
+
+ subTest("PKIX_List_AppendItem");
+ testAppendItem(list, testItem);
+
+ subTest("Nested Lists");
+ testNestedLists(list, list2, testItem, testItem2);
+
+ subTest("PKIX_List_DeleteItem");
+ testDeleteItem(list, list2, testItem2, testItem3);
+
+ PKIX_TEST_DECREF_BC(testItem);
+ PKIX_TEST_DECREF_BC(testItem2);
+ PKIX_TEST_DECREF_BC(testItem3);
+
+#if testContainsFunction
+ /* This test requires pkix_List_Contains to be in nss.def */
+ testContains();
+#endif
+
+ subTest("PKIX_List Error Handling");
+ testErrorHandling();
+
+ subTest("PKIX_List_Destroy");
+ testDestroy(list);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Lists");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/util/test_list2.c b/security/nss/cmd/libpkix/pkix/util/test_list2.c
new file mode 100644
index 0000000000..b802ff0e66
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/test_list2.c
@@ -0,0 +1,118 @@
+/* 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_list2.c
+ *
+ * Performs an in-place sort on a list
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+int
+test_list2(int argc, char *argv[])
+{
+
+ PKIX_List *list;
+ char *temp;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Int32 cmpResult;
+ PKIX_PL_OID *testOID;
+ PKIX_PL_String *testString;
+ PKIX_PL_Object *obj, *obj2;
+ PKIX_UInt32 size = 10;
+ char *testOIDString[10] = {
+ "2.9.999.1.20",
+ "1.2.3.4.5.6.7",
+ "0.1",
+ "1.2.3.5",
+ "0.39",
+ "1.2.3.4.7",
+ "1.2.3.4.6",
+ "0.39.1",
+ "1.2.3.4.5",
+ "0.39.1.300"
+ };
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("List Sorting");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("Creating Unsorted Lists");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&list, plContext));
+ for (i = 0; i < size; i++) {
+ /* Create a new OID object */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(
+ testOIDString[i],
+ &testOID,
+ plContext));
+ /* Insert it into the list */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)testOID, plContext));
+ /* Decref the string object */
+ PKIX_TEST_DECREF_BC(testOID);
+ }
+
+ subTest("Outputting Unsorted List");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &testString,
+ plContext));
+ temp = PKIX_String2ASCII(testString, plContext);
+ if (temp) {
+ (void)printf("%s \n", temp);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+ PKIX_TEST_DECREF_BC(testString);
+
+ subTest("Performing Bubble Sort");
+
+ for (i = 0; i < size; i++)
+ for (j = 9; j > i; j--) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, j, &obj, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, j - 1,
+ &obj2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare(obj, obj2, &cmpResult, plContext));
+ if (cmpResult < 0) {
+ /* Exchange the items */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, j, obj2, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, j - 1,
+ obj, plContext));
+ }
+ /* DecRef objects */
+ PKIX_TEST_DECREF_BC(obj);
+ PKIX_TEST_DECREF_BC(obj2);
+ }
+
+ subTest("Outputting Sorted List");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
+ &testString,
+ plContext));
+ temp = PKIX_String2ASCII(testString, plContext);
+ if (temp) {
+ (void)printf("%s \n", temp);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(testString);
+ PKIX_TEST_DECREF_AC(list);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("List Sorting");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix/util/test_logger.c b/security/nss/cmd/libpkix/pkix/util/test_logger.c
new file mode 100644
index 0000000000..3b7e5160a3
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix/util/test_logger.c
@@ -0,0 +1,314 @@
+/* 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_logger.c
+ *
+ * Tests Logger Objects
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static char *levels[] = {
+ "None",
+ "Fatal Error",
+ "Error",
+ "Warning",
+ "Debug",
+ "Trace"
+};
+
+static PKIX_Error *
+testLoggerCallback(
+ PKIX_Logger *logger,
+ PKIX_PL_String *message,
+ PKIX_UInt32 logLevel,
+ PKIX_ERRORCLASS logComponent,
+ void *plContext)
+{
+ char *comp = NULL;
+ char *msg = NULL;
+ char result[100];
+ static int callCount = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ msg = PKIX_String2ASCII(message, plContext);
+ PR_snprintf(result, 100, "Logging %s (%s): %s",
+ levels[logLevel], PKIX_ERRORCLASSNAMES[logComponent], msg);
+ subTest(result);
+
+ callCount++;
+ if (callCount > 1) {
+ testError("Incorrect number of Logger Callback <expect 1>");
+ }
+
+cleanup:
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(msg, plContext));
+ PKIX_TEST_RETURN();
+}
+
+static PKIX_Error *
+testLoggerCallback2(
+ PKIX_Logger *logger,
+ PKIX_PL_String *message,
+ PKIX_UInt32 logLevel,
+ PKIX_ERRORCLASS logComponent,
+ void *plContext)
+{
+ char *comp = NULL;
+ char *msg = NULL;
+ char result[100];
+
+ PKIX_TEST_STD_VARS();
+
+ msg = PKIX_String2ASCII(message, plContext);
+ PR_snprintf(result, 100, "Logging %s (%s): %s",
+ levels[logLevel], PKIX_ERRORCLASSNAMES[logComponent], msg);
+ subTest(result);
+
+cleanup:
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(msg, plContext));
+ PKIX_TEST_RETURN();
+}
+
+static void
+createLogger(PKIX_Logger **logger,
+ PKIX_PL_Object *context,
+ PKIX_Logger_LogCallback cb)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_Create(cb, context, logger, plContext));
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testContextCallback(PKIX_Logger *logger, PKIX_Logger *logger2)
+{
+ PKIX_Logger_LogCallback cb = NULL;
+ PKIX_PL_Object *context = NULL;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+ PKIX_UInt32 length;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_Logger_GetLoggerContext");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetLoggerContext(logger2, &context, plContext));
+
+ testEqualsHelper((PKIX_PL_Object *)logger, context, PKIX_TRUE, plContext);
+
+ subTest("PKIX_Logger_GetLogCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetLogCallback(logger, &cb, plContext));
+
+ if (cb != testLoggerCallback) {
+ testError("Incorrect Logger Callback returned");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(context);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testComponent(PKIX_Logger *logger)
+{
+ PKIX_ERRORCLASS compName = (PKIX_ERRORCLASS)NULL;
+ PKIX_ERRORCLASS compNameReturn = (PKIX_ERRORCLASS)NULL;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_Logger_GetLoggingComponent");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetLoggingComponent(logger, &compName, plContext));
+
+ if (compName != (PKIX_ERRORCLASS)NULL) {
+ testError("Incorrect Logger Component returned. expect <NULL>");
+ }
+
+ subTest("PKIX_Logger_SetLoggingComponent");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetLoggingComponent(logger, PKIX_LIST_ERROR, plContext));
+
+ subTest("PKIX_Logger_GetLoggingComponent");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetLoggingComponent(logger, &compNameReturn, plContext));
+
+ if (compNameReturn != PKIX_LIST_ERROR) {
+ testError("Incorrect Logger Component returned.");
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testMaxLoggingLevel(PKIX_Logger *logger)
+{
+ PKIX_UInt32 level = 0;
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_Logger_GetMaxLoggingLevel");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetMaxLoggingLevel(logger, &level, plContext));
+
+ if (level != 0) {
+ testError("Incorrect Logger MaxLoggingLevel returned");
+ }
+
+ subTest("PKIX_Logger_SetMaxLoggingLevel");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetMaxLoggingLevel(logger, 3, plContext));
+
+ subTest("PKIX_Logger_GetMaxLoggingLevel");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_GetMaxLoggingLevel(logger, &level, plContext));
+
+ if (level != 3) {
+ testError("Incorrect Logger MaxLoggingLevel returned");
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testLogger(PKIX_Logger *logger, PKIX_Logger *logger2)
+{
+ PKIX_List *loggerList = NULL;
+ PKIX_List *checkList = NULL;
+ PKIX_UInt32 length;
+ PKIX_Boolean cmpResult = PKIX_FALSE;
+ char *expectedAscii = "[\n"
+ "\tLogger: \n"
+ "\tContext: (null)\n"
+ "\tMaximum Level: 3\n"
+ "\tComponent Name: LIST\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_GetLoggers");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_GetLoggers(&loggerList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(loggerList, &length, plContext));
+ if (length != 0) {
+ testError("Incorrect Logger List returned");
+ }
+ PKIX_TEST_DECREF_BC(loggerList);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&loggerList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(loggerList, (PKIX_PL_Object *)logger, plContext));
+
+ subTest("PKIX_SetLoggers");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_SetLoggers(loggerList, plContext));
+
+ subTest("PKIX_Logger_SetLoggingComponent");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetLoggingComponent(logger2, PKIX_MUTEX_ERROR, plContext));
+
+ subTest("PKIX_Logger_SetMaxLoggingLevel");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Logger_SetMaxLoggingLevel(logger2, 5, plContext));
+
+ subTest("PKIX_AddLogger");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_AddLogger(logger2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&checkList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(checkList, (PKIX_PL_Object *)logger, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(checkList, (PKIX_PL_Object *)logger2, plContext));
+
+ PKIX_TEST_DECREF_BC(loggerList);
+
+ subTest("PKIX_GetLoggers");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_GetLoggers(&loggerList, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(loggerList, &length, plContext));
+
+ subTest("pkix_Loggers_Equals");
+ testEqualsHelper((PKIX_PL_Object *)loggerList,
+ (PKIX_PL_Object *)checkList,
+ PKIX_TRUE,
+ plContext);
+
+ subTest("pkix_Loggers_Duplicate");
+ testDuplicateHelper((PKIX_PL_Object *)logger, plContext);
+
+ subTest("pkix_Loggers_Hashcode");
+ testHashcodeHelper((PKIX_PL_Object *)logger,
+ (PKIX_PL_Object *)logger,
+ PKIX_TRUE,
+ plContext);
+
+ subTest("pkix_Loggers_ToString");
+ testToStringHelper((PKIX_PL_Object *)logger, expectedAscii, plContext);
+
+ subTest("PKIX Logger Callback");
+ subTest("Expect to have ***Fatal Error (List): Null argument*** once");
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_AppendItem(NULL, (PKIX_PL_Object *)NULL, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(loggerList);
+ PKIX_TEST_DECREF_AC(checkList);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(PKIX_Logger *logger)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(logger);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_logger(int argc, char *argv[])
+{
+
+ PKIX_Logger *logger, *logger2;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Loggers");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_Logger_Create");
+ createLogger(&logger, NULL, testLoggerCallback);
+ createLogger(&logger2, (PKIX_PL_Object *)logger, testLoggerCallback2);
+
+ subTest("Logger Context and Callback");
+ testContextCallback(logger, logger2);
+
+ subTest("Logger Component");
+ testComponent(logger);
+
+ subTest("Logger MaxLoggingLevel");
+ testMaxLoggingLevel(logger);
+
+ subTest("Logger List operations");
+ testLogger(logger, logger2);
+
+ subTest("PKIX_Logger_Destroy");
+ testDestroy(logger);
+ testDestroy(logger2);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Loggers");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/Makefile b/security/nss/cmd/libpkix/pkix_pl/Makefile
new file mode 100644
index 0000000000..1de5ef2694
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/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/security/nss/cmd/libpkix/pkix_pl/manifest.mn b/security/nss/cmd/libpkix/pkix_pl/manifest.mn
new file mode 100644
index 0000000000..84997cbe6f
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/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 = module pki system \
+ $(NULL)
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/Makefile b/security/nss/cmd/libpkix/pkix_pl/module/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/Makefile
@@ -0,0 +1,45 @@
+#! 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/security/nss/cmd/libpkix/pkix_pl/module/manifest.mn b/security/nss/cmd/libpkix/pkix_pl/module/manifest.mn
new file mode 100644
index 0000000000..50d20d0bb4
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/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/.
+
+PKIX_DEPTH = ../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+
+# MODULE public and private header directories are implicitly REQUIRED.
+MODULE = nss
+
+CSRCS = test_colcertstore.c \
+ test_ekuchecker.c \
+ test_pk11certstore.c \
+ test_socket.c \
+ test_httpcertstore.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtoolmodule
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/test_colcertstore.c b/security/nss/cmd/libpkix/pkix_pl/module/test_colcertstore.c
new file mode 100644
index 0000000000..37169d6ff7
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/test_colcertstore.c
@@ -0,0 +1,247 @@
+/* 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_colcertstore.c
+ *
+ * Test CollectionCertStore Type
+ *
+ */
+
+#include "testutil.h"
+
+#include "testutil_nss.h"
+
+/* When CRL IDP is supported, change NUM_CRLS to 9 */
+#define PKIX_TEST_COLLECTIONCERTSTORE_NUM_CRLS 4
+#define PKIX_TEST_COLLECTIONCERTSTORE_NUM_CERTS 15
+
+static void *plContext = NULL;
+
+static PKIX_Error *
+testCRLSelectorMatchCallback(
+ PKIX_CRLSelector *selector,
+ PKIX_PL_CRL *crl,
+ PKIX_Boolean *pMatch,
+ void *plContext)
+{
+ *pMatch = PKIX_TRUE;
+
+ return (0);
+}
+
+static PKIX_Error *
+testCertSelectorMatchCallback(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ *pResult = PKIX_TRUE;
+
+ return (0);
+}
+
+static PKIX_Error *
+getCertCallback(
+ PKIX_CertStore *store,
+ PKIX_CertSelector *certSelector,
+ PKIX_List **pCerts,
+ 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
+testGetCRL(char *crlDir)
+{
+ PKIX_PL_String *dirString = NULL;
+ PKIX_CertStore_CRLCallback crlCallback;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_UInt32 numCrl = 0;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ crlDir,
+ 0,
+ &dirString,
+ plContext));
+
+ subTest("PKIX_PL_CollectionCertStore_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString,
+ &certStore,
+ plContext));
+
+ subTest("PKIX_CRLSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create(testCRLSelectorMatchCallback,
+ NULL,
+ &crlSelector,
+ plContext));
+
+ subTest("PKIX_CertStore_GetCRLCallback");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback(certStore, &crlCallback, NULL));
+
+ subTest("Getting data from 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(dirString);
+ PKIX_TEST_DECREF_AC(crlList);
+ PKIX_TEST_DECREF_AC(crlSelector);
+ PKIX_TEST_DECREF_AC(certStore);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCert(char *certDir)
+{
+ 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();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ certDir,
+ 0,
+ &dirString,
+ plContext));
+
+ subTest("PKIX_PL_CollectionCertStore_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(testCertSelectorMatchCallback,
+ NULL,
+ &certSelector,
+ 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_COLLECTIONCERTSTORE_NUM_CERTS) {
+ pkixTestErrorMsg = "unexpected Cert number mismatch";
+ }
+
+cleanup:
+
+ 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
+printUsage(char *pName)
+{
+ printf("\nUSAGE: %s test-purpose <data-dir> <platform-dir>\n\n", pName);
+}
+
+/* Functional tests for CollectionCertStore public functions */
+
+int
+test_colcertstore(int argc, char *argv[])
+{
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *platformDir = NULL;
+ char *dataDir = NULL;
+ char *combinedDir = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CollectionCertStore");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < (3 + j)) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ dataDir = argv[2 + j];
+ platformDir = argv[3 + j];
+ combinedDir = catDirName(platformDir, dataDir, plContext);
+
+ testGetCRL(combinedDir);
+ testGetCert(combinedDir);
+
+cleanup:
+
+ pkixTestErrorResult = PKIX_PL_Free(combinedDir, plContext);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CollectionCertStore");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/test_ekuchecker.c b/security/nss/cmd/libpkix/pkix_pl/module/test_ekuchecker.c
new file mode 100644
index 0000000000..ccd05a5bf8
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/test_ekuchecker.c
@@ -0,0 +1,275 @@
+/* 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_ekuchecker.c
+ *
+ * Test Extend Key Usage Checker
+ *
+ */
+
+#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("[E]oid[,oid]* <data-dir> 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 *
+testCertSelectorMatchCallback(
+ PKIX_CertSelector *selector,
+ PKIX_PL_Cert *cert,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ *pResult = PKIX_TRUE;
+
+ return (0);
+}
+
+static PKIX_Error *
+testEkuSetup(
+ PKIX_ValidateParams *valParams,
+ char *ekuOidString,
+ PKIX_Boolean *only4EE)
+{
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_List *ekuList = NULL;
+ PKIX_PL_OID *ekuOid = NULL;
+ PKIX_ComCertSelParams *selParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_Boolean last_token = PKIX_FALSE;
+ PKIX_UInt32 i, tokeni;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_ValidateParams_GetProcessingParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(valParams, &procParams, plContext));
+
+ /* Get extended key usage OID(s) from command line, separated by "," */
+
+ if (ekuOidString[0] == '"') {
+ /* erase doble quotes, if any */
+ i = 1;
+ while (ekuOidString[i] != '"' && ekuOidString[i] != '\0') {
+ ekuOidString[i - 1] = ekuOidString[i];
+ i++;
+ }
+ ekuOidString[i - 1] = '\0';
+ }
+
+ if (ekuOidString[0] == '\0') {
+ ekuList = NULL;
+ } else {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&ekuList, plContext));
+
+ /* if OID string start with E, only check for last cert */
+ if (ekuOidString[0] == 'E') {
+ *only4EE = PKIX_TRUE;
+ tokeni = 2;
+ i = 1;
+ } else {
+ *only4EE = PKIX_FALSE;
+ tokeni = 1;
+ i = 0;
+ }
+
+ while (last_token != PKIX_TRUE) {
+ while (ekuOidString[tokeni] != ',' &&
+ ekuOidString[tokeni] != '\0') {
+ tokeni++;
+ }
+ if (ekuOidString[tokeni] == '\0') {
+ last_token = PKIX_TRUE;
+ } else {
+ ekuOidString[tokeni] = '\0';
+ tokeni++;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(&ekuOidString[i], &ekuOid, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(ekuList, (PKIX_PL_Object *)ekuOid, plContext));
+
+ PKIX_TEST_DECREF_BC(ekuOid);
+ i = tokeni;
+ }
+ }
+
+ /* Set extended key usage link to processing params */
+
+ subTest("PKIX_ComCertSelParams_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&selParams, plContext));
+
+ subTest("PKIX_ComCertSelParams_SetExtendedKeyUsage");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetExtendedKeyUsage(selParams, ekuList, plContext));
+
+ subTest("PKIX_CertSelector_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(testCertSelectorMatchCallback,
+ NULL,
+ &certSelector,
+ plContext));
+
+ subTest("PKIX_CertSelector_SetCommonCertSelectorParams");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, selParams, plContext));
+
+ subTest("PKIX_ProcessingParams_SetTargetCertConstraints");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(selParams);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(procParams);
+ PKIX_TEST_DECREF_AC(ekuOid);
+ PKIX_TEST_DECREF_AC(ekuList);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+static PKIX_Error *
+testEkuChecker(
+ PKIX_ValidateParams *valParams,
+ PKIX_Boolean only4EE)
+{
+ PKIX_ProcessingParams *procParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams(valParams, &procParams, plContext));
+
+ subTest("PKIX_ProcessingParams_SetRevocationEnabled - disable");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_FALSE, plContext));
+
+ if (only4EE == PKIX_FALSE) {
+ subTest("PKIX_PL_EkuChecker_Create");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_EkuChecker_Create(procParams, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(procParams);
+
+ PKIX_TEST_RETURN();
+
+ return (0);
+}
+
+int
+test_ekuchecker(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];
+ char *dirName = NULL;
+ PKIX_PL_Cert *certs[PKIX_TEST_MAX_CERTS];
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean testValid = PKIX_FALSE;
+ PKIX_Boolean only4EE = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 5) {
+ printUsage1(argv[0]);
+ return (0);
+ }
+
+ startTests("EKU 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);
+ }
+
+ dirName = argv[4 + j];
+
+ chainLength = (argc - j) - 6;
+ if (chainLength > PKIX_TEST_MAX_CERTS) {
+ printUsageMax(chainLength);
+ }
+
+ for (i = 0; i < chainLength; i++) {
+
+ certNames[i] = argv[6 + i + j];
+ certs[i] = NULL;
+ }
+
+ subTest(argv[1 + j]);
+
+ subTest("Extended-Key-Usage-Checker");
+
+ subTest("Extended-Key-Usage-Checker - Create Cert Chain");
+
+ chain = createCertChainPlus(dirName, certNames, certs, chainLength, plContext);
+
+ subTest("Extended-Key-Usage-Checker - Create Params");
+
+ valParams = createValidateParams(dirName,
+ argv[5 +
+ j],
+ NULL,
+ NULL,
+ NULL,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ PKIX_FALSE,
+ chain,
+ plContext);
+
+ subTest("Default CertStore");
+
+ testEkuSetup(valParams, argv[3 + j], &only4EE);
+
+ testEkuChecker(valParams, only4EE);
+
+ subTest("Extended-Key-Usage-Checker - Validate Chain");
+
+ if (testValid == PKIX_TRUE) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, NULL, plContext));
+ } else {
+ 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_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("EKU Checker");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/test_httpcertstore.c b/security/nss/cmd/libpkix/pkix_pl/module/test_httpcertstore.c
new file mode 100644
index 0000000000..62f86300ab
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/test_httpcertstore.c
@@ -0,0 +1,300 @@
+/*
+ * test_httpcertstore.c
+ *
+ * Test Httpcertstore Type
+ *
+ * Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
+ * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
+ * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
+ * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
+ * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
+ * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
+ * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
+ * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+#include "pkix_pl_common.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(char *testname)
+{
+ char *fmt =
+ "USAGE: %s [-arenas] certDir certName\n";
+ printf(fmt, "test_httpcertstore");
+}
+
+/* Functional tests for Socket public functions */
+static void
+do_other_work(void)
+{ /* while waiting for nonblocking I/O to complete */
+ (void)PR_Sleep(2 * 60);
+}
+
+PKIX_Error *
+PKIX_PL_HttpCertStore_Create(
+ PKIX_PL_HttpClient *client, /* if NULL, use default Client */
+ PKIX_PL_GeneralName *location,
+ PKIX_CertStore **pCertStore,
+ void *plContext);
+
+PKIX_Error *
+pkix_pl_HttpCertStore_CreateWithAsciiName(
+ PKIX_PL_HttpClient *client, /* if NULL, use default Client */
+ char *location,
+ PKIX_CertStore **pCertStore,
+ void *plContext);
+
+static PKIX_Error *
+getLocation(
+ PKIX_PL_Cert *certWithAia,
+ PKIX_PL_GeneralName **pLocation,
+ void *plContext)
+{
+ PKIX_List *aiaList = NULL;
+ PKIX_UInt32 size = 0;
+ PKIX_PL_InfoAccess *aia = NULL;
+ PKIX_UInt32 iaType = PKIX_INFOACCESS_LOCATION_UNKNOWN;
+ PKIX_PL_GeneralName *location = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Getting Authority Info Access");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityInfoAccess(certWithAia, &aiaList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(aiaList, &size, plContext));
+
+ if (size != 1) {
+ pkixTestErrorMsg = "unexpected number of AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(aiaList, 0, (PKIX_PL_Object **)&aia, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_InfoAccess_GetLocationType(aia, &iaType, plContext));
+
+ if (iaType != PKIX_INFOACCESS_LOCATION_HTTP) {
+ pkixTestErrorMsg = "unexpected location type in AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_InfoAccess_GetLocation(aia, &location, plContext));
+
+ *pLocation = location;
+
+cleanup:
+ PKIX_TEST_DECREF_AC(aiaList);
+ PKIX_TEST_DECREF_AC(aia);
+
+ PKIX_TEST_RETURN();
+
+ return (NULL);
+}
+
+int
+test_httpcertstore(int argc, char *argv[])
+{
+
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 numCerts = 0;
+ PKIX_UInt32 numCrls = 0;
+ int j = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 length = 0;
+
+ char *certName = NULL;
+ char *certDir = NULL;
+ PKIX_PL_Cert *cmdLineCert = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertStore *crlStore = NULL;
+ PKIX_PL_GeneralName *location = NULL;
+ PKIX_CertStore_CertCallback getCerts = NULL;
+ PKIX_List *certs = NULL;
+ char *asciiResult = NULL;
+ void *nbio = NULL;
+
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ char *crlLocation = "http://betty.nist.gov/pathdiscoverytestsuite/CRL"
+ "files/BasicHTTPURIPeer2CACRL.crl";
+ PKIX_CertStore_CRLCallback getCrls = NULL;
+ PKIX_List *crls = NULL;
+ PKIX_PL_String *crlString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("HttpCertStore");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc != (j + 3)) {
+ printUsage(argv[0]);
+ pkixTestErrorMsg = "Missing command line argument.";
+ goto cleanup;
+ }
+
+ certDir = argv[++j];
+ certName = argv[++j];
+
+ cmdLineCert = createCert(certDir, certName, plContext);
+ if (cmdLineCert == NULL) {
+ pkixTestErrorMsg = "Unable to create Cert";
+ goto cleanup;
+ }
+
+ /* muster arguments to create HttpCertStore */
+ PKIX_TEST_EXPECT_NO_ERROR(getLocation(cmdLineCert, &location, plContext));
+
+ if (location == NULL) {
+ pkixTestErrorMsg = "Give me a cert with an HTTP URI!";
+ goto cleanup;
+ }
+
+ /* create HttpCertStore */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HttpCertStore_Create(NULL, location, &certStore, plContext));
+
+ /* get the GetCerts callback */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &getCerts, plContext));
+
+ /* create a CertSelector */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext));
+
+ /* Get the certs */
+ PKIX_TEST_EXPECT_NO_ERROR(getCerts(certStore, certSelector, &nbio, &certs, plContext));
+
+ while (nbio != NULL) {
+ /* poll for a completion */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_CertContinue(certStore, certSelector, &nbio, &certs, plContext));
+ }
+
+ if (certs) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext));
+
+ if (numCerts == 0) {
+ printf("HttpCertStore returned an empty Cert list\n");
+ goto cleanup;
+ }
+
+ 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);
+ }
+ } else {
+ printf("HttpCertStore returned a NULL Cert list\n");
+ }
+
+ /* create HttpCertStore */
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_HttpCertStore_CreateWithAsciiName(NULL, crlLocation, &crlStore, plContext));
+
+ /* get the GetCrls callback */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback(crlStore, &getCrls, plContext));
+
+ /* create a CrlSelector */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create(NULL, NULL, &crlSelector, plContext));
+
+ /* Get the crls */
+ PKIX_TEST_EXPECT_NO_ERROR(getCrls(crlStore, crlSelector, &nbio, &crls, plContext));
+
+ while (nbio != NULL) {
+ /* poll for a completion */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_CrlContinue(crlStore, crlSelector, &nbio, &crls, plContext));
+ }
+
+ if (crls) {
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(crls, &numCrls, plContext));
+
+ if (numCrls == 0) {
+ printf("HttpCertStore returned an empty CRL list\n");
+ goto cleanup;
+ }
+
+ for (i = 0; i < numCrls; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(crls,
+ i,
+ (PKIX_PL_Object **)&crl,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString(
+ (PKIX_PL_Object *)crl,
+ &crlString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(crlString,
+ PKIX_ESCASCII,
+ (void **)&asciiResult,
+ &length,
+ plContext));
+
+ printf("CRL[%d]:\n%s\n", i, asciiResult);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, plContext));
+ PKIX_TEST_DECREF_BC(crlString);
+ PKIX_TEST_DECREF_BC(crl);
+ }
+ } else {
+ printf("HttpCertStore returned a NULL CRL list\n");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(cmdLineCert);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(crlStore);
+ PKIX_TEST_DECREF_AC(location);
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(crl);
+ PKIX_TEST_DECREF_AC(crlString);
+ PKIX_TEST_DECREF_AC(crls);
+
+ PKIX_TEST_RETURN();
+
+ endTests("HttpDefaultClient");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/test_pk11certstore.c b/security/nss/cmd/libpkix/pkix_pl/module/test_pk11certstore.c
new file mode 100644
index 0000000000..58fceb14f0
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/test_pk11certstore.c
@@ -0,0 +1,580 @@
+/* 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_pk11certstore.c
+ *
+ * Test Pk11CertStore Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+/*
+ * This function creates a certSelector with ComCertSelParams set up to
+ * select entries whose Subject Name matches that in the given Cert and
+ * whose validity window includes the Date specified by "validityDate".
+ */
+static void
+test_makeSubjectCertSelector(
+ PKIX_PL_Cert *certNameToMatch,
+ PKIX_PL_Date *validityDate,
+ PKIX_CertSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *subjParams = NULL;
+ PKIX_PL_X500Name *subjectName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ 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_ComCertSelParams_SetCertificateValid(subjParams, validityDate, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, subjParams, plContext));
+ *pSelector = selector;
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(subjParams);
+ PKIX_TEST_DECREF_AC(subjectName);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function creates a certSelector with ComCertSelParams set up to
+ * select entries containing a Basic Constraints extension with a path
+ * length of at least the specified "minPathLength".
+ */
+static void
+test_makePathCertSelector(
+ PKIX_Int32 minPathLength,
+ PKIX_CertSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CertSelector *selector = NULL;
+ PKIX_ComCertSelParams *pathParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&pathParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetBasicConstraints(pathParams, minPathLength, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, pathParams, plContext));
+ *pSelector = selector;
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(pathParams);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function reads a directory-file cert specified by "desiredSubjectCert",
+ * and decodes the SubjectName. It uses that name to set up the CertSelector
+ * for a Subject Name match, and then queries the database for matching entries.
+ * It is intended to test a "smart" database query.
+ */
+static void
+testMatchCertSubject(
+ char *crlDir,
+ char *desiredSubjectCert,
+ char *expectedAscii,
+ PKIX_PL_Date *validityDate,
+ void *plContext)
+{
+ PKIX_UInt32 numCert = 0;
+ PKIX_PL_Cert *certWithDesiredSubject = NULL;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_CertStore_CertCallback getCert = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certWithDesiredSubject = createCert(crlDir, desiredSubjectCert, plContext);
+
+ test_makeSubjectCertSelector(certWithDesiredSubject,
+ validityDate,
+ &certSelector,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create(&certStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &getCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(getCert(certStore,
+ certSelector,
+ &nbioContext,
+ &certList,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext));
+
+ if (numCert > 0) {
+ /* List should be immutable */
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(certList, 0, plContext));
+ }
+
+ if (expectedAscii) {
+ testToStringHelper((PKIX_PL_Object *)certList, expectedAscii, plContext);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(certWithDesiredSubject);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certList);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function uses the minimum path length specified by "minPath" to set up
+ * a CertSelector for a BasicConstraints match, and then queries the database
+ * for matching entries. It is intended to test the case where there
+ * is no "smart" database query, so the database will be asked for all
+ * available certs and the filtering will be done by the interaction of the
+ * certstore and the selector.
+ */
+static void
+testMatchCertMinPath(
+ PKIX_Int32 minPath,
+ char *expectedAscii,
+ void *plContext)
+{
+ PKIX_CertStore *certStore = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_List *certList = NULL;
+ PKIX_CertStore_CertCallback getCert = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Searching Certs for minPath");
+
+ test_makePathCertSelector(minPath, &certSelector, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create(&certStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &getCert, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(getCert(certStore,
+ certSelector,
+ &nbioContext,
+ &certList,
+ plContext));
+
+ if (expectedAscii) {
+ testToStringHelper((PKIX_PL_Object *)certList, expectedAscii, plContext);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(certSelector);
+ PKIX_TEST_DECREF_AC(certList);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function creates a crlSelector with ComCrlSelParams set up to
+ * select entries whose Issuer Name matches that in the given Crl.
+ */
+static void
+test_makeIssuerCRLSelector(
+ PKIX_PL_CRL *crlNameToMatch,
+ PKIX_CRLSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CRLSelector *selector = NULL;
+ PKIX_ComCRLSelParams *issuerParams = NULL;
+ PKIX_PL_X500Name *issuerName = NULL;
+ PKIX_List *names = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create(&issuerParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetIssuer(crlNameToMatch, &issuerName, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&names, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(names, (PKIX_PL_Object *)issuerName, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetIssuerNames(issuerParams, names, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_SetCommonCRLSelectorParams(selector, issuerParams, plContext));
+ *pSelector = selector;
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(issuerParams);
+ PKIX_TEST_DECREF_AC(issuerName);
+ PKIX_TEST_DECREF_AC(names);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function creates a crlSelector with ComCrlSelParams set up to
+ * select entries that would be valid at the Date specified by the Date
+ * criterion.
+ */
+static void
+test_makeDateCRLSelector(
+ PKIX_PL_Date *dateToMatch,
+ PKIX_CRLSelector **pSelector,
+ void *plContext)
+{
+ PKIX_CRLSelector *selector = NULL;
+ PKIX_ComCRLSelParams *dateParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_Create(NULL, NULL, &selector, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_Create(&dateParams, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCRLSelParams_SetDateAndTime(dateParams, dateToMatch, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CRLSelector_SetCommonCRLSelectorParams(selector, dateParams, plContext));
+ *pSelector = selector;
+
+cleanup:
+ PKIX_TEST_DECREF_AC(dateParams);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function reads a directory-file crl specified by "desiredIssuerCrl",
+ * and decodes the IssuerName. It uses that name to set up the CrlSelector
+ * for a Issuer Name match, and then queries the database for matching entries.
+ * It is intended to test the case of a "smart" database query.
+ */
+static void
+testMatchCrlIssuer(
+ char *crlDir,
+ char *desiredIssuerCrl,
+ char *expectedAscii,
+ void *plContext)
+{
+ PKIX_UInt32 numCrl = 0;
+ PKIX_PL_CRL *crlWithDesiredIssuer = NULL;
+ PKIX_CertStore *crlStore = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_CertStore_CRLCallback getCrl = NULL;
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Searching CRLs for matching Issuer");
+
+ crlWithDesiredIssuer = createCRL(crlDir, desiredIssuerCrl, plContext);
+
+ test_makeIssuerCRLSelector(crlWithDesiredIssuer, &crlSelector, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create(&crlStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback(crlStore, &getCrl, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(getCrl(crlStore,
+ crlSelector,
+ &nbioContext,
+ &crlList,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(crlList, &numCrl, plContext));
+
+ if (numCrl > 0) {
+ /* List should be immutable */
+ PKIX_TEST_EXPECT_ERROR(PKIX_List_DeleteItem(crlList, 0, plContext));
+ }
+
+ if (expectedAscii) {
+ testToStringHelper((PKIX_PL_Object *)crlList, expectedAscii, plContext);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(crlWithDesiredIssuer);
+ PKIX_TEST_DECREF_AC(crlStore);
+ PKIX_TEST_DECREF_AC(crlSelector);
+ PKIX_TEST_DECREF_AC(crlList);
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * This function uses the date specified by "matchDate" to set up the
+ * CrlSelector for a Date match. It is intended to test the case where there
+ * is no "smart" database query, so the CertStore should throw an error
+ * rather than ask the database for all available CRLs and then filter the
+ * results using the selector.
+ */
+static void
+testMatchCrlDate(
+ char *dateMatch,
+ char *expectedAscii,
+ void *plContext)
+{
+ PKIX_PL_Date *dateCriterion = NULL;
+ PKIX_CertStore *crlStore = NULL;
+ PKIX_CRLSelector *crlSelector = NULL;
+ PKIX_List *crlList = NULL;
+ PKIX_CertStore_CRLCallback getCrl = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("Searching CRLs for matching Date");
+
+ dateCriterion = createDate(dateMatch, plContext);
+ test_makeDateCRLSelector(dateCriterion, &crlSelector, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create(&crlStore, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCRLCallback(crlStore, &getCrl, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(getCrl(crlStore, crlSelector, NULL, &crlList, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(dateCriterion);
+ PKIX_TEST_DECREF_AC(crlStore);
+ PKIX_TEST_DECREF_AC(crlSelector);
+ PKIX_TEST_DECREF_AC(crlList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(char *pName)
+{
+ printf("\nUSAGE: %s <-d data-dir> <database-dir>\n\n", pName);
+}
+
+/* Functional tests for Pk11CertStore public functions */
+
+int
+test_pk11certstore(int argc, char *argv[])
+{
+
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_PL_Date *validityDate = NULL;
+ PKIX_PL_Date *betweenDate = NULL;
+ char *crlDir = NULL;
+ char *expectedProfAscii = "([\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 00ca\n"
+ "\tIssuer: CN=chemistry,O=mit,C=us\n"
+ "\tSubject: CN=prof noall,O=mit,C=us\n"
+ "\tValidity: [From: Fri Feb 11 14:14:06 2005\n"
+ "\t To: Mon Jan 18, 2105]\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(6)\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: 03\n"
+ "\tIssuer: CN=physics,O=mit,C=us\n"
+ "\tSubject: CN=prof noall,O=mit,C=us\n"
+ "\tValidity: [From: Fri Feb 11 12:52:26 2005\n"
+ "\t To: Mon Jan 18, 2105]\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"
+ ")";
+ char *expectedValidityAscii = "([\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 03\n"
+ "\tIssuer: CN=physics,O=mit,C=us\n"
+ "\tSubject: CN=prof noall,O=mit,C=us\n"
+ "\tValidity: [From: Fri Feb 11 12:52:26 2005\n"
+ "\t To: Mon Jan 18, 2105]\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"
+ ")";
+ char *expectedMinPathAscii = "([\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 01\n"
+ "\tIssuer: CN=science,O=mit,C=us\n"
+ "\tSubject: CN=science,O=mit,C=us\n"
+ "\tValidity: [From: Fri Feb 11 12:47:58 2005\n"
+ "\t To: Mon Jan 18, 2105]\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(10)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "]\n"
+ ")";
+ char *expectedIssuerAscii = "([\n"
+ "\tVersion: v2\n"
+ "\tIssuer: CN=physics,O=mit,C=us\n"
+ "\tUpdate: [Last: Fri Feb 11 13:51:38 2005\n"
+ "\t Next: Mon Jan 18, 2105]\n"
+ "\tSignatureAlgId: 1.2.840.10040.4.3\n"
+ "\tCRL Number : (null)\n"
+ "\n"
+ "\tEntry List: (\n"
+ "\t[\n"
+ "\tSerialNumber: 67\n"
+ "\tReasonCode: 257\n"
+ "\tRevocationDate: Fri Feb 11 13:51:38 2005\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n"
+ "\t)\n"
+ "\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "]\n"
+ ")";
+ char *expectedDateAscii = "([\n"
+ "\tVersion: v2\n"
+ "\tIssuer: CN=science,O=mit,C=us\n"
+ "\tUpdate: [Last: Fri Feb 11 13:34:40 2005\n"
+ "\t Next: Mon Jan 18, 2105]\n"
+ "\tSignatureAlgId: 1.2.840.10040.4.3\n"
+ "\tCRL Number : (null)\n"
+ "\n"
+ "\tEntry List: (\n"
+ "\t[\n"
+ "\tSerialNumber: 65\n"
+ "\tReasonCode: 260\n"
+ "\tRevocationDate: Fri Feb 11 13:34:40 2005\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n"
+ "\t)\n"
+ "\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "]\n"
+ ", [\n"
+ "\tVersion: v2\n"
+ "\tIssuer: CN=testing CRL,O=test,C=us\n"
+ "\tUpdate: [Last: Fri Feb 11 13:14:38 2005\n"
+ "\t Next: Mon Jan 18, 2105]\n"
+ "\tSignatureAlgId: 1.2.840.10040.4.3\n"
+ "\tCRL Number : (null)\n"
+ "\n"
+ "\tEntry List: (\n"
+ "\t[\n"
+ "\tSerialNumber: 67\n"
+ "\tReasonCode: 258\n"
+ "\tRevocationDate: Fri Feb 11 13:14:38 2005\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n"
+ "\t)\n"
+ "\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "]\n"
+ ")";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Pk11CertStore");
+
+ if (argc < 3) {
+ printUsage(argv[0]);
+ return (0);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ crlDir = argv[j + 2];
+
+ /* Two certs for prof should be valid now */
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Date_CreateFromPRTime(PR_Now(), &validityDate, plContext));
+
+ subTest("Searching Certs for Subject");
+
+ testMatchCertSubject(crlDir,
+ "phy2prof.crt",
+ NULL, /* expectedProfAscii, */
+ validityDate,
+ plContext);
+
+ /* One of the certs was not yet valid at this time. */
+ betweenDate = createDate("050210184000Z", plContext);
+
+ subTest("Searching Certs for Subject and Validity");
+
+ testMatchCertSubject(crlDir,
+ "phy2prof.crt",
+ NULL, /* expectedValidityAscii, */
+ betweenDate,
+ plContext);
+
+ testMatchCertMinPath(9,
+ NULL, /* expectedMinPathAscii, */
+ plContext);
+
+ testMatchCrlIssuer(crlDir,
+ "phys.crl",
+ NULL, /* expectedIssuerAscii, */
+ plContext);
+
+ testMatchCrlDate("050211184000Z",
+ NULL, /* expectedDateAscii, */
+ plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(validityDate);
+ PKIX_TEST_DECREF_AC(betweenDate);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Pk11CertStore");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/module/test_socket.c b/security/nss/cmd/libpkix/pkix_pl/module/test_socket.c
new file mode 100644
index 0000000000..89400256d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/module/test_socket.c
@@ -0,0 +1,571 @@
+/*
+ * test_socket.c
+ *
+ * Test Socket Type
+ *
+ * Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistribution of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any kind. ALL
+ * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
+ * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
+ * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
+ * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
+ * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
+ * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
+ * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
+ * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
+ * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
+ * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed or intended for use in
+ * the design, construction, operation or maintenance of any nuclear facility.
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+#include "pkix_pl_common.h"
+
+#define LDAP_PORT 389
+
+static void *plContext = NULL;
+
+typedef enum {
+ SERVER_LISTENING,
+ SERVER_RECV1,
+ SERVER_POLL1,
+ SERVER_SEND2,
+ SERVER_POLL2,
+ SERVER_RECV3,
+ SERVER_POLL3,
+ SERVER_SEND4,
+ SERVER_POLL4,
+ SERVER_DONE,
+ SERVER_FAILED
+} SERVER_STATE;
+
+typedef enum {
+ CLIENT_WAITFORCONNECT,
+ CLIENT_SEND1,
+ CLIENT_POLL1,
+ CLIENT_RECV2,
+ CLIENT_POLL2,
+ CLIENT_SEND3,
+ CLIENT_POLL3,
+ CLIENT_RECV4,
+ CLIENT_POLL4,
+ CLIENT_DONE,
+ CLIENT_FAILED
+} CLIENT_STATE;
+
+SERVER_STATE serverState;
+CLIENT_STATE clientState;
+PKIX_PL_Socket *sSock = NULL;
+PKIX_PL_Socket *cSock = NULL;
+PKIX_PL_Socket *rendezvousSock = NULL;
+PKIX_PL_Socket_Callback *sCallbackList;
+PKIX_PL_Socket_Callback *cCallbackList;
+PKIX_PL_Socket_Callback *rvCallbackList;
+PRNetAddr serverNetAddr;
+PRNetAddr clientNetAddr;
+PRIntn backlog = 0;
+PRIntervalTime timeout = 0;
+char *sendBuf1 = "Hello, world!";
+char *sendBuf2 = "Ack";
+char *sendBuf3 = "What do you mean, \"Ack\"?";
+char *sendBuf4 = "What do you mean, \"What do you mean, \'Ack\'?\"?";
+char rcvBuf1[100];
+char rcvBuf2[100];
+
+static void
+printUsage(char *testname)
+{
+ char *fmt = "USAGE: %s [-arenas] server:port\n";
+ printf(fmt, testname);
+}
+
+/* Functional tests for Socket public functions */
+static void
+do_other_work(void)
+{ /* while waiting for nonblocking I/O to complete */
+ (void)PR_Sleep(2 * 60);
+}
+
+static PKIX_Boolean
+server()
+{
+ PKIX_Int32 bytesRead = 0;
+ PKIX_Int32 bytesWritten = 0;
+ PKIX_Boolean keepGoing = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ switch (serverState) {
+ case SERVER_LISTENING:
+ subTest("SERVER_LISTENING");
+ PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->acceptCallback(sSock, &rendezvousSock, plContext));
+ if (rendezvousSock) {
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(rendezvousSock, &rvCallbackList, plContext));
+
+ serverState = SERVER_RECV1;
+ }
+ break;
+ case SERVER_RECV1:
+ subTest("SERVER_RECV1");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->recvCallback(rendezvousSock,
+ rcvBuf1,
+ sizeof(rcvBuf1),
+ &bytesRead,
+ plContext));
+
+ if (bytesRead > 0) {
+ /* confirm that rcvBuf1 = sendBuf1 */
+ if ((bytesRead != (PRInt32)PL_strlen(sendBuf1) + 1) ||
+ (strncmp(sendBuf1, rcvBuf1, bytesRead) != 0)) {
+ testError("Receive buffer mismatch\n");
+ }
+
+ serverState = SERVER_SEND2;
+ keepGoing = PKIX_TRUE;
+ } else {
+ serverState = SERVER_POLL1;
+ }
+ break;
+ case SERVER_POLL1:
+ subTest("SERVER_POLL1");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, NULL, &bytesRead, plContext));
+
+ if (bytesRead > 0) {
+ /* confirm that rcvBuf1 = sendBuf1 */
+ if ((bytesRead != (PRInt32)PL_strlen(sendBuf1) + 1) ||
+ (strncmp(sendBuf1, rcvBuf1, bytesRead) != 0)) {
+ testError("Receive buffer mismatch\n");
+ }
+
+ serverState = SERVER_SEND2;
+ keepGoing = PKIX_TRUE;
+ }
+ break;
+ case SERVER_SEND2:
+ subTest("SERVER_SEND2");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->sendCallback(rendezvousSock,
+ sendBuf2,
+ strlen(sendBuf2) +
+ 1,
+ &bytesWritten,
+ plContext));
+ if (bytesWritten > 0) {
+ serverState = SERVER_RECV3;
+ } else {
+ serverState = SERVER_POLL2;
+ }
+ break;
+ case SERVER_POLL2:
+ subTest("SERVER_POLL2");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, &bytesWritten, NULL, plContext));
+ if (bytesWritten > 0) {
+ serverState = SERVER_RECV3;
+ }
+ break;
+ case SERVER_RECV3:
+ subTest("SERVER_RECV3");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->recvCallback(rendezvousSock,
+ rcvBuf1,
+ sizeof(rcvBuf1),
+ &bytesRead,
+ plContext));
+
+ if (bytesRead > 0) {
+ serverState = SERVER_SEND4;
+ keepGoing = PKIX_TRUE;
+ } else {
+ serverState = SERVER_POLL3;
+ }
+ break;
+ case SERVER_POLL3:
+ subTest("SERVER_POLL3");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, NULL, &bytesRead, plContext));
+ if (bytesRead > 0) {
+ serverState = SERVER_SEND4;
+ keepGoing = PKIX_TRUE;
+ }
+ break;
+ case SERVER_SEND4:
+ subTest("SERVER_SEND4");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->sendCallback(rendezvousSock,
+ sendBuf4,
+ strlen(sendBuf4) +
+ 1,
+ &bytesWritten,
+ plContext));
+
+ if (bytesWritten > 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->shutdownCallback(rendezvousSock, plContext));
+ PKIX_TEST_DECREF_BC(sSock);
+ PKIX_TEST_DECREF_BC(rendezvousSock);
+ serverState = SERVER_DONE;
+ } else {
+ serverState = SERVER_POLL4;
+ }
+ break;
+ case SERVER_POLL4:
+ subTest("SERVER_POLL4");
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->pollCallback(rendezvousSock, &bytesWritten, NULL, plContext));
+ if (bytesWritten > 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(rvCallbackList->shutdownCallback(rendezvousSock, plContext));
+ PKIX_TEST_DECREF_BC(sSock);
+ PKIX_TEST_DECREF_BC(rendezvousSock);
+ serverState = SERVER_DONE;
+ }
+ break;
+ case SERVER_DONE:
+ default:
+ subTest("SERVER_DONE");
+ break;
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (keepGoing);
+}
+
+static PKIX_Boolean
+client()
+{
+ PKIX_Boolean keepGoing = PKIX_FALSE;
+ PKIX_Int32 bytesRead = 0;
+ PKIX_Int32 bytesWritten = 0;
+ PRErrorCode cStat = 0;
+
+ /* At 2 seconds each cycle, this should suffice! */
+ PKIX_UInt32 giveUpCount = 10;
+
+ PKIX_TEST_STD_VARS();
+
+ switch (clientState) {
+ case CLIENT_WAITFORCONNECT:
+ subTest("CLIENT_WAITFORCONNECT");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->connectcontinueCallback(cSock, &cStat, plContext));
+ if (cStat == 0) {
+ clientState = CLIENT_SEND1;
+ keepGoing = PKIX_TRUE;
+ } else {
+ clientState = CLIENT_WAITFORCONNECT;
+ if (--giveUpCount == 0) {
+ testError("Client unable to connect");
+ }
+ }
+ break;
+ case CLIENT_SEND1:
+ subTest("CLIENT_SEND1");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->sendCallback(cSock,
+ sendBuf1,
+ strlen(sendBuf1) +
+ 1,
+ &bytesWritten,
+ plContext));
+ if (bytesWritten > 0) {
+ clientState = CLIENT_RECV2;
+ } else {
+ clientState = CLIENT_POLL1;
+ }
+ break;
+ case CLIENT_POLL1:
+ subTest("CLIENT_POLL1");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, &bytesWritten, NULL, plContext));
+ if (bytesWritten > 0) {
+ clientState = CLIENT_RECV2;
+ } else {
+ clientState = CLIENT_POLL1;
+ }
+ break;
+ case CLIENT_RECV2:
+ subTest("CLIENT_RECV2");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->recvCallback(cSock,
+ rcvBuf2,
+ sizeof(rcvBuf2),
+ &bytesRead,
+ plContext));
+
+ if (bytesRead > 0) {
+ /* confirm that rcvBuf2 = sendBuf2 */
+ if ((bytesRead != (PRInt32)PL_strlen(sendBuf2) + 1) ||
+ (strncmp(sendBuf2, rcvBuf2, bytesRead) != 0)) {
+ testError("Receive buffer mismatch\n");
+ }
+ clientState = CLIENT_SEND3;
+ keepGoing = PKIX_TRUE;
+ } else {
+ clientState = CLIENT_POLL2;
+ }
+ break;
+ case CLIENT_POLL2:
+ subTest("CLIENT_POLL2");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, NULL, &bytesRead, plContext));
+ if (bytesRead > 0) {
+ /* confirm that rcvBuf2 = sendBuf2 */
+ if ((bytesRead != (PRInt32)PL_strlen(sendBuf2) + 1) ||
+ (strncmp(sendBuf2, rcvBuf2, bytesRead) != 0)) {
+ testError("Receive buffer mismatch\n");
+ }
+ clientState = CLIENT_SEND3;
+ } else {
+ clientState = CLIENT_POLL2;
+ }
+ break;
+ case CLIENT_SEND3:
+ subTest("CLIENT_SEND3");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->sendCallback(cSock,
+ sendBuf3,
+ strlen(sendBuf3) +
+ 1,
+ &bytesWritten,
+ plContext));
+
+ if (bytesWritten > 0) {
+ clientState = CLIENT_RECV4;
+ } else {
+ clientState = CLIENT_POLL3;
+ }
+ break;
+ case CLIENT_POLL3:
+ subTest("CLIENT_POLL3");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, &bytesWritten, NULL, plContext));
+ if (bytesWritten > 0) {
+ clientState = CLIENT_RECV4;
+ } else {
+ clientState = CLIENT_POLL3;
+ }
+ break;
+ case CLIENT_RECV4:
+ subTest("CLIENT_RECV4");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->recvCallback(cSock,
+ rcvBuf2,
+ sizeof(rcvBuf2),
+ &bytesRead,
+ plContext));
+
+ if (bytesRead > 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->shutdownCallback(cSock, plContext));
+ PKIX_TEST_DECREF_BC(cSock);
+ clientState = CLIENT_DONE;
+ } else {
+ clientState = CLIENT_POLL4;
+ }
+ break;
+ case CLIENT_POLL4:
+ subTest("CLIENT_POLL4");
+ clientState = CLIENT_FAILED;
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->pollCallback(cSock, NULL, &bytesRead, plContext));
+ if (bytesRead > 0) {
+ PKIX_TEST_EXPECT_NO_ERROR(cCallbackList->shutdownCallback(cSock, plContext));
+ PKIX_TEST_DECREF_BC(cSock);
+ clientState = CLIENT_DONE;
+ } else {
+ clientState = CLIENT_POLL4;
+ }
+ break;
+ case CLIENT_DONE:
+ default:
+ subTest("CLIENT_DONE");
+ break;
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (keepGoing);
+}
+
+static void
+dispatcher()
+{
+ PKIX_Boolean keepGoing = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ do {
+ if (serverState < SERVER_DONE) {
+ do {
+ keepGoing = server();
+ } while (keepGoing == PKIX_TRUE);
+ }
+ if (clientState < CLIENT_DONE) {
+ do {
+ keepGoing = client();
+ } while (keepGoing == PKIX_TRUE);
+ }
+ do_other_work();
+
+ } while ((serverState < SERVER_DONE) || (clientState < CLIENT_DONE));
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_socket(int argc, char *argv[])
+{
+
+ int j = 0;
+ PKIX_UInt32 actualMinorVersion;
+ char buf[PR_NETDB_BUF_SIZE];
+ char *serverName = NULL;
+ char *sepPtr = NULL;
+ PRHostEnt hostent;
+ PRUint16 portNum = 0;
+ PRStatus prstatus = PR_FAILURE;
+ PRErrorCode cStat = 0;
+ void *ipaddr = NULL;
+ PKIX_Error *bindError = NULL;
+ PRIntn hostenum;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Socket");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc != (j + 2)) {
+ printUsage(argv[0]);
+ pkixTestErrorMsg = "Missing command line argument.";
+ goto cleanup;
+ }
+
+ serverName = argv[j + 1];
+
+ subTest("Using pkix_pl_Socket_CreateByName");
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_CreateByName(PKIX_TRUE, timeout, serverName, &cStat, &sSock, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(sSock, &sCallbackList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->listenCallback(sSock, backlog, plContext));
+
+ serverState = SERVER_LISTENING;
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_CreateByName(PKIX_FALSE, timeout, serverName, &cStat, &cSock, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(cSock, &cCallbackList, plContext));
+
+ if ((timeout == 0) && (cStat == PR_IN_PROGRESS_ERROR)) {
+ clientState = CLIENT_WAITFORCONNECT;
+ } else {
+ clientState = CLIENT_SEND1;
+ }
+
+ dispatcher();
+
+ subTest("Using pkix_pl_Socket_Create");
+
+ sepPtr = strchr(serverName, ':');
+ /* First strip off the portnum, if present, from the end of the name */
+ if (sepPtr) {
+ *sepPtr++ = '\0';
+ portNum = (PRUint16)atoi(sepPtr);
+ } else {
+ portNum = (PRUint16)LDAP_PORT;
+ }
+ /*
+ * The hostname may be a fully-qualified name. Just
+ * use the leftmost component in our lookup.
+ */
+ sepPtr = strchr(serverName, '.');
+ if (sepPtr) {
+ *sepPtr++ = '\0';
+ }
+ prstatus = PR_GetHostByName(serverName, buf, sizeof(buf), &hostent);
+
+ if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) {
+ printUsage(argv[0]);
+ pkixTestErrorMsg =
+ "PR_GetHostByName rejects command line argument.";
+ goto cleanup;
+ }
+
+ serverNetAddr.inet.family = PR_AF_INET;
+ serverNetAddr.inet.port = PR_htons(portNum);
+ serverNetAddr.inet.ip = PR_INADDR_ANY;
+
+ hostenum = PR_EnumerateHostEnt(0, &hostent, portNum, &clientNetAddr);
+ if (hostenum == -1) {
+ pkixTestErrorMsg =
+ "PR_EnumerateHostEnt failed.";
+ goto cleanup;
+ }
+
+ backlog = 5;
+
+ /* timeout = PR_INTERVAL_NO_TIMEOUT; */
+ /* timeout = 0; nonblocking */
+ timeout = 0;
+
+ bindError = pkix_pl_Socket_Create(PKIX_TRUE, timeout, &serverNetAddr, &cStat, &sSock, plContext);
+
+ /* If PR_Bind can't handle INADDR_ANY, try it with the real name */
+ if (bindError) {
+ PKIX_TEST_DECREF_BC(bindError);
+ serverNetAddr.inet.ip = PR_htonl(*(PRUint32 *)ipaddr);
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_Create(PKIX_TRUE,
+ timeout,
+ &serverNetAddr,
+ &cStat,
+ &sSock,
+ plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(sSock, &sCallbackList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(sCallbackList->listenCallback(sSock, backlog, plContext));
+
+ serverState = SERVER_LISTENING;
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_Create(PKIX_FALSE, timeout, &clientNetAddr, &cStat, &cSock, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Socket_GetCallbackList(cSock, &cCallbackList, plContext));
+
+ if ((timeout == 0) && (cStat == PR_IN_PROGRESS_ERROR)) {
+ clientState = CLIENT_WAITFORCONNECT;
+ } else {
+ clientState = CLIENT_SEND1;
+ }
+
+ dispatcher();
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(sSock);
+ PKIX_TEST_DECREF_AC(cSock);
+ PKIX_TEST_DECREF_AC(rendezvousSock);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Socket");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/Makefile b/security/nss/cmd/libpkix/pkix_pl/pki/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/Makefile
@@ -0,0 +1,45 @@
+#! 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/security/nss/cmd/libpkix/pkix_pl/pki/manifest.mn b/security/nss/cmd/libpkix/pkix_pl/pki/manifest.mn
new file mode 100644
index 0000000000..15fae7bb5f
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/manifest.mn
@@ -0,0 +1,29 @@
+#
+# 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_cert.c \
+ test_crl.c \
+ test_crlentry.c \
+ test_date.c \
+ test_generalname.c \
+ test_nameconstraints.c \
+ test_x500name.c \
+ test_authorityinfoaccess.c \
+ test_subjectinfoaccess.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtoolpki
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_authorityinfoaccess.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_authorityinfoaccess.c
new file mode 100644
index 0000000000..156b440f9c
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_authorityinfoaccess.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/. */
+/*
+ * test_authorityinfoaccess.c
+ *
+ * Test Authority InfoAccess Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+int
+test_authorityinfoaccess(int argc, char *argv[])
+{
+
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_Cert *certDiff = NULL;
+ PKIX_List *aiaList = NULL;
+ PKIX_List *siaList = NULL;
+ PKIX_PL_InfoAccess *aia = NULL;
+ PKIX_PL_InfoAccess *aiaDup = NULL;
+ PKIX_PL_InfoAccess *aiaDiff = NULL;
+ char *certPathName = NULL;
+ char *dirName = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 size, i;
+ PKIX_UInt32 j = 0;
+ char *expectedAscii = "[method:caIssuers, location:ldap:"
+ "//betty.nist.gov/cn=CA,ou=Basic%20LDAP%20URI%20OU1,"
+ "o=Test%20Certificates,c=US?cACertificate;binary,"
+ "crossCertificatePair;binary]";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("AuthorityInfoAccess");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 5 + j) {
+ printf("Usage: %s <test-purpose> <cert> <diff-cert>\n", argv[0]);
+ }
+
+ dirName = argv[2 + j];
+ certPathName = argv[3 + j];
+
+ subTest("Creating Cert with Authority Info Access");
+ cert = createCert(dirName, certPathName, plContext);
+
+ certPathName = argv[4 + j];
+
+ subTest("Creating Cert with Subject Info Access");
+ certDiff = createCert(dirName, certPathName, plContext);
+
+ subTest("Getting Authority Info Access");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityInfoAccess(cert, &aiaList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(aiaList, &size, plContext));
+
+ if (size != 1) {
+ pkixTestErrorMsg = "unexpected number of AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(aiaList, 0, (PKIX_PL_Object **)&aia, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(aiaList, 0, (PKIX_PL_Object **)&aiaDup, plContext));
+
+ subTest("Getting Subject Info Access as difference comparison");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectInfoAccess(certDiff, &siaList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(siaList, &size, plContext));
+
+ if (size != 1) {
+ pkixTestErrorMsg = "unexpected number of AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(siaList, 0, (PKIX_PL_Object **)&aiaDiff, plContext));
+
+ subTest("Checking: Equal, Hash and ToString");
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(aia, aiaDup, aiaDiff, expectedAscii, InfoAccess, PKIX_FALSE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(aia);
+ PKIX_TEST_DECREF_AC(aiaDup);
+ PKIX_TEST_DECREF_AC(aiaDiff);
+ PKIX_TEST_DECREF_AC(aiaList);
+ PKIX_TEST_DECREF_AC(siaList);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(certDiff);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Authorityinfoaccess");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_cert.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_cert.c
new file mode 100644
index 0000000000..274f818ab3
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_cert.c
@@ -0,0 +1,2088 @@
+/* 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_cert.c
+ *
+ * Test Cert Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static PKIX_PL_Cert *altNameNoneCert = NULL;
+static PKIX_PL_Cert *altNameOtherCert = NULL;
+static PKIX_PL_Cert *altNameOtherCert_diff = NULL;
+static PKIX_PL_Cert *altNameRfc822Cert = NULL;
+static PKIX_PL_Cert *altNameRfc822Cert_diff = NULL;
+static PKIX_PL_Cert *altNameDnsCert = NULL;
+static PKIX_PL_Cert *altNameDnsCert_diff = NULL;
+static PKIX_PL_Cert *altNameX400Cert = NULL;
+static PKIX_PL_Cert *altNameX400Cert_diff = NULL;
+static PKIX_PL_Cert *altNameDnCert = NULL;
+static PKIX_PL_Cert *altNameDnCert_diff = NULL;
+static PKIX_PL_Cert *altNameEdiCert = NULL;
+static PKIX_PL_Cert *altNameEdiCert_diff = NULL;
+static PKIX_PL_Cert *altNameUriCert = NULL;
+static PKIX_PL_Cert *altNameUriCert_diff = NULL;
+static PKIX_PL_Cert *altNameIpCert = NULL;
+static PKIX_PL_Cert *altNameIpCert_diff = NULL;
+static PKIX_PL_Cert *altNameOidCert = NULL;
+static PKIX_PL_Cert *altNameOidCert_diff = NULL;
+static PKIX_PL_Cert *altNameMultipleCert = NULL;
+
+static void *plContext = NULL;
+
+static void
+createCerts(
+ char *dataCentralDir,
+ char *goodInput,
+ char *diffInput,
+ PKIX_PL_Cert **goodObject,
+ PKIX_PL_Cert **equalObject,
+ PKIX_PL_Cert **diffObject)
+{
+ subTest("PKIX_PL_Cert_Create <goodObject>");
+ *goodObject = createCert(dataCentralDir, goodInput, plContext);
+
+ subTest("PKIX_PL_Cert_Create <equalObject>");
+ *equalObject = createCert(dataCentralDir, goodInput, plContext);
+
+ subTest("PKIX_PL_Cert_Create <diffObject>");
+ *diffObject = createCert(dataCentralDir, diffInput, plContext);
+}
+
+static void
+createCertsWithSubjectAltNames(char *dataCentralDir)
+{
+ subTest("PKIX_PL_Cert_Create <altNameDNS>");
+ altNameDnsCert = createCert(dataCentralDir, "generalName/altNameDnsCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameDNS_diff>");
+ altNameDnsCert_diff = createCert(dataCentralDir, "generalName/altNameDnsCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameRFC822>");
+ altNameRfc822Cert = createCert(dataCentralDir, "generalName/altNameRfc822Cert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameRFC822_diff>");
+ altNameRfc822Cert_diff = createCert(dataCentralDir, "generalName/altNameRfc822Cert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameX400Cert>");
+ altNameX400Cert = createCert(dataCentralDir, "generalName/altNameX400Cert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameX400_diff>");
+ altNameX400Cert_diff = createCert(dataCentralDir, "generalName/altNameX400Cert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameDN>");
+ altNameDnCert = createCert(dataCentralDir, "generalName/altNameDnCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameDN_diff>");
+ altNameDnCert_diff = createCert(dataCentralDir, "generalName/altNameDnCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameEdiCert>");
+ altNameEdiCert = createCert(dataCentralDir, "generalName/altNameEdiCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameEdi_diff>");
+ altNameEdiCert_diff = createCert(dataCentralDir, "generalName/altNameEdiCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameURI>");
+ altNameUriCert = createCert(dataCentralDir, "generalName/altNameUriCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameURI_diff>");
+ altNameUriCert_diff = createCert(dataCentralDir, "generalName/altNameUriCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameIP>");
+ altNameIpCert = createCert(dataCentralDir, "generalName/altNameIpCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameIP_diff>");
+ altNameIpCert_diff = createCert(dataCentralDir, "generalName/altNameIpCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameOID>");
+ altNameOidCert = createCert(dataCentralDir, "generalName/altNameOidCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameOID_diff>");
+ altNameOidCert_diff = createCert(dataCentralDir, "generalName/altNameOidCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameOther>");
+ altNameOtherCert = createCert(dataCentralDir, "generalName/altNameOtherCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameOther_diff>");
+ altNameOtherCert_diff = createCert(dataCentralDir, "generalName/altNameOtherCert_diff", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameNone>");
+ altNameNoneCert = createCert(dataCentralDir, "generalName/altNameNoneCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <altNameMultiple>");
+ altNameMultipleCert = createCert(dataCentralDir, "generalName/altNameRfc822DnsCert", plContext);
+}
+
+static void
+testGetVersion(
+ PKIX_PL_Cert *goodObject)
+{
+ PKIX_UInt32 goodVersion;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetVersion");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetVersion(goodObject, &goodVersion, plContext));
+
+ if (goodVersion != 2) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", goodVersion);
+ (void)printf("Expected value:\t2\n");
+ goto cleanup;
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSerialNumber(
+ PKIX_PL_Cert *goodObject,
+ PKIX_PL_Cert *equalObject,
+ PKIX_PL_Cert *diffObject)
+{
+ PKIX_PL_BigInt *goodSN = NULL;
+ PKIX_PL_BigInt *equalSN = NULL;
+ PKIX_PL_BigInt *diffSN = NULL;
+ char *expectedAscii = "37bc66ec";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetSerialNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSerialNumber(goodObject, &goodSN, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSerialNumber(equalObject, &equalSN, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSerialNumber(diffObject, &diffSN, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodSN, equalSN, diffSN, expectedAscii, BigInt, PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodSN);
+ PKIX_TEST_DECREF_AC(equalSN);
+ PKIX_TEST_DECREF_AC(diffSN);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSubject(
+ PKIX_PL_Cert *goodObject,
+ PKIX_PL_Cert *equalObject,
+ PKIX_PL_Cert *diffObject)
+{
+ PKIX_PL_X500Name *goodSubject = NULL;
+ PKIX_PL_X500Name *equalSubject = NULL;
+ PKIX_PL_X500Name *diffSubject = NULL;
+ char *expectedAscii = "OU=bcn,OU=east,O=sun,C=us";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetSubject");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(goodObject, &goodSubject, plContext));
+
+ if (!goodSubject) {
+ testError("Certificate Subject should not be NULL");
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(equalObject, &equalSubject, plContext));
+
+ if (!equalSubject) {
+ testError("Certificate Subject should not be NULL");
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(diffObject, &diffSubject, plContext));
+
+ if (!diffSubject) {
+ testError("Certificate Subject should not be NULL");
+ goto cleanup;
+ }
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodSubject,
+ equalSubject,
+ diffSubject,
+ expectedAscii,
+ X500Name,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodSubject);
+ PKIX_TEST_DECREF_AC(equalSubject);
+ PKIX_TEST_DECREF_AC(diffSubject);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetIssuer(
+ PKIX_PL_Cert *goodObject,
+ PKIX_PL_Cert *equalObject,
+ PKIX_PL_Cert *diffObject)
+{
+ PKIX_PL_X500Name *goodIssuer = NULL;
+ PKIX_PL_X500Name *equalIssuer = NULL;
+ PKIX_PL_X500Name *diffIssuer = NULL;
+ char *expectedAscii = "CN=yassir,OU=bcn,OU=east,O=sun,C=us";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetIssuer");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetIssuer(goodObject, &goodIssuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetIssuer(equalObject, &equalIssuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetIssuer(diffObject, &diffIssuer, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodIssuer,
+ equalIssuer,
+ diffIssuer,
+ expectedAscii,
+ X500Name,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodIssuer);
+ PKIX_TEST_DECREF_AC(equalIssuer);
+ PKIX_TEST_DECREF_AC(diffIssuer);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAltNames(
+ PKIX_PL_Cert *goodCert,
+ PKIX_PL_Cert *diffCert,
+ char *expectedAscii)
+{
+ PKIX_List *goodAltNames = NULL;
+ PKIX_List *diffAltNames = NULL;
+ PKIX_PL_GeneralName *goodAltName = NULL;
+ PKIX_PL_GeneralName *diffAltName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectAltNames(goodCert, &goodAltNames, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodAltNames,
+ 0,
+ (PKIX_PL_Object **)&goodAltName,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectAltNames(diffCert, &diffAltNames, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffAltNames,
+ 0,
+ (PKIX_PL_Object **)&diffAltName,
+ plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodAltName, goodAltName, diffAltName,
+ expectedAscii, GeneralName, PKIX_TRUE);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(goodAltNames);
+ PKIX_TEST_DECREF_AC(goodAltName);
+ PKIX_TEST_DECREF_AC(diffAltNames);
+ PKIX_TEST_DECREF_AC(diffAltName);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAltNamesNone(PKIX_PL_Cert *cert)
+{
+
+ PKIX_List *altNames = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectAltNames(cert, &altNames, plContext));
+
+ if (altNames != NULL) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%p\n", (void *)altNames);
+ (void)printf("Expected value:\tNULL\n");
+ goto cleanup;
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(altNames);
+ PKIX_TEST_RETURN();
+}
+static void
+testAltNamesMultiple()
+{
+ PKIX_List *altNames = NULL;
+ PKIX_PL_GeneralName *firstAltName = NULL;
+ PKIX_Int32 firstExpectedType = PKIX_RFC822_NAME;
+ PKIX_PL_GeneralName *secondAltName = NULL;
+ PKIX_Int32 secondExpectedType = PKIX_DNS_NAME;
+
+ char *expectedAscii =
+ "[\n"
+ "\tVersion: v3\n"
+ "\tSerialNumber: 2d\n"
+ "\tIssuer: OU=labs,O=sun,C=us\n"
+ "\tSubject: CN=yassir,OU=labs,O=sun,C=us\n"
+ "\tValidity: [From: Mon Feb 09, 2004\n"
+ /* "\tValidity: [From: Mon Feb 09 14:43:52 2004\n" */
+ "\t To: Mon Feb 09, 2004]\n"
+ /* "\t To: Mon Feb 09 14:43:52 2004]\n" */
+ "\tSubjectAltNames: (yassir@sun.com, sunray.sun.com)\n"
+ "\tAuthorityKeyId: (null)\n"
+ "\tSubjectKeyId: (null)\n"
+ "\tSubjPubKeyAlgId: ANSI X9.57 DSA Signature\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\tExtKeyUsages: (null)\n"
+ "\tBasicConstraint: (null)\n"
+ "\tCertPolicyInfo: (null)\n"
+ "\tPolicyMappings: (null)\n"
+ "\tExplicitPolicy: -1\n"
+ "\tInhibitMapping: -1\n"
+ "\tInhibitAnyPolicy:-1\n"
+ "\tNameConstraints: (null)\n"
+ "\tAuthorityInfoAccess: (null)\n"
+ "\tSubjectInfoAccess: (null)\n"
+ "\tCacheFlag: 0\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ testToStringHelper((PKIX_PL_Object *)altNameMultipleCert,
+ expectedAscii,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectAltNames(altNameMultipleCert, &altNames, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(altNames, 0, (PKIX_PL_Object **)&firstAltName, plContext));
+
+ if (firstAltName->type != firstExpectedType) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", firstAltName->type);
+ (void)printf("Expected value:\t%d\n", firstExpectedType);
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(altNames, 1, (PKIX_PL_Object **)&secondAltName, plContext));
+
+ if (secondAltName->type != secondExpectedType) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", secondAltName->type);
+ (void)printf("Expected value:\t%d\n", secondExpectedType);
+ goto cleanup;
+ }
+
+cleanup:
+ PKIX_TEST_DECREF_AC(altNames);
+ PKIX_TEST_DECREF_AC(firstAltName);
+ PKIX_TEST_DECREF_AC(secondAltName);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSubjectAltNames(char *dataCentralDir)
+{
+
+ char *expectedAscii = NULL;
+
+ createCertsWithSubjectAltNames(dataCentralDir);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <DNS>");
+ expectedAscii = "east.sun.com";
+ testAltNames(altNameDnsCert, altNameDnsCert_diff, expectedAscii);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <RFC822>");
+ expectedAscii = "alice.barnes@bcn.east.sun.com";
+ testAltNames(altNameRfc822Cert, altNameRfc822Cert_diff, expectedAscii);
+
+ /*
+ *this should work once bugzilla bug #233586 is fixed.
+ *subTest("PKIX_PL_Cert_GetSubjectAltNames <X400Address>");
+ *expectedAscii = "X400Address: <DER-encoded value>";
+ *testAltNames(altNameX400Cert, altNameX400Cert_diff, expectedAscii);
+ */
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <DN>");
+ expectedAscii = "CN=elley,OU=labs,O=sun,C=us";
+ testAltNames(altNameDnCert, altNameDnCert_diff, expectedAscii);
+
+ /*
+ * this should work once bugzilla bug #233586 is fixed.
+ * subTest("PKIX_PL_Cert_GetSubjectAltNames <EdiPartyName>");
+ * expectedAscii = "EDIPartyName: <DER-encoded value>";
+ * testAltNames(altNameEdiCert, altNameEdiCert_diff, expectedAscii);
+ */
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <URI>");
+ expectedAscii = "http://www.sun.com";
+ testAltNames(altNameUriCert, altNameUriCert_diff, expectedAscii);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <IP>");
+ expectedAscii = "1.2.3.4";
+ testAltNames(altNameIpCert, altNameIpCert_diff, expectedAscii);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <OID>");
+ expectedAscii = "1.2.39";
+ testAltNames(altNameOidCert, altNameOidCert_diff, expectedAscii);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <Other>");
+ expectedAscii = "1.7.26.97";
+ testAltNames(altNameOtherCert, altNameOtherCert_diff, expectedAscii);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <none>");
+ testAltNamesNone(altNameNoneCert);
+
+ subTest("PKIX_PL_Cert_GetSubjectAltNames <Multiple>");
+ testAltNamesMultiple();
+}
+
+static void
+testGetSubjectPublicKey(
+ PKIX_PL_Cert *goodObject,
+ PKIX_PL_Cert *equalObject,
+ PKIX_PL_Cert *diffObject)
+{
+ PKIX_PL_PublicKey *goodPubKey = NULL;
+ PKIX_PL_PublicKey *equalPubKey = NULL;
+ PKIX_PL_PublicKey *diffPubKey = NULL;
+ char *expectedAscii = "ANSI X9.57 DSA Signature";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(goodObject, &goodPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(equalObject, &equalPubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(diffObject, &diffPubKey, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodPubKey, equalPubKey, diffPubKey,
+ expectedAscii, PublicKey, PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodPubKey);
+ PKIX_TEST_DECREF_AC(equalPubKey);
+ PKIX_TEST_DECREF_AC(diffPubKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetSubjectPublicKeyAlgId(PKIX_PL_Cert *goodObject)
+{
+ PKIX_PL_OID *pkixPubKeyOID = NULL;
+ char *expectedAscii = "1.2.840.10040.4.1";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKeyAlgId");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKeyAlgId(goodObject, &pkixPubKeyOID, plContext));
+
+ testToStringHelper((PKIX_PL_Object *)pkixPubKeyOID, expectedAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(pkixPubKeyOID);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCritExtensionsPresent(PKIX_PL_Cert *cert)
+{
+ PKIX_List *critOIDList = NULL;
+ char *firstOIDAscii = "2.5.29.15";
+ PKIX_PL_OID *firstOID = NULL;
+ char *secondOIDAscii = "2.5.29.19";
+ PKIX_PL_OID *secondOID = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetCriticalExtensionOIDs(cert, &critOIDList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(critOIDList, 0, (PKIX_PL_Object **)&firstOID, plContext));
+ testToStringHelper((PKIX_PL_Object *)firstOID, firstOIDAscii, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(critOIDList, 1, (PKIX_PL_Object **)&secondOID, plContext));
+
+ testToStringHelper((PKIX_PL_Object *)secondOID, secondOIDAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(critOIDList);
+ PKIX_TEST_DECREF_AC(firstOID);
+ PKIX_TEST_DECREF_AC(secondOID);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCritExtensionsAbsent(PKIX_PL_Cert *cert)
+{
+ PKIX_List *oidList = NULL;
+ PKIX_Boolean empty;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetCriticalExtensionOIDs(cert, &oidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsEmpty(oidList, &empty, plContext));
+
+ if (!empty) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(oidList);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAllExtensionsAbsent(char *dataCentralDir)
+{
+ PKIX_List *oidList = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_Boolean empty;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <noExtensionsCert>");
+ cert = createCert(dataCentralDir, "noExtensionsCert", plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetCriticalExtensionOIDs(cert, &oidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsEmpty(oidList, &empty, plContext));
+
+ if (!empty) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+cleanup:
+ PKIX_TEST_DECREF_AC(oidList);
+ PKIX_TEST_DECREF_AC(cert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCriticalExtensionOIDs(char *dataCentralDir, PKIX_PL_Cert *goodObject)
+{
+ subTest("PKIX_PL_Cert_GetCriticalExtensionOIDs "
+ "<CritExtensionsPresent>");
+ testCritExtensionsPresent(goodObject);
+
+ subTest("PKIX_PL_Cert_GetCriticalExtensionOIDs "
+ "<CritExtensionsAbsent>");
+ testCritExtensionsAbsent(altNameOidCert);
+
+ subTest("PKIX_PL_Cert_GetCriticalExtensionOIDs "
+ "<AllExtensionsAbsent>");
+ testAllExtensionsAbsent(dataCentralDir);
+}
+
+static void
+testKeyIdentifiersMatching(char *dataCentralDir)
+{
+ PKIX_PL_Cert *subjKeyIDCert = NULL;
+ PKIX_PL_Cert *authKeyIDCert = NULL;
+ PKIX_PL_ByteArray *subjKeyID = NULL;
+ PKIX_PL_ByteArray *authKeyID = NULL;
+ PKIX_PL_ByteArray *subjKeyID_diff = NULL;
+
+ char *expectedAscii =
+ "[116, 021, 213, 036, 028, 189, 094, 101, 136, 031, 225,"
+ " 139, 009, 126, 127, 234, 025, 072, 078, 097]";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <subjKeyIDCert>");
+ subjKeyIDCert = createCert(dataCentralDir, "keyIdentifier/subjKeyIDCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <authKeyIDCert>");
+ authKeyIDCert = createCert(dataCentralDir, "keyIdentifier/authKeyIDCert", plContext);
+
+ subTest("PKIX_PL_Cert_GetSubjectKeyIdentifier <good>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectKeyIdentifier(subjKeyIDCert, &subjKeyID, plContext));
+
+ subTest("PKIX_PL_Cert_GetAuthorityKeyIdentifier <equal>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityKeyIdentifier(authKeyIDCert, &authKeyID, plContext));
+
+ subTest("PKIX_PL_Cert_GetSubjectKeyIdentifier <diff>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectKeyIdentifier(authKeyIDCert, &subjKeyID_diff, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(subjKeyID,
+ authKeyID,
+ subjKeyID_diff,
+ expectedAscii,
+ ByteArray,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(subjKeyIDCert);
+ PKIX_TEST_DECREF_AC(authKeyIDCert);
+ PKIX_TEST_DECREF_AC(subjKeyID);
+ PKIX_TEST_DECREF_AC(authKeyID);
+ PKIX_TEST_DECREF_AC(subjKeyID_diff);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testKeyIdentifierAbsent(PKIX_PL_Cert *cert)
+{
+ PKIX_PL_ByteArray *subjKeyID = NULL;
+ PKIX_PL_ByteArray *authKeyID = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectKeyIdentifier(cert, &subjKeyID, plContext));
+
+ if (subjKeyID != NULL) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityKeyIdentifier(cert, &authKeyID, plContext));
+
+ if (authKeyID != NULL) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(subjKeyID);
+ PKIX_TEST_DECREF_AC(authKeyID);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetKeyIdentifiers(char *dataCentralDir, PKIX_PL_Cert *goodObject)
+{
+ testKeyIdentifiersMatching(dataCentralDir);
+ testKeyIdentifierAbsent(goodObject);
+}
+
+static void
+testVerifyKeyUsage(
+ char *dataCentralDir,
+ char *dataDir,
+ PKIX_PL_Cert *multiKeyUsagesCert)
+{
+ PKIX_PL_Cert *encipherOnlyCert = NULL;
+ PKIX_PL_Cert *decipherOnlyCert = NULL;
+ PKIX_PL_Cert *noKeyUsagesCert = NULL;
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <encipherOnlyCert>");
+ encipherOnlyCert = createCert(dataCentralDir, "keyUsage/encipherOnlyCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <decipherOnlyCert>");
+ decipherOnlyCert = createCert(dataCentralDir, "keyUsage/decipherOnlyCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <noKeyUsagesCert>");
+ noKeyUsagesCert = createCert(dataCentralDir, "keyUsage/noKeyUsagesCert", plContext);
+
+ subTest("PKIX_PL_Cert_VerifyKeyUsage <key_cert_sign>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_VerifyKeyUsage(multiKeyUsagesCert, PKIX_KEY_CERT_SIGN, plContext));
+
+ subTest("PKIX_PL_Cert_VerifyKeyUsage <multiKeyUsages>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_VerifyKeyUsage(multiKeyUsagesCert,
+ PKIX_KEY_CERT_SIGN |
+ PKIX_DIGITAL_SIGNATURE,
+ plContext));
+
+ subTest("PKIX_PL_Cert_VerifyKeyUsage <encipher_only>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_VerifyKeyUsage(encipherOnlyCert, PKIX_ENCIPHER_ONLY, plContext));
+
+ subTest("PKIX_PL_Cert_VerifyKeyUsage <noKeyUsages>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_VerifyKeyUsage(noKeyUsagesCert, PKIX_ENCIPHER_ONLY, plContext));
+
+ subTest("PKIX_PL_Cert_VerifyKeyUsage <decipher_only>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_VerifyKeyUsage(decipherOnlyCert, PKIX_DECIPHER_ONLY, plContext));
+
+cleanup:
+ PKIX_TEST_DECREF_AC(encipherOnlyCert);
+ PKIX_TEST_DECREF_AC(decipherOnlyCert);
+ PKIX_TEST_DECREF_AC(noKeyUsagesCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetExtendedKeyUsage(char *dataCentralDir)
+{
+
+ PKIX_PL_Cert *codeSigningEKUCert = NULL;
+ PKIX_PL_Cert *multiEKUCert = NULL;
+ PKIX_PL_Cert *noEKUCert = NULL;
+ PKIX_List *firstExtKeyUsage = NULL;
+ PKIX_List *secondExtKeyUsage = NULL;
+ PKIX_List *thirdExtKeyUsage = NULL;
+ PKIX_PL_OID *firstOID = NULL;
+ char *oidAscii = "1.3.6.1.5.5.7.3.3";
+ PKIX_PL_OID *secondOID = NULL;
+ char *secondOIDAscii = "1.3.6.1.5.5.7.3.1";
+ PKIX_PL_OID *thirdOID = NULL;
+ char *thirdOIDAscii = "1.3.6.1.5.5.7.3.2";
+ PKIX_PL_OID *fourthOID = NULL;
+ PKIX_UInt32 length = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <codeSigningEKUCert>");
+ codeSigningEKUCert = createCert(dataCentralDir, "extKeyUsage/codeSigningEKUCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <multiEKUCert>");
+ multiEKUCert = createCert(dataCentralDir, "extKeyUsage/multiEKUCert", plContext);
+
+ subTest("PKIX_PL_Cert_Create <noEKUCert>");
+ noEKUCert = createCert(dataCentralDir, "extKeyUsage/noEKUCert", plContext);
+
+ subTest("PKIX_PL_Cert_ExtendedKeyUsage <codeSigningEKU>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetExtendedKeyUsage(codeSigningEKUCert, &firstExtKeyUsage, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(firstExtKeyUsage, 0, (PKIX_PL_Object **)&firstOID, plContext));
+ testToStringHelper((PKIX_PL_Object *)firstOID, oidAscii, plContext);
+
+ subTest("PKIX_PL_Cert_ExtendedKeyUsage <multiEKU>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetExtendedKeyUsage(multiEKUCert, &secondExtKeyUsage, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(secondExtKeyUsage, &length, plContext));
+
+ if (length != 3) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", length);
+ (void)printf("Expected value:\t3\n");
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(secondExtKeyUsage,
+ 0,
+ (PKIX_PL_Object **)&secondOID,
+ plContext));
+
+ testToStringHelper((PKIX_PL_Object *)secondOID, oidAscii, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(secondExtKeyUsage,
+ 1,
+ (PKIX_PL_Object **)&thirdOID,
+ plContext));
+
+ testToStringHelper((PKIX_PL_Object *)thirdOID, secondOIDAscii, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(secondExtKeyUsage,
+ 2,
+ (PKIX_PL_Object **)&fourthOID,
+ plContext));
+
+ testToStringHelper((PKIX_PL_Object *)fourthOID, thirdOIDAscii, plContext);
+
+ subTest("PKIX_PL_Cert_ExtendedKeyUsage <noEKU>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetExtendedKeyUsage(noEKUCert, &thirdExtKeyUsage, plContext));
+
+ if (thirdExtKeyUsage != NULL) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%p\n", (void *)thirdExtKeyUsage);
+ (void)printf("Expected value:\tNULL\n");
+ goto cleanup;
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstOID);
+ PKIX_TEST_DECREF_AC(secondOID);
+ PKIX_TEST_DECREF_AC(thirdOID);
+ PKIX_TEST_DECREF_AC(fourthOID);
+
+ PKIX_TEST_DECREF_AC(firstExtKeyUsage);
+ PKIX_TEST_DECREF_AC(secondExtKeyUsage);
+ PKIX_TEST_DECREF_AC(thirdExtKeyUsage);
+
+ PKIX_TEST_DECREF_AC(codeSigningEKUCert);
+ PKIX_TEST_DECREF_AC(multiEKUCert);
+ PKIX_TEST_DECREF_AC(noEKUCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testMakeInheritedDSAPublicKey(char *dataCentralDir)
+{
+ PKIX_PL_PublicKey *firstKey = NULL;
+ PKIX_PL_PublicKey *secondKey = NULL;
+ PKIX_PL_PublicKey *resultKeyPositive = NULL;
+ PKIX_PL_PublicKey *resultKeyNegative = NULL;
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <dsaWithoutParams>");
+ firstCert = createCert(dataCentralDir, "publicKey/dsaWithoutParams", plContext);
+
+ subTest("PKIX_PL_Cert_Create <dsaWithParams>");
+ secondCert = createCert(dataCentralDir, "publicKey/dsaWithParams", plContext);
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <firstKey>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(firstCert, &firstKey, plContext));
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <secondKey>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(secondCert, &secondKey, plContext));
+
+ subTest("PKIX_PL_PublicKey_MakeInheritedDSAPublicKey <positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey(firstKey, secondKey, &resultKeyPositive, plContext));
+
+ if (resultKeyPositive == NULL) {
+ testError("PKIX_PL_PublicKey_MakeInheritedDSAPublicKey failed");
+ }
+
+ subTest("PKIX_PL_PublicKey_MakeInheritedDSAPublicKey <negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey(firstKey, firstKey, &resultKeyNegative, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstCert);
+ PKIX_TEST_DECREF_AC(secondCert);
+
+ PKIX_TEST_DECREF_AC(firstKey);
+ PKIX_TEST_DECREF_AC(secondKey);
+ PKIX_TEST_DECREF_AC(resultKeyPositive);
+ PKIX_TEST_DECREF_AC(resultKeyNegative);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testVerifySignature(char *dataCentralDir)
+{
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+ PKIX_PL_PublicKey *firstPubKey = NULL;
+ PKIX_PL_PublicKey *secondPubKey = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <labs2yassir>");
+ firstCert = createCert(dataCentralDir, "publicKey/labs2yassir", plContext);
+
+ subTest("PKIX_PL_Cert_Create <yassir2labs>");
+ secondCert = createCert(dataCentralDir, "publicKey/yassir2labs", plContext);
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <labs2yassir>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(firstCert, &firstPubKey, plContext));
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <yassir2labs>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(secondCert, &secondPubKey, plContext));
+
+ subTest("PKIX_PL_Cert_VerifySignature <positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_VerifySignature(secondCert, firstPubKey, plContext));
+
+ subTest("PKIX_PL_Cert_VerifySignature <negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_VerifySignature(secondCert, secondPubKey, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstCert);
+ PKIX_TEST_DECREF_AC(secondCert);
+ PKIX_TEST_DECREF_AC(firstPubKey);
+ PKIX_TEST_DECREF_AC(secondPubKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCheckValidity(
+ PKIX_PL_Cert *olderCert,
+ PKIX_PL_Cert *newerCert)
+{
+ /*
+ * olderCert has the following Validity:
+ * notBefore = August 19, 1999: 20:19:56 GMT
+ * notAfter = August 18, 2000: 20:19:56 GMT
+ *
+ * newerCert has the following Validity:
+ * notBefore = November 13, 2003: 16:46:03 GMT
+ * notAfter = February 13, 2009: 16:46:03 GMT
+ */
+
+ /* olderDateAscii = March 29, 2000: 13:48:47 GMT */
+ char *olderAscii = "000329134847Z";
+ PKIX_PL_String *olderString = NULL;
+ PKIX_PL_Date *olderDate = NULL;
+
+ /* newerDateAscii = March 29, 2004: 13:48:47 GMT */
+ char *newerAscii = "040329134847Z";
+ PKIX_PL_String *newerString = NULL;
+ PKIX_PL_Date *newerDate = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_CheckValidity <creating Dates>");
+
+ /* create newer date when newer cert is valid but older cert is not */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, newerAscii, 0, &newerString, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Date_Create_UTCTime(newerString, &newerDate, plContext));
+
+ /* create older date when older cert is valid but newer cert is not */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, olderAscii, 0, &olderString, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Date_Create_UTCTime(olderString, &olderDate, plContext));
+
+ /* check validity of both certificates using olderDate */
+ subTest("PKIX_PL_Cert_CheckValidity <olderDate:positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_CheckValidity(olderCert, olderDate, plContext));
+
+ subTest("PKIX_PL_Cert_CheckValidity <olderDate:negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckValidity(newerCert, olderDate, plContext));
+
+ /* check validity of both certificates using newerDate */
+ subTest("PKIX_PL_Cert_CheckValidity <newerDate:positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_CheckValidity(newerCert, newerDate, plContext));
+
+ subTest("PKIX_PL_Cert_CheckValidity <newerDate:negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckValidity(olderCert, newerDate, plContext));
+
+ /*
+ * check validity of both certificates using current time
+ * NOTE: these "now" tests will not work when the current
+ * time is after newerCert.notAfter (~ February 13, 2009)
+ */
+ subTest("PKIX_PL_Cert_CheckValidity <now:positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_CheckValidity(newerCert, NULL, plContext));
+
+ subTest("PKIX_PL_Cert_CheckValidity <now:negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckValidity(olderCert, NULL, plContext));
+
+cleanup:
+ PKIX_TEST_DECREF_AC(olderString);
+ PKIX_TEST_DECREF_AC(newerString);
+ PKIX_TEST_DECREF_AC(olderDate);
+ PKIX_TEST_DECREF_AC(newerDate);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+readCertBasicConstraints(
+ char *dataDir,
+ char *goodCertName,
+ char *diffCertName,
+ PKIX_PL_CertBasicConstraints **goodBasicConstraints,
+ PKIX_PL_CertBasicConstraints **equalBasicConstraints,
+ PKIX_PL_CertBasicConstraints **diffBasicConstraints)
+{
+
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ createCerts(dataDir, goodCertName, diffCertName,
+ &goodCert, &equalCert, &diffCert);
+ /*
+ * Warning: pointer will be NULL if BasicConstraints
+ * extension is not present in the certificate. */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetBasicConstraints(goodCert, goodBasicConstraints, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetBasicConstraints(equalCert, equalBasicConstraints, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetBasicConstraints(diffCert, diffBasicConstraints, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testBasicConstraintsHelper(
+ char *dataDir,
+ char *goodCertName,
+ char *diffCertName,
+ char *expectedAscii)
+{
+ PKIX_PL_CertBasicConstraints *goodBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *equalBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *diffBasicConstraints = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ readCertBasicConstraints(dataDir,
+ goodCertName,
+ diffCertName,
+ &goodBasicConstraints,
+ &equalBasicConstraints,
+ &diffBasicConstraints);
+
+ /*
+ * The standard test macro is applicable only
+ * if BasicConstraint extension is present
+ * in the certificate. Otherwise some
+ * pointers will be null.
+ */
+ if ((goodBasicConstraints) &&
+ (equalBasicConstraints) &&
+ (diffBasicConstraints)) {
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodBasicConstraints,
+ equalBasicConstraints,
+ diffBasicConstraints,
+ expectedAscii,
+ BasicConstraints,
+ PKIX_TRUE);
+ } else {
+ /* Test what we can */
+ if (goodBasicConstraints) {
+ if (!equalBasicConstraints) {
+ testError("Unexpected NULL value of equalBasicConstraints");
+ goto cleanup;
+ }
+ subTest("PKIX_PL_BasicConstraints_Equals <match>");
+ testEqualsHelper((PKIX_PL_Object *)(goodBasicConstraints),
+ (PKIX_PL_Object *)(equalBasicConstraints),
+ PKIX_TRUE,
+ plContext);
+ subTest("PKIX_PL_BasicConstraints_Hashcode <match>");
+ testHashcodeHelper((PKIX_PL_Object *)(goodBasicConstraints),
+ (PKIX_PL_Object *)(equalBasicConstraints),
+ PKIX_TRUE,
+ plContext);
+ if (diffBasicConstraints) {
+ subTest("PKIX_PL_BasicConstraints_Equals <non-match>");
+ testEqualsHelper((PKIX_PL_Object *)(goodBasicConstraints),
+ (PKIX_PL_Object *)(diffBasicConstraints),
+ PKIX_FALSE,
+ plContext);
+ subTest("PKIX_PL_BasicConstraints_Hashcode <non-match>");
+ testHashcodeHelper((PKIX_PL_Object *)(goodBasicConstraints),
+ (PKIX_PL_Object *)(diffBasicConstraints),
+ PKIX_FALSE,
+ plContext);
+ }
+ subTest("PKIX_PL_BasicConstraints_Duplicate");
+ testDuplicateHelper((PKIX_PL_Object *)goodBasicConstraints, plContext);
+ }
+ if (expectedAscii) {
+ subTest("PKIX_PL_BasicConstraints_ToString");
+ testToStringHelper((PKIX_PL_Object *)(goodBasicConstraints),
+ expectedAscii,
+ plContext);
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodBasicConstraints);
+ PKIX_TEST_DECREF_AC(equalBasicConstraints);
+ PKIX_TEST_DECREF_AC(diffBasicConstraints);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testBasicConstraints_GetCAFlag(char *dataCentralDir)
+{
+ /*
+ * XXX When we have a certificate with a non-null Basic
+ * Constraints field and a value of FALSE for CAFlag,
+ * this test should be modified to use that
+ * certificate for diffCertName, and to verify that
+ * GetCAFlag returns a FALSE value. But our certificates for
+ * non-CAs are created with no BasicConstraints extension.
+ */
+ PKIX_PL_CertBasicConstraints *goodBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *equalBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *diffBasicConstraints = NULL;
+ char *goodCertName = "yassir2yassir";
+ char *diffCertName = "nss2alice";
+ PKIX_Boolean goodCAFlag = PKIX_FALSE;
+ PKIX_Boolean diffCAFlag = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_BasicConstraints_GetCAFlag");
+
+ readCertBasicConstraints(dataCentralDir,
+ goodCertName,
+ diffCertName,
+ &goodBasicConstraints,
+ &equalBasicConstraints,
+ &diffBasicConstraints);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetCAFlag(goodBasicConstraints, &goodCAFlag, plContext));
+ if (!goodCAFlag) {
+ testError("BasicConstraint CAFlag unexpectedly FALSE");
+ goto cleanup;
+ }
+
+ if (diffBasicConstraints) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetCAFlag(diffBasicConstraints, &diffCAFlag, plContext));
+ if (diffCAFlag) {
+ testError("BasicConstraint CAFlag unexpectedly TRUE");
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodBasicConstraints);
+ PKIX_TEST_DECREF_AC(equalBasicConstraints);
+ PKIX_TEST_DECREF_AC(diffBasicConstraints);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testBasicConstraints_GetPathLenConstraint(char *dataCentralDir)
+{
+ PKIX_PL_CertBasicConstraints *goodBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *equalBasicConstraints = NULL;
+ PKIX_PL_CertBasicConstraints *diffBasicConstraints = NULL;
+ char *goodCertName = "yassir2yassir";
+ char *diffCertName = "sun2sun";
+ PKIX_Int32 goodPathLen = 0;
+ PKIX_Int32 diffPathLen = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_BasicConstraints_GetPathLenConstraint");
+
+ readCertBasicConstraints(dataCentralDir,
+ goodCertName,
+ diffCertName,
+ &goodBasicConstraints,
+ &equalBasicConstraints,
+ &diffBasicConstraints);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetPathLenConstraint(goodBasicConstraints, &goodPathLen, plContext));
+ if (0 != goodPathLen) {
+ testError("unexpected basicConstraint pathLen");
+ (void)printf("Actual value:\t%d\n", goodPathLen);
+ (void)printf("Expected value:\t0\n");
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BasicConstraints_GetPathLenConstraint(diffBasicConstraints, &diffPathLen, plContext));
+ if (1 != diffPathLen) {
+ testError("unexpected basicConstraint pathLen");
+ (void)printf("Actual value:\t%d\n", diffPathLen);
+ (void)printf("Expected value:\t1\n");
+ goto cleanup;
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodBasicConstraints);
+ PKIX_TEST_DECREF_AC(equalBasicConstraints);
+ PKIX_TEST_DECREF_AC(diffBasicConstraints);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetBasicConstraints(char *dataCentralDir)
+{
+ char *goodCertName = NULL;
+ char *diffCertName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetBasicConstraints <CA(0) and non-CA>");
+ goodCertName = "yassir2yassir";
+ diffCertName = "nss2alice";
+ testBasicConstraintsHelper(dataCentralDir, goodCertName, diffCertName, "CA(0)");
+
+ subTest("PKIX_PL_Cert_GetBasicConstraints <non-CA and CA(1)>");
+ goodCertName = "nss2alice";
+ diffCertName = "sun2sun";
+ testBasicConstraintsHelper(dataCentralDir, goodCertName, diffCertName, NULL);
+
+ subTest("PKIX_PL_Cert_GetBasicConstraints <CA(0) and CA(1)>");
+ goodCertName = "yassir2bcn";
+ diffCertName = "sun2sun";
+ testBasicConstraintsHelper(dataCentralDir, goodCertName, diffCertName, "CA(0)");
+
+ subTest("PKIX_PL_Cert_GetBasicConstraints <CA(-1) and CA(1)>");
+ goodCertName = "anchor2dsa";
+ diffCertName = "sun2sun";
+ testBasicConstraintsHelper(dataCentralDir, goodCertName, diffCertName, "CA(-1)");
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetPolicyInformation(char *dataDir)
+{
+
+ char *goodCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *equalCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *diffCertName =
+ "UserNoticeQualifierTest17EE.crt";
+ PKIX_Boolean isImmutable = PKIX_FALSE;
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_List *goodPolicyInfo = NULL;
+ PKIX_List *equalPolicyInfo = NULL;
+ PKIX_List *diffPolicyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *goodPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *equalPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *diffPolicy = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_Cert_GetPolicyInformation");
+
+ /*
+ * Get the cert, then the list of policyInfos.
+ * Take the first policyInfo from the list.
+ */
+
+ /* Get the PolicyInfo objects */
+ goodCert = createCert(dataDir, goodCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(goodCert, &goodPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodPolicyInfo, 0, (PKIX_PL_Object **)&goodPolicy, plContext));
+
+ equalCert = createCert(dataDir, equalCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(equalCert, &equalPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalPolicyInfo,
+ 0,
+ (PKIX_PL_Object **)&equalPolicy,
+ plContext));
+
+ diffCert = createCert(dataDir, diffCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(diffCert, &diffPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffPolicyInfo, 0, (PKIX_PL_Object **)&diffPolicy, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodPolicy,
+ equalPolicy,
+ diffPolicy,
+ NULL,
+ CertPolicyInfo,
+ PKIX_FALSE);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsImmutable(goodPolicyInfo, &isImmutable, plContext));
+
+ if (isImmutable != PKIX_TRUE) {
+ testError("PolicyInfo List is not immutable");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+ PKIX_TEST_DECREF_AC(goodPolicyInfo);
+ PKIX_TEST_DECREF_AC(equalPolicyInfo);
+ PKIX_TEST_DECREF_AC(diffPolicyInfo);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertPolicy_GetPolicyId(char *dataDir)
+{
+ char *goodCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *equalCertName =
+ "UserNoticeQualifierTest16EE.crt";
+ char *diffCertName =
+ "UserNoticeQualifierTest17EE.crt";
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_List *goodPolicyInfo = NULL;
+ PKIX_List *equalPolicyInfo = NULL;
+ PKIX_List *diffPolicyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *goodPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *equalPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *diffPolicy = NULL;
+ PKIX_PL_OID *goodID = NULL;
+ PKIX_PL_OID *equalID = NULL;
+ PKIX_PL_OID *diffID = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_CertPolicyInfo_GetPolicyId");
+
+ /*
+ * Get the cert, then the list of policyInfos.
+ * Take the first policyInfo from the list.
+ * Finally, get the policyInfo's ID.
+ */
+
+ /* Get the PolicyInfo objects */
+ goodCert = createCert(dataDir, goodCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(goodCert, &goodPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodPolicyInfo, 0, (PKIX_PL_Object **)&goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId(goodPolicy, &goodID, plContext));
+
+ equalCert = createCert(dataDir, equalCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(equalCert, &equalPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalPolicyInfo,
+ 0,
+ (PKIX_PL_Object **)&equalPolicy,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId(equalPolicy, &equalID, plContext));
+
+ diffCert = createCert(dataDir, diffCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(diffCert, &diffPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffPolicyInfo, 0, (PKIX_PL_Object **)&diffPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId(diffPolicy, &diffID, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodID, equalID, diffID, NULL, OID, PKIX_FALSE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodID);
+ PKIX_TEST_DECREF_AC(equalID);
+ PKIX_TEST_DECREF_AC(diffID);
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+ PKIX_TEST_DECREF_AC(goodPolicyInfo);
+ PKIX_TEST_DECREF_AC(equalPolicyInfo);
+ PKIX_TEST_DECREF_AC(diffPolicyInfo);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertPolicy_GetPolQualifiers(char *dataDir)
+{
+ char *goodCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *equalCertName =
+ "UserNoticeQualifierTest16EE.crt";
+ char *diffCertName =
+ "UserNoticeQualifierTest18EE.crt";
+ PKIX_Boolean isImmutable = PKIX_FALSE;
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_List *goodPolicyInfo = NULL;
+ PKIX_List *equalPolicyInfo = NULL;
+ PKIX_List *diffPolicyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *goodPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *equalPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *diffPolicy = NULL;
+ PKIX_List *goodQuals = NULL;
+ PKIX_List *equalQuals = NULL;
+ PKIX_List *diffQuals = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_CertPolicyInfo_GetPolQualifiers");
+
+ /*
+ * Get the cert, then the list of policyInfos.
+ * Take the first policyInfo from the list.
+ * Get its list of PolicyQualifiers.
+ */
+
+ /* Get the PolicyInfo objects */
+ goodCert = createCert(dataDir, goodCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(goodCert, &goodPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodPolicyInfo, 0, (PKIX_PL_Object **)&goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(goodPolicy, &goodQuals, plContext));
+
+ equalCert = createCert(dataDir, equalCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(equalCert, &equalPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalPolicyInfo,
+ 0,
+ (PKIX_PL_Object **)&equalPolicy,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(equalPolicy, &equalQuals, plContext));
+
+ diffCert = createCert(dataDir, diffCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(diffCert, &diffPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffPolicyInfo, 0, (PKIX_PL_Object **)&diffPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(diffPolicy, &diffQuals, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodQuals,
+ equalQuals,
+ diffQuals,
+ NULL,
+ List,
+ PKIX_FALSE);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_IsImmutable(goodQuals, &isImmutable, plContext));
+
+ if (isImmutable != PKIX_TRUE) {
+ testError("PolicyQualifier List is not immutable");
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(goodPolicyInfo);
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(goodQuals);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(equalPolicyInfo);
+ PKIX_TEST_DECREF_AC(equalQuals);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_DECREF_AC(diffPolicyInfo);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+ PKIX_TEST_DECREF_AC(diffQuals);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testPolicyQualifier_GetQualifier(char *dataDir)
+{
+ char *goodCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *equalCertName =
+ "UserNoticeQualifierTest16EE.crt";
+ char *diffCertName =
+ "UserNoticeQualifierTest18EE.crt";
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_List *goodPolicyInfo = NULL;
+ PKIX_List *equalPolicyInfo = NULL;
+ PKIX_List *diffPolicyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *goodPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *equalPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *diffPolicy = NULL;
+ PKIX_List *goodQuals = NULL;
+ PKIX_List *equalQuals = NULL;
+ PKIX_List *diffQuals = NULL;
+ PKIX_PL_CertPolicyQualifier *goodPolQualifier = NULL;
+ PKIX_PL_CertPolicyQualifier *equalPolQualifier = NULL;
+ PKIX_PL_CertPolicyQualifier *diffPolQualifier = NULL;
+ PKIX_PL_ByteArray *goodArray = NULL;
+ PKIX_PL_ByteArray *equalArray = NULL;
+ PKIX_PL_ByteArray *diffArray = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_PolicyQualifier_GetQualifier");
+
+ /*
+ * Get the cert, then the list of policyInfos.
+ * Take the first policyInfo from the list.
+ * Get its list of PolicyQualifiers.
+ * Take the first policyQualifier from the list.
+ * Finally, get the policyQualifier's ByteArray.
+ */
+
+ /* Get the PolicyInfo objects */
+ goodCert = createCert(dataDir, goodCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(goodCert, &goodPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodPolicyInfo, 0, (PKIX_PL_Object **)&goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(goodPolicy, &goodQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodQuals,
+ 0,
+ (PKIX_PL_Object **)&goodPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetQualifier(goodPolQualifier, &goodArray, plContext));
+
+ equalCert = createCert(dataDir, equalCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(equalCert, &equalPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalPolicyInfo,
+ 0,
+ (PKIX_PL_Object **)&equalPolicy,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(equalPolicy, &equalQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalQuals,
+ 0,
+ (PKIX_PL_Object **)&equalPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetQualifier(equalPolQualifier, &equalArray, plContext));
+
+ diffCert = createCert(dataDir, diffCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(diffCert, &diffPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffPolicyInfo, 0, (PKIX_PL_Object **)&diffPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(diffPolicy, &diffQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffQuals,
+ 0,
+ (PKIX_PL_Object **)&diffPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetQualifier(diffPolQualifier, &diffArray, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodArray, equalArray, diffArray, NULL, ByteArray, PKIX_FALSE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodArray);
+ PKIX_TEST_DECREF_AC(equalArray);
+ PKIX_TEST_DECREF_AC(diffArray);
+ PKIX_TEST_DECREF_AC(goodPolQualifier);
+ PKIX_TEST_DECREF_AC(equalPolQualifier);
+ PKIX_TEST_DECREF_AC(diffPolQualifier);
+ PKIX_TEST_DECREF_AC(goodQuals);
+ PKIX_TEST_DECREF_AC(equalQuals);
+ PKIX_TEST_DECREF_AC(diffQuals);
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+ PKIX_TEST_DECREF_AC(goodPolicyInfo);
+ PKIX_TEST_DECREF_AC(equalPolicyInfo);
+ PKIX_TEST_DECREF_AC(diffPolicyInfo);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testPolicyQualifier_GetPolicyQualifierId(char *dataDir)
+{
+ char *goodCertName =
+ "UserNoticeQualifierTest15EE.crt";
+ char *equalCertName =
+ "UserNoticeQualifierTest16EE.crt";
+ char *diffCertName =
+ "CPSPointerQualifierTest20EE.crt";
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_Cert *equalCert = NULL;
+ PKIX_PL_Cert *diffCert = NULL;
+ PKIX_List *goodPolicyInfo = NULL;
+ PKIX_List *equalPolicyInfo = NULL;
+ PKIX_List *diffPolicyInfo = NULL;
+ PKIX_PL_CertPolicyInfo *goodPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *equalPolicy = NULL;
+ PKIX_PL_CertPolicyInfo *diffPolicy = NULL;
+ PKIX_List *goodQuals = NULL;
+ PKIX_List *equalQuals = NULL;
+ PKIX_List *diffQuals = NULL;
+ PKIX_PL_CertPolicyQualifier *goodPolQualifier = NULL;
+ PKIX_PL_CertPolicyQualifier *equalPolQualifier = NULL;
+ PKIX_PL_CertPolicyQualifier *diffPolQualifier = NULL;
+ PKIX_PL_OID *goodID = NULL;
+ PKIX_PL_OID *equalID = NULL;
+ PKIX_PL_OID *diffID = NULL;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_PolicyQualifier_GetPolicyQualifierId");
+
+ /*
+ * Get the cert, then the list of policyInfos.
+ * Take the first policyInfo from the list.
+ * Get its list of PolicyQualifiers.
+ * Take the first policyQualifier from the list.
+ * Finally, get the policyQualifier's ID.
+ */
+
+ /* Get the PolicyQualifier objects */
+ goodCert = createCert(dataDir, goodCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(goodCert, &goodPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodPolicyInfo, 0, (PKIX_PL_Object **)&goodPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(goodPolicy, &goodQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(goodQuals,
+ 0,
+ (PKIX_PL_Object **)&goodPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetPolicyQualifierId(goodPolQualifier, &goodID, plContext));
+
+ equalCert = createCert(dataDir, equalCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(equalCert, &equalPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalPolicyInfo,
+ 0,
+ (PKIX_PL_Object **)&equalPolicy,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(equalPolicy, &equalQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(equalQuals,
+ 0,
+ (PKIX_PL_Object **)&equalPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetPolicyQualifierId(equalPolQualifier, &equalID, plContext));
+
+ diffCert = createCert(dataDir, diffCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation(diffCert, &diffPolicyInfo, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffPolicyInfo, 0, (PKIX_PL_Object **)&diffPolicy, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers(diffPolicy, &diffQuals, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(diffQuals,
+ 0,
+ (PKIX_PL_Object **)&diffPolQualifier,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_PolicyQualifier_GetPolicyQualifierId(diffPolQualifier, &diffID, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodID, equalID, diffID, NULL, OID, PKIX_FALSE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodID);
+ PKIX_TEST_DECREF_AC(equalID);
+ PKIX_TEST_DECREF_AC(diffID);
+ PKIX_TEST_DECREF_AC(goodPolQualifier);
+ PKIX_TEST_DECREF_AC(equalPolQualifier);
+ PKIX_TEST_DECREF_AC(diffPolQualifier);
+ PKIX_TEST_DECREF_AC(goodQuals);
+ PKIX_TEST_DECREF_AC(equalQuals);
+ PKIX_TEST_DECREF_AC(diffQuals);
+ PKIX_TEST_DECREF_AC(goodPolicy);
+ PKIX_TEST_DECREF_AC(equalPolicy);
+ PKIX_TEST_DECREF_AC(diffPolicy);
+ PKIX_TEST_DECREF_AC(goodPolicyInfo);
+ PKIX_TEST_DECREF_AC(equalPolicyInfo);
+ PKIX_TEST_DECREF_AC(diffPolicyInfo);
+ PKIX_TEST_DECREF_AC(goodCert);
+ PKIX_TEST_DECREF_AC(equalCert);
+ PKIX_TEST_DECREF_AC(diffCert);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAreCertPoliciesCritical(char *dataCentralDir, char *dataDir)
+{
+
+ char *trueCertName = "CertificatePoliciesCritical.crt";
+ char *falseCertName = "UserNoticeQualifierTest15EE.crt";
+ PKIX_PL_Cert *trueCert = NULL;
+ PKIX_PL_Cert *falseCert = NULL;
+ PKIX_Boolean trueVal = PKIX_FALSE;
+ PKIX_Boolean falseVal = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_Cert_AreCertPoliciesCritical - <true>");
+
+ trueCert = createCert(dataCentralDir, trueCertName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_AreCertPoliciesCritical(trueCert, &trueVal, plContext));
+
+ if (trueVal != PKIX_TRUE) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", trueVal);
+ (void)printf("Expected value:\t1\n");
+ goto cleanup;
+ }
+
+ subTest("PKIX_PL_Cert_AreCertPoliciesCritical - <false>");
+
+ falseCert = createCert(dataDir, falseCertName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_AreCertPoliciesCritical(falseCert, &falseVal, plContext));
+
+ if (falseVal != PKIX_FALSE) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", falseVal);
+ (void)printf("Expected value:\t0\n");
+ goto cleanup;
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(trueCert);
+ PKIX_TEST_DECREF_AC(falseCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertPolicyConstraints(char *dataDir)
+{
+ char *requireExplicitPolicy2CertName =
+ "requireExplicitPolicy2CACert.crt";
+ char *inhibitPolicyMapping5CertName =
+ "inhibitPolicyMapping5CACert.crt";
+ char *inhibitAnyPolicy5CertName =
+ "inhibitAnyPolicy5CACert.crt";
+ char *inhibitAnyPolicy0CertName =
+ "inhibitAnyPolicy0CACert.crt";
+ PKIX_PL_Cert *requireExplicitPolicy2Cert = NULL;
+ PKIX_PL_Cert *inhibitPolicyMapping5Cert = NULL;
+ PKIX_PL_Cert *inhibitAnyPolicy5Cert = NULL;
+ PKIX_PL_Cert *inhibitAnyPolicy0Cert = NULL;
+ PKIX_Int32 skipCerts = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetRequireExplicitPolicy");
+ requireExplicitPolicy2Cert = createCert(dataDir, requireExplicitPolicy2CertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetRequireExplicitPolicy(requireExplicitPolicy2Cert, &skipCerts, NULL));
+ PR_ASSERT(skipCerts == 2);
+
+ subTest("PKIX_PL_Cert_GetPolicyMappingInhibited");
+ inhibitPolicyMapping5Cert = createCert(dataDir, inhibitPolicyMapping5CertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyMappingInhibited(inhibitPolicyMapping5Cert, &skipCerts, NULL));
+ PR_ASSERT(skipCerts == 5);
+
+ subTest("PKIX_PL_Cert_GetInhibitAnyPolicy");
+ inhibitAnyPolicy5Cert = createCert(dataDir, inhibitAnyPolicy5CertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetInhibitAnyPolicy(inhibitAnyPolicy5Cert, &skipCerts, NULL));
+ PR_ASSERT(skipCerts == 5);
+
+ inhibitAnyPolicy0Cert = createCert(dataDir, inhibitAnyPolicy0CertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetInhibitAnyPolicy(inhibitAnyPolicy0Cert, &skipCerts, NULL));
+ PR_ASSERT(skipCerts == 0);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(requireExplicitPolicy2Cert);
+ PKIX_TEST_DECREF_AC(inhibitPolicyMapping5Cert);
+ PKIX_TEST_DECREF_AC(inhibitAnyPolicy5Cert);
+ PKIX_TEST_DECREF_AC(inhibitAnyPolicy0Cert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCertPolicyMaps(char *dataDir)
+{
+ char *policyMappingsCertName =
+ "P1Mapping1to234CACert.crt";
+ char *expectedAscii =
+ "2.16.840.1.101.3.2.1.48.1=>2.16.840.1.101.3.2.1.48.2";
+
+ PKIX_PL_Cert *policyMappingsCert = NULL;
+ PKIX_List *mappings = NULL;
+ PKIX_PL_CertPolicyMap *goodMap = NULL;
+ PKIX_PL_CertPolicyMap *equalMap = NULL;
+ PKIX_PL_CertPolicyMap *diffMap = NULL;
+ PKIX_PL_OID *goodOID = NULL;
+ PKIX_PL_OID *equalOID = NULL;
+ PKIX_PL_OID *diffOID = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_GetPolicyMappings");
+
+ policyMappingsCert = createCert(dataDir, policyMappingsCertName, plContext);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyMappings(policyMappingsCert, &mappings, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(mappings, 0, (PKIX_PL_Object **)&goodMap, NULL));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(mappings, 0, (PKIX_PL_Object **)&equalMap, NULL));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(mappings, 2, (PKIX_PL_Object **)&diffMap, NULL));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodMap,
+ equalMap,
+ diffMap,
+ expectedAscii,
+ CertPolicyMap,
+ PKIX_TRUE);
+
+ subTest("PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy(goodMap, &goodOID, NULL));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy(diffMap, &equalOID, NULL));
+ subTest("PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy(diffMap, &diffOID, NULL));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodOID,
+ equalOID,
+ diffOID,
+ "2.16.840.1.101.3.2.1.48.1",
+ OID,
+ PKIX_FALSE);
+
+ subTest("pkix_pl_CertPolicyMap_Destroy");
+ PKIX_TEST_DECREF_BC(goodMap);
+ PKIX_TEST_DECREF_BC(equalMap);
+ PKIX_TEST_DECREF_BC(diffMap);
+
+cleanup:
+ PKIX_TEST_DECREF_AC(policyMappingsCert);
+ PKIX_TEST_DECREF_AC(mappings);
+ PKIX_TEST_DECREF_AC(goodOID);
+ PKIX_TEST_DECREF_AC(equalOID);
+ PKIX_TEST_DECREF_AC(diffOID);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testNameConstraints(char *dataDir)
+{
+ char *firstPname = "nameConstraintsDN3subCA2Cert.crt";
+ char *secondPname = "nameConstraintsDN4CACert.crt";
+ char *thirdPname = "nameConstraintsDN5CACert.crt";
+ char *lastPname = "InvalidDNnameConstraintsTest3EE.crt";
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+ PKIX_PL_Cert *thirdCert = NULL;
+ PKIX_PL_Cert *lastCert = NULL;
+ PKIX_PL_CertNameConstraints *firstNC = NULL;
+ PKIX_PL_CertNameConstraints *secondNC = NULL;
+ PKIX_PL_CertNameConstraints *thirdNC = NULL;
+ PKIX_PL_CertNameConstraints *firstMergedNC = NULL;
+ PKIX_PL_CertNameConstraints *secondMergedNC = NULL;
+ char *firstExpectedAscii =
+ "[\n"
+ "\t\tPermitted Name: (O=Test Certificates,C=US)\n"
+ "\t\tExcluded Name: (OU=excludedSubtree1,O=Test Certificates,"
+ "C=US, OU=excludedSubtree2,O=Test Certificates,C=US)\n"
+ "\t]\n";
+ char *secondExpectedAscii =
+ "[\n"
+ "\t\tPermitted Name: (O=Test Certificates,C=US, "
+ "OU=permittedSubtree1,O=Test Certificates,C=US)\n"
+ "\t\tExcluded Name: (OU=excludedSubtree1,"
+ "O=Test Certificates,"
+ "C=US, OU=excludedSubtree2,O=Test Certificates,C=US, "
+ "OU=excludedSubtree1,OU=permittedSubtree1,"
+ "O=Test Certificates,C=US)\n"
+ "\t]\n";
+
+ PKIX_TEST_STD_VARS();
+ subTest("PKIX_PL_CertNameConstraints");
+
+ firstCert = createCert(dataDir, firstPname, plContext);
+ secondCert = createCert(dataDir, secondPname, plContext);
+ thirdCert = createCert(dataDir, thirdPname, plContext);
+ lastCert = createCert(dataDir, lastPname, plContext);
+
+ subTest("PKIX_PL_Cert_GetNameConstraints <total=3>");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(firstCert, &firstNC, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(secondCert, &secondNC, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(thirdCert, &thirdNC, NULL));
+
+ subTest("PKIX_PL_Cert_MergeNameConstraints <1st and 2nd>");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_MergeNameConstraints(firstNC, secondNC, &firstMergedNC, NULL));
+
+ subTest("PKIX_PL_Cert_MergeNameConstraints <1st+2nd and 3rd>");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_MergeNameConstraints(firstMergedNC, thirdNC, &secondMergedNC, NULL));
+
+ testToStringHelper((PKIX_PL_Object *)firstMergedNC,
+ firstExpectedAscii,
+ plContext);
+
+ testToStringHelper((PKIX_PL_Object *)secondMergedNC,
+ secondExpectedAscii,
+ plContext);
+
+ subTest("PKIX_PL_Cert_CheckNameConstraints <permitted>");
+
+ /* Subject: CN=nameConstraints DN3 subCA2,O=Test Certificates,C=US */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_CheckNameConstraints(firstCert, firstMergedNC, NULL));
+
+ subTest("PKIX_PL_Cert_CheckNameConstraints <OU in excluded>");
+
+ /*
+ * Subject: CN=Invalid DN nameConstraints EE Certificate Test3,
+ * OU=permittedSubtree1,O=Test Certificates,C=US
+ */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckNameConstraints(lastCert, secondMergedNC, NULL));
+
+ subTest("PKIX_PL_Cert_CheckNameConstraints <excluded>");
+
+ /*
+ * Subject: CN=Invalid DN nameConstraints EE Certificate Test3,
+ * OU=permittedSubtree1,O=Test Certificates,C=US
+ * SubjectAltNames: CN=Invalid DN nameConstraints EE Certificate
+ * Test3,OU=excludedSubtree1,O=Test Certificates,C=US
+ */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckNameConstraints(lastCert, firstMergedNC, NULL));
+
+ subTest("PKIX_PL_Cert_CheckNameConstraints <excluded>");
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Cert_CheckNameConstraints(firstCert, secondMergedNC, NULL));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstCert);
+ PKIX_TEST_DECREF_AC(secondCert);
+ PKIX_TEST_DECREF_AC(thirdCert);
+ PKIX_TEST_DECREF_AC(lastCert);
+ PKIX_TEST_DECREF_AC(firstNC);
+ PKIX_TEST_DECREF_AC(secondNC);
+ PKIX_TEST_DECREF_AC(thirdNC);
+ PKIX_TEST_DECREF_AC(firstMergedNC);
+ PKIX_TEST_DECREF_AC(secondMergedNC);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+ PKIX_TEST_DECREF_BC(altNameNoneCert);
+ PKIX_TEST_DECREF_BC(altNameOtherCert);
+ PKIX_TEST_DECREF_BC(altNameOtherCert_diff);
+ PKIX_TEST_DECREF_BC(altNameRfc822Cert);
+ PKIX_TEST_DECREF_BC(altNameRfc822Cert_diff);
+ PKIX_TEST_DECREF_BC(altNameDnsCert);
+ PKIX_TEST_DECREF_BC(altNameDnsCert_diff);
+ PKIX_TEST_DECREF_BC(altNameX400Cert);
+ PKIX_TEST_DECREF_BC(altNameX400Cert_diff);
+ PKIX_TEST_DECREF_BC(altNameDnCert);
+ PKIX_TEST_DECREF_BC(altNameDnCert_diff);
+ PKIX_TEST_DECREF_BC(altNameEdiCert);
+ PKIX_TEST_DECREF_BC(altNameEdiCert_diff);
+ PKIX_TEST_DECREF_BC(altNameUriCert);
+ PKIX_TEST_DECREF_BC(altNameUriCert_diff);
+ PKIX_TEST_DECREF_BC(altNameIpCert);
+ PKIX_TEST_DECREF_BC(altNameIpCert_diff);
+ PKIX_TEST_DECREF_BC(altNameOidCert);
+ PKIX_TEST_DECREF_BC(altNameOidCert_diff);
+ PKIX_TEST_DECREF_BC(altNameMultipleCert);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_cert <test-purpose> <data-central-dir> <data-dir>\n\n");
+}
+
+int
+test_cert(int argc, char *argv[])
+{
+
+ PKIX_PL_Cert *goodObject = NULL;
+ PKIX_PL_Cert *equalObject = NULL;
+ PKIX_PL_Cert *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *dataCentralDir = NULL;
+ char *dataDir = NULL;
+ char *goodInput = "yassir2bcn";
+ char *diffInput = "nss2alice";
+
+ char *expectedAscii =
+ "[\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, 1999\n"
+ /* "\tValidity: [From: Thu Aug 19 16:19:56 1999\n" */
+ "\t To: Fri Aug 18, 2000]\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"
+ "\tAuthorityInfoAccess: (null)\n"
+ "\tSubjectInfoAccess: (null)\n"
+ "\tCacheFlag: 0\n"
+ "]\n";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Cert");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 3 + j) {
+ printUsage();
+ return (0);
+ }
+
+ dataCentralDir = argv[2 + j];
+ dataDir = argv[3 + j];
+
+ createCerts(dataCentralDir,
+ goodInput,
+ diffInput,
+ &goodObject,
+ &equalObject,
+ &diffObject);
+
+ testToStringHelper((PKIX_PL_Object *)goodObject, expectedAscii, plContext);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ Cert,
+ PKIX_TRUE);
+
+ testVerifyKeyUsage(dataCentralDir, dataDir, goodObject);
+
+ testGetExtendedKeyUsage(dataCentralDir);
+ testGetKeyIdentifiers(dataCentralDir, goodObject);
+
+ testGetVersion(goodObject);
+ testGetSerialNumber(goodObject, equalObject, diffObject);
+
+ testGetSubject(goodObject, equalObject, diffObject);
+ testGetIssuer(goodObject, equalObject, diffObject);
+
+ testGetSubjectAltNames(dataCentralDir);
+ testGetCriticalExtensionOIDs(dataCentralDir, goodObject);
+
+ testGetSubjectPublicKey(goodObject, equalObject, diffObject);
+ testGetSubjectPublicKeyAlgId(goodObject);
+ testMakeInheritedDSAPublicKey(dataCentralDir);
+
+ testCheckValidity(goodObject, diffObject);
+
+ testBasicConstraints_GetCAFlag(dataCentralDir);
+ testBasicConstraints_GetPathLenConstraint(dataCentralDir);
+ testGetBasicConstraints(dataCentralDir);
+
+ /* Basic Policy Processing */
+ testGetPolicyInformation(dataDir);
+ testCertPolicy_GetPolicyId(dataDir);
+ testCertPolicy_GetPolQualifiers(dataDir);
+ testPolicyQualifier_GetPolicyQualifierId(dataDir);
+ testPolicyQualifier_GetQualifier(dataDir);
+ testAreCertPoliciesCritical(dataCentralDir, dataDir);
+
+ /* Advanced Policy Processing */
+ testCertPolicyConstraints(dataDir);
+ testCertPolicyMaps(dataDir);
+
+ testNameConstraints(dataDir);
+
+ testVerifySignature(dataCentralDir);
+
+ testDestroy(goodObject, equalObject, diffObject);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Cert");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_crl.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_crl.c
new file mode 100644
index 0000000000..6372c7a370
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_crl.c
@@ -0,0 +1,302 @@
+/* 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_crl.c
+ *
+ * Test CRL Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createCRLs(
+ char *dataDir,
+ char *goodInput,
+ char *diffInput,
+ PKIX_PL_CRL **goodObject,
+ PKIX_PL_CRL **equalObject,
+ PKIX_PL_CRL **diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CRL_Create <goodObject>");
+ *goodObject = createCRL(dataDir, goodInput, plContext);
+
+ subTest("PKIX_PL_CRL_Create <equalObject>");
+ *equalObject = createCRL(dataDir, goodInput, plContext);
+
+ subTest("PKIX_PL_CRL_Create <diffObject>");
+ *diffObject = createCRL(dataDir, diffInput, plContext);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCRLEntryForSerialNumber(
+ PKIX_PL_CRL *goodObject)
+{
+ PKIX_PL_BigInt *bigInt;
+ PKIX_PL_String *bigIntString = NULL;
+ PKIX_PL_CRLEntry *crlEntry = NULL;
+ PKIX_PL_String *crlEntryString = NULL;
+ char *snAscii = "3039";
+ char *expectedAscii =
+ "\n\t[\n"
+ "\tSerialNumber: 3039\n"
+ "\tReasonCode: 257\n"
+ "\tRevocationDate: Fri Jan 07, 2005\n"
+ /* "\tRevocationDate: Fri Jan 07 15:09:10 2005\n" */
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n\t";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CRL_GetCRLEntryForSerialNumber");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ snAscii,
+ PL_strlen(snAscii),
+ &bigIntString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(
+ bigIntString,
+ &bigInt,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetCRLEntryForSerialNumber(
+ goodObject, bigInt, &crlEntry, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString(
+ (PKIX_PL_Object *)crlEntry,
+ &crlEntryString,
+ plContext));
+
+ testToStringHelper((PKIX_PL_Object *)crlEntryString,
+ expectedAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(bigIntString);
+ PKIX_TEST_DECREF_AC(bigInt);
+ PKIX_TEST_DECREF_AC(crlEntryString);
+ PKIX_TEST_DECREF_AC(crlEntry);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetIssuer(
+ PKIX_PL_CRL *goodObject,
+ PKIX_PL_CRL *equalObject,
+ PKIX_PL_CRL *diffObject)
+{
+ PKIX_PL_X500Name *goodIssuer = NULL;
+ PKIX_PL_X500Name *equalIssuer = NULL;
+ PKIX_PL_X500Name *diffIssuer = NULL;
+ char *expectedAscii = "CN=hanfeiyu,O=sun,C=us";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CRL_GetIssuer");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_CRL_GetIssuer(goodObject, &goodIssuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_CRL_GetIssuer(equalObject, &equalIssuer, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_CRL_GetIssuer(diffObject, &diffIssuer, plContext));
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodIssuer,
+ equalIssuer,
+ diffIssuer,
+ expectedAscii,
+ X500Name,
+ PKIX_TRUE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodIssuer);
+ PKIX_TEST_DECREF_AC(equalIssuer);
+ PKIX_TEST_DECREF_AC(diffIssuer);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCritExtensionsAbsent(PKIX_PL_CRL *crl)
+{
+ PKIX_List *oidList = NULL;
+ PKIX_UInt32 numOids = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetCriticalExtensionOIDs(crl, &oidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(oidList, &numOids, plContext));
+ if (numOids != 0) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(oidList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCriticalExtensionOIDs(PKIX_PL_CRL *goodObject)
+{
+ subTest("PKIX_PL_CRL_GetCriticalExtensionOIDs "
+ "<0 element>");
+ testCritExtensionsAbsent(goodObject);
+}
+
+static void
+testVerifySignature(char *dataCentralDir, PKIX_PL_CRL *crl)
+{
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+ PKIX_PL_PublicKey *firstPubKey = NULL;
+ PKIX_PL_PublicKey *secondPubKey = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Cert_Create <hanfeiyu2hanfeiyu>");
+ firstCert = createCert(dataCentralDir, "hanfeiyu2hanfeiyu", plContext);
+
+ subTest("PKIX_PL_Cert_Create <hy2hy-bc0>");
+ secondCert = createCert(dataCentralDir, "hy2hy-bc0", plContext);
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <hanfeiyu2hanfeiyu>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(firstCert, &firstPubKey, plContext));
+
+ subTest("PKIX_PL_Cert_GetSubjectPublicKey <hanfei2hanfei>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(secondCert, &secondPubKey, plContext));
+
+ subTest("PKIX_PL_CRL_VerifySignature <positive>");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_VerifySignature(crl, firstPubKey, plContext));
+
+ subTest("PKIX_PL_CRL_VerifySignature <negative>");
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_CRL_VerifySignature(crl, secondPubKey, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(firstCert);
+ PKIX_TEST_DECREF_AC(secondCert);
+ PKIX_TEST_DECREF_AC(firstPubKey);
+ PKIX_TEST_DECREF_AC(secondPubKey);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_crl <test-purpose> <data-central-dir>\n\n");
+}
+
+/* Functional tests for CRL public functions */
+
+int
+test_crl(int argc, char *argv[])
+{
+ PKIX_PL_CRL *goodObject = NULL;
+ PKIX_PL_CRL *equalObject = NULL;
+ PKIX_PL_CRL *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *dataCentralDir = NULL;
+ char *goodInput = "crlgood.crl";
+ char *diffInput = "crldiff.crl";
+ char *expectedAscii =
+ "[\n"
+ "\tVersion: v2\n"
+ "\tIssuer: CN=hanfeiyu,O=sun,C=us\n"
+ "\tUpdate: [Last: Fri Jan 07, 2005\n"
+ /* "\tUpdate: [Last: Fri Jan 07 15:09:10 2005\n" */
+ "\t Next: Sat Jan 07, 2006]\n"
+ /* "\t Next: Sat Jan 07 15:09:10 2006]\n" */
+ "\tSignatureAlgId: 1.2.840.10040.4.3\n"
+ "\tCRL Number : (null)\n"
+ "\n\tEntry List: (\n"
+ "\t[\n"
+ "\tSerialNumber: 010932\n"
+ "\tReasonCode: 260\n"
+ "\tRevocationDate: Fri Jan 07, 2005\n"
+ /* "\tRevocationDate: Fri Jan 07 15:09:10 2005\n" */
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n\t"
+ ", "
+ "\n\t[\n"
+ "\tSerialNumber: 3039\n"
+ "\tReasonCode: 257\n"
+ "\tRevocationDate: Fri Jan 07, 2005\n"
+ /* "\tRevocationDate: Fri Jan 07 15:09:10 2005\n" */
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n\t"
+ ")"
+ "\n\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "]\n";
+ /* Note XXX serialnumber and reasoncode need debug */
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CRL");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 3 + j) {
+ printUsage();
+ return (0);
+ }
+
+ dataCentralDir = argv[2 + j];
+
+ createCRLs(dataCentralDir,
+ goodInput,
+ diffInput,
+ &goodObject,
+ &equalObject,
+ &diffObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ CRL,
+ PKIX_TRUE);
+
+ testGetIssuer(goodObject, equalObject, diffObject);
+
+ testGetCriticalExtensionOIDs(goodObject);
+
+ testGetCRLEntryForSerialNumber(goodObject);
+
+ testVerifySignature(dataCentralDir, goodObject);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodObject);
+ PKIX_TEST_DECREF_AC(equalObject);
+ PKIX_TEST_DECREF_AC(diffObject);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CRL");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_crlentry.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_crlentry.c
new file mode 100644
index 0000000000..30a008b4cf
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_crlentry.c
@@ -0,0 +1,208 @@
+/* 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_crlentry.c
+ *
+ * Test CRLENTRY Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createCRLEntries(
+ char *dataDir,
+ char *crlInput,
+ PKIX_PL_CRL **pCrl,
+ PKIX_PL_CRLEntry **goodObject,
+ PKIX_PL_CRLEntry **equalObject,
+ PKIX_PL_CRLEntry **diffObject)
+{
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_PL_BigInt *firstSNBigInt = NULL;
+ PKIX_PL_BigInt *secondSNBigInt = NULL;
+ PKIX_PL_String *firstSNString = NULL;
+ PKIX_PL_String *secondSNString = NULL;
+ char *firstSNAscii = "010932";
+ char *secondSNAscii = "3039";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CRL_Create <crl>");
+ crl = createCRL(dataDir, crlInput, plContext);
+
+ subTest("PKIX_PL_CRL_GetCRLEntryForSerialNumber");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ firstSNAscii,
+ PL_strlen(firstSNAscii),
+ &firstSNString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(
+ firstSNString,
+ &firstSNBigInt,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetCRLEntryForSerialNumber(
+ crl, firstSNBigInt, goodObject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetCRLEntryForSerialNumber(
+ crl, firstSNBigInt, equalObject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ secondSNAscii,
+ PL_strlen(secondSNAscii),
+ &secondSNString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(
+ secondSNString,
+ &secondSNBigInt,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRL_GetCRLEntryForSerialNumber(
+ crl, secondSNBigInt, diffObject, plContext));
+
+ *pCrl = crl;
+
+cleanup:
+ PKIX_TEST_DECREF_AC(firstSNBigInt);
+ PKIX_TEST_DECREF_AC(secondSNBigInt);
+ PKIX_TEST_DECREF_AC(firstSNString);
+ PKIX_TEST_DECREF_AC(secondSNString);
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetReasonCode(
+ PKIX_PL_CRLEntry *goodObject)
+{
+ PKIX_Int32 reasonCode = 0;
+ PKIX_Int32 expectedReasonCode = 260;
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CRLEntry_GetCRLEntryReasonCode");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRLEntry_GetCRLEntryReasonCode(
+ goodObject, &reasonCode, plContext));
+
+ if (reasonCode != expectedReasonCode) {
+ testError("unexpected value of CRL Entry Reason Code");
+ (void)printf("Actual value:\t%d\n", reasonCode);
+ (void)printf("Expected value:\t%d\n", expectedReasonCode);
+ goto cleanup;
+ }
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCritExtensionsAbsent(PKIX_PL_CRLEntry *crlEntry)
+{
+ PKIX_List *oidList = NULL;
+ PKIX_UInt32 numOids = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs(crlEntry, &oidList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(oidList, &numOids, plContext));
+ if (numOids != 0) {
+ pkixTestErrorMsg = "unexpected mismatch";
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(oidList);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetCriticalExtensionOIDs(PKIX_PL_CRLEntry *goodObject)
+{
+ subTest("PKIX_PL_CRL_GetCriticalExtensionOIDs "
+ "<CritExtensionsAbsent>");
+ testCritExtensionsAbsent(goodObject);
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_crlentry <data-dir>\n\n");
+}
+
+/* Functional tests for CRLENTRY public functions */
+
+int
+test_crlentry(int argc, char *argv[])
+{
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_PL_CRLEntry *goodObject = NULL;
+ PKIX_PL_CRLEntry *equalObject = NULL;
+ PKIX_PL_CRLEntry *diffObject = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *dataDir = NULL;
+ char *goodInput = "crlgood.crl";
+ char *expectedAscii =
+ "\n\t[\n"
+ "\tSerialNumber: 010932\n"
+ "\tReasonCode: 260\n"
+ "\tRevocationDate: Fri Jan 07 15:09:10 2005\n"
+ "\tCritExtOIDs: (EMPTY)\n"
+ "\t]\n\t";
+
+ /* Note XXX serialnumber and reasoncode need debug */
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("CRLEntry");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 1 + j) {
+ printUsage();
+ return (0);
+ }
+
+ dataDir = argv[1 + j];
+
+ createCRLEntries(dataDir, goodInput, &crl, &goodObject, &equalObject, &diffObject);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ NULL, /* expectedAscii, */
+ CRLENTRY,
+ PKIX_TRUE);
+
+ testGetReasonCode(goodObject);
+
+ testGetCriticalExtensionOIDs(goodObject);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(crl);
+ PKIX_TEST_DECREF_AC(goodObject);
+ PKIX_TEST_DECREF_AC(equalObject);
+ PKIX_TEST_DECREF_AC(diffObject);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("CRLEntry");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_date.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_date.c
new file mode 100644
index 0000000000..4fb3718c19
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_date.c
@@ -0,0 +1,106 @@
+/* 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_date.c
+ *
+ * Test Date Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createDates(char *goodInput, char *diffInput,
+ PKIX_PL_Date **goodDate,
+ PKIX_PL_Date **equalDate,
+ PKIX_PL_Date **diffDate)
+{
+
+ subTest("PKIX_PL_Date_Create <goodDate>");
+ *goodDate = createDate(goodInput, plContext);
+
+ subTest("PKIX_PL_Date_Create <equalDate>");
+ *equalDate = createDate(goodInput, plContext);
+
+ subTest("PKIX_PL_Date_Create <diffDate>");
+ *diffDate = createDate(diffInput, plContext);
+}
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_Date_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDate(char *goodInput, char *diffInput)
+{
+
+ PKIX_PL_Date *goodDate = NULL;
+ PKIX_PL_Date *equalDate = NULL;
+ PKIX_PL_Date *diffDate = NULL;
+
+ /*
+ * The ASCII rep of the date will vary by platform and locale
+ * This particular string was generated on a SPARC running Solaris 9
+ * in an English locale
+ */
+ /* char *expectedAscii = "Mon Mar 29 08:48:47 2004"; */
+ char *expectedAscii = "Mon Mar 29, 2004";
+
+ PKIX_TEST_STD_VARS();
+
+ createDates(goodInput, diffInput,
+ &goodDate, &equalDate, &diffDate);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodDate, equalDate, diffDate, expectedAscii, Date, PKIX_TRUE);
+
+ testDestroy(goodDate, equalDate, diffDate);
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_date(int argc, char *argv[])
+{
+
+ char *goodInput = NULL;
+ char *diffInput = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Date");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ goodInput = "040329134847Z";
+ diffInput = "050329135847Z";
+ testDate(goodInput, diffInput);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Date");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_generalname.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_generalname.c
new file mode 100644
index 0000000000..88181e3f20
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_generalname.c
@@ -0,0 +1,123 @@
+/* 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_generalname.c
+ *
+ * Test GeneralName Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createGeneralNames(PKIX_UInt32 nameType, char *goodInput, char *diffInput,
+ PKIX_PL_GeneralName **goodName,
+ PKIX_PL_GeneralName **equalName,
+ PKIX_PL_GeneralName **diffName)
+{
+
+ subTest("PKIX_PL_GeneralName_Create <goodName>");
+ *goodName = createGeneralName(nameType, goodInput, plContext);
+
+ subTest("PKIX_PL_GeneralName_Create <equalName>");
+ *equalName = createGeneralName(nameType, goodInput, plContext);
+
+ subTest("PKIX_PL_GeneralName_Create <diffName>");
+ *diffName = createGeneralName(nameType, diffInput, plContext);
+}
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_GeneralName_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testNameType(PKIX_UInt32 nameType, char *goodInput, char *diffInput, char *expectedAscii)
+{
+
+ PKIX_PL_GeneralName *goodName = NULL;
+ PKIX_PL_GeneralName *equalName = NULL;
+ PKIX_PL_GeneralName *diffName = NULL;
+
+ createGeneralNames(nameType, goodInput, diffInput,
+ &goodName, &equalName, &diffName);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodName,
+ equalName,
+ diffName,
+ expectedAscii,
+ GeneralName,
+ PKIX_TRUE);
+
+ testDestroy(goodName, equalName, diffName);
+}
+
+int
+test_generalname(int argc, char *argv[])
+{
+
+ char *goodInput = NULL;
+ char *diffInput = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("GeneralName");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ goodInput = "john@sun.com";
+ diffInput = "john@labs.com";
+ testNameType(PKIX_RFC822_NAME, goodInput, diffInput, goodInput);
+
+ goodInput = "example1.com";
+ diffInput = "ex2.net";
+ testNameType(PKIX_DNS_NAME, goodInput, diffInput, goodInput);
+
+ goodInput = "cn=yassir, ou=labs, o=sun, c=us";
+ diffInput = "cn=alice, ou=labs, o=sun, c=us";
+ testNameType(PKIX_DIRECTORY_NAME,
+ goodInput,
+ diffInput,
+ "CN=yassir,OU=labs,O=sun,C=us");
+
+ goodInput = "http://example1.com";
+ diffInput = "http://ex2.net";
+ testNameType(PKIX_URI_NAME, goodInput, diffInput, goodInput);
+
+ goodInput = "1.2.840.11";
+ diffInput = "1.2.840.115349";
+ testNameType(PKIX_OID_NAME, goodInput, diffInput, goodInput);
+
+ /*
+ * We don't support creating PKIX_EDIPARTY_NAME,
+ * PKIX_IP_NAME, OTHER_NAME, X400_ADDRESS from strings
+ */
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("GeneralName");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_nameconstraints.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_nameconstraints.c
new file mode 100644
index 0000000000..636ba3ead3
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_nameconstraints.c
@@ -0,0 +1,127 @@
+/* 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_nameconstraints.c
+ *
+ * Test CERT Name Constraints Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+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
+testNameConstraints(char *dataDir)
+{
+ char *goodPname = "nameConstraintsDN5CACert.crt";
+ PKIX_PL_Cert *goodCert = NULL;
+ PKIX_PL_CertNameConstraints *goodNC = NULL;
+ char *expectedAscii =
+ "[\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";
+
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_CertNameConstraints");
+
+ goodCert = createCert(dataDir, goodPname, plContext);
+
+ subTest("PKIX_PL_Cert_GetNameConstraints");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(goodCert, &goodNC, plContext));
+
+ testToStringHelper((PKIX_PL_Object *)goodNC, expectedAscii, plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(goodNC);
+ PKIX_TEST_DECREF_AC(goodCert);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\ttest_nameconstraints <test-purpose>"
+ " <data-dir> <platform-prefix>\n\n");
+}
+
+/* Functional tests for CRL public functions */
+
+int
+test_nameconstraints(int argc, char *argv[])
+{
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ char *platformDir = NULL;
+ char *dataDir = NULL;
+ char *combinedDir = NULL;
+
+ /* Note XXX serialnumber and reasoncode need debug */
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("NameConstraints");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 3 + j) {
+ printUsage();
+ return (0);
+ }
+
+ dataDir = argv[2 + j];
+ platformDir = argv[3 + j];
+ combinedDir = catDirName(platformDir, dataDir, plContext);
+
+ testNameConstraints(combinedDir);
+
+cleanup:
+
+ pkixTestErrorResult = PKIX_PL_Free(combinedDir, plContext);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("NameConstraints");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_subjectinfoaccess.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_subjectinfoaccess.c
new file mode 100644
index 0000000000..8f2ff9ec7e
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_subjectinfoaccess.c
@@ -0,0 +1,121 @@
+/* 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_subjectinfoaccess.c
+ *
+ * Test Subject InfoAccess Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+int
+test_subjectinfoaccess(int argc, char *argv[])
+{
+
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_Cert *certDiff = NULL;
+ PKIX_List *aiaList = NULL;
+ PKIX_List *siaList = NULL;
+ PKIX_PL_InfoAccess *sia = NULL;
+ PKIX_PL_InfoAccess *siaDup = NULL;
+ PKIX_PL_InfoAccess *siaDiff = NULL;
+ PKIX_PL_GeneralName *location = NULL;
+ char *certPathName = NULL;
+ char *dirName = NULL;
+ PKIX_UInt32 method = 0;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 size, i;
+ PKIX_UInt32 j = 0;
+ char *expectedAscii = "[method:caRepository, "
+ "location:http://betty.nist.gov/pathdiscoverytestsuite/"
+ "p7cfiles/IssuedByTrustAnchor1.p7c]";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("SubjectInfoAccess");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ if (argc < 5 + j) {
+ printf("Usage: %s <test-purpose> <cert> <diff-cert>\n", argv[0]);
+ }
+
+ dirName = argv[2 + j];
+ certPathName = argv[3 + j];
+
+ subTest("Creating Cert with Subject Info Access");
+ cert = createCert(dirName, certPathName, plContext);
+
+ certPathName = argv[4 + j];
+
+ subTest("Creating Cert with Subject Info Access");
+ certDiff = createCert(dirName, certPathName, plContext);
+
+ subTest("Getting Subject Info Access");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectInfoAccess(cert, &siaList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(siaList, &size, plContext));
+
+ if (size != 1) {
+ pkixTestErrorMsg = "unexpected number of AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(siaList, 0, (PKIX_PL_Object **)&sia, plContext));
+
+ subTest("PKIX_PL_InfoAccess_GetMethod");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_InfoAccess_GetMethod(sia, &method, plContext));
+ if (method != PKIX_INFOACCESS_CA_REPOSITORY) {
+ pkixTestErrorMsg = "unexpected method of AIA";
+ goto cleanup;
+ }
+
+ subTest("PKIX_PL_InfoAccess_GetLocation");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_InfoAccess_GetLocation(sia, &location, plContext));
+ if (!location) {
+ pkixTestErrorMsg = "Cannot get AIA location";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(siaList, 0, (PKIX_PL_Object **)&siaDup, plContext));
+
+ subTest("Getting Authority Info Access as difference comparison");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetAuthorityInfoAccess(certDiff, &aiaList, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(aiaList, &size, plContext));
+
+ if (size != 1) {
+ pkixTestErrorMsg = "unexpected number of AIA";
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(aiaList, 0, (PKIX_PL_Object **)&siaDiff, plContext));
+
+ subTest("Checking: Equal, Hash and ToString");
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(sia, siaDup, siaDiff, expectedAscii, InfoAccess, PKIX_FALSE);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(location);
+ PKIX_TEST_DECREF_AC(sia);
+ PKIX_TEST_DECREF_AC(siaDup);
+ PKIX_TEST_DECREF_AC(siaDiff);
+ PKIX_TEST_DECREF_AC(aiaList);
+ PKIX_TEST_DECREF_AC(siaList);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(certDiff);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Subjectinfoaccess");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/pki/test_x500name.c b/security/nss/cmd/libpkix/pkix_pl/pki/test_x500name.c
new file mode 100644
index 0000000000..91ff63fd0a
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/pki/test_x500name.c
@@ -0,0 +1,169 @@
+/* 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_x500name.c
+ *
+ * Test X500Name Type
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static PKIX_PL_X500Name *
+createX500Name(char *asciiName, PKIX_Boolean expectedToPass)
+{
+
+ PKIX_PL_X500Name *x500Name = NULL;
+ PKIX_PL_String *plString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, asciiName, 0, &plString, plContext));
+
+ if (expectedToPass) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(plString, &x500Name, plContext));
+ } else {
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_X500Name_Create(plString, &x500Name, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(plString);
+
+ PKIX_TEST_RETURN();
+
+ return (x500Name);
+}
+
+static void
+createX500Names(char *goodInput, char *diffInput, char *diffInputMatch,
+ PKIX_PL_X500Name **goodObject,
+ PKIX_PL_X500Name **equalObject,
+ PKIX_PL_X500Name **diffObject,
+ PKIX_PL_X500Name **diffObjectMatch)
+{
+ char *badAscii = "cn=yas#sir,ou=labs,o=sun,c=us";
+ PKIX_PL_X500Name *badObject = NULL;
+
+ subTest("PKIX_PL_X500Name_Create <goodObject>");
+ *goodObject = createX500Name(goodInput, PKIX_TRUE);
+
+ subTest("PKIX_PL_X500Name_Create <equalObject>");
+ *equalObject = createX500Name(goodInput, PKIX_TRUE);
+
+ subTest("PKIX_PL_X500Name_Create <diffObject>");
+ *diffObject = createX500Name(diffInput, PKIX_TRUE);
+
+ subTest("PKIX_PL_X500Name_Create <diffObjectMatch>");
+ *diffObjectMatch = createX500Name(diffInputMatch, PKIX_TRUE);
+
+ subTest("PKIX_PL_X500Name_Create <negative>");
+ badObject = createX500Name(badAscii, PKIX_FALSE);
+}
+
+static void
+testMatchHelper(PKIX_PL_X500Name *goodName, PKIX_PL_X500Name *otherName, PKIX_Boolean match)
+{
+ PKIX_Boolean cmpResult;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Match(goodName,
+ otherName,
+ &cmpResult,
+ plContext));
+
+ if ((match && !cmpResult) || (!match && cmpResult)) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", cmpResult);
+ (void)printf("Expected value:\t%d\n", match);
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testMatch(void *goodObject, void *diffObject, void *diffObjectMatch)
+{
+ subTest("PKIX_PL_X500Name_Match <match>");
+ testMatchHelper((PKIX_PL_X500Name *)diffObject,
+ (PKIX_PL_X500Name *)diffObjectMatch,
+ PKIX_TRUE);
+
+ subTest("PKIX_PL_X500Name_Match <non-match>");
+ testMatchHelper((PKIX_PL_X500Name *)goodObject,
+ (PKIX_PL_X500Name *)diffObject,
+ PKIX_FALSE);
+}
+
+static void
+testDestroy(void *goodObject, void *equalObject, void *diffObject, void *diffObjectMatch)
+{
+ PKIX_TEST_STD_VARS();
+
+ subTest("PKIX_PL_X500Name_Destroy");
+
+ PKIX_TEST_DECREF_BC(goodObject);
+ PKIX_TEST_DECREF_BC(equalObject);
+ PKIX_TEST_DECREF_BC(diffObject);
+ PKIX_TEST_DECREF_BC(diffObjectMatch);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_x500name(int argc, char *argv[])
+{
+
+ PKIX_PL_X500Name *goodObject = NULL;
+ PKIX_PL_X500Name *equalObject = NULL;
+ PKIX_PL_X500Name *diffObject = NULL;
+ PKIX_PL_X500Name *diffObjectMatch = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ /* goodInput is encoded in PKIX_ESCASCII */
+ char *goodInput = "cn=Strau&#x00Df;,ou=labs,o=sun,c=us";
+ char *diffInput = "cn=steve,ou=labs,o=sun,c=us";
+ char *diffInputMatch = "Cn=SteVe,Ou=lABs,o=SUn,c=uS";
+ char *expectedAscii = "CN=Strau&#x00DF;,OU=labs,O=sun,C=us";
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("X500Name");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ createX500Names(goodInput, diffInput, diffInputMatch,
+ &goodObject, &equalObject, &diffObject, &diffObjectMatch);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObject,
+ equalObject,
+ diffObject,
+ expectedAscii,
+ X500Name,
+ PKIX_TRUE);
+
+ testMatch(goodObject, diffObject, diffObjectMatch);
+
+ testDestroy(goodObject, equalObject, diffObject, diffObjectMatch);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("X500Name");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/Makefile b/security/nss/cmd/libpkix/pkix_pl/system/Makefile
new file mode 100644
index 0000000000..802e7729d9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/Makefile
@@ -0,0 +1,45 @@
+#! 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/security/nss/cmd/libpkix/pkix_pl/system/manifest.mn b/security/nss/cmd/libpkix/pkix_pl/system/manifest.mn
new file mode 100644
index 0000000000..52bb34ece0
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/manifest.mn
@@ -0,0 +1,38 @@
+#
+# 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
+
+# test_rwlock.c is taken out, need to link to libpkix internals
+#
+# The test is using LIBPKIX PL call directly, which violates our
+# code convention.
+#
+CSRCS = test_bigint.c \
+ test_bytearray.c \
+ test_hashtable.c \
+ test_mem.c \
+ test_mutex.c \
+ test_mutex2.c \
+ test_mutex3.c \
+ test_monitorlock.c \
+ test_object.c \
+ test_oid.c \
+ stress_test.c \
+ test_string.c \
+ test_string2.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtoolsys
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/stress_test.c b/security/nss/cmd/libpkix/pkix_pl/system/stress_test.c
new file mode 100644
index 0000000000..839dc068d1
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/stress_test.c
@@ -0,0 +1,146 @@
+/* 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/. */
+/*
+ * stress_test.c
+ *
+ * Creates and deletes many objects
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+int
+stress_test(int argc, char *argv[])
+{
+
+ PKIX_UInt32 i, k, length, hashcode;
+ PKIX_UInt32 size = 17576;
+ char temp[4];
+ PKIX_Boolean result;
+ PKIX_PL_String *strings[17576], *tempString;
+ PKIX_PL_String *utf16strings[17576];
+ PKIX_PL_ByteArray *byteArrays[17576];
+ void *dest;
+ PKIX_PL_HashTable *ht = NULL;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Stress Test");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ /* ---------------------------- */
+ subTest("Create every three letter String");
+
+ for (i = 0; i < 26; i++)
+ for (j = 0; j < 26; j++)
+ for (k = 0; k < 26; k++) {
+ temp[0] = (char)('a' + i);
+ temp[1] = (char)('a' + j);
+ temp[2] = (char)('a' + k);
+ temp[3] = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, temp, 3,
+ &strings[26 * (i * 26 + j) + k],
+ plContext));
+ }
+
+ /* ---------------------------- */
+ subTest("Create a bytearray from each string's UTF-16 encoding");
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(strings[i],
+ PKIX_UTF16,
+ &dest,
+ &length,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create(dest, length, &byteArrays[i], plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ }
+
+ /* ---------------------------- */
+ subTest("Create a copy string from each bytearray");
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_UTF16, *(void **)byteArrays[i], 6,
+ &utf16strings[i], plContext));
+ }
+
+ /* ---------------------------- */
+ subTest("Compare each original string with the copy");
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)strings[i],
+ (PKIX_PL_Object *)utf16strings[i],
+ &result,
+ plContext));
+ if (result == 0)
+ testError("Strings do not match");
+ }
+
+ /* ---------------------------- */
+ subTest("Put each string into a Hashtable");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Create(size /
+ 2,
+ 0, &ht, plContext));
+
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Hashcode((PKIX_PL_Object *)strings[i],
+ &hashcode,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (void *)&hashcode,
+ (void *)strings[i],
+ plContext));
+ }
+
+ /* ---------------------------- */
+ subTest("Compare each copy string with the hashtable entries ");
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Hashcode((PKIX_PL_Object *)utf16strings[i],
+ &hashcode,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (void *)&hashcode,
+ (PKIX_PL_Object **)&tempString,
+ plContext));
+
+ if (tempString == NULL)
+ testError("String not found in hashtable");
+ else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)tempString,
+ (PKIX_PL_Object *)utf16strings[i],
+ &result,
+ plContext));
+ if (result == 0)
+ testError("Strings do not match");
+ PKIX_TEST_DECREF_BC(tempString);
+ }
+ }
+
+cleanup:
+
+ /* ---------------------------- */
+ subTest("Destroy All Objects");
+
+ PKIX_TEST_DECREF_AC(ht);
+
+ for (i = 0; i < size; i++) {
+ PKIX_TEST_DECREF_AC(strings[i]);
+ PKIX_TEST_DECREF_AC(utf16strings[i]);
+ PKIX_TEST_DECREF_AC(byteArrays[i]);
+ }
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Stress Test");
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_bigint.c b/security/nss/cmd/libpkix/pkix_pl/system/test_bigint.c
new file mode 100644
index 0000000000..281e373790
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_bigint.c
@@ -0,0 +1,189 @@
+/* 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_bigint.c
+ *
+ * Tests BigInt Types
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createBigInt(
+ PKIX_PL_BigInt **bigInts,
+ char *bigIntAscii,
+ PKIX_Boolean errorHandling)
+{
+ PKIX_PL_String *bigIntString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ bigIntAscii,
+ PL_strlen(bigIntAscii),
+ &bigIntString,
+ plContext));
+
+ if (errorHandling) {
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_BigInt_Create(bigIntString,
+ bigInts,
+ plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(bigIntString,
+ bigInts,
+ plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(bigIntString);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testToString(
+ PKIX_PL_BigInt *bigInt,
+ char *expAscii)
+{
+ PKIX_PL_String *bigIntString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)bigInt,
+ &bigIntString, plContext));
+
+ temp = PKIX_String2ASCII(bigIntString, plContext);
+ if (temp == plContext) {
+ testError("PKIX_String2Ascii failed");
+ goto cleanup;
+ }
+
+ if (PL_strcmp(temp, expAscii) != 0) {
+ (void)printf("\tBigInt ToString: %s %s\n", temp, expAscii);
+ testError("Output string does not match source");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(bigIntString);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCompare(
+ PKIX_PL_BigInt *firstBigInt,
+ PKIX_PL_BigInt *secondBigInt,
+ PKIX_Int32 *cmpResult)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)firstBigInt,
+ (PKIX_PL_Object *)secondBigInt,
+ cmpResult, plContext));
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_BigInt *bigInt)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(bigInt);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_bigint(int argc, char *argv[])
+{
+
+ PKIX_UInt32 size = 4, badSize = 3, i = 0;
+ PKIX_PL_BigInt *testBigInt[4] = { NULL };
+ PKIX_Int32 cmpResult;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *bigIntValue[4] = {
+ "03",
+ "ff",
+ "1010101010101010101010101010101010101010",
+ "1010101010101010101010101010101010101010",
+ };
+
+ char *badValue[3] = { "00ff", "fff", "-ff" };
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("BigInts");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ for (i = 0; i < badSize; i++) {
+ subTest("PKIX_PL_BigInt_Create <error_handling>");
+ createBigInt(&testBigInt[i], badValue[i], PKIX_TRUE);
+ }
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_BigInt_Create");
+ createBigInt(&testBigInt[i], bigIntValue[i], PKIX_FALSE);
+ }
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(testBigInt[2],
+ testBigInt[3],
+ testBigInt[1],
+ bigIntValue[2],
+ BigInt,
+ PKIX_TRUE);
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_BigInt_ToString");
+ testToString(testBigInt[i], bigIntValue[i]);
+ }
+
+ subTest("PKIX_PL_BigInt_Compare <gt>");
+ testCompare(testBigInt[2], testBigInt[1], &cmpResult);
+ if (cmpResult <= 0) {
+ testError("Invalid Result from String Compare");
+ }
+
+ subTest("PKIX_PL_BigInt_Compare <lt>");
+ testCompare(testBigInt[1], testBigInt[2], &cmpResult);
+ if (cmpResult >= 0) {
+ testError("Invalid Result from String Compare");
+ }
+
+ subTest("PKIX_PL_BigInt_Compare <eq>");
+ testCompare(testBigInt[2], testBigInt[3], &cmpResult);
+ if (cmpResult != 0) {
+ testError("Invalid Result from String Compare");
+ }
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_BigInt_Destroy");
+ testDestroy(testBigInt[i]);
+ }
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BigInt");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_bytearray.c b/security/nss/cmd/libpkix/pkix_pl/system/test_bytearray.c
new file mode 100644
index 0000000000..402685b59d
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_bytearray.c
@@ -0,0 +1,231 @@
+/* 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_bytearray.c
+ *
+ * Tests ByteArray types.
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createByteArray(
+ PKIX_PL_ByteArray **byteArray,
+ char *bytes,
+ PKIX_UInt32 length)
+{
+ PKIX_TEST_STD_VARS();
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create((void *)bytes,
+ length,
+ byteArray,
+ plContext));
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testZeroLength(void)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ void *array = NULL;
+ PKIX_UInt32 length = 2;
+
+ PKIX_TEST_STD_VARS();
+
+ createByteArray(&byteArray, NULL, 0);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_GetLength(byteArray, &length, plContext));
+ if (length != 0) {
+ testError("Length should be zero");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_GetPointer(byteArray, &array, plContext));
+ if (array) {
+ testError("Array should be NULL");
+ }
+
+ testToStringHelper((PKIX_PL_Object *)byteArray, "[]", plContext);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testToString(
+ PKIX_PL_ByteArray *byteArray,
+ char *expAscii)
+{
+ PKIX_PL_String *string = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)byteArray,
+ &string, plContext));
+
+ temp = PKIX_String2ASCII(string, plContext);
+ if (temp == NULL) {
+ testError("PKIX_String2Ascii failed");
+ goto cleanup;
+ }
+
+ if (PL_strcmp(temp, expAscii) != 0) {
+ (void)printf("\tByteArray ToString: %s %s\n", temp, expAscii);
+ testError("Output string does not match source");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(string);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetLength(
+ PKIX_PL_ByteArray *byteArray,
+ PKIX_UInt32 expLength)
+{
+ PKIX_UInt32 arrayLength;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_GetLength(byteArray, &arrayLength, plContext));
+
+ if (arrayLength != expLength) {
+ (void)printf("\tByteArray GetLength: %d %d\n",
+ arrayLength, expLength);
+ testError("Incorrect Array Length returned");
+ }
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetPointer(
+ PKIX_PL_ByteArray *byteArray,
+ char *expBytes,
+ PKIX_UInt32 arrayLength)
+{
+ char *temp = NULL;
+ PKIX_UInt32 j;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_GetPointer(byteArray, (void **)&temp, plContext));
+
+ for (j = 0; j < arrayLength; j++) {
+ if (temp[j] != expBytes[j]) {
+ testError("Incorrect Byte Array Contents");
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ PKIX_TEST_RETURN();
+}
+
+void
+testDestroy(
+ PKIX_PL_ByteArray *byteArray)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(byteArray);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_bytearray(int argc, char *argv[])
+{
+
+ PKIX_PL_ByteArray *testByteArray[4];
+
+ PKIX_UInt32 i, size = 4;
+ PKIX_UInt32 lengths[4] = { 5, 6, 1, 5 };
+ char dArray0[5] = { 1, 2, 3, 4, 5 };
+ unsigned char dArray1[6] = { 127, 128, 129, 254, 255, 0 };
+ char dArray2[1] = { 100 };
+ char dArray3[5] = { 1, 2, 3, 4, 5 };
+
+ char *expected[4] = {
+ "[001, 002, 003, 004, 005]",
+ "[127, 128, 129, 254, 255, 000]",
+ "[100]",
+ "[001, 002, 003, 004, 005]"
+ };
+
+ char *dummyArray[4];
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ dummyArray[0] = dArray0;
+ dummyArray[1] = (char *)dArray1;
+ dummyArray[2] = dArray2;
+ dummyArray[3] = dArray3;
+
+ startTests("ByteArrays");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_ByteArray_Create <zero length>");
+ testZeroLength();
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_ByteArray_Create");
+ createByteArray(&testByteArray[i], dummyArray[i], lengths[i]);
+ }
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(testByteArray[0],
+ testByteArray[3],
+ testByteArray[1],
+ "[001, 002, 003, 004, 005]",
+ ByteArray,
+ PKIX_TRUE);
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_ByteArray_ToString");
+ testToString(testByteArray[i], expected[i]);
+ }
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_ByteArray_GetLength");
+ testGetLength(testByteArray[i], lengths[i]);
+ }
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_ByteArray_GetPointer");
+ testGetPointer(testByteArray[i], dummyArray[i], lengths[i]);
+ }
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_ByteArray_Destroy");
+ testDestroy(testByteArray[i]);
+ }
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("ByteArray");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_hashtable.c b/security/nss/cmd/libpkix/pkix_pl/system/test_hashtable.c
new file mode 100644
index 0000000000..663bfc9fac
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_hashtable.c
@@ -0,0 +1,380 @@
+/* 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_hashtable.c
+ *
+ * Tests Hashtables
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createHashTables(
+ PKIX_PL_HashTable **ht,
+ PKIX_PL_HashTable **ht2,
+ PKIX_PL_HashTable **ht3,
+ PKIX_PL_HashTable **ht4)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Create(1, 0, ht, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Create(5, 0, ht2, plContext));
+
+ /* at most two entries per bucket */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Create(1, 2, ht4, plContext));
+
+ *ht3 = *ht;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)*ht3, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAdd(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_HashTable *ht2,
+ PKIX_PL_String **testString,
+ PKIX_PL_String **testString2,
+ PKIX_PL_String **testString3,
+ PKIX_PL_OID **testOID)
+{
+ char *dummyString = "test string 1";
+ char *dummyString2 = "test string 2";
+ char *dummyString3 = "test string 3";
+ char *dummyOID = "2.11.22222.33333";
+
+ PKIX_TEST_STD_VARS();
+
+ /* Make some dummy objects */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ dummyString,
+ PL_strlen(dummyString),
+ testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ dummyString2,
+ PL_strlen(dummyString2),
+ testString2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ dummyString3,
+ PL_strlen(dummyString3),
+ testString3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(dummyOID, testOID, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testString,
+ (PKIX_PL_Object *)*testString2,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht2,
+ (PKIX_PL_Object *)*testString,
+ (PKIX_PL_Object *)*testString2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testString2,
+ (PKIX_PL_Object *)*testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht2,
+ (PKIX_PL_Object *)*testString2,
+ (PKIX_PL_Object *)*testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testOID,
+ (PKIX_PL_Object *)*testOID,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht2,
+ (PKIX_PL_Object *)*testOID,
+ (PKIX_PL_Object *)*testOID,
+ plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testAddFIFO(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_String **testString,
+ PKIX_PL_String **testString2,
+ PKIX_PL_String **testString3)
+{
+ PKIX_PL_String *targetString = NULL;
+ PKIX_Boolean cmpResult;
+
+ PKIX_TEST_STD_VARS();
+
+ /*
+ * ht is created as one bucket, two entries per bucket. Since we add
+ * three items to the ht, we expect the first one to be deleted.
+ */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testString,
+ (PKIX_PL_Object *)*testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testString2,
+ (PKIX_PL_Object *)*testString2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Add(ht,
+ (PKIX_PL_Object *)*testString3,
+ (PKIX_PL_Object *)*testString3,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (PKIX_PL_Object *)*testString,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+ if (targetString != NULL) {
+ testError("HashTable_Lookup retrieved a supposed deleted item");
+ PKIX_TEST_DECREF_BC(targetString);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (PKIX_PL_Object *)*testString3,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetString,
+ (PKIX_PL_Object *)*testString3,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testLookup(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_HashTable *ht2,
+ PKIX_PL_String *testString,
+ PKIX_PL_String *testString2,
+ PKIX_PL_String *testString3,
+ PKIX_PL_OID *testOID)
+{
+ PKIX_PL_String *targetString = NULL;
+ PKIX_PL_String *targetOID = NULL;
+ PKIX_Boolean cmpResult;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (PKIX_PL_Object *)testString,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetString,
+ (PKIX_PL_Object *)testString2,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht2,
+ (PKIX_PL_Object *)testString,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetString,
+ (PKIX_PL_Object *)testString2,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht2,
+ (PKIX_PL_Object *)testString2,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetString,
+ (PKIX_PL_Object *)testString,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (PKIX_PL_Object *)testOID,
+ (PKIX_PL_Object **)&targetOID,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)targetOID, &targetString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetOID,
+ (PKIX_PL_Object *)testOID,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+ PKIX_TEST_DECREF_BC(targetOID);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht2,
+ (PKIX_PL_Object *)testOID,
+ (PKIX_PL_Object **)&targetOID,
+ plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)targetOID, &targetString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(
+ (PKIX_PL_Object *)targetOID,
+ (PKIX_PL_Object *)testOID,
+ &cmpResult,
+ plContext));
+ if (cmpResult != PKIX_TRUE) {
+ testError("HashTable_Lookup failed");
+ }
+ PKIX_TEST_DECREF_BC(targetString);
+ PKIX_TEST_DECREF_BC(targetOID);
+
+ (void)printf("Looking up item not in HashTable.\n");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Lookup(ht,
+ (PKIX_PL_Object *)testString3,
+ (PKIX_PL_Object **)&targetString,
+ plContext));
+ if (targetString == NULL)
+ (void)printf("\tCorrectly returned NULL.\n");
+ else
+ testError("Hashtable did not return NULL value as expected");
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testRemove(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_HashTable *ht2,
+ PKIX_PL_String *testString,
+ PKIX_PL_String *testString2,
+ PKIX_PL_OID *testOID)
+{
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Remove(ht,
+ (PKIX_PL_Object *)testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Remove(ht,
+ (PKIX_PL_Object *)testOID,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_HashTable_Remove(ht2,
+ (PKIX_PL_Object *)testString2,
+ plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_HashTable_Remove(ht,
+ (PKIX_PL_Object *)testString,
+ plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_HashTable *ht,
+ PKIX_PL_HashTable *ht2,
+ PKIX_PL_HashTable *ht3,
+ PKIX_PL_HashTable *ht4)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(ht);
+ PKIX_TEST_DECREF_BC(ht2);
+ PKIX_TEST_DECREF_BC(ht3);
+ PKIX_TEST_DECREF_BC(ht4);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+int
+test_hashtable(int argc, char *argv[])
+{
+
+ PKIX_PL_HashTable *ht, *ht2, *ht3, *ht4;
+ PKIX_PL_String *testString, *testString2, *testString3;
+ PKIX_PL_OID *testOID;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("HashTables");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_HashTable_Create");
+ createHashTables(&ht, &ht2, &ht3, &ht4);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(ht,
+ ht3,
+ ht2,
+ NULL,
+ HashTable,
+ PKIX_FALSE);
+
+ subTest("PKIX_PL_HashTable_Add");
+ testAdd(ht, ht2, &testString, &testString2, &testString3, &testOID);
+
+ subTest("PKIX_PL_HashTable_ADD - with Bucket Size limit");
+ testAddFIFO(ht4, &testString, &testString2, &testString3);
+
+ subTest("PKIX_PL_HashTable_Lookup");
+ testLookup(ht, ht2, testString, testString2, testString3, testOID);
+
+ subTest("PKIX_PL_HashTable_Remove");
+ testRemove(ht, ht2, testString, testString2, testOID);
+
+ PKIX_TEST_DECREF_BC(testString);
+ PKIX_TEST_DECREF_BC(testString2);
+ PKIX_TEST_DECREF_BC(testString3);
+ PKIX_TEST_DECREF_BC(testOID);
+
+ subTest("PKIX_PL_HashTable_Destroy");
+ testDestroy(ht, ht2, ht3, ht4);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("BigInt");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_mem.c b/security/nss/cmd/libpkix/pkix_pl/system/test_mem.c
new file mode 100644
index 0000000000..3a4e5f7135
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_mem.c
@@ -0,0 +1,133 @@
+/* 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_mem.c
+ *
+ * Tests Malloc, Realloc and Free
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+testMalloc(PKIX_UInt32 **array)
+{
+ PKIX_UInt32 i, arraySize = 10;
+ PKIX_TEST_STD_VARS();
+
+ /* Create an integer array of size 10 */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(
+ (PKIX_UInt32)(arraySize * sizeof(unsigned int)),
+ (void **)array, plContext));
+
+ /* Fill in some values */
+ (void)printf("Setting array[i] = i...\n");
+ for (i = 0; i < arraySize; i++) {
+ (*array)[i] = i;
+ if ((*array)[i] != i)
+ testError("Array has incorrect contents");
+ }
+
+ /* Memory now reflects changes */
+ (void)printf("\tArray: a[0] = %d, a[5] = %d, a[7] = %d.\n",
+ (*array[0]), (*array)[5], (*array)[7]);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testRealloc(PKIX_UInt32 **array)
+{
+ PKIX_UInt32 i, arraySize = 20;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Realloc(*array,
+ (PKIX_UInt32)(arraySize *
+ sizeof(unsigned int)),
+ (void **)array, plContext));
+
+ /* Fill in the new elements */
+ (void)printf("Setting new portion of array to a[i] = i...\n");
+ for (i = arraySize / 2; i < arraySize; i++) {
+ (*array)[i] = i;
+ if ((*array)[i] != i)
+ testError("Array has incorrect contents");
+ }
+
+ /* New elements should be reflected. The old should be the same */
+ (void)printf("\tArray: a[0] = %d, a[15] = %d, a[17] = %d.\n",
+ (*array)[0], (*array)[15], (*array)[17]);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testFree(PKIX_UInt32 *array)
+{
+
+ PKIX_TEST_STD_VARS();
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(array, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+int
+test_mem(int argc, char *argv[])
+{
+
+ unsigned int *array = NULL;
+ int arraySize = 10;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Memory Allocation");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_Malloc");
+ testMalloc(&array);
+
+ subTest("PKIX_PL_Realloc");
+ testRealloc(&array);
+
+ subTest("PKIX_PL_Free");
+ testFree(array);
+
+ /* --Negative Test Cases------------------- */
+ /* Create an integer array of size 10 */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(
+ (PKIX_UInt32)(arraySize * sizeof(unsigned int)),
+ (void **)&array, plContext));
+
+ (void)printf("Attempting to reallocate 0 sized memory...\n");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Realloc(array, 0, (void **)&array, plContext));
+
+ (void)printf("Attempting to allocate to null pointer...\n");
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Malloc(10, NULL, plContext));
+
+ (void)printf("Attempting to reallocate to null pointer...\n");
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Realloc(NULL, 10, NULL, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(array, plContext));
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("Memory Allocation");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_monitorlock.c b/security/nss/cmd/libpkix/pkix_pl/system/test_monitorlock.c
new file mode 100644
index 0000000000..21974258f9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_monitorlock.c
@@ -0,0 +1,104 @@
+/* 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_monitorlock.c
+ *
+ * Tests basic MonitorLock object functionality. No multi-threading.
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createMonitorLockes(
+ PKIX_PL_MonitorLock **monitorLock,
+ PKIX_PL_MonitorLock **monitorLock2,
+ PKIX_PL_MonitorLock **monitorLock3)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Create(monitorLock, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Create(monitorLock2, plContext));
+
+ *monitorLock3 = *monitorLock;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)*monitorLock3, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testLock(PKIX_PL_MonitorLock *monitorLock)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Enter(monitorLock, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Enter(monitorLock, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Exit(monitorLock, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_MonitorLock_Exit(monitorLock, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_MonitorLock *monitorLock,
+ PKIX_PL_MonitorLock *monitorLock2,
+ PKIX_PL_MonitorLock *monitorLock3)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(monitorLock);
+ PKIX_TEST_DECREF_BC(monitorLock2);
+ PKIX_TEST_DECREF_BC(monitorLock3);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+int
+test_monitorlock(int argc, char *argv[])
+{
+
+ PKIX_PL_MonitorLock *monitorLock, *monitorLock2, *monitorLock3;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("MonitorLocks");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_MonitorLock_Create");
+ createMonitorLockes(&monitorLock, &monitorLock2, &monitorLock3);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(monitorLock,
+ monitorLock3,
+ monitorLock2,
+ NULL,
+ MonitorLock,
+ PKIX_FALSE);
+
+ subTest("PKIX_PL_MonitorLock_Lock/Unlock");
+ testLock(monitorLock);
+
+ subTest("PKIX_PL_MonitorLock_Destroy");
+ testDestroy(monitorLock, monitorLock2, monitorLock3);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("MonitorLockes");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_mutex.c b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex.c
new file mode 100644
index 0000000000..bb0e7a0246
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex.c
@@ -0,0 +1,102 @@
+/* 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_mutex.c
+ *
+ * Tests basic mutex object functionality. No multi-threading.
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createMutexes(
+ PKIX_PL_Mutex **mutex,
+ PKIX_PL_Mutex **mutex2,
+ PKIX_PL_Mutex **mutex3)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Create(mutex, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Create(mutex2, plContext));
+
+ *mutex3 = *mutex;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)*mutex3, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testLock(PKIX_PL_Mutex *mutex)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Lock(mutex, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Unlock(mutex, plContext));
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_Mutex *mutex,
+ PKIX_PL_Mutex *mutex2,
+ PKIX_PL_Mutex *mutex3)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(mutex);
+ PKIX_TEST_DECREF_BC(mutex2);
+ PKIX_TEST_DECREF_BC(mutex3);
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+int
+test_mutex(int argc, char *argv[])
+{
+
+ PKIX_PL_Mutex *mutex, *mutex2, *mutex3;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Mutexes");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_Mutex_Create");
+ createMutexes(&mutex, &mutex2, &mutex3);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(mutex,
+ mutex3,
+ mutex2,
+ NULL,
+ Mutex,
+ PKIX_FALSE);
+
+ subTest("PKIX_PL_Mutex_Lock/Unlock");
+ testLock(mutex);
+
+ subTest("PKIX_PL_Mutex_Destroy");
+ testDestroy(mutex, mutex2, mutex3);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Mutexes");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_mutex2.c b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex2.c
new file mode 100644
index 0000000000..197eba2b44
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex2.c
@@ -0,0 +1,166 @@
+/* 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_mutex2.c
+ *
+ * Tests multi-threaded functionality of Mutex
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static int box1 = 0, box2 = 0, box3 = 0;
+static PKIX_PL_Mutex *mutex;
+static PRCondVar *cv;
+static void *plContext = NULL;
+
+static void
+consumer(/* ARGSUSED */ void *arg)
+{
+ PRStatus status = PR_SUCCESS;
+ PKIX_Error *errorResult;
+ int i = 0;
+ for (i = 0; i < 5; i++) {
+ (void)PKIX_PL_Mutex_Lock(mutex, plContext);
+ while (((box1 == 0) ||
+ (box2 == 0) ||
+ (box3 == 0)) &&
+ (status == PR_SUCCESS))
+ status = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
+
+ (void)printf("\tConsumer got Box1 = %d ", box1);
+ box1 = 0;
+ (void)printf("Box2 = %d ", box2);
+ box2 = 0;
+ (void)printf("Box3 = %d\n", box3);
+ box3 = 0;
+
+ status = PR_NotifyAllCondVar(cv);
+ if (status == PR_FAILURE)
+ (void)printf("Consumer error while notifying condvar\n");
+ errorResult = PKIX_PL_Mutex_Unlock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Unlock failed");
+ }
+ (void)printf("Consumer exiting...\n");
+}
+
+static void
+producer(void *arg)
+{
+ PRStatus status = PR_SUCCESS;
+ int value = *(int *)arg;
+ int i = 0;
+ int *box;
+ PKIX_Error *errorResult;
+ if (value == 10)
+ box = &box1;
+ else if (value == 20)
+ box = &box2;
+ else if (value == 30)
+ box = &box3;
+
+ for (i = 0; i < 5; i++) {
+ (void)PKIX_PL_Mutex_Lock(mutex, plContext);
+ while ((*box != 0) && (status == PR_SUCCESS))
+ status = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
+
+ *box = i + 1;
+ (void)printf("\tProducer %d put value: %d\n", value, *box);
+
+ status = PR_NotifyAllCondVar(cv);
+ if (status == PR_FAILURE)
+ (void)printf("Producer %d error while notifying condvar\n",
+ value);
+ errorResult = PKIX_PL_Mutex_Unlock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Unlock failed");
+ }
+}
+
+int
+test_mutex2(int argc, char *argv[])
+{
+
+ PRThread *consThread, *prodThread, *prodThread2, *prodThread3;
+ int x = 10, y = 20, z = 30;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Mutex and Threads");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ (void)printf("Attempting to create new mutex...\n");
+ subTest("Mutex Creation");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Create(&mutex, plContext));
+
+ cv = PR_NewCondVar(*(PRLock **)mutex);
+
+ subTest("Starting consumer thread");
+ consThread = PR_CreateThread(PR_USER_THREAD,
+ consumer,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ subTest("Starting producer thread 1");
+ prodThread = PR_CreateThread(PR_USER_THREAD,
+ producer,
+ &x,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ subTest("Starting producer thread 2");
+ prodThread2 = PR_CreateThread(PR_USER_THREAD,
+ producer,
+ &y,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ subTest("Starting producer thread 3");
+ prodThread3 = PR_CreateThread(PR_USER_THREAD,
+ producer,
+ &z,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ PR_JoinThread(consThread);
+
+ (void)PR_DestroyCondVar(cv);
+ PKIX_TEST_DECREF_BC(mutex);
+
+ /*
+ * Note: we should also be freeing each thread's stack, but we
+ * don't have access to the prodThread->stack variable (since
+ * it is not exported). As a result, we have 120 bytes of memory
+ * leakage.
+ */
+
+ PR_Free(prodThread);
+ PR_Free(prodThread2);
+ PR_Free(prodThread3);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Mutex and Threads");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_mutex3.c b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex3.c
new file mode 100644
index 0000000000..9f42f629b1
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_mutex3.c
@@ -0,0 +1,104 @@
+/* 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_mutex3.c
+ *
+ * Tests multi-threaded functionality of Mutex
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static PKIX_PL_Mutex *mutex;
+static void *plContext = NULL;
+
+static void
+t1(/* ARGSUSED */ void *arg)
+{
+ PKIX_Error *errorResult;
+
+ (void)printf("t1 acquiring lock...\n");
+ errorResult = PKIX_PL_Mutex_Lock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Lock failed");
+
+ (void)printf("t1 sleeplng for 3 seconds\n");
+ PR_Sleep(PR_SecondsToInterval(3));
+ (void)printf("t1 releasing lock...\n");
+
+ errorResult = PKIX_PL_Mutex_Unlock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Unlock failed");
+
+ (void)printf("t1 exiting...\n");
+}
+
+static void
+t2(/* ARGSUSED */ void *arg)
+{
+ PKIX_Error *errorResult;
+
+ (void)printf("t2 acquiring lock...\n");
+ errorResult = PKIX_PL_Mutex_Lock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Lock failed");
+
+ (void)printf("t2 releasing lock...\n");
+ errorResult = PKIX_PL_Mutex_Unlock(mutex, plContext);
+ if (errorResult)
+ testError("PKIX_PL_Mutex_Unlock failed");
+
+ (void)printf("t2 exiting...\n");
+}
+
+int
+test_mutex3(int argc, char *argv[])
+{
+ PRThread *thread, *thread2;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Mutex and Threads");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("Mutex Creation");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Mutex_Create(&mutex, plContext));
+
+ subTest("Starting thread");
+ thread = PR_CreateThread(PR_USER_THREAD,
+ t1,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ thread2 = PR_CreateThread(PR_USER_THREAD,
+ t2,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ PR_JoinThread(thread2);
+ PR_JoinThread(thread);
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(mutex);
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Mutex and Threads");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_object.c b/security/nss/cmd/libpkix/pkix_pl/system/test_object.c
new file mode 100644
index 0000000000..ebb691ba63
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_object.c
@@ -0,0 +1,281 @@
+/* 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_object.c
+ *
+ * Test Object Allocation, toString, Equals, Destruction
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static PKIX_Error *
+destructor(
+ /* ARGSUSED */ PKIX_PL_Object *object,
+ /* ARGSUSED */ void *plContext)
+{
+ (void)printf("\tUser defined destructor called\n");
+ return (NULL);
+}
+
+static PKIX_Error *
+toStringCallback(
+ PKIX_PL_Object *obj,
+ PKIX_PL_String **pString,
+ /* ARGSUSED */ void *plContext)
+{
+
+ PKIX_Error *errorResult;
+ PKIX_UInt32 type;
+ char *format = "(addr: %x, type: %d)";
+ PKIX_PL_String *formatString = NULL;
+
+ errorResult = PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ format,
+ PL_strlen(format),
+ &formatString,
+ plContext);
+ if (errorResult)
+ testError("PKIX_PL_String_Create failed");
+
+ if (pString == plContext)
+ testError("Null String");
+
+ type = (unsigned int)0;
+
+ (void)PKIX_PL_Object_GetType(obj, &type, plContext);
+
+ errorResult = PKIX_PL_Sprintf(pString, plContext,
+ formatString,
+ (int)obj, type);
+ if (errorResult)
+ testError("PKIX_PL_Sprintf failed");
+
+ errorResult = PKIX_PL_Object_DecRef((PKIX_PL_Object *)formatString,
+ plContext);
+ if (errorResult)
+ testError("PKIX_PL_Object_DecRef failed");
+
+ return (NULL);
+}
+
+static PKIX_Error *
+comparator(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Int32 *pValue,
+ /* ARGSUSED */ void *plContext)
+{
+ if (*(char *)first > *(char *)second)
+ *pValue = 1;
+ else if (*(char *)first < *(char *)second)
+ *pValue = -1;
+ else
+ *pValue = 0;
+ return (NULL);
+}
+
+static PKIX_Error *
+hashcodeCallback(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pValue,
+ /* ARGSUSED */ void *plContext)
+{
+ *pValue = 123456789;
+ return (NULL);
+}
+
+static PKIX_Error *
+equalsCallback(
+ PKIX_PL_Object *first,
+ PKIX_PL_Object *second,
+ PKIX_Boolean *result,
+ void *plContext)
+{
+
+ PKIX_UInt32 firstType = 0, secondType = 0;
+
+ if ((first == plContext) || (second == plContext))
+ testError("Null Object");
+
+ (void)PKIX_PL_Object_GetType(first, &firstType, plContext);
+
+ (void)PKIX_PL_Object_GetType(second, &secondType, plContext);
+
+ *result = (firstType == secondType) ? PKIX_TRUE : PKIX_FALSE;
+
+ return (NULL);
+}
+
+static void
+createObjects(
+ PKIX_PL_Object **obj,
+ PKIX_PL_Object **obj2,
+ PKIX_PL_Object **obj3,
+ PKIX_PL_Object **obj4)
+{
+ PKIX_TEST_STD_VARS();
+
+#ifdef PKIX_USER_OBJECT_TYPE
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_RegisterType(1000, /* type */
+ "thousand", /* description */
+ NULL, /* destructor */
+ NULL, /* equals */
+ (PKIX_PL_HashcodeCallback)hashcodeCallback,
+ NULL, /* toString */
+ NULL, /* Comparator */
+ NULL,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Alloc(1000, /* type */
+ 12, /* size */
+ obj,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_RegisterType(2000, /* type */
+ "two thousand" /* description */,
+ (PKIX_PL_DestructorCallback)destructor,
+ (PKIX_PL_EqualsCallback)equalsCallback,
+ NULL, /* hashcode */
+ (PKIX_PL_ToStringCallback)toStringCallback,
+ (PKIX_PL_ComparatorCallback)comparator,
+ NULL,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Alloc(2000, /* type */
+ 1, /* size */
+ obj2,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Alloc(2000, /* type */
+ 1, /* size */
+ obj4,
+ plContext));
+
+ *obj3 = *obj;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef(*obj3, plContext));
+
+cleanup:
+#endif /* PKIX_USER_OBJECT_TYPE */
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetType(
+ PKIX_PL_Object *obj,
+ PKIX_PL_Object *obj2,
+ PKIX_PL_Object *obj3)
+{
+ PKIX_UInt32 testType;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_GetType(obj, &testType, plContext));
+
+ if (testType != 1000)
+ testError("Object 1 returned the wrong type");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_GetType(obj2, &testType, plContext));
+ if (testType != 2000)
+ testError("Object 2 returned the wrong type");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_GetType(obj3, &testType, plContext));
+ if (testType != 1000)
+ testError("Object 3 returned the wrong type");
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCompare(
+ PKIX_PL_Object *obj2,
+ PKIX_PL_Object *obj4)
+{
+ PKIX_Int32 cmpResult;
+ PKIX_TEST_STD_VARS();
+
+ *(char *)obj2 = 0x20;
+ *(char *)obj4 = 0x10;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare(obj2, obj4, &cmpResult, plContext));
+ if (cmpResult <= 0)
+ testError("Invalid Result from Object Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare(obj4, obj2, &cmpResult, plContext));
+ if (cmpResult >= 0)
+ testError("Invalid Result from Object Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare(obj4, obj4, &cmpResult, plContext));
+
+ *(char *)obj2 = 0x10;
+ if (cmpResult != 0)
+ testError("Invalid Result from Object Compare");
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_Object *obj,
+ PKIX_PL_Object *obj2,
+ PKIX_PL_Object *obj3,
+ PKIX_PL_Object *obj4)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(obj);
+ PKIX_TEST_DECREF_BC(obj2);
+ PKIX_TEST_DECREF_BC(obj3);
+ PKIX_TEST_DECREF_BC(obj4);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_object(int argc, char *argv[])
+{
+
+#ifdef PKIX_USER_OBJECT_TYPE
+ PKIX_PL_Object *obj, *obj2, *obj3, *obj4;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Objects");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_Object_Create");
+ createObjects(&obj, &obj2, &obj3, &obj4);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(obj, obj3, obj2, NULL, Object, PKIX_FALSE);
+
+ subTest("PKIX_PL_Object_GetType");
+ testGetType(obj, obj2, obj3);
+
+ subTest("PKIX_PL_Object_Compare");
+ testCompare(obj2, obj4);
+
+ subTest("PKIX_PL_Object_Destroy");
+ testDestroy(obj, obj2, obj3, obj4);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("Objects");
+#endif /* PKIX_USER_OBJECT_TYPE */
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_oid.c b/security/nss/cmd/libpkix/pkix_pl/system/test_oid.c
new file mode 100644
index 0000000000..09cddaeea9
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_oid.c
@@ -0,0 +1,212 @@
+/* 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_oid.c
+ *
+ * Test OID Types
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createOID(
+ PKIX_PL_OID **testOID,
+ char *oidAscii,
+ PKIX_Boolean errorHandling)
+{
+ PKIX_TEST_STD_VARS();
+
+ if (errorHandling) {
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_OID_Create(oidAscii, testOID, plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(oidAscii, testOID, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testToString(
+ PKIX_PL_OID *oid,
+ char *expAscii)
+{
+ PKIX_PL_String *oidString = NULL;
+ char *temp = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)oid,
+ &oidString, plContext));
+
+ temp = PKIX_String2ASCII(oidString, plContext);
+ if (temp == NULL) {
+ testError("PKIX_String2Ascii failed");
+ goto cleanup;
+ }
+
+ if (PL_strcmp(temp, expAscii) != 0) {
+ (void)printf("\tOid ToString: %s %s\n", temp, expAscii);
+ testError("Output string does not match source");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(oidString);
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testCompare(
+ PKIX_PL_OID *oid0,
+ PKIX_PL_OID *oid1,
+ PKIX_PL_OID *oid2,
+ PKIX_PL_OID *oid3)
+{
+ PKIX_Int32 cmpResult;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)oid0,
+ (PKIX_PL_Object *)oid1,
+ &cmpResult, plContext));
+ if (cmpResult <= 0)
+ testError("Invalid Result from OID Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)oid1,
+ (PKIX_PL_Object *)oid0,
+ &cmpResult, plContext));
+ if (cmpResult >= 0)
+ testError("Invalid Result from OID Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)oid1,
+ (PKIX_PL_Object *)oid2,
+ &cmpResult, plContext));
+ if (cmpResult >= 0)
+ testError("Invalid Result from OID Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)oid2,
+ (PKIX_PL_Object *)oid1,
+ &cmpResult, plContext));
+ if (cmpResult <= 0)
+ testError("Invalid Result from OID Compare");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare((PKIX_PL_Object *)oid1,
+ (PKIX_PL_Object *)oid3,
+ &cmpResult, plContext));
+ if (cmpResult != 0)
+ testError("Invalid Result from OID Compare");
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_OID *oid)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(oid);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_oid(int argc, char *argv[])
+{
+
+ PKIX_PL_OID *testOID[6] = { NULL };
+ PKIX_PL_OID *badTestOID = NULL;
+ PKIX_UInt32 i, size = 6;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ char *validOID[6] = {
+ "2.11.22222.33333",
+ "1.2.3.004.5.6.7",
+ "2.11.22222.33333",
+ "1.2.3.4.5.6.7",
+ "1.2.3",
+ "2.39.3"
+ };
+
+ char *expected[6] = {
+ "2.11.22222.33333",
+ "1.2.3.4.5.6.7",
+ "2.11.22222.33333",
+ "1.2.3.4.5.6.7",
+ "1.2.3",
+ "2.39.3"
+ };
+
+ char *badOID[11] = {
+ "1.2.4294967299",
+ "this. is. a. bad. oid",
+ "00a1000.002b",
+ "100.-5.10",
+ "1.2..3",
+ ".1.2.3",
+ "1.2.3.",
+ "00010.1.2.3",
+ "1.000041.2.3",
+ "000000000000000000000000000000000000000010.3.2",
+ "1"
+ };
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("OIDs");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_OID_Create");
+ createOID(&testOID[i], validOID[i], PKIX_FALSE);
+ }
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(testOID[0],
+ testOID[2],
+ testOID[1],
+ NULL,
+ OID,
+ PKIX_FALSE);
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_OID_ToString");
+ testToString(testOID[i], expected[i]);
+ }
+
+ subTest("PKIX_PL_OID_Compare");
+ testCompare(testOID[0], testOID[1], testOID[2], testOID[3]);
+
+ for (i = 0; i < size; i++) {
+ subTest("PKIX_PL_OID_Destroy");
+ testDestroy(testOID[i]);
+ }
+
+ for (i = 0; i < 11; i++) {
+ subTest("PKIX_PL_OID Error Handling");
+ createOID(&badTestOID, badOID[i], PKIX_TRUE);
+ }
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ endTests("OIDs");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_rwlock.c b/security/nss/cmd/libpkix/pkix_pl/system/test_rwlock.c
new file mode 100644
index 0000000000..9c09d6479e
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_rwlock.c
@@ -0,0 +1,204 @@
+/* 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_rwlock.c
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static PKIX_PL_RWLock *rwlock = NULL, *rwlock2 = NULL, *rwlock3 = NULL;
+static PRThread *thread = NULL, *thread2 = NULL, *thread3 = NULL;
+static void *plContext = NULL;
+
+static void
+reader(void)
+{
+ PKIX_Error *errorResult;
+
+ errorResult = PKIX_PL_AcquireReaderLock(rwlock, NULL);
+ if (errorResult)
+ testError("PKIX_PL_AcquireReaderLock failed");
+
+ (void)printf("\t[Thread #1 Read Lock #1.]\n");
+ (void)printf("\t[Thread #1 Sleeplng for 1 seconds.]\n");
+ PR_Sleep(PR_SecondsToInterval(1));
+ PKIX_PL_ReleaseReaderLock(rwlock, NULL);
+ if (errorResult)
+ testError("PKIX_PL_ReleaseReaderLock failed");
+ (void)printf("\t[Thread #1 Read UNLock #1.]\n");
+}
+
+static void
+writer(void)
+{
+ PKIX_Error *errorResult;
+ /* This thread should stick here until lock 1 is released */
+ PKIX_PL_AcquireWriterLock(rwlock, NULL);
+ if (errorResult)
+ testError("PKIX_PL_AcquireWriterLock failed");
+
+ (void)printf("\t[Thread #2 Write Lock #1.]\n");
+
+ PKIX_PL_AcquireWriterLock(rwlock2, NULL);
+ if (errorResult)
+ testError("PKIX_PL_AcquireWriterLock failed");
+ (void)printf("\t[Thread #2 Write Lock #2.]\n");
+
+ (void)printf("\t[Thread #2 Sleeplng for 1 seconds.]\n");
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ PKIX_PL_ReleaseWriterLock(rwlock2, NULL);
+ if (errorResult)
+ testError("PKIX_PL_ReleaseWriterLock failed");
+ (void)printf("\t[Thread #2 Write UNLock #2.]\n");
+
+ (void)printf("\t[Thread #2 Sleeplng for 1 seconds.]\n");
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ PKIX_PL_ReleaseWriterLock(rwlock, NULL);
+ if (errorResult)
+ testError("PKIX_PL_ReleaseWriterLock failed");
+ (void)printf("\t[Thread #2 Write UNLock #1.]\n");
+
+ PR_JoinThread(thread3);
+}
+
+static void
+reader2(void)
+{
+ PKIX_Error *errorResult;
+ /* Reader 2 should yield here until the writer is done */
+
+ PKIX_PL_AcquireReaderLock(rwlock2, NULL);
+ if (errorResult)
+ testError("PKIX_PL_AcquireReaderLock failed");
+
+ (void)printf("\t[Thread #3 Read Lock #2.]\n");
+
+ PKIX_PL_AcquireReaderLock(rwlock3, NULL);
+ if (errorResult)
+ testError("PKIX_PL_AcquireReaderLock failed");
+ (void)printf("\t[Thread #3 Read Lock #3.]\n");
+
+ (void)printf("\t[Thread #3 Sleeplng for 1 seconds.]\n");
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ PKIX_PL_ReleaseReaderLock(rwlock3, NULL);
+ if (errorResult)
+ testError("PKIX_PL_ReleaseReaderLock failed");
+ (void)printf("\t[Thread #3 Read UNLock #3.]\n");
+
+ (void)printf("\t[Thread #3 Sleeplng for 1 seconds.]\n");
+ PR_Sleep(PR_SecondsToInterval(1));
+
+ PKIX_PL_ReleaseReaderLock(rwlock2, NULL);
+ if (errorResult)
+ testError("PKIX_PL_ReleaseReaderLock failed");
+ (void)printf("\t[Thread #3 Read UNLock #2.]\n");
+}
+
+int
+test_rwlock()
+{
+ PKIX_PL_String *outputString = NULL;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean bool;
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_TEST_STD_VARS();
+ startTests("RWLocks");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ (void)printf("Attempting to create new rwlock...\n");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_RWLock_Create(&rwlock, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_RWLock_Create(&rwlock2, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_RWLock_Create(&rwlock3, plContext));
+
+ /* Test toString functionality */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)rwlock, &outputString, plContext));
+
+ (void)printf("Testing RWLock toString: %s\n",
+ PKIX_String2ASCII(outputString));
+
+ PKIX_TEST_DECREF_BC(outputString);
+
+ /* Call Equals on two different objects */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)rwlock,
+ (PKIX_PL_Object *)rwlock2,
+ &bool,
+ plContext));
+
+ (void)printf("Testing RWLock Equals: %d (should be 0)\n", bool);
+
+ if (bool != 0)
+ testError("Error in RWLock_Equals");
+
+ /* Call Equals on two equal objects */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)rwlock,
+ (PKIX_PL_Object *)rwlock, &bool, plContext));
+
+ (void)printf("Testing RWLock Equals: %d (should be 1)\n", bool);
+ if (bool != 1)
+ testError("Error in RWLock_Equals");
+
+ subTest("Multi-Thread Read/Write Lock Testing");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_AcquireReaderLock(rwlock, plContext));
+ (void)printf("\t[Main Thread Read Lock #1.]\n");
+
+ thread = PR_CreateThread(PR_USER_THREAD,
+ reader,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ thread2 = PR_CreateThread(PR_USER_THREAD,
+ writer,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ thread3 = PR_CreateThread(PR_USER_THREAD,
+ reader2,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_LOCAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+
+ PR_JoinThread(thread);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ReleaseReaderLock(rwlock, plContext));
+ (void)printf("\t[Main Thread Read Unlock #1.]\n");
+
+ PR_JoinThread(thread2);
+
+cleanup:
+
+ /* Test destructor */
+ subTest("Testing destructor...");
+ PKIX_TEST_DECREF_AC(rwlock);
+ PKIX_TEST_DECREF_AC(rwlock2);
+ PKIX_TEST_DECREF_AC(rwlock3);
+
+ pkixTestTempResult = PKIX_Shutdown(plContext);
+ if (pkixTestTempResult)
+ pkixTestErrorResult = pkixTestTempResult;
+
+ PKIX_TEST_RETURN();
+
+ endTests("RWLocks");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_string.c b/security/nss/cmd/libpkix/pkix_pl/system/test_string.c
new file mode 100644
index 0000000000..9b84f94d9c
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_string.c
@@ -0,0 +1,434 @@
+/* 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_string.c
+ *
+ * Tests Strings.
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createString(
+ PKIX_PL_String **testString,
+ PKIX_UInt32 format,
+ char *stringAscii,
+ PKIX_UInt32 length)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(format, stringAscii, length, testString, plContext));
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+createStringOther(
+ PKIX_PL_String **testEscAscii,
+ PKIX_PL_String **testUtf16,
+ PKIX_PL_String **ampString,
+ PKIX_PL_String **testDebugAscii,
+ PKIX_PL_String **testNullString,
+ PKIX_UInt32 *utf16data)
+{
+ char *nullText = "Hi&#x0000; there!";
+
+ char *escAsciiString =
+ "&#x00A1;&#x00010000;&#x0FFF;&#x00100001;";
+
+ char *debugAsciiString =
+ "string with&#x000A;newlines and&#x0009;tabs";
+
+ char *utfAmp = "\x00&";
+
+ PKIX_TEST_STD_VARS();
+
+ createString(testEscAscii,
+ PKIX_ESCASCII,
+ escAsciiString,
+ PL_strlen(escAsciiString));
+
+ createString(testUtf16, PKIX_UTF16, (char *)utf16data, 12);
+
+ createString(ampString, PKIX_UTF16, utfAmp, 2);
+
+ createString(testDebugAscii,
+ PKIX_ESCASCII_DEBUG,
+ debugAsciiString,
+ PL_strlen(debugAsciiString));
+
+ createString(testNullString,
+ PKIX_ESCASCII_DEBUG,
+ nullText,
+ PL_strlen(nullText));
+
+ goto cleanup;
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetEncoded(
+ PKIX_PL_String *testEscAscii,
+ PKIX_PL_String *testString0,
+ PKIX_PL_String *testDebugAscii,
+ PKIX_PL_String *testNullString,
+ PKIX_UInt32 *utf16data)
+{
+ char *temp = NULL;
+ void *dest = NULL;
+ void *dest2 = NULL;
+ char *plainText = "string with\nnewlines and\ttabs";
+ PKIX_UInt32 length, length2, i;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(testEscAscii,
+ PKIX_UTF16,
+ &dest,
+ &length,
+ plContext));
+ for (i = 0; i < length; i++) {
+ if (((char *)dest)[i] != ((char *)utf16data)[i]) {
+ testError("UTF-16 Data Differs from Source");
+ printf("%d-th char is different -%c-%c-\n", i,
+ ((char *)dest)[i], ((char *)utf16data)[i]);
+ }
+ }
+
+ length = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(testNullString,
+ PKIX_UTF16,
+ &dest,
+ &length,
+ plContext));
+
+ length = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(testString0,
+ PKIX_ESCASCII_DEBUG,
+ &dest,
+ &length,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(testDebugAscii,
+ PKIX_ESCASCII_DEBUG,
+ &dest2,
+ &length2,
+ plContext));
+
+ for (i = 0; (i < length) && (i < length2); i++)
+ if (((char *)dest)[i] != ((char *)dest2)[i]) {
+ testError("Equivalent strings are unequal");
+ break;
+ }
+
+ length = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ length2 = 0;
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest2, plContext));
+
+ temp = PKIX_String2ASCII(testDebugAscii, plContext);
+ if (temp) {
+ if (PL_strcmp(plainText, temp) != 0)
+ testError("Debugged ASCII does not match "
+ "equivalent EscAscii");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testSprintf(void)
+{
+ PKIX_Int32 x = 0xCAFE;
+ PKIX_Int32 y = -12345;
+ PKIX_PL_String *testString = NULL;
+ PKIX_PL_String *formatString = NULL;
+ PKIX_PL_String *sprintfString = NULL;
+ char *plainText = "Testing Sprintf";
+ char *format = "%s %x %u %d";
+ char *convertedFormat = "%s %lx %lu %ld";
+ char *temp = NULL;
+ char *temp2 = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ plainText,
+ PL_strlen(plainText),
+ &testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ format,
+ 11,
+ &formatString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Sprintf(&sprintfString,
+ plContext,
+ formatString,
+ testString, x, y, y));
+ PKIX_TEST_DECREF_BC(testString);
+
+ temp = PR_smprintf(convertedFormat, plainText, x, y, y);
+ temp2 = PKIX_String2ASCII(sprintfString, plContext);
+
+ if (PL_strcmp(temp, temp2) != 0)
+ testError("Sprintf produced incorrect output");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp2, plContext));
+
+ PKIX_TEST_DECREF_BC(sprintfString);
+
+ PKIX_TEST_DECREF_BC(formatString);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testErrorHandling(void)
+{
+ char *debugAsciiString =
+ "string with&#x000A;newlines and&#x0009;tabs";
+
+ PKIX_PL_String *testString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ NULL,
+ 50,
+ &testString,
+ plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ "blah", 4, NULL, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_Sprintf(&testString, plContext, NULL));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_GetString(0, NULL, &testString, plContext));
+
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_GetString(0, "blah", 0, plContext));
+
+ /* ---------------------------- */
+ subTest("Unicode Error Handling");
+
+ /* &#x must be followed by 4 hexadecimal digits */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#x003k;",
+ 7,
+ &testString,
+ plContext));
+
+ /* &#x must be followed by 4 hexadecimal digits */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "abc&#x00",
+ 8,
+ &testString,
+ plContext));
+
+ /* &#x must be between 00010000-0010FFFF */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#x00200101;",
+ 11,
+ &testString,
+ plContext));
+
+ /* &#x must be followed by 8 hexadecimal digits */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#x001000",
+ 10,
+ &testString,
+ plContext));
+
+ /* &#x must be followed by 8 hexadecimal digits */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#x0010m00;",
+ 10,
+ &testString,
+ plContext));
+
+ /* Byte values D800-DFFF are reserved */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#xD800;",
+ 7,
+ &testString,
+ plContext));
+
+ /* Can't use &#x for regular characters */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&#x0032;",
+ 7,
+ &testString,
+ plContext));
+
+ /* Can't use non-printable characters */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "\xA1",
+ 1,
+ &testString,
+ plContext));
+
+ /* Only legal \\ characters are \\, u and U */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ "&blah",
+ 5,
+ &testString,
+ plContext));
+
+ /* Surrogate pairs must be legal */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_UTF16,
+ "\xd8\x00\x0\x66",
+ 4,
+ &testString,
+ plContext));
+
+ /* Debugged EscASCII should not be accepted as EscASCII */
+ PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ debugAsciiString,
+ PL_strlen(debugAsciiString),
+ &testString,
+ plContext));
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_String *string)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(string);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_string(int argc, char *argv[])
+{
+
+ PKIX_PL_String *testString[6] = { NULL };
+ PKIX_PL_String *testNullString = NULL;
+ PKIX_PL_String *testDebugAscii = NULL;
+ PKIX_PL_String *testEscAscii = NULL;
+ PKIX_PL_String *testUtf16 = NULL;
+ PKIX_PL_String *ampString = NULL;
+ unsigned char utf16Data[] = { 0x00, 0xA1, 0xD8, 0x00,
+ 0xDC, 0x00, 0x0F, 0xFF,
+ 0xDB, 0xC0, 0xDC, 0x01 };
+ PKIX_UInt32 i, size = 6;
+
+ char *plainText[6] = {
+ "string with\nnewlines and\ttabs",
+ "Not an escaped char: &amp;#x0012;",
+ "Encode &amp; with &amp;amp; in ASCII",
+ "&#x00A1;",
+ "&amp;",
+ "string with\nnewlines and\ttabs"
+ };
+
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Strings");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_String_Create <ascii format>");
+ for (i = 0; i < size; i++) {
+ testString[i] = NULL;
+ createString(&testString[i],
+ PKIX_ESCASCII,
+ plainText[i],
+ PL_strlen(plainText[i]));
+ }
+
+ subTest("PKIX_PL_String_Create <other formats>");
+ createStringOther(&testEscAscii,
+ &testUtf16,
+ &ampString,
+ &testDebugAscii,
+ &testNullString,
+ (PKIX_UInt32 *)utf16Data);
+
+ PKIX_TEST_EQ_HASH_TOSTR_DUP(testString[0],
+ testString[5],
+ testString[1],
+ plainText[0],
+ String,
+ PKIX_TRUE);
+
+ subTest("PKIX_PL_String_GetEncoded");
+ testGetEncoded(testEscAscii,
+ testString[0],
+ testDebugAscii,
+ testNullString,
+ (PKIX_UInt32 *)utf16Data);
+
+ subTest("PKIX_PL_Sprintf");
+ testSprintf();
+
+ subTest("PKIX_PL_String_Create <error_handling>");
+ testErrorHandling();
+
+ subTest("PKIX_PL_String_Destroy");
+ for (i = 0; i < size; i++) {
+ testDestroy(testString[i]);
+ }
+ testDestroy(testEscAscii);
+ testDestroy(testUtf16);
+ testDestroy(ampString);
+ testDestroy(testDebugAscii);
+ testDestroy(testNullString);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("String");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkix_pl/system/test_string2.c b/security/nss/cmd/libpkix/pkix_pl/system/test_string2.c
new file mode 100644
index 0000000000..c76d1e9ac8
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkix_pl/system/test_string2.c
@@ -0,0 +1,337 @@
+/* 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_string2.c
+ *
+ * Tests International Strings
+ *
+ */
+
+#include "testutil.h"
+#include "testutil_nss.h"
+
+static void *plContext = NULL;
+
+static void
+createString(
+ PKIX_PL_String **vivaEspanaString,
+ PKIX_PL_String **straussString,
+ PKIX_PL_String **gorbachevString,
+ PKIX_PL_String **testUTF16String,
+ PKIX_PL_String **chineseString,
+ PKIX_PL_String **jeanRenoString)
+{
+ /* this is meant to fail - it highlights bug 0002 */
+ unsigned char utf16String[4] = { 0xF8, 0x60,
+ 0xFC, 0x60 };
+
+ unsigned char chinese[16] = { 0xe7, 0xab, 0xa0,
+ 0xe5, 0xad, 0x90,
+ 0xe6, 0x80, 0xa1,
+ 0x20,
+ 0xe4, 0xb8, 0xad,
+ 0xe5, 0x9b, 0xbd };
+
+ char *jeanReno = "Jean R\303\251no is an actor.";
+ char *gorbachev = /* This is the name "Gorbachev" in cyrllic */
+ "\xd0\x93\xd0\xbe\xd1\x80\xd0\xb1\xd0\xb0\xd1\x87\xd1\x91\xd0\xb2";
+
+ char *vivaEspana =
+ "&#x00A1;Viva Espa&#x00f1;a!";
+
+ char *strauss =
+ "Strau&#x00Df; was born in &#x00D6;sterreich";
+
+ PKIX_TEST_STD_VARS();
+
+ /* ---------------------------- */
+ subTest("String Creation");
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ vivaEspana,
+ PL_strlen(vivaEspana),
+ vivaEspanaString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_ESCASCII,
+ strauss,
+ PL_strlen(strauss),
+ straussString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_UTF8,
+ gorbachev,
+ PL_strlen(gorbachev),
+ gorbachevString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_UTF16,
+ utf16String,
+ 4,
+ testUTF16String,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_UTF8,
+ chinese,
+ 16,
+ chineseString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(
+ PKIX_UTF8,
+ jeanReno,
+ PL_strlen(jeanReno),
+ jeanRenoString,
+ plContext));
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testGetEncoded(PKIX_PL_String *string, PKIX_UInt32 format)
+{
+ void *dest = NULL;
+ PKIX_UInt32 length;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(string,
+ format,
+ &dest,
+ &length,
+ plContext));
+
+ if (dest) {
+ (void)printf("\tResult: %s\n", (char *)dest);
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ }
+
+cleanup:
+ PKIX_TEST_RETURN();
+}
+
+static void
+testHTMLOutput(
+ PKIX_PL_String *vivaEspanaString,
+ PKIX_PL_String *straussString,
+ PKIX_PL_String *gorbachevString,
+ PKIX_PL_String *testUTF16String,
+ PKIX_PL_String *chineseString,
+ PKIX_PL_String *jeanRenoString)
+{
+ void *dest = NULL;
+ PKIX_UInt32 length;
+
+ FILE *htmlFile = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ /* Opening a file for output */
+ htmlFile = fopen("utf8.html", "w");
+
+ if (htmlFile != plContext) {
+ (void)fprintf(htmlFile, "<html><head>\n");
+ (void)fprintf(htmlFile, "<meta http-equiv=\"Content-Type\"");
+ (void)fprintf(htmlFile,
+ "content = \"text/html; charset = UTF-8\">\n");
+ (void)fprintf(htmlFile, "</head><body>\n");
+ (void)fprintf(htmlFile, "<font size =\"+2\">\n");
+ } else
+ (void)printf("Could not open HTML file\n");
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(testUTF16String,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(chineseString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(jeanRenoString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(vivaEspanaString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(straussString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(straussString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_GetEncoded(gorbachevString,
+ PKIX_UTF8,
+ &dest,
+ &length,
+ plContext));
+ if (htmlFile != plContext) {
+ (void)printf("%d bytes written to HTML file\n",
+ fwrite(dest, length, 1, htmlFile));
+ (void)fprintf(htmlFile, "<BR>\n");
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(dest, plContext));
+ dest = NULL;
+ length = 0;
+
+ if (htmlFile != plContext) {
+ (void)fprintf(htmlFile, "</font>\n");
+ (void)fprintf(htmlFile, "</body></html>\n");
+ (void)fclose(htmlFile);
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+static void
+testDestroy(
+ PKIX_PL_String *string)
+{
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_DECREF_BC(string);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+int
+test_string2(int argc, char *argv[])
+{
+
+ PKIX_PL_String *vivaEspanaString, *straussString, *testUTF16String;
+ PKIX_PL_String *chineseString, *jeanRenoString, *gorbachevString;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+
+ PKIX_TEST_STD_VARS();
+
+ startTests("Unicode Strings");
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ subTest("PKIX_PL_String_Create");
+ createString(&vivaEspanaString,
+ &straussString,
+ &gorbachevString,
+ &testUTF16String,
+ &chineseString,
+ &jeanRenoString);
+
+ subTest("Converting UTF-16 to EscASCII");
+ testGetEncoded(testUTF16String, PKIX_ESCASCII);
+
+ subTest("Converting UTF-8 to EscASCII");
+ testGetEncoded(chineseString, PKIX_ESCASCII);
+
+ subTest("Converting UTF-8 to EscASCII");
+ testGetEncoded(jeanRenoString, PKIX_ESCASCII);
+
+ subTest("Converting EscASCII to UTF-16");
+ testGetEncoded(vivaEspanaString, PKIX_UTF16);
+
+ subTest("Converting UTF-8 to UTF-16");
+ testGetEncoded(chineseString, PKIX_UTF16);
+
+ subTest("Creating HTML Output File \'utf8.html\'");
+ testHTMLOutput(vivaEspanaString,
+ straussString,
+ gorbachevString,
+ testUTF16String,
+ chineseString,
+ jeanRenoString);
+
+ subTest("Unicode Destructors");
+ testDestroy(testUTF16String);
+ testDestroy(chineseString);
+ testDestroy(jeanRenoString);
+ testDestroy(vivaEspanaString);
+ testDestroy(straussString);
+ testDestroy(gorbachevString);
+
+cleanup:
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("Unicode Strings");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/pkixlibs.mk b/security/nss/cmd/libpkix/pkixlibs.mk
new file mode 100755
index 0000000000..2e1eb154f0
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkixlibs.mk
@@ -0,0 +1,27 @@
+#
+# 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/.
+
+ifeq (,$(filter-out WIN%,$(OS_TARGET)))
+
+ifdef NS_USE_GCC
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib \
+ -lpkixutil \
+ $(NULL)
+else # ! NS_USE_GCC
+EXTRA_SHARED_LIBS += \
+ $(DIST)/lib/pkixutil.lib \
+ $(NULL)
+endif # NS_USE_GCC
+
+else
+
+EXTRA_SHARED_LIBS += \
+ -L$(DIST)/lib/ \
+ -lpkixutil \
+ $(NULL)
+
+endif
+
diff --git a/security/nss/cmd/libpkix/pkixrules.mk b/security/nss/cmd/libpkix/pkixrules.mk
new file mode 100755
index 0000000000..bbaf85c568
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkixrules.mk
@@ -0,0 +1,7 @@
+#
+# 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 = $(PKIX_DEPTH)/../../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
diff --git a/security/nss/cmd/libpkix/pkixutil/Makefile b/security/nss/cmd/libpkix/pkixutil/Makefile
new file mode 100644
index 0000000000..a2cfa73bd0
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkixutil/Makefile
@@ -0,0 +1,43 @@
+#! 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/security/nss/cmd/libpkix/pkixutil/manifest.mn b/security/nss/cmd/libpkix/pkixutil/manifest.mn
new file mode 100644
index 0000000000..180e995aa1
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkixutil/manifest.mn
@@ -0,0 +1,41 @@
+#
+# 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 = \
+ pkixutil.c \
+ $(NULL)
+
+PROGRAM = pkixutil
+
+TOOLS_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+EXTRA_LIBS += \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolperf.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolcertsel.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolparams.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolmodule.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolpki.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolsys.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolresults.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolstore.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtooltop.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolutil.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolsmplapps.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolchecker.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtoolcrlsel.$(LIB_SUFFIX) \
+ $(TOOLS_LIB_DIR)/$(LIB_PREFIX)pkixtooltestutil.$(LIB_SUFFIX) \
+ $(NULL)
+
+NO_MD_RELEASE = 1
+
+USE_STATIC_LIBS = 1
+
diff --git a/security/nss/cmd/libpkix/pkixutil/pkixutil.c b/security/nss/cmd/libpkix/pkixutil/pkixutil.c
new file mode 100644
index 0000000000..158f458952
--- /dev/null
+++ b/security/nss/cmd/libpkix/pkixutil/pkixutil.c
@@ -0,0 +1,299 @@
+/* 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/. */
+/*
+ * testwrapper.c
+ *
+ * Wrpper programm for libpkix tests.
+ *
+ */
+
+#include <stdio.h>
+
+#include "nspr.h"
+#include "plgetopt.h"
+
+#include "nss.h"
+#include "secport.h"
+
+typedef int (*mainTestFn)(int argc, char *argv[]);
+
+extern int libpkix_buildthreads(int argc, char *argv[]);
+extern int nss_threads(int argc, char *argv[]);
+extern int test_certselector(int argc, char *argv[]);
+extern int test_comcertselparams(int argc, char *argv[]);
+extern int test_certchainchecker(int argc, char *argv[]);
+extern int test_comcrlselparams(int argc, char *argv[]);
+extern int test_crlselector(int argc, char *argv[]);
+
+extern int test_procparams(int argc, char *argv[]);
+extern int test_resourcelimits(int argc, char *argv[]);
+extern int test_trustanchor(int argc, char *argv[]);
+extern int test_valparams(int argc, char *argv[]);
+extern int test_buildresult(int argc, char *argv[]);
+extern int test_policynode(int argc, char *argv[]);
+extern int test_valresult(int argc, char *argv[]);
+extern int test_verifynode(int argc, char *argv[]);
+extern int test_store(int argc, char *argv[]);
+extern int test_basicchecker(int argc, char *argv[]);
+extern int test_basicconstraintschecker(int argc, char *argv[]);
+extern int test_buildchain(int argc, char *argv[]);
+extern int test_buildchain_partialchain(int argc, char *argv[]);
+extern int test_buildchain_resourcelimits(int argc, char *argv[]);
+extern int test_buildchain_uchecker(int argc, char *argv[]);
+extern int test_customcrlchecker(int argc, char *argv[]);
+extern int test_defaultcrlchecker2stores(int argc, char *argv[]);
+extern int test_ocsp(int argc, char *argv[]);
+extern int test_policychecker(int argc, char *argv[]);
+extern int test_subjaltnamechecker(int argc, char *argv[]);
+extern int test_validatechain(int argc, char *argv[]);
+extern int test_validatechain_NB(int argc, char *argv[]);
+extern int test_validatechain_bc(int argc, char *argv[]);
+extern int test_error(int argc, char *argv[]);
+extern int test_list(int argc, char *argv[]);
+extern int test_list2(int argc, char *argv[]);
+extern int test_logger(int argc, char *argv[]);
+extern int test_colcertstore(int argc, char *argv[]);
+extern int test_ekuchecker(int argc, char *argv[]);
+extern int test_httpcertstore(int argc, char *argv[]);
+extern int test_pk11certstore(int argc, char *argv[]);
+extern int test_socket(int argc, char *argv[]);
+extern int test_authorityinfoaccess(int argc, char *argv[]);
+extern int test_cert(int argc, char *argv[]);
+extern int test_crl(int argc, char *argv[]);
+extern int test_crlentry(int argc, char *argv[]);
+extern int test_date(int argc, char *argv[]);
+extern int test_generalname(int argc, char *argv[]);
+extern int test_nameconstraints(int argc, char *argv[]);
+extern int test_subjectinfoaccess(int argc, char *argv[]);
+extern int test_x500name(int argc, char *argv[]);
+extern int stress_test(int argc, char *argv[]);
+extern int test_bigint(int argc, char *argv[]);
+extern int test_bytearray(int argc, char *argv[]);
+extern int test_hashtable(int argc, char *argv[]);
+extern int test_mem(int argc, char *argv[]);
+extern int test_monitorlock(int argc, char *argv[]);
+extern int test_mutex(int argc, char *argv[]);
+extern int test_mutex2(int argc, char *argv[]);
+extern int test_mutex3(int argc, char *argv[]);
+extern int test_object(int argc, char *argv[]);
+extern int test_oid(int argc, char *argv[]);
+
+/* Taken out. Problem with build */
+/* extern int test_rwlock(int argc, char *argv[]); */
+extern int test_string(int argc, char *argv[]);
+extern int test_string2(int argc, char *argv[]);
+extern int build_chain(int argc, char *argv[]);
+extern int dumpcert(int argc, char *argv[]);
+extern int dumpcrl(int argc, char *argv[]);
+extern int validate_chain(int argc, char *argv[]);
+
+typedef struct {
+ char *fnName;
+ mainTestFn fnPointer;
+} testFunctionRef;
+
+testFunctionRef testFnRefTable[] = {
+ { "libpkix_buildthreads", libpkix_buildthreads },
+ { "nss_threads", nss_threads },
+ { "test_certselector", test_certselector },
+ { "test_comcertselparams", test_comcertselparams },
+ { "test_certchainchecker", test_certchainchecker },
+ { "test_comcrlselparams", test_comcrlselparams },
+ { "test_crlselector", test_crlselector },
+ { "test_procparams", test_procparams },
+ { "test_resourcelimits", test_resourcelimits },
+ { "test_trustanchor", test_trustanchor },
+ { "test_valparams", test_valparams },
+ { "test_buildresult", test_buildresult },
+ { "test_policynode", test_policynode },
+ { "test_valresult", test_valresult },
+ { "test_verifynode", test_verifynode },
+ { "test_store", test_store },
+ { "test_basicchecker", test_basicchecker },
+ { "test_basicconstraintschecker", test_basicconstraintschecker },
+ { "test_buildchain", test_buildchain },
+ { "test_buildchain_partialchain", test_buildchain_partialchain },
+ { "test_buildchain_resourcelimits", test_buildchain_resourcelimits },
+ { "test_buildchain_uchecker", test_buildchain_uchecker },
+ { "test_customcrlchecker", test_customcrlchecker },
+ { "test_defaultcrlchecker2stores", test_defaultcrlchecker2stores },
+ { "test_ocsp", test_ocsp },
+ { "test_policychecker", test_policychecker },
+ { "test_subjaltnamechecker", test_subjaltnamechecker },
+ { "test_validatechain", test_validatechain },
+ { "test_validatechain_NB", test_validatechain_NB },
+ { "test_validatechain_bc", test_validatechain_bc },
+ { "test_error", test_error },
+ { "test_list", test_list },
+ { "test_list2", test_list2 },
+ { "test_logger", test_logger },
+ { "test_colcertstore", test_colcertstore },
+ { "test_ekuchecker", test_ekuchecker },
+ { "test_httpcertstore", test_httpcertstore },
+ { "test_pk11certstore", test_pk11certstore },
+ { "test_socket", test_socket },
+ { "test_authorityinfoaccess", test_authorityinfoaccess },
+ { "test_cert", test_cert },
+ { "test_crl", test_crl },
+ { "test_crlentry", test_crlentry },
+ { "test_date", test_date },
+ { "test_generalname", test_generalname },
+ { "test_nameconstraints", test_nameconstraints },
+ { "test_subjectinfoaccess", test_subjectinfoaccess },
+ { "test_x500name", test_x500name },
+ { "stress_test", stress_test },
+ { "test_bigint", test_bigint },
+ { "test_bytearray", test_bytearray },
+ { "test_hashtable", test_hashtable },
+ { "test_mem", test_mem },
+ { "test_monitorlock", test_monitorlock },
+ { "test_mutex", test_mutex },
+ { "test_mutex2", test_mutex2 },
+ { "test_mutex3", test_mutex3 },
+ { "test_object", test_object },
+ { "test_oid", test_oid },
+ /* {"test_rwlock", test_rwlock }*/
+ { "test_string", test_string },
+ { "test_string2", test_string2 },
+ { "build_chain", build_chain },
+ { "dumpcert", dumpcert },
+ { "dumpcrl", dumpcrl },
+ { "validate_chain", validate_chain },
+ { NULL, NULL },
+};
+
+static void
+printUsage(char *cmdName)
+{
+ int fnCounter = 0;
+
+ fprintf(stderr, "Usage: %s [test name] [arg1]...[argN]\n\n", cmdName);
+ fprintf(stderr, "List of possible names for the tests:");
+ while (testFnRefTable[fnCounter].fnName != NULL) {
+ if (fnCounter % 2 == 0) {
+ fprintf(stderr, "\n");
+ }
+ fprintf(stderr, " %-35s ", testFnRefTable[fnCounter].fnName);
+ fnCounter += 1;
+ }
+ fprintf(stderr, "\n");
+}
+
+static SECStatus
+getTestArguments(int argc,
+ char **argv,
+ mainTestFn *ptestFn,
+ char **pdbPath,
+ int *pargc,
+ char ***pargv)
+{
+ PLOptState *optstate = NULL;
+ PLOptStatus status;
+ mainTestFn testFunction = NULL;
+ char **wArgv = NULL;
+ char *dbPath = NULL;
+ char *fnName = NULL;
+ int wArgc = 0;
+ int fnCounter = 0;
+
+ if (argc < 2) {
+ printf("ERROR: insufficient number of arguments: %s.\n", fnName);
+ return SECFailure;
+ }
+
+ fnName = argv[1];
+ while (testFnRefTable[fnCounter].fnName != NULL) {
+ if (!PORT_Strcmp(fnName, testFnRefTable[fnCounter].fnName)) {
+ testFunction = testFnRefTable[fnCounter].fnPointer;
+ break;
+ }
+ fnCounter += 1;
+ }
+ if (!testFunction) {
+ printf("ERROR: unknown name of the test: %s.\n", fnName);
+ return SECFailure;
+ }
+
+ wArgv = PORT_ZNewArray(char *, argc);
+ if (!wArgv) {
+ return SECFailure;
+ }
+
+ /* set name of the function as a first arg and increment arg count. */
+ wArgv[0] = fnName;
+ wArgc += 1;
+
+ optstate = PL_CreateOptState(argc - 1, argv + 1, "d:");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case 'd':
+ dbPath = (char *)optstate->value;
+ break;
+
+ default:
+ wArgv[wArgc] = (char *)optstate->value;
+ wArgc += 1;
+ break;
+ }
+ }
+ PL_DestroyOptState(optstate);
+
+ *ptestFn = testFunction;
+ *pdbPath = dbPath;
+ *pargc = wArgc;
+ *pargv = wArgv;
+
+ return SECSuccess;
+}
+
+static int
+runCmd(mainTestFn fnPointer,
+ int argc,
+ char **argv,
+ char *dbPath)
+{
+ int retStat = 0;
+
+ /* Initialize NSPR and NSS. */
+ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
+
+ /* if using databases, use NSS_Init and not NSS_NoDB_Init */
+ if (dbPath && PORT_Strlen(dbPath) != 0) {
+ if (NSS_Init(dbPath) != SECSuccess)
+ return SECFailure;
+ } else {
+ if (NSS_NoDB_Init(NULL) != 0)
+ return SECFailure;
+ }
+ retStat = fnPointer(argc, argv);
+
+ if (NSS_Shutdown() != SECSuccess) {
+ exit(1);
+ }
+ PR_Cleanup();
+ return retStat;
+}
+
+int
+main(int argc, char **argv)
+{
+ mainTestFn testFunction = NULL;
+ char *dbPath = NULL;
+ char **testArgv = NULL;
+ int testArgc = 0;
+ int rv = 0;
+
+ rv = getTestArguments(argc, argv, &testFunction, &dbPath,
+ &testArgc, &testArgv);
+ if (rv != SECSuccess) {
+ printUsage(argv[0]);
+ return 1;
+ }
+
+ rv = runCmd(testFunction, testArgc, testArgv, dbPath);
+
+ PORT_Free(testArgv);
+
+ return rv;
+}
diff --git a/security/nss/cmd/libpkix/sample_apps/Makefile b/security/nss/cmd/libpkix/sample_apps/Makefile
new file mode 100644
index 0000000000..daa8765778
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/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/security/nss/cmd/libpkix/sample_apps/build_chain.c b/security/nss/cmd/libpkix/sample_apps/build_chain.c
new file mode 100644
index 0000000000..38bf1d9f3a
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/build_chain.c
@@ -0,0 +1,242 @@
+/* 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/. */
+/*
+ * buildChain.c
+ *
+ * Tests Cert Chain Building
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_cert.h"
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "secitem.h"
+#include "keythi.h"
+#include "nss.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\tbuildChain "
+ "<trustedCert> <targetCert> <certStoreDirectory>\n\n");
+ (void)printf("Builds a chain of certificates between "
+ "<trustedCert> and <targetCert>\n"
+ "using the certs and CRLs in <certStoreDirectory>.\n");
+}
+
+static PKIX_PL_Cert *
+createCert(char *inFileName)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ void *buf = NULL;
+ PRFileDesc *inFile = NULL;
+ PKIX_UInt32 len;
+ SECItem certDER;
+ SECStatus rv;
+ /* default: NULL cert (failure case) */
+ PKIX_PL_Cert *cert = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certDER.data = NULL;
+
+ inFile = PR_Open(inFileName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ pkixTestErrorMsg = "Unable to open cert file";
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)certDER.data;
+ len = certDER.len;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_Create(byteArray, &cert, plContext));
+
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ } else {
+ pkixTestErrorMsg = "Unable to read DER from cert file";
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ }
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+
+ return (cert);
+}
+
+int
+build_chain(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;
+ char *trustedCertFile = NULL;
+ char *targetCertFile = NULL;
+ char *storeDirAscii = NULL;
+ PKIX_PL_String *storeDirString = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *targetCert = NULL;
+ PKIX_UInt32 actualMinorVersion, numCerts, i;
+ PKIX_UInt32 j = 0;
+ PKIX_CertStore *certStore = NULL;
+ PKIX_List *certStores = NULL;
+ char *asciiResult = NULL;
+ PKIX_Boolean useArenas = PKIX_FALSE;
+ void *buildState = NULL; /* needed by pkix_build for non-blocking I/O */
+ void *nbioContext = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 4) {
+ printUsage();
+ return (0);
+ }
+
+ useArenas = PKIX_TEST_ARENAS_ARG(argv[1]);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_Initialize(PKIX_TRUE, /* nssInitNeeded */
+ useArenas,
+ PKIX_MAJOR_VERSION,
+ PKIX_MINOR_VERSION,
+ PKIX_MINOR_VERSION,
+ &actualMinorVersion,
+ &plContext));
+
+ /* create processing params with list of trust anchors */
+ trustedCertFile = argv[j + 1];
+ trustedCert = createCert(trustedCertFile);
+
+ 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));
+
+ targetCertFile = argv[j + 2];
+ targetCert = createCert(targetCertFile);
+
+ 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 */
+
+ storeDirAscii = argv[j + 3];
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, storeDirAscii, 0, &storeDirString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(storeDirString, &certStore, plContext));
+ 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 */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildChain(procParams,
+ &nbioContext,
+ &buildState,
+ &buildResult,
+ NULL,
+ plContext));
+
+ /*
+ * As long as we use only CertStores with blocking I/O, we can omit
+ * checking for completion with nbioContext.
+ */
+
+ 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_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, plContext));
+ asciiResult = NULL;
+
+ PKIX_TEST_DECREF_BC(cert);
+ }
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ (void)printf("FAILED TO BUILD CHAIN\n");
+ } else {
+ (void)printf("SUCCESSFULLY BUILT CHAIN\n");
+ }
+
+ PKIX_PL_Free(asciiResult, plContext);
+
+ PKIX_TEST_DECREF_AC(certs);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(certStore);
+ PKIX_TEST_DECREF_AC(certStores);
+ PKIX_TEST_DECREF_AC(storeDirString);
+ 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_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/sample_apps/dumpcert.c b/security/nss/cmd/libpkix/sample_apps/dumpcert.c
new file mode 100644
index 0000000000..6ff5f83779
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/dumpcert.c
@@ -0,0 +1,182 @@
+/* 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/. */
+/*
+ * dumpcert.c
+ *
+ * dump certificate sample application
+ *
+ */
+
+#include <stdio.h>
+
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "plarena.h"
+#include "seccomon.h"
+#include "secdert.h"
+#include "secasn1t.h"
+#include "certt.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\tdumpcert <certFile>\n");
+ (void)printf("\tParses a certificate located at <certFile> "
+ "and displays it.\n");
+}
+
+static void
+printFailure(char *msg)
+{
+ (void)printf("FAILURE: %s\n", msg);
+}
+
+static PKIX_PL_Cert *
+createCert(char *inFileName)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_Error *error = NULL;
+ PRFileDesc *inFile = NULL;
+ SECItem certDER;
+ void *buf = NULL;
+ PKIX_UInt32 len;
+ SECStatus rv = SECFailure;
+
+ certDER.data = NULL;
+
+ inFile = PR_Open(inFileName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ printFailure("Unable to open cert file");
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)certDER.data;
+ len = certDER.len;
+
+ error = PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext);
+
+ if (error) {
+ printFailure("PKIX_PL_ByteArray_Create failed");
+ goto cleanup;
+ }
+
+ error = PKIX_PL_Cert_Create(byteArray, &cert, plContext);
+
+ if (error) {
+ printFailure("PKIX_PL_Cert_Create failed");
+ goto cleanup;
+ }
+ } else {
+ printFailure("Unable to read DER from cert file");
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (rv == SECSuccess) {
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ }
+
+ if (byteArray) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(byteArray), plContext);
+ }
+
+ return (cert);
+}
+
+int
+dumpcert(int argc, char *argv[])
+{
+
+ PKIX_PL_String *string = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_Error *error = NULL;
+ char *ascii = NULL;
+ PKIX_UInt32 length = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean useArenas = PKIX_FALSE;
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc == 1) {
+ printUsage();
+ return (0);
+ }
+
+ useArenas = PKIX_TEST_ARENAS_ARG(argv[1]);
+
+ PKIX_Initialize(PKIX_TRUE, /* nssInitNeeded */
+ useArenas,
+ PKIX_MAJOR_VERSION,
+ PKIX_MINOR_VERSION,
+ PKIX_MINOR_VERSION,
+ &actualMinorVersion,
+ &plContext);
+
+ cert = createCert(argv[1 + j]);
+
+ if (cert) {
+
+ error = PKIX_PL_Object_ToString((PKIX_PL_Object *)cert, &string, plContext);
+
+ if (error) {
+ printFailure("Unable to get string representation "
+ "of cert");
+ goto cleanup;
+ }
+
+ error = PKIX_PL_String_GetEncoded(string,
+ PKIX_ESCASCII,
+ (void **)&ascii,
+ &length,
+ plContext);
+
+ if (error || !ascii) {
+ printFailure("Unable to get ASCII encoding of string");
+ goto cleanup;
+ }
+
+ (void)printf("OUTPUT:\n%s\n", ascii);
+
+ } else {
+ printFailure("Unable to create certificate");
+ goto cleanup;
+ }
+
+cleanup:
+
+ if (cert) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(cert), plContext);
+ }
+
+ if (string) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(string), plContext);
+ }
+
+ if (ascii) {
+ PKIX_PL_Free((PKIX_PL_Object *)(ascii), plContext);
+ }
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("DUMPCERT");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/sample_apps/dumpcrl.c b/security/nss/cmd/libpkix/sample_apps/dumpcrl.c
new file mode 100644
index 0000000000..642601409a
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/dumpcrl.c
@@ -0,0 +1,186 @@
+/* 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/. */
+/*
+ * dumpcrl.c
+ *
+ * dump CRL sample application
+ *
+ */
+
+#include <stdio.h>
+
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "plarena.h"
+#include "seccomon.h"
+#include "secdert.h"
+#include "secasn1t.h"
+#include "certt.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\tdumpcrl <crlFile>\n");
+ (void)printf("\tParses a CRL located at <crlFile> "
+ "and displays it.\n");
+}
+
+static void
+printFailure(char *msg)
+{
+ (void)printf("FAILURE: %s\n", msg);
+}
+
+static PKIX_PL_CRL *
+createCRL(char *inFileName)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_Error *error = NULL;
+ PRFileDesc *inFile = NULL;
+ SECItem crlDER;
+ void *buf = NULL;
+ PKIX_UInt32 len;
+ SECStatus rv;
+
+ PKIX_TEST_STD_VARS();
+
+ crlDER.data = NULL;
+
+ inFile = PR_Open(inFileName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ printFailure("Unable to open crl file");
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)crlDER.data;
+ len = crlDER.len;
+
+ error = PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext);
+
+ if (error) {
+ printFailure("PKIX_PL_ByteArray_Create failed");
+ goto cleanup;
+ }
+
+ error = PKIX_PL_CRL_Create(byteArray, &crl, plContext);
+ if (error) {
+ printFailure("PKIX_PL_CRL_Create failed");
+ goto cleanup;
+ }
+
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ } else {
+ printFailure("Unable to read DER from crl file");
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (error) {
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ }
+
+ if (byteArray) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(byteArray), plContext);
+ }
+
+ PKIX_TEST_RETURN();
+
+ return (crl);
+}
+
+int
+dumpcrl(int argc, char *argv[])
+{
+
+ PKIX_PL_String *string = NULL;
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_Error *error = NULL;
+ char *ascii = NULL;
+ PKIX_UInt32 length;
+ PKIX_UInt32 actualMinorVersion;
+ PKIX_UInt32 j = 0;
+ PKIX_Boolean useArenas = PKIX_FALSE;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc == 1) {
+ printUsage();
+ return (0);
+ }
+
+ useArenas = PKIX_TEST_ARENAS_ARG(argv[1]);
+
+ PKIX_Initialize(PKIX_TRUE, /* nssInitNeeded */
+ useArenas,
+ PKIX_MAJOR_VERSION,
+ PKIX_MINOR_VERSION,
+ PKIX_MINOR_VERSION,
+ &actualMinorVersion,
+ &plContext);
+
+ crl = createCRL(argv[j + 1]);
+
+ if (crl) {
+
+ error = PKIX_PL_Object_ToString((PKIX_PL_Object *)crl, &string, plContext);
+
+ if (error) {
+ printFailure("Unable to get string representation "
+ "of crl");
+ goto cleanup;
+ }
+
+ error = PKIX_PL_String_GetEncoded(string,
+ PKIX_ESCASCII,
+ (void **)&ascii,
+ &length,
+ plContext);
+ if (error || !ascii) {
+ printFailure("Unable to get ASCII encoding of string");
+ goto cleanup;
+ }
+
+ (void)printf("OUTPUT:\n%s\n", ascii);
+
+ } else {
+ printFailure("Unable to create CRL");
+ goto cleanup;
+ }
+
+cleanup:
+
+ if (crl) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(crl), plContext);
+ }
+
+ if (string) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(string), plContext);
+ }
+
+ if (ascii) {
+ PKIX_PL_Free((PKIX_PL_Object *)(ascii), plContext);
+ }
+
+ PKIX_Shutdown(plContext);
+
+ PKIX_TEST_RETURN();
+
+ endTests("DUMPCRL");
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/sample_apps/manifest.mn b/security/nss/cmd/libpkix/sample_apps/manifest.mn
new file mode 100644
index 0000000000..32926cc1bb
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/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 = dumpcert.c \
+ dumpcrl.c \
+ validate_chain.c \
+ build_chain.c \
+ $(NULL)
+
+LIBRARY_NAME=pkixtoolsmplapps
+
+SOURCE_LIB_DIR=$(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/sample_apps/validate_chain.c b/security/nss/cmd/libpkix/sample_apps/validate_chain.c
new file mode 100644
index 0000000000..1ccf364e0c
--- /dev/null
+++ b/security/nss/cmd/libpkix/sample_apps/validate_chain.c
@@ -0,0 +1,220 @@
+/* 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/. */
+/*
+ * validateChain.c
+ *
+ * Tests Cert Chain Validation
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_cert.h"
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "secitem.h"
+#include "keythi.h"
+#include "nss.h"
+
+static void *plContext = NULL;
+
+static void
+printUsage(void)
+{
+ (void)printf("\nUSAGE:\tvalidateChain <trustedCert> "
+ "<cert_1> <cert_2> ... <cert_n>\n");
+ (void)printf("\tValidates a chain of n certificates "
+ "using the given trust anchor.\n");
+}
+
+static PKIX_PL_Cert *
+createCert(char *inFileName)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ void *buf = NULL;
+ PRFileDesc *inFile = NULL;
+ PKIX_UInt32 len;
+ SECItem certDER;
+ SECStatus rv;
+ /* default: NULL cert (failure case) */
+ PKIX_PL_Cert *cert = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certDER.data = NULL;
+
+ inFile = PR_Open(inFileName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ pkixTestErrorMsg = "Unable to open cert file";
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&certDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)certDER.data;
+ len = certDER.len;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_Create(byteArray, &cert, plContext));
+
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ } else {
+ pkixTestErrorMsg = "Unable to read DER from cert file";
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ }
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+
+ return (cert);
+}
+
+int
+validate_chain(int argc, char *argv[])
+{
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_List *anchors = NULL;
+ PKIX_List *certs = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ PKIX_ComCertSelParams *certSelParams = NULL;
+ PKIX_CertSelector *certSelector = NULL;
+ PKIX_VerifyNode *verifyTree = NULL;
+ PKIX_PL_String *verifyString = NULL;
+
+ char *trustedCertFile = NULL;
+ char *chainCertFile = NULL;
+ PKIX_PL_Cert *trustedCert = NULL;
+ PKIX_PL_Cert *chainCert = NULL;
+ PKIX_UInt32 chainLength = 0;
+ PKIX_UInt32 i = 0;
+ PKIX_UInt32 j = 0;
+ PKIX_UInt32 actualMinorVersion;
+
+ PKIX_TEST_STD_VARS();
+
+ if (argc < 3) {
+ printUsage();
+ return (0);
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(
+ PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));
+
+ chainLength = (argc - j) - 2;
+
+ /* create processing params with list of trust anchors */
+ trustedCertFile = argv[1 + j];
+ trustedCert = createCert(trustedCertFile);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(trustedCert, &subject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));
+
+#if 0
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubject
+ (certSelParams, subject, plContext));
+#endif
+
+ 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_DECREF_BC(subject);
+ PKIX_TEST_DECREF_BC(certSelParams);
+
+ 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));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));
+
+ PKIX_TEST_DECREF_BC(certSelector);
+
+ /* create cert chain */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certs, plContext));
+ for (i = 0; i < chainLength; i++) {
+ chainCertFile = argv[(i + j) + 2];
+ chainCert = createCert(chainCertFile);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certs,
+ (PKIX_PL_Object *)chainCert,
+ plContext));
+
+ PKIX_TEST_DECREF_BC(chainCert);
+ chainCert = NULL;
+ }
+ /* create validate params with processing params and cert chain */
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_Create(procParams, certs, &valParams, plContext));
+
+ PKIX_TEST_DECREF_BC(trustedCert);
+ trustedCert = NULL;
+ PKIX_TEST_DECREF_BC(anchor);
+ anchor = NULL;
+ PKIX_TEST_DECREF_BC(anchors);
+ anchors = NULL;
+ PKIX_TEST_DECREF_BC(certs);
+ certs = NULL;
+ PKIX_TEST_DECREF_BC(procParams);
+ procParams = NULL;
+
+ /* validate cert chain using processing params and return valResult */
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));
+
+ if (valResult != NULL) {
+ (void)printf("SUCCESSFULLY VALIDATED\n");
+ }
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ (void)printf("FAILED TO VALIDATE\n");
+ (void)PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext);
+ (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString);
+ PKIX_TEST_DECREF_AC(verifyString);
+ }
+
+ PKIX_TEST_DECREF_AC(verifyTree);
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(valParams);
+
+ PKIX_TEST_RETURN();
+
+ PKIX_Shutdown(plContext);
+
+ return (0);
+}
diff --git a/security/nss/cmd/libpkix/testutil/Makefile b/security/nss/cmd/libpkix/testutil/Makefile
new file mode 100644
index 0000000000..cc9d235938
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/Makefile
@@ -0,0 +1,50 @@
+#! 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/security/nss/cmd/libpkix/testutil/config.mk b/security/nss/cmd/libpkix/testutil/config.mk
new file mode 100644
index 0000000000..f1f6674f90
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/config.mk
@@ -0,0 +1,8 @@
+#
+# 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/.
+
+# don't build the static library
+LIBRARY =
+RES =
diff --git a/security/nss/cmd/libpkix/testutil/manifest.mn b/security/nss/cmd/libpkix/testutil/manifest.mn
new file mode 100644
index 0000000000..184085b1b1
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/manifest.mn
@@ -0,0 +1,27 @@
+#
+# 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 = ..
+CORE_DEPTH = $(PKIX_DEPTH)/../../..
+PLAT_DEPTH = $(PKIX_DEPTH)/..
+
+MODULE = nss
+
+PRIVATE_EXPORTS = \
+ testutil_nss.h \
+ testutil.h \
+ $(NULL)
+
+CSRCS = \
+ testutil_nss.c \
+ testutil.c \
+ $(NULL)
+
+LIBRARY_NAME = pkixtooltestutil
+SHARED_LIBRARY = $(NULL)
+
+SOURCE_LIB_DIR = $(PKIX_DEPTH)/$(OBJDIR)
+
+NO_MD_RELEASE = 1
diff --git a/security/nss/cmd/libpkix/testutil/pkixutil.def b/security/nss/cmd/libpkix/testutil/pkixutil.def
new file mode 100644
index 0000000000..407d40a318
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/pkixutil.def
@@ -0,0 +1,48 @@
+;+#
+;+# 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/.
+;+#
+;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS
+;+# 1. For all unix platforms, the string ";-" means "remove this line"
+;+# 2. For all unix platforms, the string " DATA " will be removed from any
+;+# line on which it occurs.
+;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX.
+;+# On AIX, lines containing ";+" will be removed.
+;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed.
+;+# 5. For all unix platforms, after the above processing has taken place,
+;+# all characters after the first ";" on the line will be removed.
+;+# And for AIX, the first ";" will also be removed.
+;+# This file is passed directly to windows. Since ';' is a comment, all UNIX
+;+# directives are hidden behind ";", ";+", and ";-"
+;+
+;+NSS_3.12 { # NSS 3.12 release
+;+ global:
+LIBRARY pkixutil ;-
+EXPORTS ;-
+createBuildResult;
+createCRL;
+createCert;
+createCertChain;
+createCertChainPlus;
+createDate;
+createGeneralName;
+createProcessingParams;
+createTrustAnchor;
+createValidateParams;
+createValidateResult;
+endTests;
+startTests;
+subTest;
+testDuplicateHelper;
+testEqualsHelper;
+testError;
+testErrorUndo;
+testHashcodeHelper;
+testToStringHelper;
+PKIX_Cert2ASCII;
+PKIX_Error2ASCII;
+PKIX_String2ASCII;
+;+ local:
+;+ *;
+;+};
diff --git a/security/nss/cmd/libpkix/testutil/testutil.c b/security/nss/cmd/libpkix/testutil/testutil.c
new file mode 100644
index 0000000000..0f438ba430
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/testutil.c
@@ -0,0 +1,576 @@
+/* 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/. */
+/*
+ * testutil.c
+ *
+ * Utility error handling functions
+ *
+ */
+
+#include "testutil.h"
+
+/*
+ * static global variable to keep track of total number of errors for
+ * a particular test suite (eg. all the OID tests)
+ */
+static int errCount = 0;
+
+/*
+ * FUNCTION: startTests
+ * DESCRIPTION:
+ *
+ * Prints standard message for starting the test suite with the name pointed
+ * to by "testName". This function should be called in the beginning of every
+ * test suite.
+ *
+ * PARAMETERS:
+ * "testName"
+ * Address of string representing name of test suite.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "errCount"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+startTests(char *testName)
+{
+ (void)printf("*START OF TESTS FOR %s:\n", testName);
+ errCount = 0;
+}
+
+/*
+ * FUNCTION: endTests
+ * DESCRIPTION:
+ *
+ * Prints standard message for ending the test suite with the name pointed
+ * to by "testName", followed by a success/failure message. This function
+ * should be called at the end of every test suite.
+ *
+ * PARAMETERS:
+ * "testName"
+ * Address of string representing name of test suite.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "errCount"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+endTests(char *testName)
+{
+ char plural = ' ';
+
+ (void)printf("*END OF TESTS FOR %s: ", testName);
+ if (errCount > 0) {
+ if (errCount > 1)
+ plural = 's';
+ (void)printf("%d SUBTEST%c FAILED.\n\n", errCount, plural);
+ } else {
+ (void)printf("ALL TESTS COMPLETED SUCCESSFULLY.\n\n");
+ }
+}
+
+/*
+ * FUNCTION: subTest
+ * DESCRIPTION:
+ *
+ * Prints standard message for starting the subtest with the name pointed to
+ * by "subTestName". This function should be called at the beginning of each
+ * subtest.
+ *
+ * PARAMETERS:
+ * "subTestName"
+ * Address of string representing name of subTest.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+subTest(char *subTestName)
+{
+ (void)printf("TESTING: %s ...\n", subTestName);
+}
+
+/*
+ * FUNCTION: testErrorUndo
+ * DESCRIPTION:
+ *
+ * Decrements the global variable "errCount" and prints a test failure
+ * expected message followed by the string pointed to by "msg". This function
+ * should be called when an expected error condition is encountered in the
+ * tests. Calling this function *correct* the previous errCount increment.
+ * It should only be called ONCE per subtest.
+ *
+ * PARAMETERS:
+ * "msg"
+ * Address of text of error message.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "errCount"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testErrorUndo(char *msg)
+{
+ --errCount;
+ (void)printf("TEST FAILURE *** EXPECTED *** :%s\n", msg);
+}
+
+/*
+ * FUNCTION: testError
+ * DESCRIPTION:
+ *
+ * Increments the global variable "errCount" and prints a standard test
+ * failure message followed by the string pointed to by "msg". This function
+ * should be called when an unexpected error condition is encountered in the
+ * tests. It should only be called ONCE per subtest.
+ *
+ * PARAMETERS:
+ * "msg"
+ * Address of text of error message.
+ * THREAD SAFETY:
+ * Not Thread Safe - assumes exclusive access to "errCount"
+ * (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testError(char *msg)
+{
+ ++errCount;
+ (void)printf("TEST FAILURE: %s\n", msg);
+}
+
+/*
+ * FUNCTION: PKIX_String2ASCII
+ * DESCRIPTION:
+ *
+ * Converts String object pointed to by "string" to its ASCII representation
+ * and returns the converted value. Returns NULL upon failure.
+ *
+ * XXX Might want to use ESCASCII_DEBUG to show control characters, etc.
+ *
+ * PARAMETERS:
+ * "string"
+ * Address of String to be converted to ASCII. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns the ASCII representation of "string" upon success;
+ * NULL upon failure.
+ */
+char *
+PKIX_String2ASCII(PKIX_PL_String *string, void *plContext)
+{
+ PKIX_UInt32 length;
+ char *asciiString = NULL;
+ PKIX_Error *errorResult;
+
+ errorResult = PKIX_PL_String_GetEncoded(string,
+ PKIX_ESCASCII,
+ (void **)&asciiString,
+ &length,
+ plContext);
+
+ if (errorResult)
+ goto cleanup;
+
+cleanup:
+
+ if (errorResult) {
+ return (NULL);
+ }
+
+ return (asciiString);
+}
+
+/*
+ * FUNCTION: PKIX_Error2ASCII
+ * DESCRIPTION:
+ *
+ * Converts Error pointed to by "error" to its ASCII representation and
+ * returns the converted value. Returns NULL upon failure.
+ *
+ * PARAMETERS:
+ * "error"
+ * Address of Error to be converted to ASCII. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns the ASCII representation of "error" upon success;
+ * NULL upon failure.
+ */
+char *
+PKIX_Error2ASCII(PKIX_Error *error, void *plContext)
+{
+ PKIX_UInt32 length;
+ char *asciiString = NULL;
+ PKIX_PL_String *pkixString = NULL;
+ PKIX_Error *errorResult = NULL;
+
+ errorResult = PKIX_PL_Object_ToString((PKIX_PL_Object *)error, &pkixString, plContext);
+ if (errorResult)
+ goto cleanup;
+
+ errorResult = PKIX_PL_String_GetEncoded(pkixString,
+ PKIX_ESCASCII,
+ (void **)&asciiString,
+ &length,
+ plContext);
+
+cleanup:
+
+ if (pkixString) {
+ if (PKIX_PL_Object_DecRef((PKIX_PL_Object *)pkixString, plContext)) {
+ return (NULL);
+ }
+ }
+
+ if (errorResult) {
+ return (NULL);
+ }
+
+ return (asciiString);
+}
+
+/*
+ * FUNCTION: PKIX_Object2ASCII
+ * DESCRIPTION:
+ *
+ * Converts Object pointed to by "object" to its ASCII representation and
+ * returns the converted value. Returns NULL upon failure.
+ *
+ * PARAMETERS:
+ * "object"
+ * Address of Object to be converted to ASCII. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns the ASCII representation of "object" upon success;
+ * NULL upon failure.
+ */
+char *
+PKIX_Object2ASCII(PKIX_PL_Object *object)
+{
+ PKIX_UInt32 length;
+ char *asciiString = NULL;
+ PKIX_PL_String *pkixString = NULL;
+ PKIX_Error *errorResult = NULL;
+
+ errorResult = PKIX_PL_Object_ToString(object, &pkixString, NULL);
+ if (errorResult)
+ goto cleanup;
+
+ errorResult = PKIX_PL_String_GetEncoded(pkixString, PKIX_ESCASCII, (void **)&asciiString, &length, NULL);
+
+cleanup:
+
+ if (pkixString) {
+ if (PKIX_PL_Object_DecRef((PKIX_PL_Object *)pkixString, NULL)) {
+ return (NULL);
+ }
+ }
+
+ if (errorResult) {
+ return (NULL);
+ }
+
+ return (asciiString);
+}
+
+/*
+ * FUNCTION: PKIX_Cert2ASCII
+ * DESCRIPTION:
+ *
+ * Converts Cert pointed to by "cert" to its partial ASCII representation and
+ * returns the converted value. Returns NULL upon failure.
+ *
+ * PARAMETERS:
+ * "cert"
+ * Address of Cert to be converted to ASCII. Must be non-NULL.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns the partial ASCII representation of "cert" upon success;
+ * NULL upon failure.
+ */
+char *
+PKIX_Cert2ASCII(PKIX_PL_Cert *cert)
+{
+ PKIX_PL_X500Name *issuer = NULL;
+ void *issuerAscii = NULL;
+ PKIX_PL_X500Name *subject = NULL;
+ void *subjectAscii = NULL;
+ void *asciiString = NULL;
+ PKIX_Error *errorResult = NULL;
+ PKIX_UInt32 numChars;
+
+ /* Issuer */
+ errorResult = PKIX_PL_Cert_GetIssuer(cert, &issuer, NULL);
+ if (errorResult)
+ goto cleanup;
+
+ issuerAscii = PKIX_Object2ASCII((PKIX_PL_Object *)issuer);
+
+ /* Subject */
+ errorResult = PKIX_PL_Cert_GetSubject(cert, &subject, NULL);
+ if (errorResult)
+ goto cleanup;
+
+ if (subject) {
+ subjectAscii = PKIX_Object2ASCII((PKIX_PL_Object *)subject);
+ }
+
+ errorResult = PKIX_PL_Malloc(200, &asciiString, NULL);
+ if (errorResult)
+ goto cleanup;
+
+ numChars =
+ PR_snprintf(asciiString,
+ 200,
+ "Issuer=%s\nSubject=%s\n",
+ issuerAscii,
+ subjectAscii);
+
+ if (!numChars)
+ goto cleanup;
+
+cleanup:
+
+ if (issuer) {
+ if (PKIX_PL_Object_DecRef((PKIX_PL_Object *)issuer, NULL)) {
+ return (NULL);
+ }
+ }
+
+ if (subject) {
+ if (PKIX_PL_Object_DecRef((PKIX_PL_Object *)subject, NULL)) {
+ return (NULL);
+ }
+ }
+
+ if (PKIX_PL_Free((PKIX_PL_Object *)issuerAscii, NULL)) {
+ return (NULL);
+ }
+
+ if (PKIX_PL_Free((PKIX_PL_Object *)subjectAscii, NULL)) {
+ return (NULL);
+ }
+
+ if (errorResult) {
+ return (NULL);
+ }
+
+ return (asciiString);
+}
+
+/*
+ * FUNCTION: testHashcodeHelper
+ * DESCRIPTION:
+ *
+ * Computes the hashcode of the Object pointed to by "goodObject" and the
+ * Object pointed to by "otherObject" and compares them. If the result of the
+ * comparison is not the desired match as specified by "match", an error
+ * message is generated.
+ *
+ * PARAMETERS:
+ * "goodObject"
+ * Address of an object. Must be non-NULL.
+ * "otherObject"
+ * Address of another object. Must be non-NULL.
+ * "match"
+ * Boolean value representing the desired comparison result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testHashcodeHelper(
+ PKIX_PL_Object *goodObject,
+ PKIX_PL_Object *otherObject,
+ PKIX_Boolean match,
+ void *plContext)
+{
+
+ PKIX_UInt32 goodHash;
+ PKIX_UInt32 otherHash;
+ PKIX_Boolean cmpResult;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Hashcode((PKIX_PL_Object *)goodObject, &goodHash, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Hashcode((PKIX_PL_Object *)otherObject, &otherHash, plContext));
+
+ cmpResult = (goodHash == otherHash);
+
+ if ((match && !cmpResult) || (!match && cmpResult)) {
+ testError("unexpected mismatch");
+ (void)printf("Hash1:\t%d\n", goodHash);
+ (void)printf("Hash2:\t%d\n", otherHash);
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * FUNCTION: testToStringHelper
+ * DESCRIPTION:
+ *
+ * Calls toString on the Object pointed to by "goodObject" and compares the
+ * result to the string pointed to by "expected". If the results are not
+ * equal, an error message is generated.
+ *
+ * PARAMETERS:
+ * "goodObject"
+ * Address of Object. Must be non-NULL.
+ * "expected"
+ * Address of the desired string.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testToStringHelper(
+ PKIX_PL_Object *goodObject,
+ char *expected,
+ void *plContext)
+{
+ PKIX_PL_String *stringRep = NULL;
+ char *actual = NULL;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString(goodObject, &stringRep, plContext));
+
+ actual = PKIX_String2ASCII(stringRep, plContext);
+ if (actual == NULL) {
+ pkixTestErrorMsg = "PKIX_String2ASCII Failed";
+ goto cleanup;
+ }
+
+ /*
+ * If you are having trouble matching the string, uncomment the
+ * PL_strstr function to figure out what's going on.
+ */
+
+ /*
+ if (PL_strstr(actual, expected) == NULL){
+ testError("PL_strstr failed");
+ }
+ */
+
+ 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();
+}
+
+/*
+ * FUNCTION: testEqualsHelper
+ * DESCRIPTION:
+ *
+ * Checks if the Object pointed to by "goodObject" is Equal to the Object
+ * pointed to by "otherObject". If the result of the check is not the desired
+ * match as specified by "match", an error message is generated.
+ *
+ * PARAMETERS:
+ * "goodObject"
+ * Address of an Object. Must be non-NULL.
+ * "otherObject"
+ * Address of another Object. Must be non-NULL.
+ * "match"
+ * Boolean value representing the desired comparison result.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testEqualsHelper(
+ PKIX_PL_Object *goodObject,
+ PKIX_PL_Object *otherObject,
+ PKIX_Boolean match,
+ void *plContext)
+{
+
+ PKIX_Boolean cmpResult;
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(goodObject, otherObject, &cmpResult, plContext));
+
+ if ((match && !cmpResult) || (!match && cmpResult)) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", cmpResult);
+ (void)printf("Expected value:\t%d\n", match);
+ }
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+}
+
+/*
+ * FUNCTION: testDuplicateHelper
+ * DESCRIPTION:
+ * Checks if the Object pointed to by "object" is equal to its duplicate.
+ * If the result of the check is not equality, an error message is generated.
+ * PARAMETERS:
+ * "object"
+ * Address of Object. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns nothing.
+ */
+void
+testDuplicateHelper(PKIX_PL_Object *object, void *plContext)
+{
+ PKIX_PL_Object *newObject = NULL;
+ PKIX_Boolean cmpResult;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Duplicate(object, &newObject, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals(object, newObject, &cmpResult, plContext));
+
+ if (!cmpResult) {
+ testError("unexpected mismatch");
+ (void)printf("Actual value:\t%d\n", cmpResult);
+ (void)printf("Expected value:\t%d\n", PKIX_TRUE);
+ }
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(newObject);
+
+ PKIX_TEST_RETURN();
+}
diff --git a/security/nss/cmd/libpkix/testutil/testutil.h b/security/nss/cmd/libpkix/testutil/testutil.h
new file mode 100644
index 0000000000..9c594fa038
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/testutil.h
@@ -0,0 +1,292 @@
+/* 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/. */
+/*
+ * testutil.h
+ *
+ * Utility functions for handling test errors
+ *
+ */
+
+#ifndef _TESTUTIL_H
+#define _TESTUTIL_H
+
+#include "pkix.h"
+#include "plstr.h"
+#include "prprf.h"
+#include "prlong.h"
+#include "pkix_pl_common.h"
+#include "secutil.h"
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * In order to have a consistent format for displaying test information,
+ * all tests are REQUIRED to use the functions provided by this library
+ * (libtestutil.a) for displaying their information.
+ *
+ * A test using this library begins with a call to startTests with the test
+ * name as the arg (which is used only for formatting). Before the first
+ * subtest, a call to subTest should be made with the subtest name as the arg
+ * (again, for formatting). If the subTest is successful, then no action
+ * is needed. However, if the subTest is not successful, then a call
+ * to testError should be made with a descriptive error message as the arg.
+ * Note that a subTest MUST NOT call testError more than once.
+ * Finally, a call to endTests is made with the test name as the arg (for
+ * formatting). Note that most of these macros assume that a variable named
+ * "plContext" of type (void *) has been defined by the test. As such, it
+ * is essential that the test satisfy this condition.
+ */
+
+/*
+ * PKIX_TEST_STD_VARS should be called at the beginning of every function
+ * that uses PKIX_TEST_RETURN (e.g. subTests), but it should be called only
+ * AFTER declaring local variables (so we don't get compiler warnings about
+ * declarations after statements). PKIX_TEST_STD_VARS declares and initializes
+ * several variables needed by the other test macros.
+ */
+#define PKIX_TEST_STD_VARS() \
+ PKIX_Error *pkixTestErrorResult = NULL; \
+ char *pkixTestErrorMsg = NULL;
+
+/*
+ * PKIX_TEST_EXPECT_NO_ERROR should be used to wrap a standard PKIX function
+ * call (one which returns a pointer to PKIX_Error) that is expected to return
+ * NULL (i.e. to succeed). If "pkixTestErrorResult" is not NULL,
+ * "goto cleanup" is executed, where a testError call is made if there were
+ * unexpected results. This macro MUST NOT be called after the "cleanup" label.
+ *
+ * Example Usage: PKIX_TEST_EXPECT_NO_ERROR(pkixFunc_expected_to_succeed(...));
+ */
+
+#define PKIX_TEST_EXPECT_NO_ERROR(func) \
+ do { \
+ pkixTestErrorResult = (func); \
+ if (pkixTestErrorResult) { \
+ goto cleanup; \
+ } \
+ } while (0)
+
+/*
+ * PKIX_TEST_EXPECT_ERROR should be used to wrap a standard PKIX function call
+ * (one which returns a pointer to PKIX_Error) that is expected to return
+ * a non-NULL value (i.e. to fail). If "pkixTestErrorResult" is NULL,
+ * "pkixTestErrorMsg" is set to a standard string and "goto cleanup"
+ * is executed, where a testError call is made if there were unexpected
+ * results. This macro MUST NOT be called after the "cleanup" label.
+ *
+ * Example Usage: PKIX_TEST_EXPECT_ERROR(pkixFunc_expected_to_fail(...));
+ */
+
+#define PKIX_TEST_EXPECT_ERROR(func) \
+ do { \
+ pkixTestErrorResult = (func); \
+ if (!pkixTestErrorResult) { \
+ pkixTestErrorMsg = \
+ "Should have thrown an error here."; \
+ goto cleanup; \
+ } \
+ PKIX_TEST_DECREF_BC(pkixTestErrorResult); \
+ } while (0)
+
+/*
+ * PKIX_TEST_DECREF_BC is a convenience macro which should only be called
+ * BEFORE the "cleanup" label ("BC"). If the input parameter is non-NULL, it
+ * DecRefs the input parameter and wraps the function with
+ * PKIX_TEST_EXPECT_NO_ERROR, which executes "goto cleanup" upon error.
+ * This macro MUST NOT be called after the "cleanup" label.
+ */
+
+#define PKIX_TEST_DECREF_BC(obj) \
+ do { \
+ if (obj) { \
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_DecRef((PKIX_PL_Object *)(obj), plContext)); \
+ obj = NULL; \
+ } \
+ } while (0)
+
+/*
+ * PKIX_TEST_DECREF_AC is a convenience macro which should only be called
+ * AFTER the "cleanup" label ("AC"). If the input parameter is non-NULL, it
+ * DecRefs the input parameter. A pkixTestTempResult variable is used to prevent
+ * incorrectly overwriting pkixTestErrorResult with NULL.
+ * In the case DecRef succeeds, pkixTestTempResult will be NULL, and we won't
+ * overwrite a previously set pkixTestErrorResult (if any). If DecRef fails,
+ * then we do want to overwrite a previously set pkixTestErrorResult since a
+ * DecRef failure is fatal and may be indicative of memory corruption.
+ */
+
+#define PKIX_TEST_DECREF_AC(obj) \
+ do { \
+ if (obj) { \
+ PKIX_Error *pkixTestTempResult = NULL; \
+ pkixTestTempResult = \
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)(obj), plContext); \
+ if (pkixTestTempResult) \
+ pkixTestErrorResult = pkixTestTempResult; \
+ obj = NULL; \
+ } \
+ } while (0)
+
+/*
+ * PKIX_TEST_RETURN must always be AFTER the "cleanup" label. It does nothing
+ * if everything went as expected. However, if there were unexpected results,
+ * PKIX_TEST_RETURN calls testError, which displays a standard failure message
+ * and increments the number of subtests that have failed. In the case
+ * of an unexpected error, testError is called using the error's description
+ * as an input and the error is DecRef'd. In the case of unexpected success
+ * testError is called with a standard string.
+ */
+#define PKIX_TEST_RETURN() \
+ { \
+ if (pkixTestErrorMsg) { \
+ testError(pkixTestErrorMsg); \
+ } else if (pkixTestErrorResult) { \
+ pkixTestErrorMsg = \
+ PKIX_Error2ASCII(pkixTestErrorResult, plContext); \
+ if (pkixTestErrorMsg) { \
+ testError(pkixTestErrorMsg); \
+ PKIX_PL_Free((PKIX_PL_Object *)pkixTestErrorMsg, \
+ plContext); \
+ } else { \
+ testError("PKIX_Error2ASCII Failed"); \
+ } \
+ if (pkixTestErrorResult != PKIX_ALLOC_ERROR()) { \
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)pkixTestErrorResult, \
+ plContext); \
+ pkixTestErrorResult = NULL; \
+ } \
+ } \
+ }
+
+/*
+ * PKIX_TEST_EQ_HASH_TOSTR_DUP is a convenience macro which executes the
+ * standard set of operations that test the Equals, Hashcode, ToString, and
+ * Duplicate functions of an object type. The goodObj, equalObj, and diffObj
+ * are as the names suggest. The expAscii parameter is the expected result of
+ * calling ToString on the goodObj. If expAscii is NULL, then ToString will
+ * not be called on the goodObj. The checkDuplicate parameter is treated as
+ * a Boolean to indicate whether the Duplicate function should be tested. If
+ * checkDuplicate is NULL, then Duplicate will not be called on the goodObj.
+ * The type is the name of the function's family. For example, if the type is
+ * Cert, this macro will call PKIX_PL_Cert_Equals, PKIX_PL_Cert_Hashcode, and
+ * PKIX_PL_Cert_ToString.
+ *
+ * Note: If goodObj uses the default Equals and Hashcode functions, then
+ * for goodObj and equalObj to be equal, they must have the same pointer value.
+ */
+#define PKIX_TEST_EQ_HASH_TOSTR_DUP(goodObj, equalObj, diffObj, \
+ expAscii, type, checkDuplicate) \
+ do { \
+ subTest("PKIX_PL_" #type "_Equals <match>"); \
+ testEqualsHelper((PKIX_PL_Object *)(goodObj), \
+ (PKIX_PL_Object *)(equalObj), \
+ PKIX_TRUE, \
+ plContext); \
+ subTest("PKIX_PL_" #type "_Hashcode <match>"); \
+ testHashcodeHelper((PKIX_PL_Object *)(goodObj), \
+ (PKIX_PL_Object *)(equalObj), \
+ PKIX_TRUE, \
+ plContext); \
+ subTest("PKIX_PL_" #type "_Equals <non-match>"); \
+ testEqualsHelper((PKIX_PL_Object *)(goodObj), \
+ (PKIX_PL_Object *)(diffObj), \
+ PKIX_FALSE, \
+ plContext); \
+ subTest("PKIX_PL_" #type "_Hashcode <non-match>"); \
+ testHashcodeHelper((PKIX_PL_Object *)(goodObj), \
+ (PKIX_PL_Object *)(diffObj), \
+ PKIX_FALSE, \
+ plContext); \
+ if (expAscii) { \
+ subTest("PKIX_PL_" #type "_ToString"); \
+ testToStringHelper((PKIX_PL_Object *)(goodObj), \
+ (expAscii), \
+ plContext); \
+ } \
+ if (checkDuplicate) { \
+ subTest("PKIX_PL_" #type "_Duplicate"); \
+ testDuplicateHelper((PKIX_PL_Object *)goodObj, plContext); \
+ } \
+ } while (0)
+
+/*
+ * PKIX_TEST_DECREF_BC is a convenience macro which should only be called
+ * BEFORE the "cleanup" label ("BC"). If the input parameter is non-NULL, it
+ * DecRefs the input parameter and wraps the function with
+ * PKIX_TEST_EXPECT_NO_ERROR, which executes "goto cleanup" upon error.
+ * This macro MUST NOT be called after the "cleanup" label.
+ */
+
+#define PKIX_TEST_ABORT_ON_NULL(obj) \
+ do { \
+ if (!obj) { \
+ goto cleanup; \
+ } \
+ } while (0)
+
+#define PKIX_TEST_ARENAS_ARG(arena) \
+ (arena ? (PORT_Strcmp(arena, "arenas") ? PKIX_FALSE : (j++, PKIX_TRUE)) : PKIX_FALSE)
+
+#define PKIX_TEST_ERROR_RECEIVED (pkixTestErrorMsg || pkixTestErrorResult)
+
+/* see source file for function documentation */
+
+void startTests(char *testName);
+
+void endTests(char *testName);
+
+void subTest(char *subTestName);
+
+void testError(char *msg);
+
+extern PKIX_Error *
+_ErrorCheck(PKIX_Error *errorResult);
+
+extern PKIX_Error *
+_OutputError(PKIX_Error *errorResult);
+
+char *PKIX_String2ASCII(PKIX_PL_String *string, void *plContext);
+
+char *PKIX_Error2ASCII(PKIX_Error *error, void *plContext);
+
+char *PKIX_Object2ASCII(PKIX_PL_Object *object);
+
+char *PKIX_Cert2ASCII(PKIX_PL_Cert *cert);
+
+void
+testHashcodeHelper(
+ PKIX_PL_Object *goodObject,
+ PKIX_PL_Object *otherObject,
+ PKIX_Boolean match,
+ void *plContext);
+
+void
+testToStringHelper(
+ PKIX_PL_Object *goodObject,
+ char *expected,
+ void *plContext);
+
+void
+testEqualsHelper(
+ PKIX_PL_Object *goodObject,
+ PKIX_PL_Object *otherObject,
+ PKIX_Boolean match,
+ void *plContext);
+
+void
+testDuplicateHelper(
+ PKIX_PL_Object *object,
+ void *plContext);
+void
+testErrorUndo(char *msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TESTUTIL_H */
diff --git a/security/nss/cmd/libpkix/testutil/testutil_nss.c b/security/nss/cmd/libpkix/testutil/testutil_nss.c
new file mode 100644
index 0000000000..3417d0ab7c
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/testutil_nss.c
@@ -0,0 +1,579 @@
+/* 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/. */
+/*
+ * testutil_nss.c
+ *
+ * NSS-specific utility functions for handling test errors
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+
+#include "pkix_pl_generalname.h"
+#include "pkix_pl_cert.h"
+#include "pkix.h"
+#include "testutil.h"
+#include "prlong.h"
+#include "plstr.h"
+#include "prthread.h"
+#include "secutil.h"
+#include "nspr.h"
+#include "prtypes.h"
+#include "prtime.h"
+#include "pk11func.h"
+#include "secasn1.h"
+#include "cert.h"
+#include "cryptohi.h"
+#include "secoid.h"
+#include "certdb.h"
+#include "secitem.h"
+#include "keythi.h"
+#include "nss.h"
+
+static char *
+catDirName(char *dir, char *name, void *plContext)
+{
+ char *pathName = NULL;
+ PKIX_UInt32 nameLen;
+ PKIX_UInt32 dirLen;
+
+ PKIX_TEST_STD_VARS();
+
+ nameLen = PL_strlen(name);
+ dirLen = PL_strlen(dir);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Malloc(dirLen + nameLen + 2,
+ (void **)&pathName,
+ plContext));
+
+ PL_strcpy(pathName, dir);
+ PL_strcat(pathName, "/");
+ PL_strcat(pathName, name);
+ printf("pathName = %s\n", pathName);
+
+cleanup:
+
+ PKIX_TEST_RETURN();
+
+ return (pathName);
+}
+
+PKIX_PL_Cert *
+createCert(
+ char *dirName,
+ char *certFileName,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ void *buf = NULL;
+ PRFileDesc *certFile = NULL;
+ PKIX_UInt32 len;
+ SECItem certDER;
+ SECStatus rv;
+ /* default: NULL cert (failure case) */
+ PKIX_PL_Cert *cert = NULL;
+ char *pathName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ certDER.data = NULL;
+
+ pathName = catDirName(dirName, certFileName, plContext);
+ certFile = PR_Open(pathName, PR_RDONLY, 0);
+
+ if (!certFile) {
+ pkixTestErrorMsg = "Unable to open cert file";
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&certDER, certFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)certDER.data;
+ len = certDER.len;
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_Create(byteArray, &cert, plContext));
+
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ } else {
+ pkixTestErrorMsg = "Unable to read DER from cert file";
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ pkixTestErrorResult = PKIX_PL_Free(pathName, plContext);
+
+ if (certFile) {
+ PR_Close(certFile);
+ }
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ SECITEM_FreeItem(&certDER, PR_FALSE);
+ }
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+
+ return (cert);
+}
+
+PKIX_PL_CRL *
+createCRL(
+ char *dirName,
+ char *crlFileName,
+ void *plContext)
+{
+ PKIX_PL_ByteArray *byteArray = NULL;
+ PKIX_PL_CRL *crl = NULL;
+ PKIX_Error *error = NULL;
+ PRFileDesc *inFile = NULL;
+ SECItem crlDER;
+ void *buf = NULL;
+ PKIX_UInt32 len;
+ SECStatus rv;
+ char *pathName = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ crlDER.data = NULL;
+
+ pathName = catDirName(dirName, crlFileName, plContext);
+ inFile = PR_Open(pathName, PR_RDONLY, 0);
+
+ if (!inFile) {
+ pkixTestErrorMsg = "Unable to open crl file";
+ goto cleanup;
+ } else {
+ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE);
+ if (!rv) {
+ buf = (void *)crlDER.data;
+ len = crlDER.len;
+
+ error = PKIX_PL_ByteArray_Create(buf, len, &byteArray, plContext);
+
+ if (error) {
+ pkixTestErrorMsg =
+ "PKIX_PL_ByteArray_Create failed";
+ goto cleanup;
+ }
+
+ error = PKIX_PL_CRL_Create(byteArray, &crl, plContext);
+ if (error) {
+ pkixTestErrorMsg = "PKIX_PL_Crl_Create failed";
+ goto cleanup;
+ }
+
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ } else {
+ pkixTestErrorMsg = "Unable to read DER from crl file";
+ goto cleanup;
+ }
+ }
+
+cleanup:
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(pathName, plContext));
+
+ if (inFile) {
+ PR_Close(inFile);
+ }
+
+ if (error) {
+ SECITEM_FreeItem(&crlDER, PR_FALSE);
+ }
+
+ PKIX_TEST_DECREF_AC(byteArray);
+
+ PKIX_TEST_RETURN();
+
+ return (crl);
+}
+
+PKIX_TrustAnchor *
+createTrustAnchor(
+ char *dirName,
+ char *certFileName,
+ PKIX_Boolean useCert,
+ void *plContext)
+{
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_X500Name *name = NULL;
+ PKIX_PL_PublicKey *pubKey = NULL;
+ PKIX_PL_CertNameConstraints *nameConstraints = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ cert = createCert(dirName, certFileName, plContext);
+
+ if (useCert) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(cert, &anchor, plContext));
+ } else {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(cert, &name, plContext));
+
+ if (name == NULL) {
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(cert, &pubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetNameConstraints(cert, &nameConstraints, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithNameKeyPair(name, pubKey, nameConstraints, &anchor, plContext));
+ }
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(anchor);
+ }
+
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(name);
+ PKIX_TEST_DECREF_AC(pubKey);
+ PKIX_TEST_DECREF_AC(nameConstraints);
+
+ PKIX_TEST_RETURN();
+
+ return (anchor);
+}
+
+PKIX_List *
+createCertChain(
+ char *dirName,
+ char *firstCertFileName,
+ char *secondCertFileName,
+ void *plContext)
+{
+ PKIX_PL_Cert *firstCert = NULL;
+ PKIX_PL_Cert *secondCert = NULL;
+ PKIX_List *certList = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certList, plContext));
+
+ firstCert = createCert(dirName, firstCertFileName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certList, (PKIX_PL_Object *)firstCert, plContext));
+
+ if (secondCertFileName) {
+ secondCert = createCert(dirName, secondCertFileName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certList, (PKIX_PL_Object *)secondCert, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable(certList, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(certList);
+ }
+
+ PKIX_TEST_DECREF_AC(firstCert);
+ PKIX_TEST_DECREF_AC(secondCert);
+
+ PKIX_TEST_RETURN();
+
+ return (certList);
+}
+
+PKIX_List *
+createCertChainPlus(
+ char *dirName,
+ char *certNames[],
+ PKIX_PL_Cert *certs[],
+ PKIX_UInt32 numCerts,
+ void *plContext)
+{
+ PKIX_List *certList = NULL;
+ PKIX_UInt32 i;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certList, plContext));
+
+ for (i = 0; i < numCerts; i++) {
+
+ certs[i] = createCert(dirName, certNames[i], plContext);
+
+ /* Create Cert may fail */
+ if (certs[i] == NULL) {
+ PKIX_TEST_DECREF_BC(certList);
+ goto cleanup;
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certList,
+ (PKIX_PL_Object *)certs[i],
+ plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetImmutable(certList, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(certList);
+ }
+
+ for (i = 0; i < numCerts; i++) {
+ PKIX_TEST_DECREF_AC(certs[i]);
+ }
+
+ PKIX_TEST_RETURN();
+
+ return (certList);
+}
+
+PKIX_PL_Date *
+createDate(
+ char *asciiDate,
+ void *plContext)
+{
+ PKIX_PL_Date *date = NULL;
+ PKIX_PL_String *plString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, asciiDate, 0, &plString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Date_Create_UTCTime(plString, &date, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(plString);
+
+ PKIX_TEST_RETURN();
+
+ return (date);
+}
+
+PKIX_ProcessingParams *
+createProcessingParams(
+ char *dirName,
+ char *firstAnchorFileName,
+ char *secondAnchorFileName,
+ char *dateAscii,
+ PKIX_List *initialPolicies, /* List of PKIX_PL_OID */
+ PKIX_Boolean isCrlEnabled,
+ void *plContext)
+{
+
+ PKIX_TrustAnchor *firstAnchor = NULL;
+ PKIX_TrustAnchor *secondAnchor = NULL;
+ PKIX_List *anchorsList = NULL;
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_PL_String *dateString = NULL;
+ PKIX_PL_Date *testDate = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchorsList, plContext));
+
+ firstAnchor = createTrustAnchor(dirName, firstAnchorFileName, PKIX_FALSE, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchorsList,
+ (PKIX_PL_Object *)firstAnchor,
+ plContext));
+
+ if (secondAnchorFileName) {
+ secondAnchor =
+ createTrustAnchor(dirName, secondAnchorFileName, PKIX_FALSE, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchorsList,
+ (PKIX_PL_Object *)secondAnchor,
+ plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchorsList, &procParams, plContext));
+
+ if (dateAscii) {
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII,
+ dateAscii,
+ 0,
+ &dateString,
+ plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Date_Create_UTCTime(dateString, &testDate, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetDate(procParams, testDate, plContext));
+ }
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetInitialPolicies(procParams, initialPolicies, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, isCrlEnabled, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(procParams);
+ }
+
+ PKIX_TEST_DECREF_AC(dateString);
+ PKIX_TEST_DECREF_AC(testDate);
+ PKIX_TEST_DECREF_AC(anchorsList);
+ PKIX_TEST_DECREF_AC(firstAnchor);
+ PKIX_TEST_DECREF_AC(secondAnchor);
+
+ PKIX_TEST_RETURN();
+
+ return (procParams);
+}
+
+PKIX_ValidateParams *
+createValidateParams(
+ char *dirName,
+ char *firstAnchorFileName,
+ char *secondAnchorFileName,
+ char *dateAscii,
+ PKIX_List *initialPolicies, /* List of PKIX_PL_OID */
+ PKIX_Boolean initialPolicyMappingInhibit,
+ PKIX_Boolean initialAnyPolicyInhibit,
+ PKIX_Boolean initialExplicitPolicy,
+ PKIX_Boolean isCrlEnabled,
+ PKIX_List *chain,
+ void *plContext)
+{
+
+ PKIX_ProcessingParams *procParams = NULL;
+ PKIX_ValidateParams *valParams = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ procParams =
+ createProcessingParams(dirName,
+ firstAnchorFileName,
+ secondAnchorFileName,
+ dateAscii,
+ NULL,
+ isCrlEnabled,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetInitialPolicies(procParams, initialPolicies, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetPolicyMappingInhibited(procParams, initialPolicyMappingInhibit, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetAnyPolicyInhibited(procParams, initialAnyPolicyInhibit, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetExplicitPolicyRequired(procParams, initialExplicitPolicy, NULL));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_Create(procParams, chain, &valParams, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(valParams);
+ }
+
+ PKIX_TEST_DECREF_AC(procParams);
+
+ PKIX_TEST_RETURN();
+
+ return (valParams);
+}
+
+PKIX_ValidateResult *
+createValidateResult(
+ char *dirName,
+ char *anchorFileName,
+ char *pubKeyCertFileName,
+ void *plContext)
+{
+
+ PKIX_TrustAnchor *anchor = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_PL_Cert *cert = NULL;
+ PKIX_PL_PublicKey *pubKey = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ anchor = createTrustAnchor(dirName, anchorFileName, PKIX_FALSE, plContext);
+ cert = createCert(dirName, pubKeyCertFileName, plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(cert, &pubKey, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_ValidateResult_Create(pubKey, anchor, NULL, &valResult, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(valResult);
+ }
+
+ PKIX_TEST_DECREF_AC(anchor);
+ PKIX_TEST_DECREF_AC(cert);
+ PKIX_TEST_DECREF_AC(pubKey);
+
+ PKIX_TEST_RETURN();
+
+ return (valResult);
+}
+
+PKIX_PL_GeneralName *
+createGeneralName(
+ PKIX_UInt32 nameType,
+ char *asciiName,
+ void *plContext)
+{
+
+ PKIX_PL_GeneralName *generalName = NULL;
+ PKIX_PL_String *plString = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, asciiName, 0, &plString, plContext));
+
+ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_GeneralName_Create(nameType, plString, &generalName, plContext));
+
+cleanup:
+
+ PKIX_TEST_DECREF_AC(plString);
+
+ PKIX_TEST_RETURN();
+
+ return (generalName);
+}
+
+PKIX_BuildResult *
+createBuildResult(
+ char *dirName,
+ char *anchorFileName,
+ char *pubKeyCertFileName,
+ char *firstChainCertFileName,
+ char *secondChainCertFileName,
+ void *plContext)
+{
+ PKIX_BuildResult *buildResult = NULL;
+ PKIX_ValidateResult *valResult = NULL;
+ PKIX_List *certChain = NULL;
+
+ PKIX_TEST_STD_VARS();
+
+ valResult = createValidateResult(dirName, anchorFileName, pubKeyCertFileName, plContext);
+ certChain = createCertChain(dirName,
+ firstChainCertFileName,
+ secondChainCertFileName,
+ plContext);
+
+ PKIX_TEST_EXPECT_NO_ERROR(pkix_BuildResult_Create(valResult, certChain, &buildResult, plContext));
+
+cleanup:
+
+ if (PKIX_TEST_ERROR_RECEIVED) {
+ PKIX_TEST_DECREF_AC(buildResult);
+ }
+
+ PKIX_TEST_DECREF_AC(valResult);
+ PKIX_TEST_DECREF_AC(certChain);
+
+ PKIX_TEST_RETURN();
+
+ return (buildResult);
+}
diff --git a/security/nss/cmd/libpkix/testutil/testutil_nss.h b/security/nss/cmd/libpkix/testutil/testutil_nss.h
new file mode 100644
index 0000000000..e1f24af89d
--- /dev/null
+++ b/security/nss/cmd/libpkix/testutil/testutil_nss.h
@@ -0,0 +1,119 @@
+/* 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/. */
+/*
+ * testutil_nss.h
+ *
+ * NSS-specific utility functions for handling test errors
+ *
+ */
+
+#ifndef _TESTUTIL_NSS_H
+#define _TESTUTIL_NSS_H
+
+#include "pkix_tools.h"
+#include "plstr.h"
+#include "prprf.h"
+#include "prlong.h"
+#include "secutil.h"
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pkix_pl_generalname.h"
+
+/* see source file for function documentation */
+
+PKIX_PL_Cert *
+createCert(
+ char *dirName,
+ char *certFile,
+ void *plContext);
+
+PKIX_PL_CRL *
+createCRL(
+ char *dirName,
+ char *crlFileName,
+ void *plContext);
+
+PKIX_TrustAnchor *
+createTrustAnchor(
+ char *dirName,
+ char *taFileName,
+ PKIX_Boolean useCert,
+ void *plContext);
+
+PKIX_List *
+createCertChain(
+ char *dirName,
+ char *firstCertFileName,
+ char *secondCertFileName,
+ void *plContext);
+
+PKIX_List *
+createCertChainPlus(
+ char *dirName,
+ char *certNames[],
+ PKIX_PL_Cert *certs[],
+ PKIX_UInt32 numCerts,
+ void *plContext);
+
+PKIX_PL_Date *
+createDate(
+ char *asciiDate,
+ void *plContext);
+
+PKIX_ProcessingParams *
+createProcessingParams(
+ char *dirName,
+ char *firstAnchorFileName,
+ char *secondAnchorFileName,
+ char *dateAscii,
+ PKIX_List *initialPolicies, /* List of PKIX_PL_OID */
+ PKIX_Boolean isCrlEnabled,
+ void *plContext);
+
+PKIX_ValidateParams *
+createValidateParams(
+ char *dirName,
+ char *firstAnchorFileName,
+ char *secondAnchorFileName,
+ char *dateAscii,
+ PKIX_List *initialPolicies, /* List of PKIX_PL_OID */
+ PKIX_Boolean initialPolicyMappingInhibit,
+ PKIX_Boolean initialAnyPolicyInhibit,
+ PKIX_Boolean initialExplicitPolicy,
+ PKIX_Boolean isCrlEnabled,
+ PKIX_List *chain,
+ void *plContext);
+
+PKIX_ValidateResult *
+createValidateResult(
+ char *dirName,
+ char *anchorFileName,
+ char *pubKeyCertFileName,
+ void *plContext);
+
+PKIX_BuildResult *
+createBuildResult(
+ char *dirName,
+ char *anchorFileName,
+ char *pubKeyCertFileName,
+ char *firstChainCertFileName,
+ char *secondChainCertFileName,
+ void *plContext);
+
+PKIX_PL_GeneralName *
+createGeneralName(
+ PKIX_UInt32 nameType,
+ char *asciiName,
+ void *plContext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TESTUTIL_NSS_H */