diff options
Diffstat (limited to '')
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(¶m, 0, sizeof param); + + rv = SEC_QuickDERDecodeItem(pool, ¶m, + SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate), + value); + if (rv == SECSuccess) { + if (!param.hashAlg) { + SECU_Indent(out, level + 1); + fprintf(out, "Hash algorithm: default, SHA-1\n"); + } else { + SECU_PrintObjectID(out, ¶m.hashAlg->algorithm, + "Hash algorithm", level + 1); + } + if (!param.maskAlg) { + SECU_Indent(out, level + 1); + fprintf(out, "Mask algorithm: default, MGF1\n"); + SECU_Indent(out, level + 1); + fprintf(out, "Mask hash algorithm: default, SHA-1\n"); + } else { + SECU_PrintObjectID(out, ¶m.maskAlg->algorithm, + "Mask algorithm", level + 1); + rv = SEC_QuickDERDecodeItem(pool, &maskHashAlg, + SEC_ASN1_GET(SECOID_AlgorithmIDTemplate), + ¶m.maskAlg->parameters); + if (rv == SECSuccess) { + SECU_PrintObjectID(out, &maskHashAlg.algorithm, + "Mask hash algorithm", level + 1); + } else { + SECU_Indent(out, level + 1); + fprintf(out, "Invalid mask generation algorithm parameters\n"); + } + } + if (!param.saltLength.data) { + SECU_Indent(out, level + 1); + fprintf(out, "Salt length: default, %i (0x%2X)\n", 20, 20); + } else { + SECU_PrintInteger(out, ¶m.saltLength, "Salt length", level + 1); + } + } else { + SECU_Indent(out, level + 1); + fprintf(out, "Invalid RSA-PSS parameters\n"); + } + PORT_FreeArena(pool, PR_FALSE); +} + +void +secu_PrintKDF2Params(FILE *out, SECItem *value, char *m, int level) +{ + PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + SECStatus rv; + secuPBEParams param; + + if (m) { + SECU_Indent(out, level); + fprintf(out, "%s:\n", m); + } + + if (!pool) { + SECU_Indent(out, level); + fprintf(out, "Out of memory\n"); + return; + } + + PORT_Memset(¶m, 0, sizeof param); + rv = SEC_QuickDERDecodeItem(pool, ¶m, secuKDF2Params, value); + if (rv == SECSuccess) { + SECU_PrintAsHex(out, ¶m.salt, "Salt", level + 1); + SECU_PrintInteger(out, ¶m.iterationCount, "Iteration Count", + level + 1); + SECU_PrintInteger(out, ¶m.keyLength, "Key Length", level + 1); + SECU_PrintAlgorithmID(out, ¶m.kdfAlg, "KDF algorithm", level + 1); + } + PORT_FreeArena(pool, PR_FALSE); +} + +void +secu_PrintPKCS5V2Params(FILE *out, SECItem *value, char *m, int level) +{ + PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + SECStatus rv; + secuPBEParams param; + + if (m) { + SECU_Indent(out, level); + fprintf(out, "%s:\n", m); + } + + if (!pool) { + SECU_Indent(out, level); + fprintf(out, "Out of memory\n"); + return; + } + + PORT_Memset(¶m, 0, sizeof param); + rv = SEC_QuickDERDecodeItem(pool, ¶m, secuPBEV2Params, value); + if (rv == SECSuccess) { + SECU_PrintAlgorithmID(out, ¶m.kdfAlg, "KDF", level + 1); + SECU_PrintAlgorithmID(out, ¶m.cipherAlg, "Cipher", level + 1); + } + PORT_FreeArena(pool, PR_FALSE); +} + +void +secu_PrintPBEParams(FILE *out, SECItem *value, char *m, int level) +{ + PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + SECStatus rv; + secuPBEParams param; + + if (m) { + SECU_Indent(out, level); + fprintf(out, "%s:\n", m); + } + + if (!pool) { + SECU_Indent(out, level); + fprintf(out, "Out of memory\n"); + return; + } + + PORT_Memset(¶m, 0, sizeof(secuPBEParams)); + rv = SEC_QuickDERDecodeItem(pool, ¶m, secuPBEParamsTemp, value); + if (rv == SECSuccess) { + SECU_PrintAsHex(out, ¶m.salt, "Salt", level + 1); + SECU_PrintInteger(out, ¶m.iterationCount, "Iteration Count", + level + 1); + } + PORT_FreeArena(pool, PR_FALSE); +} + +/* This function does NOT expect a DER type and length. */ +void +SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, int level) +{ + SECOidTag algtag; + SECU_PrintObjectID(out, &a->algorithm, m, level); + + algtag = SECOID_GetAlgorithmTag(a); + if (SEC_PKCS5IsAlgorithmPBEAlgTag(algtag)) { + switch (algtag) { + case SEC_OID_PKCS5_PBKDF2: + secu_PrintKDF2Params(out, &a->parameters, "Parameters", level + 1); + break; + case SEC_OID_PKCS5_PBES2: + secu_PrintPKCS5V2Params(out, &a->parameters, "Encryption", level + 1); + break; + case SEC_OID_PKCS5_PBMAC1: + secu_PrintPKCS5V2Params(out, &a->parameters, "MAC", level + 1); + break; + default: + secu_PrintPBEParams(out, &a->parameters, "Parameters", level + 1); + break; + } + return; + } + + if (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(¶ms, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate(params, certToMatch, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext)); + testSelector(selector, certs, 0x008); + +cleanup: + + PKIX_TEST_DECREF_AC(selector); + PKIX_TEST_DECREF_AC(params); + + PKIX_TEST_RETURN(); +} + +static void +testNameConstraintsMatch(PKIX_List *certs) +{ + PKIX_CertSelector *selector = NULL; + PKIX_ComCertSelParams *params = NULL; + PKIX_PL_Cert *cert = NULL; + PKIX_PL_CertNameConstraints *permitNameConstraints1 = NULL; + PKIX_PL_CertNameConstraints *permitNameConstraints2 = NULL; + PKIX_PL_CertNameConstraints *permitNameConstraints3 = NULL; + PKIX_PL_CertNameConstraints *excludeNameConstraints1 = NULL; + PKIX_PL_CertNameConstraints *excludeNameConstraints2 = NULL; + PKIX_PL_CertNameConstraints *excludeNameConstraints3 = NULL; + PKIX_UInt32 numCerts = 0; + + PKIX_TEST_STD_VARS(); + + subTest("test NameConstraints Cert Selector"); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext)); + + subTest(" PKIX_PL_Cert_GetNameConstraints <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(¶ms, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext)); + + subTest(" CertNameConstraints testing permitted NONE"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, permitNameConstraints1, plContext)); + testSelector(selector, certs, 0x0); + + subTest(" PKIX_ComCertSelParams_SetNameConstraint Reset"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, NULL, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext)); + + subTest(" CertNameConstraints testing permitted ALL"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, permitNameConstraints2, plContext)); + testSelector(selector, certs, 0x07F); + + subTest(" CertNameConstraints testing permitted TWO"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, permitNameConstraints3, plContext)); + testSelector(selector, certs, 0x0041); + + subTest(" PKIX_ComCertSelParams_SetNameConstraint Reset"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, NULL, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext)); + + subTest(" CertNameConstraints testing excluded"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, excludeNameConstraints1, plContext)); + testSelector(selector, certs, 0x07F); + + subTest(" CertNameConstraints testing excluded"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, excludeNameConstraints2, plContext)); + testSelector(selector, certs, 0x07F); + + subTest(" CertNameConstraints testing excluded"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetNameConstraints(params, excludeNameConstraints3, plContext)); + testSelector(selector, certs, 0x41); + +cleanup: + + PKIX_TEST_DECREF_AC(selector); + PKIX_TEST_DECREF_AC(params); + PKIX_TEST_DECREF_AC(permitNameConstraints1); + PKIX_TEST_DECREF_AC(permitNameConstraints2); + PKIX_TEST_DECREF_AC(permitNameConstraints3); + PKIX_TEST_DECREF_AC(excludeNameConstraints1); + PKIX_TEST_DECREF_AC(excludeNameConstraints2); + PKIX_TEST_DECREF_AC(excludeNameConstraints3); + + PKIX_TEST_RETURN(); +} + +static void +testPathToNamesMatch(PKIX_List *certs) +{ + PKIX_CertSelector *selector = NULL; + PKIX_ComCertSelParams *params = NULL; + PKIX_List *nameList = NULL; + PKIX_PL_GeneralName *name = NULL; + + PKIX_TEST_STD_VARS(); + + subTest("test PathToName Cert Selector"); + + subTest(" PKIX_PL_GeneralName List create"); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&nameList, plContext)); + + subTest(" Add directory name <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(¶ms, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext)); + + subTest(" PKIX_ComCertSelParams_SetPathToNames"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetPathToNames(params, nameList, plContext)); + + subTest(" Permitting THREE"); + testSelector(selector, certs, 0x58); + + subTest(" Remove directory name <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(¶ms, 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(¶ms, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, asciiRep, 0, &stringRep, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Date_Create_UTCTime(stringRep, &testDate, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificateValid(params, testDate, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext)); + testSelector(selector, certs, 0xFFFFFFFF); + +cleanup: + + PKIX_TEST_DECREF_AC(selector); + PKIX_TEST_DECREF_AC(params); + PKIX_TEST_DECREF_AC(stringRep); + PKIX_TEST_DECREF_AC(testDate); + + PKIX_TEST_RETURN(); +} + +static void +test_customCallback1(PKIX_List *certs) +{ + PKIX_CertSelector *selector = NULL; + + PKIX_TEST_STD_VARS(); + + subTest("custom matchCallback"); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(custom_CertSelector_MatchCallback, + NULL, + &selector, + plContext)); + + testSelector(selector, certs, 0x900); + +cleanup: + + PKIX_TEST_DECREF_AC(selector); + + PKIX_TEST_RETURN(); +} + +static void +test_customCallback2(PKIX_List *certs, + PKIX_PL_Cert *anyPolicyCert) /* a source for policy anyPolicy */ +{ + PKIX_CertSelector *selector = NULL; + PKIX_List *anyPolicyList = NULL; /* OIDs */ + PKIX_PL_OID *policyOID = NULL; + + PKIX_TEST_STD_VARS(); + + subTest("custom matchCallback with CertSelectorContext"); + + testGetPolicyFromCert(anyPolicyCert, 0, &anyPolicyList); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(anyPolicyList, 0, (PKIX_PL_Object **)&policyOID, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(custom_CertSelector_MatchOIDCallback, + (PKIX_PL_Object *)policyOID, + &selector, + plContext)); + + testSelector(selector, certs, (1 << ANYPOLICYCERT)); + +cleanup: + + PKIX_TEST_DECREF_AC(selector); + PKIX_TEST_DECREF_AC(anyPolicyList); + PKIX_TEST_DECREF_AC(policyOID); + + PKIX_TEST_RETURN(); +} + +static void +testExtendedKeyUsageMatch(char *certDir) +{ + PKIX_ComCertSelParams *goodParams = NULL; + PKIX_PL_OID *ekuOid = NULL; + PKIX_List *ekuOidList = NULL; + PKIX_PL_String *dirString = NULL; + PKIX_CertStore_CertCallback certCallback; + PKIX_CertStore *certStore = NULL; + PKIX_CertSelector *certSelector = NULL; + PKIX_List *certList = NULL; + PKIX_UInt32 numCert = 0; + void *nbioContext = NULL; + + PKIX_TEST_STD_VARS(); + + subTest("test Extended KeyUsage Cert Selector"); + + subTest(" PKIX_ComCertSelParams_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext)); + + subTest(" Create Extended Key Usage OID List"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&ekuOidList, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create("1.3.6.1.5.5.7.3.2", &ekuOid, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(ekuOidList, (PKIX_PL_Object *)ekuOid, plContext)); + + PKIX_TEST_DECREF_BC(ekuOid); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create("1.3.6.1.5.5.7.3.3", &ekuOid, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(ekuOidList, (PKIX_PL_Object *)ekuOid, plContext)); + + PKIX_TEST_DECREF_BC(ekuOid); + + subTest(" PKIX_ComCertSelParams_SetExtendedKeyUsage"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetExtendedKeyUsage(goodParams, ekuOidList, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, certDir, 0, &dirString, plContext)); + + subTest(" PKIX_PL_CollectionCertStoreContext_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext)); + + subTest(" PKIX_CertSelector_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, goodParams, plContext)); + + subTest(" PKIX_CertStore_GetCertCallback"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, NULL)); + + subTest(" Getting data from Cert Callback"); + PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext)); + + if (numCert != PKIX_TEST_CERTSELECTOR_EXTKEYUSAGE_NUM_CERTS) { + pkixTestErrorMsg = "unexpected Cert number mismatch"; + } + +cleanup: + + PKIX_TEST_DECREF_AC(ekuOid); + PKIX_TEST_DECREF_AC(ekuOidList); + PKIX_TEST_DECREF_AC(goodParams); + PKIX_TEST_DECREF_AC(dirString); + PKIX_TEST_DECREF_AC(certList); + PKIX_TEST_DECREF_AC(certSelector); + PKIX_TEST_DECREF_AC(certStore); + + PKIX_TEST_RETURN(); +} + +static void +testKeyUsageMatch(char *certDir) +{ + PKIX_ComCertSelParams *goodParams = NULL; + PKIX_PL_String *dirString = NULL; + PKIX_CertStore_CertCallback certCallback; + PKIX_CertStore *certStore = NULL; + PKIX_CertSelector *certSelector = NULL; + PKIX_List *certList = NULL; + PKIX_UInt32 numCert = 0; + void *nbioContext = NULL; + + PKIX_TEST_STD_VARS(); + + subTest("test KeyUsage Cert Selector"); + + subTest(" PKIX_ComCertSelParams_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext)); + + subTest(" PKIX_ComCertSelParams_SetKeyUsage"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetKeyUsage(goodParams, PKIX_CRL_SIGN, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, certDir, 0, &dirString, plContext)); + + subTest(" PKIX_PL_CollectionCertStoreContext_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext)); + + subTest(" PKIX_CertSelector_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, goodParams, plContext)); + + subTest(" PKIX_CertStore_GetCertCallback"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, NULL)); + + subTest(" Getting data from Cert Callback"); + PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext)); + + if (numCert != PKIX_TEST_CERTSELECTOR_KEYUSAGE_NUM_CERTS) { + pkixTestErrorMsg = "unexpected Cert number mismatch"; + } + +cleanup: + + PKIX_TEST_DECREF_AC(goodParams); + PKIX_TEST_DECREF_AC(dirString); + PKIX_TEST_DECREF_AC(certList); + PKIX_TEST_DECREF_AC(certSelector); + PKIX_TEST_DECREF_AC(certStore); + + PKIX_TEST_RETURN(); +} + +static void +testCertValidMatch(char *certDir) +{ + PKIX_ComCertSelParams *goodParams = NULL; + PKIX_PL_Date *validDate = NULL; + PKIX_PL_String *dirString = NULL; + PKIX_CertStore_CertCallback certCallback; + PKIX_CertStore *certStore = NULL; + PKIX_CertSelector *certSelector = NULL; + PKIX_List *certList = NULL; + PKIX_UInt32 numCert = 0; + void *nbioContext = NULL; + + PKIX_TEST_STD_VARS(); + + subTest("test CertValid Cert Selector"); + + subTest(" PKIX_ComCertSelParams_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext)); + + validDate = createDate("050601000000Z", plContext); + + subTest(" PKIX_ComCertSelParams_SetCertificateValid"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificateValid(goodParams, validDate, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, certDir, 0, &dirString, plContext)); + + subTest(" PKIX_PL_CollectionCertStoreContext_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext)); + + subTest(" PKIX_CertSelector_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, goodParams, plContext)); + + subTest(" PKIX_CertStore_GetCertCallback"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, NULL)); + + subTest(" Getting data from Cert Callback"); + PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext)); + + if (numCert != PKIX_TEST_CERTSELECTOR_CERTVALID_NUM_CERTS) { + pkixTestErrorMsg = "unexpected Cert number mismatch"; + } + +cleanup: + + PKIX_TEST_DECREF_AC(goodParams); + PKIX_TEST_DECREF_AC(validDate); + PKIX_TEST_DECREF_AC(dirString); + PKIX_TEST_DECREF_AC(certList); + PKIX_TEST_DECREF_AC(certSelector); + PKIX_TEST_DECREF_AC(certStore); + + PKIX_TEST_RETURN(); +} + +static void +testIssuerMatch(char *certDir) +{ + PKIX_ComCertSelParams *goodParams = NULL; + PKIX_PL_X500Name *issuer = NULL; + PKIX_PL_String *issuerStr = NULL; + PKIX_PL_String *dirString = NULL; + PKIX_CertStore_CertCallback certCallback; + PKIX_CertStore *certStore = NULL; + PKIX_CertSelector *certSelector = NULL; + PKIX_List *certList = NULL; + char *issuerName = "CN=science,O=mit,C=US"; + PKIX_UInt32 numCert = 0; + void *nbioContext = NULL; + + PKIX_TEST_STD_VARS(); + + subTest("test Issuer Cert Selector"); + + subTest(" PKIX_ComCertSelParams_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, issuerName, 0, &issuerStr, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_X500Name_Create(issuerStr, &issuer, plContext)); + + subTest(" PKIX_ComCertSelParams_SetIssuer"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetIssuer(goodParams, issuer, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, certDir, 0, &dirString, plContext)); + + subTest(" PKIX_PL_CollectionCertStoreContext_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext)); + + subTest(" PKIX_CertSelector_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, goodParams, plContext)); + + subTest(" PKIX_CertStore_GetCertCallback"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, NULL)); + + subTest(" Getting data from Cert Callback"); + PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext)); + + if (numCert != PKIX_TEST_CERTSELECTOR_ISSUER_NUM_CERTS) { + pkixTestErrorMsg = "unexpected Cert number mismatch"; + } + +cleanup: + + PKIX_TEST_DECREF_AC(goodParams); + PKIX_TEST_DECREF_AC(issuer); + PKIX_TEST_DECREF_AC(issuerStr); + PKIX_TEST_DECREF_AC(dirString); + PKIX_TEST_DECREF_AC(certList); + PKIX_TEST_DECREF_AC(certSelector); + PKIX_TEST_DECREF_AC(certStore); + + PKIX_TEST_RETURN(); +} + +static void +testSerialNumberVersionMatch(char *certDir) +{ + PKIX_ComCertSelParams *goodParams = NULL; + PKIX_PL_BigInt *serialNumber = NULL; + PKIX_PL_String *serialNumberStr = NULL; + PKIX_PL_String *dirString = NULL; + PKIX_CertStore_CertCallback certCallback; + PKIX_CertStore *certStore = NULL; + PKIX_CertSelector *certSelector = NULL; + PKIX_List *certList = NULL; + PKIX_UInt32 numCert = 0; + void *nbioContext = NULL; + + PKIX_TEST_STD_VARS(); + + subTest("test Serial Number Cert Selector"); + + subTest(" PKIX_ComCertSelParams_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&goodParams, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, "01", 0, &serialNumberStr, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_BigInt_Create(serialNumberStr, &serialNumber, plContext)); + + subTest(" PKIX_ComCertSelParams_SetSerialNumber"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSerialNumber(goodParams, serialNumber, plContext)); + + subTest(" PKIX_ComCertSelParams_SetVersion"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetVersion(goodParams, 0, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, certDir, 0, &dirString, plContext)); + + subTest(" PKIX_PL_CollectionCertStoreContext_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirString, &certStore, plContext)); + + subTest(" PKIX_CertSelector_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, goodParams, plContext)); + + subTest(" PKIX_CertStore_GetCertCallback"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertStore_GetCertCallback(certStore, &certCallback, NULL)); + + subTest(" Getting data from Cert Callback"); + PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext)); + + PKIX_TEST_DECREF_BC(certList); + + if (numCert != 0) { + pkixTestErrorMsg = "unexpected Version mismatch"; + } + + subTest(" PKIX_ComCertSelParams_SetVersion"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetVersion(goodParams, 2, plContext)); + + subTest(" Getting data from Cert Callback"); + PKIX_TEST_EXPECT_NO_ERROR(certCallback(certStore, certSelector, &nbioContext, &certList, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certList, &numCert, plContext)); + + if (numCert != PKIX_TEST_CERTSELECTOR_SERIALNUMBER_NUM_CERTS) { + pkixTestErrorMsg = "unexpected Serial Number mismatch"; + } + +cleanup: + + PKIX_TEST_DECREF_AC(goodParams); + PKIX_TEST_DECREF_AC(serialNumber); + PKIX_TEST_DECREF_AC(serialNumberStr); + PKIX_TEST_DECREF_AC(dirString); + PKIX_TEST_DECREF_AC(certList); + PKIX_TEST_DECREF_AC(certSelector); + PKIX_TEST_DECREF_AC(certStore); + + PKIX_TEST_RETURN(); +} + +static void +testSubjKeyIdMatch(PKIX_List *certs) +{ + PKIX_CertSelector *selector = NULL; + PKIX_ComCertSelParams *params = NULL; + PKIX_PL_Cert *cert = NULL; + PKIX_PL_ByteArray *selSubjKeyId = NULL; + PKIX_UInt32 item = 0; + + PKIX_TEST_STD_VARS(); + + subTest("test Subject Key Id Cert Selector"); + + item = 2; + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, item, (PKIX_PL_Object **)&cert, plContext)); + + subTest(" PKIX_PL_Cert_GetSubjectKeyIdentifier"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectKeyIdentifier(cert, &selSubjKeyId, plContext)); + + subTest(" Create Selector and ComCertSelParams"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &selector, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(¶ms, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(selector, params, plContext)); + + subTest(" PKIX_ComCertSelParams_SetSubjKeyIdentifier"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubjKeyIdentifier(params, selSubjKeyId, plContext)); + + subTest(" Select One"); + testSelector(selector, certs, 1 << 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(¶ms, 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(¶ms, 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(¶ms, 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 **)©, + plContext)); + + subTest("CertChainChecker_GetCheckCallback"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCheckCallback(original, &originalCallback, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCheckCallback(copy, ©Callback, plContext)); + if (originalCallback != copyCallback) { + pkixTestErrorMsg = "CheckCallback functions are not equal!"; + goto cleanup; + } + + subTest("CertChainChecker_IsForwardCheckingSupported"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_IsForwardCheckingSupported(original, &originalForward, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_IsForwardCheckingSupported(copy, ©Forward, plContext)); + if (originalForward != copyForward) { + pkixTestErrorMsg = "ForwardChecking booleans are not equal!"; + goto cleanup; + } + + subTest("CertChainChecker_IsForwardDirectionExpected"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_IsForwardDirectionExpected(original, &originalForwardDir, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_IsForwardDirectionExpected(copy, ©ForwardDir, plContext)); + if (originalForwardDir != copyForwardDir) { + pkixTestErrorMsg = "ForwardDirection booleans are not equal!"; + goto cleanup; + } + + subTest("CertChainChecker_GetCertChainCheckerState"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCertChainCheckerState(original, &originalState, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetCertChainCheckerState(copy, ©State, plContext)); + testEqualsHelper(originalState, copyState, PKIX_TRUE, plContext); + + subTest("CertChainChecker_GetSupportedExtensions"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetSupportedExtensions(original, &originalList, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_GetSupportedExtensions(copy, ©List, plContext)); + testEqualsHelper((PKIX_PL_Object *)originalList, + (PKIX_PL_Object *)copyList, + PKIX_TRUE, + plContext); + +cleanup: + + PKIX_TEST_DECREF_AC(copy); + PKIX_TEST_DECREF_AC(originalState); + PKIX_TEST_DECREF_AC(copyState); + PKIX_TEST_DECREF_AC(originalList); + PKIX_TEST_DECREF_AC(copyList); + + PKIX_TEST_RETURN(); +} + +int +test_certchainchecker(int argc, char *argv[]) +{ + + PKIX_UInt32 actualMinorVersion; + PKIX_PL_OID *bcOID = NULL; + PKIX_PL_OID *ncOID = NULL; + PKIX_PL_OID *cpOID = NULL; + PKIX_PL_OID *pmOID = NULL; + PKIX_PL_OID *pcOID = NULL; + PKIX_PL_OID *iaOID = NULL; + PKIX_CertChainChecker *dummyChecker = NULL; + PKIX_List *supportedExtensions = NULL; + PKIX_PL_Object *initialState = NULL; + PKIX_UInt32 j = 0; + + PKIX_TEST_STD_VARS(); + + startTests("CertChainChecker"); + + PKIX_TEST_EXPECT_NO_ERROR( + PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&supportedExtensions, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_BASICCONSTRAINTS_OID, &bcOID, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)bcOID, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_NAMECONSTRAINTS_OID, &ncOID, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)ncOID, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_CERTIFICATEPOLICIES_OID, &cpOID, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)cpOID, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_POLICYMAPPINGS_OID, &pmOID, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)pmOID, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_POLICYCONSTRAINTS_OID, &pcOID, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)pcOID, plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(PKIX_INHIBITANYPOLICY_OID, &iaOID, plContext)); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(supportedExtensions, (PKIX_PL_Object *)iaOID, plContext)); + + PKIX_TEST_DECREF_BC(bcOID); + PKIX_TEST_DECREF_BC(ncOID); + PKIX_TEST_DECREF_BC(cpOID); + PKIX_TEST_DECREF_BC(pmOID); + PKIX_TEST_DECREF_BC(pcOID); + PKIX_TEST_DECREF_BC(iaOID); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)supportedExtensions, plContext)); + + initialState = (PKIX_PL_Object *)supportedExtensions; + + subTest("CertChainChecker_Create"); + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_Create(dummyChecker_Check, /* PKIX_CertChainChecker_CheckCallback */ + PKIX_FALSE, /* forwardCheckingSupported */ + PKIX_FALSE, /* forwardDirectionExpected */ + supportedExtensions, + NULL, /* PKIX_PL_Object *initialState */ + &dummyChecker, + plContext)); + + PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_SetCertChainCheckerState(dummyChecker, initialState, plContext)); + + test_CertChainChecker_Duplicate(dummyChecker); + + subTest("CertChainChecker_Destroy"); + PKIX_TEST_DECREF_BC(dummyChecker); + +cleanup: + + PKIX_TEST_DECREF_AC(dummyChecker); + PKIX_TEST_DECREF_AC(initialState); + PKIX_TEST_DECREF_AC(supportedExtensions); + + PKIX_Shutdown(plContext); + + PKIX_TEST_RETURN(); + + endTests("CertChainChecker"); + + return (0); +} diff --git a/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, ©, 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ß,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ß,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� there!"; + + char *escAsciiString = + "¡𐀀࿿􀀁"; + + char *debugAsciiString = + "string with
newlines and	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
newlines and	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, + "k;", + 7, + &testString, + plContext)); + + /* &#x must be followed by 4 hexadecimal digits */ + PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create( + PKIX_ESCASCII, + "abc�", + 8, + &testString, + plContext)); + + /* &#x must be between 00010000-0010FFFF */ + PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create( + PKIX_ESCASCII, + "�", + 11, + &testString, + plContext)); + + /* &#x must be followed by 8 hexadecimal digits */ + PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create( + PKIX_ESCASCII, + "က", + 10, + &testString, + plContext)); + + /* &#x must be followed by 8 hexadecimal digits */ + PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create( + PKIX_ESCASCII, + "m00;", + 10, + &testString, + plContext)); + + /* Byte values D800-DFFF are reserved */ + PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create( + PKIX_ESCASCII, + "�", + 7, + &testString, + plContext)); + + /* Can't use &#x for regular characters */ + PKIX_TEST_EXPECT_ERROR(PKIX_PL_String_Create( + PKIX_ESCASCII, + "2", + 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: &#x0012;", + "Encode & with &amp; in ASCII", + "¡", + "&", + "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, + &String, + &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 = + "¡Viva España!"; + + char *strauss = + "Strauß was born in Ö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 */ |